Frontend first draft
This commit is contained in:
36
frontend/pshared/lib/models/account/account.dart
Normal file
36
frontend/pshared/lib/models/account/account.dart
Normal file
@@ -0,0 +1,36 @@
|
||||
import 'package:pshared/models/account/base.dart';
|
||||
|
||||
|
||||
class Account extends AccountBase {
|
||||
final String login;
|
||||
|
||||
const Account({
|
||||
required super.storable,
|
||||
required super.avatarUrl,
|
||||
required this.login,
|
||||
required super.locale,
|
||||
required super.name,
|
||||
});
|
||||
|
||||
factory Account.fromBase(AccountBase accountBase, String login) => Account(
|
||||
storable: accountBase.storable,
|
||||
avatarUrl: accountBase.avatarUrl,
|
||||
locale: accountBase.locale,
|
||||
name: accountBase.name,
|
||||
login: login,
|
||||
);
|
||||
|
||||
@override
|
||||
Account copyWith({
|
||||
String? Function()? avatarUrl,
|
||||
String? name,
|
||||
String? locale,
|
||||
}) {
|
||||
final updatedBase = super.copyWith(
|
||||
avatarUrl: avatarUrl,
|
||||
name: name,
|
||||
locale: locale,
|
||||
);
|
||||
return Account.fromBase(updatedBase, login);
|
||||
}
|
||||
}
|
||||
35
frontend/pshared/lib/models/account/base.dart
Normal file
35
frontend/pshared/lib/models/account/base.dart
Normal file
@@ -0,0 +1,35 @@
|
||||
import 'package:pshared/models/storable.dart';
|
||||
|
||||
|
||||
class AccountBase implements Storable {
|
||||
final Storable storable;
|
||||
|
||||
@override
|
||||
String get id => storable.id;
|
||||
@override
|
||||
DateTime get createdAt => storable.createdAt;
|
||||
@override
|
||||
DateTime get updatedAt => storable.updatedAt;
|
||||
|
||||
final String? avatarUrl;
|
||||
final String name;
|
||||
final String locale;
|
||||
|
||||
const AccountBase({
|
||||
required this.storable,
|
||||
required this.name,
|
||||
required this.locale,
|
||||
required this.avatarUrl,
|
||||
});
|
||||
|
||||
AccountBase copyWith({
|
||||
String? Function()? avatarUrl,
|
||||
String? name,
|
||||
String? locale,
|
||||
}) => AccountBase(
|
||||
storable: storable,
|
||||
avatarUrl: avatarUrl != null ? avatarUrl() : this.avatarUrl,
|
||||
locale: locale ?? this.locale,
|
||||
name: name ?? this.name,
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
class OrganizationDescription {
|
||||
final String? logoUrl;
|
||||
|
||||
const OrganizationDescription({
|
||||
this.logoUrl,
|
||||
});
|
||||
}
|
||||
4
frontend/pshared/lib/models/organization/employee.dart
Normal file
4
frontend/pshared/lib/models/organization/employee.dart
Normal file
@@ -0,0 +1,4 @@
|
||||
import 'package:pshared/models/account/account.dart';
|
||||
|
||||
|
||||
typedef Employee = Account;
|
||||
34
frontend/pshared/lib/models/organization/organization.dart
Normal file
34
frontend/pshared/lib/models/organization/organization.dart
Normal file
@@ -0,0 +1,34 @@
|
||||
import 'package:pshared/models/storable.dart';
|
||||
|
||||
|
||||
class Organization implements Storable {
|
||||
final Storable storable;
|
||||
|
||||
@override
|
||||
String get id => storable.id;
|
||||
@override
|
||||
DateTime get createdAt => storable.createdAt;
|
||||
@override
|
||||
DateTime get updatedAt => storable.updatedAt;
|
||||
|
||||
final String timeZone;
|
||||
final String? logoUrl;
|
||||
|
||||
const Organization({
|
||||
required this.storable,
|
||||
required this.timeZone,
|
||||
this.logoUrl,
|
||||
});
|
||||
|
||||
|
||||
Organization copyWith({
|
||||
String? name,
|
||||
String? Function()? description,
|
||||
String? timeZone,
|
||||
String? Function()? logoUrl,
|
||||
}) => Organization(
|
||||
storable: storable, // Same Storable, same id
|
||||
timeZone: timeZone ?? this.timeZone,
|
||||
logoUrl: logoUrl != null ? logoUrl() : this.logoUrl,
|
||||
);
|
||||
}
|
||||
18
frontend/pshared/lib/models/payment/methods/card.dart
Normal file
18
frontend/pshared/lib/models/payment/methods/card.dart
Normal file
@@ -0,0 +1,18 @@
|
||||
import 'package:pshared/models/payment/methods/data.dart';
|
||||
import 'package:pshared/models/payment/type.dart';
|
||||
|
||||
|
||||
class CardPaymentMethod extends PaymentMethodData {
|
||||
@override
|
||||
final PaymentType type = PaymentType.card;
|
||||
|
||||
final String pan;
|
||||
final String firstName;
|
||||
final String lastName;
|
||||
|
||||
CardPaymentMethod({
|
||||
required this.pan,
|
||||
required this.firstName,
|
||||
required this.lastName,
|
||||
});
|
||||
}
|
||||
6
frontend/pshared/lib/models/payment/methods/data.dart
Normal file
6
frontend/pshared/lib/models/payment/methods/data.dart
Normal file
@@ -0,0 +1,6 @@
|
||||
import 'package:pshared/models/payment/type.dart';
|
||||
|
||||
|
||||
abstract class PaymentMethodData {
|
||||
PaymentType get type;
|
||||
}
|
||||
20
frontend/pshared/lib/models/payment/methods/iban.dart
Normal file
20
frontend/pshared/lib/models/payment/methods/iban.dart
Normal file
@@ -0,0 +1,20 @@
|
||||
import 'package:pshared/models/payment/methods/data.dart';
|
||||
import 'package:pshared/models/payment/type.dart';
|
||||
|
||||
|
||||
class IbanPaymentMethod extends PaymentMethodData {
|
||||
@override
|
||||
final PaymentType type = PaymentType.iban;
|
||||
|
||||
final String iban; // e.g. DE89 3704 0044 0532 0130 00
|
||||
final String accountHolder; // Full name of the recipient
|
||||
final String? bic; // Optional: for cross-border transfers
|
||||
final String? bankName; // Optional: for UI clarity
|
||||
|
||||
IbanPaymentMethod({
|
||||
required this.iban,
|
||||
required this.accountHolder,
|
||||
this.bic,
|
||||
this.bankName,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import 'package:pshared/models/payment/methods/data.dart';
|
||||
import 'package:pshared/models/payment/type.dart';
|
||||
|
||||
|
||||
class RussianBankAccountPaymentMethod extends PaymentMethodData {
|
||||
@override
|
||||
final PaymentType type = PaymentType.bankAccount;
|
||||
|
||||
final String recipientName;
|
||||
final String inn;
|
||||
final String kpp;
|
||||
final String bankName;
|
||||
final String bik;
|
||||
final String accountNumber;
|
||||
final String correspondentAccount;
|
||||
|
||||
RussianBankAccountPaymentMethod({
|
||||
required this.recipientName,
|
||||
required this.inn,
|
||||
required this.kpp,
|
||||
required this.bankName,
|
||||
required this.bik,
|
||||
required this.accountNumber,
|
||||
required this.correspondentAccount,
|
||||
});
|
||||
}
|
||||
21
frontend/pshared/lib/models/payment/methods/type.dart
Normal file
21
frontend/pshared/lib/models/payment/methods/type.dart
Normal file
@@ -0,0 +1,21 @@
|
||||
import 'package:pshared/models/payment/type.dart';
|
||||
|
||||
|
||||
class PaymentMethod {
|
||||
PaymentMethod({
|
||||
required this.id,
|
||||
required this.label,
|
||||
required this.details,
|
||||
required this.type,
|
||||
this.isEnabled = true,
|
||||
this.isMain = false,
|
||||
});
|
||||
|
||||
final String id;
|
||||
final String label;
|
||||
final String details;
|
||||
final PaymentType type;
|
||||
|
||||
bool isEnabled;
|
||||
bool isMain;
|
||||
}
|
||||
12
frontend/pshared/lib/models/payment/methods/wallet.dart
Normal file
12
frontend/pshared/lib/models/payment/methods/wallet.dart
Normal file
@@ -0,0 +1,12 @@
|
||||
import 'package:pshared/models/payment/methods/data.dart';
|
||||
import 'package:pshared/models/payment/type.dart';
|
||||
|
||||
|
||||
class WalletPaymentMethod extends PaymentMethodData {
|
||||
@override
|
||||
final PaymentType type = PaymentType.wallet;
|
||||
|
||||
final String walletId;
|
||||
|
||||
WalletPaymentMethod({required this.walletId});
|
||||
}
|
||||
30
frontend/pshared/lib/models/payment/operation.dart
Normal file
30
frontend/pshared/lib/models/payment/operation.dart
Normal file
@@ -0,0 +1,30 @@
|
||||
import 'package:pshared/models/payment/status.dart';
|
||||
|
||||
|
||||
class OperationItem {
|
||||
final OperationStatus status;
|
||||
final String? fileName;
|
||||
final double amount;
|
||||
final String currency;
|
||||
final double toAmount;
|
||||
final String toCurrency;
|
||||
final String payId;
|
||||
final String? cardNumber;
|
||||
final String name;
|
||||
final DateTime date;
|
||||
final String comment;
|
||||
|
||||
OperationItem({
|
||||
required this.status,
|
||||
this.fileName,
|
||||
required this.amount,
|
||||
required this.currency,
|
||||
required this.toAmount,
|
||||
required this.toCurrency,
|
||||
required this.payId,
|
||||
this.cardNumber,
|
||||
required this.name,
|
||||
required this.date,
|
||||
required this.comment,
|
||||
});
|
||||
}
|
||||
25
frontend/pshared/lib/models/payment/status.dart
Normal file
25
frontend/pshared/lib/models/payment/status.dart
Normal file
@@ -0,0 +1,25 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:pshared/generated/i18n/ps_localizations.dart';
|
||||
|
||||
enum OperationStatus {
|
||||
processing,
|
||||
success,
|
||||
error,
|
||||
}
|
||||
|
||||
|
||||
extension OperationStatusX on OperationStatus {
|
||||
/// Returns the localized string for this status,
|
||||
/// e.g. “Processing”, “Success”, “Error”.
|
||||
String localized(BuildContext context) {
|
||||
final loc = PSLocalizations.of(context)!;
|
||||
switch (this) {
|
||||
case OperationStatus.processing:
|
||||
return loc.operationStatusProcessing;
|
||||
case OperationStatus.success:
|
||||
return loc.operationStatusSuccess;
|
||||
case OperationStatus.error:
|
||||
return loc.operationStatusError;
|
||||
}
|
||||
}
|
||||
}
|
||||
6
frontend/pshared/lib/models/payment/type.dart
Normal file
6
frontend/pshared/lib/models/payment/type.dart
Normal file
@@ -0,0 +1,6 @@
|
||||
enum PaymentType {
|
||||
bankAccount,
|
||||
iban,
|
||||
wallet,
|
||||
card,
|
||||
}
|
||||
11
frontend/pshared/lib/models/payment/upload_history_item.dart
Normal file
11
frontend/pshared/lib/models/payment/upload_history_item.dart
Normal file
@@ -0,0 +1,11 @@
|
||||
class UploadHistoryItem {
|
||||
final String name;
|
||||
final String status;
|
||||
final String time;
|
||||
|
||||
UploadHistoryItem({
|
||||
required this.name,
|
||||
required this.status,
|
||||
required this.time,
|
||||
});
|
||||
}
|
||||
22
frontend/pshared/lib/models/permission_bound.dart
Normal file
22
frontend/pshared/lib/models/permission_bound.dart
Normal file
@@ -0,0 +1,22 @@
|
||||
import 'package:pshared/config/constants.dart';
|
||||
|
||||
|
||||
abstract class PermissionBound {
|
||||
String get permissionRef;
|
||||
String get organizationRef;
|
||||
}
|
||||
|
||||
class _PermissionBoundImp implements PermissionBound {
|
||||
@override
|
||||
final String permissionRef;
|
||||
@override
|
||||
final String organizationRef;
|
||||
|
||||
const _PermissionBoundImp({
|
||||
required this.permissionRef,
|
||||
required this.organizationRef,
|
||||
});
|
||||
}
|
||||
|
||||
PermissionBound newPermissionBound({ required String organizationRef, String? permissionRef}) =>
|
||||
_PermissionBoundImp(permissionRef: permissionRef ?? Constants.nilObjectRef, organizationRef: organizationRef);
|
||||
@@ -0,0 +1,6 @@
|
||||
import 'package:pshared/models/permission_bound.dart';
|
||||
import 'package:pshared/models/storable.dart';
|
||||
|
||||
|
||||
abstract class PermissionBoundStorable implements PermissionBound, Storable {
|
||||
}
|
||||
13
frontend/pshared/lib/models/permissions/access.dart
Normal file
13
frontend/pshared/lib/models/permissions/access.dart
Normal file
@@ -0,0 +1,13 @@
|
||||
import 'package:pshared/models/permissions/data/permissions.dart';
|
||||
import 'package:pshared/models/permissions/descriptions/permissions.dart';
|
||||
|
||||
|
||||
class UserAccess {
|
||||
final PermissionsDescription descriptions;
|
||||
final PermissionsData permissions;
|
||||
|
||||
const UserAccess({
|
||||
required this.descriptions,
|
||||
required this.permissions,
|
||||
});
|
||||
}
|
||||
15
frontend/pshared/lib/models/permissions/action.dart
Normal file
15
frontend/pshared/lib/models/permissions/action.dart
Normal file
@@ -0,0 +1,15 @@
|
||||
enum Action {
|
||||
create,
|
||||
read,
|
||||
update,
|
||||
delete,
|
||||
}
|
||||
|
||||
extension ActionExtension on Action {
|
||||
String toShortString() => toString().split('.').last;
|
||||
|
||||
static Action fromString(String value) => Action.values.firstWhere(
|
||||
(e) => e.toShortString() == value,
|
||||
orElse: () => throw ArgumentError('Invalid action: $value'),
|
||||
);
|
||||
}
|
||||
13
frontend/pshared/lib/models/permissions/action_effect.dart
Normal file
13
frontend/pshared/lib/models/permissions/action_effect.dart
Normal file
@@ -0,0 +1,13 @@
|
||||
import 'package:pshared/models/permissions/action.dart';
|
||||
import 'package:pshared/models/permissions/effect.dart';
|
||||
|
||||
|
||||
class ActionEffect {
|
||||
final Action action; // The action allowed or denied
|
||||
final Effect effect; // The effect of the policy ("allow" or "deny")
|
||||
|
||||
const ActionEffect({
|
||||
required this.action,
|
||||
required this.effect,
|
||||
});
|
||||
}
|
||||
12
frontend/pshared/lib/models/permissions/data/permission.dart
Normal file
12
frontend/pshared/lib/models/permissions/data/permission.dart
Normal file
@@ -0,0 +1,12 @@
|
||||
import 'package:pshared/models/permissions/data/policy.dart';
|
||||
|
||||
|
||||
class Permission {
|
||||
final Policy policy;
|
||||
final String accountRef;
|
||||
|
||||
const Permission({
|
||||
required this.policy,
|
||||
required this.accountRef,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import 'package:pshared/models/permissions/data/permission.dart';
|
||||
import 'package:pshared/models/permissions/data/policy.dart';
|
||||
import 'package:pshared/models/permissions/data/role.dart';
|
||||
|
||||
|
||||
class PermissionsData {
|
||||
final List<Role> roles;
|
||||
final List<Policy> policies;
|
||||
final List<Permission> permissions;
|
||||
|
||||
const PermissionsData({
|
||||
required this.roles,
|
||||
required this.policies,
|
||||
required this.permissions,
|
||||
});
|
||||
}
|
||||
18
frontend/pshared/lib/models/permissions/data/policy.dart
Normal file
18
frontend/pshared/lib/models/permissions/data/policy.dart
Normal file
@@ -0,0 +1,18 @@
|
||||
import 'package:pshared/models/permissions/action_effect.dart';
|
||||
|
||||
|
||||
class Policy {
|
||||
final String roleDescriptionRef;
|
||||
final String organizationRef;
|
||||
final String descriptionRef;
|
||||
final String? objectRef;
|
||||
final ActionEffect effect;
|
||||
|
||||
const Policy({
|
||||
required this.roleDescriptionRef,
|
||||
required this.organizationRef,
|
||||
required this.descriptionRef,
|
||||
required this.objectRef,
|
||||
required this.effect,
|
||||
});
|
||||
}
|
||||
11
frontend/pshared/lib/models/permissions/data/role.dart
Normal file
11
frontend/pshared/lib/models/permissions/data/role.dart
Normal file
@@ -0,0 +1,11 @@
|
||||
class Role {
|
||||
final String accountRef;
|
||||
final String organizationRef;
|
||||
final String descriptionRef;
|
||||
|
||||
const Role({
|
||||
required this.accountRef,
|
||||
required this.descriptionRef,
|
||||
required this.organizationRef,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import 'package:pshared/models/permissions/descriptions/policy.dart';
|
||||
import 'package:pshared/models/permissions/descriptions/role.dart';
|
||||
|
||||
|
||||
class PermissionsDescription {
|
||||
final List<RoleDescription> roles;
|
||||
final List<PolicyDescription> policies;
|
||||
|
||||
const PermissionsDescription({
|
||||
required this.roles,
|
||||
required this.policies,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import 'package:pshared/models/resources.dart';
|
||||
import 'package:pshared/models/storable.dart';
|
||||
|
||||
|
||||
class PolicyDescription implements Storable {
|
||||
final Storable storable;
|
||||
final List<ResourceType>? resourceTypes;
|
||||
final String? organizationRef;
|
||||
|
||||
@override
|
||||
String get id => storable.id;
|
||||
@override
|
||||
DateTime get createdAt => storable.createdAt;
|
||||
@override
|
||||
DateTime get updatedAt => storable.updatedAt;
|
||||
|
||||
const PolicyDescription({
|
||||
required this.storable,
|
||||
required this.resourceTypes,
|
||||
required this.organizationRef,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import 'package:pshared/models/storable.dart';
|
||||
|
||||
|
||||
class RoleDescription implements Storable {
|
||||
final Storable storable;
|
||||
|
||||
@override
|
||||
String get id => storable.id;
|
||||
@override
|
||||
DateTime get createdAt => storable.createdAt;
|
||||
@override
|
||||
DateTime get updatedAt => storable.updatedAt;
|
||||
|
||||
final String organizationRef;
|
||||
|
||||
const RoleDescription({
|
||||
required this.storable,
|
||||
required this.organizationRef,
|
||||
});
|
||||
|
||||
factory RoleDescription.build({
|
||||
required String organizationRef,
|
||||
}) => RoleDescription(
|
||||
storable: newStorable(),
|
||||
organizationRef: organizationRef
|
||||
);
|
||||
}
|
||||
13
frontend/pshared/lib/models/permissions/effect.dart
Normal file
13
frontend/pshared/lib/models/permissions/effect.dart
Normal file
@@ -0,0 +1,13 @@
|
||||
enum Effect {
|
||||
allow,
|
||||
deny,
|
||||
}
|
||||
|
||||
extension EffectExtension on Effect {
|
||||
String toShortString() => toString().split('.').last;
|
||||
|
||||
static Effect fromString(String value) => Effect.values.firstWhere(
|
||||
(e) => e.toShortString() == value,
|
||||
orElse: () => throw ArgumentError('Invalid effect: $value'),
|
||||
);
|
||||
}
|
||||
0
frontend/pshared/lib/models/pfe/services.dart
Normal file
0
frontend/pshared/lib/models/pfe/services.dart
Normal file
1
frontend/pshared/lib/models/recipient/filter.dart
Normal file
1
frontend/pshared/lib/models/recipient/filter.dart
Normal file
@@ -0,0 +1 @@
|
||||
enum RecipientFilter { all, ready, registered, notRegistered }
|
||||
78
frontend/pshared/lib/models/recipient/recipient.dart
Normal file
78
frontend/pshared/lib/models/recipient/recipient.dart
Normal file
@@ -0,0 +1,78 @@
|
||||
import 'package:pshared/models/payment/methods/card.dart';
|
||||
import 'package:pshared/models/payment/methods/iban.dart';
|
||||
import 'package:pshared/models/payment/methods/russian_bank.dart';
|
||||
import 'package:pshared/models/payment/methods/wallet.dart';
|
||||
import 'package:pshared/models/recipient/status.dart';
|
||||
import 'package:pshared/models/recipient/type.dart';
|
||||
|
||||
|
||||
class Recipient {
|
||||
final String? avatarUrl; // network URL / local asset
|
||||
final String name;
|
||||
final String email;
|
||||
final RecipientStatus status;
|
||||
final RecipientType type;
|
||||
final CardPaymentMethod? card;
|
||||
final IbanPaymentMethod? iban;
|
||||
final RussianBankAccountPaymentMethod? bank;
|
||||
final WalletPaymentMethod? wallet;
|
||||
|
||||
const Recipient({
|
||||
this.avatarUrl,
|
||||
required this.name,
|
||||
required this.email,
|
||||
required this.status,
|
||||
required this.type,
|
||||
this.card,
|
||||
this.iban,
|
||||
this.bank,
|
||||
this.wallet,
|
||||
});
|
||||
|
||||
/// Convenience factory for quickly creating mock recipients.
|
||||
factory Recipient.mock({
|
||||
required String name,
|
||||
required String email,
|
||||
required RecipientStatus status,
|
||||
required RecipientType type,
|
||||
CardPaymentMethod? card,
|
||||
IbanPaymentMethod? iban,
|
||||
RussianBankAccountPaymentMethod? bank,
|
||||
WalletPaymentMethod? wallet,
|
||||
}) =>
|
||||
Recipient(
|
||||
avatarUrl: null,
|
||||
name: name,
|
||||
email: email,
|
||||
status: status,
|
||||
type: type,
|
||||
card: card,
|
||||
iban: iban,
|
||||
bank: bank,
|
||||
wallet: wallet,
|
||||
);
|
||||
|
||||
bool matchesQuery(String q) {
|
||||
final searchable = [
|
||||
name,
|
||||
email,
|
||||
card?.pan,
|
||||
card?.firstName,
|
||||
card?.lastName,
|
||||
iban?.iban,
|
||||
iban?.accountHolder,
|
||||
iban?.bic,
|
||||
iban?.bankName,
|
||||
bank?.accountNumber,
|
||||
bank?.recipientName,
|
||||
bank?.inn,
|
||||
bank?.kpp,
|
||||
bank?.bankName,
|
||||
bank?.bik,
|
||||
bank?.correspondentAccount,
|
||||
wallet?.walletId,
|
||||
];
|
||||
|
||||
return searchable.any((field) => field?.toLowerCase().contains(q) ?? false);
|
||||
}
|
||||
}
|
||||
22
frontend/pshared/lib/models/recipient/status.dart
Normal file
22
frontend/pshared/lib/models/recipient/status.dart
Normal file
@@ -0,0 +1,22 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'package:pshared/generated/i18n/ps_localizations.dart';
|
||||
|
||||
|
||||
/// Possible payout readiness states.
|
||||
enum RecipientStatus { ready, registered, notRegistered }
|
||||
|
||||
extension RecipientStatusExtension on RecipientStatus {
|
||||
/// Human-readable, **localized** label for display in the UI.
|
||||
String label(BuildContext context) {
|
||||
final l10n = PSLocalizations.of(context)!;
|
||||
switch (this) {
|
||||
case RecipientStatus.ready:
|
||||
return l10n.statusReady;
|
||||
case RecipientStatus.registered:
|
||||
return l10n.statusRegistered;
|
||||
case RecipientStatus.notRegistered:
|
||||
return l10n.statusNotRegistered;
|
||||
}
|
||||
}
|
||||
}
|
||||
15
frontend/pshared/lib/models/recipient/type.dart
Normal file
15
frontend/pshared/lib/models/recipient/type.dart
Normal file
@@ -0,0 +1,15 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'package:pshared/generated/i18n/ps_localizations.dart';
|
||||
|
||||
|
||||
/// Indicates whether you (internal) or the other party (external) manage payout data.
|
||||
enum RecipientType { internal, external }
|
||||
|
||||
extension RecipientTypeExtension on RecipientType {
|
||||
/// Localized label – no opaque abbreviations.
|
||||
String label(BuildContext context) =>
|
||||
this == RecipientType.internal
|
||||
? PSLocalizations.of(context)!.typeInternal
|
||||
: PSLocalizations.of(context)!.typeExternal;
|
||||
}
|
||||
107
frontend/pshared/lib/models/resources.dart
Normal file
107
frontend/pshared/lib/models/resources.dart
Normal file
@@ -0,0 +1,107 @@
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
|
||||
/// Represents various resource types (mirroring your Go "Type" constants).
|
||||
enum ResourceType {
|
||||
/// Represents user accounts in the system
|
||||
@JsonValue('accounts')
|
||||
accounts,
|
||||
|
||||
/// Represents analytics integration with Amplitude
|
||||
@JsonValue('amplitude')
|
||||
amplitude,
|
||||
|
||||
/// Represents automation workflows
|
||||
@JsonValue('automations')
|
||||
automations,
|
||||
|
||||
/// Tracks changes made to resources
|
||||
@JsonValue('changes')
|
||||
changes,
|
||||
|
||||
/// Represents client information
|
||||
@JsonValue('clients')
|
||||
clients,
|
||||
|
||||
/// Represents comments on tasks or other resources
|
||||
@JsonValue('comments')
|
||||
comments,
|
||||
|
||||
/// Represents invitations sent to users
|
||||
@JsonValue('invitations')
|
||||
invitations,
|
||||
|
||||
/// Represents invoices
|
||||
@JsonValue('invoices')
|
||||
invoices,
|
||||
|
||||
/// Represents logos for organizations or projects
|
||||
@JsonValue('logo')
|
||||
logo,
|
||||
|
||||
/// Represents notifications sent to users
|
||||
@JsonValue('notifications')
|
||||
notifications,
|
||||
|
||||
/// Represents organizations in the system
|
||||
@JsonValue('organizations')
|
||||
organizations,
|
||||
|
||||
/// Represents permissions service
|
||||
@JsonValue('permissions')
|
||||
permissions,
|
||||
|
||||
/// Represents access control policies
|
||||
@JsonValue('policies')
|
||||
policies,
|
||||
|
||||
/// Represents task or project priorities
|
||||
@JsonValue('priorities')
|
||||
priorities,
|
||||
|
||||
/// Represents priority groups
|
||||
@JsonValue('priority_groups')
|
||||
priorityGroups,
|
||||
|
||||
/// Represents projects managed in the system
|
||||
@JsonValue('projects')
|
||||
projects,
|
||||
|
||||
@JsonValue('properties')
|
||||
properties,
|
||||
|
||||
/// Represents reactions
|
||||
@JsonValue('reactions')
|
||||
reactions,
|
||||
|
||||
/// Represents refresh tokens for authentication
|
||||
@JsonValue('refresh_tokens')
|
||||
refreshTokens,
|
||||
|
||||
/// Represents roles in access control
|
||||
@JsonValue('roles')
|
||||
roles,
|
||||
|
||||
/// Represents statuses of tasks or projects
|
||||
@JsonValue('statuses')
|
||||
statuses,
|
||||
|
||||
/// Represents steps in workflows or processes
|
||||
@JsonValue('steps')
|
||||
steps,
|
||||
|
||||
/// Represents tasks managed in the system
|
||||
@JsonValue('tasks')
|
||||
tasks,
|
||||
|
||||
/// Represents teams managed in the system
|
||||
@JsonValue('teams')
|
||||
teams,
|
||||
|
||||
/// Represents workflows for tasks or projects
|
||||
@JsonValue('workflows')
|
||||
workflows,
|
||||
|
||||
/// Represents workspaces containing projects and teams
|
||||
@JsonValue('workspaces')
|
||||
workspaces;
|
||||
}
|
||||
77
frontend/pshared/lib/models/settings/localizations.dart
Normal file
77
frontend/pshared/lib/models/settings/localizations.dart
Normal file
@@ -0,0 +1,77 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
|
||||
typedef LangLocalization = Map<String, String>;
|
||||
|
||||
String _translation(LangLocalization loc, String key) {
|
||||
return loc[key] ?? '';
|
||||
}
|
||||
|
||||
typedef Localizations = Map<String, LangLocalization>;
|
||||
|
||||
typedef Localizer = String Function(BuildContext);
|
||||
|
||||
class Localization {
|
||||
|
||||
static const String keyHint = 'hint';
|
||||
static const String keyLink = 'link';
|
||||
static const String keyName = 'name';
|
||||
static const String keyError = 'error';
|
||||
static const String keyAddress = 'address';
|
||||
static const String keyDetails = 'details';
|
||||
static const String keyRoute = 'route';
|
||||
static const String keyLocationName = 'location_name';
|
||||
|
||||
static String _localizeImp(Localizations localizations, String locale, String Function(LangLocalization) functor) {
|
||||
final localization = localizations[locale];
|
||||
if (localization != null) {
|
||||
return functor(localization);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
static String _localize(Localizations localizations, String locale, String Function(LangLocalization) functor, {String? fallback}) {
|
||||
final res = _localizeImp(localizations, locale, functor);
|
||||
return res.isNotEmpty ? res : (fallback ?? '');
|
||||
}
|
||||
|
||||
static bool localizationExists(Localizations loc, String locale) {
|
||||
return loc.containsKey(locale);
|
||||
}
|
||||
|
||||
static String hint(Localizations loc, String locale, {String? fallback}) {
|
||||
return _localize(loc, locale, (localization) => _translation(localization, keyHint), fallback: fallback);
|
||||
}
|
||||
|
||||
static String link(Localizations loc, String locale, {String? fallback}) {
|
||||
return _localize(loc, locale, (localization) => _translation(localization, keyLink), fallback: fallback);
|
||||
}
|
||||
|
||||
static String name(Localizations loc, String locale, {String? fallback}) {
|
||||
return _localize(loc, locale, (localization) => _translation(localization, keyName), fallback: fallback);
|
||||
}
|
||||
|
||||
static String error(Localizations loc, String locale, {String? fallback}) {
|
||||
return _localize(loc, locale, (localization) => _translation(localization, keyError), fallback: fallback);
|
||||
}
|
||||
|
||||
static String address(Localizations loc, String locale, {String? fallback}) {
|
||||
return _localize(loc, locale, (localization) => _translation(localization, keyAddress), fallback: fallback);
|
||||
}
|
||||
|
||||
static String details(Localizations loc, String locale, {String? fallback}) {
|
||||
return _localize(loc, locale, (localization) => _translation(localization, keyDetails), fallback: fallback);
|
||||
}
|
||||
|
||||
static String route(Localizations loc, String locale, {String? fallback}) {
|
||||
return _localize(loc, locale, (localization) => _translation(localization, keyRoute), fallback: fallback);
|
||||
}
|
||||
|
||||
static String locationName(Localizations loc, String locale, {String? fallback}) {
|
||||
return _localize(loc, locale, (localization) => _translation(localization, keyLocationName), fallback: fallback);
|
||||
}
|
||||
|
||||
static String translate(Localizations loc, String locale, String key, {String? fallback}) {
|
||||
return _localize(loc, locale, (localization) => _translation(localization, key), fallback: fallback);
|
||||
}
|
||||
}
|
||||
27
frontend/pshared/lib/models/settings/time_validity.dart
Normal file
27
frontend/pshared/lib/models/settings/time_validity.dart
Normal file
@@ -0,0 +1,27 @@
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
|
||||
part 'time_validity.g.dart';
|
||||
|
||||
|
||||
@JsonSerializable()
|
||||
class TimeValidity {
|
||||
final DateTime? start;
|
||||
final DateTime? expiry;
|
||||
|
||||
const TimeValidity({this.start, this.expiry});
|
||||
|
||||
bool get isExpired => expiry?.isBefore(DateTime.now()) ?? false;
|
||||
bool get isNotStarted => start?.isAfter(DateTime.now()) ?? false;
|
||||
bool get isActive => (!isNotStarted) && (!isExpired);
|
||||
|
||||
TimeValidity copyWith({
|
||||
DateTime? Function()? start,
|
||||
DateTime? Function()? expiry,
|
||||
}) => TimeValidity(
|
||||
start: start == null ? this.start : start(),
|
||||
expiry: expiry == null ? this.expiry : expiry(),
|
||||
);
|
||||
|
||||
factory TimeValidity.fromJson(Map<String, dynamic> json) => _$TimeValidityFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$TimeValidityToJson(this);
|
||||
}
|
||||
30
frontend/pshared/lib/models/storable.dart
Normal file
30
frontend/pshared/lib/models/storable.dart
Normal file
@@ -0,0 +1,30 @@
|
||||
import 'package:pshared/config/constants.dart';
|
||||
|
||||
|
||||
abstract class Storable {
|
||||
String get id;
|
||||
DateTime get createdAt;
|
||||
DateTime get updatedAt;
|
||||
}
|
||||
|
||||
class _StorableImp implements Storable {
|
||||
@override
|
||||
final String id;
|
||||
@override
|
||||
final DateTime createdAt;
|
||||
@override
|
||||
final DateTime updatedAt;
|
||||
|
||||
const _StorableImp({
|
||||
required this.id,
|
||||
required this.createdAt,
|
||||
required this.updatedAt,
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
Storable newStorable({String? id, DateTime? createdAt, DateTime? updatedAt}) => _StorableImp(
|
||||
id: id ?? Constants.nilObjectRef,
|
||||
createdAt: createdAt ?? DateTime.now().toUtc(),
|
||||
updatedAt: updatedAt ?? DateTime.now().toUtc(),
|
||||
);
|
||||
Reference in New Issue
Block a user