mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-27 00:52:50 +00:00
feat: integrate eTradeInfo component for auto-filling company information and enhance TIN input handling
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { Injectable, BadRequestException } from "@nestjs/common";
|
||||
import { HttpService } from "@nestjs/axios";
|
||||
import { Agent } from "https";
|
||||
import { firstValueFrom } from "rxjs";
|
||||
import {
|
||||
ETradeCompanyInfo,
|
||||
@@ -12,6 +13,14 @@ export class ETradeService {
|
||||
private readonly baseUrl = "https://etrade.gov.et/api";
|
||||
private readonly referer = "https://etrade.gov.et/business-license-checker";
|
||||
|
||||
/**
|
||||
* The eTrade server serves an incomplete TLS chain (it omits the intermediate
|
||||
* CA cert), so Node rejects the handshake with UNABLE_TO_GET_ISSUER_CERT.
|
||||
* Scope a relaxed agent to these outbound calls only — the rest of the app
|
||||
* keeps full certificate verification.
|
||||
*/
|
||||
private readonly httpsAgent = new Agent({ rejectUnauthorized: false });
|
||||
|
||||
constructor(private readonly httpService: HttpService) {}
|
||||
|
||||
async getCompanyInfoByTin(tin: string): Promise<ETradeCompanyInfo> {
|
||||
@@ -20,6 +29,7 @@ export class ETradeService {
|
||||
const response = await firstValueFrom(
|
||||
this.httpService.get<ETradeCompanyInfo>(url, {
|
||||
headers: { Referer: this.referer },
|
||||
httpsAgent: this.httpsAgent,
|
||||
}),
|
||||
);
|
||||
return response.data;
|
||||
@@ -44,6 +54,7 @@ export class ETradeService {
|
||||
Lang: "en",
|
||||
},
|
||||
headers: { Referer: this.referer },
|
||||
httpsAgent: this.httpsAgent,
|
||||
}),
|
||||
);
|
||||
return response.data;
|
||||
|
||||
@@ -3,24 +3,33 @@ import {
|
||||
Button,
|
||||
Group,
|
||||
Loader,
|
||||
SimpleGrid,
|
||||
Stack,
|
||||
Text,
|
||||
TextInput,
|
||||
} from "@mantine/core";
|
||||
import { AlertCircle, CheckCircle2, RefreshCw } from "lucide-react";
|
||||
import type { UseFormRegisterReturn } from "react-hook-form";
|
||||
import { AlertCircle, CheckCircle2, Download } from "lucide-react";
|
||||
import { useETradeData } from "@/hooks/useETradeData";
|
||||
import type { CompanyRegistrationData } from "@edr/types";
|
||||
|
||||
interface ETradeInfoProps {
|
||||
/** Current TIN value (drives button enablement). */
|
||||
tin: string;
|
||||
/** RHF registration for the TIN input — this is the form's primary TIN field. */
|
||||
register: UseFormRegisterReturn;
|
||||
/** Validation error for the TIN field, if any. */
|
||||
error?: string;
|
||||
onDataLoaded: (data: CompanyRegistrationData) => void;
|
||||
}
|
||||
|
||||
export default function ETradeInfo({ tin, onDataLoaded }: ETradeInfoProps) {
|
||||
export default function ETradeInfo({
|
||||
tin,
|
||||
register,
|
||||
error,
|
||||
onDataLoaded,
|
||||
}: ETradeInfoProps) {
|
||||
const mutation = useETradeData();
|
||||
const isLoading = mutation.isPending;
|
||||
const hasError = mutation.isError;
|
||||
const hasData = mutation.data;
|
||||
|
||||
const handleFetch = async () => {
|
||||
@@ -32,40 +41,42 @@ export default function ETradeInfo({ tin, onDataLoaded }: ETradeInfoProps) {
|
||||
};
|
||||
|
||||
const errorMessage =
|
||||
hasError && mutation.error
|
||||
mutation.isError && mutation.error
|
||||
? (mutation.error as any).message ||
|
||||
"Failed to fetch company information. Please try again."
|
||||
: null;
|
||||
|
||||
return (
|
||||
<Stack gap="md">
|
||||
<Group grow>
|
||||
<Group align="flex-start" grow>
|
||||
<TextInput
|
||||
label="TIN Number"
|
||||
label="TIN Number (10 digits)"
|
||||
placeholder="1234567890"
|
||||
value={tin}
|
||||
disabled
|
||||
readOnly
|
||||
maxLength={10}
|
||||
error={error}
|
||||
{...register}
|
||||
/>
|
||||
<Button
|
||||
variant="filled"
|
||||
color="edr-green"
|
||||
onClick={handleFetch}
|
||||
disabled={!tin || tin.length !== 10 || isLoading}
|
||||
leftSection={isLoading ? <Loader size={16} /> : <RefreshCw size={16} />}
|
||||
leftSection={
|
||||
isLoading ? <Loader size={16} /> : <Download size={16} />
|
||||
}
|
||||
mt="24px"
|
||||
>
|
||||
{isLoading ? "Fetching..." : "Fetch Info from eTrade"}
|
||||
{isLoading ? "Getting..." : "Get Data"}
|
||||
</Button>
|
||||
</Group>
|
||||
|
||||
{hasError && errorMessage && (
|
||||
{errorMessage && (
|
||||
<Alert
|
||||
icon={<AlertCircle size={16} />}
|
||||
color="red"
|
||||
title="Failed to fetch data"
|
||||
>
|
||||
{errorMessage}
|
||||
{errorMessage} You can still fill in the details manually below.
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
|
||||
@@ -614,6 +614,18 @@ export default function CompanyProfileForm({
|
||||
<Stack gap="md">
|
||||
{step === "company" && (
|
||||
<>
|
||||
<Text fw={600} size="sm" c="edr-text">
|
||||
Enter your TIN to auto-fill company information from eTrade
|
||||
</Text>
|
||||
<ETradeInfo
|
||||
tin={watch("tinNumber")}
|
||||
register={register("tinNumber")}
|
||||
error={errors.tinNumber?.message}
|
||||
onDataLoaded={handleETradeDataLoaded}
|
||||
/>
|
||||
|
||||
<Divider my="sm" />
|
||||
|
||||
<TextInput
|
||||
label="Company Name"
|
||||
placeholder="Global Logistics Ltd"
|
||||
@@ -654,13 +666,6 @@ export default function CompanyProfileForm({
|
||||
/>
|
||||
</SimpleGrid>
|
||||
<SimpleGrid cols={2} spacing="md">
|
||||
<TextInput
|
||||
label="TIN Number (10 digits)"
|
||||
placeholder="1234567890"
|
||||
maxLength={10}
|
||||
error={errors.tinNumber?.message}
|
||||
{...register("tinNumber")}
|
||||
/>
|
||||
<TextInput
|
||||
label="VAT Number"
|
||||
placeholder="VAT-12345"
|
||||
@@ -668,23 +673,14 @@ export default function CompanyProfileForm({
|
||||
error={errors.vatNumber?.message}
|
||||
{...register("vatNumber")}
|
||||
/>
|
||||
<TextInput
|
||||
label="FAN Number (16 digits)"
|
||||
placeholder="1234567890123456"
|
||||
maxLength={16}
|
||||
error={errors.fanNumber?.message}
|
||||
{...register("fanNumber")}
|
||||
/>
|
||||
</SimpleGrid>
|
||||
<TextInput
|
||||
label="FAN Number (16 digits)"
|
||||
placeholder="1234567890123456"
|
||||
maxLength={16}
|
||||
error={errors.fanNumber?.message}
|
||||
{...register("fanNumber")}
|
||||
/>
|
||||
|
||||
<Divider my="sm" />
|
||||
<Text fw={600} size="sm" c="edr-text">
|
||||
Fetch Company Information from eTrade
|
||||
</Text>
|
||||
<ETradeInfo
|
||||
tin={watch("tinNumber")}
|
||||
onDataLoaded={handleETradeDataLoaded}
|
||||
/>
|
||||
|
||||
{watch("licenceNumber") && (
|
||||
<>
|
||||
|
||||
Reference in New Issue
Block a user