fix(work-orders): let picker toggle clear appointment start and end

EOF
This commit is contained in:
Arthur Bassi 2026-08-31 09:35:49 -03:00
parent 740048508c
commit 15459e8d40
2 changed files with 51 additions and 6 deletions

View file

@ -35,6 +35,20 @@ function slotStyle(active: boolean): React.CSSProperties {
};
}
function nextStartSelection(
currentStart: string,
currentEnd: string,
slot: string,
): { start: string; end: string } {
if (slot === currentStart) {
return { start: "", end: "" };
}
return {
start: slot,
end: currentEnd && currentEnd <= slot ? "" : currentEnd,
};
}
function ApptTimeSlotList({
slots,
active,
@ -120,10 +134,9 @@ export function ApptTimeCell({ apptTime, onSave }: ApptTimeCellProps) {
slots={TIME_SLOTS}
active={start}
onPick={(t) => {
setStart(t);
if (end && end <= t) {
setEnd("");
}
const next = nextStartSelection(start, end, t);
setStart(next.start);
setEnd(next.end);
}}
/>
</div>
@ -131,7 +144,13 @@ export function ApptTimeCell({ apptTime, onSave }: ApptTimeCellProps) {
<Text as="p" className="px-3 pb-1 pt-2" style={SLOT_HEADER_SX}>
End <span className="font-normal normal-case">(optional)</span>
</Text>
<ApptTimeSlotList slots={endSlots} active={end} onPick={setEnd} />
<ApptTimeSlotList
slots={endSlots}
active={end}
onPick={(t) => {
setEnd(t === end ? "" : t);
}}
/>
</div>
</div>
<div className="flex items-center justify-between px-3 py-2">

View file

@ -6,7 +6,7 @@ import {
apptTimePopoverHint,
commitApptTimeSelection,
} from "@/domain/work-orders/utils/appt-time-selection";
import { fmt12 } from "@/domain/work-orders/utils/wizard-date-utils";
import { fmt12, formatApptRange } from "@/domain/work-orders/utils/wizard-date-utils";
describe("apptTimePopoverHint", () => {
it("asks for start when empty", () => {
@ -100,6 +100,32 @@ describe("ApptTimeCell", () => {
expect(onSave).not.toHaveBeenCalled();
});
it("clears optional end when the selected end slot is toggled off", async () => {
const user = userEvent.setup();
const onSave = vi.fn();
render(<ApptTimeCell apptTime="09:00 – 11:00" onSave={onSave} />);
await user.click(screen.getByRole("button", { name: formatApptRange("09:00", "11:00") }));
const endSlots = await screen.findAllByRole("button", { name: fmt12("11:00") });
await user.click(endSlots[endSlots.length - 1]!);
await user.click(screen.getByRole("button", { name: /^done$/i }));
expect(onSave).toHaveBeenCalledWith("09:00");
});
it("clears start and end when the selected start slot is toggled off", async () => {
const user = userEvent.setup();
const onSave = vi.fn();
render(<ApptTimeCell apptTime="09:00 – 11:00" onSave={onSave} />);
await user.click(screen.getByRole("button", { name: formatApptRange("09:00", "11:00") }));
const startSlots = await screen.findAllByRole("button", { name: fmt12("09:00") });
await user.click(startSlots[0]!);
await user.click(screen.getByRole("button", { name: /^done$/i }));
expect(onSave).toHaveBeenCalledWith("");
});
it("hydrates start-only stored times so Done can clear them", async () => {
const user = userEvent.setup();
const onSave = vi.fn();