import { browser } from '$app/environment'; import type { CsvImportProfile, CsvImportTab } from '$lib/csv-import-session'; const VALID_PROFILES: CsvImportProfile[] = [ 'customs_brokers', 'clients_providers', 'exchange_rates', 'american_fractions', 'pedimentos', 'material_classes', 'vehicles', 'drivers', 'trailers', 'transporters', 'part_numbers', 'boms', 'exportacion', 'imports' ]; const VALID_TABS: CsvImportTab[] = ['catalogos', 'transportes', 'importacion', 'exportacion']; export const CSV_IMPORT_PENDING_KEY = 'anexo76_csv_pending_v1'; export const CSV_IMPORT_PENDING_CHANGED = 'csvImportPendingChanged'; const MAX_ITEMS = 20; export interface CsvImportPendingEntry { companyId: number; jobId: string; profile: CsvImportProfile; activeModelTarget: string | null; activeTab: CsvImportTab; label?: string | null; savedAt: string; totalRows?: number; validRows?: number; } interface PendingStoreV1 { v: 1; items: CsvImportPendingEntry[]; } function notifyPendingChanged() { if (browser) { window.dispatchEvent(new CustomEvent(CSV_IMPORT_PENDING_CHANGED)); } } function parseStore(raw: string | null): PendingStoreV1 { if (!raw) return { v: 1, items: [] }; try { const data = JSON.parse(raw) as Partial; if (data.v !== 1 || !Array.isArray(data.items)) return { v: 1, items: [] }; return { v: 1, items: data.items.filter(isValidEntry) }; } catch { return { v: 1, items: [] }; } } function isValidEntry(x: unknown): x is CsvImportPendingEntry { if (!x || typeof x !== 'object') return false; const o = x as Record; return ( typeof o.companyId === 'number' && typeof o.jobId === 'string' && typeof o.profile === 'string' && VALID_PROFILES.includes(o.profile as CsvImportProfile) && typeof o.savedAt === 'string' && (o.activeModelTarget === null || typeof o.activeModelTarget === 'string') && typeof o.activeTab === 'string' && VALID_TABS.includes(o.activeTab as CsvImportTab) ); } function writeStore(store: PendingStoreV1, notify = true) { if (!browser) return; try { localStorage.setItem(CSV_IMPORT_PENDING_KEY, JSON.stringify(store)); if (notify) notifyPendingChanged(); } catch { // } } export function readCsvImportPendingStore(): PendingStoreV1 { if (!browser) return { v: 1, items: [] }; return parseStore(localStorage.getItem(CSV_IMPORT_PENDING_KEY)); } export function listCsvImportPendingForCompany(companyId: number | undefined): CsvImportPendingEntry[] { if (companyId === undefined) return []; const { items } = readCsvImportPendingStore(); return items .filter((i) => i.companyId === companyId) .sort((a, b) => (a.savedAt < b.savedAt ? 1 : -1)); } export function countCsvImportPendingForCompany(companyId: number | undefined): number { return listCsvImportPendingForCompany(companyId).length; } /** Inserta o actualiza por jobId; mantiene como máximo MAX_ITEMS (más recientes primero). */ export function upsertCsvImportPending(partial: Omit & { savedAt?: string }): void { if (!browser) return; const store = readCsvImportPendingStore(); const now = partial.savedAt ?? new Date().toISOString(); const next: CsvImportPendingEntry = { companyId: partial.companyId, jobId: partial.jobId, profile: partial.profile, activeModelTarget: partial.activeModelTarget, activeTab: partial.activeTab, savedAt: now, ...(partial.label !== undefined && partial.label !== null && String(partial.label).trim() ? { label: String(partial.label).trim() } : {}), ...(typeof partial.totalRows === 'number' ? { totalRows: partial.totalRows } : {}), ...(typeof partial.validRows === 'number' ? { validRows: partial.validRows } : {}) }; const without = store.items.filter((i) => i.jobId !== next.jobId); const merged = [next, ...without].sort((a, b) => (a.savedAt < b.savedAt ? 1 : -1)).slice(0, MAX_ITEMS); writeStore({ v: 1, items: merged }); } export function removeCsvImportPending(jobId: string): void { if (!browser) return; const store = readCsvImportPendingStore(); const filtered = store.items.filter((i) => i.jobId !== jobId); if (filtered.length === store.items.length) return; writeStore({ v: 1, items: filtered }); } export function updateCsvImportPendingSnapshot( jobId: string, patch: Pick ): void { if (!browser) return; const store = readCsvImportPendingStore(); const idx = store.items.findIndex((i) => i.jobId === jobId); if (idx < 0) return; const cur = store.items[idx]; store.items[idx] = { ...cur, ...(typeof patch.totalRows === 'number' ? { totalRows: patch.totalRows } : {}), ...(typeof patch.validRows === 'number' ? { validRows: patch.validRows } : {}) }; writeStore({ v: 1, items: [...store.items] }, false); }