fix(plan): edit/add the clicked record + layer-aware add in exception mode
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -31,6 +31,7 @@ interface Project {
|
||||
export type PlanCellModalMode =
|
||||
| { kind: "closed" }
|
||||
| { kind: "create"; userId: number; date: string }
|
||||
| { kind: "create-override"; userId: number; date: string }
|
||||
| {
|
||||
kind: "edit-range";
|
||||
entryId: number;
|
||||
@@ -85,8 +86,14 @@ interface Props {
|
||||
date: string,
|
||||
) => Promise<void>;
|
||||
onSwitchToEditRange: (entryId: number, userId: number, date: string) => void;
|
||||
/** Open the create form for a brand-new record on (userId, date). */
|
||||
onAddRecord: (userId: number, date: string) => void;
|
||||
/** Open the create form for a brand-new record on (userId, date). The
|
||||
* `source` picks the layer the new record lands in: "entry" in normal mode,
|
||||
* "override" in exception mode (a day whose shown records are overrides). */
|
||||
onAddRecord: (
|
||||
userId: number,
|
||||
date: string,
|
||||
source: "entry" | "override",
|
||||
) => void;
|
||||
/** Open the right editor for one of the day's existing records. */
|
||||
onEditRecord: (cell: ResolvedCell, userId: number, date: string) => void;
|
||||
}
|
||||
@@ -137,21 +144,26 @@ function EditForm(props: Props) {
|
||||
const [confirmDelete, setConfirmDelete] = useState(false);
|
||||
|
||||
// Narrow mode to the kinds EditForm actually handles. The call site in
|
||||
// PlanCellModal only passes "create" | "edit-range" | "edit-override" but
|
||||
// the parameter type is the full union, so we narrow explicitly here.
|
||||
// PlanCellModal only passes "create" | "create-override" | "edit-range" |
|
||||
// "edit-override" but the parameter type is the full union, so we narrow
|
||||
// explicitly here.
|
||||
if (
|
||||
mode.kind !== "create" &&
|
||||
mode.kind !== "create-override" &&
|
||||
mode.kind !== "edit-range" &&
|
||||
mode.kind !== "edit-override"
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const isOverride = mode.kind === "edit-override";
|
||||
// An override is a single-day record — both editing one ("edit-override")
|
||||
// and creating one ("create-override") lock the date and hide the range UI.
|
||||
const isOverride =
|
||||
mode.kind === "edit-override" || mode.kind === "create-override";
|
||||
const activeCategories = props.categories.filter((c) => c.is_active);
|
||||
|
||||
const initial = (() => {
|
||||
if (mode.kind === "create") {
|
||||
if (mode.kind === "create" || mode.kind === "create-override") {
|
||||
return {
|
||||
date_from: mode.date,
|
||||
date_to: mode.date,
|
||||
@@ -196,9 +208,11 @@ function EditForm(props: Props) {
|
||||
const title =
|
||||
mode.kind === "create"
|
||||
? "Nový záznam plánu"
|
||||
: mode.kind === "edit-range"
|
||||
? "Upravit rozsah"
|
||||
: "Upravit přepsání dne";
|
||||
: mode.kind === "create-override"
|
||||
? "Nové přepsání dne"
|
||||
: mode.kind === "edit-range"
|
||||
? "Upravit rozsah"
|
||||
: "Upravit přepsání dne";
|
||||
|
||||
const handleSubmit = async () => {
|
||||
setSubmitting(true);
|
||||
@@ -213,6 +227,17 @@ function EditForm(props: Props) {
|
||||
category,
|
||||
note,
|
||||
});
|
||||
} else if (mode.kind === "create-override") {
|
||||
// An override is a single day — lock it to mode.date regardless of
|
||||
// any local dateFrom/isRange state (the date field is disabled for
|
||||
// overrides, but be explicit).
|
||||
await onSaveOverride({
|
||||
user_id: mode.userId,
|
||||
shift_date: mode.date,
|
||||
project_id: projectId,
|
||||
category,
|
||||
note,
|
||||
});
|
||||
} else if (mode.kind === "edit-range") {
|
||||
await onUpdateEntry(mode.entryId, {
|
||||
date_from: dateFrom,
|
||||
@@ -255,6 +280,10 @@ function EditForm(props: Props) {
|
||||
const showRetiredCategory =
|
||||
category && !activeCategories.some((c) => c.key === category);
|
||||
|
||||
// Both create flows ("create" entry, "create-override") show "Vytvořit" and
|
||||
// have no Smazat button (there is no existing row to delete yet).
|
||||
const isCreate = mode.kind === "create" || mode.kind === "create-override";
|
||||
|
||||
return (
|
||||
<>
|
||||
<Modal
|
||||
@@ -262,10 +291,10 @@ function EditForm(props: Props) {
|
||||
title={title}
|
||||
onClose={onClose}
|
||||
onSubmit={handleSubmit}
|
||||
submitText={mode.kind === "create" ? "Vytvořit" : "Uložit"}
|
||||
submitText={isCreate ? "Vytvořit" : "Uložit"}
|
||||
loading={submitting}
|
||||
>
|
||||
{mode.kind !== "create" && (
|
||||
{!isCreate && (
|
||||
<Box sx={{ mb: 2 }}>
|
||||
<Button
|
||||
variant="outlined"
|
||||
@@ -537,6 +566,12 @@ function DayPanel(
|
||||
const catMap = Object.fromEntries(categories.map((x) => [x.key, x]));
|
||||
const atCap = mode.cells.length >= 3;
|
||||
const free = 3 - mode.cells.length;
|
||||
// A day is in "exception mode" when its shown records are overrides. Cells
|
||||
// are single-layer (all overrides OR all entries), so cells[0] is enough.
|
||||
// "+ Přidat záznam" must add to the layer that's showing — an override here,
|
||||
// otherwise resolveCell would hide a freshly-created entry behind the
|
||||
// existing override after refetch.
|
||||
const isOverrideMode = mode.cells[0]?.source === "override";
|
||||
return (
|
||||
<Modal
|
||||
isOpen
|
||||
@@ -601,7 +636,13 @@ function DayPanel(
|
||||
variant="contained"
|
||||
color="primary"
|
||||
disabled={atCap}
|
||||
onClick={() => onAddRecord(mode.userId, mode.date)}
|
||||
onClick={() =>
|
||||
onAddRecord(
|
||||
mode.userId,
|
||||
mode.date,
|
||||
isOverrideMode ? "override" : "entry",
|
||||
)
|
||||
}
|
||||
>
|
||||
+ Přidat záznam
|
||||
</Button>
|
||||
|
||||
Reference in New Issue
Block a user