WEB-977: Redesign client list and general tab views#3643
Conversation
|
Note
|
| Layer / File(s) | Summary |
|---|---|
Clients list: Material table to custom list src/app/clients/clients.component.html, src/app/clients/clients.component.scss, src/app/clients/clients.component.ts |
Material mat-table/paginator/sort removed; list rendering replaced by manual @for rows, toolbar search, explicit pagination/sorting state, ChangeDetectorRef usage, and helpers for initials, severity, meta-date, and page ranges. |
Client detail header: Material card to account header src/app/clients/clients-view/clients-view.component.html, src/app/clients/clients-view/clients-view.component.ts |
mat-card-header replaced with mifosx-account-header; profile image rendering with conditional sources and permission-gated upload/capture/delete buttons; signature view action; reorganized account overview metadata with masking via mifosx-entity-name. Component imports adjusted. |
Tab bar redesign: SVG icons and tab tokens src/app/clients/clients-view/clients-view.component.html, src/app/clients/clients-view/clients-view.component.scss |
Tab bar class tabs-redesign added; inline SVG icons added for General, Personal Data, Address, Family Members, Identities, Documents, Notes, and dynamic datatable tabs; Material tab styling restyled using design tokens and active border-bottom indicator. |
General tab: Accounts, KPI, Upcoming Charges src/app/clients/clients-view/general-tab/general-tab.component.html, src/app/clients/clients-view/general-tab/general-tab.component.ts |
Performance History converted to KPI grid; Upcoming Charges to conditional mat-table with row actions; accounts unified into sub-tabs (all/loan/savings/fixed/recurring/shares) with showClosedAccounts toggle, card-row rendering via @if/@for/@empty, status styling, and permission-gated actions. New public fields: currentAccountType, showClosedAccounts, accountCounts; new methods: selectAccountType(), toggleShowClosedAccounts(), loanSeverity(), accountSeverity(), loanProgress(). |
General tab and clients styles: tokenized SCSS src/app/clients/clients.component.scss, src/app/clients/clients-view/clients-view.component.scss, src/app/clients/clients-view/general-tab/general-tab.component.scss |
Introduces CSS design tokens on :host and dark overrides, token-driven styling for KPI cards, account cards/rows/chips/progress, tabs redesign, info banners, data tables, and PDF modal overlay. |
Component imports and standalone wiring src/app/clients/clients-view/clients-view.component.ts, src/app/clients/clients-view/general-tab/general-tab.component.ts |
Refined component decorator imports to narrower set of Material directives and shared standalone components; removed unused footer/table directives and StatusLookupPipe from clients view imports. |
FormatNumberPipe decimal pattern fix src/app/pipes/format-number.pipe.ts |
Decimal format now uses configured decimals value for both minimum and maximum fraction digits. |
Translation catalog updates src/assets/translations/* (multiple files) |
Extensive additions and reordering across locales (en-US, de-DE, fr-FR, es-CL, es-MX, it-IT, pt-PT, cs-CS, ko-KO, lt-LT, lv-LV, ne-NE, sw-SW) adding many new button labels, headings (Accounts), text/help entries (Activated, Council Approval, Page, Rows, Showing, Submitted), “No … Found” messages, and tooltip entries including ACTIVE/INACTIVE/PENDING and product/repayment tooltips. |
Estimated code review effort
🎯 4 (Complex) | ⏱️ ~60 minutes
Possibly related PRs
- openMF/web-app#3021: Also modifies
clients-viewheader metadata and client classification rendering. - openMF/web-app#3253: Related translation updates in
es-MX.jsonand other locale catalog work.
Suggested reviewers
- IOhacker
- adamsaghy
✨ Finishing Touches
🧪 Generate unit tests (beta)
- Create PR with unit tests
There was a problem hiding this comment.
Actionable comments posted: 9
Note
Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/assets/translations/ko-KO.json (1)
1-4788:⚠️ Potential issue | 🟠 MajorFix Prettier formatting for
src/assets/translations/ko-KO.json
npx prettier --checkfails because the configuredprettier-plugin-multiline-arraysplugin can’t be resolved. Install dependencies and rerunnpx prettier --write .to apply formatting.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/assets/translations/ko-KO.json` around lines 1 - 4788, Prettier check fails due to the missing prettier-plugin-multiline-arrays plugin causing formatting not to be applied to src/assets/translations/ko-KO.json; fix by adding the missing plugin to devDependencies and reformatting. Install the plugin (e.g. npm install --save-dev prettier prettier-plugin-multiline-arrays or yarn add -D prettier prettier-plugin-multiline-arrays), ensure package.json / .prettierrc references are unchanged, then run npx prettier --write . (or npx prettier --write src/assets/translations/ko-KO.json) to apply formatting and commit the updated file.Source: Coding guidelines
🟡 Minor comments (29)
src/app/clients/clients.component.scss-193-193 (1)
193-193:⚠️ Potential issue | 🟡 MinorEnsure
JetBrains Monois loaded (otherwise you’ll fall back).
src/app/clients/clients.component.scssusesfont-family: 'JetBrains Mono', 'Cascadia Code', monospace;at lines 193/465/611, butsrc/index.htmlonly loads Roboto/Roboto Mono and there’s no@font-faceor Google Fonts import for JetBrains Mono insrc/main.scssorsrc/theme/*. Add the JetBrains Mono import or switch these stacks toRoboto Monoto match what’s already loaded.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/clients/clients.component.scss` at line 193, The CSS rule using the exact font-family declaration "font-family: 'JetBrains Mono', 'Cascadia Code', monospace;" must not reference an unloaded font; either import JetBrains Mono at your app root (add a Google Fonts `@import` or `@font-face` for JetBrains Mono in your global stylesheet) so that that declaration can take effect, or change the declaration to use a loaded font such as "Roboto Mono" to match the fonts already included. Locate the instances of that exact font-family string in the component stylesheet and update them accordingly, and ensure the global font import is added to your main/global stylesheet if you choose to add JetBrains Mono.src/assets/translations/cs-CS.json-772-775 (1)
772-775:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winUntranslated Czech catalog values were introduced.
Several newly added
labels.catalogsvalues are still English (e.g., Line 772% Amount, Line 774% Interest, Line 775% Loan Amount + Interest, Line 813Client). Please localize these to Czech to avoid mixed-language UI.Also applies to: 813-813
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/assets/translations/cs-CS.json` around lines 772 - 775, Several catalog label keys are still in English; update the Czech translations for the translation keys "% Amount", "% Disbursement Amount", "% Interest", "% Loan Amount + Interest" (and the "Client" entry referenced) in the cs-CS.json translations so they are fully localized to Czech — replace the English strings with their correct Czech equivalents while preserving the exact JSON keys and string quoting.src/assets/translations/de-DE.json-844-844 (1)
844-844:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winUse domain-correct German for core financial terms.
These translations change meaning in ways that can confuse financial workflows (
Escheat,Flat,Principal). Please replace them with finance-appropriate German terms (e.g., “Heimfall”, “Pauschal”, “Kapital/Hauptbetrag”).Suggested patch
- "Escheat": "Betrug", + "Escheat": "Heimfall", - "Flat": "Wohnung", + "Flat": "Pauschal", - "Principal": "Rektor", + "Principal": "Kapital",Also applies to: 853-853, 924-924
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/assets/translations/de-DE.json` at line 844, The German translations use incorrect domain terms: update the JSON entries for the keys "Escheat", "Flat", and "Principal" to finance-appropriate German — replace "Escheat": "Betrug" with "Escheat": "Heimfall", change "Flat" translation to "Pauschal" (or "fest" if context requires), and change "Principal" translation to "Kapital" or "Hauptbetrag" as appropriate; ensure you also update the other occurrences of those same keys elsewhere in this file (the other "Escheat"/"Flat"/"Principal" entries mentioned in the review) so all instances use the consistent, domain-correct terms.src/assets/translations/de-DE.json-4268-4268 (1)
4268-4268:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winRecurring deposit account label is mistranslated.
“Dauerauftragskonten” means standing-order accounts, not recurring deposit accounts. This should use a recurring-deposit term to avoid product confusion.
Suggested patch
- "No Active Recurring Deposit Accounts Found": "Keine aktiven Dauerauftragskonten gefunden", + "No Active Recurring Deposit Accounts Found": "Keine aktiven Konten für wiederkehrende Einlagen gefunden",🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/assets/translations/de-DE.json` at line 4268, The German translation for the key "No Active Recurring Deposit Accounts Found" uses "Dauerauftragskonten" (standing orders) and must be replaced with a correct recurring-deposit term; update the value for the "No Active Recurring Deposit Accounts Found" key to a proper German phrase such as "Keine aktiven wiederkehrenden Spareinlagen gefunden" (or another approved product-localized term), preserving punctuation/capitalization and then run the i18n/translation validation to ensure no formatting tokens were changed.src/assets/translations/en-US.json-928-928 (1)
928-928:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winFix user-facing copy regressions in new catalog/tooltips entries.
A few newly added strings contain typos/wording errors that will surface directly in the UI.
✏️ Suggested patch
- "Quarterly": "Quartely", + "Quarterly": "Quarterly", - "fourth": "four", + "fourth": "fourth", - "This sections defines an interest penalty": "This sections defines an interest penalty for pre-mature closure.", + "This sections defines an interest penalty": "This section defines an interest penalty for pre-mature closure.", - "loan product will become inactive and unavailable to clients": "The date that the loan product will become inactive and unavailable to clients. If blank, the load product will never become inactive." + "loan product will become inactive and unavailable to clients": "The date that the loan product will become inactive and unavailable to clients. If blank, the loan product will never become inactive."Also applies to: 1015-1015, 4680-4680, 4713-4713
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/assets/translations/en-US.json` at line 928, The translation entry for the "Quarterly" key has a typo in its value ("Quartely") — update the value to the correct spelling "Quarterly" in the translations JSON (look for the "Quarterly" key), and also fix the same misspelling occurrences referenced at the other locations (the entries around the indices called out: 1015, 4680, 4713) so all user-facing strings show the corrected "Quarterly".src/assets/translations/es-CL.json-772-772 (1)
772-772:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winPercent-based catalog key lost percent meaning in translation.
Line 772 translates
"% Disbursement Amount"as"Monto de curso"; it drops the percentage concept from the label and may mislabel calculation modes.Suggested fix
- "% Disbursement Amount": "Monto de curso", + "% Disbursement Amount": "% Monto de desembolso",🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/assets/translations/es-CL.json` at line 772, The translation for the key "% Disbursement Amount" currently becomes "Monto de curso" and drops the percent semantics; update the value for the key "% Disbursement Amount" in es-CL.json so it preserves the percent meaning (for example use a phrase like "Porcentaje del monto desembolsado" or "Monto de desembolso (%)") ensuring the key "% Disbursement Amount" remains unchanged and only the translated string is corrected.src/assets/translations/es-CL.json-944-944 (1)
944-944:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winIncorrect translation for shares label.
Line 944 maps
"SHARES"to"COMPARTE", which is a verb and not the financial noun used elsewhere in this file ("Acciones"). This will show incorrect domain terminology in the UI.Suggested fix
- "SHARES": "COMPARTE", + "SHARES": "ACCIONES",🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/assets/translations/es-CL.json` at line 944, The "SHARES" translation currently set to "COMPARTE" is incorrect (verb); update the translation for the key "SHARES" to the proper financial noun "Acciones" (match existing capitalization/locale style used in this file) so the UI uses the correct domain term; ensure only the value for "SHARES" is changed and keep JSON formatting intact.src/assets/translations/es-CL.json-4484-4484 (1)
4484-4484:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winTooltip sentence is grammatically broken and hard to understand.
Line 4484 has a malformed phrase (
...incluso la cuenta de acciones... está inactiva) that reads incomplete and can confuse users.Suggested fix
- "Indicates whether the dividends can be processed even share account of this share product is inactive": "Indica si los dividendos se pueden procesar incluso la cuenta de acciones de este producto de acciones está inactiva", + "Indicates whether the dividends can be processed even share account of this share product is inactive": "Indica si los dividendos se pueden procesar incluso si la cuenta de acciones de este producto está inactiva",🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/assets/translations/es-CL.json` at line 4484, The Spanish tooltip value for the key "Indicates whether the dividends can be processed even share account of this share product is inactive" is grammatically broken; update the translation string for that exact key to a clear, natural Spanish sentence (e.g., "Indica si los dividendos pueden procesarse incluso cuando la cuenta de acciones de este producto está inactiva" or similar) so the phrase reads complete and unambiguous while preserving the original meaning.src/assets/translations/es-CL.json-4606-4606 (1)
4606-4606:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winTooltip uses wrong product term (
cargavscrédito).Line 4606 says
producto de carga, which changes meaning and conflicts with the rest of the loan domain terminology in this locale.Suggested fix
- "loan product will become inactive and unavailable to clients": "La fecha en que el producto de Crédito quedará inactivo y no estará disponibles para los clientes. Si está en blanco, el producto de carga nunca quedará inactivo." + "loan product will become inactive and unavailable to clients": "La fecha en que el producto de Crédito quedará inactivo y no estará disponible para los clientes. Si está en blanco, el producto de Crédito nunca quedará inactivo."🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/assets/translations/es-CL.json` at line 4606, The Spanish translation for the key "loan product will become inactive and unavailable to clients" incorrectly uses "producto de carga" and has number agreement errors; update the value to use the correct term "producto de crédito" and fix agreement (e.g., "no estará disponible") so the sentence reads clearly and consistently with loan domain terminology (replace all occurrences of "carga" in this value with "crédito" and correct "no estará disponibles" → "no estará disponible").src/assets/translations/es-MX.json-1436-1436 (1)
1436-1436:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winTranslate remaining English strings in
es-MXto avoid mixed-language UI.These keys are still in English (or partially English) in the Spanish locale, which creates inconsistent UX.
Suggested patch
- "Quick Access": "Quick Access", + "Quick Access": "Acceso rápido", - "Center banking": "Center banking", + "Center banking": "Banca de centros", - "Configure offerings": "Configure offerings", + "Configure offerings": "Configurar ofertas", - "Group lending": "Group lending", + "Group lending": "Crédito grupal", - "Journals and ledger": "Journals & ledger", + "Journals and ledger": "Diarios y libro mayor", - "Navigate directly to any platform area": "Navigate directly to any platform area", + "Navigate directly to any platform area": "Navega directamente a cualquier área de la plataforma", - "Offices and staff": "Offices & staff", + "Offices and staff": "Sucursales y personal", - "Profiles and accounts": "Profiles & accounts", + "Profiles and accounts": "Perfiles y cuentas", - "Savings accounts": "Savings accounts", + "Savings accounts": "Cuentas de ahorro", - "System configuration": "Configuration", + "System configuration": "Configuración del sistema",Also applies to: 3381-3381, 3415-3415, 3646-3646, 3659-3659, 3744-3744, 3777-3777, 3806-3806, 3852-3852, 3907-3907
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/assets/translations/es-MX.json` at line 1436, The es-MX locale file contains English strings (e.g., the "Quick Access" key) that should be translated into Spanish to avoid mixed-language UI; update each mentioned key in src/assets/translations/es-MX.json (including "Quick Access" and the other keys referenced at lines ~3381, 3415, 3646, 3659, 3744, 3777, 3806, 3852, 3907) by replacing the English values with appropriate Spanish translations (e.g., "Acceso rápido" for "Quick Access"), ensuring the JSON string values remain valid and preserving the original key names.src/assets/translations/es-MX.json-776-776 (1)
776-776:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winFix missing accent marks in day labels.
Diasshould beDíasfor correct Spanish orthography.Suggested patch
- "30 Days": "30 Dias", + "30 Days": "30 Días", - "365 Days": "365 Dias", + "365 Days": "365 Días",Also applies to: 779-779
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/assets/translations/es-MX.json` at line 776, The Spanish translation value for the key "30 Days" uses "30 Dias" without the accent; update the value to "30 Días" (replace "Dias" with "Días") and scan the same translations file for any other day-label values that use "Dias" (e.g., other keys like "7 Days"/"1 Day"/similar entries) and correct them to "Días" so all day labels use the proper accent.src/assets/translations/es-MX.json-947-947 (1)
947-947:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winCorrect mistranslation for
SHARES.
"SHARES": "COMPARTE"is semantically incorrect in this domain; use"Acciones".Suggested patch
- "SHARES": "COMPARTE", + "SHARES": "ACCIONES",🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/assets/translations/es-MX.json` at line 947, The translation entry for the key "SHARES" is incorrect; locate the "SHARES" property in the translations JSON (the entry reading "SHARES": "COMPARTE") and replace its value with the correct Spanish term "Acciones" so the key becomes "SHARES": "Acciones". Ensure the JSON remains valid (quotes and trailing commas) after the edit and run a quick grep for other "SHARES" occurrences to verify consistency across translation files.src/assets/translations/fr-FR.json-842-842 (1)
842-842:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winFix domain-term mistranslations in
catalogsThese two values change product meaning in finance flows:
- Line 842
"Escheat": "Escroquerie"is incorrect (escheat≠ scam).- Line 917
"Penalty": "Peine"should use the financial term for fee/penalty.Suggested patch
- "Escheat": "Escroquerie", + "Escheat": "Déshérence", ... - "Penalty": "Peine", + "Penalty": "Pénalité",Also applies to: 917-917
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/assets/translations/fr-FR.json` at line 842, The translations for the catalog domain terms are incorrect: update the JSON entries for the keys "Escheat" and "Penalty" in fr-FR.json so they use proper financial terminology—replace the value for "Escheat" with a French financial term such as "Déshérence" (or "Droit de déshérence" if more explicit) and replace the value for "Penalty" with the financial term "Pénalité" (not "Peine"); ensure the keys remain unchanged and the file remains valid JSON after editing.src/assets/translations/fr-FR.json-4031-4031 (1)
4031-4031:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winCorrect French connector mapping for
ofLine 4031 maps
"of"to"sur", which is grammatically wrong in most UI phrases and will read unnaturally in composed strings.Suggested patch
- "of": "sur", + "of": "de",🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/assets/translations/fr-FR.json` at line 4031, The translation key "of" in src/assets/translations/fr-FR.json currently maps to "sur" which is incorrect for UI connector phrases; update the value for the "of" key to the correct French connector (e.g., "de" or the appropriate contraction like "d'") so composed strings read naturally—locate the "of" key in the JSON and replace "sur" with the chosen connector.src/assets/translations/fr-FR.json-4342-4342 (1)
4342-4342:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winFix gender agreement in empty-state message
Line 4342 uses
"Aucune donnée trouvé".donnéeis feminine, so this should betrouvée.Suggested patch
- "No Data Found": "Aucune donnée trouvé", + "No Data Found": "Aucune donnée trouvée",🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/assets/translations/fr-FR.json` at line 4342, Update the French translation for the "No Data Found" key in src/assets/translations/fr-FR.json: change the value from "Aucune donnée trouvé" to the correct feminine agreement "Aucune donnée trouvée" so the message reads properly for the key "No Data Found".src/assets/translations/it-IT.json-942-945 (1)
942-945:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winUse consistent Italian domain terminology for share labels.
"SHARES": "CONDIVISIONI"conflicts with nearby"Shares": "Azioni"and the rest of the share-account vocabulary, creating inconsistent wording across the UI.Suggested fix
- "SHARES": "CONDIVISIONI", + "SHARES": "AZIONI",🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/assets/translations/it-IT.json` around lines 942 - 945, SHARES is incorrectly translated as "CONDIVISIONI" which conflicts with the domain term used by neighboring keys ("SHAREACCOUNT": "Conto Azioni", "SHAREPRODUCT": "Prodotto Azioni"); update the value for the "SHARES" key to the consistent Italian term "Azioni" (matching capitalization) so all share-related labels use the same vocabulary; also scan nearby keys like SHAREACCOUNT, SHAREPRODUCT, and SSBENEFICIARYTPT to ensure they remain consistent after the change.src/assets/translations/it-IT.json-4512-4512 (1)
4512-4512:⚠️ Potential issue | 🟡 Minor | ⚡ Quick win
PENDINGtranslation is grammatically incomplete.
"IN ATTESA DI"ends with a dangling preposition and reads truncated in status contexts.Suggested fix
- "PENDING": "IN ATTESA DI", + "PENDING": "IN ATTESA",🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/assets/translations/it-IT.json` at line 4512, The translation value for the "PENDING" key is incomplete ("IN ATTESA DI"); update the "PENDING" entry in the it-IT translations to a grammatically complete status phrase (for example replace "IN ATTESA DI" with "IN ATTESA" or another complete option like "IN ATTESA DI CONFERMA") so the status reads correctly in UI contexts.src/assets/translations/it-IT.json-771-774 (1)
771-774:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winPreserve
%semantics in percentage catalog labels.
"% Amount"and"% Interest"currently read like non-percentage fields, which can make option selection ambiguous in financial dropdowns.Suggested fix
- "% Amount": "Quantità", + "% Amount": "% Importo", "% Disbursement Amount": "Importo dell'esborso", - "% Interest": "Interesse", - "% Loan Amount + Interest": "Importo del prestito + interessi", + "% Interest": "% Interesse", + "% Loan Amount + Interest": "% Importo del prestito + interessi",🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/assets/translations/it-IT.json` around lines 771 - 774, Update the Italian translations for the percentage catalog keys so the percent semantics are preserved rather than reading as plain nouns: modify the translations for the keys "% Amount", "% Disbursement Amount", "% Interest", and "% Loan Amount + Interest" in src/assets/translations/it-IT.json to include the percent symbol or an explicit "Percentuale" wording (for example "Percentuale importo" or "% importo") so dropdown options unambiguously convey percentage values; ensure each translated value maps to the exact source key names above and keep phrasing consistent across all four entries.src/assets/translations/ko-KO.json-4028-4028 (1)
4028-4028:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winAvoid using
/as the translation for the genericoftoken.
"of": "/"can break non-pagination phrases if this shared key is reused outside a numeric context. Prefer a proper connective (e.g.,중,의) or use a dedicated pagination-specific key instead.💡 Suggested fix
- "of": "/", + "of": "중",🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/assets/translations/ko-KO.json` at line 4028, The translation for the shared key "of" is currently "/", which is unsafe for non-pagination contexts; update the "of" entry in the JSON to a proper Korean connective (e.g., "의" or "중") or replace usages with a dedicated pagination key (e.g., "pagination.of") and set that pagination-specific key to "/" so generic "of" remains a natural-language connective; ensure any code that expects a pagination-only token is updated to use the new "pagination.of" key.src/assets/translations/lt-LT.json-4523-4523 (1)
4523-4523:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winReplace non-Lithuanian text in Lithuanian locale
This value is in Latvian, not Lithuanian, causing mixed-language UX in
lt-LT.Suggested fix
- "Refund transactions where interest refund will automatically be calculated": "Atmaksas darījumi, kuros procentu atmaksa tiks aprēķināta automātiski", + "Refund transactions where interest refund will automatically be calculated": "Grąžinimo operacijos, kuriose palūkanų grąžinimas bus apskaičiuotas automatiškai",🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/assets/translations/lt-LT.json` at line 4523, The value for the JSON key "Refund transactions where interest refund will automatically be calculated" in the lt-LT locale is in Latvian; replace the current Latvian string with the correct Lithuanian translation for that key (ensure the value is valid JSON string), e.g. update the value to the proper Lithuanian phrase and run a quick locale build or linter to confirm no syntax errors; verify translation with a native speaker or translation source before committing.src/assets/translations/lv-LV.json-902-902 (1)
902-902:⚠️ Potential issue | 🟡 Minor | ⚡ Quick win
Noneis mapped to the wrong meaning.Line 902 maps
"None"to"Kapitāls", which changes the option meaning instead of translating “none”. This will show incorrect UI meaning in any enum/dropdown using this key.Suggested fix
- "None": "Kapitāls", + "None": "Nav",🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/assets/translations/lv-LV.json` at line 902, The "None" key in src/assets/translations/lv-LV.json is incorrectly translated as "Kapitāls"; update the value for the "None" JSON key to the proper Latvian equivalent for "none" (e.g., "Nav") so enum/dropdown UI shows the correct meaning; locate the "None" entry in the lv-LV.json file and replace "Kapitāls" with the correct translation string.src/assets/translations/lv-LV.json-4522-4522 (1)
4522-4522:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winWrong language content in Latvian locale.
Line 4522 contains Lithuanian text (
"Grąžinimo operacijos...") insidelv-LV.json. This will surface mixed-language UI text.Suggested fix
- "Refund transactions where interest refund will automatically be calculated": "Grąžinimo operacijos, kai palūkanų grąžinimas bus skaičiuojamas automatiškai", + "Refund transactions where interest refund will automatically be calculated": "Atmaksas darījumi, kuros procentu atmaksa tiks aprēķināta automātiski",🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/assets/translations/lv-LV.json` at line 4522, The value for the JSON key "Refund transactions where interest refund will automatically be calculated" in lv-LV locale contains Lithuanian text ("Grąžinimo operacijos..."); replace that value with the correct Latvian translation for the same key (ensure the string preserves punctuation and encoding) so the lv-LV.json entry matches Latvian UI copy and run a quick scan of lv-LV.json for any other non-Latvian entries to correct.src/assets/translations/lv-LV.json-4604-4604 (1)
4604-4604:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winTypo in tooltip text changes readability.
Line 4604 uses
"ielādes produkts"in a loan-product tooltip. This looks like a typo and reads incorrectly in Latvian.Suggested fix
- "loan product will become inactive and unavailable to clients": "Datums, kad aizdevuma produkts kļūs neaktīvs un klientiem nebūs pieejams. Ja lauks ir tukšs, ielādes produkts nekad nekļūs neaktīvs." + "loan product will become inactive and unavailable to clients": "Datums, kad aizdevuma produkts kļūs neaktīvs un klientiem nebūs pieejams. Ja lauks ir tukšs, aizdevuma produkts nekad nekļūs neaktīvs."🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/assets/translations/lv-LV.json` at line 4604, The translated value for the key "loan product will become inactive and unavailable to clients" contains a typo: "ielādes produkts" should be corrected to the proper Latvian term "aizdevuma produkts"; update the translation string so the sentence reads "Datums, kad aizdevuma produkts kļūs neaktīvs un klientiem nebūs pieejams. Ja lauks ir tukšs, aizdevuma produkts nekad nekļūs neaktīvs." ensuring the same key remains unchanged.src/assets/translations/ne-NE.json-4528-4528 (1)
4528-4528:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winReplace garbled translation in
tooltips.Resume Delinquency Classification.Line 4528 contains corrupted text (
"Deminuquicum वर्गीकरण...") instead of a valid Nepali translation, which will surface broken tooltip copy.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/assets/translations/ne-NE.json` at line 4528, The translation value for the JSON key "Resume Delinquency Classification" in src/assets/translations/ne-NE.json is corrupted; open the file, locate the "Resume Delinquency Classification" entry (tooltip key tooltips.Resume Delinquency Classification) and replace the garbled string ("Deminuquicum ...") with the correct Nepali tooltip text; ensure the new value is valid JSON (properly quoted and escaped) and matches the tone/length of other tooltip entries.src/assets/translations/ne-NE.json-4604-4604 (1)
4604-4604:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winFix term mismatch in loan-product tooltip string.
Line 4604 uses
"लोड उत्पादन"(load product) where the key is about loan product lifecycle; this appears to be a mistranslation and can mislead users.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/assets/translations/ne-NE.json` at line 4604, The translation for the key "loan product will become inactive and unavailable to clients" contains the incorrect term "लोड उत्पादन" (load product); update the Nepali value to use the correct term "ऋण उत्पादन" so the string reads with "ऋण उत्पादन निष्क्रिय र ग्राहकहरु को लागी अनुपलब्ध हुने मिति..." preserving the rest of the sentence and punctuation exactly as in the existing value.src/assets/translations/ne-NE.json-707-707 (1)
707-707:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winCorrect duplicated wording in
labels.buttons.Run and Download Report.Line 707 translates to a duplicated “download” phrase (
"रन र डाउनलोड रिपोर्ट डाउनलोड गर्नुहोस्"), producing awkward UI text.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/assets/translations/ne-NE.json` at line 707, The translation for the key labels.buttons.Run and Download Report contains a duplicated "डाउनलोड" ("रन र डाउनलोड रिपोर्ट डाउनलोड गर्नुहोस्"); update the value to a single, natural Nepali phrase (for example remove the extra "डाउनलोड" so it reads like "रन र डाउनलोड रिपोर्ट गर्नुहोस्" or "रिपोर्ट रन गरी डाउनलोड गर्नुहोस्") by editing the JSON value for "Run and Download Report" to remove the duplicated word and ensure the phrase is grammatically correct.src/assets/translations/ne-NE.json-901-901 (1)
901-901:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winFix incorrect Nepali value for
labels.catalogs.None.Line 901 maps
"None"to"राजधानी"(“capital”), which changes the meaning and will show a wrong option label in UI filters/forms.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/assets/translations/ne-NE.json` at line 901, labels.catalogs.None is incorrectly translated as "राजधानी"; update the value for the key "None" in src/assets/translations/ne-NE.json (labels.catalogs.None) to the correct Nepali equivalent for "None" (e.g., "कुनै छैन" or "कुनै") so the UI filter/form shows the intended option; ensure the JSON string is properly quoted and preserved in the same file structure.src/assets/translations/pt-PT.json-860-860 (1)
860-860:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winCorrect mistranslations that change business meaning.
Several new catalog values map to unrelated terms (
Id→Eu ia,Principal→Diretor,last→durar,on day→Um dia), which can mislead users in core loan/account flows.Suggested fix
- "Id": "Eu ia", + "Id": "ID", - "Principal": "Diretor", + "Principal": "Principal", - "last": "durar", + "last": "último", - "on day": "Um dia", + "on day": "no dia",Also applies to: 922-922, 1016-1016, 1026-1026
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/assets/translations/pt-PT.json` at line 860, Replace the incorrect Portuguese values that change business meaning for the JSON keys: update the value for "Id" (currently "Eu ia") to a correct business-term translation such as "Id" or "Identificador"; change "Principal" (currently "Diretor") back to the financial term "Principal" or "Montante principal"; correct "last" (currently "durar") to "último"; and change "on day" (currently "Um dia") to "no dia"; ensure you only modify the values for the existing keys ("Id", "Principal", "last", "on day") across the file so keys remain unchanged and semantics are restored.src/assets/translations/pt-PT.json-771-774 (1)
771-774:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winKeep
%in percentage-based option labels.These labels removed the percentage marker, making financial options ambiguous in dropdowns and summaries.
Suggested fix
- "% Amount": "Quantia", - "% Disbursement Amount": "Valor do Desembolso", - "% Interest": "Interesse", - "% Loan Amount + Interest": "Valor do empréstimo + juros", + "% Amount": "% Quantia", + "% Disbursement Amount": "% Valor do desembolso", + "% Interest": "% Juros", + "% Loan Amount + Interest": "% Valor do empréstimo + juros",🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/assets/translations/pt-PT.json` around lines 771 - 774, The translations for the percentage-based labels ("% Amount", "% Disbursement Amount", "% Interest", "% Loan Amount + Interest") removed the leading percent sign, causing ambiguity; update the values in src/assets/translations/pt-PT.json so each corresponding value includes the "%" prefix (e.g., "% Quantia", "% Valor do Desembolso", "% Interesse", "% Valor do empréstimo + juros") so UI dropdowns and summaries retain the percent marker.
🧹 Nitpick comments (9)
src/app/clients/clients.component.ts (1)
85-98: 🏗️ Heavy liftIntroduce typed interfaces for client row and API responses.
Multiple helper methods (
severity,legalFormLabel,metaDate,metaDateLabel) useanyfor therowparameter, anddataSourceis typed asMatTableDataSource<any>. Based on learnings, introduce aClientRowinterface covering{ status: { code: string, value: string }, legalForm?: { id: number }, activationDate?, submittedOnDate?, timeline?: { closedOnDate? }, ... }and aClientSearchResponseinterface for the API shape, then update method signatures and the data source accordingly.Also applies to: 101-104, 107-109, 112-117, 141-141
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/clients/clients.component.ts` around lines 85 - 98, Create a typed ClientRow interface (including fields used by the component: status { code: string; value?: string }, legalForm?: { id?: number }, activationDate?: string, submittedOnDate?: string, timeline?: { closedOnDate?: string }, etc.) and a ClientSearchResponse for the API result, then replace all any usages: change the severity(row: any) signature to severity(row: ClientRow) and update legalFormLabel, metaDate, metaDateLabel to accept ClientRow; also change the component's dataSource from MatTableDataSource<any> to MatTableDataSource<ClientRow> and update any API handling code to cast/validate to ClientSearchResponse before assigning rows to dataSource.Source: Learnings
src/app/clients/clients-view/clients-view.component.scss (2)
91-147: 💤 Low value
::ng-deepis deprecated but required for Material component styling.Line 91 uses the deprecated
::ng-deeppseudo-element to style Angular Material's MDC-based tab navigation. While stylelint flags this, it remains a necessary workaround for deep component styling when view encapsulation prevents direct selector targeting. The alternative is moving these rules to a global stylesheet, but that reduces component encapsulation. The current approach is acceptable for Material theming overrides.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/clients/clients-view/clients-view.component.scss` around lines 91 - 147, The CSS uses the deprecated ::ng-deep selector to override MDC tab styles (selector block starting with :host ::ng-deep .tabs-redesign.mat-mdc-tab-nav-bar and related rules for .mat-mdc-tab-link, .mdc-tab-indicator__content, .tab-icon); keep using ::ng-deep here but silence the linter by adding a stylelint disable/enable comment around this rule block (e.g., disable the specific rule that flags ::ng-deep) so the Material theming override remains intact while suppressing the stylelint warning.Source: Linters/SAST tools
9-38: ⚖️ Poor tradeoffDesign tokens duplicated across components.
The
--ch-*custom properties are identical to those insrc/app/clients/clients.component.scss. Consider extracting these to a shared SCSS file or defining them at the:rootlevel insrc/main.scssto avoid duplication and maintain consistency.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/clients/clients-view/clients-view.component.scss` around lines 9 - 38, The --ch-* design tokens (e.g. --ch-blue-700, --ch-surface, --ch-text-1) are duplicated in the :host and :host-context(.dark-theme) blocks; extract them into a single shared SCSS token file or define them at :root (and a .dark-theme override) in your global stylesheet, then remove these duplicated declarations from clients-view.component.scss and have the component import or rely on the global tokens; ensure the dark-theme overrides still use the same variable names so :host, :host-context(.dark-theme), and components like clients.component.scss reference the centralized tokens.src/app/clients/clients.component.scss (1)
9-53: Centralize--ch-*design tokens instead of redeclaring per component
src/main.scssandsrc/theme/mifosx-theme.scssdon’t define any shared--ch-*/$ch-*tokens, so this:host/:host-context(.dark-theme)block can’t reuse centralized values from those files. The palette is redeclared locally insrc/app/clients/clients.component.scssand is duplicated in other component styles (e.g.,src/app/clients/clients-view/clients-view.component.scss), so extract these tokens into a shared SCSS partial/global variable set and import/use it to prevent drift.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/clients/clients.component.scss` around lines 9 - 53, The color/design tokens (--ch-*) are being redeclared inside the component :host and :host-context(.dark-theme) blocks causing duplication; extract all --ch-* variables (e.g., --ch-blue-700, --ch-surface, --ch-text-1, --ch-paid, etc.) into a shared SCSS partial (a global variables file), replace the local declarations in the clients component (:host and :host-context(.dark-theme)) with imports of that partial, and update other components that currently redeclare the same tokens (e.g., any clients-view styles) to import and use the centralized tokens instead of redefining them.Source: Coding guidelines
src/app/clients/clients-view/general-tab/general-tab.component.ts (2)
258-261: 💤 Low valueConsider extracting the
accountCountstype into an interface.The inline object type for
accountCountsworks but could be more maintainable as a named interface, especially if this structure is referenced elsewhere or grows.♻️ Optional refactor
+interface AccountCounts { + loan: number; + savings: number; + fixed: number; + recurring: number; + shares: number; + total: number; +} + /** Unified accounts view state */ currentAccountType: 'all' | 'loan' | 'savings' | 'fixed' | 'recurring' | 'shares' = 'all'; showClosedAccounts = false; - accountCounts = { loan: 0, savings: 0, fixed: 0, recurring: 0, shares: 0, total: 0 }; + accountCounts: AccountCounts = { loan: 0, savings: 0, fixed: 0, recurring: 0, shares: 0, total: 0 };🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/clients/clients-view/general-tab/general-tab.component.ts` around lines 258 - 261, Extract the inline shape used for accountCounts into a named interface (e.g., AccountCounts) and use that interface for the accountCounts property type; update the declaration on general-tab.component.ts by adding an interface like interface AccountCounts { loan: number; savings: number; fixed: number; recurring: number; shares: number; total: number } and change accountCounts' type to AccountCounts to improve maintainability and reuse (refer to the accountCounts symbol and currentAccountType for locating the surrounding state).
297-339: Closed status code sets match AccountsFilterPipe
CLOSED_LOAN_CODES,CLOSED_SAVING_CODES, andCLOSED_SHARE_CODESinsrc/app/clients/clients-view/general-tab/general-tab.component.tsuse the same status code strings as thestatus === 'closed'branches insrc/app/pipes/accounts-filter.pipe.ts, so counts should align with the rendered lists; consider centralizing these constants to reduce future duplication drift.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/clients/clients-view/general-tab/general-tab.component.ts` around lines 297 - 339, Summary: duplicate closed-status code sets (CLOSED_LOAN_CODES, CLOSED_SAVING_CODES, CLOSED_SHARE_CODES) in computeAccountCounts duplicate the logic in AccountsFilterPipe leading to drift; centralize them. Fix: extract the closed status code sets into a single exported constant (e.g., CLOSED_ACCOUNT_STATUS_CODES or separate CLOSED_LOAN_CODES/.. in a new shared module/file) and import that constant into both general-tab.component.ts (used by computeAccountCounts) and accounts-filter.pipe.ts (used by its status === 'closed' branch); update computeAccountCounts to remove its local sets and reference the imported constants so both components use the same source of truth.src/app/clients/clients-view/general-tab/general-tab.component.scss (3)
207-254: 💤 Low valueConsider alternatives to
::ng-deepfor Material table styling.The
::ng-deeppseudo-element is deprecated in Angular and flagged by Stylelint. While:host ::ng-deepremains the transitional pattern for deep styling, Angular recommends alternatives:
- Disable view encapsulation:
encapsulation: ViewEncapsulation.None(affects global scope)- Use global styles in
styles.scssfor shared table styling- Use Material's theming APIs for component customization
The MDC class targeting (
.mat-mdc-header-row,.mat-mdc-cell, etc.) correctly follows the learning to prefer MDC DOM classes in Angular Material v20+.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/clients/clients-view/general-tab/general-tab.component.scss` around lines 207 - 254, The component uses the deprecated selector ":host ::ng-deep .data-table" to style Material MDC table classes (e.g., .mat-mdc-header-row, .mat-mdc-header-cell, .mat-mdc-cell); remove the ::ng-deep usage and either (A) move these selectors wholesale into the global styles file (styles.scss) so they apply app-wide, or (B) keep them in this component by setting encapsulation: ViewEncapsulation.None on the component and removing :host ::ng-deep, ensuring the same selectors (.data-table .mat-mdc-header-row, .mat-mdc-header-cell, .mat-mdc-cell, etc.) are used; choose one approach and update the component decorator or global stylesheet accordingly.Source: Linters/SAST tools
74-193: ⚡ Quick winAlign spacing values to the 8px grid system.
The coding guidelines require sticking to the 8px grid system for visual design and spacing. Several values deviate from this standard:
- Line 75:
padding: 20px 24px(20px should be 16px or 24px)- Line 80:
margin-top: 24px✓ (compliant)- Line 87:
margin-bottom: 12px,gap: 12px(12px should be 8px or 16px)- Line 127:
padding: 14px 18px(14px → 16px, 18px → 16px or 24px)♻️ Proposed alignment to 8px grid
.tab-container { - padding: 20px 24px; + padding: 16px 24px; background: var(--ch-surface-alt); } .section-head { display: flex; align-items: baseline; justify-content: space-between; - margin-bottom: 12px; - gap: 12px; + margin-bottom: 16px; + gap: 16px; } .kpi-card { flex: 1 1 0; min-width: 180px; background: var(--ch-surface); border: 1px solid var(--ch-border); border-radius: 6px; - padding: 14px 18px; + padding: 16px 16px; display: flex; flex-direction: column; gap: 6px;Review all spacing/padding/margin values throughout the file for 8px grid compliance.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/clients/clients-view/general-tab/general-tab.component.scss` around lines 74 - 193, Update SCSS spacing to the 8px grid: change .tab-container padding from 20px 24px to 16px 24px; change .section-head margin-bottom and gap from 12px to 16px; change .section-link gap from 4px to 8px; change .kpi-grid gap from 12px to 16px; change .kpi-card padding from 14px 18px to 16px 16px; change .kpi-card & .savings before widths remain but ensure any internal gaps follow 8px multiples; change .info-banner padding from 18px 22px to 16px 24px and .info-banner gap from 12px to 16px; change .info-banner-text gap from 10px to 8px. Locate these in the selectors named .tab-container, .section-head, .section-link, .kpi-grid, .kpi-card, .info-banner, and .info-banner-text and apply the new 8px-multiple values consistently.Source: Coding guidelines
9-72: Design tokens in general-tab.component.scss: align with existing theming tokens / avoid duplication
src/main.scss’s color theming is driven by Material CSS variables (e.g.,var(--md-sys-color-*)), whilegeneral-tab.component.scssintroduces its own--ch-*/--pr-*custom properties on:host/:host-context. If--ch-*/--pr-*are meant to be the canonical design-token layer, centralize their definitions (shared SCSS/mixin/theme file) or document the mapping to--md-sys-color-*to prevent drift across components.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/clients/clients-view/general-tab/general-tab.component.scss` around lines 9 - 72, general-tab.component.scss currently defines local design tokens (--ch-*/--pr-*) on :host and :host-context which duplicates theming from src/main.scss; remove these local definitions and instead import or reference the centralized theme tokens (create/extend the shared SCSS or theme mixin that exposes the canonical --ch-*/--pr-* or maps them to var(--md-sys-color-*) ), update general-tab.component.scss to use the imported/shared tokens (keep only component-specific overrides if needed) and add a short comment documenting the mapping between --ch-*/--pr-* and var(--md-sys-color-*) so other components won’t drift.Source: Coding guidelines
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 3f79a3b0-5333-4b26-aab8-d748289ed4dc
📒 Files selected for processing (23)
src/app/clients/clients-view/clients-view.component.htmlsrc/app/clients/clients-view/clients-view.component.scsssrc/app/clients/clients-view/clients-view.component.tssrc/app/clients/clients-view/general-tab/general-tab.component.htmlsrc/app/clients/clients-view/general-tab/general-tab.component.scsssrc/app/clients/clients-view/general-tab/general-tab.component.tssrc/app/clients/clients.component.htmlsrc/app/clients/clients.component.scsssrc/app/clients/clients.component.tssrc/app/pipes/format-number.pipe.tssrc/assets/translations/cs-CS.jsonsrc/assets/translations/de-DE.jsonsrc/assets/translations/en-US.jsonsrc/assets/translations/es-CL.jsonsrc/assets/translations/es-MX.jsonsrc/assets/translations/fr-FR.jsonsrc/assets/translations/it-IT.jsonsrc/assets/translations/ko-KO.jsonsrc/assets/translations/lt-LT.jsonsrc/assets/translations/lv-LV.jsonsrc/assets/translations/ne-NE.jsonsrc/assets/translations/pt-PT.jsonsrc/assets/translations/sw-SW.json
| /** | ||
| * Resolves a UI-level severity for a loan account. | ||
| * Returns one of: 'active' | 'arrears' | 'pending' | 'closed' | 'overpaid' | ||
| */ | ||
| loanSeverity(loan: any): string { | ||
| if (loan.inArrears) return 'arrears'; | ||
| if (loan.status?.overpaid) return 'overpaid'; | ||
| if (loan.status?.pendingApproval) return 'pending'; | ||
| if (loan.status?.active) return 'active'; | ||
| if (loan.status?.closed) return 'closed'; | ||
| return 'pending'; | ||
| } | ||
|
|
||
| /** | ||
| * Generic status resolver for non-loan accounts. | ||
| */ | ||
| accountSeverity(account: any): string { | ||
| if (account.status?.submittedAndPendingApproval) return 'pending'; | ||
| if (account.status?.active) return 'active'; | ||
| if (account.status?.closed) return 'closed'; | ||
| return 'pending'; | ||
| } | ||
|
|
||
| /** Repayment progress as a 0–100 percentage for a loan account. */ | ||
| loanProgress(loan: any): number { | ||
| const paid = Number(loan.amountPaid ?? 0); | ||
| if (loan.productType === 'loan') { | ||
| const original = Number(loan.originalLoan ?? 0); | ||
| if (original <= 0) return 0; | ||
| return Math.min(Math.max((paid / original) * 100, 0), 100); | ||
| } else if (loan.productType === 'working-capital') { | ||
| const original = Number(loan.loanBalance ?? 0) + paid; | ||
| if (original <= 0) return 0; | ||
| return Math.min(Math.max((paid / original) * 100, 0), 100); | ||
| } | ||
| return 0; | ||
| } |
There was a problem hiding this comment.
Replace any parameter types with proper interfaces.
The loanSeverity, accountSeverity, and loanProgress methods accept any parameters, which bypasses TypeScript's type safety. Based on learnings, avoid using any for API response shapes and introduce specific interfaces instead.
🔒 Proposed fix: introduce loan and account interfaces
Define minimal interfaces for the expected shapes:
+interface LoanAccount {
+ id: string;
+ productType?: string;
+ inArrears?: boolean;
+ status?: {
+ overpaid?: boolean;
+ pendingApproval?: boolean;
+ active?: boolean;
+ closed?: boolean;
+ };
+ amountPaid?: number;
+ originalLoan?: number;
+ loanBalance?: number;
+}
+
+interface GenericAccount {
+ status?: {
+ submittedAndPendingApproval?: boolean;
+ active?: boolean;
+ closed?: boolean;
+ };
+}
+
/**
* Resolves a UI-level severity for a loan account.
* Returns one of: 'active' | 'arrears' | 'pending' | 'closed' | 'overpaid'
*/
- loanSeverity(loan: any): string {
+ loanSeverity(loan: LoanAccount): string {
if (loan.inArrears) return 'arrears';
if (loan.status?.overpaid) return 'overpaid';
if (loan.status?.pendingApproval) return 'pending';
if (loan.status?.active) return 'active';
if (loan.status?.closed) return 'closed';
return 'pending';
}
/**
* Generic status resolver for non-loan accounts.
*/
- accountSeverity(account: any): string {
+ accountSeverity(account: GenericAccount): string {
if (account.status?.submittedAndPendingApproval) return 'pending';
if (account.status?.active) return 'active';
if (account.status?.closed) return 'closed';
return 'pending';
}
/** Repayment progress as a 0–100 percentage for a loan account. */
- loanProgress(loan: any): number {
+ loanProgress(loan: LoanAccount): number {
const paid = Number(loan.amountPaid ?? 0);
if (loan.productType === 'loan') {
const original = Number(loan.originalLoan ?? 0);
if (original <= 0) return 0;
return Math.min(Math.max((paid / original) * 100, 0), 100);
} else if (loan.productType === 'working-capital') {
const original = Number(loan.loanBalance ?? 0) + paid;
if (original <= 0) return 0;
return Math.min(Math.max((paid / original) * 100, 0), 100);
}
return 0;
}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/app/clients/clients-view/general-tab/general-tab.component.ts` around
lines 349 - 385, Methods loanSeverity, accountSeverity and loanProgress use
loose any types which bypass TypeScript checks; define and use minimal
interfaces (e.g., LoanSummary and AccountSummary) that capture the required
fields (for LoanSummary: inArrears, productType, amountPaid, originalLoan,
loanBalance, status with boolean properties
overpaid/pendingApproval/active/closed; for AccountSummary: status with
submittedAndPendingApproval/active/closed booleans) and replace the any
parameter types with these interfaces in loanSeverity(loan: LoanSummary),
accountSeverity(account: AccountSummary) and loanProgress(loan: LoanSummary);
update any related imports/types in the file to use these new interfaces and
ensure nullable fields use optional properties (?), preserving current runtime
checks.
Source: Learnings
| /** Two-letter uppercase initials from a display name. */ | ||
| initials(name: string): string { | ||
| if (!name) return '?'; | ||
| const display = this.hideClientData ? name : name; | ||
| const parts = display.trim().split(/\s+/).filter(Boolean); | ||
| if (parts.length === 0) return '?'; | ||
| if (parts.length === 1) return parts[0].substring(0, 2).toUpperCase(); | ||
| return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase(); | ||
| } |
There was a problem hiding this comment.
Redundant ternary defeats compliance masking.
Line 77 has this.hideClientData ? name : name — both branches return the same unmasked name, so compliance masking is never applied to avatar initials. This likely should use maskName(name) in the true branch to match the intent elsewhere.
🛡️ Proposed fix
initials(name: string): string {
if (!name) return '?';
- const display = this.hideClientData ? name : name;
+ const display = this.hideClientData ? this.maskName(name) : name;
const parts = display.trim().split(/\s+/).filter(Boolean);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| /** Two-letter uppercase initials from a display name. */ | |
| initials(name: string): string { | |
| if (!name) return '?'; | |
| const display = this.hideClientData ? name : name; | |
| const parts = display.trim().split(/\s+/).filter(Boolean); | |
| if (parts.length === 0) return '?'; | |
| if (parts.length === 1) return parts[0].substring(0, 2).toUpperCase(); | |
| return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase(); | |
| } | |
| /** Two-letter uppercase initials from a display name. */ | |
| initials(name: string): string { | |
| if (!name) return '?'; | |
| const display = this.hideClientData ? this.maskName(name) : name; | |
| const parts = display.trim().split(/\s+/).filter(Boolean); | |
| if (parts.length === 0) return '?'; | |
| if (parts.length === 1) return parts[0].substring(0, 2).toUpperCase(); | |
| return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase(); | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/app/clients/clients.component.ts` around lines 74 - 82, The
initials(name: string) function currently ignores masking because it uses the
redundant expression this.hideClientData ? name : name; change the true branch
to apply the masking function used elsewhere (e.g., maskName(name)) so that when
this.hideClientData is true the display variable receives the masked value; keep
the rest of initials logic the same and reference the initials method and the
hideClientData and maskName symbols when making the change.
| toggleShowClosed() { | ||
| this.showClosedAccounts = !this.showClosedAccounts; | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check if showClosedAccounts or status filtering is implemented elsewhere
rg -nP --type=ts -C3 'showClosed|closedAccounts|status.*filter' -g '!node_modules' -g 'clients.service.ts'Repository: openMF/web-app
Length of output: 40
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# 1) Find all usages of showClosedAccounts in the TS codebase
rg -n --type=ts "showClosedAccounts" .
# 2) Locate the definition and call sites of searchByText()
rg -n --type=ts "searchByText" src/app
# 3) Inspect clients.service.ts for the request/params used for the clients search endpoint
# (print only the most relevant portions)
FILE="$(fd -t f -e ts "clients.service.ts" src/app || true)"
if [ -z "${FILE}" ]; then
FILE="$(fd -t f -e ts "client*.service.ts" src/app | head -n 1 || true)"
fi
echo "Using service file: ${FILE}"
if [ -n "${FILE}" ]; then
# show around likely HTTP/query building code
rg -n --type=ts "clients?/search|/v2/clients|searchByText|HttpClient|params|query" "${FILE}" -n -S -C3 || true
# also show type of method that wraps the search
rg -n --type=ts "searchByText\\s*\\(|search\\s*By\\s*Text\\s*\\(" "${FILE}" -n -S -C5 || true
# finally, dump the full searchByText method block if small enough
METHOD_LINE="$(rg -n --type=ts "searchByText\\s*\\(" "${FILE}" | head -n 1 | cut -d: -f1 || true)"
if [ -n "${METHOD_LINE}" ]; then
start=$((METHOD_LINE-20)); end=$((METHOD_LINE+120))
sed -n "${start},${end}p" "${FILE}"
fi
fi
# 4) Check for any other filter/status params passed from the component
rg -n --type=ts "closed|status" src/app/clientsRepository: openMF/web-app
Length of output: 22447
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Show the relevant TS logic around showClosedAccounts + toggle + getClients/dataSource update
sed -n '130,320p' src/app/clients/clients.component.ts | cat -n
# Find where showClosedAccounts appears in the clients component template(s)
rg -n --hidden --glob '!**/node_modules/**' "showClosedAccounts" src/app/clients
# Dump the relevant portion of the main component HTML if present
HTML_FILES=$(fd -t f "clients.component.html" src/app/clients || true)
if [ -n "${HTML_FILES}" ]; then
for f in ${HTML_FILES}; do
echo "---- $f ----"
sed -n '1,260p' "$f" | cat -n
done
fi
# Also check if any client-side filtering is done based on "closed" near dataSource usage
rg -n --type=ts "dataSource\\.|filterData|searchByText\\(|getClients\\(|showClosed|closedAccounts|clientStatusType\\.closed" src/app/clients/clients.component.ts -n -SRepository: openMF/web-app
Length of output: 16445
Fix “Show Closed Accounts” toggle in clients list
toggleShowClosed()flipsshowClosedAccounts, butgetClients()never uses it—searchByText()is called with onlyfilterText, pagination, and sort params (src/app/clients/clients.component.ts).ClientsService.searchByText()builds the/v2/clients/searchrequest with onlyrequest.text,page,size, and optionalsorts, so the returneddata.contentis assigned directly todataSource.datawithout any closed/status filtering (src/app/clients/clients.service.ts).
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/app/clients/clients.component.ts` around lines 199 - 201, The
toggleShowClosed() flips showClosedAccounts but neither getClients() nor
ClientsService.searchByText() uses it, so closed accounts are never filtered;
update the flow so the toggle affects results by either (preferred) extending
ClientsService.searchByText(request) to accept a showClosed flag (or include it
on the request object) and send it to the backend so the /v2/clients/search call
filters server-side, or (alternative) have getClients() call searchByText(...)
as today and then apply a client-side filter on the returned data.content before
assigning dataSource.data; modify the functions referenced (toggleShowClosed,
getClients, ClientsService.searchByText and the handling of data.content /
dataSource.data) accordingly so showClosedAccounts controls which clients are
displayed.
f58b320 to
b5bae13
Compare
There was a problem hiding this comment.
Actionable comments posted: 5
♻️ Duplicate comments (3)
src/assets/translations/sw-SW.json (1)
773-774:⚠️ Potential issue | 🟠 Major | ⚡ Quick winFix incorrect Swahili glossary terms for finance/status/action keys.
Several entries still use semantically wrong terms (e.g.,
Interestas “Hamu”,PENDINGas “INAKARIBISHWA”,Waiveas “Kataa”), which can mislead users during financial operations. Please normalize these to domain-accurate wording.Suggested patch
- "% Interest": "Hamu", + "% Interest": "Riba", ... - "Due interest": "Nia inayostahili", + "Due interest": "Riba inayodaiwa", ... - "Interest": "Hamu", + "Interest": "Riba", ... - "Interest posting": "Nia ya kuchapisha", + "Interest posting": "Uchapishaji wa riba", ... - "None": "Mtaji", + "None": "Hakuna", ... - "PENDING": "INAKARIBISHWA", + "PENDING": "INASUBIRI", ... - "Waive": "Kataa", + "Waive": "Kusamehe", ... - "loan product will become inactive and unavailable to clients": "Tarehe ambayo bidhaa ya mkopo itaacha kutumika na haitapatikana kwa wateja. Ikiwa tupu, bidhaa ya kupakia haitafanya kazi kamwe." + "loan product will become inactive and unavailable to clients": "Tarehe ambayo bidhaa ya mkopo itaacha kutumika na haitapatikana kwa wateja. Ikiwa tupu, bidhaa ya mkopo haitazimwa kiotomatiki."Also applies to: 833-834, 870-874, 902-902, 4508-4508, 4595-4595, 4601-4601
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/assets/translations/sw-SW.json` around lines 773 - 774, Replace semantically incorrect Swahili finance/status/action values with domain-accurate terms: change "% Interest" value from "Hamu" to "Riba" (and ensure "% Loan Amount + Interest" stays as "Kiasi cha Mkopo + Riba"), change status "PENDING" to a waiting-state term like "INASUBIRI", and change action "Waive" from "Kataa" to a proper waiver term such as "Kuachilia" or "Kutoa msamaha"; update these keys ("% Interest", "% Loan Amount + Interest", "PENDING", "Waive") throughout the file (including the other occurrences noted) to use the corrected translations consistently.src/app/clients/clients.component.ts (2)
200-202:⚠️ Potential issue | 🔴 Critical | ⚡ Quick winWire
showClosedAccountsto the client search request.
toggleShowClosed()flips the boolean, butgetClients()(line 254) never passesshowClosedAccountstosearchByText(), so the toggle has no effect on displayed results.🛡️ Proposed fix
Extend
ClientsService.searchByText()to accept ashowClosedparameter and include it in the/v2/clients/searchrequest. Then update the call on line 254:- .searchByText(this.filterText, this.currentPage, this.pageSize, this.sortAttribute, this.sortDirection) + .searchByText(this.filterText, this.currentPage, this.pageSize, this.sortAttribute, this.sortDirection, this.showClosedAccounts)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/clients/clients.component.ts` around lines 200 - 202, The toggleShowClosed flips the component boolean but getClients never forwards showClosedAccounts to the backend; update ClientsService.searchByText to accept a showClosed (boolean) argument and include it in the /v2/clients/search request payload/query params, update any typings/signature for searchByText accordingly, and then modify the call from the component's getClients to pass this.showClosedAccounts (and update any unit tests or call sites) so the toggle actually affects search results.
76-83:⚠️ Potential issue | 🔴 Critical | ⚡ Quick winApply compliance masking before extracting initials.
initials()does not respecthideClientData—it always exposes the raw name. Whenenvironment.complianceHideClientDatais true, this leaks PII via avatar initials.🛡️ Proposed fix
initials(name: string): string { if (!name) return '?'; - const parts = name.trim().split(/\s+/).filter(Boolean); + const display = this.hideClientData ? this.maskName(name) : name; + const parts = display.trim().split(/\s+/).filter(Boolean); if (parts.length === 0) return '?'; if (parts.length === 1) return parts[0].substring(0, 2).toUpperCase(); return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/clients/clients.component.ts` around lines 76 - 83, The initials(name: string) method in clients.component.ts currently returns raw initials and ignores the compliance masking flag; update initials() to first apply the same compliance masking used elsewhere when environment.complianceHideClientData (or the component's hideClientData flag) is true, and then compute initials from the masked/obfuscated name (falling back to '?' if masking yields empty). Ensure you reference the existing initials() function and the environment.complianceHideClientData / hideClientData boolean used in the component so the avatar initials never reveal raw PII.
🧹 Nitpick comments (2)
src/app/clients/clients.component.ts (2)
107-110: 💤 Low valueConsider normalizing
metaDate()return type.Returning
Date | string | nullrequires callers to handle both Date and string values. If the backend API returns different types for different date fields, consider normalizing them to a single type (e.g., always Date or always string) for consistency.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/clients/clients.component.ts` around lines 107 - 110, metaDate currently returns Date | string | null causing callers to handle mixed types; update metaDate(row: any) to normalize all date sources (row.activationDate, row.submittedOnDate, row.timeline?.closedOnDate) to a single type (pick Date or ISO string) before returning and keep null for missing values; e.g., parse any string values into Date objects (or format Date objects to ISO strings) and return that consistent type so callers of metaDate no longer need to branch on Date vs string.
68-74:maskName()is used, but masking logic is duplicated
src/app/clients/clients.component.htmlcallsmaskName(row.displayName)whenhideClientDatais true, sosrc/app/clients/clients.component.ts’smaskName()is not dead code.- There’s also a separate
maskName()insrc/app/clients/clients-view/clients-view.component.ts(used byclients-view.component.html), and the logic differs—consider extracting a shared helper to keep masking behavior consistent.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/app/clients/clients.component.ts` around lines 68 - 74, Both components implement their own maskName logic (maskName in ClientsComponent and maskName in ClientsViewComponent) causing duplication and inconsistent behavior; create a single exported helper function (e.g., maskName) in a shared utility module and replace the component-local maskName implementations with imports of that helper in both ClientsComponent and ClientsViewComponent, update clients.component.html and clients-view.component.html usages to continue calling maskName(row.displayName) unchanged, and remove the duplicated methods so masking logic is centralized and consistent across the app.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/app/clients/clients.component.ts`:
- Around line 85-99: The severity method uses an untyped parameter (row: any);
define a proper Client interface (e.g., interface Client { status?: { code?:
string } } or a more specific ClientRow) and replace the any with that type in
the severity signature (severity(row: Client): Severity). Add the new interface
in this file or import it from the shared models/types module, update any other
usages of severity/call sites if needed to match the new type, and ensure
TypeScript strict checks pass.
- Around line 264-267: The error callback currently only resets this.isLoading
and calls this.cdr.markForCheck(), so add explicit error handling in that
subscribe error handler: log the error (e.g., console.error or your component
logger) and show a user-facing notification (e.g., call your
toast/snackbar/notification method) so users know the search failed; ensure you
still set this.isLoading = false and call this.cdr.markForCheck() in that error
branch. Target the subscribe/error callback in
src/app/clients/clients.component.ts (the block that currently only executes ()
=> { this.isLoading = false; this.cdr.markForCheck(); }) and augment it to
accept the error parameter, log it, and invoke the app's notification API.
In `@src/assets/translations/en-US.json`:
- Line 4154: The JSON English copy contains grammar/typo mistakes: update the
translation key/value for "“Maker-Checker” principle requires every tasks" to
use correct grammar ("every task") and fix the other flagged strings (the
entries at the other mentioned keys that currently read "This sections..." and
"load product") to correct English ("This section" or "These sections" as
appropriate, and "load product(s)" or "load products" depending on intent).
Locate the exact keys shown in the diff (e.g., the key starting with
“Maker-Checker” and the entries at the other two reported keys) and replace the
faulty phrases with the grammatically correct alternatives so the end-user copy
is accurate.
- Line 928: Fix the user-facing typos in the translations: update the value for
the "Quarterly" key from "Quartely" to "Quarterly", and also correct the other
misspelled value shown as "four" (update it to the intended "four"
spelling/context if it's incorrect or to the proper label if it's a numeric word
key); locate the entries by the JSON keys "Quarterly" and the nearby translation
entry referenced in the review and replace the erroneous strings with the
correct spellings so the UI displays the proper labels.
In `@src/assets/translations/es-MX.json`:
- Line 1436: Several newly added es-MX entries have English values (e.g., "Quick
Access", "Center banking", "Configure offerings", "Group lending", "Journals &
ledger", "System configuration"); update the es-MX JSON so the values are proper
Spanish translations while keeping the keys unchanged—find these keys in
src/assets/translations/es-MX.json (and the other occurrences noted) and replace
their string values with correct Spanish equivalents (preserve
punctuation/capitalization and use accents where appropriate), then run the
locale/JSON linter or tests to ensure no syntax/issues remain.
---
Duplicate comments:
In `@src/app/clients/clients.component.ts`:
- Around line 200-202: The toggleShowClosed flips the component boolean but
getClients never forwards showClosedAccounts to the backend; update
ClientsService.searchByText to accept a showClosed (boolean) argument and
include it in the /v2/clients/search request payload/query params, update any
typings/signature for searchByText accordingly, and then modify the call from
the component's getClients to pass this.showClosedAccounts (and update any unit
tests or call sites) so the toggle actually affects search results.
- Around line 76-83: The initials(name: string) method in clients.component.ts
currently returns raw initials and ignores the compliance masking flag; update
initials() to first apply the same compliance masking used elsewhere when
environment.complianceHideClientData (or the component's hideClientData flag) is
true, and then compute initials from the masked/obfuscated name (falling back to
'?' if masking yields empty). Ensure you reference the existing initials()
function and the environment.complianceHideClientData / hideClientData boolean
used in the component so the avatar initials never reveal raw PII.
In `@src/assets/translations/sw-SW.json`:
- Around line 773-774: Replace semantically incorrect Swahili
finance/status/action values with domain-accurate terms: change "% Interest"
value from "Hamu" to "Riba" (and ensure "% Loan Amount + Interest" stays as
"Kiasi cha Mkopo + Riba"), change status "PENDING" to a waiting-state term like
"INASUBIRI", and change action "Waive" from "Kataa" to a proper waiver term such
as "Kuachilia" or "Kutoa msamaha"; update these keys ("% Interest", "% Loan
Amount + Interest", "PENDING", "Waive") throughout the file (including the other
occurrences noted) to use the corrected translations consistently.
---
Nitpick comments:
In `@src/app/clients/clients.component.ts`:
- Around line 107-110: metaDate currently returns Date | string | null causing
callers to handle mixed types; update metaDate(row: any) to normalize all date
sources (row.activationDate, row.submittedOnDate, row.timeline?.closedOnDate) to
a single type (pick Date or ISO string) before returning and keep null for
missing values; e.g., parse any string values into Date objects (or format Date
objects to ISO strings) and return that consistent type so callers of metaDate
no longer need to branch on Date vs string.
- Around line 68-74: Both components implement their own maskName logic
(maskName in ClientsComponent and maskName in ClientsViewComponent) causing
duplication and inconsistent behavior; create a single exported helper function
(e.g., maskName) in a shared utility module and replace the component-local
maskName implementations with imports of that helper in both ClientsComponent
and ClientsViewComponent, update clients.component.html and
clients-view.component.html usages to continue calling maskName(row.displayName)
unchanged, and remove the duplicated methods so masking logic is centralized and
consistent across the app.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: f793b7b8-5ed1-4a2c-9671-9e181692481b
📒 Files selected for processing (23)
src/app/clients/clients-view/clients-view.component.htmlsrc/app/clients/clients-view/clients-view.component.scsssrc/app/clients/clients-view/clients-view.component.tssrc/app/clients/clients-view/general-tab/general-tab.component.htmlsrc/app/clients/clients-view/general-tab/general-tab.component.scsssrc/app/clients/clients-view/general-tab/general-tab.component.tssrc/app/clients/clients.component.htmlsrc/app/clients/clients.component.scsssrc/app/clients/clients.component.tssrc/app/pipes/format-number.pipe.tssrc/assets/translations/cs-CS.jsonsrc/assets/translations/de-DE.jsonsrc/assets/translations/en-US.jsonsrc/assets/translations/es-CL.jsonsrc/assets/translations/es-MX.jsonsrc/assets/translations/fr-FR.jsonsrc/assets/translations/it-IT.jsonsrc/assets/translations/ko-KO.jsonsrc/assets/translations/lt-LT.jsonsrc/assets/translations/lv-LV.jsonsrc/assets/translations/ne-NE.jsonsrc/assets/translations/pt-PT.jsonsrc/assets/translations/sw-SW.json
🚧 Files skipped from review as they are similar to previous changes (19)
- src/app/pipes/format-number.pipe.ts
- src/app/clients/clients.component.scss
- src/app/clients/clients-view/clients-view.component.ts
- src/app/clients/clients-view/clients-view.component.scss
- src/app/clients/clients-view/general-tab/general-tab.component.ts
- src/app/clients/clients.component.html
- src/app/clients/clients-view/clients-view.component.html
- src/app/clients/clients-view/general-tab/general-tab.component.scss
- src/app/clients/clients-view/general-tab/general-tab.component.html
- src/assets/translations/ko-KO.json
- src/assets/translations/ne-NE.json
- src/assets/translations/es-CL.json
- src/assets/translations/pt-PT.json
- src/assets/translations/lt-LT.json
- src/assets/translations/cs-CS.json
- src/assets/translations/de-DE.json
- src/assets/translations/lv-LV.json
- src/assets/translations/it-IT.json
- src/assets/translations/fr-FR.json
| /** UI severity class for a row from its status.code. */ | ||
| severity(row: any): Severity { | ||
| const code: string = row?.status?.code ?? ''; | ||
| if (code === 'clientStatusType.active' || code === 'clientStatusType.approved') return 'active'; | ||
| if ( | ||
| code === 'clientStatusType.pending' || | ||
| code === 'clientStatusType.submitted.and.pending.approval' || | ||
| code.includes('transfer') | ||
| ) { | ||
| return 'pending'; | ||
| } | ||
| if (code === 'clientStatusType.closed' || code === 'clientStatusType.withdraw') return 'closed'; | ||
| if (code === 'clientStatusType.rejected') return 'rejected'; | ||
| return 'neutral'; | ||
| } |
There was a problem hiding this comment.
Replace any with a typed Client interface.
row: any violates strict typing conventions. Define a client interface with at least { status?: { code?: string } } to type-check row access.
As per coding guidelines, "Use TypeScript for all application code with strict typing conventions." Based on learnings, avoid any for API responses and introduce specific interfaces/types for response shapes.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/app/clients/clients.component.ts` around lines 85 - 99, The severity
method uses an untyped parameter (row: any); define a proper Client interface
(e.g., interface Client { status?: { code?: string } } or a more specific
ClientRow) and replace the any with that type in the severity signature
(severity(row: Client): Severity). Add the new interface in this file or import
it from the shared models/types module, update any other usages of severity/call
sites if needed to match the new type, and ensure TypeScript strict checks pass.
Sources: Coding guidelines, Learnings
| () => { | ||
| this.isLoading = false; | ||
| this.cdr.markForCheck(); | ||
| } |
There was a problem hiding this comment.
Log or notify user on client search errors.
The error callback silently swallows exceptions—no log, no user feedback. When the search request fails, users see the loading spinner disappear but have no indication of the failure.
🛡️ Proposed fix
- () => {
+ (error) => {
+ console.error('Failed to load clients:', error);
+ // Optionally: show a user-facing error notification
this.isLoading = false;
this.cdr.markForCheck();
}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/app/clients/clients.component.ts` around lines 264 - 267, The error
callback currently only resets this.isLoading and calls this.cdr.markForCheck(),
so add explicit error handling in that subscribe error handler: log the error
(e.g., console.error or your component logger) and show a user-facing
notification (e.g., call your toast/snackbar/notification method) so users know
the search failed; ensure you still set this.isLoading = false and call
this.cdr.markForCheck() in that error branch. Target the subscribe/error
callback in src/app/clients/clients.component.ts (the block that currently only
executes () => { this.isLoading = false; this.cdr.markForCheck(); }) and augment
it to accept the error parameter, log it, and invoke the app's notification API.
| "Withdraw Deposit": "Withdraw Deposit", | ||
| "Principal, Interest, Penalties, Fees Order": "Principal, Interest, Penalties, Fees Order", | ||
| "Progressive": "Progressive", | ||
| "Quarterly": "Quartely", |
There was a problem hiding this comment.
Fix user-facing typos in catalog labels.
These values appear to be accidental misspellings and will surface directly in UI text ("Quartely" and "four").
Suggested patch
- "Quarterly": "Quartely",
+ "Quarterly": "Quarterly",
...
- "fourth": "four",
+ "fourth": "fourth",Also applies to: 1015-1015
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/assets/translations/en-US.json` at line 928, Fix the user-facing typos in
the translations: update the value for the "Quarterly" key from "Quartely" to
"Quarterly", and also correct the other misspelled value shown as "four" (update
it to the intended "four" spelling/context if it's incorrect or to the proper
label if it's a numeric word key); locate the entries by the JSON keys
"Quarterly" and the nearby translation entry referenced in the review and
replace the erroneous strings with the correct spellings so the UI displays the
proper labels.
| "Savings accounts": "Savings accounts", | ||
| "Offices and staff": "Offices & staff", | ||
| "System configuration": "Configuration" | ||
| "“Maker-Checker” principle requires every tasks": "The “Maker-Checker” principle requires every task to be completed by two people to reduce the chance of errors and misuse. One person initiates the process and the second completes it." |
There was a problem hiding this comment.
Correct grammar/wording regressions in English copy.
These changed strings contain grammatical errors/typos ("every tasks", "This sections...", "load product"), which will be visible to end users.
Suggested patch
- "“Maker-Checker” principle requires every tasks": "The “Maker-Checker” principle requires every task to be completed by two people to reduce the chance of errors and misuse. One person initiates the process and the second completes it."
+ "“Maker-Checker” principle requires every tasks": "The “Maker-Checker” principle requires every task to be completed by two people to reduce the chance of errors and misuse. One person initiates the process and the second completes it."
...
- "This sections defines an interest penalty": "This sections defines an interest penalty for pre-mature closure.",
+ "This sections defines an interest penalty": "This section defines an interest penalty for pre-mature closure.",
...
- "loan product will become inactive and unavailable to clients": "The date that the loan product will become inactive and unavailable to clients. If blank, the load product will never become inactive."
+ "loan product will become inactive and unavailable to clients": "The date that the loan product will become inactive and unavailable to clients. If blank, the loan product will never become inactive."Also applies to: 4680-4680, 4713-4713
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/assets/translations/en-US.json` at line 4154, The JSON English copy
contains grammar/typo mistakes: update the translation key/value for
"“Maker-Checker” principle requires every tasks" to use correct grammar ("every
task") and fix the other flagged strings (the entries at the other mentioned
keys that currently read "This sections..." and "load product") to correct
English ("This section" or "These sections" as appropriate, and "load
product(s)" or "load products" depending on intent). Locate the exact keys shown
in the diff (e.g., the key starting with “Maker-Checker” and the entries at the
other two reported keys) and replace the faulty phrases with the grammatically
correct alternatives so the end-user copy is accurate.
| "Progress Bar": "Barra de progreso", | ||
| "Provisioning Entries": "Entradas de aprovisionamiento", | ||
| "Question": "Pregunta", | ||
| "Quick Access": "Quick Access", |
There was a problem hiding this comment.
Translate newly added es-MX values to avoid mixed-language UI.
Several newly added es-MX values remain in English, which causes visible locale inconsistency in production UI (for example: Quick Access, Center banking, Configure offerings, Group lending, Journals & ledger, System configuration).
💡 Proposed fix (sample)
- "Quick Access": "Quick Access",
+ "Quick Access": "Acceso rápido",
...
- "Center banking": "Center banking",
+ "Center banking": "Banca de centros",
...
- "Configure offerings": "Configure offerings",
+ "Configure offerings": "Configurar ofertas",
...
- "Group lending": "Group lending",
+ "Group lending": "Crédito grupal",
...
- "Journals and ledger": "Journals & ledger",
+ "Journals and ledger": "Diarios y libro mayor",
...
- "Navigate directly to any platform area": "Navigate directly to any platform area",
+ "Navigate directly to any platform area": "Navega directamente a cualquier área de la plataforma",
...
- "Offices and staff": "Offices & staff",
+ "Offices and staff": "Oficinas y personal",
...
- "Profiles and accounts": "Profiles & accounts",
+ "Profiles and accounts": "Perfiles y cuentas",
...
- "Savings accounts": "Savings accounts",
+ "Savings accounts": "Cuentas de ahorro",
...
- "System configuration": "Configuration",
+ "System configuration": "Configuración",Also applies to: 3381-3381, 3415-3415, 3646-3646, 3659-3659, 3744-3744, 3777-3777, 3806-3806, 3852-3852, 3907-3907
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/assets/translations/es-MX.json` at line 1436, Several newly added es-MX
entries have English values (e.g., "Quick Access", "Center banking", "Configure
offerings", "Group lending", "Journals & ledger", "System configuration");
update the es-MX JSON so the values are proper Spanish translations while
keeping the keys unchanged—find these keys in src/assets/translations/es-MX.json
(and the other occurrences noted) and replace their string values with correct
Spanish equivalents (preserve punctuation/capitalization and use accents where
appropriate), then run the locale/JSON linter or tests to ensure no
syntax/issues remain.
Description
Redesign views to align with the new design system, client list and general tab
Related issues and discussion
WEB-977
Screenshots
Screen.Recording.2026-06-10.at.2.31.51.PM.mov
Checklist
Please make sure these boxes are checked before submitting your pull request - thanks!
If you have multiple commits please combine them into one commit by squashing them.
Read and understood the contribution guidelines at
web-app/.github/CONTRIBUTING.md.Summary by CodeRabbit
New Features
Bug Fixes
UI Improvements
Refactor
Localization