Improve toolbox reorder and checklist editing UX
All checks were successful
Deploy Sokko G / deploy (push) Successful in 8s
All checks were successful
Deploy Sokko G / deploy (push) Successful in 8s
This commit is contained in:
parent
1e4ac4259b
commit
8eb622e05d
11 changed files with 695 additions and 140 deletions
|
|
@ -2,6 +2,7 @@
|
|||
import { useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
||||
import { Icon } from "../../../components/Icon.jsx";
|
||||
import { Tabs } from "../../../components/Tabs.jsx";
|
||||
import { useDraftForm } from "../../../hooks/useDraftForm.js";
|
||||
import { useInlineEdit } from "../../../hooks/useInlineEdit.js";
|
||||
import { moveItem, useGroupedReorder } from "../../../hooks/useGroupedReorder.js";
|
||||
import {
|
||||
|
|
@ -24,6 +25,15 @@ const TIMER_TABS = [
|
|||
];
|
||||
|
||||
const COUNTDOWN_TYPES = ["duration", "daily_time", "time_pattern", "interval"];
|
||||
const EMPTY_TIME_PARTS = { hours: "", minutes: "", seconds: "" };
|
||||
const DEFAULT_COUNTDOWN_FORM = {
|
||||
label: "",
|
||||
type: "duration",
|
||||
duration: EMPTY_TIME_PARTS,
|
||||
time: EMPTY_TIME_PARTS,
|
||||
pattern: EMPTY_TIME_PARTS,
|
||||
interval: EMPTY_TIME_PARTS
|
||||
};
|
||||
const ALERT_MODES = [
|
||||
{ mode: "off", icon: "sound-mute" },
|
||||
{ mode: "visible", icon: "sound-min" },
|
||||
|
|
@ -73,14 +83,7 @@ export function TimerModule({ toolboxId, moduleId, context }) {
|
|||
const textContent = context.moduleText?.timer || {};
|
||||
const activeTab = data.activeTab;
|
||||
const [nowMs, setNowMs] = useState(getNowMs);
|
||||
const [countdownForm, setCountdownForm] = useState({
|
||||
label: "",
|
||||
type: "duration",
|
||||
duration: { hours: "", minutes: "", seconds: "" },
|
||||
time: { hours: "", minutes: "", seconds: "" },
|
||||
pattern: { hours: "", minutes: "", seconds: "" },
|
||||
interval: { hours: "", minutes: "", seconds: "" }
|
||||
});
|
||||
const countdownDraft = useDraftForm(DEFAULT_COUNTDOWN_FORM);
|
||||
|
||||
useEffect(() => {
|
||||
const intervalId = window.setInterval(() => setNowMs(getNowMs()), 50);
|
||||
|
|
@ -172,38 +175,35 @@ export function TimerModule({ toolboxId, moduleId, context }) {
|
|||
});
|
||||
}
|
||||
|
||||
function updateCountdownForm(patch) {
|
||||
setCountdownForm((current) => ({ ...current, ...patch }));
|
||||
}
|
||||
|
||||
function createCountdown(event) {
|
||||
event.preventDefault();
|
||||
const type = COUNTDOWN_TYPES.includes(countdownForm.type) ? countdownForm.type : "duration";
|
||||
const label = countdownForm.label.trim() || textContent.defaultCountdownLabel || "Timer";
|
||||
const now = getNowMs();
|
||||
let countdown = null;
|
||||
countdownDraft.handleSubmit(event, (draft, { updateValues }) => {
|
||||
const type = COUNTDOWN_TYPES.includes(draft.type) ? draft.type : "duration";
|
||||
const label = draft.label.trim() || textContent.defaultCountdownLabel || "Timer";
|
||||
const now = getNowMs();
|
||||
let countdown = null;
|
||||
|
||||
if (type === "duration") {
|
||||
const durationMs = timePartsToDurationMs(countdownForm.duration);
|
||||
if (durationMs > 0) countdown = { id: context.uid("timer"), label, type, durationMs, targetAt: now + durationMs };
|
||||
}
|
||||
if (type === "daily_time") {
|
||||
const time = timePartsToString(countdownForm.time);
|
||||
const targetAt = getDailyTargetMs(time, now);
|
||||
if (time && targetAt) countdown = { id: context.uid("timer"), label, type, time, targetAt };
|
||||
}
|
||||
if (type === "time_pattern") {
|
||||
const pattern = timePartsToString(countdownForm.pattern, { allowWildcard: true });
|
||||
if (pattern && getTimePatternTargetMs(pattern, now)) countdown = { id: context.uid("timer"), label, type, pattern };
|
||||
}
|
||||
if (type === "interval") {
|
||||
const intervalMs = timePartsToDurationMs(countdownForm.interval);
|
||||
if (intervalMs > 0) countdown = { id: context.uid("timer"), label, type, intervalMs, anchorAt: now };
|
||||
}
|
||||
if (type === "duration") {
|
||||
const durationMs = timePartsToDurationMs(draft.duration);
|
||||
if (durationMs > 0) countdown = { id: context.uid("timer"), label, type, durationMs, targetAt: now + durationMs };
|
||||
}
|
||||
if (type === "daily_time") {
|
||||
const time = timePartsToString(draft.time);
|
||||
const targetAt = getDailyTargetMs(time, now);
|
||||
if (time && targetAt) countdown = { id: context.uid("timer"), label, type, time, targetAt };
|
||||
}
|
||||
if (type === "time_pattern") {
|
||||
const pattern = timePartsToString(draft.pattern, { allowWildcard: true });
|
||||
if (pattern && getTimePatternTargetMs(pattern, now)) countdown = { id: context.uid("timer"), label, type, pattern };
|
||||
}
|
||||
if (type === "interval") {
|
||||
const intervalMs = timePartsToDurationMs(draft.interval);
|
||||
if (intervalMs > 0) countdown = { id: context.uid("timer"), label, type, intervalMs, anchorAt: now };
|
||||
}
|
||||
|
||||
if (!countdown) return;
|
||||
save({ ...data, countdowns: [...data.countdowns, countdown] });
|
||||
setCountdownForm((current) => ({ ...current, label: "" }));
|
||||
if (!countdown) return;
|
||||
save({ ...data, countdowns: [...data.countdowns, countdown] });
|
||||
updateValues({ label: "" });
|
||||
});
|
||||
}
|
||||
|
||||
function deleteCountdown(countdownId) {
|
||||
|
|
@ -274,8 +274,8 @@ export function TimerModule({ toolboxId, moduleId, context }) {
|
|||
) : (
|
||||
<CountdownControls
|
||||
textContent={textContent}
|
||||
form={countdownForm}
|
||||
onChange={updateCountdownForm}
|
||||
form={countdownDraft.values}
|
||||
onChange={countdownDraft.updateValues}
|
||||
onSubmit={createCountdown}
|
||||
/>
|
||||
)}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue