fix: improve error messaging for various components to provide clearer feedback on failures
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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:**
|
||||
|
||||
Reference in New Issue
Block a user