"use client"; import { useState } from "react"; import { toast } from "sonner"; import { Badge } from "@/components/ui/badge"; import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, } from "@/components/ui/card"; import { appealTransfer, cancelTransfer } from "@/app/(frontend)/transfers/actions"; import { TransferNoteDialog } from "@/components/frontend/transfers/TransferNoteDialog"; import { TRANSFER_ESCALATION_LABELS, TRANSFER_STATUS_LABELS, TRANSFER_STATUS_VARIANTS, assignmentLabel, formatTransferDate, personLabel, relationId, type TransferRecord, } from "@/components/frontend/transfers/transferTypes"; interface TransferRequestCardProps { readonly transfer: TransferRecord; readonly currentUserId: number; readonly onUpdated: () => Promise; } export function TransferRequestCard({ transfer, currentUserId, onUpdated, }: TransferRequestCardProps) { const [appealOpen, setAppealOpen] = useState(false); const [cancelBusy, setCancelBusy] = useState(false); const [confirmCancel, setConfirmCancel] = useState(false); const [error, setError] = useState(null); const isRequester = relationId(transfer.requester) === currentUserId; const canCancel = isRequester && transfer.status === "pending"; const canAppeal = isRequester && transfer.status === "rejected"; async function handleCancel() { if (!confirmCancel) { setConfirmCancel(true); return; } setCancelBusy(true); setError(null); try { const result = await cancelTransfer(transfer.id); if (!result.success) { setError(result.error ?? "Could not cancel the transfer request."); return; } setConfirmCancel(false); toast.success("Transfer request cancelled"); await onUpdated(); } catch (caughtError) { setError( caughtError instanceof Error ? caughtError.message : "Could not cancel the transfer request.", ); } finally { setCancelBusy(false); } } async function handleAppeal(note: string) { const result = await appealTransfer(transfer.id, note || undefined); if (result.success) void onUpdated(); return result; } return (
Transfer #{transfer.id} Requested {formatTransferDate(transfer.createdAt)} by {personLabel(transfer.requester)}
{TRANSFER_STATUS_LABELS[transfer.status]}
From {assignmentLabel(transfer.fromAssignment)}
Requested destination {assignmentLabel(transfer.toAssignment)}
{transfer.requestNote && (
Request note

{transfer.requestNote}

)} {transfer.rejectionReason && ( Rejection reason {transfer.rejectionReason} )} {transfer.status === "awaiting_superuser" && transfer.escalationReason && ( {TRANSFER_ESCALATION_LABELS[transfer.escalationReason]} A superuser will make the final decision. Remaining leader approvals are bypassed. )} {error && (

{error}

)}
{(canCancel || canAppeal) && ( {canCancel && ( )} {canAppeal && ( )} )}
); }