2025-09-17 18:43:43 +09:00
|
|
|
"use client";
|
|
|
|
|
|
2025-09-25 15:14:36 +09:00
|
|
|
import { SubCard } from "@/components/molecules/SubCard/SubCard";
|
2025-09-25 15:54:54 +09:00
|
|
|
import { DetailHeader } from "@/components/molecules/DetailHeader/DetailHeader";
|
2025-09-17 18:43:43 +09:00
|
|
|
import { useEffect, useState } from "react";
|
|
|
|
|
import { useParams, useSearchParams } from "next/navigation";
|
|
|
|
|
import Link from "next/link";
|
2025-12-16 13:54:31 +09:00
|
|
|
import { ServerIcon, CalendarIcon, DocumentTextIcon } from "@heroicons/react/24/outline";
|
2025-09-17 18:43:43 +09:00
|
|
|
import { format } from "date-fns";
|
|
|
|
|
import { useSubscription } from "@/features/subscriptions/hooks";
|
|
|
|
|
import { InvoicesList } from "@/features/billing/components/InvoiceList/InvoiceList";
|
2025-10-09 10:49:03 +09:00
|
|
|
import { Formatting } from "@customer-portal/domain/toolkit";
|
2025-12-16 13:54:31 +09:00
|
|
|
import { PageLayout } from "@/components/templates/PageLayout";
|
2025-10-09 10:49:03 +09:00
|
|
|
|
2025-10-22 10:58:16 +09:00
|
|
|
const { formatCurrency: sharedFormatCurrency } = Formatting;
|
2025-09-17 18:43:43 +09:00
|
|
|
import { SimManagementSection } from "@/features/sim-management";
|
2025-11-18 14:06:27 +09:00
|
|
|
import {
|
|
|
|
|
getBillingCycleLabel,
|
|
|
|
|
getSubscriptionStatusIcon,
|
|
|
|
|
getSubscriptionStatusVariant,
|
|
|
|
|
} from "@/features/subscriptions/utils/status-presenters";
|
2025-09-17 18:43:43 +09:00
|
|
|
|
|
|
|
|
export function SubscriptionDetailContainer() {
|
|
|
|
|
const params = useParams();
|
|
|
|
|
const searchParams = useSearchParams();
|
|
|
|
|
const [showInvoices, setShowInvoices] = useState(true);
|
|
|
|
|
const [showSimManagement, setShowSimManagement] = useState(false);
|
|
|
|
|
|
|
|
|
|
const subscriptionId = parseInt(params.id as string);
|
|
|
|
|
const { data: subscription, isLoading, error } = useSubscription(subscriptionId);
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
const updateVisibility = () => {
|
|
|
|
|
const hash = typeof window !== "undefined" ? window.location.hash : "";
|
|
|
|
|
const service = (searchParams.get("service") || "").toLowerCase();
|
|
|
|
|
const isSimContext = hash.includes("sim-management") || service === "sim";
|
|
|
|
|
if (isSimContext) {
|
|
|
|
|
setShowInvoices(false);
|
|
|
|
|
setShowSimManagement(true);
|
|
|
|
|
} else {
|
|
|
|
|
setShowInvoices(true);
|
|
|
|
|
setShowSimManagement(false);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
updateVisibility();
|
|
|
|
|
if (typeof window !== "undefined") {
|
|
|
|
|
window.addEventListener("hashchange", updateVisibility);
|
|
|
|
|
return () => window.removeEventListener("hashchange", updateVisibility);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}, [searchParams]);
|
|
|
|
|
|
|
|
|
|
const formatDate = (dateString: string | undefined) => {
|
|
|
|
|
if (!dateString) return "N/A";
|
|
|
|
|
try {
|
|
|
|
|
return format(new Date(dateString), "MMM d, yyyy");
|
|
|
|
|
} catch {
|
|
|
|
|
return "Invalid date";
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2025-10-22 10:58:16 +09:00
|
|
|
const formatCurrency = (amount: number) => sharedFormatCurrency(amount || 0);
|
2025-09-17 18:43:43 +09:00
|
|
|
|
2025-12-16 13:54:31 +09:00
|
|
|
const pageError =
|
|
|
|
|
error || !subscription
|
|
|
|
|
? process.env.NODE_ENV === "development"
|
|
|
|
|
? error instanceof Error
|
|
|
|
|
? error.message
|
|
|
|
|
: "Subscription not found"
|
|
|
|
|
: "Unable to load subscription details. Please try again."
|
|
|
|
|
: null;
|
2025-09-17 18:43:43 +09:00
|
|
|
|
2025-12-16 13:54:31 +09:00
|
|
|
const isSimService = Boolean(subscription?.productName?.toLowerCase().includes("sim"));
|
2025-09-17 18:43:43 +09:00
|
|
|
|
|
|
|
|
return (
|
2025-12-16 13:54:31 +09:00
|
|
|
<PageLayout
|
|
|
|
|
icon={<ServerIcon className="h-6 w-6" />}
|
|
|
|
|
title={subscription?.productName ?? "Subscription"}
|
|
|
|
|
description={
|
|
|
|
|
subscription ? `Service ID: ${subscription.serviceId}` : "View your subscription details"
|
|
|
|
|
}
|
|
|
|
|
breadcrumbs={[
|
|
|
|
|
{ label: "Subscriptions", href: "/subscriptions" },
|
|
|
|
|
{ label: subscription?.productName ?? "Subscription" },
|
|
|
|
|
]}
|
|
|
|
|
loading={isLoading}
|
|
|
|
|
error={pageError}
|
|
|
|
|
>
|
|
|
|
|
{subscription ? (
|
|
|
|
|
<div className="max-w-7xl mx-auto">
|
|
|
|
|
<SubCard className="mb-6">
|
|
|
|
|
<DetailHeader
|
|
|
|
|
title="Subscription Details"
|
|
|
|
|
subtitle="Service subscription information"
|
|
|
|
|
leftIcon={getSubscriptionStatusIcon(subscription.status)}
|
|
|
|
|
status={{
|
|
|
|
|
label: subscription.status,
|
|
|
|
|
variant: getSubscriptionStatusVariant(subscription.status),
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
<div className="pt-4">
|
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
2025-09-17 18:43:43 +09:00
|
|
|
<div>
|
2025-12-16 13:54:31 +09:00
|
|
|
<h4 className="text-sm font-medium text-muted-foreground uppercase tracking-wider">
|
|
|
|
|
Billing Amount
|
|
|
|
|
</h4>
|
|
|
|
|
<div className="mt-2 flex items-baseline gap-2">
|
|
|
|
|
<p className="text-2xl font-bold text-foreground">
|
|
|
|
|
{formatCurrency(subscription.amount)}
|
|
|
|
|
</p>
|
|
|
|
|
<span className="text-sm text-muted-foreground">
|
|
|
|
|
{getBillingCycleLabel(subscription.cycle)}
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
2025-10-29 18:19:50 +09:00
|
|
|
</div>
|
2025-12-16 13:54:31 +09:00
|
|
|
<div>
|
|
|
|
|
<h4 className="text-sm font-medium text-muted-foreground uppercase tracking-wider">
|
|
|
|
|
Next Due Date
|
|
|
|
|
</h4>
|
|
|
|
|
<div className="flex items-center mt-2">
|
|
|
|
|
<CalendarIcon className="h-4 w-4 text-muted-foreground/70 mr-2" />
|
|
|
|
|
<p className="text-lg font-medium text-foreground">
|
|
|
|
|
{formatDate(subscription.nextDue)}
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
2025-09-17 18:43:43 +09:00
|
|
|
</div>
|
2025-12-16 13:54:31 +09:00
|
|
|
<div>
|
|
|
|
|
<h4 className="text-sm font-medium text-muted-foreground uppercase tracking-wider">
|
|
|
|
|
Registration Date
|
|
|
|
|
</h4>
|
|
|
|
|
<div className="flex items-center mt-2">
|
|
|
|
|
<CalendarIcon className="h-4 w-4 text-muted-foreground/70 mr-2" />
|
|
|
|
|
<p className="text-lg font-medium text-foreground">
|
|
|
|
|
{formatDate(subscription.registrationDate)}
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
2025-10-29 18:19:50 +09:00
|
|
|
</div>
|
2025-09-17 18:43:43 +09:00
|
|
|
</div>
|
|
|
|
|
</div>
|
2025-12-16 13:54:31 +09:00
|
|
|
</SubCard>
|
2025-09-17 18:43:43 +09:00
|
|
|
|
2025-12-16 13:54:31 +09:00
|
|
|
{isSimService && (
|
|
|
|
|
<div className="mb-8">
|
|
|
|
|
<SubCard>
|
|
|
|
|
<div className="flex flex-col lg:flex-row lg:items-center lg:justify-between gap-4">
|
|
|
|
|
<div>
|
|
|
|
|
<h3 className="text-xl font-semibold text-foreground">Service Management</h3>
|
|
|
|
|
<p className="text-sm text-muted-foreground mt-1">
|
|
|
|
|
Switch between billing and SIM management views
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="flex flex-col sm:flex-row gap-2 bg-muted rounded-xl p-2 border border-border/60">
|
|
|
|
|
<Link
|
|
|
|
|
href={`/subscriptions/${subscriptionId}#sim-management`}
|
|
|
|
|
className={`px-6 py-3 text-sm font-semibold rounded-lg transition-colors min-w-[140px] text-center ${
|
|
|
|
|
showSimManagement
|
|
|
|
|
? "bg-card text-primary shadow-[var(--cp-shadow-1)]"
|
|
|
|
|
: "text-muted-foreground hover:text-foreground hover:bg-card/60"
|
|
|
|
|
}`}
|
|
|
|
|
>
|
|
|
|
|
<ServerIcon className="h-4 w-4 inline mr-2" />
|
|
|
|
|
SIM Management
|
|
|
|
|
</Link>
|
|
|
|
|
<Link
|
|
|
|
|
href={`/subscriptions/${subscriptionId}`}
|
|
|
|
|
className={`px-6 py-3 text-sm font-semibold rounded-lg transition-colors min-w-[120px] text-center ${
|
|
|
|
|
showInvoices
|
|
|
|
|
? "bg-card text-primary shadow-[var(--cp-shadow-1)]"
|
|
|
|
|
: "text-muted-foreground hover:text-foreground hover:bg-card/60"
|
|
|
|
|
}`}
|
|
|
|
|
>
|
|
|
|
|
<DocumentTextIcon className="h-4 w-4 inline mr-2" />
|
|
|
|
|
Invoices
|
|
|
|
|
</Link>
|
|
|
|
|
</div>
|
2025-09-17 18:43:43 +09:00
|
|
|
</div>
|
2025-12-16 13:54:31 +09:00
|
|
|
</SubCard>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
2025-09-17 18:43:43 +09:00
|
|
|
|
2025-12-16 13:54:31 +09:00
|
|
|
{showSimManagement && (
|
|
|
|
|
<div className="mb-10">
|
|
|
|
|
<SimManagementSection subscriptionId={subscriptionId} />
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
2025-09-17 18:43:43 +09:00
|
|
|
|
2025-12-16 13:54:31 +09:00
|
|
|
{showInvoices && <InvoicesList subscriptionId={subscriptionId} pageSize={5} />}
|
2025-11-22 18:11:43 +09:00
|
|
|
</div>
|
2025-12-16 13:54:31 +09:00
|
|
|
) : null}
|
|
|
|
|
</PageLayout>
|
2025-09-17 18:43:43 +09:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default SubscriptionDetailContainer;
|