import { useTranslation } from "react-i18next"; import { useImportWizard } from "../hooks/useImportWizard"; import ImportFolderConfig from "../components/import/ImportFolderConfig"; import SourceList from "../components/import/SourceList"; import SourceConfigPanel from "../components/import/SourceConfigPanel"; import FilePreviewTable from "../components/import/FilePreviewTable"; import FormatDriftPanel from "../components/import/FormatDriftPanel"; import DuplicateCheckPanel from "../components/import/DuplicateCheckPanel"; import ImportConfirmation from "../components/import/ImportConfirmation"; import ImportProgress from "../components/import/ImportProgress"; import ImportReportPanel from "../components/import/ImportReportPanel"; import WizardNavigation from "../components/import/WizardNavigation"; import ImportHistoryPanel from "../components/import/ImportHistoryPanel"; import { AlertCircle } from "lucide-react"; import { PageHelp } from "../components/shared/PageHelp"; export default function ImportPage() { const { t } = useTranslation(); const { state, browseFolder, refreshFolder, selectSource, updateConfig, toggleFile, selectAllFiles, parseAndPreview, checkDuplicates, flipSignConvention, executeImport, goToStep, reset, adoptDriftFormat, keepCurrentFormat, autoDetectConfig, saveConfigAsTemplate, applyConfigTemplate, updateConfigTemplate, deleteConfigTemplate, toggleDuplicateRow, setSkipAllDuplicates, } = useImportWizard(); const nextDisabled = state.selectedFiles.length === 0 || !state.sourceConfig.name; return (

{t("import.title")}

{/* Error banner */} {state.error && (
{/* The wizard reports a translation key when it has one (a stored format it cannot decode) and a raw message otherwise; `defaultValue` renders the latter unchanged. */}

{t(state.error, { defaultValue: state.error })}

)} {/* Folder config - always visible */} {/* Wizard steps */} {state.step === "source-list" && ( <> )} {state.step === "source-config" && state.selectedSource && (
{/* One way forward, and it goes through the preview (#329). The pair of buttons this replaces offered "Aperçu" as an optional detour and "Vérifier les doublons" as the real path, so the totals were the one screen an import never had to show. */} goToStep("source-list")} onNext={parseAndPreview} onCancel={reset} nextLabel={t("import.wizard.preview")} nextDisabled={nextDisabled || state.isLoading} />
)} {state.step === "file-preview" && (
{/* Format drift (#330) — ABOVE the table, because it tells the user whether the table below is worth reading. Present only when the header row moved since the last successful import of this source. */} {state.formatDrift && ( )} goToStep("source-config")} onNext={checkDuplicates} onCancel={reset} nextLabel={t("import.wizard.checkDuplicates")} nextDisabled={state.isLoading} />
)} {state.step === "duplicate-check" && state.duplicateResult && (
setSkipAllDuplicates(true)} onIncludeAll={() => setSkipAllDuplicates(false)} /> goToStep("file-preview")} onNext={() => goToStep("confirm")} onCancel={reset} nextLabel={t("import.wizard.confirm")} />
)} {state.step === "confirm" && state.duplicateResult && (
goToStep("duplicate-check")} onNext={executeImport} onCancel={reset} nextLabel={t("import.wizard.import")} showCancel={false} />
)} {state.step === "importing" && ( )} {state.step === "report" && state.importReport && ( )}
); }