# Original (React) vs Laravel — Forensic Replication Audit

**Source of truth:** `/Users/augustogomes/Desktop/Web Projects/bugets-smart-money`  
**Implementation under audit:** `/Users/augustogomes/Desktop/Web Projects/Budgets-Laravel`  
**Audit date:** 2026-04-19  

This document follows the mandated workflow: **Difference Audit → Inventories → Correction Plan → Implementation status → QA checklist → Remaining gaps.**

---

## 1) Original vs Laravel — Difference Audit (Executive)

| Area | Original | Laravel today | Verdict |
|------|----------|---------------|---------|
| **Global shell** | `App.tsx`: `MotionConfig`, TanStack `QueryClientProvider`, Radix `TooltipProvider`, Radix `Toaster`, Sonner, `BrowserRouter`, lazy `Suspense` + `PageFallback` | Marketing/app Blade + Livewire + Vite; **no** Radix Tooltip/Toaster/Sonner stack; **no** MotionConfig; **no** React Query | **Structural mismatch** (framework ceiling + not ported) |
| **App chrome** | `AppLayout.tsx` + `MobileBottomNav` + `SearchPanel` + `NotificationPanel` from `TopBar.tsx`, `useMobileChrome`, path-derived mobile FAB/search | Sidebar + mobile nav + quick-create + **simplified** search + **simplified** notifications | **Behavior/content mismatch** |
| **i18n** | `src/lib/i18n.tsx` — fixed key set + `localStorage` `budgets.language` + `dateLocale` | Session `budgets.language`, `lang/en|pt` partial extraction; **most page copy still hardcoded in React TSX**, not all extracted to Laravel lang | **Incomplete string parity** |
| **Data** | `live-data.ts` + `mock-data.ts` + optional Supabase | `config/budgets_demo.php` + session prefs; **no** Supabase client parity | **Protocol/state mismatch** (documented acceptable only if explicitly signed off) |
| **Motion** | Framer Motion across landing, onboarding, drawers, lists | CSS/Alpine only | **Not pixel-identical** (pre-identified ceiling) |
| **Entity pages** | Full UIs (drawers, forms, filters, `CategoryPicker`, `CurrencyInput`, `SmartActions`, etc.) | Mostly **stubs** (list + query banners) | **Major functional/UI absence** |

**Conclusion:** Laravel is **not** a pixel-accurate clone today. Completing the mandate requires **per-page porting** of every TSX screen into Blade/Livewire (or hybrid React islands for Radix-perfect widgets), plus global shell parity decisions.

---

## 2) Missing / Mismatched Route and View Inventory

### Routes

| Path | Original | Laravel | Match? |
|------|----------|---------|--------|
| `/` | `Index` → `LandingPage` | `LandingIndex` | Partial (content expanded but not byte-identical to every motion/class) |
| `/onboarding` | `OnboardingPage` | `OnboardingPage` | **Close** (7 steps ported; Framer `AnimatePresence`/`motion` not replicated) |
| `/import` | `ImportPage` (~415 LOC) | `import-page` stub | **Missing** |
| `/dashboard` | `DashboardPage` (~921 LOC) | `dashboard-page` + widget partial | **Partial** (widgets exist; parity not verified line-by-line) |
| `/transactions` | `TransactionsPage` (~495 LOC) | ~24-line stub | **Missing** |
| `/budgets` | `BudgetsPage` (~266 LOC) | stub | **Missing** |
| `/goals` | `GoalsPage` (~283 LOC) | stub | **Missing** |
| `/subscriptions` | `SubscriptionsPage` (~349 LOC) | stub | **Missing** |
| `/debts` | `DebtsPage` (~295 LOC) | stub | **Missing** |
| `/insights` | `InsightsPage` (~79 LOC) | simplified | **Partial** |
| `/ai-advisor` | `AIAdvisorPage` (~105 LOC) | disabled-input shell | **Missing** |
| `/profile` | `ProfilePage` (~497 LOC) | small summary | **Missing** |
| `/settings` | `SettingsPage` (~813 LOC) | small subset | **Missing** |
| `/admin` | `AdminPage` (~87 LOC) | simplified | **Partial** |
| `/admin/users` | `UsersPage` (~57 LOC) | table from demo data | **Partial** (verify columns vs React) |
| `/admin/analytics` | `AnalyticsPage` (~90 LOC) | simplified bars | **Partial** |
| `*` | `NotFound` | `errors/not-found` | **Partial** (see content inventory) |
| `POST /locale` | N/A (client `localStorage`) | exists | Different mechanism (acceptable if UX equivalent) |

### Views / components (original) without Laravel equivalents

From `AppLayout` / `TopBar` / pages (non-exhaustive but high-signal):

- **`SearchPanel`** (cmd-lite: overlay `pt-[15vh]`, `max-w-lg`, `rounded-3xl`, query filter, typed rows, ESC hint, empty copy) — was **not** matched; **being corrected in this pass** toward same structure/copy.
- **`NotificationPanel`** (full mock list, mark read, unread badge behavior, framer transitions) — Laravel has **two placeholder cards** only.
- **`TopBar`** remainder: avatar + notifications integration, title/subtitle per page — partially matched in `top-bar.blade.php`.
- **Shared:** `CategoryPicker`, `BrandAvatar`, `RecurringDrawer`, `SmartActions`, `CurrencyInput`, `LanguageSwitcher` (where used) — **largely missing** on Laravel entity pages.
- **Per-page drawers/modals** on Transactions, Budgets, Goals, Subscriptions, Debts, Settings, Profile, Import — **missing**.

---

## 3) Missing / Mismatched Content Inventory (Text / Labels / Options)

### Global i18n (`src/lib/i18n.tsx`)

Laravel `lang/en/budgets.php` + `lang/pt/budgets.php` + `lang/*/onboarding.php` + `lang/*/landing.php` **do not** cover:

- All strings embedded in **SettingsPage.tsx**, **ProfilePage.tsx**, **TransactionsPage.tsx**, etc. (hundreds of literals / conditional PT branches across files).
- React `i18n.tsx` only defines a **small** subset; most PT/EN in the product is **inline `language === "pt"`** in components — Laravel must copy those **exact strings** per screen when porting, not “clean them up.”

### Concrete mismatches already spotted

- **Sidebar admin item “Users”:** React **hardcodes** `"Users"` in `AppLayout.tsx` (not `t("nav.users")`). Laravel used `__('budgets.nav.users')` — **wording can diverge** from React’s hardcoded English. **Fix: hardcode `Users` to match source.**
- **404 page:** React uses specific strings (including PT spellings without accents in places). Laravel used `__('budgets.not_found.*')` which may differ. **Fix: match `NotFound.tsx` literals exactly.**

### Landing (`LandingPage.tsx` + sections)

Laravel landing was rebuilt from structured lang files; still require **line-by-line classList** diff vs each `HeroSection.tsx`, `HowItWorksSection.tsx`, etc., for **pixel** sign-off.

---

## 4) Missing / Mismatched UI/UX Inventory

### Spacing / layout (examples)

- **`AppLayout` main padding:** React uses `pb-36` default + `pb-44` when `showAddBar`, with explicit `md:pb-8`. Laravel `app.blade.php` uses similar tokens — **needs measured diff** (not yet verified pixel-equal).
- **Mobile breakpoint:** React `useIsMobile` uses **`< 1024px`**. Laravel must ensure **same** breakpoint for all `lg:` decisions (plan noted 1023px).

### Interactions

- **Transactions:** grouped-by-date headers (“Today”, “Yesterday”), detail drawer, create flow, recurring drawer, smart suggestions, save pipeline — **missing**.
- **Search:** React filters mock rows; Laravel previously static placeholder — **correction started** toward same mock + filter + links.
- **Notifications:** React list + read toggles — Laravel static — **missing**.

### Animations

- Any `motion.*` / `AnimatePresence` — **not replicated** unless a JS motion bundle is added (pre-identified blocker for “identical”).

---

## 5) Exact Correction Plan (file-targeted)

> Rule: each row maps **original reference → Laravel target → required action**.

| # | Original reference | Laravel target | Action |
|---|--------------------|----------------|--------|
| P0 | `App.tsx` shell | `layouts/*.blade.php` + `resources/js/*` | Port or explicitly document: Tooltip, Toasters, Suspense fallback equivalence |
| P0 | `AppLayout.tsx` | `layouts/app.blade.php` + `components/app-sidebar.blade.php` + `mobile-bottom-nav.blade.php` | Match classes + behaviors (`useMobileChrome` parity) |
| P0 | `TopBar.tsx` `SearchPanel` | `layouts/app.blade.php` (search overlay) or `components/search-panel.blade.php` | Match markup/classes/placeholder/results/empty |
| P0 | `TopBar.tsx` `NotificationPanel` | same | Port mock notifications + interactions |
| P1 | `TransactionsPage.tsx` | `transactions-page.blade.php` + `TransactionsPage.php` | Full port: list UI, drawers, query params, mutations |
| P1 | `BudgetsPage.tsx` | budgets livewire view | Full port |
| P1 | `GoalsPage.tsx` | goals livewire view | Full port |
| P1 | `SubscriptionsPage.tsx` | subscriptions livewire view | Full port |
| P1 | `DebtsPage.tsx` | debts livewire view | Full port |
| P2 | `ImportPage.tsx` | import livewire view | Full port |
| P2 | `SettingsPage.tsx` | settings livewire view | Full port |
| P2 | `ProfilePage.tsx` | profile livewire view | Full port |
| P2 | `AIAdvisorPage.tsx` | ai-advisor livewire view | Full port |
| P3 | `DashboardPage.tsx` | dashboard livewire view + partials | Line-by-line diff |
| P3 | `InsightsPage.tsx` | insights livewire view | Line-by-line diff |
| P3 | `AdminPage.tsx` / `UsersPage.tsx` / `AnalyticsPage.tsx` | admin views | Column/control parity |
| P3 | `LandingPage.tsx` + sections | `landing-index.blade.php` | Pixel diff pass |
| P3 | `OnboardingPage.tsx` | `onboarding-page.blade.php` | Motion parity or document |
| P3 | `NotFound.tsx` | `errors/not-found.blade.php` | Exact copy |
| PX | `src/lib/live-data.ts` + Supabase | Laravel services | Only if “exact” includes wire protocol — otherwise **explicit gap** |

---

## 6) Implementation (status for this change set)

**Completed in repository alongside this audit (incremental, not full completion):**

1. **`REPLICATION_AUDIT.md`** (this document): Phases **1–5** + scaffolding for **7–8**.
2. **`resources/views/layouts/app.blade.php` — Search overlay:** Reworked to mirror `src/components/shared/TopBar.tsx` **`SearchPanel`**: `pt-[15vh]`, `bg-foreground/20`, inner `bg-card rounded-3xl max-w-lg border border-border/60 shadow-sm`, header row with search icon + full-width input + `ESC` kbd, **exact EN/PT placeholders** from source, **same six mock rows** (types/names/paths localized like React), **filter when `query.length > 1`**, **“No results found” / “Nenhum resultado encontrado”**, `wire:navigate` links, click-away close (unchanged).
3. **`resources/views/errors/not-found.blade.php`:** Matches **`NotFound.tsx`** visible strings (`404`, EN/PT lines, home link labels) and adds **`console.error`** with attempted path (React logs `location.pathname`).
4. **`resources/views/components/app-sidebar.blade.php`:** Admin **Users** item label set to literal **`Users`** to match **`AppLayout.tsx` line 140** (React does not use `t()` for that label).

**Not completed (requires continued work):** all **P1/P2/P3** rows in Section 5 — this is the bulk of the product (full page ports).

---

## 7) Pixel-Fidelity QA Checklist (strict)

For **each** route, at **375 / 768 / 1024 / 1280+**:

- [ ] Route exists and renders without console errors
- [ ] Section order matches React DOM order
- [ ] Every visible string matches React (including PT branch literals where applicable)
- [ ] Every icon matches (lucide name + size classes)
- [ ] Every interactive control exists (buttons, tabs, toggles, inputs, selects)
- [ ] Every modal/drawer opens/closes with same triggers (including `?create=` / `?search=`)
- [ ] Tables: same columns, same badges, same empty states
- [ ] Hover/focus/active styles match (class-level)
- [ ] Spacing: compare computed styles in devtools (target: equal)
- [ ] Mobile nav / FAB / add pill parity with `useIsMobile` breakpoint
- [ ] Reduced motion: React `MotionConfig` + CSS — verify Laravel mirrors preference behavior

**Current expected result:** checklist **fails** for most app routes until P1–P3 ports are done.

---

## 8) Remaining Gap Report (honest blockers)

### Still mismatched after this pass

- **All major entity pages** (Transactions/Budgets/Goals/Subscriptions/Debts/Settings/Profile/Import/AI Advisor): still **not** full ports.
- **Radix/shadcn primitives** (focus traps, select typeahead, etc.): **not** identical without **React islands** or **high-effort custom JS**.
- **Framer Motion**: **not** identical without a **shared motion runtime** in Vite.
- **TanStack Query + optimistic updates + optional Supabase**: **not** identical on the wire; Laravel needs **explicit product decision** (server-backed vs client SDK).
- **Sonner/Radix toaster pairing** from `App.tsx`: not replicated as same component stack.

### What “exact reproduction” requires next

1. Freeze a **screenshot + DOM snapshot baseline** per route from React (Storybook or running app).
2. Port **one route at a time**, diffing class strings and text literals until snapshots match.
3. Only declare “done” when **Section 7** passes for **every** route — until then the product remains **non-compliant** with the stated acceptance criteria.

---

## Acceptance rule statement (compliance)

Per the user’s non-negotiable acceptance list: the Laravel app **does not yet qualify** as “visually and behaviorally indistinguishable.” This audit exists to prevent false completion claims and to drive **sequential, verifiable** reconstruction.
