feat: user friendly errors - #58
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughThis PR adds CodeRabbit review rules, a localized route error page, a global error page, a toast notification system, related i18n strings, and test coverage for the new error and toast UI. ChangesCodeRabbit Review Configuration
User-friendly Error & Toast System
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant Component
participant useToast
participant ToastProvider
participant Toast
Component->>useToast: showToast(message, severity)
useToast->>ToastProvider: update state
ToastProvider->>Toast: render toast
Toast-->>ToastProvider: close or timeout
ToastProvider->>ToastProvider: dismiss toast
sequenceDiagram
participant NextRuntime
participant ErrorPage
participant GlobalError
participant User
NextRuntime->>ErrorPage: pass route error
ErrorPage-->>User: render localized retry UI
NextRuntime->>GlobalError: pass fatal error
GlobalError-->>User: render full-page retry UI
User->>ErrorPage: retry
User->>GlobalError: retry
Related issues: Suggested labels: enhancement, feature, i18n Suggested reviewers: AlyaEngineer 🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (3)
src/providers/toast-provider/Toast.tsx (1)
16-23: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winSnackbar closes on any outside click (clickaway), not just timeout/explicit close.
onCloseis passed through toSnackbarunfiltered, so clicking anywhere on the page will dismiss the toast early (MUI passesreason: 'clickaway'for those events). Consider ignoring the clickaway reason so toasts persist until the timeout or explicit close.♻️ Proposed fix
+import { SnackbarCloseReason } from '`@mui/material`'; + +function handleClose(_event: React.SyntheticEvent | Event, reason?: SnackbarCloseReason) { + if (reason === 'clickaway') return; + onClose(); +} + <Snackbar anchorOrigin={{ horizontal: 'right', vertical: 'bottom' }} autoHideDuration={5000} - onClose={onClose} + onClose={handleClose} open={open} slots={{ transition: GrowTransition }} >🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/providers/toast-provider/Toast.tsx` around lines 16 - 23, The Toast Snackbar is dismissing on clickaway because the raw onClose handler is forwarded directly to Snackbar; update the Toast component to ignore MUI’s clickaway reason and only close on timeout or explicit user close. Use the Toast component’s onClose prop and the Snackbar/Alert onClose callbacks to filter out events where the reason is clickaway, while preserving normal close behavior for other reasons.src/providers/toast-provider/ToastProvider.tsx (2)
36-36: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low valueContext value object is recreated every render.
{ showToast }andshowToastitself are new references on each render ofToastProvider. Memoizing withuseCallback/useMemoavoids unnecessary re-renders of alluseToastconsumers once this is wired into the root layout.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/providers/toast-provider/ToastProvider.tsx` at line 36, The ToastContext provider value in ToastProvider is being recreated on every render, causing avoidable rerenders of useToast consumers. Update ToastProvider so showToast is memoized with useCallback and the provided context value object is memoized with useMemo before passing it to ToastContext.Provider, keeping the value stable unless its dependencies actually change.
20-47: 🎯 Functional Correctness | 🔵 Trivial | ⚖️ Poor tradeoffSingle-toast state can drop/clobber overlapping toasts.
If
showToastfires again while a toast is already open, the Snackbar's message/severity swap in place without a proper exit/enter transition or timer reset (MUI's known limitation for consecutive Snackbar messages). Given this provider will back many trigger points (save/validation/network/auth/history errors per the PR objectives), overlapping toasts seem likely. Consider queuing toasts (close current, then show next) if that's a real scenario for this app.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/providers/toast-provider/ToastProvider.tsx` around lines 20 - 47, The ToastProvider currently keeps only one ToastState, so repeated showToast calls can overwrite an open snackbar in place. Update ToastProvider and its showToast/handleClose flow to support queued or sequential toasts by closing the current Toast first and only then showing the next message/severity, using the ToastContext.Provider and Toast component in this file as the main touchpoints. Ensure consecutive toasts don’t clobber each other and that each message gets a fresh open cycle/reset.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/app/global-error.tsx`:
- Around line 22-24: Move the logging in global-error.tsx out of the render body
and into a useEffect so it matches the pattern used by the sibling error.tsx
component. Update the GlobalError component to log the error only after mount,
using the existing error value inside the effect, and keep the render path free
of side effects to avoid duplicate logs on re-renders and Strict Mode.
---
Nitpick comments:
In `@src/providers/toast-provider/Toast.tsx`:
- Around line 16-23: The Toast Snackbar is dismissing on clickaway because the
raw onClose handler is forwarded directly to Snackbar; update the Toast
component to ignore MUI’s clickaway reason and only close on timeout or explicit
user close. Use the Toast component’s onClose prop and the Snackbar/Alert
onClose callbacks to filter out events where the reason is clickaway, while
preserving normal close behavior for other reasons.
In `@src/providers/toast-provider/ToastProvider.tsx`:
- Line 36: The ToastContext provider value in ToastProvider is being recreated
on every render, causing avoidable rerenders of useToast consumers. Update
ToastProvider so showToast is memoized with useCallback and the provided context
value object is memoized with useMemo before passing it to
ToastContext.Provider, keeping the value stable unless its dependencies actually
change.
- Around line 20-47: The ToastProvider currently keeps only one ToastState, so
repeated showToast calls can overwrite an open snackbar in place. Update
ToastProvider and its showToast/handleClose flow to support queued or sequential
toasts by closing the current Toast first and only then showing the next
message/severity, using the ToastContext.Provider and Toast component in this
file as the main touchpoints. Ensure consecutive toasts don’t clobber each other
and that each message gets a fresh open cycle/reset.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: c4233315-3f60-48bf-99af-3477146e8705
📒 Files selected for processing (12)
.coderabbit.yamlsrc/app/[locale]/error.test.tsxsrc/app/[locale]/error.tsxsrc/app/global-error.test.tsxsrc/app/global-error.tsxsrc/i18n/messages/en.jsonsrc/i18n/messages/ru.jsonsrc/providers/toast-provider/Toast.test.tsxsrc/providers/toast-provider/Toast.tsxsrc/providers/toast-provider/ToastProvider.test.tsxsrc/providers/toast-provider/ToastProvider.tsxsrc/providers/toast-provider/types.ts
* feat: language switching (#53) * feat: install next+ts+linter+prettier+ husky+redux * feat: configs + perfectionist + lint fix * feat: install scss * refactor: add some folders * feat: install i18n + basic configs * feat: add internatiolisation * feat: language switcher * feat: dependencies update * fix: delete scss + delete unnecessary files * fix: delete unnecessary layout * feat: user friendly errors (#58) * feat: add error page component * test: add tests for error page component * feat: add global error page component * test: add tests for global error page component * feat: implement toast provider and toast component * test: add tests for toast provider and toast component * feat: add toaster messages dictionary * chore: add coderabbit config * fix: fix .coderabbit.yaml instruction * fix: add target branches for review to instructions * fix: move console.error into useEffect * fix: ignore clickaway on close * test: add test for onClose on clickaway * fix: memoize showToast and context value with useCallback/useMemo * fix: remove duplicate dependency entries from devDependencies in package.json * fix: pass showToast function directly to context instead of memoized object wrapper * fix: split combined toast state into three separate useState calls * refactor: extract error page props into named Props type * fix: fixes with Prettier * feat: integrate ToastProvider into app layout * refactor: extract shared ErrorCard component and align with MUI theme * refactor: rename ErrorCard props * fix: add suppressHydrationWarning to html tag to prevent expected mismatch * refactor: move Header and Footer into root layout * fix: wrap main content in semantic main element * fix: add borderBottom to AppBar in header --------- Co-authored-by: YuliaDemir <129578495+YuliaDemir@users.noreply.github.com>
Summary
Implemented error handling and user notifications per Feature 7 criterion "Errors are displayed in a user-friendly format" -
error.tsxandglobal-error.tsxfor catching render errors,ToastProviderfor operational errors (network, save, auth, etc.)Changes Made
error.tsx- error boundary for the [locale] segment, i18n via useTranslationsglobal-error.tsx- error boundary for the root layout, minimal standalone theme (theme.ts is unavailable at this level), English-only text without i18nToastProviderandToast- context for showing notifications via showToast(message, severity), Snackbar + Alert from MUI, bottom-right position, Grow transitiontoaster dictionaryin en.json/ru.json - messages for: schema save/validation/conversion, request network errors, cURL copy, sign-in/sign-up/sign-out, history loadtestsfor error.tsx, global-error.tsx, Toast, ToastProviderNeeded before merging into develop:
Usage example in components:
Related issue
Closes #10
Screenshots
Feature
Feature 7: General Requirements
Acceptance criteria
Feature 1: App Header
Feature 2: Sign In / Sign Up
Feature 3: Swagger Editor
Feature 4: Swagger Viewer
Feature 5: History and Analytics
Feature 6: About Page
Feature 7: General Requirements
Feature 8: YouTube Video
Type of change
Checklist
any/@ts-ignoreSummary by CodeRabbit