react-native-fpay 0.2.9 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/lib/module/FountainPayProvider.js +5 -1
  2. package/lib/module/FountainPayProvider.js.map +1 -1
  3. package/lib/module/core/api/index.js +22 -12
  4. package/lib/module/core/api/index.js.map +1 -1
  5. package/lib/module/engine/BLEReceiverService.js.map +1 -1
  6. package/lib/module/engine/FPEngine.js +24 -13
  7. package/lib/module/engine/FPEngine.js.map +1 -1
  8. package/lib/module/engine/useIsForeground.js +17 -0
  9. package/lib/module/engine/useIsForeground.js.map +1 -0
  10. package/lib/module/ui/components/AnimatedDots.js +68 -0
  11. package/lib/module/ui/components/AnimatedDots.js.map +1 -0
  12. package/lib/module/ui/components/ConfirmScreen.js +333 -0
  13. package/lib/module/ui/components/ConfirmScreen.js.map +1 -0
  14. package/lib/module/ui/modals/FPPaymentRequestModal.js +6 -8
  15. package/lib/module/ui/modals/FPPaymentRequestModal.js.map +1 -1
  16. package/lib/module/ui/modals/FPShell.js +7 -4
  17. package/lib/module/ui/modals/FPShell.js.map +1 -1
  18. package/lib/module/ui/screens/ReceiveScreen.js +379 -274
  19. package/lib/module/ui/screens/ReceiveScreen.js.map +1 -1
  20. package/lib/module/ui/screens/SendScreen.js +154 -45
  21. package/lib/module/ui/screens/SendScreen.js.map +1 -1
  22. package/lib/module/ui/screens/styles.js +89 -0
  23. package/lib/module/ui/screens/styles.js.map +1 -0
  24. package/lib/module/ui/screens/sub/receivePayment/Nfc/index.js +361 -0
  25. package/lib/module/ui/screens/sub/receivePayment/Nfc/index.js.map +1 -0
  26. package/lib/module/ui/screens/sub/receivePayment/Qr/index.js +338 -0
  27. package/lib/module/ui/screens/sub/receivePayment/Qr/index.js.map +1 -0
  28. package/lib/module/ui/screens/sub/receivePayment/Transfer/index.js +453 -0
  29. package/lib/module/ui/screens/sub/receivePayment/Transfer/index.js.map +1 -0
  30. package/lib/module/ui/screens/sub/{BluetoothSubScreen.js → sendPayment/BluetoothSubScreen.js} +25 -32
  31. package/lib/module/ui/screens/sub/sendPayment/BluetoothSubScreen.js.map +1 -0
  32. package/lib/module/ui/screens/sub/sendPayment/NFCSubScreen.js +354 -0
  33. package/lib/module/ui/screens/sub/sendPayment/NFCSubScreen.js.map +1 -0
  34. package/lib/module/ui/screens/sub/sendPayment/NQRSubScreen.js +440 -0
  35. package/lib/module/ui/screens/sub/sendPayment/NQRSubScreen.js.map +1 -0
  36. package/lib/module/ui/screens/sub/{ProximitySubScreen.js → sendPayment/ProximitySubScreen.js} +20 -111
  37. package/lib/module/ui/screens/sub/sendPayment/ProximitySubScreen.js.map +1 -0
  38. package/lib/module/ui/screens/sub/sendPayment/TransferSubScreen.js +327 -0
  39. package/lib/module/ui/screens/sub/sendPayment/TransferSubScreen.js.map +1 -0
  40. package/lib/typescript/src/FountainPayProvider.d.ts.map +1 -1
  41. package/lib/typescript/src/core/api/index.d.ts +20 -27
  42. package/lib/typescript/src/core/api/index.d.ts.map +1 -1
  43. package/lib/typescript/src/core/types/index.d.ts +56 -13
  44. package/lib/typescript/src/core/types/index.d.ts.map +1 -1
  45. package/lib/typescript/src/engine/BLEReceiverService.d.ts +2 -0
  46. package/lib/typescript/src/engine/BLEReceiverService.d.ts.map +1 -1
  47. package/lib/typescript/src/engine/FPEngine.d.ts +3 -1
  48. package/lib/typescript/src/engine/FPEngine.d.ts.map +1 -1
  49. package/lib/typescript/src/engine/useIsForeground.d.ts +2 -0
  50. package/lib/typescript/src/engine/useIsForeground.d.ts.map +1 -0
  51. package/lib/typescript/src/ui/components/AnimatedDots.d.ts +2 -0
  52. package/lib/typescript/src/ui/components/AnimatedDots.d.ts.map +1 -0
  53. package/lib/typescript/src/ui/components/ConfirmScreen.d.ts +10 -0
  54. package/lib/typescript/src/ui/components/ConfirmScreen.d.ts.map +1 -0
  55. package/lib/typescript/src/ui/components/OtpInput/Styles.d.ts +3 -3
  56. package/lib/typescript/src/ui/modals/FPPaymentRequestModal.d.ts.map +1 -1
  57. package/lib/typescript/src/ui/modals/FPShell.d.ts.map +1 -1
  58. package/lib/typescript/src/ui/screens/ReceiveScreen.d.ts +2 -9
  59. package/lib/typescript/src/ui/screens/ReceiveScreen.d.ts.map +1 -1
  60. package/lib/typescript/src/ui/screens/SendScreen.d.ts +4 -2
  61. package/lib/typescript/src/ui/screens/SendScreen.d.ts.map +1 -1
  62. package/lib/typescript/src/ui/screens/styles.d.ts +1390 -0
  63. package/lib/typescript/src/ui/screens/styles.d.ts.map +1 -0
  64. package/lib/typescript/src/ui/screens/sub/receivePayment/Nfc/index.d.ts +10 -0
  65. package/lib/typescript/src/ui/screens/sub/receivePayment/Nfc/index.d.ts.map +1 -0
  66. package/lib/typescript/src/ui/screens/sub/receivePayment/Qr/index.d.ts +10 -0
  67. package/lib/typescript/src/ui/screens/sub/receivePayment/Qr/index.d.ts.map +1 -0
  68. package/lib/typescript/src/ui/screens/sub/receivePayment/Transfer/index.d.ts +5 -0
  69. package/lib/typescript/src/ui/screens/sub/receivePayment/Transfer/index.d.ts.map +1 -0
  70. package/lib/typescript/src/ui/screens/sub/{BluetoothSubScreen.d.ts → sendPayment/BluetoothSubScreen.d.ts} +2 -11
  71. package/lib/typescript/src/ui/screens/sub/sendPayment/BluetoothSubScreen.d.ts.map +1 -0
  72. package/lib/typescript/src/ui/screens/sub/sendPayment/NFCSubScreen.d.ts +3 -0
  73. package/lib/typescript/src/ui/screens/sub/sendPayment/NFCSubScreen.d.ts.map +1 -0
  74. package/lib/typescript/src/ui/screens/sub/sendPayment/NQRSubScreen.d.ts +3 -0
  75. package/lib/typescript/src/ui/screens/sub/sendPayment/NQRSubScreen.d.ts.map +1 -0
  76. package/lib/typescript/src/ui/screens/sub/{ProximitySubScreen.d.ts → sendPayment/ProximitySubScreen.d.ts} +2 -10
  77. package/lib/typescript/src/ui/screens/sub/sendPayment/ProximitySubScreen.d.ts.map +1 -0
  78. package/lib/typescript/src/ui/screens/sub/sendPayment/TransferSubScreen.d.ts +3 -0
  79. package/lib/typescript/src/ui/screens/sub/sendPayment/TransferSubScreen.d.ts.map +1 -0
  80. package/package.json +1 -1
  81. package/src/FountainPayProvider.tsx +7 -1
  82. package/src/core/api/index.ts +34 -19
  83. package/src/core/types/index.ts +67 -13
  84. package/src/engine/BLEReceiverService.ts +2 -0
  85. package/src/engine/FPEngine.ts +29 -14
  86. package/src/engine/useIsForeground.ts +18 -0
  87. package/src/ui/components/AnimatedDots.tsx +81 -0
  88. package/src/ui/components/ConfirmScreen.tsx +421 -0
  89. package/src/ui/modals/FPPaymentRequestModal.tsx +7 -6
  90. package/src/ui/modals/FPShell.tsx +9 -9
  91. package/src/ui/screens/ReceiveScreen.tsx +266 -115
  92. package/src/ui/screens/SendScreen.tsx +141 -19
  93. package/src/ui/screens/styles.ts +101 -0
  94. package/src/ui/screens/sub/receivePayment/Nfc/index.tsx +418 -0
  95. package/src/ui/screens/sub/receivePayment/Qr/index.tsx +391 -0
  96. package/src/ui/screens/sub/receivePayment/Transfer/index.tsx +512 -0
  97. package/src/ui/screens/sub/{BluetoothSubScreen.tsx → sendPayment/BluetoothSubScreen.tsx} +27 -46
  98. package/src/ui/screens/sub/sendPayment/NFCSubScreen.tsx +302 -0
  99. package/src/ui/screens/sub/sendPayment/NQRSubScreen.tsx +490 -0
  100. package/src/ui/screens/sub/{ProximitySubScreen.tsx → sendPayment/ProximitySubScreen.tsx} +24 -44
  101. package/src/ui/screens/sub/sendPayment/TransferSubScreen.tsx +345 -0
  102. package/lib/module/ui/screens/sub/BluetoothSubScreen.js.map +0 -1
  103. package/lib/module/ui/screens/sub/NFCSubScreen.js +0 -164
  104. package/lib/module/ui/screens/sub/NFCSubScreen.js.map +0 -1
  105. package/lib/module/ui/screens/sub/NQRSubScreen.js +0 -131
  106. package/lib/module/ui/screens/sub/NQRSubScreen.js.map +0 -1
  107. package/lib/module/ui/screens/sub/ProximitySubScreen.js.map +0 -1
  108. package/lib/module/ui/screens/sub/TransferSubScreen.js +0 -353
  109. package/lib/module/ui/screens/sub/TransferSubScreen.js.map +0 -1
  110. package/lib/typescript/src/ui/screens/sub/BluetoothSubScreen.d.ts.map +0 -1
  111. package/lib/typescript/src/ui/screens/sub/NFCSubScreen.d.ts +0 -18
  112. package/lib/typescript/src/ui/screens/sub/NFCSubScreen.d.ts.map +0 -1
  113. package/lib/typescript/src/ui/screens/sub/NQRSubScreen.d.ts +0 -12
  114. package/lib/typescript/src/ui/screens/sub/NQRSubScreen.d.ts.map +0 -1
  115. package/lib/typescript/src/ui/screens/sub/ProximitySubScreen.d.ts.map +0 -1
  116. package/lib/typescript/src/ui/screens/sub/TransferSubScreen.d.ts +0 -11
  117. package/lib/typescript/src/ui/screens/sub/TransferSubScreen.d.ts.map +0 -1
  118. package/src/ui/screens/sub/NFCSubScreen.tsx +0 -86
  119. package/src/ui/screens/sub/NQRSubScreen.tsx +0 -62
  120. package/src/ui/screens/sub/TransferSubScreen.tsx +0 -147
@@ -0,0 +1,421 @@
1
+ import React, { useEffect, useRef, useState } from "react";
2
+ import {
3
+ View,
4
+ Text,
5
+ TouchableOpacity,
6
+ StyleSheet,
7
+ Animated,
8
+ StatusBar,
9
+ Dimensions,
10
+ SafeAreaView,
11
+ Vibration,
12
+ } from "react-native";
13
+ import styled from "styled-components/native";
14
+ import OTPInputs from "./OtpInput";
15
+ import { transactionAPI } from "../../core/api";
16
+ import InLoading from "./LoadingAnimation/InLoading";
17
+ import type { FPSendPaymentRequest } from "../../core/types";
18
+
19
+ const { width } = Dimensions.get("window");
20
+
21
+ // ─── Styled Components ───────────────────────────────────────────────────────
22
+
23
+ const SafeContainer = styled(SafeAreaView)`
24
+ flex: 1;
25
+ background-color: #ffffff;
26
+ `;
27
+
28
+ const Container = styled(View)`
29
+ flex: 1;
30
+ background-color: #ffffff;
31
+ padding-horizontal: 24px;
32
+ padding-top: 32px;
33
+ padding-bottom: 24px;
34
+ justify-content: space-between;
35
+ `;
36
+
37
+ const Header = styled(View)`
38
+ align-items: center;
39
+ margin-bottom: 28px;
40
+ `;
41
+
42
+ const Title = styled(Text)`
43
+ font-size: 26px;
44
+ font-weight: 700;
45
+ color: #111827;
46
+ letter-spacing: -0.5px;
47
+ margin-bottom: 12px;
48
+ font-family: "System";
49
+ `;
50
+
51
+ const SubTitle = styled(Text)`
52
+ font-size: 15px;
53
+ color: #6b7280;
54
+ text-align: center;
55
+ line-height: 22px;
56
+ max-width: 300px;
57
+ `;
58
+
59
+ const Card = styled(View)`
60
+ background-color: #f9fafb;
61
+ border-radius: 20px;
62
+ padding: 24px;
63
+ border-width: 1px;
64
+ border-color: #f0f0f0;
65
+ shadow-color: #000;
66
+ shadow-offset: 0px 2px;
67
+ shadow-opacity: 0.04;
68
+ shadow-radius: 8px;
69
+ elevation: 2;
70
+ `;
71
+
72
+ const CardTitle = styled(Text)`
73
+ font-size: 16px;
74
+ font-weight: 700;
75
+ color: #111827;
76
+ margin-bottom: 20px;
77
+ letter-spacing: -0.2px;
78
+ `;
79
+
80
+ const Divider = styled(View)`
81
+ height: 1px;
82
+ background-color: #e5e7eb;
83
+ margin-vertical: 14px;
84
+ `;
85
+
86
+ const Row = styled(View)`
87
+ flex-direction: row;
88
+ justify-content: space-between;
89
+ align-items: flex-start;
90
+ `;
91
+
92
+ const RowLabel = styled(Text)`
93
+ font-size: 14px;
94
+ color: #9ca3af;
95
+ font-weight: 500;
96
+ flex: 1;
97
+ `;
98
+
99
+ const RowValue = styled(Text)`
100
+ font-size: 14px;
101
+ color: #111827;
102
+ font-weight: 600;
103
+ flex: 1.5;
104
+ text-align: right;
105
+ `;
106
+
107
+ const AmountBadge = styled(View)`
108
+ background-color: #374151;
109
+ border-radius: 6px;
110
+ padding-horizontal: 10px;
111
+ padding-vertical: 4px;
112
+ align-self: flex-end;
113
+ margin-bottom: 4px;
114
+ `;
115
+
116
+ const AmountBadgeText = styled(Text)`
117
+ color: #ffffff;
118
+ font-size: 11px;
119
+ font-weight: 600;
120
+ letter-spacing: 0.3px;
121
+ `;
122
+
123
+ const AmountValue = styled(Text)`
124
+ font-size: 22px;
125
+ color: #111827;
126
+ font-weight: 800;
127
+ text-align: right;
128
+ letter-spacing: -0.5px;
129
+ `;
130
+
131
+ const AmountRow = styled(View)`
132
+ flex-direction: row;
133
+ justify-content: space-between;
134
+ align-items: flex-end;
135
+ `;
136
+
137
+ const AmountLabelContainer = styled(View)`
138
+ justify-content: flex-end;
139
+ padding-bottom: 2px;
140
+ `;
141
+
142
+ const AmountRightContainer = styled(View)`
143
+ align-items: flex-end;
144
+ `;
145
+
146
+ const ButtonRow = styled(View)`
147
+ flex-direction: row;
148
+ gap: 12px;
149
+ margin-top: 32px;
150
+ `;
151
+
152
+ interface RecheckButtonProps {
153
+ disabled?: boolean;
154
+ }
155
+
156
+ const RecheckButton = styled(TouchableOpacity)<RecheckButtonProps>`
157
+ flex: 1;
158
+ background-color: #dcfce7;
159
+ border-radius: 50px;
160
+ padding-vertical: 17px;
161
+ align-items: center;
162
+ justify-content: center;
163
+ `;
164
+
165
+ const RecheckButtonText = styled(Text)`
166
+ color: #16a34a;
167
+ font-size: 16px;
168
+ font-weight: 700;
169
+ letter-spacing: -0.2px;
170
+ `;
171
+
172
+ const ContinueButton = styled(TouchableOpacity)`
173
+ flex: 1;
174
+ background-color: #16a34a;
175
+ border-radius: 50px;
176
+ padding-vertical: 17px;
177
+ align-items: center;
178
+ justify-content: center;
179
+ shadow-color: #16a34a;
180
+ shadow-offset: 0px 4px;
181
+ shadow-opacity: 0.3;
182
+ shadow-radius: 10px;
183
+ elevation: 6;
184
+ `;
185
+
186
+ const ContinueButtonText = styled(Text)`
187
+ color: #ffffff;
188
+ font-size: 16px;
189
+ font-weight: 700;
190
+ letter-spacing: -0.2px;
191
+ `;
192
+
193
+ // ─── Types ───────────────────────────────────────────────────────────────────
194
+
195
+ interface TransferReminderScreenProps {
196
+ transaction: FPSendPaymentRequest;
197
+ onRecheck: () => void;
198
+ onContinue: () => void;
199
+ }
200
+
201
+ const getAmountInWords=(amount: number): string=> {
202
+ const ones = [
203
+ "One",
204
+ "Two",
205
+ "Three",
206
+ "Four",
207
+ "Five",
208
+ "Six",
209
+ "Seven",
210
+ "Eight",
211
+ "Nine",
212
+ "Ten",
213
+ "Eleven",
214
+ "Twelve",
215
+ "Thirteen",
216
+ "Fourteen",
217
+ "Fifteen",
218
+ "Sixteen",
219
+ "Seventeen",
220
+ "Eighteen",
221
+ "Nineteen",
222
+ ];
223
+ const tens = [
224
+ "",
225
+ "",
226
+ "Twenty",
227
+ "Thirty",
228
+ "Forty",
229
+ "Fifty",
230
+ "Sixty",
231
+ "Seventy",
232
+ "Eighty",
233
+ "Ninety",
234
+ ];
235
+
236
+ const integer = Math.floor(amount);
237
+
238
+ if (integer === 0) return "Zero";
239
+ if (integer < 20) return ones[integer] || "";
240
+ if (integer < 100)
241
+ return `${tens[Math.floor(integer / 10)]}${integer % 10 ? " " + ones[integer % 10] : ""}`;
242
+ if (integer < 1000)
243
+ return `${ones[Math.floor(integer / 100)]} Hundred${integer % 100 ? " " + getAmountInWords(integer % 100) : ""}`;
244
+
245
+ return `${integer.toLocaleString()}`;
246
+ }
247
+ // ─── Sub-components ──────────────────────────────────────────────────────────
248
+ const DetailRow: React.FC<{ label: string; value: string }> = ({
249
+ label,
250
+ value,
251
+ }) => (
252
+ <>
253
+ <Row>
254
+ <RowLabel>{label}</RowLabel>
255
+ <RowValue>{value}</RowValue>
256
+ </Row>
257
+ <Divider />
258
+ </>
259
+ );
260
+
261
+ // ─── Main Component ──────────────────────────────────────────────────────────
262
+
263
+ const ConfirmScreen: React.FC<TransferReminderScreenProps> = ({
264
+ transaction,
265
+ onRecheck,
266
+ onContinue,
267
+ }) => {
268
+ const fadeAnim = useRef(new Animated.Value(0)).current;
269
+ const slideAnim = useRef(new Animated.Value(30)).current;
270
+ const cardAnim = useRef(new Animated.Value(0)).current;
271
+ const cardSlideAnim = useRef(new Animated.Value(20)).current;
272
+ const buttonAnim = useRef(new Animated.Value(0)).current;
273
+
274
+ const [processing, setProcessing] = useState<boolean>(false);
275
+ const [errText, setErrText] = useState<string>("");
276
+ const [otp, setOtp] = useState<string>("");
277
+
278
+ const handleContinue=async()=>{
279
+ setProcessing(true);
280
+ try{
281
+ const response: any = await transactionAPI.validateOtp(otp, transaction?.sender?.email ?? '' );
282
+ if(!response.status){
283
+ Vibration.vibrate(100);
284
+ setErrText(response.message);
285
+ return;
286
+ }
287
+ onContinue();
288
+ }catch(error: any){
289
+ setErrText(error.message);
290
+ }finally{
291
+ setProcessing(true);
292
+ }
293
+
294
+ }
295
+
296
+ useEffect(() => {
297
+ Animated.sequence([
298
+ Animated.parallel([
299
+ Animated.timing(fadeAnim, {
300
+ toValue: 1,
301
+ duration: 400,
302
+ useNativeDriver: true,
303
+ }),
304
+ Animated.timing(slideAnim, {
305
+ toValue: 0,
306
+ duration: 400,
307
+ useNativeDriver: true,
308
+ }),
309
+ ]),
310
+ Animated.parallel([
311
+ Animated.timing(cardAnim, {
312
+ toValue: 1,
313
+ duration: 350,
314
+ useNativeDriver: true,
315
+ }),
316
+ Animated.timing(cardSlideAnim, {
317
+ toValue: 0,
318
+ duration: 350,
319
+ useNativeDriver: true,
320
+ }),
321
+ ]),
322
+ Animated.timing(buttonAnim, {
323
+ toValue: 1,
324
+ duration: 300,
325
+ useNativeDriver: true,
326
+ }),
327
+ ]).start();
328
+ }, []);
329
+
330
+ const formattedAmount = `${transaction?.currency ?? "₦"}${transaction?.amount.toFixed(2)}`;
331
+ const amountWords = getAmountInWords(transaction?.amount || 0);
332
+
333
+ return (
334
+ <Container>
335
+ <View>
336
+ <Animated.View
337
+ style={{
338
+ opacity: fadeAnim,
339
+ transform: [{ translateY: slideAnim }],
340
+ }}
341
+ >
342
+ <Header>
343
+ <Title>Reminder</Title>
344
+ <SubTitle>
345
+ Double check the transfer details before you proceed. Please
346
+ note that successful transfers cannot be reversed.
347
+ </SubTitle>
348
+ </Header>
349
+ </Animated.View>
350
+
351
+ {/* Card */}
352
+ <Animated.View
353
+ style={{
354
+ opacity: cardAnim,
355
+ transform: [{ translateY: cardSlideAnim }],
356
+ }}
357
+ >
358
+ <Card>
359
+ <CardTitle>Transaction Details</CardTitle>
360
+
361
+ <DetailRow label="Name" value={transaction?.recipient.accountName || ""} />
362
+ {transaction?.channel === 'transfer' && (
363
+ <>
364
+ <Row>
365
+ <RowLabel>Bank</RowLabel>
366
+ <RowValue>{transaction?.recipient?.bankName}</RowValue>
367
+ </Row>
368
+ <Row>
369
+ <RowLabel>Account No.</RowLabel>
370
+ <RowValue>{transaction?.recipient?.accountNumber}</RowValue>
371
+ </Row>
372
+ </>
373
+ )}
374
+
375
+ <Divider />
376
+
377
+ <AmountRow>
378
+ <AmountLabelContainer>
379
+ <RowLabel>Amount</RowLabel>
380
+ </AmountLabelContainer>
381
+ <AmountRightContainer>
382
+ <AmountBadge>
383
+ <AmountBadgeText>{amountWords}</AmountBadgeText>
384
+ </AmountBadge>
385
+ <AmountValue>{formattedAmount}</AmountValue>
386
+ </AmountRightContainer>
387
+ </AmountRow>
388
+ </Card>
389
+
390
+ <Card>
391
+ <OTPInputs callBack={setOtp} />
392
+ </Card>
393
+ </Animated.View>
394
+ </View>
395
+
396
+ {/* Buttons */}
397
+ <Animated.View style={{ opacity: buttonAnim }}>
398
+ {processing ? (
399
+ <ButtonRow>
400
+ <InLoading />
401
+ </ButtonRow>
402
+ ) : (
403
+ <ButtonRow>
404
+ <RecheckButton onPress={onRecheck} activeOpacity={0.75}>
405
+ <RecheckButtonText>Cancel</RecheckButtonText>
406
+ </RecheckButton>
407
+ <ContinueButton disabled={!otp} onPress={handleContinue} activeOpacity={0.85}>
408
+ <ContinueButtonText>Confirm</ContinueButtonText>
409
+ </ContinueButton>
410
+ </ButtonRow>
411
+ )}
412
+
413
+ </Animated.View>
414
+ </Container>
415
+ );
416
+ };
417
+
418
+
419
+
420
+
421
+ export default ConfirmScreen;
@@ -3,13 +3,16 @@ import { View, Text, Modal, StyleSheet, Animated, TouchableOpacity } from 'react
3
3
  import { FPEngine, _onEvent } from '../../engine/FPEngine';
4
4
  import { FPButton } from '../components/FPButton';
5
5
  import { C, R, S, F, shadow } from '../theme';
6
- import type { FPBluetoothPaymentRequest } from '../../core/types';
6
+ import type { FPBluetoothPaymentRequest, FPTransferRecipient, FPUserInfo } from '../../core/types';
7
7
 
8
8
  export function FPPaymentRequestModal() {
9
9
  const [request, setRequest] = useState<FPBluetoothPaymentRequest | null>(null);
10
10
  const [loading, setLoading] = useState(false);
11
11
  const scale = React.useRef(new Animated.Value(0.85)).current;
12
12
 
13
+ const recipient: FPUserInfo | null = FPEngine.getUser() ?? null;
14
+ const recipientAccount: FPTransferRecipient | null = FPEngine.getAccount() ?? null;
15
+
13
16
  useEffect(() => {
14
17
  const unsub = _onEvent('incoming_payment_request', (req: unknown) => {
15
18
  setRequest(req as FPBluetoothPaymentRequest);
@@ -36,8 +39,6 @@ export function FPPaymentRequestModal() {
36
39
 
37
40
  if (!request) return null;
38
41
 
39
- const user = FPEngine.getUser();
40
- const amountFormatted = (request.amount / 100).toLocaleString('en-NG', { minimumFractionDigits: 2 });
41
42
 
42
43
  return (
43
44
  <Modal
@@ -64,7 +65,7 @@ export function FPPaymentRequestModal() {
64
65
  <Animated.View style={[st.card, { transform: [{ scale }] }]}>
65
66
  <View style={st.avatar}>
66
67
  <Text style={st.avatarText}>
67
- {(request?.sender.accountName ?? request?.sender.deviceName ?? '?').charAt(0).toUpperCase()}
68
+ {(request?.sender.name ?? request?.sender.deviceName ?? '?').charAt(0).toUpperCase()}
68
69
  </Text>
69
70
  </View>
70
71
  <Text style={st.headline}>Payment Request</Text>
@@ -88,7 +89,7 @@ export function FPPaymentRequestModal() {
88
89
  marginBottom: 20,
89
90
  }}
90
91
  >
91
- {request.sender.accountName ?? request.sender.deviceName ?? 'Someone'}
92
+ {request.sender.name ?? request.sender.deviceName ?? 'Someone'}
92
93
  </Text>
93
94
  <Text style={st.sub}>wants to send you</Text>
94
95
  {request.amount &&(
@@ -123,7 +124,7 @@ export function FPPaymentRequestModal() {
123
124
  ) : null}
124
125
  <Text style={st.disclaimer}>
125
126
  Accepting will receive into{'\n'}
126
- <Text style={{ fontWeight: '700' }}>{user?.accountName}</Text> ({user?.accountNumber})
127
+ <Text style={{ fontWeight: '700' }}>{recipientAccount?.accountName}</Text> ({recipientAccount?.accountNumber})
127
128
  </Text>
128
129
  </View>
129
130
 
@@ -8,17 +8,18 @@ import React, { useEffect, useState, useRef } from 'react';
8
8
  import { Modal, View, Text, TouchableOpacity, StyleSheet, Animated, Dimensions, SafeAreaView, StatusBar, Platform } from 'react-native';
9
9
  import { _onEvent } from '../../engine/FPEngine';
10
10
  import SendScreen from '../screens/SendScreen';
11
- import { ReceiveScreen } from '../screens/ReceiveScreen';
11
+ import ReceiveScreen from '../screens/ReceiveScreen';
12
12
  import { FPPaymentRequestModal } from './FPPaymentRequestModal';
13
13
  import { FPEngine } from '../../engine/FPEngine';
14
14
  import { C, S, F, shadow } from '../theme';
15
- import type { FPCurrency } from '../../core/types';
15
+ import type { FPCurrency, FPUserInfo } from '../../core/types';
16
16
 
17
17
  const { width: SCREEN_W, height: SCREEN_H } = Dimensions.get('window');
18
18
 
19
19
  type SheetMode = 'send' | 'receive' | null;
20
20
 
21
21
  interface SheetState {
22
+ user?: FPUserInfo;
22
23
  mode: SheetMode;
23
24
  amount?: number;
24
25
  currency?: FPCurrency;
@@ -54,19 +55,15 @@ export function FPShell() {
54
55
  useEffect(() => {
55
56
  const unsubSend = _onEvent('show_send', (d: unknown) => {
56
57
  const data = d as any;
57
- open({ mode: 'send', amount: data?.amount, currency: data?.currency });
58
+ open({ mode: 'send', user: data?.user, amount: data?.amount, currency: data?.currency });
58
59
  });
59
60
  const unsubReceive = _onEvent('show_receive', (d: unknown) => {
60
61
  const data = d as any;
61
- open({ mode: 'receive', amount: data?.amount, currency: data?.currency });
62
+ open({ mode: 'receive', user: data?.user, amount: data?.amount, currency: data?.currency });
62
63
  });
63
64
  return () => { unsubSend(); unsubReceive(); };
64
65
  }, []);
65
66
 
66
- const title = sheet.mode === 'send' ? 'Send Money' : 'Receive Money';
67
- const accentColor = sheet.mode === 'send' ? C.brand : C.green;
68
-
69
-
70
67
  return (
71
68
  <>
72
69
  {/* Always-on BT payment request modal */}
@@ -79,6 +76,8 @@ export function FPShell() {
79
76
  <View style={st.content}>
80
77
  {sheet.mode === 'send' && (
81
78
  <SendScreen
79
+ user={FPEngine.getUser() ?? null}
80
+ account={FPEngine.getAccount() ?? null}
82
81
  amount={sheet.amount ?? 0}
83
82
  currency={sheet.currency ?? 'NGN'}
84
83
  onClose={close}
@@ -93,7 +92,8 @@ export function FPShell() {
93
92
  <ReceiveScreen
94
93
  amount={sheet.amount}
95
94
  currency={sheet.currency}
96
- user={FPEngine.getUser() ?? undefined}
95
+ user={FPEngine.getUser() ?? null}
96
+ account={FPEngine.getAccount() ?? null}
97
97
  onClose={close}
98
98
  onPaymentReceived={FPEngine.getCallbacks().onPaymentReceived}
99
99
  onError={FPEngine.getCallbacks().onError}