@php $applicationFormInModal = request()->header('Turbo-Frame') === 'loan-form-modal'; $leanAskMode = $leanAskMode ?? 'create'; $askLocked = (bool) ($askLocked ?? false); $askAmountLocked = (bool) ($askAmountLocked ?? $askLocked); $feeAttachMode = (bool) ($feeAttachMode ?? ($leanAskMode === 'fee_attach')); $feeFundingLocked = (bool) ($feeFundingLocked ?? false); $wizardStep = 1; if ($feeAttachMode) { $wizardStep = 3; } elseif ($errors->any()) { $bag = $errors->keys(); $step3Keys = array_filter($bag, static fn ($k) => str_starts_with((string) $k, 'applicant_') || str_starts_with((string) $k, 'suspense_') || in_array((string) $k, ['wallet_fee_amount', 'application_date'], true)); $step2Keys = array_filter($bag, static fn ($k) => in_array((string) $k, [ 'product_name', 'amount_requested', 'term_unit', 'term_value', 'interest_rate', 'notes', 'purpose', ], true) || str_starts_with((string) $k, 'custom_') || str_starts_with((string) $k, 'biodata_')); if ($step3Keys !== []) { $wizardStep = 3; } elseif ($step2Keys !== []) { $wizardStep = 2; } else { $wizardStep = 1; } } $wizardShowNavActions = ! $feeAttachMode && $wizardStep < 3; $wizardShowFinalActions = $feeAttachMode || $wizardStep >= 3; $draftId = (int) old('draft_id', $draftApplication?->id ?? 0); $modalTitle = $applicationFormInModal ? ($feeAttachMode && $draftId > 0 && ($draftApplication ?? null) ? 'Attach fees · '.($draftApplication->reference ?? 'Application') : ($draftId > 0 && ($draftApplication ?? null) ? 'Resume draft · '.($draftApplication->reference ?? 'Application') : (($lockPrefilledClient ?? false) && ($prefilledClient ?? null) ? 'Loan application · '.($prefilledClient->full_name ?? 'Client') : 'Loan application'))) : $title; $showPendingDraftsPicker = ! $feeAttachMode && $draftId <= 0 && ($pendingDrafts ?? collect())->isNotEmpty(); $feeAttachFormAction = ($feeAttachMode && $draftApplication) ? route('loan.book.applications.attach_fees', $draftApplication) : route('loan.book.applications.store'); @endphp @php $mapped = $loanFormMappedFields ?? []; $mappedBookingSegments = $mappedBookingFieldDisplaySegments ?? []; $createFeeMeta = (array) ($draftApplication?->form_meta ?? []); // Prefer live linked-payment coverage over stale form_meta (product fee changes after disbursement). // In fee-attach mode never pretends fees are covered from stale meta — operator must select funding. $createFeesFulfilled = ($feeAttachMode ?? false) ? false : ($draftApplication ? app(\App\Services\Loan\ApplicationOriginationGateService::class)->applicationFeesAreCovered($draftApplication) : false); $createFeeAttachedPayments = collect((array) data_get($createFeeMeta, 'fee_selected_payments', [])) ->filter(static fn ($row): bool => is_array($row) && (int) ($row['id'] ?? 0) > 0) ->map(static function (array $row): array { $id = (int) $row['id']; $amount = round((float) ($row['amount'] ?? 0), 2); $reference = (string) ($row['reference'] ?? ('PAY-#'.$id)); return [ 'id' => $id, 'amount' => $amount, 'reference' => $reference, 'label' => $reference.' | '.number_format($amount, 2).' (already attached)', 'payment_kind' => (string) ($row['payment_kind'] ?? 'attached'), 'status' => 'attached', 'channel' => '', 'transaction_at' => '', ]; }) ->values() ->all(); // If meta payments list is empty but pay-ins are linked, surface them for the fee UI. if ($createFeesFulfilled && $createFeeAttachedPayments === [] && $draftApplication) { $createFeeAttachedPayments = \App\Models\LoanBookPayment::query() ->where('loan_book_application_id', $draftApplication->id) ->whereNull('merged_into_payment_id') ->orderBy('id') ->get(['id', 'amount', 'reference', 'payment_kind']) ->map(static function ($payment): array { $id = (int) $payment->id; $amount = round((float) $payment->amount, 2); $reference = (string) ($payment->reference ?? ('PAY-#'.$id)); return [ 'id' => $id, 'amount' => $amount, 'reference' => $reference, 'label' => $reference.' | '.number_format($amount, 2).' (already attached)', 'payment_kind' => (string) ($payment->payment_kind ?? 'attached'), 'status' => 'attached', 'channel' => '', 'transaction_at' => '', ]; }) ->values() ->all(); } $createFeeWalletAmount = round((float) old( 'wallet_fee_amount', data_get($createFeeMeta, 'fee_wallet_funding_amount', 0) ), 2); @endphp
$applicationFormInModal, 'max-w-7xl grid-cols-1 xl:grid-cols-[minmax(0,1.1fr)_minmax(0,1.4fr)]' => ! $applicationFormInModal, ]) x-data="loanProductPicker( @js($productMetaByName ?? []), @js((string) old('term_unit', $draftApplication?->term_unit ?? '')), @js(old('suspense_payment_ids', (array) data_get( $draftApplication?->form_meta, 'fee_selected_payment_ids', array_values(array_filter([data_get($draftApplication?->form_meta, 'fee_selected_payment_id')])) ))), @js((int) ($showPendingDraftsPicker ? ($pendingDrafts ?? collect())->count() : 0)), @js($productFieldConfig ?? []), @js($clientLookupUrl ?? ''), @js((bool) ($lockPrefilledClient ?? false)), @js((string) old('loan_client_id', $draftApplication?->loan_client_id ?? $selectedClientId ?? '')), @js(route('loan.tools.discover_products')), @js((string) old('product_name', $draftApplication?->product_name ?? $defaultProductName ?? '')), @js((bool) ($guarantorRequiredForSubmit ?? false)), @js((int) ($guarantorCount ?? 0)), @js((bool) ($purposeRequiredForSubmit ?? false)), @js((bool) ($applicantOtpRequired ?? false)), @js((bool) $applicationFormInModal) )" data-products-store-url="{{ route('loan.book.applications.products.store') }}" data-suspense-options-url="{{ route('loan.book.applications.suspense_options') }}" data-discover-products-url="{{ route('loan.tools.discover_products') }}" data-product-bootstrap-url="{{ route('loan.book.applications.product_bootstrap') }}" data-lean-ask="1" data-lean-ask-wizard="{{ $feeAttachMode ? '0' : '1' }}" data-lean-ask-modal="{{ $applicationFormInModal ? '1' : '0' }}" data-wizard-step="{{ (int) $wizardStep }}" @if ($feeAttachMode) data-fee-attach-mode="1" @endif data-fees-fulfilled="{{ $createFeesFulfilled ? '1' : '0' }}" data-fee-wallet-amount="{{ $createFeeWalletAmount }}" data-fee-attached-payments='@json($createFeeAttachedPayments)' data-allow-concurrent-individual-loans="{{ ($allowConcurrentIndividualLoans ?? false) ? '1' : '0' }}" data-allow-balance-checkoff="{{ ($allowBalanceCheckoff ?? false) ? '1' : '0' }}" data-initial-active-loan-handling="{{ old('active_loan_handling', data_get($draftApplication?->form_meta, 'active_loan_handling', '')) }}" data-initial-requested-amount="{{ old('amount_requested', $draftApplication?->amount_requested ?? '') }}" > @if ($showPendingDraftsPicker)

Incomplete applications ()

Saved drafts or applications awaiting fee coverage.

Resume a saved draft without losing your place.

@if(($pendingDrafts ?? collect())->isNotEmpty()) @endif
@endif
@csrf @if ($applicationFormInModal) @endif @if ($feeAttachMode) {{-- Anchors for fee JS (panels 1–2 are hidden in fee-attach mode). --}} @endif
@include('loan.book.applications.partials.lean-ask.header')
@if ($feeAttachMode)
Fee attach only — client, product, amount, and certification stay locked. Select unposted pay-ins or wallet below.
@endif @unless ($feeAttachMode)

Step of

@endunless @include('loan.partials.modal-validation-alert', [ 'title' => __('Application could not be saved. Fix the issues below and try again.'), 'sticky' => $applicationFormInModal, 'id' => 'loan-application-validation-summary', ]) @if ($draftId <= 0 && ! empty($prefillEligibilityWarnings))

Eligibility notice

@if (($lockPrefilledClient ?? false) && ($prefilledClient ?? null) && auth()->user()?->hasLoanPermission('clients.update')) Update lending profile @endif
    @foreach ($prefillEligibilityWarnings as $warning)
  • {{ $warning }}
  • @endforeach
@endif @unless ($feeAttachMode)
@include('loan.book.applications.partials.lean-ask.client-selection')

Select a client to continue — readiness and fees depend on who you pick.

@include('loan.book.applications.partials.lean-ask.loan-request', [ 'purposeRequiredForSubmit' => $purposeRequiredForSubmit ?? false, ]) @if (config('loan_backdating.enabled'))
@error('application_date')

{{ $message }}

@enderror
@endif
@endunless
@unless ($feeAttachMode) @include('loan.book.applications.partials.spouse-consent', [ 'draftApplication' => $draftApplication ?? null, 'prefilledClient' => $prefilledClient ?? $draftApplication?->loanClient ?? null, ]) @include('loan.book.applications.partials.applicant-certification', [ 'draftApplication' => $draftApplication ?? null, 'prefilledClient' => $prefilledClient ?? $draftApplication?->loanClient ?? null, 'forceApplicantCertificationOpen' => true, 'applicantOtpRequired' => $applicantOtpRequired ?? false, 'applicantSignatureRequired' => $applicantSignatureRequired ?? false, ]) @endunless

Pre-booking fees

Required before this application can be saved. Extra pay-in stays Unposted.

Fetching configured fees, wallet balance, and unposted payments…

No pre-booking fee is configured for this product.

@include('loan.book.applications.partials.fee-funding-sources', [ 'draftApplication' => $draftApplication ?? null, 'askLocked' => $askLocked ?? false, 'feeFundingLocked' => $feeFundingLocked, 'feeFundingCompact' => true, 'feeAttachMode' => $feeAttachMode, ])
@unless ($feeAttachMode) @endunless