);
}
diff --git a/apps/portal/src/features/catalog/components/internet/InternetPlanCard.tsx b/apps/portal/src/features/catalog/components/internet/InternetPlanCard.tsx
index 6cfb4893..615fe0fc 100644
--- a/apps/portal/src/features/catalog/components/internet/InternetPlanCard.tsx
+++ b/apps/portal/src/features/catalog/components/internet/InternetPlanCard.tsx
@@ -14,14 +14,14 @@ import type { BadgeVariant } from "@/features/catalog/components/base/CardBadge"
import { useCatalogStore } from "@/features/catalog/services/catalog.store";
import { IS_DEVELOPMENT } from "@/config/environment";
import { parsePlanName } from "@/features/catalog/components/internet/utils/planName";
-import { useShopBasePath } from "@/features/catalog/hooks/useShopBasePath";
+import { useServicesBasePath } from "@/features/catalog/hooks/useServicesBasePath";
interface InternetPlanCardProps {
plan: InternetPlanCatalogItem;
installations: InternetInstallationCatalogItem[];
disabled?: boolean;
disabledReason?: string;
- /** Override the default configure href (default: /shop/internet/configure?planSku=...) */
+ /** Override the default configure href (default: /services/internet/configure?planSku=...) */
configureHref?: string;
/** Override default "Configure Plan" action (used for public browse-only flows) */
action?: { label: string; href: string };
@@ -71,7 +71,7 @@ export function InternetPlanCard({
titlePriority = "detail",
}: InternetPlanCardProps) {
const router = useRouter();
- const shopBasePath = useShopBasePath();
+ const servicesBasePath = useServicesBasePath();
const tier = plan.internetPlanTier;
const isGold = tier === "Gold";
const isPlatinum = tier === "Platinum";
@@ -249,7 +249,7 @@ export function InternetPlanCard({
setInternetConfig({ planSku: plan.sku, currentStep: 1 });
const href =
configureHref ??
- `${shopBasePath}/internet/configure?planSku=${encodeURIComponent(plan.sku)}`;
+ `${servicesBasePath}/internet/configure?planSku=${encodeURIComponent(plan.sku)}`;
router.push(href);
}}
>
diff --git a/apps/portal/src/features/catalog/components/internet/PlanComparisonGuide.tsx b/apps/portal/src/features/catalog/components/internet/PlanComparisonGuide.tsx
index 50b07478..4343ef67 100644
--- a/apps/portal/src/features/catalog/components/internet/PlanComparisonGuide.tsx
+++ b/apps/portal/src/features/catalog/components/internet/PlanComparisonGuide.tsx
@@ -1,9 +1,13 @@
"use client";
+import { useState } from "react";
import {
WrenchScrewdriverIcon,
SparklesIcon,
CubeTransparentIcon,
+ ChevronDownIcon,
+ ChevronUpIcon,
+ QuestionMarkCircleIcon,
} from "@heroicons/react/24/outline";
import { cn } from "@/lib/utils";
@@ -56,7 +60,7 @@ function PlanGuideItem({
highlight && "ring-2 ring-warning/30"
)}
>
-
+
-
-
Which plan is right for you?
-
- All plans include the same connection speed. The difference is in equipment and support.
-
-
+
+ {/* Collapsible header */}
+
- {/* Stacked rows - always vertical for cleaner reading */}
-
-
}
- title="Silver"
- idealFor="Tech-savvy users with their own router"
- description="You get the NTT modem and ISP connection. Bring your own WiFi router and configure the network yourself. Best for those comfortable with networking."
- />
+ {/* Expandable content */}
+ {isExpanded && (
+
+
+
}
+ title="Silver"
+ idealFor="Tech-savvy users with their own router"
+ description="You get the NTT modem and ISP connection. Bring your own WiFi router and configure the network yourself."
+ />
-
}
- title="Gold"
- idealFor="Most customers—hassle-free setup"
- description="We provide everything: NTT modem, WiFi router, and pre-configured ISP. Just plug in and connect. Optional range extender available if needed."
- highlight
- />
+
}
+ title="Gold"
+ idealFor="Most customers—hassle-free setup"
+ description="We provide everything: NTT modem, WiFi router, and pre-configured ISP. Just plug in and connect. Optional range extender available."
+ highlight
+ />
-
}
- title="Platinum"
- idealFor="Larger homes needing custom coverage"
- description="For residences 50m²+ where one router isn't enough. We design a custom mesh network with Netgear INSIGHT routers, cloud management, and professional setup."
- />
-
+
}
+ title="Platinum"
+ idealFor="Larger homes needing custom coverage"
+ description="For residences where one router isn't enough. We design a custom mesh network with Netgear INSIGHT routers, cloud management, and professional setup."
+ />
+
- {/* Platinum additional info */}
-
-
- About Platinum plans: After verifying
- your address, we'll assess your space and create a tailored proposal. This may
- include multiple mesh routers, LAN wiring, or other equipment based on your layout and
- needs. Final pricing depends on your specific setup requirements.
-
-
+
+
+ About Platinum: After verifying
+ your address, we'll assess your space and create a tailored proposal. Final pricing
+ depends on your specific setup requirements.
+
+
+
+ )}
);
}
diff --git a/apps/portal/src/features/catalog/components/internet/PublicOfferingCard.tsx b/apps/portal/src/features/catalog/components/internet/PublicOfferingCard.tsx
index e67a0dda..65773a9d 100644
--- a/apps/portal/src/features/catalog/components/internet/PublicOfferingCard.tsx
+++ b/apps/portal/src/features/catalog/components/internet/PublicOfferingCard.tsx
@@ -36,6 +36,8 @@ interface PublicOfferingCardProps {
defaultExpanded?: boolean;
/** Show info tooltip explaining connection types (for Apartment) */
showConnectionInfo?: boolean;
+ customCtaLabel?: string;
+ onCtaClick?: (e: React.MouseEvent) => void;
}
const tierStyles = {
@@ -124,6 +126,8 @@ export function PublicOfferingCard({
ctaPath,
defaultExpanded = false,
showConnectionInfo = false,
+ customCtaLabel,
+ onCtaClick,
}: PublicOfferingCardProps) {
const [isExpanded, setIsExpanded] = useState(defaultExpanded);
const [showInfo, setShowInfo] = useState(false);
@@ -259,9 +263,15 @@ export function PublicOfferingCard({
{" "}
(or 12/24-month installment)
-
+ {onCtaClick ? (
+
+ ) : (
+
+ )}
)}
diff --git a/apps/portal/src/features/catalog/components/internet/WhyChooseSection.tsx b/apps/portal/src/features/catalog/components/internet/WhyChooseSection.tsx
deleted file mode 100644
index f3fc9c2a..00000000
--- a/apps/portal/src/features/catalog/components/internet/WhyChooseSection.tsx
+++ /dev/null
@@ -1,81 +0,0 @@
-"use client";
-
-import {
- WifiIcon,
- GlobeAltIcon,
- WrenchScrewdriverIcon,
- ChatBubbleLeftRightIcon,
- UserGroupIcon,
- HomeModernIcon,
-} from "@heroicons/react/24/outline";
-
-interface FeatureItemProps {
- icon: React.ReactNode;
- title: string;
- description: string;
-}
-
-function FeatureItem({ icon, title, description }: FeatureItemProps) {
- return (
-
-
- {icon}
-
-
-
{title}
-
{description}
-
-
- );
-}
-
-export function WhyChooseSection() {
- return (
-
-
-
Why choose our internet service?
-
- Japan's most reliable fiber network with dedicated English support.
-
-
-
-
- }
- title="NTT Fiber Network"
- description="Powered by Japan's largest and most reliable optical fiber infrastructure, delivering speeds up to 10Gbps."
- />
-
- }
- title="IPoE Connection"
- description="Modern IPv6/IPoE technology for congestion-free access, even during peak hours. PPPoE also available."
- />
-
- }
- title="Flexible ISP Options"
- description="Multiple connection protocols within a single contract. Switch between IPoE and PPPoE as needed."
- />
-
- }
- title="One-Stop Solution"
- description="NTT line, ISP service, and optional equipment—all managed through one provider. One bill, one contact point."
- />
-
- }
- title="Full English Support"
- description="Native English customer service for setup, billing questions, and technical support. No language barriers."
- />
-
- }
- title="On-Site Assistance"
- description="Need help at home? Our technicians can visit for setup, troubleshooting, or network optimization."
- />
-
-
- );
-}
diff --git a/apps/portal/src/features/catalog/components/internet/WhyChooseUsPillars.tsx b/apps/portal/src/features/catalog/components/internet/WhyChooseUsPillars.tsx
deleted file mode 100644
index f3ac3aa6..00000000
--- a/apps/portal/src/features/catalog/components/internet/WhyChooseUsPillars.tsx
+++ /dev/null
@@ -1,106 +0,0 @@
-"use client";
-
-import {
- WifiIcon,
- ChatBubbleLeftRightIcon,
- BoltIcon,
- WrenchScrewdriverIcon,
- DocumentTextIcon,
- GlobeAltIcon,
-} from "@heroicons/react/24/outline";
-import { CheckCircleIcon } from "@heroicons/react/24/solid";
-
-interface FeatureProps {
- icon: React.ReactNode;
- title: string;
- description: string;
- highlight?: string;
-}
-
-function FeatureCard({ icon, title, description, highlight }: FeatureProps) {
- return (
-
-
- {icon}
-
-
-
{title}
-
{description}
- {highlight && (
-
-
- {highlight}
-
- )}
-
-
- );
-}
-
-/**
- * Why Choose Us - Clean feature grid
- * 6 key differentiators in a 3x2 grid on desktop, 2x3 on tablet, stacked on mobile
- */
-export function WhyChooseUsPillars() {
- const features: FeatureProps[] = [
- {
- icon:
,
- title: "NTT Optical Fiber",
- description: "Japan's most reliable network with speeds up to 10Gbps",
- highlight: "99.9% uptime",
- },
- {
- icon:
,
- title: "IPv6/IPoE Ready",
- description: "Next-gen protocol for congestion-free browsing",
- highlight: "No peak-hour slowdowns",
- },
- {
- icon:
,
- title: "Full English Support",
- description: "Native English service for setup, billing & technical help",
- highlight: "No language barriers",
- },
- {
- icon:
,
- title: "One Bill, One Provider",
- description: "NTT line + ISP + equipment bundled with simple billing",
- highlight: "No hidden fees",
- },
- {
- icon:
,
- title: "On-site Support",
- description: "Technicians can visit for installation & troubleshooting",
- highlight: "Professional setup",
- },
- {
- icon:
,
- title: "Flexible Options",
- description: "Multiple ISP configs available, IPv4/PPPoE if needed",
- highlight: "Customizable",
- },
- ];
-
- return (
-
- {/* Header */}
-
-
- Why Choose Us
-
-
-
- {/* Feature grid - 3 columns on large, 2 on medium, 1 on mobile */}
-
- {features.map((feature, index) => (
-
-
-
- ))}
-
-
- );
-}
diff --git a/apps/portal/src/features/catalog/components/internet/configure/InternetConfigureContainer.tsx b/apps/portal/src/features/catalog/components/internet/configure/InternetConfigureContainer.tsx
index 9de60fc9..25dd8906 100644
--- a/apps/portal/src/features/catalog/components/internet/configure/InternetConfigureContainer.tsx
+++ b/apps/portal/src/features/catalog/components/internet/configure/InternetConfigureContainer.tsx
@@ -16,7 +16,7 @@ import { InstallationStep } from "./steps/InstallationStep";
import { AddonsStep } from "./steps/AddonsStep";
import { ReviewOrderStep } from "./steps/ReviewOrderStep";
import { useConfigureState } from "./hooks/useConfigureState";
-import { useShopBasePath } from "@/features/catalog/hooks/useShopBasePath";
+import { useServicesBasePath } from "@/features/catalog/hooks/useServicesBasePath";
import { PlanHeader } from "@/features/catalog/components/internet/PlanHeader";
interface Props {
@@ -58,7 +58,7 @@ export function InternetConfigureContainer({
currentStep,
setCurrentStep,
}: Props) {
- const shopBasePath = useShopBasePath();
+ const servicesBasePath = useServicesBasePath();
const [renderedStep, setRenderedStep] = useState(currentStep);
const [transitionPhase, setTransitionPhase] = useState<"idle" | "enter" | "exit">("idle");
// Use local state ONLY for step validation, step management now in Zustand
@@ -214,7 +214,7 @@ export function InternetConfigureContainer({
{/* Plan Header */}
diff --git a/apps/portal/src/features/catalog/components/sim/SimCallingRates.tsx b/apps/portal/src/features/catalog/components/sim/SimCallingRates.tsx
new file mode 100644
index 00000000..9c7625da
--- /dev/null
+++ b/apps/portal/src/features/catalog/components/sim/SimCallingRates.tsx
@@ -0,0 +1,168 @@
+"use client";
+
+import { useState } from "react";
+import { PhoneIcon, ChatBubbleLeftIcon, GlobeAltIcon } from "@heroicons/react/24/outline";
+import { ChevronDownIcon } from "@heroicons/react/24/solid";
+
+const domesticRates = {
+ calling: { rate: 10, unit: "30 sec" },
+ sms: { rate: 3, unit: "message" },
+};
+
+const internationalSmsRate = 100; // per message
+
+const internationalCallingRates = [
+ { country: "United States", code: "US", rate: "31-34" },
+ { country: "United Kingdom", code: "UK", rate: "78-108" },
+ { country: "Australia", code: "AU", rate: "63-68" },
+ { country: "China", code: "CN", rate: "49-57" },
+ { country: "India", code: "IN", rate: "98-148" },
+ { country: "Singapore", code: "SG", rate: "63-68" },
+ { country: "France", code: "FR", rate: "78-108" },
+ { country: "Germany", code: "DE", rate: "78-108" },
+];
+
+export function SimCallingRates() {
+ const [isExpanded, setIsExpanded] = useState(false);
+
+ return (
+
+ {/* Header */}
+
+
+
+ Calling & SMS Rates
+
+
+ Pay-per-use charges apply. Billed 5-6 weeks after usage.
+
+
+
+ {/* Domestic Rates */}
+
+
+
+
+
+ Domestic (Japan)
+
+
+
+
+
+
+ ¥{domesticRates.calling.rate}
+
+ /{domesticRates.calling.unit}
+
+
+
+
+
+
+
+ SMS
+
+
+ ¥{domesticRates.sms.rate}
+
+ /{domesticRates.sms.unit}
+
+
+
+
+
+
Incoming calls and SMS are free.
+
+
+ {/* International Rates (Collapsible) */}
+
+
+
+ {isExpanded && (
+
+
+
+
+
+ | Country |
+
+ Rate (¥/30sec)
+ |
+
+
+
+ {internationalCallingRates.map((rate, index) => (
+
+ |
+ {rate.country}
+ ({rate.code})
+ |
+ ¥{rate.rate} |
+
+ ))}
+
+
+
+
+
+
• International SMS: ¥{internationalSmsRate}/message
+
• Rates vary by time of day and day of week
+
+ • For full rate details, visit{" "}
+
+ NTT Docomo's website
+
+
+
+
+ )}
+
+
+ {/* Unlimited Calling Option */}
+
+
+
+
+
Unlimited Domestic Calling
+
+ Add unlimited domestic calls to any Data+Voice plan for{" "}
+ ¥3,000/month
+
+
+ Available as an add-on during checkout. International calls not included.
+
+
+
+
+
+ );
+}
diff --git a/apps/portal/src/features/catalog/components/sim/SimConfigureView.tsx b/apps/portal/src/features/catalog/components/sim/SimConfigureView.tsx
index 499672d6..5488c46a 100644
--- a/apps/portal/src/features/catalog/components/sim/SimConfigureView.tsx
+++ b/apps/portal/src/features/catalog/components/sim/SimConfigureView.tsx
@@ -10,7 +10,7 @@ import { ActivationForm } from "@/features/catalog/components/sim/ActivationForm
import { MnpForm } from "@/features/catalog/components/sim/MnpForm";
import { ProgressSteps } from "@/components/molecules";
import { CatalogBackLink } from "@/features/catalog/components/base/CatalogBackLink";
-import { useShopBasePath } from "@/features/catalog/hooks/useShopBasePath";
+import { useServicesBasePath } from "@/features/catalog/hooks/useServicesBasePath";
import {
ArrowLeftIcon,
ArrowRightIcon,
@@ -49,7 +49,7 @@ export function SimConfigureView({
setCurrentStep,
onConfirm,
}: Props) {
- const shopBasePath = useShopBasePath();
+ const servicesBasePath = useServicesBasePath();
const getRequiredActivationFee = (
fees: SimActivationFeeCatalogItem[]
): SimActivationFeeCatalogItem | undefined => {
@@ -164,7 +164,7 @@ export function SimConfigureView({
Plan Not Found
The selected plan could not be found
← Return to SIM Plans
@@ -190,7 +190,7 @@ export function SimConfigureView({
icon={}
>
-
+
@@ -535,10 +535,24 @@ export function SimConfigureView({
)}
+
+ Prices exclude 10% consumption tax
+