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 @@
- -
-

{{ 'labels.heading.Payment' | translate }}

-

Process this Fixed Deposit now -- works whether it's Active or Matured.

+
+ +
+

+ {{ isDashboardRenewalMode ? 'Renew Fixed Deposit' : ('labels.heading.Payment' | translate) }} +

+

+ {{ + isDashboardRenewalMode + ? 'Renew ' + (dashboardRenewalRow?.accountNo ?? 'this matured FD') + '.' + : "Process this Fixed Deposit now -- works whether it's Active or Matured." + }} +

+
+
@@ -27,37 +40,46 @@
} @else {
+ @if (isDashboardRenewalMode) { +

+ + {{ dashboardRenewalTimingText }} +

+ } + @if (reinvestCap !== null && reinvestCap !== undefined) {
{{ - remainderIsApproximate - ? 'Amount available on the selected date' - : ('labels.inputs.Maturity Amount' | translate) + isDashboardRenewalMode || !remainderIsApproximate + ? ('labels.inputs.Maturity Amount' | translate) + : 'Amount available on the selected date' }} {{ reinvestCap | formatNumber }}
} - - {{ 'labels.inputs.Closed On Date' | translate }} - - - - @if (paymentForm.controls.closedOnDate.hasError('required')) { - - {{ 'labels.inputs.Closed On Date' | translate }} {{ 'labels.commons.is' | translate }} - {{ 'labels.commons.required' | translate }} - - } - + @if (!isDashboardRenewalMode) { + + {{ 'labels.inputs.Closed On Date' | translate }} + + + + @if (paymentForm.controls.closedOnDate.hasError('required')) { + + {{ 'labels.inputs.Closed On Date' | translate }} {{ 'labels.commons.is' | translate }} + {{ 'labels.commons.required' | translate }} + + } + + }
@@ -162,10 +184,12 @@ } - - {{ 'labels.inputs.Note' | translate }} - - + @if (!isDashboardRenewalMode) { + + {{ 'labels.inputs.Note' | translate }} + + + } @if (submitError) {
- +
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;