@buzztech/boi-ui 0.2.0 → 0.2.1

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.
@@ -1 +1 @@
1
- {"version":3,"file":"boi-ui.umd.cjs","sources":["../src/components/BoiButton.vue","../src/lib/utils.ts","../src/components/ui/button/index.ts","../src/components/Button.vue","../src/api/edoc.ts","../src/components/EmtsIntegration.vue","../src/composables/useEdocBanks.ts","../src/composables/useAccountVerification.ts","../src/api/bankStatements.ts","../src/api/files.ts","../src/components/BankSelect.vue","../src/components/FileInput.vue","../src/components/BankStatementIntegration.vue","../src/index.ts"],"sourcesContent":["<script setup lang=\"ts\">\ndefineProps<{\n label?: string\n variant?: 'primary' | 'secondary'\n}>()\n</script>\n\n<template>\n <button\n type=\"button\"\n class=\"boi-button\"\n :class=\"[variant ? `boi-button--${variant}` : 'boi-button--primary']\"\n >\n <slot>{{ label }}</slot>\n </button>\n</template>\n\n<style scoped>\n.boi-button {\n padding: 0.5rem 1rem;\n border-radius: 0.375rem;\n font-weight: 500;\n cursor: pointer;\n border: none;\n}\n.boi-button--primary {\n background: #2563eb;\n color: white;\n}\n.boi-button--primary:hover {\n background: #1d4ed8;\n}\n.boi-button--secondary {\n background: #e5e7eb;\n color: #374151;\n}\n.boi-button--secondary:hover {\n background: #d1d5db;\n}\n</style>\n","export function cn(...classes: Array<any>) {\n return classes.flat(Infinity).filter(Boolean).join(' ')\n}\n","export { default as Button } from './Button.vue'\n\nexport type ButtonVariants = {\n variant?: 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link'\n size?: 'default' | 'sm' | 'lg' | 'icon'\n}\n\nconst baseClasses =\n \"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive\"\n\nconst variantClasses: Record<NonNullable<ButtonVariants['variant']>, string> = {\n default: 'bg-primary text-white shadow-xs hover:bg-primary/90',\n destructive:\n 'bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60',\n outline:\n 'border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50',\n secondary: 'bg-secondary text-white shadow-xs hover:bg-secondary/80',\n ghost: 'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50',\n link: 'text-primary underline-offset-4 hover:underline',\n}\n\nconst sizeClasses: Record<NonNullable<ButtonVariants['size']>, string> = {\n default: 'h-9 px-4 py-2 has-[>svg]:px-3',\n sm: 'h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5',\n lg: 'h-10 rounded-md px-6 has-[>svg]:px-4',\n icon: 'size-9',\n}\n\nexport function buttonVariants(options: ButtonVariants = {}) {\n const variant = options.variant ?? 'default'\n const size = options.size ?? 'default'\n return [baseClasses, variantClasses[variant], sizeClasses[size]].join(' ')\n}\n","<script setup lang=\"ts\">\nimport type { HTMLAttributes } from 'vue'\nimport { cn } from '../lib/utils'\nimport { type ButtonVariants, buttonVariants } from './ui/button/index'\n\ninterface Props {\n type?: 'button' | 'submit' | 'reset'\n variant?: ButtonVariants['variant']\n size?: ButtonVariants['size']\n class?: HTMLAttributes['class']\n disabled?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n type: 'button',\n variant: 'default',\n size: 'default',\n disabled: false,\n})\n</script>\n\n<template>\n <button\n :type=\"type\"\n :disabled=\"disabled\"\n data-slot=\"button\"\n :class=\"cn(\n buttonVariants({ variant: props.variant, size: props.size }),\n props.class\n )\"\n >\n <slot />\n </button>\n</template>\n","/**\n * EDOC API endpoint paths. Host app builds full URLs (e.g. baseURL + path).\n */\nexport const edocApi = {\n getBanks: () => '/api/edoc/banks',\n initializeConsent: () => '/api/edoc/consent/initialize',\n attachAccount: () => '/api/edoc/consent/attach-account',\n getTransactions: () => '/api/edoc/consent/transactions',\n manualUpload: () => '/api/edoc/manual-upload',\n} as const\n\nexport type EdocApi = typeof edocApi\n","<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport type { BankStatementRecord, EdocBank, BankOption } from '../types/edoc'\nimport { edocApi } from '../api/edoc'\nimport BoiButton from './BoiButton.vue'\n\n/** Shared classes: compact black actions for OTP flow */\nconst otpActionClass =\n 'inline-flex items-center justify-center rounded-md bg-black px-3 py-1.5 text-xs font-medium text-white shadow-sm hover:bg-neutral-900 focus:outline-none focus:ring-2 focus:ring-black focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50'\n\nconst props = withDefaults(\n defineProps<{\n account: BankStatementRecord\n edocBanks: EdocBank[]\n bankOptions: BankOption[]\n api: { post: (url: string, data: unknown) => Promise<{ data?: unknown }>; get?: (url: string) => Promise<{ data?: unknown }> }\n companyEmail?: string\n industrialSector?: string\n applicationId?: string | number\n disabled?: boolean\n /** Prefix for EDOC API paths when using a standalone service (e.g. boi-api). */\n integrationBaseUrl?: string\n }>(),\n { disabled: false, integrationBaseUrl: '' }\n)\n\nfunction edocPath(path: string): string {\n const b = (props.integrationBaseUrl ?? '').replace(/\\/$/, '')\n if (!b) return path\n const p = path.startsWith('/') ? path : `/${path}`\n return `${b}${p}`\n}\n\nconst emit = defineEmits<{\n 'update:consentId': [consentId: string]\n 'statement-retrieved': [statement: BankStatementRecord]\n 'error': [message: string]\n}>()\n\nconst generatingStatement = ref(false)\nconst submittingOtp = ref(false)\n\nfunction bankNames(bankCode: string): string[] {\n const b = props.bankOptions.find((o) => o.value === bankCode)\n return [b?.label ?? '', ...(b?.searchKeywords ?? [])].filter(Boolean)\n}\n\nfunction matchBank(bankCode: string, enabledOnly = false): EdocBank | undefined {\n if (!bankCode || !props.edocBanks.length) return undefined\n const names = bankNames(bankCode)\n return props.edocBanks.find((b) => {\n const code = b.bankCode === bankCode || b.code === bankCode\n const name = names.some((n) => b.name?.toLowerCase().includes(n.toLowerCase()))\n return (code || name) && (!enabledOnly || b.enabled !== false)\n })\n}\n\nconst getEdocBank = (code: string) => matchBank(code, false)\nconst isBankEdocSupported = (code: string) => !!matchBank(code, true)\nconst hasBankInstructions = computed(() => !!(getEdocBank(props.account.bank)?.bankInstructions?.length))\nconst canRequestOtp = computed(() => {\n const a = props.account\n return !!a.bank && a.account_number?.length === 10 && !generatingStatement.value && !submittingOtp.value\n})\nconst canSubmitOtp = computed(() => !!props.account.otp && !submittingOtp.value)\n\nconst errMsg = (e: unknown) =>\n (e as { response?: { data?: { message?: string } }; data?: { message?: string }; message?: string })?.response?.data?.message ??\n (e as { data?: { message?: string } })?.data?.message ??\n (e as Error)?.message ??\n 'An unexpected error occurred'\n\nconst consentPayload = (email: string) => ({\n email,\n referenceId: `loan_${props.applicationId ?? 'new'}_${props.account.id}`,\n firstName: 'Company',\n lastName: 'Account',\n state: 'Lagos',\n fundType: 'online portal',\n statementDuration: '12',\n redirectionUrl: typeof window !== 'undefined' ? window.location.origin + '/loan-application' : '',\n industrialSector: props.industrialSector ?? undefined,\n})\n\nasync function consentAndAttach(edocBank: EdocBank) {\n const email = props.account.email || props.companyEmail || ''\n const res = await props.api.post(edocPath(edocApi.initializeConsent()), consentPayload(email))\n const data = res?.data as { success?: boolean; data?: { data?: { consentId?: string } }; message?: string }\n if (!data?.success) throw new Error(data?.message ?? 'Failed to initialize consent')\n const consentId = data?.data?.data?.consentId\n if (!consentId) throw new Error('No consent ID returned')\n emit('update:consentId', consentId)\n await props.api.post(edocPath(edocApi.attachAccount()), {\n consentId,\n bankId: edocBank.bankId,\n accountNumber: props.account.account_number,\n accountType: 'Business',\n statementDuration: '12',\n monthType: 'Period',\n uploadType: 'Digital',\n })\n return consentId\n}\n\nasync function generateStatement() {\n const edocBank = getEdocBank(props.account.bank)\n if (!props.account.bank) return emit('error', 'Please select a bank')\n if (props.account.account_number?.length !== 10) return emit('error', 'Please provide a valid 10-digit account number')\n if (!edocBank) return emit('error', 'Selected bank does not support electronic statement retrieval')\n generatingStatement.value = true\n try {\n await consentAndAttach(edocBank)\n } catch (err) {\n emit('error', errMsg(err))\n } finally {\n generatingStatement.value = false\n }\n}\n\nasync function submitOtp() {\n if (!props.account.otp || !props.account.consent_id) return emit('error', 'Please enter OTP')\n submittingOtp.value = true\n try {\n const res = await props.api.post(edocPath(edocApi.getTransactions()), {\n consentId: props.account.consent_id,\n verificationCode: props.account.otp,\n bankStatementId: props.account.id,\n })\n const data = res?.data as { success?: boolean; data?: { statement?: BankStatementRecord }; message?: string }\n if (!data?.success) return emit('error', data?.message ?? 'Failed to retrieve transactions')\n if (data.data?.statement) emit('statement-retrieved', data.data.statement)\n } catch (err) {\n emit('error', errMsg(err))\n } finally {\n submittingOtp.value = false\n }\n}\n\nasync function retrieveStatementDirect() {\n const edocBank = getEdocBank(props.account.bank)\n if (!props.account.bank || props.account.account_number?.length !== 10) {\n return emit('error', 'Please select a bank and provide a valid 10-digit account number')\n }\n if (!edocBank) return emit('error', 'Selected bank does not support electronic statement retrieval')\n submittingOtp.value = true\n try {\n const consentId = await consentAndAttach(edocBank)\n const res = await props.api.post(edocPath(edocApi.getTransactions()), {\n consentId,\n verificationCode: '',\n bankStatementId: props.account.id,\n })\n const data = res?.data as { success?: boolean; data?: { statement?: BankStatementRecord }; message?: string }\n if (!data?.success) return emit('error', data?.message ?? 'Failed to retrieve transactions')\n if (data.data?.statement) emit('statement-retrieved', data.data.statement)\n } catch (err) {\n emit('error', errMsg(err))\n } finally {\n submittingOtp.value = false\n }\n}\n</script>\n\n<template>\n <div class=\"boi-emts-integration space-y-4\">\n <div v-if=\"isBankEdocSupported(account.bank)\">\n <template v-if=\"hasBankInstructions && !account.statement_generated\">\n <div class=\"boi-emts-instructions rounded-lg border border-amber-200 bg-amber-50 p-4 text-sm\">\n <p class=\"mb-2 font-semibold text-amber-900\">Bank-specific instructions</p>\n <ol class=\"list-inside list-decimal space-y-1 text-amber-800\">\n <li v-for=\"(instruction, idx) in getEdocBank(account.bank)?.bankInstructions\" :key=\"idx\">{{ instruction }}</li>\n </ol>\n </div>\n <BoiButton\n :label=\"submittingOtp ? 'Retrieving…' : 'Retrieve statement'\"\n variant=\"primary\"\n :disabled=\"!canRequestOtp || disabled\"\n @click=\"retrieveStatementDirect\"\n />\n </template>\n <template v-else-if=\"!hasBankInstructions && !account.statement_generated\">\n <button\n v-if=\"!account.showOtpInput\"\n type=\"button\"\n :class=\"otpActionClass\"\n :disabled=\"!canRequestOtp || disabled\"\n @click=\"generateStatement\"\n >\n {{ generatingStatement ? 'Sending OTP…' : 'Send OTP' }}\n </button>\n <div v-else class=\"boi-emts-otp space-y-3 rounded-lg border-2 border-primary bg-primary/5 p-4\">\n <p class=\"text-sm font-medium text-gray-700\">Enter the OTP sent to your bank-registered email.</p>\n <div class=\"flex flex-wrap items-end gap-3\">\n <div class=\"min-w-[140px]\">\n <label class=\"mb-1 block text-xs font-medium text-gray-600\">OTP code</label>\n <input v-model=\"account.otp\" type=\"text\" maxlength=\"6\" placeholder=\"6-digit OTP\" class=\"w-full rounded border border-gray-300 px-3 py-2 text-lg tracking-widest\" />\n </div>\n <button\n type=\"button\"\n :class=\"otpActionClass\"\n :disabled=\"!canSubmitOtp || disabled\"\n @click=\"submitOtp\"\n >\n Verify OTP\n </button>\n </div>\n </div>\n </template>\n </div>\n <div v-if=\"account.edoc_status === 'failed'\" class=\"text-sm text-red-600\">Statement retrieval failed. Please try again or upload manually.</div>\n <div v-if=\"account.edoc_status === 'processing'\" class=\"text-sm text-amber-600\">Processing…</div>\n </div>\n</template>\n","import { ref } from 'vue'\nimport type { EdocBank } from '../types/edoc'\nimport { edocApi } from '../api/edoc'\n\nexport interface UseEdocBanksOptions {\n get: (url: string) => Promise<{ data?: unknown }>\n /** Path or absolute URL; or a getter so it stays in sync with props (e.g. integration base URL). */\n getBanksUrl?: string | (() => string)\n fallbackBanksUrl?: string | (() => string)\n}\n\nfunction toBanksList(data: unknown): EdocBank[] {\n if (!data || typeof data !== 'object') return []\n const d = data as Record<string, unknown>\n const raw = (d.success ? d.data : d.data ?? d) as unknown\n if (Array.isArray(raw)) return raw as EdocBank[]\n if (raw && typeof raw === 'object' && Array.isArray((raw as Record<string, unknown>).data)) {\n return (raw as Record<string, EdocBank[]>).data\n }\n return []\n}\n\nfunction resolveUrl(u: string | (() => string) | undefined, fallback: string): string {\n if (u === undefined) return fallback\n return typeof u === 'function' ? u() : u\n}\n\nexport function useEdocBanks(options: UseEdocBanksOptions) {\n const { get, getBanksUrl, fallbackBanksUrl } = options\n const edocBanksCache = ref<EdocBank[]>([])\n const banksCache = ref<EdocBank[]>([])\n const loadingBanks = ref(false)\n const errorBanks = ref<string | null>(null)\n let banksPromise: Promise<EdocBank[]> | null = null\n\n const loadBanksForStatement = async (): Promise<EdocBank[]> => {\n if (edocBanksCache.value.length > 0) return edocBanksCache.value\n if (banksPromise) return banksPromise\n\n loadingBanks.value = true\n errorBanks.value = null\n banksPromise = (async () => {\n try {\n const res = await get(resolveUrl(getBanksUrl, edocApi.getBanks()))\n const list = toBanksList(res?.data)\n if (list.length) {\n edocBanksCache.value = banksCache.value = list\n return list\n }\n } catch {}\n const fallbackUrl =\n fallbackBanksUrl != null ? resolveUrl(fallbackBanksUrl, '') : ''\n if (fallbackUrl) {\n try {\n const fallback = await get(fallbackUrl)\n const list = Array.isArray(fallback?.data) ? (fallback.data as EdocBank[]) : []\n edocBanksCache.value = banksCache.value = list\n return list\n } catch (err: unknown) {\n errorBanks.value = (err as { response?: { data?: { message?: string } } })?.response?.data?.message ?? 'Failed to load banks'\n throw err\n }\n }\n return []\n })().finally(() => {\n loadingBanks.value = false\n banksPromise = null\n })\n return banksPromise\n }\n\n return {\n edocBanks: edocBanksCache,\n banks: banksCache,\n loading: loadingBanks,\n error: errorBanks,\n loadBanksForStatement,\n invalidateCache: () => {\n edocBanksCache.value = banksCache.value = []\n banksPromise = null\n errorBanks.value = null\n },\n }\n}\n","import { ref } from 'vue'\n\nexport interface VerificationState {\n isLoading: boolean\n isSuccess: boolean\n isError: boolean\n errorMessage?: string\n}\n\nconst verificationStates = ref<Record<string, VerificationState>>({})\n\nexport type VerifyBankAccountFn = (\n accountNumber: string,\n bankCode: string\n) => Promise<{ account_name?: string; accountName?: string } | null>\n\nexport function useAccountVerification(\n verifyBankAccount?: VerifyBankAccountFn | (() => VerifyBankAccountFn | null | undefined) | null\n) {\n const getVerifyFn = (): VerifyBankAccountFn | null | undefined =>\n typeof verifyBankAccount === 'function' && verifyBankAccount.length === 0\n ? (verifyBankAccount as () => VerifyBankAccountFn | null | undefined)()\n : (verifyBankAccount as VerifyBankAccountFn | null | undefined)\n const getVerificationKey = (account: { bank?: string; account_number?: string }) =>\n `${account.bank ?? ''}_${account.account_number ?? ''}`\n\n const getVerificationState = (account: { bank?: string; account_number?: string }): VerificationState => {\n const key = getVerificationKey(account)\n return (\n verificationStates.value[key] ?? {\n isLoading: false,\n isSuccess: false,\n isError: false,\n }\n )\n }\n\n const clearAccountName = (account: { account_name?: string }) => {\n account.account_name = ''\n }\n\n const handleAccountVerification = async (account: {\n bank?: string\n account_number?: string\n account_name?: string\n }) => {\n const bankCode = account.bank\n const accountNumber = account.account_number\n const key = getVerificationKey(account)\n const fn = getVerifyFn()\n\n if (!fn || !bankCode || !accountNumber || accountNumber.length !== 10) {\n delete verificationStates.value[key]\n if (accountNumber?.length !== 10) clearAccountName(account)\n return\n }\n\n clearAccountName(account)\n verificationStates.value[key] = { isLoading: true, isSuccess: false, isError: false }\n\n try {\n const result = await fn(accountNumber, bankCode)\n const name = result?.account_name ?? result?.accountName ?? ''\n if (name) {\n account.account_name = name\n verificationStates.value[key] = { isLoading: false, isSuccess: true, isError: false }\n } else {\n verificationStates.value[key] = {\n isLoading: false,\n isSuccess: false,\n isError: true,\n errorMessage: 'Account verification failed',\n }\n }\n } catch (err) {\n verificationStates.value[key] = {\n isLoading: false,\n isSuccess: false,\n isError: true,\n errorMessage: err instanceof Error ? err.message : 'Verification failed',\n }\n }\n }\n\n const retryVerification = (account: { bank?: string; account_number?: string; account_name?: string }) => {\n return handleAccountVerification(account)\n }\n\n return {\n handleAccountVerification,\n retryVerification,\n getVerificationState,\n clearAccountName,\n }\n}\n","/**\n * Bank statements API URL builders. Host app builds full URLs (e.g. baseURL + path).\n */\nconst defaultPrefix = '/api/loan-applications'\n\nexport function bankStatementsUrls(applicationId: string | number, baseUrl = '') {\n const prefix = baseUrl ? `${baseUrl.replace(/\\/$/, '')}${defaultPrefix}` : defaultPrefix\n const id = String(applicationId)\n return {\n index: `${prefix}/${id}/bank-statements`,\n store: `${prefix}/${id}/bank-statements`,\n update: (statementId: string | number) => `${prefix}/${id}/bank-statements/${statementId}`,\n destroy: (statementId: string | number) => `${prefix}/${id}/bank-statements/${statementId}`,\n uploadToEdoc: (statementId: string | number) => `${prefix}/${id}/bank-statements/${statementId}/upload-to-edoc`,\n }\n}\n\nexport const bankStatementsApi = {\n urls: bankStatementsUrls,\n}\n","/**\n * File upload / view URLs on the consuming app (e.g. Glow). Presigning uses that app’s S3 config\n * (`/api/files/view`, `Storage::disk('s3')` presign in Laravel, `boi_edoc` for `edoc/statements/…`).\n *\n * Uploads may still target `integrationBaseUrl` (boi-api) via `uploadUrl` on FileInput; view always\n * uses these paths so “View document” hits the SPA host, not boi-api.\n *\n * Optional: `VITE_FILES_API_BASE` when the static SPA origin differs from the Laravel app\n * (e.g. VITE_FILES_API_BASE=https://glow.test).\n */\nconst base = (import.meta.env.VITE_FILES_API_BASE as string | undefined)?.replace(/\\/$/, '') ?? ''\n\nexport const filesApi = {\n upload: () => `${base}/api/files/upload`,\n view: (path: string) => `${base}/api/files/view?path=${encodeURIComponent(path)}`,\n} as const\n","<script setup lang=\"ts\">\nimport { computed, ref, watch, nextTick, onMounted, onUnmounted } from 'vue'\nimport type { BankOption } from '../types/edoc'\nimport { cn } from '../lib/utils'\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string\n options: BankOption[]\n placeholder?: string\n disabled?: boolean\n id?: string\n }>(),\n { placeholder: 'Select bank', disabled: false }\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: string] }>()\n\nconst isOpen = ref(false)\nconst selectRef = ref<HTMLDivElement | null>(null)\nconst searchRef = ref<HTMLInputElement | null>(null)\nconst searchQuery = ref('')\nconst highlightedIndex = ref(-1)\n\nfunction optionMatchesQuery(opt: BankOption, q: string): boolean {\n if (!q) return true\n const parts = [\n opt.label,\n opt.shortName,\n ...(opt.searchKeywords ?? []),\n ]\n .filter((s) => s != null && String(s).trim() !== '')\n .map((s) => String(s).toLowerCase())\n\n // Any field contains full query (e.g. \"fcmb\", \"first city\")\n if (parts.some((p) => p.includes(q))) return true\n\n // Multi-word: each token must match somewhere (label, short name, or keyword)\n const tokens = q.split(/\\s+/).filter(Boolean)\n if (tokens.length > 1) {\n return tokens.every((t) => parts.some((p) => p.includes(t)))\n }\n\n // Single token: also allow prefix-style match on short name / keywords (e.g. \"fcm\" → FCMB)\n return parts.some((p) => p.startsWith(q))\n}\n\nconst filteredOptions = computed(() => {\n if (!props.options?.length) return []\n if (!searchQuery.value.trim()) return props.options\n const q = searchQuery.value.toLowerCase().trim()\n return props.options.filter((opt) => optionMatchesQuery(opt, q))\n})\n\nconst selectedOption = computed(() =>\n props.options?.find((o) => String(o.value) === String(props.modelValue)) ?? null\n)\n\nconst displayValue = computed(() => selectedOption.value?.label ?? props.placeholder)\n\nfunction toggle() {\n if (props.disabled) return\n isOpen.value = !isOpen.value\n if (isOpen.value) {\n searchQuery.value = ''\n highlightedIndex.value = filteredOptions.value.length ? 0 : -1\n nextTick(() => searchRef.value?.focus())\n }\n}\n\nfunction select(opt: BankOption) {\n emit('update:modelValue', String(opt.value))\n isOpen.value = false\n searchQuery.value = ''\n}\n\nfunction onKeydown(e: KeyboardEvent) {\n if (!isOpen.value) return\n const opts = filteredOptions.value\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault()\n highlightedIndex.value = Math.min(highlightedIndex.value + 1, opts.length - 1)\n break\n case 'ArrowUp':\n e.preventDefault()\n highlightedIndex.value = Math.max(highlightedIndex.value - 1, 0)\n break\n case 'Enter':\n e.preventDefault()\n if (highlightedIndex.value >= 0 && opts[highlightedIndex.value]) {\n select(opts[highlightedIndex.value])\n }\n break\n case 'Escape':\n e.preventDefault()\n isOpen.value = false\n break\n }\n}\n\nfunction onClickOutside(e: Event) {\n if (selectRef.value && !selectRef.value.contains(e.target as Node)) {\n isOpen.value = false\n }\n}\n\nwatch(searchQuery, () => {\n highlightedIndex.value = filteredOptions.value.length ? 0 : -1\n})\n\nonMounted(() => {\n if (typeof document !== 'undefined') {\n document.addEventListener('click', onClickOutside)\n }\n})\n\nonUnmounted(() => {\n if (typeof document !== 'undefined') {\n document.removeEventListener('click', onClickOutside)\n }\n})\n</script>\n\n<template>\n <div ref=\"selectRef\" class=\"relative\">\n <button\n type=\"button\"\n :id=\"id\"\n :disabled=\"disabled\"\n :class=\"cn(\n 'flex h-9 w-full min-w-0 items-center justify-between rounded-lg border border-gray-300 bg-white px-3 py-2.5 text-sm transition-colors outline-none',\n 'focus:border-[var(--boi-primary)] focus:ring-1 focus:ring-[var(--boi-primary)]',\n 'disabled:cursor-not-allowed disabled:opacity-50',\n !selectedOption && 'text-gray-500'\n )\"\n @click=\"toggle\"\n >\n <span class=\"truncate text-left\">{{ displayValue }}</span>\n <svg class=\"h-4 w-4 shrink-0 text-gray-400\" :class=\"{ 'rotate-180': isOpen }\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M19 9l-7 7-7-7\" />\n </svg>\n </button>\n\n <div\n v-if=\"isOpen\"\n class=\"absolute z-[1000] mt-1 w-full rounded-lg border border-gray-200 bg-white shadow-lg\"\n >\n <div class=\"border-b border-gray-100 p-2\">\n <div class=\"relative\">\n <svg class=\"absolute left-2.5 top-1/2 h-4 w-4 -translate-y-1/2 text-gray-400\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\" />\n </svg>\n <input\n ref=\"searchRef\"\n v-model=\"searchQuery\"\n type=\"text\"\n placeholder=\"Type to search...\"\n class=\"w-full rounded-md border-0 bg-gray-50 py-2 pl-9 pr-3 text-sm focus:bg-white focus:ring-1 focus:ring-[var(--boi-primary)]\"\n @keydown=\"onKeydown\"\n />\n </div>\n </div>\n <div class=\"max-h-48 overflow-auto py-1\">\n <button\n v-for=\"(option, index) in filteredOptions\"\n :key=\"option.value\"\n type=\"button\"\n :class=\"cn(\n 'w-full cursor-pointer px-3 py-2.5 text-left text-sm transition-colors text-gray-900',\n index === highlightedIndex ? 'bg-gray-100' : 'hover:bg-gray-50',\n String(option.value) === String(modelValue) &&\n modelValue !== '' &&\n modelValue !== undefined &&\n 'font-semibold text-[#016837]'\n )\"\n @click=\"select(option)\"\n >\n {{ option.label }}\n </button>\n <p v-if=\"filteredOptions.length === 0\" class=\"px-3 py-2 text-center text-sm italic text-gray-500\">\n No options found for \"{{ searchQuery }}\"\n </p>\n </div>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\nimport { filesApi } from '../api/files'\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string\n placeholder?: string\n accept?: string\n disabled?: boolean\n id?: string\n maxSize?: number\n allowedTypes?: string[]\n uploadToServer?: boolean\n showRequirements?: boolean\n uploadContext?: string\n afterUpload?: (path: string) => void\n /** Upload URL (default: filesApi.upload()) */\n uploadUrl?: string\n /**\n * Base URL for “View document” (no trailing slash). Use the same host as file uploads when they go\n * through boi-api or a proxy, e.g. `https://glow.test/api/boi-api` → `{base}/api/files/view?path=…`\n * (presign runs on boi-api). If unset, uses `filesApi.view()` (consuming SPA origin / VITE_FILES_API_BASE).\n */\n viewApiBase?: string\n /**\n * S3 storage key for the view link when it must differ from `modelValue` (e.g. model holds EDOC CSV path\n * but the user should open the uploaded PDF).\n */\n viewStoragePath?: string\n /** POST function, e.g. (url, formData, opts) => axios.post(url, formData, opts). Returns Promise<{ data?: { success?, path?, message? } }>. */\n post?: (url: string, body: FormData, options?: { headers?: Record<string, string> }) => Promise<{ data?: unknown }>\n }>(),\n {\n modelValue: '',\n placeholder: 'Choose file',\n accept: '*/*',\n disabled: false,\n maxSize: 10 * 1024 * 1024,\n allowedTypes: () => [\n 'application/pdf',\n 'image/jpeg',\n 'image/jpg',\n 'image/png',\n 'application/msword',\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n 'application/vnd.ms-excel',\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n 'text/plain',\n 'text/csv',\n ],\n uploadToServer: true,\n showRequirements: true,\n }\n)\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string]\n 'validation-error': [message: string]\n 'validation-success': [message: string]\n 'uploaded': [path: string]\n}>()\n\nconst fileInput = ref<HTMLInputElement>()\nconst uploading = ref(false)\nconst fileName = ref('')\nconst errorMessage = ref('')\n\nconst typeMap: Record<string, string> = {\n 'application/pdf': 'PDF',\n 'image/jpeg': 'JPG', 'image/jpg': 'JPG', 'image/png': 'PNG',\n 'application/msword': 'DOC',\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': 'DOCX',\n 'application/vnd.ms-excel': 'XLS',\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': 'XLSX',\n 'text/plain': 'TXT', 'text/csv': 'CSV',\n}\n\nconst extToMime: Record<string, string[]> = {\n pdf: ['application/pdf'],\n jpg: ['image/jpeg', 'image/jpg'], jpeg: ['image/jpeg', 'image/jpg'],\n png: ['image/png'], doc: ['application/msword'],\n docx: ['application/vnd.openxmlformats-officedocument.wordprocessingml.document'],\n xls: ['application/vnd.ms-excel'],\n xlsx: ['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'],\n txt: ['text/plain'], csv: ['text/csv'],\n}\n\nconst allowedFormatsDisplay = computed(() =>\n [...new Set(props.allowedTypes.map((t) => typeMap[t] || t.split('/')[1]?.toUpperCase() || t))].join(', ')\n)\nconst maxSizeMB = computed(() => Math.round(props.maxSize / (1024 * 1024)))\nconst isDisabled = computed(() => props.disabled || uploading.value)\n\nconst viewApiBaseNorm = computed(() => String(props.viewApiBase ?? '').trim().replace(/\\/$/, ''))\n\n/** Path used for `/api/files/view` — prefer explicit upload path over `modelValue`. */\nconst effectiveViewStoragePath = computed(() => {\n const fromProp = String(props.viewStoragePath ?? '').trim()\n if (fromProp) return fromProp\n return String(props.modelValue ?? '').trim()\n})\n\nconst viewFileUrl = computed(() => {\n const raw = effectiveViewStoragePath.value\n if (!raw || !props.uploadToServer) return '#'\n const path = encodeURIComponent(raw)\n const base = viewApiBaseNorm.value\n if (base) return `${base}/api/files/view?path=${path}`\n return filesApi.view(raw)\n})\n\nfunction validate(file: File): boolean {\n errorMessage.value = ''\n if (file.size > props.maxSize) {\n const msg = `File size must be less than ${maxSizeMB.value}MB`\n errorMessage.value = msg\n emit('validation-error', msg)\n return false\n }\n if (props.allowedTypes.length) {\n const ext = file.name.split('.').pop()?.toLowerCase() || ''\n const ok = props.allowedTypes.includes(file.type) || (extToMime[ext] || []).some((m) => props.allowedTypes.includes(m))\n if (!ok) {\n const msg = `Only ${allowedFormatsDisplay.value} files are allowed`\n errorMessage.value = msg\n emit('validation-error', msg)\n return false\n }\n }\n return true\n}\n\nasync function handleChange(e: Event) {\n errorMessage.value = ''\n const target = e.target as HTMLInputElement\n const file = target.files?.[0]\n if (!file) {\n fileName.value = ''\n emit('update:modelValue', '')\n return\n }\n if (!validate(file)) {\n target.value = ''\n fileName.value = ''\n emit('update:modelValue', '')\n return\n }\n if (props.uploadToServer && props.post) {\n uploading.value = true\n const url = props.uploadUrl ?? filesApi.upload()\n const formData = new FormData()\n formData.append('file', file)\n formData.append('folder', 'documents')\n if (props.uploadContext) formData.append('context', props.uploadContext)\n try {\n const res = await props.post(url, formData, { headers: { 'Content-Type': 'multipart/form-data' } })\n const data = res?.data as { success?: boolean; path?: string; url?: string; message?: string } | undefined\n if (data?.success && data?.path) {\n fileName.value = file.name\n if (data.url) {\n console.log('[FileInput] S3 URL:', data.url)\n }\n emit('update:modelValue', data.path)\n emit('validation-success', 'File uploaded successfully')\n emit('uploaded', data.path)\n props.afterUpload?.(data.path)\n } else {\n const msg = data?.message ?? 'Upload failed'\n errorMessage.value = msg\n emit('validation-error', msg)\n target.value = ''\n fileName.value = ''\n emit('update:modelValue', '')\n }\n } catch (err: unknown) {\n const msg = (err as { response?: { data?: { message?: string } }; message?: string })?.response?.data?.message ?? (err as Error)?.message ?? 'Upload failed'\n errorMessage.value = msg\n emit('validation-error', msg)\n target.value = ''\n fileName.value = ''\n emit('update:modelValue', '')\n } finally {\n uploading.value = false\n }\n } else {\n fileName.value = file.name\n emit('update:modelValue', file.name)\n emit('uploaded', file.name)\n }\n}\n\nfunction openDialog() {\n if (!isDisabled.value && fileInput.value) fileInput.value.click()\n}\n\nwatch(() => props.modelValue, (v) => {\n fileName.value = (typeof v === 'string' && v ? v.split('/').pop() : '') || ''\n}, { immediate: true })\n</script>\n\n<template>\n <div class=\"boi-file-input w-full space-y-2\">\n <input\n ref=\"fileInput\"\n type=\"file\"\n :accept=\"accept\"\n :disabled=\"isDisabled\"\n :id=\"id\"\n class=\"hidden\"\n @change=\"handleChange\"\n />\n <div\n :class=\"[\n 'flex w-full items-center justify-between rounded-md border border-gray-300 bg-white px-3 py-2 transition-colors',\n isDisabled ? 'cursor-not-allowed opacity-50' : 'cursor-pointer hover:bg-gray-50',\n errorMessage ? 'border-red-500' : '',\n ]\"\n @click=\"openDialog\"\n >\n <span class=\"truncate text-sm text-gray-600\">{{ uploading ? 'Uploading...' : fileName || placeholder }}</span>\n <span class=\"text-gray-400\">📎</span>\n </div>\n <p v-if=\"errorMessage\" class=\"text-sm text-red-600\">{{ errorMessage }}</p>\n <p v-if=\"showRequirements\" class=\"text-xs text-gray-500\">Max {{ maxSizeMB }} MB. Allowed: {{ allowedFormatsDisplay }}.</p>\n <a\n v-if=\"effectiveViewStoragePath && !uploading && uploadToServer\"\n :href=\"viewFileUrl\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"text-sm text-blue-600 hover:underline\"\n >\n View document >>>\n </a>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref, watch, onMounted, onUnmounted } from 'vue'\nimport type { BankStatementRecord, BankOption, IndustrialSectorOption } from '../types/edoc'\nimport { useEdocBanks } from '../composables/useEdocBanks'\nimport { useAccountVerification } from '../composables/useAccountVerification'\nimport { bankStatementsApi } from '../api/bankStatements'\nimport { edocApi } from '../api/edoc'\nimport { filesApi } from '../api/files'\nimport Button from './Button.vue'\nimport BankSelect from './BankSelect.vue'\nimport EmtsIntegration from './EmtsIntegration.vue'\nimport FileInput from './FileInput.vue'\nimport type { VerifyBankAccountFn } from '../composables/useAccountVerification'\n\nconst props = withDefaults(\n defineProps<{\n applicationId?: string\n api: {\n get: (url: string) => Promise<{ data?: unknown }>\n post: (url: string, data?: unknown, config?: unknown) => Promise<{ data?: unknown }>\n put: (url: string, data?: unknown) => Promise<{ data?: unknown }>\n delete: (url: string) => Promise<{ data?: unknown }>\n }\n bankOptions: BankOption[]\n formData: { email?: string; industrial_sector_id?: string | number }\n industrialSectorOptions?: IndustrialSectorOption[]\n /** Legacy: only prefixes bank-statement CRUD paths. Prefer integrationBaseUrl. */\n baseUrl?: string\n /** When set (e.g. deployed boi-api origin), prefixes bank statements, EDOC, and file upload URLs. */\n integrationBaseUrl?: string\n isFormDisabled?: boolean\n maxAccounts?: number\n /** When provided, account name is resolved from account number + bank (e.g. GET /api/verify-bank?account_number=&bank_code=) */\n verifyBankAccount?: VerifyBankAccountFn | null\n /** Call when user focuses into this form so parent can block auto-save */\n blockAutoSave?: () => void\n /** Call when user focuses out so parent can unblock auto-save */\n unblockAutoSave?: () => void\n /** When false, do not poll for EDOC status (stops repeated GET list calls). Set false when upload-to-edoc is disabled. */\n pollEdocStatus?: boolean\n }>(),\n {\n baseUrl: '',\n integrationBaseUrl: '',\n isFormDisabled: false,\n maxAccounts: 5,\n verifyBankAccount: null,\n pollEdocStatus: true,\n }\n)\n\nconst emit = defineEmits<{\n 'error': [message: string]\n}>()\n\nfunction withIntegrationOrigin(path: string): string {\n const b = (props.integrationBaseUrl ?? '').replace(/\\/$/, '')\n if (!b) return path\n const p = path.startsWith('/') ? path : `/${path}`\n return `${b}${p}`\n}\n\nconst { edocBanks, loadBanksForStatement } = useEdocBanks({\n get: props.api.get,\n getBanksUrl: () => withIntegrationOrigin(edocApi.getBanks()),\n})\n\nconst {\n handleAccountVerification,\n retryVerification,\n getVerificationState,\n} = useAccountVerification(() => props.verifyBankAccount)\n\nconst activeIndex = ref(0)\nconst errorMessage = ref('')\nconst showEdocBanksList = ref(false)\nconst rootRef = ref<HTMLFieldSetElement | null>(null)\n\nfunction onFocusIn() {\n props.blockAutoSave?.()\n}\n\nfunction onFocusOut() {\n setTimeout(() => {\n const el = rootRef.value\n if (el && !el.contains(document.activeElement)) {\n props.unblockAutoSave?.()\n }\n }, 0)\n}\nconst bankStatements = ref<BankStatementRecord[]>([])\nconst loadingStatements = ref(false)\nlet pollTimer: ReturnType<typeof setInterval> | null = null\n\nconst statementsUrlPrefix = computed(\n () => props.integrationBaseUrl?.replace(/\\/$/, '') || props.baseUrl?.replace(/\\/$/, '') || ''\n)\n\nconst urls = computed(() =>\n props.applicationId ? bankStatementsApi.urls(props.applicationId, statementsUrlPrefix.value) : null\n)\n\nconst fileUploadUrl = computed(() =>\n props.integrationBaseUrl ? withIntegrationOrigin(filesApi.upload()) : undefined\n)\n\n/** Same base as uploads (boi-api or `/api/boi-api` proxy) so `/api/files/view` presigns there. */\nconst fileViewApiBase = computed(() => (props.integrationBaseUrl ?? '').trim().replace(/\\/$/, ''))\n\nconst limitedStatements = computed(() =>\n bankStatements.value.slice(0, props.maxAccounts)\n)\n\nconst canAddAccount = computed(() => bankStatements.value.length < props.maxAccounts)\nconst canRemoveAccount = computed(() => bankStatements.value.length > 0)\nconst companyEmail = computed(() => props.formData?.email ?? '')\n\nfunction getIndustrialSectorName(): string | undefined {\n const id = props.formData?.industrial_sector_id\n if (id == null) return undefined\n const opt = props.industrialSectorOptions?.find(\n (s) => s.value === id || s.id === id || s.value === String(id)\n )\n return opt?.label ?? opt?.name\n}\n\n/** EDOC CSV copy on S3 — not the user’s uploaded PDF path. */\nfunction isEdocCsvStorageKey(path: string | undefined | null): boolean {\n if (path == null || path === '') return false\n const p = path.trim().toLowerCase()\n return p.includes('edoc/statements/') && p.endsWith('.csv')\n}\n\nfunction initialUploadedStatementPath(bankStatement: string | undefined | null): string {\n const b = (bankStatement ?? '').trim()\n if (!b || isEdocCsvStorageKey(b)) return ''\n return b\n}\n\n/** Storage key for “View document” (uploaded PDF), even if `bank_statement` later holds the CSV key. */\nfunction statementViewStoragePath(account: BankStatementRecord): string {\n const u = account.uploaded_statement_path?.trim()\n if (u) return u\n const b = account.bank_statement?.trim() ?? ''\n if (b && !isEdocCsvStorageKey(b)) return b\n return ''\n}\n\nfunction onStatementFileUploaded(statement: BankStatementRecord, path: string) {\n statement.uploaded_statement_path = path.trim()\n saveStatement(statement)\n}\n\nfunction getStatementLabel(account: BankStatementRecord, index: number): string {\n const bank = props.bankOptions.find((b) => b.value === account.bank)?.label ?? ''\n const num = account.account_number ?? ''\n if (bank && num) return `${bank} (${num})`\n if (bank) return bank\n if (num) return `Account (${num})`\n return `Account ${index + 1}`\n}\n\nfunction getStatusClass(status: string): string {\n const map: Record<string, string> = {\n pending: 'bg-gray-100 text-gray-800',\n processing: 'bg-amber-100 text-amber-800',\n completed: 'bg-green-100 text-green-800',\n failed: 'bg-red-100 text-red-800',\n }\n return map[status] ?? map.pending\n}\n\nasync function loadBankStatements() {\n if (!urls.value) return\n try {\n loadingStatements.value = true\n const res = await props.api.get(urls.value.index)\n const data = res?.data as { success?: boolean; data?: BankStatementRecord[] }\n if (data?.success && Array.isArray(data.data)) {\n bankStatements.value = data.data.map((s) => ({\n ...s,\n otp: '',\n showOtpInput: false,\n uploaded_statement_path: initialUploadedStatementPath(s.bank_statement),\n }))\n }\n } catch (e) {\n console.error('Failed to load bank statements', e)\n } finally {\n loadingStatements.value = false\n }\n}\n\nasync function syncStatementsFromPoll() {\n if (!urls.value) return\n try {\n const res = await props.api.get(urls.value.index)\n const data = res?.data as { success?: boolean; data?: BankStatementRecord[] }\n if (!data?.success || !Array.isArray(data.data)) return\n const fields = ['edoc_status', 'consent_id', 'csv_url', 'statement_generated'] as const\n bankStatements.value = bankStatements.value.map((existing) => {\n const apiRow = data.data!.find((s) => s.id === existing.id)\n if (!apiRow) return existing\n const updates: Partial<BankStatementRecord> = {}\n for (const key of fields) {\n if (key in apiRow) (updates as Record<string, unknown>)[key] = apiRow[key]\n }\n let uploadedPath = existing.uploaded_statement_path ?? ''\n if ('bank_statement' in apiRow && apiRow.bank_statement !== undefined) {\n const incoming = String(apiRow.bank_statement ?? '')\n ;(updates as Record<string, unknown>).bank_statement = apiRow.bank_statement\n if (incoming && !isEdocCsvStorageKey(incoming)) {\n uploadedPath = incoming\n } else if (incoming && isEdocCsvStorageKey(incoming) && uploadedPath) {\n // keep uploaded PDF path for View document\n } else if (!incoming) {\n uploadedPath = ''\n }\n }\n updates.uploaded_statement_path = uploadedPath\n return { ...existing, ...updates }\n })\n } catch (e) {\n console.error('Sync statements failed', e)\n }\n}\n\nfunction startPolling() {\n stopPolling()\n pollTimer = setInterval(() => {\n const hasProcessing = bankStatements.value.some((s) => s.edoc_status === 'processing')\n if (!hasProcessing) {\n stopPolling()\n return\n }\n syncStatementsFromPoll()\n }, 5000)\n}\n\nfunction stopPolling() {\n if (pollTimer) {\n clearInterval(pollTimer)\n pollTimer = null\n }\n}\n\nwatch(\n () => bankStatements.value.some((s) => s.edoc_status === 'processing'),\n (hasProcessing) => {\n if (!props.pollEdocStatus) {\n stopPolling()\n return\n }\n if (hasProcessing) startPolling()\n else stopPolling()\n }\n)\n\nasync function saveStatement(statement: BankStatementRecord) {\n if (!urls.value || statement.id < 0) return\n try {\n await props.api.put(urls.value.update(statement.id), {\n bank: statement.bank,\n account_number: statement.account_number,\n account_name: statement.account_name,\n account_type: statement.account_type,\n bvn: statement.bvn,\n email: statement.email,\n bank_statement: statement.bank_statement,\n })\n } catch (e) {\n console.error('Failed to save bank statement', e)\n }\n}\n\nasync function handleAddAccount() {\n if (!urls.value || !canAddAccount.value) return\n const tempId = -Date.now()\n const newRecord: BankStatementRecord = {\n id: tempId,\n loan_application_id: Number(props.applicationId),\n bank: '',\n account_number: '',\n account_name: '',\n account_type: '',\n bvn: '',\n email: companyEmail.value,\n bank_statement: '',\n csv_url: '',\n consent_id: '',\n edoc_status: 'pending',\n statement_generated: false,\n otp: '',\n showOtpInput: false,\n uploaded_statement_path: '',\n }\n bankStatements.value.push(newRecord)\n activeIndex.value = bankStatements.value.length - 1\n\n try {\n const res = await props.api.post(urls.value.store, { email: companyEmail.value })\n const data = res?.data as { success?: boolean; data?: BankStatementRecord }\n if (data?.success && data.data) {\n const idx = bankStatements.value.findIndex((s) => s.id === tempId)\n if (idx !== -1) {\n bankStatements.value[idx] = {\n ...data.data,\n otp: '',\n showOtpInput: false,\n uploaded_statement_path: initialUploadedStatementPath(data.data.bank_statement),\n }\n }\n } else {\n bankStatements.value = bankStatements.value.filter((s) => s.id !== tempId)\n activeIndex.value = Math.max(0, bankStatements.value.length - 1)\n }\n } catch (e) {\n bankStatements.value = bankStatements.value.filter((s) => s.id !== tempId)\n activeIndex.value = Math.max(0, bankStatements.value.length - 1)\n emit('error', (e as Error)?.message ?? 'Failed to add account')\n }\n}\n\nasync function handleRemoveAccount(statement: BankStatementRecord) {\n if (!urls.value) return\n const removedIndex = bankStatements.value.findIndex((s) => s.id === statement.id)\n const removed = { ...statement }\n const isOptimistic = statement.id < 0\n bankStatements.value = bankStatements.value.filter((s) => s.id !== statement.id)\n activeIndex.value = Math.min(activeIndex.value, Math.max(0, bankStatements.value.length - 1))\n\n if (isOptimistic) return\n try {\n await props.api.delete(urls.value.destroy(statement.id))\n } catch (e) {\n bankStatements.value = bankStatements.value\n .slice(0, removedIndex)\n .concat(removed, bankStatements.value.slice(removedIndex))\n emit('error', (e as Error)?.message ?? 'Failed to remove account')\n }\n}\n\nfunction onConsentId(statement: BankStatementRecord, consentId: string) {\n statement.consent_id = consentId\n statement.showOtpInput = true\n saveStatement(statement)\n}\n\nfunction onStatementRetrieved(statement: BankStatementRecord, updated: BankStatementRecord) {\n Object.assign(statement, updated)\n saveStatement(statement)\n}\n\nfunction onEdocError(msg: string) {\n errorMessage.value = msg\n emit('error', msg)\n}\n\nfunction clearError() {\n errorMessage.value = ''\n}\n\nfunction createAfterUpload(statement: BankStatementRecord) {\n return (filePath: string) => {\n if (!urls.value) return\n props.blockAutoSave?.()\n statement.edoc_status = 'processing'\n const sector = getIndustrialSectorName()\n const unblockAfterDelay = () => {\n setTimeout(() => props.unblockAutoSave?.(), 3000)\n }\n props.api\n .post(urls.value.uploadToEdoc(statement.id), { filePath, industrialSector: sector })\n .then((res) => {\n const data = (res?.data as { data?: BankStatementRecord })?.data\n if (data) {\n const preservedPdfPath = statement.uploaded_statement_path ?? ''\n Object.assign(statement, data)\n if (\n preservedPdfPath &&\n data.bank_statement &&\n isEdocCsvStorageKey(String(data.bank_statement))\n ) {\n statement.uploaded_statement_path = preservedPdfPath\n }\n }\n startPolling()\n })\n .catch(() => {\n statement.edoc_status = 'failed'\n })\n .finally(unblockAfterDelay)\n }\n}\n\nconst isBankEdocSupported = (bankCode: string): boolean => {\n if (!bankCode || !edocBanks.value.length) return false\n const bank = props.bankOptions.find((o) => o.value === bankCode)\n const names = [bank?.label ?? '', ...(bank?.searchKeywords ?? [])].filter(Boolean)\n return edocBanks.value.some((b) => {\n const codeMatch = b.bankCode === bankCode || b.code === bankCode\n const nameMatch = names.some((n) => b.name?.toLowerCase().includes(n.toLowerCase()))\n return (codeMatch || nameMatch) && b.enabled !== false\n })\n}\n\nconst enabledEdocBanksList = computed(() =>\n (edocBanks.value || [])\n .filter((b) => b.enabled !== false)\n .map((b) => b.name || b.bankCode || 'Unknown')\n .sort((a, b) => a.localeCompare(b))\n)\n\nonMounted(async () => {\n loadBanksForStatement()\n if (props.applicationId) {\n await loadBankStatements()\n }\n})\n\nonUnmounted(() => {\n stopPolling()\n})\n</script>\n\n<template>\n <fieldset\n ref=\"rootRef\"\n :disabled=\"isFormDisabled\"\n class=\"boi-bank-statement-integration rounded-xl border border-gray-200 bg-white shadow-sm\"\n @focusin=\"onFocusIn\"\n @focusout=\"onFocusOut\"\n >\n <div class=\"border-b border-gray-100 px-4 py-3 md:px-6 md:py-4\">\n <h2 class=\"text-lg font-bold text-slate-900\">Company Bank Statements</h2>\n </div>\n\n <div class=\"px-4 pb-4 md:px-6 md:pb-6\">\n <!-- Info: Electronic statement retrieval -->\n <div class=\"mb-6 rounded-lg border border-blue-200 bg-blue-50 p-4 text-sm\">\n <p class=\"text-blue-900\">\n Some banks support <strong>Electronic Bank Statement Retrieval</strong>, so you may not need to upload a PDF.\n <button\n type=\"button\"\n @click=\"showEdocBanksList = !showEdocBanksList\"\n class=\"ml-1 font-semibold text-blue-700 underline hover:text-blue-800 focus:outline-none focus:ring-2 focus:ring-blue-300 rounded\"\n >\n {{ showEdocBanksList ? 'Hide' : 'See' }}\n </button>\n {{ showEdocBanksList ? '' : ' supported banks.' }}\n </p>\n <div v-if=\"showEdocBanksList && enabledEdocBanksList.length\" class=\"mt-3 rounded-md bg-white/80 border border-blue-100 p-3\">\n <p class=\"mb-2 text-xs font-semibold text-blue-900\">Banks that support electronic statement retrieval:</p>\n <ul class=\"list-inside list-disc space-y-0.5 text-xs text-blue-800 columns-2 gap-x-4\">\n <li v-for=\"(name, idx) in enabledEdocBanksList\" :key=\"idx\">{{ name }}</li>\n </ul>\n </div>\n <p v-else-if=\"showEdocBanksList && !enabledEdocBanksList.length\" class=\"mt-2 text-xs text-blue-700\">\n Loading supported banks…\n </p>\n </div>\n\n <!-- Loading state -->\n <div v-if=\"loadingStatements\" class=\"flex items-center justify-center py-10\">\n <span class=\"inline-block h-5 w-5 animate-spin rounded-full border-2 border-slate-300 border-t-slate-600 mr-2\" aria-hidden=\"true\" />\n <span class=\"text-sm text-slate-600\">Loading bank statements…</span>\n </div>\n\n <template v-else>\n <!-- Account tabs -->\n <div v-if=\"limitedStatements.length\" class=\"flex overflow-x-auto pb-2 gap-1 -mx-1\">\n <button\n v-for=\"(account, index) in limitedStatements\"\n :key=\"account.id\"\n type=\"button\"\n class=\"shrink-0 rounded-lg px-4 py-2 text-sm font-medium whitespace-nowrap transition-colors\"\n :class=\"activeIndex === index ? 'bg-primary text-white shadow-sm' : 'bg-slate-100 text-slate-700 hover:bg-slate-200'\"\n @click=\"activeIndex = index\"\n >\n {{ getStatementLabel(account, index) }}\n </button>\n </div>\n\n <!-- Active account card -->\n <div\n v-for=\"(account, index) in limitedStatements\"\n :key=\"account.id\"\n v-show=\"activeIndex === index\"\n class=\"mt-6 space-y-6 rounded-xl border border-gray-100 bg-gray-50/50 p-4 md:p-6\"\n >\n <div class=\"flex items-center justify-between gap-4\">\n <h4 class=\"border-b-2 border-primary pb-1 text-base font-semibold text-slate-900\">{{ getStatementLabel(account, index) }}</h4>\n <button\n type=\"button\"\n class=\"inline-flex items-center rounded-lg px-3 py-2 text-sm font-medium text-red-600 hover:bg-red-50 disabled:opacity-50 transition-colors\"\n :disabled=\"!canRemoveAccount || isFormDisabled\"\n @click=\"handleRemoveAccount(account)\"\n >\n <svg class=\"w-4 h-4 mr-1.5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16\" /></svg>\n Remove account\n </button>\n </div>\n\n <!-- Bank / account fields -->\n <slot name=\"account-fields\" :account=\"account\" :bank-options=\"bankOptions\" :verification-state=\"getVerificationState(account)\" :on-verify=\"() => handleAccountVerification(account)\" :on-retry=\"() => retryVerification(account)\">\n <div class=\"grid grid-cols-1 gap-4 md:grid-cols-3\">\n <div>\n <label class=\"mb-1.5 block text-sm font-medium text-gray-700\">Bank</label>\n <BankSelect\n :model-value=\"account.bank\"\n :options=\"bankOptions\"\n placeholder=\"Select bank\"\n :disabled=\"!!isFormDisabled\"\n @update:model-value=\"(v) => { account.bank = v; handleAccountVerification(account); saveStatement(account); }\"\n />\n </div>\n <div>\n <label class=\"mb-1.5 block text-sm font-medium text-gray-700\">Account number</label>\n <input\n v-model=\"account.account_number\"\n type=\"text\"\n maxlength=\"10\"\n inputmode=\"numeric\"\n class=\"w-full rounded-lg border border-gray-300 bg-white px-3 py-2.5 text-sm focus:border-primary focus:ring-1 focus:ring-primary\"\n placeholder=\"10 digits\"\n @blur=\"handleAccountVerification(account); saveStatement(account)\"\n />\n </div>\n <div>\n <label class=\"mb-1.5 block text-sm font-medium text-gray-700\">Account name</label>\n <input\n :value=\"account.account_name\"\n type=\"text\"\n readonly\n class=\"w-full cursor-default rounded-lg border border-gray-200 bg-gray-50 px-3 py-2.5 text-sm text-gray-700\"\n placeholder=\"Enter bank and account number to verify\"\n />\n <div v-if=\"verifyBankAccount\" class=\"mt-1.5 flex flex-wrap items-center gap-2 text-xs\">\n <span v-if=\"getVerificationState(account).isLoading\" class=\"text-blue-600\">Verifying…</span>\n <span v-else-if=\"getVerificationState(account).isSuccess\" class=\"text-green-600\">Account verified</span>\n <span v-else-if=\"getVerificationState(account).isError\" class=\"flex items-center gap-1\">\n <span class=\"text-red-600\">{{ getVerificationState(account).errorMessage }}</span>\n <button type=\"button\" class=\"rounded px-2 py-0.5 text-gray-600 hover:bg-gray-100\" @click=\"retryVerification(account)\">Retry</button>\n </span>\n </div>\n </div>\n </div>\n </slot>\n\n <div v-if=\"isBankEdocSupported(account.bank)\" class=\"boi-emts-wrapper\">\n <EmtsIntegration\n :account=\"account\"\n :edoc-banks=\"edocBanks\"\n :bank-options=\"bankOptions\"\n :api=\"{ get: api.get, post: api.post }\"\n :company-email=\"companyEmail\"\n :industrial-sector=\"getIndustrialSectorName()\"\n :application-id=\"applicationId\"\n :integration-base-url=\"integrationBaseUrl\"\n :disabled=\"isFormDisabled\"\n @update:consent-id=\"onConsentId(account, $event)\"\n @statement-retrieved=\"onStatementRetrieved(account, $event)\"\n @error=\"onEdocError\"\n />\n <p\n v-if=\"account.statement_generated || account.edoc_status === 'completed'\"\n class=\"mt-3 text-sm font-medium text-green-800\"\n >\n Succeeded.\n </p>\n </div>\n\n <div v-if=\"!isBankEdocSupported(account.bank)\" class=\"rounded-lg border border-gray-200 bg-white p-4\">\n <p class=\"mb-3 text-sm font-medium text-gray-700\">Upload bank statement (PDF)</p>\n <slot name=\"file-upload\" :account=\"account\" :after-upload=\"createAfterUpload(account)\">\n <FileInput\n v-model=\"account.bank_statement\"\n :view-storage-path=\"statementViewStoragePath(account)\"\n :post=\"(url, body, opts) => api.post(url, body, opts)\"\n :upload-url=\"fileUploadUrl\"\n :view-api-base=\"fileViewApiBase || undefined\"\n placeholder=\"Choose 12 months bank statement (PDF)\"\n accept=\".pdf\"\n :max-size=\"20 * 1024 * 1024\"\n :allowed-types=\"['application/pdf']\"\n upload-context=\"bank_statement\"\n :after-upload=\"createAfterUpload(account)\"\n :disabled=\"isFormDisabled\"\n @uploaded=\"(path) => onStatementFileUploaded(account, String(path))\"\n />\n <!-- Status -->\n <div class=\"rounded-lg py-3\">\n <div class=\"flex items-center gap-2\">\n <span class=\"text-sm font-medium text-gray-600\">Bank statement status:</span>\n <span\n :class=\"[getStatusClass(account.edoc_status || 'pending'), 'inline-flex items-center gap-1.5 rounded-full px-3 py-1 text-xs font-medium capitalize']\"\n >\n <span\n v-if=\"account.edoc_status === 'processing'\"\n class=\"inline-block h-3.5 w-3.5 animate-spin rounded-full border-2 border-current border-t-transparent\"\n aria-hidden=\"true\"\n />\n {{ account.edoc_status || 'pending' }}\n </span>\n </div>\n <p v-if=\"account.edoc_status === 'processing'\" class=\"mt-1.5 text-sm text-amber-700\">\n Processing in progress. Please wait…\n </p>\n <p v-if=\"account.edoc_status === 'failed'\" class=\"mt-1.5 text-sm text-red-600\">\n Processing failed. Please re-upload a valid bank statement or try another method.\n </p>\n </div>\n </slot>\n </div>\n\n \n\n <div v-if=\"errorMessage\" class=\"rounded-lg border border-red-200 bg-red-50 p-4 flex items-start gap-3\">\n <p class=\"flex-1 text-sm text-red-800\">{{ errorMessage }}</p>\n <button type=\"button\" class=\"shrink-0 rounded p-1 text-red-600 hover:bg-red-100\" @click=\"clearError\" aria-label=\"Dismiss\">×</button>\n </div>\n </div>\n\n <div class=\"flex justify-center\">\n <Button\n type=\"button\"\n variant=\"default\"\n size=\"lg\"\n :disabled=\"!canAddAccount || isFormDisabled || !applicationId\"\n @click=\"handleAddAccount\"\n >\n <svg class=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M12 4v16m8-8H4\" />\n </svg>\n Add account\n </Button>\n </div>\n </template>\n </div>\n </fieldset>\n</template>\n","import type { App } from 'vue'\nimport './styles/theme.css'\n\nexport { default as BoiButton } from './components/BoiButton.vue'\nexport { default as Button } from './components/Button.vue'\nexport { default as EmtsIntegration } from './components/EmtsIntegration.vue'\nexport { default as BankStatementIntegration } from './components/BankStatementIntegration.vue'\nexport { default as BankSelect } from './components/BankSelect.vue'\nexport { default as FileInput } from './components/FileInput.vue'\n\nexport { useEdocBanks } from './composables/useEdocBanks'\nexport type { UseEdocBanksOptions } from './composables/useEdocBanks'\nexport { useAccountVerification } from './composables/useAccountVerification'\nexport type { VerifyBankAccountFn, VerificationState } from './composables/useAccountVerification'\n\nexport { edocApi } from './api/edoc'\nexport type { EdocApi } from './api/edoc'\nexport { bankStatementsApi, bankStatementsUrls } from './api/bankStatements'\nexport { filesApi } from './api/files'\n\nexport type {\n EdocBank,\n BankStatementRecord,\n EdocConsentInitializePayload,\n EdocAttachAccountPayload,\n EdocGetTransactionsPayload,\n BankOption,\n IndustrialSectorOption,\n} from './types/edoc'\n\nexport function install(_app: App): void {\n // Components can be registered here for app.use() when consuming this package\n}\n\nexport default {\n install,\n}\n"],"names":["_createElementBlock","_normalizeClass","__props","_renderSlot","_ctx","cn","classes","baseClasses","variantClasses","sizeClasses","buttonVariants","options","variant","size","props","_unref","edocApi","otpActionClass","edocPath","path","b","p","emit","__emit","generatingStatement","ref","submittingOtp","bankNames","bankCode","o","matchBank","enabledOnly","names","code","name","n","_a","getEdocBank","isBankEdocSupported","hasBankInstructions","computed","_b","canRequestOtp","a","canSubmitOtp","errMsg","e","_c","consentPayload","email","consentAndAttach","edocBank","res","data","consentId","generateStatement","err","submitOtp","retrieveStatementDirect","_openBlock","_hoisted_1","_hoisted_2","_Fragment","_createElementVNode","_hoisted_3","_cache","_hoisted_4","_renderList","instruction","idx","_createVNode","BoiButton","_hoisted_6","_hoisted_7","_hoisted_8","$event","_vModelText","_hoisted_9","_hoisted_5","_hoisted_10","_hoisted_11","toBanksList","d","raw","resolveUrl","u","fallback","useEdocBanks","get","getBanksUrl","fallbackBanksUrl","edocBanksCache","banksCache","loadingBanks","errorBanks","banksPromise","list","fallbackUrl","verificationStates","useAccountVerification","verifyBankAccount","getVerifyFn","getVerificationKey","account","getVerificationState","key","clearAccountName","handleAccountVerification","accountNumber","fn","result","defaultPrefix","bankStatementsUrls","applicationId","baseUrl","prefix","id","statementId","bankStatementsApi","base","filesApi","isOpen","selectRef","searchRef","searchQuery","highlightedIndex","optionMatchesQuery","opt","q","parts","s","tokens","t","filteredOptions","selectedOption","displayValue","toggle","nextTick","select","onKeydown","opts","onClickOutside","watch","onMounted","onUnmounted","_toDisplayString","option","index","fileInput","uploading","fileName","errorMessage","typeMap","extToMime","allowedFormatsDisplay","maxSizeMB","isDisabled","viewApiBaseNorm","effectiveViewStoragePath","fromProp","viewFileUrl","validate","file","msg","ext","m","handleChange","target","url","formData","_d","openDialog","v","withIntegrationOrigin","edocBanks","loadBanksForStatement","retryVerification","activeIndex","showEdocBanksList","rootRef","onFocusIn","onFocusOut","el","bankStatements","loadingStatements","pollTimer","statementsUrlPrefix","urls","fileUploadUrl","fileViewApiBase","limitedStatements","canAddAccount","canRemoveAccount","companyEmail","getIndustrialSectorName","isEdocCsvStorageKey","initialUploadedStatementPath","bankStatement","statementViewStoragePath","onStatementFileUploaded","statement","saveStatement","getStatementLabel","bank","num","getStatusClass","status","map","loadBankStatements","syncStatementsFromPoll","fields","existing","apiRow","updates","uploadedPath","incoming","startPolling","stopPolling","hasProcessing","handleAddAccount","tempId","newRecord","handleRemoveAccount","removedIndex","removed","isOptimistic","onConsentId","onStatementRetrieved","updated","onEdocError","clearError","createAfterUpload","filePath","sector","unblockAfterDelay","preservedPdfPath","codeMatch","nameMatch","enabledEdocBanksList","_createTextVNode","_hoisted_12","_hoisted_14","BankSelect","_hoisted_17","_hoisted_18","_hoisted_19","_hoisted_20","_hoisted_21","_hoisted_22","_hoisted_23","EmtsIntegration","_hoisted_24","_hoisted_25","FileInput","body","_hoisted_26","_hoisted_27","_hoisted_28","_hoisted_29","_hoisted_30","_hoisted_31","_hoisted_32","_vShow","_hoisted_33","Button","install","_app"],"mappings":"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"}
1
+ {"version":3,"file":"boi-ui.umd.cjs","sources":["../src/components/BoiButton.vue","../src/lib/utils.ts","../src/components/ui/button/index.ts","../src/components/Button.vue","../src/api/edoc.ts","../src/components/EmtsIntegration.vue","../src/composables/useEdocBanks.ts","../src/composables/useAccountVerification.ts","../src/api/bankStatements.ts","../src/api/files.ts","../src/components/BankSelect.vue","../src/components/FileInput.vue","../src/components/BankStatementIntegration.vue","../src/index.ts"],"sourcesContent":["<script setup lang=\"ts\">\ndefineProps<{\n label?: string\n variant?: 'primary' | 'secondary'\n}>()\n</script>\n\n<template>\n <button\n type=\"button\"\n class=\"boi-button\"\n :class=\"[variant ? `boi-button--${variant}` : 'boi-button--primary']\"\n >\n <slot>{{ label }}</slot>\n </button>\n</template>\n\n<style scoped>\n.boi-button {\n padding: 0.5rem 1rem;\n border-radius: 0.375rem;\n font-weight: 500;\n cursor: pointer;\n border: none;\n}\n.boi-button--primary {\n background: #2563eb;\n color: white;\n}\n.boi-button--primary:hover {\n background: #1d4ed8;\n}\n.boi-button--secondary {\n background: #e5e7eb;\n color: #374151;\n}\n.boi-button--secondary:hover {\n background: #d1d5db;\n}\n</style>\n","export function cn(...classes: Array<any>) {\n return classes.flat(Infinity).filter(Boolean).join(' ')\n}\n","export { default as Button } from './Button.vue'\n\nexport type ButtonVariants = {\n variant?: 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link'\n size?: 'default' | 'sm' | 'lg' | 'icon'\n}\n\nconst baseClasses =\n \"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive\"\n\nconst variantClasses: Record<NonNullable<ButtonVariants['variant']>, string> = {\n default: 'bg-primary text-white shadow-xs hover:bg-primary/90',\n destructive:\n 'bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60',\n outline:\n 'border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50',\n secondary: 'bg-secondary text-white shadow-xs hover:bg-secondary/80',\n ghost: 'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50',\n link: 'text-primary underline-offset-4 hover:underline',\n}\n\nconst sizeClasses: Record<NonNullable<ButtonVariants['size']>, string> = {\n default: 'h-9 px-4 py-2 has-[>svg]:px-3',\n sm: 'h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5',\n lg: 'h-10 rounded-md px-6 has-[>svg]:px-4',\n icon: 'size-9',\n}\n\nexport function buttonVariants(options: ButtonVariants = {}) {\n const variant = options.variant ?? 'default'\n const size = options.size ?? 'default'\n return [baseClasses, variantClasses[variant], sizeClasses[size]].join(' ')\n}\n","<script setup lang=\"ts\">\nimport type { HTMLAttributes } from 'vue'\nimport { cn } from '../lib/utils'\nimport { type ButtonVariants, buttonVariants } from './ui/button/index'\n\ninterface Props {\n type?: 'button' | 'submit' | 'reset'\n variant?: ButtonVariants['variant']\n size?: ButtonVariants['size']\n class?: HTMLAttributes['class']\n disabled?: boolean\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n type: 'button',\n variant: 'default',\n size: 'default',\n disabled: false,\n})\n</script>\n\n<template>\n <button\n :type=\"type\"\n :disabled=\"disabled\"\n data-slot=\"button\"\n :class=\"cn(\n buttonVariants({ variant: props.variant, size: props.size }),\n props.class\n )\"\n >\n <slot />\n </button>\n</template>\n","/**\n * EDOC API endpoint paths. Host app builds full URLs (e.g. baseURL + path).\n */\nexport const edocApi = {\n getBanks: () => '/api/edoc/banks',\n initializeConsent: () => '/api/edoc/consent/initialize',\n attachAccount: () => '/api/edoc/consent/attach-account',\n getTransactions: () => '/api/edoc/consent/transactions',\n manualUpload: () => '/api/edoc/manual-upload',\n} as const\n\nexport type EdocApi = typeof edocApi\n","<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport type { BankStatementRecord, EdocBank, BankOption } from '../types/edoc'\nimport { edocApi } from '../api/edoc'\nimport BoiButton from './BoiButton.vue'\n\n/** Shared classes: compact black actions for OTP flow */\nconst otpActionClass =\n 'inline-flex items-center justify-center rounded-md bg-black px-3 py-1.5 text-xs font-medium text-white shadow-sm hover:bg-neutral-900 focus:outline-none focus:ring-2 focus:ring-black focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50'\n\nconst props = withDefaults(\n defineProps<{\n account: BankStatementRecord\n edocBanks: EdocBank[]\n bankOptions: BankOption[]\n api: { post: (url: string, data: unknown) => Promise<{ data?: unknown }>; get?: (url: string) => Promise<{ data?: unknown }> }\n companyEmail?: string\n industrialSector?: string\n applicationId?: string | number\n disabled?: boolean\n /** Prefix for EDOC API paths when using a standalone service (e.g. boi-api). */\n integrationBaseUrl?: string\n }>(),\n { disabled: false, integrationBaseUrl: '' }\n)\n\nfunction edocPath(path: string): string {\n const b = (props.integrationBaseUrl ?? '').replace(/\\/$/, '')\n if (!b) return path\n const p = path.startsWith('/') ? path : `/${path}`\n return `${b}${p}`\n}\n\nconst emit = defineEmits<{\n 'update:consentId': [consentId: string]\n 'statement-retrieved': [statement: BankStatementRecord]\n 'error': [message: string]\n}>()\n\nconst generatingStatement = ref(false)\nconst submittingOtp = ref(false)\n\nfunction bankNames(bankCode: string): string[] {\n const b = props.bankOptions.find((o) => o.value === bankCode)\n return [b?.label ?? '', ...(b?.searchKeywords ?? [])].filter(Boolean)\n}\n\nfunction matchBank(bankCode: string, enabledOnly = false): EdocBank | undefined {\n if (!bankCode || !props.edocBanks.length) return undefined\n const names = bankNames(bankCode)\n return props.edocBanks.find((b) => {\n const code = b.bankCode === bankCode || b.code === bankCode\n const name = names.some((n) => b.name?.toLowerCase().includes(n.toLowerCase()))\n return (code || name) && (!enabledOnly || b.enabled !== false)\n })\n}\n\nconst getEdocBank = (code: string) => matchBank(code, false)\nconst isBankEdocSupported = (code: string) => !!matchBank(code, true)\nconst hasBankInstructions = computed(() => !!(getEdocBank(props.account.bank)?.bankInstructions?.length))\nconst canRequestOtp = computed(() => {\n const a = props.account\n return !!a.bank && a.account_number?.length === 10 && !generatingStatement.value && !submittingOtp.value\n})\nconst canSubmitOtp = computed(() => !!props.account.otp && !submittingOtp.value)\n\nconst errMsg = (e: unknown) =>\n (e as { response?: { data?: { message?: string } }; data?: { message?: string }; message?: string })?.response?.data?.message ??\n (e as { data?: { message?: string } })?.data?.message ??\n (e as Error)?.message ??\n 'An unexpected error occurred'\n\nconst consentPayload = (email: string) => ({\n email,\n referenceId: `loan_${props.applicationId ?? 'new'}_${props.account.id}`,\n firstName: 'Company',\n lastName: 'Account',\n state: 'Lagos',\n fundType: 'online portal',\n statementDuration: '12',\n redirectionUrl: typeof window !== 'undefined' ? window.location.origin + '/loan-application' : '',\n industrialSector: props.industrialSector ?? undefined,\n})\n\nasync function consentAndAttach(edocBank: EdocBank) {\n const email = props.account.email || props.companyEmail || ''\n const res = await props.api.post(edocPath(edocApi.initializeConsent()), consentPayload(email))\n const data = res?.data as { success?: boolean; data?: { data?: { consentId?: string } }; message?: string }\n if (!data?.success) throw new Error(data?.message ?? 'Failed to initialize consent')\n const consentId = data?.data?.data?.consentId\n if (!consentId) throw new Error('No consent ID returned')\n emit('update:consentId', consentId)\n await props.api.post(edocPath(edocApi.attachAccount()), {\n consentId,\n bankId: edocBank.bankId,\n accountNumber: props.account.account_number,\n accountType: 'Business',\n statementDuration: '12',\n monthType: 'Period',\n uploadType: 'Digital',\n })\n return consentId\n}\n\nasync function generateStatement() {\n const edocBank = getEdocBank(props.account.bank)\n if (!props.account.bank) return emit('error', 'Please select a bank')\n if (props.account.account_number?.length !== 10) return emit('error', 'Please provide a valid 10-digit account number')\n if (!edocBank) return emit('error', 'Selected bank does not support electronic statement retrieval')\n generatingStatement.value = true\n try {\n await consentAndAttach(edocBank)\n } catch (err) {\n emit('error', errMsg(err))\n } finally {\n generatingStatement.value = false\n }\n}\n\nasync function submitOtp() {\n if (!props.account.otp || !props.account.consent_id) return emit('error', 'Please enter OTP')\n submittingOtp.value = true\n try {\n const res = await props.api.post(edocPath(edocApi.getTransactions()), {\n consentId: props.account.consent_id,\n verificationCode: props.account.otp,\n bankStatementId: props.account.id,\n })\n const data = res?.data as { success?: boolean; data?: { statement?: BankStatementRecord }; message?: string }\n if (!data?.success) return emit('error', data?.message ?? 'Failed to retrieve transactions')\n if (data.data?.statement) emit('statement-retrieved', data.data.statement)\n } catch (err) {\n emit('error', errMsg(err))\n } finally {\n submittingOtp.value = false\n }\n}\n\nasync function retrieveStatementDirect() {\n const edocBank = getEdocBank(props.account.bank)\n if (!props.account.bank || props.account.account_number?.length !== 10) {\n return emit('error', 'Please select a bank and provide a valid 10-digit account number')\n }\n if (!edocBank) return emit('error', 'Selected bank does not support electronic statement retrieval')\n submittingOtp.value = true\n try {\n const consentId = await consentAndAttach(edocBank)\n const res = await props.api.post(edocPath(edocApi.getTransactions()), {\n consentId,\n verificationCode: '',\n bankStatementId: props.account.id,\n })\n const data = res?.data as { success?: boolean; data?: { statement?: BankStatementRecord }; message?: string }\n if (!data?.success) return emit('error', data?.message ?? 'Failed to retrieve transactions')\n if (data.data?.statement) emit('statement-retrieved', data.data.statement)\n } catch (err) {\n emit('error', errMsg(err))\n } finally {\n submittingOtp.value = false\n }\n}\n</script>\n\n<template>\n <div class=\"boi-emts-integration space-y-4\">\n <div v-if=\"isBankEdocSupported(account.bank)\">\n <template v-if=\"hasBankInstructions && !account.statement_generated\">\n <div class=\"boi-emts-instructions rounded-lg border border-amber-200 bg-amber-50 p-4 text-sm\">\n <p class=\"mb-2 font-semibold text-amber-900\">Bank-specific instructions</p>\n <ol class=\"list-inside list-decimal space-y-1 text-amber-800\">\n <li v-for=\"(instruction, idx) in getEdocBank(account.bank)?.bankInstructions\" :key=\"idx\">{{ instruction }}</li>\n </ol>\n </div>\n <BoiButton\n :label=\"submittingOtp ? 'Retrieving…' : 'Retrieve statement'\"\n variant=\"primary\"\n :disabled=\"!canRequestOtp || disabled\"\n @click=\"retrieveStatementDirect\"\n />\n </template>\n <template v-else-if=\"!hasBankInstructions && !account.statement_generated\">\n <button\n v-if=\"!account.showOtpInput\"\n type=\"button\"\n :class=\"otpActionClass\"\n :disabled=\"!canRequestOtp || disabled\"\n @click=\"generateStatement\"\n >\n {{ generatingStatement ? 'Sending OTP…' : 'Send OTP' }}\n </button>\n <div v-else class=\"boi-emts-otp space-y-3 rounded-lg border-2 border-primary bg-primary/5 p-4\">\n <p class=\"text-sm font-medium text-gray-700\">Enter the OTP sent to your bank-registered email.</p>\n <div class=\"flex flex-wrap items-end gap-3\">\n <div class=\"min-w-[140px]\">\n <label class=\"mb-1 block text-xs font-medium text-gray-600\">OTP code</label>\n <input v-model=\"account.otp\" type=\"text\" maxlength=\"6\" placeholder=\"6-digit OTP\" class=\"w-full rounded border border-gray-300 px-3 py-2 text-lg tracking-widest\" />\n </div>\n <button\n type=\"button\"\n :class=\"otpActionClass\"\n :disabled=\"!canSubmitOtp || disabled\"\n @click=\"submitOtp\"\n >\n Verify OTP\n </button>\n </div>\n </div>\n </template>\n </div>\n <div v-if=\"account.edoc_status === 'failed'\" class=\"text-sm text-red-600\">Statement retrieval failed. Please try again or upload manually.</div>\n <div v-if=\"account.edoc_status === 'processing'\" class=\"text-sm text-amber-600\">Processing…</div>\n </div>\n</template>\n","import { ref } from 'vue'\nimport type { EdocBank } from '../types/edoc'\nimport { edocApi } from '../api/edoc'\n\nexport interface UseEdocBanksOptions {\n get: (url: string) => Promise<{ data?: unknown }>\n /** Path or absolute URL; or a getter so it stays in sync with props (e.g. integration base URL). */\n getBanksUrl?: string | (() => string)\n fallbackBanksUrl?: string | (() => string)\n}\n\nfunction toBanksList(data: unknown): EdocBank[] {\n if (!data || typeof data !== 'object') return []\n const d = data as Record<string, unknown>\n const raw = (d.success ? d.data : d.data ?? d) as unknown\n if (Array.isArray(raw)) return raw as EdocBank[]\n if (raw && typeof raw === 'object' && Array.isArray((raw as Record<string, unknown>).data)) {\n return (raw as Record<string, EdocBank[]>).data\n }\n return []\n}\n\nfunction resolveUrl(u: string | (() => string) | undefined, fallback: string): string {\n if (u === undefined) return fallback\n return typeof u === 'function' ? u() : u\n}\n\nexport function useEdocBanks(options: UseEdocBanksOptions) {\n const { get, getBanksUrl, fallbackBanksUrl } = options\n const edocBanksCache = ref<EdocBank[]>([])\n const banksCache = ref<EdocBank[]>([])\n const loadingBanks = ref(false)\n const errorBanks = ref<string | null>(null)\n let banksPromise: Promise<EdocBank[]> | null = null\n\n const loadBanksForStatement = async (): Promise<EdocBank[]> => {\n if (edocBanksCache.value.length > 0) return edocBanksCache.value\n if (banksPromise) return banksPromise\n\n loadingBanks.value = true\n errorBanks.value = null\n banksPromise = (async () => {\n try {\n const res = await get(resolveUrl(getBanksUrl, edocApi.getBanks()))\n const list = toBanksList(res?.data)\n if (list.length) {\n edocBanksCache.value = banksCache.value = list\n return list\n }\n } catch {}\n const fallbackUrl =\n fallbackBanksUrl != null ? resolveUrl(fallbackBanksUrl, '') : ''\n if (fallbackUrl) {\n try {\n const fallback = await get(fallbackUrl)\n const list = Array.isArray(fallback?.data) ? (fallback.data as EdocBank[]) : []\n edocBanksCache.value = banksCache.value = list\n return list\n } catch (err: unknown) {\n errorBanks.value = (err as { response?: { data?: { message?: string } } })?.response?.data?.message ?? 'Failed to load banks'\n throw err\n }\n }\n return []\n })().finally(() => {\n loadingBanks.value = false\n banksPromise = null\n })\n return banksPromise\n }\n\n return {\n edocBanks: edocBanksCache,\n banks: banksCache,\n loading: loadingBanks,\n error: errorBanks,\n loadBanksForStatement,\n invalidateCache: () => {\n edocBanksCache.value = banksCache.value = []\n banksPromise = null\n errorBanks.value = null\n },\n }\n}\n","import { ref } from 'vue'\n\nexport interface VerificationState {\n isLoading: boolean\n isSuccess: boolean\n isError: boolean\n errorMessage?: string\n}\n\nconst verificationStates = ref<Record<string, VerificationState>>({})\n\nexport type VerifyBankAccountFn = (\n accountNumber: string,\n bankCode: string\n) => Promise<{ account_name?: string; accountName?: string } | null>\n\nexport function useAccountVerification(\n verifyBankAccount?: VerifyBankAccountFn | (() => VerifyBankAccountFn | null | undefined) | null\n) {\n const getVerifyFn = (): VerifyBankAccountFn | null | undefined =>\n typeof verifyBankAccount === 'function' && verifyBankAccount.length === 0\n ? (verifyBankAccount as () => VerifyBankAccountFn | null | undefined)()\n : (verifyBankAccount as VerifyBankAccountFn | null | undefined)\n const getVerificationKey = (account: { bank?: string; account_number?: string }) =>\n `${account.bank ?? ''}_${account.account_number ?? ''}`\n\n const getVerificationState = (account: { bank?: string; account_number?: string }): VerificationState => {\n const key = getVerificationKey(account)\n return (\n verificationStates.value[key] ?? {\n isLoading: false,\n isSuccess: false,\n isError: false,\n }\n )\n }\n\n const clearAccountName = (account: { account_name?: string }) => {\n account.account_name = ''\n }\n\n const handleAccountVerification = async (account: {\n bank?: string\n account_number?: string\n account_name?: string\n }) => {\n const bankCode = account.bank\n const accountNumber = account.account_number\n const key = getVerificationKey(account)\n const fn = getVerifyFn()\n\n if (!fn || !bankCode || !accountNumber || accountNumber.length !== 10) {\n delete verificationStates.value[key]\n if (accountNumber?.length !== 10) clearAccountName(account)\n return\n }\n\n clearAccountName(account)\n verificationStates.value[key] = { isLoading: true, isSuccess: false, isError: false }\n\n try {\n const result = await fn(accountNumber, bankCode)\n const name = result?.account_name ?? result?.accountName ?? ''\n if (name) {\n account.account_name = name\n verificationStates.value[key] = { isLoading: false, isSuccess: true, isError: false }\n } else {\n verificationStates.value[key] = {\n isLoading: false,\n isSuccess: false,\n isError: true,\n errorMessage: 'Account verification failed',\n }\n }\n } catch (err) {\n verificationStates.value[key] = {\n isLoading: false,\n isSuccess: false,\n isError: true,\n errorMessage: err instanceof Error ? err.message : 'Verification failed',\n }\n }\n }\n\n const retryVerification = (account: { bank?: string; account_number?: string; account_name?: string }) => {\n return handleAccountVerification(account)\n }\n\n return {\n handleAccountVerification,\n retryVerification,\n getVerificationState,\n clearAccountName,\n }\n}\n","/**\n * Bank statements API URL builders. Host app builds full URLs (e.g. baseURL + path).\n */\nconst defaultPrefix = '/api/loan-applications'\n\nexport function bankStatementsUrls(applicationId: string | number, baseUrl = '') {\n const prefix = baseUrl ? `${baseUrl.replace(/\\/$/, '')}${defaultPrefix}` : defaultPrefix\n const id = String(applicationId)\n return {\n index: `${prefix}/${id}/bank-statements`,\n store: `${prefix}/${id}/bank-statements`,\n update: (statementId: string | number) => `${prefix}/${id}/bank-statements/${statementId}`,\n destroy: (statementId: string | number) => `${prefix}/${id}/bank-statements/${statementId}`,\n uploadToEdoc: (statementId: string | number) => `${prefix}/${id}/bank-statements/${statementId}/upload-to-edoc`,\n }\n}\n\nexport const bankStatementsApi = {\n urls: bankStatementsUrls,\n}\n","/**\n * File upload / view URLs on the consuming app (e.g. Glow). Presigning uses that app’s S3 config\n * (`/api/files/view`, `Storage::disk('s3')` presign in Laravel, `boi_edoc` for `edoc/statements/…`).\n *\n * Uploads may still target `integrationBaseUrl` (boi-api) via `uploadUrl` on FileInput; view always\n * uses these paths so “View document” hits the SPA host, not boi-api.\n *\n * Optional: `VITE_FILES_API_BASE` when the static SPA origin differs from the Laravel app\n * (e.g. VITE_FILES_API_BASE=https://glow.test).\n */\nconst base = (import.meta.env.VITE_FILES_API_BASE as string | undefined)?.replace(/\\/$/, '') ?? ''\n\nexport const filesApi = {\n upload: () => `${base}/api/files/upload`,\n view: (path: string) => `${base}/api/files/view?path=${encodeURIComponent(path)}`,\n} as const\n","<script setup lang=\"ts\">\nimport { computed, ref, watch, nextTick, onMounted, onUnmounted } from 'vue'\nimport type { BankOption } from '../types/edoc'\nimport { cn } from '../lib/utils'\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string\n options: BankOption[]\n placeholder?: string\n disabled?: boolean\n id?: string\n }>(),\n { placeholder: 'Select bank', disabled: false }\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: string] }>()\n\nconst isOpen = ref(false)\nconst selectRef = ref<HTMLDivElement | null>(null)\nconst searchRef = ref<HTMLInputElement | null>(null)\nconst searchQuery = ref('')\nconst highlightedIndex = ref(-1)\n\nfunction optionMatchesQuery(opt: BankOption, q: string): boolean {\n if (!q) return true\n const parts = [\n opt.label,\n opt.shortName,\n ...(opt.searchKeywords ?? []),\n ]\n .filter((s) => s != null && String(s).trim() !== '')\n .map((s) => String(s).toLowerCase())\n\n // Any field contains full query (e.g. \"fcmb\", \"first city\")\n if (parts.some((p) => p.includes(q))) return true\n\n // Multi-word: each token must match somewhere (label, short name, or keyword)\n const tokens = q.split(/\\s+/).filter(Boolean)\n if (tokens.length > 1) {\n return tokens.every((t) => parts.some((p) => p.includes(t)))\n }\n\n // Single token: also allow prefix-style match on short name / keywords (e.g. \"fcm\" → FCMB)\n return parts.some((p) => p.startsWith(q))\n}\n\nconst filteredOptions = computed(() => {\n if (!props.options?.length) return []\n if (!searchQuery.value.trim()) return props.options\n const q = searchQuery.value.toLowerCase().trim()\n return props.options.filter((opt) => optionMatchesQuery(opt, q))\n})\n\nconst selectedOption = computed(() =>\n props.options?.find((o) => String(o.value) === String(props.modelValue)) ?? null\n)\n\nconst displayValue = computed(() => selectedOption.value?.label ?? props.placeholder)\n\nfunction toggle() {\n if (props.disabled) return\n isOpen.value = !isOpen.value\n if (isOpen.value) {\n searchQuery.value = ''\n highlightedIndex.value = filteredOptions.value.length ? 0 : -1\n nextTick(() => searchRef.value?.focus())\n }\n}\n\nfunction select(opt: BankOption) {\n emit('update:modelValue', String(opt.value))\n isOpen.value = false\n searchQuery.value = ''\n}\n\nfunction onKeydown(e: KeyboardEvent) {\n if (!isOpen.value) return\n const opts = filteredOptions.value\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault()\n highlightedIndex.value = Math.min(highlightedIndex.value + 1, opts.length - 1)\n break\n case 'ArrowUp':\n e.preventDefault()\n highlightedIndex.value = Math.max(highlightedIndex.value - 1, 0)\n break\n case 'Enter':\n e.preventDefault()\n if (highlightedIndex.value >= 0 && opts[highlightedIndex.value]) {\n select(opts[highlightedIndex.value])\n }\n break\n case 'Escape':\n e.preventDefault()\n isOpen.value = false\n break\n }\n}\n\nfunction onClickOutside(e: Event) {\n if (selectRef.value && !selectRef.value.contains(e.target as Node)) {\n isOpen.value = false\n }\n}\n\nwatch(searchQuery, () => {\n highlightedIndex.value = filteredOptions.value.length ? 0 : -1\n})\n\nonMounted(() => {\n if (typeof document !== 'undefined') {\n document.addEventListener('click', onClickOutside)\n }\n})\n\nonUnmounted(() => {\n if (typeof document !== 'undefined') {\n document.removeEventListener('click', onClickOutside)\n }\n})\n</script>\n\n<template>\n <div ref=\"selectRef\" class=\"relative\">\n <button\n type=\"button\"\n :id=\"id\"\n :disabled=\"disabled\"\n :class=\"cn(\n 'flex h-9 w-full min-w-0 items-center justify-between rounded-lg border border-gray-300 bg-white px-3 py-2.5 text-sm transition-colors outline-none',\n 'focus:border-[var(--boi-primary)] focus:ring-1 focus:ring-[var(--boi-primary)]',\n 'disabled:cursor-not-allowed disabled:opacity-50',\n !selectedOption && 'text-gray-500'\n )\"\n @click=\"toggle\"\n >\n <span class=\"truncate text-left\">{{ displayValue }}</span>\n <svg class=\"h-4 w-4 shrink-0 text-gray-400\" :class=\"{ 'rotate-180': isOpen }\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M19 9l-7 7-7-7\" />\n </svg>\n </button>\n\n <div\n v-if=\"isOpen\"\n class=\"absolute z-[1000] mt-1 w-full rounded-lg border border-gray-200 bg-white shadow-lg\"\n >\n <div class=\"border-b border-gray-100 p-2\">\n <div class=\"relative\">\n <svg class=\"absolute left-2.5 top-1/2 h-4 w-4 -translate-y-1/2 text-gray-400\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\" />\n </svg>\n <input\n ref=\"searchRef\"\n v-model=\"searchQuery\"\n type=\"text\"\n placeholder=\"Type to search...\"\n class=\"w-full rounded-md border-0 bg-gray-50 py-2 pl-9 pr-3 text-sm focus:bg-white focus:ring-1 focus:ring-[var(--boi-primary)]\"\n @keydown=\"onKeydown\"\n />\n </div>\n </div>\n <div class=\"max-h-48 overflow-auto py-1\">\n <button\n v-for=\"(option, index) in filteredOptions\"\n :key=\"option.value\"\n type=\"button\"\n :class=\"cn(\n 'w-full cursor-pointer px-3 py-2.5 text-left text-sm transition-colors text-gray-900',\n index === highlightedIndex ? 'bg-gray-100' : 'hover:bg-gray-50',\n String(option.value) === String(modelValue) &&\n modelValue !== '' &&\n modelValue !== undefined &&\n 'font-semibold text-[#016837]'\n )\"\n @click=\"select(option)\"\n >\n {{ option.label }}\n </button>\n <p v-if=\"filteredOptions.length === 0\" class=\"px-3 py-2 text-center text-sm italic text-gray-500\">\n No options found for \"{{ searchQuery }}\"\n </p>\n </div>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\nimport { filesApi } from '../api/files'\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string\n placeholder?: string\n accept?: string\n disabled?: boolean\n id?: string\n maxSize?: number\n allowedTypes?: string[]\n uploadToServer?: boolean\n showRequirements?: boolean\n uploadContext?: string\n afterUpload?: (path: string) => void\n /** Upload URL (default: filesApi.upload()) */\n uploadUrl?: string\n /**\n * Base URL for “View document” (no trailing slash). Use the same host as file uploads when they go\n * through boi-api or a proxy, e.g. `https://glow.test/api/boi-api` → `{base}/api/files/view?path=…`\n * (presign runs on boi-api). If unset, uses `filesApi.view()` (consuming SPA origin / VITE_FILES_API_BASE).\n */\n viewApiBase?: string\n /**\n * S3 storage key for the view link when it must differ from `modelValue` (e.g. model holds EDOC CSV path\n * but the user should open the uploaded PDF).\n */\n viewStoragePath?: string\n /** POST function, e.g. (url, formData, opts) => axios.post(url, formData, opts). Returns Promise<{ data?: { success?, path?, message? } }>. */\n post?: (url: string, body: FormData, options?: { headers?: Record<string, string> }) => Promise<{ data?: unknown }>\n }>(),\n {\n modelValue: '',\n placeholder: 'Choose file',\n accept: '*/*',\n disabled: false,\n maxSize: 10 * 1024 * 1024,\n allowedTypes: () => [\n 'application/pdf',\n 'image/jpeg',\n 'image/jpg',\n 'image/png',\n 'application/msword',\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n 'application/vnd.ms-excel',\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n 'text/plain',\n 'text/csv',\n ],\n uploadToServer: true,\n showRequirements: true,\n }\n)\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string]\n 'validation-error': [message: string]\n 'validation-success': [message: string]\n 'uploaded': [path: string]\n}>()\n\nconst fileInput = ref<HTMLInputElement>()\nconst uploading = ref(false)\nconst fileName = ref('')\nconst errorMessage = ref('')\n\nconst typeMap: Record<string, string> = {\n 'application/pdf': 'PDF',\n 'image/jpeg': 'JPG', 'image/jpg': 'JPG', 'image/png': 'PNG',\n 'application/msword': 'DOC',\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': 'DOCX',\n 'application/vnd.ms-excel': 'XLS',\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': 'XLSX',\n 'text/plain': 'TXT', 'text/csv': 'CSV',\n}\n\nconst extToMime: Record<string, string[]> = {\n pdf: ['application/pdf'],\n jpg: ['image/jpeg', 'image/jpg'], jpeg: ['image/jpeg', 'image/jpg'],\n png: ['image/png'], doc: ['application/msword'],\n docx: ['application/vnd.openxmlformats-officedocument.wordprocessingml.document'],\n xls: ['application/vnd.ms-excel'],\n xlsx: ['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'],\n txt: ['text/plain'], csv: ['text/csv'],\n}\n\nconst allowedFormatsDisplay = computed(() =>\n [...new Set(props.allowedTypes.map((t) => typeMap[t] || t.split('/')[1]?.toUpperCase() || t))].join(', ')\n)\nconst maxSizeMB = computed(() => Math.round(props.maxSize / (1024 * 1024)))\nconst isDisabled = computed(() => props.disabled || uploading.value)\n\nconst viewApiBaseNorm = computed(() => String(props.viewApiBase ?? '').trim().replace(/\\/$/, ''))\n\n/** Path used for `/api/files/view` — prefer explicit upload path over `modelValue`. */\nconst effectiveViewStoragePath = computed(() => {\n const fromProp = String(props.viewStoragePath ?? '').trim()\n if (fromProp) return fromProp\n return String(props.modelValue ?? '').trim()\n})\n\nconst viewFileUrl = computed(() => {\n const raw = effectiveViewStoragePath.value\n if (!raw || !props.uploadToServer) return '#'\n const path = encodeURIComponent(raw)\n const base = viewApiBaseNorm.value\n if (base) return `${base}/api/files/view?path=${path}`\n return filesApi.view(raw)\n})\n\nfunction validate(file: File): boolean {\n errorMessage.value = ''\n if (file.size > props.maxSize) {\n const msg = `File size must be less than ${maxSizeMB.value}MB`\n errorMessage.value = msg\n emit('validation-error', msg)\n return false\n }\n if (props.allowedTypes.length) {\n const ext = file.name.split('.').pop()?.toLowerCase() || ''\n const ok = props.allowedTypes.includes(file.type) || (extToMime[ext] || []).some((m) => props.allowedTypes.includes(m))\n if (!ok) {\n const msg = `Only ${allowedFormatsDisplay.value} files are allowed`\n errorMessage.value = msg\n emit('validation-error', msg)\n return false\n }\n }\n return true\n}\n\nasync function handleChange(e: Event) {\n errorMessage.value = ''\n const target = e.target as HTMLInputElement\n const file = target.files?.[0]\n if (!file) {\n fileName.value = ''\n emit('update:modelValue', '')\n return\n }\n if (!validate(file)) {\n target.value = ''\n fileName.value = ''\n emit('update:modelValue', '')\n return\n }\n if (props.uploadToServer && props.post) {\n uploading.value = true\n const url = props.uploadUrl ?? filesApi.upload()\n const formData = new FormData()\n formData.append('file', file)\n formData.append('folder', 'documents')\n if (props.uploadContext) formData.append('context', props.uploadContext)\n try {\n const res = await props.post(url, formData, { headers: { 'Content-Type': 'multipart/form-data' } })\n const data = res?.data as { success?: boolean; path?: string; url?: string; message?: string } | undefined\n if (data?.success && data?.path) {\n fileName.value = file.name\n if (data.url) {\n console.log('[FileInput] S3 URL:', data.url)\n }\n emit('update:modelValue', data.path)\n emit('validation-success', 'File uploaded successfully')\n emit('uploaded', data.path)\n props.afterUpload?.(data.path)\n } else {\n const msg = data?.message ?? 'Upload failed'\n errorMessage.value = msg\n emit('validation-error', msg)\n target.value = ''\n fileName.value = ''\n emit('update:modelValue', '')\n }\n } catch (err: unknown) {\n const msg = (err as { response?: { data?: { message?: string } }; message?: string })?.response?.data?.message ?? (err as Error)?.message ?? 'Upload failed'\n errorMessage.value = msg\n emit('validation-error', msg)\n target.value = ''\n fileName.value = ''\n emit('update:modelValue', '')\n } finally {\n uploading.value = false\n }\n } else {\n fileName.value = file.name\n emit('update:modelValue', file.name)\n emit('uploaded', file.name)\n }\n}\n\nfunction openDialog() {\n if (!isDisabled.value && fileInput.value) fileInput.value.click()\n}\n\nwatch(() => props.modelValue, (v) => {\n fileName.value = (typeof v === 'string' && v ? v.split('/').pop() : '') || ''\n}, { immediate: true })\n</script>\n\n<template>\n <div class=\"boi-file-input w-full space-y-2\">\n <input\n ref=\"fileInput\"\n type=\"file\"\n :accept=\"accept\"\n :disabled=\"isDisabled\"\n :id=\"id\"\n class=\"hidden\"\n @change=\"handleChange\"\n />\n <div\n :class=\"[\n 'flex w-full items-center justify-between rounded-md border border-gray-300 bg-white px-3 py-2 transition-colors',\n isDisabled ? 'cursor-not-allowed opacity-50' : 'cursor-pointer hover:bg-gray-50',\n errorMessage ? 'border-red-500' : '',\n ]\"\n @click=\"openDialog\"\n >\n <span class=\"truncate text-sm text-gray-600\">{{ uploading ? 'Uploading...' : fileName || placeholder }}</span>\n <span class=\"text-gray-400\">📎</span>\n </div>\n <p v-if=\"errorMessage\" class=\"text-sm text-red-600\">{{ errorMessage }}</p>\n <p v-if=\"showRequirements\" class=\"text-xs text-gray-500\">Max {{ maxSizeMB }} MB. Allowed: {{ allowedFormatsDisplay }}.</p>\n <a\n v-if=\"effectiveViewStoragePath && !uploading && uploadToServer\"\n :href=\"viewFileUrl\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"text-sm text-blue-600 hover:underline\"\n >\n View document >>>\n </a>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref, watch, onMounted, onUnmounted } from 'vue'\nimport type { BankStatementRecord, BankOption, IndustrialSectorOption } from '../types/edoc'\nimport { useEdocBanks } from '../composables/useEdocBanks'\nimport { useAccountVerification } from '../composables/useAccountVerification'\nimport { bankStatementsApi } from '../api/bankStatements'\nimport { edocApi } from '../api/edoc'\nimport { filesApi } from '../api/files'\nimport Button from './Button.vue'\nimport BankSelect from './BankSelect.vue'\nimport EmtsIntegration from './EmtsIntegration.vue'\nimport FileInput from './FileInput.vue'\nimport type { VerifyBankAccountFn } from '../composables/useAccountVerification'\n\nconst props = withDefaults(\n defineProps<{\n applicationId?: string\n api: {\n get: (url: string) => Promise<{ data?: unknown }>\n post: (url: string, data?: unknown, config?: unknown) => Promise<{ data?: unknown }>\n put: (url: string, data?: unknown) => Promise<{ data?: unknown }>\n delete: (url: string) => Promise<{ data?: unknown }>\n }\n bankOptions: BankOption[]\n formData: { email?: string; industrial_sector_id?: string | number }\n industrialSectorOptions?: IndustrialSectorOption[]\n /** Legacy: only prefixes bank-statement CRUD paths. Prefer integrationBaseUrl. */\n baseUrl?: string\n /** When set (e.g. deployed boi-api origin), prefixes bank statements, EDOC, and file upload URLs. */\n integrationBaseUrl?: string\n isFormDisabled?: boolean\n maxAccounts?: number\n /** When provided, account name is resolved from account number + bank (e.g. GET /api/verify-bank?account_number=&bank_code=) */\n verifyBankAccount?: VerifyBankAccountFn | null\n /** Call when user focuses into this form so parent can block auto-save */\n blockAutoSave?: () => void\n /** Call when user focuses out so parent can unblock auto-save */\n unblockAutoSave?: () => void\n /** When false, do not poll for EDOC status (stops repeated GET list calls). Set false when upload-to-edoc is disabled. */\n pollEdocStatus?: boolean\n }>(),\n {\n baseUrl: '',\n integrationBaseUrl: '',\n isFormDisabled: false,\n maxAccounts: 5,\n verifyBankAccount: null,\n pollEdocStatus: true,\n }\n)\n\nconst emit = defineEmits<{\n 'error': [message: string]\n}>()\n\nfunction withIntegrationOrigin(path: string): string {\n const b = (props.integrationBaseUrl ?? '').replace(/\\/$/, '')\n if (!b) return path\n const p = path.startsWith('/') ? path : `/${path}`\n return `${b}${p}`\n}\n\nconst {\n edocBanks,\n loadBanksForStatement,\n loading: loadingEdocBanks,\n error: edocBanksError,\n} = useEdocBanks({\n get: props.api.get,\n getBanksUrl: () => withIntegrationOrigin(edocApi.getBanks()),\n})\n\nconst {\n handleAccountVerification,\n retryVerification,\n getVerificationState,\n} = useAccountVerification(() => props.verifyBankAccount)\n\nconst activeIndex = ref(0)\nconst errorMessage = ref('')\nconst showEdocBanksList = ref(false)\nconst rootRef = ref<HTMLFieldSetElement | null>(null)\n\nfunction onFocusIn() {\n props.blockAutoSave?.()\n}\n\nfunction onFocusOut() {\n setTimeout(() => {\n const el = rootRef.value\n if (el && !el.contains(document.activeElement)) {\n props.unblockAutoSave?.()\n }\n }, 0)\n}\nconst bankStatements = ref<BankStatementRecord[]>([])\nconst loadingStatements = ref(false)\nlet pollTimer: ReturnType<typeof setInterval> | null = null\n\nconst statementsUrlPrefix = computed(\n () => props.integrationBaseUrl?.replace(/\\/$/, '') || props.baseUrl?.replace(/\\/$/, '') || ''\n)\n\nconst urls = computed(() =>\n props.applicationId ? bankStatementsApi.urls(props.applicationId, statementsUrlPrefix.value) : null\n)\n\nconst fileUploadUrl = computed(() =>\n props.integrationBaseUrl ? withIntegrationOrigin(filesApi.upload()) : undefined\n)\n\n/** Same base as uploads (boi-api or `/api/boi-api` proxy) so `/api/files/view` presigns there. */\nconst fileViewApiBase = computed(() => (props.integrationBaseUrl ?? '').trim().replace(/\\/$/, ''))\n\nconst limitedStatements = computed(() =>\n bankStatements.value.slice(0, props.maxAccounts)\n)\n\nconst canAddAccount = computed(() => bankStatements.value.length < props.maxAccounts)\nconst canRemoveAccount = computed(() => bankStatements.value.length > 0)\nconst companyEmail = computed(() => props.formData?.email ?? '')\n\nfunction getIndustrialSectorName(): string | undefined {\n const id = props.formData?.industrial_sector_id\n if (id == null) return undefined\n const opt = props.industrialSectorOptions?.find(\n (s) => s.value === id || s.id === id || s.value === String(id)\n )\n return opt?.label ?? opt?.name\n}\n\n/** EDOC CSV copy on S3 — not the user’s uploaded PDF path. */\nfunction isEdocCsvStorageKey(path: string | undefined | null): boolean {\n if (path == null || path === '') return false\n const p = path.trim().toLowerCase()\n return p.includes('edoc/statements/') && p.endsWith('.csv')\n}\n\nfunction initialUploadedStatementPath(bankStatement: string | undefined | null): string {\n const b = (bankStatement ?? '').trim()\n if (!b || isEdocCsvStorageKey(b)) return ''\n return b\n}\n\n/** Storage key for “View document” (uploaded PDF), even if `bank_statement` later holds the CSV key. */\nfunction statementViewStoragePath(account: BankStatementRecord): string {\n const u = account.uploaded_statement_path?.trim()\n if (u) return u\n const b = account.bank_statement?.trim() ?? ''\n if (b && !isEdocCsvStorageKey(b)) return b\n return ''\n}\n\nfunction onStatementFileUploaded(statement: BankStatementRecord, path: string) {\n statement.uploaded_statement_path = path.trim()\n saveStatement(statement)\n}\n\nfunction getStatementLabel(account: BankStatementRecord, index: number): string {\n const bank = props.bankOptions.find((b) => b.value === account.bank)?.label ?? ''\n const num = account.account_number ?? ''\n if (bank && num) return `${bank} (${num})`\n if (bank) return bank\n if (num) return `Account (${num})`\n return `Account ${index + 1}`\n}\n\nfunction getStatusClass(status: string): string {\n const map: Record<string, string> = {\n pending: 'bg-gray-100 text-gray-800',\n processing: 'bg-amber-100 text-amber-800',\n completed: 'bg-green-100 text-green-800',\n failed: 'bg-red-100 text-red-800',\n }\n return map[status] ?? map.pending\n}\n\nasync function loadBankStatements() {\n if (!urls.value) return\n try {\n loadingStatements.value = true\n const res = await props.api.get(urls.value.index)\n const data = res?.data as { success?: boolean; data?: BankStatementRecord[] }\n if (data?.success && Array.isArray(data.data)) {\n bankStatements.value = data.data.map((s) => ({\n ...s,\n otp: '',\n showOtpInput: false,\n uploaded_statement_path: initialUploadedStatementPath(s.bank_statement),\n }))\n }\n } catch (e) {\n console.error('Failed to load bank statements', e)\n } finally {\n loadingStatements.value = false\n }\n}\n\nasync function syncStatementsFromPoll() {\n if (!urls.value) return\n try {\n const res = await props.api.get(urls.value.index)\n const data = res?.data as { success?: boolean; data?: BankStatementRecord[] }\n if (!data?.success || !Array.isArray(data.data)) return\n const fields = ['edoc_status', 'consent_id', 'csv_url', 'statement_generated'] as const\n bankStatements.value = bankStatements.value.map((existing) => {\n const apiRow = data.data!.find((s) => s.id === existing.id)\n if (!apiRow) return existing\n const updates: Partial<BankStatementRecord> = {}\n for (const key of fields) {\n if (key in apiRow) (updates as Record<string, unknown>)[key] = apiRow[key]\n }\n let uploadedPath = existing.uploaded_statement_path ?? ''\n if ('bank_statement' in apiRow && apiRow.bank_statement !== undefined) {\n const incoming = String(apiRow.bank_statement ?? '')\n ;(updates as Record<string, unknown>).bank_statement = apiRow.bank_statement\n if (incoming && !isEdocCsvStorageKey(incoming)) {\n uploadedPath = incoming\n } else if (incoming && isEdocCsvStorageKey(incoming) && uploadedPath) {\n // keep uploaded PDF path for View document\n } else if (!incoming) {\n uploadedPath = ''\n }\n }\n updates.uploaded_statement_path = uploadedPath\n return { ...existing, ...updates }\n })\n } catch (e) {\n console.error('Sync statements failed', e)\n }\n}\n\nfunction startPolling() {\n stopPolling()\n pollTimer = setInterval(() => {\n const hasProcessing = bankStatements.value.some((s) => s.edoc_status === 'processing')\n if (!hasProcessing) {\n stopPolling()\n return\n }\n syncStatementsFromPoll()\n }, 5000)\n}\n\nfunction stopPolling() {\n if (pollTimer) {\n clearInterval(pollTimer)\n pollTimer = null\n }\n}\n\nwatch(\n () => bankStatements.value.some((s) => s.edoc_status === 'processing'),\n (hasProcessing) => {\n if (!props.pollEdocStatus) {\n stopPolling()\n return\n }\n if (hasProcessing) startPolling()\n else stopPolling()\n }\n)\n\nasync function saveStatement(statement: BankStatementRecord) {\n if (!urls.value || statement.id < 0) return\n try {\n await props.api.put(urls.value.update(statement.id), {\n bank: statement.bank,\n account_number: statement.account_number,\n account_name: statement.account_name,\n account_type: statement.account_type,\n bvn: statement.bvn,\n email: statement.email,\n bank_statement: statement.bank_statement,\n })\n } catch (e) {\n console.error('Failed to save bank statement', e)\n }\n}\n\nasync function handleAddAccount() {\n if (!urls.value || !canAddAccount.value) return\n const tempId = -Date.now()\n const newRecord: BankStatementRecord = {\n id: tempId,\n loan_application_id: Number(props.applicationId),\n bank: '',\n account_number: '',\n account_name: '',\n account_type: '',\n bvn: '',\n email: companyEmail.value,\n bank_statement: '',\n csv_url: '',\n consent_id: '',\n edoc_status: 'pending',\n statement_generated: false,\n otp: '',\n showOtpInput: false,\n uploaded_statement_path: '',\n }\n bankStatements.value.push(newRecord)\n activeIndex.value = bankStatements.value.length - 1\n\n try {\n const res = await props.api.post(urls.value.store, { email: companyEmail.value })\n const data = res?.data as { success?: boolean; data?: BankStatementRecord }\n if (data?.success && data.data) {\n const idx = bankStatements.value.findIndex((s) => s.id === tempId)\n if (idx !== -1) {\n bankStatements.value[idx] = {\n ...data.data,\n otp: '',\n showOtpInput: false,\n uploaded_statement_path: initialUploadedStatementPath(data.data.bank_statement),\n }\n }\n } else {\n bankStatements.value = bankStatements.value.filter((s) => s.id !== tempId)\n activeIndex.value = Math.max(0, bankStatements.value.length - 1)\n }\n } catch (e) {\n bankStatements.value = bankStatements.value.filter((s) => s.id !== tempId)\n activeIndex.value = Math.max(0, bankStatements.value.length - 1)\n emit('error', (e as Error)?.message ?? 'Failed to add account')\n }\n}\n\nasync function handleRemoveAccount(statement: BankStatementRecord) {\n if (!urls.value) return\n const removedIndex = bankStatements.value.findIndex((s) => s.id === statement.id)\n const removed = { ...statement }\n const isOptimistic = statement.id < 0\n bankStatements.value = bankStatements.value.filter((s) => s.id !== statement.id)\n activeIndex.value = Math.min(activeIndex.value, Math.max(0, bankStatements.value.length - 1))\n\n if (isOptimistic) return\n try {\n await props.api.delete(urls.value.destroy(statement.id))\n } catch (e) {\n bankStatements.value = bankStatements.value\n .slice(0, removedIndex)\n .concat(removed, bankStatements.value.slice(removedIndex))\n emit('error', (e as Error)?.message ?? 'Failed to remove account')\n }\n}\n\nfunction onConsentId(statement: BankStatementRecord, consentId: string) {\n statement.consent_id = consentId\n statement.showOtpInput = true\n saveStatement(statement)\n}\n\nfunction onStatementRetrieved(statement: BankStatementRecord, updated: BankStatementRecord) {\n Object.assign(statement, updated)\n saveStatement(statement)\n}\n\nfunction onEdocError(msg: string) {\n errorMessage.value = msg\n emit('error', msg)\n}\n\nfunction clearError() {\n errorMessage.value = ''\n}\n\nfunction createAfterUpload(statement: BankStatementRecord) {\n return (filePath: string) => {\n if (!urls.value) return\n props.blockAutoSave?.()\n statement.edoc_status = 'processing'\n const sector = getIndustrialSectorName()\n const unblockAfterDelay = () => {\n setTimeout(() => props.unblockAutoSave?.(), 3000)\n }\n props.api\n .post(urls.value.uploadToEdoc(statement.id), { filePath, industrialSector: sector })\n .then((res) => {\n const data = (res?.data as { data?: BankStatementRecord })?.data\n if (data) {\n const preservedPdfPath = statement.uploaded_statement_path ?? ''\n Object.assign(statement, data)\n if (\n preservedPdfPath &&\n data.bank_statement &&\n isEdocCsvStorageKey(String(data.bank_statement))\n ) {\n statement.uploaded_statement_path = preservedPdfPath\n }\n }\n startPolling()\n })\n .catch(() => {\n statement.edoc_status = 'failed'\n })\n .finally(unblockAfterDelay)\n }\n}\n\nconst isBankEdocSupported = (bankCode: string): boolean => {\n if (!bankCode || !edocBanks.value.length) return false\n const bank = props.bankOptions.find((o) => o.value === bankCode)\n const names = [bank?.label ?? '', ...(bank?.searchKeywords ?? [])].filter(Boolean)\n return edocBanks.value.some((b) => {\n const codeMatch = b.bankCode === bankCode || b.code === bankCode\n const nameMatch = names.some((n) => b.name?.toLowerCase().includes(n.toLowerCase()))\n return (codeMatch || nameMatch) && b.enabled !== false\n })\n}\n\nconst enabledEdocBanksList = computed(() =>\n (edocBanks.value || [])\n .filter((b) => b.enabled !== false)\n .map((b) => b.name || b.bankCode || 'Unknown')\n .sort((a, b) => a.localeCompare(b))\n)\n\nonMounted(async () => {\n loadBanksForStatement()\n if (props.applicationId) {\n await loadBankStatements()\n }\n})\n\nonUnmounted(() => {\n stopPolling()\n})\n</script>\n\n<template>\n <fieldset\n ref=\"rootRef\"\n :disabled=\"isFormDisabled\"\n class=\"boi-bank-statement-integration rounded-xl border border-gray-200 bg-white shadow-sm\"\n @focusin=\"onFocusIn\"\n @focusout=\"onFocusOut\"\n >\n <div class=\"border-b border-gray-100 px-4 py-3 md:px-6 md:py-4\">\n <h2 class=\"text-lg font-bold text-slate-900\">Company Bank Statements</h2>\n </div>\n\n <div class=\"px-4 pb-4 md:px-6 md:pb-6\">\n <!-- Info: Electronic statement retrieval -->\n <div class=\"mb-6 rounded-lg border border-blue-200 bg-blue-50 p-4 text-sm\">\n <p class=\"text-blue-900\">\n Some banks support <strong>Electronic Bank Statement Retrieval</strong>, so you may not need to upload a PDF.\n <button\n type=\"button\"\n @click=\"showEdocBanksList = !showEdocBanksList\"\n class=\"ml-1 font-semibold text-blue-700 underline hover:text-blue-800 focus:outline-none focus:ring-2 focus:ring-blue-300 rounded\"\n >\n {{ showEdocBanksList ? 'Hide' : 'See' }}\n </button>\n {{ showEdocBanksList ? '' : ' supported banks.' }}\n </p>\n <div v-if=\"showEdocBanksList && enabledEdocBanksList.length\" class=\"mt-3 rounded-md bg-white/80 border border-blue-100 p-3\">\n <p class=\"mb-2 text-xs font-semibold text-blue-900\">Banks that support electronic statement retrieval:</p>\n <ul class=\"list-inside list-disc space-y-0.5 text-xs text-blue-800 columns-2 gap-x-4\">\n <li v-for=\"(name, idx) in enabledEdocBanksList\" :key=\"idx\">{{ name }}</li>\n </ul>\n </div>\n <p v-else-if=\"showEdocBanksList && loadingEdocBanks\" class=\"mt-2 text-xs text-blue-700\">\n Loading supported banks…\n </p>\n <p v-else-if=\"showEdocBanksList && edocBanksError\" class=\"mt-2 text-xs text-red-700\">\n Could not load the EDOC bank list. Check boi-api / <code class=\"rounded bg-red-50 px-0.5\">/api/boi-api</code> proxy and network errors.\n </p>\n <p v-else-if=\"showEdocBanksList && !enabledEdocBanksList.length\" class=\"mt-2 text-xs text-blue-700\">\n No banks are returned for electronic retrieval (EDOC list is empty on the API).\n </p>\n </div>\n\n <!-- Loading state -->\n <div v-if=\"loadingStatements\" class=\"flex items-center justify-center py-10\">\n <span class=\"inline-block h-5 w-5 animate-spin rounded-full border-2 border-slate-300 border-t-slate-600 mr-2\" aria-hidden=\"true\" />\n <span class=\"text-sm text-slate-600\">Loading bank statements…</span>\n </div>\n\n <template v-else>\n <!-- Account tabs -->\n <div v-if=\"limitedStatements.length\" class=\"flex overflow-x-auto pb-2 gap-1 -mx-1\">\n <button\n v-for=\"(account, index) in limitedStatements\"\n :key=\"account.id\"\n type=\"button\"\n class=\"shrink-0 rounded-lg px-4 py-2 text-sm font-medium whitespace-nowrap transition-colors\"\n :class=\"activeIndex === index ? 'bg-primary text-white shadow-sm' : 'bg-slate-100 text-slate-700 hover:bg-slate-200'\"\n @click=\"activeIndex = index\"\n >\n {{ getStatementLabel(account, index) }}\n </button>\n </div>\n\n <!-- Active account card -->\n <div\n v-for=\"(account, index) in limitedStatements\"\n :key=\"account.id\"\n v-show=\"activeIndex === index\"\n class=\"mt-6 space-y-6 rounded-xl border border-gray-100 bg-gray-50/50 p-4 md:p-6\"\n >\n <div class=\"flex items-center justify-between gap-4\">\n <h4 class=\"border-b-2 border-primary pb-1 text-base font-semibold text-slate-900\">{{ getStatementLabel(account, index) }}</h4>\n <button\n type=\"button\"\n class=\"inline-flex items-center rounded-lg px-3 py-2 text-sm font-medium text-red-600 hover:bg-red-50 disabled:opacity-50 transition-colors\"\n :disabled=\"!canRemoveAccount || isFormDisabled\"\n @click=\"handleRemoveAccount(account)\"\n >\n <svg class=\"w-4 h-4 mr-1.5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16\" /></svg>\n Remove account\n </button>\n </div>\n\n <!-- Bank / account fields -->\n <slot name=\"account-fields\" :account=\"account\" :bank-options=\"bankOptions\" :verification-state=\"getVerificationState(account)\" :on-verify=\"() => handleAccountVerification(account)\" :on-retry=\"() => retryVerification(account)\">\n <div class=\"grid grid-cols-1 gap-4 md:grid-cols-3\">\n <div>\n <label class=\"mb-1.5 block text-sm font-medium text-gray-700\">Bank</label>\n <BankSelect\n :model-value=\"account.bank\"\n :options=\"bankOptions\"\n placeholder=\"Select bank\"\n :disabled=\"!!isFormDisabled\"\n @update:model-value=\"(v) => { account.bank = v; handleAccountVerification(account); saveStatement(account); }\"\n />\n </div>\n <div>\n <label class=\"mb-1.5 block text-sm font-medium text-gray-700\">Account number</label>\n <input\n v-model=\"account.account_number\"\n type=\"text\"\n maxlength=\"10\"\n inputmode=\"numeric\"\n class=\"w-full rounded-lg border border-gray-300 bg-white px-3 py-2.5 text-sm focus:border-primary focus:ring-1 focus:ring-primary\"\n placeholder=\"10 digits\"\n @blur=\"handleAccountVerification(account); saveStatement(account)\"\n />\n </div>\n <div>\n <label class=\"mb-1.5 block text-sm font-medium text-gray-700\">Account name</label>\n <input\n :value=\"account.account_name\"\n type=\"text\"\n readonly\n class=\"w-full cursor-default rounded-lg border border-gray-200 bg-gray-50 px-3 py-2.5 text-sm text-gray-700\"\n placeholder=\"Enter bank and account number to verify\"\n />\n <div v-if=\"verifyBankAccount\" class=\"mt-1.5 flex flex-wrap items-center gap-2 text-xs\">\n <span v-if=\"getVerificationState(account).isLoading\" class=\"text-blue-600\">Verifying…</span>\n <span v-else-if=\"getVerificationState(account).isSuccess\" class=\"text-green-600\">Account verified</span>\n <span v-else-if=\"getVerificationState(account).isError\" class=\"flex items-center gap-1\">\n <span class=\"text-red-600\">{{ getVerificationState(account).errorMessage }}</span>\n <button type=\"button\" class=\"rounded px-2 py-0.5 text-gray-600 hover:bg-gray-100\" @click=\"retryVerification(account)\">Retry</button>\n </span>\n </div>\n </div>\n </div>\n </slot>\n\n <div v-if=\"isBankEdocSupported(account.bank)\" class=\"boi-emts-wrapper\">\n <EmtsIntegration\n :account=\"account\"\n :edoc-banks=\"edocBanks\"\n :bank-options=\"bankOptions\"\n :api=\"{ get: api.get, post: api.post }\"\n :company-email=\"companyEmail\"\n :industrial-sector=\"getIndustrialSectorName()\"\n :application-id=\"applicationId\"\n :integration-base-url=\"integrationBaseUrl\"\n :disabled=\"isFormDisabled\"\n @update:consent-id=\"onConsentId(account, $event)\"\n @statement-retrieved=\"onStatementRetrieved(account, $event)\"\n @error=\"onEdocError\"\n />\n <p\n v-if=\"account.statement_generated || account.edoc_status === 'completed'\"\n class=\"mt-3 text-sm font-medium text-green-800\"\n >\n Succeeded.\n </p>\n </div>\n\n <div v-if=\"!isBankEdocSupported(account.bank)\" class=\"rounded-lg border border-gray-200 bg-white p-4\">\n <p class=\"mb-3 text-sm font-medium text-gray-700\">Upload bank statement (PDF)</p>\n <slot name=\"file-upload\" :account=\"account\" :after-upload=\"createAfterUpload(account)\">\n <FileInput\n v-model=\"account.bank_statement\"\n :view-storage-path=\"statementViewStoragePath(account)\"\n :post=\"(url, body, opts) => api.post(url, body, opts)\"\n :upload-url=\"fileUploadUrl\"\n :view-api-base=\"fileViewApiBase || undefined\"\n placeholder=\"Choose 12 months bank statement (PDF)\"\n accept=\".pdf\"\n :max-size=\"20 * 1024 * 1024\"\n :allowed-types=\"['application/pdf']\"\n upload-context=\"bank_statement\"\n :after-upload=\"createAfterUpload(account)\"\n :disabled=\"isFormDisabled\"\n @uploaded=\"(path) => onStatementFileUploaded(account, String(path))\"\n />\n <!-- Status -->\n <div class=\"rounded-lg py-3\">\n <div class=\"flex items-center gap-2\">\n <span class=\"text-sm font-medium text-gray-600\">Bank statement status:</span>\n <span\n :class=\"[getStatusClass(account.edoc_status || 'pending'), 'inline-flex items-center gap-1.5 rounded-full px-3 py-1 text-xs font-medium capitalize']\"\n >\n <span\n v-if=\"account.edoc_status === 'processing'\"\n class=\"inline-block h-3.5 w-3.5 animate-spin rounded-full border-2 border-current border-t-transparent\"\n aria-hidden=\"true\"\n />\n {{ account.edoc_status || 'pending' }}\n </span>\n </div>\n <p v-if=\"account.edoc_status === 'processing'\" class=\"mt-1.5 text-sm text-amber-700\">\n Processing in progress. Please wait…\n </p>\n <p v-if=\"account.edoc_status === 'failed'\" class=\"mt-1.5 text-sm text-red-600\">\n Processing failed. Please re-upload a valid bank statement or try another method.\n </p>\n </div>\n </slot>\n </div>\n\n \n\n <div v-if=\"errorMessage\" class=\"rounded-lg border border-red-200 bg-red-50 p-4 flex items-start gap-3\">\n <p class=\"flex-1 text-sm text-red-800\">{{ errorMessage }}</p>\n <button type=\"button\" class=\"shrink-0 rounded p-1 text-red-600 hover:bg-red-100\" @click=\"clearError\" aria-label=\"Dismiss\">×</button>\n </div>\n </div>\n\n <div class=\"flex justify-center\">\n <Button\n type=\"button\"\n variant=\"default\"\n size=\"lg\"\n :disabled=\"!canAddAccount || isFormDisabled || !applicationId\"\n @click=\"handleAddAccount\"\n >\n <svg class=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M12 4v16m8-8H4\" />\n </svg>\n Add account\n </Button>\n </div>\n </template>\n </div>\n </fieldset>\n</template>\n","import type { App } from 'vue'\nimport './styles/theme.css'\n\nexport { default as BoiButton } from './components/BoiButton.vue'\nexport { default as Button } from './components/Button.vue'\nexport { default as EmtsIntegration } from './components/EmtsIntegration.vue'\nexport { default as BankStatementIntegration } from './components/BankStatementIntegration.vue'\nexport { default as BankSelect } from './components/BankSelect.vue'\nexport { default as FileInput } from './components/FileInput.vue'\n\nexport { useEdocBanks } from './composables/useEdocBanks'\nexport type { UseEdocBanksOptions } from './composables/useEdocBanks'\nexport { useAccountVerification } from './composables/useAccountVerification'\nexport type { VerifyBankAccountFn, VerificationState } from './composables/useAccountVerification'\n\nexport { edocApi } from './api/edoc'\nexport type { EdocApi } from './api/edoc'\nexport { bankStatementsApi, bankStatementsUrls } from './api/bankStatements'\nexport { filesApi } from './api/files'\n\nexport type {\n EdocBank,\n BankStatementRecord,\n EdocConsentInitializePayload,\n EdocAttachAccountPayload,\n EdocGetTransactionsPayload,\n BankOption,\n IndustrialSectorOption,\n} from './types/edoc'\n\nexport function install(_app: App): void {\n // Components can be registered here for app.use() when consuming this package\n}\n\nexport default {\n install,\n}\n"],"names":["_createElementBlock","_normalizeClass","__props","_renderSlot","_ctx","cn","classes","baseClasses","variantClasses","sizeClasses","buttonVariants","options","variant","size","props","_unref","edocApi","otpActionClass","edocPath","path","b","p","emit","__emit","generatingStatement","ref","submittingOtp","bankNames","bankCode","o","matchBank","enabledOnly","names","code","name","n","_a","getEdocBank","isBankEdocSupported","hasBankInstructions","computed","_b","canRequestOtp","a","canSubmitOtp","errMsg","e","_c","consentPayload","email","consentAndAttach","edocBank","res","data","consentId","generateStatement","err","submitOtp","retrieveStatementDirect","_openBlock","_hoisted_1","_hoisted_2","_Fragment","_createElementVNode","_hoisted_3","_cache","_hoisted_4","_renderList","instruction","idx","_createVNode","BoiButton","_hoisted_6","_hoisted_7","_hoisted_8","$event","_vModelText","_hoisted_9","_hoisted_5","_hoisted_10","_hoisted_11","toBanksList","d","raw","resolveUrl","u","fallback","useEdocBanks","get","getBanksUrl","fallbackBanksUrl","edocBanksCache","banksCache","loadingBanks","errorBanks","banksPromise","list","fallbackUrl","verificationStates","useAccountVerification","verifyBankAccount","getVerifyFn","getVerificationKey","account","getVerificationState","key","clearAccountName","handleAccountVerification","accountNumber","fn","result","defaultPrefix","bankStatementsUrls","applicationId","baseUrl","prefix","id","statementId","bankStatementsApi","base","filesApi","isOpen","selectRef","searchRef","searchQuery","highlightedIndex","optionMatchesQuery","opt","q","parts","tokens","t","filteredOptions","selectedOption","displayValue","toggle","nextTick","select","onKeydown","opts","onClickOutside","watch","onMounted","onUnmounted","_toDisplayString","option","index","fileInput","uploading","fileName","errorMessage","typeMap","extToMime","allowedFormatsDisplay","maxSizeMB","isDisabled","viewApiBaseNorm","effectiveViewStoragePath","fromProp","viewFileUrl","validate","file","msg","ext","m","handleChange","target","url","formData","_d","openDialog","v","withIntegrationOrigin","edocBanks","loadBanksForStatement","loadingEdocBanks","edocBanksError","retryVerification","activeIndex","showEdocBanksList","rootRef","onFocusIn","onFocusOut","el","bankStatements","loadingStatements","pollTimer","statementsUrlPrefix","urls","fileUploadUrl","fileViewApiBase","limitedStatements","canAddAccount","canRemoveAccount","companyEmail","getIndustrialSectorName","s","isEdocCsvStorageKey","initialUploadedStatementPath","bankStatement","statementViewStoragePath","onStatementFileUploaded","statement","saveStatement","getStatementLabel","bank","num","getStatusClass","status","map","loadBankStatements","syncStatementsFromPoll","fields","existing","apiRow","updates","uploadedPath","incoming","startPolling","stopPolling","hasProcessing","handleAddAccount","tempId","newRecord","handleRemoveAccount","removedIndex","removed","isOptimistic","onConsentId","onStatementRetrieved","updated","onEdocError","clearError","createAfterUpload","filePath","sector","unblockAfterDelay","preservedPdfPath","codeMatch","nameMatch","enabledEdocBanksList","_createTextVNode","_hoisted_12","_hoisted_13","_hoisted_14","_hoisted_16","BankSelect","_hoisted_19","_hoisted_20","_hoisted_21","_hoisted_22","_hoisted_23","_hoisted_24","_hoisted_25","EmtsIntegration","_hoisted_26","_hoisted_27","FileInput","body","_hoisted_28","_hoisted_29","_hoisted_30","_hoisted_31","_hoisted_32","_hoisted_33","_hoisted_34","_vShow","_hoisted_35","Button","install","_app"],"mappings":"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"}
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.2.0",
6
+ "version": "0.2.1",
7
7
  "description": "BOI Vue 3 TypeScript UI package",
8
8
  "type": "module",
9
9
  "keywords": [