Update Service Pages Metadata and Content for Enhanced User Engagement

- Revised metadata titles and descriptions across various service pages to better reflect offerings and improve SEO.
- Updated content in the About Us, Contact, and Support pages to emphasize English support and services for expats in Japan.
- Removed TV Services references from the portal, streamlining service offerings and focusing on core services.
- Enhanced service descriptions to clarify benefits and features, ensuring users understand the value of each service.
This commit is contained in:
tema 2026-01-20 17:19:00 +09:00
parent 7139e0489d
commit ff870c9f4f
20 changed files with 763 additions and 1034 deletions

View File

@ -8,19 +8,19 @@ import type { Metadata } from "next";
import { AboutUsView } from "@/features/marketing/views/AboutUsView"; import { AboutUsView } from "@/features/marketing/views/AboutUsView";
export const metadata: Metadata = { export const metadata: Metadata = {
title: "About Us - Assist Solutions Corp. | Company Profile", title: "About Us - 20+ Years Serving Expats in Japan | Assist Solutions",
description: description:
"Learn about Assist Solutions Corp., established in 2002. A registered telecom carrier (A-19-9538) providing IT services to Japan's international community with bilingual support.", "Since 2002, Assist Solutions has been the trusted IT partner for expats and international businesses in Japan. Bilingual support, no Japanese required.",
keywords: [ keywords: [
"Assist Solutions", "Assist Solutions expats",
"IT company Tokyo", "IT company foreigners Japan",
"English IT support Tokyo",
"expat services Japan", "expat services Japan",
"telecom carrier Japan",
], ],
openGraph: { openGraph: {
title: "About Assist Solutions Corp.", title: "About Assist Solutions - IT for Expats Since 2002",
description: description:
"Established in 2002, serving Japan's international community with reliable IT solutions and English support.", "20+ years serving Japan's international community. Internet, mobile, VPN, and tech support with full English support.",
type: "website", type: "website",
}, },
}; };

View File

@ -8,20 +8,20 @@ import type { Metadata } from "next";
import { PublicContactView } from "@/features/support/views/PublicContactView"; import { PublicContactView } from "@/features/support/views/PublicContactView";
export const metadata: Metadata = { export const metadata: Metadata = {
title: "Support & Contact - Assist Solutions | Get Help", title: "Contact Us - English Support for Expats | Assist Solutions",
description: description:
"Get support from Assist Solutions. FAQ, live chat, phone support (0120-660-470), and contact form. English and Japanese support available for internet, mobile, and IT services.", "Need help? Our English-speaking team is here for you. Call 0120-660-470 (toll-free in Japan), chat, or email. No Japanese required.",
keywords: [ keywords: [
"English support Japan",
"IT help expats Tokyo",
"contact Assist Solutions", "contact Assist Solutions",
"IT support Tokyo", "bilingual support Japan",
"customer service Japan", "English customer service",
"English support",
"FAQ",
], ],
openGraph: { openGraph: {
title: "Support & Contact - Assist Solutions", title: "Contact Us - English Support | Assist Solutions",
description: description:
"Get help with your internet, mobile, or IT services. Bilingual support available. Toll-free: 0120-660-470", "Questions about internet, mobile, or IT services? Our English-speaking team is ready to help. Toll-free: 0120-660-470",
type: "website", type: "website",
}, },
}; };

View File

@ -3,20 +3,20 @@ import { Button } from "@/components/atoms";
import { Server, Monitor, Wrench, Globe } from "lucide-react"; import { Server, Monitor, Wrench, Globe } from "lucide-react";
export const metadata: Metadata = { export const metadata: Metadata = {
title: "Business Solutions - Enterprise IT Services | Assist Solutions", title: "IT Solutions for International Businesses in Japan | Assist Solutions",
description: description:
"Comprehensive business IT solutions: Dedicated Internet Access with SLA, office LAN setup, data center services at Equinix Tokyo, and ongoing tech support.", "Enterprise IT for foreign companies in Japan. Dedicated internet, office networks, data center hosting, all with bilingual support. We understand international business needs.",
keywords: [ keywords: [
"business internet Japan", "IT for foreign companies Japan",
"dedicated internet access", "international business IT Tokyo",
"office LAN setup Tokyo", "bilingual IT support Japan",
"data center Japan", "office network setup foreigners",
"enterprise IT Tokyo", "enterprise IT English support",
], ],
openGraph: { openGraph: {
title: "Business Solutions - Assist Solutions", title: "Business IT for International Companies - Assist Solutions",
description: description:
"Enterprise-grade IT services with dedicated bandwidth, data center hosting, and bilingual support.", "Enterprise IT with bilingual support. Dedicated internet, office networks, and data center services for foreign companies in Japan.",
type: "website", type: "website",
}, },
}; };
@ -27,11 +27,11 @@ export default function BusinessSolutionsPage() {
{/* Header */} {/* Header */}
<div className="text-center mb-16 pt-8"> <div className="text-center mb-16 pt-8">
<h1 className="text-4xl sm:text-5xl font-extrabold text-foreground mb-6 tracking-tight"> <h1 className="text-4xl sm:text-5xl font-extrabold text-foreground mb-6 tracking-tight">
Business Solutions IT for International Businesses
</h1> </h1>
<p className="text-xl text-muted-foreground max-w-2xl mx-auto leading-relaxed"> <p className="text-xl text-muted-foreground max-w-2xl mx-auto leading-relaxed">
We provide comprehensive business solutions including DIA (Dedicated Internet Access) with Running an international company in Japan? We provide enterprise IT with bilingual
SLA and bandwidth guarantees to ensure your business stays connected. support, so your team can focus on business, not navigating Japanese tech providers.
</p> </p>
</div> </div>
@ -43,10 +43,9 @@ export default function BusinessSolutionsPage() {
</div> </div>
<h2 className="text-2xl font-bold text-foreground mb-4">Office LAN Setup</h2> <h2 className="text-2xl font-bold text-foreground mb-4">Office LAN Setup</h2>
<p className="text-muted-foreground leading-relaxed mb-6"> <p className="text-muted-foreground leading-relaxed mb-6">
Whether you are upgrading your current LAN for greater bandwidth and reliability or Setting up a new office or upgrading your network? We handle everything in English. from
installing a new LAN for a new facility, Assist Solutions will ensure you make informed planning to installation. Cable runs, switches, routers, and firewalls configured by
decisions. From cable installation and data switches to configuration of routers and bilingual technicians who understand international business needs.
firewalls, we help you determine a cost-effective and reliable way to do this.
</p> </p>
</div> </div>
@ -57,10 +56,9 @@ export default function BusinessSolutionsPage() {
</div> </div>
<h2 className="text-2xl font-bold text-foreground mb-4">Onsite & Remote Tech Support</h2> <h2 className="text-2xl font-bold text-foreground mb-4">Onsite & Remote Tech Support</h2>
<p className="text-muted-foreground leading-relaxed mb-6"> <p className="text-muted-foreground leading-relaxed mb-6">
We provide onsite and remote support to make sure your network is up and running as IT issues don&apos;t wait, and neither do we. Our English-speaking technicians provide
quickly as possible. Assist Solutions can help with your IT needs so you can grow your fast onsite and remote support for your business. Network problems, hardware issues,
business with ease and stability. From computer networks to phone and printer software setup. We keep your operations running smoothly.
installations, our team will complete your project to your highest satisfaction.
</p> </p>
</div> </div>
@ -73,10 +71,9 @@ export default function BusinessSolutionsPage() {
Dedicated Internet Access (DIA) Dedicated Internet Access (DIA)
</h2> </h2>
<p className="text-muted-foreground leading-relaxed mb-6"> <p className="text-muted-foreground leading-relaxed mb-6">
Dedicated Internet Access is designed for businesses that need greater Internet capacity Need guaranteed bandwidth for your business? Our Dedicated Internet Access provides
and a dedicated connection between their existing Local Area Network (LAN) and the enterprise-grade connectivity with SLA guarantees. Perfect for companies requiring
public Internet. We are able to provide a bandwidth guarantee with a service level reliable, high-capacity connections with English contracts and support.
agreement depending on what is most suitable for your business.
</p> </p>
</div> </div>
@ -87,10 +84,9 @@ export default function BusinessSolutionsPage() {
</div> </div>
<h2 className="text-2xl font-bold text-foreground mb-4">Data Center Service</h2> <h2 className="text-2xl font-bold text-foreground mb-4">Data Center Service</h2>
<p className="text-muted-foreground leading-relaxed mb-6"> <p className="text-muted-foreground leading-relaxed mb-6">
Our Data Center Service provides high-quality data center facilities in Equinix (Tokyo Host your infrastructure in world-class Tokyo data centers (Equinix, GDC Gotenyama). We
Tennozu Isle) and GDC (Gotenyama) and many value-added network services to help provide colocation and managed services with English support, making it easy for
establish stable infrastructure platforms. This improves both reliability and efficiency international companies to establish reliable IT infrastructure in Japan.
in your company.
</p> </p>
</div> </div>
</div> </div>
@ -98,13 +94,15 @@ export default function BusinessSolutionsPage() {
{/* CTA */} {/* CTA */}
<div className="text-center py-12 bg-muted/20 rounded-3xl mb-16"> <div className="text-center py-12 bg-muted/20 rounded-3xl mb-16">
<h2 className="text-2xl font-bold text-foreground mb-4"> <h2 className="text-2xl font-bold text-foreground mb-4">
Interested in our Business Solutions? Let&apos;s Talk About Your IT Needs
</h2> </h2>
<p className="text-muted-foreground mb-8 max-w-2xl mx-auto"> <p className="text-muted-foreground mb-8 max-w-2xl mx-auto">
Contact us today to discuss your requirements and how we can help your business grow. Running an international business in Japan comes with unique challenges. We&apos;ve been
helping foreign companies navigate Japanese IT for over 20 years. Let&apos;s discuss how
we can support your operations.
</p> </p>
<Button as="a" href="/contact" size="lg"> <Button as="a" href="/contact" size="lg">
Contact Us Get in Touch
</Button> </Button>
</div> </div>
</div> </div>

View File

@ -9,20 +9,20 @@ import { PublicInternetPlansView } from "@/features/services/views/PublicInterne
import { RedirectAuthenticatedToAccountServices } from "@/features/services/components/common/RedirectAuthenticatedToAccountServices"; import { RedirectAuthenticatedToAccountServices } from "@/features/services/components/common/RedirectAuthenticatedToAccountServices";
export const metadata: Metadata = { export const metadata: Metadata = {
title: "Internet Plans - Fiber Optic Internet in Japan | Assist Solutions", title: "Internet for Expats in Japan - Fiber Optic with English Support | Assist Solutions",
description: description:
"Get reliable NTT fiber optic internet up to 10Gbps with English support. IPv6/IPoE connections, no long-term contracts, monthly billing. Serving expats in Tokyo.", "High-speed NTT fiber internet with full English support. No Japanese required for signup. We handle the paperwork, you enjoy fast internet. Serving expats since 2002.",
keywords: [ keywords: [
"fiber internet Japan", "internet for expats Japan",
"NTT fiber optic", "English internet service Tokyo",
"internet for expats", "NTT fiber foreigners",
"10Gbps internet Tokyo", "10Gbps internet expats",
"IPv6 Japan", "no Japanese internet signup",
], ],
openGraph: { openGraph: {
title: "Internet Plans - Assist Solutions", title: "Internet for Expats - Assist Solutions",
description: description:
"High-speed NTT fiber optic internet with English support. Up to 10Gbps, no long-term contracts.", "High-speed fiber internet with English support. No Japanese required. We handle everything.",
type: "website", type: "website",
}, },
}; };

View File

@ -10,26 +10,27 @@ export function OnsiteSupportContent() {
{/* Header */} {/* Header */}
<div className="text-center mb-16 pt-8"> <div className="text-center mb-16 pt-8">
<h1 className="text-4xl sm:text-5xl font-extrabold text-foreground mb-6 tracking-tight"> <h1 className="text-4xl sm:text-5xl font-extrabold text-foreground mb-6 tracking-tight">
Onsite Support Tech Help in English, At Your Door
</h1> </h1>
<p className="text-xl text-muted-foreground max-w-2xl mx-auto leading-relaxed"> <p className="text-xl text-muted-foreground max-w-2xl mx-auto leading-relaxed">
We dispatch our skillful in-house tech staff to your residence or office for your needs. Need help with your router, computer, or home network? Our English-speaking technicians
come to your home or office to solve tech problems, explained in a language you
understand.
</p> </p>
</div> </div>
{/* Main Services */} {/* Main Services */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-12 mb-20"> <div className="grid grid-cols-1 md:grid-cols-2 gap-12 mb-20">
<div className="space-y-6"> <div className="space-y-6">
<h2 className="text-3xl font-bold text-foreground">Need Our Technical Support?</h2> <h2 className="text-3xl font-bold text-foreground">We Come to You</h2>
<p className="text-muted-foreground leading-relaxed"> <p className="text-muted-foreground leading-relaxed">
We can provide you with on-site technical support service. If you would like for our Living in Japan without strong Japanese skills can make tech problems frustrating.
technicians to visit your residence and provide technical assistance, please let us That&apos;s where we come in. Our English-speaking technicians visit your home or office
know. to help with setup, troubleshooting, and configuration.
</p> </p>
<p className="text-muted-foreground leading-relaxed"> <p className="text-muted-foreground leading-relaxed">
We also provide &quot;Remote Access Services&quot; which allows our technicians to do For quick fixes, we also offer remote support. We connect to your device securely over
support via Remote Access Software over the Internet connection to fix up the issue the internet to diagnose and resolve issues without a home visit.
(depends on what the issue is).
</p> </p>
<div className="pt-4"> <div className="pt-4">
<Button as="a" href="/contact" size="lg"> <Button as="a" href="/contact" size="lg">
@ -129,9 +130,15 @@ export function OnsiteSupportContent() {
{/* CTA */} {/* CTA */}
<div className="text-center py-12 bg-muted/20 rounded-3xl"> <div className="text-center py-12 bg-muted/20 rounded-3xl">
<h2 className="text-2xl font-bold text-foreground mb-4">Ready to get started?</h2> <h2 className="text-2xl font-bold text-foreground mb-4">
Tech Problems? We Speak Your Language.
</h2>
<p className="text-muted-foreground mb-6 max-w-xl mx-auto">
Don&apos;t struggle with Japanese-only support lines. Get help from technicians who
explain things clearly in English.
</p>
<Button as="a" href="/contact" size="lg"> <Button as="a" href="/contact" size="lg">
Contact Us for Support Request Support
</Button> </Button>
</div> </div>
</div> </div>

View File

@ -2,19 +2,20 @@ import type { Metadata } from "next";
import { OnsiteSupportContent } from "./OnsiteSupportContent"; import { OnsiteSupportContent } from "./OnsiteSupportContent";
export const metadata: Metadata = { export const metadata: Metadata = {
title: "Onsite Support - Tech Support in Tokyo | Assist Solutions", title: "English Tech Support at Home - Tokyo & Surrounding Areas | Assist Solutions",
description: description:
"Professional onsite and remote tech support in Tokyo, Saitama, and Kanagawa. Wi-Fi setup, network troubleshooting, computer repair. English-speaking technicians.", "Tech help in English at your door. Wi-Fi, computers, networks. Our bilingual technicians solve problems and explain things clearly. Tokyo, Saitama, Kanagawa.",
keywords: [ keywords: [
"tech support Tokyo", "English tech support Tokyo",
"IT support expats", "IT support expats Japan",
"computer repair Japan", "bilingual computer help",
"Wi-Fi setup Tokyo", "home network setup foreigners",
"English IT support", "English speaking IT Japan",
], ],
openGraph: { openGraph: {
title: "Onsite Tech Support - Assist Solutions", title: "English Tech Support at Home - Assist Solutions",
description: "English-speaking technicians for home and office IT support in Tokyo area.", description:
"Bilingual technicians for home and office IT support. We explain things in English.",
type: "website", type: "website",
}, },
}; };

View File

@ -2,19 +2,20 @@ import type { Metadata } from "next";
import { ServicesGrid } from "@/features/services/components/common/ServicesGrid"; import { ServicesGrid } from "@/features/services/components/common/ServicesGrid";
export const metadata: Metadata = { export const metadata: Metadata = {
title: "Services - Internet, Mobile, VPN & IT Support | Assist Solutions", title: "Services for Expats in Japan - Internet, Mobile, VPN & IT Support | Assist Solutions",
description: description:
"Explore our comprehensive IT services: fiber optic internet up to 10Gbps, mobile SIM cards, VPN access, TV services, and professional onsite support in Tokyo.", "IT services designed for foreigners in Japan. Fiber internet, SIM cards, VPN access, and tech support, all with full English support. No Japanese required.",
keywords: [ keywords: [
"internet service Japan", "internet service Japan expats",
"SIM card Tokyo", "SIM card foreigners Tokyo",
"VPN service", "VPN service Japan",
"IT support expats", "IT support expats Japan",
"fiber internet", "English internet service Japan",
], ],
openGraph: { openGraph: {
title: "Our Services - Assist Solutions", title: "Services for Expats - Assist Solutions",
description: "Internet, mobile, VPN, TV and tech support services for expats in Japan.", description:
"Internet, mobile, VPN and tech support services with full English support for expats in Japan.",
type: "website", type: "website",
}, },
}; };
@ -29,11 +30,11 @@ export default function ServicesPage({ basePath = "/services" }: ServicesPagePro
{/* Header */} {/* Header */}
<div className="text-center mb-16 pt-8"> <div className="text-center mb-16 pt-8">
<h1 className="text-4xl sm:text-5xl font-extrabold text-foreground mb-6 tracking-tight"> <h1 className="text-4xl sm:text-5xl font-extrabold text-foreground mb-6 tracking-tight">
Our Services Services for Expats in Japan
</h1> </h1>
<p className="text-xl text-muted-foreground max-w-2xl mx-auto leading-relaxed"> <p className="text-xl text-muted-foreground max-w-2xl mx-auto leading-relaxed">
From high-speed internet to onsite support, we provide comprehensive solutions for your Tired of navigating Japanese-only websites and contracts? We provide internet, mobile, and
home and business. IT services with full English support. No Japanese required.
</p> </p>
</div> </div>

View File

@ -9,20 +9,20 @@ import { PublicSimPlansView } from "@/features/services/views/PublicSimPlans";
import { RedirectAuthenticatedToAccountServices } from "@/features/services/components/common/RedirectAuthenticatedToAccountServices"; import { RedirectAuthenticatedToAccountServices } from "@/features/services/components/common/RedirectAuthenticatedToAccountServices";
export const metadata: Metadata = { export const metadata: Metadata = {
title: "SIM Card Plans - Mobile Service in Japan | Assist Solutions", title: "SIM Cards for Foreigners in Japan - No Hanko Required | Assist Solutions",
description: description:
"Get affordable SIM cards using NTT Docomo's network. Voice + Data and Data-only plans, eSIM available. First month free, no credit check for foreigners.", "SIM cards for expats on Japan's best network. Foreign credit cards accepted, no hanko needed, English support. First month free. Get connected in days, not weeks.",
keywords: [ keywords: [
"SIM card Japan", "SIM card foreigners Japan",
"mobile service expats", "mobile service expats Tokyo",
"Docomo MVNO", "no hanko SIM Japan",
"eSIM Japan", "foreign credit card SIM",
"prepaid SIM Tokyo", "English SIM service Japan",
], ],
openGraph: { openGraph: {
title: "Mobile SIM Card Plans - Assist Solutions", title: "SIM Cards for Foreigners - Assist Solutions",
description: description:
"Affordable mobile plans on Docomo's network with English support. SIM and eSIM available.", "Mobile plans for expats. Foreign credit cards accepted, no hanko. English support included.",
type: "website", type: "website",
}, },
}; };

View File

@ -1,24 +0,0 @@
import type { Metadata } from "next";
export const metadata: Metadata = {
title: "TV Services - Satellite & Cable TV in Japan | Assist Solutions",
description:
"Access premium TV services including Sky PerfecTV, iTSCOM, and J:COM. We arrange your TV service at no extra fee. English support available.",
keywords: [
"cable TV Japan",
"satellite TV Tokyo",
"Sky PerfecTV",
"JCOM English",
"TV service expats",
],
openGraph: {
title: "TV Services - Assist Solutions",
description:
"Premium cable and satellite TV options in Japan. Free consultation and arrangement service.",
type: "website",
},
};
export default function TVServicesLayout({ children }: { children: React.ReactNode }) {
return children;
}

View File

@ -1,727 +0,0 @@
"use client";
import { useState } from "react";
import { Button } from "@/components/atoms";
import {
Tv,
Film,
Music,
Trophy,
Newspaper,
Sparkles,
MoreHorizontal,
GraduationCap,
Globe,
ChevronDown,
Check,
Satellite,
Cable,
Zap,
} from "lucide-react";
import { cn } from "@/shared/utils";
// TV Service Data
const tvServices = [
{
id: "sky-hikari",
name: "Sky PerfecTV Premium Hikari",
shortName: "Sky Hikari",
type: "Optical Fiber",
icon: <Zap className="h-5 w-5" />,
fees: [
{ type: "Apartment", initial: "Free", monthly: "4,567" },
{ type: "Home", initial: "14,630", monthly: "5,392" },
],
note: "Home initial: 6,680 JPY if simultaneous installation",
channels: {
Movie: [
"The Cinema HD",
"Movie Plus HD",
"Channel NECO HD",
"Japanese Movie HD",
"Fox Movie Premium HD",
"Cinefil Wowow HD",
"NTV G HD",
"EX Sports",
"Dance Channel",
],
Sports: [
"Golf Network HD",
"GAORA HD",
"J Sports 1 HD",
"J Sports 2 HD",
"J Sports 3 HD",
"Sky A Sports HD",
],
Music: [
"Music Japan TV HD",
"MTV HD",
"Music ON! TV HD",
"Space Shower TV HD",
"Space Shower TV Plus HD",
"Kayou Pops HD",
"Music Air HD",
"Music Graffiti TV",
],
Kids: [
"Cartoon Network HD",
"Disney Channel HD",
"Disney XD HD",
"Kids Station HD",
"Animax HD",
"Lala HD",
"Asia Dramatic TV HD",
"KBS World HD",
],
"Foreign Drama": [
"Super Drama TV HD",
"AXN Mystery HD",
"AXN HD",
"FOX HD",
"FOX CLASSICS HD",
],
Documentary: [
"History Channel HD",
"National Geographic HD",
"Discovery HD",
"Nat Geo Wild HD",
"Animal Planet HD",
],
"News & Business": [
"TBS News Bird HD",
"Nikkei CNBC HD",
"BBC World News HD",
"CNNj HD",
"NTV News 24",
"SORA Weather Channel",
"E-tenki.net",
"Entametele HD",
"Nittele Plus HD",
],
Entertainment: [
"Fox Sports HD",
"FujiTV One HD",
"FujiTV Two HD",
"TBS Channel 1 HD",
"TBS Channel 2 HD",
"TV Asahi Channel 1 HD",
"TV Asahi Channel 2 HD",
],
Others: [
"Mondo TV HD",
"Family Theater HD",
"Home Drama HD",
"Samurai Drama HD",
"TABI Channel HD",
"Tsuri Vision HD",
"Igo/Shogi Channel HD",
],
},
},
{
id: "sky-premium",
name: "Sky PerfecTV Premium",
shortName: "Sky Premium",
type: "Satellite",
icon: <Satellite className="h-5 w-5" />,
fees: [{ type: "Standard", initial: "Free", monthly: "4,514" }],
channels: {
Movie: [
"Imagica BS HD",
"The Cinema HD",
"Movie Plus HD",
"Channel NECO HD",
"Japanese Movie HD",
"Fox Movie Premium HD",
"Cinefil Wowow HD",
],
Sports: ["J Sports 3 HD", "Sky A Sports HD", "NTV G HD", "EX Sports", "Dance Channel"],
Music: [
"Music Japan TV HD",
"MTV HD",
"Music ON! TV HD",
"Space Shower TV HD",
"Space Shower TV Plus HD",
"Kayou Pops HD",
"Music Air HD",
"Music Graffiti TV",
],
Kids: [
"Cartoon Network HD",
"Disney Channel HD",
"Disney XD HD",
"Kids Station HD",
"Animax HD",
"Disney Junior",
"Asia Dramatic TV HD",
"KBS World HD",
],
"Foreign Drama": [
"Super Drama TV HD",
"AXN Mystery HD",
"AXN HD",
"FOX HD",
"FOX CLASSICS HD",
"Lala HD",
],
Documentary: [
"History Channel HD",
"National Geographic HD",
"Discovery HD",
"Nat Geo Wild HD",
"Animal Planet HD",
],
"News & Business": [
"TBS News Bird HD",
"Nikkei CNBC HD",
"BBC World News HD",
"CNNj HD",
"NTV News 24",
"CCTV Daifu",
"SORA Weather Channel",
"Entametele HD",
"NTV Plus HD",
"Channel Ginga",
],
Entertainment: [
"Fox Sports HD",
"FujiTV One HD",
"FujiTV Two HD",
"TBS Channel 1 HD",
"TBS Channel 2 HD",
"TV Asahi Channel 1 HD",
"TV Asahi Channel 2 HD",
"Yose Channel",
],
Others: [
"IGO & Shogi",
"Mondo 21 HD",
"Family Theater HD",
"Home Drama HD",
"Samurai Drama HD",
"TABI Channel HD",
"Railyway Channel HD",
],
},
},
{
id: "sky-basic",
name: "Sky PerfecTV",
shortName: "Sky Basic",
type: "Satellite",
icon: <Satellite className="h-5 w-5" />,
fees: [
{ type: "Apartment", initial: "Free", monthly: "4,389" },
{ type: "Home", initial: "11,330", monthly: "5,214" },
],
note: "Home initial: 6,680 JPY if simultaneous installation",
channels: {
Movie: [
"Movie Plus HD",
"Japanese Movie HD (BS)",
"The Cinema",
"Channel NECO",
"Cinefil Wowow HD",
],
Sports: ["Nittele G HD", "Sky A Sports HD", "GAORA Sports HD", "Fox Sports HD"],
Music: [
"MTV HD",
"Music ON! TV HD",
"Space Shower TV",
"Music Air",
"Space Shower TV Plus",
"Kayo Pops",
],
Kids: [
"Kids Station HD",
"BS Animax HD (BS)",
"Disney (BS)",
"Cartoon Network",
"Disney Junior",
],
"Foreign Drama": ["Lala HD", "Super Drama TV HD", "AXN", "AXN Mystery", "FOX"],
Documentary: ["History Channel", "National Geographic", "Discovery", "Animal Planet"],
"News & Business": [
"TBS News Bird",
"BBC World News",
"CNNj",
"NTV News 24",
"TBS Channel 1 HD",
"TBS Channel 2",
"NTV Plus",
"Channel Ginga",
],
Entertainment: [
"Fuji TV One HD",
"Fuji TV Two HD",
"TV Asahi Channel 1 HD",
"TV Asahi Channel 2 HD",
"Igo/Shogi Channel",
"Mondo TV HD",
],
Others: [
"Tsuri Vision HD (BS)",
"Family Gekijo HD",
"Samurai Drama HD",
"Home Drama Channel",
],
},
},
{
id: "itscom",
name: "iTSCOM",
shortName: "iTSCOM",
type: "Cable TV",
icon: <Cable className="h-5 w-5" />,
fees: [{ type: "Big Package", initial: "11,000", monthly: "5,280" }],
channels: {
Movie: ["Movie Plus HD", "Japanese Movie HD", "Channel NECO HD", "FOX Movie Premium HD"],
Sports: [
"Golf Network HD",
"Nittele G HD",
"Sky A Sports HD",
"GAORA HD",
"J Sports 1 HD",
"J Sports 2 HD",
"J Sports 3 HD",
],
Music: ["MTV HD", "Music ON! TV HD", "Space Shower TV", "Music Air"],
Kids: [
"Animax HD",
"Kids Station HD",
"Disney XD",
"Cartoon Network",
"Baby TV",
"Disney Junior",
],
"Foreign Drama": [
"AXN HD",
"FOX HD",
"Asia Dramatic TV HD",
"Super Drama TV HD",
"AXN Mystery HD",
"Family Theater HD",
],
Documentary: [
"Discovery HD",
"National Geographic",
"Animal Planet HD",
"History Channel HD",
],
"News & Business": [
"BBC World News HD",
"CNNj HD",
"Nikkei CNBC HD",
"TBS News Bird HD",
"TV Asahi Channel 2",
"NTV News 24",
"NHK World Japan",
"Disney Channel HD",
],
Entertainment: [
"LaLa TV HD",
"Channel Ginga HD",
"Dlife HD",
"FOX Sports HD",
"TBS Channel 1 HD",
"TBS Channel 2",
"NTV Plus",
],
Others: [
"Japanet Channel DX HD",
"Jewelly Gem Shopping HD",
"Samurai Drama HD",
"TABI Channel",
"QVC",
"Shop Channel",
"Igo/Shogi Channel",
],
},
},
{
id: "jcom",
name: "J:COM",
shortName: "J:COM",
type: "Cable TV",
icon: <Cable className="h-5 w-5" />,
fees: [{ type: "Standard Package", initial: "9,900", monthly: "6,074" }],
channels: {
Movie: [
"Movie Plus HD",
"The Cinema HD",
"Channel NECO HD",
"Japanese Movie HD",
"Fox Movies",
"Cinefil Wowow HD",
"Fox Sports & Entertainment",
],
Sports: [
"J Sports 1 HD",
"J Sports 2 HD",
"J Sports 3 HD",
"Sky A Sports HD",
"Golf Network HD",
"GAORA HD",
],
Music: ["MTV HD", "Music ON! TV HD", "Space Shower TV", "Kayou Pops"],
Kids: [
"Animax HD",
"Kids Station HD",
"Cartoon Network HD",
"Disney Channel HD",
"Disney XD HD",
"Disney Junior HD",
"AXN Mystery HD",
],
"Foreign Drama": [
"Super Drama TV HD",
"FOX HD",
"FOX Classics HD",
"AXN HD",
"Lala HD",
"KBS World HD",
],
Documentary: [
"History Channel HD",
"National Geographic HD",
"Discovery Channel HD",
"Animal Planet HD",
],
"News & Business": [
"TBS News Bird HD",
"Nikkei CNBC HD",
"TV Asahi Channel 2 HD",
"CNNj",
"NTV News 24",
"NHK World Japan",
"KBS World",
"NTV Plus",
"Act On TV",
],
Entertainment: [
"FujiTV One HD",
"FujiTV Two HD",
"TBS Channel 1 HD",
"TBS Channel 2 HD",
"Channel Ginga HD",
"TV Asahi Channel 1",
"Housou University TV",
],
Others: [
"Family Theater HD",
"Samurai Drama HD",
"Home Drama Channel HD",
"Mondo TV HD",
"Tsuri Vision HD",
"Igo/Shogi Channel",
],
},
},
];
const categoryIcons: Record<string, React.ReactNode> = {
Movie: <Film className="h-4 w-4" />,
Music: <Music className="h-4 w-4" />,
Sports: <Trophy className="h-4 w-4" />,
"News & Business": <Newspaper className="h-4 w-4" />,
Entertainment: <Sparkles className="h-4 w-4" />,
Kids: <Sparkles className="h-4 w-4" />,
"Foreign Drama": <Globe className="h-4 w-4" />,
Documentary: <GraduationCap className="h-4 w-4" />,
Others: <MoreHorizontal className="h-4 w-4" />,
};
export default function TVServicesPage() {
const [selectedService, setSelectedService] = useState(tvServices[0].id);
const [expandedCategories, setExpandedCategories] = useState<string[]>([]);
const activeService = tvServices.find(s => s.id === selectedService)!;
const toggleCategory = (category: string) => {
setExpandedCategories(prev =>
prev.includes(category) ? prev.filter(c => c !== category) : [...prev, category]
);
};
const expandAll = () => {
setExpandedCategories(Object.keys(activeService.channels));
};
const collapseAll = () => {
setExpandedCategories([]);
};
return (
<div className="max-w-6xl mx-auto px-4 pb-16">
{/* Header */}
<div className="text-center mb-12 pt-8">
<h1 className="text-4xl sm:text-5xl font-extrabold text-foreground mb-4 tracking-tight">
TV Services
</h1>
<p className="text-lg text-muted-foreground max-w-2xl mx-auto leading-relaxed">
Satellite TV, Cable TV and Optical Fiber TV options. We arrange your service at no extra
fee.
</p>
</div>
{/* Service Selector Cards */}
<div className="mb-8">
<h2 className="text-sm font-semibold text-muted-foreground uppercase tracking-wider mb-4">
Select a Service
</h2>
<div className="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-5 gap-3">
{tvServices.map(service => {
const isSelected = selectedService === service.id;
const lowestMonthly = Math.min(
...service.fees.map(f => parseInt(f.monthly.replace(",", "")))
);
return (
<button
key={service.id}
type="button"
onClick={() => {
setSelectedService(service.id);
setExpandedCategories([]);
}}
className={cn(
"relative p-4 rounded-xl border-2 text-left transition-all duration-200",
isSelected
? "border-primary bg-primary/5 shadow-md"
: "border-border/60 bg-white hover:border-primary/40 hover:shadow-sm"
)}
>
{isSelected && (
<div className="absolute top-2 right-2">
<Check className="h-4 w-4 text-primary" />
</div>
)}
<div
className={cn(
"flex items-center justify-center w-10 h-10 rounded-lg mb-3",
isSelected ? "bg-primary text-white" : "bg-muted/50 text-primary"
)}
>
{service.icon}
</div>
<h3 className="font-bold text-sm text-foreground leading-tight mb-1">
{service.shortName}
</h3>
<p className="text-xs text-muted-foreground mb-2">{service.type}</p>
<p className="text-sm font-bold text-primary">
¥{lowestMonthly.toLocaleString()}
<span className="text-xs font-normal text-muted-foreground">/mo~</span>
</p>
</button>
);
})}
</div>
</div>
{/* Selected Service Details */}
<div className="bg-white border border-border/60 rounded-2xl shadow-sm overflow-hidden mb-12">
{/* Service Header */}
<div className="bg-gradient-to-r from-primary/10 to-primary/5 p-6 border-b border-border/60">
<div className="flex items-center gap-4">
<div className="h-12 w-12 rounded-xl bg-primary flex items-center justify-center text-white">
<Tv className="h-6 w-6" />
</div>
<div>
<h2 className="text-2xl font-bold text-foreground">{activeService.name}</h2>
<p className="text-sm text-muted-foreground">{activeService.type} Service</p>
</div>
</div>
</div>
<div className="p-6">
{/* Pricing Table */}
<div className="mb-8">
<h3 className="text-sm font-semibold text-muted-foreground uppercase tracking-wider mb-3">
Pricing
</h3>
<div className="overflow-x-auto">
<table className="w-full text-sm">
<thead>
<tr className="bg-muted/50">
<th className="text-left px-4 py-3 font-medium text-muted-foreground rounded-l-lg">
Plan
</th>
<th className="text-left px-4 py-3 font-medium text-muted-foreground">
Initial Cost
</th>
<th className="text-left px-4 py-3 font-medium text-muted-foreground rounded-r-lg">
Monthly
</th>
</tr>
</thead>
<tbody className="divide-y divide-border/60">
{activeService.fees.map((fee, i) => (
<tr key={i}>
<td className="px-4 py-3 font-medium text-foreground">{fee.type}</td>
<td className="px-4 py-3 text-muted-foreground">
{fee.initial === "Free" ? (
<span className="text-success font-medium">Free</span>
) : (
`¥${fee.initial}`
)}
</td>
<td className="px-4 py-3 font-bold text-foreground">¥{fee.monthly}/mo</td>
</tr>
))}
</tbody>
</table>
</div>
{activeService.note && (
<p className="text-xs text-muted-foreground mt-2">* {activeService.note}</p>
)}
<p className="text-xs text-muted-foreground mt-1">* Prices include 10% tax</p>
</div>
{/* Channel List */}
<div>
<div className="flex items-center justify-between mb-4">
<h3 className="text-sm font-semibold text-muted-foreground uppercase tracking-wider">
Channel Lineup ({Object.values(activeService.channels).flat().length} channels)
</h3>
<div className="flex gap-2">
<button
type="button"
onClick={expandAll}
className="text-xs text-primary hover:underline"
>
Expand All
</button>
<span className="text-muted-foreground">|</span>
<button
type="button"
onClick={collapseAll}
className="text-xs text-primary hover:underline"
>
Collapse All
</button>
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-3">
{Object.entries(activeService.channels).map(([category, channels]) => {
const isExpanded = expandedCategories.includes(category);
return (
<div
key={category}
className="border border-border/60 rounded-xl overflow-hidden bg-muted/20"
>
<button
type="button"
onClick={() => toggleCategory(category)}
className="w-full flex items-center justify-between p-4 hover:bg-muted/40 transition-colors"
>
<div className="flex items-center gap-3">
<span className="text-primary">{categoryIcons[category]}</span>
<span className="font-semibold text-foreground text-sm">{category}</span>
<span className="text-xs text-muted-foreground bg-muted px-2 py-0.5 rounded-full">
{channels.length}
</span>
</div>
<ChevronDown
className={cn(
"h-4 w-4 text-muted-foreground transition-transform",
isExpanded && "rotate-180"
)}
/>
</button>
{isExpanded && (
<div className="px-4 pb-4 pt-0">
<ul className="space-y-1.5">
{channels.map(channel => (
<li
key={channel}
className="text-xs text-muted-foreground flex items-center gap-2"
>
<span className="w-1 h-1 rounded-full bg-primary/50" />
{channel}
</li>
))}
</ul>
</div>
)}
</div>
);
})}
</div>
</div>
</div>
</div>
{/* Info Banner */}
<div className="bg-primary/5 border border-primary/20 rounded-2xl p-6 mb-12">
<div className="flex flex-col sm:flex-row items-start sm:items-center gap-4">
<div className="h-12 w-12 rounded-xl bg-primary/10 flex items-center justify-center text-primary flex-shrink-0">
<Tv className="h-6 w-6" />
</div>
<div className="flex-1">
<h3 className="font-bold text-foreground mb-1">Not sure which service is available?</h3>
<p className="text-sm text-muted-foreground">
Most buildings in Japan have pre-assigned TV service providers. Contact us for a free
consultation to find out which services you can apply for.
</p>
</div>
<Button as="a" href="/contact" className="flex-shrink-0">
Check Availability
</Button>
</div>
</div>
{/* FAQ Section */}
<div className="mb-12">
<h2 className="text-2xl font-bold text-foreground mb-6 text-center">
Frequently Asked Questions
</h2>
<div className="space-y-4 max-w-3xl mx-auto">
<FaqItem
question="Is Assist Solutions directly providing the TV service?"
answer="As partners, we are able to refer you to each cable TV company available at your home. However, once the service starts, the cable TV service itself will be directly provided by each cable TV company."
/>
<FaqItem
question="Would I be able to choose any cable TV service that Assist Solutions is partnered with?"
answer="In Japan, most cable TV companies have predetermined service areas. We will be able to check which services are available for your home. Please contact us at info@asolutions.co.jp for a free consultation."
/>
</div>
</div>
{/* CTA */}
<div className="text-center py-10 bg-muted/30 rounded-2xl">
<h2 className="text-2xl font-bold text-foreground mb-3">
Find the best TV service for you
</h2>
<p className="text-muted-foreground mb-6">Free consultation and arrangement service</p>
<Button as="a" href="/contact" size="lg">
Contact Us
</Button>
</div>
</div>
);
}
/**
* FAQ Item component with expand/collapse functionality
*/
function FaqItem({ question, answer }: { question: string; answer: string }) {
const [isOpen, setIsOpen] = useState(false);
return (
<div className="border border-border rounded-xl overflow-hidden bg-card">
<button
type="button"
onClick={() => setIsOpen(!isOpen)}
className="w-full flex items-start justify-between gap-3 p-4 text-left hover:bg-muted/50 transition-colors"
>
<span className="font-medium text-foreground">{question}</span>
<ChevronDown
className={`w-5 h-5 text-muted-foreground flex-shrink-0 mt-0.5 transition-transform duration-200 ${isOpen ? "rotate-180" : ""}`}
/>
</button>
{isOpen && (
<div className="px-4 pb-4 text-sm text-muted-foreground leading-relaxed">{answer}</div>
)}
</div>
);
}

View File

@ -9,14 +9,19 @@ import { PublicVpnPlansView } from "@/features/services/views/PublicVpnPlans";
import { RedirectAuthenticatedToAccountServices } from "@/features/services/components/common/RedirectAuthenticatedToAccountServices"; import { RedirectAuthenticatedToAccountServices } from "@/features/services/components/common/RedirectAuthenticatedToAccountServices";
export const metadata: Metadata = { export const metadata: Metadata = {
title: "VPN Service - Secure VPN Access from Japan | Assist Solutions", title: "VPN for Expats - Stream US/UK Content in Japan | Assist Solutions",
description: description:
"Reliable VPN service with servers in San Francisco and London. Static routing from Tokyo, optional VPN Wi-Fi router rental. Perfect for streaming and privacy.", "Watch your favorite shows from home while living in Japan. Pre-configured VPN router, just plug in and stream. US and UK servers available.",
keywords: ["VPN Japan", "VPN service Tokyo", "streaming VPN", "secure internet Japan"], keywords: [
"VPN expats Japan",
"stream US content Japan",
"Netflix VPN Tokyo",
"UK streaming Japan",
],
openGraph: { openGraph: {
title: "VPN Service - Assist Solutions", title: "VPN for Expats in Japan - Assist Solutions",
description: description:
"Secure VPN access from Tokyo with servers in US and UK. Static routing and router rental available.", "Stream your favorite content from home. Pre-configured router, just plug in. US and UK servers.",
type: "website", type: "website",
}, },
}; };

View File

@ -12,16 +12,7 @@ import Link from "next/link";
import { Logo } from "@/components/atoms/logo"; import { Logo } from "@/components/atoms/logo";
import { SiteFooter } from "@/components/organisms/SiteFooter"; import { SiteFooter } from "@/components/organisms/SiteFooter";
import { useAuthStore } from "@/features/auth/stores/auth.store"; import { useAuthStore } from "@/features/auth/stores/auth.store";
import { import { Wifi, Smartphone, Building2, Lock, Wrench, ChevronDown, ArrowRight } from "lucide-react";
Wifi,
Smartphone,
Building2,
Lock,
Tv,
Wrench,
ChevronDown,
ArrowRight,
} from "lucide-react";
export interface PublicShellProps { export interface PublicShellProps {
children: ReactNode; children: ReactNode;
@ -118,13 +109,6 @@ export function PublicShell({ children }: PublicShellProps) {
icon: <Lock className="h-5 w-5" />, icon: <Lock className="h-5 w-5" />,
color: "bg-amber-50 text-amber-600", color: "bg-amber-50 text-amber-600",
}, },
{
href: "/services/tv",
label: "TV Services",
desc: "Satellite & Cable TV",
icon: <Tv className="h-5 w-5" />,
color: "bg-rose-50 text-rose-600",
},
{ {
href: "/services/onsite", href: "/services/onsite",
label: "Onsite Support", label: "Onsite Support",

View File

@ -11,15 +11,15 @@ import {
BadgeCheck, BadgeCheck,
Wrench, Wrench,
Building2, Building2,
Tv,
MapPin, MapPin,
Mail, Mail,
MessageSquare, MessageSquare,
PhoneCall, PhoneCall,
Train, Train,
Globe,
Server, Server,
Shield, Shield,
Code,
Settings,
} from "lucide-react"; } from "lucide-react";
type ServiceCategory = "personal" | "business"; type ServiceCategory = "personal" | "business";
@ -42,7 +42,6 @@ const personalServices: ServiceItem[] = [
href: "/services/sim", href: "/services/sim",
}, },
{ title: "VPN Service", icon: <Lock className="h-8 w-8 text-primary" />, href: "/services/vpn" }, { title: "VPN Service", icon: <Lock className="h-8 w-8 text-primary" />, href: "/services/vpn" },
{ title: "TV Services", icon: <Tv className="h-8 w-8 text-primary" />, href: "/services/tv" },
{ {
title: "Onsite Support", title: "Onsite Support",
icon: <Wrench className="h-8 w-8 text-primary" />, icon: <Wrench className="h-8 w-8 text-primary" />,
@ -72,8 +71,13 @@ const businessServices: ServiceItem[] = [
href: "/services/business", href: "/services/business",
}, },
{ {
title: "Website Construction & Maintenance", title: "Website Construction",
icon: <Globe className="h-8 w-8 text-primary" />, icon: <Code className="h-8 w-8 text-primary" />,
href: "/services/business",
},
{
title: "Website Maintenance",
icon: <Settings className="h-8 w-8 text-primary" />,
href: "/services/business", href: "/services/business",
}, },
]; ];
@ -96,41 +100,35 @@ export function PublicLandingView() {
{ {
title: "Internet Plans", title: "Internet Plans",
description: description:
"Utilizing NTT's optical fiber network, we deliver one of the most reliable Internet connections in Japan.", "High-speed NTT fiber with English installation support. No Japanese paperwork, we handle everything for you.",
icon: <Wifi className="h-8 w-8 text-primary" />, icon: <Wifi className="h-8 w-8 text-primary" />,
href: "/services/internet", href: "/services/internet",
}, },
{ {
title: "Phone Plans", title: "Phone Plans",
description: description:
"Using NTT DOCOMO's vast mobile network, we deliver one of the most cost-friendly SIM card services in Japan.", "SIM cards on Japan's best network. Foreign credit cards accepted, no hanko required. Get connected in days.",
icon: <Smartphone className="h-8 w-8 text-primary" />, icon: <Smartphone className="h-8 w-8 text-primary" />,
href: "/services/sim", href: "/services/sim",
}, },
{ {
title: "Business Solutions", title: "Business Solutions",
description: description:
"Dedicated Internet Access, office network setup, data center services, and ongoing tech support.", "Enterprise IT for international companies. Dedicated internet, office networks, and bilingual tech support.",
icon: <Building2 className="h-8 w-8 text-primary" />, icon: <Building2 className="h-8 w-8 text-primary" />,
href: "/services/business", href: "/services/business",
}, },
{ {
title: "VPN", title: "VPN",
description: description:
"Choose any of our VPN server locations that connect directly from Tokyo with static routing.", "Stream your favorite shows from home. Pre-configured router, just plug in and watch US/UK content.",
icon: <Lock className="h-8 w-8 text-primary" />, icon: <Lock className="h-8 w-8 text-primary" />,
href: "/services/vpn", href: "/services/vpn",
}, },
{
title: "TV Services",
description: "A variety of options for customers such as Satellite TV and Optical Fiber TV.",
icon: <Tv className="h-8 w-8 text-primary" />,
href: "/services/tv",
},
{ {
title: "Onsite Support", title: "Onsite Support",
description: description:
"Professional technical support at your residence or office for setup, configuration, and troubleshooting.", "English-speaking technicians at your home or office. Router setup, network issues, and device help.",
icon: <Wrench className="h-8 w-8 text-primary" />, icon: <Wrench className="h-8 w-8 text-primary" />,
href: "/services/onsite", href: "/services/onsite",
}, },
@ -196,11 +194,17 @@ export function PublicLandingView() {
title: "Acronis Quick Assist", title: "Acronis Quick Assist",
href: "https://www.acronis.com/en/products/cloud/quick-assist/download/", href: "https://www.acronis.com/en/products/cloud/quick-assist/download/",
image: "/assets/images/arconis.png", image: "/assets/images/arconis.png",
description:
"Secure remote desktop tool for quick troubleshooting. Our technicians can view your screen and resolve issues in real-time.",
useCase: "Best for: General tech support & diagnostics",
}, },
{ {
title: "TeamViewer QS", title: "TeamViewer QS",
href: "https://get.teamviewer.com/tokyo", href: "https://get.teamviewer.com/tokyo",
image: "/assets/images/teamviewer.png", image: "/assets/images/teamviewer.png",
description:
"Industry-standard remote access software. Allows our team to securely connect to your device for hands-on assistance.",
useCase: "Best for: Complex configurations & file transfers",
}, },
]; ];
@ -261,12 +265,12 @@ export function PublicLandingView() {
<div className="relative mx-auto max-w-6xl grid grid-cols-1 lg:grid-cols-[1.05fr_minmax(0,0.95fr)] items-center gap-10 lg:gap-16 px-6 sm:px-10 lg:px-14"> <div className="relative mx-auto max-w-6xl grid grid-cols-1 lg:grid-cols-[1.05fr_minmax(0,0.95fr)] items-center gap-10 lg:gap-16 px-6 sm:px-10 lg:px-14">
<div className="space-y-6 text-left max-w-2xl"> <div className="space-y-6 text-left max-w-2xl">
<h1 className="text-4xl sm:text-5xl lg:text-6xl font-extrabold leading-tight text-foreground"> <h1 className="text-4xl sm:text-5xl lg:text-6xl font-extrabold leading-tight text-foreground">
<span className="block whitespace-nowrap">One Stop Solution</span> <span className="block whitespace-nowrap">A One Stop Solution</span>
<span className="block text-primary mt-2 whitespace-nowrap">for Your IT Needs</span> <span className="block text-primary mt-2 whitespace-nowrap">for Your IT Needs</span>
</h1> </h1>
<p className="text-base sm:text-lg text-muted-foreground leading-relaxed font-semibold"> <p className="text-base sm:text-lg text-muted-foreground leading-relaxed font-semibold">
Serving Japan&apos;s international community with reliable, English-supported No Japanese required. Get reliable internet, mobile, and VPN services with full
internet, mobile, and VPN solutions and many more. English support. Serving expats and international businesses for over 20 years.
</p> </p>
<div className="flex flex-col sm:flex-row items-start sm:items-center gap-3 sm:gap-4 pt-2"> <div className="flex flex-col sm:flex-row items-start sm:items-center gap-3 sm:gap-4 pt-2">
<Link <Link
@ -314,18 +318,36 @@ export function PublicLandingView() {
</div> </div>
{/* Services Grid - Fixed height for consistent sizing */} {/* Services Grid - Fixed height for consistent sizing */}
<div className="grid grid-cols-2 gap-4 min-h-[340px] content-start"> <div className="grid grid-cols-2 gap-3 h-[320px] content-start overflow-hidden">
{(activeCategory === "personal" ? personalServices : businessServices).map( {(activeCategory === "personal" ? personalServices : businessServices).map(
service => ( service => (
<Link <Link
key={service.title} key={service.title}
href={service.href} href={service.href}
className="group flex flex-col items-center gap-3 p-4 rounded-xl hover:bg-gray-50 transition-colors h-[100px]" className={`group flex flex-col items-center justify-center gap-2 p-3 rounded-xl hover:bg-gray-50 transition-colors ${
activeCategory === "personal" ? "h-[152px]" : "h-[100px]"
}`}
> >
<div className="w-16 h-16 rounded-full border-2 border-primary/30 flex items-center justify-center group-hover:border-primary/60 transition-colors flex-shrink-0"> <div
{service.icon} className={`rounded-full border-2 border-primary/30 flex items-center justify-center group-hover:border-primary/60 transition-colors flex-shrink-0 ${
activeCategory === "personal" ? "w-20 h-20" : "w-14 h-14"
}`}
>
<div
className={
activeCategory === "personal"
? "[&>svg]:h-10 [&>svg]:w-10"
: "[&>svg]:h-7 [&>svg]:w-7"
}
>
{service.icon}
</div>
</div> </div>
<span className="text-sm font-semibold text-foreground text-center leading-tight"> <span
className={`font-semibold text-foreground text-center leading-tight ${
activeCategory === "personal" ? "text-sm" : "text-xs"
}`}
>
{service.title} {service.title}
</span> </span>
</Link> </Link>
@ -351,17 +373,21 @@ export function PublicLandingView() {
</div> </div>
<div className="space-y-6"> <div className="space-y-6">
<div> <div>
<p className="text-2xl sm:text-3xl font-extrabold text-primary uppercase tracking-wide mb-3"> <h2 className="text-2xl sm:text-3xl font-extrabold text-primary uppercase tracking-wide mb-3">
Built on Trust and Excellence Built on Trust and Excellence
</h2>
<p className="text-xl sm:text-2xl font-semibold text-foreground leading-relaxed">
For over two decades, we&apos;ve been helping foreigners, expats, and international
businesses in Japan navigate the tech landscape with confidence.
</p> </p>
<h3 className="text-xl sm:text-2xl font-semibold text-foreground leading-relaxed">
For over two decades, we&apos;ve been helping expats & businesses navigate complex
technological challenges with confidence.
</h3>
</div> </div>
<ul className="space-y-3 text-foreground"> <ul className="space-y-3 text-foreground">
{["One Stop Solution", "English Support", "Onsite Support"].map(item => ( {[
"Full English support, no Japanese needed",
"Foreign credit cards accepted",
"Bilingual contracts and documentation",
].map(item => (
<li key={item} className="flex items-center gap-3 text-base font-semibold"> <li key={item} className="flex items-center gap-3 text-base font-semibold">
<BadgeCheck className="h-5 w-5 text-primary" /> <BadgeCheck className="h-5 w-5 text-primary" />
<span>{item}</span> <span>{item}</span>
@ -433,37 +459,62 @@ export function PublicLandingView() {
</section> </section>
{/* Support Downloads */} {/* Support Downloads */}
<section className="max-w-5xl mx-auto px-6 sm:px-10 lg:px-14 pb-16"> <section className="max-w-5xl mx-auto px-6 sm:px-10 lg:px-14 pt-16 pb-20">
<h3 className="text-center text-3xl sm:text-4xl font-extrabold text-primary tracking-tight mb-10"> <div className="text-center mb-12">
SUPPORT <h2 className="text-3xl sm:text-4xl font-extrabold text-primary tracking-tight mb-4">
</h3> Remote Support
<div className="grid grid-cols-1 sm:grid-cols-2 gap-8 sm:gap-10"> </h2>
<p className="text-lg text-muted-foreground max-w-2xl mx-auto leading-relaxed">
Stuck with a tech issue? Our English-speaking technicians can connect to your device
remotely and fix problems in real-time. Download one of these secure tools to get
started.
</p>
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-8 sm:gap-12">
{supportDownloads.map(item => ( {supportDownloads.map(item => (
<div <div key={item.title} className="flex flex-col items-center text-center">
key={item.title} <div className="h-20 w-20 rounded-2xl flex items-center justify-center bg-gradient-to-br from-primary/10 to-sky-100 mb-5">
className="flex flex-col items-center gap-4 rounded-2xl bg-white p-6"
>
<div className="text-center space-y-2">
<p className="text-lg font-semibold text-foreground leading-snug">{item.title}</p>
</div>
<div className="h-24 w-24 rounded-full flex items-center justify-center bg-primary/5 shadow-sm">
<Image <Image
src={item.image} src={item.image}
alt={item.title} alt={item.title}
width={64} width={56}
height={64} height={56}
className="object-contain" className="object-contain"
/> />
</div> </div>
<p className="text-xl font-bold text-foreground mb-1">{item.title}</p>
<p className="text-sm font-medium text-primary mb-3">{item.useCase}</p>
<p className="text-sm text-muted-foreground mb-5 leading-relaxed max-w-xs">
{item.description}
</p>
<Link <Link
href={item.href} href={item.href}
className="inline-flex items-center gap-2 rounded-md bg-primary px-4 py-2 text-sm font-semibold text-primary-foreground hover:bg-primary/90 transition-colors shadow-sm" target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-2 rounded-full bg-primary px-6 py-2.5 text-sm font-semibold text-primary-foreground hover:bg-primary/90 transition-colors shadow-sm hover:shadow-md"
> >
Download <ArrowRight className="h-4 w-4" /> Download <ArrowRight className="h-4 w-4" />
</Link> </Link>
</div> </div>
))} ))}
</div> </div>
<div className="mt-12 text-center">
<p className="text-sm text-muted-foreground leading-relaxed">
After downloading, run the application and share the session ID with our support team.
</p>
<p className="mt-2 text-sm font-medium text-foreground">
Contact us at{" "}
<a href="mailto:info@asolutions.co.jp" className="text-primary hover:underline">
info@asolutions.co.jp
</a>{" "}
or call{" "}
<a href="tel:0120-660-470" className="text-primary hover:underline">
0120-660-470
</a>
</p>
</div>
</section> </section>
{/* Contact Section */} {/* Contact Section */}

View File

@ -6,7 +6,6 @@ import {
Wifi, Wifi,
Smartphone, Smartphone,
Building2, Building2,
Tv,
Lock, Lock,
Wrench, Wrench,
Heart, Heart,
@ -26,27 +25,27 @@ import {
export function AboutUsView() { export function AboutUsView() {
const values = [ const values = [
{ {
text: "Provide the most customer-oriented service in this industry in Japan.", text: "Make technology accessible for everyone, regardless of language barriers.",
icon: <Heart className="h-6 w-6" />, icon: <Heart className="h-6 w-6" />,
color: "bg-rose-50 text-rose-500 border-rose-100", color: "bg-rose-50 text-rose-500 border-rose-100",
}, },
{ {
text: "Through our service, we save client's time and enrich customers' lives.", text: "Save our customers time by handling Japanese bureaucracy and paperwork for them.",
icon: <Clock3 className="h-6 w-6" />, icon: <Clock3 className="h-6 w-6" />,
color: "bg-amber-50 text-amber-500 border-amber-100", color: "bg-amber-50 text-amber-500 border-amber-100",
}, },
{ {
text: "We always have the latest and most efficient knowledge required for our service.", text: "Stay current with the latest technology to provide the best solutions for our clients.",
icon: <Lightbulb className="h-6 w-6" />, icon: <Lightbulb className="h-6 w-6" />,
color: "bg-sky-50 text-sky-500 border-sky-100", color: "bg-sky-50 text-sky-500 border-sky-100",
}, },
{ {
text: "Be a responsible participant in Japan's international community.", text: "Be a bridge between Japan's tech infrastructure and its international community.",
icon: <Globe className="h-6 w-6" />, icon: <Globe className="h-6 w-6" />,
color: "bg-emerald-50 text-emerald-500 border-emerald-100", color: "bg-emerald-50 text-emerald-500 border-emerald-100",
}, },
{ {
text: "Maintain high ethical standards in all business activities.", text: "Operate with transparency and integrity in all our customer relationships.",
icon: <Shield className="h-6 w-6" />, icon: <Shield className="h-6 w-6" />,
color: "bg-violet-50 text-violet-500 border-violet-100", color: "bg-violet-50 text-violet-500 border-violet-100",
}, },
@ -56,33 +55,29 @@ export function AboutUsView() {
{ {
title: "Internet Plans", title: "Internet Plans",
description: description:
"Utilizing NTT's optical fiber network, we deliver one of the most reliable Internet connections in Japan.", "High-speed NTT fiber with English support. We handle the Japanese paperwork so you don't have to.",
icon: <Wifi className="h-7 w-7 text-primary" />, icon: <Wifi className="h-7 w-7 text-primary" />,
}, },
{ {
title: "Phone Plans", title: "Phone Plans",
description: description:
"Using NTT DOCOMO's network, we deliver cost-friendly SIM card services across Japan.", "SIM cards on Japan's best network. Foreign credit cards accepted, no hanko required.",
icon: <Smartphone className="h-7 w-7 text-primary" />, icon: <Smartphone className="h-7 w-7 text-primary" />,
}, },
{ {
title: "Business Solutions", title: "Business Solutions",
description: "Dedicated Internet access, office network setup, data center services.", description:
"Enterprise IT for international companies. Dedicated internet, office networks, and data centers.",
icon: <Building2 className="h-7 w-7 text-primary" />, icon: <Building2 className="h-7 w-7 text-primary" />,
}, },
{ {
title: "VPN", title: "VPN",
description: "Connect directly from Tokyo with static routing across global endpoints.", description: "Stream your favorite shows from home. Pre-configured router for US/UK content.",
icon: <Lock className="h-7 w-7 text-primary" />, icon: <Lock className="h-7 w-7 text-primary" />,
}, },
{
title: "TV Services",
description: "Options for Satellite TV and Optical Fiber TV tailored to your needs.",
icon: <Tv className="h-7 w-7 text-primary" />,
},
{ {
title: "Onsite Support", title: "Onsite Support",
description: "Professional setup, configuration, and troubleshooting at your location.", description: "English-speaking technicians at your door for setup and troubleshooting.",
icon: <Wrench className="h-7 w-7 text-primary" />, icon: <Wrench className="h-7 w-7 text-primary" />,
}, },
]; ];
@ -141,14 +136,14 @@ export function AboutUsView() {
</h1> </h1>
<div className="space-y-4 text-muted-foreground leading-relaxed text-base sm:text-lg"> <div className="space-y-4 text-muted-foreground leading-relaxed text-base sm:text-lg">
<p> <p>
Assist Solutions Corp. is a privately-owned entrepreneurial IT service company. We Since 2002, Assist Solutions has been the trusted IT partner for expats and
specialize in serving Japan&apos;s international community with the most reliable international businesses in Japan. We understand the unique challenges of living
and cost-efficient IT & TV solutions available. and working in a country where language barriers can make simple tasks difficult.
</p> </p>
<p> <p>
We are dedicated to providing comfortable support for our customer&apos;s diverse Our bilingual team provides internet, mobile, VPN, and tech support services with
needs in both English and Japanese. Our excellent bi-lingual support, flexible full English support. No Japanese required. We handle everything from contracts to
service, and deep industry knowledge set us apart. installation coordination, so you can focus on enjoying life in Japan.
</p> </p>
</div> </div>
</div> </div>

View File

@ -1,5 +1,5 @@
import Link from "next/link"; import Link from "next/link";
import { Building2, Wrench, Tv, ArrowRight, Wifi, Smartphone, Lock } from "lucide-react"; import { Building2, Wrench, ArrowRight, Wifi, Smartphone, Lock } from "lucide-react";
interface ServicesGridProps { interface ServicesGridProps {
basePath?: string; basePath?: string;
@ -18,8 +18,8 @@ export function ServicesGrid({ basePath = "/services" }: ServicesGridProps) {
Internet Internet
</h2> </h2>
<p className="text-muted-foreground mb-6 flex-grow"> <p className="text-muted-foreground mb-6 flex-grow">
NTT fiber with speeds up to 10Gbps and professional installation support. Fast and High-speed NTT fiber up to 10Gbps with English installation support. We handle the
reliable connectivity. Japanese paperwork so you don&apos;t have to.
</p> </p>
<div className="flex items-center text-blue-600 font-medium mt-auto"> <div className="flex items-center text-blue-600 font-medium mt-auto">
View Plans{" "} View Plans{" "}
@ -38,8 +38,8 @@ export function ServicesGrid({ basePath = "/services" }: ServicesGridProps) {
SIM & eSIM SIM & eSIM
</h2> </h2>
<p className="text-muted-foreground mb-6 flex-grow"> <p className="text-muted-foreground mb-6 flex-grow">
Data, voice & SMS on NTT Docomo's nationwide network. Available as physical SIM or Japan&apos;s best network coverage. Foreign credit cards accepted, no hanko required.
instant eSIM. Physical SIM or instant eSIM available.
</p> </p>
<div className="flex items-center text-green-600 font-medium mt-auto"> <div className="flex items-center text-green-600 font-medium mt-auto">
View Plans{" "} View Plans{" "}
@ -58,8 +58,8 @@ export function ServicesGrid({ basePath = "/services" }: ServicesGridProps) {
VPN VPN
</h2> </h2>
<p className="text-muted-foreground mb-6 flex-grow"> <p className="text-muted-foreground mb-6 flex-grow">
Access US/UK content with a pre-configured router. Easy plug & play setup for seamless Watch your favorite shows from home. Pre-configured router, just plug in and stream
streaming. US/UK content from Japan.
</p> </p>
<div className="flex items-center text-purple-600 font-medium mt-auto"> <div className="flex items-center text-purple-600 font-medium mt-auto">
View Plans{" "} View Plans{" "}
@ -78,8 +78,8 @@ export function ServicesGrid({ basePath = "/services" }: ServicesGridProps) {
Business Solutions Business Solutions
</h2> </h2>
<p className="text-muted-foreground mb-6 flex-grow"> <p className="text-muted-foreground mb-6 flex-grow">
Dedicated Internet Access (DIA), Office LAN setup, Data Center services, and Enterprise IT for international companies in Japan. Dedicated internet, office networks,
onsite/remote tech support. and bilingual tech support.
</p> </p>
<div className="flex items-center text-primary font-medium mt-auto"> <div className="flex items-center text-primary font-medium mt-auto">
Learn more{" "} Learn more{" "}
@ -98,28 +98,8 @@ export function ServicesGrid({ basePath = "/services" }: ServicesGridProps) {
Onsite Support Onsite Support
</h2> </h2>
<p className="text-muted-foreground mb-6 flex-grow"> <p className="text-muted-foreground mb-6 flex-grow">
Professional technical support at your residence or office. Network setup, device English-speaking technicians at your home or office. Network setup, device help, and
configuration, and troubleshooting. troubleshooting, explained in a language you understand.
</p>
<div className="flex items-center text-primary font-medium mt-auto">
Learn more{" "}
<ArrowRight className="h-4 w-4 ml-2 group-hover:translate-x-1 transition-transform" />
</div>
</div>
</Link>
{/* TV Services */}
<Link href="/services/tv" className="group block h-full">
<div className="h-full bg-card rounded-2xl border border-border/60 p-8 shadow-sm transition-all duration-300 hover:shadow-md hover:border-primary/50 flex flex-col">
<div className="h-14 w-14 rounded-2xl bg-primary/10 flex items-center justify-center text-primary mb-6 group-hover:scale-110 transition-transform">
<Tv className="h-7 w-7" />
</div>
<h2 className="text-2xl font-bold text-foreground mb-3 group-hover:text-primary transition-colors">
TV Services
</h2>
<p className="text-muted-foreground mb-6 flex-grow">
Satellite, Cable, and Optical Fiber TV services. We arrange subscriptions for major
Japanese TV providers.
</p> </p>
<div className="flex items-center text-primary font-medium mt-auto"> <div className="flex items-center text-primary font-medium mt-auto">
Learn more{" "} Learn more{" "}

View File

@ -165,35 +165,35 @@ export function SimPlansContent({
const hasExistingSim = useMemo(() => simPlans.some(p => p.simHasFamilyDiscount), [simPlans]); const hasExistingSim = useMemo(() => simPlans.some(p => p.simHasFamilyDiscount), [simPlans]);
const simFeatures: HighlightFeature[] = [ const simFeatures: HighlightFeature[] = [
{
icon: <CreditCard className="h-6 w-6" />,
title: "Foreign Cards Accepted",
description: "Use your overseas credit card. No Japanese bank account needed",
highlight: "Easy payment",
},
{ {
icon: <Signal className="h-6 w-6" />, icon: <Signal className="h-6 w-6" />,
title: "NTT Docomo Network", title: "Japan's Best Network",
description: "Best area coverage among the main three carriers in Japan", description: "NTT Docomo coverage reaches 99.9% of Japan's population",
highlight: "Nationwide coverage", highlight: "Nationwide",
}, },
{ {
icon: <CircleDollarSign className="h-6 w-6" />, icon: <CircleDollarSign className="h-6 w-6" />,
title: "First Month Free", title: "First Month Free",
description: "Basic fee waived on signup to get you started risk-free", description: "Try risk-free. Your first month's basic fee is waived",
highlight: "Great value", highlight: "Great value",
}, },
{
icon: <CreditCard className="h-6 w-6" />,
title: "Foreign Cards Accepted",
description: "We accept both foreign and Japanese credit cards",
highlight: "No hassle",
},
{ {
icon: <Calendar className="h-6 w-6" />, icon: <Calendar className="h-6 w-6" />,
title: "No Binding Contract", title: "Flexible Terms",
description: "Minimum 4 months service (1st month free + 3 billing months)", description: "No multi-year contracts. Stay as long as you need",
highlight: "Flexible contract", highlight: "No lock-in",
}, },
{ {
icon: <ArrowRightLeft className="h-6 w-6" />, icon: <ArrowRightLeft className="h-6 w-6" />,
title: "Number Portability", title: "Keep Your Number",
description: "Easily switch to us keeping your current Japanese number", description: "Switching from another carrier? Bring your Japanese number with you",
highlight: "Keep your number", highlight: "Easy transfer",
}, },
{ {
icon: <Smartphone className="h-6 w-6" />, icon: <Smartphone className="h-6 w-6" />,
@ -288,11 +288,11 @@ export function SimPlansContent({
<span className="text-sm font-medium text-primary">Powered by NTT DOCOMO</span> <span className="text-sm font-medium text-primary">Powered by NTT DOCOMO</span>
</div> </div>
<h1 className="text-3xl md:text-4xl font-bold text-foreground mb-4"> <h1 className="text-3xl md:text-4xl font-bold text-foreground mb-4">
Choose Your SIM Plan SIM Cards for Foreigners in Japan
</h1> </h1>
<p className="text-lg text-muted-foreground max-w-2xl mx-auto"> <p className="text-lg text-muted-foreground max-w-2xl mx-auto">
Get connected with Japan&apos;s best network coverage. Choose eSIM for quick digital No hanko, no complicated Japanese forms. Get a SIM card with your foreign credit card and
delivery or physical SIM shipped to your door. English support. eSIM for instant delivery or physical SIM shipped to your door.
</p> </p>
</div> </div>
@ -399,6 +399,9 @@ export function SimPlansContent({
)} )}
</div> </div>
{/* Device Compatibility Section - below plans */}
<DeviceCompatibility />
{/* How It Works Section */} {/* How It Works Section */}
<div className="mt-12"> <div className="mt-12">
<SimHowItWorksSection /> <SimHowItWorksSection />
@ -614,9 +617,6 @@ export function SimPlansContent({
</CollapsibleSection> </CollapsibleSection>
</div> </div>
{/* Device Compatibility Section */}
<DeviceCompatibility />
{/* FAQ Section */} {/* FAQ Section */}
<div className="mt-12 mb-8"> <div className="mt-12 mb-8">
<h2 className="text-2xl font-bold text-foreground mb-6 text-center"> <h2 className="text-2xl font-bold text-foreground mb-6 text-center">

View File

@ -11,6 +11,9 @@ import {
Wrench, Wrench,
Globe, Globe,
ChevronDown, ChevronDown,
ChevronUp,
Home,
Building,
} from "lucide-react"; } from "lucide-react";
import { usePublicInternetCatalog } from "@/features/services/hooks"; import { usePublicInternetCatalog } from "@/features/services/hooks";
import type { import type {
@ -204,6 +207,351 @@ function ConsolidatedInternetCard({
); );
} }
/**
* Offering type configuration for expandable plan cards
*/
interface OfferingTypeConfig {
id: string;
title: string;
badge: string;
badgeColor: string;
description: string;
icon: React.ReactNode;
}
const offeringTypeConfigs: OfferingTypeConfig[] = [
{
id: "home10g",
title: "Home 10Gbps",
badge: "10Gbps",
badgeColor: "bg-primary text-white",
description: "Ultra-fast fiber with the highest speeds available in Japan.",
icon: <Home className="h-5 w-5 text-muted-foreground" />,
},
{
id: "home1g",
title: "Home 1Gbps",
badge: "1Gbps",
badgeColor: "bg-gray-200 text-gray-700",
description: "High-speed fiber. The most popular choice for home internet.",
icon: <Home className="h-5 w-5 text-muted-foreground" />,
},
{
id: "apartment",
title: "Apartment",
badge: "Up to 1Gbps",
badgeColor: "bg-gray-200 text-gray-700",
description:
"For mansions and apartment buildings. Speed depends on your building (up to 1Gbps).",
icon: <Building className="h-5 w-5 text-muted-foreground" />,
},
];
/**
* Get offering type ID from plan's internetOfferingType field
*/
function getOfferingTypeId(offeringType: string | undefined): string {
if (!offeringType) return "home1g";
const type = offeringType.toLowerCase();
if (type.includes("10g") || type.includes("10gbps")) return "home10g";
if (type.includes("apartment") || type.includes("mansion")) return "apartment";
if (type.includes("1g") || type.includes("1gbps") || type.includes("home")) return "home1g";
return "home1g";
}
/**
* Plan Card Header - Compact horizontal card for offering type
*/
function PlanCardHeader({
config,
minPrice,
isExpanded,
onToggle,
}: {
config: OfferingTypeConfig;
minPrice: number;
isExpanded: boolean;
onToggle: () => void;
}) {
return (
<div
className={cn(
"rounded-xl border-2 shadow-sm overflow-hidden h-full flex flex-col transition-all duration-200",
isExpanded
? "border-primary bg-primary/5 shadow-md ring-1 ring-primary/20"
: "border-border bg-card hover:border-primary/40"
)}
>
{/* Header - Clickable to expand/collapse */}
<button
type="button"
onClick={onToggle}
className="w-full p-4 flex flex-col gap-3 hover:bg-muted/30 transition-colors text-left flex-grow"
>
<div className="flex items-start justify-between gap-2">
<div
className={cn(
"flex h-10 w-10 items-center justify-center rounded-xl flex-shrink-0 transition-colors",
isExpanded ? "bg-primary/10" : "bg-muted/50"
)}
>
{config.icon}
</div>
<div
className={cn(
"flex items-center gap-1 transition-colors",
isExpanded ? "text-primary" : "text-muted-foreground"
)}
>
<span className="text-xs font-medium">{isExpanded ? "Hide tiers" : "Show tiers"}</span>
{isExpanded ? <ChevronUp className="h-4 w-4" /> : <ChevronDown className="h-4 w-4" />}
</div>
</div>
<div>
<div className="flex items-center gap-2 flex-wrap mb-1">
<h3
className={cn(
"text-base font-bold transition-colors",
isExpanded ? "text-primary" : "text-foreground"
)}
>
{config.title}
</h3>
<span
className={cn("text-xs font-semibold px-2 py-0.5 rounded-full", config.badgeColor)}
>
{config.badge}
</span>
</div>
{config.id === "home10g" && (
<span className="text-xs text-muted-foreground">(select areas)</span>
)}
<p className="text-sm text-muted-foreground mt-1">{config.description}</p>
<p className="text-sm text-muted-foreground mt-2">
From{" "}
<span className="font-bold text-foreground text-lg">¥{minPrice.toLocaleString()}</span>{" "}
/mo
</p>
</div>
</button>
</div>
);
}
/**
* Expanded Tier Details - Shows tier cards below the header cards
*/
function ExpandedTierDetails({
config,
tiers,
setupFee,
ctaPath,
ctaLabel,
onCtaClick,
}: {
config: OfferingTypeConfig;
tiers: TierInfo[];
setupFee: number;
ctaPath: string;
ctaLabel: string;
onCtaClick?: (e: React.MouseEvent) => void;
}) {
return (
<div className="rounded-xl border border-border bg-card shadow-sm overflow-hidden">
{/* Header */}
<div className="px-5 py-4 border-b border-border bg-muted/20">
<div className="flex items-center gap-3">
<div className="flex h-10 w-10 items-center justify-center rounded-xl bg-muted/50">
{config.icon}
</div>
<div>
<div className="flex items-center gap-2 flex-wrap">
<h3 className="text-lg font-bold text-foreground">{config.title}</h3>
<span
className={cn("text-xs font-semibold px-2 py-0.5 rounded-full", config.badgeColor)}
>
{config.badge}
</span>
{config.id === "home10g" && (
<span className="text-xs text-muted-foreground">(select areas)</span>
)}
</div>
</div>
</div>
</div>
{/* Tier Cards */}
<div className="p-5">
<div className="grid grid-cols-1 sm:grid-cols-3 gap-4">
{tiers.map(tier => (
<div
key={tier.tier}
className={cn(
"rounded-xl border p-4 transition-all duration-200 flex flex-col relative bg-white",
tierStyles[tier.tier].card
)}
>
{/* Popular Badge for Gold */}
{tier.tier === "Gold" && (
<div className="absolute -top-3 left-1/2 -translate-x-1/2">
<span className="inline-flex items-center gap-1 px-3 py-1 rounded-full bg-amber-500 text-white text-xs font-semibold shadow-sm">
<Sparkles className="h-3 w-3" />
Popular
</span>
</div>
)}
{/* Tier Name */}
<h4
className={cn(
"font-bold text-lg mb-2",
tier.tier === "Gold" ? "mt-2" : "",
tierStyles[tier.tier].accent
)}
>
{tier.tier}
</h4>
{/* Price */}
<div className="mb-3">
<div className="flex items-baseline gap-0.5 flex-wrap">
<span className="text-2xl font-bold text-foreground">
¥{tier.monthlyPrice.toLocaleString()}
</span>
<span className="text-sm text-muted-foreground">/mo</span>
</div>
{tier.pricingNote && (
<span
className={`text-xs ${tier.tier === "Platinum" ? "text-primary" : "text-amber-600"}`}
>
{tier.pricingNote}
</span>
)}
</div>
{/* Description */}
<p className="text-sm text-muted-foreground mb-3">{tier.description}</p>
{/* Features */}
<ul className="space-y-2 flex-grow">
{tier.features.map((feature, index) => (
<li key={index} className="flex items-start gap-2 text-sm">
<svg
className="h-4 w-4 text-green-500 flex-shrink-0 mt-0.5"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fillRule="evenodd"
d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
clipRule="evenodd"
/>
</svg>
<span className="text-muted-foreground">{feature}</span>
</li>
))}
</ul>
</div>
))}
</div>
{/* Footer with setup fee and CTA */}
<div className="flex flex-col sm:flex-row items-stretch sm:items-center justify-between gap-4 pt-5 mt-5 border-t border-border">
<p className="text-sm text-muted-foreground">
<span className="font-semibold text-foreground">
+ ¥{setupFee.toLocaleString()} one-time setup
</span>{" "}
(or 12/24-month installment)
</p>
{onCtaClick ? (
<Button onClick={onCtaClick} size="lg" className="whitespace-nowrap">
{ctaLabel}
</Button>
) : (
<Button as="a" href={ctaPath} size="lg" className="whitespace-nowrap">
{ctaLabel}
</Button>
)}
</div>
</div>
</div>
);
}
/**
* Available Plans Section - Horizontal cards for each offering type with expandable details
*/
function AvailablePlansSection({
plansByOffering,
setupFee,
ctaPath,
ctaLabel,
onCtaClick,
}: {
plansByOffering: Record<string, { minPrice: number; tiers: TierInfo[] }>;
setupFee: number;
ctaPath: string;
ctaLabel: string;
onCtaClick?: (e: React.MouseEvent) => void;
}) {
const [expandedCards, setExpandedCards] = useState<Record<string, boolean>>({
home10g: false,
home1g: false,
apartment: false,
});
const toggleCard = (id: string) => {
setExpandedCards(prev => ({ ...prev, [id]: !prev[id] }));
};
// Get configs that have data
const availableConfigs = offeringTypeConfigs.filter(config => plansByOffering[config.id]);
return (
<section className="space-y-6 mt-8">
<h2 className="text-2xl font-bold text-foreground text-center">Available Plans</h2>
{/* Horizontal card headers */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
{availableConfigs.map(config => {
const offeringData = plansByOffering[config.id];
if (!offeringData) return null;
return (
<PlanCardHeader
key={config.id}
config={config}
minPrice={offeringData.minPrice}
isExpanded={expandedCards[config.id] ?? false}
onToggle={() => toggleCard(config.id)}
/>
);
})}
</div>
{/* Expanded tier details - shown below the horizontal cards */}
<div className="space-y-4">
{availableConfigs.map(config => {
const offeringData = plansByOffering[config.id];
if (!offeringData || !expandedCards[config.id]) return null;
return (
<ExpandedTierDetails
key={config.id}
config={config}
tiers={offeringData.tiers}
setupFee={setupFee}
ctaPath={ctaPath}
ctaLabel={ctaLabel}
onCtaClick={onCtaClick}
/>
);
})}
</div>
</section>
);
}
export interface PublicInternetPlansContentProps { export interface PublicInternetPlansContentProps {
onCtaClick?: (e: React.MouseEvent) => void; onCtaClick?: (e: React.MouseEvent) => void;
ctaPath?: string; ctaPath?: string;
@ -219,8 +567,8 @@ export function PublicInternetPlansContent({
onCtaClick, onCtaClick,
ctaPath: propCtaPath, ctaPath: propCtaPath,
ctaLabel = "Check Availability", ctaLabel = "Check Availability",
heroTitle = "Internet Service Plans", heroTitle = "Internet for Expats in Japan",
heroDescription = "NTT Optical Fiber with full English support", heroDescription = "Fast, reliable fiber internet with full English support. No Japanese required",
}: PublicInternetPlansContentProps) { }: PublicInternetPlansContentProps) {
const { data: servicesCatalog, error } = usePublicInternetCatalog(); const { data: servicesCatalog, error } = usePublicInternetCatalog();
// Simple loading check: show skeleton until we have data or an error // Simple loading check: show skeleton until we have data or an error
@ -236,35 +584,35 @@ export function PublicInternetPlansContent({
description: "Japan's most reliable network with speeds up to 10Gbps", description: "Japan's most reliable network with speeds up to 10Gbps",
highlight: "99.9% uptime", highlight: "99.9% uptime",
}, },
{
icon: <Zap className="h-6 w-6" />,
title: "IPv6/IPoE Ready",
description: "Next-gen protocol for congestion-free browsing",
highlight: "No peak-hour slowdowns",
},
{ {
icon: <Languages className="h-6 w-6" />, icon: <Languages className="h-6 w-6" />,
title: "Full English Support", title: "No Japanese Required",
description: "Native English service for setup, billing & technical help", description: "English contracts, English support, English installation coordination",
highlight: "No language barriers", highlight: "Fully bilingual",
}, },
{ {
icon: <FileText className="h-6 w-6" />, icon: <FileText className="h-6 w-6" />,
title: "One Bill, One Provider", title: "We Handle the Paperwork",
description: "NTT line + ISP + equipment bundled with simple billing", description: "No need to navigate Japanese forms or phone calls",
highlight: "No hidden fees", highlight: "Hassle-free setup",
},
{
icon: <Zap className="h-6 w-6" />,
title: "IPv6/IPoE Ready",
description: "Next-gen protocol for congestion-free browsing",
highlight: "No slowdowns",
}, },
{ {
icon: <Wrench className="h-6 w-6" />, icon: <Wrench className="h-6 w-6" />,
title: "On-site Support", title: "English Onsite Support",
description: "Technicians can visit for installation & troubleshooting", description: "Our technicians speak English and can visit your home",
highlight: "Professional setup", highlight: "In-person help",
}, },
{ {
icon: <Globe className="h-6 w-6" />, icon: <Globe className="h-6 w-6" />,
title: "Flexible Options", title: "Flexible Contracts",
description: "Multiple ISP configs available, IPv4/PPPoE if needed", description: "Monthly billing, no long-term commitment required",
highlight: "Customizable", highlight: "Cancel anytime",
}, },
]; ];
@ -321,6 +669,103 @@ export function PublicInternetPlansContent({
}; };
}, [servicesCatalog]); }, [servicesCatalog]);
// Plans grouped by offering type (Home 10G, Home 1G, Apartment)
const plansByOffering = useMemo(() => {
// Default pricing for each offering type (used when catalog doesn't have specific data)
const defaultOfferingPrices: Record<
string,
{ silver: number; gold: number; platinum: number }
> = {
home10g: { silver: 8000, gold: 8500, platinum: 8500 },
home1g: { silver: 6000, gold: 6500, platinum: 6500 },
apartment: { silver: 4800, gold: 5300, platinum: 5300 },
};
const tierOrder: Record<string, number> = { Silver: 0, Gold: 1, Platinum: 2 };
const offeringData: Record<
string,
{
minPrice: number;
tierData: Record<string, { price: number; plan?: InternetPlanCatalogItem }>;
}
> = {};
// Process catalog plans if available
if (servicesCatalog?.plans) {
for (const plan of servicesCatalog.plans) {
const offeringType = getOfferingTypeId(plan.internetOfferingType);
const tier = plan.internetPlanTier ?? "Silver";
const price = plan.monthlyPrice ?? 0;
if (!offeringData[offeringType]) {
offeringData[offeringType] = { minPrice: Infinity, tierData: {} };
}
offeringData[offeringType].minPrice = Math.min(offeringData[offeringType].minPrice, price);
// Keep the price for this tier (use lowest if multiple plans for same tier)
if (
!offeringData[offeringType].tierData[tier] ||
price < offeringData[offeringType].tierData[tier].price
) {
offeringData[offeringType].tierData[tier] = { price, plan };
}
}
}
// Ensure all three offering types exist with default data
for (const config of offeringTypeConfigs) {
if (!offeringData[config.id]) {
const defaults = defaultOfferingPrices[config.id];
offeringData[config.id] = {
minPrice: defaults.silver,
tierData: {
Silver: { price: defaults.silver },
Gold: { price: defaults.gold },
Platinum: { price: defaults.platinum },
},
};
} else {
// Fill in missing tiers with defaults
const defaults = defaultOfferingPrices[config.id];
if (!offeringData[config.id].tierData.Silver) {
offeringData[config.id].tierData.Silver = { price: defaults.silver };
}
if (!offeringData[config.id].tierData.Gold) {
offeringData[config.id].tierData.Gold = { price: defaults.gold };
}
if (!offeringData[config.id].tierData.Platinum) {
offeringData[config.id].tierData.Platinum = { price: defaults.platinum };
}
// Recalculate min price
const allPrices = Object.values(offeringData[config.id].tierData).map(t => t.price);
offeringData[config.id].minPrice = Math.min(...allPrices);
}
}
// Convert to the format expected by AvailablePlansSection
const result: Record<string, { minPrice: number; tiers: TierInfo[] }> = {};
for (const [offeringType, data] of Object.entries(offeringData)) {
const tiers: TierInfo[] = Object.entries(data.tierData)
.sort(([a], [b]) => (tierOrder[a] ?? 99) - (tierOrder[b] ?? 99))
.map(([tier, tierInfo]) => ({
tier: tier as TierInfo["tier"],
monthlyPrice: tierInfo.price,
description: getTierDescription(tier),
features: getTierFeatures(tier),
pricingNote: tier === "Platinum" ? "+ equipment fees" : undefined,
}));
result[offeringType] = {
minPrice: data.minPrice,
tiers,
};
}
return result;
}, [servicesCatalog]);
// Error state // Error state
if (error) { if (error) {
return ( return (
@ -366,6 +811,17 @@ export function PublicInternetPlansContent({
) : null} ) : null}
</section> </section>
{/* Available Plans - Expandable cards by offering type */}
{!isLoading && plansByOffering && consolidatedPlanData && (
<AvailablePlansSection
plansByOffering={plansByOffering}
setupFee={consolidatedPlanData.setupFee}
ctaPath={ctaPath}
ctaLabel={ctaLabel}
onCtaClick={onCtaClick}
/>
)}
{/* How It Works Section */} {/* How It Works Section */}
<HowItWorksSection /> <HowItWorksSection />

View File

@ -61,39 +61,39 @@ export function PublicVpnPlansView() {
const vpnFeatures: HighlightFeature[] = [ const vpnFeatures: HighlightFeature[] = [
{ {
icon: <Router className="h-6 w-6" />, icon: <Router className="h-6 w-6" />,
title: "Pre-configured Router", title: "Zero Setup Required",
description: "Ready to use out of the box — just plug in and connect", description: "Router arrives pre-configured. Just plug in and you're connected",
highlight: "Plug & play", highlight: "Plug & play",
}, },
{
icon: <Tv className="h-6 w-6" />,
title: "Stream from Home",
description: "Watch Netflix, Hulu, BBC iPlayer and more from the US or UK",
highlight: "Your content",
},
{ {
icon: <Globe className="h-6 w-6" />, icon: <Globe className="h-6 w-6" />,
title: "US & UK Servers", title: "US & UK Servers",
description: "Access content from San Francisco or London regions", description: "Choose San Francisco for US content or London for UK content",
highlight: "2 locations", highlight: "2 regions",
},
{
icon: <Tv className="h-6 w-6" />,
title: "Streaming Ready",
description: "Works with Apple TV, Roku, Amazon Fire, and more",
highlight: "All devices",
}, },
{ {
icon: <Wifi className="h-6 w-6" />, icon: <Wifi className="h-6 w-6" />,
title: "Separate Network", title: "Dedicated VPN WiFi",
description: "VPN runs on dedicated WiFi, keep regular internet normal", description: "Separate network for VPN. Your regular internet stays fast",
highlight: "No interference", highlight: "No slowdown",
}, },
{ {
icon: <Package className="h-6 w-6" />, icon: <Package className="h-6 w-6" />,
title: "Router Rental Included", title: "All-Inclusive Rental",
description: "No equipment purchase — router rental is part of the plan", description: "Router rental included in your monthly fee. Nothing extra to buy",
highlight: "No hidden costs", highlight: "Simple pricing",
}, },
{ {
icon: <Headphones className="h-6 w-6" />, icon: <Headphones className="h-6 w-6" />,
title: "English Support", title: "English Support",
description: "Full English assistance for setup and troubleshooting", description: "Questions? Our English-speaking team is here to help",
highlight: "Dedicated help", highlight: "We speak your language",
}, },
]; ];
@ -102,8 +102,8 @@ export function PublicVpnPlansView() {
<ServicesBackLink href={servicesBasePath} label="Back to Services" /> <ServicesBackLink href={servicesBasePath} label="Back to Services" />
<ServicesHero <ServicesHero
title="VPN Router Service" title="Stream Your Favorites from Home"
description="Secure VPN connections to San Francisco or London using a pre-configured router." description="Missing shows from back home? Our VPN lets you watch US and UK content in Japan. Pre-configured router, just plug in and stream."
/> />
{/* Service Highlights */} {/* Service Highlights */}

View File

@ -122,10 +122,11 @@ export function PublicContactView() {
<HelpCircle className="h-8 w-8" /> <HelpCircle className="h-8 w-8" />
</div> </div>
<h1 className="text-4xl sm:text-5xl font-extrabold text-foreground mb-4 tracking-tight"> <h1 className="text-4xl sm:text-5xl font-extrabold text-foreground mb-4 tracking-tight">
Support & Contact We Speak Your Language
</h1> </h1>
<p className="text-lg text-muted-foreground max-w-2xl mx-auto leading-relaxed"> <p className="text-lg text-muted-foreground max-w-2xl mx-auto leading-relaxed">
Have a question? We&apos;re here to help. Reach out through any channel below. Have a question about our services? Our English-speaking team is here to help. No Japanese
required. Reach out through any channel below.
</p> </p>
</div> </div>

View File

@ -37,9 +37,10 @@ export function PublicSupportView() {
<div className="inline-flex items-center justify-center w-16 h-16 bg-primary/10 rounded-2xl mb-2 text-primary"> <div className="inline-flex items-center justify-center w-16 h-16 bg-primary/10 rounded-2xl mb-2 text-primary">
<HelpCircle className="h-8 w-8" /> <HelpCircle className="h-8 w-8" />
</div> </div>
<h1 className="text-3xl font-bold text-foreground">How can we help?</h1> <h1 className="text-3xl font-bold text-foreground">How Can We Help?</h1>
<p className="text-lg text-muted-foreground max-w-2xl mx-auto"> <p className="text-lg text-muted-foreground max-w-2xl mx-auto">
Find answers to common questions or get in touch with our support team. Questions about our services? Our English-speaking team is ready to assist. Find answers
below or reach out directly.
</p> </p>
</div> </div>