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
|
# IDE and editor files
|
||||||
.vscode/
|
.vscode/
|
||||||
.idea/
|
.idea/
|
||||||
|
.cursor/
|
||||||
*.swp
|
*.swp
|
||||||
*.swo
|
*.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