Files
cbsnexora/src/app/loan-origination/application-detail/field-visit-details-dialog/field-visit-details-dialog.component.scss
T
niteshandClaude Sonnet 5 c18219fce5
build-run / Run Lint, Build and Deploy (push) Canceled after 0s
Publish Image in Docker Hub / build (push) Canceled after 0s
Playwright E2E Tests / Run Playwright Tests (push) Canceled after 0s
Tests / testRigor (push) Canceled after 0s
feat(loan-origination): persist the sanctioning pipeline to the backend
Replaces the in-memory mock (LOAN_APPLICATIONS array + seeded RNG, reset on
every refresh) with real Fineract-backed persistence: a new
LoanOriginationService for CRUD plus one API call per stage transition, a
loan-fineract-bridge that creates a real loan account (create + approve +
disburse) at disbursement for Existing Customers, and file uploads through
Fineract's generic document store keyed by a stable checklist slot so
"On file"/View controls survive a reload.

Also fixes several gaps found while verifying full-cycle persistence:
- CIC charge-account selection never saved (missing persist() call)
- Co-borrower relationship/monthly income lived in local-only component state
  instead of on the application, so they reset on refresh
- Field Investigation "View Full Details" showed local-session photos only;
  stored photos are now downloaded and shown as real thumbnails
- "Assign Field Officer" was free text; now a dropdown of real CBS loan
  officers pulled from /staff
- site photos and cheque/signature images now open in the same zoomable,
  pannable lightgallery viewer used elsewhere in the app

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-17 17:05:05 +05:30

139 lines
2.2 KiB
SCSS

/**
* Copyright since 2025 Mifos Initiative
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
.fvd-content {
min-width: 420px;
max-width: 640px;
display: flex;
flex-direction: column;
gap: 14px;
}
.fvd-badge {
display: inline-flex;
align-items: center;
align-self: flex-start;
padding: 5px 14px;
border-radius: 999px;
font-size: 12px;
font-weight: 800;
letter-spacing: 0.05em;
&--verified {
background: #d1fae5;
color: #047857;
}
&--failed {
background: #fee2e2;
color: #b91c1c;
}
&--pending {
background: #fef3c7;
color: #b45309;
}
}
.fvd-kv-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
gap: 12px 18px;
margin: 0;
}
.fvd-kv-field {
display: flex;
flex-direction: column;
gap: 3px;
dt {
font-size: 10px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.05em;
color: #94a3b8;
}
dd {
margin: 0;
font-size: 13.5px;
font-weight: 600;
color: #1e293b;
}
}
.fvd-photos-title {
margin: 0;
font-size: 12.5px;
font-weight: 700;
color: #334155;
}
.fvd-photo-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
gap: 10px;
}
.fvd-photo {
height: 90px;
border-radius: 10px;
border: 1px solid #e2e8f0;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
background: #f8fafc;
padding: 0;
margin: 0;
font: inherit;
cursor: default;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
.fvd-photo--stored {
&:hover {
border-color: #94a3b8;
background: #f1f5f9;
}
}
// Any tile that opens the zoomable lightbox on click -- local captures and stored photos alike.
.fvd-photo--zoomable {
cursor: zoom-in;
&:hover {
border-color: #94a3b8;
}
}
.fvd-lightbox-root {
display: none;
}
.fvd-photo-label {
font-size: 11px;
color: #64748b;
padding: 0 6px;
text-align: center;
word-break: break-word;
}
.fvd-no-photos {
margin: 0;
font-size: 12.5px;
color: #64748b;
line-height: 1.5;
}