import { useEffect, useState } from "react"; import { Link } from "react-router-dom"; import { useTranslation } from "react-i18next"; import { FolderTree, ChevronRight, MoveRight, RotateCcw } from "lucide-react"; import { getPreference } from "../../services/userPreferenceService"; import { readLastMigrationJournal, type RestorableMigrationJournal, } from "../../services/categoryRestoreService"; import CategoriesMigrationBackupBanner from "./CategoriesMigrationBackupBanner"; import CategoriesMigrationRestoreModal from "./CategoriesMigrationRestoreModal"; /** * Card that surfaces category-related entries in the Settings page. * * Entries, decided by the profile's categories_schema_version and whether a * migration was previously recorded: * - "Standard categories guide" (always visible) — read-only tree (#117). * - "Migrate to the standard structure" (v2 only) — 3-step migration (#121). * - "Restore a backup" (when a migration journal exists, regardless of age) * — opens the same modal as the 90-day banner (#122). * * Profiles already on v1 never see the migrate entry (they're done) but they * keep the Restore entry as long as a journal is present, so they can always * roll back even after the banner has expired. */ export default function CategoriesCard() { const { t } = useTranslation(); const [showMigrate, setShowMigrate] = useState(false); const [journal, setJournal] = useState( null, ); const [isRestoreModalOpen, setIsRestoreModalOpen] = useState(false); useEffect(() => { let cancelled = false; (async () => { try { const [version, loadedJournal] = await Promise.all([ getPreference("categories_schema_version"), readLastMigrationJournal(), ]); if (cancelled) return; setShowMigrate(version === "v2"); setJournal(loadedJournal); } catch { if (!cancelled) { setShowMigrate(false); setJournal(null); } } })(); return () => { cancelled = true; }; }, []); // The permanent Restore entry is shown whenever a journal exists, even past // the 90-day banner window AND even after the user already reverted (a user // who wants to re-import the backup a second time is free to do so — the // SREF file is still valid as long as it is on disk). const showRestoreEntry = journal !== null; return (
{/* Post-migration 90-day banner — renders only within window and when un-dismissed and not-yet-reverted. */}

{t("settings.categoriesCard.standardGuideTitle")}

{t("settings.categoriesCard.standardGuideDescription")}

{showMigrate && (

{t("settings.categoriesCard.migrateTitle")}

{t("settings.categoriesCard.migrateDescription")}

)} {showRestoreEntry && journal && ( )} {isRestoreModalOpen && journal && ( setIsRestoreModalOpen(false)} /> )}
); }