215 lines
6.9 KiB
TypeScript
215 lines
6.9 KiB
TypeScript
"use client";
|
|
|
|
import React, { useState, useEffect } from "react";
|
|
import { useSearchParams } from "next/navigation";
|
|
import { toast } from "sonner";
|
|
import { RegistrationLayout } from "@/components/auth/registration-layout";
|
|
import { IdentityForm } from "@/components/auth/identity-form";
|
|
import { RegistrationOTPForm } from "@/components/auth/registration-otp-form";
|
|
import { ProfileForm } from "@/components/auth/profile-form";
|
|
import {
|
|
RegistrationStep,
|
|
UserCategory,
|
|
JournalistRegistrationData,
|
|
PersonnelRegistrationData,
|
|
GeneralRegistrationData,
|
|
RegistrationFormData
|
|
} from "@/types/registration";
|
|
import { isValidCategory } from "@/lib/registration-utils";
|
|
import { useOTP } from "@/hooks/use-registration";
|
|
|
|
const RegistrationPage = () => {
|
|
const searchParams = useSearchParams();
|
|
const [currentStep, setCurrentStep] = useState<RegistrationStep>("identity");
|
|
const [category, setCategory] = useState<UserCategory>("general");
|
|
const [identityData, setIdentityData] = useState<JournalistRegistrationData | PersonnelRegistrationData | GeneralRegistrationData | null>(null);
|
|
const [userData, setUserData] = useState<any>(null);
|
|
const { requestOTP } = useOTP();
|
|
|
|
// Get category from URL params
|
|
useEffect(() => {
|
|
const categoryParam = searchParams?.get("category");
|
|
console.log("Search params:", searchParams);
|
|
console.log("Category param from URL:", categoryParam);
|
|
console.log("Is valid category:", categoryParam && isValidCategory(categoryParam));
|
|
|
|
if (categoryParam && isValidCategory(categoryParam)) {
|
|
console.log("Setting category to:", categoryParam);
|
|
setCategory(categoryParam as UserCategory);
|
|
} else {
|
|
// Fallback: try to get category from URL directly
|
|
const urlParams = new URLSearchParams(window.location.search);
|
|
const fallbackCategory = urlParams.get("category");
|
|
console.log("Fallback category from URL:", fallbackCategory);
|
|
|
|
if (fallbackCategory && isValidCategory(fallbackCategory)) {
|
|
console.log("Setting category from fallback to:", fallbackCategory);
|
|
setCategory(fallbackCategory as UserCategory);
|
|
} else {
|
|
console.log("Using default category:", "general");
|
|
setCategory("general");
|
|
}
|
|
}
|
|
}, [searchParams]);
|
|
|
|
// Handle identity form success
|
|
const handleIdentitySuccess = async (data: JournalistRegistrationData | PersonnelRegistrationData | GeneralRegistrationData) => {
|
|
try {
|
|
// Store identity data
|
|
setIdentityData(data);
|
|
|
|
// Get member identity based on category
|
|
let memberIdentity: string | undefined;
|
|
if (category === "6") {
|
|
memberIdentity = (data as JournalistRegistrationData).journalistCertificate;
|
|
} else if (category === "7") {
|
|
memberIdentity = (data as PersonnelRegistrationData).policeNumber;
|
|
}
|
|
|
|
// Debug logging
|
|
console.log("=== OTP Request Debug ===");
|
|
console.log("Category:", category);
|
|
console.log("Category type:", typeof category);
|
|
console.log("Email:", data.email);
|
|
console.log("Member Identity:", memberIdentity);
|
|
console.log("Current URL:", window.location.href);
|
|
console.log("URL search params:", window.location.search);
|
|
|
|
// Validate category before proceeding
|
|
if (!category || !isValidCategory(category)) {
|
|
console.error("Invalid category detected:", category);
|
|
toast.error("Invalid registration category. Please refresh the page and try again.");
|
|
return;
|
|
}
|
|
|
|
// Request OTP
|
|
const success = await requestOTP(data.email, category, memberIdentity);
|
|
|
|
if (success) {
|
|
// Move to OTP step only if OTP request was successful
|
|
setCurrentStep("otp");
|
|
} else {
|
|
toast.error("Failed to send OTP. Please try again.");
|
|
}
|
|
} catch (error: any) {
|
|
toast.error(error.message || "Failed to send OTP");
|
|
}
|
|
};
|
|
|
|
const handleIdentityError = (error: string) => {
|
|
toast.error(error);
|
|
};
|
|
|
|
// Handle OTP form success
|
|
const handleOTPSuccess = (data: any) => {
|
|
setUserData(data);
|
|
setCurrentStep("profile");
|
|
};
|
|
|
|
const handleOTPError = (error: string) => {
|
|
toast.error(error);
|
|
};
|
|
|
|
const handleOTPResend = () => {
|
|
toast.info("OTP resent successfully");
|
|
};
|
|
|
|
// Handle profile form success
|
|
const handleProfileSuccess = (data: RegistrationFormData) => {
|
|
toast.success("Registration completed successfully!");
|
|
// Redirect to login page after a short delay
|
|
setTimeout(() => {
|
|
window.location.href = "/auth";
|
|
}, 2000);
|
|
};
|
|
|
|
const handleProfileError = (error: string) => {
|
|
toast.error(error);
|
|
};
|
|
|
|
// Render current step
|
|
const renderCurrentStep = () => {
|
|
switch (currentStep) {
|
|
case "identity":
|
|
return (
|
|
<IdentityForm
|
|
category={category}
|
|
onSuccess={handleIdentitySuccess}
|
|
onError={handleIdentityError}
|
|
/>
|
|
);
|
|
case "otp":
|
|
if (!identityData) {
|
|
toast.error("Identity data not found. Please start over.");
|
|
setCurrentStep("identity");
|
|
return null;
|
|
}
|
|
return (
|
|
<RegistrationOTPForm
|
|
email={identityData.email}
|
|
category={category}
|
|
memberIdentity={
|
|
category === "6"
|
|
? (identityData as JournalistRegistrationData).journalistCertificate
|
|
: category === "7"
|
|
? (identityData as PersonnelRegistrationData).policeNumber
|
|
: undefined
|
|
}
|
|
onSuccess={handleOTPSuccess}
|
|
onError={handleOTPError}
|
|
onResend={handleOTPResend}
|
|
/>
|
|
);
|
|
case "profile":
|
|
// Always render the profile form, even if userData is null/undefined
|
|
return (
|
|
<ProfileForm
|
|
userData={userData}
|
|
category={category}
|
|
onSuccess={handleProfileSuccess}
|
|
onError={handleProfileError}
|
|
/>
|
|
);
|
|
default:
|
|
return (
|
|
<IdentityForm
|
|
category={category}
|
|
onSuccess={handleIdentitySuccess}
|
|
onError={handleIdentityError}
|
|
/>
|
|
);
|
|
}
|
|
};
|
|
|
|
// Don't render if category is invalid
|
|
if (!isValidCategory(category)) {
|
|
return (
|
|
<div className="flex items-center justify-center min-h-screen">
|
|
<div className="text-center">
|
|
<h1 className="text-2xl font-bold text-red-600 mb-4">Invalid Registration Category</h1>
|
|
<p className="text-gray-600 mb-4">
|
|
The registration category specified is not valid.
|
|
</p>
|
|
<a
|
|
href="/auth"
|
|
className="inline-block bg-red-600 text-white px-6 py-2 rounded-lg hover:bg-red-700 transition-colors"
|
|
>
|
|
Back to Login
|
|
</a>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<RegistrationLayout
|
|
currentStep={currentStep}
|
|
totalSteps={3}
|
|
>
|
|
{renderCurrentStep()}
|
|
</RegistrationLayout>
|
|
);
|
|
};
|
|
|
|
export default RegistrationPage;
|