Basic wallet page

This commit is contained in:
LittleSheep 2025-01-29 15:18:35 +08:00
parent 9471fe40fe
commit 73b82f65e4
12 changed files with 1093 additions and 9 deletions

View File

@ -15,11 +15,11 @@ body:json {
"client_id": "{{third_client_id}}",
"client_secret":"{{third_client_tk}}",
"type": "general",
"subject": "Merry Christmas!",
"subject": "新年快乐!",
"subtitle": "一条来自 Solar Network 团队的信息",
"content": "今天是 12 月 25 日 (UTC+8),小羊祝您圣诞快乐 🎄",
"content": "今天是农历正月初一,小羊祝您新年快乐 🎉",
"metadata": {
"image": "6EqsYQwmFRCkbmhR"
"image": "D2EDbcrsTugs3xk5"
},
"priority": 10
}

View File

@ -1,8 +1,8 @@
vars {
endpoint: https://api.sn.solsynth.dev
third_client_id: alphabot
atk: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL3NvbHN5bnRoLmRldiIsInN1YiI6IjEiLCJhdWQiOlsic29sYXItbmV0d29yayJdLCJleHAiOjE3MzgwODE2OTYsIm5iZiI6MTczODA3ODY5NiwiaWF0IjoxNzM4MDc4Njk2LCJqdGkiOiI1Yzg2MTYxZC00MTZjLTQwNDYtOWFlNS04YWZhNGIyZjdlMTkiLCJzZWQiOiIyMTciLCJ0eXAiOiJhY2Nlc3MifQ.LdLZ6FLb8IqPI__U8sT6VyxK5S_ZgwVGGL-tk01tK9C19wnbFFThPDgga1pJu_VVVpGVxzvMyd-3tBotzLMB5LjhYbtPOJakN2oug1HAgJ8zfc1clORlpHlUVisaiQtl3ZkWtzxni8etZDhJpqHU65IGQG01TO6PZGLgxKkMel4gGeeKhHpg9Q4Eewr3Pbl_wJkHVChJ9IJPmgioc_CACE10nEHZgwptCbndUz3AbIDOG9qW-7ZoprtKoRwAcuUXANK277VvdBRhwQjqKBREqVeMXP_Rv37jDPYhWpfS6HtKoHElZOTJG-69S2Zc3HyHlPJAPlzLAjGPoxScky79Gg
}
vars:secret [
atk,
third_client_tk
]

View File

@ -18,6 +18,7 @@
"screenAbuseReport": "Abuse Reports",
"screenSettings": "Settings",
"screenAccountSettings": "Account Settings",
"screenFactorSettings": "Auth Factors",
"screenAccountWallet": "Wallet",
"screenNews": "News",
"screenAlbum": "Album",
@ -30,7 +31,6 @@
"screenNotification": "Notification",
"screenPostSearch": "Search Posts",
"screenFriend": "Friends",
"screenFactorSettings": "Auth Factors",
"dialogOkay": "Okay",
"dialogCancel": "Cancel",
"dialogConfirm": "Confirm",
@ -592,5 +592,14 @@
"totpPostSetupDescription": "Scan the QR Code below with Google Authenticator, Microsoft Authenticator, 1Password, Authy, Bitwarden or any of kind of authenticator app which supports TOTP.",
"totpNeverShare": "Never share this QR Code",
"needHelp": "Need Help?",
"needHelpLaunch": "Check out our Goatpedia!"
"needHelpLaunch": "Check out our Goatpedia!",
"walletCreate": "Create a Wallet",
"walletCreateSubtitle": "Create a wallet to start using Solar Coins",
"walletCreateTerms": "By creating a wallet, you agree to Solar Wallet's Extra Terms of Service.",
"walletCreatePassword": "Set a payment password for your new wallet below",
"walletCurrencyShort": "Credit",
"walletCurrency": {
"one": "{} Social Credit Point",
"other": "{} Social Credit Points"
}
}

View File

@ -16,6 +16,7 @@
"screenAbuseReport": "滥用检举",
"screenSettings": "设置",
"screenAccountSettings": "账号设置",
"screenFactorSettings": "验证因子",
"screenAccountWallet": "钱包",
"screenNews": "新闻",
"screenAlbum": "相册",
@ -589,5 +590,10 @@
"totpPostSetupDescription": "使用 Google Authenticator, Microsoft Authenticator, 1Password, Authy, Bitwarden 或其他支持 TOTP 的验证器扫描本 QR Code 来添加。",
"totpNeverShare": "永远不要分享这个 QR Code",
"needHelp": "需要帮助?",
"needHelpLaunch": "查看我们的山羊维基!"
"needHelpLaunch": "查看我们的山羊维基!",
"walletCurrencyShort": "信用点",
"walletCurrency": {
"one": "{} 社会信用点",
"other": "{} 社会信用点"
}
}

View File

@ -33,6 +33,7 @@ import 'package:surface/screens/realm/manage.dart';
import 'package:surface/screens/realm/realm_detail.dart';
import 'package:surface/screens/settings.dart';
import 'package:surface/screens/sharing.dart';
import 'package:surface/screens/wallet.dart';
import 'package:surface/types/post.dart';
import 'package:surface/widgets/about.dart';
import 'package:surface/widgets/navigation/app_scaffold.dart';
@ -99,6 +100,11 @@ final _appRoutes = [
],
),
GoRoute(path: '/account', name: 'account', builder: (context, state) => const AccountScreen(), routes: [
GoRoute(
path: '/wallet',
name: 'accountWallet',
builder: (context, state) => const WalletScreen(),
),
GoRoute(
path: '/settings',
name: 'accountSettings',

View File

@ -144,6 +144,16 @@ class _AuthorizedAccountScreen extends StatelessWidget {
GoRouter.of(context).pushNamed('factorSettings');
},
),
ListTile(
title: Text('accountWallet').tr(),
subtitle: Text('accountWalletSubtitle').tr(),
contentPadding: const EdgeInsets.symmetric(horizontal: 24),
leading: const Icon(Symbols.wallet),
trailing: const Icon(Symbols.chevron_right),
onTap: () {
GoRouter.of(context).pushNamed('accountWallet');
},
),
ListTile(
title: Text('accountSettings').tr(),
subtitle: Text('accountSettingsSubtitle').tr(),

View File

@ -238,7 +238,7 @@ class _FactorNewDialogState extends State<_FactorNewDialog> {
class _FactorTotpFactorDialog extends StatelessWidget {
final SnAuthFactor factor;
const _FactorTotpFactorDialog({super.key, required this.factor});
const _FactorTotpFactorDialog({required this.factor});
@override
Widget build(BuildContext context) {

View File

@ -412,8 +412,9 @@ class _LoginLookupScreenState extends State<_LoginLookupScreen> {
await sn.client.post('/cgi/id/users/me/password-reset', data: {
'user_id': lookupResp.data['id'],
});
if (mounted)
if (mounted) {
context.showModalDialog('done'.tr(), 'signinResetPasswordSent'.tr());
}
} catch (err) {
if (mounted) context.showErrorDialog(err);
} finally {

284
lib/screens/wallet.dart Normal file
View File

@ -0,0 +1,284 @@
import 'dart:convert';
import 'dart:developer';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:material_symbols_icons/material_symbols_icons.dart';
import 'package:provider/provider.dart';
import 'package:styled_widget/styled_widget.dart';
import 'package:surface/providers/sn_network.dart';
import 'package:surface/types/wallet.dart';
import 'package:surface/widgets/dialog.dart';
import 'package:surface/widgets/loading_indicator.dart';
import 'package:surface/widgets/navigation/app_scaffold.dart';
import 'package:very_good_infinite_list/very_good_infinite_list.dart';
class WalletScreen extends StatefulWidget {
const WalletScreen({super.key});
@override
State<WalletScreen> createState() => _WalletScreenState();
}
class _WalletScreenState extends State<WalletScreen> {
bool _isBusy = false;
SnWallet? _wallet;
Future<void> _fetchWallet() async {
try {
setState(() => _isBusy = true);
final sn = context.read<SnNetworkProvider>();
final resp = await sn.client.get('/cgi/wa/wallets/me');
_wallet = SnWallet.fromJson(resp.data);
} catch (err) {
if (!mounted) return;
context.showErrorDialog(err);
} finally {
setState(() => _isBusy = false);
}
}
@override
void initState() {
super.initState();
_fetchWallet();
}
@override
Widget build(BuildContext context) {
return AppScaffold(
appBar: AppBar(
leading: PageBackButton(),
title: Text('screenAccountWallet').tr(),
),
body: Column(
children: [
LoadingIndicator(isActive: _isBusy),
if (_wallet == null)
Expanded(
child: _CreateWalletWidget(
onCreate: () {
_fetchWallet();
},
),
)
else
Card(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
CircleAvatar(
radius: 28,
child: Icon(Symbols.wallet, size: 28),
),
const Gap(12),
SizedBox(width: double.infinity),
Text(
NumberFormat.compactCurrency(
locale: EasyLocalization.of(context)!.currentLocale.toString(),
symbol: '${'walletCurrencyShort'.tr()} ',
decimalDigits: 2,
).format(double.parse(_wallet!.balance)),
style: Theme.of(context).textTheme.titleLarge,
),
Text('walletCurrency'.plural(double.parse(_wallet!.balance))),
],
).padding(horizontal: 20, vertical: 24),
),
if (_wallet != null) Expanded(child: _WalletTransactionList(myself: _wallet!)),
],
),
);
}
}
class _WalletTransactionList extends StatefulWidget {
final SnWallet myself;
const _WalletTransactionList({required this.myself});
@override
State<_WalletTransactionList> createState() => _WalletTransactionListState();
}
class _WalletTransactionListState extends State<_WalletTransactionList> {
bool _isBusy = false;
int? _totalCount;
final List<SnTransaction> _transactions = List.empty(growable: true);
Future<void> _fetchTransactions() async {
try {
setState(() => _isBusy = true);
final sn = context.read<SnNetworkProvider>();
final resp = await sn.client.get('/cgi/wa/transactions/me', queryParameters: {
'take': 10,
'offset': _transactions.length,
});
_totalCount = resp.data['count'];
_transactions.addAll(
resp.data['data']?.map((e) => SnTransaction.fromJson(e)).cast<SnTransaction>() ?? [],
);
} catch (err) {
if (!mounted) return;
context.showErrorDialog(err);
} finally {
setState(() => _isBusy = false);
}
}
@override
void initState() {
super.initState();
_fetchTransactions();
}
@override
Widget build(BuildContext context) {
return MediaQuery.removePadding(
context: context,
removeTop: true,
child: RefreshIndicator(
onRefresh: _fetchTransactions,
child: InfiniteList(
itemCount: _transactions.length,
isLoading: _isBusy,
hasReachedMax: _totalCount != null && _transactions.length >= _totalCount!,
onFetchData: () {
_fetchTransactions();
},
itemBuilder: (context, idx) {
final ele = _transactions[idx];
final isIncoming = ele.payeeId == widget.myself.id;
return ListTile(
leading: isIncoming ? const Icon(Symbols.call_received) : const Icon(Symbols.call_made),
title: Text(
'${isIncoming ? '+' : '-'}${ele.amount} ${'walletCurrencyShort'.tr()}',
style: TextStyle(color: isIncoming ? Colors.green : Colors.red),
),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(ele.remark),
const Gap(2),
Text(
DateFormat(
null,
EasyLocalization.of(context)!.currentLocale.toString(),
).format(ele.createdAt),
style: Theme.of(context).textTheme.labelSmall,
),
],
),
contentPadding: const EdgeInsets.symmetric(horizontal: 24),
);
},
),
),
);
}
}
class _CreateWalletWidget extends StatefulWidget {
final Function()? onCreate;
const _CreateWalletWidget({required this.onCreate});
@override
State<_CreateWalletWidget> createState() => _CreateWalletWidgetState();
}
class _CreateWalletWidgetState extends State<_CreateWalletWidget> {
bool _isBusy = false;
Future<void> _createWallet() async {
final TextEditingController passwordController = TextEditingController();
final password = await showDialog<String?>(
context: context,
builder: (ctx) => AlertDialog(
title: Text('walletCreate').tr(),
content: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text('walletCreatePassword').tr(),
const Gap(8),
TextField(
autofocus: true,
obscureText: true,
controller: passwordController,
decoration: InputDecoration(
labelText: 'fieldPassword'.tr(),
),
),
],
),
actions: [
TextButton(
onPressed: () => Navigator.of(ctx).pop(),
child: Text('cancel').tr(),
),
TextButton(
onPressed: () {
Navigator.of(ctx).pop(passwordController.text);
},
child: Text('next').tr(),
),
],
),
);
WidgetsBinding.instance.addPostFrameCallback((_) {
passwordController.dispose();
});
if (password == null || password.isEmpty) return;
if (!mounted) return;
try {
setState(() => _isBusy = true);
final sn = context.read<SnNetworkProvider>();
await sn.client.post('/cgi/wa/wallets/me', data: {
'password': password,
});
} catch (err) {
if (!mounted) return;
context.showErrorDialog(err);
} finally {
setState(() => _isBusy = false);
}
}
@override
Widget build(BuildContext context) {
return Center(
child: Container(
constraints: const BoxConstraints(maxWidth: 380),
child: Card(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
CircleAvatar(
radius: 28,
child: Icon(Symbols.add, size: 28),
),
const Gap(12),
Text('walletCreate', style: Theme.of(context).textTheme.titleLarge).tr(),
Text('walletCreateSubtitle', style: Theme.of(context).textTheme.bodyMedium).tr(),
const Gap(4),
Text('walletCreateTerms', style: Theme.of(context).textTheme.bodySmall).tr(),
const Gap(8),
Align(
alignment: Alignment.centerRight,
child: TextButton(
onPressed: _isBusy ? null : () => _createWallet(),
child: Text('next').tr(),
),
),
],
).padding(horizontal: 20, vertical: 24),
),
),
);
}
}

37
lib/types/wallet.dart Normal file
View File

@ -0,0 +1,37 @@
import 'package:freezed_annotation/freezed_annotation.dart';
part 'wallet.freezed.dart';
part 'wallet.g.dart';
@freezed
class SnWallet with _$SnWallet {
const factory SnWallet({
required int id,
required DateTime createdAt,
required DateTime updatedAt,
required DateTime? deletedAt,
required String balance,
required String password,
required int accountId,
}) = _SnWallet;
factory SnWallet.fromJson(Map<String, dynamic> json) => _$SnWalletFromJson(json);
}
@freezed
class SnTransaction with _$SnTransaction {
const factory SnTransaction({
required int id,
required DateTime createdAt,
required DateTime updatedAt,
required DateTime? deletedAt,
required String remark,
required String amount,
required SnWallet? payer,
required SnWallet? payee,
required int? payerId,
required int? payeeId,
}) = _SnTransaction;
factory SnTransaction.fromJson(Map<String, dynamic> json) => _$SnTransactionFromJson(json);
}

View File

@ -0,0 +1,666 @@
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'wallet.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
SnWallet _$SnWalletFromJson(Map<String, dynamic> json) {
return _SnWallet.fromJson(json);
}
/// @nodoc
mixin _$SnWallet {
int get id => throw _privateConstructorUsedError;
DateTime get createdAt => throw _privateConstructorUsedError;
DateTime get updatedAt => throw _privateConstructorUsedError;
DateTime? get deletedAt => throw _privateConstructorUsedError;
String get balance => throw _privateConstructorUsedError;
String get password => throw _privateConstructorUsedError;
int get accountId => throw _privateConstructorUsedError;
/// Serializes this SnWallet to a JSON map.
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
/// Create a copy of SnWallet
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
$SnWalletCopyWith<SnWallet> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $SnWalletCopyWith<$Res> {
factory $SnWalletCopyWith(SnWallet value, $Res Function(SnWallet) then) =
_$SnWalletCopyWithImpl<$Res, SnWallet>;
@useResult
$Res call(
{int id,
DateTime createdAt,
DateTime updatedAt,
DateTime? deletedAt,
String balance,
String password,
int accountId});
}
/// @nodoc
class _$SnWalletCopyWithImpl<$Res, $Val extends SnWallet>
implements $SnWalletCopyWith<$Res> {
_$SnWalletCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of SnWallet
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? id = null,
Object? createdAt = null,
Object? updatedAt = null,
Object? deletedAt = freezed,
Object? balance = null,
Object? password = null,
Object? accountId = null,
}) {
return _then(_value.copyWith(
id: null == id
? _value.id
: id // ignore: cast_nullable_to_non_nullable
as int,
createdAt: null == createdAt
? _value.createdAt
: createdAt // ignore: cast_nullable_to_non_nullable
as DateTime,
updatedAt: null == updatedAt
? _value.updatedAt
: updatedAt // ignore: cast_nullable_to_non_nullable
as DateTime,
deletedAt: freezed == deletedAt
? _value.deletedAt
: deletedAt // ignore: cast_nullable_to_non_nullable
as DateTime?,
balance: null == balance
? _value.balance
: balance // ignore: cast_nullable_to_non_nullable
as String,
password: null == password
? _value.password
: password // ignore: cast_nullable_to_non_nullable
as String,
accountId: null == accountId
? _value.accountId
: accountId // ignore: cast_nullable_to_non_nullable
as int,
) as $Val);
}
}
/// @nodoc
abstract class _$$SnWalletImplCopyWith<$Res>
implements $SnWalletCopyWith<$Res> {
factory _$$SnWalletImplCopyWith(
_$SnWalletImpl value, $Res Function(_$SnWalletImpl) then) =
__$$SnWalletImplCopyWithImpl<$Res>;
@override
@useResult
$Res call(
{int id,
DateTime createdAt,
DateTime updatedAt,
DateTime? deletedAt,
String balance,
String password,
int accountId});
}
/// @nodoc
class __$$SnWalletImplCopyWithImpl<$Res>
extends _$SnWalletCopyWithImpl<$Res, _$SnWalletImpl>
implements _$$SnWalletImplCopyWith<$Res> {
__$$SnWalletImplCopyWithImpl(
_$SnWalletImpl _value, $Res Function(_$SnWalletImpl) _then)
: super(_value, _then);
/// Create a copy of SnWallet
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? id = null,
Object? createdAt = null,
Object? updatedAt = null,
Object? deletedAt = freezed,
Object? balance = null,
Object? password = null,
Object? accountId = null,
}) {
return _then(_$SnWalletImpl(
id: null == id
? _value.id
: id // ignore: cast_nullable_to_non_nullable
as int,
createdAt: null == createdAt
? _value.createdAt
: createdAt // ignore: cast_nullable_to_non_nullable
as DateTime,
updatedAt: null == updatedAt
? _value.updatedAt
: updatedAt // ignore: cast_nullable_to_non_nullable
as DateTime,
deletedAt: freezed == deletedAt
? _value.deletedAt
: deletedAt // ignore: cast_nullable_to_non_nullable
as DateTime?,
balance: null == balance
? _value.balance
: balance // ignore: cast_nullable_to_non_nullable
as String,
password: null == password
? _value.password
: password // ignore: cast_nullable_to_non_nullable
as String,
accountId: null == accountId
? _value.accountId
: accountId // ignore: cast_nullable_to_non_nullable
as int,
));
}
}
/// @nodoc
@JsonSerializable()
class _$SnWalletImpl implements _SnWallet {
const _$SnWalletImpl(
{required this.id,
required this.createdAt,
required this.updatedAt,
required this.deletedAt,
required this.balance,
required this.password,
required this.accountId});
factory _$SnWalletImpl.fromJson(Map<String, dynamic> json) =>
_$$SnWalletImplFromJson(json);
@override
final int id;
@override
final DateTime createdAt;
@override
final DateTime updatedAt;
@override
final DateTime? deletedAt;
@override
final String balance;
@override
final String password;
@override
final int accountId;
@override
String toString() {
return 'SnWallet(id: $id, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, balance: $balance, password: $password, accountId: $accountId)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$SnWalletImpl &&
(identical(other.id, id) || other.id == id) &&
(identical(other.createdAt, createdAt) ||
other.createdAt == createdAt) &&
(identical(other.updatedAt, updatedAt) ||
other.updatedAt == updatedAt) &&
(identical(other.deletedAt, deletedAt) ||
other.deletedAt == deletedAt) &&
(identical(other.balance, balance) || other.balance == balance) &&
(identical(other.password, password) ||
other.password == password) &&
(identical(other.accountId, accountId) ||
other.accountId == accountId));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType, id, createdAt, updatedAt,
deletedAt, balance, password, accountId);
/// Create a copy of SnWallet
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$SnWalletImplCopyWith<_$SnWalletImpl> get copyWith =>
__$$SnWalletImplCopyWithImpl<_$SnWalletImpl>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$SnWalletImplToJson(
this,
);
}
}
abstract class _SnWallet implements SnWallet {
const factory _SnWallet(
{required final int id,
required final DateTime createdAt,
required final DateTime updatedAt,
required final DateTime? deletedAt,
required final String balance,
required final String password,
required final int accountId}) = _$SnWalletImpl;
factory _SnWallet.fromJson(Map<String, dynamic> json) =
_$SnWalletImpl.fromJson;
@override
int get id;
@override
DateTime get createdAt;
@override
DateTime get updatedAt;
@override
DateTime? get deletedAt;
@override
String get balance;
@override
String get password;
@override
int get accountId;
/// Create a copy of SnWallet
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
_$$SnWalletImplCopyWith<_$SnWalletImpl> get copyWith =>
throw _privateConstructorUsedError;
}
SnTransaction _$SnTransactionFromJson(Map<String, dynamic> json) {
return _SnTransaction.fromJson(json);
}
/// @nodoc
mixin _$SnTransaction {
int get id => throw _privateConstructorUsedError;
DateTime get createdAt => throw _privateConstructorUsedError;
DateTime get updatedAt => throw _privateConstructorUsedError;
DateTime? get deletedAt => throw _privateConstructorUsedError;
String get remark => throw _privateConstructorUsedError;
String get amount => throw _privateConstructorUsedError;
SnWallet? get payer => throw _privateConstructorUsedError;
SnWallet? get payee => throw _privateConstructorUsedError;
int? get payerId => throw _privateConstructorUsedError;
int? get payeeId => throw _privateConstructorUsedError;
/// Serializes this SnTransaction to a JSON map.
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
/// Create a copy of SnTransaction
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
$SnTransactionCopyWith<SnTransaction> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $SnTransactionCopyWith<$Res> {
factory $SnTransactionCopyWith(
SnTransaction value, $Res Function(SnTransaction) then) =
_$SnTransactionCopyWithImpl<$Res, SnTransaction>;
@useResult
$Res call(
{int id,
DateTime createdAt,
DateTime updatedAt,
DateTime? deletedAt,
String remark,
String amount,
SnWallet? payer,
SnWallet? payee,
int? payerId,
int? payeeId});
$SnWalletCopyWith<$Res>? get payer;
$SnWalletCopyWith<$Res>? get payee;
}
/// @nodoc
class _$SnTransactionCopyWithImpl<$Res, $Val extends SnTransaction>
implements $SnTransactionCopyWith<$Res> {
_$SnTransactionCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of SnTransaction
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? id = null,
Object? createdAt = null,
Object? updatedAt = null,
Object? deletedAt = freezed,
Object? remark = null,
Object? amount = null,
Object? payer = freezed,
Object? payee = freezed,
Object? payerId = freezed,
Object? payeeId = freezed,
}) {
return _then(_value.copyWith(
id: null == id
? _value.id
: id // ignore: cast_nullable_to_non_nullable
as int,
createdAt: null == createdAt
? _value.createdAt
: createdAt // ignore: cast_nullable_to_non_nullable
as DateTime,
updatedAt: null == updatedAt
? _value.updatedAt
: updatedAt // ignore: cast_nullable_to_non_nullable
as DateTime,
deletedAt: freezed == deletedAt
? _value.deletedAt
: deletedAt // ignore: cast_nullable_to_non_nullable
as DateTime?,
remark: null == remark
? _value.remark
: remark // ignore: cast_nullable_to_non_nullable
as String,
amount: null == amount
? _value.amount
: amount // ignore: cast_nullable_to_non_nullable
as String,
payer: freezed == payer
? _value.payer
: payer // ignore: cast_nullable_to_non_nullable
as SnWallet?,
payee: freezed == payee
? _value.payee
: payee // ignore: cast_nullable_to_non_nullable
as SnWallet?,
payerId: freezed == payerId
? _value.payerId
: payerId // ignore: cast_nullable_to_non_nullable
as int?,
payeeId: freezed == payeeId
? _value.payeeId
: payeeId // ignore: cast_nullable_to_non_nullable
as int?,
) as $Val);
}
/// Create a copy of SnTransaction
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$SnWalletCopyWith<$Res>? get payer {
if (_value.payer == null) {
return null;
}
return $SnWalletCopyWith<$Res>(_value.payer!, (value) {
return _then(_value.copyWith(payer: value) as $Val);
});
}
/// Create a copy of SnTransaction
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$SnWalletCopyWith<$Res>? get payee {
if (_value.payee == null) {
return null;
}
return $SnWalletCopyWith<$Res>(_value.payee!, (value) {
return _then(_value.copyWith(payee: value) as $Val);
});
}
}
/// @nodoc
abstract class _$$SnTransactionImplCopyWith<$Res>
implements $SnTransactionCopyWith<$Res> {
factory _$$SnTransactionImplCopyWith(
_$SnTransactionImpl value, $Res Function(_$SnTransactionImpl) then) =
__$$SnTransactionImplCopyWithImpl<$Res>;
@override
@useResult
$Res call(
{int id,
DateTime createdAt,
DateTime updatedAt,
DateTime? deletedAt,
String remark,
String amount,
SnWallet? payer,
SnWallet? payee,
int? payerId,
int? payeeId});
@override
$SnWalletCopyWith<$Res>? get payer;
@override
$SnWalletCopyWith<$Res>? get payee;
}
/// @nodoc
class __$$SnTransactionImplCopyWithImpl<$Res>
extends _$SnTransactionCopyWithImpl<$Res, _$SnTransactionImpl>
implements _$$SnTransactionImplCopyWith<$Res> {
__$$SnTransactionImplCopyWithImpl(
_$SnTransactionImpl _value, $Res Function(_$SnTransactionImpl) _then)
: super(_value, _then);
/// Create a copy of SnTransaction
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? id = null,
Object? createdAt = null,
Object? updatedAt = null,
Object? deletedAt = freezed,
Object? remark = null,
Object? amount = null,
Object? payer = freezed,
Object? payee = freezed,
Object? payerId = freezed,
Object? payeeId = freezed,
}) {
return _then(_$SnTransactionImpl(
id: null == id
? _value.id
: id // ignore: cast_nullable_to_non_nullable
as int,
createdAt: null == createdAt
? _value.createdAt
: createdAt // ignore: cast_nullable_to_non_nullable
as DateTime,
updatedAt: null == updatedAt
? _value.updatedAt
: updatedAt // ignore: cast_nullable_to_non_nullable
as DateTime,
deletedAt: freezed == deletedAt
? _value.deletedAt
: deletedAt // ignore: cast_nullable_to_non_nullable
as DateTime?,
remark: null == remark
? _value.remark
: remark // ignore: cast_nullable_to_non_nullable
as String,
amount: null == amount
? _value.amount
: amount // ignore: cast_nullable_to_non_nullable
as String,
payer: freezed == payer
? _value.payer
: payer // ignore: cast_nullable_to_non_nullable
as SnWallet?,
payee: freezed == payee
? _value.payee
: payee // ignore: cast_nullable_to_non_nullable
as SnWallet?,
payerId: freezed == payerId
? _value.payerId
: payerId // ignore: cast_nullable_to_non_nullable
as int?,
payeeId: freezed == payeeId
? _value.payeeId
: payeeId // ignore: cast_nullable_to_non_nullable
as int?,
));
}
}
/// @nodoc
@JsonSerializable()
class _$SnTransactionImpl implements _SnTransaction {
const _$SnTransactionImpl(
{required this.id,
required this.createdAt,
required this.updatedAt,
required this.deletedAt,
required this.remark,
required this.amount,
required this.payer,
required this.payee,
required this.payerId,
required this.payeeId});
factory _$SnTransactionImpl.fromJson(Map<String, dynamic> json) =>
_$$SnTransactionImplFromJson(json);
@override
final int id;
@override
final DateTime createdAt;
@override
final DateTime updatedAt;
@override
final DateTime? deletedAt;
@override
final String remark;
@override
final String amount;
@override
final SnWallet? payer;
@override
final SnWallet? payee;
@override
final int? payerId;
@override
final int? payeeId;
@override
String toString() {
return 'SnTransaction(id: $id, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, remark: $remark, amount: $amount, payer: $payer, payee: $payee, payerId: $payerId, payeeId: $payeeId)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$SnTransactionImpl &&
(identical(other.id, id) || other.id == id) &&
(identical(other.createdAt, createdAt) ||
other.createdAt == createdAt) &&
(identical(other.updatedAt, updatedAt) ||
other.updatedAt == updatedAt) &&
(identical(other.deletedAt, deletedAt) ||
other.deletedAt == deletedAt) &&
(identical(other.remark, remark) || other.remark == remark) &&
(identical(other.amount, amount) || other.amount == amount) &&
(identical(other.payer, payer) || other.payer == payer) &&
(identical(other.payee, payee) || other.payee == payee) &&
(identical(other.payerId, payerId) || other.payerId == payerId) &&
(identical(other.payeeId, payeeId) || other.payeeId == payeeId));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType, id, createdAt, updatedAt,
deletedAt, remark, amount, payer, payee, payerId, payeeId);
/// Create a copy of SnTransaction
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$SnTransactionImplCopyWith<_$SnTransactionImpl> get copyWith =>
__$$SnTransactionImplCopyWithImpl<_$SnTransactionImpl>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$SnTransactionImplToJson(
this,
);
}
}
abstract class _SnTransaction implements SnTransaction {
const factory _SnTransaction(
{required final int id,
required final DateTime createdAt,
required final DateTime updatedAt,
required final DateTime? deletedAt,
required final String remark,
required final String amount,
required final SnWallet? payer,
required final SnWallet? payee,
required final int? payerId,
required final int? payeeId}) = _$SnTransactionImpl;
factory _SnTransaction.fromJson(Map<String, dynamic> json) =
_$SnTransactionImpl.fromJson;
@override
int get id;
@override
DateTime get createdAt;
@override
DateTime get updatedAt;
@override
DateTime? get deletedAt;
@override
String get remark;
@override
String get amount;
@override
SnWallet? get payer;
@override
SnWallet? get payee;
@override
int? get payerId;
@override
int? get payeeId;
/// Create a copy of SnTransaction
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
_$$SnTransactionImplCopyWith<_$SnTransactionImpl> get copyWith =>
throw _privateConstructorUsedError;
}

65
lib/types/wallet.g.dart Normal file
View File

@ -0,0 +1,65 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'wallet.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_$SnWalletImpl _$$SnWalletImplFromJson(Map<String, dynamic> json) =>
_$SnWalletImpl(
id: (json['id'] as num).toInt(),
createdAt: DateTime.parse(json['created_at'] as String),
updatedAt: DateTime.parse(json['updated_at'] as String),
deletedAt: json['deleted_at'] == null
? null
: DateTime.parse(json['deleted_at'] as String),
balance: json['balance'] as String,
password: json['password'] as String,
accountId: (json['account_id'] as num).toInt(),
);
Map<String, dynamic> _$$SnWalletImplToJson(_$SnWalletImpl instance) =>
<String, dynamic>{
'id': instance.id,
'created_at': instance.createdAt.toIso8601String(),
'updated_at': instance.updatedAt.toIso8601String(),
'deleted_at': instance.deletedAt?.toIso8601String(),
'balance': instance.balance,
'password': instance.password,
'account_id': instance.accountId,
};
_$SnTransactionImpl _$$SnTransactionImplFromJson(Map<String, dynamic> json) =>
_$SnTransactionImpl(
id: (json['id'] as num).toInt(),
createdAt: DateTime.parse(json['created_at'] as String),
updatedAt: DateTime.parse(json['updated_at'] as String),
deletedAt: json['deleted_at'] == null
? null
: DateTime.parse(json['deleted_at'] as String),
remark: json['remark'] as String,
amount: json['amount'] as String,
payer: json['payer'] == null
? null
: SnWallet.fromJson(json['payer'] as Map<String, dynamic>),
payee: json['payee'] == null
? null
: SnWallet.fromJson(json['payee'] as Map<String, dynamic>),
payerId: (json['payer_id'] as num?)?.toInt(),
payeeId: (json['payee_id'] as num?)?.toInt(),
);
Map<String, dynamic> _$$SnTransactionImplToJson(_$SnTransactionImpl instance) =>
<String, dynamic>{
'id': instance.id,
'created_at': instance.createdAt.toIso8601String(),
'updated_at': instance.updatedAt.toIso8601String(),
'deleted_at': instance.deletedAt?.toIso8601String(),
'remark': instance.remark,
'amount': instance.amount,
'payer': instance.payer?.toJson(),
'payee': instance.payee?.toJson(),
'payer_id': instance.payerId,
'payee_id': instance.payeeId,
};