import { useState } from "react";
import type { WeeklyHours } from "../../api/types";
import { changeDay, DAY_NAMES, dayRows, hoursErrors, hoursFrom, type DayRow } from "../../logic/hours";
import { checkClass, cn, FieldError, fieldClass, Hint } from "../kit";
const timeClass = cn(fieldClass, "w-[122px] px-2 tabular-nums");
/** One week of hours, a row a day: open with its times, or closed. Tells the parent the hours and whether they can be saved. */
export function HoursEditor({
id,
legend,
help,
hours,
disabled,
onChange,
}: {
id: string;
legend: string;
help: string;
hours: WeeklyHours;
disabled: boolean;
onChange: (hours: WeeklyHours, valid: boolean) => void;
}) {
const [rows, setRows] = useState<DayRow[]>(() => dayRows(hours));
const errors = hoursErrors(rows);
const update = (day: number, change: Partial<Omit<DayRow, "day">>) => {
const next = changeDay(rows, day, change);
setRows(next);
onChange(hoursFrom(next), Object.keys(hoursErrors(next)).length === 0);
};
return (
<fieldset className="m-0 flex min-w-0 flex-col border-0 p-0" disabled={disabled} aria-describedby={`${id}-help`}>
<legend className="sr-only">{legend}</legend>
<Hint id={`${id}-help`} className="-mt-2 mb-2">
{help}
</Hint>
{rows.map((r) => {
const name = DAY_NAMES[r.day];
const errorId = `${id}-${r.day}-error`;
return (
<div key={r.day} className="flex flex-wrap items-center gap-x-3 gap-y-1.5 py-2 shadow-[inset_0_-1px_0_var(--color-hairline)] last:shadow-none">
<label className="flex w-[100px] shrink-0 cursor-pointer items-center gap-2.5 text-[13.5px] font-medium text-ink has-disabled:cursor-not-allowed">
<input type="checkbox" className={checkClass.replace("mt-0.5 ", "")} checked={r.open} onChange={(e) => update(r.day, { open: e.target.checked })} />
{name}
</label>
{r.open ? (
<span className="flex flex-wrap items-center gap-2 text-[13px] text-muted">
<input
type="time"
step={300}
className={timeClass}
aria-label={`${name}, from`}
value={r.from}
aria-invalid={errors[r.day] ? true : undefined}
aria-describedby={errors[r.day] ? errorId : undefined}
onChange={(e) => update(r.day, { from: e.target.value })}
/>
<span aria-hidden="true">to</span>
<input
type="time"
step={300}
className={timeClass}
aria-label={`${name}, until`}
value={r.to}
aria-invalid={errors[r.day] ? true : undefined}
aria-describedby={errors[r.day] ? errorId : undefined}
onChange={(e) => update(r.day, { to: e.target.value })}
/>
{r.more.length > 0 && <small className="text-[12.5px] text-muted">also {r.more.map((m) => `${m.open}–${m.close}`).join(", ")}</small>}
</span>
) : (
<span className="flex h-[38px] items-center text-[13px] text-subtle">Closed</span>
)}
{errors[r.day] && (
<FieldError id={errorId} className="basis-full pl-[112px] max-sm:pl-0">
{errors[r.day]}
</FieldError>
)}
</div>
);
})}
</fieldset>
);
}