diff --git a/src/app/deposits/fixed-deposits/fixed-deposit-account-view/custom-dialogs/payment-dialog/payment-dialog.component.html b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/custom-dialogs/payment-dialog/payment-dialog.component.html
index 659f79528..34a510e7f 100644
--- a/src/app/deposits/fixed-deposits/fixed-deposit-account-view/custom-dialogs/payment-dialog/payment-dialog.component.html
+++ b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/custom-dialogs/payment-dialog/payment-dialog.component.html
@@ -8,11 +8,24 @@
diff --git a/src/app/deposits/fixed-deposits/fixed-deposit-account-view/custom-dialogs/payment-dialog/payment-dialog.component.scss b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/custom-dialogs/payment-dialog/payment-dialog.component.scss
index 48967437c..a95aa35aa 100644
--- a/src/app/deposits/fixed-deposits/fixed-deposit-account-view/custom-dialogs/payment-dialog/payment-dialog.component.scss
+++ b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/custom-dialogs/payment-dialog/payment-dialog.component.scss
@@ -6,291 +6,404 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-$navy: #0d1b2a;
-$slate: #475569;
-$muted: #64748b;
-$border: #e2e8f0;
-$soft: #f8fafc;
-$blue: #1e40af;
-$blue-soft: #eff6ff;
-$green: #166534;
-$green-soft: #f0fdf4;
+/**
+ * Payment / Renewal Dialog Styles
+ * CBSNexora Core Banking System
+ */
.pmt {
display: flex;
flex-direction: column;
- min-height: 320px;
- max-height: 85vh;
+ height: 100%;
+ max-height: 92vh;
+ box-sizing: border-box;
+ font-family:
+ 'DM Sans',
+ system-ui,
+ -apple-system,
+ sans-serif;
+ color: #0f172a;
+ border-radius: 16px;
overflow: hidden;
- margin: -24px;
+ box-shadow: 0 24px 48px -12px rgb(15 23 42 / 25%);
}
.pmt__header {
- display: flex;
- align-items: flex-start;
- gap: 14px;
- padding: 22px 28px 18px;
- background: linear-gradient(135deg, #1e3a8a 0%, #1e40af 55%, #4338ca 100%);
- color: #fff;
- flex: 0 0 auto;
-}
-
-.pmt__header-ico {
- width: 40px;
- height: 40px;
- min-width: 40px;
- border-radius: 10px;
- background: rgb(255 255 255 / 15%);
display: flex;
align-items: center;
- justify-content: center;
- font-size: 18px;
+ justify-content: space-between;
+ gap: 16px;
+ padding: 26px 30px;
+ background: linear-gradient(135deg, #1e3a8a 0%, #1d4ed8 55%, #2563eb 100%);
+ color: #fff;
+ flex-shrink: 0;
+ position: relative;
+ overflow: hidden;
+
+ &::after {
+ content: '';
+ position: absolute;
+ inset: 0;
+ background: radial-gradient(circle at 88% -20%, rgb(255 255 255 / 22%), transparent 55%);
+ pointer-events: none;
+ }
+
+ &-left {
+ display: flex;
+ align-items: center;
+ gap: 16px;
+ position: relative;
+ z-index: 1;
+ }
+
+ &-ico {
+ width: 48px;
+ height: 48px;
+ border-radius: 14px;
+ background: rgb(255 255 255 / 16%);
+ border: 1px solid rgb(255 255 255 / 25%);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 20px;
+ color: #fff;
+ flex-shrink: 0;
+ }
+
+ &-text {
+ display: flex;
+ flex-direction: column;
+ }
+
+ &-close {
+ position: relative;
+ z-index: 1;
+ background: rgb(255 255 255 / 14%);
+ border: none;
+ color: #fff;
+ width: 34px;
+ height: 34px;
+ border-radius: 50%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ cursor: pointer;
+ transition: all 0.2s ease;
+ flex-shrink: 0;
+
+ &:hover:not(:disabled) {
+ background: rgb(255 255 255 / 28%);
+ transform: rotate(90deg);
+ }
+
+ &:disabled {
+ opacity: 0.5;
+ cursor: not-allowed;
+ }
+ }
}
.pmt__title {
margin: 0;
- font-size: 19px;
- font-weight: 700;
+ font-size: 20px;
+ font-weight: 800;
+ color: #fff;
+ line-height: 1.25;
+ letter-spacing: -0.01em;
}
.pmt__subtitle {
- margin: 4px 0 0;
- font-size: 12.5px;
- color: rgb(255 255 255 / 82%);
+ margin: 5px 0 0;
+ font-size: 13px;
+ color: rgb(255 255 255 / 88%);
line-height: 1.4;
}
.pmt__content {
- padding: 22px 28px 8px !important;
+ padding: 26px 30px !important;
overflow-y: auto;
flex: 1 1 auto;
+ background: #fbfcfe;
+
+ mat-form-field {
+ width: 100%;
+ }
}
.pmt__loading {
display: flex;
justify-content: center;
align-items: center;
- min-height: 260px;
+ min-height: 240px;
}
.pmt__stat {
display: flex;
flex-direction: column;
- gap: 2px;
- background: $blue-soft;
- border: 1px solid #dbeafe;
- border-radius: 10px;
- padding: 12px 16px;
+ gap: 4px;
+ background: linear-gradient(135deg, #eff6ff 0%, #e0e9ff 100%);
+ border: 1px solid #bfdbfe;
+ border-radius: 14px;
+ padding: 18px 22px;
margin-bottom: 18px;
-}
-.pmt__stat-label {
- font-size: 11px;
- font-weight: 700;
- text-transform: uppercase;
- letter-spacing: 0.05em;
- color: $blue;
-}
+ &-label {
+ font-size: 11.5px;
+ font-weight: 700;
+ text-transform: uppercase;
+ letter-spacing: 0.07em;
+ color: #1d4ed8;
+ }
-.pmt__stat-value {
- font-size: 22px;
- font-weight: 800;
- color: $navy;
- font-variant-numeric: tabular-nums;
-}
-
-.pmt__date {
- width: 100%;
+ &-value {
+ font-family: 'JetBrains Mono', 'DM Sans', monospace;
+ font-size: 28px;
+ font-weight: 800;
+ color: #0f172a;
+ letter-spacing: -0.01em;
+ }
}
.pmt__section-label {
- font-size: 11.5px;
+ font-size: 12px;
font-weight: 700;
text-transform: uppercase;
- letter-spacing: 0.05em;
- color: $slate;
- margin: 4px 0 10px;
+ letter-spacing: 0.06em;
+ color: #475569;
+ margin: 10px 0 12px;
}
+/* Action Options Grid - 2 Equal Columns, comfortably wide now that the dialog itself is wider */
.pmt__options {
display: grid;
- grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
- gap: 10px;
- margin-bottom: 6px;
+ grid-template-columns: repeat(2, 1fr);
+ gap: 14px;
+ margin-bottom: 18px;
+
+ @media (width <= 560px) {
+ grid-template-columns: 1fr;
+ }
}
.pmt__option {
display: flex;
align-items: flex-start;
- gap: 10px;
+ gap: 14px;
text-align: left;
background: #fff;
- border: 1.5px solid $border;
- border-radius: 10px;
- padding: 12px 14px;
+ border: 1.5px solid #e2e8f0;
+ border-radius: 14px;
+ padding: 16px;
cursor: pointer;
font: inherit;
- transition:
- border-color 0.15s,
- background 0.15s,
- box-shadow 0.15s;
-}
+ transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
+ position: relative;
-.pmt__option:hover {
- border-color: #93c5fd;
- background: $blue-soft;
-}
+ &:hover {
+ border-color: #93c5fd;
+ background: #f8fafc;
+ box-shadow: 0 6px 16px rgb(15 23 42 / 6%);
+ transform: translateY(-1px);
+ }
-.pmt__option--active {
- border-color: $blue;
- background: $blue-soft;
- box-shadow: 0 0 0 1px $blue;
-}
+ &--active {
+ border-color: #2563eb;
+ background: #eff6ff;
+ box-shadow: 0 0 0 1.5px #2563eb;
-.pmt__option-ico {
- width: 30px;
- height: 30px;
- min-width: 30px;
- border-radius: 8px;
- background: $soft;
- color: $blue;
- display: flex;
- align-items: center;
- justify-content: center;
- font-size: 13px;
-}
+ .pmt__option-ico {
+ background: #2563eb;
+ color: #fff;
+ border-color: #2563eb;
+ }
+ }
-.pmt__option--active .pmt__option-ico {
- background: $blue;
- color: #fff;
-}
+ &-ico {
+ width: 38px;
+ height: 38px;
+ min-width: 38px;
+ border-radius: 10px;
+ background: #f1f5f9;
+ border: 1px solid #e2e8f0;
+ color: #2563eb;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 15px;
+ flex-shrink: 0;
+ transition: all 0.2s ease;
+ }
-.pmt__option-text {
- display: flex;
- flex-direction: column;
- gap: 2px;
-}
+ // Distinct accent per option while unselected, purely presentational -- helps the four cards read
+ // apart at a glance. Selecting a card always fills its icon blue (see &--active above), matching the
+ // blue selection border/check regardless of which option it is, rather than mixing selection-blue
+ // with the option's own accent.
+ &:not(.pmt__option--active):nth-child(2) .pmt__option-ico {
+ color: #7c3aed;
+ }
-.pmt__option-title {
- font-size: 13px;
- font-weight: 700;
- color: $navy;
-}
+ &:not(.pmt__option--active):nth-child(3) .pmt__option-ico {
+ color: #0d9488;
+ }
-.pmt__option-desc {
- font-size: 11px;
- color: $muted;
- line-height: 1.35;
-}
+ &:not(.pmt__option--active):nth-child(4) .pmt__option-ico {
+ color: #d97706;
+ }
-.pmt__option:focus-visible {
- outline: 2px solid $blue;
- outline-offset: 2px;
-}
+ &-text {
+ display: flex;
+ flex-direction: column;
+ gap: 4px;
+ flex: 1;
+ }
-.pmt__option-check {
- margin-left: auto;
- color: $blue;
- font-size: 13px;
+ &-title {
+ font-size: 14px;
+ font-weight: 700;
+ color: #0f172a;
+ line-height: 1.3;
+ }
+
+ &-desc {
+ font-size: 12px;
+ color: #64748b;
+ line-height: 1.4;
+ }
+
+ &-check {
+ color: #2563eb;
+ font-size: 17px;
+ position: absolute;
+ top: 14px;
+ right: 14px;
+ }
}
.pmt__option-error {
color: #b91c1c;
font-size: 12px;
- margin: 4px 0 14px;
-}
-
-.pmt__error {
- display: flex;
- align-items: flex-start;
- gap: 4px;
- background: #fef2f2;
- border: 1px solid #fecaca;
- border-radius: 8px;
- color: #b91c1c;
- font-size: 12.5px;
- line-height: 1.45;
- padding: 10px 14px;
- margin: 4px 0 8px;
-}
-
-.pmt__hint {
- display: flex;
- align-items: flex-start;
- gap: 4px;
- background: $soft;
- border: 1px solid $border;
- border-radius: 8px;
- color: $slate;
- font-size: 12px;
- line-height: 1.45;
- padding: 9px 13px;
- margin: 0 0 10px;
-}
-
-.pmt__hint--warn {
- background: #fffbeb;
- border-color: #fde68a;
- color: #92400e;
+ font-weight: 600;
+ margin: -10px 0 14px;
}
.pmt__split {
display: flex;
align-items: center;
- gap: 12px;
- background: $soft;
+ gap: 16px;
+ background: #f8fafc;
border: 1px dashed #cbd5e1;
- border-radius: 10px;
- padding: 14px 16px 0;
- margin: 4px 0 8px;
+ border-radius: 14px;
+ padding: 18px;
+ margin: 10px 0 18px;
flex-wrap: wrap;
+
+ &-input {
+ flex: 1 1 220px;
+ }
+
+ &-arrow {
+ color: #94a3b8;
+ font-size: 17px;
+ }
+
+ &-remainder {
+ display: flex;
+ flex-direction: column;
+ gap: 3px;
+ background: #f0fdf4;
+ border: 1px solid #bbf7d0;
+ border-radius: 10px;
+ padding: 12px 16px;
+ flex: 1 1 220px;
+
+ &-label {
+ font-size: 11px;
+ font-weight: 700;
+ text-transform: uppercase;
+ letter-spacing: 0.04em;
+ color: #166534;
+ }
+
+ &-value {
+ font-family: 'JetBrains Mono', 'DM Sans', monospace;
+ font-size: 19px;
+ font-weight: 800;
+ color: #166534;
+ }
+ }
}
-.pmt__split-input {
- flex: 1 1 180px;
- min-width: 160px;
-}
-
-.pmt__split-arrow {
- color: $muted;
- font-size: 14px;
- margin-bottom: 20px;
-}
-
-.pmt__split-remainder {
+.pmt__hint {
display: flex;
- flex-direction: column;
- gap: 2px;
- background: $green-soft;
- border: 1px solid #bbf7d0;
- border-radius: 8px;
- padding: 8px 14px;
- margin-bottom: 14px;
- flex: 1 1 180px;
- min-width: 160px;
+ align-items: flex-start;
+ gap: 10px;
+ background: #f0f9ff;
+ border: 1px solid #bae6fd;
+ border-left: 4px solid #0284c7;
+ border-radius: 10px;
+ color: #0369a1;
+ font-size: 13px;
+ line-height: 1.5;
+ padding: 12px 16px;
+ margin: 0 0 18px;
+
+ &--warn {
+ background: #fffbeb;
+ border-color: #fde68a;
+ border-left-color: #d97706;
+ color: #b45309;
+ }
}
-.pmt__split-remainder-label {
- font-size: 10.5px;
- font-weight: 700;
- text-transform: uppercase;
- letter-spacing: 0.04em;
- color: $green;
-}
-
-.pmt__split-remainder-value {
- font-size: 16px;
- font-weight: 800;
- color: $green;
- font-variant-numeric: tabular-nums;
-}
-
-.pmt__content mat-form-field {
- width: 100%;
+.pmt__error {
+ display: flex;
+ align-items: flex-start;
+ gap: 10px;
+ background: #fef2f2;
+ border: 1px solid #fecaca;
+ border-left: 4px solid #ef4444;
+ border-radius: 10px;
+ color: #b91c1c;
+ font-size: 13px;
+ padding: 12px 16px;
+ margin: 10px 0;
}
.pmt__actions {
- padding: 14px 28px 20px !important;
- border-top: 1px solid $border;
- flex: 0 0 auto;
+ padding: 18px 30px !important;
+ border-top: 1px solid #e2e8f0;
+ background: #fff;
+ display: flex;
+ align-items: center;
+ justify-content: flex-end;
+ gap: 14px;
+ flex-shrink: 0;
+
+ .pmt__btn-cancel {
+ border-radius: 10px;
+ font-weight: 600;
+ color: #475569;
+ }
+
+ .pmt__btn-submit {
+ border-radius: 10px;
+ font-weight: 700;
+ padding: 0 26px;
+ height: 42px;
+ background: linear-gradient(135deg, #1d4ed8 0%, #2563eb 100%);
+ color: #fff;
+ box-shadow: 0 8px 20px rgb(37 99 235 / 30%);
+ transition: all 0.2s ease;
+
+ &:hover:not(:disabled) {
+ box-shadow: 0 10px 24px rgb(37 99 235 / 40%);
+ transform: translateY(-1px);
+ }
+
+ &:disabled {
+ background: #cbd5e1;
+ box-shadow: none;
+ color: #64748b;
+ }
+ }
}
diff --git a/src/app/deposits/fixed-deposits/fixed-deposit-account-view/custom-dialogs/payment-dialog/payment-dialog.component.ts b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/custom-dialogs/payment-dialog/payment-dialog.component.ts
index cd433f83c..4e1cc8c39 100644
--- a/src/app/deposits/fixed-deposits/fixed-deposit-account-view/custom-dialogs/payment-dialog/payment-dialog.component.ts
+++ b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/custom-dialogs/payment-dialog/payment-dialog.component.ts
@@ -27,12 +27,22 @@ import { SettingsService } from 'app/settings/settings.service';
import { Dates } from 'app/core/utils/dates';
import { FormatNumberPipe } from '../../../../../pipes/format-number.pipe';
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
+import { FdMaturityRow } from 'app/fd-dashboard/fd-dashboard.compute';
/**
* "Payment" dialog -- an always-available alternative to Premature Close (Active-only, no reinvest) and
* Close (Matured-only, no partial option). Works on an FD in either state and offers a fourth choice,
* Partial Reinvest, alongside the ones the backend's `DepositAccountOnClosureType` already had: the
* entered amount renews on this same account, the rest transfers to a savings account picked here.
+ *
+ * Doubles as the FD Dashboard's Renew action when opened with `data.dashboardRenewal` set: same form,
+ * same full set of closure types (nothing removed -- Transfer to Savings and Partial Reinvest work from
+ * the Dashboard too, not just the two Reinvest options). The only two differences in that mode: the
+ * Closed On Date is computed from the FD's grace window instead of picked freely (backdated to the
+ * original maturity date within grace, today once it's passed -- the picker is hidden, not just
+ * defaulted, so it can't accidentally be moved off that date), and submit() first calls
+ * `creditGapInterestIfPastGrace` when past grace, crediting the gap-period interest (at the linked
+ * account's rate) onto the FD before the normal `payment` command runs and reads its balance.
*/
@Component({
selector: 'mifosx-payment-dialog',
@@ -76,7 +86,13 @@ export class PaymentDialogComponent implements OnInit {
};
dialogRef = inject
>(MatDialogRef);
- data: { accountId: number | string; accountBalance?: number; maturityDate?: any } = inject(MAT_DIALOG_DATA);
+ data: {
+ accountId: number | string;
+ accountBalance?: number;
+ maturityDate?: any;
+ /** Present only when opened from the FD Dashboard's Renew action. */
+ dashboardRenewal?: { row: FdMaturityRow };
+ } = inject(MAT_DIALOG_DATA);
private formBuilder = inject(UntypedFormBuilder);
private fixedDepositsService = inject(FixedDepositsService);
private settingsService = inject(SettingsService);
@@ -93,6 +109,10 @@ export class PaymentDialogComponent implements OnInit {
submitError: string = null;
maxDate: Date;
+ /** Whether gap-interest still needs crediting before this submits -- only ever true once, right
+ * after open; cleared as soon as `submit()` has credited it, so a retried submit doesn't double-post. */
+ private gapInterestPending = false;
+
ngOnInit(): void {
this.maxDate = this.settingsService.businessDate;
this.paymentForm = this.formBuilder.group({
@@ -106,6 +126,18 @@ export class PaymentDialogComponent implements OnInit {
],
note: ['']
});
+
+ const dashboardRow = this.dashboardRenewalRow;
+ if (dashboardRow) {
+ // Computed from the grace window, never picked -- the date field stays in the form (the generic
+ // submit path and reinvestCap/processingOnOrAfterMaturity both key off it) but its picker is
+ // hidden in this mode (see the template), so it can't be moved off this value.
+ this.paymentForm
+ .get('closedOnDate')
+ .setValue(dashboardRow.withinGraceWindow ? new Date(dashboardRow.maturityDate) : this.maxDate);
+ this.gapInterestPending = !dashboardRow.withinGraceWindow;
+ }
+
this.paymentForm.get('onAccountClosureId').valueChanges.subscribe((id: number) => this.onClosureTypeChange(id));
// The cap depends on whether the chosen date is on or after maturity, so a date change can make an
// already-entered amount valid or invalid. Without this the amount keeps its verdict from the old date.
@@ -136,6 +168,25 @@ export class PaymentDialogComponent implements OnInit {
});
}
+ get isDashboardRenewalMode(): boolean {
+ return !!this.data.dashboardRenewal;
+ }
+
+ get dashboardRenewalRow(): FdMaturityRow | null {
+ return this.data.dashboardRenewal?.row ?? null;
+ }
+
+ /** What clicking Confirm is actually about to do -- shown above the (hidden-picker) date in this
+ * mode, since the date itself is no longer visible to explain it. */
+ get dashboardRenewalTimingText(): string {
+ const row = this.dashboardRenewalRow;
+ if (!row) return '';
+ return row.withinGraceWindow
+ ? `Backdated to its original maturity date (${row.maturityDate}), at the currently active interest rate.`
+ : `This FD's grace period has passed -- gap-period interest (for the days since maturity) will be ` +
+ `credited at the linked account's rate first, then this renews from today.`;
+ }
+
/**
* The amount being split, and the bound the entered partial amount is checked against.
*
@@ -259,6 +310,31 @@ export class PaymentDialogComponent implements OnInit {
}
submit(): void {
+ if (this.gapInterestPending) {
+ this.submitting = true;
+ this.submitError = null;
+ this.fixedDepositsService.creditGapInterestIfPastGrace(this.data.accountId).subscribe({
+ next: () => {
+ this.gapInterestPending = false;
+ this.submitGenericPayment();
+ },
+ error: (error: any) => {
+ this.submitting = false;
+ this.submitError =
+ error?.error?.defaultUserMessage ??
+ error?.error?.errors?.[0]?.defaultUserMessage ??
+ 'Could not credit gap-period interest. Please review the details and try again.';
+ }
+ });
+ return;
+ }
+ this.submitGenericPayment();
+ }
+
+ /** The same `command=payment` submission every non-Dashboard call to this dialog already used --
+ * Dashboard-renewal mode reaches it too, once any gap-interest pre-step above has cleared, so every
+ * closure type behaves identically regardless of where the dialog was opened from. */
+ private submitGenericPayment(): void {
const formValue = { ...this.paymentForm.value };
const locale = this.settingsService.language.code;
const dateFormat = this.settingsService.dateFormat;
diff --git a/src/app/deposits/fixed-deposits/fixed-deposit-account-view/fixed-deposit-account-view.component.ts b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/fixed-deposit-account-view.component.ts
index fefdb323d..42f39f6c5 100644
--- a/src/app/deposits/fixed-deposits/fixed-deposit-account-view/fixed-deposit-account-view.component.ts
+++ b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/fixed-deposit-account-view.component.ts
@@ -276,7 +276,7 @@ export class FixedDepositAccountViewComponent implements OnInit {
*/
private openPaymentDialog(): void {
const paymentDialogRef = this.dialog.open(PaymentDialogComponent, {
- width: '640px',
+ width: '720px',
maxWidth: '95vw',
data: {
accountId: this.fixedDepositsAccountData.id,
diff --git a/src/app/deposits/fixed-deposits/fixed-deposit-account-view/fixed-deposits-buttons.config.ts b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/fixed-deposits-buttons.config.ts
index 3146a730c..76abd062d 100644
--- a/src/app/deposits/fixed-deposits/fixed-deposit-account-view/fixed-deposits-buttons.config.ts
+++ b/src/app/deposits/fixed-deposits/fixed-deposit-account-view/fixed-deposits-buttons.config.ts
@@ -57,11 +57,12 @@ export class FixedDepositsButtonsConfiguration {
];
break;
case 'Matured':
+ // 'Close' (the generic Fineract apply-maturity-instructions action) is deliberately left out
+ // here -- what happens to a matured FD is now handled either automatically by the nightly job
+ // (an account opened with an explicit instruction) or manually via the FD Dashboard's Renew
+ // action (an account left without one, backdated within grace / gap-interest after). Closing
+ // from here would go around both of those paths.
this.buttonsArray = [
- {
- name: 'Close',
- icon: 'fa fa-arrow-right'
- },
{
name: 'Calculate Interest',
icon: 'fa fa-table'
diff --git a/src/environments/.env.ts b/src/environments/.env.ts
index 0ec45a382..f08a6bab3 100644
--- a/src/environments/.env.ts
+++ b/src/environments/.env.ts
@@ -9,8 +9,8 @@
/* tslint:disable */
export default {
'mifos_x': {
- 'version': '260921',
- 'hash': '3c363d03'
+ 'version': '260923',
+ 'hash': '3f59cc6b'
},
'allow_switching_backend_instance': true
};
diff --git a/src/main.scss b/src/main.scss
index 16f91750d..c74b84479 100644
--- a/src/main.scss
+++ b/src/main.scss
@@ -55,6 +55,19 @@
box-shadow: none;
}
+// ===== Payment / Renewal Dialog Panel =====
+.pmt-dialog-panel .mat-mdc-dialog-container .mdc-dialog__surface {
+ padding: 0 !important;
+ border-radius: 16px !important;
+ overflow: hidden !important;
+ box-shadow: 0 20px 40px rgb(15 23 42 / 25%) !important;
+}
+
+.pmt-dialog-panel .mat-mdc-dialog-content {
+ padding: 0 !important;
+ max-height: none !important;
+}
+
.ipd-dialog .mdc-dialog__surface {
border-radius: 20px !important;
background: transparent !important;