-
-
Notifications
You must be signed in to change notification settings - Fork 48
Added the save button and Added validation for note title/content and toast alert #68
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,9 +1,10 @@ | ||||||
| import { useState, useEffect } from "react"; | ||||||
| import { Note, formatTimestamp, getRelativeTime } from "@/types/note"; | ||||||
| import { Input } from "@/components/ui/input"; | ||||||
| import { Textarea } from "@/components/ui/textarea"; | ||||||
| import { Button } from "@/components/ui/button"; | ||||||
| import { Trash2, Calendar, Clock } from "lucide-react"; | ||||||
| import { useState, useEffect } from 'react'; | ||||||
| import { Note, formatTimestamp, getRelativeTime } from '@/types/note'; | ||||||
| import { Input } from '@/components/ui/input'; | ||||||
| import { Textarea } from '@/components/ui/textarea'; | ||||||
| import { Button } from '@/components/ui/button'; | ||||||
| import { Trash2, Calendar, Clock, Save } from 'lucide-react'; | ||||||
|
|
||||||
| import { | ||||||
| AlertDialog, | ||||||
| AlertDialogAction, | ||||||
|
|
@@ -14,7 +15,9 @@ | |||||
| AlertDialogHeader, | ||||||
| AlertDialogTitle, | ||||||
| AlertDialogTrigger, | ||||||
| } from "@/components/ui/alert-dialog"; | ||||||
| } from '@/components/ui/alert-dialog'; | ||||||
| import { toast } from "sonner"; | ||||||
|
|
||||||
|
|
||||||
| interface NoteEditorProps { | ||||||
| note: Note; | ||||||
|
|
@@ -28,56 +31,97 @@ | |||||
| export function NoteEditor({ note, onUpdate, onDelete }: NoteEditorProps) { | ||||||
| const [title, setTitle] = useState(note.title); | ||||||
| const [content, setContent] = useState(note.content); | ||||||
| const [hasInteracted, setHasInteracted] = useState(false); | ||||||
|
|
||||||
|
|
||||||
| useEffect(() => { | ||||||
| setTitle(note.title); | ||||||
| setContent(note.content); | ||||||
| setHasInteracted(false); | ||||||
| }, [note.id, note.title, note.content]); | ||||||
|
|
||||||
| useEffect(() => { | ||||||
| const timer = setTimeout(() => { | ||||||
| if (title !== note.title || content !== note.content) { | ||||||
| onUpdate(note.id, { title, content }); | ||||||
|
|
||||||
| const trimmedTitle = title.trim(); | ||||||
| const trimmedContent = content.trim(); | ||||||
|
|
||||||
| const isValid = | ||||||
| trimmedTitle && | ||||||
| trimmedContent; | ||||||
|
|
||||||
| const hasChanged = | ||||||
| trimmedTitle !== note.title || trimmedContent !== note.content; | ||||||
|
|
||||||
|
|
||||||
| if (!isValid && hasInteracted) { | ||||||
| toast.warning('Please use a non-Empty title and non-empty content to save your note.'); | ||||||
| return; | ||||||
| } | ||||||
|
|
||||||
|
|
||||||
| if (hasInteracted && isValid && hasChanged) { | ||||||
| onUpdate(note.id, { | ||||||
| title: trimmedTitle, | ||||||
| content: trimmedContent, | ||||||
| }); | ||||||
| } | ||||||
| }, 500); | ||||||
|
|
||||||
| return () => clearTimeout(timer); | ||||||
| }, [title, content, note.id, note.title, note.content, onUpdate]); | ||||||
|
Check warning on line 72 in src/components/NoteEditor.tsx
|
||||||
|
|
||||||
|
|
||||||
| return ( | ||||||
| <div className="flex flex-col h-full"> | ||||||
| <div className="flex items-center justify-between"> | ||||||
| <Input | ||||||
| value={title} | ||||||
| onChange={(e) => setTitle(e.target.value)} | ||||||
| onChange={(e) => { | ||||||
| setTitle(e.target.value); | ||||||
| setHasInteracted(true); | ||||||
| } | ||||||
| } | ||||||
| className="text-2xl font-semibold border-none shadow-none focus-visible:ring-0 px-0" | ||||||
| placeholder="Note title..." | ||||||
| /> | ||||||
| <Button | ||||||
| variant="ghost" | ||||||
| size="icon" | ||||||
| title="Save Note" | ||||||
| className="text-teal-600 hover:text-white hover:bg-teal-600" | ||||||
| onClick={() => { | ||||||
| const trimmedTitle = title.trim(); | ||||||
| const trimmedContent = content.trim(); | ||||||
|
|
||||||
| if (!trimmedTitle || !trimmedContent) { | ||||||
| toast.error('Cannot save: Content and Title can not be empty '); | ||||||
|
||||||
| toast.error('Cannot save: Content and Title can not be empty '); | |
| toast.error('Cannot save: Content and Title cannot be empty.'); |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,8 +1,19 @@ | ||||||||||||||||||
| import { useState, useEffect } from 'react'; | ||||||||||||||||||
| import { Note } from '@/types/note'; | ||||||||||||||||||
|
|
||||||||||||||||||
| import { toast } from "sonner"; | ||||||||||||||||||
| import { title } from 'process'; | ||||||||||||||||||
|
||||||||||||||||||
| import { title } from 'process'; |
Copilot
AI
Oct 14, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed grammatical error in comment from 'Add validation' to 'Added validation'.
| //Add validation : Avanish | |
| // Added validation : Avanish |
Copilot
AI
Oct 14, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Filtering out invalid notes during localStorage save can cause data loss. Invalid notes that users are actively editing will be permanently removed. Consider saving all notes but marking invalid ones differently.
| const validNotes = notes.filter(isValidNote); | |
| localStorage.setItem(STORAGE_KEY, JSON.stringify(validNotes)); | |
| // Save all notes, but mark invalid ones with an 'invalid' flag | |
| const notesToSave = notes.map(note => ({ | |
| ...note, | |
| invalid: !isValidNote(note), | |
| })); | |
| localStorage.setItem(STORAGE_KEY, JSON.stringify(notesToSave)); |
Copilot
AI
Oct 14, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Multiple spelling errors in comment: 'fro' should be 'for', 'emppty' should be 'empty', and 'ans' should be 'and'.
| //Validate fro the emppty title ans empty content : Avanish | |
| // Validate for the empty title and empty content : Avanish |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inconsistent capitalization: 'non-Empty' should be 'non-empty' to match the style used elsewhere.