---
name: Restructure to Account Portal
overview: Restructure the app to have public pages under (public)/ and all authenticated portal pages under /account/*, with auth-aware headers in public shells.
todos:
  - id: auth-aware-public-shell
    content: "Make PublicShell auth-aware: show 'My Account' for logged-in users, 'Sign in' for guests"
    status: pending
  - id: auth-aware-catalog-shell
    content: Make CatalogShell auth-aware with same pattern
    status: pending
  - id: create-account-layout
    content: Create account/layout.tsx with AppShell and auth guard redirect
    status: pending
  - id: move-dashboard-to-account
    content: Move dashboard page to account/page.tsx
    status: pending
  - id: move-billing-to-account
    content: Move billing pages to account/billing/*
    status: pending
  - id: move-subscriptions-to-services
    content: Move subscriptions to account/services/*
    status: pending
  - id: move-orders-to-account
    content: Move orders to account/orders/*
    status: pending
  - id: move-support-to-account
    content: Move support cases to account/support/*
    status: pending
  - id: move-profile-to-settings
    content: Move account/profile to account/settings/*
    status: pending
  - id: fix-shop-double-header
    content: Fix shop layout to not create double header - add CatalogNav only
    status: pending
  - id: create-contact-route
    content: Create (public)/contact/page.tsx for contact form
    status: pending
  - id: update-navigation
    content: Update AppShell navigation.ts with /account/* paths
    status: pending
  - id: update-catalog-links
    content: Replace all /catalog links with /shop
    status: pending
  - id: update-portal-links
    content: Replace all old portal links with /account/* paths
    status: pending
  - id: remove-sfnumber
    content: Remove sfNumber from domain schema and signup components
    status: pending
  - id: delete-old-authenticated
    content: Delete (authenticated)/ directory after migration
    status: pending
  - id: rebuild-test
    content: Rebuild domain package and test all routes
    status: pending
---

# Restructure Portal to /account/\* Architecture

## Target Architecture

```mermaid
flowchart TB
    subgraph public ["(public)/ - Public Pages"]
        P1["/"] --> Home["Homepage"]
        P2["/auth/*"] --> Auth["Login, Signup, etc"]
        P3["/shop/*"] --> Shop["Product Catalog"]
        P4["/help"] --> Help["FAQ & Knowledge Base"]
        P5["/contact"] --> Contact["Contact Form"]
        P6["/order/*"] --> Order["Checkout Flow"]
    end

    subgraph account ["/account/* - My Portal"]
        A1["/account"] --> Dashboard["Dashboard"]
        A2["/account/billing"] --> Billing["Invoices & Payments"]
        A3["/account/services"] --> Services["My Subscriptions"]
        A4["/account/orders"] --> Orders["Order History"]
        A5["/account/support"] --> Support["My Tickets"]
        A6["/account/settings"] --> Settings["Profile Settings"]
    end

    public -.->|"Auth-aware header"| account
```

---

## Phase 1: Make Shells Auth-Aware

### 1.1 Update PublicShell

**File:** `apps/portal/src/components/templates/PublicShell/PublicShell.tsx`

Add auth detection to header navigation:

```tsx
"use client";
import { useAuthStore } from "@/features/auth/services/auth.store";

export function PublicShell({ children }: PublicShellProps) {
  const { isAuthenticated } = useAuthStore();

  return (
    <div className="min-h-screen...">
      <header>
        <nav>
          <Link href="/shop">Services</Link>
          <Link href="/help">Support</Link>

          {isAuthenticated ? (
            <Link href="/account" className="primary-button">
              My Account
            </Link>
          ) : (
            <Link href="/auth/login" className="primary-button">
              Sign in
            </Link>
          )}
        </nav>
      </header>
      ...
    </div>
  );
}
```

### 1.2 Update CatalogShell

**File:** `apps/portal/src/components/templates/CatalogShell/CatalogShell.tsx`

Same auth-aware pattern - show "My Account" or "Sign in" based on auth state.

---

## Phase 2: Create /account Route Structure

### 2.1 Create Account Layout with Auth Guard

**File:** `apps/portal/src/app/account/layout.tsx` (NEW)

```tsx
import { redirect } from "next/navigation";
import { cookies } from "next/headers";
import { AppShell } from "@/components/organisms/AppShell";

export default async function AccountLayout({ children }: { children: React.ReactNode }) {
  const cookieStore = await cookies();
  const hasAuthToken = cookieStore.has("access_token");

  if (!hasAuthToken) {
    redirect("/auth/login?redirect=/account");
  }

  return <AppShell>{children}</AppShell>;
}
```

### 2.2 Create Account Pages

Move and rename pages:

| Current Path | New Path | New File |

|--------------|----------|----------|

| `(authenticated)/dashboard/page.tsx` | `/account` | `account/page.tsx` |

| `(authenticated)/billing/*` | `/account/billing/*` | `account/billing/*` |

| `(authenticated)/subscriptions/*` | `/account/services/*` | `account/services/*` |

| `(authenticated)/orders/*` | `/account/orders/*` | `account/orders/*` |

| `(authenticated)/support/*` | `/account/support/*` | `account/support/*` |

| `(authenticated)/account/*` | `/account/settings/*` | `account/settings/*` |

---

## Phase 3: Update Navigation

### 3.1 Update AppShell Navigation

**File:** `apps/portal/src/components/organisms/AppShell/navigation.ts`

Update all paths to use `/account/*`:

```typescript
export const baseNavigation: NavigationItem[] = [
  { name: "Dashboard", href: "/account", icon: HomeIcon },
  { name: "Orders", href: "/account/orders", icon: ClipboardDocumentListIcon },
  {
    name: "Billing",
    icon: CreditCardIcon,
    children: [
      { name: "Invoices", href: "/account/billing/invoices" },
      { name: "Payment Methods", href: "/account/billing/payments" },
    ],
  },
  {
    name: "My Services",
    icon: ServerIcon,
    children: [{ name: "All Services", href: "/account/services" }],
  },
  { name: "Shop", href: "/shop", icon: Squares2X2Icon }, // Links to public shop
  {
    name: "Support",
    icon: ChatBubbleLeftRightIcon,
    children: [
      { name: "My Tickets", href: "/account/support" },
      { name: "New Ticket", href: "/account/support/new" },
    ],
  },
  { name: "Settings", href: "/account/settings", icon: UserIcon },
  { name: "Log out", href: "#", icon: ArrowRightStartOnRectangleIcon, isLogout: true },
];
```

---

## Phase 4: Fix Public Routes

### 4.1 Fix Double Header in Shop

Remove the nested shell issue by having CatalogShell NOT render a full page wrapper, or by not nesting it under PublicShell.

**Option A:** Move shop out of (public) to its own route with CatalogShell only

**Option B:** Have (public)/shop/layout.tsx return just children with catalog nav (no shell)

Recommended: **Option B** - Keep shop under (public) but have shop layout add only catalog navigation, not a full shell.

**File:** `apps/portal/src/app/(public)/shop/layout.tsx`

```tsx
import { CatalogNav } from "@/components/templates/CatalogShell";

export default function ShopLayout({ children }: { children: React.ReactNode }) {
  // Don't wrap with another shell - parent (public) layout already has PublicShell
  return (
    <>
      <CatalogNav />
      {children}
    </>
  );
}
```

**File:** `apps/portal/src/components/templates/CatalogShell/CatalogShell.tsx`

Split into two exports:

- `CatalogShell` - full shell (if ever needed standalone)
- `CatalogNav` - just the navigation bar

### 4.2 Create /contact Route

**File:** `apps/portal/src/app/(public)/contact/page.tsx` (NEW)

Move content from `(public)/help/contact/` to `(public)/contact/`.

---

## Phase 5: Delete Old Routes

### 5.1 Delete (authenticated) Directory

After moving all content to /account/:

- Delete entire `apps/portal/src/app/(authenticated)/` directory

### 5.2 Clean Up Unused Files

- Delete `(public)/help/contact/` (moved to /contact)
- Keep `(public)/help/page.tsx` for FAQ

---

## Phase 6: Update All Internal Links

### 6.1 Update /catalog to /shop Links

Replace in feature components (11 files, 27 occurrences):

```
/catalog → /shop
/catalog/internet → /shop/internet
/catalog/sim → /shop/sim
/catalog/vpn → /shop/vpn
```

### 6.2 Update Dashboard/Portal Links

Replace throughout codebase:

```
/dashboard → /account
/billing → /account/billing
/subscriptions → /account/services
/orders → /account/orders
/support/cases → /account/support
```

---

## Phase 7: Remove sfNumber from Signup

### 7.1 Update Domain Schema

**File:** `packages/domain/auth/schema.ts`

```typescript
// Line 44: Remove required sfNumber
// Before:
sfNumber: z.string().min(6, "Customer number must be at least 6 characters"),

// After:
sfNumber: z.string().optional(),
```

Also update `validateSignupRequestSchema` to not require sfNumber.

### 7.2 Update SignupForm Components

- `SignupForm.tsx` - Remove sfNumber from initialValues and validation
- `AccountStep.tsx` - Remove Customer Number form field
- `ReviewStep.tsx` - Remove Customer Number display

---

## Phase 8: Rebuild and Test

### 8.1 Rebuild Domain Package

```bash
pnpm --filter @customer-portal/domain build
```

### 8.2 Test Matrix

| Scenario | URL | Expected |

|----------|-----|----------|

| Public homepage | `/` | PublicShell, homepage content |

| Public shop | `/shop` | CatalogShell (auth-aware), products |

| Auth user in shop | `/shop` | "My Account" button, personalized pricing |

| Public help | `/help` | FAQ content |

| Public contact | `/contact` | Contact form, prefills if logged in |

| Login | `/auth/login` | Login form |

| Signup | `/auth/signup` | No sfNumber field |

| Account dashboard | `/account` | AppShell, dashboard (redirect if not auth) |

| My services | `/account/services` | Subscriptions list |

| My tickets | `/account/support` | Support cases |

| Checkout | `/order` | CheckoutShell, wizard |

---

## Files Summary

| Category | Action | Count |

|----------|--------|-------|

| New account/ routes | Create | ~15 files |

| Shell components | Modify | 2 (PublicShell, CatalogShell) |

| Shop layout | Modify | 1 |

| Navigation | Modify | 1 |

| Link updates | Modify | ~20 files |

| Domain schema | Modify | 1 |

| Signup components | Modify | 3 |

| Delete old routes | Delete | ~20 files |

**Total: ~60+ file operations**
