import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../core/storage/draft_storage.dart'; import 'expense_model.dart'; import 'expense_api.dart'; const expenseDraftKey = 'expense'; class ExpenseCreateState { final ExpenseModel expense; final bool isSubmitting; const ExpenseCreateState({required this.expense, this.isSubmitting = false}); ExpenseCreateState copyWith({ExpenseModel? expense, bool? isSubmitting}) { return ExpenseCreateState( expense: expense ?? this.expense, isSubmitting: isSubmitting ?? this.isSubmitting, ); } } class ExpenseCreateController extends StateNotifier { final ExpenseApi _api; ExpenseCreateController(this._api, {ExpenseModel? initial}) : super( ExpenseCreateState( expense: initial ?? ExpenseModel( id: '', expenseNo: '', createTime: DateTime.now(), updateTime: DateTime.now(), ), ), ); void updateCurrencyCode(String code) { state = state.copyWith(expense: state.expense.copyWith(currencyCode: code)); } void updateApprovedAmount(double amount) { state = state.copyWith(expense: state.expense.copyWith(approvedAmount: amount)); } void updateDetailApprovedAmount(int index, double amount) { final details = [...state.expense.details]; details[index] = details[index].copyWith(approvedAmount: amount); state = state.copyWith(expense: state.expense.copyWith(details: details)); } void updateDetailCustomerVendor(int index, String name) { final details = [...state.expense.details]; details[index] = details[index].copyWith(customerVendorName: name); state = state.copyWith(expense: state.expense.copyWith(details: details)); } void updateDetailProjectId(int index, String id) { final details = [...state.expense.details]; details[index] = details[index].copyWith(projectId: id); state = state.copyWith(expense: state.expense.copyWith(details: details)); } void updateDetailAcctSubjectId(int index, String id) { final details = [...state.expense.details]; details[index] = details[index].copyWith(acctSubjectId: id); state = state.copyWith(expense: state.expense.copyWith(details: details)); } void updateDetailOffsetAmount(int index, double amount) { final details = [...state.expense.details]; details[index] = details[index].copyWith(offsetAmount: amount); state = state.copyWith(expense: state.expense.copyWith(details: details)); } void restoreFromDraft(ExpenseModel draft, ExpenseApi api) { state = ExpenseCreateState(expense: draft); } void updatePurpose(String purpose) { state = state.copyWith(expense: state.expense.copyWith(purpose: purpose)); } void addDetail(ExpenseDetailModel detail) { final details = [...state.expense.details, detail]; state = state.copyWith(expense: state.expense.copyWith(details: details)); } void removeDetail(int index) { final details = [...state.expense.details]..removeAt(index); state = state.copyWith(expense: state.expense.copyWith(details: details)); } void recalculateAmount() { var totalAmount = 0.0; var approvedAmount = 0.0; for (final d in state.expense.details) { totalAmount += d.totalAmount; approvedAmount += d.approvedAmount; } state = state.copyWith( expense: state.expense.copyWith( totalAmount: totalAmount, approvedAmount: approvedAmount, ), ); } Future submit() async { state = state.copyWith(isSubmitting: true); try { await _api.submit(state.expense.copyWith(status: 'pending').toJson()); await DraftStorage.delete(expenseDraftKey); return true; } catch (_) { return false; } finally { state = state.copyWith(isSubmitting: false); } } Future saveDraft() async { state = state.copyWith(isSubmitting: true); try { await DraftStorage.save(expenseDraftKey, state.expense.toJson()); return true; } catch (_) { return false; } finally { state = state.copyWith(isSubmitting: false); } } static Future loadDraft() async { final data = await DraftStorage.load(expenseDraftKey); if (data == null) return null; try { return ExpenseModel.fromJson(data); } catch (_) { return null; } } static Future hasDraft() => DraftStorage.has(expenseDraftKey); static Future deleteDraft() => DraftStorage.delete(expenseDraftKey); } final expenseCreateProvider = StateNotifierProvider.autoDispose .family((ref, editId) { final api = ref.watch(expenseApiProvider); return ExpenseCreateController(api); });