From bccfec940fe95cbc83a8ce12b7f160c625324ccc Mon Sep 17 00:00:00 2001 From: tema Date: Sat, 22 Nov 2025 18:23:52 +0900 Subject: [PATCH] Enhance SIM Management Section with new features and improved UI - Integrated subscription and invoice fetching to display relevant billing information. - Added data usage tracking and visual representation for better user insights. - Introduced new action buttons for data top-up, plan changes, and SIM reissue. - Improved error handling and loading states for a smoother user experience. - Updated layout and styling for better responsiveness and clarity. --- .../components/SimManagementSection.tsx | 420 +++++++++++++----- 1 file changed, 307 insertions(+), 113 deletions(-) diff --git a/apps/portal/src/features/sim-management/components/SimManagementSection.tsx b/apps/portal/src/features/sim-management/components/SimManagementSection.tsx index 22e2bbb6..6d130672 100644 --- a/apps/portal/src/features/sim-management/components/SimManagementSection.tsx +++ b/apps/portal/src/features/sim-management/components/SimManagementSection.tsx @@ -5,18 +5,47 @@ import { DevicePhoneMobileIcon, ExclamationTriangleIcon, ArrowPathIcon, + SignalIcon, + ArrowsRightLeftIcon, + ArrowPathRoundedSquareIcon, + XCircleIcon, } from "@heroicons/react/24/outline"; -import { SimDetailsCard, type SimDetails } from "./SimDetailsCard"; -import { SimActions } from "./SimActions"; import { apiClient } from "@/lib/api"; -import { SimFeatureToggles } from "./SimFeatureToggles"; +import { useSubscription, useSubscriptionInvoices } from "@/features/subscriptions/hooks"; +import { useCreateInvoiceSsoLink } from "@/features/billing/hooks/useBilling"; +import { format } from "date-fns"; +import { Formatting } from "@customer-portal/domain/toolkit"; + +const { formatCurrency } = Formatting; interface SimManagementSectionProps { subscriptionId: number; } +interface SimDetails { + account: string; + msisdn: string; + iccid?: string; + imsi?: string; + eid?: string; + planCode: string; + status: "active" | "suspended" | "cancelled" | "pending"; + simType: "physical" | "esim" | "standard" | "nano" | "micro"; + remainingQuotaMb: number; + remainingQuotaKb: number; + voiceMailEnabled?: boolean; + callWaitingEnabled?: boolean; + internationalRoamingEnabled?: boolean; + networkType?: string; +} + interface SimInfo { details: SimDetails; + usage?: { + todayUsageMb: number; + monthlyUsageMb?: number; + recentDaysUsage?: Array<{ date: string; usageMb: number }>; + }; } export function SimManagementSection({ subscriptionId }: SimManagementSectionProps) { @@ -24,6 +53,22 @@ export function SimManagementSection({ subscriptionId }: SimManagementSectionPro const [loading, setLoading] = useState(true); const [error, setError] = useState(null); + // Fetch subscription data + const { data: subscription } = useSubscription(subscriptionId); + + // Fetch latest invoice (limit 1) + const { data: invoicesData } = useSubscriptionInvoices(subscriptionId, { limit: 1 }); + const latestInvoice = invoicesData?.invoices?.[0]; + + // SSO link mutation for payment + const createSsoLink = useCreateInvoiceSsoLink({ + onSuccess: (data) => { + if (data.url) { + window.open(data.url, '_blank'); + } + }, + }); + const fetchSimInfo = useCallback(async () => { try { setError(null); @@ -38,8 +83,10 @@ export function SimManagementSection({ subscriptionId }: SimManagementSectionPro throw new Error("Failed to load SIM information"); } - // Only use the details part, ignore usage data - setSimInfo({ details: payload.details }); + setSimInfo({ + details: payload.details, + usage: payload.usage + }); } catch (err: unknown) { const hasStatus = (v: unknown): v is { status: number } => typeof v === "object" && @@ -47,7 +94,6 @@ export function SimManagementSection({ subscriptionId }: SimManagementSectionPro "status" in v && typeof (v as { status: unknown }).status === "number"; if (hasStatus(err) && err.status === 400) { - // Not a SIM subscription - this component shouldn't be shown setError("This subscription is not a SIM service"); } else { setError(err instanceof Error ? err.message : "Failed to load SIM information"); @@ -67,31 +113,31 @@ export function SimManagementSection({ subscriptionId }: SimManagementSectionPro }; const handleActionSuccess = () => { - // Refresh SIM info after any successful action void fetchSimInfo(); }; + const handlePayInvoice = () => { + if (latestInvoice?.id) { + createSsoLink.mutate({ invoiceId: latestInvoice.id, target: 'pay' }); + } + }; + + const formatDate = (dateString: string | undefined) => { + if (!dateString) return "N/A"; + try { + return format(new Date(dateString), "MMM d yyyy"); + } catch { + return "Invalid date"; + } + }; + if (loading) { return ( -
-
-
-
- -
-
-

SIM Management

-

Loading your SIM service details...

-
-
+
+
-
-
-
-
-
@@ -100,16 +146,7 @@ export function SimManagementSection({ subscriptionId }: SimManagementSectionPro if (error) { return ( -
-
-
- -
-
-

SIM Management

-

Unable to load SIM information

-
-
+
@@ -120,7 +157,7 @@ export function SimManagementSection({ subscriptionId }: SimManagementSectionPro

{error}

+ )} + + {/* Top Up Data Button */} +
+
- {/* SIM Management Actions Card */} -
-
-

SIM Management Actions

+ {/* Right: Data Usage Circle */} +
+
+ + + + +
+

Remaining data

+

{remainingGB} GB

+

-{usedGB} GB

+
- -
- - {/* Voice Status Card */} -
-
-

Voice Status

-
-
- {/* Right Column - SIM Details & Usage */} -
- {/* SIM Details Card */} -
-
-

SIM Details

-
- + {/* SIM Management Actions - 2x2 Grid on Desktop, 2x2 on Mobile */} +
+

SIM Management Actions

+
+ + + + + + +
+ + {/* Voice Status Section */} +
+

Voice Status

+
+
+
+
+

Voice Mail

+ {simInfo.details.voiceMailEnabled && ( +

+ On +
+ Enabled +

+ )} +
+ +
+
+ +
+
+
+

Network Type

+

+ {simInfo.details.networkType ? simInfo.details.networkType : 'Disabled'} +

+
+ +
+
+ +
+
+
+

Call Waiting

+
+ +
+
+ +
+
+
+

International Roaming

+
+ +
+
+
+
+ + {/* Important Notes */} +
+

Important Notes

+
    +
  • + + Changes will take effect instantaneously (approx. 30min) +
  • +
  • + + May require smartphone device restart after changes are applied +
  • +
  • + + Voice, network, and plan changes must be requested at least 30 minutes apart. +
  • +
  • + + Changes to Voice Mail / Call Waiting must be requested before the 25th of the month +
  • +
+
);