77} from '@tanstack/react-table' ;
88import { Card , CardHeader , CardTitle , CardDescription , CardContent } from '../components/ui/card' ;
99import { Button } from '../components/ui/button' ;
10- import { fetchGitHubRepositories , submitRepositories } from '../lib/api' ;
10+ import { fetchGitHubRepositories , submitRepositories , ApiError } from '../lib/api' ;
1111import { useToast } from '../components/ui/use-toast' ;
1212import { RepositoryTable } from '../components/RepositoryTable' ;
1313
@@ -33,6 +33,66 @@ export default function OnboardingPage(): React.ReactElement {
3333 enabled : true , // Fetch automatically when component mounts
3434 } ) ;
3535
36+ // Get appropriate error message based on error details
37+ const getErrorMessage = ( ) : { title : string ; message : string ; action : string } => {
38+ // Safely cast error to ApiError, ensuring it's actually an ApiError type
39+ if ( ! error ) {
40+ return {
41+ title : 'Unknown Error' ,
42+ message : 'An unexpected error occurred.' ,
43+ action : 'Please try refreshing the page.'
44+ } ;
45+ }
46+
47+ // Check if error is an ApiError by checking for the isAxiosError property
48+ const apiError = error as unknown as ApiError ;
49+ const isApiError = apiError && 'isAxiosError' in apiError ;
50+
51+ // If it's not an ApiError, provide a default error message
52+ if ( ! isApiError ) {
53+ return {
54+ title : 'Error Fetching Repositories' ,
55+ message : error instanceof Error ? error . message : 'Unknown error occurred' ,
56+ action : 'Please try refreshing the page.'
57+ } ;
58+ }
59+
60+ const statusCode = apiError . statusCode ;
61+ const errorMessage = apiError . message || 'Unknown error occurred' ;
62+
63+ // Default error info
64+ let title = 'Error Fetching Repositories' ;
65+ let message = 'We encountered an issue while trying to fetch your repositories.' ;
66+ let action = 'Please try refreshing the page.' ;
67+
68+ // Handle specific error cases
69+ if ( statusCode === 404 ) {
70+ title = 'GitHub Credentials Missing' ;
71+ message = 'We couldn\'t find your GitHub credentials in our system.' ;
72+ action = 'Please set up your GitHub token first.' ;
73+ } else if ( statusCode === 401 || ( errorMessage && errorMessage . includes ( 'token' ) ) ) {
74+ title = 'Authentication Error' ;
75+ message = 'Your GitHub token may have expired or doesn\'t have the necessary permissions.' ;
76+ action = 'Please update your GitHub toke from settings page with appropriate permissions.' ;
77+ } else if ( statusCode === 500 ) {
78+ if ( errorMessage . includes ( 'decryption' ) ) {
79+ title = 'Token Decryption Error' ;
80+ message = 'We had trouble decrypting your GitHub token.' ;
81+ action = 'Please try setting up your token again.' ;
82+ } else if ( errorMessage . includes ( 'GitHub API error' ) ) {
83+ title = 'GitHub API Error' ;
84+ message = 'GitHub API returned an error while fetching your repositories.' ;
85+ action = 'Please check your GitHub account status and try again later.' ;
86+ } else if ( errorMessage . includes ( 'Database error' ) ) {
87+ title = 'System Error' ;
88+ message = 'We encountered a database issue while accessing your credentials.' ;
89+ action = 'Please try again later. If the problem persists, contact support.' ;
90+ }
91+ }
92+
93+ return { title, message, action } ;
94+ } ;
95+
3696 // Function to handle submitting selected repositories
3797 const handleSubmitSelections = async ( ) : Promise < void > => {
3898 try {
@@ -68,6 +128,18 @@ export default function OnboardingPage(): React.ReactElement {
68128 }
69129 } ;
70130
131+ // Route to token setup page
132+ const goToTokenSetup = ( ) : void => {
133+ window . location . href = '/setup' ;
134+ } ;
135+
136+ // Function to safely check if an error is an ApiError with the specified status
137+ const isApiErrorWithStatus = ( statusCode : number ) : boolean => {
138+ if ( ! error ) return false ;
139+ const apiError = error as unknown as ApiError ;
140+ return 'isAxiosError' in apiError && apiError . statusCode === statusCode ;
141+ } ;
142+
71143 return (
72144 < div className = "container mx-auto py-8" >
73145 < h1 className = "text-3xl font-bold tracking-tight mb-6" > GitHub Repository Selection</ h1 >
@@ -90,11 +162,35 @@ export default function OnboardingPage(): React.ReactElement {
90162
91163 { error && (
92164 < div className = "bg-destructive/10 border-l-4 border-destructive p-4 mb-4 rounded" >
93- < div className = "flex" >
165+ < div className = "flex flex-col " >
94166 < div className = "ml-3" >
95- < p className = "text-sm text-destructive" >
96- Failed to fetch repositories. Please try refreshing the page.
167+ < h3 className = "text-sm font-medium text-destructive" >
168+ { getErrorMessage ( ) . title }
169+ </ h3 >
170+ < p className = "text-sm text-destructive/90 mt-1" >
171+ { getErrorMessage ( ) . message }
172+ </ p >
173+ < p className = "text-sm text-destructive/80 mt-2" >
174+ { getErrorMessage ( ) . action }
97175 </ p >
176+ < div className = "mt-3 flex flex-row gap-2" >
177+ < Button
178+ variant = "outline"
179+ onClick = { ( ) => refetch ( ) }
180+ size = "sm"
181+ >
182+ Try Again
183+ </ Button >
184+ { isApiErrorWithStatus ( 404 ) && (
185+ < Button
186+ variant = "default"
187+ onClick = { goToTokenSetup }
188+ size = "sm"
189+ >
190+ Set Up GitHub Token
191+ </ Button >
192+ ) }
193+ </ div >
98194 </ div >
99195 </ div >
100196 </ div >
@@ -134,13 +230,22 @@ export default function OnboardingPage(): React.ReactElement {
134230 < p className = "text-sm text-amber-700" >
135231 No repositories found. This could be because your GitHub token doesn't have the necessary permissions.
136232 </ p >
137- < Button
138- variant = "ghost"
139- onClick = { ( ) => refetch ( ) }
140- className = "mt-2"
141- >
142- Try refreshing
143- </ Button >
233+ < div className = "mt-2 flex gap-2" >
234+ < Button
235+ variant = "ghost"
236+ onClick = { ( ) => refetch ( ) }
237+ size = "sm"
238+ >
239+ Try refreshing
240+ </ Button >
241+ < Button
242+ variant = "outline"
243+ onClick = { goToTokenSetup }
244+ size = "sm"
245+ >
246+ Update GitHub Token
247+ </ Button >
248+ </ div >
144249 </ div >
145250 </ div >
146251 </ div >
0 commit comments