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 ; +} diff --git a/apps/portal/src/app/(portal)/layout.tsx b/apps/portal/src/app/(authenticated)/layout.tsx similarity index 100% rename from apps/portal/src/app/(portal)/layout.tsx rename to apps/portal/src/app/(authenticated)/layout.tsx diff --git a/apps/portal/src/app/(portal)/orders/[id]/loading.tsx b/apps/portal/src/app/(authenticated)/orders/[id]/loading.tsx similarity index 100% rename from apps/portal/src/app/(portal)/orders/[id]/loading.tsx rename to apps/portal/src/app/(authenticated)/orders/[id]/loading.tsx diff --git a/apps/portal/src/app/(portal)/orders/[id]/page.tsx b/apps/portal/src/app/(authenticated)/orders/[id]/page.tsx similarity index 100% rename from apps/portal/src/app/(portal)/orders/[id]/page.tsx rename to apps/portal/src/app/(authenticated)/orders/[id]/page.tsx diff --git a/apps/portal/src/app/(portal)/orders/loading.tsx b/apps/portal/src/app/(authenticated)/orders/loading.tsx similarity index 100% rename from apps/portal/src/app/(portal)/orders/loading.tsx rename to apps/portal/src/app/(authenticated)/orders/loading.tsx diff --git a/apps/portal/src/app/(portal)/orders/page.tsx b/apps/portal/src/app/(authenticated)/orders/page.tsx similarity index 100% rename from apps/portal/src/app/(portal)/orders/page.tsx rename to apps/portal/src/app/(authenticated)/orders/page.tsx diff --git a/apps/portal/src/app/(portal)/subscriptions/[id]/loading.tsx b/apps/portal/src/app/(authenticated)/subscriptions/[id]/loading.tsx similarity index 100% rename from apps/portal/src/app/(portal)/subscriptions/[id]/loading.tsx rename to apps/portal/src/app/(authenticated)/subscriptions/[id]/loading.tsx diff --git a/apps/portal/src/app/(portal)/subscriptions/[id]/page.tsx b/apps/portal/src/app/(authenticated)/subscriptions/[id]/page.tsx similarity index 100% rename from apps/portal/src/app/(portal)/subscriptions/[id]/page.tsx rename to apps/portal/src/app/(authenticated)/subscriptions/[id]/page.tsx diff --git a/apps/portal/src/app/(portal)/subscriptions/[id]/sim/cancel/page.tsx b/apps/portal/src/app/(authenticated)/subscriptions/[id]/sim/cancel/page.tsx similarity index 100% rename from apps/portal/src/app/(portal)/subscriptions/[id]/sim/cancel/page.tsx rename to apps/portal/src/app/(authenticated)/subscriptions/[id]/sim/cancel/page.tsx diff --git a/apps/portal/src/app/(portal)/subscriptions/[id]/sim/change-plan/page.tsx b/apps/portal/src/app/(authenticated)/subscriptions/[id]/sim/change-plan/page.tsx similarity index 100% rename from apps/portal/src/app/(portal)/subscriptions/[id]/sim/change-plan/page.tsx rename to apps/portal/src/app/(authenticated)/subscriptions/[id]/sim/change-plan/page.tsx diff --git a/apps/portal/src/app/(portal)/subscriptions/[id]/sim/reissue/page.tsx b/apps/portal/src/app/(authenticated)/subscriptions/[id]/sim/reissue/page.tsx similarity index 100% rename from apps/portal/src/app/(portal)/subscriptions/[id]/sim/reissue/page.tsx rename to apps/portal/src/app/(authenticated)/subscriptions/[id]/sim/reissue/page.tsx diff --git a/apps/portal/src/app/(portal)/subscriptions/[id]/sim/top-up/page.tsx b/apps/portal/src/app/(authenticated)/subscriptions/[id]/sim/top-up/page.tsx similarity index 100% rename from apps/portal/src/app/(portal)/subscriptions/[id]/sim/top-up/page.tsx rename to apps/portal/src/app/(authenticated)/subscriptions/[id]/sim/top-up/page.tsx diff --git a/apps/portal/src/app/(portal)/subscriptions/loading.tsx b/apps/portal/src/app/(authenticated)/subscriptions/loading.tsx similarity index 100% rename from apps/portal/src/app/(portal)/subscriptions/loading.tsx rename to apps/portal/src/app/(authenticated)/subscriptions/loading.tsx diff --git a/apps/portal/src/app/(portal)/subscriptions/page.tsx b/apps/portal/src/app/(authenticated)/subscriptions/page.tsx similarity index 100% rename from apps/portal/src/app/(portal)/subscriptions/page.tsx rename to apps/portal/src/app/(authenticated)/subscriptions/page.tsx diff --git a/apps/portal/src/app/(portal)/support/cases/loading.tsx b/apps/portal/src/app/(authenticated)/support/cases/loading.tsx similarity index 100% rename from apps/portal/src/app/(portal)/support/cases/loading.tsx rename to apps/portal/src/app/(authenticated)/support/cases/loading.tsx diff --git a/apps/portal/src/app/(authenticated)/support/cases/page.tsx b/apps/portal/src/app/(authenticated)/support/cases/page.tsx new file mode 100644 index 00000000..54a27c29 --- /dev/null +++ b/apps/portal/src/app/(authenticated)/support/cases/page.tsx @@ -0,0 +1,5 @@ +import { SupportCasesView } from "@/features/support"; + +export default function SupportCasesPage() { + return ; +} diff --git a/apps/portal/src/app/(portal)/support/new/loading.tsx b/apps/portal/src/app/(authenticated)/support/new/loading.tsx similarity index 100% rename from apps/portal/src/app/(portal)/support/new/loading.tsx rename to apps/portal/src/app/(authenticated)/support/new/loading.tsx diff --git a/apps/portal/src/app/(authenticated)/support/new/page.tsx b/apps/portal/src/app/(authenticated)/support/new/page.tsx new file mode 100644 index 00000000..65c960da --- /dev/null +++ b/apps/portal/src/app/(authenticated)/support/new/page.tsx @@ -0,0 +1,5 @@ +import { NewSupportCaseView } from "@/features/support"; + +export default function NewSupportCasePage() { + return ; +} diff --git a/apps/portal/src/app/(portal)/support/new/page.tsx b/apps/portal/src/app/(portal)/support/new/page.tsx deleted file mode 100644 index aa113065..00000000 --- a/apps/portal/src/app/(portal)/support/new/page.tsx +++ /dev/null @@ -1,260 +0,0 @@ -"use client"; -import { logger } from "@/core/config"; - -import { useState } from "react"; -import { useRouter } from "next/navigation"; -import Link from "next/link"; -import { - ArrowLeftIcon, - PaperAirplaneIcon, - ExclamationCircleIcon, - InformationCircleIcon, -} from "@heroicons/react/24/outline"; - -export default function NewSupportCasePage() { - const router = useRouter(); - const [isSubmitting, setIsSubmitting] = useState(false); - const [formData, setFormData] = useState({ - subject: "", - category: "Technical", - priority: "Medium", - description: "", - }); - - const handleSubmit = (e: React.FormEvent) => { - e.preventDefault(); - setIsSubmitting(true); - - // Mock submission - would normally send to API - void (async () => { - try { - await new Promise(resolve => setTimeout(resolve, 2000)); - - // Redirect to cases list with success message - router.push("/support/cases?created=true"); - } catch (error) { - logger.error(error, "Error creating case"); - } finally { - setIsSubmitting(false); - } - })(); - }; - - const handleInputChange = (field: string, value: string) => { - setFormData(prev => ({ - ...prev, - [field]: value, - })); - }; - - const isFormValid = formData.subject.trim() && formData.description.trim(); - - return ( -
-
- {/* Header */} -
-
- -
- -
-

Create Support Case

-

Get help from our support team

-
-
- - {/* Help Tips */} -
-
-
- -
-
-

Before creating a case

-
-
    -
  • Check our knowledge base for common solutions
  • -
  • Include relevant error messages or screenshots
  • -
  • Provide detailed steps to reproduce the issue
  • -
  • Mention your service or subscription if applicable
  • -
-
-
-
-
- - {/* Form */} -
-
- {/* Subject */} -
- - handleInputChange("subject", e.target.value)} - placeholder="Brief description of your issue" - className="block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-blue-500 focus:border-blue-500" - required - /> -
- - {/* Category and Priority */} -
-
- - -
- -
- - -
-
- - {/* Description */} -
- -