Offer: valid-till is a date-time picker, never in the past

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Yashas 2026-10-26 16:44:29 +05:30
parent 2e3c42df5e
commit 470ddc98c4

View File

@ -14,6 +14,12 @@ function fmtDateTime(v: string): string {
if (!v || isNaN(d.getTime())) return '';
return d.toLocaleDateString('en-GB', { day: '2-digit', month: 'short', year: 'numeric' }) + ', ' + d.toTimeString().slice(0, 5);
}
/** Now, in the datetime-local input's format, so a validity cannot be set in the past. */
function nowLocal(): string {
const d = new Date();
d.setMinutes(d.getMinutes() - d.getTimezoneOffset());
return d.toISOString().slice(0, 16);
}
/** A delivery window as the text the offer and the customer read: "12 Nov 2026, 06:00 - 12:00 IST". */
function fmtWindow(from: string, to: string): string {
const a = fmtDateTime(from);
@ -248,18 +254,18 @@ function OpsForm({ e, onDone }: { e: Enquiry; onDone: () => void }) {
function OfferForm({ e, onDone, revise, onCancel }: { e: Enquiry; onDone: () => void; revise: boolean; onCancel?: () => void }) {
const { busy, error, ok, submit } = useSubmit(e, onDone);
const [f, setF] = useState({ price: revise && e.price_usd_mt ? String(e.price_usd_mt) : '', basis: e.price_basis ?? `delivered ex-${e.supply_mode === 'pipeline' ? 'wharf' : 'barge'} ${e.port ?? ''}`.trim(),
valid: e.offer_valid_till ?? '', terms: e.payment_terms ?? '30 days from date of delivery', remarks: '' });
valid: '', terms: e.payment_terms ?? '30 days from date of delivery', remarks: '' });
const [regret, setRegret] = useState(false);
if (regret) return <ReasonForm e={e} onDone={onDone} activity={ACT.REGRET} field="lost_reason__regret" title="Regret the enquiry" cta="Send regret to customer" onCancel={() => setRegret(false)} />;
const sfx = revise ? 'revise' : 'offer';
return (
<Card title={revise ? 'Revise the offer' : 'Price and send the offer'} action={<Badge tone="notice">Your action</Badge>}>
<form className="grid gap-3 sm:grid-cols-2" onSubmit={(ev) => { ev.preventDefault();
const data: Record<string, unknown> = { [`price_usd_mt__${sfx}`]: Number(f.price), [`offer_valid_till__${sfx}`]: f.valid, [`offer_remarks__${sfx}`]: f.remarks };
const data: Record<string, unknown> = { [`price_usd_mt__${sfx}`]: Number(f.price), [`offer_valid_till__${sfx}`]: fmtDateTime(f.valid) + ' IST', [`offer_remarks__${sfx}`]: f.remarks };
if (!revise) { data.price_basis__offer = f.basis; data.payment_terms__offer = f.terms; }
submit(revise ? ACT.REVISE : ACT.OFFER, data); }}>
<Field label="Price (USD per MT)" required><input className="field-input" type="number" step="0.01" min="0" required value={f.price} onChange={(x) => setF({ ...f, price: x.target.value })} /></Field>
<Field label="Offer valid till" required><input className="field-input" required placeholder="26 Oct, 18:00 IST" value={f.valid} onChange={(x) => setF({ ...f, valid: x.target.value })} /></Field>
<Field label="Offer valid till (IST)" required><input className="field-input" type="datetime-local" required min={nowLocal()} value={f.valid} onChange={(x) => setF({ ...f, valid: x.target.value })} /></Field>
{!revise && <Field label="Price basis"><input className="field-input" value={f.basis} onChange={(x) => setF({ ...f, basis: x.target.value })} /></Field>}
{!revise && <Field label="Payment terms"><input className="field-input" value={f.terms} onChange={(x) => setF({ ...f, terms: x.target.value })} /></Field>}
<div className="sm:col-span-2"><Field label="Remarks for the customer"><textarea className="field-input" rows={2} value={f.remarks} onChange={(x) => setF({ ...f, remarks: x.target.value })} /></Field></div>