added sort
This commit is contained in:
parent
ccda98a6a5
commit
4a07c5e47c
3
ipi-survey-platform/public/assets/images/active-sort.svg
Normal file
3
ipi-survey-platform/public/assets/images/active-sort.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M4.19561 2.86196C4.32062 2.73698 4.49016 2.66677 4.66694 2.66677C4.84371 2.66677 5.01325 2.73698 5.13827 2.86196L7.80494 5.52863C7.92638 5.65436 7.99357 5.82276 7.99205 5.99756C7.99054 6.17236 7.92042 6.33957 7.79682 6.46317C7.67321 6.58678 7.506 6.65689 7.33121 6.65841C7.15641 6.65993 6.98801 6.59273 6.86227 6.47129L5.33361 4.94263V12.6666C5.33361 12.8434 5.26337 13.013 5.13834 13.138C5.01332 13.2631 4.84375 13.3333 4.66694 13.3333C4.49013 13.3333 4.32056 13.2631 4.19553 13.138C4.07051 13.013 4.00027 12.8434 4.00027 12.6666V4.94263L2.4716 6.47129C2.34587 6.59273 2.17747 6.65993 2.00267 6.65841C1.82787 6.65689 1.66066 6.58678 1.53706 6.46317C1.41345 6.33957 1.34334 6.17236 1.34182 5.99756C1.3403 5.82276 1.4075 5.65436 1.52894 5.52863L4.19561 2.86196ZM10.6669 11.0573V3.33329C10.6669 3.15648 10.7372 2.98691 10.8622 2.86189C10.9872 2.73686 11.1568 2.66663 11.3336 2.66663C11.5104 2.66663 11.68 2.73686 11.805 2.86189C11.93 2.98691 12.0003 3.15648 12.0003 3.33329V11.0573L13.5289 9.52863C13.6547 9.40719 13.8231 9.33999 13.9979 9.34151C14.1727 9.34303 14.3399 9.41314 14.4635 9.53675C14.5871 9.66035 14.6572 9.82756 14.6587 10.0024C14.6602 10.1772 14.593 10.3456 14.4716 10.4713L11.8049 13.138C11.6799 13.2629 11.5104 13.3332 11.3336 13.3332C11.1568 13.3332 10.9873 13.2629 10.8623 13.138L8.19561 10.4713C8.07417 10.3456 8.00697 10.1772 8.00849 10.0024C8.01001 9.82756 8.08012 9.66035 8.20373 9.53675C8.32733 9.41314 8.49454 9.34303 8.66934 9.34151C8.84414 9.33999 9.01254 9.40719 9.13827 9.52863L10.6669 11.0573Z" fill="#92722A"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
@ -0,0 +1,3 @@
|
||||
<svg width="14" height="11" viewBox="0 0 14 11" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M2.85381 0.195333C2.97883 0.0703528 3.14837 0.000142415 3.32514 0.000142415C3.50192 0.000142415 3.67146 0.0703528 3.79647 0.195333L6.46314 2.862C6.58458 2.98774 6.65178 3.15614 6.65026 3.33093C6.64874 3.50573 6.57863 3.67294 6.45502 3.79655C6.33142 3.92015 6.16421 3.99026 5.98941 3.99178C5.81461 3.9933 5.64621 3.92611 5.52047 3.80467L3.99181 2.276V10C3.99181 10.1768 3.92157 10.3464 3.79655 10.4714C3.67152 10.5964 3.50195 10.6667 3.32514 10.6667C3.14833 10.6667 2.97876 10.5964 2.85374 10.4714C2.72871 10.3464 2.65847 10.1768 2.65847 10V2.276L1.12981 3.80467C1.00407 3.92611 0.835672 3.9933 0.660874 3.99178C0.486076 3.99026 0.318868 3.92015 0.195262 3.79655C0.0716568 3.67294 0.00154415 3.50573 2.52018e-05 3.33093C-0.00149374 3.15614 0.0657025 2.98774 0.187141 2.862L2.85381 0.195333ZM9.32514 8.39067V0.666667C9.32514 0.489856 9.39538 0.320287 9.5204 0.195262C9.64543 0.070238 9.815 0 9.99181 0C10.1686 0 10.3382 0.070238 10.4632 0.195262C10.5882 0.320287 10.6585 0.489856 10.6585 0.666667V8.39067L12.1871 6.862C12.3129 6.74056 12.4813 6.67337 12.6561 6.67488C12.8309 6.6764 12.9981 6.74652 13.1217 6.87012C13.2453 6.99373 13.3154 7.16093 13.3169 7.33573C13.3184 7.51053 13.2512 7.67893 13.1298 7.80467L10.4631 10.4713C10.3381 10.5963 10.1686 10.6665 9.99181 10.6665C9.81503 10.6665 9.64549 10.5963 9.52047 10.4713L6.85381 7.80467C6.73237 7.67893 6.66517 7.51053 6.66669 7.33573C6.66821 7.16093 6.73832 6.99373 6.86193 6.87012C6.98553 6.74652 7.15274 6.6764 7.32754 6.67488C7.50234 6.67337 7.67074 6.74056 7.79647 6.862L9.32514 8.39067Z" fill="#9EA2A9"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
@ -375,6 +375,10 @@ const IsicHsCodes = () => {
|
||||
});
|
||||
const [showImportModal, setShowImportModal] = React.useState(false);
|
||||
const [isRefreshing, setIsRefreshing] = React.useState(false);
|
||||
const [sortConfig, setSortConfig] = React.useState({
|
||||
key: null,
|
||||
direction: 'asc'
|
||||
});
|
||||
|
||||
// Get user profile from session
|
||||
const userProfile = React.useMemo(() => {
|
||||
@ -459,7 +463,7 @@ const IsicHsCodes = () => {
|
||||
|
||||
if (product.created_by) {
|
||||
try {
|
||||
createdByName = product.created_by_user?.name || '-';
|
||||
createdByName = product.created_by_name?.name || '-';
|
||||
} catch (error) {
|
||||
console.error('Error fetching creator info:', error);
|
||||
}
|
||||
@ -471,7 +475,7 @@ const IsicHsCodes = () => {
|
||||
product: product.product_name || 'N/A',
|
||||
unit: product.unit?.uom || 'N/A',
|
||||
estimatedMapped: product.mapped_establishment_count || 0,
|
||||
createdBy: createdByName,
|
||||
createdBy: product.created_by_name || 'N/A',
|
||||
createdOn: createdDate || null,
|
||||
updated: updatedDate,
|
||||
createdById: createdById,
|
||||
@ -499,16 +503,100 @@ const IsicHsCodes = () => {
|
||||
fetchProducts();
|
||||
}, []);
|
||||
|
||||
const handleSort = (key) => {
|
||||
let direction = 'asc';
|
||||
if (sortConfig.key === key && sortConfig.direction === 'asc') {
|
||||
direction = 'desc';
|
||||
}
|
||||
setSortConfig({ key, direction });
|
||||
};
|
||||
|
||||
const getSortedData = (data) => {
|
||||
if (!sortConfig.key) return data;
|
||||
|
||||
return [...data].sort((a, b) => {
|
||||
let aValue = a[sortConfig.key];
|
||||
let bValue = b[sortConfig.key];
|
||||
|
||||
if (sortConfig.key === 'estimatedMapped') {
|
||||
return sortConfig.direction === 'asc'
|
||||
? aValue - bValue
|
||||
: bValue - aValue;
|
||||
}
|
||||
|
||||
if (aValue < bValue) {
|
||||
return sortConfig.direction === 'asc' ? -1 : 1;
|
||||
}
|
||||
if (aValue > bValue) {
|
||||
return sortConfig.direction === 'asc' ? 1 : -1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
};
|
||||
|
||||
const headers = [
|
||||
'HS Code',
|
||||
'Product Name',
|
||||
'Description',
|
||||
'Unit',
|
||||
'Establishment Mapped',
|
||||
'Created By',
|
||||
'Last Updated',
|
||||
'Action',
|
||||
];
|
||||
{
|
||||
name: <span className="whitespace-nowrap">HS Code</span>,
|
||||
key: 'code',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
name: <span className="whitespace-nowrap">Product Name</span>,
|
||||
key: 'product',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
name: <span className="whitespace-nowrap">Description</span>,
|
||||
key: 'description',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
name: <span className="whitespace-nowrap">Unit</span>,
|
||||
key: 'unit',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
name: <span className="whitespace-nowrap">Establishment Mapped</span>,
|
||||
key: 'estimatedMapped',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
name: <span className="whitespace-nowrap">Created By</span>,
|
||||
key: 'createdBy',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
name: <span className="whitespace-nowrap">Last Updated</span>,
|
||||
key: 'updated',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
name: 'Actions',
|
||||
key: 'actions',
|
||||
sortable: false
|
||||
}
|
||||
].map(header => {
|
||||
if (!header.sortable) return { name: header.name };
|
||||
|
||||
const isActive = sortConfig.key === header.key;
|
||||
const isAsc = sortConfig.direction === 'asc';
|
||||
|
||||
return {
|
||||
name: (
|
||||
<div
|
||||
className="flex items-center cursor-pointer gap-1"
|
||||
onClick={() => handleSort(header.key)}
|
||||
>
|
||||
<span>{header.name}</span>
|
||||
<img
|
||||
src={isActive ? "/assets/images/active-sort.svg" : "/assets/images/inactive-sort.svg"}
|
||||
alt="Sort"
|
||||
className={`w-3 h-3 transition-transform ${isActive && isAsc ? 'transform rotate-180' : ''}`}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
};
|
||||
});
|
||||
|
||||
// Filter data based on search term
|
||||
React.useEffect(() => {
|
||||
@ -527,7 +615,9 @@ const IsicHsCodes = () => {
|
||||
setCurrentPage(1); // Reset to first page when searching
|
||||
}, [searchTerm, rowsData]);
|
||||
|
||||
const rows = filteredData.map((item) => {
|
||||
const sortedData = getSortedData(filteredData);
|
||||
|
||||
const rows = sortedData.map((item) => {
|
||||
let displayName = item.createdBy;
|
||||
if (displayName === '-' && item.createdById) {
|
||||
try {
|
||||
@ -548,7 +638,7 @@ const IsicHsCodes = () => {
|
||||
item.product,
|
||||
item.description || '-',
|
||||
item.unit,
|
||||
item.estimatedMapped,
|
||||
<div className="whitespace-nowrap">{item.estimatedMapped}</div>,
|
||||
displayName,
|
||||
item.updated || item.createdOn || '-',
|
||||
'actions',
|
||||
@ -1212,10 +1302,21 @@ const IsicHsCodes = () => {
|
||||
</div>
|
||||
|
||||
{/* Table - Desktop */}
|
||||
<div className="hidden md:block">
|
||||
<div className="hidden md:block w-full overflow-x-auto">
|
||||
<Table
|
||||
headers={headers}
|
||||
rows={rows}
|
||||
columnWidths={[
|
||||
'140px', // HS Code
|
||||
'250px', // Product Name
|
||||
'200px', // Description
|
||||
'140px', // Unit
|
||||
'170px', // Establishment Mapped
|
||||
'150px', // Created By
|
||||
'130px', // Last Updated
|
||||
'130px' // Actions
|
||||
]}
|
||||
className="w-full"
|
||||
renderCell={(value, rowIndex, colIndex) => {
|
||||
// Handle product name and description columns with text wrapping
|
||||
if (colIndex === 1 || colIndex === 2) {
|
||||
@ -1225,6 +1326,13 @@ const IsicHsCodes = () => {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
if (colIndex === 5 || colIndex === 6) {
|
||||
return (
|
||||
<div className="max-w-[200px] whitespace-normal break-words">
|
||||
{value}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Handle action buttons column (index 7)
|
||||
if (colIndex === 7) {
|
||||
|
||||
@ -89,6 +89,10 @@ const QuarterlyWindows = () => {
|
||||
const [isLoading, setIsLoading] = React.useState(false);
|
||||
const [validationErrors, setValidationErrors] = React.useState({});
|
||||
const [toastData, setToastData] = React.useState(null);
|
||||
const [sortConfig, setSortConfig] = React.useState({
|
||||
key: null,
|
||||
direction: 'asc'
|
||||
});
|
||||
|
||||
// Format date to yyyy-MM-dd for input fields
|
||||
const formatDateForInput = (dateString) => {
|
||||
@ -142,19 +146,139 @@ const QuarterlyWindows = () => {
|
||||
}, []);
|
||||
|
||||
// Table headers with left alignment and no wrapping
|
||||
const handleSort = (key) => {
|
||||
let direction = 'asc';
|
||||
if (sortConfig.key === key && sortConfig.direction === 'asc') {
|
||||
direction = 'desc';
|
||||
}
|
||||
setSortConfig({ key, direction });
|
||||
};
|
||||
|
||||
const getSortedData = (data) => {
|
||||
if (!sortConfig.key) return data;
|
||||
|
||||
return [...data].sort((a, b) => {
|
||||
let aValue = a[sortConfig.key];
|
||||
let bValue = b[sortConfig.key];
|
||||
|
||||
// Handle numeric comparisons
|
||||
if (['year', 'assigned', 'responded', 'not_responded', 'submissionCount'].includes(sortConfig.key)) {
|
||||
aValue = Number(aValue) || 0;
|
||||
bValue = Number(bValue) || 0;
|
||||
return sortConfig.direction === 'asc' ? aValue - bValue : bValue - aValue;
|
||||
}
|
||||
|
||||
// Handle date comparisons
|
||||
if (['startDate', 'endDate'].includes(sortConfig.key)) {
|
||||
aValue = aValue ? new Date(aValue).getTime() : 0;
|
||||
bValue = bValue ? new Date(bValue).getTime() : 0;
|
||||
return sortConfig.direction === 'asc' ? aValue - bValue : bValue - aValue;
|
||||
}
|
||||
|
||||
// Default string comparison
|
||||
aValue = String(aValue || '').toLowerCase();
|
||||
bValue = String(bValue || '').toLowerCase();
|
||||
|
||||
if (aValue < bValue) {
|
||||
return sortConfig.direction === 'asc' ? -1 : 1;
|
||||
}
|
||||
if (aValue > bValue) {
|
||||
return sortConfig.direction === 'asc' ? 1 : -1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
};
|
||||
|
||||
const headers = [
|
||||
{ name: 'Survey Name', className: 'whitespace-nowrap text-left' },
|
||||
{ name: 'Year', className: 'whitespace-nowrap text-left' },
|
||||
{ name: 'Quarter', className: 'whitespace-nowrap text-left' },
|
||||
{ name: 'Start Date', className: 'whitespace-nowrap text-left' },
|
||||
{ name: 'End Date', className: 'whitespace-nowrap text-left' },
|
||||
{ name: 'Grace Period', className: 'whitespace-nowrap text-left' },
|
||||
{ name: 'Assigned', className: 'whitespace-nowrap text-left' },
|
||||
{ name: 'Responded', className: 'whitespace-nowrap text-left' },
|
||||
{ name: 'Not Responded', className: 'whitespace-nowrap text-left' },
|
||||
{ name: 'Submission Count', className: 'whitespace-nowrap text-left' },
|
||||
{ name: 'Actions', className: 'whitespace-nowrap text-left' },
|
||||
];
|
||||
{
|
||||
name: 'Survey Name',
|
||||
key: 'survey_name',
|
||||
sortable: true,
|
||||
className: 'whitespace-nowrap text-left'
|
||||
},
|
||||
{
|
||||
name: 'Year',
|
||||
key: 'year',
|
||||
sortable: true,
|
||||
className: 'whitespace-nowrap text-left'
|
||||
},
|
||||
{
|
||||
name: 'Quarter',
|
||||
key: 'quarter',
|
||||
sortable: true,
|
||||
className: 'whitespace-nowrap text-left'
|
||||
},
|
||||
{
|
||||
name: 'Start Date',
|
||||
key: 'startDate',
|
||||
sortable: true,
|
||||
className: 'whitespace-nowrap text-left'
|
||||
},
|
||||
{
|
||||
name: 'End Date',
|
||||
key: 'endDate',
|
||||
sortable: true,
|
||||
className: 'whitespace-nowrap text-left'
|
||||
},
|
||||
{
|
||||
name: 'Grace Period',
|
||||
key: 'gracePeriod',
|
||||
sortable: false,
|
||||
className: 'whitespace-nowrap text-left'
|
||||
},
|
||||
{
|
||||
name: 'Assigned',
|
||||
key: 'assigned',
|
||||
sortable: false,
|
||||
className: 'whitespace-nowrap text-left'
|
||||
},
|
||||
{
|
||||
name: 'Responded',
|
||||
key: 'responded',
|
||||
sortable: false,
|
||||
className: 'whitespace-nowrap text-left'
|
||||
},
|
||||
{
|
||||
name: 'Not Responded',
|
||||
key: 'not_responded',
|
||||
sortable: false,
|
||||
className: 'whitespace-nowrap text-left'
|
||||
},
|
||||
{
|
||||
name: 'Submission Count',
|
||||
key: 'submissionCount',
|
||||
sortable: false,
|
||||
className: 'whitespace-nowrap text-left'
|
||||
},
|
||||
{
|
||||
name: 'Actions',
|
||||
key: 'actions',
|
||||
sortable: false,
|
||||
className: 'whitespace-nowrap text-left'
|
||||
},
|
||||
].map(header => {
|
||||
if (!header.sortable) return { name: header.name, className: header.className };
|
||||
|
||||
const isActive = sortConfig.key === header.key;
|
||||
const isAsc = sortConfig.direction === 'asc';
|
||||
|
||||
return {
|
||||
name: (
|
||||
<div
|
||||
className="flex items-center cursor-pointer gap-1"
|
||||
onClick={() => handleSort(header.key)}
|
||||
>
|
||||
<span>{header.name}</span>
|
||||
<img
|
||||
src={isActive ? "/assets/images/active-sort.svg" : "/assets/images/inactive-sort.svg"}
|
||||
alt="Sort"
|
||||
className={`w-3 h-3 transition-transform ${isActive && isAsc ? 'transform rotate-180' : ''}`}
|
||||
/>
|
||||
</div>
|
||||
),
|
||||
className: header.className
|
||||
};
|
||||
});
|
||||
|
||||
const columnwidth = [
|
||||
220, // Survey Name
|
||||
@ -215,7 +339,9 @@ const QuarterlyWindows = () => {
|
||||
</div>
|
||||
);
|
||||
|
||||
const rows = filteredRows.map((item) => [
|
||||
const sortedRows = getSortedData(filteredRows);
|
||||
|
||||
const rows = sortedRows.map((item) => [
|
||||
item.survey_name || '-',
|
||||
item.year,
|
||||
item.quarter,
|
||||
|
||||
@ -89,8 +89,53 @@ const UnitMaster = () => {
|
||||
const [importError, setImportError] = useState('');
|
||||
const fileInputRef = useRef(null);
|
||||
const [pageSize, setPageSize] = React.useState(10);
|
||||
|
||||
// const pageSize = 10;
|
||||
const [sortConfig, setSortConfig] = React.useState({
|
||||
key: 'created_at',
|
||||
direction: 'desc'
|
||||
});
|
||||
|
||||
// Sort units based on sortConfig
|
||||
const sortedUnits = React.useMemo(() => {
|
||||
const sortableItems = [...units];
|
||||
if (sortConfig.key) {
|
||||
sortableItems.sort((a, b) => {
|
||||
let aValue, bValue;
|
||||
|
||||
// Get the values to sort by
|
||||
if (sortConfig.key === 'created_by') {
|
||||
// For created_by, use created_by_name for sorting
|
||||
aValue = (a.created_by_name || '').toString().toLowerCase();
|
||||
bValue = (b.created_by_name || '').toString().toLowerCase();
|
||||
} else if (sortConfig.key === 'created_at' || sortConfig.key === 'updated_at') {
|
||||
// Handle date fields
|
||||
aValue = a[sortConfig.key] ? new Date(a[sortConfig.key]) : new Date(0);
|
||||
bValue = b[sortConfig.key] ? new Date(b[sortConfig.key]) : new Date(0);
|
||||
} else {
|
||||
// Handle other string fields
|
||||
aValue = (a[sortConfig.key] || '').toString().toLowerCase();
|
||||
bValue = (b[sortConfig.key] || '').toString().toLowerCase();
|
||||
}
|
||||
|
||||
if (aValue < bValue) {
|
||||
return sortConfig.direction === 'asc' ? -1 : 1;
|
||||
}
|
||||
if (aValue > bValue) {
|
||||
return sortConfig.direction === 'asc' ? 1 : -1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
return sortableItems;
|
||||
}, [units, sortConfig]);
|
||||
|
||||
// Handle sort request
|
||||
const requestSort = (key) => {
|
||||
let direction = 'asc';
|
||||
if (sortConfig.key === key && sortConfig.direction === 'asc') {
|
||||
direction = 'desc';
|
||||
}
|
||||
setSortConfig({ key, direction });
|
||||
};
|
||||
|
||||
// Fetch units on component mount
|
||||
useEffect(() => {
|
||||
@ -101,7 +146,7 @@ const UnitMaster = () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const response = await getUnits();
|
||||
|
||||
|
||||
// Handle different response formats
|
||||
let unitsData = [];
|
||||
if (Array.isArray(response)) {
|
||||
@ -136,13 +181,19 @@ const UnitMaster = () => {
|
||||
};
|
||||
|
||||
const filteredUnits = useMemo(() => {
|
||||
if (!searchTerm) return units;
|
||||
const term = searchTerm.toLowerCase();
|
||||
return units.filter(unit =>
|
||||
(unit.uom && unit.uom.toLowerCase().includes(term)) ||
|
||||
(unit.description && unit.description.toLowerCase().includes(term))
|
||||
);
|
||||
}, [units, searchTerm]);
|
||||
let result = [...sortedUnits];
|
||||
|
||||
// Apply search filter if searchTerm exists
|
||||
if (searchTerm) {
|
||||
const term = searchTerm.toLowerCase();
|
||||
result = result.filter(unit =>
|
||||
(unit.uom && unit.uom.toLowerCase().includes(term)) ||
|
||||
(unit.description && unit.description.toLowerCase().includes(term))
|
||||
);
|
||||
}
|
||||
|
||||
return result;
|
||||
}, [sortedUnits, searchTerm]);
|
||||
|
||||
useEffect(() => {
|
||||
const userProfile = sessionStorage.getItem('user_profile');
|
||||
@ -159,15 +210,110 @@ const UnitMaster = () => {
|
||||
}, []);
|
||||
|
||||
const headers = [
|
||||
'Unit Name',
|
||||
'Description',
|
||||
'Created By',
|
||||
'Created On',
|
||||
'Last Updated',
|
||||
'Actions',
|
||||
{
|
||||
name: (
|
||||
<div className="flex items-center gap-1">
|
||||
<span>Unit Name</span>
|
||||
<button
|
||||
onClick={() => requestSort('uom')}
|
||||
className="text-gray-400 hover:text-gray-600"
|
||||
>
|
||||
<img
|
||||
src={sortConfig.key === 'uom' ? "/assets/images/active-sort.svg" : "/assets/images/inactive-sort.svg"}
|
||||
alt="Sort"
|
||||
className={`w-3 h-3 transition-transform ${sortConfig.key === 'uom' && sortConfig.direction === 'asc' ? 'transform rotate-180' : ''}`}
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
),
|
||||
key: 'uom',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
name: (
|
||||
<div className="flex items-center gap-1">
|
||||
<span>Description</span>
|
||||
<button
|
||||
onClick={() => requestSort('description')}
|
||||
className="text-gray-400 hover:text-gray-600"
|
||||
>
|
||||
<img
|
||||
src={sortConfig.key === 'description' ? "/assets/images/active-sort.svg" : "/assets/images/inactive-sort.svg"}
|
||||
alt="Sort"
|
||||
className={`w-3 h-3 transition-transform ${sortConfig.key === 'description' && sortConfig.direction === 'asc' ? 'transform rotate-180' : ''}`}
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
),
|
||||
key: 'description',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
name: (
|
||||
<div className="flex items-center gap-1">
|
||||
<span>Created By</span>
|
||||
<button
|
||||
onClick={() => requestSort('created_by_name')}
|
||||
className="text-gray-400 hover:text-gray-600"
|
||||
>
|
||||
<img
|
||||
src={sortConfig.key === 'created_by_name' ? "/assets/images/active-sort.svg" : "/assets/images/inactive-sort.svg"}
|
||||
alt="Sort"
|
||||
className={`w-3 h-3 transition-transform ${sortConfig.key === 'created_by_name' && sortConfig.direction === 'asc' ? 'transform rotate-180' : ''}`}
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
),
|
||||
key: 'created_by',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
name: (
|
||||
<div className="flex items-center gap-1">
|
||||
<span>Created On</span>
|
||||
<button
|
||||
onClick={() => requestSort('created_at')}
|
||||
className="text-gray-400 hover:text-gray-600"
|
||||
>
|
||||
<img
|
||||
src={sortConfig.key === 'created_at' ? "/assets/images/active-sort.svg" : "/assets/images/inactive-sort.svg"}
|
||||
alt="Sort"
|
||||
className={`w-3 h-3 transition-transform ${sortConfig.key === 'created_at' && sortConfig.direction === 'asc' ? 'transform rotate-180' : ''}`}
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
),
|
||||
key: 'created_at',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
name: (
|
||||
<div className="flex items-center gap-1">
|
||||
<span>Last Updated</span>
|
||||
<button
|
||||
onClick={() => requestSort('updated_at')}
|
||||
className="text-gray-400 hover:text-gray-600"
|
||||
>
|
||||
<img
|
||||
src={sortConfig.key === 'updated_at' ? "/assets/images/active-sort.svg" : "/assets/images/inactive-sort.svg"}
|
||||
alt="Sort"
|
||||
className={`w-3 h-3 transition-transform ${sortConfig.key === 'updated_at' && sortConfig.direction === 'asc' ? 'transform rotate-180' : ''}`}
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
),
|
||||
key: 'updated_at',
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
name: 'Actions',
|
||||
key: 'actions',
|
||||
sortable: false
|
||||
},
|
||||
];
|
||||
|
||||
const rows = useMemo(() => {
|
||||
// Use filteredUnits which is already sorted
|
||||
return filteredUnits.map((item) => {
|
||||
const createdDate = item.created_at
|
||||
? new Date(item.created_at).toLocaleDateString('en-GB')
|
||||
@ -176,7 +322,7 @@ const UnitMaster = () => {
|
||||
? new Date(item.updated_at).toLocaleDateString('en-GB')
|
||||
: '-';
|
||||
|
||||
const createdByName = item.created_by_name || currentUser?.name || '-';
|
||||
const createdByName = item.created_by_name ||'-';
|
||||
|
||||
return [
|
||||
item.uom || '-',
|
||||
|
||||
Loading…
Reference in New Issue
Block a user