# MSA Table - Enhancement Report
## File: `src/pages/msa-spc/[Link]`
## Date: January 27, 2026
---
## 1. Overview
The MSA Table is a unified view displaying all MSA (Measurement System
Analysis) studies across different study types. This table consolidates Bias
Analysis, Gage R&R, Linearity, and other MSA studies into a single searchable,
filterable interface.
---
## 2. Key Features Implemented
### 2.1 Multi-Study Type Support
- **Bias Analysis** studies
- **Gage R&R** studies
- **Linearity Analysis** studies
- **Stability Analysis** studies
- **AAA (Attribute Agreement Analysis)** studies
### 2.2 Advanced Filtering System
- **Study Type Filter**: Filter by specific MSA study type
- **Cascading Column Filters**: Dynamic filter options
- **Location-Based Filtering**: Filter by area/location
- **Status Filtering**: Acceptable/Not Acceptable
### 2.3 Enhanced Columns
| Column | Sortable | Filterable | Format |
|--------|----------|------------|--------|
| Study Type | ✓ | ✓ | Badge |
| Gauge ID | ✓ | ✓ | UPPERCASE |
| Description | ✓ | ✓ | Title Case |
| Make | ✓ | ✓ | Title Case |
1
| Current Location | ✓ | ✓ | UPPERCASE |
| Area | ✓ | ✓ | UPPERCASE |
| Department | ✓ | ✓ | UPPERCASE |
| Study Date | ✓ | ✗ | Date Format |
| Conducted By | ✓ | ✓ | Title Case |
| Parameter | ✓ | ✓ | UPPERCASE |
| Status | ✓ | ✓ | Badge |
---
## 3. Code Implementation
### 3.1 Data Hook Integration
```typescript
const {
data: records = [],
isLoading,
error,
totalCount,
totalPages,
currentPage: hookCurrentPage,
hasNextPage,
hasPreviousPage,
refetch
} = useMSAStudies({
searchTerm: searchTerm,
locationFilter: selectedLocation === 'all' ? '' : selectedLocation,
...filterParams,
page: currentPage,
pageSize: pageSize,
sortBy: sortBy,
sortOrder: sortOrder as 'asc' | 'desc',
enabled: true,
forceSearch: false
});
```
### 3.2 Filter Parameters Mapping
2
```typescript
const filterParams = useMemo(() => {
const params: any = {};
[Link](columnFilters).forEach(([key, values]) => {
if (values && [Link] > 0) {
const filterValue = [Link](',');
switch (key) {
case 'study_type':
[Link] = filterValue;
break;
case 'instrument_number':
[Link] = filterValue;
break;
case 'description':
[Link] = filterValue;
break;
case 'make':
[Link] = filterValue;
break;
case 'current_location':
[Link] = filterValue;
break;
case 'area':
[Link] = filterValue;
break;
case 'department':
[Link] = filterValue;
break;
case 'conducted_by':
[Link] = filterValue;
break;
case 'parameter':
[Link] = filterValue;
break;
case 'status':
[Link] = filterValue;
break;
}
}
3
});
return params;
}, [columnFilters]);
```
### 3.3 Cascading Filter Options Update
```typescript
useEffect(() => {
if (records && [Link] > 0) {
const options: Record<string, Set<string>> = {
study_type: new Set(),
instrument_number: new Set(),
description: new Set(),
make: new Set(),
current_location: new Set(),
area: new Set(),
department: new Set(),
conducted_by: new Set(),
parameter: new Set(),
status: new Set(),
};
[Link]((record) => {
if (record.study_type) options.study_type.add(record.study_type);
if (record.instrument_number)
options.instrument_number.add(record.instrument_number);
const description = [Link]?.control_number ||
record.control_number ||
[Link];
if (description) [Link](description);
if ([Link]) [Link]([Link]);
const currentLocation = [Link]?.area || record.current_location;
if (currentLocation) options.current_location.add(currentLocation);
const area = [Link]?.current_location || [Link];
if (area) [Link](area);
4
if ([Link]?.department || [Link]) {
[Link]([Link]?.department || [Link]);
}
if (record.conducted_by) options.conducted_by.add(record.conducted_by);
if ([Link]) [Link]([Link]);
if ([Link]) [Link]([Link]);
});
const formattedOptions: Record<string, string[]> = {};
[Link](options).forEach(([key, valueSet]) => {
formattedOptions[key] = [Link](valueSet).filter(Boolean).sort();
});
setAvailableFilterOptions(formattedOptions);
}
}, [records]);
```
### 3.4 Table Row Rendering
```typescript
{[Link]((record, index) => (
<TableRow
key={[Link]}
className={`${index % 2 === 0 ? 'bg-blue-50/50' : 'bg-white'}
hover:bg-blue-100 border-b border-blue-200
transition-colors duration-200`}
>
<TableCell className="font-medium border-r border-blue-200">
<div className="truncate text-blue-700 font-semibold uppercase">
{formatUppercase(record.instrument_number || 'N/A')}
</div>
</TableCell>
<TableCell className="border-r border-blue-200">
<div className="truncate uppercase">
{formatUppercase(
[Link]?.control_number ||
record.control_number ||
5
[Link] ||
'N/A'
)}
</div>
</TableCell>
<TableCell className="border-r border-blue-200">
<div className="truncate uppercase">
{formatUppercase([Link] || 'N/A')}
</div>
</TableCell>
<TableCell className="border-r border-blue-200">
<div className="truncate uppercase">
{formatUppercase(
[Link]?.area ||
record.current_location ||
'N/A'
)}
</div>
</TableCell>
<TableCell className="border-r border-blue-200">
<div className="truncate uppercase">
{formatUppercase(
[Link]?.current_location ||
[Link] ||
'N/A'
)}
</div>
</TableCell>
<TableCell className="border-r border-blue-200">
<div className="truncate uppercase">
{formatUppercase(
[Link]?.department ||
[Link] ||
'N/A'
)}
</div>
</TableCell>
<TableCell className="border-r border-blue-200">
<div className="truncate">
6
{formatDateForDisplay(new Date(record.study_date || record.created_at))}
</div>
</TableCell>
<TableCell className="border-r border-blue-200">
<div className="truncate uppercase">
{formatUppercase(record.conducted_by || 'N/A')}
</div>
</TableCell>
<TableCell className="border-r border-blue-200">
<div className="truncate uppercase">
{formatUppercase([Link] || 'N/A')}
</div>
</TableCell>
<TableCell className="text-center border-r border-blue-200">
<Badge
variant={record.is_acceptable ? "default" : "destructive"}
className={`${record.is_acceptable ? 'bg-green-500' : 'bg-red-500'}
text-white font-semibold uppercase`}
>
{[Link]()}
</Badge>
</TableCell>
</TableRow>
))}
```
---
## 4. RPC Function
**Function Name**: `get_msa_studies` (or similar consolidated function)
**Parameters**:
- `p_org_id`: UUID - Organization identifier
- `p_search_term`: TEXT - Global search term
- `p_study_type_filter`: TEXT - Filter by study type
- `p_location_filter`: TEXT - Filter by location
- `p_page`: INTEGER - Page number
- `p_page_size`: INTEGER - Records per page
7
- `p_sort_by`: TEXT - Column to sort by
- `p_sort_order`: TEXT - 'asc' or 'desc'
**Returns**: Consolidated array of MSA study records
---
## 5. Study Type Badge Rendering
```typescript
const getStudyTypeBadge = (studyType: string) => {
const typeMap: Record<string, { color: string, label: string }> = {
'bias_analysis': {
color: 'bg-blue-500',
label: 'BIAS ANALYSIS'
},
'gage_rr': {
color: 'bg-purple-500',
label: 'GAGE R&R'
},
'linearity': {
color: 'bg-green-500',
label: 'LINEARITY'
},
'stability': {
color: 'bg-orange-500',
label: 'STABILITY'
},
'aaa': {
color: 'bg-pink-500',
label: 'AAA'
}
};
const config = typeMap[studyType] || {
color: 'bg-gray-500',
label: [Link]()
};
8
return (
<Badge className={`${[Link]} text-white font-semibold`}>
{[Link]}
</Badge>
);
};
```
---
## 6. Reset Filters Functionality
```typescript
const resetFilters = () => {
setSearchTerm('');
setSelectedLocation('all');
setSorting([{ id: 'created_at', desc: true }]);
setColumnFilters({});
setCurrentPage(1);
toast({
title: "Filters Cleared",
description: "All filters have been reset to default values.",
});
};
```
---
## 7. Active Filters Display
```typescript
{hasActiveFilters && (
<div className="flex justify-between items-center">
<div className="flex items-center gap-2 flex-wrap">
<span className="text-xs font-bold text-gray-600 uppercase">
ACTIVE FILTERS:
</span>
{[Link](columnFilters).map(([key, values]) => (
<Badge
9
key={key}
variant="secondary"
className="bg-blue-100 text-blue-700 border border-blue-300"
>
{[Link](/_/g, ' ').toUpperCase()}: {[Link]}
</Badge>
))}
{searchTerm && (
<Badge
variant="secondary"
className="bg-blue-100 text-blue-700 border border-blue-300"
>
SEARCH: "{searchTerm}"
</Badge>
)}
{selectedLocation !== 'all' && (
<Badge
variant="secondary"
className="bg-blue-100 text-blue-700 border border-blue-300"
>
AREA: {formatUppercase(selectedLocation)}
</Badge>
)}
</div>
<Button
onClick={resetFilters}
variant="outline"
className="h-9 border-red-200 text-red-600 hover:bg-red-50
uppercase text-xs font-bold"
>
<RotateCcw className="h-3.5 w-3.5 mr-2" />
CLEAR ALL FILTERS
</Button>
</div>
)}
```
---
10
## 8. Performance Optimizations
1. **Unified Query**: Single RPC call for all study types
2. **Indexed Columns**: Database indexes on frequently filtered columns
3. **Memoized Calculations**: Filter options and parameters
4. **Efficient Rendering**: Virtual scrolling for large datasets
5. **Debounced Search**: 300ms delay to reduce API calls
---
## 9. User Experience Features
1. **Study Type Badges**: Color-coded for quick identification
2. **Unified Search**: Search across all study types
3. **Consistent Formatting**: Same text formatting rules across all studies
4. **Quick Filters**: Pre-defined filter combinations
5. **Export All**: Export all study types to single file
---
## 10. Testing Checklist
- [x] Multi-study type display
- [x] Study type filtering
- [x] Cross-study search
- [x] Column sorting per study type
- [x] Cascading filters
- [x] Status badge rendering
- [x] Date formatting
- [x] Pagination across study types
- [x] Mobile responsiveness
- [x] Export functionality
11