From d00483661578c2f45f1bb813a330b75693e0982d Mon Sep 17 00:00:00 2001 From: Firman Ramdhani <33869609+firmanramdhani@users.noreply.github.com> Date: Thu, 16 Jul 2026 11:28:55 +0700 Subject: [PATCH 01/13] fix: remove highlightDataKey from EnterpriseDetailPageProvider in FullPagePageDetail --- .../full-page/presentation/pages/full-page.page.detail.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/web/src/apps/modules/example/full-page/presentation/pages/full-page.page.detail.tsx b/apps/web/src/apps/modules/example/full-page/presentation/pages/full-page.page.detail.tsx index 2fc576b..4114ca6 100644 --- a/apps/web/src/apps/modules/example/full-page/presentation/pages/full-page.page.detail.tsx +++ b/apps/web/src/apps/modules/example/full-page/presentation/pages/full-page.page.detail.tsx @@ -6,7 +6,6 @@ export default function FullPagePageDetail() { return ( Date: Thu, 16 Jul 2026 11:36:17 +0700 Subject: [PATCH 02/13] feat: add StatusBadge component with configurable status display --- packages/ui/src/components/status-badge/index.ts | 2 +- .../{status-badge.component.tsx => status-badge.tsx} | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) rename packages/ui/src/components/status-badge/{status-badge.component.tsx => status-badge.tsx} (98%) diff --git a/packages/ui/src/components/status-badge/index.ts b/packages/ui/src/components/status-badge/index.ts index ec4be4f..a32b0fb 100644 --- a/packages/ui/src/components/status-badge/index.ts +++ b/packages/ui/src/components/status-badge/index.ts @@ -1 +1 @@ -export * from './status-badge.component'; +export * from './status-badge'; diff --git a/packages/ui/src/components/status-badge/status-badge.component.tsx b/packages/ui/src/components/status-badge/status-badge.tsx similarity index 98% rename from packages/ui/src/components/status-badge/status-badge.component.tsx rename to packages/ui/src/components/status-badge/status-badge.tsx index 73cd894..3b3c2cc 100644 --- a/packages/ui/src/components/status-badge/status-badge.component.tsx +++ b/packages/ui/src/components/status-badge/status-badge.tsx @@ -38,7 +38,7 @@ export enum STATUS_DATA { WAIT = 'wait', WAITING = 'waiting', - WAITLIST = 'wait-list', + WAITING_LIST = 'waiting-list', PROCESS = 'process', PROCESSING = 'processing', @@ -173,7 +173,7 @@ export const DEFAULT_STATUS_MAP: Record = { // #6C5DD0 [STATUS_DATA.WAIT]: { color: '#6C5DD0', leftSection: getIcon(Clock) }, [STATUS_DATA.WAITING]: { color: '#6C5DD0', leftSection: getIcon(Clock) }, - [STATUS_DATA.WAITLIST]: { color: '#6C5DD0', leftSection: getIcon(Clock) }, + [STATUS_DATA.WAITING_LIST]: { color: '#6C5DD0', leftSection: getIcon(Clock) }, // #D26DA9 [STATUS_DATA.CANCEL]: { color: '#D26DA9', leftSection: getIcon(XCircle) }, From d089c40707a163c45084ffb2612a67877437a89b Mon Sep 17 00:00:00 2001 From: Firman Ramdhani <33869609+firmanramdhani@users.noreply.github.com> Date: Mon, 20 Jul 2026 11:48:47 +0700 Subject: [PATCH 03/13] feat: integrate AG Grid with Mantine theme and add showcase component --- .../showcase/components/AgGridShowcase.tsx | 218 ++++++++++++++++++ apps/web/src/apps/showcase/registry.ts | 10 +- packages/ui/package.json | 6 +- .../components/ag-grid/ag-grid-provider.tsx | 77 +++++++ .../src/components/ag-grid/ag-grid-setup.ts | 49 ++++ .../src/components/ag-grid/ag-grid-theme.ts | 95 ++++++++ .../ui/src/components/ag-grid/data-grid.tsx | 26 +++ packages/ui/src/components/ag-grid/index.ts | 15 ++ packages/ui/src/components/index.ts | 1 + pnpm-lock.yaml | 85 ++++++- 10 files changed, 577 insertions(+), 5 deletions(-) create mode 100644 apps/web/src/apps/showcase/components/AgGridShowcase.tsx create mode 100644 packages/ui/src/components/ag-grid/ag-grid-provider.tsx create mode 100644 packages/ui/src/components/ag-grid/ag-grid-setup.ts create mode 100644 packages/ui/src/components/ag-grid/ag-grid-theme.ts create mode 100644 packages/ui/src/components/ag-grid/data-grid.tsx create mode 100644 packages/ui/src/components/ag-grid/index.ts diff --git a/apps/web/src/apps/showcase/components/AgGridShowcase.tsx b/apps/web/src/apps/showcase/components/AgGridShowcase.tsx new file mode 100644 index 0000000..a6a0f90 --- /dev/null +++ b/apps/web/src/apps/showcase/components/AgGridShowcase.tsx @@ -0,0 +1,218 @@ +import { useState, useMemo } from 'react'; +import { Card, Title, Text, Stack, Badge, Group, Select, NumberInput } from '@repo/ui/components'; +import { AgGridProvider, DataGrid } from '@repo/ui/ag-grid'; +import type { ColDef, ValueFormatterParams } from '@repo/ui/ag-grid'; + +/* ─── Sample Data ──────────────────────────────────────────────── */ + +interface OrderRow { + id: string; + orderCode: string; + customer: string; + email: string; + product: string; + quantity: number; + unitPrice: number; + total: number; + status: 'Draft' | 'Pending' | 'Processing' | 'Shipped' | 'Delivered' | 'Cancelled'; + createdAt: string; + region: string; +} + +const SAMPLE_DATA: OrderRow[] = [ + { id: '1', orderCode: 'ORD-2026-001', customer: 'Acme Corp', email: 'acme@example.com', product: 'Widget A', quantity: 120, unitPrice: 24.5, total: 2940, status: 'Delivered', createdAt: '2026-01-15', region: 'North America' }, + { id: '2', orderCode: 'ORD-2026-002', customer: 'Globex Inc', email: 'info@globex.com', product: 'Widget B', quantity: 50, unitPrice: 89.99, total: 4499.5, status: 'Shipped', createdAt: '2026-02-03', region: 'Europe' }, + { id: '3', orderCode: 'ORD-2026-003', customer: 'Initech', email: 'orders@initech.com', product: 'Gadget Pro', quantity: 200, unitPrice: 15.0, total: 3000, status: 'Processing', createdAt: '2026-03-21', region: 'Asia Pacific' }, + { id: '4', orderCode: 'ORD-2026-004', customer: 'Umbrella Ltd', email: 'sales@umbrella.co', product: 'Widget A', quantity: 75, unitPrice: 24.5, total: 1837.5, status: 'Pending', createdAt: '2026-04-10', region: 'Europe' }, + { id: '5', orderCode: 'ORD-2026-005', customer: 'Stark Industries', email: 'tony@stark.io', product: 'Gadget Elite', quantity: 10, unitPrice: 499.0, total: 4990, status: 'Delivered', createdAt: '2026-04-18', region: 'North America' }, + { id: '6', orderCode: 'ORD-2026-006', customer: 'Wayne Enterprises', email: 'bruce@wayne.com', product: 'Widget C', quantity: 300, unitPrice: 12.75, total: 3825, status: 'Draft', createdAt: '2026-05-02', region: 'North America' }, + { id: '7', orderCode: 'ORD-2026-007', customer: 'Cyberdyne', email: 'info@cyberdyne.jp', product: 'Gadget Pro', quantity: 150, unitPrice: 15.0, total: 2250, status: 'Cancelled', createdAt: '2026-05-15', region: 'Asia Pacific' }, + { id: '8', orderCode: 'ORD-2026-008', customer: 'Oscorp', email: 'orders@oscorp.com', product: 'Widget B', quantity: 90, unitPrice: 89.99, total: 8099.1, status: 'Shipped', createdAt: '2026-06-01', region: 'North America' }, + { id: '9', orderCode: 'ORD-2026-009', customer: 'LexCorp', email: 'lex@lexcorp.com', product: 'Gadget Elite', quantity: 5, unitPrice: 499.0, total: 2495, status: 'Processing', createdAt: '2026-06-12', region: 'Europe' }, + { id: '10', orderCode: 'ORD-2026-010', customer: 'Pied Piper', email: 'richard@piedpiper.io', product: 'Widget A', quantity: 500, unitPrice: 24.5, total: 12250, status: 'Pending', createdAt: '2026-06-20', region: 'North America' }, + { id: '11', orderCode: 'ORD-2026-011', customer: 'Hooli', email: 'gavin@hooli.com', product: 'Gadget Pro', quantity: 1000, unitPrice: 15.0, total: 15000, status: 'Delivered', createdAt: '2026-07-01', region: 'North America' }, + { id: '12', orderCode: 'ORD-2026-012', customer: 'Massive Dynamic', email: 'nina@massive.com', product: 'Widget C', quantity: 60, unitPrice: 12.75, total: 765, status: 'Shipped', createdAt: '2026-07-08', region: 'Europe' }, +]; + +/* ─── Status Badge Renderer ─────────────────────────────────────── */ + +const STATUS_COLORS: Record = { + Draft: 'gray', + Pending: 'warning', + Processing: 'info', + Shipped: 'brand', + Delivered: 'success', + Cancelled: 'error', +}; + +function StatusCellRenderer({ value }: { value: OrderRow['status'] }) { + return ( + + {value} + + ); +} + +/* ─── Currency Formatter ────────────────────────────────────────── */ + +function currencyFormatter(params: ValueFormatterParams): string { + if (params.value == null) return '-'; + return new Intl.NumberFormat('en-US', { + style: 'currency', + currency: 'USD', + minimumFractionDigits: 2, + }).format(params.value); +} + +/* ─── Showcase Component ────────────────────────────────────────── */ + +export default function AgGridShowcase() { + const [gridHeight, setGridHeight] = useState(460); + const [rowModelType, setRowModelType] = useState('clientSide'); + + const defaultColDef = useMemo( + () => ({ + flex: 1, + minWidth: 100, + sortable: true, + filter: true, + resizable: true, + }), + [], + ); + + const columnDefs = useMemo[]>( + () => [ + { + field: 'orderCode', + headerName: 'Order Code', + pinned: 'left', + minWidth: 140, + filter: 'agTextColumnFilter', + }, + { + field: 'status', + headerName: 'Status', + minWidth: 120, + cellRenderer: StatusCellRenderer, + filter: 'agSetColumnFilter', + }, + { + field: 'customer', + headerName: 'Customer', + minWidth: 160, + filter: 'agTextColumnFilter', + }, + { + field: 'email', + headerName: 'Email', + minWidth: 180, + filter: 'agTextColumnFilter', + }, + { + field: 'product', + headerName: 'Product', + minWidth: 130, + filter: 'agSetColumnFilter', + }, + { + field: 'region', + headerName: 'Region', + minWidth: 140, + filter: 'agSetColumnFilter', + enableRowGroup: true, + }, + { + field: 'quantity', + headerName: 'Qty', + minWidth: 80, + filter: 'agNumberColumnFilter', + type: 'numericColumn', + }, + { + field: 'unitPrice', + headerName: 'Unit Price', + minWidth: 110, + filter: 'agNumberColumnFilter', + type: 'numericColumn', + valueFormatter: currencyFormatter, + }, + { + field: 'total', + headerName: 'Total', + minWidth: 120, + filter: 'agNumberColumnFilter', + type: 'numericColumn', + valueFormatter: currencyFormatter, + }, + { + field: 'createdAt', + headerName: 'Created Date', + minWidth: 130, + filter: 'agDateColumnFilter', + }, + ], + [], + ); + + return ( + + + {/* ── Info Card ────────────────────────────────── */} + + + AG Grid Enterprise — Mantine Integration + + + This showcase demonstrates AG Grid integrated with Mantine's theme system. The grid + automatically adapts to dark/light mode changes, inherits brand colors, typography, and + border radius from the Mantine theme — all via AG Grid's built-in CSS variable system with + zero custom stylesheets. Toggle the color scheme in the Theme Controls above to see it in + action. + + + setGridHeight(Number(val) || 400)} + min={300} + max={800} + step={50} + w={180} + /> +