chore: remove IDE artifacts and update gitignore
- Remove .cursor/ folder from tracking (plans, worktrees, rules) - Remove sim-api-test-log.csv from tracking - Add .cursor/ and *.csv to gitignore
This commit is contained in:
parent
b957877c6f
commit
70f65cedaa
@ -1,350 +0,0 @@
|
||||
<!-- 67f8fea5-b6cb-4187-8097-25ccb37e1dcf fa268fdd-dd67-4003-bb94-8236ed95ab44 -->
|
||||
|
||||
# Domain & BFF Clean Architecture Refactoring
|
||||
|
||||
## Overview
|
||||
|
||||
Establish clean separation between domain (business logic) and BFF (infrastructure) layers by:
|
||||
|
||||
1. Removing redundant mapper service wrappers in BFF
|
||||
2. Moving query builders from domain to BFF integration
|
||||
3. Using domain mappers directly in BFF services
|
||||
4. Eliminating unnecessary transformation layers
|
||||
|
||||
## Current Issues
|
||||
|
||||
### 1. Query Builders in Wrong Layer
|
||||
|
||||
**Location**: `packages/domain/orders/providers/salesforce/query.ts`
|
||||
|
||||
- `buildOrderSelectFields()`, `buildOrderItemSelectFields()`, `buildOrderItemProduct2Fields()`
|
||||
- These are SOQL infrastructure concerns, not business logic
|
||||
- Domain should not know about Salesforce query language
|
||||
|
||||
### 2. Redundant Mapper Service Wrapper
|
||||
|
||||
**Location**: `apps/bff/src/modules/orders/services/order-whmcs-mapper.service.ts`
|
||||
|
||||
- Just wraps `Providers.Whmcs.mapFulfillmentOrderItems()` from domain
|
||||
- Adds logging but no transformation logic
|
||||
- Creates confusion about where mapping lives
|
||||
|
||||
### 3. Double Transformation Pattern
|
||||
|
||||
**Current Flow**:
|
||||
|
||||
```
|
||||
BFF query → Raw SF data → Domain mapper → Domain type → BFF mapper??? → Same type
|
||||
```
|
||||
|
||||
**Should Be**:
|
||||
|
||||
```
|
||||
BFF query → Raw SF data → Domain mapper → Domain type → Use directly
|
||||
```
|
||||
|
||||
### 4. Catalog Services Do It Correctly
|
||||
|
||||
**Good Example**: `apps/bff/src/modules/catalog/services/sim-catalog.service.ts`
|
||||
|
||||
```typescript
|
||||
const product = CatalogProviders.Salesforce.mapSimProduct(record, entry);
|
||||
// Uses domain mapper directly, no BFF wrapper!
|
||||
```
|
||||
|
||||
## Architecture Principles
|
||||
|
||||
### Domain Layer (`packages/domain/`)
|
||||
|
||||
**Contains**:
|
||||
|
||||
- ✅ Business types (OrderDetails, OrderSummary)
|
||||
- ✅ Raw provider types (SalesforceOrderRecord)
|
||||
- ✅ Validation schemas (Zod)
|
||||
- ✅ Transformation mappers (Raw → Domain)
|
||||
- ✅ Business validation functions
|
||||
|
||||
**Does NOT Contain**:
|
||||
|
||||
- ❌ Query builders (SOQL, GraphQL)
|
||||
- ❌ Field configuration
|
||||
- ❌ HTTP/API concerns
|
||||
|
||||
### BFF Integration Layer (`apps/bff/src/integrations/`)
|
||||
|
||||
**Contains**:
|
||||
|
||||
- ✅ Query builders (SOQL construction)
|
||||
- ✅ Connection services
|
||||
- ✅ Integration services that:
|
||||
- Build queries
|
||||
- Execute queries
|
||||
- Use domain mappers
|
||||
- Return domain types
|
||||
|
||||
**Does NOT Contain**:
|
||||
|
||||
- ❌ Additional mapping logic
|
||||
- ❌ Business validation
|
||||
|
||||
### BFF Application Layer (`apps/bff/src/modules/`)
|
||||
|
||||
**Contains**:
|
||||
|
||||
- ✅ Orchestrators (workflow coordination)
|
||||
- ✅ Controllers (HTTP endpoints)
|
||||
- ✅ Uses integration services
|
||||
- ✅ Uses domain types directly
|
||||
|
||||
**Does NOT Contain**:
|
||||
|
||||
- ❌ Direct Salesforce queries
|
||||
- ❌ Mapper service wrappers
|
||||
- ❌ Double transformations
|
||||
|
||||
## Refactoring Steps
|
||||
|
||||
### Phase 1: Create Salesforce Integration Services
|
||||
|
||||
#### 1.1 Create `SalesforceOrderService`
|
||||
|
||||
**File**: `apps/bff/src/integrations/salesforce/services/salesforce-order.service.ts`
|
||||
|
||||
Encapsulates all Salesforce order operations:
|
||||
|
||||
- `getOrderById(orderId): Promise<OrderDetails | null>`
|
||||
- `getOrdersForAccount(accountId): Promise<OrderSummary[]>`
|
||||
- Builds queries internally
|
||||
- Uses domain mappers for transformation
|
||||
- Returns domain types
|
||||
|
||||
**Benefits**:
|
||||
|
||||
- Encapsulation of SF-specific logic
|
||||
- Easy to test
|
||||
- Easy to swap providers
|
||||
- No SF details leak to application layer
|
||||
|
||||
#### 1.2 Update OrderOrchestrator
|
||||
|
||||
- Remove direct `this.sf.query()` calls
|
||||
- Inject and use `SalesforceOrderService`
|
||||
- Remove query building logic
|
||||
- Just coordinate workflows
|
||||
|
||||
### Phase 2: Move Query Builders
|
||||
|
||||
#### 2.1 Move Query Builders to BFF
|
||||
|
||||
**From**: `packages/domain/orders/providers/salesforce/query.ts`
|
||||
|
||||
**To**: `apps/bff/src/integrations/salesforce/utils/order-query-builder.ts`
|
||||
|
||||
Move these functions:
|
||||
|
||||
- `buildOrderSelectFields()`
|
||||
- `buildOrderItemSelectFields()`
|
||||
- `buildOrderItemProduct2Fields()`
|
||||
|
||||
#### 2.2 Clean Domain Exports
|
||||
|
||||
Remove query builder exports from:
|
||||
|
||||
- `packages/domain/orders/providers/salesforce/index.ts`
|
||||
- `packages/domain/orders/providers/index.ts`
|
||||
- `packages/domain/orders/index.ts`
|
||||
|
||||
### Phase 3: Remove Redundant Mapper Services
|
||||
|
||||
#### 3.1 Delete OrderWhmcsMapper Service
|
||||
|
||||
**File to DELETE**: `apps/bff/src/modules/orders/services/order-whmcs-mapper.service.ts`
|
||||
|
||||
It only wraps domain mappers - provides no value.
|
||||
|
||||
#### 3.2 Update OrderFulfillmentOrchestrator
|
||||
|
||||
Replace:
|
||||
|
||||
```typescript
|
||||
constructor(private orderWhmcsMapper: OrderWhmcsMapper) {}
|
||||
const result = this.orderWhmcsMapper.mapOrderItemsToWhmcs(items);
|
||||
```
|
||||
|
||||
With:
|
||||
|
||||
```typescript
|
||||
import { Providers } from "@customer-portal/domain/orders";
|
||||
const result = Providers.Whmcs.mapFulfillmentOrderItems(items);
|
||||
```
|
||||
|
||||
**Direct domain mapper usage** - single transformation!
|
||||
|
||||
#### 3.3 Update orders.module.ts
|
||||
|
||||
- Remove `OrderWhmcsMapper` from providers
|
||||
- Remove import statement
|
||||
|
||||
### Phase 4: Verify Catalog Pattern Consistency
|
||||
|
||||
Catalog services already follow the clean pattern - verify they continue to:
|
||||
|
||||
- Build queries in BFF service layer
|
||||
- Use `CatalogProviders.Salesforce.mapXXXProduct()` directly
|
||||
- Return domain types without additional mapping
|
||||
|
||||
### Phase 5: Clean Up Field Configuration (If Unused)
|
||||
|
||||
**Investigation needed**: Check if `SalesforceFieldConfigService` is actually used.
|
||||
|
||||
If NOT used in order/catalog flows:
|
||||
|
||||
- Consider removing or documenting as future feature
|
||||
- Field names are already defined in raw types
|
||||
|
||||
### Phase 6: Documentation Updates
|
||||
|
||||
#### 6.1 Update Domain README
|
||||
|
||||
- Clarify that query builders don't belong in domain
|
||||
- Add architecture diagram showing clear boundaries
|
||||
|
||||
#### 6.2 Create Integration Layer Guide
|
||||
|
||||
Document:
|
||||
|
||||
- When to create integration services
|
||||
- Pattern: Query → Transform → Return domain type
|
||||
- No additional mapping in BFF
|
||||
|
||||
#### 6.3 Update ORDERS-ARCHITECTURE-REVIEW.md
|
||||
|
||||
- Mark query builders as moved
|
||||
- Mark mapper wrappers as removed
|
||||
- Show final clean architecture
|
||||
|
||||
## File Changes Summary
|
||||
|
||||
### Files to CREATE
|
||||
|
||||
1. `apps/bff/src/integrations/salesforce/services/salesforce-order.service.ts`
|
||||
2. `apps/bff/src/integrations/salesforce/utils/order-query-builder.ts`
|
||||
|
||||
### Files to MODIFY
|
||||
|
||||
3. `apps/bff/src/modules/orders/services/order-orchestrator.service.ts` - Use SalesforceOrderService
|
||||
4. `apps/bff/src/modules/orders/services/order-fulfillment-orchestrator.service.ts` - Use domain mapper directly
|
||||
5. `apps/bff/src/modules/orders/orders.module.ts` - Update providers
|
||||
6. `apps/bff/src/integrations/salesforce/salesforce.module.ts` - Export new service
|
||||
7. `packages/domain/orders/providers/salesforce/index.ts` - Remove query exports
|
||||
8. `packages/domain/orders/providers/index.ts` - Remove query exports
|
||||
9. `packages/domain/orders/index.ts` - Remove query exports
|
||||
|
||||
### Files to DELETE
|
||||
|
||||
10. `apps/bff/src/modules/orders/services/order-whmcs-mapper.service.ts`
|
||||
11. `packages/domain/orders/providers/salesforce/query.ts`
|
||||
|
||||
### Documentation to UPDATE
|
||||
|
||||
12. `packages/domain/README.md`
|
||||
13. `ORDERS-ARCHITECTURE-REVIEW.md`
|
||||
14. Create: `docs/BFF-INTEGRATION-PATTERNS.md`
|
||||
|
||||
## Expected Outcomes
|
||||
|
||||
### Architecture Cleanliness
|
||||
|
||||
- ✅ Single source of truth for transformations (domain mappers)
|
||||
- ✅ Clear separation: domain = business, BFF = infrastructure
|
||||
- ✅ No redundant mapping layers
|
||||
- ✅ Query logic in correct layer (BFF integration)
|
||||
|
||||
### Code Quality
|
||||
|
||||
- ✅ Easier to test (clear boundaries)
|
||||
- ✅ Easier to maintain (no duplication)
|
||||
- ✅ Easier to understand (one transformation path)
|
||||
- ✅ Easier to swap providers (integration services encapsulate)
|
||||
|
||||
### Developer Experience
|
||||
|
||||
- ✅ Clear patterns to follow
|
||||
- ✅ No confusion about where code goes
|
||||
- ✅ Consistent with catalog services
|
||||
- ✅ Self-documenting architecture
|
||||
|
||||
## Migration Notes
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
**None for consumers** - All changes are internal refactoring
|
||||
|
||||
### Testing
|
||||
|
||||
- Unit test new `SalesforceOrderService`
|
||||
- Verify order creation flow still works
|
||||
- Verify order fulfillment flow still works
|
||||
- Verify catalog fetching still works
|
||||
|
||||
### Rollback Plan
|
||||
|
||||
Git history preserves old structure - can revert commits if issues arise.
|
||||
|
||||
## Success Criteria
|
||||
|
||||
- [x] Query builders moved to BFF integration layer
|
||||
- [x] `OrderWhmcsMapper` service deleted
|
||||
- [x] `SalesforceOrderService` created and used
|
||||
- [x] `OrderOrchestrator` no longer builds SOQL queries
|
||||
- [x] `OrderFulfillmentOrchestrator` uses domain mapper directly
|
||||
- [x] Domain exports cleaned (no query builders)
|
||||
- [x] Documentation updated
|
||||
- [x] All tests passing (no linting errors)
|
||||
- [x] Order creation works end-to-end (ready for testing)
|
||||
- [x] Order fulfillment works end-to-end (ready for testing)
|
||||
|
||||
---
|
||||
|
||||
**Final Architecture**:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────┐
|
||||
│ Controller (HTTP) │
|
||||
└──────────────┬──────────────────────────┘
|
||||
│
|
||||
┌──────────────▼──────────────────────────┐
|
||||
│ Orchestrator (Application) │
|
||||
│ - Coordinates workflows │
|
||||
│ - Uses Integration Services │
|
||||
│ - Works with Domain Types │
|
||||
└──────────────┬──────────────────────────┘
|
||||
│
|
||||
┌──────────┴──────────┐
|
||||
│ │
|
||||
┌───▼───────────┐ ┌──────▼──────────────┐
|
||||
│ Domain │ │ Integration │
|
||||
│ (Business) │ │ (Infrastructure) │
|
||||
│ │ │ │
|
||||
│ • Types │ │ • SF OrderService │
|
||||
│ • Schemas │ │ • Query Builders │
|
||||
│ • Mappers ────┼──┤ • Connections │
|
||||
│ • Validators │ │ • Field Mapping │
|
||||
└───────────────┘ └─────────────────────┘
|
||||
|
||||
Flow: Query (BFF) → Raw Data → Domain Mapper → Domain Type → Use Directly
|
||||
└─ One transformation, no duplication ─┘
|
||||
```
|
||||
|
||||
### To-dos
|
||||
|
||||
- [x] Create SalesforceOrderService in BFF integration layer with methods: getOrderById, getOrdersForAccount
|
||||
- [x] Move query builders from packages/domain/orders/providers/salesforce/query.ts to apps/bff/src/integrations/salesforce/utils/order-query-builder.ts
|
||||
- [x] Update OrderOrchestrator to use SalesforceOrderService instead of direct SF queries
|
||||
- [x] Delete redundant OrderWhmcsMapper service wrapper
|
||||
- [x] Update OrderFulfillmentOrchestrator to use domain Providers.Whmcs mapper directly
|
||||
- [x] Remove query builder exports from domain package index files
|
||||
- [x] Update orders.module.ts and salesforce.module.ts with new services
|
||||
- [x] Verify catalog services follow same clean pattern (already correct)
|
||||
- [x] Update domain README and architecture documentation with clean patterns
|
||||
- [x] Test order creation and fulfillment flows end-to-end
|
||||
@ -1,390 +0,0 @@
|
||||
---
|
||||
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**
|
||||
@ -1,10 +0,0 @@
|
||||
---
|
||||
alwaysApply: true
|
||||
---
|
||||
## Codebase Coding Standard
|
||||
|
||||
1. Have types and validation in the shared domain layer.
|
||||
2. Keep business logic out of the frontend; use services and APIs instead.
|
||||
3. Reuse existing types and functions; extend them when additional behavior is needed.
|
||||
4. Read and understand the structures and workflows documented in docs. Start from docs/README.md
|
||||
5. Follow structures and our codebase rules inside docs/development directory
|
||||
@ -1,3 +0,0 @@
|
||||
{
|
||||
"setup-worktree": ["pnpm install"]
|
||||
}
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@ -31,6 +31,7 @@ build/
|
||||
# IDE and editor files
|
||||
.vscode/
|
||||
.idea/
|
||||
.cursor/
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
|
||||
@ -1 +0,0 @@
|
||||
Timestamp,API Endpoint,API Method,Phone Number,SIM Identifier,Request Payload,Response Status,Error,Additional Info
|
||||
|
Loading…
x
Reference in New Issue
Block a user