fix(plan): add 'Upravit celý rozsah' button, use class-based action rows
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user