mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-07 18:55:42 +00:00
feat: add etrade precheck
This commit is contained in:
@@ -7,9 +7,11 @@ import {
|
||||
Text,
|
||||
TextInput,
|
||||
} from "@mantine/core";
|
||||
import { useEffect, useRef } from "react";
|
||||
import type { UseFormRegisterReturn } from "react-hook-form";
|
||||
import { AlertCircle, CheckCircle2, Download } from "lucide-react";
|
||||
import { AlertCircle, CheckCircle2, Download, Info } from "lucide-react";
|
||||
import { useETradeData } from "@/hooks/useETradeData";
|
||||
import { extractApiError } from "@/utils/result";
|
||||
import type { CompanyRegistrationData } from "@edr/types";
|
||||
|
||||
interface ETradeInfoProps {
|
||||
@@ -22,6 +24,8 @@ interface ETradeInfoProps {
|
||||
onDataLoaded: (data: CompanyRegistrationData) => void;
|
||||
}
|
||||
|
||||
const isValidTin = (tin: string) => tin.length === 10;
|
||||
|
||||
export default function ETradeInfo({
|
||||
tin,
|
||||
register,
|
||||
@@ -30,53 +34,100 @@ export default function ETradeInfo({
|
||||
}: ETradeInfoProps) {
|
||||
const mutation = useETradeData();
|
||||
const isLoading = mutation.isPending;
|
||||
const hasData = mutation.data;
|
||||
const tinTaken = mutation.data?.tinTaken;
|
||||
const hasData =
|
||||
mutation.data && !mutation.data.tinTaken ? mutation.data : null;
|
||||
|
||||
const handleFetch = async () => {
|
||||
if (!tin || tin.length !== 10 || !tin.startsWith("00")) return;
|
||||
if (!isValidTin(tin)) return;
|
||||
const result = await mutation.mutateAsync(tin);
|
||||
if (result) {
|
||||
if (result && !result.tinTaken) {
|
||||
onDataLoaded(result);
|
||||
}
|
||||
};
|
||||
|
||||
const errorMessage =
|
||||
// Auto-fetch as soon as the TIN reaches its full 10-digit length — only
|
||||
// once per distinct value, so retyping the same TIN doesn't refetch.
|
||||
const lastFetchedTin = useRef<string | null>(null);
|
||||
useEffect(() => {
|
||||
if (isValidTin(tin) && lastFetchedTin.current !== tin) {
|
||||
lastFetchedTin.current = tin;
|
||||
handleFetch();
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [tin]);
|
||||
|
||||
const apiError =
|
||||
mutation.isError && mutation.error
|
||||
? (mutation.error as any).message ||
|
||||
"Failed to fetch company information. Please try again."
|
||||
? extractApiError(mutation.error)
|
||||
: null;
|
||||
// A 400 here means eTrade simply has no record for this TIN — not a
|
||||
// failure. Soft-pedal it as an FYI, not a red error, so filling in
|
||||
// manually doesn't feel like something went wrong.
|
||||
const notFound = apiError?.statusCode === 400;
|
||||
const errorMessage =
|
||||
apiError && !notFound
|
||||
? apiError.message ||
|
||||
"We couldn't reach eTrade to fetch your company information. Please try again, or fill in the details manually below."
|
||||
: null;
|
||||
|
||||
return (
|
||||
<Stack gap="md">
|
||||
<Group align="flex-start" grow>
|
||||
<TextInput
|
||||
label={<>TIN Number (10 digits) <span style={{ color: "var(--mantine-color-red-6)" }}>*</span></>}
|
||||
label={
|
||||
<>
|
||||
TIN Number (10 digits){" "}
|
||||
<span style={{ color: "var(--mantine-color-red-6)" }}>*</span>
|
||||
</>
|
||||
}
|
||||
placeholder="0012345678"
|
||||
maxLength={10}
|
||||
error={error}
|
||||
{...register}
|
||||
/>
|
||||
<Button
|
||||
variant="filled"
|
||||
color="edr-green"
|
||||
onClick={handleFetch}
|
||||
disabled={!tin || tin.length !== 10 || !tin.startsWith("00") || isLoading}
|
||||
leftSection={
|
||||
isLoading ? <Loader size={16} /> : <Download size={16} />
|
||||
}
|
||||
mt="24px"
|
||||
>
|
||||
{isLoading ? "Getting..." : "Get Data"}
|
||||
</Button>
|
||||
{errorMessage && (
|
||||
<Button
|
||||
variant="filled"
|
||||
color="edr-green"
|
||||
onClick={handleFetch}
|
||||
disabled={!isValidTin(tin) || isLoading}
|
||||
leftSection={
|
||||
isLoading ? <Loader size={16} /> : <Download size={16} />
|
||||
}
|
||||
mt="24px"
|
||||
>
|
||||
{isLoading ? "Getting..." : "Get Data"}
|
||||
</Button>
|
||||
)}
|
||||
</Group>
|
||||
|
||||
{notFound && (
|
||||
<Alert icon={<Info size={16} />} color="gray">
|
||||
We couldn't find a matching business record for this TIN — no
|
||||
problem, just fill in the details below.
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
{errorMessage && (
|
||||
<Alert
|
||||
icon={<AlertCircle size={16} />}
|
||||
color="red"
|
||||
title="Failed to fetch data"
|
||||
title="Couldn't fetch eTrade data"
|
||||
>
|
||||
{errorMessage} You can still fill in the details manually below.
|
||||
{errorMessage}
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
{tinTaken && (
|
||||
<Alert
|
||||
icon={<AlertCircle size={16} />}
|
||||
color="red"
|
||||
title="TIN already registered"
|
||||
>
|
||||
This TIN is already registered to another company account. Please
|
||||
double-check the number, or contact support if you believe this is a
|
||||
mistake.
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
|
||||
@@ -450,8 +450,6 @@ export default function CompanyProfileForm({
|
||||
onDataLoaded={handleETradeDataLoaded}
|
||||
/>
|
||||
|
||||
<Divider my="sm" />
|
||||
|
||||
<TextInput
|
||||
label="Company Name"
|
||||
placeholder="Global Logistics Ltd"
|
||||
@@ -507,7 +505,7 @@ export default function CompanyProfileForm({
|
||||
from eTrade · read-only
|
||||
</Text>
|
||||
</Group>
|
||||
<SimpleGrid cols={2} spacing="md">
|
||||
<SimpleGrid cols={2} spacing="sm">
|
||||
<ReadOnlyField
|
||||
label="License Number"
|
||||
value={watch("licenceNumber")}
|
||||
|
||||
Reference in New Issue
Block a user