Organize/components/profile/request-link-form.tsx

104 lines
3.3 KiB
TypeScript

"use client";
import { useState } from "react";
import { toast } from "sonner";
import { Clock, Link2, Loader2 } from "lucide-react";
import { Button } from "@/components/ui/button";
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { requestAccountLink } from "@/lib/actions/account-links";
/**
* "Request Account Link": asks to link this account with another one on
* the server by email. On success the form is replaced by the
* "awaiting confirmation" status, since the recipient still has to accept
* it from their own Profile page.
*/
export function RequestLinkForm() {
const [email, setEmail] = useState("");
const [submitting, setSubmitting] = useState(false);
// Set once a request goes out; the section then shows the awaiting
// confirmation status until the recipient responds (or it's denied).
const [requestedEmail, setRequestedEmail] = useState<string | null>(null);
async function handleSubmit(event: React.FormEvent<HTMLFormElement>) {
event.preventDefault();
if (submitting) return;
setSubmitting(true);
try {
const result = await requestAccountLink(email);
if (result?.error) {
toast.error(result.error);
return;
}
setRequestedEmail(email.trim().toLowerCase());
toast.success("Link request sent.");
} catch {
toast.error("Couldn't send the link request. Try again.");
} finally {
setSubmitting(false);
}
}
return (
<Card>
<CardHeader>
<CardTitle>Request Account Link</CardTitle>
<CardDescription>
Link this account with another account on this server so you can
toggle between them. The other account has to accept the request.
</CardDescription>
</CardHeader>
<CardContent>
{requestedEmail ? (
<div className="flex items-center gap-2 text-sm">
<Clock className="size-4 shrink-0 text-muted-foreground" />
<span>
Request sent to{" "}
<span className="font-medium">{requestedEmail}</span> awaiting
confirmation.
</span>
</div>
) : (
<form
onSubmit={handleSubmit}
className="flex flex-col gap-3 sm:flex-row sm:items-end"
>
<div className="flex-1 space-y-1.5">
<Label htmlFor="link-request-email">Account email</Label>
<Input
id="link-request-email"
type="email"
required
autoComplete="off"
spellCheck={false}
placeholder="you@example.com"
value={email}
disabled={submitting}
onChange={(e) => setEmail(e.target.value)}
/>
</div>
<Button type="submit" disabled={submitting || !email.trim()}>
{submitting ? (
<Loader2 className="size-3.5 animate-spin" />
) : (
<Link2 className="size-3.5" />
)}
{submitting ? "Requesting…" : "Request Account Link"}
</Button>
</form>
)}
</CardContent>
</Card>
);
}