Skip to content

feat: history and analytics - #88

Merged
AlyaEngineer merged 10 commits into
developfrom
feature/5-history-and-analytics
Jul 13, 2026
Merged

feat: history and analytics#88
AlyaEngineer merged 10 commits into
developfrom
feature/5-history-and-analytics

Conversation

@AlyaEngineer

@AlyaEngineer AlyaEngineer commented Jul 13, 2026

Copy link
Copy Markdown
Owner

Summary

Implemented the History & Analytics feature for authenticated users. Added a server-side rendered history page that displays executed API requests with analytics, including an empty state and error handling.

Changes Made

  • Added a server-side History & Analytics page accessible only to authenticated users.
  • Implemented request history retrieval from Supabase, sorted by timestamp in descending order.
  • Added request history table with pagination.
  • Displayed request analytics, including:
    • HTTP method
    • endpoint/URL
    • response status code
    • request duration
    • request size
    • response size
    • request timestamp
    • error details
  • Added an empty state with links back to the Editor.
  • Added error handling for history loading failures.
  • Added i18n for History page.
  • Added a server-side utility for persisting request history records to the database.

TODO

Replace the local METHOD_COLOR constant and getMethodColor() function in src/components/history-list/history-table-row.tsx with imports from @/utils/swagger-editor/ after merging the feature/4-swagger-viewer branch.

Related issue

Closes #33

Feature

Feature 5: History and Analytics

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

Screenshot

Снимок экрана 2026-07-13 142946 Снимок экрана 2026-07-13 142929 Снимок экрана 2026-07-13 143008 Снимок экрана 2026-07-13 143024

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 request history page for authenticated users, with distinct loading outcomes (error, empty, and populated states).
    • Introduced a request history table with method/status chips, localized timestamps, error detail previews (full details on hover), and pagination with rows-per-page controls, plus a “Go to Editor” link when empty.
  • Tests
    • Added Vitest coverage for page states, empty-state messaging, history table rendering (including tooltips), pagination, and request history fetch/save behavior.
  • Style
    • Enhanced standard alert styling to reflect severity more accurately, including dark mode.

@AlyaEngineer AlyaEngineer added the feature-5-history Feature 5: History and Analytics label Jul 13, 2026
@AlyaEngineer AlyaEngineer linked an issue Jul 13, 2026 that may be closed by this pull request
@vercel

vercel Bot commented Jul 13, 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 13, 2026 5:24pm

@AlyaEngineer AlyaEngineer changed the title Feature/5 history and analytics feat: history and analytics Jul 13, 2026
@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 96c31b13-1475-463c-89ed-59344bacff2c

📥 Commits

Reviewing files that changed from the base of the PR and between dee4727 and ba96563.

📒 Files selected for processing (3)
  • src/app/[locale]/history/page.tsx
  • src/components/history-list/history-list.tsx
  • src/components/history-list/history-table-header.tsx
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/components/history-list/history-table-header.tsx
  • src/app/[locale]/history/page.tsx
  • src/components/history-list/history-list.tsx

📝 Walkthrough

Walkthrough

Adds an authenticated request-history page backed by Supabase persistence and retrieval, with localized empty/error states, a paginated analytics table, alert styling, and component and utility tests.

Changes

Request history

Layer / File(s) Summary
History data contract and persistence
src/utils/history/history-types.ts, src/utils/history/save-request-history.ts, src/utils/history/save-request-history.test.ts
Defines history record shapes, saves authenticated request metadata to request_history, and tests authenticated, unauthenticated, and insert-error paths.
History retrieval and result mapping
src/utils/history/get-request-history.ts, src/utils/history/get-request-history.test.ts
Fetches records ordered by newest first, maps database fields to camelCase entries, and handles successful, empty, null, and failed queries.
History table and pagination
src/components/history-list/*
Adds translated headers, formatted request rows, method/status chips, error previews with tooltips, and configurable pagination.
Authenticated page states and presentation
src/app/[locale]/history/*, src/components/history-empty-state/*, src/i18n/messages/*, src/theme/components.ts
Adds authenticated page loading with error, empty, and populated states, localized messages, editor navigation, alert styling, and route/component tests.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

Suggested labels: feature-2-auth

Suggested reviewers: yuliademir, ivan-khodorov

Sequence Diagram(s)

sequenceDiagram
  participant HistoryPage
  participant getAuthenticatedUser
  participant getRequestHistory
  participant Supabase
  participant HistoryList
  HistoryPage->>getAuthenticatedUser: authenticate route request
  HistoryPage->>getRequestHistory: load request history
  getRequestHistory->>Supabase: query ordered request history
  Supabase-->>getRequestHistory: rows and query status
  getRequestHistory-->>HistoryPage: entries and hasError
  HistoryPage->>HistoryList: render entries when available
Loading
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning Issue [#33] is only partially met: SSR, sorting, and analytics are present, but the empty state lacks a Viewer link and entries don't link to detailed analytics. Add a Viewer link to the empty state and make each history row navigate to its detailed analytics view, while preserving SSR and auth gating.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately names the main history/analytics feature change.
Out of Scope Changes check ✅ Passed All changes stay within the history/analytics feature area, including page, utilities, tests, i18n, and theme updates.
✨ 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 feature/5-history-and-analytics

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: 4

🧹 Nitpick comments (3)
src/components/history-list/history-table-row.tsx (1)

21-35: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Duplicate getMethodColor tracked via TODO.

Self-acknowledged duplication with the upcoming feature/4-swagger-viewer implementation; no action needed beyond the existing TODO before that branch merges.

As per path instructions, "Flag duplicate implementations of the same logic in different files."

🤖 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/components/history-list/history-table-row.tsx` around lines 21 - 35,
Remove the local METHOD_COLOR mapping and getMethodColor function from this
component, and import and reuse getMethodColor from
`@/utils/swagger-editor/get-method-color`. Remove the obsolete TODO once the
shared implementation is used.

Source: Path instructions

src/utils/history/get-request-history.ts (1)

22-25: 🚀 Performance & Scalability | 🔵 Trivial | 🏗️ Heavy lift

No limit on the query while the client already assumes full-list pagination.

The query fetches the entire request_history table for the user on every page load (no .limit()), and HistoryList then slices client-side. As history grows this bloats the SSR payload and the DB query cost.

🤖 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/utils/history/get-request-history.ts` around lines 22 - 25, Update the
request-history query in getRequestHistory to apply a server-side limit and
return only the page-sized results expected by HistoryList, rather than fetching
the full table for client-side slicing. Preserve the existing user filtering,
descending created_at ordering, and pagination behavior while passing the
appropriate page parameters to the Supabase query.
src/app/[locale]/history/page.test.tsx (1)

45-52: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Assert that a failed load does not render HistoryList.

This test only checks for the error alert. Add a negative assertion for history-list-stub; otherwise the current error-plus-empty-table behavior can pass the suite.

🤖 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/app/`[locale]/history/page.test.tsx around lines 45 - 52, Update the
“shows an error alert when the history fails to load” test around HistoryPage to
also assert that the history-list-stub element is not present after rendering.
Keep the existing error-alert assertion unchanged and verify the failed load
renders no HistoryList.
🤖 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/`[locale]/history/page.tsx:
- Around line 20-26: The history page should render mutually exclusive error,
empty-success, and non-empty-success states. Update the rendering around the
hasError condition in src/app/[locale]/history/page.tsx:20-26 so HistoryList is
omitted when loading fails; then update the error-case test in
src/app/[locale]/history/page.test.tsx:45-52 to assert that history-list-stub is
absent.
- Around line 12-14: Update the history page’s getRequestHistory flow to catch
failures from both createClient and the query, ensuring any Supabase client or
cookies error returns the localized history error state with empty entries and
hasError true instead of rejecting page rendering.
- Line 5: Replace the static HistoryList import in the history page with a
next/dynamic lazy import, preserving the component’s existing usage and enabling
SSR so initial rows can remain server-rendered.

In `@src/components/history-empty-state/history-empty-state.tsx`:
- Around line 14-18: The HistoryEmptyState component currently links only to the
Editor; add a second localized AppLinkButton for the Viewer using the existing
Viewer route and translation keys, and add the corresponding Viewer translation
in both locale files while preserving the existing Editor link.

---

Nitpick comments:
In `@src/app/`[locale]/history/page.test.tsx:
- Around line 45-52: Update the “shows an error alert when the history fails to
load” test around HistoryPage to also assert that the history-list-stub element
is not present after rendering. Keep the existing error-alert assertion
unchanged and verify the failed load renders no HistoryList.

In `@src/components/history-list/history-table-row.tsx`:
- Around line 21-35: Remove the local METHOD_COLOR mapping and getMethodColor
function from this component, and import and reuse getMethodColor from
`@/utils/swagger-editor/get-method-color`. Remove the obsolete TODO once the
shared implementation is used.

In `@src/utils/history/get-request-history.ts`:
- Around line 22-25: Update the request-history query in getRequestHistory to
apply a server-side limit and return only the page-sized results expected by
HistoryList, rather than fetching the full table for client-side slicing.
Preserve the existing user filtering, descending created_at ordering, and
pagination behavior while passing the appropriate page parameters to the
Supabase query.
🪄 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: aad29674-7c03-41c5-9c3a-3d4ef3832de4

📥 Commits

Reviewing files that changed from the base of the PR and between 87d1003 and fde4f59.

📒 Files selected for processing (13)
  • src/app/[locale]/history/page.test.tsx
  • src/app/[locale]/history/page.tsx
  • src/components/history-empty-state/history-empty-state.test.tsx
  • src/components/history-empty-state/history-empty-state.tsx
  • src/components/history-list/history-list.test.tsx
  • src/components/history-list/history-list.tsx
  • src/components/history-list/history-table-header.tsx
  • src/components/history-list/history-table-row.tsx
  • src/i18n/messages/en.json
  • src/i18n/messages/ru.json
  • src/theme/components.ts
  • src/utils/history/get-request-history.test.ts
  • src/utils/history/get-request-history.ts

import { getTranslations } from 'next-intl/server';

import { HistoryEmptyState } from '@/components/history-empty-state/history-empty-state';
import { HistoryList } from '@/components/history-list/history-list';

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🚀 Performance & Scalability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## File map\n'
git ls-files 'src/app/[locale]/history/page.tsx' 'src/components/history-list/history-list.*' 'src/app/**/page.tsx' | sed 's#^`#-` #'

printf '\n## Outline: history page\n'
ast-grep outline src/app/[locale]/history/page.tsx --view expanded || true

printf '\n## Outline: history list component\n'
ast-grep outline src/components/history-list/history-list.tsx --view expanded || true

printf '\n## Relevant route imports/usages\n'
rg -n --glob 'src/app/**/page.tsx' "HistoryList|dynamic\\(|next/dynamic|history-list" src/app || true

printf '\n## History page contents (numbered)\n'
wc -l src/app/[locale]/history/page.tsx
cat -n src/app/[locale]/history/page.tsx | sed -n '1,220p'

printf '\n## History list contents (numbered, first 260 lines)\n'
wc -l src/components/history-list/history-list.tsx
cat -n src/components/history-list/history-list.tsx | sed -n '1,260p'

Repository: AlyaEngineer/swagger-editor-app

Length of output: 4494


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## Helper outlines\n'
ast-grep outline src/utils/auth/get-authenticated-user.ts --view expanded || true
ast-grep outline src/utils/history/get-request-history.ts --view expanded || true

printf '\n## Auth helper\n'
wc -l src/utils/auth/get-authenticated-user.ts
cat -n src/utils/auth/get-authenticated-user.ts | sed -n '1,220p'

printf '\n## History helper\n'
wc -l src/utils/history/get-request-history.ts
cat -n src/utils/history/get-request-history.ts | sed -n '1,260p'

Repository: AlyaEngineer/swagger-editor-app

Length of output: 2671


Lazy-load HistoryList on the history route.
src/app/[locale]/history/page.tsx still statically imports the table component, which violates the History & Analytics lazy-loading requirement. Switch this to next/dynamic here; keep SSR on if you still want the initial rows in the server-rendered HTML.

🤖 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/app/`[locale]/history/page.tsx at line 5, Replace the static HistoryList
import in the history page with a next/dynamic lazy import, preserving the
component’s existing usage and enabling SSR so initial rows can remain
server-rendered.

Source: Path instructions

Comment thread src/app/[locale]/history/page.tsx
Comment thread src/app/[locale]/history/page.tsx Outdated
Comment thread src/components/history-empty-state/history-empty-state.tsx

@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 (1)
src/utils/history/get-request-history.ts (1)

6-9: 🚀 Performance & Scalability | 🔵 Trivial | 🏗️ Heavy lift

Bound the history query for pagination.

select('*') retrieves every history row on each SSR request. As a user’s history grows, database, network, and rendering costs grow without bound; pass page/limit parameters and use Supabase range pagination (or enforce retention).

🤖 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/utils/history/get-request-history.ts` around lines 6 - 9, Update the
request-history query in getRequestHistory to accept page and limit parameters
and apply Supabase range pagination with .range() after ordering by created_at.
Ensure the calculated range returns only the requested page and retains the
existing data/error handling.
🤖 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/utils/history/save-request-history.ts`:
- Around line 5-29: Wrap the Supabase operations in both saveRequestHistory in
src/utils/history/save-request-history.ts (lines 5-29) and the corresponding
getRequestHistory path in src/utils/history/get-request-history.ts (lines 4-14)
with try/catch handling. Preserve the existing unauthenticated skip and { error
} checks, while catching rejected auth or query-builder calls, logging or
returning the established history error state as appropriate, and preventing
failures from propagating into the request path.

---

Nitpick comments:
In `@src/utils/history/get-request-history.ts`:
- Around line 6-9: Update the request-history query in getRequestHistory to
accept page and limit parameters and apply Supabase range pagination with
.range() after ordering by created_at. Ensure the calculated range returns only
the requested page and retains the existing data/error handling.
🪄 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: 039233fb-d990-4330-85dc-b3a2f53b4b0a

📥 Commits

Reviewing files that changed from the base of the PR and between fde4f59 and b88a2b4.

📒 Files selected for processing (7)
  • src/components/history-list/history-list.test.tsx
  • src/components/history-list/history-list.tsx
  • src/components/history-list/history-table-row.tsx
  • src/utils/history/get-request-history.ts
  • src/utils/history/history-types.ts
  • src/utils/history/save-request-history.test.ts
  • src/utils/history/save-request-history.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/components/history-list/history-table-row.tsx
  • src/components/history-list/history-list.test.tsx
  • src/components/history-list/history-list.tsx

Comment thread src/utils/history/save-request-history.ts
lexarudak
lexarudak previously approved these changes Jul 13, 2026
@AlyaEngineer
AlyaEngineer merged commit 35cabfa into develop Jul 13, 2026
3 checks passed
@coderabbitai coderabbitai Bot mentioned this pull request Jul 13, 2026
8 tasks
@coderabbitai coderabbitai Bot mentioned this pull request Jul 14, 2026
8 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature-5-history Feature 5: History and Analytics

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature 5: History and Analytics (70 points)

3 participants