mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-07 21:15:41 +00:00
fix: etrade loading
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import { Alert, Button, Group, Loader, Stack, TextInput } from "@mantine/core";
|
import { Alert, Button, Loader, Stack, TextInput } from "@mantine/core";
|
||||||
import { useEffect, useRef } from "react";
|
import { useEffect, useRef } from "react";
|
||||||
import type { UseFormRegisterReturn } from "react-hook-form";
|
import type { UseFormRegisterReturn } from "react-hook-form";
|
||||||
import { AlertCircle, Download } from "lucide-react";
|
import { AlertCircle, Download } from "lucide-react";
|
||||||
@@ -24,6 +24,8 @@ interface ETradeInfoProps {
|
|||||||
onDataLoaded: (data: CompanyRegistrationData) => void;
|
onDataLoaded: (data: CompanyRegistrationData) => void;
|
||||||
/** Reports the live lookup status so the parent step can gate on it. */
|
/** Reports the live lookup status so the parent step can gate on it. */
|
||||||
onStatusChange?: (status: ETradeStatus) => void;
|
onStatusChange?: (status: ETradeStatus) => void;
|
||||||
|
/** Called when the TIN changes away from the last fetched value — clear whatever it filled in. */
|
||||||
|
onReset?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const isValidTin = (tin: string) => tin.length === 10;
|
const isValidTin = (tin: string) => tin.length === 10;
|
||||||
@@ -34,14 +36,22 @@ export default function ETradeInfo({
|
|||||||
error,
|
error,
|
||||||
onDataLoaded,
|
onDataLoaded,
|
||||||
onStatusChange,
|
onStatusChange,
|
||||||
|
onReset,
|
||||||
}: ETradeInfoProps) {
|
}: ETradeInfoProps) {
|
||||||
const mutation = useETradeData();
|
const mutation = useETradeData();
|
||||||
const isLoading = mutation.isPending;
|
const isLoading = mutation.isPending;
|
||||||
const tinTaken = mutation.data?.tinTaken;
|
const tinTaken = mutation.data?.tinTaken;
|
||||||
|
|
||||||
|
// Bumped on every TIN change so a fetch already in flight for an older TIN
|
||||||
|
// is ignored when it lands — otherwise a slow lookup can resolve after the
|
||||||
|
// user has typed a different TIN and overwrite its fields with stale data.
|
||||||
|
const requestIdRef = useRef(0);
|
||||||
|
|
||||||
const handleFetch = async () => {
|
const handleFetch = async () => {
|
||||||
if (!isValidTin(tin)) return;
|
if (!isValidTin(tin)) return;
|
||||||
|
const requestId = ++requestIdRef.current;
|
||||||
const result = await mutation.mutateAsync(tin);
|
const result = await mutation.mutateAsync(tin);
|
||||||
|
if (requestIdRef.current !== requestId) return;
|
||||||
if (result && !result.tinTaken) {
|
if (result && !result.tinTaken) {
|
||||||
onDataLoaded(result);
|
onDataLoaded(result);
|
||||||
}
|
}
|
||||||
@@ -53,6 +63,16 @@ export default function ETradeInfo({
|
|||||||
// doesn't refire the lookup the moment this mounts.
|
// doesn't refire the lookup the moment this mounts.
|
||||||
const lastFetchedTin = useRef<string | null>(tin || null);
|
const lastFetchedTin = useRef<string | null>(tin || null);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (tin !== lastFetchedTin.current) {
|
||||||
|
// TIN moved away from whatever we last fetched — that result (verified
|
||||||
|
// data, "taken", or an error) no longer describes this TIN. Drop it so
|
||||||
|
// the UI doesn't keep showing the previous TIN's outcome.
|
||||||
|
requestIdRef.current++;
|
||||||
|
if (mutation.data || mutation.error) {
|
||||||
|
mutation.reset();
|
||||||
|
onReset?.();
|
||||||
|
}
|
||||||
|
}
|
||||||
if (isValidTin(tin) && lastFetchedTin.current !== tin) {
|
if (isValidTin(tin) && lastFetchedTin.current !== tin) {
|
||||||
lastFetchedTin.current = tin;
|
lastFetchedTin.current = tin;
|
||||||
handleFetch();
|
handleFetch();
|
||||||
@@ -90,8 +110,13 @@ export default function ETradeInfo({
|
|||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [status]);
|
}, [status]);
|
||||||
|
|
||||||
const showRetry =
|
// True for the one render between the TIN reaching 10 digits and the
|
||||||
isValidTin(tin) && status !== "verified" && status !== "loading";
|
// effect above actually starting the fetch — without this, "Get Data"
|
||||||
|
// flashes on screen for that frame before `isLoading` ever turns true.
|
||||||
|
const willAutoFetch = isValidTin(tin) && lastFetchedTin.current !== tin;
|
||||||
|
const showLoading = isLoading || willAutoFetch;
|
||||||
|
|
||||||
|
const showRetry = isValidTin(tin) && status !== "verified" && !showLoading;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack gap="md">
|
<Stack gap="md">
|
||||||
@@ -103,18 +128,27 @@ export default function ETradeInfo({
|
|||||||
error={error}
|
error={error}
|
||||||
{...register}
|
{...register}
|
||||||
/>
|
/>
|
||||||
|
{showLoading && (
|
||||||
|
<Button
|
||||||
|
className="max-w-none"
|
||||||
|
variant="filled"
|
||||||
|
color="edr-green"
|
||||||
|
disabled
|
||||||
|
leftSection={<Loader size={16} />}
|
||||||
|
>
|
||||||
|
Getting...
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
{showRetry && (
|
{showRetry && (
|
||||||
<Button
|
<Button
|
||||||
className="max-w-none"
|
className="max-w-none"
|
||||||
variant="filled"
|
variant="filled"
|
||||||
color="edr-green"
|
color="edr-green"
|
||||||
onClick={handleFetch}
|
onClick={handleFetch}
|
||||||
disabled={!isValidTin(tin) || isLoading}
|
disabled={!isValidTin(tin)}
|
||||||
leftSection={
|
leftSection={<Download size={16} />}
|
||||||
isLoading ? <Loader size={16} /> : <Download size={16} />
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
{isLoading ? "Getting..." : "Get Data"}
|
Get Data
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -288,6 +288,24 @@ export default function CompanyProfileForm({
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TIN changed since the last successful lookup — the registration/address
|
||||||
|
// fields it filled in describe the OLD TIN, not this one, so clear them
|
||||||
|
// rather than leaving them stale on screen.
|
||||||
|
const handleETradeReset = () => {
|
||||||
|
setValue("licenceNumber", "");
|
||||||
|
setValue("statusDescription", "");
|
||||||
|
setValue("dateRegistered", "");
|
||||||
|
setValue("renewedFrom", "");
|
||||||
|
setValue("renewalDate", "");
|
||||||
|
setValue("renewedTo", "");
|
||||||
|
setValue("region", "");
|
||||||
|
setValue("zone", "");
|
||||||
|
setValue("woreda", "");
|
||||||
|
setValue("kebele", "");
|
||||||
|
setValue("houseNo", "");
|
||||||
|
setEtradeOwner(null);
|
||||||
|
};
|
||||||
|
|
||||||
// companyEmail/companyPhone are no longer typed — the Fayda-verified owner
|
// companyEmail/companyPhone are no longer typed — the Fayda-verified owner
|
||||||
// is the highest-trust source (that's the whole point of verifying), eTrade's
|
// is the highest-trust source (that's the whole point of verifying), eTrade's
|
||||||
// registered number and the account email/phone are the fallbacks used
|
// registered number and the account email/phone are the fallbacks used
|
||||||
@@ -718,6 +736,7 @@ export default function CompanyProfileForm({
|
|||||||
error={errors.tinNumber?.message}
|
error={errors.tinNumber?.message}
|
||||||
onDataLoaded={handleETradeDataLoaded}
|
onDataLoaded={handleETradeDataLoaded}
|
||||||
onStatusChange={setTinStatus}
|
onStatusChange={setTinStatus}
|
||||||
|
onReset={handleETradeReset}
|
||||||
/>
|
/>
|
||||||
{tinVerified && (
|
{tinVerified && (
|
||||||
<ETradeCompanyCard
|
<ETradeCompanyCard
|
||||||
|
|||||||
Reference in New Issue
Block a user