diff --git a/apps/web/src/routes/_app/calendar.tsx b/apps/web/src/routes/_app/calendar.tsx index 005f0d7..f818e00 100644 --- a/apps/web/src/routes/_app/calendar.tsx +++ b/apps/web/src/routes/_app/calendar.tsx @@ -162,7 +162,6 @@ function EventForm({ event, onClose }: { event?: CalendarEvent; onClose: () => v function CalendarPage() { const queryClient = useQueryClient(); const [date, setDate] = useState(new Date()); - const [view, setView] = useState("month"); const [createOpen, setCreateOpen] = useState(false); const [selectedEvent, setSelectedEvent] = useState(null); const [eventDetailOpen, setEventDetailOpen] = useState(false); @@ -177,12 +176,7 @@ function CalendarPage() { return () => window.removeEventListener("resize", check); }, []); - // Auto-switch to agenda on mobile - useEffect(() => { - if (isMobile && view === "month") { - setView("agenda"); - } - }, [isMobile]); + // Mobile: defaultView is set to agenda via isMobile check const { data: eventsData } = useApiQuery<{ items: CalendarEvent[]; totalItems: number }>( ["calendar-events", date.toISOString()], @@ -241,8 +235,9 @@ function CalendarPage() { setDate(newDate); }, []); + const viewRef = useRef("month"); const handleViewChange = useCallback((newView: string) => { - setView(newView); + viewRef.current = newView; }, []); return ( @@ -267,8 +262,7 @@ function CalendarPage() { startAccessor="start" endAccessor="end" date={date} - view={view} - defaultView={Views.MONTH} + defaultView={isMobile ? Views.AGENDA : Views.MONTH} onNavigate={handleNavigate} onView={handleViewChange} onSelectEvent={handleSelectEvent} @@ -281,7 +275,7 @@ function CalendarPage() { showMultiDayTimes components={{ event: EventComponent, - toolbar: (props: any) => , + toolbar: (props: any) => , }} views={["month", "week", "work_week", "day", "agenda"]} step={30} diff --git a/apps/web/src/routes/_app/index.tsx b/apps/web/src/routes/_app/index.tsx index 5d3deae..6378bc1 100644 --- a/apps/web/src/routes/_app/index.tsx +++ b/apps/web/src/routes/_app/index.tsx @@ -205,6 +205,7 @@ function QuickCaptureWidget() { }); const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); + e.stopPropagation(); if (!text.trim()) return; if (type === "task") createTask.mutate(text.trim()); else createNote.mutate(text.trim()); @@ -221,7 +222,7 @@ function QuickCaptureWidget() { setText(e.target.value)} className="h-9" /> - + ); } diff --git a/apps/web/src/routes/_app/notes.tsx b/apps/web/src/routes/_app/notes.tsx index bbaf90a..73a70ec 100644 --- a/apps/web/src/routes/_app/notes.tsx +++ b/apps/web/src/routes/_app/notes.tsx @@ -1,4 +1,4 @@ -import { useState, useCallback, useRef, useEffect } from "react"; +import { useState, useCallback, useRef, useEffect, memo } from "react"; import { createRoute } from "@tanstack/react-router"; import { Route as appRoute } from "../_app"; import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; @@ -17,7 +17,7 @@ import { cn } from "@/lib/utils"; import type { Note, PaginatedResponse } from "@/lib/types"; // Simple TipTap-like editor using contentEditable -function NoteEditor({ content, onChange, placeholder = "Start writing..." }: { content: string; onChange: (html: string) => void; placeholder?: string }) { +const NoteEditor = memo(function NoteEditor({ content, onChange, placeholder = "Start writing..." }: { content: string; onChange: (html: string) => void; placeholder?: string }) { const editorRef = useRef(null); const [isPlaceholder, setIsPlaceholder] = useState(!content); @@ -47,14 +47,14 @@ function NoteEditor({ content, onChange, placeholder = "Start writing..." }: { c /> ); -} +}); function NotesPage() { const queryClient = useQueryClient(); const [search, setSearch] = useState(""); const [selectedNote, setSelectedNote] = useState(null); const [editorContent, setEditorContent] = useState(""); - const [saveTimer, setSaveTimer] = useState | null>(null); + const saveTimerRef = useRef | null>(null); const [showBacklinks, setShowBacklinks] = useState(false); const [showVersions, setShowVersions] = useState(false); @@ -104,14 +104,13 @@ function NotesPage() { const handleContentChange = useCallback((html: string) => { setEditorContent(html); - if (saveTimer) clearTimeout(saveTimer); - const timer = setTimeout(() => { + if (saveTimerRef.current) clearTimeout(saveTimerRef.current); + saveTimerRef.current = setTimeout(() => { if (selectedNote) { updateMutation.mutate({ id: selectedNote.id, data: { content: html } }); } }, 500); - setSaveTimer(timer); - }, [selectedNote, updateMutation, saveTimer]); + }, [selectedNote, updateMutation]); const handleTitleChange = (title: string) => { if (selectedNote) {