Skip to content

feat(ui): Improve user experience, polish ui & add AI chat, Budgets#199

Merged
austin047 merged 21 commits into
devfrom
feat/ui-design-refresh
Jun 5, 2026
Merged

feat(ui): Improve user experience, polish ui & add AI chat, Budgets#199
austin047 merged 21 commits into
devfrom
feat/ui-design-refresh

Conversation

@nfebe

@nfebe nfebe commented May 20, 2026

Copy link
Copy Markdown
Contributor

Description

Cosmetic UI changes to improve UX and UI.

  • Detailed screens for groups, parties, wallets, categories.
  • Better reporting and statistics.
  • Refresh onboarding and authentication.
  • Refreshed main pages, settings, and components.
  • AI chat introduction

Type of Change

Cosmetic UI changes.

  • ✨ New feature (non-breaking change which adds functionality)
  • 🛠️ Bug fix (non-breaking change which fixes an issue)
  • ❌ Breaking change (fix or feature that would cause existing functionality to change)
  • 🧹 Code refactor
  • ✅ Build configuration change
  • 📝 Documentation
  • 🗑️ Chore

nfebe added 3 commits May 21, 2026 00:23
Introduces a tonal palette (brand, brand-soft, income, expense, neutral,
warm) wired in as theme extensions for light and dark, with a tighter
shared radius scale and motion tokens. A new PageAppBar carries every
content page with a context-aware leading slot: back arrow when there
is a stack, brand mark that opens the drawer on root-level pages,
search trigger that transforms the title into an inline field. Titles
are screen-centered and rendered in brand green for presence. The bar
shares the page surface with a hairline separator, so toolbar and body
read as one continuous canvas.

Drawer slims its rows, surfaces user identity in the header, and groups
items by usage rhythm (Everyday, Organize, More) rather than alphabetic
order. Empty states, tip banners, party cards, and the home wallet
tile pick up the new tones and the Trakli warm accent appears in places
that signal "you are here" or "this is a hint" without competing with
the green primary.
… pattern

All four entity surfaces follow one rhythm now: a slim summary chip up top,
optional filter pills below, then a single rounded surface card holding
compact tile rows with hairline dividers. Tapping a row opens a dedicated
detail screen that shows hero + Received/Spent/Net totals + a six-month
activity chart + the recent transactions for that entity. Edit and delete
are demoted to the row overflow menu and the detail screen's app bar.

Sorting now leads with whatever the user actually uses (most active first,
default wallet pinned to the top), and search lives in the top bar via the
search icon transforming the title into an inline input.

Add screens (party, wallet, category, group) drop the old saturated green
custom app bar in favour of the shared PageAppBar so they look like they
belong to the same app.
The statistics tab leads with a compact recap teaser: brand→brand-soft
gradient surface, warm-tinted month chip, In/Out/Net pills, a live
30-day net sparkline, and a glassy play affordance. Tap launches a
full-screen Stories-style player with seven slide kinds (opening,
cash in, cash out, top category, top payee, biggest expense, closing),
animated count-up numbers, staggered slide-in entrances, layered halo
illustrations, and tap-zones for prev / pause / next. Picks the most
recent month with activity instead of going dark when the current
calendar month is empty.

A new Reports destination (launched from a labelled pill in the stats
bar) bundles period chips (30D/90D/6M/12M), a four-cell KPI grid,
weekly cashflow spline area, and a chip-row tab card containing the
category donut + ranking, daily bar chart, calendar heatmap, and
savings / expense ratios with target markers.
@nfebe nfebe marked this pull request as ready for review May 21, 2026 00:01
Login landing pairs a brand-soft tonal hero (logo + tagline + restored
side illustration) with a clear eyebrow / display heading and tonal
primary / outlined / OAuth buttons under an OR divider. Email login
swaps the heavy default TabBar for a tonal segmented Email/Phone
control, gains labelled fields, and adopts the shared page header so
back navigation and styling match the rest of the app.

Onboarding is a three-slide carousel with curated illustrations:
- Simplified personal finance (wallet)
- Automated (AI importer reads receipts, PDFs, CSV, XLS; integrations
  like Plaid and MCP)
- Open source (yours to inspect, host and trust)

Theme toggle lives in the top-right of both onboarding and the login
landing so visitors can flip light / dark before they sign in. The
white wordmark variant is in for dark mode.
@sourceant

sourceant Bot commented May 21, 2026

Copy link
Copy Markdown

Code Review Summary

This PR delivers a significant UI refresh and introduces core functionality for AI-assisted chat and Budget management. It centralizes design tokens and standardizes the top bar across the app.

🚀 Key Improvements

  • Introduction of a structured design token system (AppTones, AppRadii).
  • New AI-powered chat feature for financial insights.
  • Comprehensive Budgeting system with local recomputation and server sync.
  • Improved detail screens for Categories, Groups, and Wallets with analytical charts.

💡 Minor Suggestions

  • Extract hardcoded durations in AiChatCubit.
  • Use a dedicated package for slug generation in BudgetRepository.

@sourceant sourceant Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review complete. See the overview comment for a summary.

Comment on lines +78 to +79
}
if (candidate == null) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fallback logic to find the latest transaction month can be expensive if the list is large. Since transactions are typically sorted or can be reduced more efficiently, consider optimizing the search.

Suggested change
}
if (candidate == null) {
if (candidate == null && transactions.isNotEmpty) {
DateTime latest = transactions.first.transaction.datetime;
for (final t in transactions) {
if (t.transaction.datetime.isAfter(latest)) {
latest = t.transaction.datetime;
}
}
candidate = DateTime(latest.year, latest.month, 1);
}


void _openSearch() {
setState(() => _searching = true);
WidgetsBinding.instance.addPostFrameCallback((_) => _focus.requestFocus());

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is safer to use SchedulerBinding or check if the focus node is still attached before requesting focus to avoid potential 'FocusNode used after dispose' errors during fast navigation transitions.

Suggested change
WidgetsBinding.instance.addPostFrameCallback((_) => _focus.requestFocus());
WidgetsBinding.instance.addPostFrameCallback((_) {
if (_focus.canRequestFocus) _focus.requestFocus();
});

Home keeps the dedicated drawer trigger SVG icon and shows the Trakli
wordmark logo in the title (icon-only mark is reserved for non-home
root pages). Profile uses a tonal brand hero with avatar derived from
the user's initials (deterministic hashed pastel background), name
and email beside it, plus a single grouped surface for Account info
and Log out as tonal action tiles.

Bottom navigation active state now uses the Trakli warm accent so the
"you are here" signal pops without competing with the dominant green.
@nfebe nfebe marked this pull request as draft May 21, 2026 00:02
nfebe added 12 commits May 21, 2026 01:03
Add-transaction adopts the shared page header and replaces the saturated
green TabBar with a tonal segmented Expense/Income picker tinted by
context. Body switches via IndexedStack behind a horizontal-drag
detector so swipe still flips the tab but content swaps instantly,
removing the cross-fade flash on the Record button colour change.
The Record button accent is now the canonical danger red on expense
and primary green on income, instead of always green.
Record button gains a gradient surface (accent to slightly darker
accent), a soft inner highlight, an accent-tinted shadow, and a
tighter corner radius so the primary action feels lifted instead of
flat. Currency chip and the "+" add affordances next to the wallet,
party and category dropdowns share that family: calm tinted background
at 10-12% accent alpha with a matching border and accent-coloured
glyph, so they read as siblings of the form's segmented picker.
Filter triggers on the transaction history page (Date, Category,
Wallet) are now per-filter tonal chips — Date in brand green, Category
in warm orange, Wallet in income green. Each chip fills with its tone,
hairline accent border, deep colour for icon, label and caret. The
title also drops Title Case for sentence case to match the rest of the
copy.
…ings

Settings root, account info, account & privacy, advanced, defaults,
display, notification settings, sync history, orphaned-media log,
data deletion, transfers, savings (list + add), and notifications all
drop the saturated green primary-colour CustomAppBar in favour of the
shared page header so navigation chrome, typography and back behaviour
match the rest of the app. The settings root wraps its tiles in a
single tonal section card so the page reads as one grouped surface
instead of free-floating list items.
Pins the recap fallback (must surface the most recent active month, not
null when this calendar month is empty) and the savings-rate safety
when income is zero. Locks the canonical Trakli green and orange to
their hex values so palette refactors can't silently drift the brand.
Covers PageAppBar's search-in-title transform and the brand-mark anchor
on root pages. Existing party-card test updated to assert against the
tonal palette instead of the now-removed hardcoded avatar hex values.
Users can ask Trakli questions from a dedicated bottom-nav tab, see
assistant replies arrive via polling, and browse or resume past
conversations through a history sheet. Empty state offers suggested
prompts so a first question is one tap away. The new tab replaces the
former profile slot; profile is now reached from the home app bar.
Parties, wallets, groups and categories now carry the same quiet
three-motif background pattern as the AI tab, each scoped to its own
representative icon. Gives every landing surface a subtle identity
without affecting content or interactions.
Replace the manual refresh button with a gradient initials avatar that
opens the profile screen. Pull-to-refresh on the body continues to sync,
so the refresh capability is unchanged. Notifications icon remains.
Wallet-to-wallet transfers were buried behind a per-wallet overflow
menu. Surface them alongside expense and income on the add-transaction
screen so the action is discoverable from the primary entry point. The
transfer form renders inline (no extra navigation) and saves through the
existing flow. The original per-wallet entry remains.
Dark mode left input borders transparent by default, so text fields and
selectors had no visible outline at rest while the focused state showed
a brand-colored ring. Apply a subtle visible border colour for the
unfocused state so every field reads as bounded in dark mode while
staying quiet in light.
Profile was opened as a pushed route but explicitly hid its back button,
leaving the only way back as the system gesture. Restore the default
back affordance.
Budgets can now be created and managed on mobile, matching the web feature.
Each budget has a period (weekly, monthly, yearly, or custom), an optional
target scope across categories, wallets, or groups, threshold and forecast
alerts, and rollover support.

The detail screen fetches live progress for the current period and shows
past closed-period snapshots once they sync. Open it from the new Budgets
entry in the sidebar.
@nfebe nfebe changed the title feat(ui): Improve user experience, polish ui & add AI chat feat(ui): Improve user experience, polish ui & add AI chat, Budgets May 22, 2026
austin047 added 4 commits May 27, 2026 00:16
- Updated all  language translation files
- Fixed critical bug: 'Budgets' menu item now properly localized
- Update the budget screens to use proper bloc and cubit patterns
- Update budgets screens to use default custom snack bar
Extract use cases for AI Chat and Budget features to align with established architectural patterns used across other features.

Update AiChatCubit and BudgetCubit to inject use cases instead of repositories, replacing all repository method calls with use case invocations. Regenerate DI configuration to auto-register new use cases.

This eliminates architectural inconsistency and improves maintainability by ensuring all features follow the unified UseCase<T, Params> pattern with dependency injection.
- Compute budget progress locally (compute_local_progress) and persist it to
  the budgets.progress column via BudgetProgressRecomputer; recompute on
  transaction/target/budget mutations.
- Add budget self-heal: recompute budgets when a fresh exchange rate is cached
  (ExchangeRateRepository.onExchangeRateUpdated), folding in foreign-currency
  transactions that were excluded while no rate was available.
- Exclude un-convertible foreign-currency transactions from the bar instead of
  surfacing a misleading cross-currency total; drop currencyMismatchCount /
  currencyMismatchRawAmount from entity, DTO, mapper, UI, and translations.
- Restrict the add-budget currency picker to wallet currencies + app default.
- Persist progress through the datasource (updateBudgetProgressByServerId)
  rather than touching Drift directly in the repository.
- Add read-only BudgetPeriodState sync handler + DTO.
@austin047 austin047 force-pushed the feat/ui-design-refresh branch from d8e1c36 to 34dfb6e Compare June 5, 2026 11:15
@austin047 austin047 marked this pull request as ready for review June 5, 2026 11:23
@austin047 austin047 merged commit 7d8bbd3 into dev Jun 5, 2026
3 checks passed
@austin047 austin047 deleted the feat/ui-design-refresh branch June 5, 2026 11:23

@sourceant sourceant Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review complete. See the overview comment for a summary.

final BudgetTargetType type;
final String clientId;
const BudgetTargetInput({required this.type, required this.clientId});
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is safer to use a dedicated slugification library or a more robust regex to handle special characters and non-ASCII names to prevent invalid slugs.

Suggested change
}
String _slugify(String name) {
return name
.trim()
.toLowerCase()
.replaceAll(RegExp(r'[^a-z0-9]+'), '-')
.replaceAll(RegExp(r'^-+|-+$'), '');
}

String? transferClientId,
}) async {
return database.transaction(() async {
// Capture original tag-set before the mutation so we can also recompute

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fetching categories and transactions before the main transaction logic increases DB overhead. Consider moving this logic inside the database.transaction block or using a more optimized query to fetch only necessary IDs.

Suggested change
// Capture original tag-set before the mutation so we can also recompute
final result = await database.transaction(() async {
final originalSnapshot = await (database.select(database.transactions)
..where((t) => t.clientId.equals(id)))
.getSingleOrNull();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants