mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-03 20:13:15 +00:00
136 lines
4.2 KiB
TypeScript
136 lines
4.2 KiB
TypeScript
import { useState } from "react";
|
|
import { Text } from "@/components/ui/text";
|
|
import { UpliftRequestForm } from "@/app/v/[token]/dispatch/_components/uplift-request-form";
|
|
import type { UpliftFormValues } from "@/domain/vendor-portal/lib/uplift-validation";
|
|
import type { VendorPortalUpliftRequest } from "@/domain/vendor-portal/types/vendor-portal";
|
|
import { formatDateTime } from "@/lib/time-utils";
|
|
|
|
type UpliftRequestCardProps = {
|
|
request: VendorPortalUpliftRequest;
|
|
locked: boolean;
|
|
canAct: boolean;
|
|
uploadingPercent: number | undefined;
|
|
submitting: boolean;
|
|
errorMessage: string;
|
|
onWithdraw: (request: VendorPortalUpliftRequest) => void;
|
|
onRevise: (request: VendorPortalUpliftRequest, values: UpliftFormValues) => void;
|
|
onCancelRevise: () => void;
|
|
};
|
|
|
|
const WITHDRAWABLE_STATUSES = new Set(["Pending", "ChangesRequested"]);
|
|
|
|
function statusClassName(status: string): string {
|
|
return `vp-uplift-status-${String(status).toLowerCase()}`;
|
|
}
|
|
|
|
export function UpliftRequestCard({
|
|
request,
|
|
locked,
|
|
canAct,
|
|
uploadingPercent,
|
|
submitting,
|
|
errorMessage,
|
|
onWithdraw,
|
|
onRevise,
|
|
onCancelRevise,
|
|
}: UpliftRequestCardProps) {
|
|
const [revising, setRevising] = useState(false);
|
|
const canWithdraw = !locked && canAct && WITHDRAWABLE_STATUSES.has(request.status);
|
|
const canRevise = !locked && canAct && request.status === "ChangesRequested";
|
|
|
|
return (
|
|
<div className="vp-uplift-row">
|
|
<div className="vp-row">
|
|
<strong>Requested</strong>
|
|
<span>
|
|
${Number(request.requestedNTE).toFixed(2)} (was $
|
|
{Number(request.currentNTE ?? 0).toFixed(2)})
|
|
</span>
|
|
</div>
|
|
<div className="vp-row">
|
|
<strong>Status</strong>
|
|
<span>
|
|
<span className={statusClassName(request.status)}>{request.status}</span>
|
|
</span>
|
|
</div>
|
|
{Boolean(request.expiresAt) && (
|
|
<div className="vp-row">
|
|
<strong>Expires</strong>
|
|
<span>{formatDateTime(request.expiresAt as string)}</span>
|
|
</div>
|
|
)}
|
|
{Boolean(request.vendorReason) && (
|
|
<div className="vp-row">
|
|
<strong>Reason</strong>
|
|
<span>{request.vendorReason}</span>
|
|
</div>
|
|
)}
|
|
{Boolean(request.evidenceFileName) && (
|
|
<div className="vp-row">
|
|
<strong>Evidence</strong>
|
|
<span>
|
|
{request.evidenceFileName}
|
|
{request.evidenceContentType ? ` · ${request.evidenceContentType}` : ""}
|
|
</span>
|
|
</div>
|
|
)}
|
|
{Boolean(request.decisionNote) && (
|
|
<div className="vp-row">
|
|
<strong>Decision</strong>
|
|
<span>
|
|
{request.decisionNote}
|
|
{request.decidedByName ? ` — ${request.decidedByName}` : ""}
|
|
</span>
|
|
</div>
|
|
)}
|
|
{request.notificationStatus === "Error" && Boolean(request.notificationError) && (
|
|
<div className="vp-row">
|
|
<strong>Notification</strong>
|
|
<span className="vp-error-inline">{request.notificationError}</span>
|
|
</div>
|
|
)}
|
|
<Text variant="error" when={Boolean(errorMessage)}>
|
|
{errorMessage}
|
|
</Text>
|
|
|
|
{revising && canRevise ? (
|
|
<UpliftRequestForm
|
|
mode="revise"
|
|
currentNte={request.currentNTE}
|
|
initialRequested={String(request.requestedNTE)}
|
|
initialReason={request.vendorReason ?? ""}
|
|
hasExistingEvidence={request.evidenceDocumentId != null}
|
|
submitting={submitting}
|
|
uploadingPercent={uploadingPercent}
|
|
errorMessage=""
|
|
onSubmit={(values) => onRevise(request, values)}
|
|
onCancel={() => {
|
|
setRevising(false);
|
|
onCancelRevise();
|
|
}}
|
|
/>
|
|
) : (
|
|
<div className="vp-actions">
|
|
{canWithdraw && (
|
|
<button
|
|
type="button"
|
|
className="vp-btn vp-btn-ghost"
|
|
onClick={() => onWithdraw(request)}
|
|
>
|
|
Withdraw request
|
|
</button>
|
|
)}
|
|
{canRevise && (
|
|
<button
|
|
type="button"
|
|
className="vp-btn vp-btn-primary"
|
|
onClick={() => setRevising(true)}
|
|
>
|
|
Revise
|
|
</button>
|
|
)}
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|