Skip to content

Migrate admin-frontend to shadcn/ui, add dark mode, and translate UI to pt-BR - #23

Merged
evertonschuster merged 3 commits into
mainfrom
feature/admin-frontend-shadcn-ui-ptbr
Jul 11, 2026
Merged

Migrate admin-frontend to shadcn/ui, add dark mode, and translate UI to pt-BR#23
evertonschuster merged 3 commits into
mainfrom
feature/admin-frontend-shadcn-ui-ptbr

Conversation

@evertonschuster

@evertonschuster evertonschuster commented Jul 11, 2026

Copy link
Copy Markdown
Owner

Summary

  • Replaces the hand-rolled component layer with shadcn/ui (Radix primitives + Tailwind, CLI-generated and kept close to registry output — no speculative custom props/variants). Resets the theme to the stock "Nova"/neutral palette; confirmed via CLI experimentation (Vega preset) that this verbosity is shared across every shadcn preset, not something worth fighting.
  • Adds a full light/dark theme system (ThemeProvider/useTheme/ThemeToggle): defaults to OS preference, persists an explicit override.
  • Makes AdminLayout responsive: collapsible desktop icon-rail sidebar (persisted) + off-canvas mobile drawer below md.
  • Reworks the Tags vertical as the reference implementation for every future feature vertical: list is a Table (not stacked Cards), create/edit is a single Dialog modal (not inline/routed).
  • Translates all user-facing text — labels, messages, aria-labels, window.confirm prompts, and reachable domain/error messages — to Brazilian Portuguese (pt-BR), per explicit project requirement. Code, comments, and docs stay in English.
  • Updates CLAUDE.md, the admin-feature-vertical skill, docs/DECISIONS.md, docs/STATUS.md, and adds docs/adr/005-shadcn-ui-component-library.md so these conventions apply automatically when Services/Clients/Appointments/Inbox/Dashboard/Settings get built.

Test plan

  • npm run build — clean
  • npm run lint — 0 errors (32 pre-existing warnings, all in unmodified shadcn-generated files)
  • npm run test — 116/116 passing
  • Manual check in a browser (light + dark mode, desktop + mobile) — not verified live this session due to a local port-5173 conflict with an unrelated process; please sanity-check before merging

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added a consistent admin interface design with reusable controls, tables, dialogs, forms, and loading states.
    • Added light/dark theme switching with system preference detection and saved selection.
    • Improved responsive navigation with collapsible desktop and mobile sidebars.
    • Updated tag management with table-based listings and a unified create/edit dialog.
    • Localized user-facing messages and controls in Brazilian Portuguese.
  • Bug Fixes

    • Improved login, authentication callback, loading, and error-state presentations.
    • Added responsive behavior and accessibility improvements across navigation and forms.
  • Tests

    • Expanded coverage for themes, navigation, forms, tags, login, and placeholder pages.

…to pt-BR

Replaces the hand-rolled component layer with shadcn/ui (Radix primitives
+ Tailwind, CLI-generated, kept close to registry output per project
convention) and resets the theme to the stock "Nova"/neutral palette.
Adds a full light/dark theme system (OS-aware default, persisted
override) and makes AdminLayout responsive (collapsible desktop
sidebar, off-canvas mobile drawer).

Reworks the Tags vertical's list/form pattern as the reference
implementation for every future feature vertical: a Table instead of
stacked Cards, and a single Dialog modal for create/edit instead of an
inline form. Translates all user-facing text (labels, messages,
aria-labels, confirm prompts) to Brazilian Portuguese per explicit
project requirement, including reachable domain/error messages.

Updates CLAUDE.md, the admin-feature-vertical skill, DECISIONS.md, and
adds ADR 005 so the new conventions (shadcn/ui, Table+Dialog, pt-BR
text) apply automatically to the next feature verticals.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@evertonschuster, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 20 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9b0c5d75-b08a-4cc7-b128-5306a7374362

📥 Commits

Reviewing files that changed from the base of the PR and between ad0b050 and 9cdd3c1.

📒 Files selected for processing (30)
  • apps/admin-frontend/.skills/admin-feature-vertical/SKILL.md
  • apps/admin-frontend/docs/DECISIONS.md
  • apps/admin-frontend/package.json
  • apps/admin-frontend/src/components/ui/alert-dialog.tsx
  • apps/admin-frontend/src/components/ui/sheet.tsx
  • apps/admin-frontend/src/presentation/layouts/AdminLayout.test.tsx
  • apps/admin-frontend/src/presentation/layouts/AdminLayout.tsx
  • apps/admin-frontend/src/presentation/pages/CallbackPage/CallbackPage.tsx
  • apps/admin-frontend/src/presentation/pages/TagsPage/TagForm.tsx
  • apps/admin-frontend/src/presentation/pages/TagsPage/TagsPage.test.tsx
  • apps/admin-frontend/src/presentation/pages/TagsPage/TagsPage.tsx
  • apps/admin-frontend/src/presentation/providers/ThemeProvider.test.tsx
  • apps/admin-frontend/src/presentation/providers/ThemeProvider.tsx
  • backend/services/identity-service/IdentityService.Application/Tenants/ProvisionTenant/ProvisionTenantCommandValidator.cs
  • backend/services/identity-service/IdentityService.Domain/Entities/Tenant.cs
  • backend/services/services-service/ServicesService.Application/ServiceOfferings/CreateServiceOffering/CreateServiceOfferingCommandHandler.cs
  • backend/services/services-service/ServicesService.Application/ServiceOfferings/CreateServiceOffering/CreateServiceOfferingCommandValidator.cs
  • backend/services/services-service/ServicesService.Application/ServiceOfferings/DeleteServiceOffering/DeleteServiceOfferingCommandHandler.cs
  • backend/services/services-service/ServicesService.Application/ServiceOfferings/UpdateServiceOffering/UpdateServiceOfferingCommandHandler.cs
  • backend/services/services-service/ServicesService.Application/ServiceOfferings/UpdateServiceOffering/UpdateServiceOfferingCommandValidator.cs
  • backend/services/services-service/ServicesService.Application/Tags/CreateTag/CreateTagCommandHandler.cs
  • backend/services/services-service/ServicesService.Application/Tags/CreateTag/CreateTagCommandValidator.cs
  • backend/services/services-service/ServicesService.Application/Tags/DeleteTag/DeleteTagCommandHandler.cs
  • backend/services/services-service/ServicesService.Application/Tags/UpdateTag/UpdateTagCommandHandler.cs
  • backend/services/services-service/ServicesService.Application/Tags/UpdateTag/UpdateTagCommandValidator.cs
  • backend/services/services-service/ServicesService.Domain/Entities/ServiceOffering.cs
  • backend/services/services-service/ServicesService.Domain/Entities/Tag.cs
  • backend/services/services-service/ServicesService.Domain/Exceptions/InvalidTenantException.cs
  • backend/services/services-service/ServicesService.Domain/ValueObjects/TagColor.cs
  • backend/shared/Admin.SharedKernel/GenericExceptionHandler.cs
📝 Walkthrough

Walkthrough

The admin frontend adds a shadcn/ui-based component system, semantic light/dark theming, responsive navigation, Portuguese localization, shared page components, and a table-based Tags CRUD flow using one create/edit dialog.

Changes

Admin frontend UI refresh

Layer / File(s) Summary
UI foundation and project conventions
.claude/launch.json, apps/admin-frontend/{components.json,package.json,tsconfig*.json,vite.config.ts,vitest.config.ts}, apps/admin-frontend/src/index.css, apps/admin-frontend/docs/*, apps/admin-frontend/.skills/*, apps/admin-frontend/CLAUDE.md
Adds shadcn/ui configuration, dependencies, semantic theme tokens, path aliases, launch configuration, and updated implementation guidance.
Shared UI primitives and composites
apps/admin-frontend/src/components/ui/*, apps/admin-frontend/src/presentation/components/*, apps/admin-frontend/src/lib/utils.ts
Adds reusable styled primitives, form fields, status and placeholder components, loading UI, and class-name merging utilities.
Theme and responsive application shell
apps/admin-frontend/src/presentation/providers/*, apps/admin-frontend/src/presentation/layouts/*, apps/admin-frontend/src/presentation/hooks/useTheme.ts, apps/admin-frontend/src/presentation/components/ThemeToggle.tsx, apps/admin-frontend/src/presentation/routes/ProtectedRoute.tsx, apps/admin-frontend/src/test/setup.ts
Adds persisted theme selection, OS preference handling, responsive collapsible navigation, mobile drawer behavior, and shared authentication loading UI.
Localized page shells and authentication states
apps/admin-frontend/src/presentation/pages/{AppointmentsPage,ClientsPage,DashboardPage,InboxPage,ServicesPage,SettingsPage}/*, apps/admin-frontend/src/presentation/pages/{CallbackPage,LoginPage}/*, apps/admin-frontend/src/infrastructure/http/UnauthenticatedError.ts
Replaces duplicated placeholder markup with shared components and updates callback/login states and messages to Portuguese.
Table and dialog Tags workflow
apps/admin-frontend/src/presentation/pages/TagsPage/*, apps/admin-frontend/src/domain/entities/Tag.ts, apps/admin-frontend/src/presentation/hooks/useTags.ts
Refactors Tags into a table with Edit/Delete actions and one create/edit Dialog, updates shared form controls, and localizes validation and mutation errors.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

  • evertonschuster/Agenza#17: Directly overlaps with the Tags CRUD implementation, including useTags, TagsPage, TagForm, and Portuguese error messages.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 2.94% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: shadcn/ui migration, dark mode support, and pt-BR localization.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/admin-frontend-shadcn-ui-ptbr

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

🧹 Nitpick comments (3)
apps/admin-frontend/src/presentation/components/StatusMessage.tsx (1)

10-16: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Guard the indexed access on TONE_CLASSES for noUncheckedIndexedAccess compliance.

With noUncheckedIndexedAccess: true, TONE_CLASSES[tone] is typed string | undefined. The coding guidelines require guarding indexed-access results before use. Add a fallback to prevent a potential "text-sm undefined" class string.

As per coding guidelines: "With noUncheckedIndexedAccess: true, always guard indexed-access results before using them."

♻️ Proposed fix
-  return <p className={`text-sm ${TONE_CLASSES[tone]}`}>{children}</p>
+  return <p className={`text-sm ${TONE_CLASSES[tone] ?? ''}`}>{children}</p>
🤖 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 `@apps/admin-frontend/src/presentation/components/StatusMessage.tsx` around
lines 10 - 16, Guard the indexed lookup in StatusMessage before constructing the
className: assign TONE_CLASSES[tone] to a local variable and provide a safe
fallback (such as an empty string or muted tone class) when it is undefined,
then use that guarded value in the returned paragraph.

Source: Coding guidelines

apps/admin-frontend/src/components/ui/spinner.tsx (1)

1-4: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Add import * as React from 'react' for consistency with sibling UI components.

React.ComponentProps<'svg'> on line 4 references the React namespace without an explicit import. While this resolves via the UMD global from @types/react, every other component in components/ui/ explicitly imports React. Adding the import keeps the directory consistent and avoids confusion.

♻️ Proposed fix
+import * as React from 'react'
 import { cn } from '`@/lib/utils`'
 import { Loader2Icon } from 'lucide-react'
🤖 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 `@apps/admin-frontend/src/components/ui/spinner.tsx` around lines 1 - 4, Add an
explicit `import * as React from 'react'` alongside the existing imports in the
`Spinner` component file so its `React.ComponentProps<'svg'>` type reference
follows the convention used by sibling UI components.
apps/admin-frontend/src/presentation/pages/CallbackPage/CallbackPage.tsx (1)

38-43: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Use <Link> instead of a raw <a> for the login redirect.

The raw anchor causes a full page reload. React Router's <Link to="/login"> enables client-side navigation and preserves SPA behavior. The existing test (getByRole('link') + toHaveAttribute('href', '/login')) will still pass since <Link> renders an <a>.

♻️ Proposed refactor
-import { useNavigate } from 'react-router'
+import { useNavigate, Link } from 'react-router'
-            <a
-              href="/login"
-              className="mt-6 inline-block text-sm font-medium text-primary hover:underline"
-            >
+            <Link
+              to="/login"
+              className="mt-6 inline-block text-sm font-medium text-primary hover:underline"
+            >
               Voltar para o login
-            </a>
+            </Link>
🤖 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 `@apps/admin-frontend/src/presentation/pages/CallbackPage/CallbackPage.tsx`
around lines 38 - 43, Replace the raw anchor in CallbackPage with React Router’s
Link component, importing it from the project’s router dependency and changing
href="/login" to to="/login" while preserving the existing className and label.
🤖 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 `@apps/admin-frontend/package.json`:
- Line 28: Move the shadcn package entry from dependencies to devDependencies in
the package manifest, preserving its version and removing the duplicate
dependency entry.

In `@apps/admin-frontend/src/components/ui/dialog.tsx`:
- Around line 79-104: Remove the non-standard showCloseButton prop and its
conditional DialogPrimitive.Close rendering from DialogFooter, restoring it to
the generated shadcn/ui styled div API. Move any required close-button rendering
into each consuming form or dialog component.

In `@apps/admin-frontend/src/presentation/layouts/AdminLayout.test.tsx`:
- Around line 110-117: The mobile sidebar test in “opens and closes the mobile
sidebar drawer” only checks a link that remains in the DOM regardless of drawer
state. Assert the drawer’s backdrop is present after clicking “abrir menu” and
absent after clicking the “Painel” link, using the drawer/backdrop’s accessible
role or identifying selector.

In `@apps/admin-frontend/src/presentation/layouts/AdminLayout.tsx`:
- Around line 68-176: Replace the hand-rolled mobile drawer in AdminLayout with
the shadcn/ui Sheet component, preserving the existing navigation, collapsed
desktop sidebar, backdrop behavior, Escape handling, and mobile open state. Use
SheetTrigger for the “Abrir menu” control and SheetContent for the mobile
navigation so focus trapping, focus restoration, and dialog ARIA semantics are
handled automatically; keep the desktop aside separate and ensure mobile
navigation closes through the Sheet state and NavLink actions.

In `@apps/admin-frontend/src/presentation/pages/TagsPage/TagsPage.tsx`:
- Around line 84-89: Update handleDelete to wrap deleteTag(id) in try/catch,
including any subsequent refetch failure, and report the error through the
page-level error state used by handleSubmit via messageFrom. Render that error
state below PageHeader so deletion failures provide user feedback and do not
produce unhandled promise rejections.

In `@apps/admin-frontend/src/presentation/providers/ThemeProvider.tsx`:
- Around line 31-45: OS theme changes can override a user-selected theme because
the listener in the mount-only useEffect remains active after setTheme persists
a preference. Update handleChange to re-check localStorage.getItem(STORAGE_KEY)
and return without calling setThemeState when an explicit value exists;
otherwise continue applying the media query preference.

---

Nitpick comments:
In `@apps/admin-frontend/src/components/ui/spinner.tsx`:
- Around line 1-4: Add an explicit `import * as React from 'react'` alongside
the existing imports in the `Spinner` component file so its
`React.ComponentProps<'svg'>` type reference follows the convention used by
sibling UI components.

In `@apps/admin-frontend/src/presentation/components/StatusMessage.tsx`:
- Around line 10-16: Guard the indexed lookup in StatusMessage before
constructing the className: assign TONE_CLASSES[tone] to a local variable and
provide a safe fallback (such as an empty string or muted tone class) when it is
undefined, then use that guarded value in the returned paragraph.

In `@apps/admin-frontend/src/presentation/pages/CallbackPage/CallbackPage.tsx`:
- Around line 38-43: Replace the raw anchor in CallbackPage with React Router’s
Link component, importing it from the project’s router dependency and changing
href="/login" to to="/login" while preserving the existing className and label.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 21285447-6909-41dd-8354-53bf11feaabb

📥 Commits

Reviewing files that changed from the base of the PR and between 719494f and ad0b050.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (57)
  • .claude/launch.json
  • apps/admin-frontend/.skills/admin-feature-vertical/SKILL.md
  • apps/admin-frontend/CLAUDE.md
  • apps/admin-frontend/components.json
  • apps/admin-frontend/docs/DECISIONS.md
  • apps/admin-frontend/docs/STATUS.md
  • apps/admin-frontend/docs/adr/005-shadcn-ui-component-library.md
  • apps/admin-frontend/package.json
  • apps/admin-frontend/src/components/ui/button.tsx
  • apps/admin-frontend/src/components/ui/card.tsx
  • apps/admin-frontend/src/components/ui/dialog.tsx
  • apps/admin-frontend/src/components/ui/input.tsx
  • apps/admin-frontend/src/components/ui/label.tsx
  • apps/admin-frontend/src/components/ui/spinner.tsx
  • apps/admin-frontend/src/components/ui/table.tsx
  • apps/admin-frontend/src/components/ui/textarea.tsx
  • apps/admin-frontend/src/domain/entities/Tag.ts
  • apps/admin-frontend/src/index.css
  • apps/admin-frontend/src/infrastructure/http/UnauthenticatedError.ts
  • apps/admin-frontend/src/lib/utils.ts
  • apps/admin-frontend/src/presentation/components/CenteredScreen.tsx
  • apps/admin-frontend/src/presentation/components/FullScreenSpinner.tsx
  • apps/admin-frontend/src/presentation/components/PageHeader.tsx
  • apps/admin-frontend/src/presentation/components/PlaceholderPage.test.tsx
  • apps/admin-frontend/src/presentation/components/PlaceholderPage.tsx
  • apps/admin-frontend/src/presentation/components/StatusMessage.tsx
  • apps/admin-frontend/src/presentation/components/TextAreaField.tsx
  • apps/admin-frontend/src/presentation/components/TextField.test.tsx
  • apps/admin-frontend/src/presentation/components/TextField.tsx
  • apps/admin-frontend/src/presentation/components/ThemeToggle.tsx
  • apps/admin-frontend/src/presentation/hooks/useTags.ts
  • apps/admin-frontend/src/presentation/hooks/useTheme.ts
  • apps/admin-frontend/src/presentation/layouts/AdminLayout.test.tsx
  • apps/admin-frontend/src/presentation/layouts/AdminLayout.tsx
  • apps/admin-frontend/src/presentation/pages/AppointmentsPage/AppointmentsPage.tsx
  • apps/admin-frontend/src/presentation/pages/CallbackPage/CallbackPage.test.tsx
  • apps/admin-frontend/src/presentation/pages/CallbackPage/CallbackPage.tsx
  • apps/admin-frontend/src/presentation/pages/ClientsPage/ClientsPage.tsx
  • apps/admin-frontend/src/presentation/pages/DashboardPage/DashboardPage.tsx
  • apps/admin-frontend/src/presentation/pages/InboxPage/InboxPage.tsx
  • apps/admin-frontend/src/presentation/pages/LoginPage/LoginPage.test.tsx
  • apps/admin-frontend/src/presentation/pages/LoginPage/LoginPage.tsx
  • apps/admin-frontend/src/presentation/pages/ServicesPage/ServicesPage.tsx
  • apps/admin-frontend/src/presentation/pages/SettingsPage/SettingsPage.tsx
  • apps/admin-frontend/src/presentation/pages/TagsPage/TagForm.tsx
  • apps/admin-frontend/src/presentation/pages/TagsPage/TagsPage.test.tsx
  • apps/admin-frontend/src/presentation/pages/TagsPage/TagsPage.tsx
  • apps/admin-frontend/src/presentation/providers/AppProviders.tsx
  • apps/admin-frontend/src/presentation/providers/ThemeContext.ts
  • apps/admin-frontend/src/presentation/providers/ThemeProvider.test.tsx
  • apps/admin-frontend/src/presentation/providers/ThemeProvider.tsx
  • apps/admin-frontend/src/presentation/routes/ProtectedRoute.tsx
  • apps/admin-frontend/src/test/setup.ts
  • apps/admin-frontend/tsconfig.app.json
  • apps/admin-frontend/tsconfig.json
  • apps/admin-frontend/vite.config.ts
  • apps/admin-frontend/vitest.config.ts

Comment thread apps/admin-frontend/package.json Outdated
Comment thread apps/admin-frontend/src/components/ui/dialog.tsx
Comment thread apps/admin-frontend/src/presentation/layouts/AdminLayout.test.tsx
Comment thread apps/admin-frontend/src/presentation/layouts/AdminLayout.tsx
Comment thread apps/admin-frontend/src/presentation/pages/TagsPage/TagsPage.tsx Outdated
Comment thread apps/admin-frontend/src/presentation/providers/ThemeProvider.tsx
evertonschuster and others added 2 commits July 10, 2026 22:16
… feedback

Fixes found via adversarial testing of the Tags screen: duplicate-tag
error message was untranslated (backend-owned text), the submit button
stayed enabled with a blank name, and a stale "Editar etiqueta" dialog
flashed empty after creating a tag (Dialog title/content were derived
from state that clears before the close animation finishes).

Extends the pt-BR requirement to the backend: every FluentValidation
rule now has an explicit Portuguese message (most were silently falling
back to FluentValidation's English defaults), plus all Result/domain
exception messages reachable through the API (Tags, ServiceOfferings,
tenant provisioning, the shared generic-exception-handler fallback).

Addresses CodeRabbit review feedback on PR #23:
- shadcn moved to devDependencies (dev-only CLI tool)
- ThemeProvider's OS-theme listener now re-checks localStorage inside
  its handler, not just at effect setup, so it can't override an
  explicit choice made after mount
- handleDelete now catches and surfaces errors instead of leaving an
  unhandled rejection
- CallbackPage uses react-router's Link instead of a raw <a>
- AdminLayout's mobile drawer now uses shadcn's Sheet (Radix Dialog)
  instead of a hand-rolled backdrop, gaining focus trap, focus
  restoration, Escape-to-close, and aria-modal semantics for free

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Swaps the Tags delete flow's native window.confirm for shadcn/ui's
AlertDialog: styled consistently with the rest of the app, translatable,
and testable with normal RTL queries (window.confirm blocked automated
testing of the delete flow entirely).

AlertDialogAction closes itself by default on click, so onClick calls
event.preventDefault() to keep the dialog open until the delete request
actually resolves — a failure now shows inline instead of silently
closing. Documents the pattern in the skill/DECISIONS.md so future
delete flows (Services, Clients, etc.) follow it by default.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@evertonschuster
evertonschuster merged commit 3a35242 into main Jul 11, 2026
15 checks passed
@evertonschuster
evertonschuster deleted the feature/admin-frontend-shadcn-ui-ptbr branch July 11, 2026 01:33
@evertonschuster
evertonschuster restored the feature/admin-frontend-shadcn-ui-ptbr branch July 11, 2026 01:44
evertonschuster added a commit that referenced this pull request Jul 11, 2026
* Migrate admin-frontend to shadcn/ui, add dark mode, and translate UI to pt-BR

Replaces the hand-rolled component layer with shadcn/ui (Radix primitives
+ Tailwind, CLI-generated, kept close to registry output per project
convention) and resets the theme to the stock "Nova"/neutral palette.
Adds a full light/dark theme system (OS-aware default, persisted
override) and makes AdminLayout responsive (collapsible desktop
sidebar, off-canvas mobile drawer).

Reworks the Tags vertical's list/form pattern as the reference
implementation for every future feature vertical: a Table instead of
stacked Cards, and a single Dialog modal for create/edit instead of an
inline form. Translates all user-facing text (labels, messages,
aria-labels, confirm prompts) to Brazilian Portuguese per explicit
project requirement, including reachable domain/error messages.

Updates CLAUDE.md, the admin-feature-vertical skill, DECISIONS.md, and
adds ADR 005 so the new conventions (shadcn/ui, Table+Dialog, pt-BR
text) apply automatically to the next feature verticals.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* Fix Tags UX bugs, translate backend messages to pt-BR, address review feedback

Fixes found via adversarial testing of the Tags screen: duplicate-tag
error message was untranslated (backend-owned text), the submit button
stayed enabled with a blank name, and a stale "Editar etiqueta" dialog
flashed empty after creating a tag (Dialog title/content were derived
from state that clears before the close animation finishes).

Extends the pt-BR requirement to the backend: every FluentValidation
rule now has an explicit Portuguese message (most were silently falling
back to FluentValidation's English defaults), plus all Result/domain
exception messages reachable through the API (Tags, ServiceOfferings,
tenant provisioning, the shared generic-exception-handler fallback).

Addresses CodeRabbit review feedback on PR #23:
- shadcn moved to devDependencies (dev-only CLI tool)
- ThemeProvider's OS-theme listener now re-checks localStorage inside
  its handler, not just at effect setup, so it can't override an
  explicit choice made after mount
- handleDelete now catches and surfaces errors instead of leaving an
  unhandled rejection
- CallbackPage uses react-router's Link instead of a raw <a>
- AdminLayout's mobile drawer now uses shadcn's Sheet (Radix Dialog)
  instead of a hand-rolled backdrop, gaining focus trap, focus
  restoration, Escape-to-close, and aria-modal semantics for free

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* Replace window.confirm with shadcn's AlertDialog for delete confirmation

Swaps the Tags delete flow's native window.confirm for shadcn/ui's
AlertDialog: styled consistently with the rest of the app, translatable,
and testable with normal RTL queries (window.confirm blocked automated
testing of the delete flow entirely).

AlertDialogAction closes itself by default on click, so onClick calls
event.preventDefault() to keep the dialog open until the delete request
actually resolves — a failure now shows inline instead of silently
closing. Documents the pattern in the skill/DECISIONS.md so future
delete flows (Services, Clients, etc.) follow it by default.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
@evertonschuster
evertonschuster deleted the feature/admin-frontend-shadcn-ui-ptbr branch July 11, 2026 01:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant