diff --git a/src/components/import/DuplicateCheckPanel.tsx b/src/components/import/DuplicateCheckPanel.tsx index 40114c3..cbd63ee 100644 --- a/src/components/import/DuplicateCheckPanel.tsx +++ b/src/components/import/DuplicateCheckPanel.tsx @@ -25,13 +25,13 @@ export default function DuplicateCheckPanel({ {/* File-level duplicate */} {result.fileAlreadyImported && ( -
- +
+
-

+

{t("import.duplicates.fileAlreadyImported")}

-

+

{t("import.duplicates.fileAlreadyImportedDesc")}

@@ -41,18 +41,18 @@ export default function DuplicateCheckPanel({ {/* Row-level duplicates */} {result.duplicateRows.length > 0 ? (
-
+
-

+

{t("import.duplicates.rowsFound", { count: result.duplicateRows.length, })}

-

+

{t("import.duplicates.rowsFoundDesc")}

@@ -105,7 +105,7 @@ export default function DuplicateCheckPanel({ {result.duplicateRows.map((row) => ( {row.rowIndex + 1} @@ -125,9 +125,9 @@ export default function DuplicateCheckPanel({
) : ( !result.fileAlreadyImported && ( -
- -

+

+ +

{t("import.duplicates.noneFound")}

diff --git a/src/components/import/FilePreviewTable.tsx b/src/components/import/FilePreviewTable.tsx index d22c1cd..05a83c7 100644 --- a/src/components/import/FilePreviewTable.tsx +++ b/src/components/import/FilePreviewTable.tsx @@ -32,7 +32,7 @@ export default function FilePreviewTable({ {t("import.preview.rowCount", { count: rows.length })} {errorCount > 0 && ( - + {t("import.preview.errorCount", { count: errorCount })} @@ -67,7 +67,7 @@ export default function FilePreviewTable({ key={row.rowIndex} className={ row.error - ? "bg-red-50 dark:bg-red-950/20" + ? "bg-[color-mix(in_srgb,var(--negative)_10%,var(--card))]" : "hover:bg-[var(--muted)]" } > @@ -76,7 +76,7 @@ export default function FilePreviewTable({ {row.parsed?.date || ( - + {row.error || "—"} )} diff --git a/src/components/import/ImportReportPanel.tsx b/src/components/import/ImportReportPanel.tsx index e17096c..e20d505 100644 --- a/src/components/import/ImportReportPanel.tsx +++ b/src/components/import/ImportReportPanel.tsx @@ -30,19 +30,19 @@ export default function ImportReportPanel({ icon: CheckCircle, label: t("import.report.imported"), value: report.importedCount, - color: "text-emerald-500", + color: "text-[var(--positive)]", }, { icon: AlertTriangle, label: t("import.report.skippedDuplicates"), value: report.skippedDuplicates, - color: "text-amber-500", + color: "text-[var(--accent)]", }, { icon: XCircle, label: t("import.report.errors"), value: report.errorCount, - color: "text-red-500", + color: "text-[var(--negative)]", }, { icon: Tag, @@ -85,7 +85,7 @@ export default function ImportReportPanel({ {/* Errors list */} {report.errors.length > 0 && (
-

+

{t("import.report.errorDetails")}

@@ -104,7 +104,7 @@ export default function ImportReportPanel({ {report.errors.map((err, i) => ( {err.rowIndex + 1} - {err.message} + {err.message} ))} diff --git a/src/pages/ImportPage.tsx b/src/pages/ImportPage.tsx index 4c6f5ad..dd94c2b 100644 --- a/src/pages/ImportPage.tsx +++ b/src/pages/ImportPage.tsx @@ -35,9 +35,9 @@ export default function ImportPage() { {/* Error banner */} {state.error && ( -
- -

+

+ +

{state.error}

diff --git a/src/services/importedFileService.ts b/src/services/importedFileService.ts index 2a5b94d..9eefd49 100644 --- a/src/services/importedFileService.ts +++ b/src/services/importedFileService.ts @@ -32,6 +32,19 @@ export async function createImportedFile(file: { notes?: string; }): Promise { const db = await getDb(); + // Check if file already exists (e.g. from a previous failed import) + const existing = await db.select( + "SELECT id FROM imported_files WHERE source_id = $1 AND file_hash = $2", + [file.source_id, file.file_hash] + ); + if (existing.length > 0) { + await db.execute( + `UPDATE imported_files SET filename = $1, row_count = $2, status = $3, notes = $4, import_date = CURRENT_TIMESTAMP WHERE id = $5`, + [file.filename, file.row_count, file.status, file.notes || null, existing[0].id] + ); + return existing[0].id; + } + const result = await db.execute( `INSERT INTO imported_files (source_id, filename, file_hash, row_count, status, notes) VALUES ($1, $2, $3, $4, $5, $6)`,