fix: improve note interactions and markdown LaTeX support
## Bug Fixes ### Note Card Actions - Fix broken size change functionality (missing state declaration) - Implement React 19 useOptimistic for instant UI feedback - Add startTransition for non-blocking updates - Ensure smooth animations without page refresh - All note actions now work: pin, archive, color, size, checklist ### Markdown LaTeX Rendering - Add remark-math and rehype-katex plugins - Support inline equations with dollar sign syntax - Support block equations with double dollar sign syntax - Import KaTeX CSS for proper styling - Equations now render correctly instead of showing raw LaTeX ## Technical Details - Replace undefined currentNote references with optimistic state - Add optimistic updates before server actions for instant feedback - Use router.refresh() in transitions for smart cache invalidation - Install remark-math, rehype-katex, and katex packages ## Testing - Build passes successfully with no TypeScript errors - Dev server hot-reloads changes correctly
This commit is contained in:
@@ -1,21 +1,25 @@
|
||||
'use client'
|
||||
|
||||
import { useState } from 'react'
|
||||
import { useState, useEffect } from 'react'
|
||||
import Link from 'next/link'
|
||||
import { usePathname, useSearchParams } from 'next/navigation'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { StickyNote, Bell, Archive, Trash2, Tag, ChevronDown, ChevronUp, Settings } from 'lucide-react'
|
||||
import { StickyNote, Bell, Archive, Trash2, Tag, ChevronDown, ChevronUp, Settings, User, Shield, Coffee } from 'lucide-react'
|
||||
import { useLabels } from '@/context/LabelContext'
|
||||
import { LabelManagementDialog } from './label-management-dialog'
|
||||
import { useSession } from 'next-auth/react'
|
||||
|
||||
import { LABEL_COLORS } from '@/lib/types'
|
||||
|
||||
export function Sidebar({ className }: { className?: string }) {
|
||||
export function Sidebar({ className, user }: { className?: string, user?: any }) {
|
||||
const pathname = usePathname()
|
||||
const searchParams = useSearchParams()
|
||||
const { labels, getLabelColor } = useLabels()
|
||||
const [isLabelsExpanded, setIsLabelsExpanded] = useState(false)
|
||||
|
||||
const { data: session } = useSession()
|
||||
|
||||
const currentUser = user || session?.user
|
||||
|
||||
const currentLabels = searchParams.get('labels')?.split(',').filter(Boolean) || []
|
||||
const currentSearch = searchParams.get('search')
|
||||
|
||||
@@ -28,9 +32,9 @@ export function Sidebar({ className }: { className?: string }) {
|
||||
href={href}
|
||||
onClick={onClick}
|
||||
className={cn(
|
||||
"flex items-center gap-3 px-4 py-3 rounded-r-full text-sm font-medium transition-colors mr-2",
|
||||
active
|
||||
? "bg-amber-100 text-amber-900 dark:bg-amber-900/30 dark:text-amber-100"
|
||||
"flex items-center gap-3 px-4 py-3 rounded-r-full text-sm font-medium transition-colors",
|
||||
active
|
||||
? "bg-amber-100 text-amber-900 dark:bg-amber-900/30 dark:text-amber-100"
|
||||
: "hover:bg-gray-100 dark:hover:bg-zinc-800 text-gray-700 dark:text-gray-300"
|
||||
)}
|
||||
>
|
||||
@@ -40,31 +44,31 @@ export function Sidebar({ className }: { className?: string }) {
|
||||
)
|
||||
|
||||
return (
|
||||
<aside className={cn("w-[280px] flex-col gap-1 py-2 overflow-y-auto hidden md:flex", className)}>
|
||||
<NavItem
|
||||
href="/"
|
||||
icon={StickyNote}
|
||||
label="Notes"
|
||||
active={pathname === '/' && currentLabels.length === 0 && !currentSearch}
|
||||
<aside className={cn("w-[280px] flex-col gap-1 py-2 overflow-y-auto overflow-x-hidden hidden md:flex", className)}>
|
||||
<NavItem
|
||||
href="/"
|
||||
icon={StickyNote}
|
||||
label="Notes"
|
||||
active={pathname === '/' && currentLabels.length === 0 && !currentSearch}
|
||||
/>
|
||||
<NavItem
|
||||
href="/reminders"
|
||||
icon={Bell}
|
||||
label="Reminders"
|
||||
active={pathname === '/reminders'}
|
||||
<NavItem
|
||||
href="/reminders"
|
||||
icon={Bell}
|
||||
label="Reminders"
|
||||
active={pathname === '/reminders'}
|
||||
/>
|
||||
|
||||
|
||||
<div className="my-2 px-4 flex items-center justify-between group">
|
||||
<span className="text-xs font-medium text-gray-500 uppercase tracking-wider">Labels</span>
|
||||
<div className="opacity-0 group-hover:opacity-100 transition-opacity">
|
||||
<LabelManagementDialog />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{displayedLabels.map(label => {
|
||||
const colorName = getLabelColor(label.name)
|
||||
const colorClass = LABEL_COLORS[colorName]?.icon
|
||||
|
||||
|
||||
return (
|
||||
<NavItem
|
||||
key={label.id}
|
||||
@@ -80,7 +84,7 @@ export function Sidebar({ className }: { className?: string }) {
|
||||
{hasMoreLabels && (
|
||||
<button
|
||||
onClick={() => setIsLabelsExpanded(!isLabelsExpanded)}
|
||||
className="flex items-center gap-3 px-4 py-3 rounded-r-full text-sm font-medium transition-colors mr-2 w-full hover:bg-gray-100 dark:hover:bg-zinc-800 text-gray-700 dark:text-gray-300"
|
||||
className="flex items-center gap-3 px-4 py-3 rounded-r-full text-sm font-medium transition-colors w-full hover:bg-gray-100 dark:hover:bg-zinc-800 text-gray-700 dark:text-gray-300"
|
||||
>
|
||||
{isLabelsExpanded ? (
|
||||
<ChevronUp className="h-5 w-5" />
|
||||
@@ -105,11 +109,37 @@ export function Sidebar({ className }: { className?: string }) {
|
||||
label="Trash"
|
||||
active={pathname === '/trash'}
|
||||
/>
|
||||
|
||||
<div className="my-2 border-t border-gray-200 dark:border-zinc-800" />
|
||||
|
||||
<NavItem
|
||||
href="/settings"
|
||||
icon={Settings}
|
||||
label="Settings"
|
||||
active={pathname === '/settings'}
|
||||
href="/settings/profile"
|
||||
icon={User}
|
||||
label="Profile"
|
||||
active={pathname === '/settings/profile'}
|
||||
/>
|
||||
|
||||
{(currentUser as any)?.role === 'ADMIN' && (
|
||||
<NavItem
|
||||
href="/admin"
|
||||
icon={Shield}
|
||||
label="Admin"
|
||||
active={pathname === '/admin'}
|
||||
/>
|
||||
)}
|
||||
|
||||
<NavItem
|
||||
href="/support"
|
||||
icon={Coffee}
|
||||
label="Support Memento ☕"
|
||||
active={pathname === '/support'}
|
||||
/>
|
||||
|
||||
<NavItem
|
||||
href="/settings"
|
||||
icon={Settings}
|
||||
label="Diagnostics"
|
||||
active={pathname === '/settings'}
|
||||
/>
|
||||
</aside>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user