-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTaxResidencyActions.tsx
More file actions
133 lines (115 loc) · 4.02 KB
/
TaxResidencyActions.tsx
File metadata and controls
133 lines (115 loc) · 4.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
'use client';
import AccountBalanceIcon from '@mui/icons-material/AccountBalance';
import AccountBalanceWalletOutlinedIcon from '@mui/icons-material/AccountBalanceWalletOutlined';
import QrCode2OutlinedIcon from '@mui/icons-material/QrCode2Outlined';
import { Box, Button, Stack, Typography } from '@mui/material';
import { useRouter } from 'next/navigation';
import { useState, useEffect } from 'react';
import { isMobile } from 'react-device-detect';
import { toast } from 'react-toastify';
import LogoBox from './LogoBox';
export default function TaxResidencyActions({ applicationId }: { applicationId: string }) {
const router = useRouter();
const [busy, setBusy] = useState<'cross' | 'same' | null>(null);
const [mounted, setMounted] = useState(false);
useEffect(() => {
setMounted(true);
}, []);
const provideTaxResidencyCrossDevice = async () => {
setBusy('cross');
try {
const response = await fetch(`/api/applications/${applicationId}/verify-tax-residency`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ taxResidency: true, sameDeviceFlow: false }),
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.error || `HTTP ${response.status}`);
}
await response.json();
// Navigate to tax residency QR code page
router.push(`/applications/${applicationId}/tax-residency`);
} catch (error) {
const message =
error instanceof Error ? error.message : "Couldn't start tax residency verification.";
toast.error(message);
setBusy(null);
}
};
const provideTaxResidencySameDevice = async () => {
setBusy('same');
try {
const response = await fetch(`/api/applications/${applicationId}/verify-tax-residency`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ taxResidency: true, sameDeviceFlow: true }),
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.error || `HTTP ${response.status}`);
}
const result = await response.json();
// Try deep link; detect failure (no handler) by lack of backgrounding
let opened = false;
const onVisibility = () => {
if (document.hidden) opened = true;
};
document.addEventListener('visibilitychange', onVisibility, { once: true });
window.location.href = result.url;
// If the page didn't background, show a hint
setTimeout(() => {
document.removeEventListener('visibilitychange', onVisibility);
if (!opened) {
toast.error('No wallet handled the link. Try the QR Code option.');
setBusy(null);
}
}, 1500);
} catch (error) {
const message =
error instanceof Error ? error.message : "Couldn't start tax residency verification.";
toast.error(message);
setBusy(null);
}
};
return (
<Box>
<Stack direction="row" spacing={1} alignItems="center" sx={{ mb: 1.5 }}>
<AccountBalanceIcon sx={{ color: 'primary.main' }} />
<Typography variant="h6">Tax Residency (optional)</Typography>
</Stack>
<LogoBox />
<Typography variant="body2" color="text.secondary" sx={{ mb: 2, textAlign: 'center' }}>
Use your European Digital Identity Wallet to provide tax residency attestation
</Typography>
<Stack spacing={1} alignItems="center">
{/* Only show Same Device button on mobile */}
{mounted && isMobile && (
<Button
fullWidth
variant="outlined"
color="primary"
startIcon={<AccountBalanceWalletOutlinedIcon />}
disabled={busy !== null}
onClick={provideTaxResidencySameDevice}
>
{busy === 'same' ? 'Starting…' : 'Provide Tax Residency'}
</Button>
)}
{/* Only show QR Code button on desktop */}
{mounted && !isMobile && (
<Button
fullWidth
variant="outlined"
color="primary"
startIcon={<QrCode2OutlinedIcon />}
disabled={busy !== null}
onClick={provideTaxResidencyCrossDevice}
>
{busy === 'cross' ? 'Starting…' : 'Provide Tax Residency (QR Code)'}
</Button>
)}
</Stack>
</Box>
);
}