@@ -5,7 +5,6 @@ import { CommentData, PostData, baseUrl, getMockHandlers } from 'tanstack-query-
55import { setupMSW } from 'tanstack-query-builder-example-mocks/setup-msw' ;
66import { HttpQueryBuilder } from 'tanstack-query-builder/http' ;
77import { queryClient } from './client' ;
8- import './App.css' ;
98import './index.css' ;
109
1110await setupMSW ( ...getMockHandlers ( ) ) . start ( { onUnhandledRequest : 'bypass' , quiet : true , waitUntilReady : true } ) ;
@@ -96,46 +95,63 @@ function AppCore() {
9695
9796 return (
9897 < >
99- < button onClick = { reload } disabled = { posts . isFetching } >
100- Reload
101- </ button >
102-
103- < button onClick = { ( ) => reset . mutateAsync ( { } ) } disabled = { reset . isPending } >
104- Reset
105- </ button >
106-
107- < label >
108- < input type = "checkbox" onChange = { ( e ) => setEnablePrefetch ( e . target . checked ) } checked = { enablePrefetch } />
109- Enable prefetch
110- </ label >
111-
112- { posts . isLoading
113- ? 'Loading...'
114- : posts . isError
115- ? posts . error . message
116- : posts . data ?. pages ?. flat ( ) . map ( ( post ) => (
117- < div key = { post . id } >
118- < a >
119- < h2 onClick = { ( ) => setPostId ( post . id ) } onMouseOver = { ( ) => enablePrefetch && postQuery . client . prefetch ( { id : post . id } ) } >
120- { post . id } - { post . title }
121- </ h2 >
122- </ a >
123-
124- < button
125- onClick = { ( ) => deletePostMutation . client . mutate ( { params : { id : post . id } } ) . catch ( ( ) => { } ) }
126- disabled = { deletePostMutation . client . isMutating ( { params : { id : post . id } } ) > 0 }
98+ < div className = "p-4" >
99+ < button onClick = { reload } disabled = { posts . isFetching } className = "btn btn-primary mr-2" >
100+ Reload
101+ </ button >
102+
103+ < button onClick = { ( ) => reset . mutateAsync ( { } ) } disabled = { reset . isPending } className = "btn btn-secondary mr-2" >
104+ Reset
105+ </ button >
106+
107+ < label className = "flex items-center" >
108+ < input type = "checkbox" onChange = { ( e ) => setEnablePrefetch ( e . target . checked ) } checked = { enablePrefetch } className = "mr-2" />
109+ Enable prefetch on hover
110+ </ label >
111+ </ div >
112+
113+ { posts . isLoading ? (
114+ < div className = "text-center" > Loading...</ div >
115+ ) : posts . isError ? (
116+ < div className = "text-red-500" > { posts . error . message } </ div >
117+ ) : (
118+ posts . data ?. pages ?. flat ( ) . map ( ( post ) => (
119+ < div key = { post . id } className = "p-4 border-b flex flex-row" >
120+ < div className = "flex flex-col grow" >
121+ < a >
122+ < h2
123+ onClick = { ( ) => setPostId ( post . id ) }
124+ onMouseOver = { ( ) => {
125+ if ( ! enablePrefetch ) return ;
126+ postQuery . client . prefetch ( { id : post . id } ) ;
127+ commentsQuery . client . prefetch ( { search : { postId : post . id } } ) ;
128+ } }
129+ className = "text-xl font-bold cursor-pointer text-blue-800 hover:underline"
127130 >
128- Delete
129- </ button >
131+ { post . id } - { post . title }
132+ </ h2 >
133+ </ a >
130134
131- { deleteErrors . includes ( post . id ) && < span style = { { color : 'red' } } > Error deleting post</ span > }
135+ < p className = "mt-2 whitespace-pre-wrap" > { post . body } </ p >
136+ </ div >
132137
133- < p > { post . body } </ p >
134- </ div >
135- ) ) }
138+ < div className = "flex flex-col items-end" >
139+ < button
140+ onClick = { ( ) => deletePostMutation . client . mutate ( { params : { id : post . id } } ) . catch ( ( ) => { } ) }
141+ disabled = { deletePostMutation . client . isMutating ( { params : { id : post . id } } ) > 0 }
142+ className = "btn btn-danger mt-2"
143+ >
144+ Delete
145+ </ button >
146+
147+ { deleteErrors . includes ( post . id ) && < span className = "text-red-500 ml-4" > Error deleting post</ span > }
148+ </ div >
149+ </ div >
150+ ) )
151+ ) }
136152
137153 { posts . hasNextPage && (
138- < button onClick = { ( ) => posts . fetchNextPage ( ) } disabled = { posts . isFetchingNextPage } >
154+ < button onClick = { ( ) => posts . fetchNextPage ( ) } disabled = { posts . isFetchingNextPage } className = "btn btn-primary mt-4" >
139155 Load next page
140156 </ button >
141157 ) }
@@ -157,27 +173,29 @@ function PostPage({ postId, onBack }: { postId: number; onBack: () => void }) {
157173 { ! showEdit ? (
158174 < >
159175 { post . isLoading ? (
160- ' Loading...'
176+ < div className = "text-center" > Loading...</ div >
161177 ) : post . isError ? (
162- post . error . message
178+ < div className = "text-red-500" > { post . error . message } </ div >
163179 ) : (
164- < div >
165- < h2 > { post . data ?. titleUppercase } </ h2 >
166- < p > { post . data ?. body } </ p >
167- < button onClick = { onBack } > Back</ button >
168- < button onClick = { ( ) => setShowEdit ( true ) } disabled = { editPost . isPending } >
180+ < div className = "p-4" >
181+ < h2 className = "text-2xl font-bold" > { post . data ?. titleUppercase } </ h2 >
182+ < p className = "mt-2 whitespace-pre-wrap" > { post . data ?. body } </ p >
183+ < button onClick = { onBack } className = "btn btn-secondary mt-4 mr-2" >
184+ Back
185+ </ button >
186+ < button onClick = { ( ) => setShowEdit ( true ) } disabled = { editPost . isPending } className = "btn btn-primary mt-4" >
169187 Edit post
170188 </ button >
171189 </ div >
172190 ) }
173191 </ >
174192 ) : (
175- < >
176- < h2 > Edit post</ h2 >
193+ < div className = "p-4" >
194+ < h2 className = "text-2xl font-bold" > Edit post</ h2 >
177195
178- < input ref = { titleRef } defaultValue = { post . data ?. title } style = { { display : 'block' } } />
196+ < input ref = { titleRef } defaultValue = { post . data ?. title } className = "block w-full mt-2 p-2 border rounded" />
179197
180- < textarea ref = { bodyRef } defaultValue = { post . data ?. body } style = { { display : 'block' , width : 400 } } />
198+ < textarea ref = { bodyRef } defaultValue = { post . data ?. body } className = "block w-full mt-2 p-2 border rounded" />
181199
182200 < button
183201 onClick = { ( ) => {
@@ -193,24 +211,27 @@ function PostPage({ postId, onBack }: { postId: number; onBack: () => void }) {
193211 setShowEdit ( false ) ;
194212 } }
195213 disabled = { editPost . isPending }
214+ className = "btn btn-primary mt-4"
196215 >
197216 Save
198217 </ button >
199- </ >
218+ </ div >
200219 ) }
201220
202- < h3 > Comments</ h3 >
203-
204- { comments . isLoading
205- ? 'Loading comments...'
206- : comments . isError
207- ? comments . error . message
208- : comments . data ?. map ( ( comment ) => (
209- < div key = { comment . id } >
210- < h5 > { comment . name } </ h5 >
211- < p > { comment . body } </ p >
212- </ div >
213- ) ) }
221+ < h3 className = "text-xl font-bold m-4" > Comments</ h3 >
222+
223+ { comments . isLoading ? (
224+ < div className = "text-center" > Loading comments...</ div >
225+ ) : comments . isError ? (
226+ < div className = "text-red-500" > { comments . error . message } </ div >
227+ ) : (
228+ comments . data ?. map ( ( comment ) => (
229+ < div key = { comment . id } className = "p-4 border-b" >
230+ < h5 className = "text-lg font-bold" > { comment . name } </ h5 >
231+ < p className = "mt-2" > { comment . body } </ p >
232+ </ div >
233+ ) )
234+ ) }
214235 </ >
215236 ) ;
216237}
0 commit comments