refactor: enhance TimerPage layout and functionality; update theme and tokens for improved design consistency

- Refactored TimerPage component to improve layout and user experience.
- Updated theme configuration to utilize design tokens for better maintainability.
- Introduced new tokens for colors and typography to align with design principles.
- Simplified state management and improved timer functionality.
- Enhanced accessibility and responsiveness of UI elements.
This commit is contained in:
timka123 committed 2026-10-18 23:57:36 +03:00
1 parent 17a0a3c4c9
commit 77b26757bf
84 files changed
+4501 -2682

No files matched your search

+24 -45
View File
@@ -6,9 +6,6 @@
*/
import { useEffect, useState } from "react";
import {
Accordion,
AccordionDetails,
AccordionSummary,
Alert,
Box,
Button,
@@ -22,8 +19,8 @@ import {
TextField,
Typography,
} from "@mui/material";
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
import { PageHeader, Panel, SectionTitle } from "../components/Layout";
import { api, getToken, setToken } from "../lib/api";
import { useSettings } from "../lib/settings";
import type { AppSettings } from "../lib/types";
@@ -59,7 +56,13 @@ export default function SettingsPage({ onToast }: { onToast: (message: string) =
};
return (
<Stack spacing={2}>
<>
<PageHeader
eyebrow="Shared with the desktop app and the Telegram bot"
title="Settings"
caption="Secrets are masked once stored — leave the dots alone to keep the saved value."
/>
<Stack spacing={5}>
<Section title="Timer" subtitle="Shared with the desktop app and the Telegram bot.">
<Grid container spacing={2}>
{(
@@ -85,6 +88,7 @@ export default function SettingsPage({ onToast }: { onToast: (message: string) =
<Stack direction="row" sx={{ flexWrap: "wrap", mt: 1 }}>
{(
[
["timer_enabled", "Timer enabled (off = view only)"],
["auto_start_breaks", "Auto-start breaks"],
["auto_start_work", "Auto-start next focus"],
["allow_pause", "Allow pausing"],
@@ -159,17 +163,6 @@ export default function SettingsPage({ onToast }: { onToast: (message: string) =
value={settings.sources.jira.start_date_field}
onCommit={(value) => void patch({ sources: { jira: { start_date_field: value } } })}
/>
<FormControlLabel
control={
<Switch
checked={settings.sources.jira.writeback_done}
onChange={(event) =>
void patch({ sources: { jira: { writeback_done: event.target.checked } } })
}
/>
}
label="Completing a task here transitions the Jira issue to Done"
/>
</SourceBlock>
<SourceBlock
@@ -443,13 +436,6 @@ export default function SettingsPage({ onToast }: { onToast: (message: string) =
<MenuItem value="light">Light</MenuItem>
<MenuItem value="dark">Dark</MenuItem>
</TextField>
<TextField
label="Accent colour"
type="color"
sx={{ width: 120 }}
value={settings.appearance.accent}
onChange={(event) => void patch({ appearance: { accent: event.target.value } })}
/>
<TextField
label="API token (this browser)"
type="password"
@@ -462,12 +448,13 @@ export default function SettingsPage({ onToast }: { onToast: (message: string) =
}}
/>
</Stack>
<Alert severity="info" sx={{ mt: 2 }}>
<Alert severity="info" variant="outlined" sx={{ mt: 2 }}>
Website and application blocking is enforced by the native desktop app — install it from{" "}
<code>desktop/</code>, then its lists live on the <strong>Blocker</strong> page.
<code>desktop/</code>; its lists live on the <strong>Blocker</strong> page.
</Alert>
</Section>
</Stack>
</Stack>
</>
);
}
@@ -481,23 +468,15 @@ function Section({
children: React.ReactNode;
}) {
return (
<Accordion defaultExpanded disableGutters sx={{ borderRadius: 3, "&::before": { display: "none" } }}>
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
<Box>
<Typography variant="subtitle1" sx={{ fontWeight: 600 }}>
{title}
</Typography>
{subtitle && (
<Typography variant="body2" color="text.secondary">
{subtitle}
</Typography>
)}
</Box>
</AccordionSummary>
<AccordionDetails>
<Stack spacing={1.5}>{children}</Stack>
</AccordionDetails>
</Accordion>
<Box>
<SectionTitle>{title}</SectionTitle>
{subtitle && (
<Typography variant="body2" color="text.secondary" sx={{ mb: 2 }}>
{subtitle}
</Typography>
)}
<Stack spacing={2}>{children}</Stack>
</Box>
);
}
@@ -518,7 +497,7 @@ function SourceBlock({
children: React.ReactNode;
}) {
return (
<Box sx={{ border: 1, borderColor: "divider", borderRadius: 3, p: 2 }}>
<Panel>
<Stack direction="row" alignItems="center" spacing={1} sx={{ mb: enabled ? 1.5 : 0 }}>
<Typography sx={{ fontWeight: 600, flexGrow: 1 }}>{label}</Typography>
{enabled && <Chip size="small" color="success" variant="outlined" label="on" />}
@@ -532,7 +511,7 @@ function SourceBlock({
{children}
</Stack>
)}
</Box>
</Panel>
);
}