diff --git a/README.md b/README.md index b3f2aacd..97b60e32 100644 --- a/README.md +++ b/README.md @@ -292,7 +292,7 @@ When running `pnpm dev:tools`, you get access to: ### Catalog & Orders -- `GET /api/catalog` - WHMCS GetProducts (cached 5-15m) +- `GET /api/services/*` - Services catalog endpoints (internet/sim/vpn) - `POST /api/orders` - WHMCS AddOrder with idempotency ### Invoices diff --git a/apps/bff/src/app.module.ts b/apps/bff/src/app.module.ts index 169c7a7f..b8724f28 100644 --- a/apps/bff/src/app.module.ts +++ b/apps/bff/src/app.module.ts @@ -30,7 +30,7 @@ import { AuthModule } from "@bff/modules/auth/auth.module.js"; import { UsersModule } from "@bff/modules/users/users.module.js"; import { MeStatusModule } from "@bff/modules/me-status/me-status.module.js"; import { MappingsModule } from "@bff/modules/id-mappings/mappings.module.js"; -import { CatalogModule } from "@bff/modules/catalog/catalog.module.js"; +import { ServicesModule } from "@bff/modules/services/services.module.js"; import { OrdersModule } from "@bff/modules/orders/orders.module.js"; import { InvoicesModule } from "@bff/modules/invoices/invoices.module.js"; import { SubscriptionsModule } from "@bff/modules/subscriptions/subscriptions.module.js"; @@ -84,7 +84,7 @@ import { HealthModule } from "@bff/modules/health/health.module.js"; UsersModule, MeStatusModule, MappingsModule, - CatalogModule, + ServicesModule, OrdersModule, InvoicesModule, SubscriptionsModule, diff --git a/apps/bff/src/core/config/router.config.ts b/apps/bff/src/core/config/router.config.ts index ed10783f..08b80968 100644 --- a/apps/bff/src/core/config/router.config.ts +++ b/apps/bff/src/core/config/router.config.ts @@ -3,7 +3,7 @@ import { AuthModule } from "@bff/modules/auth/auth.module.js"; import { UsersModule } from "@bff/modules/users/users.module.js"; import { MeStatusModule } from "@bff/modules/me-status/me-status.module.js"; import { MappingsModule } from "@bff/modules/id-mappings/mappings.module.js"; -import { CatalogModule } from "@bff/modules/catalog/catalog.module.js"; +import { ServicesModule } from "@bff/modules/services/services.module.js"; import { OrdersModule } from "@bff/modules/orders/orders.module.js"; import { InvoicesModule } from "@bff/modules/invoices/invoices.module.js"; import { SubscriptionsModule } from "@bff/modules/subscriptions/subscriptions.module.js"; @@ -22,7 +22,7 @@ export const apiRoutes: Routes = [ { path: "", module: UsersModule }, { path: "", module: MeStatusModule }, { path: "", module: MappingsModule }, - { path: "", module: CatalogModule }, + { path: "", module: ServicesModule }, { path: "", module: OrdersModule }, { path: "", module: InvoicesModule }, { path: "", module: SubscriptionsModule }, diff --git a/apps/bff/src/infra/cache/README.md b/apps/bff/src/infra/cache/README.md index f469e043..c4d761d0 100644 --- a/apps/bff/src/infra/cache/README.md +++ b/apps/bff/src/infra/cache/README.md @@ -64,11 +64,13 @@ Redis-backed caching system with CDC (Change Data Capture) event-driven invalida **No TTL** - Cache persists indefinitely until CDC event triggers invalidation. **Pros:** + - Real-time invalidation when data changes - Zero stale data for customer-visible fields - Optimal for frequently read, infrequently changed data **Example:** + ```typescript @Injectable() export class OrdersCacheService { @@ -88,11 +90,13 @@ export class OrdersCacheService { **Fixed TTL** - Cache expires after a set duration. **Pros:** + - Simple, predictable behavior - Good for external systems without CDC - Automatic cleanup of stale data **Example:** + ```typescript @Injectable() export class WhmcsCacheService { @@ -160,7 +164,8 @@ All cache services track performance metrics: ``` Access via health endpoints: -- `GET /health/catalog/cache` + +- `GET /api/health/services/cache` - `GET /health` ## Creating a New Cache Service @@ -194,7 +199,7 @@ export class MyDomainCacheService { ```typescript async getMyData(id: string, fetcher: () => Promise): Promise { const key = `mydomain:${id}`; - + // Check cache const cached = await this.cache.get(key); if (cached) { @@ -255,6 +260,7 @@ domain:type:identifier[:subkey] ``` Examples: + - `orders:account:001xx000003EgI1AAK` - `orders:detail:80122000000D4UGAA0` - `catalog:internet:acc_001:jp` @@ -288,7 +294,7 @@ Provides global `REDIS_CLIENT` using ioredis. GET /health # Catalog cache metrics -GET /health/catalog/cache +GET /api/health/services/cache ``` ### Response Format @@ -357,4 +363,3 @@ console.log(`${count} keys using ${usage} bytes`); - [Salesforce CDC Events](../../integrations/salesforce/events/README.md) - [Order Fulfillment Flow](../../modules/orders/docs/FULFILLMENT.md) - [Redis Configuration](../redis/README.md) - diff --git a/apps/bff/src/integrations/salesforce/events/catalog-cdc.subscriber.ts b/apps/bff/src/integrations/salesforce/events/catalog-cdc.subscriber.ts index 27668fb1..848902cf 100644 --- a/apps/bff/src/integrations/salesforce/events/catalog-cdc.subscriber.ts +++ b/apps/bff/src/integrations/salesforce/events/catalog-cdc.subscriber.ts @@ -4,7 +4,7 @@ import { ConfigService } from "@nestjs/config"; import { Logger } from "nestjs-pino"; import PubSubApiClientPkg from "salesforce-pubsub-api-client"; import { SalesforceConnection } from "../services/salesforce-connection.service.js"; -import { CatalogCacheService } from "@bff/modules/catalog/services/catalog-cache.service.js"; +import { CatalogCacheService } from "@bff/modules/services/services/catalog-cache.service.js"; import { RealtimeService } from "@bff/infra/realtime/realtime.service.js"; import { AccountNotificationHandler } from "@bff/modules/notifications/account-cdc-listener.service.js"; @@ -195,8 +195,8 @@ export class CatalogCdcSubscriber implements OnModuleInit, OnModuleDestroy { } ); await this.invalidateAllCatalogs(); - // Full invalidation already implies all clients should refetch catalog - this.realtime.publish("global:catalog", "catalog.changed", { + // Full invalidation already implies all clients should refetch services + this.realtime.publish("global:services", "services.changed", { reason: "product.cdc.fallback_full_invalidation", timestamp: new Date().toISOString(), }); @@ -204,7 +204,7 @@ export class CatalogCdcSubscriber implements OnModuleInit, OnModuleDestroy { } // Product changes can affect catalog results for all users - this.realtime.publish("global:catalog", "catalog.changed", { + this.realtime.publish("global:services", "services.changed", { reason: "product.cdc", timestamp: new Date().toISOString(), }); @@ -249,14 +249,14 @@ export class CatalogCdcSubscriber implements OnModuleInit, OnModuleDestroy { } ); await this.invalidateAllCatalogs(); - this.realtime.publish("global:catalog", "catalog.changed", { + this.realtime.publish("global:services", "services.changed", { reason: "pricebook.cdc.fallback_full_invalidation", timestamp: new Date().toISOString(), }); return; } - this.realtime.publish("global:catalog", "catalog.changed", { + this.realtime.publish("global:services", "services.changed", { reason: "pricebook.cdc", timestamp: new Date().toISOString(), }); @@ -316,7 +316,7 @@ export class CatalogCdcSubscriber implements OnModuleInit, OnModuleDestroy { } // Notify connected portals immediately (multi-instance safe via Redis pub/sub) - this.realtime.publish(`account:sf:${accountId}`, "catalog.eligibility.changed", { + this.realtime.publish(`account:sf:${accountId}`, "services.eligibility.changed", { timestamp: new Date().toISOString(), }); diff --git a/apps/bff/src/integrations/salesforce/events/events.module.ts b/apps/bff/src/integrations/salesforce/events/events.module.ts index 6556f353..3b67c30e 100644 --- a/apps/bff/src/integrations/salesforce/events/events.module.ts +++ b/apps/bff/src/integrations/salesforce/events/events.module.ts @@ -2,7 +2,7 @@ import { Module, forwardRef } from "@nestjs/common"; import { ConfigModule } from "@nestjs/config"; import { IntegrationsModule } from "@bff/integrations/integrations.module.js"; import { OrdersModule } from "@bff/modules/orders/orders.module.js"; -import { CatalogModule } from "@bff/modules/catalog/catalog.module.js"; +import { ServicesModule } from "@bff/modules/services/services.module.js"; import { NotificationsModule } from "@bff/modules/notifications/notifications.module.js"; import { CatalogCdcSubscriber } from "./catalog-cdc.subscriber.js"; import { OrderCdcSubscriber } from "./order-cdc.subscriber.js"; @@ -12,7 +12,7 @@ import { OrderCdcSubscriber } from "./order-cdc.subscriber.js"; ConfigModule, forwardRef(() => IntegrationsModule), forwardRef(() => OrdersModule), - forwardRef(() => CatalogModule), + forwardRef(() => ServicesModule), forwardRef(() => NotificationsModule), ], providers: [ diff --git a/apps/bff/src/integrations/whmcs/connection/services/whmcs-connection-orchestrator.service.ts b/apps/bff/src/integrations/whmcs/connection/services/whmcs-connection-orchestrator.service.ts index da0c9916..c662ecad 100644 --- a/apps/bff/src/integrations/whmcs/connection/services/whmcs-connection-orchestrator.service.ts +++ b/apps/bff/src/integrations/whmcs/connection/services/whmcs-connection-orchestrator.service.ts @@ -33,7 +33,7 @@ import type { } from "@customer-portal/domain/payments"; import type { WhmcsGetClientsProductsParams } from "@customer-portal/domain/subscriptions"; import type { WhmcsProductListResponse } from "@customer-portal/domain/subscriptions"; -import type { WhmcsCatalogProductListResponse } from "@customer-portal/domain/catalog"; +import type { WhmcsCatalogProductListResponse } from "@customer-portal/domain/services"; import type { WhmcsErrorResponse } from "@customer-portal/domain/common"; import type { WhmcsRequestOptions, WhmcsConnectionStats } from "../types/connection.types.js"; diff --git a/apps/bff/src/integrations/whmcs/services/whmcs-payment.service.ts b/apps/bff/src/integrations/whmcs/services/whmcs-payment.service.ts index 56104db4..13409a87 100644 --- a/apps/bff/src/integrations/whmcs/services/whmcs-payment.service.ts +++ b/apps/bff/src/integrations/whmcs/services/whmcs-payment.service.ts @@ -11,7 +11,7 @@ import type { import { Providers as CatalogProviders, type WhmcsCatalogProductNormalized, -} from "@customer-portal/domain/catalog"; +} from "@customer-portal/domain/services"; import { WhmcsConnectionOrchestratorService } from "../connection/services/whmcs-connection-orchestrator.service.js"; import { WhmcsCacheService } from "../cache/whmcs-cache.service.js"; import type { WhmcsCreateSsoTokenParams } from "@customer-portal/domain/customer"; diff --git a/apps/bff/src/integrations/whmcs/whmcs.service.ts b/apps/bff/src/integrations/whmcs/whmcs.service.ts index 487606d3..4f239f93 100644 --- a/apps/bff/src/integrations/whmcs/whmcs.service.ts +++ b/apps/bff/src/integrations/whmcs/whmcs.service.ts @@ -20,7 +20,7 @@ import { WhmcsOrderService } from "./services/whmcs-order.service.js"; import type { WhmcsAddClientParams, WhmcsClientResponse } from "@customer-portal/domain/customer"; import type { WhmcsGetClientsProductsParams } from "@customer-portal/domain/subscriptions"; import type { WhmcsProductListResponse } from "@customer-portal/domain/subscriptions"; -import type { WhmcsCatalogProductNormalized } from "@customer-portal/domain/catalog"; +import type { WhmcsCatalogProductNormalized } from "@customer-portal/domain/services"; import { Logger } from "nestjs-pino"; @Injectable() diff --git a/apps/bff/src/modules/me-status/me-status.module.ts b/apps/bff/src/modules/me-status/me-status.module.ts index e568dade..e06f3711 100644 --- a/apps/bff/src/modules/me-status/me-status.module.ts +++ b/apps/bff/src/modules/me-status/me-status.module.ts @@ -3,7 +3,7 @@ import { MeStatusController } from "./me-status.controller.js"; import { MeStatusService } from "./me-status.service.js"; import { UsersModule } from "@bff/modules/users/users.module.js"; import { OrdersModule } from "@bff/modules/orders/orders.module.js"; -import { CatalogModule } from "@bff/modules/catalog/catalog.module.js"; +import { ServicesModule } from "@bff/modules/services/services.module.js"; import { VerificationModule } from "@bff/modules/verification/verification.module.js"; import { WhmcsModule } from "@bff/integrations/whmcs/whmcs.module.js"; import { MappingsModule } from "@bff/modules/id-mappings/mappings.module.js"; @@ -14,7 +14,7 @@ import { SalesforceModule } from "@bff/integrations/salesforce/salesforce.module imports: [ UsersModule, OrdersModule, - CatalogModule, + ServicesModule, VerificationModule, WhmcsModule, MappingsModule, diff --git a/apps/bff/src/modules/me-status/me-status.service.ts b/apps/bff/src/modules/me-status/me-status.service.ts index d8ed3692..f3eefe6d 100644 --- a/apps/bff/src/modules/me-status/me-status.service.ts +++ b/apps/bff/src/modules/me-status/me-status.service.ts @@ -2,7 +2,7 @@ import { Injectable, Inject } from "@nestjs/common"; import { Logger } from "nestjs-pino"; import { UsersFacade } from "@bff/modules/users/application/users.facade.js"; import { OrderOrchestrator } from "@bff/modules/orders/services/order-orchestrator.service.js"; -import { InternetCatalogService } from "@bff/modules/catalog/services/internet-catalog.service.js"; +import { InternetCatalogService } from "@bff/modules/services/services/internet-catalog.service.js"; import { ResidenceCardService } from "@bff/modules/verification/residence-card.service.js"; import { MappingsService } from "@bff/modules/id-mappings/mappings.service.js"; import { WhmcsPaymentService } from "@bff/integrations/whmcs/services/whmcs-payment.service.js"; @@ -15,7 +15,7 @@ import { type PaymentMethodsStatus, } from "@customer-portal/domain/dashboard"; import { NOTIFICATION_SOURCE, NOTIFICATION_TYPE } from "@customer-portal/domain/notifications"; -import type { InternetEligibilityDetails } from "@customer-portal/domain/catalog"; +import type { InternetEligibilityDetails } from "@customer-portal/domain/services"; import type { ResidenceCardVerification } from "@customer-portal/domain/customer"; import type { OrderSummary } from "@customer-portal/domain/orders"; diff --git a/apps/bff/src/modules/orders/orders.module.ts b/apps/bff/src/modules/orders/orders.module.ts index 5156e324..74a4d28a 100644 --- a/apps/bff/src/modules/orders/orders.module.ts +++ b/apps/bff/src/modules/orders/orders.module.ts @@ -6,7 +6,7 @@ import { MappingsModule } from "@bff/modules/id-mappings/mappings.module.js"; import { UsersModule } from "@bff/modules/users/users.module.js"; import { CoreConfigModule } from "@bff/core/config/config.module.js"; import { DatabaseModule } from "@bff/core/database/database.module.js"; -import { CatalogModule } from "@bff/modules/catalog/catalog.module.js"; +import { ServicesModule } from "@bff/modules/services/services.module.js"; import { CacheModule } from "@bff/infra/cache/cache.module.js"; import { VerificationModule } from "@bff/modules/verification/verification.module.js"; import { NotificationsModule } from "@bff/modules/notifications/notifications.module.js"; @@ -39,7 +39,7 @@ import { OrderFieldConfigModule } from "./config/order-field-config.module.js"; UsersModule, CoreConfigModule, DatabaseModule, - CatalogModule, + ServicesModule, CacheModule, VerificationModule, NotificationsModule, diff --git a/apps/bff/src/modules/orders/services/checkout.service.ts b/apps/bff/src/modules/orders/services/checkout.service.ts index 07d32765..bcbd162a 100644 --- a/apps/bff/src/modules/orders/services/checkout.service.ts +++ b/apps/bff/src/modules/orders/services/checkout.service.ts @@ -20,10 +20,10 @@ import type { SimCatalogProduct, SimActivationFeeCatalogItem, VpnCatalogProduct, -} from "@customer-portal/domain/catalog"; -import { InternetCatalogService } from "@bff/modules/catalog/services/internet-catalog.service.js"; -import { SimCatalogService } from "@bff/modules/catalog/services/sim-catalog.service.js"; -import { VpnCatalogService } from "@bff/modules/catalog/services/vpn-catalog.service.js"; +} from "@customer-portal/domain/services"; +import { InternetCatalogService } from "@bff/modules/services/services/internet-catalog.service.js"; +import { SimCatalogService } from "@bff/modules/services/services/sim-catalog.service.js"; +import { VpnCatalogService } from "@bff/modules/services/services/vpn-catalog.service.js"; import { getErrorMessage } from "@bff/core/utils/error.util.js"; @Injectable() diff --git a/apps/bff/src/modules/orders/services/order-pricebook.service.ts b/apps/bff/src/modules/orders/services/order-pricebook.service.ts index 4b57d278..ec650e3b 100644 --- a/apps/bff/src/modules/orders/services/order-pricebook.service.ts +++ b/apps/bff/src/modules/orders/services/order-pricebook.service.ts @@ -5,7 +5,7 @@ import { SalesforceConnection } from "@bff/integrations/salesforce/services/sale import type { SalesforceProduct2Record, SalesforcePricebookEntryRecord, -} from "@customer-portal/domain/catalog"; +} from "@customer-portal/domain/services"; import type { SalesforceResponse } from "@customer-portal/domain/common"; import { assertSalesforceId, diff --git a/apps/bff/src/modules/orders/services/order-validator.service.ts b/apps/bff/src/modules/orders/services/order-validator.service.ts index 9f24b5fb..06ada154 100644 --- a/apps/bff/src/modules/orders/services/order-validator.service.ts +++ b/apps/bff/src/modules/orders/services/order-validator.service.ts @@ -13,8 +13,8 @@ import { import type { Providers } from "@customer-portal/domain/subscriptions"; type WhmcsProduct = Providers.WhmcsRaw.WhmcsProductRaw; -import { SimCatalogService } from "@bff/modules/catalog/services/sim-catalog.service.js"; -import { InternetCatalogService } from "@bff/modules/catalog/services/internet-catalog.service.js"; +import { SimCatalogService } from "@bff/modules/services/services/sim-catalog.service.js"; +import { InternetCatalogService } from "@bff/modules/services/services/internet-catalog.service.js"; import { OrderPricebookService, type PricebookProductMeta } from "./order-pricebook.service.js"; import { PaymentValidatorService } from "./payment-validator.service.js"; import { ResidenceCardService } from "@bff/modules/verification/residence-card.service.js"; diff --git a/apps/bff/src/modules/realtime/realtime.controller.ts b/apps/bff/src/modules/realtime/realtime.controller.ts index 9c71a826..44e86a5e 100644 --- a/apps/bff/src/modules/realtime/realtime.controller.ts +++ b/apps/bff/src/modules/realtime/realtime.controller.ts @@ -67,14 +67,14 @@ export class RealtimeController { } ); - const globalCatalogStream = this.realtime.subscribe("global:catalog", { + const globalServicesStream = this.realtime.subscribe("global:services", { // Avoid duplicate ready/heartbeat noise on the combined stream. readyEvent: null, heartbeatEvent: null, heartbeatMs: 0, }); - return merge(accountStream, globalCatalogStream).pipe( + return merge(accountStream, globalServicesStream).pipe( finalize(() => { this.limiter.release(req.user.id); this.logger.debug("Account realtime stream disconnected", { diff --git a/apps/bff/src/modules/catalog/internet-eligibility.controller.ts b/apps/bff/src/modules/services/internet-eligibility.controller.ts similarity index 92% rename from apps/bff/src/modules/catalog/internet-eligibility.controller.ts rename to apps/bff/src/modules/services/internet-eligibility.controller.ts index 7ca825ff..0f5e70ff 100644 --- a/apps/bff/src/modules/catalog/internet-eligibility.controller.ts +++ b/apps/bff/src/modules/services/internet-eligibility.controller.ts @@ -5,7 +5,7 @@ import type { RequestWithUser } from "@bff/modules/auth/auth.types.js"; import { RateLimit, RateLimitGuard } from "@bff/core/rate-limiting/index.js"; import { InternetCatalogService } from "./services/internet-catalog.service.js"; import { addressSchema } from "@customer-portal/domain/customer"; -import type { InternetEligibilityDetails } from "@customer-portal/domain/catalog"; +import type { InternetEligibilityDetails } from "@customer-portal/domain/services"; const eligibilityRequestSchema = z.object({ notes: z.string().trim().max(2000).optional(), @@ -21,10 +21,10 @@ type EligibilityRequest = z.infer; * - fetching current Salesforce eligibility value * - requesting a (manual) eligibility/availability check * - * Note: CatalogController is @Public, so we keep these endpoints in a separate controller + * Note: ServicesController is @Public, so we keep these endpoints in a separate controller * to ensure GlobalAuthGuard enforces authentication. */ -@Controller("catalog/internet") +@Controller("services/internet") @UseGuards(RateLimitGuard) export class InternetEligibilityController { constructor(private readonly internetCatalog: InternetCatalogService) {} diff --git a/apps/bff/src/modules/catalog/catalog-health.controller.ts b/apps/bff/src/modules/services/services-health.controller.ts similarity index 82% rename from apps/bff/src/modules/catalog/catalog-health.controller.ts rename to apps/bff/src/modules/services/services-health.controller.ts index b645a6b1..dda457ae 100644 --- a/apps/bff/src/modules/catalog/catalog-health.controller.ts +++ b/apps/bff/src/modules/services/services-health.controller.ts @@ -3,7 +3,7 @@ import { CatalogCacheService } from "./services/catalog-cache.service.js"; import type { CatalogCacheSnapshot } from "./services/catalog-cache.service.js"; import { Public } from "@bff/modules/auth/decorators/public.decorator.js"; -interface CatalogCacheHealthResponse { +interface ServicesCacheHealthResponse { timestamp: string; metrics: CatalogCacheSnapshot; ttl: { @@ -14,13 +14,13 @@ interface CatalogCacheHealthResponse { }; } -@Controller("health/catalog") +@Controller("health/services") @Public() -export class CatalogHealthController { +export class ServicesHealthController { constructor(private readonly catalogCache: CatalogCacheService) {} @Get("cache") - getCacheMetrics(): CatalogCacheHealthResponse { + getCacheMetrics(): ServicesCacheHealthResponse { const ttl = this.catalogCache.getTtlConfiguration(); return { timestamp: new Date().toISOString(), diff --git a/apps/bff/src/modules/catalog/catalog.controller.ts b/apps/bff/src/modules/services/services.controller.ts similarity index 95% rename from apps/bff/src/modules/catalog/catalog.controller.ts rename to apps/bff/src/modules/services/services.controller.ts index 53a09f4f..957bb2f7 100644 --- a/apps/bff/src/modules/catalog/catalog.controller.ts +++ b/apps/bff/src/modules/services/services.controller.ts @@ -12,16 +12,16 @@ import { type SimCatalogCollection, type SimCatalogProduct, type VpnCatalogProduct, -} from "@customer-portal/domain/catalog"; +} from "@customer-portal/domain/services"; import { InternetCatalogService } from "./services/internet-catalog.service.js"; import { SimCatalogService } from "./services/sim-catalog.service.js"; import { VpnCatalogService } from "./services/vpn-catalog.service.js"; import { SalesforceReadThrottleGuard } from "@bff/integrations/salesforce/guards/salesforce-read-throttle.guard.js"; -@Controller("catalog") -@Public() // Allow public access - catalog can be browsed without authentication +@Controller("services") +@Public() // Allow public access - services can be browsed without authentication @UseGuards(SalesforceReadThrottleGuard, RateLimitGuard) -export class CatalogController { +export class ServicesController { constructor( private internetCatalog: InternetCatalogService, private simCatalog: SimCatalogService, diff --git a/apps/bff/src/modules/catalog/catalog.module.ts b/apps/bff/src/modules/services/services.module.ts similarity index 82% rename from apps/bff/src/modules/catalog/catalog.module.ts rename to apps/bff/src/modules/services/services.module.ts index e3521ee6..f0ffa53a 100644 --- a/apps/bff/src/modules/catalog/catalog.module.ts +++ b/apps/bff/src/modules/services/services.module.ts @@ -1,6 +1,6 @@ import { Module, forwardRef } from "@nestjs/common"; -import { CatalogController } from "./catalog.controller.js"; -import { CatalogHealthController } from "./catalog-health.controller.js"; +import { ServicesController } from "./services.controller.js"; +import { ServicesHealthController } from "./services-health.controller.js"; import { InternetEligibilityController } from "./internet-eligibility.controller.js"; import { IntegrationsModule } from "@bff/integrations/integrations.module.js"; import { MappingsModule } from "@bff/modules/id-mappings/mappings.module.js"; @@ -22,7 +22,7 @@ import { CatalogCacheService } from "./services/catalog-cache.service.js"; CacheModule, QueueModule, ], - controllers: [CatalogController, CatalogHealthController, InternetEligibilityController], + controllers: [ServicesController, ServicesHealthController, InternetEligibilityController], providers: [ BaseCatalogService, InternetCatalogService, @@ -32,4 +32,4 @@ import { CatalogCacheService } from "./services/catalog-cache.service.js"; ], exports: [InternetCatalogService, SimCatalogService, VpnCatalogService, CatalogCacheService], }) -export class CatalogModule {} +export class ServicesModule {} diff --git a/apps/bff/src/modules/catalog/services/base-catalog.service.ts b/apps/bff/src/modules/services/services/base-catalog.service.ts similarity index 98% rename from apps/bff/src/modules/catalog/services/base-catalog.service.ts rename to apps/bff/src/modules/services/services/base-catalog.service.ts index 694e4d89..f1996fb6 100644 --- a/apps/bff/src/modules/catalog/services/base-catalog.service.ts +++ b/apps/bff/src/modules/services/services/base-catalog.service.ts @@ -14,8 +14,8 @@ import { getErrorMessage } from "@bff/core/utils/error.util.js"; import type { SalesforceProduct2WithPricebookEntries, SalesforcePricebookEntryRecord, -} from "@customer-portal/domain/catalog"; -import { Providers as CatalogProviders } from "@customer-portal/domain/catalog"; +} from "@customer-portal/domain/services"; +import { Providers as CatalogProviders } from "@customer-portal/domain/services"; import type { SalesforceResponse } from "@customer-portal/domain/common"; @Injectable() diff --git a/apps/bff/src/modules/catalog/services/catalog-cache.service.ts b/apps/bff/src/modules/services/services/catalog-cache.service.ts similarity index 100% rename from apps/bff/src/modules/catalog/services/catalog-cache.service.ts rename to apps/bff/src/modules/services/services/catalog-cache.service.ts diff --git a/apps/bff/src/modules/catalog/services/internet-catalog.service.ts b/apps/bff/src/modules/services/services/internet-catalog.service.ts similarity index 99% rename from apps/bff/src/modules/catalog/services/internet-catalog.service.ts rename to apps/bff/src/modules/services/services/internet-catalog.service.ts index e59ed167..a5778e79 100644 --- a/apps/bff/src/modules/catalog/services/internet-catalog.service.ts +++ b/apps/bff/src/modules/services/services/internet-catalog.service.ts @@ -9,14 +9,14 @@ import type { InternetAddonCatalogItem, InternetEligibilityDetails, InternetEligibilityStatus, -} from "@customer-portal/domain/catalog"; +} from "@customer-portal/domain/services"; import { Providers as CatalogProviders, enrichInternetPlanMetadata, inferAddonTypeFromSku, inferInstallationTermFromSku, internetEligibilityDetailsSchema, -} from "@customer-portal/domain/catalog"; +} from "@customer-portal/domain/services"; import { MappingsService } from "@bff/modules/id-mappings/mappings.service.js"; import { SalesforceConnection } from "@bff/integrations/salesforce/services/salesforce-connection.service.js"; import { OpportunityResolutionService } from "@bff/integrations/salesforce/services/opportunity-resolution.service.js"; diff --git a/apps/bff/src/modules/catalog/services/internet-eligibility.types.ts b/apps/bff/src/modules/services/services/internet-eligibility.types.ts similarity index 100% rename from apps/bff/src/modules/catalog/services/internet-eligibility.types.ts rename to apps/bff/src/modules/services/services/internet-eligibility.types.ts diff --git a/apps/bff/src/modules/catalog/services/sim-catalog.service.ts b/apps/bff/src/modules/services/services/sim-catalog.service.ts similarity index 99% rename from apps/bff/src/modules/catalog/services/sim-catalog.service.ts rename to apps/bff/src/modules/services/services/sim-catalog.service.ts index fccf572c..ccfdcffd 100644 --- a/apps/bff/src/modules/catalog/services/sim-catalog.service.ts +++ b/apps/bff/src/modules/services/services/sim-catalog.service.ts @@ -6,8 +6,8 @@ import type { SalesforceProduct2WithPricebookEntries, SimCatalogProduct, SimActivationFeeCatalogItem, -} from "@customer-portal/domain/catalog"; -import { Providers as CatalogProviders } from "@customer-portal/domain/catalog"; +} from "@customer-portal/domain/services"; +import { Providers as CatalogProviders } from "@customer-portal/domain/services"; import { MappingsService } from "@bff/modules/id-mappings/mappings.service.js"; import { SalesforceConnection } from "@bff/integrations/salesforce/services/salesforce-connection.service.js"; import { Logger } from "nestjs-pino"; diff --git a/apps/bff/src/modules/catalog/services/vpn-catalog.service.ts b/apps/bff/src/modules/services/services/vpn-catalog.service.ts similarity index 97% rename from apps/bff/src/modules/catalog/services/vpn-catalog.service.ts rename to apps/bff/src/modules/services/services/vpn-catalog.service.ts index 478d2038..2d5e3056 100644 --- a/apps/bff/src/modules/catalog/services/vpn-catalog.service.ts +++ b/apps/bff/src/modules/services/services/vpn-catalog.service.ts @@ -6,8 +6,8 @@ import { BaseCatalogService } from "./base-catalog.service.js"; import type { SalesforceProduct2WithPricebookEntries, VpnCatalogProduct, -} from "@customer-portal/domain/catalog"; -import { Providers as CatalogProviders } from "@customer-portal/domain/catalog"; +} from "@customer-portal/domain/services"; +import { Providers as CatalogProviders } from "@customer-portal/domain/services"; @Injectable() export class VpnCatalogService extends BaseCatalogService { diff --git a/apps/bff/src/modules/catalog/utils/salesforce-product.pricing.ts b/apps/bff/src/modules/services/utils/salesforce-product.pricing.ts similarity index 100% rename from apps/bff/src/modules/catalog/utils/salesforce-product.pricing.ts rename to apps/bff/src/modules/services/utils/salesforce-product.pricing.ts diff --git a/apps/bff/src/modules/subscriptions/sim-management/services/sim-plan.service.ts b/apps/bff/src/modules/subscriptions/sim-management/services/sim-plan.service.ts index 1e1416a1..87d48013 100644 --- a/apps/bff/src/modules/subscriptions/sim-management/services/sim-plan.service.ts +++ b/apps/bff/src/modules/subscriptions/sim-management/services/sim-plan.service.ts @@ -12,8 +12,8 @@ import { SimScheduleService } from "./sim-schedule.service.js"; import { SimActionRunnerService } from "./sim-action-runner.service.js"; import { SimManagementQueueService } from "../queue/sim-management.queue.js"; import { SimApiNotificationService } from "./sim-api-notification.service.js"; -import { SimCatalogService } from "@bff/modules/catalog/services/sim-catalog.service.js"; -import type { SimCatalogProduct } from "@customer-portal/domain/catalog"; +import { SimCatalogService } from "@bff/modules/services/services/sim-catalog.service.js"; +import type { SimCatalogProduct } from "@customer-portal/domain/services"; // Mapping from Salesforce SKU to Freebit plan code const SKU_TO_FREEBIT_PLAN_CODE: Record = { diff --git a/apps/bff/src/modules/subscriptions/sim-management/sim-management.module.ts b/apps/bff/src/modules/subscriptions/sim-management/sim-management.module.ts index 6bedf729..3eec6618 100644 --- a/apps/bff/src/modules/subscriptions/sim-management/sim-management.module.ts +++ b/apps/bff/src/modules/subscriptions/sim-management/sim-management.module.ts @@ -27,7 +27,7 @@ import { SimManagementQueueService } from "./queue/sim-management.queue.js"; import { SimManagementProcessor } from "./queue/sim-management.processor.js"; import { SimVoiceOptionsService } from "./services/sim-voice-options.service.js"; import { SimCallHistoryService } from "./services/sim-call-history.service.js"; -import { CatalogModule } from "@bff/modules/catalog/catalog.module.js"; +import { ServicesModule } from "@bff/modules/services/services.module.js"; import { NotificationsModule } from "@bff/modules/notifications/notifications.module.js"; @Module({ @@ -37,7 +37,7 @@ import { NotificationsModule } from "@bff/modules/notifications/notifications.mo SalesforceModule, MappingsModule, EmailModule, - CatalogModule, + ServicesModule, SftpModule, NotificationsModule, ], diff --git a/apps/portal/src/app/(public)/(site)/services/internet/configure/page.tsx b/apps/portal/src/app/(public)/(site)/services/internet/configure/page.tsx index fc4a373f..8da5fac7 100644 --- a/apps/portal/src/app/(public)/(site)/services/internet/configure/page.tsx +++ b/apps/portal/src/app/(public)/(site)/services/internet/configure/page.tsx @@ -4,8 +4,8 @@ * Configure internet plan for unauthenticated users. */ -import { PublicInternetConfigureView } from "@/features/catalog/views/PublicInternetConfigure"; -import { RedirectAuthenticatedToAccountServices } from "@/features/catalog/components/common/RedirectAuthenticatedToAccountServices"; +import { PublicInternetConfigureView } from "@/features/services/views/PublicInternetConfigure"; +import { RedirectAuthenticatedToAccountServices } from "@/features/services/components/common/RedirectAuthenticatedToAccountServices"; export default function PublicInternetConfigurePage() { return ( diff --git a/apps/portal/src/app/(public)/(site)/services/internet/page.tsx b/apps/portal/src/app/(public)/(site)/services/internet/page.tsx index 7d414020..2e23ef80 100644 --- a/apps/portal/src/app/(public)/(site)/services/internet/page.tsx +++ b/apps/portal/src/app/(public)/(site)/services/internet/page.tsx @@ -4,8 +4,8 @@ * Displays internet plans for unauthenticated users. */ -import { PublicInternetPlansView } from "@/features/catalog/views/PublicInternetPlans"; -import { RedirectAuthenticatedToAccountServices } from "@/features/catalog/components/common/RedirectAuthenticatedToAccountServices"; +import { PublicInternetPlansView } from "@/features/services/views/PublicInternetPlans"; +import { RedirectAuthenticatedToAccountServices } from "@/features/services/components/common/RedirectAuthenticatedToAccountServices"; export default function PublicInternetPlansPage() { return ( diff --git a/apps/portal/src/app/(public)/(site)/services/page.tsx b/apps/portal/src/app/(public)/(site)/services/page.tsx index 64557aa4..f3d8cb70 100644 --- a/apps/portal/src/app/(public)/(site)/services/page.tsx +++ b/apps/portal/src/app/(public)/(site)/services/page.tsx @@ -1,4 +1,4 @@ -import { ServicesGrid } from "@/features/catalog/components/common/ServicesGrid"; +import { ServicesGrid } from "@/features/services/components/common/ServicesGrid"; interface ServicesPageProps { basePath?: string; diff --git a/apps/portal/src/app/(public)/(site)/services/sim/configure/page.tsx b/apps/portal/src/app/(public)/(site)/services/sim/configure/page.tsx index 09bf21fd..da3da30e 100644 --- a/apps/portal/src/app/(public)/(site)/services/sim/configure/page.tsx +++ b/apps/portal/src/app/(public)/(site)/services/sim/configure/page.tsx @@ -4,8 +4,8 @@ * Configure SIM plan for unauthenticated users. */ -import { PublicSimConfigureView } from "@/features/catalog/views/PublicSimConfigure"; -import { RedirectAuthenticatedToAccountServices } from "@/features/catalog/components/common/RedirectAuthenticatedToAccountServices"; +import { PublicSimConfigureView } from "@/features/services/views/PublicSimConfigure"; +import { RedirectAuthenticatedToAccountServices } from "@/features/services/components/common/RedirectAuthenticatedToAccountServices"; export default function PublicSimConfigurePage() { return ( diff --git a/apps/portal/src/app/(public)/(site)/services/sim/page.tsx b/apps/portal/src/app/(public)/(site)/services/sim/page.tsx index 99c71361..365bfbbb 100644 --- a/apps/portal/src/app/(public)/(site)/services/sim/page.tsx +++ b/apps/portal/src/app/(public)/(site)/services/sim/page.tsx @@ -4,8 +4,8 @@ * Displays SIM plans for unauthenticated users. */ -import { PublicSimPlansView } from "@/features/catalog/views/PublicSimPlans"; -import { RedirectAuthenticatedToAccountServices } from "@/features/catalog/components/common/RedirectAuthenticatedToAccountServices"; +import { PublicSimPlansView } from "@/features/services/views/PublicSimPlans"; +import { RedirectAuthenticatedToAccountServices } from "@/features/services/components/common/RedirectAuthenticatedToAccountServices"; export default function PublicSimPlansPage() { return ( diff --git a/apps/portal/src/app/(public)/(site)/services/vpn/page.tsx b/apps/portal/src/app/(public)/(site)/services/vpn/page.tsx index 7236a8f5..abb231d5 100644 --- a/apps/portal/src/app/(public)/(site)/services/vpn/page.tsx +++ b/apps/portal/src/app/(public)/(site)/services/vpn/page.tsx @@ -4,8 +4,8 @@ * Displays VPN plans for unauthenticated users. */ -import { PublicVpnPlansView } from "@/features/catalog/views/PublicVpnPlans"; -import { RedirectAuthenticatedToAccountServices } from "@/features/catalog/components/common/RedirectAuthenticatedToAccountServices"; +import { PublicVpnPlansView } from "@/features/services/views/PublicVpnPlans"; +import { RedirectAuthenticatedToAccountServices } from "@/features/services/components/common/RedirectAuthenticatedToAccountServices"; export default function PublicVpnPlansPage() { return ( diff --git a/apps/portal/src/app/account/services/internet/configure/page.tsx b/apps/portal/src/app/account/services/internet/configure/page.tsx index f4c70ebb..34f3a8c0 100644 --- a/apps/portal/src/app/account/services/internet/configure/page.tsx +++ b/apps/portal/src/app/account/services/internet/configure/page.tsx @@ -1,4 +1,4 @@ -import { InternetConfigureContainer } from "@/features/catalog/views/InternetConfigure"; +import { InternetConfigureContainer } from "@/features/services/views/InternetConfigure"; export default function AccountInternetConfigurePage() { return ; diff --git a/apps/portal/src/app/account/services/internet/page.tsx b/apps/portal/src/app/account/services/internet/page.tsx index 469f6ade..d38e2fb3 100644 --- a/apps/portal/src/app/account/services/internet/page.tsx +++ b/apps/portal/src/app/account/services/internet/page.tsx @@ -1,4 +1,4 @@ -import { InternetPlansContainer } from "@/features/catalog/views/InternetPlans"; +import { InternetPlansContainer } from "@/features/services/views/InternetPlans"; export default function AccountInternetPlansPage() { return ; diff --git a/apps/portal/src/app/account/services/layout.tsx b/apps/portal/src/app/account/services/layout.tsx index f0737f4d..6c1b729c 100644 --- a/apps/portal/src/app/account/services/layout.tsx +++ b/apps/portal/src/app/account/services/layout.tsx @@ -1,5 +1,5 @@ import type { ReactNode } from "react"; -export default function AccountShopLayout({ children }: { children: ReactNode }) { +export default function AccountServicesLayout({ children }: { children: ReactNode }) { return <>{children}; } diff --git a/apps/portal/src/app/account/services/page.tsx b/apps/portal/src/app/account/services/page.tsx index 77770ab6..94bc3d1c 100644 --- a/apps/portal/src/app/account/services/page.tsx +++ b/apps/portal/src/app/account/services/page.tsx @@ -1,6 +1,6 @@ -import { ServicesGrid } from "@/features/catalog/components/common/ServicesGrid"; +import { ServicesGrid } from "@/features/services/components/common/ServicesGrid"; -export default function AccountShopPage() { +export default function AccountServicesPage() { return (
diff --git a/apps/portal/src/app/account/services/sim/configure/page.tsx b/apps/portal/src/app/account/services/sim/configure/page.tsx index ab66d78c..37415f7f 100644 --- a/apps/portal/src/app/account/services/sim/configure/page.tsx +++ b/apps/portal/src/app/account/services/sim/configure/page.tsx @@ -1,4 +1,4 @@ -import { SimConfigureContainer } from "@/features/catalog/views/SimConfigure"; +import { SimConfigureContainer } from "@/features/services/views/SimConfigure"; export default function AccountSimConfigurePage() { return ; diff --git a/apps/portal/src/app/account/services/sim/page.tsx b/apps/portal/src/app/account/services/sim/page.tsx index e00978cf..a791ff47 100644 --- a/apps/portal/src/app/account/services/sim/page.tsx +++ b/apps/portal/src/app/account/services/sim/page.tsx @@ -1,4 +1,4 @@ -import { SimPlansContainer } from "@/features/catalog/views/SimPlans"; +import { SimPlansContainer } from "@/features/services/views/SimPlans"; export default function AccountSimPlansPage() { return ; diff --git a/apps/portal/src/app/account/services/vpn/page.tsx b/apps/portal/src/app/account/services/vpn/page.tsx index 701c37c7..e524d558 100644 --- a/apps/portal/src/app/account/services/vpn/page.tsx +++ b/apps/portal/src/app/account/services/vpn/page.tsx @@ -1,4 +1,4 @@ -import { VpnPlansView } from "@/features/catalog/views/VpnPlans"; +import { VpnPlansView } from "@/features/services/views/VpnPlans"; export default function AccountVpnPlansPage() { return ; diff --git a/apps/portal/src/app/account/my-services/[id]/internet/cancel/page.tsx b/apps/portal/src/app/account/subscriptions/[id]/internet/cancel/page.tsx similarity index 100% rename from apps/portal/src/app/account/my-services/[id]/internet/cancel/page.tsx rename to apps/portal/src/app/account/subscriptions/[id]/internet/cancel/page.tsx diff --git a/apps/portal/src/app/account/my-services/[id]/loading.tsx b/apps/portal/src/app/account/subscriptions/[id]/loading.tsx similarity index 100% rename from apps/portal/src/app/account/my-services/[id]/loading.tsx rename to apps/portal/src/app/account/subscriptions/[id]/loading.tsx diff --git a/apps/portal/src/app/account/my-services/[id]/page.tsx b/apps/portal/src/app/account/subscriptions/[id]/page.tsx similarity index 100% rename from apps/portal/src/app/account/my-services/[id]/page.tsx rename to apps/portal/src/app/account/subscriptions/[id]/page.tsx diff --git a/apps/portal/src/app/account/my-services/[id]/sim/call-history/page.tsx b/apps/portal/src/app/account/subscriptions/[id]/sim/call-history/page.tsx similarity index 100% rename from apps/portal/src/app/account/my-services/[id]/sim/call-history/page.tsx rename to apps/portal/src/app/account/subscriptions/[id]/sim/call-history/page.tsx diff --git a/apps/portal/src/app/account/my-services/[id]/sim/cancel/page.tsx b/apps/portal/src/app/account/subscriptions/[id]/sim/cancel/page.tsx similarity index 100% rename from apps/portal/src/app/account/my-services/[id]/sim/cancel/page.tsx rename to apps/portal/src/app/account/subscriptions/[id]/sim/cancel/page.tsx diff --git a/apps/portal/src/app/account/my-services/[id]/sim/change-plan/page.tsx b/apps/portal/src/app/account/subscriptions/[id]/sim/change-plan/page.tsx similarity index 100% rename from apps/portal/src/app/account/my-services/[id]/sim/change-plan/page.tsx rename to apps/portal/src/app/account/subscriptions/[id]/sim/change-plan/page.tsx diff --git a/apps/portal/src/app/account/my-services/[id]/sim/reissue/page.tsx b/apps/portal/src/app/account/subscriptions/[id]/sim/reissue/page.tsx similarity index 100% rename from apps/portal/src/app/account/my-services/[id]/sim/reissue/page.tsx rename to apps/portal/src/app/account/subscriptions/[id]/sim/reissue/page.tsx diff --git a/apps/portal/src/app/account/my-services/[id]/sim/top-up/page.tsx b/apps/portal/src/app/account/subscriptions/[id]/sim/top-up/page.tsx similarity index 100% rename from apps/portal/src/app/account/my-services/[id]/sim/top-up/page.tsx rename to apps/portal/src/app/account/subscriptions/[id]/sim/top-up/page.tsx diff --git a/apps/portal/src/app/account/my-services/loading.tsx b/apps/portal/src/app/account/subscriptions/loading.tsx similarity index 100% rename from apps/portal/src/app/account/my-services/loading.tsx rename to apps/portal/src/app/account/subscriptions/loading.tsx diff --git a/apps/portal/src/app/account/my-services/page.tsx b/apps/portal/src/app/account/subscriptions/page.tsx similarity index 71% rename from apps/portal/src/app/account/my-services/page.tsx rename to apps/portal/src/app/account/subscriptions/page.tsx index 13e6e5bb..e26c9905 100644 --- a/apps/portal/src/app/account/my-services/page.tsx +++ b/apps/portal/src/app/account/subscriptions/page.tsx @@ -1,5 +1,5 @@ import SubscriptionsListContainer from "@/features/subscriptions/views/SubscriptionsList"; -export default function AccountServicesPage() { +export default function AccountSubscriptionsPage() { return ; } diff --git a/apps/portal/src/components/organisms/AppShell/AppShell.tsx b/apps/portal/src/components/organisms/AppShell/AppShell.tsx index 4c04191f..a4435c4a 100644 --- a/apps/portal/src/components/organisms/AppShell/AppShell.tsx +++ b/apps/portal/src/components/organisms/AppShell/AppShell.tsx @@ -98,7 +98,7 @@ export function AppShell({ children }: AppShellProps) { useEffect(() => { setExpandedItems(prev => { const next = new Set(prev); - if (pathname.startsWith("/account/services")) next.add("My Services"); + if (pathname.startsWith("/account/subscriptions")) next.add("Subscriptions"); if (pathname.startsWith("/account/billing")) next.add("Billing"); if (pathname.startsWith("/account/support")) next.add("Support"); if (pathname.startsWith("/account/settings")) next.add("Settings"); diff --git a/apps/portal/src/components/organisms/AppShell/navigation.ts b/apps/portal/src/components/organisms/AppShell/navigation.ts index ba64f773..1667487f 100644 --- a/apps/portal/src/components/organisms/AppShell/navigation.ts +++ b/apps/portal/src/components/organisms/AppShell/navigation.ts @@ -37,9 +37,9 @@ export const baseNavigation: NavigationItem[] = [ ], }, { - name: "My Services", + name: "Subscriptions", icon: ServerIcon, - children: [{ name: "All Services", href: "/account/my-services" }], + children: [{ name: "All Subscriptions", href: "/account/subscriptions" }], }, { name: "Services", href: "/account/services", icon: Squares2X2Icon }, { @@ -64,17 +64,17 @@ export function computeNavigation(activeSubscriptions?: Subscription[]): Navigat children: item.children ? [...item.children] : undefined, })); - const subIdx = nav.findIndex(n => n.name === "My Services"); + const subIdx = nav.findIndex(n => n.name === "Subscriptions"); if (subIdx >= 0) { const dynamicChildren = (activeSubscriptions || []).map(sub => ({ name: truncate(sub.productName || `Subscription ${sub.id}`, 28), - href: `/account/my-services/${sub.id}`, + href: `/account/subscriptions/${sub.id}`, tooltip: sub.productName || `Subscription ${sub.id}`, })); nav[subIdx] = { ...nav[subIdx], - children: [{ name: "All Services", href: "/account/my-services" }, ...dynamicChildren], + children: [{ name: "All Subscriptions", href: "/account/subscriptions" }, ...dynamicChildren], }; } diff --git a/apps/portal/src/features/account/components/AddressCard.tsx b/apps/portal/src/features/account/components/AddressCard.tsx index d45ea2b0..69416d1b 100644 --- a/apps/portal/src/features/account/components/AddressCard.tsx +++ b/apps/portal/src/features/account/components/AddressCard.tsx @@ -2,7 +2,7 @@ import { SubCard } from "@/components/molecules/SubCard/SubCard"; import { MapPinIcon, PencilIcon, CheckIcon, XMarkIcon } from "@heroicons/react/24/outline"; -import { AddressForm, type AddressFormProps } from "@/features/catalog/components"; +import { AddressForm, type AddressFormProps } from "@/features/services/components"; import type { Address } from "@customer-portal/domain/customer"; import { getCountryName } from "@/lib/constants/countries"; diff --git a/apps/portal/src/features/account/hooks/useAddressEdit.ts b/apps/portal/src/features/account/hooks/useAddressEdit.ts index 34261a02..0165c81d 100644 --- a/apps/portal/src/features/account/hooks/useAddressEdit.ts +++ b/apps/portal/src/features/account/hooks/useAddressEdit.ts @@ -19,7 +19,7 @@ export function useAddressEdit(initial: AddressFormData) { const requestData = addressFormToRequest(formData); await accountService.updateAddress(requestData); // Address changes can affect server-personalized catalog results (eligibility). - await queryClient.invalidateQueries({ queryKey: queryKeys.catalog.all() }); + await queryClient.invalidateQueries({ queryKey: queryKeys.services.all() }); }, [queryClient] ); diff --git a/apps/portal/src/features/account/hooks/useProfileData.ts b/apps/portal/src/features/account/hooks/useProfileData.ts index 86572e47..fcdaf244 100644 --- a/apps/portal/src/features/account/hooks/useProfileData.ts +++ b/apps/portal/src/features/account/hooks/useProfileData.ts @@ -113,7 +113,7 @@ export function useProfileData() { phoneCountryCode: next.phoneCountryCode, }); // Address changes can affect server-personalized catalog results (eligibility). - await queryClient.invalidateQueries({ queryKey: queryKeys.catalog.all() }); + await queryClient.invalidateQueries({ queryKey: queryKeys.services.all() }); setBillingInfo({ address: next }); setAddress(next); return true; diff --git a/apps/portal/src/features/account/views/ProfileContainer.tsx b/apps/portal/src/features/account/views/ProfileContainer.tsx index 0048b3df..c765940f 100644 --- a/apps/portal/src/features/account/views/ProfileContainer.tsx +++ b/apps/portal/src/features/account/views/ProfileContainer.tsx @@ -14,7 +14,7 @@ import { import { useAuthStore } from "@/features/auth/services/auth.store"; import { accountService } from "@/features/account/services/account.service"; import { useProfileEdit } from "@/features/account/hooks/useProfileEdit"; -import { AddressForm } from "@/features/catalog/components/base/AddressForm"; +import { AddressForm } from "@/features/services/components/base/AddressForm"; import { Button } from "@/components/atoms/button"; import { StatusPill } from "@/components/atoms/status-pill"; import { useAddressEdit } from "@/features/account/hooks/useAddressEdit"; diff --git a/apps/portal/src/features/billing/components/InvoiceDetail/InvoiceItems.tsx b/apps/portal/src/features/billing/components/InvoiceDetail/InvoiceItems.tsx index aba4a124..2c48d90d 100644 --- a/apps/portal/src/features/billing/components/InvoiceDetail/InvoiceItems.tsx +++ b/apps/portal/src/features/billing/components/InvoiceDetail/InvoiceItems.tsx @@ -72,7 +72,7 @@ export function InvoiceItems({ items = [], currency }: InvoiceItemsProps) { clipRule="evenodd" /> - Service #{item.serviceId} + Subscription #{item.serviceId} ) : ( @@ -104,7 +104,7 @@ export function InvoiceItems({ items = [], currency }: InvoiceItemsProps) { if (isLinked) { return ( - + {itemContent} ); diff --git a/apps/portal/src/features/billing/components/InvoiceItemRow.tsx b/apps/portal/src/features/billing/components/InvoiceItemRow.tsx index 76939ed6..95b17291 100644 --- a/apps/portal/src/features/billing/components/InvoiceItemRow.tsx +++ b/apps/portal/src/features/billing/components/InvoiceItemRow.tsx @@ -25,7 +25,7 @@ export function InvoiceItemRow({ ? "border-blue-200 bg-blue-50 hover:bg-blue-100 cursor-pointer hover:shadow-sm" : "border-gray-200 bg-gray-50" }`} - onClick={serviceId ? () => router.push(`/account/services/${serviceId}`) : undefined} + onClick={serviceId ? () => router.push(`/account/subscriptions/${serviceId}`) : undefined} >
- Service #{serviceId} • Click to view + Subscription #{serviceId} • Click to view
)}
diff --git a/apps/portal/src/features/catalog/services/index.ts b/apps/portal/src/features/catalog/services/index.ts deleted file mode 100644 index 14dc64fb..00000000 --- a/apps/portal/src/features/catalog/services/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { catalogService } from "./catalog.service"; diff --git a/apps/portal/src/features/catalog/utils/index.ts b/apps/portal/src/features/catalog/utils/index.ts deleted file mode 100644 index 4f516e0a..00000000 --- a/apps/portal/src/features/catalog/utils/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./catalog.utils"; -export * from "./pricing"; diff --git a/apps/portal/src/features/checkout/components/AccountCheckoutContainer.tsx b/apps/portal/src/features/checkout/components/AccountCheckoutContainer.tsx index 66bb32ab..00a357d6 100644 --- a/apps/portal/src/features/checkout/components/AccountCheckoutContainer.tsx +++ b/apps/portal/src/features/checkout/components/AccountCheckoutContainer.tsx @@ -10,15 +10,15 @@ import { Button } from "@/components/atoms/button"; import { AlertBanner } from "@/components/molecules/AlertBanner/AlertBanner"; import { InlineToast } from "@/components/atoms/inline-toast"; import { StatusPill } from "@/components/atoms/status-pill"; -import { AddressConfirmation } from "@/features/catalog/components/base/AddressConfirmation"; +import { AddressConfirmation } from "@/features/services/components/base/AddressConfirmation"; import { useCheckoutStore } from "@/features/checkout/stores/checkout.store"; import { ordersService } from "@/features/orders/services/orders.service"; import { usePaymentMethods } from "@/features/billing/hooks/useBilling"; import { usePaymentRefresh } from "@/features/billing/hooks/usePaymentRefresh"; import { useActiveSubscriptions } from "@/features/subscriptions/hooks/useSubscriptions"; import { ACTIVE_INTERNET_SUBSCRIPTION_WARNING } from "@/features/checkout/constants"; -import { useInternetEligibility } from "@/features/catalog/hooks/useInternetEligibility"; -import { useRequestInternetEligibilityCheck } from "@/features/catalog/hooks/useInternetEligibility"; +import { useInternetEligibility } from "@/features/services/hooks/useInternetEligibility"; +import { useRequestInternetEligibilityCheck } from "@/features/services/hooks/useInternetEligibility"; import { useResidenceCardVerification, useSubmitResidenceCard, diff --git a/apps/portal/src/features/checkout/components/EmptyCartRedirect.tsx b/apps/portal/src/features/checkout/components/EmptyCartRedirect.tsx index 3cb3efa0..fc924c68 100644 --- a/apps/portal/src/features/checkout/components/EmptyCartRedirect.tsx +++ b/apps/portal/src/features/checkout/components/EmptyCartRedirect.tsx @@ -4,7 +4,7 @@ import { useEffect } from "react"; import { useRouter } from "next/navigation"; import { ShoppingCartIcon } from "@heroicons/react/24/outline"; import { Button } from "@/components/atoms/button"; -import { useServicesBasePath } from "@/features/catalog/hooks/useServicesBasePath"; +import { useServicesBasePath } from "@/features/services/hooks/useServicesBasePath"; /** * EmptyCartRedirect - Shown when checkout is accessed without a cart diff --git a/apps/portal/src/features/dashboard/utils/dashboard.utils.ts b/apps/portal/src/features/dashboard/utils/dashboard.utils.ts index 355d6be5..24ea6b7d 100644 --- a/apps/portal/src/features/dashboard/utils/dashboard.utils.ts +++ b/apps/portal/src/features/dashboard/utils/dashboard.utils.ts @@ -40,7 +40,7 @@ export function getActivityNavigationPath(activity: Activity): string | null { case "invoice_paid": return `/account/billing/invoices/${activity.relatedId}`; case "service_activated": - return `/account/services/${activity.relatedId}`; + return `/account/subscriptions/${activity.relatedId}`; case "case_created": case "case_closed": return `/account/support/${activity.relatedId}`; diff --git a/apps/portal/src/features/dashboard/views/DashboardView.tsx b/apps/portal/src/features/dashboard/views/DashboardView.tsx index 332e6ca0..2ee9864d 100644 --- a/apps/portal/src/features/dashboard/views/DashboardView.tsx +++ b/apps/portal/src/features/dashboard/views/DashboardView.tsx @@ -10,7 +10,7 @@ import { ErrorState } from "@/components/atoms/error-state"; import { PageLayout } from "@/components/templates"; import { cn } from "@/lib/utils"; import { InlineToast } from "@/components/atoms/inline-toast"; -import { useInternetEligibility } from "@/features/catalog/hooks"; +import { useInternetEligibility } from "@/features/services/hooks"; export function DashboardView() { const { user, isAuthenticated, loading: authLoading, clearLoading } = useAuthStore(); diff --git a/apps/portal/src/features/realtime/components/AccountEventsListener.tsx b/apps/portal/src/features/realtime/components/AccountEventsListener.tsx index b563c789..d7b84985 100644 --- a/apps/portal/src/features/realtime/components/AccountEventsListener.tsx +++ b/apps/portal/src/features/realtime/components/AccountEventsListener.tsx @@ -42,15 +42,15 @@ export function AccountEventsListener() { const parsed = JSON.parse(event.data) as RealtimeEventEnvelope; if (!parsed || typeof parsed !== "object") return; - if (parsed.event === "catalog.eligibility.changed") { - logger.info("Received catalog.eligibility.changed; invalidating catalog queries"); - void queryClient.invalidateQueries({ queryKey: queryKeys.catalog.all() }); + if (parsed.event === "services.eligibility.changed") { + logger.info("Received services.eligibility.changed; invalidating services queries"); + void queryClient.invalidateQueries({ queryKey: queryKeys.services.all() }); return; } - if (parsed.event === "catalog.changed") { - logger.info("Received catalog.changed; invalidating catalog queries"); - void queryClient.invalidateQueries({ queryKey: queryKeys.catalog.all() }); + if (parsed.event === "services.changed") { + logger.info("Received services.changed; invalidating services queries"); + void queryClient.invalidateQueries({ queryKey: queryKeys.services.all() }); return; } diff --git a/apps/portal/src/features/catalog/components/base/AddonGroup.tsx b/apps/portal/src/features/services/components/base/AddonGroup.tsx similarity index 99% rename from apps/portal/src/features/catalog/components/base/AddonGroup.tsx rename to apps/portal/src/features/services/components/base/AddonGroup.tsx index 7d890288..0b6b84a4 100644 --- a/apps/portal/src/features/catalog/components/base/AddonGroup.tsx +++ b/apps/portal/src/features/services/components/base/AddonGroup.tsx @@ -1,7 +1,7 @@ "use client"; import { CheckCircleIcon } from "@heroicons/react/24/solid"; -import type { CatalogProductBase } from "@customer-portal/domain/catalog"; +import type { CatalogProductBase } from "@customer-portal/domain/services"; interface AddonGroupProps { addons: Array; selectedAddonSkus: string[]; diff --git a/apps/portal/src/features/catalog/components/base/AddressConfirmation.tsx b/apps/portal/src/features/services/components/base/AddressConfirmation.tsx similarity index 99% rename from apps/portal/src/features/catalog/components/base/AddressConfirmation.tsx rename to apps/portal/src/features/services/components/base/AddressConfirmation.tsx index 4906c0d8..9306312e 100644 --- a/apps/portal/src/features/catalog/components/base/AddressConfirmation.tsx +++ b/apps/portal/src/features/services/components/base/AddressConfirmation.tsx @@ -156,7 +156,7 @@ export function AddressConfirmation({ const updatedAddress = await accountService.updateAddress(sanitizedAddress); // Address changes can affect server-personalized catalog results (eligibility). - await queryClient.invalidateQueries({ queryKey: queryKeys.catalog.all() }); + await queryClient.invalidateQueries({ queryKey: queryKeys.services.all() }); // Rebuild BillingInfo from updated address const updatedInfo: BillingInfo = { diff --git a/apps/portal/src/features/catalog/components/base/AddressForm.tsx b/apps/portal/src/features/services/components/base/AddressForm.tsx similarity index 100% rename from apps/portal/src/features/catalog/components/base/AddressForm.tsx rename to apps/portal/src/features/services/components/base/AddressForm.tsx diff --git a/apps/portal/src/features/catalog/components/base/CardBadge.tsx b/apps/portal/src/features/services/components/base/CardBadge.tsx similarity index 100% rename from apps/portal/src/features/catalog/components/base/CardBadge.tsx rename to apps/portal/src/features/services/components/base/CardBadge.tsx diff --git a/apps/portal/src/features/catalog/components/base/CardPricing.tsx b/apps/portal/src/features/services/components/base/CardPricing.tsx similarity index 100% rename from apps/portal/src/features/catalog/components/base/CardPricing.tsx rename to apps/portal/src/features/services/components/base/CardPricing.tsx diff --git a/apps/portal/src/features/catalog/components/base/CatalogBackLink.tsx b/apps/portal/src/features/services/components/base/CatalogBackLink.tsx similarity index 100% rename from apps/portal/src/features/catalog/components/base/CatalogBackLink.tsx rename to apps/portal/src/features/services/components/base/CatalogBackLink.tsx diff --git a/apps/portal/src/features/catalog/components/base/CatalogHero.tsx b/apps/portal/src/features/services/components/base/CatalogHero.tsx similarity index 100% rename from apps/portal/src/features/catalog/components/base/CatalogHero.tsx rename to apps/portal/src/features/services/components/base/CatalogHero.tsx diff --git a/apps/portal/src/features/catalog/components/base/ConfigurationStep.tsx b/apps/portal/src/features/services/components/base/ConfigurationStep.tsx similarity index 100% rename from apps/portal/src/features/catalog/components/base/ConfigurationStep.tsx rename to apps/portal/src/features/services/components/base/ConfigurationStep.tsx diff --git a/apps/portal/src/features/catalog/components/base/EnhancedOrderSummary.tsx b/apps/portal/src/features/services/components/base/EnhancedOrderSummary.tsx similarity index 99% rename from apps/portal/src/features/catalog/components/base/EnhancedOrderSummary.tsx rename to apps/portal/src/features/services/components/base/EnhancedOrderSummary.tsx index 5dbbe283..b0e61701 100644 --- a/apps/portal/src/features/catalog/components/base/EnhancedOrderSummary.tsx +++ b/apps/portal/src/features/services/components/base/EnhancedOrderSummary.tsx @@ -10,7 +10,7 @@ import { Button } from "@/components/atoms/button"; import { useRouter } from "next/navigation"; // Align with shared catalog contracts -import type { CatalogProductBase } from "@customer-portal/domain/catalog"; +import type { CatalogProductBase } from "@customer-portal/domain/services"; import type { CheckoutTotals } from "@customer-portal/domain/orders"; // Enhanced order item representation for UI summary diff --git a/apps/portal/src/features/catalog/components/base/OrderSummary.tsx b/apps/portal/src/features/services/components/base/OrderSummary.tsx similarity index 99% rename from apps/portal/src/features/catalog/components/base/OrderSummary.tsx rename to apps/portal/src/features/services/components/base/OrderSummary.tsx index a5756a89..04b0958c 100644 --- a/apps/portal/src/features/catalog/components/base/OrderSummary.tsx +++ b/apps/portal/src/features/services/components/base/OrderSummary.tsx @@ -1,5 +1,5 @@ import { ArrowLeftIcon, ArrowRightIcon } from "@heroicons/react/24/outline"; -import type { CatalogProductBase } from "@customer-portal/domain/catalog"; +import type { CatalogProductBase } from "@customer-portal/domain/services"; import { useRouter } from "next/navigation"; import { Button } from "@/components/atoms/button"; diff --git a/apps/portal/src/features/catalog/components/base/PaymentForm.tsx b/apps/portal/src/features/services/components/base/PaymentForm.tsx similarity index 100% rename from apps/portal/src/features/catalog/components/base/PaymentForm.tsx rename to apps/portal/src/features/services/components/base/PaymentForm.tsx diff --git a/apps/portal/src/features/catalog/components/base/PricingDisplay.tsx b/apps/portal/src/features/services/components/base/PricingDisplay.tsx similarity index 99% rename from apps/portal/src/features/catalog/components/base/PricingDisplay.tsx rename to apps/portal/src/features/services/components/base/PricingDisplay.tsx index 79ab096c..da9a24d8 100644 --- a/apps/portal/src/features/catalog/components/base/PricingDisplay.tsx +++ b/apps/portal/src/features/services/components/base/PricingDisplay.tsx @@ -3,7 +3,7 @@ import { ReactNode } from "react"; import { CurrencyYenIcon, InformationCircleIcon } from "@heroicons/react/24/outline"; import { Formatting } from "@customer-portal/domain/toolkit"; -import type { PricingTier } from "@customer-portal/domain/catalog"; +import type { PricingTier } from "@customer-portal/domain/services"; const { formatCurrency } = Formatting; diff --git a/apps/portal/src/features/catalog/components/base/ProductCard.tsx b/apps/portal/src/features/services/components/base/ProductCard.tsx similarity index 100% rename from apps/portal/src/features/catalog/components/base/ProductCard.tsx rename to apps/portal/src/features/services/components/base/ProductCard.tsx diff --git a/apps/portal/src/features/catalog/components/base/ProductComparison.tsx b/apps/portal/src/features/services/components/base/ProductComparison.tsx similarity index 100% rename from apps/portal/src/features/catalog/components/base/ProductComparison.tsx rename to apps/portal/src/features/services/components/base/ProductComparison.tsx diff --git a/apps/portal/src/features/catalog/components/base/ServiceHighlights.tsx b/apps/portal/src/features/services/components/base/ServiceHighlights.tsx similarity index 100% rename from apps/portal/src/features/catalog/components/base/ServiceHighlights.tsx rename to apps/portal/src/features/services/components/base/ServiceHighlights.tsx diff --git a/apps/portal/src/features/catalog/components/base/index.ts b/apps/portal/src/features/services/components/base/index.ts similarity index 100% rename from apps/portal/src/features/catalog/components/base/index.ts rename to apps/portal/src/features/services/components/base/index.ts diff --git a/apps/portal/src/features/catalog/components/common/FeatureCard.tsx b/apps/portal/src/features/services/components/common/FeatureCard.tsx similarity index 100% rename from apps/portal/src/features/catalog/components/common/FeatureCard.tsx rename to apps/portal/src/features/services/components/common/FeatureCard.tsx diff --git a/apps/portal/src/features/catalog/components/common/RedirectAuthenticatedToAccountServices.tsx b/apps/portal/src/features/services/components/common/RedirectAuthenticatedToAccountServices.tsx similarity index 100% rename from apps/portal/src/features/catalog/components/common/RedirectAuthenticatedToAccountServices.tsx rename to apps/portal/src/features/services/components/common/RedirectAuthenticatedToAccountServices.tsx diff --git a/apps/portal/src/features/catalog/components/common/ServiceHeroCard.tsx b/apps/portal/src/features/services/components/common/ServiceHeroCard.tsx similarity index 100% rename from apps/portal/src/features/catalog/components/common/ServiceHeroCard.tsx rename to apps/portal/src/features/services/components/common/ServiceHeroCard.tsx diff --git a/apps/portal/src/features/catalog/components/common/ServicesGrid.tsx b/apps/portal/src/features/services/components/common/ServicesGrid.tsx similarity index 100% rename from apps/portal/src/features/catalog/components/common/ServicesGrid.tsx rename to apps/portal/src/features/services/components/common/ServicesGrid.tsx diff --git a/apps/portal/src/features/catalog/components/index.ts b/apps/portal/src/features/services/components/index.ts similarity index 100% rename from apps/portal/src/features/catalog/components/index.ts rename to apps/portal/src/features/services/components/index.ts diff --git a/apps/portal/src/features/catalog/components/internet/HowItWorksSection.tsx b/apps/portal/src/features/services/components/internet/HowItWorksSection.tsx similarity index 100% rename from apps/portal/src/features/catalog/components/internet/HowItWorksSection.tsx rename to apps/portal/src/features/services/components/internet/HowItWorksSection.tsx diff --git a/apps/portal/src/features/catalog/components/internet/InstallationOptions.tsx b/apps/portal/src/features/services/components/internet/InstallationOptions.tsx similarity index 97% rename from apps/portal/src/features/catalog/components/internet/InstallationOptions.tsx rename to apps/portal/src/features/services/components/internet/InstallationOptions.tsx index 949f5417..4c685cec 100644 --- a/apps/portal/src/features/catalog/components/internet/InstallationOptions.tsx +++ b/apps/portal/src/features/services/components/internet/InstallationOptions.tsx @@ -1,7 +1,7 @@ "use client"; -import type { InternetInstallationCatalogItem } from "@customer-portal/domain/catalog"; -import { CardPricing } from "@/features/catalog/components/base/CardPricing"; +import type { InternetInstallationCatalogItem } from "@customer-portal/domain/services"; +import { CardPricing } from "@/features/services/components/base/CardPricing"; interface InstallationOptionsProps { installations: InternetInstallationCatalogItem[]; diff --git a/apps/portal/src/features/catalog/components/internet/InternetConfigureView.tsx b/apps/portal/src/features/services/components/internet/InternetConfigureView.tsx similarity index 88% rename from apps/portal/src/features/catalog/components/internet/InternetConfigureView.tsx rename to apps/portal/src/features/services/components/internet/InternetConfigureView.tsx index 982f690e..e8e4a696 100644 --- a/apps/portal/src/features/catalog/components/internet/InternetConfigureView.tsx +++ b/apps/portal/src/features/services/components/internet/InternetConfigureView.tsx @@ -1,7 +1,7 @@ "use client"; import { InternetConfigureContainer } from "./configure"; -import type { UseInternetConfigureResult } from "@/features/catalog/hooks/useInternetConfigure"; +import type { UseInternetConfigureResult } from "@/features/services/hooks/useInternetConfigure"; interface Props extends UseInternetConfigureResult { onConfirm: () => void; diff --git a/apps/portal/src/features/catalog/components/internet/InternetImportantNotes.tsx b/apps/portal/src/features/services/components/internet/InternetImportantNotes.tsx similarity index 100% rename from apps/portal/src/features/catalog/components/internet/InternetImportantNotes.tsx rename to apps/portal/src/features/services/components/internet/InternetImportantNotes.tsx diff --git a/apps/portal/src/features/catalog/components/internet/InternetModalShell.tsx b/apps/portal/src/features/services/components/internet/InternetModalShell.tsx similarity index 100% rename from apps/portal/src/features/catalog/components/internet/InternetModalShell.tsx rename to apps/portal/src/features/services/components/internet/InternetModalShell.tsx diff --git a/apps/portal/src/features/catalog/components/internet/InternetOfferingCard.tsx b/apps/portal/src/features/services/components/internet/InternetOfferingCard.tsx similarity index 98% rename from apps/portal/src/features/catalog/components/internet/InternetOfferingCard.tsx rename to apps/portal/src/features/services/components/internet/InternetOfferingCard.tsx index 6d3ed82f..b0b38169 100644 --- a/apps/portal/src/features/catalog/components/internet/InternetOfferingCard.tsx +++ b/apps/portal/src/features/services/components/internet/InternetOfferingCard.tsx @@ -2,7 +2,7 @@ import { Home, Building2, Zap } from "lucide-react"; import { Button } from "@/components/atoms/button"; -import { CardBadge } from "@/features/catalog/components/base/CardBadge"; +import { CardBadge } from "@/features/services/components/base/CardBadge"; import { cn } from "@/lib/utils"; interface TierInfo { diff --git a/apps/portal/src/features/catalog/components/internet/InternetPlanCard.tsx b/apps/portal/src/features/services/components/internet/InternetPlanCard.tsx similarity index 94% rename from apps/portal/src/features/catalog/components/internet/InternetPlanCard.tsx rename to apps/portal/src/features/services/components/internet/InternetPlanCard.tsx index 615fe0fc..dbd788c5 100644 --- a/apps/portal/src/features/catalog/components/internet/InternetPlanCard.tsx +++ b/apps/portal/src/features/services/components/internet/InternetPlanCard.tsx @@ -6,15 +6,15 @@ import { ArrowRightIcon, CheckIcon } from "@heroicons/react/24/outline"; import type { InternetPlanCatalogItem, InternetInstallationCatalogItem, -} from "@customer-portal/domain/catalog"; +} from "@customer-portal/domain/services"; import { useRouter } from "next/navigation"; -import { CardPricing } from "@/features/catalog/components/base/CardPricing"; -import { CardBadge } from "@/features/catalog/components/base/CardBadge"; -import type { BadgeVariant } from "@/features/catalog/components/base/CardBadge"; -import { useCatalogStore } from "@/features/catalog/services/catalog.store"; +import { CardPricing } from "@/features/services/components/base/CardPricing"; +import { CardBadge } from "@/features/services/components/base/CardBadge"; +import type { BadgeVariant } from "@/features/services/components/base/CardBadge"; +import { useCatalogStore } from "@/features/services/services/services.store"; import { IS_DEVELOPMENT } from "@/config/environment"; -import { parsePlanName } from "@/features/catalog/components/internet/utils/planName"; -import { useServicesBasePath } from "@/features/catalog/hooks/useServicesBasePath"; +import { parsePlanName } from "@/features/services/components/internet/utils/planName"; +import { useServicesBasePath } from "@/features/services/hooks/useServicesBasePath"; interface InternetPlanCardProps { plan: InternetPlanCatalogItem; diff --git a/apps/portal/src/features/catalog/components/internet/InternetTierPricingModal.tsx b/apps/portal/src/features/services/components/internet/InternetTierPricingModal.tsx similarity index 93% rename from apps/portal/src/features/catalog/components/internet/InternetTierPricingModal.tsx rename to apps/portal/src/features/services/components/internet/InternetTierPricingModal.tsx index d97af70c..9a8f27b6 100644 --- a/apps/portal/src/features/catalog/components/internet/InternetTierPricingModal.tsx +++ b/apps/portal/src/features/services/components/internet/InternetTierPricingModal.tsx @@ -2,10 +2,10 @@ import { BoltIcon } from "@heroicons/react/24/outline"; import { Button } from "@/components/atoms/button"; -import { CardBadge } from "@/features/catalog/components/base/CardBadge"; +import { CardBadge } from "@/features/services/components/base/CardBadge"; import { cn } from "@/lib/utils"; -import type { TierInfo } from "@/features/catalog/components/internet/InternetOfferingCard"; -import { InternetModalShell } from "@/features/catalog/components/internet/InternetModalShell"; +import type { TierInfo } from "@/features/services/components/internet/InternetOfferingCard"; +import { InternetModalShell } from "@/features/services/components/internet/InternetModalShell"; interface InternetTierPricingModalProps { isOpen: boolean; diff --git a/apps/portal/src/features/catalog/components/internet/PlanComparisonGuide.tsx b/apps/portal/src/features/services/components/internet/PlanComparisonGuide.tsx similarity index 100% rename from apps/portal/src/features/catalog/components/internet/PlanComparisonGuide.tsx rename to apps/portal/src/features/services/components/internet/PlanComparisonGuide.tsx diff --git a/apps/portal/src/features/catalog/components/internet/PlanHeader.tsx b/apps/portal/src/features/services/components/internet/PlanHeader.tsx similarity index 89% rename from apps/portal/src/features/catalog/components/internet/PlanHeader.tsx rename to apps/portal/src/features/services/components/internet/PlanHeader.tsx index 4ff5c759..6dbc6882 100644 --- a/apps/portal/src/features/catalog/components/internet/PlanHeader.tsx +++ b/apps/portal/src/features/services/components/internet/PlanHeader.tsx @@ -2,10 +2,10 @@ import { ArrowLeftIcon } from "@heroicons/react/24/outline"; import { Button } from "@/components/atoms/button"; -import { CardBadge } from "@/features/catalog/components/base/CardBadge"; -import type { BadgeVariant } from "@/features/catalog/components/base/CardBadge"; -import { parsePlanName } from "@/features/catalog/components/internet/utils/planName"; -import type { InternetPlanCatalogItem } from "@customer-portal/domain/catalog"; +import { CardBadge } from "@/features/services/components/base/CardBadge"; +import type { BadgeVariant } from "@/features/services/components/base/CardBadge"; +import { parsePlanName } from "@/features/services/components/internet/utils/planName"; +import type { InternetPlanCatalogItem } from "@customer-portal/domain/services"; interface PlanHeaderProps { plan: InternetPlanCatalogItem; diff --git a/apps/portal/src/features/catalog/components/internet/PublicOfferingCard.tsx b/apps/portal/src/features/services/components/internet/PublicOfferingCard.tsx similarity index 99% rename from apps/portal/src/features/catalog/components/internet/PublicOfferingCard.tsx rename to apps/portal/src/features/services/components/internet/PublicOfferingCard.tsx index 5ecdebcb..1b7a6acd 100644 --- a/apps/portal/src/features/catalog/components/internet/PublicOfferingCard.tsx +++ b/apps/portal/src/features/services/components/internet/PublicOfferingCard.tsx @@ -3,7 +3,7 @@ import { useState } from "react"; import { ChevronDown, ChevronUp, Home, Building2, Zap, Info, X } from "lucide-react"; import { Button } from "@/components/atoms/button"; -import { CardBadge } from "@/features/catalog/components/base/CardBadge"; +import { CardBadge } from "@/features/services/components/base/CardBadge"; import { cn } from "@/lib/utils"; interface TierInfo { diff --git a/apps/portal/src/features/catalog/components/internet/configure/InternetConfigureContainer.tsx b/apps/portal/src/features/services/components/internet/configure/InternetConfigureContainer.tsx similarity index 97% rename from apps/portal/src/features/catalog/components/internet/configure/InternetConfigureContainer.tsx rename to apps/portal/src/features/services/components/internet/configure/InternetConfigureContainer.tsx index 25dd8906..9a1c01b4 100644 --- a/apps/portal/src/features/catalog/components/internet/configure/InternetConfigureContainer.tsx +++ b/apps/portal/src/features/services/components/internet/configure/InternetConfigureContainer.tsx @@ -8,7 +8,7 @@ import type { InternetPlanCatalogItem, InternetInstallationCatalogItem, InternetAddonCatalogItem, -} from "@customer-portal/domain/catalog"; +} from "@customer-portal/domain/services"; import type { AccessModeValue } from "@customer-portal/domain/orders"; import { ConfigureLoadingSkeleton } from "./components/ConfigureLoadingSkeleton"; import { ServiceConfigurationStep } from "./steps/ServiceConfigurationStep"; @@ -16,8 +16,8 @@ import { InstallationStep } from "./steps/InstallationStep"; import { AddonsStep } from "./steps/AddonsStep"; import { ReviewOrderStep } from "./steps/ReviewOrderStep"; import { useConfigureState } from "./hooks/useConfigureState"; -import { useServicesBasePath } from "@/features/catalog/hooks/useServicesBasePath"; -import { PlanHeader } from "@/features/catalog/components/internet/PlanHeader"; +import { useServicesBasePath } from "@/features/services/hooks/useServicesBasePath"; +import { PlanHeader } from "@/features/services/components/internet/PlanHeader"; interface Props { plan: InternetPlanCatalogItem | null; diff --git a/apps/portal/src/features/catalog/components/internet/configure/components/ConfigureLoadingSkeleton.tsx b/apps/portal/src/features/services/components/internet/configure/components/ConfigureLoadingSkeleton.tsx similarity index 100% rename from apps/portal/src/features/catalog/components/internet/configure/components/ConfigureLoadingSkeleton.tsx rename to apps/portal/src/features/services/components/internet/configure/components/ConfigureLoadingSkeleton.tsx diff --git a/apps/portal/src/features/catalog/components/internet/configure/hooks/useConfigureState.ts b/apps/portal/src/features/services/components/internet/configure/hooks/useConfigureState.ts similarity index 97% rename from apps/portal/src/features/catalog/components/internet/configure/hooks/useConfigureState.ts rename to apps/portal/src/features/services/components/internet/configure/hooks/useConfigureState.ts index d2ebd37b..2dbbab3a 100644 --- a/apps/portal/src/features/catalog/components/internet/configure/hooks/useConfigureState.ts +++ b/apps/portal/src/features/services/components/internet/configure/hooks/useConfigureState.ts @@ -5,7 +5,7 @@ import type { InternetPlanCatalogItem, InternetInstallationCatalogItem, InternetAddonCatalogItem, -} from "@customer-portal/domain/catalog"; +} from "@customer-portal/domain/services"; import type { AccessModeValue } from "@customer-portal/domain/orders"; /** diff --git a/apps/portal/src/features/catalog/components/internet/configure/index.ts b/apps/portal/src/features/services/components/internet/configure/index.ts similarity index 100% rename from apps/portal/src/features/catalog/components/internet/configure/index.ts rename to apps/portal/src/features/services/components/internet/configure/index.ts diff --git a/apps/portal/src/features/catalog/components/internet/configure/steps/AddonsStep.tsx b/apps/portal/src/features/services/components/internet/configure/steps/AddonsStep.tsx similarity index 94% rename from apps/portal/src/features/catalog/components/internet/configure/steps/AddonsStep.tsx rename to apps/portal/src/features/services/components/internet/configure/steps/AddonsStep.tsx index e68717db..f86f0f31 100644 --- a/apps/portal/src/features/catalog/components/internet/configure/steps/AddonsStep.tsx +++ b/apps/portal/src/features/services/components/internet/configure/steps/AddonsStep.tsx @@ -2,9 +2,9 @@ import { Button } from "@/components/atoms/button"; import { StepHeader } from "@/components/atoms"; -import { AddonGroup } from "@/features/catalog/components/base/AddonGroup"; +import { AddonGroup } from "@/features/services/components/base/AddonGroup"; import { ArrowLeftIcon, ArrowRightIcon } from "@heroicons/react/24/outline"; -import type { InternetAddonCatalogItem } from "@customer-portal/domain/catalog"; +import type { InternetAddonCatalogItem } from "@customer-portal/domain/services"; interface Props { addons: InternetAddonCatalogItem[]; diff --git a/apps/portal/src/features/catalog/components/internet/configure/steps/InstallationStep.tsx b/apps/portal/src/features/services/components/internet/configure/steps/InstallationStep.tsx similarity index 98% rename from apps/portal/src/features/catalog/components/internet/configure/steps/InstallationStep.tsx rename to apps/portal/src/features/services/components/internet/configure/steps/InstallationStep.tsx index 1eb8c7ae..96f514ee 100644 --- a/apps/portal/src/features/catalog/components/internet/configure/steps/InstallationStep.tsx +++ b/apps/portal/src/features/services/components/internet/configure/steps/InstallationStep.tsx @@ -4,7 +4,7 @@ import { Button } from "@/components/atoms/button"; import { StepHeader } from "@/components/atoms"; import { InstallationOptions } from "../../InstallationOptions"; import { ArrowLeftIcon, ArrowRightIcon } from "@heroicons/react/24/outline"; -import type { InternetInstallationCatalogItem } from "@customer-portal/domain/catalog"; +import type { InternetInstallationCatalogItem } from "@customer-portal/domain/services"; interface Props { installations: InternetInstallationCatalogItem[]; diff --git a/apps/portal/src/features/catalog/components/internet/configure/steps/ReviewOrderStep.tsx b/apps/portal/src/features/services/components/internet/configure/steps/ReviewOrderStep.tsx similarity index 99% rename from apps/portal/src/features/catalog/components/internet/configure/steps/ReviewOrderStep.tsx rename to apps/portal/src/features/services/components/internet/configure/steps/ReviewOrderStep.tsx index be527a3a..869725d1 100644 --- a/apps/portal/src/features/catalog/components/internet/configure/steps/ReviewOrderStep.tsx +++ b/apps/portal/src/features/services/components/internet/configure/steps/ReviewOrderStep.tsx @@ -8,7 +8,7 @@ import type { InternetPlanCatalogItem, InternetInstallationCatalogItem, InternetAddonCatalogItem, -} from "@customer-portal/domain/catalog"; +} from "@customer-portal/domain/services"; import type { AccessModeValue } from "@customer-portal/domain/orders"; interface Props { diff --git a/apps/portal/src/features/catalog/components/internet/configure/steps/ServiceConfigurationStep.tsx b/apps/portal/src/features/services/components/internet/configure/steps/ServiceConfigurationStep.tsx similarity index 99% rename from apps/portal/src/features/catalog/components/internet/configure/steps/ServiceConfigurationStep.tsx rename to apps/portal/src/features/services/components/internet/configure/steps/ServiceConfigurationStep.tsx index b0def944..a97390a1 100644 --- a/apps/portal/src/features/catalog/components/internet/configure/steps/ServiceConfigurationStep.tsx +++ b/apps/portal/src/features/services/components/internet/configure/steps/ServiceConfigurationStep.tsx @@ -4,7 +4,7 @@ import { Button } from "@/components/atoms/button"; import { StepHeader } from "@/components/atoms"; import { ArrowRightIcon } from "@heroicons/react/24/outline"; import type { ReactNode } from "react"; -import type { InternetPlanCatalogItem } from "@customer-portal/domain/catalog"; +import type { InternetPlanCatalogItem } from "@customer-portal/domain/services"; import type { AccessModeValue } from "@customer-portal/domain/orders"; interface Props { diff --git a/apps/portal/src/features/catalog/components/internet/utils/groupPlansByOfferingType.ts b/apps/portal/src/features/services/components/internet/utils/groupPlansByOfferingType.ts similarity index 98% rename from apps/portal/src/features/catalog/components/internet/utils/groupPlansByOfferingType.ts rename to apps/portal/src/features/services/components/internet/utils/groupPlansByOfferingType.ts index 83d91b63..469bed5c 100644 --- a/apps/portal/src/features/catalog/components/internet/utils/groupPlansByOfferingType.ts +++ b/apps/portal/src/features/services/components/internet/utils/groupPlansByOfferingType.ts @@ -1,4 +1,4 @@ -import type { InternetPlanCatalogItem } from "@customer-portal/domain/catalog"; +import type { InternetPlanCatalogItem } from "@customer-portal/domain/services"; export type InternetOfferingTypeGroup = { offeringType: string; diff --git a/apps/portal/src/features/catalog/components/internet/utils/planName.ts b/apps/portal/src/features/services/components/internet/utils/planName.ts similarity index 98% rename from apps/portal/src/features/catalog/components/internet/utils/planName.ts rename to apps/portal/src/features/services/components/internet/utils/planName.ts index 3d152385..1913a678 100644 --- a/apps/portal/src/features/catalog/components/internet/utils/planName.ts +++ b/apps/portal/src/features/services/components/internet/utils/planName.ts @@ -1,6 +1,6 @@ "use client"; -import type { InternetPlanCatalogItem } from "@customer-portal/domain/catalog"; +import type { InternetPlanCatalogItem } from "@customer-portal/domain/services"; type ParsedPlanName = { baseName: string; diff --git a/apps/portal/src/features/catalog/components/sim/ActivationForm.tsx b/apps/portal/src/features/services/components/sim/ActivationForm.tsx similarity index 98% rename from apps/portal/src/features/catalog/components/sim/ActivationForm.tsx rename to apps/portal/src/features/services/components/sim/ActivationForm.tsx index 9e5d6f24..894e5acb 100644 --- a/apps/portal/src/features/catalog/components/sim/ActivationForm.tsx +++ b/apps/portal/src/features/services/components/sim/ActivationForm.tsx @@ -1,6 +1,6 @@ "use client"; -import { CardPricing } from "@/features/catalog/components/base/CardPricing"; +import { CardPricing } from "@/features/services/components/base/CardPricing"; interface ActivationFeeDetails { amount: number; diff --git a/apps/portal/src/features/catalog/components/sim/MnpForm.tsx b/apps/portal/src/features/services/components/sim/MnpForm.tsx similarity index 100% rename from apps/portal/src/features/catalog/components/sim/MnpForm.tsx rename to apps/portal/src/features/services/components/sim/MnpForm.tsx diff --git a/apps/portal/src/features/catalog/components/sim/SimCallingRates.tsx b/apps/portal/src/features/services/components/sim/SimCallingRates.tsx similarity index 100% rename from apps/portal/src/features/catalog/components/sim/SimCallingRates.tsx rename to apps/portal/src/features/services/components/sim/SimCallingRates.tsx diff --git a/apps/portal/src/features/catalog/components/sim/SimConfigureView.tsx b/apps/portal/src/features/services/components/sim/SimConfigureView.tsx similarity index 97% rename from apps/portal/src/features/catalog/components/sim/SimConfigureView.tsx rename to apps/portal/src/features/services/components/sim/SimConfigureView.tsx index 5488c46a..b7400002 100644 --- a/apps/portal/src/features/catalog/components/sim/SimConfigureView.tsx +++ b/apps/portal/src/features/services/components/sim/SimConfigureView.tsx @@ -3,14 +3,14 @@ import { PageLayout } from "@/components/templates/PageLayout"; import { Button } from "@/components/atoms/button"; import { AnimatedCard } from "@/components/molecules"; -import { AddonGroup } from "@/features/catalog/components/base/AddonGroup"; +import { AddonGroup } from "@/features/services/components/base/AddonGroup"; import { StepHeader } from "@/components/atoms"; -import { SimTypeSelector } from "@/features/catalog/components/sim/SimTypeSelector"; -import { ActivationForm } from "@/features/catalog/components/sim/ActivationForm"; -import { MnpForm } from "@/features/catalog/components/sim/MnpForm"; +import { SimTypeSelector } from "@/features/services/components/sim/SimTypeSelector"; +import { ActivationForm } from "@/features/services/components/sim/ActivationForm"; +import { MnpForm } from "@/features/services/components/sim/MnpForm"; import { ProgressSteps } from "@/components/molecules"; -import { CatalogBackLink } from "@/features/catalog/components/base/CatalogBackLink"; -import { useServicesBasePath } from "@/features/catalog/hooks/useServicesBasePath"; +import { CatalogBackLink } from "@/features/services/components/base/CatalogBackLink"; +import { useServicesBasePath } from "@/features/services/hooks/useServicesBasePath"; import { ArrowLeftIcon, ArrowRightIcon, @@ -18,8 +18,8 @@ import { ExclamationTriangleIcon, UsersIcon, } from "@heroicons/react/24/outline"; -import type { UseSimConfigureResult } from "@/features/catalog/hooks/useSimConfigure"; -import type { SimActivationFeeCatalogItem } from "@customer-portal/domain/catalog"; +import type { UseSimConfigureResult } from "@/features/services/hooks/useSimConfigure"; +import type { SimActivationFeeCatalogItem } from "@customer-portal/domain/services"; type Props = UseSimConfigureResult & { onConfirm: () => void; diff --git a/apps/portal/src/features/catalog/components/sim/SimFees.tsx b/apps/portal/src/features/services/components/sim/SimFees.tsx similarity index 100% rename from apps/portal/src/features/catalog/components/sim/SimFees.tsx rename to apps/portal/src/features/services/components/sim/SimFees.tsx diff --git a/apps/portal/src/features/catalog/components/sim/SimOrderProcess.tsx b/apps/portal/src/features/services/components/sim/SimOrderProcess.tsx similarity index 100% rename from apps/portal/src/features/catalog/components/sim/SimOrderProcess.tsx rename to apps/portal/src/features/services/components/sim/SimOrderProcess.tsx diff --git a/apps/portal/src/features/catalog/components/sim/SimPlanCard.tsx b/apps/portal/src/features/services/components/sim/SimPlanCard.tsx similarity index 90% rename from apps/portal/src/features/catalog/components/sim/SimPlanCard.tsx rename to apps/portal/src/features/services/components/sim/SimPlanCard.tsx index f8960f68..5cdcd7cc 100644 --- a/apps/portal/src/features/catalog/components/sim/SimPlanCard.tsx +++ b/apps/portal/src/features/services/components/sim/SimPlanCard.tsx @@ -4,12 +4,12 @@ import { DevicePhoneMobileIcon } from "@heroicons/react/24/outline"; import { AnimatedCard } from "@/components/molecules/AnimatedCard/AnimatedCard"; import { Button } from "@/components/atoms/button"; import { ArrowRightIcon } from "@heroicons/react/24/outline"; -import type { SimCatalogProduct } from "@customer-portal/domain/catalog"; -import { CardPricing } from "@/features/catalog/components/base/CardPricing"; -import { CardBadge } from "@/features/catalog/components/base/CardBadge"; +import type { SimCatalogProduct } from "@customer-portal/domain/services"; +import { CardPricing } from "@/features/services/components/base/CardPricing"; +import { CardBadge } from "@/features/services/components/base/CardBadge"; import { useRouter } from "next/navigation"; -import { useCatalogStore } from "@/features/catalog/services/catalog.store"; -import { useServicesBasePath } from "@/features/catalog/hooks/useServicesBasePath"; +import { useCatalogStore } from "@/features/services/services/services.store"; +import { useServicesBasePath } from "@/features/services/hooks/useServicesBasePath"; export type SimPlanCardAction = { label: string; href: string }; export type SimPlanCardActionResolver = diff --git a/apps/portal/src/features/catalog/components/sim/SimPlanTypeSection.tsx b/apps/portal/src/features/services/components/sim/SimPlanTypeSection.tsx similarity index 99% rename from apps/portal/src/features/catalog/components/sim/SimPlanTypeSection.tsx rename to apps/portal/src/features/services/components/sim/SimPlanTypeSection.tsx index 697b86f2..1a50119e 100644 --- a/apps/portal/src/features/catalog/components/sim/SimPlanTypeSection.tsx +++ b/apps/portal/src/features/services/components/sim/SimPlanTypeSection.tsx @@ -2,7 +2,7 @@ import React from "react"; import { UsersIcon } from "@heroicons/react/24/outline"; -import type { SimCatalogProduct } from "@customer-portal/domain/catalog"; +import type { SimCatalogProduct } from "@customer-portal/domain/services"; import { SimPlanCard, type SimPlanCardActionResolver } from "./SimPlanCard"; export function SimPlanTypeSection({ diff --git a/apps/portal/src/features/catalog/components/sim/SimTypeComparison.tsx b/apps/portal/src/features/services/components/sim/SimTypeComparison.tsx similarity index 100% rename from apps/portal/src/features/catalog/components/sim/SimTypeComparison.tsx rename to apps/portal/src/features/services/components/sim/SimTypeComparison.tsx diff --git a/apps/portal/src/features/catalog/components/sim/SimTypeSelector.tsx b/apps/portal/src/features/services/components/sim/SimTypeSelector.tsx similarity index 100% rename from apps/portal/src/features/catalog/components/sim/SimTypeSelector.tsx rename to apps/portal/src/features/services/components/sim/SimTypeSelector.tsx diff --git a/apps/portal/src/features/catalog/components/vpn/VpnPlanCard.tsx b/apps/portal/src/features/services/components/vpn/VpnPlanCard.tsx similarity index 94% rename from apps/portal/src/features/catalog/components/vpn/VpnPlanCard.tsx rename to apps/portal/src/features/services/components/vpn/VpnPlanCard.tsx index 59953c19..036233ea 100644 --- a/apps/portal/src/features/catalog/components/vpn/VpnPlanCard.tsx +++ b/apps/portal/src/features/services/components/vpn/VpnPlanCard.tsx @@ -3,8 +3,8 @@ import { AnimatedCard } from "@/components/molecules"; import { Button } from "@/components/atoms/button"; import { ArrowRight, ShieldCheck } from "lucide-react"; -import type { VpnCatalogProduct } from "@customer-portal/domain/catalog"; -import { CardPricing } from "@/features/catalog/components/base/CardPricing"; +import type { VpnCatalogProduct } from "@customer-portal/domain/services"; +import { CardPricing } from "@/features/services/components/base/CardPricing"; interface VpnPlanCardProps { plan: VpnCatalogProduct; diff --git a/apps/portal/src/features/catalog/containers/InternetConfigure.tsx b/apps/portal/src/features/services/containers/InternetConfigure.tsx similarity index 68% rename from apps/portal/src/features/catalog/containers/InternetConfigure.tsx rename to apps/portal/src/features/services/containers/InternetConfigure.tsx index 5b93545b..6414556e 100644 --- a/apps/portal/src/features/catalog/containers/InternetConfigure.tsx +++ b/apps/portal/src/features/services/containers/InternetConfigure.tsx @@ -1,8 +1,8 @@ "use client"; import { useRouter } from "next/navigation"; -import { useInternetConfigure } from "@/features/catalog/hooks/useInternetConfigure"; -import { InternetConfigureView } from "@/features/catalog/components/internet/InternetConfigureView"; +import { useInternetConfigure } from "@/features/services/hooks/useInternetConfigure"; +import { InternetConfigureView } from "@/features/services/components/internet/InternetConfigureView"; export function InternetConfigureContainer() { const router = useRouter(); diff --git a/apps/portal/src/features/catalog/containers/SimConfigure.tsx b/apps/portal/src/features/services/containers/SimConfigure.tsx similarity index 77% rename from apps/portal/src/features/catalog/containers/SimConfigure.tsx rename to apps/portal/src/features/services/containers/SimConfigure.tsx index 29147ac4..25c817a9 100644 --- a/apps/portal/src/features/catalog/containers/SimConfigure.tsx +++ b/apps/portal/src/features/services/containers/SimConfigure.tsx @@ -1,8 +1,8 @@ "use client"; import { useSearchParams, useRouter } from "next/navigation"; -import { useSimConfigure } from "@/features/catalog/hooks/useSimConfigure"; -import { SimConfigureView } from "@/features/catalog/components/sim/SimConfigureView"; +import { useSimConfigure } from "@/features/services/hooks/useSimConfigure"; +import { SimConfigureView } from "@/features/services/components/sim/SimConfigureView"; export function SimConfigureContainer() { const searchParams = useSearchParams(); diff --git a/apps/portal/src/features/catalog/hooks/index.ts b/apps/portal/src/features/services/hooks/index.ts similarity index 86% rename from apps/portal/src/features/catalog/hooks/index.ts rename to apps/portal/src/features/services/hooks/index.ts index 10c1ca61..0febb2a5 100644 --- a/apps/portal/src/features/catalog/hooks/index.ts +++ b/apps/portal/src/features/services/hooks/index.ts @@ -1,4 +1,4 @@ -export * from "./useCatalog"; +export * from "./useServices"; export * from "./useConfigureParams"; export * from "./useSimConfigure"; export * from "./useInternetConfigure"; diff --git a/apps/portal/src/features/catalog/hooks/useConfigureParams.ts b/apps/portal/src/features/services/hooks/useConfigureParams.ts similarity index 98% rename from apps/portal/src/features/catalog/hooks/useConfigureParams.ts rename to apps/portal/src/features/services/hooks/useConfigureParams.ts index 50ab1b1d..093041f5 100644 --- a/apps/portal/src/features/catalog/hooks/useConfigureParams.ts +++ b/apps/portal/src/features/services/hooks/useConfigureParams.ts @@ -8,7 +8,7 @@ import type { AccessModeValue } from "@customer-portal/domain/orders"; * Parse URL parameters for configuration deep linking * * Note: These params are only used for initial page load/deep linking. - * State management is handled by Zustand store (catalog.store.ts). + * State management is handled by Zustand store (services.store.ts). * The store's restore functions handle parsing these params into state. */ diff --git a/apps/portal/src/features/catalog/hooks/useInternetConfigure.ts b/apps/portal/src/features/services/hooks/useInternetConfigure.ts similarity index 98% rename from apps/portal/src/features/catalog/hooks/useInternetConfigure.ts rename to apps/portal/src/features/services/hooks/useInternetConfigure.ts index e22d80bf..937dd789 100644 --- a/apps/portal/src/features/catalog/hooks/useInternetConfigure.ts +++ b/apps/portal/src/features/services/hooks/useInternetConfigure.ts @@ -3,14 +3,14 @@ import { useEffect, useMemo, useRef } from "react"; import { useRouter, useSearchParams } from "next/navigation"; import { useInternetCatalog, useInternetPlan } from "."; -import { useCatalogStore } from "../services/catalog.store"; +import { useCatalogStore } from "../services/services.store"; import { useServicesBasePath } from "./useServicesBasePath"; import type { AccessModeValue } from "@customer-portal/domain/orders"; import type { InternetPlanCatalogItem, InternetInstallationCatalogItem, InternetAddonCatalogItem, -} from "@customer-portal/domain/catalog"; +} from "@customer-portal/domain/services"; type InstallationTerm = NonNullable< NonNullable["installationTerm"] diff --git a/apps/portal/src/features/catalog/hooks/useInternetEligibility.ts b/apps/portal/src/features/services/hooks/useInternetEligibility.ts similarity index 81% rename from apps/portal/src/features/catalog/hooks/useInternetEligibility.ts rename to apps/portal/src/features/services/hooks/useInternetEligibility.ts index e22d416a..30dca74a 100644 --- a/apps/portal/src/features/catalog/hooks/useInternetEligibility.ts +++ b/apps/portal/src/features/services/hooks/useInternetEligibility.ts @@ -2,12 +2,12 @@ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { queryKeys } from "@/lib/api"; -import { catalogService } from "@/features/catalog/services"; +import { catalogService } from "@/features/services/services"; import type { Address } from "@customer-portal/domain/customer"; export function useInternetEligibility(options?: { enabled?: boolean }) { return useQuery({ - queryKey: queryKeys.catalog.internet.eligibility(), + queryKey: queryKeys.services.internet.eligibility(), queryFn: () => catalogService.getInternetEligibility(), enabled: options?.enabled, }); @@ -20,8 +20,8 @@ export function useRequestInternetEligibilityCheck() { mutationFn: (body?: { notes?: string; address?: Partial
}) => catalogService.requestInternetEligibilityCheck(body), onSuccess: async () => { - await queryClient.invalidateQueries({ queryKey: queryKeys.catalog.internet.eligibility() }); - await queryClient.invalidateQueries({ queryKey: queryKeys.catalog.internet.combined() }); + await queryClient.invalidateQueries({ queryKey: queryKeys.services.internet.eligibility() }); + await queryClient.invalidateQueries({ queryKey: queryKeys.services.internet.combined() }); }, }); } diff --git a/apps/portal/src/features/catalog/hooks/useCatalog.ts b/apps/portal/src/features/services/hooks/useServices.ts similarity index 93% rename from apps/portal/src/features/catalog/hooks/useCatalog.ts rename to apps/portal/src/features/services/hooks/useServices.ts index 236464ec..0b552cf0 100644 --- a/apps/portal/src/features/catalog/hooks/useCatalog.ts +++ b/apps/portal/src/features/services/hooks/useServices.ts @@ -13,7 +13,7 @@ import { catalogService } from "../services"; */ export function useInternetCatalog() { return useQuery({ - queryKey: queryKeys.catalog.internet.combined(), + queryKey: queryKeys.services.internet.combined(), queryFn: () => catalogService.getInternetCatalog(), }); } @@ -24,7 +24,7 @@ export function useInternetCatalog() { */ export function useSimCatalog() { return useQuery({ - queryKey: queryKeys.catalog.sim.combined(), + queryKey: queryKeys.services.sim.combined(), queryFn: () => catalogService.getSimCatalog(), }); } @@ -35,7 +35,7 @@ export function useSimCatalog() { */ export function useVpnCatalog() { return useQuery({ - queryKey: queryKeys.catalog.vpn.combined(), + queryKey: queryKeys.services.vpn.combined(), queryFn: () => catalogService.getVpnCatalog(), }); } diff --git a/apps/portal/src/features/catalog/hooks/useServicesBasePath.ts b/apps/portal/src/features/services/hooks/useServicesBasePath.ts similarity index 100% rename from apps/portal/src/features/catalog/hooks/useServicesBasePath.ts rename to apps/portal/src/features/services/hooks/useServicesBasePath.ts diff --git a/apps/portal/src/features/catalog/hooks/useSimConfigure.ts b/apps/portal/src/features/services/hooks/useSimConfigure.ts similarity index 98% rename from apps/portal/src/features/catalog/hooks/useSimConfigure.ts rename to apps/portal/src/features/services/hooks/useSimConfigure.ts index d0994aac..77905e64 100644 --- a/apps/portal/src/features/catalog/hooks/useSimConfigure.ts +++ b/apps/portal/src/features/services/hooks/useSimConfigure.ts @@ -3,7 +3,7 @@ import { useEffect, useCallback, useMemo, useRef } from "react"; import { useRouter, useSearchParams } from "next/navigation"; import { useSimCatalog, useSimPlan } from "."; -import { useCatalogStore } from "../services/catalog.store"; +import { useCatalogStore } from "../services/services.store"; import { useServicesBasePath } from "./useServicesBasePath"; import { simConfigureFormSchema, @@ -15,7 +15,7 @@ import { import type { SimCatalogProduct, SimActivationFeeCatalogItem, -} from "@customer-portal/domain/catalog"; +} from "@customer-portal/domain/services"; export type UseSimConfigureResult = { // data diff --git a/apps/portal/src/features/catalog/index.ts b/apps/portal/src/features/services/index.ts similarity index 69% rename from apps/portal/src/features/catalog/index.ts rename to apps/portal/src/features/services/index.ts index 21b163f0..03d25e6d 100644 --- a/apps/portal/src/features/catalog/index.ts +++ b/apps/portal/src/features/services/index.ts @@ -1,6 +1,6 @@ /** - * Catalog Feature Module - * Product catalog and ordering functionality including components, hooks, and services + * Services Feature Module + * Service browsing and ordering functionality including components, hooks, and services */ // Components diff --git a/apps/portal/src/features/services/services/index.ts b/apps/portal/src/features/services/services/index.ts new file mode 100644 index 00000000..9d4462df --- /dev/null +++ b/apps/portal/src/features/services/services/index.ts @@ -0,0 +1 @@ +export { catalogService } from "./services.service"; diff --git a/apps/portal/src/features/catalog/services/catalog.service.ts b/apps/portal/src/features/services/services/services.service.ts similarity index 89% rename from apps/portal/src/features/catalog/services/catalog.service.ts rename to apps/portal/src/features/services/services/services.service.ts index 58ed4caf..de6a5fd8 100644 --- a/apps/portal/src/features/catalog/services/catalog.service.ts +++ b/apps/portal/src/features/services/services/services.service.ts @@ -17,12 +17,12 @@ import { type SimCatalogProduct, type VpnCatalogCollection, type VpnCatalogProduct, -} from "@customer-portal/domain/catalog"; +} from "@customer-portal/domain/services"; import type { Address } from "@customer-portal/domain/customer"; export const catalogService = { async getInternetCatalog(): Promise { - const response = await apiClient.GET("/api/catalog/internet/plans"); + const response = await apiClient.GET("/api/services/internet/plans"); const data = getDataOrThrow( response, "Failed to load internet catalog" @@ -32,7 +32,7 @@ export const catalogService = { async getInternetInstallations(): Promise { const response = await apiClient.GET( - "/api/catalog/internet/installations" + "/api/services/internet/installations" ); const data = getDataOrDefault(response, []); return internetInstallationCatalogItemSchema.array().parse(data); @@ -40,47 +40,47 @@ export const catalogService = { async getInternetAddons(): Promise { const response = await apiClient.GET( - "/api/catalog/internet/addons" + "/api/services/internet/addons" ); const data = getDataOrDefault(response, []); return internetAddonCatalogItemSchema.array().parse(data); }, async getSimCatalog(): Promise { - const response = await apiClient.GET("/api/catalog/sim/plans"); + const response = await apiClient.GET("/api/services/sim/plans"); const data = getDataOrDefault(response, EMPTY_SIM_CATALOG); return data; // BFF already validated }, async getSimActivationFees(): Promise { const response = await apiClient.GET( - "/api/catalog/sim/activation-fees" + "/api/services/sim/activation-fees" ); const data = getDataOrDefault(response, []); return simActivationFeeCatalogItemSchema.array().parse(data); }, async getSimAddons(): Promise { - const response = await apiClient.GET("/api/catalog/sim/addons"); + const response = await apiClient.GET("/api/services/sim/addons"); const data = getDataOrDefault(response, []); return simCatalogProductSchema.array().parse(data); }, async getVpnCatalog(): Promise { - const response = await apiClient.GET("/api/catalog/vpn/plans"); + const response = await apiClient.GET("/api/services/vpn/plans"); const data = getDataOrDefault(response, EMPTY_VPN_CATALOG); return data; // BFF already validated }, async getVpnActivationFees(): Promise { - const response = await apiClient.GET("/api/catalog/vpn/activation-fees"); + const response = await apiClient.GET("/api/services/vpn/activation-fees"); const data = getDataOrDefault(response, []); return vpnCatalogProductSchema.array().parse(data); }, async getInternetEligibility(): Promise { const response = await apiClient.GET( - "/api/catalog/internet/eligibility" + "/api/services/internet/eligibility" ); const data = getDataOrThrow(response, "Failed to load internet eligibility"); return internetEligibilityDetailsSchema.parse(data); @@ -91,7 +91,7 @@ export const catalogService = { address?: Partial
; }): Promise<{ requestId: string }> { const response = await apiClient.POST<{ requestId: string }>( - "/api/catalog/internet/eligibility-request", + "/api/services/internet/eligibility-request", { body: body ?? {}, } diff --git a/apps/portal/src/features/catalog/services/catalog.store.ts b/apps/portal/src/features/services/services/services.store.ts similarity index 100% rename from apps/portal/src/features/catalog/services/catalog.store.ts rename to apps/portal/src/features/services/services/services.store.ts diff --git a/apps/portal/src/features/services/utils/index.ts b/apps/portal/src/features/services/utils/index.ts new file mode 100644 index 00000000..317073c5 --- /dev/null +++ b/apps/portal/src/features/services/utils/index.ts @@ -0,0 +1,2 @@ +export * from "./services.utils"; +export * from "./pricing"; diff --git a/apps/portal/src/features/catalog/utils/pricing.ts b/apps/portal/src/features/services/utils/pricing.ts similarity index 90% rename from apps/portal/src/features/catalog/utils/pricing.ts rename to apps/portal/src/features/services/utils/pricing.ts index ec9e4e57..3cff36bb 100644 --- a/apps/portal/src/features/catalog/utils/pricing.ts +++ b/apps/portal/src/features/services/utils/pricing.ts @@ -7,7 +7,7 @@ import { getCatalogProductPriceDisplay, type CatalogProductBase, type CatalogPriceInfo, -} from "@customer-portal/domain/catalog"; +} from "@customer-portal/domain/services"; // Re-export domain type for compatibility export type PriceInfo = CatalogPriceInfo; diff --git a/apps/portal/src/features/catalog/utils/catalog.utils.ts b/apps/portal/src/features/services/utils/services.utils.ts similarity index 96% rename from apps/portal/src/features/catalog/utils/catalog.utils.ts rename to apps/portal/src/features/services/utils/services.utils.ts index 9033a926..140f073e 100644 --- a/apps/portal/src/features/catalog/utils/catalog.utils.ts +++ b/apps/portal/src/features/services/utils/services.utils.ts @@ -9,8 +9,8 @@ import type { InternetInstallationCatalogItem, SimCatalogProduct, VpnCatalogProduct, -} from "@customer-portal/domain/catalog"; -import { calculateSavingsPercentage } from "@customer-portal/domain/catalog"; +} from "@customer-portal/domain/services"; +import { calculateSavingsPercentage } from "@customer-portal/domain/services"; type CatalogProduct = | InternetPlanCatalogItem diff --git a/apps/portal/src/features/catalog/views/InternetConfigure.tsx b/apps/portal/src/features/services/views/InternetConfigure.tsx similarity index 92% rename from apps/portal/src/features/catalog/views/InternetConfigure.tsx rename to apps/portal/src/features/services/views/InternetConfigure.tsx index fd78b7d9..f41396c7 100644 --- a/apps/portal/src/features/catalog/views/InternetConfigure.tsx +++ b/apps/portal/src/features/services/views/InternetConfigure.tsx @@ -2,8 +2,8 @@ import { usePathname, useRouter } from "next/navigation"; import { logger } from "@/lib/logger"; -import { useInternetConfigure } from "@/features/catalog/hooks/useInternetConfigure"; -import { InternetConfigureView as InternetConfigureInnerView } from "@/features/catalog/components/internet/InternetConfigureView"; +import { useInternetConfigure } from "@/features/services/hooks/useInternetConfigure"; +import { InternetConfigureView as InternetConfigureInnerView } from "@/features/services/components/internet/InternetConfigureView"; export function InternetConfigureContainer() { const router = useRouter(); diff --git a/apps/portal/src/features/catalog/views/InternetPlans.tsx b/apps/portal/src/features/services/views/InternetPlans.tsx similarity index 97% rename from apps/portal/src/features/catalog/views/InternetPlans.tsx rename to apps/portal/src/features/services/views/InternetPlans.tsx index 54caf808..a5bb3588 100644 --- a/apps/portal/src/features/catalog/views/InternetPlans.tsx +++ b/apps/portal/src/features/services/views/InternetPlans.tsx @@ -3,29 +3,29 @@ import { useEffect, useMemo, useState } from "react"; import { useRouter, useSearchParams } from "next/navigation"; import { Server, CheckCircle, Clock, TriangleAlert, MapPin } from "lucide-react"; -import { useInternetCatalog } from "@/features/catalog/hooks"; +import { useInternetCatalog } from "@/features/services/hooks"; import { useActiveSubscriptions } from "@/features/subscriptions/hooks/useSubscriptions"; import type { InternetPlanCatalogItem, InternetInstallationCatalogItem, -} from "@customer-portal/domain/catalog"; +} from "@customer-portal/domain/services"; import { Skeleton } from "@/components/atoms/loading-skeleton"; import { AsyncBlock } from "@/components/molecules/AsyncBlock/AsyncBlock"; import { AlertBanner } from "@/components/molecules/AlertBanner/AlertBanner"; import { Button } from "@/components/atoms/button"; -import { CatalogBackLink } from "@/features/catalog/components/base/CatalogBackLink"; -import { useServicesBasePath } from "@/features/catalog/hooks/useServicesBasePath"; -import { InternetImportantNotes } from "@/features/catalog/components/internet/InternetImportantNotes"; +import { CatalogBackLink } from "@/features/services/components/base/CatalogBackLink"; +import { useServicesBasePath } from "@/features/services/hooks/useServicesBasePath"; +import { InternetImportantNotes } from "@/features/services/components/internet/InternetImportantNotes"; import { InternetOfferingCard, type TierInfo, -} from "@/features/catalog/components/internet/InternetOfferingCard"; -import { PublicInternetPlansContent } from "@/features/catalog/views/PublicInternetPlans"; -import { PlanComparisonGuide } from "@/features/catalog/components/internet/PlanComparisonGuide"; +} from "@/features/services/components/internet/InternetOfferingCard"; +import { PublicInternetPlansContent } from "@/features/services/views/PublicInternetPlans"; +import { PlanComparisonGuide } from "@/features/services/components/internet/PlanComparisonGuide"; import { useInternetEligibility, useRequestInternetEligibilityCheck, -} from "@/features/catalog/hooks"; +} from "@/features/services/hooks"; import { useAuthSession } from "@/features/auth/services/auth.store"; import { cn } from "@/lib/utils"; diff --git a/apps/portal/src/features/catalog/views/PublicInternetConfigure.tsx b/apps/portal/src/features/services/views/PublicInternetConfigure.tsx similarity index 94% rename from apps/portal/src/features/catalog/views/PublicInternetConfigure.tsx rename to apps/portal/src/features/services/views/PublicInternetConfigure.tsx index 8c6ff870..9a760d27 100644 --- a/apps/portal/src/features/catalog/views/PublicInternetConfigure.tsx +++ b/apps/portal/src/features/services/views/PublicInternetConfigure.tsx @@ -2,11 +2,11 @@ import { useSearchParams } from "next/navigation"; import { WifiIcon, ClockIcon, EnvelopeIcon, CheckCircleIcon } from "@heroicons/react/24/outline"; -import { CatalogBackLink } from "@/features/catalog/components/base/CatalogBackLink"; +import { CatalogBackLink } from "@/features/services/components/base/CatalogBackLink"; import { InlineAuthSection } from "@/features/auth/components/InlineAuthSection/InlineAuthSection"; -import { useServicesBasePath } from "@/features/catalog/hooks/useServicesBasePath"; -import { useInternetPlan } from "@/features/catalog/hooks"; -import { CardPricing } from "@/features/catalog/components/base/CardPricing"; +import { useServicesBasePath } from "@/features/services/hooks/useServicesBasePath"; +import { useInternetPlan } from "@/features/services/hooks"; +import { CardPricing } from "@/features/services/components/base/CardPricing"; import { Skeleton } from "@/components/atoms/loading-skeleton"; /** diff --git a/apps/portal/src/features/catalog/views/PublicInternetPlans.tsx b/apps/portal/src/features/services/views/PublicInternetPlans.tsx similarity index 96% rename from apps/portal/src/features/catalog/views/PublicInternetPlans.tsx rename to apps/portal/src/features/services/views/PublicInternetPlans.tsx index b67fe3d2..e026834e 100644 --- a/apps/portal/src/features/catalog/views/PublicInternetPlans.tsx +++ b/apps/portal/src/features/services/views/PublicInternetPlans.tsx @@ -13,22 +13,22 @@ import { Wrench, Globe, } from "lucide-react"; -import { useInternetCatalog } from "@/features/catalog/hooks"; +import { useInternetCatalog } from "@/features/services/hooks"; import type { InternetPlanCatalogItem, InternetInstallationCatalogItem, -} from "@customer-portal/domain/catalog"; +} from "@customer-portal/domain/services"; import { Skeleton } from "@/components/atoms/loading-skeleton"; import { AlertBanner } from "@/components/molecules/AlertBanner/AlertBanner"; -import { CatalogBackLink } from "@/features/catalog/components/base/CatalogBackLink"; -import { useServicesBasePath } from "@/features/catalog/hooks/useServicesBasePath"; +import { CatalogBackLink } from "@/features/services/components/base/CatalogBackLink"; +import { useServicesBasePath } from "@/features/services/hooks/useServicesBasePath"; import { Button } from "@/components/atoms/button"; -import { PublicOfferingCard } from "@/features/catalog/components/internet/PublicOfferingCard"; -import type { TierInfo } from "@/features/catalog/components/internet/PublicOfferingCard"; +import { PublicOfferingCard } from "@/features/services/components/internet/PublicOfferingCard"; +import type { TierInfo } from "@/features/services/components/internet/PublicOfferingCard"; import { ServiceHighlights, HighlightFeature, -} from "@/features/catalog/components/base/ServiceHighlights"; +} from "@/features/services/components/base/ServiceHighlights"; // Types interface GroupedOffering { diff --git a/apps/portal/src/features/catalog/views/PublicSimConfigure.tsx b/apps/portal/src/features/services/views/PublicSimConfigure.tsx similarity index 95% rename from apps/portal/src/features/catalog/views/PublicSimConfigure.tsx rename to apps/portal/src/features/services/views/PublicSimConfigure.tsx index 166cce40..ce7374fb 100644 --- a/apps/portal/src/features/catalog/views/PublicSimConfigure.tsx +++ b/apps/portal/src/features/services/views/PublicSimConfigure.tsx @@ -3,11 +3,11 @@ import { useSearchParams } from "next/navigation"; import { DevicePhoneMobileIcon, CheckIcon, BoltIcon } from "@heroicons/react/24/outline"; import { AlertBanner } from "@/components/molecules/AlertBanner/AlertBanner"; -import { CatalogBackLink } from "@/features/catalog/components/base/CatalogBackLink"; -import { useServicesBasePath } from "@/features/catalog/hooks/useServicesBasePath"; -import { useSimPlan } from "@/features/catalog/hooks"; +import { CatalogBackLink } from "@/features/services/components/base/CatalogBackLink"; +import { useServicesBasePath } from "@/features/services/hooks/useServicesBasePath"; +import { useSimPlan } from "@/features/services/hooks"; import { InlineAuthSection } from "@/features/auth/components/InlineAuthSection/InlineAuthSection"; -import { CardPricing } from "@/features/catalog/components/base/CardPricing"; +import { CardPricing } from "@/features/services/components/base/CardPricing"; import { Skeleton } from "@/components/atoms/loading-skeleton"; /** diff --git a/apps/portal/src/features/catalog/views/PublicSimPlans.tsx b/apps/portal/src/features/services/views/PublicSimPlans.tsx similarity index 98% rename from apps/portal/src/features/catalog/views/PublicSimPlans.tsx rename to apps/portal/src/features/services/views/PublicSimPlans.tsx index a5d5c662..03fe3831 100644 --- a/apps/portal/src/features/catalog/views/PublicSimPlans.tsx +++ b/apps/portal/src/features/services/views/PublicSimPlans.tsx @@ -20,15 +20,15 @@ import { } from "lucide-react"; import { Skeleton } from "@/components/atoms/loading-skeleton"; import { Button } from "@/components/atoms/button"; -import { useSimCatalog } from "@/features/catalog/hooks"; -import type { SimCatalogProduct } from "@customer-portal/domain/catalog"; -import { CatalogBackLink } from "@/features/catalog/components/base/CatalogBackLink"; -import { useServicesBasePath } from "@/features/catalog/hooks/useServicesBasePath"; -import { CardPricing } from "@/features/catalog/components/base/CardPricing"; +import { useSimCatalog } from "@/features/services/hooks"; +import type { SimCatalogProduct } from "@customer-portal/domain/services"; +import { CatalogBackLink } from "@/features/services/components/base/CatalogBackLink"; +import { useServicesBasePath } from "@/features/services/hooks/useServicesBasePath"; +import { CardPricing } from "@/features/services/components/base/CardPricing"; import { ServiceHighlights, HighlightFeature, -} from "@/features/catalog/components/base/ServiceHighlights"; +} from "@/features/services/components/base/ServiceHighlights"; interface PlansByType { DataOnly: SimCatalogProduct[]; diff --git a/apps/portal/src/features/catalog/views/PublicVpnPlans.tsx b/apps/portal/src/features/services/views/PublicVpnPlans.tsx similarity index 92% rename from apps/portal/src/features/catalog/views/PublicVpnPlans.tsx rename to apps/portal/src/features/services/views/PublicVpnPlans.tsx index e6a6ed06..c66bead3 100644 --- a/apps/portal/src/features/catalog/views/PublicVpnPlans.tsx +++ b/apps/portal/src/features/services/views/PublicVpnPlans.tsx @@ -1,14 +1,14 @@ "use client"; import { ShieldCheck, Zap } from "lucide-react"; -import { useVpnCatalog } from "@/features/catalog/hooks"; +import { useVpnCatalog } from "@/features/services/hooks"; import { LoadingCard } from "@/components/atoms"; import { AsyncBlock } from "@/components/molecules/AsyncBlock/AsyncBlock"; import { AlertBanner } from "@/components/molecules/AlertBanner/AlertBanner"; -import { VpnPlanCard } from "@/features/catalog/components/vpn/VpnPlanCard"; -import { CatalogBackLink } from "@/features/catalog/components/base/CatalogBackLink"; -import { CatalogHero } from "@/features/catalog/components/base/CatalogHero"; -import { useServicesBasePath } from "@/features/catalog/hooks/useServicesBasePath"; +import { VpnPlanCard } from "@/features/services/components/vpn/VpnPlanCard"; +import { CatalogBackLink } from "@/features/services/components/base/CatalogBackLink"; +import { CatalogHero } from "@/features/services/components/base/CatalogHero"; +import { useServicesBasePath } from "@/features/services/hooks/useServicesBasePath"; /** * Public VPN Plans View diff --git a/apps/portal/src/features/catalog/views/SimConfigure.tsx b/apps/portal/src/features/services/views/SimConfigure.tsx similarity index 86% rename from apps/portal/src/features/catalog/views/SimConfigure.tsx rename to apps/portal/src/features/services/views/SimConfigure.tsx index cf7d7424..e0420aa8 100644 --- a/apps/portal/src/features/catalog/views/SimConfigure.tsx +++ b/apps/portal/src/features/services/views/SimConfigure.tsx @@ -1,8 +1,8 @@ "use client"; import { usePathname, useSearchParams, useRouter } from "next/navigation"; -import { useSimConfigure } from "@/features/catalog/hooks/useSimConfigure"; -import { SimConfigureView as SimConfigureInnerView } from "@/features/catalog/components/sim/SimConfigureView"; +import { useSimConfigure } from "@/features/services/hooks/useSimConfigure"; +import { SimConfigureView as SimConfigureInnerView } from "@/features/services/components/sim/SimConfigureView"; export function SimConfigureContainer() { const searchParams = useSearchParams(); diff --git a/apps/portal/src/features/catalog/views/SimPlans.tsx b/apps/portal/src/features/services/views/SimPlans.tsx similarity index 98% rename from apps/portal/src/features/catalog/views/SimPlans.tsx rename to apps/portal/src/features/services/views/SimPlans.tsx index 77f589cc..d0f92eab 100644 --- a/apps/portal/src/features/catalog/views/SimPlans.tsx +++ b/apps/portal/src/features/services/views/SimPlans.tsx @@ -22,17 +22,17 @@ import { import { Skeleton } from "@/components/atoms/loading-skeleton"; import { Button } from "@/components/atoms/button"; import { AlertBanner } from "@/components/molecules/AlertBanner/AlertBanner"; -import { useSimCatalog } from "@/features/catalog/hooks"; -import type { SimCatalogProduct } from "@customer-portal/domain/catalog"; -import { CatalogBackLink } from "@/features/catalog/components/base/CatalogBackLink"; -import { useServicesBasePath } from "@/features/catalog/hooks/useServicesBasePath"; +import { useSimCatalog } from "@/features/services/hooks"; +import type { SimCatalogProduct } from "@customer-portal/domain/services"; +import { CatalogBackLink } from "@/features/services/components/base/CatalogBackLink"; +import { useServicesBasePath } from "@/features/services/hooks/useServicesBasePath"; import { usePaymentMethods } from "@/features/billing/hooks/useBilling"; -import { CardPricing } from "@/features/catalog/components/base/CardPricing"; +import { CardPricing } from "@/features/services/components/base/CardPricing"; import { useRouter } from "next/navigation"; import { ServiceHighlights, HighlightFeature, -} from "@/features/catalog/components/base/ServiceHighlights"; +} from "@/features/services/components/base/ServiceHighlights"; interface PlansByType { DataOnly: SimCatalogProduct[]; diff --git a/apps/portal/src/features/catalog/views/VpnPlans.tsx b/apps/portal/src/features/services/views/VpnPlans.tsx similarity index 93% rename from apps/portal/src/features/catalog/views/VpnPlans.tsx rename to apps/portal/src/features/services/views/VpnPlans.tsx index 27b5c042..758e4526 100644 --- a/apps/portal/src/features/catalog/views/VpnPlans.tsx +++ b/apps/portal/src/features/services/views/VpnPlans.tsx @@ -2,14 +2,14 @@ import { PageLayout } from "@/components/templates/PageLayout"; import { ShieldCheckIcon } from "@heroicons/react/24/outline"; -import { useVpnCatalog } from "@/features/catalog/hooks"; +import { useVpnCatalog } from "@/features/services/hooks"; import { LoadingCard } from "@/components/atoms"; import { AsyncBlock } from "@/components/molecules/AsyncBlock/AsyncBlock"; import { AlertBanner } from "@/components/molecules/AlertBanner/AlertBanner"; -import { VpnPlanCard } from "@/features/catalog/components/vpn/VpnPlanCard"; -import { CatalogBackLink } from "@/features/catalog/components/base/CatalogBackLink"; -import { CatalogHero } from "@/features/catalog/components/base/CatalogHero"; -import { useServicesBasePath } from "@/features/catalog/hooks/useServicesBasePath"; +import { VpnPlanCard } from "@/features/services/components/vpn/VpnPlanCard"; +import { CatalogBackLink } from "@/features/services/components/base/CatalogBackLink"; +import { CatalogHero } from "@/features/services/components/base/CatalogHero"; +import { useServicesBasePath } from "@/features/services/hooks/useServicesBasePath"; export function VpnPlansView() { const servicesBasePath = useServicesBasePath(); diff --git a/apps/portal/src/features/sim-management/components/SimActions.tsx b/apps/portal/src/features/sim-management/components/SimActions.tsx index d421d254..7687afed 100644 --- a/apps/portal/src/features/sim-management/components/SimActions.tsx +++ b/apps/portal/src/features/sim-management/components/SimActions.tsx @@ -149,7 +149,7 @@ export function SimActions({ onClick={() => { setActiveInfo("topup"); try { - router.push(`/account/services/${subscriptionId}/sim/top-up`); + router.push(`/account/subscriptions/${subscriptionId}/sim/top-up`); } catch { setShowTopUpModal(true); } @@ -177,7 +177,7 @@ export function SimActions({ onClick={() => { setActiveInfo("changePlan"); try { - router.push(`/account/services/${subscriptionId}/sim/change-plan`); + router.push(`/account/subscriptions/${subscriptionId}/sim/change-plan`); } catch { setShowChangePlanModal(true); } @@ -236,7 +236,7 @@ export function SimActions({ onClick={() => { setActiveInfo("cancel"); try { - router.push(`/account/services/${subscriptionId}/sim/cancel`); + router.push(`/account/subscriptions/${subscriptionId}/sim/cancel`); } catch { // Fallback to inline confirmation modal if navigation is unavailable setShowCancelConfirm(true); diff --git a/apps/portal/src/features/sim-management/components/SimManagementSection.tsx b/apps/portal/src/features/sim-management/components/SimManagementSection.tsx index fc3ba9d2..ebb0b65f 100644 --- a/apps/portal/src/features/sim-management/components/SimManagementSection.tsx +++ b/apps/portal/src/features/sim-management/components/SimManagementSection.tsx @@ -56,13 +56,14 @@ export function SimManagementSection({ subscriptionId }: SimManagementSectionPro const [error, setError] = useState(null); // Navigation handlers - const navigateToTopUp = () => router.push(`/account/services/${subscriptionId}/sim/top-up`); + const navigateToTopUp = () => router.push(`/account/subscriptions/${subscriptionId}/sim/top-up`); const navigateToChangePlan = () => - router.push(`/account/services/${subscriptionId}/sim/change-plan`); - const navigateToReissue = () => router.push(`/account/services/${subscriptionId}/sim/reissue`); - const navigateToCancel = () => router.push(`/account/services/${subscriptionId}/sim/cancel`); + router.push(`/account/subscriptions/${subscriptionId}/sim/change-plan`); + const navigateToReissue = () => + router.push(`/account/subscriptions/${subscriptionId}/sim/reissue`); + const navigateToCancel = () => router.push(`/account/subscriptions/${subscriptionId}/sim/cancel`); const navigateToCallHistory = () => - router.push(`/account/services/${subscriptionId}/sim/call-history`); + router.push(`/account/subscriptions/${subscriptionId}/sim/call-history`); // Fetch subscription data const { data: subscription } = useSubscription(subscriptionId); diff --git a/apps/portal/src/features/subscriptions/components/SubscriptionTable/SubscriptionTable.tsx b/apps/portal/src/features/subscriptions/components/SubscriptionTable/SubscriptionTable.tsx index 61251db1..059f6ff9 100644 --- a/apps/portal/src/features/subscriptions/components/SubscriptionTable/SubscriptionTable.tsx +++ b/apps/portal/src/features/subscriptions/components/SubscriptionTable/SubscriptionTable.tsx @@ -101,7 +101,7 @@ export function SubscriptionTable({ if (onSubscriptionClick) { onSubscriptionClick(subscription); } else { - router.push(`/account/services/${subscription.id}`); + router.push(`/account/subscriptions/${subscription.id}`); } }, [onSubscriptionClick, router] diff --git a/apps/portal/src/features/subscriptions/containers/SimCancel.tsx b/apps/portal/src/features/subscriptions/containers/SimCancel.tsx index fa2b2ab3..357cfd7f 100644 --- a/apps/portal/src/features/subscriptions/containers/SimCancel.tsx +++ b/apps/portal/src/features/subscriptions/containers/SimCancel.tsx @@ -108,7 +108,10 @@ export function SimCancelContainer() { try { await simActionsService.cancel(subscriptionId, { scheduledAt: runDate }); setMessage("Cancellation request submitted. You will receive a confirmation email."); - setTimeout(() => router.push(`/account/services/${subscriptionId}#sim-management`), 1500); + setTimeout( + () => router.push(`/account/subscriptions/${subscriptionId}#sim-management`), + 1500 + ); } catch (e: unknown) { setError(e instanceof Error ? e.message : "Failed to submit cancellation"); } finally { @@ -120,7 +123,7 @@ export function SimCancelContainer() {
← Back to SIM Management diff --git a/apps/portal/src/features/subscriptions/views/InternetCancel.tsx b/apps/portal/src/features/subscriptions/views/InternetCancel.tsx index 14ed1267..d478c104 100644 --- a/apps/portal/src/features/subscriptions/views/InternetCancel.tsx +++ b/apps/portal/src/features/subscriptions/views/InternetCancel.tsx @@ -106,7 +106,7 @@ export function InternetCancelContainer() { comments: comments.trim() || undefined, }); setMessage("Cancellation request submitted. You will receive a confirmation email."); - setTimeout(() => router.push(`/account/services/${subscriptionId}`), 2000); + setTimeout(() => router.push(`/account/subscriptions/${subscriptionId}`), 2000); } catch (e: unknown) { setError( process.env.NODE_ENV === "development" @@ -129,8 +129,11 @@ export function InternetCancelContainer() { title="Cancel Internet" description="Cancel your Internet subscription" breadcrumbs={[ - { label: "Services", href: "/account/services" }, - { label: preview?.productName || "Internet", href: `/account/services/${subscriptionId}` }, + { label: "Subscriptions", href: "/account/subscriptions" }, + { + label: preview?.productName || "Internet", + href: `/account/subscriptions/${subscriptionId}`, + }, { label: "Cancel" }, ]} loading={loadingPreview} @@ -140,10 +143,10 @@ export function InternetCancelContainer() {
- ← Back to Service Details + ← Back to Subscription Details
{[1, 2, 3].map(s => ( diff --git a/apps/portal/src/features/subscriptions/views/SimCallHistory.tsx b/apps/portal/src/features/subscriptions/views/SimCallHistory.tsx index 5bc0cfc4..b4f38d6f 100644 --- a/apps/portal/src/features/subscriptions/views/SimCallHistory.tsx +++ b/apps/portal/src/features/subscriptions/views/SimCallHistory.tsx @@ -138,7 +138,7 @@ export function SimCallHistoryContainer() {
← Back to SIM Management diff --git a/apps/portal/src/features/subscriptions/views/SimCancel.tsx b/apps/portal/src/features/subscriptions/views/SimCancel.tsx index 61780fa6..35cace87 100644 --- a/apps/portal/src/features/subscriptions/views/SimCancel.tsx +++ b/apps/portal/src/features/subscriptions/views/SimCancel.tsx @@ -102,7 +102,10 @@ export function SimCancelContainer() { comments: comments.trim() || undefined, }); setMessage("Cancellation request submitted. You will receive a confirmation email."); - setTimeout(() => router.push(`/account/services/${subscriptionId}#sim-management`), 2000); + setTimeout( + () => router.push(`/account/subscriptions/${subscriptionId}#sim-management`), + 2000 + ); } catch (e: unknown) { setError( process.env.NODE_ENV === "development" @@ -125,8 +128,11 @@ export function SimCancelContainer() { title="Cancel SIM" description="Cancel your SIM subscription" breadcrumbs={[ - { label: "Services", href: "/account/services" }, - { label: "SIM Management", href: `/account/services/${subscriptionId}#sim-management` }, + { label: "Subscriptions", href: "/account/subscriptions" }, + { + label: "SIM Management", + href: `/account/subscriptions/${subscriptionId}#sim-management`, + }, { label: "Cancel SIM" }, ]} loading={loadingPreview} @@ -136,7 +142,7 @@ export function SimCancelContainer() {
← Back to SIM Management diff --git a/apps/portal/src/features/subscriptions/views/SimChangePlan.tsx b/apps/portal/src/features/subscriptions/views/SimChangePlan.tsx index ca7096e2..42c948dd 100644 --- a/apps/portal/src/features/subscriptions/views/SimChangePlan.tsx +++ b/apps/portal/src/features/subscriptions/views/SimChangePlan.tsx @@ -89,7 +89,7 @@ export function SimChangePlanContainer() {
← Back to SIM Management @@ -241,7 +241,7 @@ export function SimChangePlanContainer() { } > diff --git a/apps/portal/src/lib/api/index.ts b/apps/portal/src/lib/api/index.ts index 60c92ef3..4202cfe5 100644 --- a/apps/portal/src/lib/api/index.ts +++ b/apps/portal/src/lib/api/index.ts @@ -142,18 +142,18 @@ export const queryKeys = { dashboard: { summary: () => ["dashboard", "summary"] as const, }, - catalog: { - all: () => ["catalog"] as const, - products: () => ["catalog", "products"] as const, + services: { + all: () => ["services"] as const, + products: () => ["services", "products"] as const, internet: { - combined: () => ["catalog", "internet", "combined"] as const, - eligibility: () => ["catalog", "internet", "eligibility"] as const, + combined: () => ["services", "internet", "combined"] as const, + eligibility: () => ["services", "internet", "eligibility"] as const, }, sim: { - combined: () => ["catalog", "sim", "combined"] as const, + combined: () => ["services", "sim", "combined"] as const, }, vpn: { - combined: () => ["catalog", "vpn", "combined"] as const, + combined: () => ["services", "vpn", "combined"] as const, }, }, orders: { diff --git a/docs/architecture/domain-layer.md b/docs/architecture/domain-layer.md index 0b17b62f..c36046c8 100644 --- a/docs/architecture/domain-layer.md +++ b/docs/architecture/domain-layer.md @@ -90,7 +90,7 @@ import type { Invoice, InvoiceList } from "@customer-portal/domain/billing"; import type { Subscription } from "@customer-portal/domain/subscriptions"; import type { SimDetails } from "@customer-portal/domain/sim"; import type { OrderSummary } from "@customer-portal/domain/orders"; -import type { CatalogProduct } from "@customer-portal/domain/catalog"; +import type { CatalogProduct } from "@customer-portal/domain/services"; ``` ### Import Schemas diff --git a/docs/how-it-works/COMPLETE-GUIDE.md b/docs/how-it-works/COMPLETE-GUIDE.md index c250c7c5..bb8fccf6 100644 --- a/docs/how-it-works/COMPLETE-GUIDE.md +++ b/docs/how-it-works/COMPLETE-GUIDE.md @@ -501,7 +501,7 @@ The dashboard aggregates data from multiple sources: | Channel | Events | | ---------------------------- | ---------------------------------------- | | `account:sf:{sf_account_id}` | Order status updates, fulfillment events | -| `global:catalog` | Catalog/pricebook invalidation | +| `global:services` | Services/pricebook invalidation | ### Connection Management diff --git a/docs/integrations/salesforce/opportunity-lifecycle.md b/docs/integrations/salesforce/opportunity-lifecycle.md index 61df6a01..cd5a605b 100644 --- a/docs/integrations/salesforce/opportunity-lifecycle.md +++ b/docs/integrations/salesforce/opportunity-lifecycle.md @@ -178,7 +178,7 @@ This guide documents the Salesforce Opportunity integration for service lifecycl ├─────────────────────────────────────────────────────────────────────────┤ │ │ │ 1. CUSTOMER ENTERS ADDRESS │ -│ └─ Portal: POST /api/catalog/internet/eligibility-request │ +│ └─ Portal: POST /api/services/internet/eligibility-request │ │ │ │ 2. CHECK IF ELIGIBILITY ALREADY KNOWN │ │ └─ Query: SELECT Internet_Eligibility__c FROM Account │ diff --git a/docs/operations/monitoring-setup.md b/docs/operations/monitoring-setup.md index b40808cf..aa9a682b 100644 --- a/docs/operations/monitoring-setup.md +++ b/docs/operations/monitoring-setup.md @@ -8,14 +8,14 @@ This document provides guidance for setting up monitoring infrastructure for the The BFF exposes several health check endpoints for monitoring: -| Endpoint | Purpose | Authentication | -| ------------------------------- | ------------------------------------------ | -------------- | -| `GET /health` | Core system health (database, cache) | Public | -| `GET /health/queues` | Request queue metrics (WHMCS, Salesforce) | Public | -| `GET /health/queues/whmcs` | WHMCS queue details | Public | -| `GET /health/queues/salesforce` | Salesforce queue details | Public | -| `GET /health/catalog/cache` | Catalog cache metrics | Public | -| `GET /auth/health-check` | Integration health (DB, WHMCS, Salesforce) | Public | +| Endpoint | Purpose | Authentication | +| -------------------------------- | ------------------------------------------ | -------------- | +| `GET /health` | Core system health (database, cache) | Public | +| `GET /health/queues` | Request queue metrics (WHMCS, Salesforce) | Public | +| `GET /health/queues/whmcs` | WHMCS queue details | Public | +| `GET /health/queues/salesforce` | Salesforce queue details | Public | +| `GET /api/health/services/cache` | Services cache metrics | Public | +| `GET /auth/health-check` | Integration health (DB, WHMCS, Salesforce) | Public | ### Core Health Response diff --git a/packages/domain/dashboard/schema.ts b/packages/domain/dashboard/schema.ts index e7fb3f2f..d06dd7be 100644 --- a/packages/domain/dashboard/schema.ts +++ b/packages/domain/dashboard/schema.ts @@ -1,6 +1,6 @@ import { z } from "zod"; import { invoiceSchema } from "../billing/schema.js"; -import { internetEligibilityDetailsSchema } from "../catalog/schema.js"; +import { internetEligibilityDetailsSchema } from "../services/schema.js"; import { residenceCardVerificationSchema } from "../customer/schema.js"; export const activityTypeSchema = z.enum([ diff --git a/packages/domain/index.ts b/packages/domain/index.ts index fb7038a8..6fa3935b 100644 --- a/packages/domain/index.ts +++ b/packages/domain/index.ts @@ -5,7 +5,7 @@ // Re-export domain modules export * as Billing from "./billing/index.js"; -export * as Catalog from "./catalog/index.js"; +export * as Services from "./services/index.js"; export * as Checkout from "./checkout/index.js"; export * as Common from "./common/index.js"; export * as Customer from "./customer/index.js"; diff --git a/packages/domain/orders/contract.ts b/packages/domain/orders/contract.ts index 35243f77..57a8f54a 100644 --- a/packages/domain/orders/contract.ts +++ b/packages/domain/orders/contract.ts @@ -1,11 +1,11 @@ /** * Orders Domain - Contract - * + * * Business types and provider-specific mapping types. * Validated types are derived from schemas (see schema.ts). */ -import type { SalesforceProductFieldMap } from "../catalog/contract.js"; +import type { SalesforceProductFieldMap } from "../services/contract.js"; import type { SalesforceAccountFieldMap } from "../customer/index.js"; import type { UserIdMapping } from "../mappings/contract.js"; import type { SalesforceOrderRecord } from "./providers/salesforce/raw.types.js"; @@ -105,7 +105,7 @@ export const ORDER_FULFILLMENT_ERROR_CODE = { PROVISIONING_ERROR: "PROVISIONING_ERROR", } as const; -export type OrderFulfillmentErrorCode = +export type OrderFulfillmentErrorCode = (typeof ORDER_FULFILLMENT_ERROR_CODE)[keyof typeof ORDER_FULFILLMENT_ERROR_CODE]; // ============================================================================ @@ -147,7 +147,7 @@ export interface CheckoutItem { monthlyPrice?: number; oneTimePrice?: number; quantity: number; - itemType: 'plan' | 'installation' | 'addon' | 'activation' | 'vpn'; + itemType: "plan" | "installation" | "addon" | "activation" | "vpn"; autoAdded?: boolean; } @@ -205,4 +205,4 @@ export type { CreateOrderRequest, OrderBusinessValidation, SfOrderIdParam, -} from './schema.js'; +} from "./schema.js"; diff --git a/packages/domain/orders/providers/salesforce/field-map.ts b/packages/domain/orders/providers/salesforce/field-map.ts index 72aa7a19..78ac6f83 100644 --- a/packages/domain/orders/providers/salesforce/field-map.ts +++ b/packages/domain/orders/providers/salesforce/field-map.ts @@ -1,8 +1,5 @@ -import type { SalesforceProduct2WithPricebookEntries } from "../../../catalog/providers/salesforce/raw.types.js"; -import type { - SalesforceOrderItemRecord, - SalesforceOrderRecord, -} from "./raw.types.js"; +import type { SalesforceProduct2WithPricebookEntries } from "../../../services/providers/salesforce/raw.types.js"; +import type { SalesforceOrderItemRecord, SalesforceOrderRecord } from "./raw.types.js"; export interface SalesforceOrderFieldMap { order: { @@ -127,4 +124,3 @@ export function createSalesforceOrderFieldMap( product: { ...defaultSalesforceOrderFieldMap.product, ...overrides.product }, }; } - diff --git a/packages/domain/orders/providers/salesforce/mapper.ts b/packages/domain/orders/providers/salesforce/mapper.ts index ab6b2997..3286f25e 100644 --- a/packages/domain/orders/providers/salesforce/mapper.ts +++ b/packages/domain/orders/providers/salesforce/mapper.ts @@ -15,7 +15,7 @@ import { orderDetailsSchema, orderSummarySchema, orderItemDetailsSchema } from " import type { SalesforceProduct2WithPricebookEntries, SalesforcePricebookEntryRecord, -} from "../../../catalog/providers/salesforce/raw.types.js"; +} from "../../../services/providers/salesforce/raw.types.js"; import { defaultSalesforceOrderFieldMap, type SalesforceOrderFieldMap } from "./field-map.js"; import type { SalesforceOrderItemRecord, SalesforceOrderRecord } from "./raw.types.js"; diff --git a/packages/domain/package.json b/packages/domain/package.json index f9537d54..5610854e 100644 --- a/packages/domain/package.json +++ b/packages/domain/package.json @@ -31,13 +31,13 @@ "import": "./dist/billing/*.js", "types": "./dist/billing/*.d.ts" }, - "./catalog": { - "import": "./dist/catalog/index.js", - "types": "./dist/catalog/index.d.ts" + "./services": { + "import": "./dist/services/index.js", + "types": "./dist/services/index.d.ts" }, - "./catalog/*": { - "import": "./dist/catalog/*.js", - "types": "./dist/catalog/*.d.ts" + "./services/*": { + "import": "./dist/services/*.js", + "types": "./dist/services/*.d.ts" }, "./checkout": { "import": "./dist/checkout/index.js", diff --git a/packages/domain/realtime/events.ts b/packages/domain/realtime/events.ts index da6e3f0b..4976851b 100644 --- a/packages/domain/realtime/events.ts +++ b/packages/domain/realtime/events.ts @@ -9,7 +9,7 @@ export interface RealtimeEventEnvelope | RealtimeEventEnvelope<"account.stream.heartbeat", { topic: string; timestamp: string }> - | RealtimeEventEnvelope<"catalog.eligibility.changed", CatalogEligibilityChangedPayload>; + | RealtimeEventEnvelope<"services.eligibility.changed", ServicesEligibilityChangedPayload>; diff --git a/packages/domain/catalog/contract.ts b/packages/domain/services/contract.ts similarity index 100% rename from packages/domain/catalog/contract.ts rename to packages/domain/services/contract.ts diff --git a/packages/domain/catalog/index.ts b/packages/domain/services/index.ts similarity index 100% rename from packages/domain/catalog/index.ts rename to packages/domain/services/index.ts diff --git a/packages/domain/catalog/providers/index.ts b/packages/domain/services/providers/index.ts similarity index 100% rename from packages/domain/catalog/providers/index.ts rename to packages/domain/services/providers/index.ts diff --git a/packages/domain/catalog/providers/salesforce/index.ts b/packages/domain/services/providers/salesforce/index.ts similarity index 100% rename from packages/domain/catalog/providers/salesforce/index.ts rename to packages/domain/services/providers/salesforce/index.ts diff --git a/packages/domain/catalog/providers/salesforce/mapper.ts b/packages/domain/services/providers/salesforce/mapper.ts similarity index 98% rename from packages/domain/catalog/providers/salesforce/mapper.ts rename to packages/domain/services/providers/salesforce/mapper.ts index 3fc6cdc7..8a5f5ee5 100644 --- a/packages/domain/catalog/providers/salesforce/mapper.ts +++ b/packages/domain/services/providers/salesforce/mapper.ts @@ -1,6 +1,6 @@ /** * Catalog Domain - Salesforce Provider Mapper - * + * * Transforms Salesforce Product2 records to normalized catalog contracts. */ @@ -88,8 +88,7 @@ function baseProduct( base.oneTimePrice = oneTimeField; } - const primaryPrice = - unitPriceFromPricebook ?? monthlyField ?? priceField ?? oneTimeField; + const primaryPrice = unitPriceFromPricebook ?? monthlyField ?? priceField ?? oneTimeField; if (primaryPrice !== undefined) { if (billingCycle === "monthly") { diff --git a/packages/domain/catalog/providers/salesforce/raw.types.ts b/packages/domain/services/providers/salesforce/raw.types.ts similarity index 92% rename from packages/domain/catalog/providers/salesforce/raw.types.ts rename to packages/domain/services/providers/salesforce/raw.types.ts index 403f1f58..33dd748a 100644 --- a/packages/domain/catalog/providers/salesforce/raw.types.ts +++ b/packages/domain/services/providers/salesforce/raw.types.ts @@ -1,6 +1,6 @@ /** * Catalog Domain - Salesforce Provider Raw Types - * + * * Raw Salesforce API response types for Product2 and PricebookEntry sobjects. */ @@ -67,9 +67,13 @@ export type SalesforcePricebookEntryRecord = z.infer; +export type SalesforceProduct2WithPricebookEntries = z.infer< + typeof salesforceProduct2WithPricebookEntriesSchema +>; diff --git a/packages/domain/catalog/providers/whmcs/index.ts b/packages/domain/services/providers/whmcs/index.ts similarity index 96% rename from packages/domain/catalog/providers/whmcs/index.ts rename to packages/domain/services/providers/whmcs/index.ts index 3f41fad4..53ce7f60 100644 --- a/packages/domain/catalog/providers/whmcs/index.ts +++ b/packages/domain/services/providers/whmcs/index.ts @@ -1,2 +1 @@ export * from "./raw.types.js"; - diff --git a/packages/domain/catalog/providers/whmcs/mapper.ts b/packages/domain/services/providers/whmcs/mapper.ts similarity index 100% rename from packages/domain/catalog/providers/whmcs/mapper.ts rename to packages/domain/services/providers/whmcs/mapper.ts diff --git a/packages/domain/catalog/providers/whmcs/raw.types.ts b/packages/domain/services/providers/whmcs/raw.types.ts similarity index 99% rename from packages/domain/catalog/providers/whmcs/raw.types.ts rename to packages/domain/services/providers/whmcs/raw.types.ts index 3dcf43d1..5be7ab94 100644 --- a/packages/domain/catalog/providers/whmcs/raw.types.ts +++ b/packages/domain/services/providers/whmcs/raw.types.ts @@ -1,6 +1,6 @@ /** * WHMCS Catalog Provider - Raw Types - * + * * Type definitions for raw WHMCS API responses related to catalog/products. */ @@ -58,4 +58,3 @@ export const whmcsCatalogProductListResponseSchema = z.object({ }); export type WhmcsCatalogProductListResponse = z.infer; - diff --git a/packages/domain/catalog/schema.ts b/packages/domain/services/schema.ts similarity index 100% rename from packages/domain/catalog/schema.ts rename to packages/domain/services/schema.ts diff --git a/packages/domain/catalog/utils.ts b/packages/domain/services/utils.ts similarity index 93% rename from packages/domain/catalog/utils.ts rename to packages/domain/services/utils.ts index 7f5c4f06..55b58a4b 100644 --- a/packages/domain/catalog/utils.ts +++ b/packages/domain/services/utils.ts @@ -99,11 +99,13 @@ export function getInternetTierTemplate(tier?: string | null): InternetPlanTempl } const normalized = tier.trim().toLowerCase(); - return INTERNET_TIER_METADATA[normalized] ?? { - tierDescription: `${tier} plan`, - description: undefined, - features: undefined, - }; + return ( + INTERNET_TIER_METADATA[normalized] ?? { + tierDescription: `${tier} plan`, + description: undefined, + features: undefined, + } + ); } export type InternetInstallationTerm = "One-time" | "12-Month" | "24-Month"; @@ -120,9 +122,7 @@ export type InternetAddonType = "hikari-denwa-service" | "hikari-denwa-installat export function inferAddonTypeFromSku(sku: string): InternetAddonType { const upperSku = sku.toUpperCase(); const isDenwa = - upperSku.includes("DENWA") || - upperSku.includes("HOME-PHONE") || - upperSku.includes("PHONE"); + upperSku.includes("DENWA") || upperSku.includes("HOME-PHONE") || upperSku.includes("PHONE"); if (!isDenwa) { return "other"; @@ -145,7 +145,8 @@ export function enrichInternetPlanMetadata(plan: InternetPlanCatalogItem): Inter tierDescription: existingMetadata.tierDescription ?? template.tierDescription, features: existingMetadata.features ?? template.features, isRecommended: - existingMetadata.isRecommended ?? (plan.internetPlanTier?.toLowerCase() === "gold" ? true : undefined), + existingMetadata.isRecommended ?? + (plan.internetPlanTier?.toLowerCase() === "gold" ? true : undefined), }; return internetPlanCatalogItemSchema.parse({ diff --git a/packages/domain/tsconfig.json b/packages/domain/tsconfig.json index 905d9e22..1eed2b4a 100644 --- a/packages/domain/tsconfig.json +++ b/packages/domain/tsconfig.json @@ -12,7 +12,7 @@ "include": [ "auth/**/*", "billing/**/*", - "catalog/**/*", + "services/**/*", "checkout/**/*", "common/**/*", "customer/**/*", diff --git a/scripts/migrate-imports.sh b/scripts/migrate-imports.sh index 24aecd66..9b032bd8 100755 --- a/scripts/migrate-imports.sh +++ b/scripts/migrate-imports.sh @@ -58,10 +58,10 @@ migrate_directory() { -e 's|@customer-portal/integrations-whmcs/mappers/order|@customer-portal/domain/orders|g' \ {} + - # Catalog domain + # Services domain find "$dir" -type f \( -name "*.ts" -o -name "*.tsx" \) -exec sed -i \ - -e 's|@customer-portal/contracts/catalog|@customer-portal/domain/catalog|g' \ - -e 's|@customer-portal/domain/src/contracts/catalog|@customer-portal/domain/catalog|g' \ + -e 's|@customer-portal/contracts/catalog|@customer-portal/domain/services|g' \ + -e 's|@customer-portal/domain/src/contracts/catalog|@customer-portal/domain/services|g' \ {} + # Common types