Uncaught TypeError: cannot use 'in' operator to search for "email" in "We could not val..."
    updateField Signup.tsx:166
    React 5
    Signup Signup.tsx:107
    React 21
    ["4dmnR"]< index.tsx:14
    newRequire public.6efbc4f8.js:84
    <anonymous> public.6efbc4f8.js:144
    <anonymous> public.6efbc4f8.js:163
Signup.tsx:166:16
An error occurred in the <Signup> component.

Consider adding an error boundary to your tree to customize error handling behavior.
Visit https://react.dev/link/error-boundaries to learn more about error boundaries.

// src/components/site/Signup.tsx

// Yup validation schemas per stage
const stageSchemas =
[
	// Stage One - Email
	yup.object({ email: yup.string().email('Invalid email').required('Email is required') }),
	// Stage One"B" - Verify
	yup.object({ token: yup.string().required('Verification token is required') }),
	
	// ...
];

// Type defining your signup form data shape (you can extend)
interface SignupData
{
	email: string;
	token: string;
	fullName: string;
	password: string;
	passwordRepeat: string;
	category: string;
	businessName: string;
	description?: string;
	phone?: string;
	website?: string;
	contactEmail?: string;
	address?: string;
	hours?: string;
	businessCard?: File | null;
	profilePicture?: File | null;
	banner?: File | null;
}

const initialSignupData: SignupData =
{
	email: '',
	token: '',
	fullName: '',
	password: '',
	passwordRepeat: '',
	category: '',
	businessName: '',
	description: '',
	phone: '',
	website: '',
	contactEmail: '',
	address: '',
	hours: '',
	businessCard: null,
	profilePicture: null,
	banner: null,
};

const TOTAL_STEPS = stageSchemas.length;
//const TOTAL_STEPS = 9;

function Signup()
{
	// Signup process
	const [step, setStep] = useState<number>(1);
	const [userId, setUserId] = useState<number | null>(null);
	const [categories, setCategories] = useState<BusinessCategoryData[]>([]);
	const [signupData, setSignupData] = useState<SignupData>(initialSignupData);
	
	// CSRF token and param names
	const [csrf, setCsrf] = useState<CsrfData | null>(null);
	
	const [loading, setLoading] = useState(false);
	
	const [error, setError] = useState<string | null>(null);// For top-level general errors
	const [formErrors, setFormErrors] = useState<Record<string, string[] | string>>({});
	
	useEffect(() =>
	{
		async function init()
		{
			setLoading(true);
			
			try
			{
				const csrfToken = await fetchCsrfToken();
				console.log(csrfToken);
				setCsrf(csrfToken);
			}
			catch (error)
			{
				console.error('CSRF token fetch failed:', error);
				setError('Failed to initialize form. Please refresh.');
			}
			finally
			{
				setLoading(false);
			}
		}
		
		init();
		
	}, []);// Empty dependency array ensures it only runs once
	
	/**
	* Update Feild Helper
	* Helper that updates field value and clears the error on change
	*/
	const updateField = useCallback(<Key extends keyof SignupData>
	(
		field: Key,
		value: SignupData[Key]
	) =>
	{
		setSignupData(prev => ({ ...prev, [field]: value }));
		
		// Clear error for this field on change
		setFormErrors(prev =>
		{
			if (field in prev)
			{
				const copy = { ...prev };
				delete copy[field];
				return copy;
			}
			
			return prev;
		});
		
	}, []);// Empty dependency array ensures it only runs once
	
	/**
	* Handle file input updates
	*/
	const handleFileChange = useCallback(
	(
		error: ChangeEvent<HTMLInputElement>,
		field: keyof SignupData
	) =>
	{
		updateField(field, error.target.files?.[0] || null);
	}, [updateField]);
	
	/**
	* Progress calculation
	*/
	const progressPercent = (step / TOTAL_STEPS) * 100;
	
	/**
	* Centralized submit handler keyed by stage number
	*/
	const submitStage = useCallback(async () =>
	{
		// Clear previous errors
		setError(null);
		setFormErrors({});
		
		if (!csrf)
		{
			setError('CSRF token missing, please refresh.');
			return;
		}
		
		setLoading(true);
		
		try
		{
			let response;
			
			switch (step)
			{
				//  Stage One - Submit email
				case 1 :
					try
					{
						// Yup validation
						await stageSchemas[0].validate({ email: signupData.email }, { abortEarly: false });
						
						response = await signupService.submitSignupStageOneEmail(
							{ email: signupData.email },
							csrf
						);
						
						if (response.success && response.userId)
						{
							setError(null);
							setUserId(response.userId);
							setStep(2);
						}
						else if (response.status === 'error')
						{
							// Set the general error message
							setError(response.message || 'An error occurred.');
							
							if (response.errors && typeof response.errors === 'object')
							{
								setFormErrors(response.message);
							}
							else
							{
								setFormErrors({});
							}
						}
						else
						{
							// Unknown error format
							setError('Unexpected response from the server.');
							setFormErrors({});
						}
					}
					catch (validationError)
					{
						// Handle client-side Yup validation errors here if needed
						if (validationError.inner)
						{
							// Create field errors from validationError.inner array
							const yupErrors: Record<string, string[]> = {};
							validationError.inner.forEach((error: any) =>
							{
								if (!yupErrors[error.path])
								{
									yupErrors[error.path] = [];
								}
								
								yupErrors[error.path].push(error.message);
							});
							
							setFormErrors(yupErrors);	
						}
						else
						{
							setError(validationError.message || 'Validation failed.');
						}
					}
					
					break;
					
				default :
					throw new Error('Invalid step');
			}	
		}
		catch (error: any)
		{
			setError(error.message || 'Unknown error occurred');
		}
		finally
		{
			setLoading(false);
		}
	
	//}, [step, signupData, userId, csrf]);
	}, [step, signupData, csrf]);
	
	/**
	* Navigation: Back button
	*/
	const handleBack = useCallback(() =>
	{
		if (step > 1)
		{
			setError(null);
			setStep(step - 1);
		}
	}, [step]);
	
	/**
	* Render file inputs helper
	*/
	const renderFileInput = (
		label: string,
		fieldName: keyof SignupData,
		accept?: string
	) => (
		<>
			<label className="form-label">{label}</label>
			<input
				type="file"
				accept={accept}
				disabled={loading}
				onChange={(e) => handleFileChange(e, fieldName)}
				className="form-control mb-3"
			/>
		</>
	);
	
	/**
	* Render fields based on current step
	*/
	const renderStepFields = () =>
	{
		switch (step)
		{
			case 1 :
				return (
					<div className="mb-3">
						
						{csrf && (
							<input type="hidden" name={csrf?.csrfParam} value={csrf?.csrfToken} />
						)}
						
						<label htmlFor="email" className="form-label">Email</label>
						<input
							id="email"
							type="email"
							className={`form-control ${formErrors.email ? 'is-invalid' : ''}`}
							value={signupData.email}
							onChange={e => updateField('email', e.target.value)}
							disabled={loading}
							required
						/>
						{formErrors.email && (
							<div className="invalid-feedback">
								{Array.isArray(formErrors.email) ? formErrors.email[0] : formErrors.email}
							</div>
						)}
						
					</div>
				);
			
			default :
				return <p>Invalid step</p>;
		}
	};
	
	return (
		<div id="site-signup-page" className="site-signup-page d-flex justify-content-center align-items-center" style={{ minheight: '80vh' }}>
			<div className="row justify-content-center align-items-center w-100 h-100">
			
				<div className="col-lg-6 col-md-6 col-sm-12">
				
					<div className="alert alert-info mt-4" role="alert">
						You are currently signing up during our beta phase. Once we are out of beta, there will 
						be a 14-day trial period. Pricing details will be provided then.
					</div>
					
					{step > 1 && (
						<>
							<h3 className="text-center mt-5">Sign Up - Step {step - 1} of {TOTAL_STEPS - 1}</h3>
							
							<div className="progress mb-4" style={{ height: '1.5rem' }}>
								<div
									className="progress-bar progress-bar-striped"
									role="progressbar"
									style={{ width: `${((step - 1) / (TOTAL_STEPS - 1)) * 100}%` }}
									aria-valuenow={step - 1}
									aria-valuemin={1}
									aria-valuemax={TOTAL_STEPS - 1}
									>
										Step {step - 1} of {TOTAL_STEPS - 1}
								</div>
							</div>
						</>
					)}
			
					{error && <div className="alert alert-danger">{error}</div>}
			
					{/**
					* Wrap current step fields in a form for accessibility 
					* Note: Using React.FormEvent
					*/}
					<form onSubmit={(e: FormEvent) =>
					{
						e.preventDefault();
						if (!loading)
						{
							submitStage();
						}
					}} noValidate>
						
						{renderStepFields()}
						
						
						{step > 1 && (
							<button
								type="button"
								className="btn btn-secondary"
								onClick={handleBack}
								disabled={loading}
							>
								Back
							</button>
						)}
						
						<button
							type="submit"
							className="btn btn-blue w-100"
							disabled={
								loading
								|| (step === 1 && !signupData.email)
								|| (step > 1 && !signupData.token)// or your real validation for other steps
							}
						>
							{loading ? 'Please wait...' : step === TOTAL_STEPS ? 'Confirm & Submit' : 'Next'}
						</button>
					</form>
					
					<p className="mt-3 text-center">Already have an account? <a href="/login">Log in</a></p>
				</div>
			</div>
		</div>
	);
}

export default Signup;