From e9acbd899c5b191c1cff8f068290a7d402852ba8 Mon Sep 17 00:00:00 2001
From: NTumurbars <156628271+NTumurbars@users.noreply.github.com>
Date: Thu, 18 Sep 2025 16:39:57 +0900
Subject: [PATCH] refactor: layer portal routes through feature modules
---
apps/portal/ARCHITECTURE.md | 72 ++--
.../account/loading.tsx | 0
.../account/page.tsx | 0
.../account/profile/page.tsx | 0
.../billing/invoices/[id]/loading.tsx | 0
.../billing/invoices/[id]/page.tsx | 0
.../billing/invoices/loading.tsx | 0
.../billing/invoices/page.tsx | 0
.../billing/payments/loading.tsx | 0
.../billing/payments/page.tsx | 0
.../catalog/internet/configure/page.tsx | 0
.../catalog/internet/page.tsx | 0
.../catalog/loading.tsx | 0
.../catalog/page.tsx | 0
.../catalog/sim/configure/page.tsx | 0
.../catalog/sim/page.tsx | 0
.../catalog/vpn/page.tsx | 0
.../checkout/loading.tsx | 0
.../checkout/page.tsx | 0
.../dashboard/loading.tsx | 0
.../app/(authenticated)/dashboard/page.tsx | 5 +
.../{(portal) => (authenticated)}/layout.tsx | 0
.../orders/[id]/loading.tsx | 0
.../orders/[id]/page.tsx | 0
.../orders/loading.tsx | 0
.../orders/page.tsx | 0
.../subscriptions/[id]/loading.tsx | 0
.../subscriptions/[id]/page.tsx | 0
.../subscriptions/[id]/sim/cancel/page.tsx | 0
.../[id]/sim/change-plan/page.tsx | 0
.../subscriptions/[id]/sim/reissue/page.tsx | 0
.../subscriptions/[id]/sim/top-up/page.tsx | 0
.../subscriptions/loading.tsx | 0
.../subscriptions/page.tsx | 0
.../support/cases/loading.tsx | 0
.../(authenticated)/support/cases/page.tsx | 5 +
.../support/new/loading.tsx | 0
.../app/(authenticated)/support/new/page.tsx | 5 +
.../src/app/(portal)/support/new/page.tsx | 260 -------------
.../auth/forgot-password/page.tsx | 0
.../{ => (public)}/auth/link-whmcs/page.tsx | 0
.../src/app/{ => (public)}/auth/loading.tsx | 0
.../app/{ => (public)}/auth/login/page.tsx | 0
.../auth/reset-password/page.tsx | 0
.../{ => (public)}/auth/set-password/page.tsx | 0
.../app/{ => (public)}/auth/signup/page.tsx | 0
apps/portal/src/app/(public)/loading.tsx | 5 +
apps/portal/src/app/(public)/page.tsx | 5 +
apps/portal/src/app/page.tsx | 288 --------------
apps/portal/src/features/dashboard/index.ts | 1 +
.../dashboard/views/DashboardView.tsx} | 59 +--
.../src/features/dashboard/views/index.ts | 1 +
apps/portal/src/features/index.ts | 2 +
apps/portal/src/features/marketing/index.ts | 2 +
.../views/PublicLandingLoadingView.tsx} | 11 +-
.../marketing/views/PublicLandingView.tsx | 368 ++++++++++++++++++
apps/portal/src/features/support/index.ts | 10 +-
.../support/views/NewSupportCaseView.tsx | 247 ++++++++++++
.../support/views/SupportCasesView.tsx} | 28 +-
.../src/features/support/views/index.ts | 2 +
apps/portal/tsconfig.json | 6 +
docs/SUBSCRIPTION-SERVICE-MANAGEMENT.md | 2 +-
eslint.config.mjs | 12 +-
63 files changed, 761 insertions(+), 635 deletions(-)
rename apps/portal/src/app/{(portal) => (authenticated)}/account/loading.tsx (100%)
rename apps/portal/src/app/{(portal) => (authenticated)}/account/page.tsx (100%)
rename apps/portal/src/app/{(portal) => (authenticated)}/account/profile/page.tsx (100%)
rename apps/portal/src/app/{(portal) => (authenticated)}/billing/invoices/[id]/loading.tsx (100%)
rename apps/portal/src/app/{(portal) => (authenticated)}/billing/invoices/[id]/page.tsx (100%)
rename apps/portal/src/app/{(portal) => (authenticated)}/billing/invoices/loading.tsx (100%)
rename apps/portal/src/app/{(portal) => (authenticated)}/billing/invoices/page.tsx (100%)
rename apps/portal/src/app/{(portal) => (authenticated)}/billing/payments/loading.tsx (100%)
rename apps/portal/src/app/{(portal) => (authenticated)}/billing/payments/page.tsx (100%)
rename apps/portal/src/app/{(portal) => (authenticated)}/catalog/internet/configure/page.tsx (100%)
rename apps/portal/src/app/{(portal) => (authenticated)}/catalog/internet/page.tsx (100%)
rename apps/portal/src/app/{(portal) => (authenticated)}/catalog/loading.tsx (100%)
rename apps/portal/src/app/{(portal) => (authenticated)}/catalog/page.tsx (100%)
rename apps/portal/src/app/{(portal) => (authenticated)}/catalog/sim/configure/page.tsx (100%)
rename apps/portal/src/app/{(portal) => (authenticated)}/catalog/sim/page.tsx (100%)
rename apps/portal/src/app/{(portal) => (authenticated)}/catalog/vpn/page.tsx (100%)
rename apps/portal/src/app/{(portal) => (authenticated)}/checkout/loading.tsx (100%)
rename apps/portal/src/app/{(portal) => (authenticated)}/checkout/page.tsx (100%)
rename apps/portal/src/app/{(portal) => (authenticated)}/dashboard/loading.tsx (100%)
create mode 100644 apps/portal/src/app/(authenticated)/dashboard/page.tsx
rename apps/portal/src/app/{(portal) => (authenticated)}/layout.tsx (100%)
rename apps/portal/src/app/{(portal) => (authenticated)}/orders/[id]/loading.tsx (100%)
rename apps/portal/src/app/{(portal) => (authenticated)}/orders/[id]/page.tsx (100%)
rename apps/portal/src/app/{(portal) => (authenticated)}/orders/loading.tsx (100%)
rename apps/portal/src/app/{(portal) => (authenticated)}/orders/page.tsx (100%)
rename apps/portal/src/app/{(portal) => (authenticated)}/subscriptions/[id]/loading.tsx (100%)
rename apps/portal/src/app/{(portal) => (authenticated)}/subscriptions/[id]/page.tsx (100%)
rename apps/portal/src/app/{(portal) => (authenticated)}/subscriptions/[id]/sim/cancel/page.tsx (100%)
rename apps/portal/src/app/{(portal) => (authenticated)}/subscriptions/[id]/sim/change-plan/page.tsx (100%)
rename apps/portal/src/app/{(portal) => (authenticated)}/subscriptions/[id]/sim/reissue/page.tsx (100%)
rename apps/portal/src/app/{(portal) => (authenticated)}/subscriptions/[id]/sim/top-up/page.tsx (100%)
rename apps/portal/src/app/{(portal) => (authenticated)}/subscriptions/loading.tsx (100%)
rename apps/portal/src/app/{(portal) => (authenticated)}/subscriptions/page.tsx (100%)
rename apps/portal/src/app/{(portal) => (authenticated)}/support/cases/loading.tsx (100%)
create mode 100644 apps/portal/src/app/(authenticated)/support/cases/page.tsx
rename apps/portal/src/app/{(portal) => (authenticated)}/support/new/loading.tsx (100%)
create mode 100644 apps/portal/src/app/(authenticated)/support/new/page.tsx
delete mode 100644 apps/portal/src/app/(portal)/support/new/page.tsx
rename apps/portal/src/app/{ => (public)}/auth/forgot-password/page.tsx (100%)
rename apps/portal/src/app/{ => (public)}/auth/link-whmcs/page.tsx (100%)
rename apps/portal/src/app/{ => (public)}/auth/loading.tsx (100%)
rename apps/portal/src/app/{ => (public)}/auth/login/page.tsx (100%)
rename apps/portal/src/app/{ => (public)}/auth/reset-password/page.tsx (100%)
rename apps/portal/src/app/{ => (public)}/auth/set-password/page.tsx (100%)
rename apps/portal/src/app/{ => (public)}/auth/signup/page.tsx (100%)
create mode 100644 apps/portal/src/app/(public)/loading.tsx
create mode 100644 apps/portal/src/app/(public)/page.tsx
delete mode 100644 apps/portal/src/app/page.tsx
rename apps/portal/src/{app/(portal)/dashboard/page.tsx => features/dashboard/views/DashboardView.tsx} (90%)
create mode 100644 apps/portal/src/features/dashboard/views/index.ts
create mode 100644 apps/portal/src/features/marketing/index.ts
rename apps/portal/src/{app/loading.tsx => features/marketing/views/PublicLandingLoadingView.tsx} (85%)
create mode 100644 apps/portal/src/features/marketing/views/PublicLandingView.tsx
create mode 100644 apps/portal/src/features/support/views/NewSupportCaseView.tsx
rename apps/portal/src/{app/(portal)/support/cases/page.tsx => features/support/views/SupportCasesView.tsx} (95%)
create mode 100644 apps/portal/src/features/support/views/index.ts
diff --git a/apps/portal/ARCHITECTURE.md b/apps/portal/ARCHITECTURE.md
index 4b725daf..c2d3f421 100644
--- a/apps/portal/ARCHITECTURE.md
+++ b/apps/portal/ARCHITECTURE.md
@@ -6,26 +6,31 @@ This document outlines the new feature-driven architecture implemented for the c
```
apps/portal/src/
-├── app/ # Next.js App Router pages
-├── components/ # Shared UI components (Design System)
-│ ├── ui/ # Base UI components (atoms)
-│ ├── layout/ # Layout components (organisms)
-│ └── common/ # Shared business components (molecules)
-├── features/ # Feature-specific modules
-│ ├── auth/ # Authentication feature
-│ ├── dashboard/ # Dashboard feature
-│ ├── billing/ # Billing feature
-│ ├── subscriptions/ # Subscriptions feature
-│ ├── catalog/ # Product catalog feature
-│ └── support/ # Support feature
-├── lib/ # Core utilities and services (replaces core/shared)
-│ ├── api/ # API client and base services
-│ ├── query.ts # Query client and keys
-│ ├── env.ts # Runtime env parsing
-│ ├── types/ # Shared TypeScript types
-│ └── utils/ # Utility functions (cn, currency, error-display, ...)
-├── providers/ # React context providers (e.g., QueryProvider)
-└── styles/ # Global styles and design tokens
+├── app/ # Next.js App Router entry points (route groups only)
+│ ├── (public)/ # Marketing + auth routes, pages import feature views
+│ ├── (authenticated)/ # Signed-in portal routes, thin wrappers around features
+│ ├── api/ # App Router API routes
+│ ├── favicon.ico / globals.css # Global assets
+│ └── layout.tsx # Root layout/providers
+├── components/ # Shared UI components (design system atoms/molecules)
+│ ├── ui/
+│ ├── layout/
+│ └── common/
+├── core/ # App-wide configuration (env, logger, providers)
+├── features/ # Feature-specific modules composed by routes
+│ ├── account/
+│ ├── auth/
+│ ├── billing/
+│ ├── catalog/
+│ ├── dashboard/
+│ ├── marketing/
+│ ├── orders/
+│ ├── service-management/
+│ ├── subscriptions/
+│ └── support/
+├── shared/ # Cross-feature helpers (e.g., constants, locale data)
+├── styles/ # Global styles and design tokens
+└── types/ # Portal-specific TypeScript types
```
## Design Principles
@@ -48,7 +53,7 @@ Each feature module contains:
- `utils/`: Utility functions
### 4. Centralized Shared Resources
-Common utilities, types, and components are centralized in the `lib/` and `components/` directories.
+Common utilities, types, and components are centralized in the `core/`, `shared/`, and `components/` directories.
## Feature Module Structure
@@ -118,20 +123,21 @@ import { DataTable } from '@/components/common';
import type { User, ApiResponse } from '@/types';
// Utility imports
-import { designSystem } from '@/lib/design-system';
-// Prefer feature services/hooks over direct apiClient usage in pages
-import { apiClient } from '@/lib/api/client';
+import { QueryProvider } from '@/core/providers';
+// Prefer feature services/hooks over direct api usage in pages
+import { logger } from '@/core/config';
```
### Path Mappings
- `@/*` - Root src directory
- `@/components/*` - Component library
+- `@/core/*` - App-wide configuration and providers
- `@/features/*` - Feature modules
-- `@/lib/*` - Core utilities
-- `@/types` - Type definitions
+- `@/shared/*` - Shared helpers/constants
- `@/styles/*` - Style files
-- `@shared/*` - Shared package
+- `@/types/*` - Portal-specific types
+- `@shared/*` - Shared package exports
## Migration Strategy
@@ -179,6 +185,14 @@ The migration to this new architecture will be done incrementally:
This ensures pages remain declarative and the feature layer encapsulates logic.
+### Route Layering
+
+- `(public)`: marketing landing and authentication flows. These routes render feature views such as `marketing/PublicLandingView` and `auth` screens while remaining server components by default.
+- `(authenticated)`: signed-in portal experience. Pages import dashboard, billing, subscriptions, etc. from the feature layer and rely on the shared route-group layout to provide navigation.
+- `api/`: App Router API endpoints remain colocated under `src/app/api` and can reuse feature services for data access.
+
+Only `layout.tsx`, `page.tsx`, and `loading.tsx` files live inside the route groups. All reusable UI, hooks, and services live under `src/features/**` to keep routing concerns thin.
+
### Current Feature Hooks/Services
- Catalog
@@ -191,3 +205,7 @@ This ensures pages remain declarative and the feature layer encapsulates logic.
- Service: `ordersService` (list/detail/create)
- Account
- Service: `accountService` (`/me/address`)
+- Support
+ - Views: `SupportCasesView`, `NewSupportCaseView` (mock data, ready for API wiring)
+- Marketing
+ - Views: `PublicLandingView`, `PublicLandingLoadingView`
diff --git a/apps/portal/src/app/(portal)/account/loading.tsx b/apps/portal/src/app/(authenticated)/account/loading.tsx
similarity index 100%
rename from apps/portal/src/app/(portal)/account/loading.tsx
rename to apps/portal/src/app/(authenticated)/account/loading.tsx
diff --git a/apps/portal/src/app/(portal)/account/page.tsx b/apps/portal/src/app/(authenticated)/account/page.tsx
similarity index 100%
rename from apps/portal/src/app/(portal)/account/page.tsx
rename to apps/portal/src/app/(authenticated)/account/page.tsx
diff --git a/apps/portal/src/app/(portal)/account/profile/page.tsx b/apps/portal/src/app/(authenticated)/account/profile/page.tsx
similarity index 100%
rename from apps/portal/src/app/(portal)/account/profile/page.tsx
rename to apps/portal/src/app/(authenticated)/account/profile/page.tsx
diff --git a/apps/portal/src/app/(portal)/billing/invoices/[id]/loading.tsx b/apps/portal/src/app/(authenticated)/billing/invoices/[id]/loading.tsx
similarity index 100%
rename from apps/portal/src/app/(portal)/billing/invoices/[id]/loading.tsx
rename to apps/portal/src/app/(authenticated)/billing/invoices/[id]/loading.tsx
diff --git a/apps/portal/src/app/(portal)/billing/invoices/[id]/page.tsx b/apps/portal/src/app/(authenticated)/billing/invoices/[id]/page.tsx
similarity index 100%
rename from apps/portal/src/app/(portal)/billing/invoices/[id]/page.tsx
rename to apps/portal/src/app/(authenticated)/billing/invoices/[id]/page.tsx
diff --git a/apps/portal/src/app/(portal)/billing/invoices/loading.tsx b/apps/portal/src/app/(authenticated)/billing/invoices/loading.tsx
similarity index 100%
rename from apps/portal/src/app/(portal)/billing/invoices/loading.tsx
rename to apps/portal/src/app/(authenticated)/billing/invoices/loading.tsx
diff --git a/apps/portal/src/app/(portal)/billing/invoices/page.tsx b/apps/portal/src/app/(authenticated)/billing/invoices/page.tsx
similarity index 100%
rename from apps/portal/src/app/(portal)/billing/invoices/page.tsx
rename to apps/portal/src/app/(authenticated)/billing/invoices/page.tsx
diff --git a/apps/portal/src/app/(portal)/billing/payments/loading.tsx b/apps/portal/src/app/(authenticated)/billing/payments/loading.tsx
similarity index 100%
rename from apps/portal/src/app/(portal)/billing/payments/loading.tsx
rename to apps/portal/src/app/(authenticated)/billing/payments/loading.tsx
diff --git a/apps/portal/src/app/(portal)/billing/payments/page.tsx b/apps/portal/src/app/(authenticated)/billing/payments/page.tsx
similarity index 100%
rename from apps/portal/src/app/(portal)/billing/payments/page.tsx
rename to apps/portal/src/app/(authenticated)/billing/payments/page.tsx
diff --git a/apps/portal/src/app/(portal)/catalog/internet/configure/page.tsx b/apps/portal/src/app/(authenticated)/catalog/internet/configure/page.tsx
similarity index 100%
rename from apps/portal/src/app/(portal)/catalog/internet/configure/page.tsx
rename to apps/portal/src/app/(authenticated)/catalog/internet/configure/page.tsx
diff --git a/apps/portal/src/app/(portal)/catalog/internet/page.tsx b/apps/portal/src/app/(authenticated)/catalog/internet/page.tsx
similarity index 100%
rename from apps/portal/src/app/(portal)/catalog/internet/page.tsx
rename to apps/portal/src/app/(authenticated)/catalog/internet/page.tsx
diff --git a/apps/portal/src/app/(portal)/catalog/loading.tsx b/apps/portal/src/app/(authenticated)/catalog/loading.tsx
similarity index 100%
rename from apps/portal/src/app/(portal)/catalog/loading.tsx
rename to apps/portal/src/app/(authenticated)/catalog/loading.tsx
diff --git a/apps/portal/src/app/(portal)/catalog/page.tsx b/apps/portal/src/app/(authenticated)/catalog/page.tsx
similarity index 100%
rename from apps/portal/src/app/(portal)/catalog/page.tsx
rename to apps/portal/src/app/(authenticated)/catalog/page.tsx
diff --git a/apps/portal/src/app/(portal)/catalog/sim/configure/page.tsx b/apps/portal/src/app/(authenticated)/catalog/sim/configure/page.tsx
similarity index 100%
rename from apps/portal/src/app/(portal)/catalog/sim/configure/page.tsx
rename to apps/portal/src/app/(authenticated)/catalog/sim/configure/page.tsx
diff --git a/apps/portal/src/app/(portal)/catalog/sim/page.tsx b/apps/portal/src/app/(authenticated)/catalog/sim/page.tsx
similarity index 100%
rename from apps/portal/src/app/(portal)/catalog/sim/page.tsx
rename to apps/portal/src/app/(authenticated)/catalog/sim/page.tsx
diff --git a/apps/portal/src/app/(portal)/catalog/vpn/page.tsx b/apps/portal/src/app/(authenticated)/catalog/vpn/page.tsx
similarity index 100%
rename from apps/portal/src/app/(portal)/catalog/vpn/page.tsx
rename to apps/portal/src/app/(authenticated)/catalog/vpn/page.tsx
diff --git a/apps/portal/src/app/(portal)/checkout/loading.tsx b/apps/portal/src/app/(authenticated)/checkout/loading.tsx
similarity index 100%
rename from apps/portal/src/app/(portal)/checkout/loading.tsx
rename to apps/portal/src/app/(authenticated)/checkout/loading.tsx
diff --git a/apps/portal/src/app/(portal)/checkout/page.tsx b/apps/portal/src/app/(authenticated)/checkout/page.tsx
similarity index 100%
rename from apps/portal/src/app/(portal)/checkout/page.tsx
rename to apps/portal/src/app/(authenticated)/checkout/page.tsx
diff --git a/apps/portal/src/app/(portal)/dashboard/loading.tsx b/apps/portal/src/app/(authenticated)/dashboard/loading.tsx
similarity index 100%
rename from apps/portal/src/app/(portal)/dashboard/loading.tsx
rename to apps/portal/src/app/(authenticated)/dashboard/loading.tsx
diff --git a/apps/portal/src/app/(authenticated)/dashboard/page.tsx b/apps/portal/src/app/(authenticated)/dashboard/page.tsx
new file mode 100644
index 00000000..0871d6d4
--- /dev/null
+++ b/apps/portal/src/app/(authenticated)/dashboard/page.tsx
@@ -0,0 +1,5 @@
+import { DashboardView } from "@/features/dashboard";
+
+export default function DashboardPage() {
+ return
Get help from our support team
-
- 9:30-18:00 JST
-
- 0120-660-470
-
- Search our help articles for quick solutions
-
-
- Browse Knowledge Base
-
-
Customer Portal
-Choose the option that applies to you
-- Migrate to our new portal and enjoy enhanced security with modern interface. -
- -Takes just a few minutes
-- Sign in to access your dashboard and manage all your services efficiently. -
- -Secure access to your account
-- Create your account and access our full range of IT solutions and services. -
- -Start your journey with us
-- Everything you need to manage your Assist Solutions services -
-- View invoices, payment history, and manage billing -
-Control and configure your active services
-Create and track support requests
-Monitor service usage and performance
-Our support team is here to assist you
-9:30-18:00 JST
-0120-660-470
-Toll Free within Japan
-Response within 24h
- - Send Message - -Available 24/7
- - Start Chat - -
- Monday - Saturday:
-
- 10:00 AM - 6:00 PM JST
-
- Sunday:
-
- Closed
-
Customer Portal
+Choose the option that applies to you
++ Migrate to our new portal and enjoy enhanced security with modern interface. +
+ +Takes just a few minutes
++ Sign in to access your dashboard and manage all your services efficiently. +
+ +Secure access to your account
++ Create your account and access our full range of IT solutions and services. +
+ +Start your journey with us
++ Modern tools to manage your IT services with confidence +
++ Transparent invoicing, automated payments, and flexible billing options tailored to + your business. +
++ Control subscriptions, manage network services, and track usage from a single pane + of glass. +
++ Dedicated support team with SLA-backed response times and proactive service + monitoring. +
++ Real-time analytics and reporting to help you optimize resource usage and forecast + demand. +
++ Guided onboarding for WHMCS customers with automatic data migration and validation. +
++ Built on modern infrastructure with continuous updates, security patches, and new + features. +
++ Join thousands of customers who trust Assist Solutions to keep their business + connected and secure. +
+Get help from our support team
+
+ 9:30-18:00 JST
+
+ 0120-660-470
+
+ Search our help articles for quick solutions
+
+
+ Browse Knowledge Base
+
+