import 'package:dio/dio.dart'; import 'package:fintracker_api/fintracker_api.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../core/api/api_client.dart'; import '../../core/auth/auth_controller.dart'; import 'providers.dart'; /// The brokers whose accounts are created by hand: T-Invest accounts come from the sync. const _brokerChoices = [ (Broker.sber, 'Сбер'), (Broker.vtb, 'ВТБ'), (Broker.other, 'Другой (CSV)'), ]; /// Maps the import contract's broker key (`sber | vtb | csv`) onto a creatable broker. Broker? brokerFromImportKey(String? key) => switch (key) { 'sber' => Broker.sber, 'vtb' => Broker.vtb, 'csv' => Broker.other, _ => null, }; /// Asks for the details of a broker account and creates it. Returns the new account, or null /// when cancelled or when the server refused (the reason is shown in the dialog). Future showAccountCreateDialog( BuildContext context, { Broker? broker, String? sourceId, String? name, }) => showDialog( context: context, builder: (_) => _AccountCreateDialog(broker: broker, sourceId: sourceId, name: name), ); class _AccountCreateDialog extends ConsumerStatefulWidget { const _AccountCreateDialog({this.broker, this.sourceId, this.name}); final Broker? broker; final String? sourceId; final String? name; @override ConsumerState<_AccountCreateDialog> createState() => _AccountCreateDialogState(); } class _AccountCreateDialogState extends ConsumerState<_AccountCreateDialog> { final _formKey = GlobalKey(); late final _name = TextEditingController(text: widget.name ?? ''); late final _sourceId = TextEditingController(text: widget.sourceId ?? ''); final _currency = TextEditingController(text: 'RUB'); late Broker _broker = widget.broker ?? Broker.sber; bool _saving = false; String? _error; @override void dispose() { _name.dispose(); _sourceId.dispose(); _currency.dispose(); super.dispose(); } Future _save() async { if (!(_formKey.currentState?.validate() ?? false)) return; setState(() { _saving = true; _error = null; }); try { final r = await ref .read(apiProvider) .getAccountsApi() .accountsCreate( accountCreate: AccountCreate( name: _name.text.trim(), broker: _broker, sourceId: _sourceId.text.trim(), currency: _currency.text.trim().toUpperCase(), ), ); ref.invalidate(accountsProvider); if (mounted) Navigator.of(context).pop(r.data); } on DioException catch (e) { if (mounted) { setState(() { _saving = false; _error = problemMessage(e); }); } } } @override Widget build(BuildContext context) { return AlertDialog( title: const Text('Новый брокерский счёт'), content: SizedBox( width: 420, child: Form( key: _formKey, child: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, children: [ TextFormField( controller: _name, decoration: const InputDecoration(labelText: 'Название'), validator: (v) => (v ?? '').trim().isEmpty ? 'Обязательное поле' : null, ), const SizedBox(height: 12), DropdownButtonFormField( initialValue: _broker, decoration: const InputDecoration(labelText: 'Брокер'), items: [ for (final (b, label) in _brokerChoices) DropdownMenuItem(value: b, child: Text(label)), ], onChanged: (b) => setState(() => _broker = b ?? _broker), ), const SizedBox(height: 12), TextFormField( controller: _sourceId, decoration: const InputDecoration( labelText: 'Номер договора', helperText: 'Как напечатан в отчёте брокера — по нему импорт находит счёт', helperMaxLines: 2, ), validator: (v) => (v ?? '').trim().isEmpty ? 'Обязательное поле' : null, ), const SizedBox(height: 12), TextFormField( controller: _currency, textCapitalization: TextCapitalization.characters, decoration: const InputDecoration(labelText: 'Валюта'), validator: (v) => (v ?? '').trim().length == 3 ? null : 'Три буквы, например RUB', ), if (_error != null) ...[ const SizedBox(height: 12), Text( _error!, style: TextStyle( color: Theme.of(context).colorScheme.error, ), ), ], ], ), ), ), ), actions: [ TextButton( onPressed: _saving ? null : () => Navigator.of(context).pop(), child: const Text('Отмена'), ), FilledButton( onPressed: _saving ? null : _save, child: const Text('Создать'), ), ], ); } }