Enhance Support & Contact Page and Navigation
- Updated the Public Contact Page to include a combined FAQ section, improving user assistance and engagement. - Renamed the Public Support Page to Public Help Page, redirecting to the updated contact page for better user flow. - Modified SiteFooter and PublicShell components to reflect updated navigation links, enhancing clarity and accessibility. - Improved styling and layout for better visual consistency across the portal.
This commit is contained in:
parent
933a461372
commit
ab3561ba5c
23
apps/portal/src/app/(public)/(site)/blog/layout.tsx
Normal file
23
apps/portal/src/app/(public)/(site)/blog/layout.tsx
Normal file
@ -0,0 +1,23 @@
|
||||
import type { Metadata } from "next";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Blog & Updates - Assist Solutions",
|
||||
description:
|
||||
"Tips, guides, and news for expats and businesses in Japan. Learn about internet setup, SIM cards, VPN services, and life in Japan.",
|
||||
keywords: [
|
||||
"Japan expat blog",
|
||||
"internet Japan guide",
|
||||
"SIM card Japan",
|
||||
"living in Japan tips",
|
||||
"Assist Solutions news",
|
||||
],
|
||||
openGraph: {
|
||||
title: "Blog & Updates - Assist Solutions",
|
||||
description: "Tips, guides, and news for the international community in Japan.",
|
||||
type: "website",
|
||||
},
|
||||
};
|
||||
|
||||
export default function BlogLayout({ children }: { children: React.ReactNode }) {
|
||||
return children;
|
||||
}
|
||||
247
apps/portal/src/app/(public)/(site)/blog/page.tsx
Normal file
247
apps/portal/src/app/(public)/(site)/blog/page.tsx
Normal file
@ -0,0 +1,247 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import Link from "next/link";
|
||||
import { cn } from "@/shared/utils";
|
||||
|
||||
// Sample blog data
|
||||
const categories = [
|
||||
{ id: "all", label: "Latest", count: 8 },
|
||||
{ id: "guides", label: "Guides", count: 3 },
|
||||
{ id: "tech", label: "Tech Tips", count: 2 },
|
||||
{ id: "news", label: "Company News", count: 2 },
|
||||
{ id: "lifestyle", label: "Expat Life", count: 1 },
|
||||
];
|
||||
|
||||
const authors = {
|
||||
daisuke: {
|
||||
name: "Daisuke Nagakawa",
|
||||
role: "CEO, Assist Solutions",
|
||||
avatar: "/assets/images/avatar-placeholder.png",
|
||||
},
|
||||
support: {
|
||||
name: "Support Team",
|
||||
role: "Assist Solutions",
|
||||
avatar: "/assets/images/avatar-placeholder.png",
|
||||
},
|
||||
tech: {
|
||||
name: "Tech Team",
|
||||
role: "Assist Solutions",
|
||||
avatar: "/assets/images/avatar-placeholder.png",
|
||||
},
|
||||
};
|
||||
|
||||
const blogPosts = [
|
||||
{
|
||||
id: "1",
|
||||
slug: "getting-internet-japan-guide",
|
||||
category: "guides",
|
||||
categoryLabel: "Guides",
|
||||
title: "The Complete Guide to Getting Internet in Japan",
|
||||
excerpt:
|
||||
"Moving to Japan and need internet? This comprehensive guide covers everything from choosing between fiber and mobile internet to understanding NTT's installation process.",
|
||||
image: "/assets/images/blog-placeholder-1.jpg",
|
||||
author: authors.support,
|
||||
date: "2025-01-10",
|
||||
featured: true,
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
slug: "5g-coverage-tokyo-2025",
|
||||
category: "tech",
|
||||
categoryLabel: "Tech Tips",
|
||||
title: "5G Coverage in Tokyo: What You Need to Know in 2025",
|
||||
excerpt:
|
||||
"With Docomo, au, and SoftBank expanding their 5G networks, we break down the current coverage in Tokyo and which areas have the best connectivity.",
|
||||
image: "/assets/images/blog-placeholder-2.jpg",
|
||||
author: authors.tech,
|
||||
date: "2025-01-08",
|
||||
featured: true,
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
slug: "choosing-sim-card-japan",
|
||||
category: "guides",
|
||||
categoryLabel: "Guides",
|
||||
title: "Data-Only vs Voice SIM: Which One Do You Need?",
|
||||
excerpt:
|
||||
"Confused about SIM card options in Japan? We explain the differences between data-only and voice SIMs, and help you choose the right one for your needs.",
|
||||
image: "/assets/images/blog-placeholder-3.jpg",
|
||||
author: authors.support,
|
||||
date: "2025-01-05",
|
||||
},
|
||||
{
|
||||
id: "4",
|
||||
slug: "work-from-home-internet-tips",
|
||||
category: "tech",
|
||||
categoryLabel: "Tech Tips",
|
||||
title: "Optimizing Your Home Network for Remote Work",
|
||||
excerpt:
|
||||
"Working from home in Japan? Learn how to set up your router, optimize Wi-Fi coverage, and troubleshoot common connectivity issues.",
|
||||
image: "/assets/images/blog-placeholder-4.jpg",
|
||||
author: authors.tech,
|
||||
date: "2025-01-03",
|
||||
},
|
||||
{
|
||||
id: "5",
|
||||
slug: "assist-solutions-2024-review",
|
||||
category: "news",
|
||||
categoryLabel: "Company News",
|
||||
title: "2024 Year in Review: Serving Our Community",
|
||||
excerpt:
|
||||
"A look back at the past year - new services launched, customer milestones reached, and our continued commitment to the international community in Japan.",
|
||||
image: "/assets/images/blog-placeholder-5.jpg",
|
||||
author: authors.daisuke,
|
||||
date: "2024-12-28",
|
||||
},
|
||||
{
|
||||
id: "6",
|
||||
slug: "vpn-streaming-guide",
|
||||
category: "guides",
|
||||
categoryLabel: "Guides",
|
||||
title: "Using VPN to Access Streaming Services in Japan",
|
||||
excerpt:
|
||||
"Want to watch your favorite shows from back home? Here's how to set up and use a VPN to access international streaming platforms while living in Japan.",
|
||||
image: "/assets/images/blog-placeholder-6.jpg",
|
||||
author: authors.support,
|
||||
date: "2024-12-20",
|
||||
},
|
||||
{
|
||||
id: "7",
|
||||
slug: "new-office-announcement",
|
||||
category: "news",
|
||||
categoryLabel: "Company News",
|
||||
title: "Expanded Support Hours & New Team Members",
|
||||
excerpt:
|
||||
"We're excited to announce extended support hours and welcome new bilingual team members to better serve our growing customer base.",
|
||||
image: "/assets/images/blog-placeholder-7.jpg",
|
||||
author: authors.daisuke,
|
||||
date: "2024-12-15",
|
||||
},
|
||||
{
|
||||
id: "8",
|
||||
slug: "moving-to-japan-checklist",
|
||||
category: "lifestyle",
|
||||
categoryLabel: "Expat Life",
|
||||
title: "Moving to Japan: Your Essential IT & Utilities Checklist",
|
||||
excerpt:
|
||||
"From setting up a bank account to getting internet installed - everything you need to know about utilities and connectivity when relocating to Japan.",
|
||||
image: "/assets/images/blog-placeholder-8.jpg",
|
||||
author: authors.support,
|
||||
date: "2024-12-10",
|
||||
},
|
||||
];
|
||||
|
||||
export default function BlogPage() {
|
||||
const [activeCategory, setActiveCategory] = useState("all");
|
||||
|
||||
const filteredPosts =
|
||||
activeCategory === "all"
|
||||
? blogPosts
|
||||
: blogPosts.filter(post => post.category === activeCategory);
|
||||
|
||||
return (
|
||||
<div className="max-w-7xl mx-auto px-4 py-8 sm:py-12">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-[240px_1fr] gap-10 lg:gap-14">
|
||||
{/* Sidebar */}
|
||||
<aside className="lg:sticky lg:top-24 lg:self-start">
|
||||
<div className="mb-8">
|
||||
<h1 className="text-3xl sm:text-4xl font-extrabold text-foreground leading-tight">
|
||||
Blog
|
||||
</h1>
|
||||
<p className="text-base italic text-primary mt-1">& Updates</p>
|
||||
<p className="text-sm text-muted-foreground mt-4 leading-relaxed">
|
||||
Tips, guides, and news for the international community in Japan.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="border-t border-border/60 pt-6">
|
||||
<h2 className="text-sm font-bold text-foreground mb-4">Categories</h2>
|
||||
<nav className="space-y-1">
|
||||
{categories.map(category => (
|
||||
<button
|
||||
key={category.id}
|
||||
type="button"
|
||||
onClick={() => setActiveCategory(category.id)}
|
||||
className={cn(
|
||||
"w-full flex items-center justify-between px-3 py-2 rounded-lg text-sm font-medium transition-colors",
|
||||
activeCategory === category.id
|
||||
? "bg-primary/10 text-primary"
|
||||
: "text-muted-foreground hover:text-foreground hover:bg-muted/50"
|
||||
)}
|
||||
>
|
||||
<span>{category.label}</span>
|
||||
<span
|
||||
className={cn(
|
||||
"text-xs px-2 py-0.5 rounded-full",
|
||||
activeCategory === category.id
|
||||
? "bg-primary/20 text-primary"
|
||||
: "bg-muted text-muted-foreground"
|
||||
)}
|
||||
>
|
||||
{category.count}
|
||||
</span>
|
||||
</button>
|
||||
))}
|
||||
</nav>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
{/* Blog Grid */}
|
||||
<main>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
|
||||
{filteredPosts.map(post => (
|
||||
<article key={post.id} className="group">
|
||||
<Link href={`/blog/${post.slug}`} className="block">
|
||||
{/* Image */}
|
||||
<div className="relative aspect-[16/10] rounded-2xl overflow-hidden bg-muted mb-4">
|
||||
<div className="absolute inset-0 bg-gradient-to-br from-primary/20 to-sky-200/30 flex items-center justify-center">
|
||||
<span className="text-4xl font-bold text-primary/30">
|
||||
{post.title.charAt(0)}
|
||||
</span>
|
||||
</div>
|
||||
{/* Hover overlay */}
|
||||
<div className="absolute inset-0 bg-primary/5 opacity-0 group-hover:opacity-100 transition-opacity" />
|
||||
</div>
|
||||
|
||||
{/* Category */}
|
||||
<span className="text-xs font-semibold text-primary uppercase tracking-wider">
|
||||
{post.categoryLabel}
|
||||
</span>
|
||||
|
||||
{/* Title */}
|
||||
<h2 className="text-xl font-bold text-foreground mt-2 mb-3 group-hover:text-primary transition-colors leading-snug">
|
||||
{post.title}
|
||||
</h2>
|
||||
|
||||
{/* Excerpt */}
|
||||
<p className="text-sm text-muted-foreground leading-relaxed line-clamp-3 mb-4">
|
||||
{post.excerpt}
|
||||
</p>
|
||||
|
||||
{/* Author */}
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-10 h-10 rounded-full bg-muted flex items-center justify-center text-muted-foreground text-sm font-bold">
|
||||
{post.author.name.charAt(0)}
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm font-semibold text-foreground">{post.author.name}</p>
|
||||
<p className="text-xs text-muted-foreground">{post.author.role}</p>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Empty state */}
|
||||
{filteredPosts.length === 0 && (
|
||||
<div className="text-center py-16">
|
||||
<p className="text-muted-foreground">No posts found in this category.</p>
|
||||
</div>
|
||||
)}
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -1,20 +1,27 @@
|
||||
/**
|
||||
* Public Contact Page
|
||||
* Public Support & Contact Page
|
||||
*
|
||||
* Contact form for unauthenticated users.
|
||||
* Combined FAQ, contact options, and contact form for unauthenticated users.
|
||||
*/
|
||||
|
||||
import type { Metadata } from "next";
|
||||
import { PublicContactView } from "@/features/support/views/PublicContactView";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Contact Us - Assist Solutions | Get Support",
|
||||
title: "Support & Contact - Assist Solutions | Get Help",
|
||||
description:
|
||||
"Contact Assist Solutions for internet, mobile, and IT support inquiries. Call toll-free 0120-660-470 or reach us online. English and Japanese support available.",
|
||||
keywords: ["contact Assist Solutions", "IT support Tokyo", "customer service"],
|
||||
"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.",
|
||||
keywords: [
|
||||
"contact Assist Solutions",
|
||||
"IT support Tokyo",
|
||||
"customer service Japan",
|
||||
"English support",
|
||||
"FAQ",
|
||||
],
|
||||
openGraph: {
|
||||
title: "Contact Assist Solutions",
|
||||
description: "Get in touch with our bilingual support team. Toll-free: 0120-660-470",
|
||||
title: "Support & Contact - Assist Solutions",
|
||||
description:
|
||||
"Get help with your internet, mobile, or IT services. Bilingual support available. Toll-free: 0120-660-470",
|
||||
type: "website",
|
||||
},
|
||||
};
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
/**
|
||||
* Public Support Page
|
||||
* Public Help Page
|
||||
*
|
||||
* FAQ and help center for unauthenticated users.
|
||||
* Redirects to the combined Support & Contact page.
|
||||
*/
|
||||
|
||||
import { PublicSupportView } from "@/features/support/views/PublicSupportView";
|
||||
import { redirect } from "next/navigation";
|
||||
|
||||
export default function PublicSupportPage() {
|
||||
return <PublicSupportView />;
|
||||
export default function PublicHelpPage() {
|
||||
redirect("/contact");
|
||||
}
|
||||
|
||||
@ -94,15 +94,15 @@ export function SiteFooter() {
|
||||
href="/contact"
|
||||
className="text-muted-foreground hover:text-foreground transition-colors"
|
||||
>
|
||||
Contact
|
||||
Support & Contact
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link
|
||||
href="/help"
|
||||
href="/blog"
|
||||
className="text-muted-foreground hover:text-foreground transition-colors"
|
||||
>
|
||||
Support
|
||||
Blog
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@ -175,12 +175,6 @@ export function PublicShell({ children }: PublicShellProps) {
|
||||
>
|
||||
About
|
||||
</Link>
|
||||
<Link
|
||||
href="/contact"
|
||||
className="inline-flex items-center px-3 py-2 rounded-md hover:text-foreground transition-colors"
|
||||
>
|
||||
Contact
|
||||
</Link>
|
||||
<Link
|
||||
href="/blog"
|
||||
className="hidden sm:inline-flex items-center px-3 py-2 rounded-md hover:text-foreground transition-colors"
|
||||
@ -188,8 +182,8 @@ export function PublicShell({ children }: PublicShellProps) {
|
||||
Blog
|
||||
</Link>
|
||||
<Link
|
||||
href="/help"
|
||||
className="hidden md:inline-flex items-center px-3 py-2 rounded-md hover:text-foreground transition-colors"
|
||||
href="/contact"
|
||||
className="inline-flex items-center px-3 py-2 rounded-md hover:text-foreground transition-colors"
|
||||
>
|
||||
Support
|
||||
</Link>
|
||||
|
||||
@ -208,24 +208,21 @@ export function SignupForm({
|
||||
isSubmitting,
|
||||
} = form;
|
||||
|
||||
const normalizeAutofillValue = useCallback(
|
||||
(field: string, value: string) => {
|
||||
switch (field) {
|
||||
case "phoneCountryCode": {
|
||||
let normalized = value.replace(/[^\d+]/g, "");
|
||||
if (!normalized.startsWith("+")) normalized = "+" + normalized.replace(/\+/g, "");
|
||||
return normalized.slice(0, 5);
|
||||
}
|
||||
case "phone":
|
||||
return value.replace(/\D/g, "");
|
||||
case "address.postcode":
|
||||
return formatJapanesePostalCode(value);
|
||||
default:
|
||||
return value;
|
||||
const normalizeAutofillValue = useCallback((field: string, value: string) => {
|
||||
switch (field) {
|
||||
case "phoneCountryCode": {
|
||||
let normalized = value.replace(/[^\d+]/g, "");
|
||||
if (!normalized.startsWith("+")) normalized = "+" + normalized.replace(/\+/g, "");
|
||||
return normalized.slice(0, 5);
|
||||
}
|
||||
},
|
||||
[formatJapanesePostalCode]
|
||||
);
|
||||
case "phone":
|
||||
return value.replace(/\D/g, "");
|
||||
case "address.postcode":
|
||||
return formatJapanesePostalCode(value);
|
||||
default:
|
||||
return value;
|
||||
}
|
||||
}, []);
|
||||
|
||||
const syncStepValues = useCallback(
|
||||
(shouldFlush = true) => {
|
||||
|
||||
@ -99,7 +99,6 @@ export function PublicLandingView() {
|
||||
"Utilizing NTT's optical fiber network, we deliver one of the most reliable Internet connections in Japan.",
|
||||
icon: <Wifi className="h-8 w-8 text-primary" />,
|
||||
href: "/services/internet",
|
||||
price: "From 5,280 JPY/mo",
|
||||
},
|
||||
{
|
||||
title: "Phone Plans",
|
||||
@ -107,7 +106,6 @@ export function PublicLandingView() {
|
||||
"Using NTT DOCOMO's vast mobile network, we deliver one of the most cost-friendly SIM card services in Japan.",
|
||||
icon: <Smartphone className="h-8 w-8 text-primary" />,
|
||||
href: "/services/sim",
|
||||
price: "From 1,078 JPY/mo",
|
||||
},
|
||||
{
|
||||
title: "Business Solutions",
|
||||
@ -115,7 +113,6 @@ export function PublicLandingView() {
|
||||
"Dedicated Internet Access, office network setup, data center services, and ongoing tech support.",
|
||||
icon: <Building2 className="h-8 w-8 text-primary" />,
|
||||
href: "/services/business",
|
||||
price: "Custom Quote",
|
||||
},
|
||||
{
|
||||
title: "VPN",
|
||||
@ -123,14 +120,12 @@ export function PublicLandingView() {
|
||||
"Choose any of our VPN server locations that connect directly from Tokyo with static routing.",
|
||||
icon: <Lock className="h-8 w-8 text-primary" />,
|
||||
href: "/services/vpn",
|
||||
price: "From 1,100 JPY/mo",
|
||||
},
|
||||
{
|
||||
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",
|
||||
price: "From 4,389 JPY/mo",
|
||||
},
|
||||
{
|
||||
title: "Onsite Support",
|
||||
@ -138,7 +133,6 @@ export function PublicLandingView() {
|
||||
"Professional technical support at your residence or office for setup, configuration, and troubleshooting.",
|
||||
icon: <Wrench className="h-8 w-8 text-primary" />,
|
||||
href: "/services/onsite",
|
||||
price: "From 5,000 JPY",
|
||||
},
|
||||
];
|
||||
const isScrollingRef = useRef(false);
|
||||
@ -251,8 +245,20 @@ export function PublicLandingView() {
|
||||
return (
|
||||
<div className="space-y-0 pb-8 pt-0">
|
||||
{/* Hero Section */}
|
||||
<section className="relative left-1/2 right-1/2 w-screen -translate-x-1/2 bg-[#f7f7f7] py-12 sm:py-16">
|
||||
<div className="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">
|
||||
<section className="relative left-1/2 right-1/2 w-screen -translate-x-1/2 bg-gradient-to-br from-slate-50 via-white to-sky-50/50 py-12 sm:py-16 overflow-hidden">
|
||||
{/* Abstract gradient blobs */}
|
||||
<div className="absolute inset-0 overflow-hidden pointer-events-none">
|
||||
{/* Top-left blob */}
|
||||
<div className="absolute -top-24 -left-24 w-96 h-96 bg-gradient-to-br from-primary/20 to-sky-300/20 rounded-full blur-3xl opacity-60" />
|
||||
{/* Top-right blob */}
|
||||
<div className="absolute -top-12 right-0 w-80 h-80 bg-gradient-to-bl from-cyan-200/30 to-blue-300/20 rounded-full blur-3xl opacity-50" />
|
||||
{/* Bottom-left blob */}
|
||||
<div className="absolute bottom-0 left-1/4 w-72 h-72 bg-gradient-to-tr from-sky-200/25 to-indigo-200/20 rounded-full blur-3xl opacity-40" />
|
||||
{/* Center-right accent */}
|
||||
<div className="absolute top-1/2 right-1/4 w-64 h-64 bg-gradient-to-tl from-primary/10 to-cyan-300/15 rounded-full blur-3xl opacity-50" />
|
||||
</div>
|
||||
|
||||
<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">
|
||||
<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>
|
||||
@ -400,7 +406,6 @@ export function PublicLandingView() {
|
||||
<p className="text-muted-foreground leading-relaxed flex-grow">
|
||||
{service.description}
|
||||
</p>
|
||||
<p className="text-sm font-bold text-primary mt-4">{service.price}</p>
|
||||
</article>
|
||||
</Link>
|
||||
))}
|
||||
|
||||
@ -119,34 +119,51 @@ export function AboutUsView() {
|
||||
}, [computeScrollAmount]);
|
||||
|
||||
return (
|
||||
<div className="max-w-6xl mx-auto space-y-12 px-6 sm:px-8">
|
||||
{/* Hero */}
|
||||
<section className="grid grid-cols-1 lg:grid-cols-[1.05fr_minmax(0,0.95fr)] gap-10 items-center">
|
||||
<div className="space-y-5">
|
||||
<h1 className="text-3xl sm:text-4xl font-bold text-primary leading-tight">About Us</h1>
|
||||
<div className="space-y-4 text-muted-foreground leading-relaxed">
|
||||
<p>
|
||||
Assist Solutions Corp. is a privately-owned entrepreneurial IT service company. We
|
||||
specialize in serving Japan's international community with the most reliable and
|
||||
cost-efficient IT & TV solutions available.
|
||||
</p>
|
||||
<p>
|
||||
We are dedicated to providing comfortable support for our customer's diverse
|
||||
needs in both English and Japanese. Our excellent bi-lingual support, flexible
|
||||
service, and deep industry knowledge set us apart.
|
||||
</p>
|
||||
<div className="space-y-12">
|
||||
{/* Hero with geometric pattern */}
|
||||
<section className="relative left-1/2 right-1/2 w-screen -translate-x-1/2 bg-gradient-to-br from-slate-50 to-sky-50/30 py-12 sm:py-16 overflow-hidden">
|
||||
{/* Dot grid pattern */}
|
||||
<div
|
||||
className="absolute inset-0 opacity-[0.4]"
|
||||
style={{
|
||||
backgroundImage: `radial-gradient(circle, #0ea5e9 1px, transparent 1px)`,
|
||||
backgroundSize: "24px 24px",
|
||||
}}
|
||||
/>
|
||||
{/* Subtle gradient overlay for depth */}
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-white/80 via-transparent to-white/40" />
|
||||
|
||||
<div className="relative max-w-6xl mx-auto px-6 sm:px-8">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-[1.05fr_minmax(0,0.95fr)] gap-10 items-center">
|
||||
<div className="space-y-5">
|
||||
<h1 className="text-4xl sm:text-5xl font-extrabold text-primary leading-tight tracking-tight">
|
||||
About Us
|
||||
</h1>
|
||||
<div className="space-y-4 text-muted-foreground leading-relaxed text-base sm:text-lg">
|
||||
<p>
|
||||
Assist Solutions Corp. is a privately-owned entrepreneurial IT service company. We
|
||||
specialize in serving Japan's international community with the most reliable
|
||||
and cost-efficient IT & TV solutions available.
|
||||
</p>
|
||||
<p>
|
||||
We are dedicated to providing comfortable support for our customer's diverse
|
||||
needs in both English and Japanese. Our excellent bi-lingual support, flexible
|
||||
service, and deep industry knowledge set us apart.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="relative h-full min-h-[420px]">
|
||||
<Image
|
||||
src="/assets/images/About us.png"
|
||||
alt="Assist Solutions team in Tokyo"
|
||||
fill
|
||||
priority
|
||||
className="object-contain drop-shadow-lg"
|
||||
sizes="(max-width: 1024px) 100vw, 45vw"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="relative h-full min-h-[420px]">
|
||||
<Image
|
||||
src="/assets/images/About us.png"
|
||||
alt="Assist Solutions team in Tokyo"
|
||||
fill
|
||||
priority
|
||||
className="object-contain"
|
||||
sizes="(max-width: 1024px) 100vw, 45vw"
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Business Solutions Carousel */}
|
||||
|
||||
@ -6,26 +6,81 @@ import { Button, Input } from "@/components/atoms";
|
||||
import { FormField } from "@/components/molecules/FormField/FormField";
|
||||
import { AlertBanner } from "@/components/molecules/AlertBanner/AlertBanner";
|
||||
import { useZodForm } from "@/shared/hooks";
|
||||
import { Mail, CheckCircle, MapPin } from "lucide-react";
|
||||
import {
|
||||
Mail,
|
||||
CheckCircle,
|
||||
MapPin,
|
||||
Phone,
|
||||
MessageSquare,
|
||||
ChevronDown,
|
||||
Clock,
|
||||
HelpCircle,
|
||||
Send,
|
||||
ExternalLink,
|
||||
} from "lucide-react";
|
||||
import {
|
||||
publicContactRequestSchema,
|
||||
type PublicContactRequest,
|
||||
} from "@customer-portal/domain/support";
|
||||
import { apiClient, ApiError, isApiError } from "@/core/api";
|
||||
import { cn } from "@/shared/utils";
|
||||
|
||||
const FAQ_ITEMS = [
|
||||
{
|
||||
question: "How do I get started with your services?",
|
||||
answer:
|
||||
"Simply browse our services, select a plan that fits your needs, and complete the checkout process. You can create an account during checkout or contact us for personalized assistance.",
|
||||
},
|
||||
{
|
||||
question: "What payment methods do you accept?",
|
||||
answer:
|
||||
"We accept major credit cards (Visa, Mastercard, American Express) including foreign-issued cards, and bank transfers. Payment methods can be managed in your account settings.",
|
||||
},
|
||||
{
|
||||
question: "How long does installation take?",
|
||||
answer:
|
||||
"Internet installation typically takes 2-4 weeks depending on your location and the type of installation required. SIM cards are shipped within 3-5 business days.",
|
||||
},
|
||||
{
|
||||
question: "Can I change my plan after signing up?",
|
||||
answer:
|
||||
"Yes, you can upgrade or downgrade your plan at any time. Changes typically take effect at the start of your next billing cycle.",
|
||||
},
|
||||
{
|
||||
question: "What is your cancellation policy?",
|
||||
answer:
|
||||
"Most services have a minimum contract period (typically 4 months for SIM, varies for internet). After this period, you can cancel with one month's notice.",
|
||||
},
|
||||
{
|
||||
question: "Do you offer business solutions?",
|
||||
answer:
|
||||
"Yes, we offer dedicated business plans including Dedicated Internet Access, office LAN setup, data center services, and ongoing tech support. Please contact us for a custom quote.",
|
||||
},
|
||||
{
|
||||
question: "Do you provide English support?",
|
||||
answer:
|
||||
"Yes! Our entire team is bilingual and provides full support in both English and Japanese. This includes phone support, email, and onsite visits.",
|
||||
},
|
||||
{
|
||||
question: "What areas do you service?",
|
||||
answer:
|
||||
"We primarily serve the greater Tokyo area for onsite support. Internet and SIM services are available nationwide through NTT and Docomo networks.",
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* PublicContactView - Contact page with form, phone, chat, and location info
|
||||
* PublicContactView - Combined Support & Contact page
|
||||
*/
|
||||
export function PublicContactView() {
|
||||
const [isSubmitted, setIsSubmitted] = useState(false);
|
||||
const [submitError, setSubmitError] = useState<string | null>(null);
|
||||
const [expandedFaq, setExpandedFaq] = useState<number | null>(null);
|
||||
|
||||
const handleSubmit = useCallback(async (data: PublicContactRequest) => {
|
||||
setSubmitError(null);
|
||||
|
||||
try {
|
||||
await apiClient.POST("/api/support/contact", { body: data });
|
||||
|
||||
setIsSubmitted(true);
|
||||
} catch (error) {
|
||||
if (isApiError(error)) {
|
||||
@ -54,17 +109,17 @@ export function PublicContactView() {
|
||||
|
||||
if (isSubmitted) {
|
||||
return (
|
||||
<div className="max-w-lg mx-auto text-center py-12">
|
||||
<div className="w-16 h-16 bg-success/10 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<CheckCircle className="h-8 w-8 text-success" />
|
||||
<div className="max-w-lg mx-auto text-center py-16">
|
||||
<div className="w-20 h-20 bg-success/10 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<CheckCircle className="h-10 w-10 text-success" />
|
||||
</div>
|
||||
<h1 className="text-2xl font-bold text-foreground mb-2">Message Sent!</h1>
|
||||
<p className="text-muted-foreground mb-6">
|
||||
<h1 className="text-3xl font-bold text-foreground mb-3">Message Sent!</h1>
|
||||
<p className="text-muted-foreground mb-8 text-lg">
|
||||
Thank you for contacting us. We'll get back to you within 24 hours.
|
||||
</p>
|
||||
<div className="flex gap-4 justify-center">
|
||||
<Button as="a" href="/help" variant="outline">
|
||||
Back to Support
|
||||
<Button as="a" href="/" variant="outline">
|
||||
Back to Home
|
||||
</Button>
|
||||
<Button as="a" href="/services">
|
||||
Browse Services
|
||||
@ -75,224 +130,336 @@ export function PublicContactView() {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="max-w-6xl mx-auto px-4">
|
||||
<div className="max-w-6xl mx-auto px-4 pb-16">
|
||||
{/* Header */}
|
||||
<div className="text-center mb-16 pt-8">
|
||||
<h1 className="text-4xl sm:text-5xl font-extrabold text-foreground mb-6 tracking-tight">
|
||||
Get in Touch
|
||||
<div className="text-center mb-12 pt-8">
|
||||
<div className="inline-flex items-center justify-center w-16 h-16 bg-primary/10 rounded-2xl mb-4 text-primary">
|
||||
<HelpCircle className="h-8 w-8" />
|
||||
</div>
|
||||
<h1 className="text-4xl sm:text-5xl font-extrabold text-foreground mb-4 tracking-tight">
|
||||
Support & Contact
|
||||
</h1>
|
||||
<p className="text-xl text-muted-foreground max-w-2xl mx-auto leading-relaxed">
|
||||
Have a question about our services? We're here to help you find the perfect solution for
|
||||
your stay in Japan.
|
||||
<p className="text-lg text-muted-foreground max-w-2xl mx-auto leading-relaxed">
|
||||
Have a question? We're here to help. Reach out through any channel below.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 lg:grid-cols-12 gap-10">
|
||||
{/* Left Column - Contact Form */}
|
||||
<div className="lg:col-span-7">
|
||||
<div className="bg-card rounded-2xl border border-border/60 shadow-sm overflow-hidden">
|
||||
<div className="p-6 sm:p-8 border-b border-border/60 bg-muted/20">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="h-10 w-10 rounded-xl bg-primary/10 flex items-center justify-center text-primary">
|
||||
<Mail className="h-5 w-5" />
|
||||
</div>
|
||||
<div>
|
||||
<h2 className="text-xl font-bold text-foreground">Send a Message</h2>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
We typically reply within 24 hours
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{/* Quick Contact Options */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 mb-12">
|
||||
{/* Phone */}
|
||||
<a
|
||||
href="tel:0120-660-470"
|
||||
className="group bg-white rounded-2xl border border-border/60 p-6 hover:border-primary/40 hover:shadow-md transition-all duration-200"
|
||||
>
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="h-12 w-12 rounded-xl bg-primary/10 flex items-center justify-center text-primary group-hover:bg-primary group-hover:text-white transition-colors">
|
||||
<Phone className="h-6 w-6" />
|
||||
</div>
|
||||
|
||||
<div className="p-6 sm:p-8">
|
||||
{submitError && (
|
||||
<AlertBanner variant="error" title="Error" className="mb-6">
|
||||
{submitError}
|
||||
</AlertBanner>
|
||||
)}
|
||||
|
||||
<form onSubmit={event => void form.handleSubmit(event)} className="space-y-6">
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-6">
|
||||
<FormField
|
||||
label="Name"
|
||||
error={form.touched.name ? form.errors.name : undefined}
|
||||
required
|
||||
>
|
||||
<Input
|
||||
value={form.values.name}
|
||||
onChange={e => form.setValue("name", e.target.value)}
|
||||
onBlur={() => form.setTouchedField("name")}
|
||||
placeholder="Your name"
|
||||
className="bg-background"
|
||||
/>
|
||||
</FormField>
|
||||
|
||||
<FormField
|
||||
label="Email"
|
||||
error={form.touched.email ? form.errors.email : undefined}
|
||||
required
|
||||
>
|
||||
<Input
|
||||
type="email"
|
||||
value={form.values.email}
|
||||
onChange={e => form.setValue("email", e.target.value)}
|
||||
onBlur={() => form.setTouchedField("email")}
|
||||
placeholder="your@email.com"
|
||||
className="bg-background"
|
||||
/>
|
||||
</FormField>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-6">
|
||||
<FormField
|
||||
label="Phone (Optional)"
|
||||
error={form.touched.phone ? form.errors.phone : undefined}
|
||||
>
|
||||
<Input
|
||||
value={form.values.phone ?? ""}
|
||||
onChange={e => form.setValue("phone", e.target.value)}
|
||||
onBlur={() => form.setTouchedField("phone")}
|
||||
placeholder="+81 90-1234-5678"
|
||||
className="bg-background"
|
||||
/>
|
||||
</FormField>
|
||||
|
||||
<FormField
|
||||
label="Subject"
|
||||
error={form.touched.subject ? form.errors.subject : undefined}
|
||||
required
|
||||
>
|
||||
<Input
|
||||
value={form.values.subject}
|
||||
onChange={e => form.setValue("subject", e.target.value)}
|
||||
onBlur={() => form.setTouchedField("subject")}
|
||||
placeholder="How can we help?"
|
||||
className="bg-background"
|
||||
/>
|
||||
</FormField>
|
||||
</div>
|
||||
|
||||
<FormField
|
||||
label="Message"
|
||||
error={form.touched.message ? form.errors.message : undefined}
|
||||
required
|
||||
>
|
||||
<textarea
|
||||
className="flex min-h-[160px] w-full rounded-lg border border-input bg-background px-4 py-3 text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:border-transparent disabled:cursor-not-allowed disabled:opacity-50 transition-colors resize-y"
|
||||
value={form.values.message}
|
||||
onChange={e => form.setValue("message", e.target.value)}
|
||||
onBlur={() => form.setTouchedField("message")}
|
||||
placeholder="Tell us more about your inquiry..."
|
||||
rows={5}
|
||||
/>
|
||||
</FormField>
|
||||
|
||||
<Button
|
||||
type="submit"
|
||||
className="w-full sm:w-auto min-w-[160px]"
|
||||
size="lg"
|
||||
disabled={form.isSubmitting}
|
||||
isLoading={form.isSubmitting}
|
||||
loadingText="Sending..."
|
||||
>
|
||||
Send Message
|
||||
</Button>
|
||||
</form>
|
||||
|
||||
<p className="text-xs text-muted-foreground mt-6 pt-6 border-t border-border/60">
|
||||
By submitting this form, you agree to our{" "}
|
||||
<Link href="#" className="text-primary hover:underline font-medium">
|
||||
Privacy Policy
|
||||
</Link>
|
||||
. Your information is secure and will only be used to respond to your inquiry.
|
||||
</p>
|
||||
<div>
|
||||
<h3 className="font-bold text-foreground group-hover:text-primary transition-colors">
|
||||
Call Us
|
||||
</h3>
|
||||
<p className="text-lg font-bold text-primary">0120-660-470</p>
|
||||
<p className="text-xs text-muted-foreground">Toll-free in Japan</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
{/* Right Column - Contact Info */}
|
||||
<div className="lg:col-span-5 space-y-6">
|
||||
{/* By Phone */}
|
||||
<div className="bg-card rounded-2xl border border-border/60 p-6 sm:p-8 hover:border-primary/30 transition-colors duration-300">
|
||||
<h2 className="text-xl font-bold text-foreground mb-4">Phone Support</h2>
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<div className="text-xs font-semibold text-muted-foreground uppercase tracking-wider mb-1">
|
||||
Japan (Toll Free)
|
||||
</div>
|
||||
<a
|
||||
href="tel:0120-660-470"
|
||||
className="text-2xl font-bold text-foreground hover:text-primary transition-colors inline-block"
|
||||
>
|
||||
0120-660-470
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-xs font-semibold text-muted-foreground uppercase tracking-wider mb-1">
|
||||
International
|
||||
</div>
|
||||
<a
|
||||
href="tel:+81-3-3560-1006"
|
||||
className="text-lg font-semibold text-foreground hover:text-primary transition-colors inline-block"
|
||||
>
|
||||
+81-3-3560-1006
|
||||
</a>
|
||||
</div>
|
||||
<div className="text-sm text-muted-foreground pt-4 border-t border-border/60">
|
||||
9:30 - 18:00 JST (Mon - Fri)
|
||||
</div>
|
||||
{/* Chat */}
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
/* Trigger chat */
|
||||
}}
|
||||
className="group bg-white rounded-2xl border border-border/60 p-6 hover:border-blue-500/40 hover:shadow-md transition-all duration-200 text-left"
|
||||
>
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="h-12 w-12 rounded-xl bg-blue-500/10 flex items-center justify-center text-blue-500 group-hover:bg-blue-500 group-hover:text-white transition-colors">
|
||||
<MessageSquare className="h-6 w-6" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* By Chat */}
|
||||
<div className="bg-card rounded-2xl border border-border/60 p-6 sm:p-8 hover:border-blue-500/30 transition-colors duration-300">
|
||||
<h2 className="text-xl font-bold text-foreground mb-4">Live Chat</h2>
|
||||
<p className="text-muted-foreground mb-6">
|
||||
Need quick answers? Chat with our support team directly in your browser.
|
||||
</p>
|
||||
<Button
|
||||
variant="outline"
|
||||
className="w-full justify-start"
|
||||
onClick={() => {
|
||||
/* Trigger chat logic would go here */
|
||||
}}
|
||||
>
|
||||
<span className="flex items-center gap-2">
|
||||
<span className="relative flex h-2 w-2 mr-1">
|
||||
<div>
|
||||
<h3 className="font-bold text-foreground group-hover:text-blue-500 transition-colors">
|
||||
Live Chat
|
||||
</h3>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="relative flex h-2 w-2">
|
||||
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-success opacity-75"></span>
|
||||
<span className="relative inline-flex rounded-full h-2 w-2 bg-success"></span>
|
||||
</span>
|
||||
Chat Available
|
||||
</span>
|
||||
</Button>
|
||||
<span className="text-sm text-muted-foreground">Available now</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
{/* Email */}
|
||||
<a
|
||||
href="mailto:support@assist-solutions.jp"
|
||||
className="group bg-white rounded-2xl border border-border/60 p-6 hover:border-emerald-500/40 hover:shadow-md transition-all duration-200"
|
||||
>
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="h-12 w-12 rounded-xl bg-emerald-500/10 flex items-center justify-center text-emerald-500 group-hover:bg-emerald-500 group-hover:text-white transition-colors">
|
||||
<Mail className="h-6 w-6" />
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="font-bold text-foreground group-hover:text-emerald-500 transition-colors">
|
||||
Email Us
|
||||
</h3>
|
||||
<p className="text-sm text-muted-foreground">support@assist-solutions.jp</p>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{/* Business Hours Banner */}
|
||||
<div className="bg-muted/30 rounded-xl p-4 mb-12 flex items-center justify-center gap-3 text-sm">
|
||||
<Clock className="h-4 w-4 text-muted-foreground" />
|
||||
<span className="text-muted-foreground">
|
||||
<span className="font-medium text-foreground">Business Hours:</span> Mon - Fri, 9:30 AM -
|
||||
6:00 PM JST
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-10 mb-16">
|
||||
{/* FAQ Section */}
|
||||
<div>
|
||||
<h2 className="text-2xl font-bold text-foreground mb-6 flex items-center gap-2">
|
||||
<HelpCircle className="h-6 w-6 text-primary" />
|
||||
Frequently Asked Questions
|
||||
</h2>
|
||||
<div className="space-y-3">
|
||||
{FAQ_ITEMS.map((item, index) => {
|
||||
const isExpanded = expandedFaq === index;
|
||||
return (
|
||||
<div
|
||||
key={index}
|
||||
className="bg-white rounded-xl border border-border/60 overflow-hidden"
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setExpandedFaq(isExpanded ? null : index)}
|
||||
className="w-full flex items-center justify-between p-4 text-left hover:bg-muted/30 transition-colors"
|
||||
>
|
||||
<span className="font-medium text-foreground text-sm pr-4">
|
||||
{item.question}
|
||||
</span>
|
||||
<ChevronDown
|
||||
className={cn(
|
||||
"h-4 w-4 text-muted-foreground flex-shrink-0 transition-transform",
|
||||
isExpanded && "rotate-180"
|
||||
)}
|
||||
/>
|
||||
</button>
|
||||
{isExpanded && (
|
||||
<div className="px-4 pb-4">
|
||||
<p className="text-sm text-muted-foreground leading-relaxed">{item.answer}</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Contact Form */}
|
||||
<div>
|
||||
<h2 className="text-2xl font-bold text-foreground mb-6 flex items-center gap-2">
|
||||
<Send className="h-6 w-6 text-primary" />
|
||||
Send a Message
|
||||
</h2>
|
||||
<div className="bg-white rounded-2xl border border-border/60 p-6">
|
||||
{submitError && (
|
||||
<AlertBanner variant="error" title="Error" className="mb-6">
|
||||
{submitError}
|
||||
</AlertBanner>
|
||||
)}
|
||||
|
||||
<form onSubmit={event => void form.handleSubmit(event)} className="space-y-5">
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-5">
|
||||
<FormField
|
||||
label="Name"
|
||||
error={form.touched.name ? form.errors.name : undefined}
|
||||
required
|
||||
>
|
||||
<Input
|
||||
value={form.values.name}
|
||||
onChange={e => form.setValue("name", e.target.value)}
|
||||
onBlur={() => form.setTouchedField("name")}
|
||||
placeholder="Your name"
|
||||
className="bg-muted/20"
|
||||
/>
|
||||
</FormField>
|
||||
|
||||
<FormField
|
||||
label="Email"
|
||||
error={form.touched.email ? form.errors.email : undefined}
|
||||
required
|
||||
>
|
||||
<Input
|
||||
type="email"
|
||||
value={form.values.email}
|
||||
onChange={e => form.setValue("email", e.target.value)}
|
||||
onBlur={() => form.setTouchedField("email")}
|
||||
placeholder="your@email.com"
|
||||
className="bg-muted/20"
|
||||
/>
|
||||
</FormField>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-5">
|
||||
<FormField label="Phone" error={form.touched.phone ? form.errors.phone : undefined}>
|
||||
<Input
|
||||
value={form.values.phone ?? ""}
|
||||
onChange={e => form.setValue("phone", e.target.value)}
|
||||
onBlur={() => form.setTouchedField("phone")}
|
||||
placeholder="+81 90-1234-5678"
|
||||
className="bg-muted/20"
|
||||
/>
|
||||
</FormField>
|
||||
|
||||
<FormField
|
||||
label="Subject"
|
||||
error={form.touched.subject ? form.errors.subject : undefined}
|
||||
required
|
||||
>
|
||||
<Input
|
||||
value={form.values.subject}
|
||||
onChange={e => form.setValue("subject", e.target.value)}
|
||||
onBlur={() => form.setTouchedField("subject")}
|
||||
placeholder="How can we help?"
|
||||
className="bg-muted/20"
|
||||
/>
|
||||
</FormField>
|
||||
</div>
|
||||
|
||||
<FormField
|
||||
label="Message"
|
||||
error={form.touched.message ? form.errors.message : undefined}
|
||||
required
|
||||
>
|
||||
<textarea
|
||||
className="flex min-h-[120px] w-full rounded-lg border border-input bg-muted/20 px-4 py-3 text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:border-transparent disabled:cursor-not-allowed disabled:opacity-50 transition-colors resize-y text-sm"
|
||||
value={form.values.message}
|
||||
onChange={e => form.setValue("message", e.target.value)}
|
||||
onBlur={() => form.setTouchedField("message")}
|
||||
placeholder="Tell us more about your inquiry..."
|
||||
rows={4}
|
||||
/>
|
||||
</FormField>
|
||||
|
||||
<Button
|
||||
type="submit"
|
||||
className="w-full"
|
||||
size="lg"
|
||||
disabled={form.isSubmitting}
|
||||
isLoading={form.isSubmitting}
|
||||
loadingText="Sending..."
|
||||
>
|
||||
Send Message
|
||||
</Button>
|
||||
</form>
|
||||
|
||||
<p className="text-xs text-muted-foreground mt-4 pt-4 border-t border-border/60">
|
||||
By submitting, you agree to our{" "}
|
||||
<Link href="#" className="text-primary hover:underline">
|
||||
Privacy Policy
|
||||
</Link>
|
||||
. We typically respond within 24 hours.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Office Location */}
|
||||
<div className="bg-white rounded-2xl border border-border/60 overflow-hidden">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2">
|
||||
{/* Map */}
|
||||
<div className="h-[300px] lg:h-auto">
|
||||
<iframe
|
||||
title="Assist Solutions Corp Office"
|
||||
src="https://www.google.com/maps?q=Assist+Solutions+Corp,+3-8-2+Higashi+Azabu,+Minato-ku,+Tokyo&output=embed"
|
||||
className="w-full h-full"
|
||||
loading="lazy"
|
||||
allowFullScreen
|
||||
referrerPolicy="no-referrer-when-downgrade"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Access / Location */}
|
||||
<div className="bg-card rounded-2xl border border-border/60 p-6 sm:p-8 hover:border-primary/30 transition-colors duration-300">
|
||||
{/* Address Info */}
|
||||
<div className="p-8">
|
||||
<div className="flex items-center gap-3 mb-6">
|
||||
<div className="h-10 w-10 rounded-xl bg-primary/10 flex items-center justify-center text-primary">
|
||||
<MapPin className="h-5 w-5" />
|
||||
<div className="h-12 w-12 rounded-xl bg-primary/10 flex items-center justify-center text-primary">
|
||||
<MapPin className="h-6 w-6" />
|
||||
</div>
|
||||
<h2 className="text-xl font-bold text-foreground">Visit Us</h2>
|
||||
</div>
|
||||
<div className="space-y-4">
|
||||
<address className="text-muted-foreground leading-relaxed not-italic">
|
||||
3F Azabu Maruka Bldg., 3-8-2 Higashi Azabu,
|
||||
<br />
|
||||
Minato-ku, Tokyo 106-0044
|
||||
</address>
|
||||
<div className="pt-4 border-t border-border/60">
|
||||
<div>
|
||||
<h2 className="text-xl font-bold text-foreground">Visit Our Office</h2>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Short walk from Exit 6 of Azabu-Juban Station
|
||||
Walk-ins welcome during business hours
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h3 className="text-sm font-semibold text-muted-foreground uppercase tracking-wider mb-2">
|
||||
Address
|
||||
</h3>
|
||||
<address className="text-foreground leading-relaxed not-italic">
|
||||
3F Azabu Maruka Bldg., 3-8-2 Higashi Azabu,
|
||||
<br />
|
||||
Minato-ku, Tokyo 106-0044
|
||||
</address>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="text-sm font-semibold text-muted-foreground uppercase tracking-wider mb-2">
|
||||
Contact
|
||||
</h3>
|
||||
<p className="text-foreground">
|
||||
Tel: 03-3560-1006
|
||||
<br />
|
||||
Fax: 03-3560-1007
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="text-sm font-semibold text-muted-foreground uppercase tracking-wider mb-2">
|
||||
Access
|
||||
</h3>
|
||||
<p className="text-sm text-muted-foreground leading-relaxed">
|
||||
5 min walk from Exit 6 of Azabu-Juban Station
|
||||
<br />
|
||||
(Subway Oedo Line / Nanboku Line)
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<a
|
||||
href="https://www.google.com/maps/dir//Assist+Solutions+Corp,+3-8-2+Higashi+Azabu,+Minato-ku,+Tokyo"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="inline-flex items-center gap-2 text-primary font-medium hover:underline"
|
||||
>
|
||||
Get Directions
|
||||
<ExternalLink className="h-4 w-4" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Existing Customer CTA */}
|
||||
<div className="text-center mt-12 pt-8 border-t border-border/60">
|
||||
<p className="text-muted-foreground">
|
||||
Already have an account?{" "}
|
||||
<Link
|
||||
href="/auth/login"
|
||||
className="font-semibold text-primary hover:text-primary/80 hover:underline transition-colors"
|
||||
>
|
||||
Sign in
|
||||
</Link>{" "}
|
||||
to access your dashboard and support tickets.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user