feat(onboarding): dashboard empty state, getting-started checklist and re-show button (#352) #378

Merged
maximus merged 2 commits from issue-352-dashboard-empty-state into main 2026-10-04 12:51:19 +00:00
Showing only changes of commit 3f3531392e - Show all commits

View file

@ -12,24 +12,25 @@ import {
} from "../../services/onboardingService";
import { logError } from "../../services/logService";
// Re-show button of the getting-started checklist (#352). `hidden` = the
// preference was "1" at mount; `shown` = the button was clicked and the
// preference removed, so a confirmation line replaces the button.
type ChecklistButtonState = "unknown" | "visible" | "hidden" | "shown";
// Getting-started checklist preference, for its re-show button (#352).
// `dismissed` = the preference was "1" at mount, the button is offered;
// `restored` = the button was clicked and the preference removed, so a
// confirmation line replaces it; `shown` = nothing to offer.
type ChecklistPreference = "unknown" | "shown" | "dismissed" | "restored";
export default function UsersSettingsPage() {
const { t } = useTranslation();
const [checklistButton, setChecklistButton] = useState<ChecklistButtonState>("unknown");
const [checklistPref, setChecklistPref] = useState<ChecklistPreference>("unknown");
useEffect(() => {
let cancelled = false;
(async () => {
try {
const value = await getPreference(ONBOARDING_CHECKLIST_HIDDEN_KEY);
if (!cancelled) setChecklistButton(value === "1" ? "hidden" : "visible");
if (!cancelled) setChecklistPref(value === "1" ? "dismissed" : "shown");
} catch (e) {
// Informational control: without the preference, keep it out of the way.
if (!cancelled) setChecklistButton("visible");
if (!cancelled) setChecklistPref("shown");
logError("Settings: failed to read the checklist preference", e);
}
})();
@ -41,7 +42,7 @@ export default function UsersSettingsPage() {
const handleShowChecklist = async () => {
try {
await showChecklist();
setChecklistButton("shown");
setChecklistPref("restored");
} catch (e) {
logError("Settings: failed to show the checklist", e);
}
@ -77,11 +78,11 @@ export default function UsersSettingsPage() {
<h2 className="text-sm font-semibold uppercase tracking-wider text-[var(--muted-foreground)]">
{t("settings.users.sections.userGuide")}
</h2>
{(checklistButton === "hidden" || checklistButton === "shown") && (
{(checklistPref === "dismissed" || checklistPref === "restored") && (
<div className="flex flex-wrap items-center gap-3 rounded-xl border border-[var(--border)] bg-[var(--card)] p-4 text-sm">
<ListChecks size={18} className="shrink-0 text-[var(--muted-foreground)]" aria-hidden="true" />
<span className="flex-1 min-w-[12rem]">{t("settings.users.onboarding.label")}</span>
{checklistButton === "hidden" ? (
{checklistPref === "dismissed" ? (
<button
type="button"
onClick={handleShowChecklist}