Frontend first draft
This commit is contained in:
32
frontend/pweb/lib/providers/balance.dart
Normal file
32
frontend/pweb/lib/providers/balance.dart
Normal file
@@ -0,0 +1,32 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:pweb/services/balance.dart';
|
||||
|
||||
|
||||
class BalanceProvider with ChangeNotifier {
|
||||
final BalanceService _service;
|
||||
|
||||
BalanceProvider(this._service);
|
||||
|
||||
double? _balance;
|
||||
String? _walletName;
|
||||
String? _walletId;
|
||||
bool _isHidden = true;
|
||||
|
||||
double? get balance => _balance;
|
||||
String? get walletName => _walletName;
|
||||
String? get walletId => _walletId;
|
||||
bool get isHidden => _isHidden;
|
||||
|
||||
Future<void> loadData() async {
|
||||
_balance = await _service.getBalance();
|
||||
_walletName = await _service.getWalletName();
|
||||
_walletId = await _service.getWalletId();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void toggleVisibility() {
|
||||
_isHidden = !_isHidden;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
15
frontend/pweb/lib/providers/carousel.dart
Normal file
15
frontend/pweb/lib/providers/carousel.dart
Normal file
@@ -0,0 +1,15 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
|
||||
class CarouselIndexProvider extends ChangeNotifier {
|
||||
int _currentIndex = 0;
|
||||
|
||||
int get currentIndex => _currentIndex;
|
||||
|
||||
void updateIndex(int index) {
|
||||
if (_currentIndex != index) {
|
||||
_currentIndex = index;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
}
|
||||
24
frontend/pweb/lib/providers/mock_payment.dart
Normal file
24
frontend/pweb/lib/providers/mock_payment.dart
Normal file
@@ -0,0 +1,24 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
|
||||
class MockPaymentProvider with ChangeNotifier {
|
||||
double _amount = 10.0;
|
||||
bool _payerCoversFee = true;
|
||||
|
||||
double get amount => _amount;
|
||||
bool get payerCoversFee => _payerCoversFee;
|
||||
|
||||
double get fee => _amount * 0.05;
|
||||
double get total => payerCoversFee ? (_amount + fee) : _amount;
|
||||
double get recipientGets => payerCoversFee ? _amount : (_amount - fee);
|
||||
|
||||
void setAmount(double value) {
|
||||
_amount = value;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void setPayerCoversFee(bool value) {
|
||||
_payerCoversFee = value;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
99
frontend/pweb/lib/providers/page_selector.dart
Normal file
99
frontend/pweb/lib/providers/page_selector.dart
Normal file
@@ -0,0 +1,99 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:pshared/models/payment/type.dart';
|
||||
import 'package:pshared/models/recipient/recipient.dart';
|
||||
|
||||
import 'package:pweb/models/wallet.dart';
|
||||
import 'package:pweb/providers/wallets.dart';
|
||||
import 'package:pweb/widgets/sidebar/destinations.dart';
|
||||
import 'package:pweb/services/amplitude.dart';
|
||||
import 'package:pweb/providers/recipient.dart';
|
||||
|
||||
|
||||
class PageSelectorProvider extends ChangeNotifier {
|
||||
PayoutDestination _selected = PayoutDestination.dashboard;
|
||||
PaymentType? _type;
|
||||
bool _cameFromRecipientList = false;
|
||||
|
||||
final RecipientProvider? recipientProvider;
|
||||
final WalletsProvider? walletsProvider;
|
||||
|
||||
PayoutDestination get selected => _selected;
|
||||
PaymentType? get type => _type;
|
||||
|
||||
PageSelectorProvider({this.recipientProvider, this.walletsProvider});
|
||||
|
||||
void selectPage(PayoutDestination dest) {
|
||||
_selected = dest;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void selectRecipient(Recipient? recipient, {bool fromList = false}) {
|
||||
if (recipientProvider != null) {
|
||||
recipientProvider!.selectRecipient(recipient);
|
||||
_cameFromRecipientList = fromList;
|
||||
_selected = PayoutDestination.payment;
|
||||
notifyListeners();
|
||||
} else {
|
||||
debugPrint("RecipientProvider is null — cannot select recipient");
|
||||
}
|
||||
}
|
||||
|
||||
void editRecipient(Recipient? recipient, {bool fromList = false}) {
|
||||
if (recipientProvider != null) {
|
||||
recipientProvider!.selectRecipient(recipient);
|
||||
_cameFromRecipientList = fromList;
|
||||
_selected = PayoutDestination.addrecipient;
|
||||
notifyListeners();
|
||||
} else {
|
||||
debugPrint("RecipientProvider is null — cannot select recipient");
|
||||
}
|
||||
}
|
||||
|
||||
void goToAddRecipient() {
|
||||
if (recipientProvider != null) {
|
||||
AmplitudeService.recipientAddStarted();
|
||||
recipientProvider!.selectRecipient(null);
|
||||
_selected = PayoutDestination.addrecipient;
|
||||
_cameFromRecipientList = false;
|
||||
notifyListeners();
|
||||
} else {
|
||||
debugPrint("RecipientProvider is null — cannot go to add recipient");
|
||||
}
|
||||
}
|
||||
|
||||
void startPaymentWithoutRecipient(PaymentType type) {
|
||||
if (recipientProvider != null) {
|
||||
recipientProvider!.selectRecipient(null);
|
||||
}
|
||||
_type = type;
|
||||
_cameFromRecipientList = false;
|
||||
_selected = PayoutDestination.payment;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void goBackFromPayment() {
|
||||
_selected = _cameFromRecipientList
|
||||
? PayoutDestination.recipients
|
||||
: PayoutDestination.dashboard;
|
||||
_type = null;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void goBackFromWalletEdit() {
|
||||
selectPage(PayoutDestination.methods);
|
||||
}
|
||||
|
||||
void selectWallet(Wallet wallet) {
|
||||
if (walletsProvider != null) {
|
||||
walletsProvider!.selectWallet(wallet);
|
||||
_selected = PayoutDestination.editwallet;
|
||||
notifyListeners();
|
||||
} else {
|
||||
debugPrint("RecipientProvider is null — cannot select wallet");
|
||||
}
|
||||
}
|
||||
|
||||
Recipient? get selectedRecipient => recipientProvider?.selectedRecipient;
|
||||
Wallet? get selectedWallet => walletsProvider?.selectedWallet;
|
||||
}
|
||||
66
frontend/pweb/lib/providers/payment_methods.dart
Normal file
66
frontend/pweb/lib/providers/payment_methods.dart
Normal file
@@ -0,0 +1,66 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:pshared/models/payment/methods/type.dart';
|
||||
|
||||
import 'package:pweb/services/payments/payment_methods.dart';
|
||||
|
||||
|
||||
class PaymentMethodsProvider extends ChangeNotifier {
|
||||
final PaymentMethodsService service;
|
||||
|
||||
List<PaymentMethod> _methods = [];
|
||||
PaymentMethod? _selectedMethod;
|
||||
bool _isLoading = false;
|
||||
String? _error;
|
||||
|
||||
PaymentMethodsProvider({required this.service});
|
||||
|
||||
List<PaymentMethod> get methods => _methods;
|
||||
PaymentMethod? get selectedMethod => _selectedMethod;
|
||||
bool get isLoading => _isLoading;
|
||||
String? get error => _error;
|
||||
|
||||
Future<void> loadMethods() async {
|
||||
_isLoading = true;
|
||||
_error = null;
|
||||
notifyListeners();
|
||||
|
||||
try {
|
||||
_methods = await service.fetchMethods();
|
||||
_selectedMethod = _methods.firstWhere((m) => m.isMain, orElse: () => _methods.first);
|
||||
} catch (e) {
|
||||
_error = e.toString();
|
||||
}
|
||||
|
||||
_isLoading = false;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void selectMethod(PaymentMethod method) {
|
||||
_selectedMethod = method;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void deleteMethod(PaymentMethod method) {
|
||||
_methods.remove(method);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void reorderMethods(int oldIndex, int newIndex) {
|
||||
if (newIndex > oldIndex) newIndex--;
|
||||
final item = _methods.removeAt(oldIndex);
|
||||
_methods.insert(newIndex, item);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void toggleEnabled(PaymentMethod method, bool value) {
|
||||
method.isEnabled = value;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void makeMain(PaymentMethod method) {
|
||||
for (final m in _methods) m.isMain = false;
|
||||
method.isMain = true;
|
||||
selectMethod(method);
|
||||
}
|
||||
}
|
||||
80
frontend/pweb/lib/providers/recipient.dart
Normal file
80
frontend/pweb/lib/providers/recipient.dart
Normal file
@@ -0,0 +1,80 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import 'package:pshared/models/recipient/filter.dart';
|
||||
import 'package:pshared/models/recipient/recipient.dart';
|
||||
import 'package:pshared/models/recipient/status.dart';
|
||||
|
||||
import 'package:pweb/services/recipient/recipient.dart';
|
||||
|
||||
|
||||
class RecipientProvider extends ChangeNotifier {
|
||||
final RecipientService _service;
|
||||
|
||||
RecipientProvider(this._service);
|
||||
|
||||
List<Recipient> _recipients = [];
|
||||
bool _isLoading = false;
|
||||
String? _error;
|
||||
RecipientFilter _selectedFilter = RecipientFilter.all;
|
||||
String _query = '';
|
||||
|
||||
Recipient? _selectedRecipient;
|
||||
|
||||
List<Recipient> get recipients => _recipients;
|
||||
bool get isLoading => _isLoading;
|
||||
String? get error => _error;
|
||||
RecipientFilter get selectedFilter => _selectedFilter;
|
||||
String get query => _query;
|
||||
Recipient? get selectedRecipient => _selectedRecipient;
|
||||
|
||||
List<Recipient> get filteredRecipients {
|
||||
List<Recipient> filtered = _recipients.where((r) {
|
||||
switch (_selectedFilter) {
|
||||
case RecipientFilter.ready:
|
||||
return r.status == RecipientStatus.ready;
|
||||
case RecipientFilter.registered:
|
||||
return r.status == RecipientStatus.registered;
|
||||
case RecipientFilter.notRegistered:
|
||||
return r.status == RecipientStatus.notRegistered;
|
||||
case RecipientFilter.all:
|
||||
return true;
|
||||
}
|
||||
}).toList();
|
||||
|
||||
if (_query.isNotEmpty) {
|
||||
filtered = filtered.where((r) => r.matchesQuery(_query)).toList();
|
||||
}
|
||||
|
||||
return filtered;
|
||||
}
|
||||
|
||||
Future<void> loadRecipients() async {
|
||||
_isLoading = true;
|
||||
_error = null;
|
||||
notifyListeners();
|
||||
|
||||
try {
|
||||
_recipients = await _service.fetchRecipients();
|
||||
} catch (e) {
|
||||
_error = e.toString();
|
||||
} finally {
|
||||
_isLoading = false;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
void setFilter(RecipientFilter filter) {
|
||||
_selectedFilter = filter;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void setQuery(String query) {
|
||||
_query = query.trim().toLowerCase();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void selectRecipient(Recipient? recipient) {
|
||||
_selectedRecipient = recipient;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
31
frontend/pweb/lib/providers/template.dart
Normal file
31
frontend/pweb/lib/providers/template.dart
Normal file
@@ -0,0 +1,31 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
|
||||
class FutureProviderTemplate<T> extends ChangeNotifier {
|
||||
FutureProviderTemplate({required this.loader});
|
||||
|
||||
final Future<T> Function() loader;
|
||||
|
||||
T? _data;
|
||||
bool _isLoading = false;
|
||||
String? _error;
|
||||
|
||||
T? get data => _data;
|
||||
bool get isLoading => _isLoading;
|
||||
String? get error => _error;
|
||||
|
||||
Future<void> load() async {
|
||||
_isLoading = true;
|
||||
_error = null;
|
||||
notifyListeners();
|
||||
|
||||
try {
|
||||
_data = await loader();
|
||||
} catch (e) {
|
||||
_error = e.toString();
|
||||
}
|
||||
|
||||
_isLoading = false;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
38
frontend/pweb/lib/providers/two_factor.dart
Normal file
38
frontend/pweb/lib/providers/two_factor.dart
Normal file
@@ -0,0 +1,38 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:pweb/services/auth.dart';
|
||||
|
||||
|
||||
class TwoFactorProvider extends ChangeNotifier {
|
||||
final AuthenticationService _authService;
|
||||
|
||||
TwoFactorProvider(this._authService);
|
||||
|
||||
bool _isSubmitting = false;
|
||||
bool _hasError = false;
|
||||
bool _verificationSuccess = false;
|
||||
|
||||
bool get isSubmitting => _isSubmitting;
|
||||
bool get hasError => _hasError;
|
||||
bool get verificationSuccess => _verificationSuccess;
|
||||
|
||||
|
||||
Future<void> submitCode(String code) async {
|
||||
_isSubmitting = true;
|
||||
_hasError = false;
|
||||
_verificationSuccess = false;
|
||||
notifyListeners();
|
||||
|
||||
try {
|
||||
final success = await _authService.verifyTwoFactorCode(code);
|
||||
if (success) {
|
||||
_verificationSuccess = true;
|
||||
}
|
||||
} catch (e) {
|
||||
_hasError = true;
|
||||
} finally {
|
||||
_isSubmitting = false;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
}
|
||||
10
frontend/pweb/lib/providers/upload_history.dart
Normal file
10
frontend/pweb/lib/providers/upload_history.dart
Normal file
@@ -0,0 +1,10 @@
|
||||
import 'package:pshared/models/payment/upload_history_item.dart';
|
||||
|
||||
import 'package:pweb/providers/template.dart';
|
||||
import 'package:pweb/services/payments/upload_history.dart';
|
||||
|
||||
|
||||
class UploadHistoryProvider extends FutureProviderTemplate<List<UploadHistoryItem>> {
|
||||
UploadHistoryProvider({required UploadHistoryService service})
|
||||
: super(loader: service.fetchHistory);
|
||||
}
|
||||
126
frontend/pweb/lib/providers/wallets.dart
Normal file
126
frontend/pweb/lib/providers/wallets.dart
Normal file
@@ -0,0 +1,126 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:pweb/models/wallet.dart';
|
||||
import 'package:pweb/services/wallets.dart';
|
||||
|
||||
|
||||
class WalletsProvider with ChangeNotifier {
|
||||
final WalletsService _service;
|
||||
|
||||
WalletsProvider(this._service);
|
||||
|
||||
List<Wallet>? _wallets;
|
||||
bool _isLoading = false;
|
||||
String? _error;
|
||||
Wallet? _selectedWallet;
|
||||
bool _isHidden = true;
|
||||
|
||||
List<Wallet>? get wallets => _wallets;
|
||||
bool get isLoading => _isLoading;
|
||||
String? get error => _error;
|
||||
Wallet? get selectedWallet => _selectedWallet;
|
||||
bool get isHidden => _isHidden;
|
||||
|
||||
|
||||
|
||||
|
||||
void selectWallet(Wallet wallet) {
|
||||
_selectedWallet = wallet;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> loadData() async {
|
||||
_isLoading = true;
|
||||
_error = null;
|
||||
notifyListeners();
|
||||
|
||||
try {
|
||||
_wallets = await _service.getWallets();
|
||||
} catch (e) {
|
||||
_error = e.toString();
|
||||
} finally {
|
||||
_isLoading = false;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
Future<Wallet?> getWalletById(String walletId) async {
|
||||
_isLoading = true;
|
||||
_error = null;
|
||||
notifyListeners();
|
||||
|
||||
try {
|
||||
final wallet = await _service.getWallet(walletId);
|
||||
return wallet;
|
||||
} catch (e) {
|
||||
_error = e.toString();
|
||||
return null;
|
||||
} finally {
|
||||
_isLoading = false;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
void updateName(String walletRef, String newName) {
|
||||
final index = _wallets?.indexWhere((w) => w.id == walletRef);
|
||||
if (index != null && index >= 0) {
|
||||
_wallets![index] = _wallets![index].copyWith(name: newName);
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void updateBalance(String walletRef, double newBalance) {
|
||||
final index = _wallets?.indexWhere((w) => w.id == walletRef);
|
||||
if (index != null && index >= 0) {
|
||||
_wallets![index] = _wallets![index].copyWith(balance: newBalance);
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> updateWallet(Wallet wallet) async {
|
||||
try {
|
||||
await _service.updateWallet();
|
||||
final index = _wallets?.indexWhere((w) => w.id == wallet.id);
|
||||
if (index != null && index >= 0) {
|
||||
_wallets![index] = wallet;
|
||||
notifyListeners();
|
||||
}
|
||||
} catch (e) {
|
||||
_error = e.toString();
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Future<void> addWallet(Wallet wallet) async {
|
||||
try {
|
||||
final newWallet = await _service.createWallet(); // Pass the wallet parameter
|
||||
_wallets = [...?_wallets, ]; // Add the new wallet
|
||||
notifyListeners();
|
||||
} catch (e) {
|
||||
_error = e.toString();
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> deleteWallet(String walletId) async {
|
||||
try {
|
||||
await _service.deleteWallet(); // Pass the walletId parameter
|
||||
_wallets?.removeWhere((w) => w.id == walletId);
|
||||
notifyListeners();
|
||||
} catch (e) {
|
||||
_error = e.toString();
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
void toggleVisibility(String walletId) {
|
||||
final index = _wallets?.indexWhere((w) => w.id == walletId);
|
||||
if (index != null && index >= 0) {
|
||||
final wallet = _wallets![index];
|
||||
_wallets![index] = wallet.copyWith(isHidden: !wallet.isHidden);
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user