import React, { useEffect, useState } from 'react'; import { useParams, Link, useNavigate } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import { PencilSquareIcon, TrashIcon, TagIcon, FolderIcon, } from '@heroicons/react/24/solid'; import { useToast } from '../Shared/ToastContext'; import ConfirmDialog from '../Shared/ConfirmDialog'; import NoteModal from './NoteModal'; import MarkdownRenderer from '../Shared/MarkdownRenderer'; import { Note } from '../../entities/Note'; import { fetchNoteBySlug, updateNote as apiUpdateNote, } from '../../utils/notesService'; import { deleteNoteWithStoreUpdate } from '../../utils/noteDeleteUtils'; import { createProject } from '../../utils/projectsService'; import { useStore } from '../../store/useStore'; const NoteDetails: React.FC = () => { const { t } = useTranslation(); const { showSuccessToast } = useToast(); const { uidSlug } = useParams<{ uidSlug: string }>(); const [note, setNote] = useState(null); const [isNoteModalOpen, setIsNoteModalOpen] = useState(false); const [isConfirmDialogOpen, setIsConfirmDialogOpen] = useState(false); const [noteToDelete, setNoteToDelete] = useState(null); const [isLoading, setIsLoading] = useState(true); const [isError, setIsError] = useState(false); const projects = useStore((state: any) => state.projectsStore.projects); const { setProjects } = useStore((state: any) => state.projectsStore); const navigate = useNavigate(); // Dispatch global modal events useEffect(() => { const fetchNote = async () => { try { setIsLoading(true); const foundNote = await fetchNoteBySlug(uidSlug!); setNote(foundNote || null); if (!foundNote) { setIsError(true); } } catch (err) { setIsError(true); console.error('Error fetching note:', err); } finally { setIsLoading(false); } }; fetchNote(); }, [uidSlug]); // Projects are now loaded by Layout component into global store const handleDeleteNote = async () => { if (!noteToDelete) return; try { await deleteNoteWithStoreUpdate(noteToDelete, showSuccessToast, t); navigate('/notes'); } catch (err) { console.error('Error deleting note:', err); } }; const handleSaveNote = async (updatedNote: Note) => { try { const noteIdentifier = updatedNote.uid ?? (updatedNote.id !== undefined ? String(updatedNote.id) : null); if (noteIdentifier) { const savedNote = await apiUpdateNote( noteIdentifier, updatedNote ); setNote(savedNote); } else { console.error('Error: Note identifier is undefined.'); } } catch (err) { console.error('Error saving note:', err); } setIsNoteModalOpen(false); }; const handleEditNote = () => { setIsNoteModalOpen(true); }; const handleCreateProject = async (name: string) => { try { const newProject = await createProject({ name, priority: 'low', }); setProjects([...projects, newProject]); return newProject; } catch (error) { console.error('Error creating project:', error); throw error; } }; const handleOpenConfirmDialog = (note: Note) => { setNoteToDelete(note); setIsConfirmDialogOpen(true); }; if (isLoading) { return (
Loading note details...
); } if (isError || !note) { return (
{isError ? 'Error loading note details.' : 'Note not found.'}
); } return (
{/* Header Section with Title and Action Buttons */}

{note.title}

{/* Project and Tags under title */} {(note.project || note.Project || (note.tags && note.tags.length > 0) || (note.Tags && note.Tags.length > 0)) && (
{(note.project || note.Project) && (
{ ( note.project || note.Project )?.name }
)} {(note.project || note.Project) && ((note.tags && note.tags.length > 0) || (note.Tags && note.Tags.length > 0)) && ( )} {((note.tags && note.tags.length > 0) || (note.Tags && note.Tags.length > 0)) && (
{(note.tags || note.Tags || []) .map((tag) => tag.name) .join(', ')}
)}
)}
{/* Action Buttons */}
{/* Note Content */}
{ // Update local state immediately const updatedNote = { ...note, content: newContent, }; setNote(updatedNote); // Auto-save try { const noteIdentifier = note.uid ?? (note.id !== undefined ? String(note.id) : null); if (noteIdentifier) { await apiUpdateNote( noteIdentifier, updatedNote ); } } catch (err) { console.error( 'Error auto-saving checkbox:', err ); } }} />
{/* NoteModal for editing */} {isNoteModalOpen && ( setIsNoteModalOpen(false)} onSave={handleSaveNote} onDelete={async (noteUid) => { try { await deleteNoteWithStoreUpdate( noteUid, showSuccessToast, t ); navigate('/notes'); } catch (err) { console.error('Error deleting note:', err); } }} note={note} projects={projects} onCreateProject={handleCreateProject} /> )} {/* ConfirmDialog */} {isConfirmDialogOpen && noteToDelete && ( { setIsConfirmDialogOpen(false); setNoteToDelete(null); }} /> )}
); }; export default NoteDetails;