"use client"; import { useMemo, useRef } from "react"; import { useTranslations } from "next-intl"; import { useSettingsStore } from "@/stores/settings-store"; import { SettingsSection, SettingItem, Select, ToggleSwitch } from "./settings-section"; import { RotateCcw } from "lucide-react"; import { cn } from "@/lib/utils"; import { DEFAULT_ATTACHMENT_TEMPLATE, DEFAULT_BUNDLE_TEMPLATE, DEFAULT_EMAIL_TEMPLATE, EMAIL_TOKENS, ATTACHMENT_TOKENS, BUNDLE_TOKENS, bundleExportFilename, emailExportFilename, attachmentDownloadFilename, buildSampleEmail, type EmailFilenameOptions, } from "@/lib/download-filename"; function insertTokenAtCursor( input: HTMLInputElement, token: string, current: string, onChange: (next: string) => void, ): void { const start = input.selectionStart ?? current.length; const end = input.selectionEnd ?? current.length; const before = current.slice(0, start); const after = current.slice(end); const insertion = `{${token}}`; const next = `${before}${insertion}${after}`; onChange(next); // Restore focus and place caret after the inserted token. requestAnimationFrame(() => { input.focus(); const caret = before.length + insertion.length; input.setSelectionRange(caret, caret); }); } interface TemplateEditorProps { label: string; description: string; value: string; defaultValue: string; tokens: { token: string; description: string }[]; preview: string; onChange: (next: string) => void; resetLabel: string; previewLabel: string; placeholder?: string; } function TemplateEditor({ label, description, value, defaultValue, tokens, preview, onChange, resetLabel, previewLabel, placeholder, }: TemplateEditorProps) { const inputRef = useRef(null); return (

{description}

onChange(e.target.value)} spellCheck={false} className="flex-1 px-3 py-1.5 text-sm rounded-md bg-muted border border-border text-foreground font-mono focus:outline-none focus:ring-2 focus:ring-ring transition-colors duration-150" />
{tokens.map((t) => ( ))}
{previewLabel} {preview}
); } export function DownloadsSettings() { const t = useTranslations("settings.downloads"); const { emailDownloadTemplate, attachmentDownloadTemplate, bundleDownloadTemplate, filenameSpaceReplacement, filenameLowercase, filenameStripDiacritics, filenameCollapseSeparators, postExportAction, updateSetting, } = useSettingsStore(); const sampleEmail = useMemo(() => buildSampleEmail(), []); const sampleAttachment = useMemo(() => ({ name: "Invoice-2026-05.pdf", type: "application/pdf" }), []); const transform = useMemo( () => ({ spaceReplacement: filenameSpaceReplacement, lowercase: filenameLowercase, stripDiacritics: filenameStripDiacritics, collapseSeparators: filenameCollapseSeparators, }), [filenameSpaceReplacement, filenameLowercase, filenameStripDiacritics, filenameCollapseSeparators], ); const emailOptions: EmailFilenameOptions = useMemo( () => ({ ...transform, template: emailDownloadTemplate || DEFAULT_EMAIL_TEMPLATE }), [transform, emailDownloadTemplate], ); const attachmentOptions: EmailFilenameOptions = useMemo( () => ({ ...transform, template: attachmentDownloadTemplate || DEFAULT_ATTACHMENT_TEMPLATE }), [transform, attachmentDownloadTemplate], ); const bundleOptions: EmailFilenameOptions = useMemo( () => ({ ...transform, template: bundleDownloadTemplate || DEFAULT_BUNDLE_TEMPLATE }), [transform, bundleDownloadTemplate], ); const emlPreview = useMemo( () => emailExportFilename(sampleEmail, emailOptions), [sampleEmail, emailOptions], ); const attachmentPreview = useMemo( () => attachmentDownloadFilename(sampleEmail, sampleAttachment, attachmentOptions), [sampleEmail, sampleAttachment, attachmentOptions], ); const bundlePreview = useMemo( // Render with the email's fixed sample date so the preview is stable as the // user types in the template field. () => bundleExportFilename(3, bundleOptions, sampleEmail.receivedAt ?? undefined), [bundleOptions, sampleEmail], ); return ( updateSetting("emailDownloadTemplate", next)} resetLabel={t("reset")} previewLabel={t("preview")} placeholder={DEFAULT_EMAIL_TEMPLATE} /> updateSetting("attachmentDownloadTemplate", next)} resetLabel={t("reset")} previewLabel={t("preview")} placeholder={DEFAULT_ATTACHMENT_TEMPLATE} /> updateSetting("bundleDownloadTemplate", next)} resetLabel={t("reset")} previewLabel={t("preview")} placeholder={DEFAULT_BUNDLE_TEMPLATE} /> updateSetting("postExportAction", value as "keep" | "archive" | "trash")} options={[ { value: "keep", label: t("after_export.keep") }, { value: "archive", label: t("after_export.archive") }, { value: "trash", label: t("after_export.trash") }, ]} /> ); }