fix(plan): keep retired category usable when editing an entry's note

Update validates the category only when it changes, so a note-only edit on an entry whose category was later hidden/deleted no longer 400s. The edit select also shows the current (retired) category marked '(skryta)' instead of silently snapping to the first active option; create defaults to an active category.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
BOHA
2026-06-06 01:17:23 +02:00
parent fce27633a9
commit e845400fca
2 changed files with 23 additions and 3 deletions

View File

@@ -122,7 +122,11 @@ function EditForm(props: Props) {
date_to: mode.date, date_to: mode.date,
is_range: false, is_range: false,
project_id: null as number | null, project_id: null as number | null,
category: "work", // Default to "work" when it's active, otherwise the first active
// category, so a new entry never starts on a retired key.
category: activeCategories.some((c) => c.key === "work")
? "work"
: (activeCategories[0]?.key ?? "work"),
note: "", note: "",
}; };
} }
@@ -294,6 +298,19 @@ function EditForm(props: Props) {
value={category} value={category}
onChange={(e) => setCategory(e.target.value)} onChange={(e) => setCategory(e.target.value)}
> >
{/* If the row's current category was retired/hidden, still show it
(marked) so the select reflects reality instead of silently
snapping to the first active option. The server only re-checks
the category if it changes, so keeping it saves fine. */}
{category && !activeCategories.some((c) => c.key === category) && (
<option value={category}>
{planCategoryLabel(
category,
Object.fromEntries(props.categories.map((x) => [x.key, x])),
)}{" "}
(skrytá)
</option>
)}
{activeCategories.map((c) => ( {activeCategories.map((c) => (
<option key={c.key} value={c.key}> <option key={c.key} value={c.key}>
{c.label} {c.label}

View File

@@ -502,7 +502,9 @@ export async function updateEntry(
return { error: "Datum do musí být stejné nebo po datumu od", status: 400 }; return { error: "Datum do musí být stejné nebo po datumu od", status: 400 };
} }
if (input.category) { // Only validate the category when it actually changes — so editing just the
// note of an entry whose category was later retired/hidden still saves.
if (input.category && input.category !== existing.category) {
const catErr = await assertActiveCategory(input.category); const catErr = await assertActiveCategory(input.category);
if (catErr) return catErr; if (catErr) return catErr;
} }
@@ -695,7 +697,8 @@ export async function updateOverride(
const lock = assertNotPastDate(dateStr, force); const lock = assertNotPastDate(dateStr, force);
if (lock) return lock; if (lock) return lock;
if (input.category) { // Only validate the category when it actually changes (see updateEntry).
if (input.category && input.category !== existing.category) {
const catErr = await assertActiveCategory(input.category); const catErr = await assertActiveCategory(input.category);
if (catErr) return catErr; if (catErr) return catErr;
} }