11'use client'
2+ import React from 'react'
23import { VoloCmsKitContentsPageDto } from '@/client'
34import { PageView } from '@/components/page/PageView'
45import { Button } from '@/components/ui/button'
6+ import { Card , CardContent , CardDescription , CardHeader , CardTitle } from '@/components/ui/card'
7+ import { Alert , AlertDescription } from '@/components/ui/alert'
58import Error from '@/components/ui/Error'
69import Loader from '@/components/ui/Loader'
710import { usePageBySlug } from '@/lib/hooks/usePages'
11+ import { AlertTriangle , Home , RefreshCw , Search } from 'lucide-react'
812import Link from 'next/link'
9- import { useParams } from 'next/navigation'
13+ import { useParams , useRouter } from 'next/navigation'
14+ import { useEffect , useState } from 'react'
1015
1116export default function PageViewPage ( ) {
1217 const params = useParams ( )
18+ const router = useRouter ( )
1319 const slug = params . slug as string
20+ const [ retryCount , setRetryCount ] = useState ( 0 )
1421
15- const { data : page , isLoading, isError } = usePageBySlug ( slug )
22+ const {
23+ data : page ,
24+ isLoading,
25+ isError,
26+ error,
27+ refetch
28+ } = usePageBySlug ( slug )
1629
17- if ( isLoading ) return < Loader />
18- if ( isError ) return < Error />
30+ // Handle retry logic
31+ const handleRetry = ( ) => {
32+ setRetryCount ( prev => prev + 1 )
33+ refetch ( )
34+ }
1935
20- if ( ! page ) {
36+ // Reset retry count when slug changes
37+ useEffect ( ( ) => {
38+ setRetryCount ( 0 )
39+ } , [ slug ] )
40+
41+ // Loading state with better UX
42+ if ( isLoading ) {
2143 return (
22- < div className = "container mx-auto p-4" >
23- < div className = "text-center py-8" >
24- < h1 className = "text-2xl font-bold mb-4" > Page Not Found</ h1 >
25- < p className = "text-muted-foreground mb-4" >
26- The page with slug "{ slug } " could not be found.
27- </ p >
28- < div className = "flex gap-2 justify-center" >
29- < Link href = "/" >
30- < Button variant = "outline" > Back to Home</ Button >
31- </ Link >
32- </ div >
44+ < div className = "min-h-screen bg-background flex items-center justify-center" >
45+ < div className = "text-center space-y-4" >
46+ < Loader />
47+ < p className = "text-muted-foreground" > Loading page...</ p >
48+ </ div >
49+ </ div >
50+ )
51+ }
52+
53+ // Handle different types of errors gracefully
54+ if ( isError ) {
55+ const errorMessage = error && typeof error === 'object' && 'message' in error
56+ ? String ( error . message )
57+ : 'An unexpected error occurred'
58+
59+ // Network or server errors
60+ if ( errorMessage . includes ( 'fetch' ) || errorMessage . includes ( 'network' ) || errorMessage . includes ( 'timeout' ) ) {
61+ return (
62+ < div className = "min-h-screen bg-background flex items-center justify-center p-4" >
63+ < Card className = "w-full max-w-md" >
64+ < CardHeader className = "text-center" >
65+ < div className = "mx-auto mb-4 flex h-12 w-12 items-center justify-center rounded-full bg-orange-100" >
66+ < AlertTriangle className = "h-6 w-6 text-orange-600" />
67+ </ div >
68+ < CardTitle > Connection Error</ CardTitle >
69+ < CardDescription >
70+ We're having trouble connecting to our servers. This might be a temporary issue.
71+ </ CardDescription >
72+ </ CardHeader >
73+ < CardContent className = "space-y-4" >
74+ < Alert >
75+ < AlertTriangle className = "h-4 w-4" />
76+ < AlertDescription >
77+ { retryCount > 0
78+ ? `Attempt ${ retryCount + 1 } failed. Please try again.`
79+ : 'Please check your internet connection and try again.'
80+ }
81+ </ AlertDescription >
82+ </ Alert >
83+ < div className = "flex gap-2" >
84+ < Button onClick = { handleRetry } className = "flex-1" >
85+ < RefreshCw className = "mr-2 h-4 w-4" />
86+ Try Again
87+ </ Button >
88+ < Button variant = "outline" onClick = { ( ) => router . push ( '/' ) } >
89+ < Home className = "mr-2 h-4 w-4" />
90+ Go Home
91+ </ Button >
92+ </ div >
93+ </ CardContent >
94+ </ Card >
95+ </ div >
96+ )
97+ }
98+
99+ // 404 or page not found errors
100+ if ( errorMessage . includes ( 'not found' ) || errorMessage . includes ( '404' ) ) {
101+ return (
102+ < div className = "min-h-screen bg-background flex items-center justify-center p-4" >
103+ < Card className = "w-full max-w-md" >
104+ < CardHeader className = "text-center" >
105+ < div className = "mx-auto mb-4 flex h-12 w-12 items-center justify-center rounded-full bg-blue-100" >
106+ < Search className = "h-6 w-6 text-blue-600" />
107+ </ div >
108+ < CardTitle > Page Not Found</ CardTitle >
109+ < CardDescription >
110+ The page you're looking for doesn't exist or may have been moved.
111+ </ CardDescription >
112+ </ CardHeader >
113+ < CardContent className = "space-y-4" >
114+ < div className = "text-sm text-muted-foreground" >
115+ < p > Slug: < code className = "bg-muted px-1 rounded" > { slug } </ code > </ p >
116+ </ div >
117+ < div className = "flex gap-2" >
118+ < Button asChild className = "flex-1" >
119+ < Link href = "/" >
120+ < Home className = "mr-2 h-4 w-4" />
121+ Go Home
122+ </ Link >
123+ </ Button >
124+ < Button variant = "outline" onClick = { ( ) => router . back ( ) } >
125+ Go Back
126+ </ Button >
127+ </ div >
128+ </ CardContent >
129+ </ Card >
33130 </ div >
131+ )
132+ }
133+
134+ // Generic error fallback
135+ return (
136+ < div className = "min-h-screen bg-background flex items-center justify-center p-4" >
137+ < Card className = "w-full max-w-md" >
138+ < CardHeader className = "text-center" >
139+ < div className = "mx-auto mb-4 flex h-12 w-12 items-center justify-center rounded-full bg-red-100" >
140+ < AlertTriangle className = "h-6 w-6 text-red-600" />
141+ </ div >
142+ < CardTitle > Something Went Wrong</ CardTitle >
143+ < CardDescription >
144+ We encountered an unexpected error while loading this page.
145+ </ CardDescription >
146+ </ CardHeader >
147+ < CardContent className = "space-y-4" >
148+ < Alert >
149+ < AlertTriangle className = "h-4 w-4" />
150+ < AlertDescription >
151+ { errorMessage }
152+ </ AlertDescription >
153+ </ Alert >
154+ < div className = "flex gap-2" >
155+ < Button onClick = { handleRetry } className = "flex-1" >
156+ < RefreshCw className = "mr-2 h-4 w-4" />
157+ Try Again
158+ </ Button >
159+ < Button variant = "outline" asChild >
160+ < Link href = "/" >
161+ < Home className = "mr-2 h-4 w-4" />
162+ Go Home
163+ </ Link >
164+ </ Button >
165+ </ div >
166+ </ CardContent >
167+ </ Card >
34168 </ div >
35169 )
36170 }
37171
38- return < PageView page = { page as VoloCmsKitContentsPageDto } />
172+ // Handle case where page data is null/undefined
173+ if ( ! page ) {
174+ return (
175+ < div className = "min-h-screen bg-background flex items-center justify-center p-4" >
176+ < Card className = "w-full max-w-md" >
177+ < CardHeader className = "text-center" >
178+ < div className = "mx-auto mb-4 flex h-12 w-12 items-center justify-center rounded-full bg-gray-100" >
179+ < Search className = "h-6 w-6 text-gray-600" />
180+ </ div >
181+ < CardTitle > Page Not Available</ CardTitle >
182+ < CardDescription >
183+ This page exists but is currently not available for viewing.
184+ </ CardDescription >
185+ </ CardHeader >
186+ < CardContent className = "space-y-4" >
187+ < div className = "flex gap-2" >
188+ < Button asChild className = "flex-1" >
189+ < Link href = "/" >
190+ < Home className = "mr-2 h-4 w-4" />
191+ Go Home
192+ </ Link >
193+ </ Button >
194+ < Button variant = "outline" onClick = { ( ) => router . back ( ) } >
195+ Go Back
196+ </ Button >
197+ </ div >
198+ </ CardContent >
199+ </ Card >
200+ </ div >
201+ )
202+ }
203+
204+ // Render the page with error boundary
205+ return (
206+ < ErrorBoundary fallback = { < Error /> } >
207+ < PageView page = { page as VoloCmsKitContentsPageDto } />
208+ </ ErrorBoundary >
209+ )
210+ }
211+
212+ // Error Boundary Component
213+ class ErrorBoundary extends React . Component <
214+ { children : React . ReactNode ; fallback : React . ReactNode } ,
215+ { hasError : boolean ; error ?: Error }
216+ > {
217+ constructor ( props : { children : React . ReactNode ; fallback : React . ReactNode } ) {
218+ super ( props )
219+ this . state = { hasError : false }
220+ }
221+
222+ static getDerivedStateFromError ( error : unknown ) {
223+ const errorObj = error && typeof error === 'object' && 'message' in error
224+ ? error as Error
225+ : { message : String ( error ) , name : 'Error' } as Error
226+ return { hasError : true , error : errorObj }
227+ }
228+
229+ componentDidCatch ( error : unknown , errorInfo : React . ErrorInfo ) {
230+ console . error ( 'PageView Error Boundary caught an error:' , error , errorInfo )
231+ }
232+
233+ render ( ) {
234+ if ( this . state . hasError ) {
235+ return this . props . fallback
236+ }
237+
238+ return this . props . children
239+ }
39240}
0 commit comments