"use client"; import { useEffect, useState, useRef } from "react"; import { useSession } from "next-auth/react"; import { redirect } from "next/navigation"; import Navigation from "@/components/carnet/navigation"; import { NotesView } from "@/components/carnet/notes-view"; import { Editor } from "@/components/carnet/editor"; import { PanelResizer } from "@/components/carnet/panel-resizer"; import { useMediaQuery } from "@/hooks/use-media-query"; // Layout modes export enum PaneLayout { TagSelection = "tag-selection", ItemSelection = "item-selection", TableView = "table-view", Editing = "editing" } interface Note { id: string; title: string; content: string; lastModified: string; type: string; mime: string; etag: string; } export default function CarnetPage() { const { data: session, status } = useSession(); const [isLoading, setIsLoading] = useState(true); const [layoutMode, setLayoutMode] = useState("item-selection"); const [selectedNote, setSelectedNote] = useState(null); const [isMobile, setIsMobile] = useState(false); const [showNav, setShowNav] = useState(true); const [showNotes, setShowNotes] = useState(true); const [nextcloudFolders, setNextcloudFolders] = useState([]); const [selectedFolder, setSelectedFolder] = useState('Notes'); const [notes, setNotes] = useState([]); const [isLoadingNotes, setIsLoadingNotes] = useState(true); // Panel widths state const [navWidth, setNavWidth] = useState(220); const [notesWidth, setNotesWidth] = useState(400); const [isDraggingNav, setIsDraggingNav] = useState(false); const [isDraggingNotes, setIsDraggingNotes] = useState(false); // Check screen size const isSmallScreen = useMediaQuery("(max-width: 768px)"); const isMediumScreen = useMediaQuery("(max-width: 1024px)"); // Cache for Nextcloud folders const foldersCache = useRef<{ folders: string[]; timestamp: number } | null>(null); useEffect(() => { const fetchNextcloudFolders = async () => { // Check cache first if (foldersCache.current) { const cacheAge = Date.now() - foldersCache.current.timestamp; if (cacheAge < 5 * 60 * 1000) { // 5 minutes cache setNextcloudFolders(foldersCache.current.folders); return; } } try { const response = await fetch('/api/nextcloud/status'); if (!response.ok) { throw new Error('Failed to fetch Nextcloud folders'); } const data = await response.json(); const folders = data.folders || []; // Update cache foldersCache.current = { folders, timestamp: Date.now() }; setNextcloudFolders(folders); } catch (err) { console.error('Error fetching Nextcloud folders:', err); setNextcloudFolders([]); } }; if (status === "authenticated") { fetchNextcloudFolders(); } }, [status]); useEffect(() => { if (status === "unauthenticated") { redirect("/signin"); } if (status !== "loading") { setIsLoading(false); } }, [status]); useEffect(() => { if (isSmallScreen) { setIsMobile(true); setShowNav(false); setShowNotes(false); } else if (isMediumScreen) { setIsMobile(false); setShowNav(true); setShowNotes(false); } else { setIsMobile(false); setShowNav(true); setShowNotes(true); } }, [isSmallScreen, isMediumScreen]); useEffect(() => { const fetchNotes = async () => { try { setIsLoadingNotes(true); const response = await fetch(`/api/nextcloud/files?folder=${selectedFolder}`); if (!response.ok) { throw new Error('Failed to fetch notes'); } const data = await response.json(); setNotes(data); } catch (error) { console.error('Error fetching notes:', error); setNotes([]); } finally { setIsLoadingNotes(false); } }; fetchNotes(); }, [selectedFolder]); // Handle panel resizing const handleNavResize = (e: MouseEvent) => { if (!isDraggingNav) return; const newWidth = e.clientX; if (newWidth >= 48 && newWidth <= 400) { setNavWidth(newWidth); } }; const handleNotesResize = (e: MouseEvent) => { if (!isDraggingNotes) return; const newWidth = e.clientX - navWidth - 2; // 2px for the resizer if (newWidth >= 200) { setNotesWidth(newWidth); } }; const handleNoteSelect = (note: Note) => { setSelectedNote(note); if (isMobile) { setShowNotes(false); } }; const handleNoteSave = async (note: Note) => { try { const endpoint = note.id ? '/api/nextcloud/files' : '/api/nextcloud/files'; const method = note.id ? 'PUT' : 'POST'; const response = await fetch(endpoint, { method, headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ id: note.id, title: note.title, content: note.content, folder: selectedFolder }), }); if (!response.ok) { throw new Error('Failed to save note'); } // After successful save, refresh the notes list const notesResponse = await fetch(`/api/nextcloud/files?folder=${selectedFolder}`); if (notesResponse.ok) { const updatedNotes = await notesResponse.json(); setNotes(updatedNotes); } } catch (error) { console.error('Error saving note:', error); } }; const handleFolderSelect = (folder: string) => { console.log('Selected folder:', folder); setSelectedFolder(folder); setLayoutMode("item-selection"); }; const handleNewNote = () => { setSelectedNote({ id: '', title: '', content: '', lastModified: new Date().toISOString(), type: 'file', mime: 'text/markdown', etag: '' }); if (isMobile) { setShowNotes(false); } }; const handleDeleteNote = async (note: Note) => { try { const response = await fetch(`/api/nextcloud/files`, { method: 'DELETE', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ id: note.id, folder: selectedFolder }), }); if (!response.ok) { throw new Error('Failed to delete note'); } // Refresh the notes list const notesResponse = await fetch(`/api/nextcloud/files?folder=${selectedFolder}`); if (notesResponse.ok) { const updatedNotes = await notesResponse.json(); setNotes(updatedNotes); } // If the deleted note was selected, clear the selection if (selectedNote?.id === note.id) { setSelectedNote(null); } } catch (error) { console.error('Error deleting note:', error); } }; if (isLoading) { return (
); } return (
{/* Navigation Panel */} {showNav && ( <>
{/* Navigation Resizer */} setIsDraggingNav(true)} onDragEnd={() => setIsDraggingNav(false)} onDrag={handleNavResize} /> )} {/* Notes Panel */} {showNotes && ( <>
{/* Notes Resizer */} setIsDraggingNotes(true)} onDragEnd={() => setIsDraggingNotes(false)} onDrag={handleNotesResize} /> )} {/* Editor Panel */}
{ // Refresh the notes list fetch(`/api/nextcloud/files?folder=${selectedFolder}`) .then(response => response.json()) .then(updatedNotes => setNotes(updatedNotes)) .catch(error => console.error('Error refreshing notes:', error)); }} />
{/* Mobile Navigation Toggle */} {isMobile && (
)}
); }