feat: update onboarding and company role handling to support multiple service types

This commit is contained in:
Marshal
2026-06-22 12:30:44 +00:00
parent ad0043b580
commit 30b022356c
5 changed files with 52 additions and 49 deletions

View File

@@ -1,6 +1,6 @@
import { Modal, ScrollArea, Stack, Text } from "@mantine/core";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { useCallback, useRef, useState } from "react";
import { useCallback, useEffect, useRef, useState } from "react";
import useAuth from "@/hooks/useAuth";
import { api } from "@/services/api";
@@ -13,9 +13,7 @@ import { companiesService } from "@/services/companies.service";
import type { UpdateProfilePayload } from "@/types/profile";
import { extractApiError } from "@/utils/result";
import CompanyProfileForm from "@/pages/accounts/CompanyProfileForm";
import ForwarderForm from "@/pages/accounts/ForwarderForm";
import type { RoleLicenseProfile } from "@/components/onboarding/RoleLicenseStep";
import { FREIGHT_FORWARDER } from "@/pages/settings/companyRoles";
import NationalitySelect from "@/pages/settings/NationalitySelect";
import OnboardingRoleSelect from "@/pages/settings/OnboardingRoleSelect";
@@ -42,9 +40,14 @@ interface OnboardingWizardDialogProps {
onClose: () => void;
}
/** Map the chosen operational roles to the company type they belong to. */
function companyTypeForRoles(roles: string[]): string {
return roles.includes(FREIGHT_FORWARDER.type) ? "forwarder" : "customer";
/**
* The company type for the onboarding selection. Importer / Exporter / Freight
* Forwarder are all services a single "customer" company can hold (in any
* combination), each with its own business license — so the company is always
* registered as a "customer".
*/
function companyTypeForRoles(_roles: string[]): string {
return "customer";
}
/** Document upload setting code per company nationality. */
@@ -161,6 +164,23 @@ export default function OnboardingWizardDialog({
api.companies.setOnboardingStep.call({ step }).catch(() => {});
}, []);
// The company query may resolve AFTER this dialog mounts (it's kept mounted by
// the gate), so the phase/roles/nationality initial state can be stale — a
// draft that already exists would otherwise leave us stuck on the first
// (nationality) phase. Once a draft loads, jump straight into the form with
// the persisted roles/nationality. Runs once per resumed draft.
const resumedRef = useRef(false);
useEffect(() => {
if (!companyAlreadyStarted || resumedRef.current) return;
resumedRef.current = true;
setRoles(existingProfiles.map((p) => p.type));
setNationality(savedNationality);
setPhase("form");
const idx = FORM_STEPS.indexOf(resumeFormStep);
if (idx > furthestIdxRef.current) furthestIdxRef.current = idx;
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [companyAlreadyStarted, resumeFormStep]);
const handleNationalityContinue = useCallback(() => {
if (nationality) setPhase("role");
}, [nationality]);
@@ -205,8 +225,7 @@ export default function OnboardingWizardDialog({
if (!user) return null;
const isForwarder = roles.includes(FREIGHT_FORWARDER.type);
// Importer+Exporter (or either alone) is a valid customer selection.
// Any non-empty combination of importer/exporter/freight-forwarder is valid.
const rolesValid = roles.length > 0;
// Documents depend on nationality; fall back to the saved one (resume) then ethiopian.
const effectiveNationality: CompanyNationality =
@@ -293,8 +312,6 @@ export default function OnboardingWizardDialog({
onClick={handleRolesContinue}
/>
</Stack>
) : isForwarder ? (
<ForwarderForm {...formProps} />
) : (
<CompanyProfileForm {...formProps} />
)}