diff --git a/apps/portal/src/app/(public)/(site)/blog/layout.tsx b/apps/portal/src/app/(public)/(site)/blog/layout.tsx new file mode 100644 index 00000000..4cbb618f --- /dev/null +++ b/apps/portal/src/app/(public)/(site)/blog/layout.tsx @@ -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; +} diff --git a/apps/portal/src/app/(public)/(site)/blog/page.tsx b/apps/portal/src/app/(public)/(site)/blog/page.tsx new file mode 100644 index 00000000..37f875cd --- /dev/null +++ b/apps/portal/src/app/(public)/(site)/blog/page.tsx @@ -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 ( +
+
+ {/* Sidebar */} + + + {/* Blog Grid */} +
+
+ {filteredPosts.map(post => ( +
+ + {/* Image */} +
+
+ + {post.title.charAt(0)} + +
+ {/* Hover overlay */} +
+
+ + {/* Category */} + + {post.categoryLabel} + + + {/* Title */} +

+ {post.title} +

+ + {/* Excerpt */} +

+ {post.excerpt} +

+ + {/* Author */} +
+
+ {post.author.name.charAt(0)} +
+
+

{post.author.name}

+

{post.author.role}

+
+
+ +
+ ))} +
+ + {/* Empty state */} + {filteredPosts.length === 0 && ( +
+

No posts found in this category.

+
+ )} +
+
+
+ ); +} diff --git a/apps/portal/src/app/(public)/(site)/contact/page.tsx b/apps/portal/src/app/(public)/(site)/contact/page.tsx index d767b2c8..64e4c02a 100644 --- a/apps/portal/src/app/(public)/(site)/contact/page.tsx +++ b/apps/portal/src/app/(public)/(site)/contact/page.tsx @@ -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", }, }; diff --git a/apps/portal/src/app/(public)/(site)/help/page.tsx b/apps/portal/src/app/(public)/(site)/help/page.tsx index dc45df1d..36d84e3e 100644 --- a/apps/portal/src/app/(public)/(site)/help/page.tsx +++ b/apps/portal/src/app/(public)/(site)/help/page.tsx @@ -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 ; +export default function PublicHelpPage() { + redirect("/contact"); } diff --git a/apps/portal/src/components/organisms/SiteFooter/SiteFooter.tsx b/apps/portal/src/components/organisms/SiteFooter/SiteFooter.tsx index b46808df..a5845c5a 100644 --- a/apps/portal/src/components/organisms/SiteFooter/SiteFooter.tsx +++ b/apps/portal/src/components/organisms/SiteFooter/SiteFooter.tsx @@ -94,15 +94,15 @@ export function SiteFooter() { href="/contact" className="text-muted-foreground hover:text-foreground transition-colors" > - Contact + Support & Contact
  • - Support + Blog
  • diff --git a/apps/portal/src/components/templates/PublicShell/PublicShell.tsx b/apps/portal/src/components/templates/PublicShell/PublicShell.tsx index 42e3ea08..81b8fb1d 100644 --- a/apps/portal/src/components/templates/PublicShell/PublicShell.tsx +++ b/apps/portal/src/components/templates/PublicShell/PublicShell.tsx @@ -175,12 +175,6 @@ export function PublicShell({ children }: PublicShellProps) { > About - - Contact - Support diff --git a/apps/portal/src/features/auth/components/SignupForm/SignupForm.tsx b/apps/portal/src/features/auth/components/SignupForm/SignupForm.tsx index d8104db7..44795c58 100644 --- a/apps/portal/src/features/auth/components/SignupForm/SignupForm.tsx +++ b/apps/portal/src/features/auth/components/SignupForm/SignupForm.tsx @@ -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) => { diff --git a/apps/portal/src/features/landing-page/views/PublicLandingView.tsx b/apps/portal/src/features/landing-page/views/PublicLandingView.tsx index b83aa379..f8d0f4b9 100644 --- a/apps/portal/src/features/landing-page/views/PublicLandingView.tsx +++ b/apps/portal/src/features/landing-page/views/PublicLandingView.tsx @@ -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: , 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: , 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: , 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: , 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: , 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: , href: "/services/onsite", - price: "From 5,000 JPY", }, ]; const isScrollingRef = useRef(false); @@ -251,8 +245,20 @@ export function PublicLandingView() { return (
    {/* Hero Section */} -
    -
    +
    + {/* Abstract gradient blobs */} +
    + {/* Top-left blob */} +
    + {/* Top-right blob */} +
    + {/* Bottom-left blob */} +
    + {/* Center-right accent */} +
    +
    + +

    One Stop Solution @@ -400,7 +406,6 @@ export function PublicLandingView() {

    {service.description}

    -

    {service.price}

    ))} diff --git a/apps/portal/src/features/marketing/views/AboutUsView.tsx b/apps/portal/src/features/marketing/views/AboutUsView.tsx index 69bfc170..b779ad8a 100644 --- a/apps/portal/src/features/marketing/views/AboutUsView.tsx +++ b/apps/portal/src/features/marketing/views/AboutUsView.tsx @@ -119,34 +119,51 @@ export function AboutUsView() { }, [computeScrollAmount]); return ( -
    - {/* Hero */} -
    -
    -

    About Us

    -
    -

    - 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. -

    -

    - 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. -

    +
    + {/* Hero with geometric pattern */} +
    + {/* Dot grid pattern */} +
    + {/* Subtle gradient overlay for depth */} +
    + +
    +
    +
    +

    + About Us +

    +
    +

    + 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. +

    +

    + 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. +

    +
    +
    +
    + Assist Solutions team in Tokyo +
    -
    - Assist Solutions team in Tokyo -
    {/* Business Solutions Carousel */} diff --git a/apps/portal/src/features/support/views/PublicContactView.tsx b/apps/portal/src/features/support/views/PublicContactView.tsx index 114e6c64..e8cdb455 100644 --- a/apps/portal/src/features/support/views/PublicContactView.tsx +++ b/apps/portal/src/features/support/views/PublicContactView.tsx @@ -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(null); + const [expandedFaq, setExpandedFaq] = useState(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 ( -
    -
    - +
    +
    +
    -

    Message Sent!

    -

    +

    Message Sent!

    +

    Thank you for contacting us. We'll get back to you within 24 hours.

    -