fix: improve error messaging for various components to provide clearer feedback on failures

This commit is contained in:
Usman Baig
2026-02-22 19:17:20 +01:00
parent ac6a9429d4
commit 156d9986df
15 changed files with 25 additions and 24 deletions

View File

@@ -12,6 +12,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
- **Smoother loading experience.** Pages now show a subtle preview of the layout while data loads instead of a blank screen or spinner. This applies everywhere — dashboards, settings, uptime, funnels, notifications, billing, and detail modals.
- **No more loading flicker.** Fast-loading pages no longer flash a loading state for a split second before showing content.
- **Clearer error messages.** When something goes wrong, the error message now tells you what failed (e.g. "Failed to load uptime monitors") instead of a generic "Failed to load data".
## [0.10.0-alpha] - 2026-02-21

View File

@@ -170,7 +170,7 @@ export default function HomePage() {
const data = await listSites()
setSites(Array.isArray(data) ? data : [])
} catch (error: any) {
toast.error(getAuthErrorMessage(error) || 'Failed to load sites: ' + ((error as Error)?.message || 'Unknown error'))
toast.error(getAuthErrorMessage(error) || 'Failed to load your sites')
setSites([])
} finally {
setSitesLoading(false)
@@ -199,7 +199,7 @@ export default function HomePage() {
toast.success('Site deleted successfully')
loadSites()
} catch (error: any) {
toast.error(getAuthErrorMessage(error) || 'Failed to delete site: ' + ((error as Error)?.message || 'Unknown error'))
toast.error(getAuthErrorMessage(error) || 'Failed to delete site')
}
}

View File

@@ -166,7 +166,7 @@ export default function PublicDashboardPage() {
} else if (error.status === 404 || error.response?.status === 404) {
toast.error('Site not found')
} else if (!silent) {
toast.error(getAuthErrorMessage(error) || 'Failed to load dashboard: ' + ((error as Error)?.message || 'Unknown error'))
toast.error(getAuthErrorMessage(error) || 'Failed to load public dashboard')
}
} finally {
if (!silent) setLoading(false)

View File

@@ -64,7 +64,7 @@ export default function FunnelReportPage() {
if (status === 404) setLoadError('not_found')
else if (status === 403) setLoadError('forbidden')
else setLoadError('error')
if (status !== 404 && status !== 403) toast.error('Failed to load funnel data')
if (status !== 404 && status !== 403) toast.error('Failed to load funnel details')
} finally {
setLoading(false)
}

View File

@@ -84,7 +84,7 @@ export default function CreateFunnelPage() {
toast.success('Funnel created')
router.push(`/sites/${siteId}/funnels`)
} catch (error) {
toast.error('Failed to create funnel')
toast.error('Failed to create funnel. Please try again.')
} finally {
setSaving(false)
}

View File

@@ -21,7 +21,7 @@ export default function FunnelsPage() {
const data = await listFunnels(siteId)
setFunnels(data)
} catch (error) {
toast.error('Failed to load funnels')
toast.error('Failed to load your funnels')
} finally {
setLoading(false)
}

View File

@@ -191,7 +191,7 @@ export default function SiteDashboardPage() {
setLastUpdatedAt(Date.now())
} catch (error: unknown) {
if (!silent) {
toast.error(getAuthErrorMessage(error) || 'Failed to load data: ' + ((error as Error)?.message || 'Unknown error'))
toast.error(getAuthErrorMessage(error) || 'Failed to load dashboard analytics')
}
} finally {
if (!silent) setLoading(false)

View File

@@ -48,7 +48,7 @@ export default function RealtimePage() {
handleSelectVisitor(visitorsData[0])
}
} catch (error: unknown) {
toast.error(getAuthErrorMessage(error) || 'Failed to load data')
toast.error(getAuthErrorMessage(error) || 'Failed to load realtime visitors')
} finally {
setLoading(false)
}
@@ -85,7 +85,7 @@ export default function RealtimePage() {
const events = await getSessionDetails(siteId, visitor.session_id)
setSessionEvents(events || [])
} catch (error: unknown) {
toast.error(getAuthErrorMessage(error) || 'Failed to load session details')
toast.error(getAuthErrorMessage(error) || 'Failed to load session events')
} finally {
setLoadingEvents(false)
}

View File

@@ -152,7 +152,7 @@ export default function SiteSettingsPage() {
setIsPasswordEnabled(false)
}
} catch (error: any) {
toast.error(getAuthErrorMessage(error) || 'Failed to load site: ' + ((error as Error)?.message || 'Unknown error'))
toast.error(getAuthErrorMessage(error) || 'Failed to load site settings')
} finally {
setLoading(false)
}
@@ -266,7 +266,7 @@ export default function SiteSettingsPage() {
toast.success('Site updated successfully')
loadSite()
} catch (error: any) {
toast.error(getAuthErrorMessage(error) || 'Failed to update site: ' + ((error as Error)?.message || 'Unknown error'))
toast.error(getAuthErrorMessage(error) || 'Failed to save site settings')
} finally {
setSaving(false)
}
@@ -281,7 +281,7 @@ export default function SiteSettingsPage() {
await resetSiteData(siteId)
toast.success('All site data has been reset')
} catch (error: any) {
toast.error(getAuthErrorMessage(error) || 'Failed to reset data: ' + ((error as Error)?.message || 'Unknown error'))
toast.error(getAuthErrorMessage(error) || 'Failed to reset site data')
}
}
@@ -297,7 +297,7 @@ export default function SiteSettingsPage() {
toast.success('Site deleted successfully')
router.push('/')
} catch (error: any) {
toast.error(getAuthErrorMessage(error) || 'Failed to delete site: ' + ((error as Error)?.message || 'Unknown error'))
toast.error(getAuthErrorMessage(error) || 'Failed to delete site')
}
}

View File

@@ -615,7 +615,7 @@ export default function UptimePage() {
setSite(siteData)
setUptimeData(statusData)
} catch (error: unknown) {
toast.error(getAuthErrorMessage(error) || 'Failed to load uptime data')
toast.error(getAuthErrorMessage(error) || 'Failed to load uptime monitors')
} finally {
setLoading(false)
}

View File

@@ -87,7 +87,7 @@ export default function NewSitePage() {
sessionStorage.setItem(LAST_CREATED_SITE_KEY, JSON.stringify({ id: site.id }))
}
} catch (error: unknown) {
toast.error(getAuthErrorMessage(error) || 'Failed to create site: ' + ((error as Error)?.message || 'Unknown error'))
toast.error(getAuthErrorMessage(error) || 'Failed to create site. Please try again.')
} finally {
setLoading(false)
}

View File

@@ -162,7 +162,7 @@ function WelcomeContent() {
setStep(3)
}
} catch (err) {
toast.error(getAuthErrorMessage(err) || 'Failed to switch organization')
toast.error(getAuthErrorMessage(err) || 'Failed to switch workspace')
} finally {
setSwitchingOrgId(null)
}

View File

@@ -205,7 +205,7 @@ export default function PricingSection() {
} catch (error: any) {
console.error('Checkout error:', error)
toast.error('Failed to start checkout. Please try again.')
toast.error('Failed to start checkout — please try again')
} finally {
setLoadingPlan(null)
}

View File

@@ -248,7 +248,7 @@ export default function OrganizationSettings() {
setAuditTotal(typeof total === 'number' ? total : 0)
} catch (error) {
console.error('Failed to load audit log', error)
toast.error(getAuthErrorMessage(error as Error) || 'Failed to load audit log')
toast.error(getAuthErrorMessage(error as Error) || 'Failed to load audit log entries')
} finally {
setIsLoadingAudit(false)
}
@@ -333,7 +333,7 @@ export default function OrganizationSettings() {
const { url } = await createPortalSession()
window.location.href = url
} catch (error: any) {
toast.error(getAuthErrorMessage(error) || error.message || 'Failed to redirect to billing portal')
toast.error(getAuthErrorMessage(error) || error.message || 'Failed to open billing portal')
setIsRedirectingToPortal(false)
}
}
@@ -398,7 +398,7 @@ export default function OrganizationSettings() {
else throw new Error('No checkout URL')
}
} catch (error: any) {
toast.error(getAuthErrorMessage(error) || error.message || 'Something went wrong.')
toast.error(getAuthErrorMessage(error) || error.message || 'Failed to update member role')
} finally {
setIsChangingPlan(false)
}
@@ -484,7 +484,7 @@ export default function OrganizationSettings() {
setIsEditing(false)
loadMembers()
} catch (error: any) {
toast.error(getAuthErrorMessage(error) || error.message || 'Failed to update organization')
toast.error(getAuthErrorMessage(error) || error.message || 'Failed to save organization settings')
} finally {
setIsSaving(false)
}
@@ -1145,7 +1145,7 @@ export default function OrganizationSettings() {
toast.success('Notification settings updated')
})
.catch((err) => {
toast.error(getAuthErrorMessage(err) || 'Failed to update settings')
toast.error(getAuthErrorMessage(err) || 'Failed to save notification preferences')
setNotificationSettings(prev)
})
.finally(() => setIsSavingNotificationSettings(false))

View File

@@ -405,8 +405,8 @@ toast.success('Site created successfully')
**Error Toast:**
```tsx
toast.error('Failed to load data')
// Red toast with X icon
toast.error('Failed to load uptime monitors')
// Red toast with X icon — always mention what failed
```
**Error Display:**