mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-30 04:08:11 +00:00
feat: merge the role and nationality step
This commit is contained in:
@@ -10,10 +10,8 @@ import {
|
|||||||
} from "@mantine/core";
|
} from "@mantine/core";
|
||||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||||
import {
|
import {
|
||||||
ArrowLeft,
|
|
||||||
ArrowRight,
|
ArrowRight,
|
||||||
Building2,
|
Building2,
|
||||||
CheckCircle2,
|
|
||||||
Clock,
|
Clock,
|
||||||
FileText,
|
FileText,
|
||||||
Globe2,
|
Globe2,
|
||||||
@@ -42,42 +40,29 @@ import type { UpdateProfilePayload } from "@/types/profile";
|
|||||||
import { extractApiError } from "@/utils/result";
|
import { extractApiError } from "@/utils/result";
|
||||||
|
|
||||||
/** Form steps rendered by CompanyProfileForm. */
|
/** Form steps rendered by CompanyProfileForm. */
|
||||||
type FormStep =
|
type FormStep = "company" | "personnel" | "contact" | "poa" | "documents";
|
||||||
| "company"
|
|
||||||
| "personnel"
|
|
||||||
| "contact"
|
|
||||||
| "poa"
|
|
||||||
| "documents"
|
|
||||||
| "additional";
|
|
||||||
const FORM_STEPS: FormStep[] = [
|
const FORM_STEPS: FormStep[] = [
|
||||||
"company",
|
"company",
|
||||||
"personnel",
|
"personnel",
|
||||||
"contact",
|
"contact",
|
||||||
"poa",
|
"poa",
|
||||||
"documents",
|
"documents",
|
||||||
"additional",
|
|
||||||
];
|
];
|
||||||
|
|
||||||
/** The full onboarding journey: the two pre-form phases + the form steps. */
|
/** The full onboarding journey: the two pre-form phases + the form steps. */
|
||||||
type WizardStep = "nationality" | "role" | FormStep;
|
type WizardStep = "nationality-role" | FormStep;
|
||||||
const WIZARD_STEPS: WizardStep[] = ["nationality", "role", ...FORM_STEPS];
|
const WIZARD_STEPS: WizardStep[] = ["nationality-role", ...FORM_STEPS];
|
||||||
|
|
||||||
/** Icon + title + description shown in the global dialog header per step. */
|
/** Icon + title + description shown in the global dialog header per step. */
|
||||||
const STEP_META: Record<
|
const STEP_META: Record<
|
||||||
WizardStep,
|
WizardStep,
|
||||||
{ icon: ReactNode; title: string; description: string }
|
{ icon: ReactNode; title: string; description: string }
|
||||||
> = {
|
> = {
|
||||||
nationality: {
|
"nationality-role": {
|
||||||
icon: <Globe2 size={20} />,
|
icon: <Globe2 size={20} />,
|
||||||
title: "Where is your company registered?",
|
title: "Tell us about your company",
|
||||||
description: "This determines the documents we'll ask you to provide.",
|
description: "This determines the documents we'll ask you to provide.",
|
||||||
},
|
},
|
||||||
role: {
|
|
||||||
icon: <Building2 size={20} />,
|
|
||||||
title: "What does your company do?",
|
|
||||||
description:
|
|
||||||
"Pick any combination of Importer, Exporter and Freight Forwarder — each is set up with its own business license.",
|
|
||||||
},
|
|
||||||
company: {
|
company: {
|
||||||
icon: <Building2 size={20} />,
|
icon: <Building2 size={20} />,
|
||||||
title: "Company Information",
|
title: "Company Information",
|
||||||
@@ -103,11 +88,6 @@ const STEP_META: Record<
|
|||||||
title: "Upload Documents",
|
title: "Upload Documents",
|
||||||
description: "Provide the required company documents.",
|
description: "Provide the required company documents.",
|
||||||
},
|
},
|
||||||
additional: {
|
|
||||||
icon: <CheckCircle2 size={20} />,
|
|
||||||
title: "Business License",
|
|
||||||
description: "Upload a business license for each operational profile.",
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
interface OnboardingWizardDialogProps {
|
interface OnboardingWizardDialogProps {
|
||||||
@@ -165,12 +145,8 @@ export default function OnboardingWizardDialog({
|
|||||||
|
|
||||||
// Phases: nationality → role → form. If a draft already exists, resume
|
// Phases: nationality → role → form. If a draft already exists, resume
|
||||||
// straight into the form with nationality + roles pre-selected.
|
// straight into the form with nationality + roles pre-selected.
|
||||||
const [phase, setPhase] = useState<"nationality" | "role" | "form">(
|
const [phase, setPhase] = useState<"nationality-role" | "form">(
|
||||||
companyAlreadyStarted
|
companyAlreadyStarted ? "form" : "nationality-role",
|
||||||
? hasOperationalProfiles
|
|
||||||
? "form"
|
|
||||||
: "role"
|
|
||||||
: "nationality",
|
|
||||||
);
|
);
|
||||||
const [nationality, setNationality] = useState<CompanyNationality | null>(
|
const [nationality, setNationality] = useState<CompanyNationality | null>(
|
||||||
savedNationality,
|
savedNationality,
|
||||||
@@ -295,16 +271,12 @@ export default function OnboardingWizardDialog({
|
|||||||
setNationality(savedNationality);
|
setNationality(savedNationality);
|
||||||
// Resume into the form only when profiles exist; otherwise send the user to
|
// Resume into the form only when profiles exist; otherwise send the user to
|
||||||
// role selection so the missing operational profiles get created.
|
// role selection so the missing operational profiles get created.
|
||||||
setPhase(hasOperationalProfiles ? "form" : "role");
|
setPhase(hasOperationalProfiles ? "form" : "nationality-role");
|
||||||
const idx = FORM_STEPS.indexOf(resumeFormStep);
|
const idx = FORM_STEPS.indexOf(resumeFormStep);
|
||||||
if (idx > furthestIdxRef.current) furthestIdxRef.current = idx;
|
if (idx > furthestIdxRef.current) furthestIdxRef.current = idx;
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [companyAlreadyStarted, resumeFormStep]);
|
}, [companyAlreadyStarted, resumeFormStep]);
|
||||||
|
|
||||||
const handleNationalityContinue = useCallback(() => {
|
|
||||||
if (nationality) setPhase("role");
|
|
||||||
}, [nationality]);
|
|
||||||
|
|
||||||
const handleRolesContinue = useCallback(() => {
|
const handleRolesContinue = useCallback(() => {
|
||||||
setStartError(null);
|
setStartError(null);
|
||||||
startMutation.mutate({
|
startMutation.mutate({
|
||||||
@@ -387,6 +359,7 @@ export default function OnboardingWizardDialog({
|
|||||||
// The active step across the whole journey, driving the header + progress pill.
|
// The active step across the whole journey, driving the header + progress pill.
|
||||||
const activeStep: WizardStep = phase === "form" ? formStep : phase;
|
const activeStep: WizardStep = phase === "form" ? formStep : phase;
|
||||||
const stepMeta = STEP_META[activeStep];
|
const stepMeta = STEP_META[activeStep];
|
||||||
|
console.log({ stepMeta, activeStep, STEP_META });
|
||||||
const activeIdx = WIZARD_STEPS.indexOf(activeStep);
|
const activeIdx = WIZARD_STEPS.indexOf(activeStep);
|
||||||
|
|
||||||
// Closing from the congratulations panel also clears the completed flag so a
|
// Closing from the congratulations panel also clears the completed flag so a
|
||||||
@@ -418,7 +391,7 @@ export default function OnboardingWizardDialog({
|
|||||||
);
|
);
|
||||||
const effectiveResumeStep: FormStep =
|
const effectiveResumeStep: FormStep =
|
||||||
requiredDocsMissing &&
|
requiredDocsMissing &&
|
||||||
FORM_STEPS.indexOf(resumeFormStep) > FORM_STEPS.indexOf("documents")
|
FORM_STEPS.indexOf(resumeFormStep) > FORM_STEPS.indexOf("documents")
|
||||||
? "documents"
|
? "documents"
|
||||||
: resumeFormStep;
|
: resumeFormStep;
|
||||||
|
|
||||||
@@ -490,26 +463,19 @@ export default function OnboardingWizardDialog({
|
|||||||
<OnboardingCompletePanel onClose={handleClose} />
|
<OnboardingCompletePanel onClose={handleClose} />
|
||||||
) : (
|
) : (
|
||||||
<Stack gap="xl">
|
<Stack gap="xl">
|
||||||
{phase === "nationality" ? (
|
{phase === "nationality-role" ? (
|
||||||
<Stack gap="lg">
|
<Stack gap="lg">
|
||||||
|
<Text fw={600} size="lg" c="edr-text">
|
||||||
|
Where is your company registered?
|
||||||
|
</Text>
|
||||||
<NationalitySelect
|
<NationalitySelect
|
||||||
value={nationality}
|
value={nationality}
|
||||||
onChange={setNationality}
|
onChange={setNationality}
|
||||||
embedded
|
embedded
|
||||||
/>
|
/>
|
||||||
<Group justify="flex-end" pt="xs">
|
<Text fw={600} size="lg" c="edr-text">
|
||||||
<Button
|
What does your company do?(multiple)
|
||||||
color="edr-green"
|
</Text>
|
||||||
onClick={handleNationalityContinue}
|
|
||||||
disabled={!nationality}
|
|
||||||
rightSection={<ArrowRight size={16} />}
|
|
||||||
>
|
|
||||||
Continue
|
|
||||||
</Button>
|
|
||||||
</Group>
|
|
||||||
</Stack>
|
|
||||||
) : phase === "role" ? (
|
|
||||||
<Stack gap="lg">
|
|
||||||
<OnboardingRoleSelect
|
<OnboardingRoleSelect
|
||||||
value={roles}
|
value={roles}
|
||||||
onChange={setRoles}
|
onChange={setRoles}
|
||||||
@@ -520,14 +486,7 @@ export default function OnboardingWizardDialog({
|
|||||||
{startError}
|
{startError}
|
||||||
</Text>
|
</Text>
|
||||||
)}
|
)}
|
||||||
<Group justify="space-between" pt="xs">
|
<Group justify="flex-end" pt="xs">
|
||||||
<Button
|
|
||||||
variant="default"
|
|
||||||
leftSection={<ArrowLeft size={16} />}
|
|
||||||
onClick={() => setPhase("nationality")}
|
|
||||||
>
|
|
||||||
Back
|
|
||||||
</Button>
|
|
||||||
<Button
|
<Button
|
||||||
color="edr-green"
|
color="edr-green"
|
||||||
onClick={handleRolesContinue}
|
onClick={handleRolesContinue}
|
||||||
@@ -609,7 +568,7 @@ function OnboardingCompletePanel({ onClose }: { onClose: () => void }) {
|
|||||||
</Stack>
|
</Stack>
|
||||||
|
|
||||||
<Button color="edr-green" size="md" onClick={onClose} mt="xs">
|
<Button color="edr-green" size="md" onClick={onClose} mt="xs">
|
||||||
Go to my dashboard
|
Continue to Dashboard
|
||||||
</Button>
|
</Button>
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user