Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 14 additions & 22 deletions src/components/NoteCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,33 +28,25 @@ export function NoteCard({ note, isActive, onClick, onDelete, onDuplicate }: Not

return (
<Card
className={`p-4 cursor-pointer transition-all justify-between flex hover:shadow-md ${
isActive ? 'ring-2 ring-primary bg-accent/5' : ''
className={`p-4 rounded-xl cursor-pointer transition-all flex flex-col gap-2 shadow-sm border border-border hover:shadow-lg ${
isActive ? 'ring-2 ring-primary bg-accent/10 border-primary' : 'bg-card'
}`}
onClick={onClick}
>
<div className="flex flex-col">
<h3 className="font-semibold text-foreground mb-1 truncate font-serif">
<div className="flex flex-col gap-1">
<h3 className="font-semibold text-lg text-foreground truncate font-serif">
{note.title || 'Untitled Note'}
</h3>

{/* Timestamp Display */}
<div className="flex flex-col gap-1 pt-2 border-t border-border/50">
<div className="flex items-center gap-1.5 text-xs text-muted-foreground">
<Calendar className="w-3 h-3" />
<span>Created: {formatTimestamp(note.createdAt)}</span>
</div>
<div className="flex items-center gap-1.5 text-xs text-muted-foreground">
<Clock className="w-3 h-3" />
<span>Edited {getRelativeTime(note.updatedAt)}</span>
</div>
</div>
</div>

<div className="flex justify-center items-center">
<div className="flex gap-2 items-center">
{/* Duplicate button (optional) */}
{onDuplicate && (
<p className="text-xs text-muted-foreground font-sans">
{formatDistanceToNow(note.updatedAt, { addSuffix: true })}
</p>
</div>
<p className="text-sm text-muted-foreground truncate mb-2">
{preview}
</p>
<div className="flex justify-end items-center mt-auto">
<AlertDialog>
<AlertDialogTrigger asChild>
<Button
variant="ghost"
size="icon"
Expand Down
82 changes: 38 additions & 44 deletions src/components/NoteEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,53 +42,47 @@ export function NoteEditor({ note, onUpdate, onDelete }: NoteEditorProps) {
}, [title, content, note.id, note.title, note.content, onUpdate]);

return (
<div className="flex flex-col h-full">
<div className="flex items-center justify-between">
<Input
value={title}
onChange={(e) => setTitle(e.target.value)}
className="text-2xl font-semibold border-none shadow-none focus-visible:ring-0 px-0"
placeholder="Note title..."
/>
<AlertDialog>
<AlertDialogTrigger asChild>
<Button variant="ghost" size="icon" className="text-destructive hover:text-white" title="Delete Note">
<Trash2 className="h-5 w-5" />
</Button>
</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Delete Note</AlertDialogTitle>
<AlertDialogDescription>
Are you sure you want to delete this note? This action cannot be undone.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction onClick={() => onDelete(note.id)} className="bg-destructive text-destructive-foreground hover:bg-destructive/90">
Delete
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
</div>

{/* Timestamp Display */}
<div className="flex items-center gap-4 text-sm text-muted-foreground">
<div className="flex items-center gap-1.5">
<Calendar className="w-4 h-4" />
<span>Created: {formatTimestamp(note.createdAt)}</span>
</div>
<span className="text-muted-foreground/40">•</span>
<div className="flex items-center gap-1.5">
<Clock className="w-4 h-4" />
<span>Edited {getRelativeTime(note.updatedAt)}</span>
</div>
</div>
<div className="flex flex-col h-full bg-card rounded-xl shadow-md p-6">
<div className="flex items-center justify-between mb-4 pb-4 border-b">
<Input
value={title}
onChange={(e) => setTitle(e.target.value)}
className="text-2xl font-semibold font-serif border-none shadow-none focus-visible:ring-0 px-0 bg-transparent"
placeholder="Note title..."
/>
<AlertDialog>
<AlertDialogTrigger asChild>
<Button variant="ghost" size="icon" className="text-destructive hover:text-destructive">
<Trash2 className="h-5 w-5" />
</Button>
</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Delete Note</AlertDialogTitle>
<AlertDialogDescription>
Are you sure you want to delete this note? This action cannot be undone.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction onClick={() => onDelete(note.id)} className="bg-destructive text-destructive-foreground hover:bg-destructive/90">
Delete
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
</div>
{/* Toolbar for future formatting features */}
<div className="flex gap-2 mb-4">
<Button variant="ghost" size="icon" title="Bold" className="text-muted-foreground"><b>B</b></Button>
<Button variant="ghost" size="icon" title="Italic" className="text-muted-foreground"><i>I</i></Button>
<Button variant="ghost" size="icon" title="Underline" className="text-muted-foreground"><u>U</u></Button>
{/* Add more formatting buttons as needed */}
</div>
<Textarea
value={content}
onChange={(e) => setContent(e.target.value)}
className="flex-1 resize-none border-none shadow-none focus-visible:ring-0 text-base leading-relaxed"
className="flex-1 resize-none border-none shadow-none focus-visible:ring-0 text-base leading-relaxed bg-transparent rounded-lg p-3"
placeholder="Start writing..."
/>
</div>
Expand Down
11 changes: 5 additions & 6 deletions src/components/NotesSidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,17 +84,17 @@ export function NotesSidebar({
</Button>
</div>
</div>
<div className="relative">
<div className="relative mt-2">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-muted-foreground" />
<Input
placeholder="Search notes..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
className="pl-9"
className="pl-9 rounded-lg bg-secondary/60 border border-border focus-visible:ring-2 focus-visible:ring-primary"
/>
</div>
</div>
<ScrollArea className="flex-1">
<ScrollArea className="flex-1 bg-secondary/50">
<div className="p-4 space-y-2">
{filteredNotes.length === 0 ? (
<div className="text-center py-8 text-muted-foreground">
Expand All @@ -107,13 +107,12 @@ export function NotesSidebar({
note={note}
isActive={note.id === activeNoteId}
onClick={() => onSelectNote(note.id)}
onDuplicate={onDuplicateNote ?? undefined}
onDelete={onDelete ?? (() => {})}
onDelete={onCreateNote} // TODO: Replace with actual delete logic if needed
/>
))
)}
</div>
</ScrollArea>
</div>
</aside>
);
}
73 changes: 16 additions & 57 deletions src/pages/Index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { useState, useEffect, useCallback } from "react";
import { useNotes } from "@/hooks/useNotes";
import { NotesSidebar } from "@/components/NotesSidebar";
import { NoteEditor } from "@/components/NoteEditor";
import { FileText, ArrowLeft } from "lucide-react";
import { toast } from "sonner";

import { useState, useEffect } from 'react';
import { useNotes } from '@/hooks/useNotes';
import { NotesSidebar } from '@/components/NotesSidebar';
import { NoteEditor } from '@/components/NoteEditor';
import { FileText, ArrowLeft } from 'lucide-react';

const Index = () => {
const { notes, createNote, updateNote, deleteNote, duplicateNote } =
Expand All @@ -14,8 +14,8 @@ const Index = () => {
useEffect(() => {
const checkMobile = () => setIsMobile(window.innerWidth < 768);
checkMobile();
window.addEventListener("resize", checkMobile);
return () => window.removeEventListener("resize", checkMobile);
window.addEventListener('resize', checkMobile);
return () => window.removeEventListener('resize', checkMobile);
}, []);

const handleCreateNote = () => {
Expand Down Expand Up @@ -137,7 +137,7 @@ const Index = () => {
<div className="flex h-screen overflow-hidden bg-background">
{/* Desktop Layout */}
{!isMobile && (
<>
<div className="flex w-full h-full">
<NotesSidebar
notes={notes}
activeNoteId={activeNoteId}
Expand All @@ -146,50 +146,9 @@ const Index = () => {
onDuplicateNote={handleDuplicateNote}
onDelete={handleDeleteNote}
/>
<main className="flex-1 overflow-hidden relative">
{/* Keyboard Shortcuts Helper */}
<div
className=" hidden md:block absolute bottom-4 right-4 bg-card border border-border rounded-lg p-3 shadow-lg text-xs z-10"
role="region"
aria-labelledby="shortcuts-heading"
>
<div
id="shortcuts-heading"
className="font-semibold text-foreground mb-2 text-sm"
>
Keyboard Shortcuts
</div>
<div className="space-y-1 text-muted-foreground">
<div className="flex items-center justify-between gap-4">
<span>New note</span>
<kbd className="px-2 py-0.5 bg-muted rounded border border-border font-mono">
Cmd/Ctrl+K
</kbd>
</div>
<div className="flex items-center justify-between gap-4">
<span>Save note</span>
<kbd className="px-2 py-0.5 bg-muted rounded border border-border font-mono">
Cmd/Ctrl+S
</kbd>
</div>
<div className="flex items-center justify-between gap-4">
<span>Delete note</span>
<kbd className="px-2 py-0.5 bg-muted rounded border border-border font-mono">
Cmd/Ctrl+D
</kbd>
</div>

<div className="flex items-center justify-between gap-4">
<span>Navigate</span>
<kbd className="px-2 py-0.5 bg-muted rounded border border-border font-mono">
Cmd/Ctrl+↑↓
</kbd>
</div>
</div>
</div>

<main className="flex-1 flex items-center justify-center bg-card">
{activeNote ? (
<div className="h-full p-8">
<div className="w-full max-w-2xl h-full p-8 mx-auto">
<NoteEditor
note={activeNote}
onUpdate={updateNote}
Expand All @@ -205,17 +164,17 @@ const Index = () => {
</div>
)}
</main>
</>
</div>
)}

{/* Mobile Layout */}
{isMobile && (
<main className="flex-1 overflow-hidden">
<main className="flex-1 overflow-hidden bg-card">
{activeNote ? (
<div className="h-full p-4">
<div className="h-full p-4 max-w-xl mx-auto">
{/* Back button */}
<button
onClick={() => setActiveNoteId(null)}
className="mb-4 flex items-center text-sm text-blue-600"
className="mb-4 flex items-center text-sm text-primary font-medium"
>
<ArrowLeft className="h-4 w-4 mr-2" /> Back
</button>
Expand Down