Skip to content

feat: user friendly errors - #58

Merged
AlyaEngineer merged 18 commits into
feature/7-general-requirementsfrom
story/7-user-friendly-errors
Jul 3, 2026
Merged

feat: user friendly errors#58
AlyaEngineer merged 18 commits into
feature/7-general-requirementsfrom
story/7-user-friendly-errors

Conversation

@AlyaEngineer

@AlyaEngineer AlyaEngineer commented Jul 3, 2026

Copy link
Copy Markdown
Owner

Summary

Implemented error handling and user notifications per Feature 7 criterion "Errors are displayed in a user-friendly format" - error.tsx and global-error.tsx for catching render errors, ToastProvider for operational errors (network, save, auth, etc.)

Changes Made

  • error.tsx - error boundary for the [locale] segment, i18n via useTranslations
  • global-error.tsx - error boundary for the root layout, minimal standalone theme (theme.ts is unavailable at this level), English-only text without i18n
  • ToastProvider and Toast - context for showing notifications via showToast(message, severity), Snackbar + Alert from MUI, bottom-right position, Grow transition
  • toaster dictionary in en.json/ru.json - messages for: schema save/validation/conversion, request network errors, cURL copy, sign-in/sign-up/sign-out, history load
  • tests for error.tsx, global-error.tsx, Toast, ToastProvider

Needed before merging into develop:

  • wrap the app in ToastProvider in the root layout.tsx (the full provider stack - MuiProvider, NextIntlClientProvider, etc. - is being assembled in another branch; ToastProvider needs to be added there too)

Usage example in components:

typescriptreactconst { showToast } = useToast();
const t = useTranslations('toaster');

try {
  await saveSchema(schema);
} catch {
  showToast(t('schemaSaveError'), 'error');
}

Related issue

Closes #10

Screenshots

Снимок экрана 2026-07-03 130955 Снимок экрана 2026-07-03 131007 Снимок экрана 2026-07-03 131453 Снимок экрана 2026-07-03 131515 Снимок экрана 2026-07-03 154256 Снимок экрана 2026-07-03 154306 Снимок экрана 2026-07-03 195354 Снимок экрана 2026-07-03 195403

Feature

Feature 7: General Requirements

Acceptance criteria

Feature 1: App Header
  • Non-auth users see Sign In / Sign Up in header (upper right) — 15
  • Auth users see History / Sign Out in header — 10
  • About link in header and footer — 10
  • Expired/invalid token → redirect from private routes to Main — 10
  • Sign In / Sign Up buttons redirect to respective form route — 15
Feature 2: Sign In / Sign Up
  • Sign In / Sign Up / Sign Out buttons present everywhere they should be — 10
  • Client-side validation (email, password: 8+ chars, letter+digit+special, Unicode) — 20
  • Successful login → redirect to Main — 10
  • Logged-in user on Sign In / Sign Up routes → redirect to Main — 10
Feature 3: Swagger Editor
  • Load/paste schema in JSON and YAML — 25
  • Auto-detect input format (JSON vs YAML) — 20
  • Format switch with JSON ↔ YAML conversion, no data loss — 20
  • Schema validation with error indication — 15
  • Auth users save schema; restored on next login — 10
  • Viewer auto-populates with endpoints on valid schema — 10
  • Responsive split view (horizontal/vertical by orientation) — 20
Feature 4: Swagger Viewer
  • Endpoint list organized by path/method — 20
  • Details: method, path, all param types (path/query/header/cookie) — 25
  • Request schema and example payloads displayed — 20
  • Response schema, examples, all status codes displayed — 25
  • Try-It-Out: fill params/headers/body, execute, show response — 20
  • Generate cURL + copy-to-clipboard — 10
Feature 5: History and Analytics
  • SSR-generated; empty state with links to editor/viewer — 15
  • Requests sorted by timestamp (most recent first) — 10
  • Server-side analytics: duration, status, timestamp, method, request size, response size, error details, endpoint/URL — 45
Feature 6: About Page
  • Public route, accessible to all — 5
  • Info about RS School course — 5
  • Team info (names, roles, GitHub links) — 10
  • Design consistent with the app — 5
Feature 7: General Requirements
  • i18n: 2+ languages with toggler in header — 30
  • Sticky header with animation on stick — 10
  • User-friendly error display — 10
  • Private routes protected (401 if not authenticated) — 5
Feature 8: YouTube Video
  • 5–7 min YouTube walkthrough linked, covers all criteria — 50

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would break existing functionality)
  • Documentation update

Checklist

  • Self-review done
  • No console errors / warnings / logs
  • No any / @ts-ignore
  • Tests added / updated and passing

Summary by CodeRabbit

  • New Features
    • Added a localized page-level error UI with a “retry” action, and a global error screen with “Try again”.
    • Introduced a reusable bottom-right toast notification system with success/error variants.
  • Bug Fixes
    • Updated English and Russian translations for the new error and toast messages.
  • Tests
    • Added automated tests for error screens (rendering, retry behavior, error logging) and toast functionality (display by severity, auto-dismiss/close behavior, provider usage).

@AlyaEngineer AlyaEngineer added this to the Week 1 - 22/06 - 28/06 milestone Jul 3, 2026
@AlyaEngineer AlyaEngineer added the feature-7-general Feature 7: General Requirements label Jul 3, 2026
@vercel

vercel Bot commented Jul 3, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
swagger-editor-app Ready Ready Preview, Comment Jul 3, 2026 5:45pm

@coderabbitai

coderabbitai Bot commented Jul 3, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This 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.

Changes

CodeRabbit Review Configuration

Layer / File(s) Summary
Configuration settings
.coderabbit.yaml
Defines review profile, auto-review behavior, branch selection, path-scoped instructions, and chat auto-reply.

User-friendly Error & Toast System

Layer / File(s) Summary
Toast type and component
src/providers/toast-provider/types.ts, src/providers/toast-provider/Toast.tsx, src/providers/toast-provider/Toast.test.tsx
Defines toast severity values and a Snackbar-based toast UI with close handling and tests.
ToastProvider context and hook
src/providers/toast-provider/ToastProvider.tsx, src/providers/toast-provider/ToastProvider.test.tsx
Implements toast state, showToast dispatching, dismissal handling, and the useToast hook with provider tests.
Route-level error boundary
src/app/[locale]/error.tsx, src/app/[locale]/error.test.tsx
Adds the locale-scoped error page that logs errors, renders translated content, and retries via unstable_retry.
Global error boundary
src/app/global-error.tsx, src/app/global-error.test.tsx
Adds the global error page that logs errors, renders html/body with a fallback theme, and exposes a retry action.
Error page and toaster translations
src/i18n/messages/en.json, src/i18n/messages/ru.json
Adds errorPage and toaster translation keys in English and Russian.

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
Loading
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
Loading

Related issues: #10

Suggested labels: enhancement, feature, i18n

Suggested reviewers: AlyaEngineer

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning Critical error pages and toast components were added, but the toast system is not integrated into the app or listed call sites, so the issue isn't fully met. Wrap ToastProvider in the root layout and add toast calls at the listed save, parse, network, clipboard, auth, and history error paths.
Out of Scope Changes check ⚠️ Warning The PR includes a large .coderabbit.yaml review-config change that is unrelated to the user-friendly error handling work. Move the CodeRabbit configuration changes to a separate PR focused on review automation.
✅ Passed checks (3 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly reflects the PR’s main change: adding user-friendly error handling and toast notifications.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch story/7-user-friendly-errors

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
src/providers/toast-provider/Toast.tsx (1)

16-23: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Snackbar closes on any outside click (clickaway), not just timeout/explicit close.

onClose is passed through to Snackbar unfiltered, so clicking anywhere on the page will dismiss the toast early (MUI passes reason: '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 value

Context value object is recreated every render.

{ showToast } and showToast itself are new references on each render of ToastProvider. Memoizing with useCallback/useMemo avoids unnecessary re-renders of all useToast consumers 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 tradeoff

Single-toast state can drop/clobber overlapping toasts.

If showToast fires 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

📥 Commits

Reviewing files that changed from the base of the PR and between 8a41799 and 7d228e1.

📒 Files selected for processing (12)
  • .coderabbit.yaml
  • src/app/[locale]/error.test.tsx
  • src/app/[locale]/error.tsx
  • src/app/global-error.test.tsx
  • src/app/global-error.tsx
  • src/i18n/messages/en.json
  • src/i18n/messages/ru.json
  • src/providers/toast-provider/Toast.test.tsx
  • src/providers/toast-provider/Toast.tsx
  • src/providers/toast-provider/ToastProvider.test.tsx
  • src/providers/toast-provider/ToastProvider.tsx
  • src/providers/toast-provider/types.ts

Comment thread src/app/global-error.tsx
@AlyaEngineer
AlyaEngineer requested review from lexarudak and removed request for YuliaDemir July 3, 2026 17:46
@AlyaEngineer
AlyaEngineer merged commit 2b74ed5 into feature/7-general-requirements Jul 3, 2026
3 checks passed
AlyaEngineer added a commit that referenced this pull request Jul 8, 2026
* 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>
@AlyaEngineer
AlyaEngineer deleted the story/7-user-friendly-errors branch July 8, 2026 11:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature-7-general Feature 7: General Requirements

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants