feat(frontend): improve error handling and UX - Sprint 3 Story 4
Add comprehensive error handling with Error Boundary and improve user feedback. Changes: - Created global ErrorBoundary component with fallback UI using react-error-boundary - Integrated ErrorBoundary in root layout to catch all errors - Created Loading component with variants (sm, md, lg) for consistent loading states - Created EmptyState component for better empty data display with CTAs - Improved form error messages in login and register pages (consistent destructive styling) - Updated projects page to use EmptyState component - Added better error handling with retry actions UX improvements: - Better error messages and recovery options with clear action buttons - Consistent loading indicators across all pages - Helpful empty states with clear descriptions and CTAs - Graceful error handling without crashes - Consistent destructive color theme for all error messages Technical: - Installed react-error-boundary package (v5) - All TypeScript types are properly defined - Build and type checking pass successfully 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -56,9 +56,9 @@ function LoginContent() {
|
||||
)}
|
||||
|
||||
{error && (
|
||||
<div className="rounded bg-red-50 p-3 text-sm text-red-600">
|
||||
<div className="rounded-md bg-destructive/10 border border-destructive/20 p-3 text-sm text-destructive">
|
||||
{(error as { response?: { data?: { message?: string } } })
|
||||
?.response?.data?.message || 'Login failed. Please try again.'}
|
||||
?.response?.data?.message || 'Login failed. Please check your credentials and try again.'}
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -72,7 +72,7 @@ function LoginContent() {
|
||||
placeholder="your-company"
|
||||
/>
|
||||
{errors.tenantSlug && (
|
||||
<p className="mt-1 text-sm text-red-600">{errors.tenantSlug.message}</p>
|
||||
<p className="mt-1 text-sm text-destructive">{errors.tenantSlug.message}</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -86,7 +86,7 @@ function LoginContent() {
|
||||
placeholder="you@example.com"
|
||||
/>
|
||||
{errors.email && (
|
||||
<p className="mt-1 text-sm text-red-600">{errors.email.message}</p>
|
||||
<p className="mt-1 text-sm text-destructive">{errors.email.message}</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -100,7 +100,7 @@ function LoginContent() {
|
||||
placeholder="••••••••"
|
||||
/>
|
||||
{errors.password && (
|
||||
<p className="mt-1 text-sm text-red-600">
|
||||
<p className="mt-1 text-sm text-destructive">
|
||||
{errors.password.message}
|
||||
</p>
|
||||
)}
|
||||
|
||||
@@ -54,10 +54,10 @@ export default function RegisterPage() {
|
||||
className="mt-8 space-y-6 rounded-lg bg-white p-8 shadow"
|
||||
>
|
||||
{error && (
|
||||
<div className="rounded bg-red-50 p-3 text-sm text-red-600">
|
||||
<div className="rounded-md bg-destructive/10 border border-destructive/20 p-3 text-sm text-destructive">
|
||||
{(error as { response?: { data?: { message?: string } } })
|
||||
?.response?.data?.message ||
|
||||
'Registration failed. Please try again.'}
|
||||
'Registration failed. Please check your information and try again.'}
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -71,7 +71,7 @@ export default function RegisterPage() {
|
||||
placeholder="John Doe"
|
||||
/>
|
||||
{errors.fullName && (
|
||||
<p className="mt-1 text-sm text-red-600">
|
||||
<p className="mt-1 text-sm text-destructive">
|
||||
{errors.fullName.message}
|
||||
</p>
|
||||
)}
|
||||
@@ -87,7 +87,7 @@ export default function RegisterPage() {
|
||||
placeholder="you@example.com"
|
||||
/>
|
||||
{errors.email && (
|
||||
<p className="mt-1 text-sm text-red-600">{errors.email.message}</p>
|
||||
<p className="mt-1 text-sm text-destructive">{errors.email.message}</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -101,7 +101,7 @@ export default function RegisterPage() {
|
||||
placeholder="••••••••"
|
||||
/>
|
||||
{errors.password && (
|
||||
<p className="mt-1 text-sm text-red-600">
|
||||
<p className="mt-1 text-sm text-destructive">
|
||||
{errors.password.message}
|
||||
</p>
|
||||
)}
|
||||
@@ -120,7 +120,7 @@ export default function RegisterPage() {
|
||||
placeholder="Acme Inc."
|
||||
/>
|
||||
{errors.tenantName && (
|
||||
<p className="mt-1 text-sm text-red-600">
|
||||
<p className="mt-1 text-sm text-destructive">
|
||||
{errors.tenantName.message}
|
||||
</p>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user