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:
84 files changed
+4501
-2682
No files matched your search
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user