Skip to content

Migrate UI to PrimeReact + full mobile responsiveness#29

Merged
parameshjava merged 78 commits into
mainfrom
feat/primereact-migration
Jun 16, 2026
Merged

Migrate UI to PrimeReact + full mobile responsiveness#29
parameshjava merged 78 commits into
mainfrom
feat/primereact-migration

Conversation

@parameshjava

Copy link
Copy Markdown
Owner

Summary

Migrates the entire UI from shadcn/ui + base-ui (Tailwind v4) to PrimeReact and makes every screen mobile-responsive (375 / 768 / 1280px). Delivered in phases, each independently green (build + lint + 244 tests).

Note: the request named PrimeNG (Angular-only); the React-native equivalent PrimeReact is what's used here.

What changed

Foundation

  • primereact@10.9.7 + primeicons; Lara theme loaded into a cascade layer ordered after Tailwind base (beats preflight) but before utilities (Tailwind utilities still win). PrimeReactProvider wired at a client boundary.

Shared wrappers (src/components/ui/pr/) — one reusable component per pattern (DRY):
Button · Dropdown · MultiSelect · InputNumber (rupee, en-IN) · DatePicker (Calendar) · DataTable (filter format) · Dialog · ConfirmDialog · Accordion · TabStrip · Sidebar drawer · Field.

Charts — Recharts → Chart.js (chart.js + chartjs-plugin-datalabels, shared setup module). Preserved stacked totals, click-to-navigate, ceiling line, donuts; tuned bar sizing + canvas fill.

Screens migrated

  • Mobile nav → PrimeReact Sidebar drawer; responsive top bar.
  • Tabs (dashboard/loans/meetings) → PrTabStrip (panels don't remount — charts/edit state survive).
  • Dialogs (8 sites) → PrDialog + shared ConfirmDialog.
  • Accordions (members sections, EMI panel) → PrAccordion.
  • All 5 tables → one PrDataTable with the DataTable filter format: per-column + global filters, sorting, export reflecting filtered/sorted rows, row expansion, totals footers, responsive stack/scroll.
  • All 12 forms → PrimeReact inputs (controlled state + hidden inputs preserve FormData/server actions; showWords retained).
  • All date inputsPrDatePicker (compact, spaced title).

Cleanup

  • Deleted 9 orphaned shadcn primitives; removed @base-ui/react.

Test Plan

  • npm run build, npm run lint, npm test (244 passing) green on the branch.
  • Browser QA (couldn't be automated — no DOM tests): charts; mobile nav at 375/768/1280; tables (filters/sort/export/expansion); forms submit correctly; dialogs/confirms; members directory + EMI accordions render and toggle; date pickers.

Follow-up polish (optional, non-blocking)

  • phone-input/ifsc-field → PrimeReact InputMask.
  • A couple native <select> (e.g. pending-payment edit row) → PrDropdown.
  • Restore green "Approve" button (add a success variant to pr/button).

🤖 Generated with Claude Code

pkorrakuti-mvrk and others added 30 commits June 16, 2026 16:35
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ce-order fallback)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds primereact/primeicons (pinned), Aura/Lara theme in a cascade layer,
PrimeReactProvider boundary, and additive wrapper components (Button,
Dropdown, MultiSelect, InputNumber, DataTable) + migration spike notes.
Purely additive — no existing screens changed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
All 3 chart modules (dashboard bars/member/pie/section, eligibility monthly,
poll donut) reimplemented on Chart.js + chartjs-plugin-datalabels with full
feature parity (stacked totals, click-to-navigate, ceiling line, donuts).
Recharts + the shadcn ChartContainer wrapper removed. Visual parity pending
human browser QA (checklist in PR notes).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Chart.js default bar sizing rendered very wide bars in the full-width
container. Add a shared BAR_SIZING (maxBarThickness + tighter category/bar
percentages) applied across DashboardBars, MemberContributionBars,
SectionBars, and the eligibility chart so bars stay slim with clear gaps.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Mobile nav drawer migrated from shadcn Sheet to PrimeReact Sidebar (PrDrawer
wrapper); top bar made responsive (40px hamburger, fits 375px, no overflow).
Nav links, admin role-gating, active highlighting, badges all preserved.
Includes P3/P4 plan + DataTable filter-format requirement. shadcn sheet.tsx
now orphaned (P5 removal).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
pkorrakuti-mvrk and others added 26 commits June 16, 2026 19:29
…ells)

Lara's default DataTable padding/header sizing was much larger than the app's
prior compact tables. Render the shared wrapper with size="small" and add
.p-datatable-sm overrides (components layer) for tight cell padding and small
uppercase headers, restoring the previous scannable density across all tables.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add optional name/required (+ showClear on dropdown) to the pr/ wrappers so
they emit hidden inputs for FormData: PrDropdown one hidden input, PrMultiSelect
one per selected value (getAll), PrAmountInput the raw numeric value. Existing
controlled usages are unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Field(label, htmlFor?, required?, error?, hint?, className, children) renders the
label (+ required asterisk), the control, and an inline error/hint — centralizing
the repeated label+error markup so errors always stay inline per AGENTS.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… + Field

Swap the old multi-select for PrMultiSelect and wrap labels in the shared Field;
buttons now use pr/button. URL-param behavior, Apply/Reset/dirty logic, empty
'All members'/'All types' placeholders, and responsive stacking are preserved.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…meReact inputs

Reuse shared pr/ wrappers (PrDropdown, PrAmountInput, Field, Button) for the
admin transaction forms. Member/poll/loan pickers and transaction_type now use
PrDropdown ({id,name}->{value,label}, name hidden input for FormData, showClear/
required preserved). Amount uses controlled PrAmountInput with the number-to-words
helper preserved via Field hint. interest_source radios, loan show/hide, date,
bank ref, description, BankBalanceUpdater, and loan-interest guard all unchanged.
Server actions untouched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Migrate new/edit/close loan forms to the shared PrimeReact form
wrappers (PrDropdown, PrAmountInput, Field, pr/Button), matching the
transactions-form pattern. Member/poll pickers -> PrDropdown; principal,
bad_debt, interest_waived -> PrAmountInput with number-to-words rendered
via Field hint. Server actions, EMI preview, loan-type radios,
interest-waiver logic, close/write-off/reopen flows unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Finishes the forms cluster — swaps the last searchable-select / amount-input
usages for the shared pr/* wrappers (PrDropdown, PrAmountInput, Field, Button).

- admin-exit-member-form: SearchableSelect -> PrDropdown + Field; submit -> Button
- loan-poll-picker: drop searchable-select type import; export own PollPickerOption
- history-editor: AmountInput -> PrAmountInput (inr only) + Field hint words; Button
- pending-payment-row: AmountInput -> controlled PrAmountInput; buttons -> Button
- submit-payment-form: selects -> PrDropdown, AmountInput -> PrAmountInput, Button

Old searchable-select.tsx and amount-input.tsx are now fully orphaned (P5 delete).
Server actions / FormData contracts unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
PrMultiSelect now defaults to compact 'comma' display with maxSelectedLabels=2
(shows 'N selected' past two picks) instead of always rendering every chip, and
the filter grids get [&>*]:min-w-0 so a wide member field can't blow out its 1fr
track and push the date fields past the viewport.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
All 12 admin/dashboard forms migrated off shadcn searchable-select/multi-select/
amount-input to the shared pr/ wrappers. Wrappers gained FormData support
(name -> hidden input), required, showClear; PrMultiSelect made compact
(N-selected, no row blowout). New shared Field (label + inline error/hint)
reused across forms. Server actions + FormData wiring unchanged; showWords
reproduced via Field hint. Filter grids get min-w-0 so multi-select can't push
the row off-screen. Old searchable-select/multi-select/amount-input now fully
orphaned (P5 removal).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ISO yyyy-mm-dd contract with a hidden input for FormData posting; parses
yyyy-mm-dd as a local date to avoid the UTC off-by-one; dd/mm/yy display.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replaces every <input type="date"> across loans, transactions, meetings,
pending payments, reference history/table, contributions filter, submit
payment and loan calculator with the PrimeReact-backed PrDatePicker so all
controls share the Lara height (fixes filter/form row misalignment).

FormData posting is preserved: form fields pass name= so the hidden input
still carries yyyy-mm-dd; uncontrolled defaultValue fields were converted to
controlled state seeded from the default. Date-as-YYYYMMDD-int reference
fields keep their existing conversion via the controlled value/onChange.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
New shared PrDatePicker wrapper (ISO yyyy-mm-dd in/out, name->hidden input for
FormData, min/max, local-date parsing to avoid UTC off-by-one). All 13 native
<input type="date"> fields across filters + forms migrated to it. Fixes the
filter-row misalignment (date controls now match Lara dropdown height) and the
"calendar not migrated" gap. Server actions + yyyy-mm-dd posting + YYYYMMDD-int
round-trip preserved.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reusable titled-card accordion matching the prior shadcn section look
(bordered rounded card, bold title + muted subtitle, divider + content).
Supports independent multi-open (default), uncontrolled default-open via
defaultActiveIndex, and fully controlled activeIndex/onTabChange. Styled
via pt so Tailwind utilities win over the layered Lara theme.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace shadcn Accordion with PrAccordion/PrAccordionTab for the
Active/Inactive member sections. Preserves titles, member-count
subtitles, per-section default-open state (active open, inactive
closed), and the nested PrDataTable (row expansion, global search,
export all unchanged).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace shadcn Accordion with PrAccordion/PrAccordionTab for the
Repayment schedule (default-open) and Prepayment estimate
(default-closed) sections. Only accordion markup touched — dialogs,
date pickers, and EMI math untouched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
New shared PrAccordion/PrAccordionTab wrapper. members-directory section
headers + emi-schedule-panel sections migrated; nested DataTable + EMI logic
untouched, default-open states preserved. shadcn accordion.tsx orphaned (P5).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Last 5 shadcn Button consumers migrated to pr/button; deleted 9 orphaned
files (ui button/dialog/sheet/tabs/accordion + searchable-select/multi-select/
amount-input/table-controls); uninstalled @base-ui/react. App now runs on
PrimeReact for interactive primitives (card/sonner/domain helpers retained).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
PrAccordionTab was a wrapper component returning <AccordionTab>, but PrimeReact's
Accordion only recognises literal AccordionTab children — so it found none and
rendered nothing (members directory + EMI panel went blank). PrAccordionTab is
now a prop-carrier; PrAccordion reads its props and emits real <AccordionTab>
elements. Also manage open state internally for the uncontrolled case (passing
activeIndex without onTabChange previously locked the panels).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Lara renders the datepicker month + year as adjacent buttons with no gap
('June2026'). Add a small inline-flex gap on .p-datepicker-title.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Lara's default day-cell sizing/padding made the popup large; tighten cells
(2rem), header, table, and the Today/Clear button bar.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 16, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
aits-fcf-tracker Ready Ready Preview, Comment Jun 16, 2026 3:36pm

@parameshjava parameshjava merged commit 70ebeba into main Jun 16, 2026
3 checks passed
@parameshjava parameshjava deleted the feat/primereact-migration branch June 16, 2026 15:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants