fix: unify day boundaries on device-local time, JSON import preview parity

- Limits/streaks/greeting now use device-local days (was hardcoded Europe/London),
  matching dashboard metrics; label copy updated
- JSON imports now go through the same preview/duplicate-detection modal as Excel
This commit is contained in:
nh9961
2026-07-19 21:12:02 +00:00
parent 9e8f3c55d6
commit 767967f25d
7 changed files with 52 additions and 49 deletions
+10 -17
View File
@@ -21,7 +21,6 @@ import {
createEntries,
createEntry,
deleteEntry as deleteEntryDocument,
isDuplicateDraft,
listEntries,
updateEntry,
} from "./lib/appwriteEntries";
@@ -52,7 +51,7 @@ import {
} from "./lib/userLimits";
import { createExcelExport, downloadBlob, parseExcelImport } from "./lib/excel";
import { buildEntryDerived, groupByDay, groupByFlavour, groupByWeek, humanDateTime, makeId } from "./lib/metrics";
import { exportPayload, parseImport } from "./lib/storage";
import { buildJsonImportPreview, exportPayload, parseImport } from "./lib/storage";
import { useToasts } from "./lib/toasts";
import type {
AppView,
@@ -547,18 +546,18 @@ function App() {
}
}
async function confirmExcelImport() {
async function confirmImportPreview() {
if (!user || !importPreview) return;
const drafts = importPreview.rows
.filter((row) => row.entry && !row.errors.length && !row.duplicate)
.map((row) => row.entry as EntryDraft);
if (!drafts.length) {
setNotice("No valid new Excel rows to import.");
setNotice("No valid new rows to import.");
return;
}
setBusyAction("confirm-excel-import");
setBusyAction("confirm-import");
setSyncError("");
importInFlightRef.current = true;
setImportProgress({ done: 0, total: drafts.length });
@@ -566,7 +565,7 @@ function App() {
const saved = await createEntries(user.$id, drafts, (done, total) => setImportProgress({ done, total }));
setEntries((current) => sortEntries([...saved, ...current]));
setImportPreview(null);
setNotice(`${saved.length} Excel row${saved.length === 1 ? "" : "s"} saved to Appwrite.`);
setNotice(`${saved.length} row${saved.length === 1 ? "" : "s"} saved to Appwrite.`);
} catch (error) {
setSyncError(appwriteErrorMessage(error));
} finally {
@@ -588,18 +587,12 @@ function App() {
setSyncError("");
try {
const drafts = parseImport(await file.text());
const uniqueDrafts = drafts.filter((draft) => !isDuplicateDraft(entries, draft));
if (!uniqueDrafts.length) {
setNotice("No new JSON entries found.");
return;
}
importInFlightRef.current = true;
const saved = await createEntries(user.$id, uniqueDrafts.map((draft) => ({ ...draft, source: "json" })));
setEntries((current) => sortEntries([...saved, ...current])); setNotice(`${saved.length} JSON entr${saved.length === 1 ? "y" : "ies"} saved to Appwrite.`);
const preview = buildJsonImportPreview(drafts, entries, file.name);
setImportPreview(preview);
setNotice(`${preview.rows.length} JSON row${preview.rows.length === 1 ? "" : "s"} parsed for review.`);
} catch (error) {
setSyncError(error instanceof Error ? error.message : "JSON import failed.");
} finally {
importInFlightRef.current = false;
if (jsonFileInputRef.current) jsonFileInputRef.current.value = "";
setBusyAction(null);
}
@@ -810,11 +803,11 @@ function App() {
/>
<ImportPreviewModal
busy={busyAction === "confirm-excel-import"}
busy={busyAction === "confirm-import"}
preview={importPreview}
importProgress={importProgress}
onClose={() => setImportPreview(null)}
onConfirm={() => void confirmExcelImport()}
onConfirm={() => void confirmImportPreview()}
/>
<ConfirmDialog