diff --git a/src/components/NoteEditor.tsx b/src/components/NoteEditor.tsx
index 76b24df..d660248 100644
--- a/src/components/NoteEditor.tsx
+++ b/src/components/NoteEditor.tsx
@@ -1,82 +1,14 @@
import { useState } from 'react'
-import type { NoteEditorProps, NoteFormProps } from '../interfaces/note-editor'
+import type { NoteEditorProps } from '../interfaces/note-editor'
import { isTitleValid, normalizeTitle } from '../lib/noteValidation'
-import DeleteModal from './DeleteModal'
-
-const TITLE_REQUIRED_MESSAGE = 'Le titre est obligatoire.'
-
-function NoteForm({
- title,
- content,
- titleMissing,
- cancelLabel,
- onTitleChange,
- onContentChange,
- onCancel,
- onSubmit,
-}: NoteFormProps) {
- return (
-
- )
-}
+import NoteForm from './NoteForm'
+import NoteReadView from './NoteReadView'
function NoteEditor(props: NoteEditorProps) {
const [editing, setEditing] = useState(props.mode === 'create')
const [title, setTitle] = useState(props.mode === 'edit' ? props.note.title : '')
const [content, setContent] = useState(props.mode === 'edit' ? props.note.content : '')
const [titleMissing, setTitleMissing] = useState(false)
- const [confirmDelete, setConfirmDelete] = useState(false)
const handleTitleChange = (value: string) => {
setTitle(value)
@@ -114,45 +46,16 @@ function NoteEditor(props: NoteEditorProps) {
const { note } = props
return (
-
-
-
{note.title || 'Sans titre'}
-
-
-
- {note.content || Note vide}
-
-
-
-
- {
- setConfirmDelete(false)
- props.onDelete(note.id)
- }}
- onCancel={() => setConfirmDelete(false)}
- />
-
+ {
+ setTitle(note.title)
+ setContent(note.content)
+ setEditing(true)
+ }}
+ onDelete={props.onDelete}
+ />
)
}
-export default NoteEditor
+export default NoteEditor
\ No newline at end of file
diff --git a/src/components/NoteForm.tsx b/src/components/NoteForm.tsx
new file mode 100644
index 0000000..9d93e23
--- /dev/null
+++ b/src/components/NoteForm.tsx
@@ -0,0 +1,71 @@
+import type { NoteFormProps } from '../interfaces/note-editor'
+
+const TITLE_REQUIRED_MESSAGE = 'Le titre est obligatoire.'
+
+function NoteForm({
+ title,
+ content,
+ titleMissing,
+ cancelLabel,
+ onTitleChange,
+ onContentChange,
+ onCancel,
+ onSubmit,
+}: NoteFormProps) {
+ return (
+
+ )
+}
+
+export default NoteForm
\ No newline at end of file
diff --git a/src/components/NoteReadView.test.tsx b/src/components/NoteReadView.test.tsx
new file mode 100644
index 0000000..df8b738
--- /dev/null
+++ b/src/components/NoteReadView.test.tsx
@@ -0,0 +1,59 @@
+import { fireEvent, render, screen } from '@testing-library/react'
+import { describe, expect, it, vi } from 'vitest'
+import NoteReadView from './NoteReadView'
+import type { Note } from '../types/note'
+
+const note: Note = { id: 42, title: 'Courses', content: 'Lait\nOeufs' }
+
+const renderView = (overrides: Partial = {}) => {
+ const onEdit = vi.fn()
+ const onDelete = vi.fn()
+ render(
+ ,
+ )
+ return { onEdit, onDelete }
+}
+
+describe('NoteReadView', () => {
+ it('displays the note title and content', () => {
+ renderView()
+
+ expect(screen.getByText('Courses')).toBeInTheDocument()
+ expect(screen.getByText('Lait Oeufs')).toBeInTheDocument()
+ expect(screen.getByRole('button', { name: 'Éditer' })).toBeInTheDocument()
+ })
+
+ it('shows placeholders for a note without title or content', () => {
+ renderView({ title: '', content: '' })
+
+ expect(screen.getByText('Sans titre')).toBeInTheDocument()
+ expect(screen.getByText('Note vide')).toBeInTheDocument()
+ })
+
+ it('calls onEdit when Éditer is clicked', () => {
+ const { onEdit } = renderView()
+
+ fireEvent.click(screen.getByRole('button', { name: 'Éditer' }))
+
+ expect(onEdit).toHaveBeenCalled()
+ })
+
+ it('deletes the note after confirmation', () => {
+ const { onDelete } = renderView()
+
+ fireEvent.click(screen.getByRole('button', { name: 'Supprimer la note' }))
+ fireEvent.click(screen.getByRole('button', { name: 'Supprimer' }))
+
+ expect(onDelete).toHaveBeenCalledWith(42)
+ expect(screen.queryByRole('dialog')).not.toBeInTheDocument()
+ })
+
+ it('does not delete when the confirmation is cancelled', () => {
+ const { onDelete } = renderView()
+
+ fireEvent.click(screen.getByRole('button', { name: 'Supprimer la note' }))
+ fireEvent.click(screen.getByRole('button', { name: 'Annuler' }))
+
+ expect(onDelete).not.toHaveBeenCalled()
+ })
+})
\ No newline at end of file
diff --git a/src/components/NoteReadView.tsx b/src/components/NoteReadView.tsx
new file mode 100644
index 0000000..6d1d1cc
--- /dev/null
+++ b/src/components/NoteReadView.tsx
@@ -0,0 +1,46 @@
+import { useState } from 'react'
+import type { NoteReadViewProps } from '../interfaces/note-editor'
+import DeleteModal from './DeleteModal'
+
+function NoteReadView({ note, onEdit, onDelete }: NoteReadViewProps) {
+ const [confirmDelete, setConfirmDelete] = useState(false)
+
+ return (
+
+
+
{note.title || 'Sans titre'}
+
+
+
+ {note.content || Note vide}
+
+
+
+
+ {
+ setConfirmDelete(false)
+ onDelete(note.id)
+ }}
+ onCancel={() => setConfirmDelete(false)}
+ />
+
+ )
+}
+
+export default NoteReadView
\ No newline at end of file
diff --git a/src/interfaces/note-editor.ts b/src/interfaces/note-editor.ts
index 56e64e0..9f9260b 100644
--- a/src/interfaces/note-editor.ts
+++ b/src/interfaces/note-editor.ts
@@ -17,6 +17,12 @@ export interface CreateNoteEditorProps {
export type NoteEditorProps = EditNoteEditorProps | CreateNoteEditorProps
+export interface NoteReadViewProps {
+ note: Note
+ onEdit: () => void
+ onDelete: (id: number) => void
+}
+
export interface NoteFormProps {
title: string
content: string