feat: enhance SaveStatusBadge component with pending changes display and save functionality

This commit is contained in:
Jaime Idolpx 2026-06-07 20:35:45 -04:00
parent 5ac6b6ce95
commit 284b91b963

View File

@ -35,7 +35,7 @@ type AppId =
export default function App() {
const [currentPage, setCurrentPage] = useState<Page>('status');
const { config, setConfig, saveStatus, reload } = useSettings();
const { config, setConfig, saveStatus, pendingCount, flushNow, reload } = useSettings();
const [showSearch, setShowSearch] = useState(false);
const [showProfileMenu, setShowProfileMenu] = useState(false);
@ -168,7 +168,7 @@ function AppPage({ title, onBack }: { title: string; onBack: () => void }) {
>
<AppWindow className="w-5 h-5 text-white" />
</button>
<SaveStatusBadge status={saveStatus} onReload={reload} />
<SaveStatusBadge status={saveStatus} pendingCount={pendingCount} onSave={flushNow} onReload={reload} />
<div className="relative">
<button
onClick={() => setShowProfileMenu(!showProfileMenu)}
@ -285,46 +285,61 @@ function AppPage({ title, onBack }: { title: string; onBack: () => void }) {
/**
* Tiny indicator that reflects the current save status of the settings
* file. Renders nothing when idle (so it doesn't clutter the header).
* Clicking the error badge re-attempts the load.
*/
function SaveStatusBadge({
status,
pendingCount,
onSave,
onReload,
}: {
status: 'idle' | 'loading' | 'saving' | 'saved' | 'error';
status: 'idle' | 'loading' | 'unsaved' | 'saving' | 'saved' | 'error';
pendingCount: number;
onSave: () => void;
onReload: () => void;
}) {
if (status === 'idle') return null;
if (status === 'loading') {
return (
<span
className="text-xs text-white/80 inline-flex items-center gap-1"
title="Loading settings from /.sys/config.json"
>
<span className="text-xs text-white/80 inline-flex items-center gap-1" title="Loading settings from /.sys/config.json">
<Loader2 className="w-3 h-3 animate-spin" /> Loading
</span>
);
}
if (status === 'unsaved') {
return (
<span className="inline-flex items-center gap-1">
<span className="text-xs text-amber-300" title={`${pendingCount} unsaved change${pendingCount === 1 ? '' : 's'}`}>
{pendingCount} unsaved
</span>
<button
onClick={onSave}
className="text-xs bg-amber-500 hover:bg-amber-400 text-white px-2 py-0.5 rounded"
title="Save now"
>
Save
</button>
</span>
);
}
if (status === 'saving') {
return (
<span
className="text-xs text-white/80 inline-flex items-center gap-1"
title="Saving to /.sys/config.json"
>
<span className="text-xs text-white/80 inline-flex items-center gap-1" title="Saving to /.sys/config.json">
<Loader2 className="w-3 h-3 animate-spin" /> Saving
</span>
);
}
if (status === 'saved') {
return (
<span
className="text-xs text-white/80 inline-flex items-center gap-1"
title="Saved to /.sys/config.json"
>
<span className="text-xs text-white/80 inline-flex items-center gap-1" title="Saved to /.sys/config.json">
<Check className="w-3 h-3" /> Saved
</span>
);
}
// error
return (
<button