feat: non-individual entity UI improvements — hide individual-only sections, fix legal form display, send extended fields to API
- Hide Family Members tab/section for non-individual entities in client view, create flow, and preview - Hide Financial & Classification section for non-individual entities in personal data and preview - Fix legal form column in clients list — fetch legalForm from client API for correct display - Add person/business icon before client name in list rows - Remove unsupportedNpd filter — send authorizedSignatory, additionalInfo, dateOfRegistration to API - Add registration number format hint (mat-hint) based on constitution type - Add spacing between verification row and constitution type dropdowns - Reduce table cell padding and prevent action buttons from being clipped - Add missing MPL-2.0 license headers Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
ab01111424
commit
b890d24bb7
+158
-141
@@ -6,179 +6,196 @@
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
-->
|
||||
|
||||
<!-- Modern Glassmorphism Login with Animated Gradient Background -->
|
||||
<div class="login-wrapper">
|
||||
<!-- Animated Gradient Background -->
|
||||
<div class="gradient-bg">
|
||||
<div class="gradient-orb orb-1"></div>
|
||||
<div class="gradient-orb orb-2"></div>
|
||||
<div class="gradient-orb orb-3"></div>
|
||||
<div class="gradient-orb orb-4"></div>
|
||||
</div>
|
||||
<div class="login-page">
|
||||
<div class="login-split">
|
||||
|
||||
<!-- Settings Icon - Top Right -->
|
||||
<button
|
||||
class="settings-trigger"
|
||||
(click)="toggleSettingsPanel()"
|
||||
matTooltip="Settings"
|
||||
attr.aria-label="Settings"
|
||||
>
|
||||
<mifosx-m3-icon [name]="settingsPanelOpen ? 'close' : 'settings'"></mifosx-m3-icon>
|
||||
</button>
|
||||
<!-- ══ LEFT PANEL — SLIDER ══ -->
|
||||
<div class="left-panel">
|
||||
<div class="left-panel__dots-bg"></div>
|
||||
|
||||
<!-- Settings Popup Panel -->
|
||||
@if (settingsPanelOpen) {
|
||||
<div class="settings-overlay" (click)="toggleSettingsPanel()"></div>
|
||||
<div class="settings-panel" @settingsAnimation>
|
||||
<div class="settings-panel-header">
|
||||
<h3 class="settings-title">
|
||||
<mifosx-m3-icon name="tune"></mifosx-m3-icon>
|
||||
{{ 'labels.heading.Settings' | translate }}
|
||||
</h3>
|
||||
</div>
|
||||
<div class="settings-panel-body">
|
||||
<!-- Theme Toggle -->
|
||||
<div class="settings-item">
|
||||
<span class="settings-label">
|
||||
<mifosx-m3-icon name="dark_mode"></mifosx-m3-icon>
|
||||
{{ 'labels.heading.Theme' | translate }}
|
||||
</span>
|
||||
<mifosx-theme-toggle></mifosx-theme-toggle>
|
||||
</div>
|
||||
<!-- Slides -->
|
||||
<div class="slides-wrap">
|
||||
@for (slide of slides; track slide.tag; let i = $index) {
|
||||
<div class="slide" [class.active]="currentSlide === i" [ngClass]="'s' + (i + 1)">
|
||||
<div class="slide__glow"></div>
|
||||
<span class="slide__tag"><span class="slide__pulse"></span>{{ slide.tag }}</span>
|
||||
|
||||
<!-- Language Selector -->
|
||||
<div class="settings-item">
|
||||
<span class="settings-label">
|
||||
<mifosx-m3-icon name="language"></mifosx-m3-icon>
|
||||
{{ 'labels.heading.Language' | translate }}
|
||||
</span>
|
||||
<mifosx-language-selector appearance="outline" [showLabel]="false"></mifosx-language-selector>
|
||||
</div>
|
||||
<!-- LincShield SVG for FRM slide -->
|
||||
@if (i === 1) {
|
||||
<div class="lincshield-logo">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 180" width="420" height="100">
|
||||
<defs>
|
||||
<linearGradient id="blueGD2" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#4D90E8"/><stop offset="100%" style="stop-color:#2563C8"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="greenGD2" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#34D05C"/><stop offset="100%" style="stop-color:#28B84E"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="shieldGD2" x1="0%" y1="0%" x2="60%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#34D05C"/><stop offset="100%" style="stop-color:#1A9040"/>
|
||||
</linearGradient>
|
||||
<filter id="glow3">
|
||||
<feGaussianBlur stdDeviation="3" result="b"/>
|
||||
<feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
|
||||
</filter>
|
||||
</defs>
|
||||
<path d="M14 22 Q14 19 17 17 L44 8 Q47 7 50 8 L77 17 Q80 19 80 22 L80 72 Q80 100 47 114 Q14 100 14 72 Z" fill="url(#shieldGD2)" filter="url(#glow3)"/>
|
||||
<path d="M22 28 Q22 26 24 25 L46 18 Q48 17 50 18 L72 25 Q74 26 74 28 L74 71 Q74 93 47 105 Q20 93 20 71 Z" fill="none" stroke="rgba(255,255,255,0.15)" stroke-width="1.5"/>
|
||||
<path d="M33 65 L44 76 L66 50" stroke="white" stroke-width="6" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
|
||||
<path d="M35 42 Q47 34 59 42" stroke="rgba(255,255,255,0.7)" stroke-width="3" stroke-linecap="round" fill="none"/>
|
||||
<polygon points="59,37 59,47 65,42" fill="rgba(255,255,255,0.7)"/>
|
||||
<text x="98" y="105" font-family="Georgia, 'Times New Roman', serif" font-size="96" font-weight="900" font-style="italic" fill="url(#blueGD2)" letter-spacing="-2">Linc</text>
|
||||
<path d="M334 48 Q344 35 358 46" stroke="#34D05C" stroke-width="6.5" stroke-linecap="round" fill="none"/>
|
||||
<polygon points="356,38 362,50 350,49" fill="#34D05C"/>
|
||||
<text x="356" y="105" font-family="Georgia, 'Times New Roman', serif" font-size="96" font-weight="900" font-style="italic" fill="url(#greenGD2)" letter-spacing="-2">Shield</text>
|
||||
<line x1="98" y1="122" x2="752" y2="122" stroke="#1a2d47" stroke-width="1"/>
|
||||
<text x="98" y="148" font-family="'Trebuchet MS', 'Segoe UI', sans-serif" font-size="18" font-weight="700" letter-spacing="6" fill="#4D90E8">LINK</text>
|
||||
<circle cx="178" cy="140" r="3" fill="#34D05C"/>
|
||||
<text x="190" y="148" font-family="'Trebuchet MS', 'Segoe UI', sans-serif" font-size="18" font-weight="700" letter-spacing="6" fill="#8899bb">DETECT</text>
|
||||
<circle cx="312" cy="140" r="3" fill="#34D05C"/>
|
||||
<text x="324" y="148" font-family="'Trebuchet MS', 'Segoe UI', sans-serif" font-size="18" font-weight="700" letter-spacing="6" fill="#34D05C">PROTECT.</text>
|
||||
</svg>
|
||||
</div>
|
||||
} @else {
|
||||
<span class="slide__icon">{{ slide.icon }}</span>
|
||||
}
|
||||
|
||||
<!-- Server Selector -->
|
||||
@if (allowServerSwitch()) {
|
||||
<div class="settings-item">
|
||||
<span class="settings-label">
|
||||
<mifosx-m3-icon name="dns"></mifosx-m3-icon>
|
||||
{{ 'labels.heading.Server' | translate }}
|
||||
</span>
|
||||
<mifosx-server-selector appearance="outline" [showLabel]="false"></mifosx-server-selector>
|
||||
<h2 class="slide__title" [innerHTML]="slide.title"></h2>
|
||||
<p class="slide__desc">{{ slide.desc }}</p>
|
||||
<div class="slide__stats">
|
||||
@for (stat of slide.stats; track stat.label) {
|
||||
<div class="stat-chip">
|
||||
<div class="stat-chip__value">{{ stat.value }}</div>
|
||||
<div class="stat-chip__label">{{ stat.label }}</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<!-- Flow diagram -->
|
||||
<div class="slide__flow">
|
||||
@for (node of slide.flow; track node; let last = $last) {
|
||||
<div class="flow-node">{{ node }}</div>
|
||||
@if (!last) {
|
||||
<div class="flow-arrow"></div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="settings-panel-footer">
|
||||
<button
|
||||
mat-button
|
||||
(click)="reloadSettings()"
|
||||
class="reload-settings-btn"
|
||||
>
|
||||
<mifosx-m3-icon name="refresh"></mifosx-m3-icon>
|
||||
{{ 'labels.buttons.Reload' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- Floating Glass Login Card -->
|
||||
<div class="glass-card-container">
|
||||
<div class="glass-card" @cardAnimation>
|
||||
<!-- Logo Section -->
|
||||
<div class="logo-section">
|
||||
@if (!themeDarkEnabled) {
|
||||
<img [src]="logoPath" (error)="onLogoError()" alt="{{ 'APP_NAME' | translate }} Logo" class="logo-image" />
|
||||
} @else {
|
||||
<img
|
||||
[src]="logoPathDark"
|
||||
(error)="onLogoErrorDark()"
|
||||
alt="{{ 'APP_NAME' | translate }} Logo"
|
||||
class="logo-image"
|
||||
/>
|
||||
<!-- Nav dots -->
|
||||
<div class="slide-nav">
|
||||
@for (slide of slides; track slide.tag; let i = $index) {
|
||||
<button class="slide-dot" [class.active]="currentSlide === i" (click)="goToSlide(i)"></button>
|
||||
}
|
||||
</div>
|
||||
<div class="slide-progress" [style.animation-duration]="slideDuration + 'ms'"></div>
|
||||
</div>
|
||||
|
||||
<!-- Welcome Text -->
|
||||
<div class="welcome-section">
|
||||
<h1 class="welcome-title">{{ 'labels.heading.Welcome Back' | translate }}</h1>
|
||||
<p class="welcome-subtitle">{{ 'labels.text.Sign in to continue' | translate }}</p>
|
||||
</div>
|
||||
<!-- ══ RIGHT PANEL — LOGIN ══ -->
|
||||
<div class="right-panel">
|
||||
|
||||
<!-- Tenant Selector -->
|
||||
@if (showTenantSelector) {
|
||||
<div class="tenant-section">
|
||||
<mifosx-tenant-selector></mifosx-tenant-selector>
|
||||
<!-- Settings trigger -->
|
||||
<button class="settings-btn" (click)="toggleSettingsPanel()" matTooltip="Settings">
|
||||
<mifosx-m3-icon [name]="settingsPanelOpen ? 'close' : 'settings'"></mifosx-m3-icon>
|
||||
</button>
|
||||
|
||||
<!-- Settings panel -->
|
||||
@if (settingsPanelOpen) {
|
||||
<div class="settings-overlay" (click)="toggleSettingsPanel()"></div>
|
||||
<div class="settings-panel" @settingsAnimation>
|
||||
<div class="settings-panel__header">
|
||||
<mifosx-m3-icon name="tune"></mifosx-m3-icon>
|
||||
<h3>{{ 'labels.heading.Settings' | translate }}</h3>
|
||||
</div>
|
||||
<div class="settings-panel__body">
|
||||
@if (showTenantSelector) {
|
||||
<div class="settings-item">
|
||||
<span class="settings-item__label">
|
||||
<mifosx-m3-icon name="domain"></mifosx-m3-icon>
|
||||
{{ 'labels.inputs.Tenant' | translate }}
|
||||
</span>
|
||||
<mifosx-tenant-selector></mifosx-tenant-selector>
|
||||
</div>
|
||||
}
|
||||
<div class="settings-item">
|
||||
<span class="settings-item__label">
|
||||
<mifosx-m3-icon name="dark_mode"></mifosx-m3-icon>
|
||||
{{ 'labels.heading.Theme' | translate }}
|
||||
</span>
|
||||
<mifosx-theme-toggle></mifosx-theme-toggle>
|
||||
</div>
|
||||
<div class="settings-item">
|
||||
<span class="settings-item__label">
|
||||
<mifosx-m3-icon name="language"></mifosx-m3-icon>
|
||||
{{ 'labels.heading.Language' | translate }}
|
||||
</span>
|
||||
<mifosx-language-selector appearance="outline" [showLabel]="false"></mifosx-language-selector>
|
||||
</div>
|
||||
@if (allowServerSwitch()) {
|
||||
<div class="settings-item">
|
||||
<span class="settings-item__label">
|
||||
<mifosx-m3-icon name="dns"></mifosx-m3-icon>
|
||||
{{ 'labels.heading.Server' | translate }}
|
||||
</span>
|
||||
<mifosx-server-selector appearance="outline" [showLabel]="false"></mifosx-server-selector>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- Brand -->
|
||||
<div class="brand">
|
||||
<div class="brand__logo">
|
||||
@if (!themeDarkEnabled) {
|
||||
<img [src]="logoPath" (error)="onLogoError()" alt="{{ 'APP_NAME' | translate }}" />
|
||||
} @else {
|
||||
<img [src]="logoPathDark" (error)="onLogoErrorDark()" alt="{{ 'APP_NAME' | translate }}" />
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Welcome -->
|
||||
<div class="welcome">
|
||||
<h2>{{ 'labels.heading.Welcome Back' | translate }}</h2>
|
||||
<p>{{ 'labels.text.Sign in to continue' | translate }}</p>
|
||||
</div>
|
||||
|
||||
<!-- Login Forms -->
|
||||
@if (!resetPassword && !twoFactorAuthenticationRequired) {
|
||||
<mifosx-login-form></mifosx-login-form>
|
||||
}
|
||||
|
||||
@if (resetPassword) {
|
||||
<mifosx-reset-password></mifosx-reset-password>
|
||||
}
|
||||
|
||||
@if (twoFactorAuthenticationRequired) {
|
||||
<mifosx-two-factor-authentication></mifosx-two-factor-authentication>
|
||||
}
|
||||
|
||||
<!-- Version Info Section -->
|
||||
<div class="login-version-info" *ngIf="displayBackendInfo"></div>
|
||||
|
||||
<!-- Branding Footer -->
|
||||
@if (!productionMode) {
|
||||
<div class="card-footer">
|
||||
<span class="footer-text">
|
||||
{{ 'APP_NAME' | translate }}
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
<div class="right-footer">
|
||||
RBI Licensed · PCI-DSS Compliant · ISO 27001 Certified
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="login-footer">
|
||||
<span>🇮🇳</span>
|
||||
<span class="login-footer__text">
|
||||
Compliant with guidelines issued by
|
||||
<strong>Institute for Development and Research in Banking Technology (IDRBT)</strong>
|
||||
— Established by Reserve Bank of India
|
||||
</span>
|
||||
<span class="login-footer__sep">|</span>
|
||||
<span class="login-footer__text">© 2025 {{ 'APP_NAME' | translate }}. All rights reserved.</span>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<!-- Resource Menus (kept for compatibility) -->
|
||||
<mat-menu #resourcesMenu="matMenu" class="modern-menu">
|
||||
<mat-menu #resourcesMenu="matMenu">
|
||||
<a [href]="'userManual' | documentationLink" target="_blank" rel="noopener noreferrer" mat-menu-item>
|
||||
<fa-icon icon="book-open" class="menu-icon"></fa-icon>
|
||||
{{ 'labels.links.User Manual' | translate }}
|
||||
</a>
|
||||
<a [href]="'fineractFunctionalSpecs' | documentationLink" target="_blank" rel="noopener noreferrer" mat-menu-item>
|
||||
<fa-icon icon="file-alt" class="menu-icon"></fa-icon>
|
||||
{{ 'labels.links.Functional Specifications' | translate }}
|
||||
</a>
|
||||
<a [href]="'fineractContributorZone' | documentationLink" target="_blank" rel="noopener noreferrer" mat-menu-item>
|
||||
<fa-icon icon="code" class="menu-icon"></fa-icon>
|
||||
{{ 'labels.links.Developer Zone' | translate }}
|
||||
</a>
|
||||
</mat-menu>
|
||||
|
||||
<mat-menu #communityMenu="matMenu" class="modern-menu">
|
||||
<a [href]="'mifosUserGroup' | documentationLink" target="_blank" rel="noopener noreferrer" mat-menu-item>
|
||||
<fa-icon icon="users" class="menu-icon"></fa-icon>
|
||||
{{ 'labels.links.User Group' | translate }}
|
||||
</a>
|
||||
<a [href]="'mifosDeveloperGroup' | documentationLink" target="_blank" rel="noopener noreferrer" mat-menu-item>
|
||||
<fa-icon icon="laptop-code" class="menu-icon"></fa-icon>
|
||||
{{ 'labels.links.Developer Group' | translate }}
|
||||
</a>
|
||||
<a [href]="'mifosIrc' | documentationLink" target="_blank" rel="noopener noreferrer" mat-menu-item>
|
||||
<fa-icon icon="comments" class="menu-icon"></fa-icon>
|
||||
{{ 'labels.links.IRC' | translate }}
|
||||
</a>
|
||||
</mat-menu>
|
||||
|
||||
<mat-menu #contributeMenu="matMenu" class="modern-menu">
|
||||
<a [href]="'keyDesignPrinciples' | documentationLink" target="_blank" rel="noopener noreferrer" mat-menu-item>
|
||||
<fa-icon icon="lightbulb" class="menu-icon"></fa-icon>
|
||||
{{ 'labels.links.Key Design Principles' | translate }}
|
||||
</a>
|
||||
<a [href]="'sourceforgeMifos' | documentationLink" target="_blank" rel="noopener noreferrer" mat-menu-item>
|
||||
<fa-icon icon="code-branch" class="menu-icon"></fa-icon>
|
||||
{{ 'labels.links.Working with Code' | translate }}
|
||||
</a>
|
||||
<a [href]="'mifosDonate' | documentationLink" target="_blank" rel="noopener noreferrer" mat-menu-item>
|
||||
<fa-icon icon="hand-holding-heart" class="menu-icon"></fa-icon>
|
||||
{{ 'labels.links.Donate' | translate }}
|
||||
</a>
|
||||
</mat-menu>
|
||||
|
||||
Reference in New Issue
Block a user