2025-11-23 09:08:01 +00:00
|
|
|
import {
|
2025-11-26 21:38:58 +00:00
|
|
|
BoldItalicUnderlineToggles,
|
2025-11-23 09:08:01 +00:00
|
|
|
codeBlockPlugin,
|
|
|
|
|
codeMirrorPlugin,
|
2025-11-25 22:09:02 +00:00
|
|
|
diffSourcePlugin,
|
2025-11-23 09:08:01 +00:00
|
|
|
headingsPlugin,
|
2025-11-25 22:09:02 +00:00
|
|
|
imagePlugin,
|
2025-11-23 09:08:01 +00:00
|
|
|
linkPlugin,
|
|
|
|
|
listsPlugin,
|
|
|
|
|
markdownShortcutPlugin,
|
|
|
|
|
MDXEditor,
|
|
|
|
|
quotePlugin,
|
|
|
|
|
SandpackConfig,
|
|
|
|
|
sandpackPlugin,
|
2025-11-25 22:09:02 +00:00
|
|
|
tablePlugin,
|
2025-11-23 09:08:01 +00:00
|
|
|
thematicBreakPlugin,
|
2025-11-26 21:38:58 +00:00
|
|
|
toolbarPlugin,
|
|
|
|
|
UndoRedo,
|
|
|
|
|
DiffSourceToggleWrapper,
|
2025-11-23 09:08:01 +00:00
|
|
|
} from "@mdxeditor/editor";
|
2025-11-26 21:38:58 +00:00
|
|
|
import { SetStateAction, useEffect, useRef, useState } from "react";
|
2025-11-23 09:08:01 +00:00
|
|
|
import {
|
|
|
|
|
folderApi,
|
|
|
|
|
FolderCreate,
|
|
|
|
|
FolderTreeNode,
|
|
|
|
|
FolderTreeResponse,
|
|
|
|
|
NoteRead,
|
|
|
|
|
} from "../api/folders";
|
|
|
|
|
import { NoteCreate, notesApi } from "../api/notes";
|
|
|
|
|
import "../main.css";
|
2025-11-23 15:14:48 +00:00
|
|
|
import {
|
|
|
|
|
DndContext,
|
|
|
|
|
DragEndEvent,
|
|
|
|
|
PointerSensor,
|
|
|
|
|
useSensor,
|
|
|
|
|
useSensors,
|
|
|
|
|
} from "@dnd-kit/core";
|
2025-11-23 09:08:01 +00:00
|
|
|
|
|
|
|
|
import "@mdxeditor/editor/style.css";
|
|
|
|
|
import { DroppableFolder } from "../components/sidebar/DroppableFolder";
|
|
|
|
|
import { DraggableNote } from "../components/sidebar/DraggableNote";
|
2025-11-30 19:40:10 +00:00
|
|
|
// @ts-ignore
|
2025-11-25 22:09:02 +00:00
|
|
|
import CheckIcon from "../assets/fontawesome/svg/circle-check.svg?react";
|
2025-11-30 19:40:10 +00:00
|
|
|
// @ts-ignore
|
2025-11-25 22:09:02 +00:00
|
|
|
import SpinnerIcon from "../assets/fontawesome/svg/rotate.svg?react";
|
2025-11-29 12:45:41 +00:00
|
|
|
import { useNoteStore } from "../stores/notesStore";
|
|
|
|
|
import { create } from "zustand";
|
2025-11-30 18:01:57 +00:00
|
|
|
import { Sidebar } from "../components/sidebar/SideBar";
|
2025-11-30 20:32:22 +00:00
|
|
|
import { Editor } from "../components/editor/Editor";
|
|
|
|
|
import { useUIStore } from "../stores/uiStore";
|
2025-11-23 09:08:01 +00:00
|
|
|
|
|
|
|
|
function Home() {
|
2025-11-29 12:45:41 +00:00
|
|
|
// const [folderTree, setFolderTree] = useState<FolderTreeResponse | null>(null);
|
2025-11-30 18:01:57 +00:00
|
|
|
// const [selectedNote, setSelectedNote] = useState<NoteRead | null>(null);
|
2025-11-23 09:08:01 +00:00
|
|
|
const [title, setTitle] = useState("");
|
2025-11-25 22:09:02 +00:00
|
|
|
const [content, setContent] = useState("");
|
2025-11-23 09:08:01 +00:00
|
|
|
const [newFolder, setNewFolder] = useState(false);
|
|
|
|
|
const [newFolderText, setNewFolderText] = useState("");
|
2025-11-30 18:01:57 +00:00
|
|
|
// const [selectedFolder, setSelectedFolder] = useState<number | null>(null);
|
2025-11-23 15:14:48 +00:00
|
|
|
const [encrypted, setEncrypted] = useState(false);
|
2025-11-30 20:32:22 +00:00
|
|
|
// const [updating, setUpdating] = useState(false);
|
2025-11-25 22:09:02 +00:00
|
|
|
|
2025-11-30 18:01:57 +00:00
|
|
|
const {
|
|
|
|
|
setSelectedFolder,
|
|
|
|
|
selectedFolder,
|
|
|
|
|
folderTree,
|
|
|
|
|
loadFolderTree,
|
|
|
|
|
createNote,
|
|
|
|
|
createFolder,
|
|
|
|
|
updateNote,
|
|
|
|
|
setSelectedNote,
|
|
|
|
|
selectedNote,
|
|
|
|
|
} = useNoteStore();
|
2025-11-29 12:45:41 +00:00
|
|
|
|
2025-11-30 20:32:22 +00:00
|
|
|
const { updating } = useUIStore();
|
2025-11-25 22:09:02 +00:00
|
|
|
|
|
|
|
|
const newFolderRef = useRef<HTMLInputElement>(null);
|
|
|
|
|
|
2025-11-23 09:08:01 +00:00
|
|
|
useEffect(() => {
|
|
|
|
|
loadFolderTree();
|
|
|
|
|
}, []);
|
|
|
|
|
|
2025-11-25 22:09:02 +00:00
|
|
|
useEffect(() => {
|
|
|
|
|
if (newFolder && newFolderRef.current) {
|
|
|
|
|
newFolderRef.current.focus();
|
|
|
|
|
}
|
|
|
|
|
}, [newFolder]);
|
|
|
|
|
|
2025-11-23 09:08:01 +00:00
|
|
|
const handleCreate = async () => {
|
|
|
|
|
if (!title.trim()) return;
|
2025-11-29 12:45:41 +00:00
|
|
|
await createNote({ title, content, folder_id: null });
|
2025-11-23 09:08:01 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleDelete = async (id: number) => {
|
|
|
|
|
await notesApi.delete(id);
|
|
|
|
|
loadFolderTree();
|
2025-11-25 22:09:02 +00:00
|
|
|
clearSelection();
|
2025-11-23 09:08:01 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const clearSelection = () => {
|
|
|
|
|
setSelectedNote(null);
|
|
|
|
|
setTitle("");
|
2025-11-25 22:09:02 +00:00
|
|
|
setContent("");
|
2025-11-23 09:08:01 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return (
|
2025-11-30 20:32:22 +00:00
|
|
|
<div className="flex bg-ctp-base h-screen text-ctp-text overflow-hidden">
|
|
|
|
|
{/* Sidebar */}
|
2025-11-30 19:40:10 +00:00
|
|
|
|
2025-11-30 20:32:22 +00:00
|
|
|
<Sidebar clearSelection={clearSelection} />
|
2025-11-25 22:09:02 +00:00
|
|
|
|
2025-11-30 20:32:22 +00:00
|
|
|
{/* Main editor area */}
|
|
|
|
|
<div className="flex flex-col w-full h-screen overflow-hidden">
|
|
|
|
|
{/* Top accent bar */}
|
|
|
|
|
<div className="w-full bg-ctp-crust h-1 shrink-0"></div>
|
2025-11-25 22:09:02 +00:00
|
|
|
|
2025-11-30 20:32:22 +00:00
|
|
|
<Editor />
|
2025-11-26 21:38:58 +00:00
|
|
|
|
2025-11-30 20:32:22 +00:00
|
|
|
{/* Action bar */}
|
|
|
|
|
<div className="flex items-center gap-3 px-8 py-4 border-t border-ctp-surface2 bg-ctp-mantle shrink-0">
|
|
|
|
|
{selectedNote ? (
|
|
|
|
|
<>
|
|
|
|
|
{/*<button
|
|
|
|
|
onClick={handleUpdate}
|
|
|
|
|
className="px-2 py-0.5 bg-ctp-blue text-ctp-base rounded-lg hover:bg-ctp-sapphire transition-colors font-medium shadow-sm"
|
|
|
|
|
>
|
|
|
|
|
Save
|
|
|
|
|
</button>*/}
|
2025-11-25 22:09:02 +00:00
|
|
|
<button
|
2025-11-30 20:32:22 +00:00
|
|
|
onClick={() => handleDelete(selectedNote.id)}
|
|
|
|
|
className="px-2 py-0.5 bg-ctp-red text-ctp-base rounded-lg hover:bg-ctp-maroon transition-colors font-medium shadow-sm"
|
2025-11-25 22:09:02 +00:00
|
|
|
>
|
2025-11-30 20:32:22 +00:00
|
|
|
Delete
|
|
|
|
|
</button>
|
|
|
|
|
<button
|
|
|
|
|
onClick={clearSelection}
|
|
|
|
|
className="px-2 py-0.5 bg-ctp-surface0 text-ctp-text rounded-lg hover:bg-ctp-surface1 transition-colors font-medium"
|
|
|
|
|
>
|
|
|
|
|
Cancel
|
2025-11-25 22:09:02 +00:00
|
|
|
</button>
|
|
|
|
|
</>
|
|
|
|
|
) : (
|
2025-11-30 20:32:22 +00:00
|
|
|
<button
|
|
|
|
|
onClick={handleCreate}
|
|
|
|
|
className="px-2 py-0.5 bg-ctp-green text-ctp-base rounded-lg hover:bg-ctp-teal transition-colors font-medium shadow-sm"
|
|
|
|
|
>
|
|
|
|
|
Create Note
|
|
|
|
|
</button>
|
2025-11-25 22:09:02 +00:00
|
|
|
)}
|
|
|
|
|
</div>
|
2025-11-23 09:08:01 +00:00
|
|
|
</div>
|
2025-11-30 20:32:22 +00:00
|
|
|
|
|
|
|
|
{/* Status indicator */}
|
|
|
|
|
<div className="fixed bottom-4 right-4 bg-ctp-surface0 border border-ctp-surface2 rounded-lg px-2 py-0.5 flex items-center gap-2.5 shadow-lg backdrop-blur-sm">
|
|
|
|
|
{updating ? (
|
|
|
|
|
<>
|
|
|
|
|
<SpinnerIcon className="animate-spin h-4 w-4 [&_.fa-primary]:fill-ctp-blue [&_.fa-secondary]:fill-ctp-sapphire" />
|
|
|
|
|
<span className="text-sm text-ctp-subtext0 font-medium">
|
|
|
|
|
Saving...
|
|
|
|
|
</span>
|
|
|
|
|
</>
|
|
|
|
|
) : (
|
|
|
|
|
<>
|
|
|
|
|
<CheckIcon className="h-4 w-4 [&_.fa-primary]:fill-ctp-green [&_.fa-secondary]:fill-ctp-teal" />
|
|
|
|
|
<span className="text-sm text-ctp-subtext0 font-medium">Saved</span>
|
|
|
|
|
</>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2025-11-23 09:08:01 +00:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default Home;
|