-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathGuardianStatusPanel.tsx
More file actions
75 lines (70 loc) · 2.44 KB
/
Copy pathGuardianStatusPanel.tsx
File metadata and controls
75 lines (70 loc) · 2.44 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
import { useState } from 'react';
import { useMutation } from '@tanstack/react-query';
import { ApiError, resendGuardianInvite, type GuardianStatus } from '../../api/client';
type Props = {
guardian: GuardianStatus | undefined;
guardianName?: string | undefined;
};
export function GuardianStatusPanel({ guardian, guardianName }: Props) {
const [flash, setFlash] = useState<string | null>(null);
const [error, setError] = useState<string | null>(null);
const mut = useMutation({
mutationFn: () => resendGuardianInvite(),
onSuccess: () => {
setError(null);
setFlash('Invite sent.');
},
onError: (err) => {
setFlash(null);
if (err instanceof ApiError && err.status === 429) {
setError('Please wait a bit before resending — we don’t want to spam your parent.');
} else {
setError('Could not send the invite. Please try again.');
}
},
});
if (!guardian || !guardian.hasLink || !guardian.guardianEmail) {
return null;
}
const status = guardian.taskComplete
? 'complete'
: guardian.acceptedAt
? 'in_progress'
: 'not_started';
const label =
status === 'complete'
? 'Parent portal: complete'
: status === 'in_progress'
? 'Parent portal: in progress'
: 'Parent portal: not started';
const dot =
status === 'complete' ? 'bg-accent' : status === 'in_progress' ? 'bg-ink' : 'bg-muted';
const displayName = guardianName?.trim() || guardian.guardianEmail;
return (
<aside className="rule-t rule-b py-4 my-6 flex flex-wrap items-baseline gap-x-6 gap-y-2 text-sm">
<span className="inline-flex items-baseline gap-2">
<span
aria-hidden
className={`inline-block w-2 h-2 rounded-full self-center ${dot}`}
/>
<span className="smallcaps text-muted">{label}</span>
</span>
<span className="text-ink">
We’ve emailed <em>{displayName}</em> at{' '}
<span className="font-mono">{guardian.guardianEmail}</span>.
</span>
{status !== 'complete' && (
<button
type="button"
className="text-accent hover:underline text-sm"
disabled={mut.isPending}
onClick={() => mut.mutate()}
>
{mut.isPending ? 'Sending…' : 'Resend invite'}
</button>
)}
{flash && <span className="text-muted italic">{flash}</span>}
{error && <span className="text-accent">{error}</span>}
</aside>
);
}