mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-09-30 06:53:12 +00:00
166 lines
4.6 KiB
TypeScript
166 lines
4.6 KiB
TypeScript
import { Text } from "@/components/ui/text";
|
|
import { formatVendorPortalDateTime } from "@/domain/vendor-portal/lib/status-helpers";
|
|
import type { VendorPortalDispatchDetail } from "@/domain/vendor-portal/types/vendor-portal";
|
|
|
|
type DispatchSnapshotDetailsProps = {
|
|
data: VendorPortalDispatchDetail;
|
|
locked: boolean;
|
|
};
|
|
|
|
function resolveCanonicalService(workOrder: VendorPortalDispatchDetail["workOrder"]): string {
|
|
if (workOrder?.service) {
|
|
return workOrder.service;
|
|
}
|
|
|
|
return [workOrder?.trade, workOrder?.subTrade].filter(Boolean).join(" · ");
|
|
}
|
|
|
|
function DispatchCommercialDetails({ data }: Pick<DispatchSnapshotDetailsProps, "data">) {
|
|
const service = resolveCanonicalService(data.workOrder);
|
|
|
|
return (
|
|
<div style={{ marginTop: 12 }}>
|
|
{data.workOrder != null && Boolean(data.workOrder.internalWONumber) && (
|
|
<div className="vp-row">
|
|
<strong>WO #</strong>
|
|
<span>{data.workOrder.internalWONumber}</span>
|
|
</div>
|
|
)}
|
|
{Boolean(service) && (
|
|
<div className="vp-row">
|
|
<strong>Service</strong>
|
|
<span>{service}</span>
|
|
</div>
|
|
)}
|
|
{Boolean(data.poNumber) && (
|
|
<div className="vp-row">
|
|
<strong>PO #</strong>
|
|
<span>{data.poNumber}</span>
|
|
</div>
|
|
)}
|
|
{data.nteAmount != null && (
|
|
<div className="vp-row">
|
|
<strong>NTE</strong>
|
|
<span>${Number(data.nteAmount).toFixed(2)}</span>
|
|
</div>
|
|
)}
|
|
<div className="vp-row">
|
|
<strong>Invoice</strong>
|
|
<span>
|
|
{data.invoiceStatus || "Not Submitted"}
|
|
{data.invoiceNumber ? ` · ${data.invoiceNumber}` : ""}
|
|
</span>
|
|
</div>
|
|
<div className="vp-row">
|
|
<strong>Payment</strong>
|
|
<span>{data.paymentStatus || "Unavailable"}</span>
|
|
</div>
|
|
{Boolean(data.scheduledDate) && (
|
|
<div className="vp-row">
|
|
<strong>Scheduled</strong>
|
|
<span>{formatVendorPortalDateTime(data.scheduledDate)}</span>
|
|
</div>
|
|
)}
|
|
{Boolean(data.statusUpdatedAt) && (
|
|
<div className="vp-row">
|
|
<strong>Status updated</strong>
|
|
<span>{formatVendorPortalDateTime(data.statusUpdatedAt)}</span>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function DispatchLocationDetails({ data }: Pick<DispatchSnapshotDetailsProps, "data">) {
|
|
if (data.location == null) {
|
|
return null;
|
|
}
|
|
|
|
const address = [
|
|
data.location.address,
|
|
data.location.city,
|
|
data.location.state,
|
|
data.location.zipCode,
|
|
]
|
|
.filter(Boolean)
|
|
.join(", ");
|
|
|
|
return (
|
|
<>
|
|
<Text variant="heading" sx={{ marginTop: 2 }}>
|
|
Location
|
|
</Text>
|
|
{Boolean(data.workOrder?.siteCode) && (
|
|
<div className="vp-row">
|
|
<strong>Site code</strong>
|
|
<span>{data.workOrder?.siteCode}</span>
|
|
</div>
|
|
)}
|
|
<div>{data.location.name}</div>
|
|
<div className="vp-muted">{address}</div>
|
|
</>
|
|
);
|
|
}
|
|
|
|
function DispatcherContactDetails({ data }: Pick<DispatchSnapshotDetailsProps, "data">) {
|
|
const contact = data.dispatcherContact;
|
|
if (!contact || (!contact.name && !contact.email && !contact.phone)) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<Text variant="heading" sx={{ marginTop: 2 }}>
|
|
Dispatcher
|
|
</Text>
|
|
{Boolean(contact.name) && (
|
|
<div className="vp-row">
|
|
<strong>Name</strong>
|
|
<span>{contact.name}</span>
|
|
</div>
|
|
)}
|
|
{Boolean(contact.email) && (
|
|
<div className="vp-row">
|
|
<strong>Email</strong>
|
|
<span>
|
|
<a href={`mailto:${contact.email}`}>{contact.email}</a>
|
|
</span>
|
|
</div>
|
|
)}
|
|
{Boolean(contact.phone) && (
|
|
<div className="vp-row">
|
|
<strong>Phone</strong>
|
|
<span>
|
|
<a href={`tel:${contact.phone}`}>{contact.phone}</a>
|
|
</span>
|
|
</div>
|
|
)}
|
|
</>
|
|
);
|
|
}
|
|
|
|
export function DispatchSnapshotDetails({ data, locked }: DispatchSnapshotDetailsProps) {
|
|
const description = data.description || data.workOrder?.description;
|
|
|
|
return (
|
|
<>
|
|
<DispatchCommercialDetails data={data} />
|
|
<DispatchLocationDetails data={data} />
|
|
<DispatcherContactDetails data={data} />
|
|
{locked && (
|
|
<Text variant="feedback" className="vp-muted" sx={{ marginTop: 2 }}>
|
|
This dispatch is {data.status.toLowerCase()} and locked to further changes. Comments
|
|
remain open.
|
|
</Text>
|
|
)}
|
|
{Boolean(description) && (
|
|
<>
|
|
<Text variant="heading" sx={{ marginTop: 2 }}>
|
|
Description
|
|
</Text>
|
|
<div>{description}</div>
|
|
</>
|
|
)}
|
|
</>
|
|
);
|
|
}
|