From 84ef53ae0596520a11c6172b392b2a481d607dba Mon Sep 17 00:00:00 2001 From: lubiana Date: Fri, 25 Jul 2025 20:18:05 +0200 Subject: [PATCH] import export --- frontend/src/components/CreateChecklist.tsx | 67 +++++++- frontend/src/components/SavedChecklists.tsx | 23 ++- frontend/src/hooks/useLocalStorage.ts | 161 +++++++++++++++++++- frontend/src/pages/Checklist.tsx | 23 +++ test-checklist.json | 47 ++++++ 5 files changed, 315 insertions(+), 6 deletions(-) create mode 100644 test-checklist.json diff --git a/frontend/src/components/CreateChecklist.tsx b/frontend/src/components/CreateChecklist.tsx index 9a46447..c220870 100644 --- a/frontend/src/components/CreateChecklist.tsx +++ b/frontend/src/components/CreateChecklist.tsx @@ -1,5 +1,6 @@ -import { useState } from 'react' +import { useState, useRef } from 'react' import { useNavigate } from 'react-router-dom' +import { importChecklistFromJSON } from '../hooks/useLocalStorage' interface CreateChecklistProps { className?: string @@ -8,6 +9,8 @@ interface CreateChecklistProps { export default function CreateChecklist({ className = '' }: CreateChecklistProps) { const [checklistName, setChecklistName] = useState('') const [isCreating, setIsCreating] = useState(false) + const [isImporting, setIsImporting] = useState(false) + const fileInputRef = useRef(null) const navigate = useNavigate() const createChecklist = async () => { @@ -46,22 +49,48 @@ export default function CreateChecklist({ className = '' }: CreateChecklistProps } } + const handleImportChecklist = async (event: React.ChangeEvent) => { + const file = event.target.files?.[0] + if (!file) return + + setIsImporting(true) + try { + const newUuid = await importChecklistFromJSON(file) + navigate(`/${newUuid}`) + } catch (error) { + console.error('Error importing checklist:', error) + alert('Failed to import checklist. Please check the file format.') + } finally { + setIsImporting(false) + // Reset the file input + if (fileInputRef.current) { + fileInputRef.current.value = '' + } + } + } + + const triggerFileInput = () => { + fileInputRef.current?.click() + } + return (

Create New Checklist

-
+ + {/* Create new checklist section */} +
setChecklistName(e.target.value)} onKeyDown={handleKeyDown} - disabled={isCreating} + disabled={isCreating || isImporting} className="flex-1 px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent disabled:bg-gray-100 dark:disabled:bg-gray-700 disabled:text-gray-500 dark:disabled:text-gray-400 bg-white dark:bg-gray-700 text-gray-900 dark:text-white placeholder-gray-500 dark:placeholder-gray-400" /> +
+
) } \ No newline at end of file diff --git a/frontend/src/components/SavedChecklists.tsx b/frontend/src/components/SavedChecklists.tsx index a482e9d..2525b1d 100644 --- a/frontend/src/components/SavedChecklists.tsx +++ b/frontend/src/components/SavedChecklists.tsx @@ -1,5 +1,5 @@ import { Link } from 'react-router-dom' -import { loadSavedChecklists } from '../hooks/useLocalStorage' +import { loadSavedChecklists, exportChecklistToJSON } from '../hooks/useLocalStorage' import { useState } from 'react' interface SavedChecklistsProps { @@ -8,12 +8,25 @@ interface SavedChecklistsProps { export default function SavedChecklists({ className = '' }: SavedChecklistsProps) { const [savedChecklists, setSavedChecklists] = useState<{ uuid: string; name: string; lastOpened?: string }[]>(loadSavedChecklists()) + const [exportingChecklist, setExportingChecklist] = useState(null) + const handleForgetCheckList = (uuid: string): void => { const updatedChecklists = savedChecklists.filter((checklist: { uuid: string }) => checklist.uuid !== uuid) localStorage.setItem('gocheck-saved-checklists', JSON.stringify(updatedChecklists)) setSavedChecklists(updatedChecklists) } + const handleExportChecklist = async (uuid: string, name: string): Promise => { + setExportingChecklist(uuid) + try { + await exportChecklistToJSON(uuid, name) + } catch (error) { + alert('Failed to export checklist') + } finally { + setExportingChecklist(null) + } + } + if (savedChecklists.length === 0) { return ( @@ -67,6 +80,14 @@ export default function SavedChecklists({ className = '' }: SavedChecklistsProps > 📤 Share + {isConnected ? ( diff --git a/test-checklist.json b/test-checklist.json new file mode 100644 index 0000000..2396dbc --- /dev/null +++ b/test-checklist.json @@ -0,0 +1,47 @@ +{ + "name": "Test Import Checklist", + "uuid": "test-uuid-123", + "exportedAt": "2024-01-01T12:00:00.000Z", + "items": [ + { + "id": 1, + "content": "First item", + "checked": false, + "parent_id": null, + "checklist_uuid": "test-uuid-123", + "dependencies": [], + "not_before": null, + "not_after": null + }, + { + "id": 2, + "content": "Second item (depends on first)", + "checked": false, + "parent_id": null, + "checklist_uuid": "test-uuid-123", + "dependencies": [1], + "not_before": null, + "not_after": null + }, + { + "id": 3, + "content": "Child item", + "checked": true, + "parent_id": 1, + "checklist_uuid": "test-uuid-123", + "dependencies": [], + "not_before": null, + "not_after": null + }, + { + "id": 4, + "content": "Item with date constraints", + "checked": false, + "parent_id": null, + "checklist_uuid": "test-uuid-123", + "dependencies": [2], + "not_before": "2024-01-01T10:00:00Z", + "not_after": "2024-01-01T14:00:00Z" + } + ] +} \ No newline at end of file