From 7dff7dc7285095517ac6187874f0bc4c2aee79e8 Mon Sep 17 00:00:00 2001
From: barsa
Date: Tue, 20 Jan 2026 19:40:55 +0900
Subject: [PATCH] refactor(auth): remove SignupForm and related steps, migrate
to new account creation flow
- Deleted SignupForm component and its associated steps (AccountStep, AddressStep, PasswordStep, ReviewStep).
- Removed references to SignupForm in index files and views.
- Updated MigrateAccountView to redirect to the new get-started flow.
- Adjusted PublicInternetConfigureView to use InlineGetStartedSection instead of InlineAuthSection.
- Cleaned up unused hooks and store methods related to WHMCS linking.
---
.../app/(public)/(site)/auth/migrate/page.tsx | 4 +-
apps/portal/src/core/api/index.ts | 1 -
.../auth/components/AuthModal/AuthModal.tsx | 140 ------
.../auth/components/AuthModal/index.ts | 1 -
.../InlineAuthSection/InlineAuthSection.tsx | 134 ------
.../LinkWhmcsForm/LinkWhmcsForm.tsx | 86 ----
.../auth/components/LoginForm/LoginForm.tsx | 4 +-
.../SetPasswordForm/SetPasswordForm.tsx | 4 +-
.../components/SignupForm/MultiStepForm.tsx | 122 -----
.../auth/components/SignupForm/SignupForm.tsx | 430 ------------------
.../auth/components/SignupForm/index.ts | 3 -
.../SignupForm/steps/AccountStep.tsx | 178 --------
.../SignupForm/steps/AddressStep.tsx | 182 --------
.../SignupForm/steps/PasswordStep.tsx | 166 -------
.../SignupForm/steps/ReviewStep.tsx | 225 ---------
.../auth/components/SignupForm/steps/index.ts | 4 -
.../src/features/auth/components/index.ts | 3 -
apps/portal/src/features/auth/hooks/index.ts | 1 -
.../src/features/auth/hooks/use-auth.ts | 18 -
.../src/features/auth/stores/auth.store.ts | 28 --
.../auth/views/MigrateAccountView.tsx | 104 -----
.../features/auth/views/SetPasswordView.tsx | 4 +-
.../src/features/auth/views/SignupView.tsx | 31 --
apps/portal/src/features/auth/views/index.ts | 2 -
.../views/PublicInternetConfigure.tsx | 7 +-
25 files changed, 12 insertions(+), 1870 deletions(-)
delete mode 100644 apps/portal/src/features/auth/components/AuthModal/AuthModal.tsx
delete mode 100644 apps/portal/src/features/auth/components/AuthModal/index.ts
delete mode 100644 apps/portal/src/features/auth/components/InlineAuthSection/InlineAuthSection.tsx
delete mode 100644 apps/portal/src/features/auth/components/LinkWhmcsForm/LinkWhmcsForm.tsx
delete mode 100644 apps/portal/src/features/auth/components/SignupForm/MultiStepForm.tsx
delete mode 100644 apps/portal/src/features/auth/components/SignupForm/SignupForm.tsx
delete mode 100644 apps/portal/src/features/auth/components/SignupForm/index.ts
delete mode 100644 apps/portal/src/features/auth/components/SignupForm/steps/AccountStep.tsx
delete mode 100644 apps/portal/src/features/auth/components/SignupForm/steps/AddressStep.tsx
delete mode 100644 apps/portal/src/features/auth/components/SignupForm/steps/PasswordStep.tsx
delete mode 100644 apps/portal/src/features/auth/components/SignupForm/steps/ReviewStep.tsx
delete mode 100644 apps/portal/src/features/auth/components/SignupForm/steps/index.ts
delete mode 100644 apps/portal/src/features/auth/views/MigrateAccountView.tsx
delete mode 100644 apps/portal/src/features/auth/views/SignupView.tsx
diff --git a/apps/portal/src/app/(public)/(site)/auth/migrate/page.tsx b/apps/portal/src/app/(public)/(site)/auth/migrate/page.tsx
index 97b8450a..67803013 100644
--- a/apps/portal/src/app/(public)/(site)/auth/migrate/page.tsx
+++ b/apps/portal/src/app/(public)/(site)/auth/migrate/page.tsx
@@ -1,5 +1,5 @@
-import { MigrateAccountView } from "@/features/auth/views/MigrateAccountView";
+import { redirect } from "next/navigation";
export default function MigrateAccountPage() {
- return ;
+ redirect("/auth/get-started");
}
diff --git a/apps/portal/src/core/api/index.ts b/apps/portal/src/core/api/index.ts
index 01494fe4..bc41194f 100644
--- a/apps/portal/src/core/api/index.ts
+++ b/apps/portal/src/core/api/index.ts
@@ -25,7 +25,6 @@ export * from "./response-helpers";
const AUTH_ENDPOINTS = [
"/api/auth/login",
"/api/auth/signup",
- "/api/auth/migrate",
"/api/auth/set-password",
"/api/auth/reset-password",
"/api/auth/check-password-needed",
diff --git a/apps/portal/src/features/auth/components/AuthModal/AuthModal.tsx b/apps/portal/src/features/auth/components/AuthModal/AuthModal.tsx
deleted file mode 100644
index bd65a7d5..00000000
--- a/apps/portal/src/features/auth/components/AuthModal/AuthModal.tsx
+++ /dev/null
@@ -1,140 +0,0 @@
-"use client";
-
-import { useState, useEffect } from "react";
-import { XMarkIcon } from "@heroicons/react/24/outline";
-import { SignupForm } from "../SignupForm/SignupForm";
-import { LoginForm } from "../LoginForm/LoginForm";
-import { useAuthStore } from "../../stores/auth.store";
-import { useRouter } from "next/navigation";
-
-interface AuthModalProps {
- isOpen: boolean;
- onClose: () => void;
- initialMode?: "signup" | "login" | undefined;
- redirectTo?: string | undefined;
- title?: string | undefined;
- description?: string | undefined;
- showCloseButton?: boolean | undefined;
-}
-
-export function AuthModal({
- isOpen,
- onClose,
- initialMode = "signup",
- redirectTo,
- title,
- description,
- showCloseButton = true,
-}: AuthModalProps) {
- const [mode, setMode] = useState<"signup" | "login">(initialMode);
- const router = useRouter();
- const isAuthenticated = useAuthStore(state => state.isAuthenticated);
- const hasCheckedAuth = useAuthStore(state => state.hasCheckedAuth);
-
- // Update mode when initialMode changes
- useEffect(() => {
- setMode(initialMode);
- }, [initialMode]);
-
- // Close modal and redirect when authenticated
- useEffect(() => {
- if (isOpen && hasCheckedAuth && isAuthenticated && redirectTo) {
- onClose();
- router.push(redirectTo);
- }
- }, [isOpen, hasCheckedAuth, isAuthenticated, redirectTo, onClose, router]);
-
- if (!isOpen) return null;
-
- const defaultTitle = mode === "signup" ? "Create your account" : "Sign in to continue";
- const defaultDescription =
- mode === "signup"
- ? "Create an account to continue with your order and access personalized plans."
- : "Sign in to your account to continue with your order.";
-
- return (
- {
- if (e.target === e.currentTarget) {
- onClose();
- }
- }}
- >
- {/* Backdrop */}
-
-
- {/* Modal */}
-
e.stopPropagation()}
- >
-
-
-
{title || defaultTitle}
-
- {description || defaultDescription}
-
-
- {showCloseButton && (
-
- )}
-
-
-
- {mode === "signup" ? (
-
{
- // Will be handled by useEffect above
- }}
- />
- ) : (
- {
- // Will be handled by useEffect above
- }}
- showSignupLink={false}
- />
- )}
-
- {/* Toggle between signup and login */}
-
- {mode === "signup" ? (
-
- Already have an account?{" "}
-
-
- ) : (
-
- Don't have an account?{" "}
-
-
- )}
-
-
-
-
- );
-}
diff --git a/apps/portal/src/features/auth/components/AuthModal/index.ts b/apps/portal/src/features/auth/components/AuthModal/index.ts
deleted file mode 100644
index 11ee2cc1..00000000
--- a/apps/portal/src/features/auth/components/AuthModal/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { AuthModal } from "./AuthModal";
diff --git a/apps/portal/src/features/auth/components/InlineAuthSection/InlineAuthSection.tsx b/apps/portal/src/features/auth/components/InlineAuthSection/InlineAuthSection.tsx
deleted file mode 100644
index fba5ceeb..00000000
--- a/apps/portal/src/features/auth/components/InlineAuthSection/InlineAuthSection.tsx
+++ /dev/null
@@ -1,134 +0,0 @@
-"use client";
-
-import { useState } from "react";
-import { useRouter } from "next/navigation";
-import { Button } from "@/components/atoms/button";
-import { SignupForm } from "../SignupForm/SignupForm";
-import { LoginForm } from "../LoginForm/LoginForm";
-import { LinkWhmcsForm } from "../LinkWhmcsForm/LinkWhmcsForm";
-import { getSafeRedirect } from "@/features/auth/utils/route-protection";
-
-interface HighlightItem {
- title: string;
- description: string;
-}
-
-interface InlineAuthSectionProps {
- title: string;
- description?: string | undefined;
- redirectTo?: string | undefined;
- initialMode?: "signup" | "login" | undefined;
- highlights?: HighlightItem[] | undefined;
- className?: string | undefined;
-}
-
-export function InlineAuthSection({
- title,
- description,
- redirectTo,
- initialMode = "signup",
- highlights = [],
- className = "",
-}: InlineAuthSectionProps) {
- const router = useRouter();
- const [mode, setMode] = useState<"signup" | "login" | "migrate">(initialMode);
- const safeRedirect = getSafeRedirect(redirectTo, "/account");
-
- return (
-
-
-
{title}
- {description && (
-
{description}
- )}
-
-
-
-
-
-
-
-
-
-
-
-
- {mode === "signup" && (
- <>
-
Create your account
-
- Set up your portal access in a few simple steps.
-
-
- >
- )}
- {mode === "login" && (
- <>
-
Sign in
-
Access your account to continue.
-
- >
- )}
- {mode === "migrate" && (
- <>
-
Migrate your account
-
- Use your legacy portal credentials to transfer your account.
-
-
{
- if (result.needsPasswordSet) {
- const params = new URLSearchParams({
- email: result.user.email,
- redirect: safeRedirect,
- });
- router.push(`/auth/set-password?${params.toString()}`);
- return;
- }
- router.push(safeRedirect);
- }}
- />
- >
- )}
-
-
-
- {highlights.length > 0 && (
-
-
- {highlights.map(item => (
-
-
{item.title}
-
{item.description}
-
- ))}
-
-
- )}
-
- );
-}
diff --git a/apps/portal/src/features/auth/components/LinkWhmcsForm/LinkWhmcsForm.tsx b/apps/portal/src/features/auth/components/LinkWhmcsForm/LinkWhmcsForm.tsx
deleted file mode 100644
index 86d4fd59..00000000
--- a/apps/portal/src/features/auth/components/LinkWhmcsForm/LinkWhmcsForm.tsx
+++ /dev/null
@@ -1,86 +0,0 @@
-/**
- * Link WHMCS Form - Account migration form using domain schema
- */
-
-"use client";
-
-import { Button, Input, ErrorMessage } from "@/components/atoms";
-import { FormField } from "@/components/molecules/FormField/FormField";
-import { useWhmcsLink } from "@/features/auth/hooks";
-import { linkWhmcsRequestSchema, type LinkWhmcsResponse } from "@customer-portal/domain/auth";
-import { useZodForm } from "@/shared/hooks";
-
-interface LinkWhmcsFormProps {
- onTransferred?: ((result: LinkWhmcsResponse) => void) | undefined;
- className?: string | undefined;
- initialEmail?: string | undefined;
-}
-
-export function LinkWhmcsForm({ onTransferred, className = "", initialEmail }: LinkWhmcsFormProps) {
- const { linkWhmcs, loading, error, clearError } = useWhmcsLink();
-
- const form = useZodForm({
- schema: linkWhmcsRequestSchema,
- initialValues: { email: initialEmail ?? "", password: "" },
- onSubmit: async data => {
- clearError();
- const result = await linkWhmcs(data);
- onTransferred?.(result);
- },
- });
-
- const isLoading = form.isSubmitting || loading;
-
- return (
-
- );
-}
diff --git a/apps/portal/src/features/auth/components/LoginForm/LoginForm.tsx b/apps/portal/src/features/auth/components/LoginForm/LoginForm.tsx
index 628145d7..1b43e2f5 100644
--- a/apps/portal/src/features/auth/components/LoginForm/LoginForm.tsx
+++ b/apps/portal/src/features/auth/components/LoginForm/LoginForm.tsx
@@ -171,10 +171,10 @@ export function LoginForm({
Existing customer?{" "}
- Migrate your account
+ Transfer your account
diff --git a/apps/portal/src/features/auth/components/SetPasswordForm/SetPasswordForm.tsx b/apps/portal/src/features/auth/components/SetPasswordForm/SetPasswordForm.tsx
index e713b001..0721abe7 100644
--- a/apps/portal/src/features/auth/components/SetPasswordForm/SetPasswordForm.tsx
+++ b/apps/portal/src/features/auth/components/SetPasswordForm/SetPasswordForm.tsx
@@ -8,7 +8,7 @@ import { useEffect } from "react";
import Link from "next/link";
import { Button, Input, ErrorMessage } from "@/components/atoms";
import { FormField } from "@/components/molecules/FormField/FormField";
-import { useWhmcsLink } from "../../hooks/use-auth";
+import { useAuth } from "../../hooks/use-auth";
import { useZodForm } from "@/shared/hooks";
import {
setPasswordRequestSchema,
@@ -38,7 +38,7 @@ export function SetPasswordForm({
onError,
className = "",
}: SetPasswordFormProps) {
- const { setPassword, loading, error, clearError } = useWhmcsLink();
+ const { setPassword, loading, error, clearError } = useAuth();
const form = useZodForm({
schema: setPasswordFormSchema,
diff --git a/apps/portal/src/features/auth/components/SignupForm/MultiStepForm.tsx b/apps/portal/src/features/auth/components/SignupForm/MultiStepForm.tsx
deleted file mode 100644
index 850790e9..00000000
--- a/apps/portal/src/features/auth/components/SignupForm/MultiStepForm.tsx
+++ /dev/null
@@ -1,122 +0,0 @@
-/**
- * Multi-Step Form Wrapper
- * Clean, modern UI for multi-step signup forms
- */
-
-"use client";
-
-import { useEffect, type ReactNode } from "react";
-import { Button } from "@/components/atoms";
-import { CheckIcon } from "@heroicons/react/24/solid";
-
-export interface FormStep {
- key: string;
- title: string;
- description: string;
- content: ReactNode;
- isValid?: boolean;
-}
-
-interface MultiStepFormProps {
- steps: FormStep[];
- currentStep: number;
- onNext: () => void;
- onPrevious: () => void;
- isLastStep: boolean;
- isSubmitting?: boolean;
- canProceed?: boolean;
- onStepChange?: (stepIndex: number) => void;
- className?: string;
-}
-
-export function MultiStepForm({
- steps,
- currentStep,
- onNext,
- onPrevious,
- isLastStep,
- isSubmitting = false,
- canProceed = true,
- onStepChange,
- className = "",
-}: MultiStepFormProps) {
- useEffect(() => {
- onStepChange?.(currentStep);
- }, [currentStep, onStepChange]);
-
- const step = steps[currentStep] ?? steps[0];
- const isFirstStep = currentStep === 0;
- const disableNext = isSubmitting || (!canProceed && !isLastStep);
-
- return (
-
- {/* Simple Step Indicators */}
-
- {steps.map((s, idx) => {
- const isCompleted = idx < currentStep;
- const isCurrent = idx === currentStep;
-
- return (
-
-
- {isCompleted ? : idx + 1}
-
- {idx < steps.length - 1 && (
-
- )}
-
- );
- })}
-
-
- {/* Step Title & Description */}
-
-
{step?.title}
-
{step?.description}
-
-
- {/* Step Content */}
-
{step?.content}
-
- {/* Navigation Buttons */}
-
-
-
-
-
-
- );
-}
diff --git a/apps/portal/src/features/auth/components/SignupForm/SignupForm.tsx b/apps/portal/src/features/auth/components/SignupForm/SignupForm.tsx
deleted file mode 100644
index ad701f90..00000000
--- a/apps/portal/src/features/auth/components/SignupForm/SignupForm.tsx
+++ /dev/null
@@ -1,430 +0,0 @@
-/**
- * Signup Form - Multi-step signup for Japanese customers
- * Uses domain schemas from @customer-portal/domain
- */
-
-"use client";
-
-import { useState, useCallback, useEffect, useRef } from "react";
-import { flushSync } from "react-dom";
-import Link from "next/link";
-import { useSearchParams } from "next/navigation";
-import { ErrorMessage } from "@/components/atoms";
-import { useSignupWithRedirect } from "../../hooks/use-auth";
-import { signupInputSchema, buildSignupRequest } from "@customer-portal/domain/auth";
-import { genderEnum } from "@customer-portal/domain/common";
-import { addressFormSchema } from "@customer-portal/domain/customer";
-import { useZodForm } from "@/shared/hooks";
-import { z } from "zod";
-import { getSafeRedirect } from "@/features/auth/utils/route-protection";
-import { formatJapanesePostalCode } from "@/shared/constants";
-
-import { MultiStepForm } from "./MultiStepForm";
-import { AccountStep } from "./steps/AccountStep";
-import { AddressStepJapan } from "@/features/address";
-import { PasswordStep } from "./steps/PasswordStep";
-
-/**
- * Frontend signup form schema
- * Extends the domain signupInputSchema with:
- * - confirmPassword: UI-only field for password confirmation
- * - phoneCountryCode: Separate field for country code input
- * - address: Required addressFormSchema (domain schema makes it optional)
- * - dateOfBirth: Required for signup (domain schema makes it optional)
- * - gender: Required for signup (domain schema makes it optional)
- */
-const genderSchema = genderEnum;
-
-const signupAddressSchema = addressFormSchema.extend({
- address2: z
- .string()
- .min(1, "Address line 2 is required")
- .max(200, "Address line 2 is too long")
- .trim(),
-});
-
-const signupFormBaseSchema = signupInputSchema.omit({ sfNumber: true }).extend({
- confirmPassword: z.string().min(1, "Please confirm your password"),
- phoneCountryCode: z.string().regex(/^\+\d{1,4}$/, "Enter a valid country code (e.g., +81)"),
- address: signupAddressSchema,
- dateOfBirth: z.string().min(1, "Date of birth is required"),
- gender: genderSchema,
-});
-
-const signupFormSchema = signupFormBaseSchema
- .refine(data => data.acceptTerms === true, {
- message: "You must accept the terms and conditions",
- path: ["acceptTerms"],
- })
- .refine(data => data.password === data.confirmPassword, {
- message: "Passwords do not match",
- path: ["confirmPassword"],
- });
-
-type SignupFormData = z.infer;
-type SignupAddress = SignupFormData["address"];
-
-interface SignupFormProps {
- onSuccess?: (() => void) | undefined;
- onError?: ((error: string) => void) | undefined;
- className?: string | undefined;
- redirectTo?: string | undefined;
- initialEmail?: string | undefined;
- showFooterLinks?: boolean | undefined;
-}
-
-const STEPS = [
- {
- key: "account",
- title: "Account Details",
- description: "Your contact information",
- },
- {
- key: "address",
- title: "Address",
- description: "Used for service eligibility and delivery",
- },
- {
- key: "security",
- title: "Security & Terms",
- description: "Create a password and confirm agreements",
- },
-] as const;
-
-const STEP_FIELD_KEYS: Record<(typeof STEPS)[number]["key"], Array> = {
- account: ["firstName", "lastName", "email", "phone", "phoneCountryCode", "dateOfBirth", "gender"],
- address: ["address"],
- security: ["password", "confirmPassword", "acceptTerms", "marketingConsent"],
-};
-
-const STEP_VALIDATION_SCHEMAS: Record<(typeof STEPS)[number]["key"], z.ZodTypeAny | undefined> = {
- account: signupFormBaseSchema.pick({
- firstName: true,
- lastName: true,
- email: true,
- phone: true,
- phoneCountryCode: true,
- dateOfBirth: true,
- gender: true,
- }),
- address: signupFormBaseSchema.pick({
- address: true,
- }),
- security: signupFormBaseSchema
- .pick({
- password: true,
- confirmPassword: true,
- acceptTerms: true,
- })
- .refine(data => data.password === data.confirmPassword, {
- message: "Passwords do not match",
- path: ["confirmPassword"],
- })
- .refine(data => data.acceptTerms === true, {
- message: "You must accept the terms and conditions",
- path: ["acceptTerms"],
- }),
-};
-
-export function SignupForm({
- onSuccess,
- onError,
- className = "",
- redirectTo,
- initialEmail,
- showFooterLinks = true,
-}: SignupFormProps) {
- const formRef = useRef(null);
- const searchParams = useSearchParams();
- const [step, setStep] = useState(0);
- const redirectFromQuery = searchParams?.get("next") || searchParams?.get("redirect");
- const redirect = getSafeRedirect(redirectTo || redirectFromQuery, "");
- const redirectQuery = redirect ? `?redirect=${encodeURIComponent(redirect)}` : "";
- const { signup, loading, error, clearError } = useSignupWithRedirect(
- redirect ? { redirectTo: redirect } : undefined
- );
-
- const form = useZodForm({
- schema: signupFormSchema,
- initialValues: {
- firstName: "",
- lastName: "",
- email: initialEmail ?? "",
- phone: "",
- phoneCountryCode: "+81",
- company: "",
- dateOfBirth: "",
- gender: "" as unknown as "male" | "female" | "other", // Will be validated on submit
- address: {
- address1: "",
- address2: "",
- city: "",
- state: "",
- postcode: "",
- country: "JP",
- countryCode: "JP",
- },
- password: "",
- confirmPassword: "",
- acceptTerms: false,
- marketingConsent: false,
- },
- onSubmit: async data => {
- clearError();
- try {
- // Combine country code + phone for WHMCS format: +CC.NNNNNNNN
- const countryDigits = data.phoneCountryCode.replace(/\D/g, "");
- const phoneDigits = data.phone.replace(/\D/g, "");
- const formattedPhone = `+${countryDigits}.${phoneDigits}`;
-
- // Build request with normalized address and phone
- // Exclude UI-only fields (confirmPassword) from the request
- const { confirmPassword: _confirmPassword, ...requestData } = data;
- const request = buildSignupRequest({
- ...requestData,
- phone: formattedPhone,
- dateOfBirth: data.dateOfBirth || undefined,
- gender: data.gender || undefined,
- address: {
- ...data.address,
- country: "JP",
- countryCode: "JP",
- },
- });
- await signup(request);
- onSuccess?.();
- } catch (err) {
- onError?.(err instanceof Error ? err.message : "Signup failed");
- throw err;
- }
- },
- });
-
- const {
- values,
- errors,
- touched,
- setValue: setFormValue,
- setTouchedField: setFormTouchedField,
- handleSubmit,
- 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 syncStepValues = useCallback(
- (shouldFlush = true) => {
- const formNode = formRef.current;
- if (!formNode) {
- return values;
- }
-
- const nextValues: SignupFormData = {
- ...values,
- address: { ...values.address },
- };
-
- const fields = formNode.querySelectorAll(
- "[data-field]"
- );
- for (const field of fields) {
- const key = field.dataset["field"];
- if (!key) {
- continue;
- }
- const normalized = normalizeAutofillValue(key, field.value);
- if (key.startsWith("address.")) {
- const addressKey = key.replace("address.", "") as keyof SignupAddress;
- nextValues.address[addressKey] = normalized;
- } else if (key === "acceptTerms" || key === "marketingConsent") {
- // Handle boolean fields separately
- const boolValue =
- field.type === "checkbox" ? (field as HTMLInputElement).checked : normalized === "true";
- (nextValues as Record)[key] = boolValue;
- } else {
- // Only assign to string fields
- const stringKey = key as keyof Pick<
- SignupFormData,
- Exclude
- >;
- (nextValues as Record)[stringKey] = normalized;
- }
- }
-
- const applySyncedValues = () => {
- for (const key of Object.keys(nextValues) as Array) {
- if (key === "address") {
- continue;
- }
- if (nextValues[key] !== values[key]) {
- setFormValue(key, nextValues[key]);
- }
- }
-
- const addressChanged = (Object.keys(nextValues.address) as Array).some(
- key => nextValues.address[key] !== values.address[key]
- );
- if (addressChanged) {
- setFormValue("address", nextValues.address);
- }
- };
-
- if (shouldFlush) {
- flushSync(() => {
- applySyncedValues();
- });
- } else {
- applySyncedValues();
- }
-
- return nextValues;
- },
- [normalizeAutofillValue, setFormValue, values]
- );
-
- useEffect(() => {
- const syncTimer = window.setTimeout(() => {
- syncStepValues(false);
- }, 0);
-
- return () => {
- window.clearTimeout(syncTimer);
- };
- }, [step, syncStepValues]);
-
- const isLastStep = step === STEPS.length - 1;
-
- const markStepTouched = useCallback(
- (stepIndex: number) => {
- const stepKey = STEPS[stepIndex]?.key;
- if (!stepKey) {
- return;
- }
- const fields = STEP_FIELD_KEYS[stepKey] ?? [];
- for (const field of fields) setFormTouchedField(field);
- },
- [setFormTouchedField]
- );
-
- const isStepValid = useCallback(
- (stepIndex: number, data: SignupFormData = values) => {
- const stepKey = STEPS[stepIndex]?.key;
- if (!stepKey) {
- return true;
- }
- const schema = STEP_VALIDATION_SCHEMAS[stepKey];
- if (!schema) {
- return true;
- }
- return schema.safeParse(data).success;
- },
- [values]
- );
-
- const handleNext = useCallback(() => {
- const syncedValues = syncStepValues();
- markStepTouched(step);
-
- if (isLastStep) {
- void handleSubmit();
- return;
- }
-
- if (!isStepValid(step, syncedValues)) {
- return;
- }
-
- setStep(s => Math.min(s + 1, STEPS.length - 1));
- }, [handleSubmit, isLastStep, isStepValid, markStepTouched, step, syncStepValues]);
-
- const handlePrevious = useCallback(() => {
- setStep(s => Math.max(0, s - 1));
- }, []);
-
- // Wrap form methods to have generic types for step components
- const formProps = {
- values,
- errors,
- touched,
- setValue: (field: string, value: unknown) =>
- setFormValue(field as keyof SignupFormData, value as never),
- setTouchedField: (field: string) => setFormTouchedField(field as keyof SignupFormData),
- };
-
- const stepContent = [
- ,
- ,
- ,
- ];
-
- const steps = STEPS.map((s, i) => ({
- ...s,
- content: stepContent[i],
- }));
-
- return (
-
-
-
- {error && (
-
- {error}
-
- )}
-
- {showFooterLinks && (
-
-
- Already have an account?{" "}
-
- Sign in
-
-
-
- Existing customer?{" "}
-
- Migrate your account
-
-
-
- )}
-
- );
-}
diff --git a/apps/portal/src/features/auth/components/SignupForm/index.ts b/apps/portal/src/features/auth/components/SignupForm/index.ts
deleted file mode 100644
index 7aec3070..00000000
--- a/apps/portal/src/features/auth/components/SignupForm/index.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export { SignupForm } from "./SignupForm";
-export { MultiStepForm } from "./MultiStepForm";
-export * from "./steps";
diff --git a/apps/portal/src/features/auth/components/SignupForm/steps/AccountStep.tsx b/apps/portal/src/features/auth/components/SignupForm/steps/AccountStep.tsx
deleted file mode 100644
index 2ffe8f93..00000000
--- a/apps/portal/src/features/auth/components/SignupForm/steps/AccountStep.tsx
+++ /dev/null
@@ -1,178 +0,0 @@
-/**
- * Account Step - Contact info
- */
-
-"use client";
-
-import { Input } from "@/components/atoms";
-import { FormField } from "@/components/molecules/FormField/FormField";
-import { genderEnum } from "@customer-portal/domain/common";
-
-interface AccountStepProps {
- form: {
- values: {
- firstName: string;
- lastName: string;
- email: string;
- phone: string;
- phoneCountryCode: string;
- company?: string | undefined;
- dateOfBirth?: string | undefined;
- gender?: "male" | "female" | "other" | undefined;
- };
- errors: Record;
- touched: Record;
- setValue: (field: string, value: unknown) => void;
- setTouchedField: (field: string) => void;
- };
-}
-
-export function AccountStep({ form }: AccountStepProps) {
- const { values, errors, touched, setValue, setTouchedField } = form;
- const getError = (field: string) => (touched[field] ? errors[field] : undefined);
- const genderOptions = genderEnum.options;
- const formatGender = (value: string) => value.charAt(0).toUpperCase() + value.slice(1);
-
- return (
-
- {/* Name Fields */}
-
-
- setValue("firstName", e.target.value)}
- onBlur={() => setTouchedField("firstName")}
- placeholder="Taro"
- autoComplete="section-signup given-name"
- autoFocus
- data-field="firstName"
- />
-
-
- setValue("lastName", e.target.value)}
- onBlur={() => setTouchedField("lastName")}
- placeholder="Yamada"
- autoComplete="section-signup family-name"
- data-field="lastName"
- />
-
-
-
- {/* Email */}
-
- setValue("email", e.target.value)}
- onBlur={() => setTouchedField("email")}
- placeholder="taro.yamada@example.com"
- autoComplete="section-signup email"
- data-field="email"
- />
-
-
- {/* Phone - Country code + number */}
-
-
- {
- // Allow + and digits only, max 5 chars
- let val = e.target.value.replace(/[^\d+]/g, "");
- if (!val.startsWith("+")) val = "+" + val.replace(/\+/g, "");
- if (val.length > 5) val = val.slice(0, 5);
- setValue("phoneCountryCode", val);
- }}
- onBlur={() => setTouchedField("phoneCountryCode")}
- placeholder="+81"
- autoComplete="section-signup tel-country-code"
- className="w-20 text-center"
- data-field="phoneCountryCode"
- />
- {
- // Only allow digits
- const cleaned = e.target.value.replace(/\D/g, "");
- setValue("phone", cleaned);
- }}
- onBlur={() => setTouchedField("phone")}
- placeholder="9012345678"
- autoComplete="section-signup tel-national"
- className="flex-1"
- data-field="phone"
- />
-
-
-
- {/* DOB + Gender (Required) */}
-
-
- setValue("dateOfBirth", e.target.value || undefined)}
- onBlur={() => setTouchedField("dateOfBirth")}
- autoComplete="section-signup bday"
- data-field="dateOfBirth"
- />
-
-
-
-
-
-
-
- {/* Company (Optional) */}
-
- setValue("company", e.target.value)}
- onBlur={() => setTouchedField("company")}
- placeholder="Company name"
- autoComplete="section-signup organization"
- data-field="company"
- />
-
-
- );
-}
diff --git a/apps/portal/src/features/auth/components/SignupForm/steps/AddressStep.tsx b/apps/portal/src/features/auth/components/SignupForm/steps/AddressStep.tsx
deleted file mode 100644
index 1fed145f..00000000
--- a/apps/portal/src/features/auth/components/SignupForm/steps/AddressStep.tsx
+++ /dev/null
@@ -1,182 +0,0 @@
-/**
- * Address Step - Japanese address input for WHMCS
- *
- * Field mapping to WHMCS:
- * - postcode → postcode
- * - state → state (prefecture)
- * - city → city
- * - address1 → address1 (building/room)
- * - address2 → address2 (street/block)
- * - country → "JP"
- */
-
-"use client";
-
-import { useCallback, useEffect } from "react";
-import { ChevronDown } from "lucide-react";
-import { Input } from "@/components/atoms";
-import { FormField } from "@/components/molecules/FormField/FormField";
-import { JAPAN_PREFECTURES, formatJapanesePostalCode } from "@/shared/constants";
-
-interface AddressData {
- address1: string;
- address2: string;
- city: string;
- state: string;
- postcode: string;
- country: string;
- countryCode?: string | undefined;
-}
-
-interface AddressStepProps {
- form: {
- values: { address: AddressData };
- errors: Record;
- touched: Record;
- setValue: (field: string, value: unknown) => void;
- setTouchedField: (field: string) => void;
- };
-}
-
-export function AddressStep({ form }: AddressStepProps) {
- const { values, errors, touched, setValue, setTouchedField } = form;
- const address = values.address;
-
- const getError = (field: string) => {
- const key = `address.${field}`;
- return touched[key] || touched["address"] ? (errors[key] ?? errors[field]) : undefined;
- };
-
- const updateAddress = useCallback(
- (field: keyof AddressData, value: string) => {
- setValue("address", { ...address, [field]: value });
- },
- [address, setValue]
- );
-
- const handlePostcodeChange = useCallback(
- (e: React.ChangeEvent) => {
- const formatted = formatJapanesePostalCode(e.target.value);
- updateAddress("postcode", formatted);
- },
- [updateAddress]
- );
-
- const markTouched = () => setTouchedField("address");
-
- // Set Japan as default country on mount if empty
- useEffect(() => {
- if (!address.country) {
- setValue("address", { ...address, country: "JP", countryCode: "JP" });
- }
- }, [address, setValue]);
-
- return (
-
- );
-}
diff --git a/apps/portal/src/features/auth/components/SignupForm/steps/PasswordStep.tsx b/apps/portal/src/features/auth/components/SignupForm/steps/PasswordStep.tsx
deleted file mode 100644
index 3c949477..00000000
--- a/apps/portal/src/features/auth/components/SignupForm/steps/PasswordStep.tsx
+++ /dev/null
@@ -1,166 +0,0 @@
-/**
- * Password Step - Password creation with strength indicator
- */
-
-"use client";
-
-import Link from "next/link";
-import { Input } from "@/components/atoms";
-import { FormField } from "@/components/molecules/FormField/FormField";
-import { checkPasswordStrength, getPasswordStrengthDisplay } from "@customer-portal/domain/auth";
-
-interface PasswordStepProps {
- form: {
- values: {
- email: string;
- password: string;
- confirmPassword: string;
- acceptTerms: boolean;
- marketingConsent?: boolean | undefined;
- };
- errors: Record;
- touched: Record;
- setValue: (field: string, value: unknown) => void;
- setTouchedField: (field: string) => void;
- };
-}
-
-export function PasswordStep({ form }: PasswordStepProps) {
- const { values, errors, touched, setValue, setTouchedField } = form;
- const { requirements, strength, isValid } = checkPasswordStrength(values.password);
- const { label, colorClass } = getPasswordStrengthDisplay(strength);
- const passwordsMatch = values.password === values.confirmPassword;
-
- return (
-
- {/* Hidden email field for browser password manager to associate credentials */}
-
-
-
- setValue("password", e.target.value)}
- onBlur={() => setTouchedField("password")}
- placeholder="Create a secure password"
- autoComplete="section-signup new-password"
- data-field="password"
- />
-
-
- {values.password && (
-
-
-
- {requirements.map(r => (
-
-
- {r.met ? "✓" : "○"}
-
- {r.label}
-
- ))}
-
-
- )}
-
-
- setValue("confirmPassword", e.target.value)}
- onBlur={() => setTouchedField("confirmPassword")}
- placeholder="Re-enter your password"
- autoComplete="section-signup new-password"
- data-field="confirmPassword"
- />
-
-
- {values.confirmPassword && (
-
- {passwordsMatch ? "✓ Passwords match" : "✗ Passwords do not match"}
-
- )}
-
-
-
- );
-}
diff --git a/apps/portal/src/features/auth/components/SignupForm/steps/ReviewStep.tsx b/apps/portal/src/features/auth/components/SignupForm/steps/ReviewStep.tsx
deleted file mode 100644
index a677314b..00000000
--- a/apps/portal/src/features/auth/components/SignupForm/steps/ReviewStep.tsx
+++ /dev/null
@@ -1,225 +0,0 @@
-/**
- * Review Step - Summary and terms acceptance
- */
-
-"use client";
-
-import Link from "next/link";
-
-type FormErrors = Record;
-
-/** Format field names for display (e.g., "address.city" → "City") */
-function formatFieldName(field: string): string {
- return field
- .replace("address.", "")
- .replace(/([A-Z])/g, " $1")
- .replace(/^./, s => s.toUpperCase())
- .trim();
-}
-
-/** Display validation errors from previous steps */
-function ValidationErrors({ errors }: { errors: FormErrors }) {
- // Collect errors excluding acceptTerms (shown inline) and _form (shown separately)
- const fieldErrors = Object.entries(errors)
- .filter(([key, value]) => value && key !== "acceptTerms" && key !== "_form")
- .map(([key, value]) => ({ field: key, message: value }));
-
- const hasErrors = fieldErrors.length > 0 || errors["_form"];
- if (!hasErrors) return null;
-
- return (
-
-
Please fix the following errors:
-
- {errors["_form"] && - {errors["_form"]}
}
- {fieldErrors.map(({ field, message }) => (
- -
- {formatFieldName(field)}: {message}
-
- ))}
-
-
- );
-}
-
-/** Ready message shown when form is valid */
-function ReadyMessage({ errors }: { errors: FormErrors }) {
- const hasErrors = Object.values(errors).some(Boolean);
- if (hasErrors) return null;
-
- return (
-
-
🚀
-
-
Ready to create your account!
-
- Click "Create Account" below to complete your registration.
-
-
-
- );
-}
-
-interface ReviewStepProps {
- form: {
- values: {
- firstName: string;
- lastName: string;
- email: string;
- phone: string;
- phoneCountryCode: string;
- company?: string;
- dateOfBirth?: string;
- gender?: "male" | "female" | "other";
- address: {
- address1: string;
- address2: string;
- city: string;
- state: string;
- postcode: string;
- country: string;
- };
- acceptTerms: boolean;
- marketingConsent?: boolean;
- };
- errors: Record;
- touched: Record;
- setValue: (field: string, value: unknown) => void;
- setTouchedField: (field: string) => void;
- };
-}
-
-export function ReviewStep({ form }: ReviewStepProps) {
- const { values, errors, setValue, setTouchedField } = form;
- const address = values.address;
-
- // Format address for display
- const formattedAddress = [
- address.address2,
- address.address1,
- address.city,
- address.state,
- address.postcode,
- ]
- .filter(Boolean)
- .join(", ");
-
- return (
-
- {/* Account Summary */}
-
-
-
- ✓
-
- Account Summary
-
-
-
-
- Name
- -
- {values.firstName} {values.lastName}
-
-
-
-
- Email
- - {values.email}
-
-
-
- Phone
- -
- {values.phoneCountryCode} {values.phone}
-
-
- {values.company && (
-
-
- Company
- - {values.company}
-
- )}
- {values.dateOfBirth && (
-
-
- Date of Birth
- - {values.dateOfBirth}
-
- )}
- {values.gender && (
-
-
- Gender
- - {values.gender}
-
- )}
-
-
-
- {/* Address Summary */}
- {address?.address1 && (
-
-
-
- 📍
-
- Delivery Address
-
-
{formattedAddress}
-
- )}
-
- {/* Terms & Conditions */}
-
-
Terms & Agreements
-
-
- {errors["acceptTerms"] && (
-
{errors["acceptTerms"]}
- )}
-
-
-
-
-
-
-
-
- );
-}
diff --git a/apps/portal/src/features/auth/components/SignupForm/steps/index.ts b/apps/portal/src/features/auth/components/SignupForm/steps/index.ts
deleted file mode 100644
index 7bf590d7..00000000
--- a/apps/portal/src/features/auth/components/SignupForm/steps/index.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export { AccountStep } from "./AccountStep";
-export { AddressStep } from "./AddressStep";
-export { PasswordStep } from "./PasswordStep";
-export { ReviewStep } from "./ReviewStep";
diff --git a/apps/portal/src/features/auth/components/index.ts b/apps/portal/src/features/auth/components/index.ts
index b98495f1..577dcb66 100644
--- a/apps/portal/src/features/auth/components/index.ts
+++ b/apps/portal/src/features/auth/components/index.ts
@@ -4,9 +4,6 @@
*/
export { LoginForm } from "./LoginForm/LoginForm";
-export { SignupForm } from "./SignupForm/SignupForm";
export { PasswordResetForm } from "./PasswordResetForm/PasswordResetForm";
export { SetPasswordForm } from "./SetPasswordForm/SetPasswordForm";
-export { LinkWhmcsForm } from "./LinkWhmcsForm/LinkWhmcsForm";
-export { InlineAuthSection } from "./InlineAuthSection/InlineAuthSection";
export { AuthLayout } from "@/components/templates/AuthLayout";
diff --git a/apps/portal/src/features/auth/hooks/index.ts b/apps/portal/src/features/auth/hooks/index.ts
index a1dea43a..645912dd 100644
--- a/apps/portal/src/features/auth/hooks/index.ts
+++ b/apps/portal/src/features/auth/hooks/index.ts
@@ -9,7 +9,6 @@ export {
useSignup,
usePasswordReset,
usePasswordChange,
- useWhmcsLink,
useSession,
useUser,
usePermissions,
diff --git a/apps/portal/src/features/auth/hooks/use-auth.ts b/apps/portal/src/features/auth/hooks/use-auth.ts
index 0a8f2978..a27f9b42 100644
--- a/apps/portal/src/features/auth/hooks/use-auth.ts
+++ b/apps/portal/src/features/auth/hooks/use-auth.ts
@@ -36,7 +36,6 @@ export function useAuth() {
resetPassword,
changePassword,
checkPasswordNeeded,
- linkWhmcs,
setPassword,
checkAuth,
refreshSession,
@@ -93,7 +92,6 @@ export function useAuth() {
resetPassword,
changePassword,
checkPasswordNeeded,
- linkWhmcs,
setPassword,
checkAuth,
refreshSession,
@@ -165,22 +163,6 @@ export function usePasswordChange() {
};
}
-/**
- * Hook for WHMCS linking functionality
- */
-export function useWhmcsLink() {
- const { checkPasswordNeeded, linkWhmcs, setPassword, loading, error, clearError } = useAuth();
-
- return {
- checkPasswordNeeded,
- linkWhmcs,
- setPassword,
- loading,
- error,
- clearError,
- };
-}
-
/**
* Hook for session management
*/
diff --git a/apps/portal/src/features/auth/stores/auth.store.ts b/apps/portal/src/features/auth/stores/auth.store.ts
index 6a513510..bc27e487 100644
--- a/apps/portal/src/features/auth/stores/auth.store.ts
+++ b/apps/portal/src/features/auth/stores/auth.store.ts
@@ -10,11 +10,8 @@ import { logger } from "@/core/logger";
import {
authResponseSchema,
checkPasswordNeededResponseSchema,
- linkWhmcsResponseSchema,
type AuthSession,
type CheckPasswordNeededResponse,
- type LinkWhmcsRequest,
- type LinkWhmcsResponse,
type LoginRequest,
type SignupRequest,
} from "@customer-portal/domain/auth";
@@ -47,7 +44,6 @@ export interface AuthState {
resetPassword: (token: string, password: string) => Promise;
changePassword: (currentPassword: string, newPassword: string) => Promise;
checkPasswordNeeded: (email: string) => Promise;
- linkWhmcs: (request: LinkWhmcsRequest) => Promise;
setPassword: (email: string, password: string) => Promise;
refreshUser: () => Promise;
refreshSession: () => Promise;
@@ -280,30 +276,6 @@ export const useAuthStore = create()((set, get) => {
}
},
- linkWhmcs: async (linkRequest: LinkWhmcsRequest) => {
- set({ loading: true, error: null });
- try {
- const response = await apiClient.POST("/api/auth/migrate", {
- body: linkRequest,
- disableCsrf: true, // Public auth endpoint, exempt from CSRF
- });
-
- const parsed = linkWhmcsResponseSchema.safeParse(response.data);
- if (!parsed.success) {
- throw new Error(parsed.error.issues?.[0]?.message ?? "WHMCS link failed");
- }
-
- set({ loading: false });
- return parsed.data;
- } catch (error) {
- set({
- loading: false,
- error: error instanceof Error ? error.message : "WHMCS link failed",
- });
- throw error;
- }
- },
-
setPassword: async (email: string, password: string) => {
set({ loading: true, error: null });
try {
diff --git a/apps/portal/src/features/auth/views/MigrateAccountView.tsx b/apps/portal/src/features/auth/views/MigrateAccountView.tsx
deleted file mode 100644
index 54c85a0e..00000000
--- a/apps/portal/src/features/auth/views/MigrateAccountView.tsx
+++ /dev/null
@@ -1,104 +0,0 @@
-/**
- * Migrate Account View - Account migration page
- */
-
-"use client";
-
-import Link from "next/link";
-import { useRouter, useSearchParams } from "next/navigation";
-import { AuthLayout } from "../components";
-import { LinkWhmcsForm } from "@/features/auth/components";
-import { getSafeRedirect } from "@/features/auth/utils/route-protection";
-import { MIGRATION_TRANSFER_ITEMS, MIGRATION_STEPS } from "@customer-portal/domain/auth";
-
-export function MigrateAccountView() {
- const router = useRouter();
- const searchParams = useSearchParams();
- const initialEmail = searchParams.get("email") ?? undefined;
- const redirectTo = getSafeRedirect(searchParams.get("redirect"), "/account");
-
- return (
-
-
- {/* What transfers */}
-
-
What gets transferred:
-
- {MIGRATION_TRANSFER_ITEMS.map((item, i) => (
- -
- ✓ {item}
-
- ))}
-
-
-
- {/* Form */}
-
-
- Enter Legacy Portal Credentials
-
-
- Use your previous Assist Solutions portal email and password.
-
-
{
- if (result.needsPasswordSet) {
- const params = new URLSearchParams({
- email: result.user.email,
- redirect: redirectTo,
- });
- router.push(`/auth/set-password?${params.toString()}`);
- } else {
- router.push(redirectTo);
- }
- }}
- />
-
-
- {/* Links */}
-
-
- New customer?{" "}
-
- Create account
-
-
-
- Already transferred?{" "}
-
- Sign in
-
-
-
-
- {/* Steps */}
-
-
How it works
-
- {MIGRATION_STEPS.map((step, i) => (
- -
-
- {i + 1}
-
- {step}
-
- ))}
-
-
-
-
- Need help?{" "}
-
- Contact support
-
-
-
-
- );
-}
-
-export default MigrateAccountView;
diff --git a/apps/portal/src/features/auth/views/SetPasswordView.tsx b/apps/portal/src/features/auth/views/SetPasswordView.tsx
index 32df4755..67338559 100644
--- a/apps/portal/src/features/auth/views/SetPasswordView.tsx
+++ b/apps/portal/src/features/auth/views/SetPasswordView.tsx
@@ -16,7 +16,7 @@ function SetPasswordContent() {
useEffect(() => {
if (!email) {
- router.replace("/auth/migrate");
+ router.replace("/auth/get-started");
}
}, [email, router]);
@@ -33,7 +33,7 @@ function SetPasswordContent() {
again so we can verify your account.
Go to account transfer
diff --git a/apps/portal/src/features/auth/views/SignupView.tsx b/apps/portal/src/features/auth/views/SignupView.tsx
deleted file mode 100644
index dbd71eba..00000000
--- a/apps/portal/src/features/auth/views/SignupView.tsx
+++ /dev/null
@@ -1,31 +0,0 @@
-"use client";
-
-import { AuthLayout } from "../components";
-import { SignupForm } from "@/features/auth/components";
-import { useAuthStore } from "../stores/auth.store";
-import { LoadingOverlay } from "@/components/atoms";
-
-export function SignupView() {
- const { loading, isAuthenticated } = useAuthStore();
-
- return (
- <>
-
-
-
-
- {/* Full-page loading overlay during authentication */}
-
- >
- );
-}
-
-export default SignupView;
diff --git a/apps/portal/src/features/auth/views/index.ts b/apps/portal/src/features/auth/views/index.ts
index 7e3ecdc2..7efe9c65 100644
--- a/apps/portal/src/features/auth/views/index.ts
+++ b/apps/portal/src/features/auth/views/index.ts
@@ -1,6 +1,4 @@
export { LoginView } from "./LoginView";
-export { SignupView } from "./SignupView";
export { ForgotPasswordView } from "./ForgotPasswordView";
export { ResetPasswordView } from "./ResetPasswordView";
export { SetPasswordView } from "./SetPasswordView";
-export { MigrateAccountView } from "./MigrateAccountView";
diff --git a/apps/portal/src/features/services/views/PublicInternetConfigure.tsx b/apps/portal/src/features/services/views/PublicInternetConfigure.tsx
index 47c70209..5db3a23d 100644
--- a/apps/portal/src/features/services/views/PublicInternetConfigure.tsx
+++ b/apps/portal/src/features/services/views/PublicInternetConfigure.tsx
@@ -3,7 +3,7 @@
import { useSearchParams } from "next/navigation";
import { WifiIcon, ClockIcon, EnvelopeIcon, CheckCircleIcon } from "@heroicons/react/24/outline";
import { ServicesBackLink } from "@/features/services/components/base/ServicesBackLink";
-import { InlineAuthSection } from "@/features/auth/components/InlineAuthSection/InlineAuthSection";
+import { InlineGetStartedSection } from "@/features/get-started";
import { useServicesBasePath } from "@/features/services/hooks/useServicesBasePath";
import { usePublicInternetPlan } from "@/features/services/hooks";
import { CardPricing } from "@/features/services/components/base/CardPricing";
@@ -76,9 +76,10 @@ export function PublicInternetConfigureView() {
)}
{/* Auth Section - Primary focus */}
-