1
+ import type { ActionFunctionArgs , LoaderFunctionArgs } from "@remix-run/node" ;
2
+ import { json , redirect } from "@remix-run/node" ;
3
+ import { Form , useActionData , useLoaderData , useNavigate } from "@remix-run/react" ;
4
+ import invariant from "tiny-invariant" ;
5
+
6
+ import { updateNote , getNote } from "~/models/note.server" ;
7
+ import { requireUserId } from "~/session.server" ;
8
+
9
+ export const loader = async ( { params, request } : LoaderFunctionArgs ) => {
10
+ const userId = await requireUserId ( request ) ;
11
+ invariant ( params . noteId , "noteId not found" ) ;
12
+
13
+ console . log ( 'Loading note - noteId:' , params . noteId , 'userId:' , userId ) ;
14
+
15
+ const note = await getNote ( { id : params . noteId , userId } ) ;
16
+ if ( ! note ) {
17
+ throw new Response ( "Not Found" , { status : 404 } ) ;
18
+ }
19
+ return json ( { note } ) ;
20
+ } ;
21
+
22
+ export const action = async ( { params, request } : ActionFunctionArgs ) => {
23
+ const userId = await requireUserId ( request ) ;
24
+ invariant ( params . noteId , "noteId not found" ) ;
25
+ invariant ( typeof params . noteId === "string" , "noteId must be a string" ) ;
26
+
27
+ const formData = await request . formData ( ) ;
28
+ const title = formData . get ( "title" ) as string ;
29
+ const body = formData . get ( "body" ) as string ;
30
+
31
+ if ( ! title || title . length === 0 ) {
32
+ return json ( { errors : { title : "Title is required" } } , { status : 400 } ) ;
33
+ }
34
+
35
+ if ( ! body || body . length === 0 ) {
36
+ return json ( { errors : { body : "Body is required" } } , { status : 400 } ) ;
37
+ }
38
+
39
+ console . log ( "Action: Updating note with id:" , params . noteId , "title:" , title , "body:" , body , "userId:" , userId ) ;
40
+
41
+ try {
42
+ await updateNote ( {
43
+ id : params . noteId ,
44
+ title,
45
+ body,
46
+ userId,
47
+ } ) ;
48
+ return redirect ( `/notes/${ params . noteId } ` ) ;
49
+ } catch ( error ) {
50
+ console . error ( "Action Error: Failed to update note:" , error ) ;
51
+ return json (
52
+ { errors : { server : "Failed to update note. Please try again." } } ,
53
+ { status : 500 }
54
+ ) ;
55
+ }
56
+ } ;
57
+
58
+ export default function NoteEditPage ( ) {
59
+ const { note } = useLoaderData < typeof loader > ( ) ;
60
+ const actionData = useActionData < typeof action > ( ) ;
61
+ const navigate = useNavigate ( ) ;
62
+
63
+ console . log ( "Rendering NoteEditPage with note:" , note ) ;
64
+
65
+ return (
66
+ < div className = "flex-1 p-6 bg-gray-100 min-h-screen" >
67
+ < h1 className = "text-3xl font-bold mb-6 text-gray-800" > Edit Note</ h1 >
68
+ { actionData ?. errors && (
69
+ < div className = "mb-4 p-4 bg-red-100 text-red-700 rounded-lg" >
70
+ { Object . entries ( actionData . errors ) . map ( ( [ key , value ] ) => (
71
+ < p key = { key } > { value } </ p >
72
+ ) ) }
73
+ </ div >
74
+ ) }
75
+ < Form method = "post" onSubmit = { ( e ) => {
76
+ console . log ( "Form submitted with data:" , new FormData ( e . currentTarget ) ) ;
77
+ } } className = "space-y-6 max-w-2xl bg-white p-6 rounded-lg shadow-md" >
78
+ < div >
79
+ < label htmlFor = "title" className = "block text-lg font-medium text-gray-700 mb-2" >
80
+ Title
81
+ </ label >
82
+ < input
83
+ type = "text"
84
+ id = "title"
85
+ name = "title"
86
+ defaultValue = { note . title }
87
+ required
88
+ className = "mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50 p-2"
89
+ />
90
+ </ div >
91
+
92
+ < div >
93
+ < label htmlFor = "body" className = "block text-lg font-medium text-gray-700 mb-2" >
94
+ Body
95
+ </ label >
96
+ < textarea
97
+ id = "body"
98
+ name = "body"
99
+ defaultValue = { note . body }
100
+ required
101
+ rows = { 6 }
102
+ className = "mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50 p-2"
103
+ />
104
+ </ div >
105
+
106
+ < div className = "flex space-x-4" >
107
+ < button
108
+ type = "submit"
109
+ className = "w-full py-3 px-6 bg-blue-600 text-white rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition duration-300"
110
+ >
111
+ Update Note
112
+ </ button >
113
+ < button
114
+ type = "button"
115
+ onClick = { ( ) => navigate ( - 1 ) }
116
+ className = "w-full py-3 px-6 bg-gray-500 text-white rounded-md hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500 transition duration-300"
117
+ >
118
+ Cancel
119
+ </ button >
120
+ </ div >
121
+ </ Form >
122
+ </ div >
123
+ ) ;
124
+ }
0 commit comments