use client;
import * as React from react;
import
ColumnDef
flexRender
getCoreRowModel
useReactTable
from @tanstack/react-table;
import
Table
TableBody
TableCell
TableHead
TableHeader
TableRow
from @/components/ui/table;
import Card CardContent CardHeader CardTitle CardDescription from @/components/ui/card;
import CheckCircle2 XCircle Pencil Trash2 Plus from lucide-react;
import Button from @/components/ui/button;
type ComplianceMatrixRow
id: string;
rfpSection: string;
requirementSummary: string;
painPoint: string;
proposalSection: string;
vtechSolution: string;
keyDifferentiator: string;
compliant: string;
clarifications: string;
priceToWinStrategy: string;
;
type Props
data: ComplianceMatrixRow;
onSave: (row: ComplianceMatrixRow) > Promise;
readOnly: boolean;
;
export function ComplianceMatrix( data: initialData onSave readOnly false : Props)
const data setData (initialData);
const editingRowId setEditingRowId (null);
const editBuffer setEditBuffer (null);
const saving setSaving (false);
(() >
setData(initialData);
initialData);
const startEditing (row: ComplianceMatrixRow) >
setEditingRowId();
setEditBuffer( ...row );
;
const cancelEditing () >
setEditingRowId(null);
setEditBuffer(null);
;
const updateEditBuffer (field: keyof ComplianceMatrixRow value: any) >
setEditBuffer(prev > ( ...(prev ) field: value ));
;
const saveEditing async () >
if (!editingRowId !editBuffer) return;
setSaving(true);
try
// Optimistic update
setData(prev > (r > ( editingRowId ( ...(r as any) ...(editBuffer as any) ) : r)));
// API call to save changes
if (onSave)
await onSave(editBuffer as ComplianceMatrixRow);
setEditingRowId(null);
setEditBuffer(null);
catch (err: any)
alert(Error saving: $ Unknown error);
finally
setSaving(false);
;
const handleDeleteRow (id: string) >
if (!confirm(Are you sure you want to delete this row)) return;
setData(prev > (r > ! id));
if (editingRowId id) cancelEditing();
;
const handleAddRow () >
const newRow: ComplianceMatrixRow
id: new-$()
rfpSection:
requirementSummary:
painPoint:
proposalSection:
vtechSolution:
keyDifferentiator:
compliant:
clarifications:
priceToWinStrategy:
;
setData(prev > ...prev newRow);
setTimeout(() > startEditing(newRow) 50);
;
const columns: ColumnDef
accessorKey: rfpSection
header: RFP Section/ID
cell: ( row ) >
const isEditing editingRowId && !readOnly;
return isEditing (
updateEditBuffer(rfpSection )
classNamew-full border rounded px-2 py-1
/>
) : (
);
accessorKey: requirementSummary
header: Requirement Summary
cell: ( row ) >
const isEditing editingRowId && !readOnly;
return isEditing (
updateEditBuffer(requirementSummary )
classNamew-full border rounded px-2 py-1 min-h-64px resize-y
/>
) : (
);
accessorKey: painPoint
header: Pain Point / Need
cell: ( row ) >
const isEditing editingRowId && !readOnly;
return isEditing (
updateEditBuffer(painPoint )
classNamew-full border rounded px-2 py-1 min-h-48px resize-y
/>
) : (
);
accessorKey: proposalSection
header: Proposal Section
cell: ( row ) >
const isEditing editingRowId && !readOnly;
return isEditing (
updateEditBuffer(proposalSection )
classNamew-full border rounded px-2 py-1
/>
) : (
);
accessorKey: vtechSolution
header: vTech Solution Summary
cell: ( row ) >
const isEditing editingRowId && !readOnly;
return isEditing (
updateEditBuffer(vtechSolution )
classNamew-full border rounded px-2 py-1 min-h-64px resize-y
/>
) : (
);
accessorKey: keyDifferentiator
header: Key Differentiator
cell: ( row ) >
const isEditing editingRowId && !readOnly;
return isEditing (
updateEditBuffer(keyDifferentiator )
classNamew-full border rounded px-2 py-1 min-h-48px resize-y
/>
) : (
);
accessorKey: compliant
header: Compliant
cell: ( row ) >
const isEditing editingRowId && !readOnly;
if (isEditing)
return (
updateEditBuffer(compliant )
classNameborder rounded px-2 py-1
>
Select
Yes
No
Yes (YES)
);
const compliantValue String((compliant) ).toUpperCase().trim();
const isCompliant compliantValue Y compliantValue YES;
return isCompliant : ;
accessorKey: clarifications
header: Clarifications / Assumptions
cell: ( row ) >
const isEditing editingRowId && !readOnly;
return isEditing (
updateEditBuffer(clarifications )
classNamew-full border rounded px-2 py-1 min-h-48px resize-y
/>
) : (
);
accessorKey: priceToWinStrategy
header: Price-to-Win Strategy
cell: ( row ) >
const isEditing editingRowId && !readOnly;
return isEditing (
updateEditBuffer(priceToWinStrategy )
classNamew-full border rounded px-2 py-1 min-h-48px resize-y
/>
) : (
);
id: actions
header: Actions
cell: ( row ) >
if (readOnly) return null;
const isEditing editingRowId;
return isEditing (
saving Saving... : Save
Cancel
handleDeleteRow()>
) : (
startEditing( as ComplianceMatrixRow)>
Edit
handleDeleteRow()>
);
;
const table useReactTable(
data
columns
getCoreRowModel: getCoreRowModel()
);
return (
Compliance Matrix
A detailed breakdown of RFP requirements our proposed solutions and strategic analysis.
!readOnly && (
)
().map((headerGroup) > (
((header) >
return (
null
: flexRender( ())
);
)
))
(). (
().((row) > (
().map((cell) > (
flexRender( ())
))
))
) : (
No results.
)
);