feat(uat-batch-23): supplemental-info — separate Generate link + Send by email
The single-button "Request more info" conflated link generation with
email send. Once tokens became reusable until expiry (PR15), the
two-step UX makes more sense — reps often need to copy the link and
share it via WhatsApp / iMessage instead of letting SMTP route it.
- API: POST /supplemental-info-request now accepts an optional
`{ sendEmail?: boolean }` body (defaults true for back-compat).
Generate-only callers pass `{ sendEmail: false }`.
- UI: two buttons replace the single CTA — "Generate link" (always
generates, never emails) + "Send by email" (the original
full-blow behaviour). Re-clicking "Generate link" with a token
already issued mints a fresh one (labeled "Regenerate link").
- Email body copy: drop "can only be used once" since PR15 made the
link reusable until expiry.
tsc clean. 1419/1419 vitest pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -40,16 +40,19 @@ export function SupplementalInfoRequestButton({ interestId, eoiStatus }: Props)
|
||||
const [link, setLink] = useState<string | null>(null);
|
||||
|
||||
const mutation = useMutation({
|
||||
mutationFn: () =>
|
||||
mutationFn: (vars: { sendEmail: boolean }) =>
|
||||
apiFetch<IssueResponse>(`/api/v1/interests/${interestId}/supplemental-info-request`, {
|
||||
method: 'POST',
|
||||
body: vars,
|
||||
}),
|
||||
onSuccess: (res) => {
|
||||
setLink(res.data.link);
|
||||
if (res.data.emailSent) {
|
||||
toast.success('Email sent — link also shown below for sharing manually.');
|
||||
toast.success('Email sent. Link also shown below for sharing manually.');
|
||||
} else {
|
||||
toast.message('Link generated — no client email on file, share manually.');
|
||||
toast.message(
|
||||
'Link generated. Click "Send by email" to mail it, or copy it to share manually.',
|
||||
);
|
||||
}
|
||||
},
|
||||
onError: (err) =>
|
||||
@@ -76,11 +79,20 @@ export function SupplementalInfoRequestButton({ interestId, eoiStatus }: Props)
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
onClick={() => mutation.mutate()}
|
||||
variant={link ? 'outline' : 'default'}
|
||||
onClick={() => mutation.mutate({ sendEmail: false })}
|
||||
disabled={mutation.isPending}
|
||||
>
|
||||
{mutation.isPending ? 'Generating…' : link ? 'Regenerate link' : 'Generate link'}
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
onClick={() => mutation.mutate({ sendEmail: true })}
|
||||
disabled={mutation.isPending}
|
||||
>
|
||||
<Mail className="mr-1.5 size-3.5" aria-hidden />
|
||||
{mutation.isPending ? 'Generating…' : link ? 'Resend' : 'Request more info'}
|
||||
{link ? 'Send by email' : 'Generate + email'}
|
||||
</Button>
|
||||
{link ? (
|
||||
<>
|
||||
|
||||
Reference in New Issue
Block a user