- Ticket 10: Navegación completa de listas por teclado (↑↓ Enter E F P) - Ticket 13: Historial de navegación contextual con recent-context-list - Ticket 17: Exportación mejorada a Markdown con frontmatter - Ticket 18: Exportación HTML simple y legible - Ticket 19: Importador Markdown mejorado con frontmatter, tags, wiki links - Ticket 20: Importador Obsidian-compatible (wiki links, #tags inline) - Ticket 21: Centro de respaldo y portabilidad en Settings - Ticket 22: Configuración visible de feature flags - Ticket 24: Tests de command palette y captura externa - Ticket 25: Harden de validaciones y límites (50MB backup, 10K notas, etc)
87 lines
2.4 KiB
TypeScript
87 lines
2.4 KiB
TypeScript
'use client'
|
|
|
|
import { useCallback } from 'react'
|
|
import { Note } from '@/types/note'
|
|
import { NoteCard } from './note-card'
|
|
import { useNoteListKeyboard } from '@/hooks/use-note-list-keyboard'
|
|
import { toast } from 'sonner'
|
|
|
|
interface KeyboardNavigableNoteListProps {
|
|
notes: Note[]
|
|
onEdit?: (noteId: string) => void
|
|
}
|
|
|
|
export function KeyboardNavigableNoteList({
|
|
notes,
|
|
onEdit,
|
|
}: KeyboardNavigableNoteListProps) {
|
|
const handleFavorite = useCallback(async (noteId: string) => {
|
|
try {
|
|
const res = await fetch(`/api/notes/${noteId}`, {
|
|
method: 'PATCH',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ isFavorite: true }),
|
|
})
|
|
if (res.ok) {
|
|
toast.success('Añadido a favoritos')
|
|
window.location.reload()
|
|
}
|
|
} catch {
|
|
toast.error('Error al añadir a favoritos')
|
|
}
|
|
}, [])
|
|
|
|
const handlePin = useCallback(async (noteId: string) => {
|
|
try {
|
|
const res = await fetch(`/api/notes/${noteId}`, {
|
|
method: 'PATCH',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ isPinned: true }),
|
|
})
|
|
if (res.ok) {
|
|
toast.success('Nota fijada')
|
|
window.location.reload()
|
|
}
|
|
} catch {
|
|
toast.error('Error al fijar nota')
|
|
}
|
|
}, [])
|
|
|
|
const { selectedIndex } = useNoteListKeyboard({
|
|
notes,
|
|
onEdit,
|
|
onFavorite: handleFavorite,
|
|
onPin: handlePin,
|
|
})
|
|
|
|
if (notes.length === 0) {
|
|
return (
|
|
<div className="text-center py-12 text-gray-500">
|
|
<p className="text-lg">No hay notas todavía</p>
|
|
<p className="text-sm">Crea tu primera nota para comenzar</p>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
|
{notes.map((note, index) => (
|
|
<div
|
|
key={note.id}
|
|
className={`relative ${index === selectedIndex ? 'ring-2 ring-primary ring-offset-2 rounded-lg' : ''}`}
|
|
data-selected={index === selectedIndex}
|
|
>
|
|
<NoteCard note={note} />
|
|
{index === selectedIndex && (
|
|
<div className="absolute bottom-2 right-2 flex gap-1">
|
|
<span className="px-1.5 py-0.5 bg-muted text-xs rounded text-muted-foreground">
|
|
Enter: abrir | E: editar | F: favoritar | P: fijar
|
|
</span>
|
|
</div>
|
|
)}
|
|
</div>
|
|
))}
|
|
</div>
|
|
)
|
|
}
|