@retinalabsllc/zairusjs 0.5.0 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +30 -1
- package/dist/index.d.ts +30 -1
- package/dist/index.js +620 -6
- package/dist/index.mjs +620 -7
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1513,7 +1513,7 @@ var UniversalSidebar = ({
|
|
|
1513
1513
|
className: "absolute inset-0 bg-black/30",
|
|
1514
1514
|
onClick: onCancelIntercept
|
|
1515
1515
|
}
|
|
1516
|
-
), /* @__PURE__ */ React25.createElement("div", { className: "relative w-72 bg-white rounded-2xl flex flex-col items-center overflow-hidden shadow-2xl animate-in zoom-in-95 duration-200" }, /* @__PURE__ */ React25.createElement("div", { className: "p-6 text-center w-full" }, /* @__PURE__ */ React25.createElement("h3", { className: " font-serif text-[
|
|
1516
|
+
), /* @__PURE__ */ React25.createElement("div", { className: "relative w-72 bg-white rounded-2xl flex flex-col items-center overflow-hidden shadow-2xl animate-in zoom-in-95 duration-200" }, /* @__PURE__ */ React25.createElement("div", { className: "p-6 text-center w-full" }, /* @__PURE__ */ React25.createElement("h3", { className: " font-serif text-[17px] text-black tracking-tight mb-1" }, interceptTitle), /* @__PURE__ */ React25.createElement("p", { className: "text-[12px] text-neutral-500 leading-snug mt-2" }, interceptMessage)), /* @__PURE__ */ React25.createElement("div", { className: "w-full flex" }, /* @__PURE__ */ React25.createElement(
|
|
1517
1517
|
"button",
|
|
1518
1518
|
{
|
|
1519
1519
|
onClick: onCancelIntercept,
|
|
@@ -1535,7 +1535,7 @@ import React26, { useState as useState10 } from "react";
|
|
|
1535
1535
|
import Link10 from "next/link";
|
|
1536
1536
|
import { HugeiconsIcon as HugeiconsIcon14 } from "@hugeicons/react";
|
|
1537
1537
|
import {
|
|
1538
|
-
|
|
1538
|
+
UserSwitchIcon,
|
|
1539
1539
|
SidebarLeft01Icon as SidebarLeft01Icon2,
|
|
1540
1540
|
CheckmarkCircle01Icon,
|
|
1541
1541
|
LogoutCircle02Icon,
|
|
@@ -1584,7 +1584,7 @@ var UniversalHeader = ({
|
|
|
1584
1584
|
className: "w-10 h-10 rounded-full border border-neutral-100 bg-white flex items-center justify-center text-neutral-500 hover:text-black hover:border-black hover:bg-neutral-50 transition-all group outline-none",
|
|
1585
1585
|
"aria-label": "Switch Workspace"
|
|
1586
1586
|
},
|
|
1587
|
-
/* @__PURE__ */ React26.createElement(HugeiconsIcon14, { icon:
|
|
1587
|
+
/* @__PURE__ */ React26.createElement(HugeiconsIcon14, { icon: UserSwitchIcon, size: 16, className: "transition-transform group-hover:-translate-x-0.5" })
|
|
1588
1588
|
), showLogoutAction && /* @__PURE__ */ React26.createElement(
|
|
1589
1589
|
"button",
|
|
1590
1590
|
{
|
|
@@ -1607,7 +1607,7 @@ var UniversalHeader = ({
|
|
|
1607
1607
|
className: "absolute inset-0 bg-black/30",
|
|
1608
1608
|
onClick: () => setShowSwitcherDialog(false)
|
|
1609
1609
|
}
|
|
1610
|
-
), /* @__PURE__ */ React26.createElement("div", { className: "relative w-full max-w-sm bg-white rounded-2xl flex flex-col overflow-hidden shadow-2xl animate-in zoom-in-95 duration-200" }, /* @__PURE__ */ React26.createElement("div", { className: "p-5 text-center w-full" }, /* @__PURE__ */ React26.createElement("h3", { className: " font-serif text-[
|
|
1610
|
+
), /* @__PURE__ */ React26.createElement("div", { className: "relative w-full max-w-sm bg-white rounded-2xl flex flex-col overflow-hidden shadow-2xl animate-in zoom-in-95 duration-200" }, /* @__PURE__ */ React26.createElement("div", { className: "p-5 text-center w-full" }, /* @__PURE__ */ React26.createElement("h3", { className: " font-serif text-[17px] text-black tracking-tight mb-1" }, "Switch Workspace"), /* @__PURE__ */ React26.createElement("p", { className: "text-[11px] text-neutral-500 leading-snug" }, "Select an organization to switch your current context.")), /* @__PURE__ */ React26.createElement("div", { className: "max-h-75 overflow-y-auto w-full custom-scrollbar" }, workspaces.map((org) => /* @__PURE__ */ React26.createElement(
|
|
1611
1611
|
"button",
|
|
1612
1612
|
{
|
|
1613
1613
|
key: org.id,
|
|
@@ -1632,7 +1632,7 @@ var UniversalHeader = ({
|
|
|
1632
1632
|
className: "absolute inset-0 bg-black/30",
|
|
1633
1633
|
onClick: () => !isLoggingOut && setShowLogoutDialog(false)
|
|
1634
1634
|
}
|
|
1635
|
-
), /* @__PURE__ */ React26.createElement("div", { className: "relative w-72 bg-white rounded-2xl flex flex-col items-center overflow-hidden shadow-2xl animate-in zoom-in-95 duration-200" }, /* @__PURE__ */ React26.createElement("div", { className: "p-6 text-center w-full" }, /* @__PURE__ */ React26.createElement("h3", { className: " font-serif text-[
|
|
1635
|
+
), /* @__PURE__ */ React26.createElement("div", { className: "relative w-72 bg-white rounded-2xl flex flex-col items-center overflow-hidden shadow-2xl animate-in zoom-in-95 duration-200" }, /* @__PURE__ */ React26.createElement("div", { className: "p-6 text-center w-full" }, /* @__PURE__ */ React26.createElement("h3", { className: " font-serif text-[17px] text-black tracking-tight mb-1" }, "Secure Logout"), /* @__PURE__ */ React26.createElement("p", { className: "text-[12px] text-neutral-500 leading-snug mt-2" }, "Are you sure you want to log out? You will need to authenticate to return.")), /* @__PURE__ */ React26.createElement("div", { className: "w-full flex" }, /* @__PURE__ */ React26.createElement(
|
|
1636
1636
|
"button",
|
|
1637
1637
|
{
|
|
1638
1638
|
onClick: () => setShowLogoutDialog(false),
|
|
@@ -1900,7 +1900,7 @@ var UniversalIdentityPage = ({
|
|
|
1900
1900
|
},
|
|
1901
1901
|
"Delete ",
|
|
1902
1902
|
headerTitle.split(" ")[0]
|
|
1903
|
-
)))), isDeleteModalOpen && !isReadOnly && allowDeletion && /* @__PURE__ */ React28.createElement("div", { className: "fixed inset-0 z-110 flex items-center justify-center p-4" }, /* @__PURE__ */ React28.createElement("div", { className: "absolute inset-0 bg-black/30 shadow-2xl", onClick: () => !isDeleting && setIsDeleteModalOpen(false) }), /* @__PURE__ */ React28.createElement("div", { className: "relative w-72 bg-white shadow-2xl rounded-2xl flex flex-col items-center overflow-hidden animate-in zoom-in-95 duration-200" }, /* @__PURE__ */ React28.createElement("div", { className: "p-6 text-center w-full" }, /* @__PURE__ */ React28.createElement("h3", { className: " font-serif text-[
|
|
1903
|
+
)))), isDeleteModalOpen && !isReadOnly && allowDeletion && /* @__PURE__ */ React28.createElement("div", { className: "fixed inset-0 z-110 flex items-center justify-center p-4" }, /* @__PURE__ */ React28.createElement("div", { className: "absolute inset-0 bg-black/30 shadow-2xl", onClick: () => !isDeleting && setIsDeleteModalOpen(false) }), /* @__PURE__ */ React28.createElement("div", { className: "relative w-72 bg-white shadow-2xl rounded-2xl flex flex-col items-center overflow-hidden animate-in zoom-in-95 duration-200" }, /* @__PURE__ */ React28.createElement("div", { className: "p-6 text-center w-full" }, /* @__PURE__ */ React28.createElement("h3", { className: " font-serif text-[17px] text-black tracking-tight mb-1" }, "Confirm Deletion"), /* @__PURE__ */ React28.createElement("p", { className: "text-[12px] text-neutral-500 leading-snug mt-2" }, deleteWarningText)), /* @__PURE__ */ React28.createElement("div", { className: "w-full flex" }, /* @__PURE__ */ React28.createElement(
|
|
1904
1904
|
"button",
|
|
1905
1905
|
{
|
|
1906
1906
|
type: "button",
|
|
@@ -2185,7 +2185,7 @@ var UniversalMembersPage = ({
|
|
|
2185
2185
|
className: "w-full py-2.5 text-[13px] text-neutral-600 hover:bg-neutral-50 transition-colors disabled:opacity-50 outline-none"
|
|
2186
2186
|
},
|
|
2187
2187
|
"Cancel"
|
|
2188
|
-
)))), memberToDelete && canManage && /* @__PURE__ */ React29.createElement("div", { className: "fixed inset-0 z-110 flex items-center justify-center p-4" }, /* @__PURE__ */ React29.createElement("div", { className: "absolute inset-0 bg-black/30", onClick: () => !isDeleting && setMemberToDelete(null) }), /* @__PURE__ */ React29.createElement("div", { className: "relative w-72 bg-white shadow-2xl rounded-2xl flex flex-col items-center overflow-hidden animate-in zoom-in-95 duration-200" }, /* @__PURE__ */ React29.createElement("div", { className: "p-6 text-center w-full" }, /* @__PURE__ */ React29.createElement("h3", { className: " font-serif text-[
|
|
2188
|
+
)))), memberToDelete && canManage && /* @__PURE__ */ React29.createElement("div", { className: "fixed inset-0 z-110 flex items-center justify-center p-4" }, /* @__PURE__ */ React29.createElement("div", { className: "absolute inset-0 bg-black/30", onClick: () => !isDeleting && setMemberToDelete(null) }), /* @__PURE__ */ React29.createElement("div", { className: "relative w-72 bg-white shadow-2xl rounded-2xl flex flex-col items-center overflow-hidden animate-in zoom-in-95 duration-200" }, /* @__PURE__ */ React29.createElement("div", { className: "p-6 text-center w-full" }, /* @__PURE__ */ React29.createElement("h3", { className: " font-serif text-[17px] text-black tracking-tight mb-1" }, "Remove Member"), /* @__PURE__ */ React29.createElement("p", { className: "text-[12px] text-neutral-500 leading-snug mt-2" }, "Are you sure you want to remove this member? They will lose access instantly.")), /* @__PURE__ */ React29.createElement("div", { className: "w-full flex" }, /* @__PURE__ */ React29.createElement("button", { onClick: () => setMemberToDelete(null), disabled: isDeleting, className: "flex-1 py-2 text-[13px] text-neutral-600 hover:bg-neutral-50 transition-colors disabled:opacity-50 outline-none" }, "Cancel"), /* @__PURE__ */ React29.createElement("button", { onClick: handleDelete, disabled: isDeleting, className: "flex-1 py-2 text-[13px] text-red-600 hover:bg-neutral-50 transition-colors disabled:opacity-50 flex justify-center outline-none" }, isDeleting ? /* @__PURE__ */ React29.createElement(ButtonSpinner3, null) : "Remove")))));
|
|
2189
2189
|
};
|
|
2190
2190
|
|
|
2191
2191
|
// src/components/UniversalProfileSettings.tsx
|
|
@@ -2912,6 +2912,618 @@ var Stagger = ({ steps, currentStep }) => {
|
|
|
2912
2912
|
return /* @__PURE__ */ React40.createElement("div", { key: step, className: `w-6 h-6 rounded-full flex items-center justify-center transition-colors duration-300 ${colorClass}` }, /* @__PURE__ */ React40.createElement(HugeiconsIcon24, { icon: getIconForStep(step), size: 11 }));
|
|
2913
2913
|
}));
|
|
2914
2914
|
};
|
|
2915
|
+
|
|
2916
|
+
// src/components/UniversalRegistrationFlow.tsx
|
|
2917
|
+
import React41, { useState as useState20, useEffect as useEffect12, useRef as useRef6 } from "react";
|
|
2918
|
+
import toast6 from "react-hot-toast";
|
|
2919
|
+
import { HugeiconsIcon as HugeiconsIcon25 } from "@hugeicons/react";
|
|
2920
|
+
import { CheckmarkBadge01Icon, Upload01Icon as Upload01Icon3, UserIcon, Location01Icon, Briefcase02Icon as Briefcase02Icon2, Loading03Icon as Loading03Icon12, PencilEdit01Icon as PencilEdit01Icon2, Delete02Icon as Delete02Icon2, SignatureIcon, IdentificationIcon, ArrowLeft01Icon as ArrowLeft01Icon7, TimeQuarterPassIcon, Cancel01Icon as Cancel01Icon3 } from "@hugeicons/core-free-icons";
|
|
2921
|
+
var MACRO_STEPS = ["Details", "Documents", "Review", "Submit"];
|
|
2922
|
+
var NIGERIAN_STATES = ["Abia", "Adamawa", "Akwa Ibom", "Anambra", "Bauchi", "Bayelsa", "Benue", "Borno", "Cross River", "Delta", "Ebonyi", "Edo", "Ekiti", "Enugu", "FCT - Abuja", "Gombe", "Imo", "Jigawa", "Kaduna", "Kano", "Katsina", "Kebbi", "Kogi", "Kwara", "Lagos", "Nasarawa", "Niger", "Ogun", "Ondo", "Osun", "Oyo", "Plateau", "Rivers", "Sokoto", "Taraba", "Yobe", "Zamfara"];
|
|
2923
|
+
var MEMBER_ROLES = ["Director Only", "Shareholder Only", "Both Director & Shareholder"];
|
|
2924
|
+
var NATIONALITIES = ["Nigerian"];
|
|
2925
|
+
var UniversalRegistrationFlow = ({
|
|
2926
|
+
applicationId,
|
|
2927
|
+
type,
|
|
2928
|
+
apiEndpoint,
|
|
2929
|
+
onCancelOrClose,
|
|
2930
|
+
onRedirectToBilling,
|
|
2931
|
+
onRedirectToApplication
|
|
2932
|
+
}) => {
|
|
2933
|
+
const [isBooting, setIsBooting] = useState20(true);
|
|
2934
|
+
const [macroStep, setMacroStep] = useState20(0);
|
|
2935
|
+
const [appStatus, setAppStatus] = useState20("");
|
|
2936
|
+
const [isAbortModalOpen, setIsAbortModalOpen] = useState20(false);
|
|
2937
|
+
const [isAborting, setIsAborting] = useState20(false);
|
|
2938
|
+
const [formState, setFormState] = useState20({
|
|
2939
|
+
natureApproved: false,
|
|
2940
|
+
nameApproved: false,
|
|
2941
|
+
addressApproved: false,
|
|
2942
|
+
membersDetailsApproved: false,
|
|
2943
|
+
membersDocsApproved: false,
|
|
2944
|
+
ownerApproved: false,
|
|
2945
|
+
idApproved: false,
|
|
2946
|
+
passportApproved: false,
|
|
2947
|
+
signatureApproved: false
|
|
2948
|
+
});
|
|
2949
|
+
const idRef = useRef6(null);
|
|
2950
|
+
const passportRef = useRef6(null);
|
|
2951
|
+
const signatureRef = useRef6(null);
|
|
2952
|
+
const other1Ref = useRef6(null);
|
|
2953
|
+
const other2Ref = useRef6(null);
|
|
2954
|
+
const other3Ref = useRef6(null);
|
|
2955
|
+
const [formData, setFormData] = useState20({
|
|
2956
|
+
businessDesc: "",
|
|
2957
|
+
natureOfBusiness: null,
|
|
2958
|
+
proposedName: "",
|
|
2959
|
+
proposedName2: "",
|
|
2960
|
+
approvedName: "",
|
|
2961
|
+
address: "",
|
|
2962
|
+
city: "",
|
|
2963
|
+
state: "",
|
|
2964
|
+
members: [{ id: Date.now().toString(), fullName: "", email: "", phone: "", role: "Both Director & Shareholder", sharePercentage: "100", nationality: "Nigerian", address: "", city: "", state: "", idFileUrl: "", idMetadata: null, idExtractedData: null, passportFileUrl: "", passportMetadata: null, signatureFileUrl: "", signatureMetadata: null }],
|
|
2965
|
+
ownerName: "",
|
|
2966
|
+
ownerPhone: "",
|
|
2967
|
+
ownerEmail: "",
|
|
2968
|
+
idExtractedData: null,
|
|
2969
|
+
idFileUrl: "",
|
|
2970
|
+
idMetadata: null,
|
|
2971
|
+
passportFileUrl: "",
|
|
2972
|
+
passportMetadata: null,
|
|
2973
|
+
signatureFileUrl: "",
|
|
2974
|
+
signatureMetadata: null,
|
|
2975
|
+
otherDoc1Url: "",
|
|
2976
|
+
otherDoc1Meta: null,
|
|
2977
|
+
otherDoc2Url: "",
|
|
2978
|
+
otherDoc2Meta: null,
|
|
2979
|
+
otherDoc3Url: "",
|
|
2980
|
+
otherDoc3Meta: null
|
|
2981
|
+
});
|
|
2982
|
+
const [activeModal, setActiveModal] = useState20({ isOpen: false, type: null, memberIndex: null });
|
|
2983
|
+
const [iAgree, setIAgree] = useState20(false);
|
|
2984
|
+
const [isAnalyzingNature, setIsAnalyzingNature] = useState20(false);
|
|
2985
|
+
const [suggestedNature, setSuggestedNature] = useState20(null);
|
|
2986
|
+
const [isCheckingQualifier, setIsCheckingQualifier] = useState20(false);
|
|
2987
|
+
const [qualifierCheckResult, setQualifierCheckResult] = useState20(null);
|
|
2988
|
+
const [isCheckingName, setIsCheckingName] = useState20(false);
|
|
2989
|
+
const [nameCheckResult, setNameCheckResult] = useState20(null);
|
|
2990
|
+
const [globalExtractingId, setGlobalExtractingId] = useState20(false);
|
|
2991
|
+
const [globalUploadingPassport, setGlobalUploadingPassport] = useState20(false);
|
|
2992
|
+
const [globalUploadingSignature, setGlobalUploadingSignature] = useState20(false);
|
|
2993
|
+
const [isUploadingOther1, setIsUploadingOther1] = useState20(false);
|
|
2994
|
+
const [isUploadingOther2, setIsUploadingOther2] = useState20(false);
|
|
2995
|
+
const [isUploadingOther3, setIsUploadingOther3] = useState20(false);
|
|
2996
|
+
const [aiTasks, setAiTasks] = useState20([]);
|
|
2997
|
+
const [isSubmitting, setIsSubmitting] = useState20(false);
|
|
2998
|
+
const isReadOnly = ["PENDING", "AWAITING_PAYMENT", "COMPLETED"].includes(appStatus);
|
|
2999
|
+
const isAnyUploading = globalExtractingId || globalUploadingPassport || globalUploadingSignature || isUploadingOther1 || isUploadingOther2 || isUploadingOther3;
|
|
3000
|
+
const baseApi = async (action, payload = {}) => {
|
|
3001
|
+
try {
|
|
3002
|
+
const res = await fetch(apiEndpoint, {
|
|
3003
|
+
method: "POST",
|
|
3004
|
+
headers: { "Content-Type": "application/json" },
|
|
3005
|
+
body: JSON.stringify({ applicationId, action, payload })
|
|
3006
|
+
});
|
|
3007
|
+
return await res.json();
|
|
3008
|
+
} catch (error) {
|
|
3009
|
+
return { success: false, error: "Network communication failed." };
|
|
3010
|
+
}
|
|
3011
|
+
};
|
|
3012
|
+
useEffect12(() => {
|
|
3013
|
+
baseApi("progress_load").then((data) => {
|
|
3014
|
+
if (data.success && data.data) {
|
|
3015
|
+
const meta = data.data;
|
|
3016
|
+
if (meta.formData && meta.formState) {
|
|
3017
|
+
setFormData((p) => ({ ...p, ...meta.formData }));
|
|
3018
|
+
setFormState((p) => ({ ...p, ...meta.formState }));
|
|
3019
|
+
if (meta.macroStep !== void 0) setMacroStep(meta.macroStep);
|
|
3020
|
+
} else if (meta.proposedNames || meta.natureOfBusiness) {
|
|
3021
|
+
if (type === "company" && (meta.companyAddress || meta.directorsAndShareholders)) {
|
|
3022
|
+
const mappedForm = {
|
|
3023
|
+
businessDesc: meta.natureOfBusiness?.specificLabel ? `Form loaded: ${meta.natureOfBusiness.specificLabel}` : "",
|
|
3024
|
+
natureOfBusiness: meta.natureOfBusiness || null,
|
|
3025
|
+
proposedName: meta.proposedNames?.[0] || "",
|
|
3026
|
+
proposedName2: meta.proposedNames?.[1] || "",
|
|
3027
|
+
approvedName: meta.proposedNames?.[0] || "",
|
|
3028
|
+
address: meta.companyAddress?.streetAddress || "",
|
|
3029
|
+
city: meta.companyAddress?.city || "",
|
|
3030
|
+
state: meta.companyAddress?.state || "",
|
|
3031
|
+
members: (meta.directorsAndShareholders || []).map((m, idx) => ({
|
|
3032
|
+
id: idx.toString(),
|
|
3033
|
+
fullName: m.fullName || "",
|
|
3034
|
+
email: m.emailAddress || "",
|
|
3035
|
+
phone: m.phoneNumber || "",
|
|
3036
|
+
role: m.role || "Both Director & Shareholder",
|
|
3037
|
+
sharePercentage: m.sharePercentage || "",
|
|
3038
|
+
nationality: m.nationality || "Nigerian",
|
|
3039
|
+
address: m.residentialAddress?.streetAddress || "",
|
|
3040
|
+
city: m.residentialAddress?.city || "",
|
|
3041
|
+
state: m.residentialAddress?.state || "",
|
|
3042
|
+
idFileUrl: m.passportPhotograph?.fileDataUrl || "",
|
|
3043
|
+
idMetadata: null,
|
|
3044
|
+
idExtractedData: m.identification ? { fullName: m.fullName, idNumber: m.identification.idNumber, dob: m.dateOfBirth, documentType: m.identification.type } : null,
|
|
3045
|
+
passportFileUrl: m.passportPhotograph?.fileDataUrl || "",
|
|
3046
|
+
passportMetadata: m.passportPhotograph || null,
|
|
3047
|
+
signatureFileUrl: m.signature?.fileDataUrl || "",
|
|
3048
|
+
signatureMetadata: m.signature || null
|
|
3049
|
+
})),
|
|
3050
|
+
otherDoc1Url: meta.additionalDocuments?.[0]?.fileDataUrl || "",
|
|
3051
|
+
otherDoc1Meta: meta.additionalDocuments?.[0] || null,
|
|
3052
|
+
otherDoc2Url: meta.additionalDocuments?.[1]?.fileDataUrl || "",
|
|
3053
|
+
otherDoc2Meta: meta.additionalDocuments?.[1] || null,
|
|
3054
|
+
otherDoc3Url: meta.additionalDocuments?.[2]?.fileDataUrl || "",
|
|
3055
|
+
otherDoc3Meta: meta.additionalDocuments?.[2] || null
|
|
3056
|
+
};
|
|
3057
|
+
setFormData((p) => ({ ...p, ...mappedForm }));
|
|
3058
|
+
setFormState((p) => ({
|
|
3059
|
+
...p,
|
|
3060
|
+
natureApproved: !!meta.natureOfBusiness,
|
|
3061
|
+
nameApproved: !!meta.proposedNames?.[0],
|
|
3062
|
+
addressApproved: !!meta.companyAddress?.streetAddress,
|
|
3063
|
+
membersDetailsApproved: (meta.directorsAndShareholders || []).length > 0,
|
|
3064
|
+
membersDocsApproved: (meta.directorsAndShareholders || []).every((m) => m.passportPhotograph && m.signature)
|
|
3065
|
+
}));
|
|
3066
|
+
if (meta.directorsAndShareholders?.length > 0) {
|
|
3067
|
+
const docsApproved = (meta.directorsAndShareholders || []).every((m) => m.passportPhotograph && m.signature);
|
|
3068
|
+
setMacroStep(docsApproved ? 2 : 1);
|
|
3069
|
+
}
|
|
3070
|
+
} else if (type === "business" && (meta.businessAddress || meta.proprietors)) {
|
|
3071
|
+
const proprietor = meta.proprietors?.[0] || {};
|
|
3072
|
+
const mappedForm = {
|
|
3073
|
+
businessDesc: meta.natureOfBusiness?.specificLabel ? `Form loaded: ${meta.natureOfBusiness.specificLabel}` : "",
|
|
3074
|
+
natureOfBusiness: meta.natureOfBusiness || null,
|
|
3075
|
+
proposedName: meta.proposedNames?.[0] || "",
|
|
3076
|
+
proposedName2: meta.proposedNames?.[1] || "",
|
|
3077
|
+
approvedName: meta.proposedNames?.[0] || "",
|
|
3078
|
+
address: meta.businessAddress?.streetAddress || "",
|
|
3079
|
+
city: meta.businessAddress?.city || "",
|
|
3080
|
+
state: meta.businessAddress?.state || "",
|
|
3081
|
+
ownerName: proprietor.fullName || "",
|
|
3082
|
+
ownerPhone: proprietor.phoneNumber || "",
|
|
3083
|
+
ownerEmail: proprietor.emailAddress || "",
|
|
3084
|
+
idExtractedData: proprietor.identification ? { fullName: proprietor.fullName, idNumber: proprietor.identification.idNumber, dob: proprietor.dateOfBirth, documentType: proprietor.identification.type } : null,
|
|
3085
|
+
idFileUrl: "",
|
|
3086
|
+
idMetadata: null,
|
|
3087
|
+
passportFileUrl: proprietor.passportPhotograph?.fileDataUrl || "",
|
|
3088
|
+
passportMetadata: proprietor.passportPhotograph || null,
|
|
3089
|
+
signatureFileUrl: proprietor.signature?.fileDataUrl || "",
|
|
3090
|
+
signatureMetadata: proprietor.signature || null,
|
|
3091
|
+
otherDoc1Url: meta.additionalDocuments?.[0]?.fileDataUrl || "",
|
|
3092
|
+
otherDoc1Meta: meta.additionalDocuments?.[0] || null,
|
|
3093
|
+
otherDoc2Url: meta.additionalDocuments?.[1]?.fileDataUrl || "",
|
|
3094
|
+
otherDoc2Meta: meta.additionalDocuments?.[1] || null,
|
|
3095
|
+
otherDoc3Url: meta.additionalDocuments?.[2]?.fileDataUrl || "",
|
|
3096
|
+
otherDoc3Meta: meta.additionalDocuments?.[2] || null
|
|
3097
|
+
};
|
|
3098
|
+
setFormData((p) => ({ ...p, ...mappedForm }));
|
|
3099
|
+
const calcFormState = {
|
|
3100
|
+
natureApproved: !!meta.natureOfBusiness,
|
|
3101
|
+
nameApproved: !!meta.proposedNames?.[0],
|
|
3102
|
+
addressApproved: !!meta.businessAddress?.streetAddress,
|
|
3103
|
+
ownerApproved: !!proprietor.fullName && !!proprietor.phoneNumber,
|
|
3104
|
+
idApproved: !!proprietor.identification,
|
|
3105
|
+
passportApproved: !!proprietor.passportPhotograph,
|
|
3106
|
+
signatureApproved: !!proprietor.signature
|
|
3107
|
+
};
|
|
3108
|
+
setFormState((p) => ({ ...p, ...calcFormState }));
|
|
3109
|
+
if (proprietor.fullName || calcFormState.nameApproved) {
|
|
3110
|
+
setMacroStep(calcFormState.idApproved && calcFormState.passportApproved && calcFormState.signatureApproved ? 2 : 1);
|
|
3111
|
+
}
|
|
3112
|
+
}
|
|
3113
|
+
}
|
|
3114
|
+
}
|
|
3115
|
+
if (data.appStatus) {
|
|
3116
|
+
setAppStatus(data.appStatus);
|
|
3117
|
+
if (data.appStatus === "QUEUED" || data.appStatus === "REJECTED") setMacroStep(0);
|
|
3118
|
+
}
|
|
3119
|
+
}).catch(() => {
|
|
3120
|
+
toast6.error("Uh oh! Something went wrong while loading.");
|
|
3121
|
+
}).finally(() => setIsBooting(false));
|
|
3122
|
+
}, [applicationId, type, apiEndpoint]);
|
|
3123
|
+
const saveProgress = async (newFormData = formData, newFormState = formState, newMacro = macroStep) => {
|
|
3124
|
+
if (isReadOnly) return;
|
|
3125
|
+
baseApi("progress_save", { formData: newFormData, formState: newFormState, macroStep: newMacro }).catch(() => {
|
|
3126
|
+
});
|
|
3127
|
+
};
|
|
3128
|
+
const handleAbort = async () => {
|
|
3129
|
+
setIsAborting(true);
|
|
3130
|
+
const data = await baseApi("abort");
|
|
3131
|
+
if (data.success) {
|
|
3132
|
+
toast6.success("Application aborted.");
|
|
3133
|
+
setAppStatus("DRAFT");
|
|
3134
|
+
setMacroStep(0);
|
|
3135
|
+
setIsAbortModalOpen(false);
|
|
3136
|
+
} else toast6.error(data.error || "Uh oh! Something went wrong.");
|
|
3137
|
+
setIsAborting(false);
|
|
3138
|
+
};
|
|
3139
|
+
const handleBack = () => {
|
|
3140
|
+
if (macroStep === 0) {
|
|
3141
|
+
onCancelOrClose();
|
|
3142
|
+
} else {
|
|
3143
|
+
const prevStep = macroStep - 1;
|
|
3144
|
+
setMacroStep(prevStep);
|
|
3145
|
+
saveProgress(formData, formState, prevStep);
|
|
3146
|
+
}
|
|
3147
|
+
};
|
|
3148
|
+
const handleNext = () => {
|
|
3149
|
+
const nextStep = macroStep + 1;
|
|
3150
|
+
setMacroStep(nextStep);
|
|
3151
|
+
saveProgress(formData, formState, nextStep);
|
|
3152
|
+
};
|
|
3153
|
+
const editSection = (section) => {
|
|
3154
|
+
if (isReadOnly) return;
|
|
3155
|
+
const newState = { ...formState, [section]: false };
|
|
3156
|
+
setFormState(newState);
|
|
3157
|
+
saveProgress(formData, newState, macroStep);
|
|
3158
|
+
};
|
|
3159
|
+
const approveSection = (section, newFormData = formData) => {
|
|
3160
|
+
if (isReadOnly) return;
|
|
3161
|
+
const newState = { ...formState, [section]: true };
|
|
3162
|
+
setFormState(newState);
|
|
3163
|
+
saveProgress(newFormData, newState, macroStep);
|
|
3164
|
+
};
|
|
3165
|
+
const getBase64Safe = (file) => {
|
|
3166
|
+
return new Promise((resolve, reject) => {
|
|
3167
|
+
if (!["image/jpeg", "image/png", "image/webp", "application/pdf"].includes(file.type)) return reject(new Error("Unsupported file type. Allowed: JPG, PNG, WEBP, PDF."));
|
|
3168
|
+
if (file.size > 5 * 1024 * 1024) return reject(new Error("File too large. Maximum size is 5MB."));
|
|
3169
|
+
const reader = new FileReader();
|
|
3170
|
+
reader.readAsDataURL(file);
|
|
3171
|
+
reader.onloadend = () => resolve(reader.result);
|
|
3172
|
+
reader.onerror = () => reject(new Error("Failed to process file locally."));
|
|
3173
|
+
});
|
|
3174
|
+
};
|
|
3175
|
+
const handleAnalyzeNature = async () => {
|
|
3176
|
+
setIsAnalyzingNature(true);
|
|
3177
|
+
const data = await baseApi("analyze_nature", { description: formData.businessDesc });
|
|
3178
|
+
if (data.success) setSuggestedNature(data.data);
|
|
3179
|
+
else toast6.error(data.error || "Uh oh! Something went wrong.");
|
|
3180
|
+
setIsAnalyzingNature(false);
|
|
3181
|
+
};
|
|
3182
|
+
const pollNameCheckJob = async (jobId) => {
|
|
3183
|
+
const poll = await baseApi("check_name_poll", { jobId });
|
|
3184
|
+
if (poll.success && poll.data.status === "completed") {
|
|
3185
|
+
setNameCheckResult(poll.data.result);
|
|
3186
|
+
setIsCheckingName(false);
|
|
3187
|
+
} else if (poll.success && poll.data.status === "error") {
|
|
3188
|
+
toast6.error(poll.data.error || "Uh oh! Something went wrong.");
|
|
3189
|
+
setIsCheckingName(false);
|
|
3190
|
+
} else setTimeout(() => pollNameCheckJob(jobId), 3e3);
|
|
3191
|
+
};
|
|
3192
|
+
const handleCheckNames = async (nameToCheck) => {
|
|
3193
|
+
setIsCheckingQualifier(true);
|
|
3194
|
+
setNameCheckResult(null);
|
|
3195
|
+
const qualifierData = await baseApi("validate_name_qualifier", { name1: formData.proposedName, name2: formData.proposedName2, description: formData.businessDesc });
|
|
3196
|
+
setIsCheckingQualifier(false);
|
|
3197
|
+
if (qualifierData.success && !qualifierData.data.hasQualifier) {
|
|
3198
|
+
setQualifierCheckResult(qualifierData.data);
|
|
3199
|
+
return;
|
|
3200
|
+
}
|
|
3201
|
+
setQualifierCheckResult(null);
|
|
3202
|
+
setIsCheckingName(true);
|
|
3203
|
+
const data = await baseApi("check_name_start", { name: nameToCheck, lineOfBusiness: formData.natureOfBusiness?.specificLabel });
|
|
3204
|
+
if (data.success && data.data.jobId) pollNameCheckJob(data.data.jobId);
|
|
3205
|
+
else {
|
|
3206
|
+
toast6.error(data.error || "Uh oh! Something went wrong.");
|
|
3207
|
+
setIsCheckingName(false);
|
|
3208
|
+
}
|
|
3209
|
+
};
|
|
3210
|
+
const handleOptionalUpload = async (e, optType) => {
|
|
3211
|
+
if (isReadOnly) return;
|
|
3212
|
+
const file = e.target.files?.[0];
|
|
3213
|
+
if (!file) return;
|
|
3214
|
+
try {
|
|
3215
|
+
if (optType === "other1") setIsUploadingOther1(true);
|
|
3216
|
+
else if (optType === "other2") setIsUploadingOther2(true);
|
|
3217
|
+
else if (optType === "other3") setIsUploadingOther3(true);
|
|
3218
|
+
const base64data = await getBase64Safe(file);
|
|
3219
|
+
const data = await baseApi("upload_document", { imageBase64: base64data, docType: optType });
|
|
3220
|
+
if (data.success) {
|
|
3221
|
+
const updatedForm = { ...formData };
|
|
3222
|
+
const docNum = optType.replace("other", "");
|
|
3223
|
+
updatedForm[`otherDoc${docNum}Url`] = data.data.fileUrl || base64data;
|
|
3224
|
+
updatedForm[`otherDoc${docNum}Meta`] = { fileName: file.name, contentType: file.type, fileSizeInBytes: file.size };
|
|
3225
|
+
setFormData(updatedForm);
|
|
3226
|
+
saveProgress(updatedForm);
|
|
3227
|
+
}
|
|
3228
|
+
} catch (error) {
|
|
3229
|
+
toast6.error(error.message);
|
|
3230
|
+
} finally {
|
|
3231
|
+
if (optType === "other1") {
|
|
3232
|
+
setIsUploadingOther1(false);
|
|
3233
|
+
if (other1Ref.current) other1Ref.current.value = "";
|
|
3234
|
+
} else if (optType === "other2") {
|
|
3235
|
+
setIsUploadingOther2(false);
|
|
3236
|
+
if (other2Ref.current) other2Ref.current.value = "";
|
|
3237
|
+
} else if (optType === "other3") {
|
|
3238
|
+
setIsUploadingOther3(false);
|
|
3239
|
+
if (other3Ref.current) other3Ref.current.value = "";
|
|
3240
|
+
}
|
|
3241
|
+
}
|
|
3242
|
+
};
|
|
3243
|
+
const deleteOptionalDocument = (optType) => {
|
|
3244
|
+
if (isReadOnly || isAnyUploading) return;
|
|
3245
|
+
const updatedForm = { ...formData };
|
|
3246
|
+
const docNum = optType.replace("other", "");
|
|
3247
|
+
const fileUrl = formData[`otherDoc${docNum}Url`];
|
|
3248
|
+
updatedForm[`otherDoc${docNum}Url`] = "";
|
|
3249
|
+
updatedForm[`otherDoc${docNum}Meta`] = null;
|
|
3250
|
+
setFormData(updatedForm);
|
|
3251
|
+
saveProgress(updatedForm);
|
|
3252
|
+
if (fileUrl) baseApi("delete_document", { url: fileUrl }).catch(() => {
|
|
3253
|
+
});
|
|
3254
|
+
};
|
|
3255
|
+
const addCompanyMember = () => {
|
|
3256
|
+
if (isReadOnly) return;
|
|
3257
|
+
setFormData((p) => ({ ...p, members: [...p.members, { id: Date.now().toString(), fullName: "", email: "", phone: "", role: "Shareholder Only", sharePercentage: "", nationality: "Nigerian", address: "", city: "", state: "", idFileUrl: "", idMetadata: null, idExtractedData: null, passportFileUrl: "", passportMetadata: null, signatureFileUrl: "", signatureMetadata: null }] }));
|
|
3258
|
+
};
|
|
3259
|
+
const removeCompanyMember = (index) => {
|
|
3260
|
+
if (isReadOnly) return;
|
|
3261
|
+
const updated = [...formData.members];
|
|
3262
|
+
updated.splice(index, 1);
|
|
3263
|
+
setFormData({ ...formData, members: updated });
|
|
3264
|
+
};
|
|
3265
|
+
const updateCompanyMemberInfo = (index, key, value) => {
|
|
3266
|
+
if (isReadOnly) return;
|
|
3267
|
+
const updated = [...formData.members];
|
|
3268
|
+
if (key === "sharePercentage") {
|
|
3269
|
+
if (value === "") updated[index] = { ...updated[index], [key]: "" };
|
|
3270
|
+
else {
|
|
3271
|
+
let numValue = Number(value);
|
|
3272
|
+
if (!isNaN(numValue)) {
|
|
3273
|
+
const otherSharesSum = updated.reduce((acc, m, i) => {
|
|
3274
|
+
if (i === index || m.role === "Director Only") return acc;
|
|
3275
|
+
return acc + (Number(m.sharePercentage) || 0);
|
|
3276
|
+
}, 0);
|
|
3277
|
+
const maxAllowed = Math.max(0, 100 - otherSharesSum);
|
|
3278
|
+
if (numValue > maxAllowed) {
|
|
3279
|
+
numValue = maxAllowed;
|
|
3280
|
+
toast6.error(`Total shares cannot exceed 100%. Remaining: ${maxAllowed}%`, { id: "share-limit" });
|
|
3281
|
+
} else if (numValue < 0) numValue = 0;
|
|
3282
|
+
updated[index] = { ...updated[index], [key]: numValue.toString() };
|
|
3283
|
+
}
|
|
3284
|
+
}
|
|
3285
|
+
} else updated[index] = { ...updated[index], [key]: value };
|
|
3286
|
+
setFormData({ ...formData, members: updated });
|
|
3287
|
+
};
|
|
3288
|
+
const getCompanyTotalShares = () => formData.members.reduce((acc, m) => acc + (m.role !== "Director Only" ? Number(m.sharePercentage) || 0 : 0), 0);
|
|
3289
|
+
const areCompanyMembersValid = () => {
|
|
3290
|
+
if (getCompanyTotalShares() !== 100) return false;
|
|
3291
|
+
return formData.members.every((m) => m.fullName && m.email && m.phone && m.address && m.city && m.state && m.nationality && (m.role === "Director Only" || m.sharePercentage !== ""));
|
|
3292
|
+
};
|
|
3293
|
+
const areCompanyMemberDocsValid = () => formData.members.every((m) => m.idExtractedData && m.passportFileUrl && m.signatureFileUrl);
|
|
3294
|
+
const handleCompanyMemberUpload = async (e, memberIndex, docType) => {
|
|
3295
|
+
const file = e.target.files?.[0];
|
|
3296
|
+
if (!file) return;
|
|
3297
|
+
try {
|
|
3298
|
+
const base64data = await getBase64Safe(file);
|
|
3299
|
+
if (docType === "id") {
|
|
3300
|
+
setGlobalExtractingId(true);
|
|
3301
|
+
setAiTasks([{ id: "1", label: "Document Scanned", status: "success" }, { id: "2", label: `Extracting ID for Member ${memberIndex + 1}...`, status: "loading" }]);
|
|
3302
|
+
const data = await baseApi("extract_id", { imageBase64: base64data });
|
|
3303
|
+
if (data.success) {
|
|
3304
|
+
const updatedMembers = [...formData.members];
|
|
3305
|
+
updatedMembers[memberIndex] = { ...updatedMembers[memberIndex], idExtractedData: data.data, idFileUrl: data.data.fileUrl || base64data, idMetadata: { fileName: file.name, contentType: file.type, fileSizeInBytes: file.size } };
|
|
3306
|
+
setFormData({ ...formData, members: updatedMembers });
|
|
3307
|
+
saveProgress({ ...formData, members: updatedMembers });
|
|
3308
|
+
} else toast6.error(data.error || "Uh oh! Something went wrong.");
|
|
3309
|
+
} else {
|
|
3310
|
+
if (docType === "passport") setGlobalUploadingPassport(true);
|
|
3311
|
+
else setGlobalUploadingSignature(true);
|
|
3312
|
+
const data = await baseApi("upload_document", { imageBase64: base64data, docType: `member_${memberIndex}_${docType}` });
|
|
3313
|
+
if (data.success) {
|
|
3314
|
+
const updatedMembers = [...formData.members];
|
|
3315
|
+
if (docType === "passport") {
|
|
3316
|
+
updatedMembers[memberIndex].passportFileUrl = data.data.fileUrl || base64data;
|
|
3317
|
+
updatedMembers[memberIndex].passportMetadata = { fileName: file.name, contentType: file.type, fileSizeInBytes: file.size };
|
|
3318
|
+
} else {
|
|
3319
|
+
updatedMembers[memberIndex].signatureFileUrl = data.data.fileUrl || base64data;
|
|
3320
|
+
updatedMembers[memberIndex].signatureMetadata = { fileName: file.name, contentType: file.type, fileSizeInBytes: file.size };
|
|
3321
|
+
}
|
|
3322
|
+
setFormData({ ...formData, members: updatedMembers });
|
|
3323
|
+
saveProgress({ ...formData, members: updatedMembers });
|
|
3324
|
+
} else toast6.error(`Failed to upload ${docType}.`);
|
|
3325
|
+
}
|
|
3326
|
+
} catch (error) {
|
|
3327
|
+
toast6.error(error.message);
|
|
3328
|
+
} finally {
|
|
3329
|
+
if (docType === "id") setGlobalExtractingId(false);
|
|
3330
|
+
else if (docType === "passport") setGlobalUploadingPassport(false);
|
|
3331
|
+
else setGlobalUploadingSignature(false);
|
|
3332
|
+
e.target.value = "";
|
|
3333
|
+
}
|
|
3334
|
+
};
|
|
3335
|
+
const deleteCompanyMemberDocument = (memberIndex, docType) => {
|
|
3336
|
+
if (isReadOnly || isAnyUploading) return;
|
|
3337
|
+
const updatedMembers = [...formData.members];
|
|
3338
|
+
let fileUrl = "";
|
|
3339
|
+
if (docType === "id") {
|
|
3340
|
+
fileUrl = updatedMembers[memberIndex].idFileUrl;
|
|
3341
|
+
updatedMembers[memberIndex].idFileUrl = "";
|
|
3342
|
+
updatedMembers[memberIndex].idExtractedData = null;
|
|
3343
|
+
updatedMembers[memberIndex].idMetadata = null;
|
|
3344
|
+
} else if (docType === "passport") {
|
|
3345
|
+
fileUrl = updatedMembers[memberIndex].passportFileUrl;
|
|
3346
|
+
updatedMembers[memberIndex].passportFileUrl = "";
|
|
3347
|
+
updatedMembers[memberIndex].passportMetadata = null;
|
|
3348
|
+
} else if (docType === "signature") {
|
|
3349
|
+
fileUrl = updatedMembers[memberIndex].signatureFileUrl;
|
|
3350
|
+
updatedMembers[memberIndex].signatureFileUrl = "";
|
|
3351
|
+
updatedMembers[memberIndex].signatureMetadata = null;
|
|
3352
|
+
}
|
|
3353
|
+
setFormData({ ...formData, members: updatedMembers });
|
|
3354
|
+
saveProgress({ ...formData, members: updatedMembers });
|
|
3355
|
+
if (fileUrl) baseApi("delete_document", { docType, url: fileUrl }).catch(() => {
|
|
3356
|
+
});
|
|
3357
|
+
};
|
|
3358
|
+
const handleBusinessUpload = async (e, docType) => {
|
|
3359
|
+
const file = e.target.files?.[0];
|
|
3360
|
+
if (!file) return;
|
|
3361
|
+
try {
|
|
3362
|
+
const base64data = await getBase64Safe(file);
|
|
3363
|
+
if (docType === "id") {
|
|
3364
|
+
setGlobalExtractingId(true);
|
|
3365
|
+
setAiTasks([{ id: "1", label: "Document Scanned", status: "success" }, { id: "2", label: "Extracting Identity Data...", status: "loading" }]);
|
|
3366
|
+
const data = await baseApi("extract_id", { imageBase64: base64data });
|
|
3367
|
+
if (data.success) {
|
|
3368
|
+
setAiTasks([{ id: "1", label: "Document Scanned", status: "success" }, { id: "2", label: "Identity Data Extracted", status: "success" }]);
|
|
3369
|
+
const updatedForm = { ...formData, idExtractedData: data.data, idFileUrl: data.data.fileUrl || base64data, idMetadata: { fileName: file.name, contentType: file.type, fileSizeInBytes: file.size } };
|
|
3370
|
+
setFormData(updatedForm);
|
|
3371
|
+
saveProgress(updatedForm);
|
|
3372
|
+
} else {
|
|
3373
|
+
toast6.error(data.error || "Uh oh! Something went wrong.");
|
|
3374
|
+
setAiTasks([{ id: "1", label: "Document Scanned", status: "success" }, { id: "2", label: "Extraction Failed", status: "error" }]);
|
|
3375
|
+
}
|
|
3376
|
+
} else {
|
|
3377
|
+
if (docType === "passport") setGlobalUploadingPassport(true);
|
|
3378
|
+
else setGlobalUploadingSignature(true);
|
|
3379
|
+
const data = await baseApi("upload_document", { imageBase64: base64data, docType });
|
|
3380
|
+
if (data.success) {
|
|
3381
|
+
const updatedForm = { ...formData };
|
|
3382
|
+
if (docType === "passport") {
|
|
3383
|
+
updatedForm.passportFileUrl = data.data.fileUrl || base64data;
|
|
3384
|
+
updatedForm.passportMetadata = { fileName: file.name, contentType: file.type, fileSizeInBytes: file.size };
|
|
3385
|
+
approveSection("passportApproved", updatedForm);
|
|
3386
|
+
} else {
|
|
3387
|
+
updatedForm.signatureFileUrl = data.data.fileUrl || base64data;
|
|
3388
|
+
updatedForm.signatureMetadata = { fileName: file.name, contentType: file.type, fileSizeInBytes: file.size };
|
|
3389
|
+
approveSection("signatureApproved", updatedForm);
|
|
3390
|
+
}
|
|
3391
|
+
setFormData(updatedForm);
|
|
3392
|
+
} else toast6.error(data.error || `Failed to upload ${docType}.`);
|
|
3393
|
+
}
|
|
3394
|
+
} catch (error) {
|
|
3395
|
+
toast6.error(error.message);
|
|
3396
|
+
} finally {
|
|
3397
|
+
if (docType === "id") {
|
|
3398
|
+
setGlobalExtractingId(false);
|
|
3399
|
+
if (idRef.current) idRef.current.value = "";
|
|
3400
|
+
} else if (docType === "passport") {
|
|
3401
|
+
setGlobalUploadingPassport(false);
|
|
3402
|
+
if (passportRef.current) passportRef.current.value = "";
|
|
3403
|
+
} else {
|
|
3404
|
+
setGlobalUploadingSignature(false);
|
|
3405
|
+
if (signatureRef.current) signatureRef.current.value = "";
|
|
3406
|
+
}
|
|
3407
|
+
}
|
|
3408
|
+
};
|
|
3409
|
+
const deleteBusinessDocument = (docType) => {
|
|
3410
|
+
if (isReadOnly || isAnyUploading) return;
|
|
3411
|
+
const updatedForm = { ...formData };
|
|
3412
|
+
let fileUrl = "";
|
|
3413
|
+
if (docType === "id") {
|
|
3414
|
+
fileUrl = formData.idFileUrl;
|
|
3415
|
+
updatedForm.idFileUrl = "";
|
|
3416
|
+
updatedForm.idExtractedData = null;
|
|
3417
|
+
updatedForm.idMetadata = null;
|
|
3418
|
+
editSection("idApproved");
|
|
3419
|
+
} else if (docType === "passport") {
|
|
3420
|
+
fileUrl = formData.passportFileUrl;
|
|
3421
|
+
updatedForm.passportFileUrl = "";
|
|
3422
|
+
updatedForm.passportMetadata = null;
|
|
3423
|
+
editSection("passportApproved");
|
|
3424
|
+
} else if (docType === "signature") {
|
|
3425
|
+
fileUrl = formData.signatureFileUrl;
|
|
3426
|
+
updatedForm.signatureFileUrl = "";
|
|
3427
|
+
updatedForm.signatureMetadata = null;
|
|
3428
|
+
editSection("signatureApproved");
|
|
3429
|
+
}
|
|
3430
|
+
setFormData(updatedForm);
|
|
3431
|
+
if (fileUrl) baseApi("delete_document", { docType, url: fileUrl }).catch(() => {
|
|
3432
|
+
});
|
|
3433
|
+
};
|
|
3434
|
+
const handleFinalSubmit = async () => {
|
|
3435
|
+
if (!iAgree || isReadOnly) return;
|
|
3436
|
+
setIsSubmitting(true);
|
|
3437
|
+
let finalJsonPayload = {
|
|
3438
|
+
iAgree: true,
|
|
3439
|
+
proposedNames: [formData.approvedName, formData.proposedName2],
|
|
3440
|
+
natureOfBusiness: formData.natureOfBusiness,
|
|
3441
|
+
additionalDocuments: [
|
|
3442
|
+
formData.otherDoc1Url ? { fileDataUrl: formData.otherDoc1Url, ...formData.otherDoc1Meta } : null,
|
|
3443
|
+
formData.otherDoc2Url ? { fileDataUrl: formData.otherDoc2Url, ...formData.otherDoc2Meta } : null,
|
|
3444
|
+
formData.otherDoc3Url ? { fileDataUrl: formData.otherDoc3Url, ...formData.otherDoc3Meta } : null
|
|
3445
|
+
].filter(Boolean)
|
|
3446
|
+
};
|
|
3447
|
+
if (type === "company") {
|
|
3448
|
+
finalJsonPayload.companyAddress = { streetAddress: formData.address, city: formData.city, state: formData.state, postalCode: "000000" };
|
|
3449
|
+
finalJsonPayload.directorsAndShareholders = formData.members.map((m) => ({
|
|
3450
|
+
role: m.role,
|
|
3451
|
+
sharePercentage: m.role !== "Director Only" ? m.sharePercentage : "0",
|
|
3452
|
+
fullName: m.idExtractedData?.fullName || m.fullName,
|
|
3453
|
+
dateOfBirth: m.idExtractedData?.dob || "",
|
|
3454
|
+
phoneNumber: m.phone,
|
|
3455
|
+
emailAddress: m.email,
|
|
3456
|
+
residentialAddress: { streetAddress: m.address, city: m.city, state: m.state, country: m.nationality === "Nigerian" ? "Nigeria" : "Foreign" },
|
|
3457
|
+
nationality: m.nationality,
|
|
3458
|
+
identification: { type: m.idExtractedData?.documentType || "ID", idNumber: m.idExtractedData?.idNumber || "UNKNOWN" },
|
|
3459
|
+
passportPhotograph: m.passportFileUrl ? { ...m.passportMetadata, fileDataUrl: m.passportFileUrl } : void 0,
|
|
3460
|
+
signature: m.signatureFileUrl ? { ...m.signatureMetadata, fileDataUrl: m.signatureFileUrl } : void 0
|
|
3461
|
+
}));
|
|
3462
|
+
} else {
|
|
3463
|
+
finalJsonPayload.businessAddress = { streetAddress: formData.address, city: formData.city, state: formData.state, postalCode: "000000" };
|
|
3464
|
+
finalJsonPayload.proprietors = [{
|
|
3465
|
+
fullName: formData.idExtractedData?.fullName || formData.ownerName,
|
|
3466
|
+
dateOfBirth: formData.idExtractedData?.dob || "",
|
|
3467
|
+
phoneNumber: formData.ownerPhone,
|
|
3468
|
+
emailAddress: formData.ownerEmail,
|
|
3469
|
+
residentialAddress: { streetAddress: formData.address, city: formData.city, state: formData.state, country: "Nigeria" },
|
|
3470
|
+
nationality: "Nigerian",
|
|
3471
|
+
identification: { type: formData.idExtractedData?.documentType || "ID", idNumber: formData.idExtractedData?.idNumber || "UNKNOWN" },
|
|
3472
|
+
passportPhotograph: formData.passportFileUrl ? { ...formData.passportMetadata, fileDataUrl: formData.passportFileUrl } : void 0,
|
|
3473
|
+
signature: formData.signatureFileUrl ? { ...formData.signatureMetadata, fileDataUrl: formData.signatureFileUrl } : void 0
|
|
3474
|
+
}];
|
|
3475
|
+
}
|
|
3476
|
+
const data = await baseApi("submit", finalJsonPayload);
|
|
3477
|
+
if (data.success) {
|
|
3478
|
+
toast6.success("Application Submitted!");
|
|
3479
|
+
onRedirectToApplication(applicationId);
|
|
3480
|
+
} else {
|
|
3481
|
+
toast6.error(data.error || "Uh oh! Something went wrong.");
|
|
3482
|
+
setIsSubmitting(false);
|
|
3483
|
+
}
|
|
3484
|
+
};
|
|
3485
|
+
const isStep0Valid = type === "company" ? formState.natureApproved && formState.nameApproved && formState.addressApproved && formState.membersDetailsApproved : formState.natureApproved && formState.nameApproved && formState.addressApproved && formState.ownerApproved;
|
|
3486
|
+
const isStep1Valid = type === "company" ? formState.membersDocsApproved : formState.idApproved && formState.passportApproved && formState.signatureApproved;
|
|
3487
|
+
const titleText = type === "company" ? "Company Incorporation (LLC)" : "Business Name Registration";
|
|
3488
|
+
if (isBooting) return /* @__PURE__ */ React41.createElement("div", { className: "flex justify-center py-20" }, /* @__PURE__ */ React41.createElement(HugeiconsIcon25, { icon: Loading03Icon12, size: 32, className: "animate-spin text-black" }));
|
|
3489
|
+
if (!["DRAFT", "QUEUED", "REJECTED"].includes(appStatus) && appStatus !== "") {
|
|
3490
|
+
return /* @__PURE__ */ React41.createElement("div", { className: "w-full max-w-3xl mx-auto bg-white rounded-4xl p-6 sm:p-10 flex flex-col items-center justify-center text-center gap-5 animate-in fade-in slide-in-from-bottom-2 duration-500 mb-20 py-24" }, appStatus === "COMPLETED" ? /* @__PURE__ */ React41.createElement(React41.Fragment, null, /* @__PURE__ */ React41.createElement("div", { className: "w-20 h-20 bg-neutral-50 text-neutral-500 rounded-full flex items-center justify-center mb-2" }, /* @__PURE__ */ React41.createElement(HugeiconsIcon25, { icon: CheckmarkBadge01Icon, size: 40 })), /* @__PURE__ */ React41.createElement("h2", { className: "text-xl font-serif text-black" }, "Registration Completed"), /* @__PURE__ */ React41.createElement("p", { className: "text-sm text-neutral-500 max-w-md" }, "Your application has been successfully verified and registered.")) : appStatus === "PENDING" ? /* @__PURE__ */ React41.createElement(React41.Fragment, null, /* @__PURE__ */ React41.createElement("div", { className: "w-20 h-20 bg-neutral-50 text-neutral-500 rounded-full flex items-center justify-center mb-2" }, /* @__PURE__ */ React41.createElement(HugeiconsIcon25, { icon: TimeQuarterPassIcon, size: 40, className: "animate-spin" })), /* @__PURE__ */ React41.createElement("h2", { className: "text-xl font-serif text-black" }, "Application is Pending"), /* @__PURE__ */ React41.createElement("p", { className: "text-sm text-neutral-500 max-w-md" }, "Your application is currently pending review.")) : appStatus === "AWAITING_PAYMENT" ? /* @__PURE__ */ React41.createElement(React41.Fragment, null, /* @__PURE__ */ React41.createElement("div", { className: "w-20 h-20 bg-amber-50 text-amber-500 rounded-full flex items-center justify-center mb-2" }, /* @__PURE__ */ React41.createElement(HugeiconsIcon25, { icon: TimeQuarterPassIcon, size: 40, className: "animate-pulse" })), /* @__PURE__ */ React41.createElement("h2", { className: "text-xl text-black" }, "Awaiting Payment"), /* @__PURE__ */ React41.createElement("p", { className: "text-sm text-neutral-500 max-w-md" }, "Your application is complete and awaiting government fee settlement. Please go to the Billing tab to authorize payment."), /* @__PURE__ */ React41.createElement("div", { className: "mt-6 flex flex-col items-center gap-3" }, /* @__PURE__ */ React41.createElement("button", { onClick: onRedirectToBilling, className: "px-8 py-3 bg-black text-white text-[11px] tracking-widest rounded-full hover:bg-neutral-800 outline-none" }, "Go to Billing & Invoices"), /* @__PURE__ */ React41.createElement("button", { onClick: () => setIsAbortModalOpen(true), className: "px-8 py-3 border border-neutral-200 text-neutral-600 text-[11px] tracking-widest rounded-full hover:bg-neutral-50 outline-none" }, "Abort & Edit Application"))) : /* @__PURE__ */ React41.createElement(React41.Fragment, null, /* @__PURE__ */ React41.createElement("div", { className: "w-20 h-20 bg-neutral-50 text-neutral-500 rounded-full flex items-center justify-center mb-2" }, /* @__PURE__ */ React41.createElement(HugeiconsIcon25, { icon: TimeQuarterPassIcon, size: 40 })), /* @__PURE__ */ React41.createElement("h2", { className: "text-xl font-serif text-black" }, "Application Submitted"), /* @__PURE__ */ React41.createElement("p", { className: "text-sm text-neutral-500 max-w-md" }, "Your application is currently ", appStatus.replace(/_/g, " ").toLowerCase(), "."), ["AWAITING_PAYMENT", "READY_FOR_SUBMISSION", "AWAITING_CONFIRMATION"].includes(appStatus) && /* @__PURE__ */ React41.createElement("div", { className: "mt-6 flex flex-col items-center gap-3" }, /* @__PURE__ */ React41.createElement("button", { onClick: () => setIsAbortModalOpen(true), className: "px-8 py-3 border border-neutral-200 text-neutral-600 text-[11px] tracking-widest rounded-full hover:bg-neutral-50 outline-none" }, "Abort Application"))), isAbortModalOpen && /* @__PURE__ */ React41.createElement("div", { className: "fixed inset-0 z-110 flex items-center justify-center p-4" }, /* @__PURE__ */ React41.createElement("div", { className: "absolute inset-0 bg-black/30", onClick: () => !isAborting && setIsAbortModalOpen(false) }), /* @__PURE__ */ React41.createElement("div", { className: "relative w-100 bg-white shadow-2xl rounded-3xl flex flex-col overflow-hidden animate-in zoom-in-95 duration-200 text-left" }, /* @__PURE__ */ React41.createElement("div", { className: "p-6 flex flex-col gap-4 text-center" }, /* @__PURE__ */ React41.createElement("h3", { className: "text-[17px] font-serif text-black tracking-tight" }, "Abort Application?"), /* @__PURE__ */ React41.createElement("p", { className: "text-[12px] text-neutral-500 leading-relaxed" }, "Are you sure you want to abort? If you have already made a payment, returning to draft may cause issues. Your invoice will be deleted.")), /* @__PURE__ */ React41.createElement("div", { className: "w-full flex " }, /* @__PURE__ */ React41.createElement("button", { onClick: () => setIsAbortModalOpen(false), disabled: isAborting, className: "flex-1 py-4 text-[13px] text-neutral-500 hover:bg-neutral-50 transition-colors outline-none disabled:opacity-50" }, "Cancel"), /* @__PURE__ */ React41.createElement("button", { onClick: handleAbort, disabled: isAborting, className: "flex-1 py-4 text-[13px] text-red-500 hover:bg-neutral-50 transition-colors outline-none disabled:opacity-50" }, isAborting ? "Aborting..." : "Yes, Abort")))));
|
|
3491
|
+
}
|
|
3492
|
+
return /* @__PURE__ */ React41.createElement("div", { className: "w-full max-w-3xl mx-auto bg-white rounded-4xl p-6 sm:p-10 flex flex-col gap-10 animate-in fade-in slide-in-from-bottom-2 duration-500 mb-20" }, /* @__PURE__ */ React41.createElement("div", { className: "flex flex-col gap-8" }, /* @__PURE__ */ React41.createElement("div", null, /* @__PURE__ */ React41.createElement("h2", { className: "text-xl font-serif text-black tracking-tight mb-1" }, titleText), /* @__PURE__ */ React41.createElement("p", { className: "text-sm text-neutral-500" }, "Answer the questions below to build your official application.")), /* @__PURE__ */ React41.createElement("div", { className: "px-2" }, /* @__PURE__ */ React41.createElement(Stagger, { steps: MACRO_STEPS, currentStep: macroStep }))), /* @__PURE__ */ React41.createElement("div", { className: "flex flex-col gap-8" }, macroStep === 0 && /* @__PURE__ */ React41.createElement("div", { className: "flex flex-col gap-8 animate-in fade-in" }, /* @__PURE__ */ React41.createElement("div", { className: "flex flex-col gap-4" }, /* @__PURE__ */ React41.createElement("div", { className: "flex items-center gap-2 text-black" }, /* @__PURE__ */ React41.createElement(HugeiconsIcon25, { icon: Briefcase02Icon2, size: 18 }), /* @__PURE__ */ React41.createElement("h3", { className: "text-sm " }, "What does your ", type === "company" ? "company" : "business", " do?")), !formState.natureApproved ? /* @__PURE__ */ React41.createElement(React41.Fragment, null, /* @__PURE__ */ React41.createElement("div", { className: "flex flex-col gap-3 " }, /* @__PURE__ */ React41.createElement(TextInput, { label: type === "company" ? "Company Description" : "Business Description", placeholder: "e.g. We provide professional services to clients.", value: formData.businessDesc, onChange: (v) => setFormData({ ...formData, businessDesc: v }), disabled: isReadOnly || isSubmitting }), /* @__PURE__ */ React41.createElement(ThreeDActionButton, { onClick: handleAnalyzeNature, disabled: formData.businessDesc.length < 5 || isAnalyzingNature || isReadOnly, isLoading: isAnalyzingNature, className: "w-fit" }, "Analyze Nature")), isAnalyzingNature && /* @__PURE__ */ React41.createElement("div", { className: " mt-2" }, /* @__PURE__ */ React41.createElement(AiStageCheck, { tasks: [{ id: "1", label: "Matching with Official Categories...", status: "loading" }] })), suggestedNature && /* @__PURE__ */ React41.createElement("div", { className: " mt-2 animate-in fade-in" }, /* @__PURE__ */ React41.createElement(AiApproveDecline, { suggestionTitle: "Classification Found", suggestionValue: /* @__PURE__ */ React41.createElement("div", null, /* @__PURE__ */ React41.createElement("p", { className: " text-black" }, suggestedNature.specificLabel), /* @__PURE__ */ React41.createElement("p", { className: "text-xs text-neutral-500 mt-1" }, "Category: ", suggestedNature.categoryLabel)), onApprove: () => {
|
|
3493
|
+
const newForm = { ...formData, natureOfBusiness: suggestedNature };
|
|
3494
|
+
setFormData(newForm);
|
|
3495
|
+
approveSection("natureApproved", newForm);
|
|
3496
|
+
}, onDecline: () => setSuggestedNature(null) }))) : /* @__PURE__ */ React41.createElement("div", { className: " flex items-center justify-between border border-neutral-100 p-4 rounded-xl" }, /* @__PURE__ */ React41.createElement("div", { className: "pr-4" }, /* @__PURE__ */ React41.createElement("p", { className: "text-sm text-black" }, formData.natureOfBusiness?.specificLabel), /* @__PURE__ */ React41.createElement("p", { className: "text-xs text-neutral-500 mt-1" }, formData.businessDesc)), !isReadOnly && /* @__PURE__ */ React41.createElement("button", { onClick: () => editSection("natureApproved"), className: "p-2 text-neutral-400 hover:text-black transition-colors outline-none shrink-0" }, /* @__PURE__ */ React41.createElement(HugeiconsIcon25, { icon: PencilEdit01Icon2, size: 16 })))), formState.natureApproved && /* @__PURE__ */ React41.createElement("div", { className: "flex flex-col gap-4 pt-6 animate-in slide-in-from-top-4 duration-500" }, /* @__PURE__ */ React41.createElement("div", { className: "flex items-center gap-2 text-black" }, /* @__PURE__ */ React41.createElement(HugeiconsIcon25, { icon: CheckmarkBadge01Icon, size: 18 }), /* @__PURE__ */ React41.createElement("h3", { className: "text-sm " }, "What name would you like to register?")), /* @__PURE__ */ React41.createElement("p", { className: "text-xs text-neutral-500 -mt-2" }, "Provide two options. We will verify availability against the official registry."), !formState.nameApproved ? /* @__PURE__ */ React41.createElement(React41.Fragment, null, /* @__PURE__ */ React41.createElement("div", { className: "flex flex-col gap-4" }, /* @__PURE__ */ React41.createElement(TextInput, { label: "Proposed Name 1 (Preferred)", value: formData.proposedName, onChange: (v) => setFormData({ ...formData, proposedName: v }), disabled: isReadOnly || isSubmitting }), /* @__PURE__ */ React41.createElement(TextInput, { label: "Proposed Name 2 (Alternative)", value: formData.proposedName2, onChange: (v) => setFormData({ ...formData, proposedName2: v }), disabled: isReadOnly || isSubmitting }), /* @__PURE__ */ React41.createElement(ThreeDActionButton, { onClick: () => handleCheckNames(formData.proposedName), disabled: !formData.proposedName || !formData.proposedName2 || isCheckingName || isCheckingQualifier || isReadOnly, isLoading: isCheckingQualifier || isCheckingName, className: "w-fit" }, "Check Availability")), (isCheckingQualifier || isCheckingName) && /* @__PURE__ */ React41.createElement("div", { className: " mt-2" }, /* @__PURE__ */ React41.createElement(AiStageCheck, { tasks: [{ id: "1", label: "AI Qualifier Pre-check...", status: isCheckingQualifier ? "loading" : "success" }, { id: "2", label: "Checking Official Registry Database...", status: isCheckingName ? "loading" : "pending" }, { id: "3", label: "Fallback Checking Public Database...", status: isCheckingName ? "loading" : "pending" }, { id: "4", label: "Validation Status...", status: isCheckingName ? "loading" : "pending" }] })), qualifierCheckResult && /* @__PURE__ */ React41.createElement("div", { className: "mt-2 animate-in fade-in" }, /* @__PURE__ */ React41.createElement("div", { className: "border border-purple-100 bg-linear-to-bl from-purple-50/80 via-white to-white p-5 rounded-2xl flex flex-col gap-4 relative overflow-hidden" }, /* @__PURE__ */ React41.createElement("div", null, /* @__PURE__ */ React41.createElement("span", { className: "text-[10px] tracking-widest text-purple-600 block mb-1" }, "AI Suggestion: Structural Qualifier Missing"), /* @__PURE__ */ React41.createElement("p", { className: "text-sm text-black mb-3" }, "Nigerian registrations require a structural qualifier to be approved."), /* @__PURE__ */ React41.createElement("div", { className: "flex flex-col gap-2" }, (qualifierCheckResult.suggestions || []).map((alt, i) => /* @__PURE__ */ React41.createElement("button", { key: i, onClick: () => setFormData({ ...formData, proposedName: alt }), className: "text-left px-4 py-2 border border-neutral-200 rounded-full hover:border-black text-sm transition-colors outline-none" }, alt)))), /* @__PURE__ */ React41.createElement("button", { onClick: () => setQualifierCheckResult(null), className: "w-fit text-[11px] tracking-widest text-neutral-500 hover:text-black transition-colors mt-2 outline-none" }, "Edit Name Manually"))), nameCheckResult && /* @__PURE__ */ React41.createElement("div", { className: " mt-2 animate-in fade-in" }, nameCheckResult.status === "APPROVED" || nameCheckResult.status === "APPROVED_WARNING" || nameCheckResult.status === "SKIPPED" ? /* @__PURE__ */ React41.createElement(AiApproveDecline, { suggestionTitle: nameCheckResult.status === "APPROVED" ? "Name Available!" : "Fallback Approval", suggestionValue: /* @__PURE__ */ React41.createElement("div", null, /* @__PURE__ */ React41.createElement("p", { className: `mb-1 ${nameCheckResult.status === "APPROVED" ? "text-emerald-600 " : "text-orange-500 "}` }, nameCheckResult.status === "APPROVED" ? "Excellent chance of approval." : "Validation Bypassed / Fallback."), /* @__PURE__ */ React41.createElement("p", { className: "text-xs text-neutral-600" }, nameCheckResult.message), /* @__PURE__ */ React41.createElement("p", { className: "text-xs text-neutral-600 mt-2 " }, "Proposed Option: ", nameCheckResult.approvedOption)), onApprove: () => {
|
|
3497
|
+
const newForm = { ...formData, approvedName: nameCheckResult.approvedOption };
|
|
3498
|
+
setFormData(newForm);
|
|
3499
|
+
approveSection("nameApproved", newForm);
|
|
3500
|
+
}, onDecline: () => setNameCheckResult(null) }) : /* @__PURE__ */ React41.createElement("div", { className: "border border-red-100 bg-linear-to-bl from-red-50/80 via-white to-white p-5 rounded-2xl flex flex-col gap-4 relative overflow-hidden" }, /* @__PURE__ */ React41.createElement("div", null, /* @__PURE__ */ React41.createElement("span", { className: "text-[10px] tracking-widest text-red-600 block mb-1" }, "Registry Conflict Detected"), /* @__PURE__ */ React41.createElement("p", { className: "text-sm text-black mb-3" }, nameCheckResult.message), /* @__PURE__ */ React41.createElement("div", { className: "flex flex-col gap-2" }, (nameCheckResult.alternatives || []).map((alt, i) => /* @__PURE__ */ React41.createElement("button", { key: i, onClick: () => setFormData({ ...formData, proposedName: alt }), className: "text-left px-4 py-2 border border-neutral-200 rounded-full hover:border-black text-sm transition-colors outline-none" }, alt)))), /* @__PURE__ */ React41.createElement("button", { onClick: () => setNameCheckResult(null), className: "w-fit text-[11px] tracking-widest text-neutral-500 hover:text-black transition-colors mt-2 outline-none" }, "Try New Name")))) : /* @__PURE__ */ React41.createElement("div", { className: " flex items-center justify-between border border-neutral-100 p-4 rounded-xl" }, /* @__PURE__ */ React41.createElement("div", null, /* @__PURE__ */ React41.createElement("p", { className: "text-sm text-black" }, formData.approvedName), /* @__PURE__ */ React41.createElement("p", { className: "text-xs text-emerald-600 mt-1" }, "Verified against registry")), !isReadOnly && /* @__PURE__ */ React41.createElement("button", { onClick: () => editSection("nameApproved"), className: "p-2 text-neutral-400 hover:text-black transition-colors outline-none shrink-0" }, /* @__PURE__ */ React41.createElement(HugeiconsIcon25, { icon: PencilEdit01Icon2, size: 16 })))), formState.nameApproved && /* @__PURE__ */ React41.createElement("div", { className: "flex flex-col gap-4 pt-6 animate-in slide-in-from-top-4 duration-500" }, /* @__PURE__ */ React41.createElement("div", { className: "flex items-center gap-2 text-black" }, /* @__PURE__ */ React41.createElement(HugeiconsIcon25, { icon: Location01Icon, size: 18 }), /* @__PURE__ */ React41.createElement("h3", { className: "text-sm " }, "Where is your head office located?")), !formState.addressApproved ? /* @__PURE__ */ React41.createElement("div", { className: "flex flex-col gap-4 " }, /* @__PURE__ */ React41.createElement(TextInput, { label: "Street Address", value: formData.address, onChange: (v) => setFormData({ ...formData, address: v }), disabled: isReadOnly || isSubmitting }), /* @__PURE__ */ React41.createElement("div", { className: "grid grid-cols-2 gap-4" }, /* @__PURE__ */ React41.createElement(TextInput, { label: "City", value: formData.city, onChange: (v) => setFormData({ ...formData, city: v }), disabled: isReadOnly || isSubmitting }), /* @__PURE__ */ React41.createElement(TextInput, { label: "State", value: formData.state, readOnly: true, onClick: () => !isReadOnly && setActiveModal({ isOpen: true, type: "state", memberIndex: null, isGlobalState: true }), placeholder: "Select State", onChange: () => {
|
|
3501
|
+
}, disabled: isReadOnly || isSubmitting })), /* @__PURE__ */ React41.createElement(ThreeDActionButton, { onClick: () => approveSection("addressApproved"), disabled: !formData.address || !formData.city || !formData.state || isReadOnly, className: "w-fit mt-2" }, "Confirm Address")) : /* @__PURE__ */ React41.createElement("div", { className: " flex items-center justify-between border border-neutral-100 p-4 rounded-xl" }, /* @__PURE__ */ React41.createElement("p", { className: "text-sm text-neutral-500" }, formData.address, ", ", formData.city, ", ", formData.state), !isReadOnly && /* @__PURE__ */ React41.createElement("button", { onClick: () => editSection("addressApproved"), className: "p-2 text-neutral-400 hover:text-black transition-colors outline-none shrink-0" }, /* @__PURE__ */ React41.createElement(HugeiconsIcon25, { icon: PencilEdit01Icon2, size: 16 })))), formState.addressApproved && type === "company" && /* @__PURE__ */ React41.createElement("div", { className: "flex flex-col gap-4 pt-6 animate-in slide-in-from-top-4 duration-500" }, /* @__PURE__ */ React41.createElement("div", { className: "flex items-center justify-between gap-2 text-black border-b border-neutral-100 pb-3" }, /* @__PURE__ */ React41.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React41.createElement(HugeiconsIcon25, { icon: UserIcon, size: 18 }), /* @__PURE__ */ React41.createElement("h3", { className: "text-sm " }, "Directors & Shareholders")), !formState.membersDetailsApproved && /* @__PURE__ */ React41.createElement("div", { className: `text-xs px-3 py-1 rounded-full ${getCompanyTotalShares() === 100 ? "bg-emerald-50 text-emerald-600" : "bg-red-50 text-red-500"}` }, "Total Shares: ", getCompanyTotalShares(), "%")), /* @__PURE__ */ React41.createElement("p", { className: "text-xs text-neutral-500 -mt-2" }, "Provide details for all individuals. Ensure total share percentage equals 100%."), !formState.membersDetailsApproved ? /* @__PURE__ */ React41.createElement("div", { className: "flex flex-col gap-6 " }, formData.members.map((member, i) => /* @__PURE__ */ React41.createElement("div", { key: member.id, className: "flex flex-col gap-4 border border-neutral-100 p-5 rounded-2xl bg-neutral-50/30" }, /* @__PURE__ */ React41.createElement("div", { className: "flex justify-between items-center mb-1" }, /* @__PURE__ */ React41.createElement("span", { className: "text-[10px] tracking-widest text-neutral-400" }, "Member ", i + 1), formData.members.length > 1 && !isReadOnly && /* @__PURE__ */ React41.createElement("button", { onClick: () => removeCompanyMember(i), className: "text-red-500 text-xs hover:text-red-600" }, "Remove")), /* @__PURE__ */ React41.createElement("div", { className: "grid grid-cols-2 gap-4" }, /* @__PURE__ */ React41.createElement(TextInput, { label: "Role", value: member.role, readOnly: true, onClick: () => !isReadOnly && setActiveModal({ isOpen: true, type: "role", memberIndex: i }), onChange: () => {
|
|
3502
|
+
}, disabled: isReadOnly || isSubmitting }), member.role !== "Director Only" && /* @__PURE__ */ React41.createElement(NumberInput, { label: "Share Percentage (%)", value: member.sharePercentage, onChange: (v) => updateCompanyMemberInfo(i, "sharePercentage", v), disabled: isReadOnly || isSubmitting })), /* @__PURE__ */ React41.createElement(TextInput, { label: "Full Name", value: member.fullName, onChange: (v) => updateCompanyMemberInfo(i, "fullName", v), disabled: isReadOnly || isSubmitting }), /* @__PURE__ */ React41.createElement("div", { className: "grid grid-cols-2 gap-4" }, /* @__PURE__ */ React41.createElement(NumberInput, { label: "Phone Number", value: member.phone, onChange: (v) => updateCompanyMemberInfo(i, "phone", v), disabled: isReadOnly || isSubmitting }), /* @__PURE__ */ React41.createElement(TextInput, { label: "Email Address", value: member.email, onChange: (v) => updateCompanyMemberInfo(i, "email", v), disabled: isReadOnly || isSubmitting })), /* @__PURE__ */ React41.createElement(TextInput, { label: "Nationality", value: member.nationality, readOnly: true, onClick: () => !isReadOnly && setActiveModal({ isOpen: true, type: "nationality", memberIndex: i }), onChange: () => {
|
|
3503
|
+
}, disabled: isReadOnly || isSubmitting }), /* @__PURE__ */ React41.createElement(TextInput, { label: "Residential Address", value: member.address, onChange: (v) => updateCompanyMemberInfo(i, "address", v), disabled: isReadOnly || isSubmitting }), /* @__PURE__ */ React41.createElement("div", { className: "grid grid-cols-2 gap-4" }, /* @__PURE__ */ React41.createElement(TextInput, { label: "City", value: member.city, onChange: (v) => updateCompanyMemberInfo(i, "city", v), disabled: isReadOnly || isSubmitting }), /* @__PURE__ */ React41.createElement(TextInput, { label: "State", value: member.state, readOnly: true, onClick: () => !isReadOnly && setActiveModal({ isOpen: true, type: "state", memberIndex: i }), onChange: () => {
|
|
3504
|
+
}, disabled: isReadOnly || isSubmitting })))), /* @__PURE__ */ React41.createElement("div", { className: "flex items-center justify-between mt-2" }, !isReadOnly && /* @__PURE__ */ React41.createElement("button", { onClick: addCompanyMember, className: "px-6 py-2 bg-white border border-neutral-200 text-black text-[11px] tracking-widest rounded-full hover:bg-neutral-50 transition-colors outline-none" }, "+ Add Member"), /* @__PURE__ */ React41.createElement(ThreeDActionButton, { onClick: () => approveSection("membersDetailsApproved"), disabled: !areCompanyMembersValid() || isReadOnly, className: "w-fit" }, "Confirm Members"))) : /* @__PURE__ */ React41.createElement("div", { className: " flex items-center justify-between border border-neutral-100 p-4 rounded-xl" }, /* @__PURE__ */ React41.createElement("div", null, /* @__PURE__ */ React41.createElement("p", { className: "text-sm text-black" }, formData.members.length, " Member(s) Registered"), /* @__PURE__ */ React41.createElement("p", { className: "text-xs text-neutral-500 mt-1" }, "Total Shares: 100% Verified.")), !isReadOnly && /* @__PURE__ */ React41.createElement("button", { onClick: () => editSection("membersDetailsApproved"), className: "p-2 text-neutral-400 hover:text-black transition-colors outline-none shrink-0" }, /* @__PURE__ */ React41.createElement(HugeiconsIcon25, { icon: PencilEdit01Icon2, size: 16 })))), formState.addressApproved && type === "business" && /* @__PURE__ */ React41.createElement("div", { className: "flex flex-col gap-4 pt-6 animate-in slide-in-from-top-4 duration-500" }, /* @__PURE__ */ React41.createElement("div", { className: "flex items-center gap-2 text-black" }, /* @__PURE__ */ React41.createElement(HugeiconsIcon25, { icon: UserIcon, size: 18 }), /* @__PURE__ */ React41.createElement("h3", { className: "text-sm " }, "Who owns the business?")), /* @__PURE__ */ React41.createElement("p", { className: "text-xs text-neutral-500 -mt-2" }, "Provide basic contact info. We will extract your DOB and ID number automatically in the next step."), !formState.ownerApproved ? /* @__PURE__ */ React41.createElement("div", { className: "flex flex-col gap-4 " }, /* @__PURE__ */ React41.createElement(TextInput, { label: "Full Name", value: formData.ownerName, onChange: (v) => setFormData({ ...formData, ownerName: v }), disabled: isReadOnly || isSubmitting }), /* @__PURE__ */ React41.createElement("div", { className: "grid grid-cols-2 gap-4" }, /* @__PURE__ */ React41.createElement(NumberInput, { label: "Phone Number", value: formData.ownerPhone, onChange: (v) => setFormData({ ...formData, ownerPhone: v }), disabled: isReadOnly || isSubmitting }), /* @__PURE__ */ React41.createElement(TextInput, { label: "Email Address", value: formData.ownerEmail, onChange: (v) => setFormData({ ...formData, ownerEmail: v }), disabled: isReadOnly || isSubmitting })), /* @__PURE__ */ React41.createElement(ThreeDActionButton, { onClick: () => approveSection("ownerApproved"), disabled: !formData.ownerName || !formData.ownerPhone || !formData.ownerEmail || isReadOnly, className: "w-fit mt-2" }, "Confirm Owner Details")) : /* @__PURE__ */ React41.createElement("div", { className: " flex items-center justify-between border border-neutral-100 p-4 rounded-xl" }, /* @__PURE__ */ React41.createElement("div", null, /* @__PURE__ */ React41.createElement("p", { className: "text-sm text-black" }, formData.ownerName), /* @__PURE__ */ React41.createElement("p", { className: "text-xs text-neutral-500 mt-1" }, formData.ownerEmail, " \u2022 ", formData.ownerPhone)), !isReadOnly && /* @__PURE__ */ React41.createElement("button", { onClick: () => editSection("ownerApproved"), className: "p-2 text-neutral-400 hover:text-black transition-colors outline-none shrink-0" }, /* @__PURE__ */ React41.createElement(HugeiconsIcon25, { icon: PencilEdit01Icon2, size: 16 })))), /* @__PURE__ */ React41.createElement("div", { className: "flex items-center justify-between mt-8 pt-6 " }, /* @__PURE__ */ React41.createElement("button", { onClick: handleBack, className: "flex items-center gap-2 px-6 py-2 text-[11px] tracking-widest text-neutral-500 hover:text-black hover:bg-neutral-50 rounded-full transition-colors outline-none" }, /* @__PURE__ */ React41.createElement(HugeiconsIcon25, { icon: Cancel01Icon3, size: 14 }), " Close"), /* @__PURE__ */ React41.createElement(ThreeDActionButton, { onClick: handleNext, disabled: !isStep0Valid, className: "w-fit shrink-0" }, "Next Step"))), macroStep === 1 && /* @__PURE__ */ React41.createElement("div", { className: "flex flex-col gap-8 animate-in fade-in" }, type === "company" ? /* @__PURE__ */ React41.createElement(React41.Fragment, null, /* @__PURE__ */ React41.createElement("div", { className: "flex flex-col gap-2" }, /* @__PURE__ */ React41.createElement("h3", { className: "text-sm text-black" }, "Member Identity Documents"), /* @__PURE__ */ React41.createElement("p", { className: "text-xs text-neutral-500 leading-relaxed" }, "Upload valid means of identification, passport photographs, and signatures for every director and shareholder.")), !formState.membersDocsApproved ? /* @__PURE__ */ React41.createElement("div", { className: "flex flex-col gap-6" }, formData.members.map((member, i) => /* @__PURE__ */ React41.createElement("div", { key: member.id, className: "flex flex-col gap-4" }, /* @__PURE__ */ React41.createElement("span", { className: "text-[11px] tracking-widest text-black mb-1" }, member.fullName || `Member ${i + 1}`, " ", /* @__PURE__ */ React41.createElement("span", { className: "text-neutral-400 ml-2" }, "(", member.role, ")")), /* @__PURE__ */ React41.createElement("input", { id: `id-upload-${i}`, type: "file", accept: "image/jpeg, image/png, image/webp, application/pdf", className: "hidden", onChange: (e) => handleCompanyMemberUpload(e, i, "id"), disabled: isReadOnly || isAnyUploading }), /* @__PURE__ */ React41.createElement("input", { id: `pass-upload-${i}`, type: "file", accept: "image/jpeg, image/png, image/webp, application/pdf", className: "hidden", onChange: (e) => handleCompanyMemberUpload(e, i, "passport"), disabled: isReadOnly || isAnyUploading }), /* @__PURE__ */ React41.createElement("input", { id: `sig-upload-${i}`, type: "file", accept: "image/jpeg, image/png, image/webp, application/pdf", className: "hidden", onChange: (e) => handleCompanyMemberUpload(e, i, "signature"), disabled: isReadOnly || isAnyUploading }), !member.idExtractedData && !globalExtractingId ? /* @__PURE__ */ React41.createElement("button", { onClick: () => !isReadOnly && !isAnyUploading && document.getElementById(`id-upload-${i}`)?.click(), className: `flex items-center gap-3 p-4 border border-neutral-200 rounded-full transition-colors text-sm w-full outline-none ${isAnyUploading ? "opacity-50 cursor-not-allowed bg-neutral-50 text-neutral-400" : "text-black hover:bg-neutral-50"}`, disabled: isReadOnly || isAnyUploading }, /* @__PURE__ */ React41.createElement(HugeiconsIcon25, { icon: Upload01Icon3, size: 18, className: "text-neutral-400" }), " Upload Valid ID (NIN, License, Voter's Card)") : globalExtractingId && !member.idExtractedData ? /* @__PURE__ */ React41.createElement("div", { className: " mt-2" }, /* @__PURE__ */ React41.createElement(AiStageCheck, { tasks: aiTasks })) : member.idExtractedData ? /* @__PURE__ */ React41.createElement("div", { className: " mt-2 animate-in fade-in border border-purple-100 bg-linear-to-bl from-purple-50/80 via-white to-white p-5 rounded-xl flex flex-col gap-4 relative overflow-hidden" }, /* @__PURE__ */ React41.createElement("div", null, /* @__PURE__ */ React41.createElement("span", { className: "text-[10px] tracking-widest text-purple-600 block mb-2" }, "Review Extracted ID"), /* @__PURE__ */ React41.createElement("div", { className: "flex flex-col gap-4" }, /* @__PURE__ */ React41.createElement(TextInput, { label: "Full Name on ID", value: member.idExtractedData.fullName, onChange: (v) => updateCompanyMemberInfo(i, "idExtractedData", { ...member.idExtractedData, fullName: v }), disabled: isReadOnly || isAnyUploading }), /* @__PURE__ */ React41.createElement("div", { className: "grid grid-cols-2 gap-4" }, /* @__PURE__ */ React41.createElement(TextInput, { label: "ID Number", value: member.idExtractedData.idNumber, onChange: (v) => updateCompanyMemberInfo(i, "idExtractedData", { ...member.idExtractedData, idNumber: v }), disabled: isReadOnly || isAnyUploading }), /* @__PURE__ */ React41.createElement(TextInput, { label: "Date of Birth", value: member.idExtractedData.dob, onChange: (v) => updateCompanyMemberInfo(i, "idExtractedData", { ...member.idExtractedData, dob: v }), disabled: isReadOnly || isAnyUploading })))), /* @__PURE__ */ React41.createElement("div", { className: "flex items-center gap-2 mt-2" }, !isReadOnly && /* @__PURE__ */ React41.createElement("button", { onClick: () => deleteCompanyMemberDocument(i, "id"), disabled: isAnyUploading, className: "px-6 py-2 bg-white border border-neutral-200 text-neutral-500 text-[11px] rounded-full tracking-widest hover:bg-neutral-50 transition-colors outline-none disabled:opacity-50 disabled:cursor-not-allowed" }, "Delete & Re-upload ID"))) : null, !member.passportFileUrl && !globalUploadingPassport ? /* @__PURE__ */ React41.createElement("button", { onClick: () => !isReadOnly && !isAnyUploading && document.getElementById(`pass-upload-${i}`)?.click(), className: `flex items-center gap-3 p-4 border border-neutral-200 rounded-full transition-colors text-sm w-full outline-none ${isAnyUploading ? "opacity-50 cursor-not-allowed bg-neutral-50 text-neutral-400" : "text-black hover:bg-neutral-50"}`, disabled: isReadOnly || isAnyUploading }, /* @__PURE__ */ React41.createElement(HugeiconsIcon25, { icon: Upload01Icon3, size: 18, className: "text-neutral-400" }), " Upload Passport Photo") : globalUploadingPassport && !member.passportFileUrl ? /* @__PURE__ */ React41.createElement("div", { className: "flex items-center gap-3 p-4 border border-neutral-200 rounded-full bg-neutral-50 text-neutral-500 text-sm w-full" }, /* @__PURE__ */ React41.createElement(HugeiconsIcon25, { icon: Loading03Icon12, size: 18, className: "animate-spin text-black" }), " Uploading Passport...") : member.passportFileUrl ? /* @__PURE__ */ React41.createElement("div", { className: "flex items-center justify-between p-4 bg-emerald-50 rounded-full text-emerald-800 text-sm w-full" }, /* @__PURE__ */ React41.createElement("div", { className: "flex items-center gap-3" }, /* @__PURE__ */ React41.createElement(HugeiconsIcon25, { icon: IdentificationIcon, size: 18 }), " Passport Uploaded"), !isReadOnly && /* @__PURE__ */ React41.createElement("button", { onClick: () => deleteCompanyMemberDocument(i, "passport"), disabled: isAnyUploading, className: "text-emerald-700 hover:text-red-500 transition-colors p-1 outline-none shrink-0 disabled:opacity-50 disabled:cursor-not-allowed" }, /* @__PURE__ */ React41.createElement(HugeiconsIcon25, { icon: Delete02Icon2, size: 16 }))) : null, !member.signatureFileUrl && !globalUploadingSignature ? /* @__PURE__ */ React41.createElement("button", { onClick: () => !isReadOnly && !isAnyUploading && document.getElementById(`sig-upload-${i}`)?.click(), className: `flex items-center gap-3 p-4 border border-neutral-200 rounded-full transition-colors text-sm w-full outline-none ${isAnyUploading ? "opacity-50 cursor-not-allowed bg-neutral-50 text-neutral-400" : "text-black hover:bg-neutral-50"}`, disabled: isReadOnly || isAnyUploading }, /* @__PURE__ */ React41.createElement(HugeiconsIcon25, { icon: Upload01Icon3, size: 18, className: "text-neutral-400" }), " Upload Signature") : globalUploadingSignature && !member.signatureFileUrl ? /* @__PURE__ */ React41.createElement("div", { className: "flex items-center gap-3 p-4 border border-neutral-200 rounded-full bg-neutral-50 text-neutral-500 text-sm w-full" }, /* @__PURE__ */ React41.createElement(HugeiconsIcon25, { icon: Loading03Icon12, size: 18, className: "animate-spin text-black" }), " Uploading Signature...") : member.signatureFileUrl ? /* @__PURE__ */ React41.createElement("div", { className: "flex items-center justify-between p-4 bg-emerald-50 rounded-full text-emerald-800 text-sm w-full" }, /* @__PURE__ */ React41.createElement("div", { className: "flex items-center gap-3" }, /* @__PURE__ */ React41.createElement(HugeiconsIcon25, { icon: SignatureIcon, size: 18 }), " Signature Uploaded"), !isReadOnly && /* @__PURE__ */ React41.createElement("button", { onClick: () => deleteCompanyMemberDocument(i, "signature"), disabled: isAnyUploading, className: "text-emerald-700 hover:text-red-500 transition-colors p-1 outline-none shrink-0 disabled:opacity-50 disabled:cursor-not-allowed" }, /* @__PURE__ */ React41.createElement(HugeiconsIcon25, { icon: Delete02Icon2, size: 16 }))) : null)), /* @__PURE__ */ React41.createElement("div", { className: "flex justify-end" }, /* @__PURE__ */ React41.createElement(ThreeDActionButton, { onClick: () => approveSection("membersDocsApproved"), disabled: !areCompanyMemberDocsValid() || isReadOnly || isAnyUploading, className: "w-fit" }, "Confirm All Documents"))) : /* @__PURE__ */ React41.createElement("div", { className: " flex items-center justify-between bg-emerald-50 p-6 rounded-2xl" }, /* @__PURE__ */ React41.createElement("div", null, /* @__PURE__ */ React41.createElement("p", { className: "text-sm text-emerald-800" }, "All Member Documents Verified"), /* @__PURE__ */ React41.createElement("p", { className: "text-xs text-emerald-600 mt-1" }, "Data safely extracted and ready for submission.")), !isReadOnly && /* @__PURE__ */ React41.createElement("button", { onClick: () => editSection("membersDocsApproved"), className: "p-2 text-emerald-700 hover:text-black transition-colors outline-none shrink-0" }, /* @__PURE__ */ React41.createElement(HugeiconsIcon25, { icon: PencilEdit01Icon2, size: 16 })))) : /* @__PURE__ */ React41.createElement(React41.Fragment, null, /* @__PURE__ */ React41.createElement("input", { type: "file", accept: "image/jpeg, image/png, image/webp, application/pdf", ref: idRef, onChange: (e) => handleBusinessUpload(e, "id"), disabled: isReadOnly || isAnyUploading, className: "hidden" }), /* @__PURE__ */ React41.createElement("input", { type: "file", accept: "image/jpeg, image/png, image/webp, application/pdf", ref: passportRef, onChange: (e) => handleBusinessUpload(e, "passport"), disabled: isReadOnly || isAnyUploading, className: "hidden" }), /* @__PURE__ */ React41.createElement("input", { type: "file", accept: "image/jpeg, image/png, image/webp, application/pdf", ref: signatureRef, onChange: (e) => handleBusinessUpload(e, "signature"), disabled: isReadOnly || isAnyUploading, className: "hidden" }), /* @__PURE__ */ React41.createElement("div", { className: "flex flex-col gap-4" }, /* @__PURE__ */ React41.createElement("div", { className: "flex items-center gap-2 text-black" }, /* @__PURE__ */ React41.createElement("h3", { className: "text-sm " }, "Upload Means of Identification")), /* @__PURE__ */ React41.createElement("p", { className: "text-xs text-neutral-500 -mt-2" }, "Upload your NIN, Driver's License, Voter's Card, or Int'l Passport (JPG/PNG/WEBP)."), !formState.idApproved ? /* @__PURE__ */ React41.createElement(React41.Fragment, null, /* @__PURE__ */ React41.createElement("button", { onClick: () => !isReadOnly && !isAnyUploading && idRef.current?.click(), disabled: isReadOnly || isAnyUploading, className: `w-full h-32 border border-neutral-200 rounded-2xl flex flex-col items-center justify-center gap-2 transition-colors outline-none ${isAnyUploading ? "opacity-50 cursor-not-allowed bg-neutral-50 text-neutral-400" : "hover:bg-neutral-50 text-black"}` }, /* @__PURE__ */ React41.createElement(HugeiconsIcon25, { icon: Upload01Icon3, size: 24, className: "text-neutral-400" }), /* @__PURE__ */ React41.createElement("span", { className: "text-xs" }, "Select ID Image to Upload")), globalExtractingId && /* @__PURE__ */ React41.createElement("div", { className: " mt-2" }, /* @__PURE__ */ React41.createElement(AiStageCheck, { tasks: aiTasks })), formData.idExtractedData && /* @__PURE__ */ React41.createElement("div", { className: " mt-2 animate-in fade-in border border-purple-100 bg-linear-to-bl from-purple-50/80 via-white to-white p-5 rounded-2xl flex flex-col gap-4 relative overflow-hidden" }, /* @__PURE__ */ React41.createElement("div", null, /* @__PURE__ */ React41.createElement("span", { className: "text-[10px] tracking-widest text-purple-600 block mb-2" }, "Review AI Extracted Data"), /* @__PURE__ */ React41.createElement("p", { className: "text-xs text-neutral-500 mb-4" }, "Please verify the extracted information and correct any OCR mistakes before approving."), /* @__PURE__ */ React41.createElement("div", { className: "flex flex-col gap-4" }, /* @__PURE__ */ React41.createElement(TextInput, { label: "Full Name on ID", value: formData.idExtractedData.fullName, onChange: (v) => setFormData((f) => ({ ...f, idExtractedData: { ...f.idExtractedData, fullName: v } })), disabled: isReadOnly || isAnyUploading }), /* @__PURE__ */ React41.createElement("div", { className: "grid grid-cols-2 gap-4" }, /* @__PURE__ */ React41.createElement(TextInput, { label: "ID Number", value: formData.idExtractedData.idNumber, onChange: (v) => setFormData((f) => ({ ...f, idExtractedData: { ...f.idExtractedData, idNumber: v } })), disabled: isReadOnly || isAnyUploading }), /* @__PURE__ */ React41.createElement(TextInput, { label: "Date of Birth (YYYY-MM-DD)", value: formData.idExtractedData.dob, onChange: (v) => setFormData((f) => ({ ...f, idExtractedData: { ...f.idExtractedData, dob: v } })), disabled: isReadOnly || isAnyUploading })))), /* @__PURE__ */ React41.createElement("div", { className: "flex items-center gap-2 mt-2" }, /* @__PURE__ */ React41.createElement(ThreeDActionButton, { onClick: () => approveSection("idApproved"), disabled: isAnyUploading || isReadOnly, className: "w-fit shrink-0" }, "Approve Data"), !isReadOnly && /* @__PURE__ */ React41.createElement("button", { onClick: () => deleteBusinessDocument("id"), disabled: isAnyUploading, className: "px-6 py-2 bg-white border border-neutral-200 text-neutral-500 text-[11px] rounded-full tracking-widest hover:bg-neutral-50 transition-colors outline-none disabled:opacity-50 disabled:cursor-not-allowed" }, "Delete & Re-upload")))) : /* @__PURE__ */ React41.createElement("div", { className: " flex items-center justify-between bg-emerald-50 p-6 rounded-2xl" }, /* @__PURE__ */ React41.createElement("div", null, /* @__PURE__ */ React41.createElement("p", { className: "text-sm text-emerald-800" }, "ID Document Verified"), /* @__PURE__ */ React41.createElement("p", { className: "text-xs text-emerald-600 mt-1" }, "Data safely extracted and stored.")), !isReadOnly && /* @__PURE__ */ React41.createElement("button", { onClick: () => editSection("idApproved"), className: "p-2 text-emerald-700 hover:text-black transition-colors outline-none shrink-0" }, /* @__PURE__ */ React41.createElement(HugeiconsIcon25, { icon: PencilEdit01Icon2, size: 16 })))), /* @__PURE__ */ React41.createElement("div", { className: "flex flex-col gap-4 pt-6 animate-in slide-in-from-top-4 duration-500" }, /* @__PURE__ */ React41.createElement("div", { className: "flex flex-col gap-3 " }, !formState.passportApproved && !globalUploadingPassport ? /* @__PURE__ */ React41.createElement("button", { onClick: () => !isReadOnly && !isAnyUploading && passportRef.current?.click(), disabled: isReadOnly || isAnyUploading, className: `flex items-center gap-3 p-4 border border-neutral-200 rounded-full transition-colors text-sm w-full outline-none ${isAnyUploading ? "opacity-50 cursor-not-allowed bg-neutral-50 text-neutral-400" : "text-black hover:bg-neutral-50"}` }, /* @__PURE__ */ React41.createElement(HugeiconsIcon25, { icon: Upload01Icon3, size: 18, className: "text-neutral-400" }), " Upload Passport Photo") : globalUploadingPassport && !formData.passportFileUrl ? /* @__PURE__ */ React41.createElement("div", { className: "flex items-center gap-3 p-4 border border-neutral-200 rounded-full bg-neutral-50 text-neutral-500 text-sm w-full" }, /* @__PURE__ */ React41.createElement(HugeiconsIcon25, { icon: Loading03Icon12, size: 18, className: "animate-spin text-black" }), " Uploading Passport...") : /* @__PURE__ */ React41.createElement("div", { className: "flex items-center justify-between p-4 bg-emerald-50 rounded-full text-emerald-800 text-sm w-full" }, /* @__PURE__ */ React41.createElement("div", { className: "flex items-center gap-3" }, /* @__PURE__ */ React41.createElement(HugeiconsIcon25, { icon: IdentificationIcon, size: 18 }), " Passport Uploaded"), !isReadOnly && /* @__PURE__ */ React41.createElement("button", { onClick: () => deleteBusinessDocument("passport"), disabled: isAnyUploading, className: "text-emerald-700 hover:text-red-500 transition-colors p-1 outline-none shrink-0 disabled:opacity-50 disabled:cursor-not-allowed" }, /* @__PURE__ */ React41.createElement(HugeiconsIcon25, { icon: Delete02Icon2, size: 16 }))), !formState.signatureApproved && !globalUploadingSignature ? /* @__PURE__ */ React41.createElement("button", { onClick: () => !isReadOnly && !isAnyUploading && signatureRef.current?.click(), disabled: isReadOnly || isAnyUploading, className: `flex items-center gap-3 p-4 border border-neutral-200 rounded-full transition-colors text-sm w-full outline-none ${isAnyUploading ? "opacity-50 cursor-not-allowed bg-neutral-50 text-neutral-400" : "text-black hover:bg-neutral-50"}` }, /* @__PURE__ */ React41.createElement(HugeiconsIcon25, { icon: Upload01Icon3, size: 18, className: "text-neutral-400" }), " Upload Signature") : globalUploadingSignature && !formData.signatureFileUrl ? /* @__PURE__ */ React41.createElement("div", { className: "flex items-center gap-3 p-4 border border-neutral-200 rounded-full bg-neutral-50 text-neutral-500 text-sm w-full" }, /* @__PURE__ */ React41.createElement(HugeiconsIcon25, { icon: Loading03Icon12, size: 18, className: "animate-spin text-black" }), " Uploading Signature...") : /* @__PURE__ */ React41.createElement("div", { className: "flex items-center justify-between p-4 bg-emerald-50 rounded-full text-emerald-800 text-sm w-full" }, /* @__PURE__ */ React41.createElement("div", { className: "flex items-center gap-3" }, /* @__PURE__ */ React41.createElement(HugeiconsIcon25, { icon: SignatureIcon, size: 18 }), " Signature Uploaded"), !isReadOnly && /* @__PURE__ */ React41.createElement("button", { onClick: () => deleteBusinessDocument("signature"), disabled: isAnyUploading, className: "text-emerald-700 hover:text-red-500 transition-colors p-1 outline-none shrink-0 disabled:opacity-50 disabled:cursor-not-allowed" }, /* @__PURE__ */ React41.createElement(HugeiconsIcon25, { icon: Delete02Icon2, size: 16 })))))), /* @__PURE__ */ React41.createElement("div", { className: "flex flex-col gap-4 pt-6 border-t border-neutral-100 animate-in slide-in-from-top-4 duration-500" }, /* @__PURE__ */ React41.createElement("input", { type: "file", accept: "image/jpeg, image/png, image/webp, application/pdf", ref: other1Ref, onChange: (e) => handleOptionalUpload(e, "other1"), disabled: isAnyUploading || isReadOnly, className: "hidden" }), /* @__PURE__ */ React41.createElement("input", { type: "file", accept: "image/jpeg, image/png, image/webp, application/pdf", ref: other2Ref, onChange: (e) => handleOptionalUpload(e, "other2"), disabled: isAnyUploading || isReadOnly, className: "hidden" }), /* @__PURE__ */ React41.createElement("input", { type: "file", accept: "image/jpeg, image/png, image/webp, application/pdf", ref: other3Ref, onChange: (e) => handleOptionalUpload(e, "other3"), disabled: isAnyUploading || isReadOnly, className: "hidden" }), /* @__PURE__ */ React41.createElement("div", { className: "flex flex-col gap-1 mb-2" }, /* @__PURE__ */ React41.createElement("h3", { className: "text-sm text-black" }, "Additional Documents (Optional)"), /* @__PURE__ */ React41.createElement("p", { className: "text-xs text-neutral-500 leading-relaxed" }, "If your ", type === "company" ? "company" : "business", " involves regulated professional services, please upload relevant licenses, certificates, or permits here (up to 3 documents).")), /* @__PURE__ */ React41.createElement("div", { className: "flex flex-col gap-3" }, [1, 2, 3].map((num) => {
|
|
3505
|
+
const docType = `other${num}`;
|
|
3506
|
+
const ref = num === 1 ? other1Ref : num === 2 ? other2Ref : other3Ref;
|
|
3507
|
+
const isUploading = num === 1 ? isUploadingOther1 : num === 2 ? isUploadingOther2 : isUploadingOther3;
|
|
3508
|
+
const fileUrl = formData[`otherDoc${num}Url`];
|
|
3509
|
+
if (!fileUrl && !isUploading) {
|
|
3510
|
+
const prevUrl = num > 1 ? formData[`otherDoc${num - 1}Url`] : true;
|
|
3511
|
+
if (!prevUrl) return null;
|
|
3512
|
+
return /* @__PURE__ */ React41.createElement("button", { key: num, onClick: () => !isReadOnly && !isAnyUploading && ref.current?.click(), disabled: isReadOnly || isAnyUploading, className: `flex items-center gap-3 p-4 border border-neutral-200 rounded-full transition-colors text-sm w-full outline-none ${isAnyUploading ? "opacity-50 cursor-not-allowed bg-neutral-50 text-neutral-400" : "text-black hover:bg-neutral-50"}` }, /* @__PURE__ */ React41.createElement(HugeiconsIcon25, { icon: Upload01Icon3, size: 18, className: "text-neutral-400" }), " Upload Optional Document ", num);
|
|
3513
|
+
}
|
|
3514
|
+
if (isUploading) {
|
|
3515
|
+
return /* @__PURE__ */ React41.createElement("div", { key: num, className: "flex items-center gap-3 p-4 border border-neutral-200 rounded-full bg-neutral-50 text-neutral-500 text-sm w-full" }, /* @__PURE__ */ React41.createElement(HugeiconsIcon25, { icon: Loading03Icon12, size: 18, className: "animate-spin text-black" }), " Uploading Document ", num, "...");
|
|
3516
|
+
}
|
|
3517
|
+
return /* @__PURE__ */ React41.createElement("div", { key: num, className: "flex items-center justify-between p-4 bg-emerald-50 rounded-full text-emerald-800 text-sm w-full" }, /* @__PURE__ */ React41.createElement("div", { className: "flex items-center gap-3" }, /* @__PURE__ */ React41.createElement(HugeiconsIcon25, { icon: CheckmarkBadge01Icon, size: 18 }), " Optional Document ", num, " Uploaded"), !isReadOnly && /* @__PURE__ */ React41.createElement("button", { onClick: () => deleteOptionalDocument(docType), disabled: isAnyUploading, className: "text-emerald-700 hover:text-red-500 transition-colors p-1 outline-none shrink-0 disabled:opacity-50 disabled:cursor-not-allowed" }, /* @__PURE__ */ React41.createElement(HugeiconsIcon25, { icon: Delete02Icon2, size: 16 })));
|
|
3518
|
+
}))), /* @__PURE__ */ React41.createElement("div", { className: "flex items-center justify-between mt-8 pt-6 " }, /* @__PURE__ */ React41.createElement("button", { onClick: handleBack, disabled: isAnyUploading, className: "flex items-center gap-2 px-6 py-2 text-[11px] tracking-widest text-neutral-500 hover:text-black hover:bg-neutral-50 rounded-full transition-colors outline-none disabled:opacity-50 disabled:cursor-not-allowed" }, /* @__PURE__ */ React41.createElement(HugeiconsIcon25, { icon: ArrowLeft01Icon7, size: 14 }), " Back"), /* @__PURE__ */ React41.createElement(ThreeDActionButton, { onClick: handleNext, disabled: !isStep1Valid || isAnyUploading, className: "w-fit shrink-0" }, "Review Application"))), macroStep === 2 && /* @__PURE__ */ React41.createElement("div", { className: "flex flex-col gap-6 animate-in fade-in" }, /* @__PURE__ */ React41.createElement("div", null, /* @__PURE__ */ React41.createElement("h3", { className: "text-sm mb-5 text-black" }, "Application Summary"), /* @__PURE__ */ React41.createElement("div", { className: "flex flex-col gap-4 text-sm" }, /* @__PURE__ */ React41.createElement("div", { className: "flex flex-col sm:flex-row sm:justify-between border-b border-neutral-100 pb-3 gap-1" }, /* @__PURE__ */ React41.createElement("span", { className: "text-neutral-500 truncate text-[13px] " }, type === "company" ? "Company Name" : "Business Name"), /* @__PURE__ */ React41.createElement("span", { className: " text-black text-[13px]" }, formData.approvedName)), /* @__PURE__ */ React41.createElement("div", { className: "flex flex-col sm:flex-row sm:justify-between border-b border-neutral-100 pb-3 gap-1" }, /* @__PURE__ */ React41.createElement("span", { className: "text-neutral-500 text-[13px] " }, "Classification"), /* @__PURE__ */ React41.createElement("span", { className: " text-black truncate sm:text-right text-[13px] " }, formData.natureOfBusiness?.specificLabel || "Pending")), type === "company" ? /* @__PURE__ */ React41.createElement(React41.Fragment, null, /* @__PURE__ */ React41.createElement("div", { className: "flex flex-col sm:flex-row sm:justify-between border-b border-neutral-100 pb-3 gap-1" }, /* @__PURE__ */ React41.createElement("span", { className: "text-neutral-500 text-[13px] " }, "Total Members"), /* @__PURE__ */ React41.createElement("span", { className: " text-black truncate text-[13px] " }, formData.members.length, " Directors/Shareholders")), /* @__PURE__ */ React41.createElement("div", { className: "flex flex-col sm:flex-row sm:justify-between border-b border-neutral-100 pb-3 gap-1" }, /* @__PURE__ */ React41.createElement("span", { className: "text-neutral-500 text-[13px] " }, "Share Capital"), /* @__PURE__ */ React41.createElement("span", { className: " text-black truncate text-[13px] " }, "100% Allocated"))) : /* @__PURE__ */ React41.createElement("div", { className: "flex flex-col sm:flex-row sm:justify-between border-b border-neutral-100 pb-3 gap-1" }, /* @__PURE__ */ React41.createElement("span", { className: "text-neutral-500 text-[13px] " }, "Proprietor"), /* @__PURE__ */ React41.createElement("span", { className: " text-black truncate text-[13px] " }, formData.ownerName)), /* @__PURE__ */ React41.createElement("div", { className: "flex flex-col sm:flex-row sm:justify-between pb-2 gap-1" }, /* @__PURE__ */ React41.createElement("span", { className: "text-neutral-500 text-[13px] " }, "Documents Attached"), /* @__PURE__ */ React41.createElement("span", { className: " text-neutral-400 text-[13px] " }, "ID, Passport, Signature")), formData.otherDoc1Url && /* @__PURE__ */ React41.createElement("div", { className: "flex flex-col sm:flex-row sm:justify-between pb-2 gap-1" }, /* @__PURE__ */ React41.createElement("span", { className: "text-neutral-500 text-[13px] " }, "Optional Documents"), /* @__PURE__ */ React41.createElement("span", { className: " text-neutral-400 text-[13px] " }, [formData.otherDoc1Url, formData.otherDoc2Url, formData.otherDoc3Url].filter(Boolean).length, " Attached")))), /* @__PURE__ */ React41.createElement("div", { className: "flex items-center justify-between mt-4 pt-4 " }, /* @__PURE__ */ React41.createElement("button", { onClick: handleBack, className: "flex items-center gap-2 px-6 py-2 rounded-full text-[11px] tracking-widest text-neutral-500 hover:text-black hover:bg-neutral-50 transition-colors outline-none" }, /* @__PURE__ */ React41.createElement(HugeiconsIcon25, { icon: ArrowLeft01Icon7, size: 14 }), " Back"), /* @__PURE__ */ React41.createElement(ThreeDActionButton, { onClick: handleNext, className: "w-fit shrink-0" }, "Confirm & Proceed"))), macroStep === 3 && /* @__PURE__ */ React41.createElement("div", { className: "flex flex-col gap-6 py-6 animate-in zoom-in-95 duration-500" }, /* @__PURE__ */ React41.createElement("h2", { className: "text-lg font-serif text-black tracking-tight mb-2" }, "Terms and Conditions of Application"), /* @__PURE__ */ React41.createElement("div", { className: "text-xs text-neutral-500 mb-4" }, /* @__PURE__ */ React41.createElement("p", { className: " mb-3" }, "Declaration and Consent"), /* @__PURE__ */ React41.createElement("p", { className: "mb-3 leading-relaxed" }, "By proceeding with this application, you acknowledge and agree that all data, documents, and identification materials provided herein will be securely transmitted to the relevant official registries and authorized agents for the purpose of ", type === "company" ? "company" : "business", " incorporation and compliance verification."), /* @__PURE__ */ React41.createElement("p", { className: "mb-3 leading-relaxed" }, "You confirm that all information provided is accurate and authentic. Any falsification of identity or corporate data may result in immediate rejection, and you may be held liable under applicable laws and regulations."), /* @__PURE__ */ React41.createElement("p", { className: "mb-3 leading-relaxed" }, "This service operates strictly as a digital intermediary connecting you with official registries. The final approval of the ", type === "company" ? "company" : "business", " name and registration rests solely with the regulatory authorities. We are not liable for rejections arising from pre existing conflicts, non compliance, or regulatory policy changes not flagged during the AI pre check stages."), /* @__PURE__ */ React41.createElement("p", { className: "leading-relaxed" }, "Proceeding to generate the invoice confirms your acceptance of these terms and initiates the formal filing process.")), /* @__PURE__ */ React41.createElement("label", { className: "flex items-start gap-3 mt-2 cursor-pointer group" }, /* @__PURE__ */ React41.createElement("input", { type: "checkbox", checked: iAgree, onChange: (e) => setIAgree(e.target.checked), disabled: isReadOnly, className: "mt-0.5 w-4 h-4 accent-black rounded cursor-pointer" }), /* @__PURE__ */ React41.createElement("span", { className: "text-[13px] text-red-500 group-hover:text-red-600 transition-colors" }, "I have read, understood, and agree to the terms of data transfer and processing.")), /* @__PURE__ */ React41.createElement("div", { className: "flex flex-col sm:flex-row items-center gap-4 mt-8 w-full justify-end pt-6" }, /* @__PURE__ */ React41.createElement("button", { onClick: onCancelOrClose, disabled: isSubmitting, className: "px-8 py-2 text-[11px] tracking-widest text-neutral-500 hover:text-black hover:bg-neutral-50 rounded-full transition-colors outline-none w-full sm:w-auto" }, "Cancel"), /* @__PURE__ */ React41.createElement("button", { onClick: () => setMacroStep(0), disabled: isSubmitting || isReadOnly, className: "px-8 py-2 text-[11px] tracking-widest text-neutral-500 hover:text-black hover:bg-neutral-50 rounded-full transition-colors outline-none w-full sm:w-auto" }, "Edit Application"), /* @__PURE__ */ React41.createElement(ThreeDActionButton, { onClick: handleFinalSubmit, disabled: isSubmitting || !iAgree || isReadOnly, isLoading: isSubmitting, className: "min-w-40 w-full sm:w-auto" }, "Submit")))), activeModal.isOpen && /* @__PURE__ */ React41.createElement("div", { className: "fixed inset-0 z-110 flex items-center justify-center p-4" }, /* @__PURE__ */ React41.createElement("div", { className: "absolute inset-0 bg-black/30", onClick: () => setActiveModal({ isOpen: false, type: null, memberIndex: null }) }), /* @__PURE__ */ React41.createElement("div", { className: "relative w-80 bg-white shadow-2xl rounded-3xl flex flex-col overflow-hidden animate-in zoom-in-95 duration-200 max-h-[80vh]" }, /* @__PURE__ */ React41.createElement("div", { className: "p-4 text-center w-full shrink-0" }, /* @__PURE__ */ React41.createElement("h3", { className: "text-[14px] text-black tracking-tight capitalize" }, "Select ", activeModal.type)), /* @__PURE__ */ React41.createElement("div", { className: "p-4 flex flex-col gap-2 overflow-y-auto custom-scrollbar" }, (activeModal.type === "state" ? NIGERIAN_STATES : activeModal.type === "role" ? MEMBER_ROLES : NATIONALITIES).map((opt) => {
|
|
3519
|
+
const isSelected = activeModal.isGlobalState ? formData.state === opt : formData.members[activeModal.memberIndex][activeModal.type] === opt;
|
|
3520
|
+
return /* @__PURE__ */ React41.createElement("button", { key: opt, onClick: () => {
|
|
3521
|
+
if (activeModal.isGlobalState) setFormData({ ...formData, state: opt });
|
|
3522
|
+
else updateCompanyMemberInfo(activeModal.memberIndex, activeModal.type, opt);
|
|
3523
|
+
setActiveModal({ isOpen: false, type: null, memberIndex: null });
|
|
3524
|
+
}, className: `text-left px-4 py-3 rounded-full text-[13px] transition-colors outline-none ${isSelected ? "bg-neutral-100 text-black" : "text-neutral-500 hover:bg-neutral-50 hover:text-black"}` }, opt);
|
|
3525
|
+
})), /* @__PURE__ */ React41.createElement("div", { className: "w-full flex mt-auto shrink-0 " }, /* @__PURE__ */ React41.createElement("button", { onClick: () => setActiveModal({ isOpen: false, type: null, memberIndex: null }), className: "w-full py-4 text-[13px] text-neutral-500 hover:bg-neutral-50 transition-colors outline-none" }, "Close")))));
|
|
3526
|
+
};
|
|
2915
3527
|
export {
|
|
2916
3528
|
AITranscriptionFeature,
|
|
2917
3529
|
AiApproveDecline,
|
|
@@ -2952,6 +3564,7 @@ export {
|
|
|
2952
3564
|
UniversalOrganizationPage,
|
|
2953
3565
|
UniversalOverviewPage,
|
|
2954
3566
|
UniversalProfileSettings,
|
|
3567
|
+
UniversalRegistrationFlow,
|
|
2955
3568
|
UniversalSidebar,
|
|
2956
3569
|
ZairusAuth
|
|
2957
3570
|
};
|