feat: reports, timeline toggles, and stock correction improvements (#236)
* refactor(frontend): modularize styles and polish modal/ui interactions * feat: add report workflow and timeline/settings improvements * fix: resolve CI failures for backend typing, lint, and playwright config
This commit is contained in:
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -192,8 +192,12 @@ export function SchedulePage() {
|
||||
<div key={dose.id} className="dose-item past">
|
||||
<span className="dose-time">{dose.timeStr}</span>
|
||||
<span className="dose-usage">
|
||||
{dose.usage} {dose.usage !== 1 ? t("common.pills") : t("common.pill")}
|
||||
{med?.pillWeightMg && ` (${dose.usage * med.pillWeightMg} ${med.doseUnit ?? "mg"})`}
|
||||
<span className="dose-usage-main">
|
||||
{dose.usage} {dose.usage !== 1 ? t("common.pills") : t("common.pill")}
|
||||
</span>
|
||||
{med?.pillWeightMg && (
|
||||
<span className="dose-usage-weight">{`${dose.usage * med.pillWeightMg} ${med.doseUnit ?? "mg"}`}</span>
|
||||
)}
|
||||
</span>{" "}
|
||||
{dose.intakeRemindersEnabled && (
|
||||
<span
|
||||
@@ -235,7 +239,8 @@ export function SchedulePage() {
|
||||
disabled={isEmpty}
|
||||
title={t("dose.markAsTaken")}
|
||||
>
|
||||
✓
|
||||
<span className="dose-btn-label">{t("dose.take")}</span>
|
||||
<span aria-hidden="true">✓</span>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
@@ -348,8 +353,12 @@ export function SchedulePage() {
|
||||
<div key={dose.id} className="dose-item">
|
||||
<span className="dose-time">{dose.timeStr}</span>
|
||||
<span className="dose-usage">
|
||||
{dose.usage} {dose.usage !== 1 ? t("common.pills") : t("common.pill")}
|
||||
{med?.pillWeightMg && ` (${dose.usage * med.pillWeightMg} ${med.doseUnit ?? "mg"})`}
|
||||
<span className="dose-usage-main">
|
||||
{dose.usage} {dose.usage !== 1 ? t("common.pills") : t("common.pill")}
|
||||
</span>
|
||||
{med?.pillWeightMg && (
|
||||
<span className="dose-usage-weight">{`${dose.usage * med.pillWeightMg} ${med.doseUnit ?? "mg"}`}</span>
|
||||
)}
|
||||
</span>
|
||||
{dose.intakeRemindersEnabled && (
|
||||
<span
|
||||
@@ -395,7 +404,8 @@ export function SchedulePage() {
|
||||
disabled={isEmpty}
|
||||
title={t("dose.markAsTaken")}
|
||||
>
|
||||
✓
|
||||
<span className="dose-btn-label">{t("dose.take")}</span>
|
||||
<span aria-hidden="true">✓</span>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -34,7 +34,6 @@ export function SettingsPage() {
|
||||
} = useAppContext();
|
||||
|
||||
const hasExistingData = meds.length > 0;
|
||||
|
||||
return (
|
||||
<section className="grid">
|
||||
{settingsLoading ? (
|
||||
@@ -674,8 +673,62 @@ export function SettingsPage() {
|
||||
<p className="threshold-validation-error">{t("settings.stock.thresholdValidation")}</p>
|
||||
)}
|
||||
</div>
|
||||
</article>
|
||||
|
||||
{/* General UI */}
|
||||
<article className="card">
|
||||
<div className="card-head">
|
||||
<h2>{t("settings.timeline.title")}</h2>
|
||||
</div>
|
||||
|
||||
<div className="setting-section">
|
||||
<div className="section-header">
|
||||
<h3>{t("settings.timeline.dashboardSectionOrder")}</h3>
|
||||
</div>
|
||||
<div className="setting-row compact">
|
||||
<div className="setting-label">
|
||||
<span>{t("settings.timeline.swapDashboardSections")}</span>
|
||||
<span className="info-tooltip small" data-tooltip={t("settings.timeline.swapDashboardSectionsDesc")}>
|
||||
ⓘ
|
||||
</span>
|
||||
</div>
|
||||
<label className="toggle-switch small">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={settings.swapDashboardMainSections}
|
||||
onChange={(e) => setSettings({ ...settings, swapDashboardMainSections: e.target.checked })}
|
||||
/>
|
||||
<span className="toggle-slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="setting-section">
|
||||
<div className="section-header">
|
||||
<h3>{t("settings.timeline.upcomingSection")}</h3>
|
||||
</div>
|
||||
<div className="setting-row compact">
|
||||
<div className="setting-label">
|
||||
<span>{t("settings.timeline.upcomingTodayOnly")}</span>
|
||||
<span className="info-tooltip small" data-tooltip={t("settings.timeline.upcomingTodayOnlyDesc")}>
|
||||
ⓘ
|
||||
</span>
|
||||
</div>
|
||||
<label className="toggle-switch small">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={settings.upcomingTodayOnly}
|
||||
onChange={(e) => setSettings({ ...settings, upcomingTodayOnly: e.target.checked })}
|
||||
/>
|
||||
<span className="toggle-slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="setting-section">
|
||||
<div className="section-header">
|
||||
<h3>{t("settings.timeline.sharedSection")}</h3>
|
||||
</div>
|
||||
<div className="setting-row compact">
|
||||
<div className="setting-label">
|
||||
<span>{t("settings.stock.shareStockStatus")}</span>
|
||||
@@ -692,6 +745,22 @@ export function SettingsPage() {
|
||||
<span className="toggle-slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
<div className="setting-row compact" style={{ marginTop: "10px" }}>
|
||||
<div className="setting-label">
|
||||
<span>{t("settings.timeline.shareScheduleTodayOnly")}</span>
|
||||
<span className="info-tooltip small" data-tooltip={t("settings.timeline.shareScheduleTodayOnlyDesc")}>
|
||||
ⓘ
|
||||
</span>
|
||||
</div>
|
||||
<label className="toggle-switch small">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={settings.shareScheduleTodayOnly}
|
||||
onChange={(e) => setSettings({ ...settings, shareScheduleTodayOnly: e.target.checked })}
|
||||
/>
|
||||
<span className="toggle-slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
@@ -737,6 +806,7 @@ export function SettingsPage() {
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setImportResult(null)}
|
||||
aria-label={t("common.close")}
|
||||
style={{
|
||||
background: "none",
|
||||
border: "none",
|
||||
@@ -747,7 +817,6 @@ export function SettingsPage() {
|
||||
color: "inherit",
|
||||
opacity: 0.7,
|
||||
}}
|
||||
aria-label="Close"
|
||||
>
|
||||
×
|
||||
</button>
|
||||
|
||||
Reference in New Issue
Block a user