65 lines
2.1 KiB
TypeScript
65 lines
2.1 KiB
TypeScript
'use client';
|
|
import { FunctionComponent, useState } from 'react';
|
|
import { useSearchParams } from 'next/navigation';
|
|
|
|
import { APP_ROLES, RETURN_URL_PARAM, type AppRole } from '@/constants';
|
|
import { OTP_RESEND_FALLBACK_SECONDS } from '@/services/auth/constants';
|
|
import AuthCard from './AuthCard';
|
|
import PhoneStep from './PhoneStep';
|
|
import OtpStep from './OtpStep';
|
|
import RoleRouter from './RoleRouter';
|
|
|
|
type Step = 'phone' | 'otp' | 'routing';
|
|
|
|
/**
|
|
* The single login stack for both actors (A1/A2 customer, B1/B2 nurse). One OTP mechanism,
|
|
* parameterised by `intendedRole` (seeded from `?role=nurse`) — no forked login trees. After a
|
|
* successful verify it hands off to the role router.
|
|
* @component LoginFlow
|
|
*/
|
|
const LoginFlow: FunctionComponent = () => {
|
|
const searchParams = useSearchParams();
|
|
const [intendedRole, setIntendedRole] = useState<AppRole>(
|
|
searchParams.get('role') === APP_ROLES.NURSE ? APP_ROLES.NURSE : APP_ROLES.CUSTOMER,
|
|
);
|
|
const [step, setStep] = useState<Step>('phone');
|
|
const [phone, setPhone] = useState('');
|
|
const [resendSeconds, setResendSeconds] = useState(OTP_RESEND_FALLBACK_SECONDS);
|
|
// Carried from middleware.ts's redirect-to-login so a deep link survives the auth round trip.
|
|
const next = searchParams.get(RETURN_URL_PARAM);
|
|
|
|
if (step === 'routing') {
|
|
return <RoleRouter intendedRole={intendedRole} next={next} />;
|
|
}
|
|
|
|
return (
|
|
<AuthCard>
|
|
{step === 'phone' ? (
|
|
<PhoneStep
|
|
intendedRole={intendedRole}
|
|
onSwitchRole={() =>
|
|
setIntendedRole((role) =>
|
|
role === APP_ROLES.NURSE ? APP_ROLES.CUSTOMER : APP_ROLES.NURSE,
|
|
)
|
|
}
|
|
onSent={(nextPhone, result) => {
|
|
setPhone(nextPhone);
|
|
setResendSeconds(result.resendAvailableInSeconds);
|
|
setStep('otp');
|
|
}}
|
|
/>
|
|
) : (
|
|
<OtpStep
|
|
phone={phone}
|
|
intendedRole={intendedRole}
|
|
resendSeconds={resendSeconds}
|
|
onVerified={() => setStep('routing')}
|
|
onChangeNumber={() => setStep('phone')}
|
|
/>
|
|
)}
|
|
</AuthCard>
|
|
);
|
|
};
|
|
|
|
export default LoginFlow;
|