app working with sandbox

This commit is contained in:
davmar
2026-09-06 21:13:30 +02:00
parent 8475abeddb
commit 773187f0af
18 changed files with 1909 additions and 100 deletions
+59
View File
@@ -0,0 +1,59 @@
/// Shared UI helpers for bank connect actions.
library;
import 'package:flutter/material.dart';
import '../providers/bank_provider.dart';
import '../screens/bank_auth_screen.dart';
Future<void> runConnectBank(BuildContext context, BankController bank) async {
final start = await bank.beginConnect();
if (!context.mounted) return;
if (start == null) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(bank.error ?? 'Could not start bank connect')),
);
return;
}
final result = await Navigator.of(context).push<BankAuthResult>(
MaterialPageRoute(
builder: (_) => BankAuthScreen(
authUrl: start.authUrl,
pendingState: start.state,
),
),
);
if (!context.mounted) return;
if (result == null) return;
if (result.error != null && result.error!.isNotEmpty) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Bank auth failed: ${result.error}')),
);
return;
}
if (!result.hasCode) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Bank redirect missing code')),
);
return;
}
final linked = await bank.completeWithCode(
code: result.code!,
state: result.state,
);
if (!context.mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
linked ? 'Bank linked' : (bank.error ?? 'Could not complete connect'),
),
),
);
}
+27 -1
View File
@@ -2,7 +2,7 @@
library;
/// Human-readable name shown in the splash screen, app bars, and About tile.
const String kAppName = 'MyApp';
const String kAppName = 'IngTrak';
/// Package / Android application id.
const String kPackageName = 'com.example.myapp';
@@ -10,6 +10,32 @@ const String kPackageName = 'com.example.myapp';
/// How long the splash screen stays visible before navigating to the shell.
const Duration kSplashDuration = Duration(seconds: 2);
/// Base URL for the personal ingtrak FastAPI backend.
///
/// Override at build/run time:
/// `flutter run --dart-define=API_BASE_URL=http://192.168.1.114:8000`
///
/// Defaults:
/// - Android emulator → `http://10.0.2.2:8000` (host loopback)
/// - iOS Simulator → `http://127.0.0.1:8000`
/// - Physical device → Mac LAN IP, e.g. `http://192.168.1.114:8000`
const String kApiBaseUrl = String.fromEnvironment(
'API_BASE_URL',
defaultValue: 'http://10.0.2.2:8000',
);
/// Enable Banking only accepts http(s) redirect URLs (not custom schemes).
/// Keep this exact value in the Control Panel and backend `REDIRECT_URI`.
/// The app opens auth in a WebView and intercepts this callback to read `code`.
const String kEnableBankingRedirectUri =
'http://localhost:8000/api/connect/callback';
/// Optional app-scheme bounce used after the http callback (not registered
/// with Enable Banking).
const String kBankRedirectScheme = 'ingtrak';
const String kBankRedirectHost = 'connected';
const String kBankRedirectUri = '$kBankRedirectScheme://$kBankRedirectHost';
/// SharedPreferences keys.
abstract final class StorageKeys {
static const themeMode = 'theme_mode';
+28
View File
@@ -57,3 +57,31 @@ String labelForThemeMode(ThemeMode mode) {
ThemeMode.system => 'System',
};
}
/// Formats a money amount with currency code, e.g. `1 234,56 EUR`.
String formatMoney(double amount, String currency) {
final sign = amount < 0 ? '-' : '';
final abs = amount.abs();
final fixed = abs.toStringAsFixed(2);
final parts = fixed.split('.');
final whole = parts[0];
final fraction = parts.length > 1 ? parts[1] : '00';
final buffer = StringBuffer();
for (var i = 0; i < whole.length; i++) {
final fromEnd = whole.length - i;
buffer.write(whole[i]);
if (fromEnd > 1 && fromEnd % 3 == 1) {
buffer.write('\u00a0');
}
}
return '$sign${buffer.toString()},$fraction $currency';
}
/// Formats an ISO date string (`yyyy-MM-dd` or full ISO) for list rows.
String formatIsoDate(String raw) {
if (raw.isEmpty) return '';
final parsed = DateTime.tryParse(raw);
if (parsed == null) return raw;
return formatDate(parsed);
}