dev
dart 206 lines 6.09 KB
Raw
1 import 'package:cake_wallet/core/utilities.dart';
2 import 'package:cake_wallet/entities/fiat_currency.dart';
3
4 enum CakePayCardType {
5 prepaid('Prepaid Cards'),
6 gift('gift'),
7 onDemand('on_demand'),
8 custom('custom');
9
10 const CakePayCardType(this.apiValue);
11
12 final String apiValue;
13 }
14
15 class CakePayCard {
16 final int id;
17 final String name;
18 final CakePayCardType? type;
19 final String? description;
20 final String? termsAndConditions;
21 final String? howToUse;
22 final String? expiryAndValidity;
23 final String? cardImageUrl;
24 final String? country;
25 final FiatCurrency fiatCurrency;
26 final String? minValueUsd;
27 final String? maxValueUsd;
28 final String? minValue;
29 final String? maxValue;
30 final List<Denomination> denominationItems;
31 final List<PrepaidRange> prepaidRange;
32
33 CakePayCard(
34 {required this.id,
35 required this.name,
36 this.type,
37 this.description,
38 this.termsAndConditions,
39 this.howToUse,
40 this.expiryAndValidity,
41 this.cardImageUrl,
42 this.country,
43 required this.fiatCurrency,
44 this.minValueUsd,
45 this.maxValueUsd,
46 this.minValue,
47 this.maxValue,
48 List<Denomination>? denominationItems,
49 List<PrepaidRange>? prepaidRange})
50 : denominationItems = denominationItems ?? const [],
51 prepaidRange = prepaidRange ?? const [];
52
53 CakePayCard copyWith({
54 int? id,
55 String? name,
56 CakePayCardType? type,
57 String? description,
58 String? termsAndConditions,
59 String? howToUse,
60 String? expiryAndValidity,
61 String? cardImageUrl,
62 String? country,
63 FiatCurrency? fiatCurrency,
64 String? minValueUsd,
65 String? maxValueUsd,
66 String? minValue,
67 String? maxValue,
68 List<Denomination>? denominationItems,
69 List<PrepaidRange>? prepaidRange,
70 }) {
71 return CakePayCard(
72 id: id ?? this.id,
73 name: name ?? this.name,
74 type: type ?? this.type,
75 description: description ?? this.description,
76 termsAndConditions: termsAndConditions ?? this.termsAndConditions,
77 howToUse: howToUse ?? this.howToUse,
78 expiryAndValidity: expiryAndValidity ?? this.expiryAndValidity,
79 cardImageUrl: cardImageUrl ?? this.cardImageUrl,
80 country: country ?? this.country,
81 fiatCurrency: fiatCurrency ?? this.fiatCurrency,
82 minValueUsd: minValueUsd ?? this.minValueUsd,
83 maxValueUsd: maxValueUsd ?? this.maxValueUsd,
84 minValue: minValue ?? this.minValue,
85 maxValue: maxValue ?? this.maxValue,
86 denominationItems: denominationItems ?? this.denominationItems,
87 prepaidRange: prepaidRange ?? this.prepaidRange,
88 );
89 }
90
91 static CakePayCardType? cakePayCardTypeFromApi(String? value) {
92 if (value == null) return null;
93 final normalized = value.trim().toLowerCase();
94 return CakePayCardType.values.firstWhereOrNull(
95 (e) => e.apiValue.toLowerCase() == normalized,
96 );
97 }
98
99 factory CakePayCard.fromJson(Map<String, dynamic> json) {
100 final name = stripHtmlIfNeeded(json['name'] as String? ?? '');
101 final typeString = json['type'] as String? ?? '';
102 final description = stripHtmlIfNeeded(json['description'] as String? ?? '');
103 final termsAndConditions = stripHtmlIfNeeded(json['terms_and_conditions'] as String? ?? '');
104 final howToUse = stripHtmlIfNeeded(json['how_to_use'] as String? ?? '');
105 final fiatCurrency = FiatCurrency.deserialize(raw: json['currency_code'] as String? ?? '');
106
107 String? minValue = json['min_value'] as String?;
108
109 final parsedMinValueLocal = _toDouble(json['min_value']);
110 final parsedMinValueUsd = _toDouble(json['min_value_usd']);
111
112 if (parsedMinValueLocal != null &&
113 parsedMinValueLocal > 0 &&
114 parsedMinValueUsd != null &&
115 parsedMinValueUsd > 0 &&
116 parsedMinValueUsd < 10.0) {
117 final rate = parsedMinValueLocal / parsedMinValueUsd;
118 final minLocalValueLimit = 10.0 * rate;
119 minValue = minLocalValueLimit.toStringAsFixed(2);
120 }
121
122 final raw = (json['denominations'] as List?) ?? const [];
123 final denominations = <Denomination>[];
124 for (final item in raw) {
125 if (item is Map) {
126 denominations.add(Denomination.fromJson(Map<String, dynamic>.from(item)));
127 }
128 }
129
130 final cakePayCardType = cakePayCardTypeFromApi(typeString);
131
132 return CakePayCard(
133 id: json['id'] as int? ?? 0,
134 name: name,
135 type: cakePayCardType,
136 description: description,
137 termsAndConditions: termsAndConditions,
138 howToUse: howToUse,
139 expiryAndValidity: json['expiry_and_validity'] as String?,
140 cardImageUrl: json['card_image_url'] as String?,
141 country: json['country'] as String?,
142 fiatCurrency: fiatCurrency,
143 minValueUsd: json['min_value_usd'] as String?,
144 maxValueUsd: json['max_value_usd'] as String?,
145 minValue: minValue,
146 maxValue: json['max_value'] as String?,
147 denominationItems: denominations,
148 );
149 }
150
151 static String stripHtmlIfNeeded(String text) {
152 return text.replaceAll(RegExp(r'<[^>]*>|&[^;]+;'), ' ');
153 }
154
155 static double? _toDouble(dynamic v) {
156 if (v == null) return null;
157 if (v is num) return v.toDouble();
158 return double.tryParse(v.toString());
159 }
160 }
161
162 class Denomination {
163 final double value;
164 final int? cardId;
165 final double? usdValue;
166
167 Denomination({
168 required this.value,
169 required this.cardId,
170 this.usdValue,
171 });
172
173 factory Denomination.fromJson(Map<String, dynamic> json) {
174 return Denomination(
175 value: _toDouble(json['value']) ?? 0,
176 cardId: json['card_id'] is int ? json['card_id'] as int : int.tryParse('${json['card_id']}'),
177 usdValue: _toDouble(json['usd_value']),
178 );
179 }
180 }
181
182 class PrepaidRange {
183 final double minValue;
184 final double maxValue;
185 final String rangeId;
186
187 PrepaidRange({
188 required this.minValue,
189 required this.maxValue,
190 required this.rangeId,
191 });
192
193 factory PrepaidRange.fromCard(CakePayCard card) {
194 return PrepaidRange(
195 minValue: _toDouble(card.minValue) ?? 0,
196 maxValue: _toDouble(card.maxValue) ?? 0,
197 rangeId: card.id.toString(),
198 );
199 }
200 }
201
202 double? _toDouble(dynamic v) {
203 if (v == null) return null;
204 if (v is num) return v.toDouble();
205 return double.tryParse(v.toString());
206 }