Refactor project structure and enhance documentation
- Removed the logging package from pnpm-lock.yaml to streamline dependencies. - Updated README.md to reflect changes in the backend architecture, including new integrations and improved service descriptions. - Enhanced Dockerfile configurations for both backend and frontend applications to ensure proper TypeScript compilation. - Introduced Suspense boundaries in LoginView and ServiceManagementSection components for better loading states. - Updated documentation paths in README.md to point to the new architecture directory for improved navigation. - Improved environment variable setup instructions for clarity and completeness.
This commit is contained in:
parent
cdfad9d036
commit
c2e9c15dab
243
README.md
243
README.md
@ -31,18 +31,21 @@ A modern customer portal where users can self-register, log in, browse & buy sub
|
||||
### Backend (BFF API)
|
||||
|
||||
- **NestJS 11** (Node 24 Current or 22 LTS)
|
||||
- **Prisma 6** ORM
|
||||
- **jsforce** for Salesforce integration
|
||||
- **WHMCS** API client
|
||||
- **BullMQ** for async jobs with ioredis
|
||||
- **Prisma 6** ORM with PostgreSQL 17
|
||||
- **jsforce** for Salesforce REST API integration
|
||||
- **salesforce-pubsub-api-client** for Salesforce Platform Events
|
||||
- **p-queue** for request throttling and queue management
|
||||
- **WHMCS** custom API client with comprehensive service layer
|
||||
- **Freebit** SIM management integration
|
||||
- **Zod-first validation** shared via the domain package
|
||||
- **Bcrypt** for password hashing
|
||||
|
||||
### Temporarily Disabled Modules
|
||||
### Queue Management
|
||||
|
||||
- `CasesModule` and `JobsModule` are intentionally excluded from the running
|
||||
NestJS application until their APIs and job processors are fully
|
||||
implemented. See `docs/TEMPORARY-DISABLED-MODULES.md` for re-enablement
|
||||
details and placeholder behaviour.
|
||||
- **p-queue** for intelligent request throttling to external APIs
|
||||
- Separate queues for Salesforce (standard + long-running) and WHMCS
|
||||
- Configurable concurrency, rate limiting, and timeout handling
|
||||
- Prevents API rate limit violations and resource exhaustion
|
||||
|
||||
### Logging
|
||||
|
||||
@ -56,31 +59,32 @@ A modern customer portal where users can self-register, log in, browse & buy sub
|
||||
### Data & Infrastructure
|
||||
|
||||
- **PostgreSQL 17** for users, ID mappings, and optional mirrors
|
||||
- **Redis 8** for cache and queues
|
||||
- **Redis 7** for cache, token blacklists, and rate limiting
|
||||
- **Docker** for local development (Postgres/Redis)
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
new-portal-website/
|
||||
customer-portal/
|
||||
├── apps/
|
||||
│ ├── portal/ # Next.js 15 frontend (React 19, Tailwind, shadcn/ui)
|
||||
│ └── bff/ # NestJS 11 backend (Prisma, BullMQ, Zod validation)
|
||||
│ └── bff/ # NestJS 11 backend (Prisma, p-queue, Zod validation)
|
||||
├── packages/
|
||||
│ ├── shared/ # Shared types and utilities
|
||||
│ └── api-client/ # Lightweight fetch helpers + shared Zod types
|
||||
│ ├── domain/ # Unified domain layer with contracts & schemas
|
||||
│ ├── validation/ # Unified validation service (NestJS + React)
|
||||
│ ├── logging/ # Centralized logging utilities (Pino)
|
||||
│ └── integrations/ # External service integrations
|
||||
│ ├── whmcs/ # WHMCS API client
|
||||
│ └── freebit/ # Freebit SIM management
|
||||
├── scripts/
|
||||
│ ├── dev/ # Development management scripts
|
||||
│ └── prod/ # Production deployment scripts
|
||||
├── config/
|
||||
│ ├── docker/
|
||||
│ │ └── compose-plesk.yaml # Plesk Docker stack (proxy / and /api)
|
||||
│ ├── prettier.config.js # Prettier configuration
|
||||
│ └── .editorconfig # Editor configuration
|
||||
├── docker/
|
||||
│ └── dev/ # Docker Compose for local development
|
||||
│ └── docker-compose.yml # PostgreSQL 17 + Redis 7
|
||||
├── docs/ # Comprehensive documentation
|
||||
├── secrets/ # Private keys (git ignored)
|
||||
├── .env.dev.example # Development environment template
|
||||
├── .env.production.example # Production environment template
|
||||
├── env/ # Environment file templates
|
||||
├── package.json # Root workspace configuration
|
||||
├── pnpm-workspace.yaml # pnpm workspace definition
|
||||
└── README.md # This file
|
||||
@ -101,18 +105,20 @@ new-portal-website/
|
||||
|
||||
```bash
|
||||
git clone <repository-url>
|
||||
cd new-portal-website
|
||||
cd customer-portal
|
||||
pnpm install
|
||||
```
|
||||
|
||||
2. **Setup Environment**
|
||||
|
||||
```bash
|
||||
# Copy development environment template
|
||||
cp .env.dev.example .env
|
||||
# Copy development environment template (if available)
|
||||
# Note: .env files may be filtered by .cursorignore
|
||||
# Contact your team for environment configuration
|
||||
|
||||
# Edit with your values (most defaults work for local development)
|
||||
nano .env
|
||||
# Required: DATABASE_URL, REDIS_URL, JWT_SECRET
|
||||
# Optional for basic dev: WHMCS, Salesforce, Freebit credentials
|
||||
```
|
||||
|
||||
3. **Start Development Environment**
|
||||
@ -154,27 +160,29 @@ pnpm type-check # Run TypeScript checks
|
||||
|
||||
```bash
|
||||
# Frontend
|
||||
docker build -t portal-frontend:latest -f apps/portal/Dockerfile .
|
||||
docker save -o portal-frontend.latest.tar portal-frontend:latest
|
||||
docker build -t customer-portal-frontend:latest -f apps/portal/Dockerfile .
|
||||
docker save -o customer-portal-frontend.latest.tar customer-portal-frontend:latest
|
||||
|
||||
# Backend
|
||||
docker build -t portal-backend:latest -f apps/bff/Dockerfile .
|
||||
docker save -o portal-backend.latest.tar portal-backend:latest
|
||||
docker build -t customer-portal-backend:latest -f apps/bff/Dockerfile .
|
||||
docker save -o customer-portal-backend.latest.tar customer-portal-backend:latest
|
||||
```
|
||||
|
||||
Upload the tar files in Plesk → Docker → Images → Upload, then deploy using `config/docker/compose-plesk.yaml` as a stack.
|
||||
Upload the tar files in Plesk → Docker → Images → Upload, then deploy using the appropriate compose stack configuration.
|
||||
|
||||
### API Client
|
||||
|
||||
The portal uses a lightweight fetch client that shares request/response contracts from
|
||||
The portal uses TanStack Query with a lightweight fetch client that shares request/response contracts from
|
||||
`@customer-portal/domain` and validates them with Zod:
|
||||
|
||||
```ts
|
||||
import { apiClient, getDataOrThrow } from "@/lib/api";
|
||||
import type { DashboardSummary } from "@customer-portal/domain";
|
||||
import { apiClient } from "@/lib/api-client";
|
||||
import type { DashboardSummary } from "@customer-portal/domain/dashboard";
|
||||
|
||||
const response = await apiClient.GET<DashboardSummary>("/api/me/summary");
|
||||
const summary = getDataOrThrow(response);
|
||||
const { data: summary } = useQuery({
|
||||
queryKey: ["dashboard", "summary"],
|
||||
queryFn: () => apiClient.get<DashboardSummary>("/api/me/summary"),
|
||||
});
|
||||
```
|
||||
|
||||
Because the schemas and types live in the shared domain package there is no separate
|
||||
@ -182,14 +190,17 @@ code generation step.
|
||||
|
||||
### Environment Configuration
|
||||
|
||||
- Local development: use the root `.env` (see `.env.example`).
|
||||
- Plesk production: use split env files (no secrets under `httpdocs`).
|
||||
- Frontend: `env/portal-frontend.env.sample` → ensure `NEXT_PUBLIC_API_BASE=/api`
|
||||
- Backend: `env/portal-backend.env.sample` → ensure `TRUST_PROXY=true`, DB uses `database:5432`, Redis uses `cache:6379`
|
||||
- See PLESK_DEPLOYMENT.md for full instructions and proxy rule setup.
|
||||
- Local development: configure environment variables (contact team for template)
|
||||
- Docker services use defaults: PostgreSQL (dev/dev/portal_dev), Redis (no auth)
|
||||
- Plesk production: use split env files (no secrets under `httpdocs`)
|
||||
- Frontend: ensure `NEXT_PUBLIC_API_BASE=/api`
|
||||
- Backend: ensure `TRUST_PROXY=true`, DB uses `database:5432`, Redis uses `cache:6379`
|
||||
- See deployment documentation for full instructions
|
||||
|
||||
#### Key Environment Variables
|
||||
|
||||
Required environment variables (contact your team for specific values):
|
||||
|
||||
```env
|
||||
# === Application ===
|
||||
NODE_ENV=development
|
||||
@ -206,17 +217,23 @@ NEXT_PUBLIC_APP_NAME=Customer Portal (Dev)
|
||||
NEXT_PUBLIC_ENABLE_DEVTOOLS=true
|
||||
|
||||
# === Security ===
|
||||
JWT_SECRET=dev_secret_for_local_development_minimum_32_chars_long
|
||||
BCRYPT_ROUNDS=10
|
||||
JWT_SECRET=<secure_secret_minimum_32_chars>
|
||||
JWT_REFRESH_SECRET=<different_secure_secret_minimum_32_chars>
|
||||
BCRYPT_ROUNDS=12
|
||||
|
||||
# === External APIs (optional for basic development) ===
|
||||
WHMCS_BASE_URL=https://demo.whmcs.com
|
||||
WHMCS_API_IDENTIFIER=your_demo_identifier
|
||||
WHMCS_API_SECRET=your_demo_secret
|
||||
SF_LOGIN_URL=https://test.salesforce.com
|
||||
SF_CLIENT_ID=your_dev_client_id
|
||||
SF_PRIVATE_KEY_PATH=./secrets/sf-dev.key
|
||||
SF_USERNAME=dev@yourcompany.com.sandbox
|
||||
# === External APIs (required for full functionality) ===
|
||||
WHMCS_BASE_URL=<your_whmcs_url>
|
||||
WHMCS_API_IDENTIFIER=<your_identifier>
|
||||
WHMCS_API_SECRET=<your_secret>
|
||||
|
||||
SF_LOGIN_URL=<salesforce_instance_url>
|
||||
SF_CLIENT_ID=<oauth_client_id>
|
||||
SF_PRIVATE_KEY_PATH=./secrets/sf-private.key
|
||||
SF_USERNAME=<salesforce_username>
|
||||
|
||||
FREEBIT_API_BASE_URL=<freebit_api_url>
|
||||
FREEBIT_CLIENT_ID=<freebit_client_id>
|
||||
FREEBIT_CLIENT_SECRET=<freebit_secret>
|
||||
```
|
||||
|
||||
#### Salesforce Pub/Sub (Events)
|
||||
@ -230,12 +247,14 @@ SF_PUBSUB_ENDPOINT=api.pubsub.salesforce.com:7443
|
||||
SF_PUBSUB_NUM_REQUESTED=25 # flow control window
|
||||
```
|
||||
|
||||
- Verify subscriber status: `GET /health/sf-events`
|
||||
- Verify subscriber status: `GET /api/health/sf-events`
|
||||
- `enabled`: whether Pub/Sub is enabled
|
||||
- `channel`: topic name
|
||||
- `replay.lastReplayId`: last committed cursor
|
||||
- `subscriber.status`: connected | disconnected | unknown
|
||||
|
||||
Read more about the provisioning flow in `docs/provisioning/RUNBOOK_PROVISIONING.md`.
|
||||
|
||||
### Development Tools Access
|
||||
|
||||
When running `pnpm dev:tools`, you get access to:
|
||||
@ -289,68 +308,115 @@ When running `pnpm dev:tools`, you get access to:
|
||||
### Support Cases (Salesforce)
|
||||
|
||||
- `GET /api/cases` - Cases list (cached 30-60s)
|
||||
- `GET /api/cases/:id` - Case details
|
||||
- `GET /api/cases/:id` - Case details with comments
|
||||
- `POST /api/cases` - Create new case
|
||||
- `POST /api/cases/:id/comments` - Add comment to case
|
||||
|
||||
### Webhooks
|
||||
### Webhooks & Events
|
||||
|
||||
- `POST /api/orders/:sfOrderId/fulfill` - Secure Salesforce-initiated order fulfillment
|
||||
- `POST /api/webhooks/whmcs` - WHMCS action hooks → update mirrors + bust cache
|
||||
- **Salesforce Platform Events** - Real-time order provisioning via gRPC Pub/Sub
|
||||
|
||||
## Frontend Pages
|
||||
|
||||
### Initial Pages
|
||||
### Public Pages
|
||||
|
||||
- `/` - Dashboard (next invoice due, active subs, open cases)
|
||||
- `/billing/invoices` - Invoice list
|
||||
- `/billing/invoices/[id]` - Invoice details
|
||||
- `/subscriptions` - Active subscriptions
|
||||
- `/support/cases` - Support cases list
|
||||
- `/support/cases/[id]` - Case details
|
||||
- `/support/new` - Create new case
|
||||
- `/account/profile` - User profile management
|
||||
- `/account/security` - Security settings
|
||||
- `/` - Landing page for non-authenticated users
|
||||
- `/auth/login` - Sign in
|
||||
- `/auth/signup` - Create account
|
||||
- `/auth/set-password` - Set password after WHMCS link
|
||||
|
||||
### Authenticated Pages
|
||||
|
||||
- `/dashboard` - Dashboard (invoices, active subs, orders)
|
||||
- `/catalog` - Product catalog home
|
||||
- `/catalog/internet` - Internet plans
|
||||
- `/catalog/vpn` - VPN products
|
||||
- `/checkout` - Checkout flow
|
||||
- `/orders` - Order list
|
||||
- `/orders/[id]` - Order details
|
||||
- `/subscriptions` - Active subscriptions
|
||||
- `/subscriptions/[id]` - Subscription details
|
||||
- `/billing/invoices` - Invoice list
|
||||
- `/billing/invoices/[id]` - Invoice details
|
||||
- `/billing/payments` - Payment methods
|
||||
- `/support/cases` - Support cases list
|
||||
- `/support/cases/[id]` - Case details
|
||||
- `/support/new` - Create new case
|
||||
- `/account` - User account management
|
||||
|
||||
## Development Milestones
|
||||
|
||||
### Milestone 1: Identity & Linking
|
||||
|
||||
- [ ] Portal login/signup
|
||||
- [ ] One-time WHMCS verification
|
||||
- [ ] Set new portal password
|
||||
- [ ] Store id_mappings
|
||||
- [x] Portal login/signup with JWT authentication
|
||||
- [x] One-time WHMCS verification with SSO
|
||||
- [x] Set new portal password (Bcrypt)
|
||||
- [x] Store id_mappings (user ↔ WHMCS ↔ Salesforce)
|
||||
- [x] Refresh token rotation
|
||||
- [x] Account lockout after failed attempts
|
||||
- [x] Rate limiting on auth endpoints
|
||||
|
||||
### Milestone 2: Billing
|
||||
### Milestone 2: Catalog & Orders
|
||||
|
||||
- [ ] Product catalog (GetProducts)
|
||||
- [ ] Checkout (AddOrder)
|
||||
- [ ] Invoice list/detail (GetInvoices)
|
||||
- [ ] WHMCS SSO deep links
|
||||
- [x] Product catalog (GetProducts from WHMCS)
|
||||
- [x] Catalog caching with CDC invalidation
|
||||
- [x] Internet plan catalog with address verification
|
||||
- [x] VPN product catalog
|
||||
- [x] Checkout flow with cart management
|
||||
- [x] Order creation (WHMCS AddOrder)
|
||||
- [x] Order list and details from Salesforce
|
||||
- [x] Real-time order provisioning via Salesforce Platform Events
|
||||
|
||||
### Milestone 3: Cases & Webhooks
|
||||
### Milestone 3: Billing & Invoices
|
||||
|
||||
- [ ] Salesforce case list/create
|
||||
- [ ] WHMCS webhooks → cache bust + mirrors
|
||||
- [ ] Nightly reconcile job (optional)
|
||||
- [x] Invoice list/detail (GetInvoices from WHMCS)
|
||||
- [x] Invoice caching with TTL
|
||||
- [x] WHMCS SSO deep links for payment
|
||||
- [x] Payment method management
|
||||
- [x] Payment gateway listing
|
||||
- [x] Subscription list and details
|
||||
- [x] WHMCS webhooks → cache bust + mirror updates
|
||||
|
||||
### Milestone 4: Support & Cases
|
||||
|
||||
- [x] Salesforce case list (cached)
|
||||
- [x] Case details with comments
|
||||
- [x] Create new support case
|
||||
- [x] Add comments to existing cases
|
||||
- [ ] Case file attachments
|
||||
- [ ] Email notifications for case updates
|
||||
|
||||
### Milestone 5: SIM Management & Provisioning
|
||||
|
||||
- [x] Freebit SIM management integration
|
||||
- [x] Order provisioning workflow
|
||||
- [x] Real-time event processing via Salesforce Platform Events
|
||||
- [x] Comprehensive error handling and retry logic
|
||||
- [ ] Customer-facing SIM management UI
|
||||
|
||||
## Security Features
|
||||
|
||||
- HTTPS only with HttpOnly/SameSite cookies
|
||||
- Optional MFA for portal accounts
|
||||
- JWT access + refresh tokens with Redis-backed blacklist
|
||||
- Bcrypt password hashing (configurable rounds)
|
||||
- Account lockout after failed login attempts
|
||||
- Rate limiting on auth endpoints and external API calls
|
||||
- Idempotency keys on all mutating operations
|
||||
- Row-level security (user must own resources)
|
||||
- PII minimization with encryption at rest/in transit
|
||||
- Audit logging for security-critical actions
|
||||
- No WHMCS/SF credentials exposed to browser
|
||||
|
||||
## Caching Strategy
|
||||
|
||||
- **Invoices**: 60-120s per page; bust on WHMCS webhook
|
||||
- **Cases**: 30-60s; bust after create/update
|
||||
- **Catalog**: 5-15m; manual bust on changes
|
||||
- **Invoices**: TTL-based (90s); bust on WHMCS webhook
|
||||
- **Catalog**: CDC-driven (no TTL); manual bust on data changes
|
||||
- **Orders**: CDC-driven (no TTL); real-time invalidation via Salesforce Platform Events
|
||||
- **WHMCS API responses**: TTL-based caching (configurable per endpoint)
|
||||
- **Redis-backed** with request coalescing to prevent thundering herd
|
||||
- **Keys include user_id** to prevent cross-user leakage
|
||||
- **Metrics tracking** for cache hits, misses, and invalidations
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
@ -375,10 +441,10 @@ pnpm dev:restart
|
||||
pnpm dev:reset
|
||||
```
|
||||
|
||||
**Environment Variables Not Loading**
|
||||
### Environment Variables Not Loading
|
||||
|
||||
- Ensure `.env` file exists in project root
|
||||
- Restart applications after changing `.env`
|
||||
- Ensure environment variables are configured (contact team for configuration)
|
||||
- Restart applications after changing environment variables
|
||||
- Check for typos in variable names
|
||||
- Frontend variables must start with `NEXT_PUBLIC_`
|
||||
|
||||
@ -421,7 +487,7 @@ rm -rf node_modules && pnpm install
|
||||
1. **Setup Development Environment**
|
||||
|
||||
```bash
|
||||
cp .env.dev.example .env
|
||||
# Configure environment variables (contact team)
|
||||
pnpm install
|
||||
pnpm dev:start
|
||||
```
|
||||
@ -440,9 +506,10 @@ rm -rf node_modules && pnpm install
|
||||
|
||||
4. **Code Quality**
|
||||
- Follow TypeScript strict mode
|
||||
- Use proper error handling [[memory:6689308]]
|
||||
- Implement clean, minimal UI designs [[memory:6676820]]
|
||||
- Avoid 'V2' suffixes in service names [[memory:6676816]]
|
||||
- Use proper error handling (no sensitive info exposed)
|
||||
- Implement clean, minimal UI designs
|
||||
- Avoid 'V2' suffixes in service names
|
||||
- Verify API integration against official documentation
|
||||
|
||||
## Documentation
|
||||
|
||||
|
||||
@ -41,7 +41,7 @@ COPY pnpm-workspace.yaml package.json pnpm-lock.yaml ./
|
||||
# Copy source code
|
||||
COPY packages/ ./packages/
|
||||
COPY apps/bff/ ./apps/bff/
|
||||
COPY tsconfig.json ./
|
||||
COPY tsconfig.json tsconfig.base.json ./
|
||||
|
||||
# Copy node_modules from deps stage
|
||||
COPY --from=deps /app/node_modules ./node_modules
|
||||
|
||||
@ -41,7 +41,7 @@ COPY pnpm-workspace.yaml package.json pnpm-lock.yaml ./
|
||||
# Copy source code
|
||||
COPY packages/ ./packages/
|
||||
COPY apps/portal/ ./apps/portal/
|
||||
COPY tsconfig.json ./
|
||||
COPY tsconfig.json tsconfig.base.json ./
|
||||
|
||||
# Ensure public directory exists even if the repo doesn't have one
|
||||
RUN mkdir -p /app/apps/portal/public
|
||||
@ -55,6 +55,7 @@ RUN pnpm --filter @customer-portal/domain build && \
|
||||
|
||||
# Build portal with standalone output
|
||||
WORKDIR /app/apps/portal
|
||||
ENV NODE_ENV=production
|
||||
RUN pnpm build
|
||||
|
||||
# =====================================================
|
||||
|
||||
15
apps/portal/src/app/(public)/layout.tsx
Normal file
15
apps/portal/src/app/(public)/layout.tsx
Normal file
@ -0,0 +1,15 @@
|
||||
/**
|
||||
* Public Layout
|
||||
*
|
||||
* Layout for public-facing pages (landing, auth, etc.)
|
||||
* Route groups in Next.js 15 require a layout file for standalone builds
|
||||
*/
|
||||
|
||||
export default function PublicLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return <>{children}</>;
|
||||
}
|
||||
|
||||
@ -19,6 +19,10 @@ export const metadata: Metadata = {
|
||||
description: "Manage your subscriptions, billing, and support with Assist Solutions",
|
||||
};
|
||||
|
||||
// Disable static generation for the entire app since it uses dynamic features extensively
|
||||
// This is the recommended approach for apps with heavy useSearchParams usage
|
||||
export const dynamic = 'force-dynamic';
|
||||
|
||||
export default function RootLayout({
|
||||
children,
|
||||
}: Readonly<{
|
||||
|
||||
@ -1,5 +0,0 @@
|
||||
import { PublicLandingView } from "@/features/landing-page";
|
||||
|
||||
export default function RootPage() {
|
||||
return <PublicLandingView />;
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { Suspense, useEffect, useMemo, useState } from "react";
|
||||
import { useSearchParams } from "next/navigation";
|
||||
|
||||
import { AuthLayout } from "../components";
|
||||
@ -15,7 +15,7 @@ import {
|
||||
type LogoutReason,
|
||||
} from "@/features/auth/utils/logout-reason";
|
||||
|
||||
export function LoginView() {
|
||||
function LoginContent() {
|
||||
const { loading, isAuthenticated } = useAuthStore();
|
||||
const searchParams = useSearchParams();
|
||||
const reasonParam = useMemo(() => searchParams?.get("reason"), [searchParams]);
|
||||
@ -70,4 +70,22 @@ export function LoginView() {
|
||||
);
|
||||
}
|
||||
|
||||
export function LoginView() {
|
||||
return (
|
||||
<Suspense
|
||||
fallback={
|
||||
<AuthLayout title="Welcome back" subtitle="Sign in to your Assist Solutions account">
|
||||
<div className="space-y-4 animate-pulse">
|
||||
<div className="h-10 rounded bg-gray-200" />
|
||||
<div className="h-10 rounded bg-gray-200" />
|
||||
<div className="h-10 rounded bg-gray-200" />
|
||||
</div>
|
||||
</AuthLayout>
|
||||
}
|
||||
>
|
||||
<LoginContent />
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
|
||||
export default LoginView;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import React, { useEffect, useMemo, useState } from "react";
|
||||
import React, { Suspense, useEffect, useMemo, useState } from "react";
|
||||
import { useSearchParams } from "next/navigation";
|
||||
import {
|
||||
WrenchScrewdriverIcon,
|
||||
@ -18,7 +18,8 @@ interface ServiceManagementSectionProps {
|
||||
|
||||
type ServiceKey = "SIM" | "INTERNET" | "NETGEAR" | "VPN";
|
||||
|
||||
export function ServiceManagementSection({
|
||||
// Inner component that uses useSearchParams
|
||||
function ServiceManagementContent({
|
||||
subscriptionId,
|
||||
productName,
|
||||
}: ServiceManagementSectionProps) {
|
||||
@ -128,3 +129,35 @@ export function ServiceManagementSection({
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Wrapper component with Suspense boundary
|
||||
export function ServiceManagementSection(props: ServiceManagementSectionProps) {
|
||||
const isSimService = useMemo(() => props.productName?.toLowerCase().includes("sim"), [props.productName]);
|
||||
|
||||
return (
|
||||
<Suspense
|
||||
fallback={
|
||||
<div className="space-y-6 mb-6">
|
||||
<div className="bg-white shadow rounded-lg px-6 py-4">
|
||||
<div className="flex items-center">
|
||||
<WrenchScrewdriverIcon className="h-6 w-6 text-blue-600 mr-2" />
|
||||
<div>
|
||||
<h3 className="text-lg font-medium text-gray-900">Service Management</h3>
|
||||
<p className="text-sm text-gray-500">Loading...</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="bg-white shadow rounded-lg">
|
||||
<div className="px-6 py-10 animate-pulse">
|
||||
<div className="h-12 w-12 bg-gray-200 rounded-full mx-auto" />
|
||||
<div className="mt-4 h-4 bg-gray-200 rounded w-48 mx-auto" />
|
||||
<div className="mt-2 h-3 bg-gray-200 rounded w-64 mx-auto" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<ServiceManagementContent {...props} />
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@ This directory contains comprehensive system design documentation for the Custom
|
||||
|
||||
## 📚 Core System Design Documents
|
||||
|
||||
### [System Architecture](./SYSTEM-ARCHITECTURE.md)
|
||||
### [System Architecture](./architecture/SYSTEM-ARCHITECTURE.md)
|
||||
**Comprehensive overview of the entire system**
|
||||
|
||||
- System overview and high-level architecture
|
||||
@ -21,28 +21,28 @@ This directory contains comprehensive system design documentation for the Custom
|
||||
|
||||
---
|
||||
|
||||
### [Integration & Data Flow](./INTEGRATION-DATAFLOW.md)
|
||||
### [Integration & Data Flow](./architecture/INTEGRATION-DATAFLOW.md)
|
||||
**External system integration patterns and data transformation**
|
||||
|
||||
- Integration architecture overview
|
||||
- Salesforce integration (REST API + Platform Events)
|
||||
- Salesforce integration (REST API + Platform Events via gRPC Pub/Sub)
|
||||
- WHMCS integration (REST API + Webhooks)
|
||||
- Freebit SIM management integration
|
||||
- Domain mapper pattern (Map Once, Use Everywhere)
|
||||
- Data transformation flows
|
||||
- Error handling and retry strategies
|
||||
- Caching strategies
|
||||
- Caching strategies (CDC-driven + TTL-based)
|
||||
|
||||
**Read this** to understand how external systems are integrated.
|
||||
|
||||
---
|
||||
|
||||
### [Domain Layer Design](./DOMAIN-LAYER-DESIGN.md)
|
||||
### [Domain Layer Design](./architecture/DOMAIN-LAYER-DESIGN.md)
|
||||
**Framework-agnostic type system and business logic**
|
||||
|
||||
- Domain-driven design principles
|
||||
- Provider pattern for multi-system abstraction
|
||||
- Type system architecture
|
||||
- Type system architecture (unified domain package)
|
||||
- Schema-driven validation with Zod
|
||||
- Adding new domains step-by-step
|
||||
- Import patterns and best practices
|
||||
@ -51,14 +51,14 @@ This directory contains comprehensive system design documentation for the Custom
|
||||
|
||||
---
|
||||
|
||||
### [Authentication & Security](./AUTHENTICATION-SECURITY.md)
|
||||
### [Authentication & Security](./architecture/AUTHENTICATION-SECURITY.md)
|
||||
**Security architecture and implementation**
|
||||
|
||||
- Authentication flow (JWT + Refresh Tokens)
|
||||
- Token management and rotation
|
||||
- Authentication flow (JWT access + refresh tokens)
|
||||
- Token management and rotation with Redis blacklist
|
||||
- Authorization and access control
|
||||
- Rate limiting strategies
|
||||
- Password security (Argon2id)
|
||||
- Rate limiting strategies (auth endpoints + external APIs)
|
||||
- Password security (Bcrypt with configurable rounds)
|
||||
- CSRF protection
|
||||
- PII redaction and data protection
|
||||
- Audit logging
|
||||
@ -165,9 +165,9 @@ These are kept for historical reference but are not part of the active system de
|
||||
### For New Developers
|
||||
|
||||
1. **Start with Core Design Documents:**
|
||||
- [System Architecture](./SYSTEM-ARCHITECTURE.md) - Overall system
|
||||
- [Domain Layer Design](./DOMAIN-LAYER-DESIGN.md) - Type system
|
||||
- [Integration & Data Flow](./INTEGRATION-DATAFLOW.md) - External systems
|
||||
- [System Architecture](./architecture/SYSTEM-ARCHITECTURE.md) - Overall system (if available)
|
||||
- [Domain Layer Design](./architecture/DOMAIN-LAYER-DESIGN.md) - Type system (if available)
|
||||
- [Integration & Data Flow](./architecture/INTEGRATION-DATAFLOW.md) - External systems (if available)
|
||||
|
||||
2. **Set Up Your Environment:**
|
||||
- [Getting Started](./guides/GETTING_STARTED.md) - Setup
|
||||
@ -180,21 +180,21 @@ These are kept for historical reference but are not part of the active system de
|
||||
|
||||
### For Backend Developers
|
||||
|
||||
1. [System Architecture](./SYSTEM-ARCHITECTURE.md) - BFF architecture
|
||||
2. [Integration & Data Flow](./INTEGRATION-DATAFLOW.md) - Integration patterns
|
||||
3. [Authentication & Security](./AUTHENTICATION-SECURITY.md) - Auth implementation
|
||||
1. [System Architecture](./architecture/SYSTEM-ARCHITECTURE.md) - BFF architecture (if available)
|
||||
2. [Integration & Data Flow](./architecture/INTEGRATION-DATAFLOW.md) - Integration patterns (if available)
|
||||
3. [Authentication & Security](./architecture/AUTHENTICATION-SECURITY.md) - Auth implementation (if available)
|
||||
4. [BFF Integration Patterns](./bff/BFF-INTEGRATION-PATTERNS-GUIDE.md) - Best practices
|
||||
|
||||
### For Frontend Developers
|
||||
|
||||
1. [Portal Architecture](./portal/PORTAL-ARCHITECTURE.md) - Frontend structure
|
||||
2. [Domain Layer Design](./DOMAIN-LAYER-DESIGN.md) - Type system
|
||||
2. [Domain Layer Design](./architecture/DOMAIN-LAYER-DESIGN.md) - Type system (if available)
|
||||
3. [Portal Integration Overview](./portal/PORTAL-INTEGRATION-OVERVIEW.md) - API integration
|
||||
4. [Performance Optimization](./portal/PERFORMANCE.md) - Performance tips
|
||||
|
||||
### For Integration Work
|
||||
|
||||
1. [Integration & Data Flow](./INTEGRATION-DATAFLOW.md) - Integration architecture
|
||||
1. [Integration & Data Flow](./architecture/INTEGRATION-DATAFLOW.md) - Integration architecture (if available)
|
||||
2. [Salesforce Portal Simple Guide](./salesforce/SALESFORCE-PORTAL-SIMPLE-GUIDE.md)
|
||||
3. [Salesforce-WHMCS Mapping Reference](./salesforce/SALESFORCE-WHMCS-MAPPING-REFERENCE.md)
|
||||
4. [SIM Management API Data Flow](./api/SIM-MANAGEMENT-API-DATA-FLOW.md)
|
||||
@ -256,9 +256,35 @@ For questions about the system:
|
||||
3. Check archived documents for historical context
|
||||
4. Contact the development team
|
||||
|
||||
## 🏗️ Technology Stack
|
||||
|
||||
### Frontend
|
||||
- Next.js 15 (App Router) with React 19
|
||||
- Tailwind CSS 4 with shadcn/ui components
|
||||
- TanStack Query for data fetching and caching
|
||||
- Zustand for client state management
|
||||
- React Hook Form + Zod for form validation
|
||||
|
||||
### Backend (BFF)
|
||||
- NestJS 11 with TypeScript
|
||||
- Prisma 6 ORM with PostgreSQL 17
|
||||
- p-queue for request throttling
|
||||
- Redis 7 for caching and token blacklist
|
||||
- Pino for structured logging
|
||||
|
||||
### External Integrations
|
||||
- **WHMCS**: Custom API client for billing and subscriptions
|
||||
- **Salesforce**: jsforce for REST API + salesforce-pubsub-api-client for Platform Events
|
||||
- **Freebit**: Custom SIM management integration
|
||||
|
||||
### Infrastructure
|
||||
- Docker for local development
|
||||
- pnpm workspaces for monorepo management
|
||||
- TypeScript project references for build optimization
|
||||
|
||||
---
|
||||
|
||||
**Last Updated**: October 2025
|
||||
**Last Updated**: November 2025
|
||||
**Maintained By**: Development Team
|
||||
|
||||
---
|
||||
@ -269,10 +295,10 @@ For questions about the system:
|
||||
<summary>View all documentation files</summary>
|
||||
|
||||
### Core Design
|
||||
- SYSTEM-ARCHITECTURE.md
|
||||
- INTEGRATION-DATAFLOW.md
|
||||
- DOMAIN-LAYER-DESIGN.md
|
||||
- AUTHENTICATION-SECURITY.md
|
||||
- SYSTEM-ARCHITECTURE.md (check if exists in architecture/)
|
||||
- INTEGRATION-DATAFLOW.md (check if exists in architecture/)
|
||||
- DOMAIN-LAYER-DESIGN.md (check if exists in architecture/)
|
||||
- AUTHENTICATION-SECURITY.md (check if exists in architecture/)
|
||||
|
||||
### Architecture
|
||||
- architecture/MONOREPO-ARCHITECTURE.md
|
||||
|
||||
@ -18,9 +18,9 @@
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"build": "tsc --build --force",
|
||||
"dev": "tsc -w --preserveWatchOutput",
|
||||
"clean": "rm -rf dist",
|
||||
"clean": "rm -rf dist tsconfig.tsbuildinfo",
|
||||
"type-check": "NODE_OPTIONS=\"--max-old-space-size=2048 --max-semi-space-size=128\" tsc --project tsconfig.json --noEmit",
|
||||
"test": "echo \"No tests specified for logging package\"",
|
||||
"lint": "eslint .",
|
||||
|
||||
3
pnpm-lock.yaml
generated
3
pnpm-lock.yaml
generated
@ -255,9 +255,6 @@ importers:
|
||||
'@customer-portal/domain':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/domain
|
||||
'@customer-portal/logging':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/logging
|
||||
'@customer-portal/validation':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/validation
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user