Files
sure/mobile
Lazy Bone fdc2ce1feb Add category support to transactions (#1251)
* Move debug logs button from Home to Settings page, remove refresh/logout from Home AppBar

- Remove Debug Logs, Refresh, and Sign Out buttons from DashboardScreen AppBar
- Add Debug Logs ListTile entry in SettingsScreen under app info section
- Remove unused _handleLogout method from DashboardScreen
- Remove unused log_viewer_screen.dart import from DashboardScreen

https://claude.ai/code/session_017XQZdaEwUuRS75tJMcHzB9

* Add category picker to Android transaction form

Implements category selection when creating transactions in the mobile app.
Uses the existing /api/v1/categories endpoint to fetch categories and sends
category_id when creating transactions via the API.

New files:
- Category model, CategoriesService, CategoriesProvider
Updated:
- Transaction/OfflineTransaction models with categoryId/categoryName
- TransactionsService/Provider to pass category_id
- DB schema v2 migration for category columns
- TransactionFormScreen with category dropdown in "More" section

Closes #78

https://claude.ai/code/session_01Dgj8tYrCkoUaLW2WrQ3vMJ

* Fix ambiguous Category import in CategoriesProvider

Hide Flutter's built-in Category annotation from foundation.dart
to resolve name collision with our Category model.

https://claude.ai/code/session_01Dgj8tYrCkoUaLW2WrQ3vMJ

* Add category filter on Dashboard, clear categories on data reset, fix ambiguous imports

- Add CategoryFilter widget (horizontal chip row like CurrencyFilter)
- Show category filter on Dashboard below currency filter (2nd row)
- Add "Show Category Filter" toggle in Settings > Display section
- Clear CategoriesProvider on "Clear Local Data" and "Reset Account"
- Fix Category name collision: hide Flutter's Category from material.dart
- Add getShowCategoryFilter/setShowCategoryFilter to PreferencesService

https://claude.ai/code/session_01Dgj8tYrCkoUaLW2WrQ3vMJ

* Fix Category name collision using prefixed imports

Use 'import as models' instead of 'hide Category' to avoid
undefined_hidden_name warnings with flutter/material.dart.

https://claude.ai/code/session_01Dgj8tYrCkoUaLW2WrQ3vMJ

* Fix duplicate column error in SQLite migration

Check if category_id/category_name columns exist before running
ALTER TABLE, preventing crashes when the DB was already at v2
or the migration had partially succeeded.

https://claude.ai/code/session_01Dgj8tYrCkoUaLW2WrQ3vMJ

* Move CategoryFilter from dashboard to transaction list screen

CategoryFilter was filtering accounts on the dashboard but accounts
are already grouped by type. Moved it to TransactionsListScreen where
it filters transactions by category, which is the correct placement.

https://claude.ai/code/session_01Dgj8tYrCkoUaLW2WrQ3vMJ

* Add category tag badge next to transaction name

Shows an oval-bordered category label after each transaction's
name for quick visual identification of transaction types.

https://claude.ai/code/session_01Dgj8tYrCkoUaLW2WrQ3vMJ

* Address review findings for category feature

1. Category.fromJson now recursively parses parent chain;
   displayName walks all ancestors (e.g. "Grandparent > Parent > Child")
2. CategoriesProvider.fetchCategories guards against concurrent/duplicate
   calls by checking _isLoading and _hasFetched early
3. CategoryFilter chips use displayName to distinguish subcategories
4. Transaction badge resolves full displayName from CategoriesProvider
   with overflow ellipsis for long paths
5. Offline storage preserves local category values when server response
   omits them (coalesce with ??)

https://claude.ai/code/session_01Dgj8tYrCkoUaLW2WrQ3vMJ

* Fix missing closing brace in PreferencesService causing theme_provider analyze errors

https://claude.ai/code/session_01Dgj8tYrCkoUaLW2WrQ3vMJ

* Fix sync category upload, empty-state refresh, badge reactivity, and preferences syntax

- Add categoryId to SyncService pending transaction upload payload
- Replace non-scrollable Center with ListView for empty filter state so
  RefreshIndicator works when no transactions match
- Use listen:true for CategoriesProvider in badge display so badges
  rebuild when categories finish loading
- Fix missing closing brace in PreferencesService.setShowCategoryFilter

https://claude.ai/code/session_01Dgj8tYrCkoUaLW2WrQ3vMJ

---------

Signed-off-by: Juan José Mata <juanjo.mata@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Juan José Mata <juanjo.mata@gmail.com>
2026-04-13 20:01:08 +02:00
..
2026-02-18 13:37:31 +01:00
2026-02-18 01:54:17 +01:00
2026-02-18 10:11:16 +01:00
2026-04-09 13:22:26 +02:00

Sure Mobile

A Flutter mobile application for Sure personal finance management system. This is the mobile client that connects to the Sure backend server.

About

This app is a mobile companion to the Sure personal finance management system. It provides basic functionality to:

  • Login - Authenticate with your Sure Finances server
  • View Balance - See all your accounts and their balances

For more detailed technical documentation, see docs/TECHNICAL_GUIDE.md.

Features

  • 🔐 Secure authentication with OAuth 2.0
  • 📱 Cross-platform support (Android & iOS)
  • 💰 View all linked accounts
  • 🎨 Material Design 3 with light/dark theme support
  • 🔄 Token refresh for persistent sessions
  • 🔒 Two-factor authentication (MFA) support

Requirements

  • Flutter SDK >= 3.0.0
  • Dart SDK >= 3.0.0
  • Android SDK (for Android builds)
  • Xcode (for iOS builds)

Getting Started

1. Install Flutter

Follow the official Flutter installation guide: https://docs.flutter.dev/get-started/install

2. Install Dependencies

flutter pub get

# For iOS development, also install CocoaPods dependencies
cd ios
pod install
cd ..

3. Generate App Icons

flutter pub run flutter_launcher_icons

This step generates the app icons for all platforms based on the source icon in assets/icon/app_icon.png. This is required before building the app locally.

4. Configure API Endpoint

Edit lib/services/api_config.dart to point to your Sure Finances server:

// For local development with Android emulator
static String _baseUrl = 'http://10.0.2.2:3000';

// For local development with iOS simulator
static String _baseUrl = 'http://localhost:3000';

// For production
static String _baseUrl = 'https://your-sure-server.com';

5. Run the App

# For Android
flutter run -d android

# For iOS
flutter run -d <simulator-device-UDID>
# or
flutter run -d "iPhone 17 Pro"

# For web (development only)
flutter run -d chrome

Project Structure

.
├── lib/
│   ├── main.dart              # App entry point
│   ├── models/                # Data models
│   │   ├── account.dart
│   │   ├── auth_tokens.dart
│   │   └── user.dart
│   ├── providers/             # State management
│   │   ├── auth_provider.dart
│   │   └── accounts_provider.dart
│   ├── screens/               # UI screens
│   │   ├── login_screen.dart
│   │   └── dashboard_screen.dart
│   ├── services/              # API services
│   │   ├── api_config.dart
│   │   ├── auth_service.dart
│   │   ├── accounts_service.dart
│   │   └── device_service.dart
│   └── widgets/               # Reusable widgets
│       └── account_card.dart
├── android/                   # Android configuration
├── ios/                       # iOS configuration
├── pubspec.yaml               # Dependencies
└── README.md

API Integration

This app integrates with the Sure Finances Rails API:

Authentication

  • POST /api/v1/auth/login - User authentication
  • POST /api/v1/auth/signup - User registration
  • POST /api/v1/auth/refresh - Token refresh

Accounts

  • GET /api/v1/accounts - Fetch user accounts

Transactions

  • GET /api/v1/transactions - Get all transactions (optionally filter by account_id query parameter)
  • POST /api/v1/transactions - Create a new transaction
  • PUT /api/v1/transactions/:id - Update an existing transaction
  • DELETE /api/v1/transactions/:id - Delete a transaction

Transaction POST Request Format

{
  "transaction": {
    "account_id": "2980ffb0-f595-4572-be0e-7b9b9c53949b",  // required
    "name": "test",  // required
    "date": "2025-07-15",  // required
    "amount": 100,  // optional, defaults to 0
    "currency": "AUD",  // optional, defaults to your profile currency
    "nature": "expense"  // optional, defaults to "expense", other option is "income"
  }
}

CI/CD

The app includes automated CI/CD via GitHub Actions (.github/workflows/flutter-build.yml):

  • Triggers: On push/PR to main branch when Flutter files change
  • Android Build: Generates release APK and AAB artifacts
  • iOS Build: Generates iOS release build (unsigned)
  • Quality Checks: Code analysis and tests run before building
  • TestFlight: mobile-release (mobile tags) triggers .github/workflows/ios-testflight.yml for signed App Store Connect uploads as part of one release flow

See mobile/docs/iOS_TESTFLIGHT.md for required secrets and setup.

Downloading Build Artifacts

After a successful CI run, download artifacts from the GitHub Actions workflow:

  • app-release-apk - Android APK file
  • app-release-aab - Android App Bundle (for Play Store)
  • ios-build-unsigned - iOS app bundle (unsigned, see iOS build guide for signing)

Building for Release

Android

flutter build apk --release
# or for App Bundle
flutter build appbundle --release

Android release metadata comes from pubspec.yaml (version: <name>+<code>). Keep the numeric build code increasing for every release so Android can install upgrades over older APKs.

iOS

# Ensure CocoaPods dependencies are installed first
cd ios && pod install && cd ..

# Build iOS release
flutter build ios --release

For detailed iOS build instructions, troubleshooting, and CI/CD setup, see docs/iOS_BUILD.md.

Future Expansion

This app provides a foundation for additional features:

  • Transaction history
  • Account sync
  • Budget management
  • Investment tracking
  • AI chat assistant
  • Push notifications
  • Biometric authentication

License

This project is distributed under the AGPLv3 license.