2025-09-09 16:13:17 +09:00

235 lines
9.1 KiB
TypeScript

"use client";
import React, { useState, useEffect, useCallback } from "react";
import {
DevicePhoneMobileIcon,
ExclamationTriangleIcon,
ArrowPathIcon,
} from "@heroicons/react/24/outline";
import { SimDetailsCard, type SimDetails } from "./SimDetailsCard";
import { DataUsageChart, type SimUsage } from "./DataUsageChart";
import { SimActions } from "./SimActions";
import { authenticatedApi } from "@/lib/api";
import { SimFeatureToggles } from "./SimFeatureToggles";
interface SimManagementSectionProps {
subscriptionId: number;
}
interface SimInfo {
details: SimDetails;
usage: SimUsage;
}
export function SimManagementSection({ subscriptionId }: SimManagementSectionProps) {
const [simInfo, setSimInfo] = useState<SimInfo | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const fetchSimInfo = useCallback(async () => {
try {
setError(null);
const data = await authenticatedApi.get<{
details: SimDetails;
usage: SimUsage;
}>(`/subscriptions/${subscriptionId}/sim`);
setSimInfo(data);
} catch (err: unknown) {
const hasStatus = (v: unknown): v is { status: number } =>
typeof v === "object" &&
v !== null &&
"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");
}
} finally {
setLoading(false);
}
}, [subscriptionId]);
useEffect(() => {
void fetchSimInfo();
}, [fetchSimInfo]);
const handleRefresh = () => {
setLoading(true);
void fetchSimInfo();
};
const handleActionSuccess = () => {
// Refresh SIM info after any successful action
void fetchSimInfo();
};
if (loading) {
return (
<div className="space-y-8">
<div className="bg-white shadow-lg rounded-xl border border-gray-100 p-8">
<div className="flex items-center mb-6">
<div className="bg-blue-50 rounded-xl p-2 mr-4">
<DevicePhoneMobileIcon className="h-6 w-6 text-blue-600" />
</div>
<div>
<h2 className="text-2xl font-bold text-gray-900">SIM Management</h2>
<p className="text-gray-600 mt-1">Loading your SIM service details...</p>
</div>
</div>
<div className="animate-pulse space-y-6">
<div className="h-6 bg-gradient-to-r from-gray-200 to-gray-300 rounded-lg w-3/4"></div>
<div className="h-5 bg-gradient-to-r from-gray-200 to-gray-300 rounded-lg w-1/2"></div>
<div className="h-48 bg-gradient-to-r from-gray-200 to-gray-300 rounded-xl"></div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div className="h-32 bg-gradient-to-r from-gray-200 to-gray-300 rounded-xl"></div>
<div className="h-32 bg-gradient-to-r from-gray-200 to-gray-300 rounded-xl"></div>
</div>
</div>
</div>
</div>
);
}
if (error) {
return (
<div className="bg-white shadow-lg rounded-xl border border-red-100 p-8">
<div className="flex items-center mb-6">
<div className="bg-blue-50 rounded-xl p-2 mr-4">
<DevicePhoneMobileIcon className="h-6 w-6 text-blue-600" />
</div>
<div>
<h2 className="text-2xl font-bold text-gray-900">SIM Management</h2>
<p className="text-gray-600 mt-1">Unable to load SIM information</p>
</div>
</div>
<div className="text-center py-12">
<div className="bg-red-50 rounded-full p-4 w-20 h-20 mx-auto mb-6">
<ExclamationTriangleIcon className="h-12 w-12 text-red-500 mx-auto" />
</div>
<h3 className="text-xl font-semibold text-gray-900 mb-3">
Unable to Load SIM Information
</h3>
<p className="text-gray-600 mb-8 max-w-md mx-auto">{error}</p>
<button
onClick={handleRefresh}
className="inline-flex items-center px-6 py-3 border border-transparent text-sm font-semibold rounded-xl text-white bg-gradient-to-r from-blue-600 to-blue-700 hover:from-blue-700 hover:to-blue-800 hover:shadow-lg hover:scale-105 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-all duration-200"
>
<ArrowPathIcon className="h-5 w-5 mr-2" />
Retry
</button>
</div>
</div>
);
}
if (!simInfo) {
return null;
}
return (
<div id="sim-management" className="space-y-8">
{/* SIM Details and Usage - Main Content */}
<div className="grid grid-cols-1 xl:grid-cols-3 gap-8">
{/* Main Content Area - Actions and Settings (Left Side) */}
<div className="order-2 xl:col-span-2 xl:order-1">
<div className="bg-white shadow-lg rounded-xl border border-gray-100 p-6">
<SimActions
subscriptionId={subscriptionId}
simType={simInfo.details.simType}
status={simInfo.details.status}
currentPlanCode={simInfo.details.planCode}
onTopUpSuccess={handleActionSuccess}
onPlanChangeSuccess={handleActionSuccess}
onCancelSuccess={handleActionSuccess}
onReissueSuccess={handleActionSuccess}
embedded={true}
/>
<div className="mt-6">
<p className="text-sm text-gray-600 font-medium mb-3">Modify service options</p>
<SimFeatureToggles
subscriptionId={subscriptionId}
voiceMailEnabled={simInfo.details.voiceMailEnabled}
callWaitingEnabled={simInfo.details.callWaitingEnabled}
internationalRoamingEnabled={simInfo.details.internationalRoamingEnabled}
networkType={simInfo.details.networkType}
onChanged={handleActionSuccess}
embedded
/>
</div>
</div>
</div>
{/* Sidebar - Compact Info (Right Side) */}
<div className="order-1 xl:order-2 space-y-8">
{/* Details + Usage combined card for mobile-first */}
<div className="bg-white shadow-lg rounded-xl border border-gray-100 p-6 space-y-6">
<SimDetailsCard
simDetails={simInfo.details}
isLoading={false}
error={null}
embedded={true}
showFeaturesSummary={false}
/>
<DataUsageChart
usage={simInfo.usage}
remainingQuotaMb={simInfo.details.remainingQuotaMb}
isLoading={false}
error={null}
embedded={true}
/>
</div>
{/* Important Information Card */}
<div className="bg-gradient-to-br from-blue-50 to-blue-100 border border-blue-200 rounded-xl p-6">
<div className="flex items-center mb-4">
<div className="bg-blue-200 rounded-lg p-2 mr-3">
<svg
className="h-5 w-5 text-blue-600"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
</div>
<h3 className="text-lg font-semibold text-blue-900">Important Information</h3>
</div>
<ul className="space-y-2 text-sm text-blue-800">
<li className="flex items-start">
<span className="inline-block w-1.5 h-1.5 bg-blue-600 rounded-full mt-2 mr-3 flex-shrink-0"></span>
Data usage is updated in real-time and may take a few minutes to reflect recent
activity
</li>
<li className="flex items-start">
<span className="inline-block w-1.5 h-1.5 bg-blue-600 rounded-full mt-2 mr-3 flex-shrink-0"></span>
Top-up data will be available immediately after successful processing
</li>
<li className="flex items-start">
<span className="inline-block w-1.5 h-1.5 bg-blue-600 rounded-full mt-2 mr-3 flex-shrink-0"></span>
SIM cancellation is permanent and cannot be undone
</li>
{simInfo.details.simType === "esim" && (
<li className="flex items-start">
<span className="inline-block w-1.5 h-1.5 bg-blue-600 rounded-full mt-2 mr-3 flex-shrink-0"></span>
eSIM profile reissue will provide a new QR code for activation
</li>
)}
</ul>
</div>
{/* (On desktop, details+usage are above; on mobile they appear first since this section is above actions) */}
</div>
</div>
</div>
);
}