fix(plan): add 'Upravit celý rozsah' button, use class-based action rows

This commit is contained in:
BOHA
2026-06-05 13:58:07 +02:00
parent 9a11a8f001
commit 2f76fe0bc1
3 changed files with 61 additions and 23 deletions

View File

@@ -8,6 +8,7 @@ import { ResolvedCell } from "../lib/queries/plan";
interface Project {
id: number;
name: string;
project_number?: string;
}
export type PlanCellModalMode =
@@ -64,6 +65,7 @@ interface Props {
userId: number,
date: string,
) => Promise<void>;
onSwitchToEditRange: (entryId: number, userId: number, date: string) => void;
}
const CATEGORIES = [
@@ -218,13 +220,7 @@ function EditForm(props: Props) {
loading={submitting}
>
{mode.kind !== "create" && (
<div
style={{
marginBottom: 12,
display: "flex",
justifyContent: "flex-end",
}}
>
<div className="plan-modal-actions">
<button
type="button"
className="admin-btn admin-btn-danger"
@@ -314,7 +310,8 @@ function EditForm(props: Props) {
function DayInRangeModal(
props: Props & { mode: Extract<PlanCellModalMode, { kind: "day-in-range" }> },
) {
const { mode, onClose, onCreateOverrideFromRange } = props;
const { mode, onClose, onCreateOverrideFromRange, onSwitchToEditRange } =
props;
return (
<FormModal
isOpen
@@ -331,22 +328,17 @@ function DayInRangeModal(
<p>Co chcete udělat?</p>
<ul>
<li>
Upravit celý rozsah klikněte na tlačítko níže nebo zavřete a
klikněte znovu na buňku v režimu editace rozsahu.
<strong>Upravit celý rozsah</strong> otevře editor celého rozsahu.
</li>
<li>
Upravit pouze tento den vytvoří přepsání (override) pro toto datum.
<strong>Upravit pouze tento den</strong> vytvoří přepsání (override)
pro toto datum; zbytek rozsahu zůstane beze změny.
</li>
<li>
<strong>Zavřít</strong> ponechá rozsah beze změny.
</li>
<li>Zavřít ponechá rozsah beze změny.</li>
</ul>
<div
style={{
marginTop: 12,
display: "flex",
gap: 8,
justifyContent: "flex-end",
}}
>
<div className="plan-modal-actions">
<button
type="button"
className="admin-btn admin-btn-secondary"
@@ -368,15 +360,27 @@ function DayInRangeModal(
>
Upravit pouze tento den
</button>
<button
type="button"
className="admin-btn admin-btn-primary"
onClick={() =>
onSwitchToEditRange(mode.entryId, mode.userId, mode.date)
}
>
Upravit celý rozsah
</button>
</div>
</FormModal>
);
}
function ViewModal(props: Props) {
const { mode, onClose } = props;
const { mode, onClose, projects } = props;
if (mode.kind !== "view") return null;
const c = mode.cell;
const project = c.project_id
? (projects.find((p) => p.id === c.project_id) ?? null)
: null;
return (
<FormModal isOpen title="Detail plánu" onClose={onClose} hideFooter>
<p>
@@ -386,10 +390,15 @@ function ViewModal(props: Props) {
<strong>Kategorie:</strong> {c.category}
</p>
<p>
<strong>Projekt:</strong> {c.project_id ?? ""}
<strong>Projekt:</strong>{" "}
{project
? project.project_number
? `${project.project_number}${project.name}`
: project.name
: "—"}
</p>
<p>
<strong>Text:</strong> {c.note}
<strong>Text:</strong> {c.note || "—"}
</p>
{c.rangeFrom && c.rangeTo && (
<p>

View File

@@ -203,6 +203,23 @@ export default function PlanWork() {
setModalCell(null);
}, [setHookModal]);
// Switch the modal from "day-in-range" to "edit-range" mode, keeping the
// same cell context so the EditForm opens with the range's values.
const switchToEditRange = useCallback(
(entryId: number, userId: number, date: string) => {
const cell = getCell(grid, userId, date);
if (!cell) return;
setModalCell(cell);
setHookModal({
kind: "edit-range",
entryId,
userId,
date,
});
},
[grid, setHookModal],
);
// --- Mutation wrappers -----------------------------------------------------
// The modal calls these with plain objects / ids. We resolve them to the
// hook's mutateAsync calls and surface server errors as alerts.
@@ -468,6 +485,7 @@ export default function PlanWork() {
onUpdateOverride={updateOverrideFn}
onDeleteOverride={deleteOverrideFn}
onCreateOverrideFromRange={createOverrideFromRange}
onSwitchToEditRange={switchToEditRange}
/>
</div>
);

View File

@@ -167,3 +167,14 @@
background: transparent;
padding: 0;
}
/* Action row inside a modal body (e.g. Delete button at top, or button
group in the day-in-range chooser). Mirrors .admin-modal-footer
styling but lives inside .admin-modal-body. */
.plan-modal-actions {
display: flex;
gap: 8px;
justify-content: flex-end;
margin-top: 12px;
margin-bottom: 0;
}