mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
feat(portal): let an investor company switch back to eTrade registration
A company that ticked the investment-licence box by mistake, or that has since been registered with the trade registry, had no way back — the flag is chosen once, on a step onboarding never returns to. The Company tab now carries a Registration source card for those companies. It is a re-application rather than a settings edit, so the confirmation says so outright: the typed registration is cleared, the company returns to pending and the wizard reopens on the company step, while documents, owner and contact details stay. Hidden for everyone else, and disabled while a profile change request is under review — switching then would strand it.
This commit is contained in:
@@ -47,6 +47,7 @@ import useAuth from "@/hooks/useAuth";
|
||||
import { rolesForCompanyType } from "./settings/companyRoles";
|
||||
import TabAccount from "./settings/TabAccount";
|
||||
import TabCompanyProfile from "./settings/TabCompanyProfile";
|
||||
import RegistrationSourceCard from "./settings/RegistrationSourceCard";
|
||||
import TabContactPerson from "./settings/TabContactPerson";
|
||||
import TabDocuments from "./settings/TabDocuments";
|
||||
import TabOwner from "./settings/TabOwner";
|
||||
@@ -398,6 +399,7 @@ export default function SettingsPage() {
|
||||
/>
|
||||
</Fieldset>
|
||||
<OperationalServicesCard profile={profile} />
|
||||
<RegistrationSourceCard profile={profile} disabled={locked} />
|
||||
</Tabs.Panel>
|
||||
<Tabs.Panel value="contact">
|
||||
<TabContactPerson profile={profile} mode="edit" />
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
import { useState } from "react";
|
||||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import {
|
||||
Alert,
|
||||
Button,
|
||||
Card,
|
||||
Group,
|
||||
List,
|
||||
Modal,
|
||||
Stack,
|
||||
Text,
|
||||
Title,
|
||||
} from "@mantine/core";
|
||||
import { AlertCircle, FileSearch } from "lucide-react";
|
||||
|
||||
import { api } from "@/services/api";
|
||||
import type { ProfileResponse } from "@/types/profile";
|
||||
import { extractApiError } from "@/utils/result";
|
||||
|
||||
/**
|
||||
* Leave the foreign investment-licence route and go back to the ordinary eTrade
|
||||
* one — for a company that has since been registered with the trade registry,
|
||||
* or that ticked the box by mistake.
|
||||
*
|
||||
* It is a re-application, not a settings edit: the API clears the registration
|
||||
* the customer typed (nothing on file was ever checked against a licence) and
|
||||
* puts the company back to pending, so the wizard reopens on the company step
|
||||
* and the TIN goes through eTrade this time. Said plainly here rather than
|
||||
* discovered afterwards.
|
||||
*/
|
||||
export default function RegistrationSourceCard({
|
||||
profile,
|
||||
disabled = false,
|
||||
}: {
|
||||
profile: ProfileResponse;
|
||||
/** A change request is under review — switching now would strand it. */
|
||||
disabled?: boolean;
|
||||
}) {
|
||||
const queryClient = useQueryClient();
|
||||
const [confirming, setConfirming] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const revert = useMutation({
|
||||
mutationFn: () => api.companies.revertToRegularCompany.call(),
|
||||
onSuccess: async () => {
|
||||
setConfirming(false);
|
||||
// getInfo is what the onboarding gate reads, so refreshing it is what
|
||||
// reopens the wizard.
|
||||
await Promise.all([
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: api.companies.getInfo.queryKey(),
|
||||
}),
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: api.companies.getProfile.queryKey(),
|
||||
}),
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: api.companies.onboardingRequirements.queryKey(),
|
||||
}),
|
||||
]);
|
||||
},
|
||||
onError: (err) => setError(extractApiError(err).message),
|
||||
});
|
||||
|
||||
if (!profile.investorLicence) return null;
|
||||
|
||||
return (
|
||||
<>
|
||||
<Card padding="lg" radius="lg" mt="lg">
|
||||
<Group gap="sm" mb="md">
|
||||
<FileSearch size={20} />
|
||||
<Title order={3}>Registration source</Title>
|
||||
</Group>
|
||||
<Stack gap="md">
|
||||
<Text size="sm" c="edr-muted">
|
||||
Your company is registered on a foreign investment licence, so your
|
||||
registration details were entered by hand instead of being read from
|
||||
eTrade. Our team reviews them against the documents you uploaded.
|
||||
</Text>
|
||||
<Text size="sm" c="edr-muted">
|
||||
If your company now holds an eTrade trade licence, you can switch
|
||||
over and have your registration verified automatically.
|
||||
</Text>
|
||||
<Group justify="flex-end">
|
||||
<Button
|
||||
variant="default"
|
||||
disabled={disabled}
|
||||
onClick={() => {
|
||||
setError(null);
|
||||
setConfirming(true);
|
||||
}}
|
||||
>
|
||||
Switch to eTrade registration
|
||||
</Button>
|
||||
</Group>
|
||||
{disabled && (
|
||||
<Text size="xs" c="edr-muted" ta="right">
|
||||
Not available while your profile changes are under review.
|
||||
</Text>
|
||||
)}
|
||||
</Stack>
|
||||
</Card>
|
||||
|
||||
<Modal
|
||||
opened={confirming}
|
||||
onClose={() => setConfirming(false)}
|
||||
title="Switch to eTrade registration?"
|
||||
centered
|
||||
radius="lg"
|
||||
>
|
||||
<Stack gap="md">
|
||||
<Text size="sm">This re-opens your application:</Text>
|
||||
<List size="sm" spacing="xs">
|
||||
<List.Item>
|
||||
The registration details you typed are cleared — eTrade supplies
|
||||
them once your TIN is found.
|
||||
</List.Item>
|
||||
<List.Item>
|
||||
Your company goes back to pending and is reviewed again.
|
||||
</List.Item>
|
||||
<List.Item>
|
||||
Your documents, owner and contact details stay as they are.
|
||||
</List.Item>
|
||||
</List>
|
||||
<Alert color="amber" variant="light" icon={<AlertCircle size={18} />}>
|
||||
If eTrade holds no record for your TIN you won't be able to finish —
|
||||
come back here and re-select the investment licence in the wizard.
|
||||
</Alert>
|
||||
{error && (
|
||||
<Text size="sm" c="red">
|
||||
{error}
|
||||
</Text>
|
||||
)}
|
||||
<Group justify="flex-end">
|
||||
<Button variant="default" onClick={() => setConfirming(false)}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
color="edr-green"
|
||||
loading={revert.isPending}
|
||||
onClick={() => revert.mutate()}
|
||||
>
|
||||
Switch and re-apply
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user