From 3aee23f6dc922cc3c17016d8fa4ef0b6077ba3c9 Mon Sep 17 00:00:00 2001 From: Caio Pizzol Date: Thu, 9 Oct 2025 17:21:00 -0300 Subject: [PATCH] feat: add import functionality for .docx files in the template builder This commit introduces a new import feature that allows users to upload .docx files. It includes UI updates for the import button and error handling for invalid file types. The toolbar now displays an error message if the import fails, enhancing user experience. --- demo/src/App.css | 38 ++++++++++++++++++++++++++++ demo/src/App.tsx | 65 +++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 100 insertions(+), 3 deletions(-) diff --git a/demo/src/App.css b/demo/src/App.css index d19213f..8d344b0 100644 --- a/demo/src/App.css +++ b/demo/src/App.css @@ -83,6 +83,12 @@ header { box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); } +.toolbar-right { + display: flex; + align-items: center; + gap: 0.75rem; +} + .toolbar-left { display: flex; align-items: center; @@ -113,6 +119,38 @@ header { background: #0051d5; } +.export-button:disabled, +.import-button:disabled { + cursor: not-allowed; + opacity: 0.7; +} + +.import-button { + padding: 0.5rem 1.25rem; + background: white; + color: #007aff; + border: 1px solid #b0d4ff; + border-radius: 8px; + font-weight: 600; + cursor: pointer; + transition: background 0.2s, color 0.2s, border-color 0.2s; +} + +.import-button:hover { + background: #e8f2ff; + border-color: #007aff; +} + +.toolbar-error { + margin-top: 0.75rem; + padding: 0.75rem 1rem; + background: #fef2f2; + color: #b91c1c; + border: 1px solid #fecaca; + border-radius: 8px; + font-size: 0.875rem; +} + /* Template Builder Container */ .superdoc-template-builder { background: white; diff --git a/demo/src/App.tsx b/demo/src/App.tsx index 478dcc7..6c1a179 100644 --- a/demo/src/App.tsx +++ b/demo/src/App.tsx @@ -46,7 +46,14 @@ export function App() { const [fields, setFields] = useState([]); const [events, setEvents] = useState([]); const [isDownloading, setIsDownloading] = useState(false); + const [isImporting, setIsImporting] = useState(false); + const [importError, setImportError] = useState(null); + const [documentSource, setDocumentSource] = useState( + "https://storage.googleapis.com/public_static_hosting/public_demo_docs/service_agreement.docx", + ); const builderRef = useRef(null); + const fileInputRef = useRef(null); + const importingRef = useRef(false); const log = useCallback((msg: string) => { const time = new Date().toLocaleTimeString(); @@ -75,6 +82,12 @@ export function App() { const handleReady = useCallback(() => { log('✓ Template builder ready'); + if (importingRef.current) { + log('📄 Document imported'); + importingRef.current = false; + setImportError(null); + setIsImporting(false); + } }, [log]); const handleTrigger = useCallback(() => { @@ -114,9 +127,35 @@ export function App() { }; const documentConfig = useMemo(() => ({ - source: "https://storage.googleapis.com/public_static_hosting/public_demo_docs/service_agreement.docx", + source: documentSource, mode: 'editing' as const - }), []); + }), [documentSource]); + + const handleImportButtonClick = useCallback(() => { + if (isImporting) return; + fileInputRef.current?.click(); + }, [isImporting]); + + const handleFileInputChange = useCallback((event: React.ChangeEvent) => { + const file = event.target.files?.[0]; + event.target.value = ""; + + if (!file) return; + + const extension = file.name.split('.').pop()?.toLowerCase(); + if (extension !== 'docx') { + const message = 'Invalid file type. Please choose a .docx file.'; + setImportError(message); + log('⚠️ ' + message); + return; + } + + importingRef.current = true; + setImportError(null); + setIsImporting(true); + setDocumentSource(file); + log(`📥 Importing "${file.name}"`); + }, [log]); const fieldsConfig = useMemo(() => ({ available: availableFields, @@ -160,16 +199,36 @@ export function App() { Tab/Shift+Tab to navigate
+ +
+ {importError && ( +
+ {importError} +
+ )} +