- "frontend/src/pages/ReviewQueue.tsx" - "frontend/src/pages/MomentDetail.tsx" - "frontend/src/components/StatusBadge.tsx" - "frontend/src/components/ModeToggle.tsx" - "frontend/src/App.tsx" - "frontend/src/App.css" GSD-Task: S04/T03
59 lines
1.6 KiB
TypeScript
59 lines
1.6 KiB
TypeScript
/**
|
|
* Review / Auto mode toggle switch.
|
|
*
|
|
* Reads and writes mode via getReviewMode / setReviewMode API.
|
|
* Green dot = review mode active; amber = auto mode.
|
|
*/
|
|
|
|
import { useEffect, useState } from "react";
|
|
import { getReviewMode, setReviewMode } from "../api/client";
|
|
|
|
export default function ModeToggle() {
|
|
const [reviewMode, setReviewModeState] = useState<boolean | null>(null);
|
|
const [toggling, setToggling] = useState(false);
|
|
|
|
useEffect(() => {
|
|
let cancelled = false;
|
|
getReviewMode()
|
|
.then((res) => {
|
|
if (!cancelled) setReviewModeState(res.review_mode);
|
|
})
|
|
.catch(() => {
|
|
// silently fail — mode indicator will just stay hidden
|
|
});
|
|
return () => { cancelled = true; };
|
|
}, []);
|
|
|
|
async function handleToggle() {
|
|
if (reviewMode === null || toggling) return;
|
|
setToggling(true);
|
|
try {
|
|
const res = await setReviewMode(!reviewMode);
|
|
setReviewModeState(res.review_mode);
|
|
} catch {
|
|
// swallow — leave previous state
|
|
} finally {
|
|
setToggling(false);
|
|
}
|
|
}
|
|
|
|
if (reviewMode === null) return null;
|
|
|
|
return (
|
|
<div className="mode-toggle">
|
|
<span
|
|
className={`mode-toggle__dot ${reviewMode ? "mode-toggle__dot--review" : "mode-toggle__dot--auto"}`}
|
|
/>
|
|
<span className="mode-toggle__label">
|
|
{reviewMode ? "Review Mode" : "Auto Mode"}
|
|
</span>
|
|
<button
|
|
type="button"
|
|
className={`mode-toggle__switch ${reviewMode ? "mode-toggle__switch--active" : ""}`}
|
|
onClick={handleToggle}
|
|
disabled={toggling}
|
|
aria-label={`Switch to ${reviewMode ? "auto" : "review"} mode`}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|