From a9d9036095a7bdd09b26dd5b99cff0a96bf049a7 Mon Sep 17 00:00:00 2001 From: "T. Narantuya" Date: Sat, 20 Sep 2025 13:37:54 +0900 Subject: [PATCH] Refactor subscription hooks to utilize useAuthStore for token management, enhancing authentication checks. Update query keys for subscriptions to include parameters for better data handling. Remove unused useAuthSession hook and clean up imports in related files. --- .../components/molecules/SubCard/SubCard.tsx | 2 - .../src/features/auth/services/index.ts | 13 ----- .../subscriptions/hooks/useSubscriptions.ts | 22 ++++----- .../services/sim-actions.service.ts | 49 +++++++++++++++++++ apps/portal/src/lib/api/index.ts | 6 ++- apps/portal/src/lib/validation/index.ts | 4 +- 6 files changed, 67 insertions(+), 29 deletions(-) create mode 100644 apps/portal/src/features/subscriptions/services/sim-actions.service.ts diff --git a/apps/portal/src/components/molecules/SubCard/SubCard.tsx b/apps/portal/src/components/molecules/SubCard/SubCard.tsx index 786daa64..0675d8a7 100644 --- a/apps/portal/src/components/molecules/SubCard/SubCard.tsx +++ b/apps/portal/src/components/molecules/SubCard/SubCard.tsx @@ -54,5 +54,3 @@ export const SubCard = forwardRef( ) ); SubCard.displayName = "SubCard"; - -export { SubCard }; diff --git a/apps/portal/src/features/auth/services/index.ts b/apps/portal/src/features/auth/services/index.ts index c0caf8b6..1a7c0614 100644 --- a/apps/portal/src/features/auth/services/index.ts +++ b/apps/portal/src/features/auth/services/index.ts @@ -4,16 +4,3 @@ */ export { useAuthStore, selectAuthTokens, selectIsAuthenticated, selectAuthUser } from "./auth.store"; - -// Create a hook for session management -export const useAuthSession = () => { - const tokens = useAuthStore(selectAuthTokens); - const isAuthenticated = useAuthStore(selectIsAuthenticated); - const user = useAuthStore(selectAuthUser); - - return { - tokens, - isAuthenticated, - user, - }; -}; diff --git a/apps/portal/src/features/subscriptions/hooks/useSubscriptions.ts b/apps/portal/src/features/subscriptions/hooks/useSubscriptions.ts index 9a717446..34904390 100644 --- a/apps/portal/src/features/subscriptions/hooks/useSubscriptions.ts +++ b/apps/portal/src/features/subscriptions/hooks/useSubscriptions.ts @@ -5,7 +5,7 @@ import { useQuery } from "@tanstack/react-query"; import { apiClient, queryKeys, getDataOrDefault, getDataOrThrow, getNullableData } from "@/lib/api"; -import { useAuthSession } from "@/features/auth/services/auth.store"; +import { useAuthStore } from "@/features/auth/services"; import type { InvoiceList, Subscription, SubscriptionList } from "@customer-portal/domain"; interface UseSubscriptionsOptions { @@ -54,7 +54,7 @@ function toSubscriptionList( */ export function useSubscriptions(options: UseSubscriptionsOptions = {}) { const { status } = options; - const { isAuthenticated, hasValidToken } = useAuthSession(); + const { isAuthenticated, tokens } = useAuthStore(); return useQuery({ queryKey: queryKeys.subscriptions.list(status ? { status } : undefined), @@ -66,7 +66,7 @@ export function useSubscriptions(options: UseSubscriptionsOptions = {}) { }, staleTime: 5 * 60 * 1000, gcTime: 10 * 60 * 1000, - enabled: isAuthenticated && hasValidToken, + enabled: isAuthenticated && !!tokens?.accessToken, }); } @@ -74,7 +74,7 @@ export function useSubscriptions(options: UseSubscriptionsOptions = {}) { * Hook to fetch active subscriptions only */ export function useActiveSubscriptions() { - const { isAuthenticated, hasValidToken } = useAuthSession(); + const { isAuthenticated, tokens } = useAuthStore(); return useQuery({ queryKey: queryKeys.subscriptions.active(), @@ -84,7 +84,7 @@ export function useActiveSubscriptions() { }, staleTime: 5 * 60 * 1000, gcTime: 10 * 60 * 1000, - enabled: isAuthenticated && hasValidToken, + enabled: isAuthenticated && !!tokens?.accessToken, }); } @@ -92,7 +92,7 @@ export function useActiveSubscriptions() { * Hook to fetch subscription statistics */ export function useSubscriptionStats() { - const { isAuthenticated, hasValidToken } = useAuthSession(); + const { isAuthenticated, tokens } = useAuthStore(); return useQuery({ queryKey: queryKeys.subscriptions.stats(), @@ -102,7 +102,7 @@ export function useSubscriptionStats() { }, staleTime: 5 * 60 * 1000, gcTime: 10 * 60 * 1000, - enabled: isAuthenticated && hasValidToken, + enabled: isAuthenticated && !!tokens?.accessToken, }); } @@ -110,7 +110,7 @@ export function useSubscriptionStats() { * Hook to fetch a specific subscription */ export function useSubscription(subscriptionId: number) { - const { isAuthenticated, hasValidToken } = useAuthSession(); + const { isAuthenticated, tokens } = useAuthStore(); return useQuery({ queryKey: queryKeys.subscriptions.detail(String(subscriptionId)), @@ -122,7 +122,7 @@ export function useSubscription(subscriptionId: number) { }, staleTime: 5 * 60 * 1000, gcTime: 10 * 60 * 1000, - enabled: isAuthenticated && hasValidToken && subscriptionId > 0, + enabled: isAuthenticated && !!tokens?.accessToken && subscriptionId > 0, }); } @@ -134,7 +134,7 @@ export function useSubscriptionInvoices( options: { page?: number; limit?: number } = {} ) { const { page = 1, limit = 10 } = options; - const { isAuthenticated, hasValidToken } = useAuthSession(); + const { isAuthenticated, tokens } = useAuthStore(); return useQuery({ queryKey: queryKeys.subscriptions.invoices(subscriptionId, { page, limit }), @@ -155,6 +155,6 @@ export function useSubscriptionInvoices( }, staleTime: 60 * 1000, gcTime: 5 * 60 * 1000, - enabled: isAuthenticated && hasValidToken && subscriptionId > 0, + enabled: isAuthenticated && !!tokens?.accessToken && subscriptionId > 0, }); } diff --git a/apps/portal/src/features/subscriptions/services/sim-actions.service.ts b/apps/portal/src/features/subscriptions/services/sim-actions.service.ts new file mode 100644 index 00000000..7bab0cdf --- /dev/null +++ b/apps/portal/src/features/subscriptions/services/sim-actions.service.ts @@ -0,0 +1,49 @@ +import { apiClient, getDataOrDefault } from "@/lib/api"; + +export interface TopUpRequest { + quotaMb: number; +} + +export interface ChangePlanRequest { + newPlanCode: string; + assignGlobalIp: boolean; +} + +export interface CancelRequest { + scheduledAt: string; +} + +export interface SimInfo { + details: T; + error?: E; +} + +export const simActionsService = { + async topUp(subscriptionId: string, request: TopUpRequest): Promise { + await apiClient.POST("/api/subscriptions/{subscriptionId}/sim/top-up", { + params: { path: { subscriptionId } }, + body: request, + }); + }, + + async changePlan(subscriptionId: string, request: ChangePlanRequest): Promise { + await apiClient.POST("/api/subscriptions/{subscriptionId}/sim/change-plan", { + params: { path: { subscriptionId } }, + body: request, + }); + }, + + async cancel(subscriptionId: string, request: CancelRequest): Promise { + await apiClient.POST("/api/subscriptions/{subscriptionId}/sim/cancel", { + params: { path: { subscriptionId } }, + body: request, + }); + }, + + async getSimInfo(subscriptionId: string): Promise | null> { + const response = await apiClient.GET("/api/subscriptions/{subscriptionId}/sim/info", { + params: { path: { subscriptionId } }, + }); + return getDataOrDefault(response, null); + }, +}; diff --git a/apps/portal/src/lib/api/index.ts b/apps/portal/src/lib/api/index.ts index 1e85e4b2..5b997d33 100644 --- a/apps/portal/src/lib/api/index.ts +++ b/apps/portal/src/lib/api/index.ts @@ -28,7 +28,11 @@ export const queryKeys = { }, subscriptions: { all: () => ['subscriptions'] as const, - list: () => ['subscriptions', 'list'] as const, + list: (params?: Record) => ['subscriptions', 'list', params] as const, + active: () => ['subscriptions', 'active'] as const, + stats: () => ['subscriptions', 'stats'] as const, + detail: (id: string) => ['subscriptions', 'detail', id] as const, + invoices: (id: number, params?: Record) => ['subscriptions', 'invoices', id, params] as const, }, dashboard: { summary: () => ['dashboard', 'summary'] as const, diff --git a/apps/portal/src/lib/validation/index.ts b/apps/portal/src/lib/validation/index.ts index a8c86c4f..ce9f91f7 100644 --- a/apps/portal/src/lib/validation/index.ts +++ b/apps/portal/src/lib/validation/index.ts @@ -10,8 +10,8 @@ export type { ZodFormOptions } from './zod-form'; // Re-export Zod for convenience export { z } from 'zod'; -// Re-export shared validation schemas -export * from '@customer-portal/validation'; +// Re-export shared validation schemas (React-specific only) +export * from '@customer-portal/validation/react'; // Additional React-specific form utilities export type { UseZodFormReturn } from './zod-form';