11import { router } from '@inertiajs/react'
22import { useEffect , useState } from 'react'
3+ import { toast } from 'sonner'
34import {
45 Accordion ,
56 AccordionContent ,
@@ -124,6 +125,7 @@ function ComponentShowcase({
124125}
125126
126127const Demo = ( ) => {
128+ const [ fetching , setFetching ] = useState ( false )
127129 const [ sliderValue , setSliderValue ] = useState ( [ 50 ] )
128130 const [ switchChecked , setSwitchChecked ] = useState ( false )
129131 const [ selectValue , setSelectValue ] = useState ( '' )
@@ -134,6 +136,28 @@ const Demo = () => {
134136 const [ dialogOpen , setDialogOpen ] = useState ( false )
135137 const [ alertDialogOpen , setAlertDialogOpen ] = useState ( false )
136138
139+ const handleClientFetch = async ( ) => {
140+ setFetching ( true )
141+ try {
142+ const csrfToken =
143+ document . querySelector < HTMLMetaElement > ( 'meta[name="csrf-token"]' ) ?. content ?? ''
144+ const res = await fetch ( '/demo/fetch' , {
145+ method : 'POST' ,
146+ headers : { 'X-CSRF-Token' : csrfToken , 'Content-Type' : 'application/json' } ,
147+ } )
148+ const data = await res . json ( )
149+ if ( res . ok ) {
150+ toast . success ( data . message )
151+ } else {
152+ toast . error ( data . message )
153+ }
154+ } catch {
155+ toast . error ( 'Network error' )
156+ } finally {
157+ setFetching ( false )
158+ }
159+ }
160+
137161 useEffect ( ( ) => {
138162 if ( switchChecked ) {
139163 document . documentElement . classList . add ( 'dark' )
@@ -153,17 +177,31 @@ const Demo = () => {
153177 </ div >
154178 </ div >
155179
156- < Card >
157- < CardHeader >
158- < CardTitle className = "text-base" > Flash Messages Test</ CardTitle >
159- < CardDescription > Click buttons to trigger flash messages via Inertia</ CardDescription >
160- </ CardHeader >
161- < CardContent className = "flex flex-wrap gap-2" >
162- < Button variant = "default" onClick = { ( ) => router . post ( '/demo' ) } >
163- Trigger POST Toast
164- </ Button >
165- </ CardContent >
166- </ Card >
180+ < div className = "grid gap-4 sm:grid-cols-2" >
181+ < Card >
182+ < CardHeader >
183+ < CardTitle className = "text-base" > Flash Messages Test</ CardTitle >
184+ < CardDescription > Click buttons to trigger flash messages via Inertia</ CardDescription >
185+ </ CardHeader >
186+ < CardContent className = "flex flex-wrap gap-2" >
187+ < Button variant = "default" onClick = { ( ) => router . post ( '/demo' ) } >
188+ Trigger POST Toast
189+ </ Button >
190+ </ CardContent >
191+ </ Card >
192+
193+ < Card >
194+ < CardHeader >
195+ < CardTitle className = "text-base" > Client Fetch Demo</ CardTitle >
196+ < CardDescription > Uses raw fetch() — 50% success, 50% error</ CardDescription >
197+ </ CardHeader >
198+ < CardContent className = "flex flex-wrap gap-2" >
199+ < Button variant = "outline" onClick = { handleClientFetch } disabled = { fetching } >
200+ { fetching ? 'Sending…' : 'Send Fetch Request' }
201+ </ Button >
202+ </ CardContent >
203+ </ Card >
204+ </ div >
167205
168206 < Tabs value = { tabsValue } onValueChange = { setTabsValue } >
169207 < TabsList >
0 commit comments