Spaces:
Running
Running
James McCool
commited on
Commit
·
9f63aed
1
Parent(s):
f0d329b
Add sorting functionality to DataTable component with visual indicators for column headers
Browse files- src/components/DataTable.jsx +70 -5
src/components/DataTable.jsx
CHANGED
|
@@ -6,6 +6,7 @@ const DataTable = () => {
|
|
| 6 |
const [data, setData] = useState([]);
|
| 7 |
const [loading, setLoading] = useState(true);
|
| 8 |
const [error, setError] = useState(null);
|
|
|
|
| 9 |
|
| 10 |
// Mock data for demonstration - replace with actual MongoDB data
|
| 11 |
const mockData = [
|
|
@@ -24,6 +25,48 @@ const DataTable = () => {
|
|
| 24 |
}, 1000);
|
| 25 |
}, []);
|
| 26 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
const fetchFromMongoDB = async () => {
|
| 28 |
try {
|
| 29 |
setLoading(true);
|
|
@@ -57,6 +100,8 @@ const DataTable = () => {
|
|
| 57 |
);
|
| 58 |
}
|
| 59 |
|
|
|
|
|
|
|
| 60 |
return (
|
| 61 |
<div className="w-full mx-auto p-6">
|
| 62 |
<div className="flex justify-between items-center mb-6">
|
|
@@ -71,14 +116,34 @@ const DataTable = () => {
|
|
| 71 |
<TableCaption>A list of users from the database.</TableCaption>
|
| 72 |
<TableHeader>
|
| 73 |
<TableRow>
|
| 74 |
-
<TableHead
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 78 |
</TableRow>
|
| 79 |
</TableHeader>
|
| 80 |
<TableBody>
|
| 81 |
-
{
|
| 82 |
<TableRow key={user.id}>
|
| 83 |
<TableCell className="font-medium">{user.id}</TableCell>
|
| 84 |
<TableCell>{user.name}</TableCell>
|
|
|
|
| 6 |
const [data, setData] = useState([]);
|
| 7 |
const [loading, setLoading] = useState(true);
|
| 8 |
const [error, setError] = useState(null);
|
| 9 |
+
const [sortConfig, setSortConfig] = useState({ key: null, direction: 'asc' });
|
| 10 |
|
| 11 |
// Mock data for demonstration - replace with actual MongoDB data
|
| 12 |
const mockData = [
|
|
|
|
| 25 |
}, 1000);
|
| 26 |
}, []);
|
| 27 |
|
| 28 |
+
// Sorting function
|
| 29 |
+
const sortData = (key) => {
|
| 30 |
+
let direction = 'asc';
|
| 31 |
+
|
| 32 |
+
// If clicking the same column, toggle direction
|
| 33 |
+
if (sortConfig.key === key && sortConfig.direction === 'asc') {
|
| 34 |
+
direction = 'desc';
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
+
setSortConfig({ key, direction });
|
| 38 |
+
};
|
| 39 |
+
|
| 40 |
+
// Get sorted data
|
| 41 |
+
const getSortedData = () => {
|
| 42 |
+
if (!sortConfig.key) return data;
|
| 43 |
+
|
| 44 |
+
return [...data].sort((a, b) => {
|
| 45 |
+
let aValue = a[sortConfig.key];
|
| 46 |
+
let bValue = b[sortConfig.key];
|
| 47 |
+
|
| 48 |
+
// Handle string comparison (case-insensitive)
|
| 49 |
+
if (typeof aValue === 'string') {
|
| 50 |
+
aValue = aValue.toLowerCase();
|
| 51 |
+
bValue = bValue.toLowerCase();
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
if (aValue < bValue) {
|
| 55 |
+
return sortConfig.direction === 'asc' ? -1 : 1;
|
| 56 |
+
}
|
| 57 |
+
if (aValue > bValue) {
|
| 58 |
+
return sortConfig.direction === 'asc' ? 1 : -1;
|
| 59 |
+
}
|
| 60 |
+
return 0;
|
| 61 |
+
});
|
| 62 |
+
};
|
| 63 |
+
|
| 64 |
+
// Get sort indicator for column headers
|
| 65 |
+
const getSortIndicator = (key) => {
|
| 66 |
+
if (sortConfig.key !== key) return '↕️';
|
| 67 |
+
return sortConfig.direction === 'asc' ? '↑' : '↓';
|
| 68 |
+
};
|
| 69 |
+
|
| 70 |
const fetchFromMongoDB = async () => {
|
| 71 |
try {
|
| 72 |
setLoading(true);
|
|
|
|
| 100 |
);
|
| 101 |
}
|
| 102 |
|
| 103 |
+
const sortedData = getSortedData();
|
| 104 |
+
|
| 105 |
return (
|
| 106 |
<div className="w-full mx-auto p-6">
|
| 107 |
<div className="flex justify-between items-center mb-6">
|
|
|
|
| 116 |
<TableCaption>A list of users from the database.</TableCaption>
|
| 117 |
<TableHeader>
|
| 118 |
<TableRow>
|
| 119 |
+
<TableHead
|
| 120 |
+
className="cursor-pointer hover:bg-muted/50 transition-colors"
|
| 121 |
+
onClick={() => sortData('id')}
|
| 122 |
+
>
|
| 123 |
+
ID {getSortIndicator('id')}
|
| 124 |
+
</TableHead>
|
| 125 |
+
<TableHead
|
| 126 |
+
className="cursor-pointer hover:bg-muted/50 transition-colors"
|
| 127 |
+
onClick={() => sortData('name')}
|
| 128 |
+
>
|
| 129 |
+
Name {getSortIndicator('name')}
|
| 130 |
+
</TableHead>
|
| 131 |
+
<TableHead
|
| 132 |
+
className="cursor-pointer hover:bg-muted/50 transition-colors"
|
| 133 |
+
onClick={() => sortData('email')}
|
| 134 |
+
>
|
| 135 |
+
Email {getSortIndicator('email')}
|
| 136 |
+
</TableHead>
|
| 137 |
+
<TableHead
|
| 138 |
+
className="cursor-pointer hover:bg-muted/50 transition-colors"
|
| 139 |
+
onClick={() => sortData('role')}
|
| 140 |
+
>
|
| 141 |
+
Role {getSortIndicator('role')}
|
| 142 |
+
</TableHead>
|
| 143 |
</TableRow>
|
| 144 |
</TableHeader>
|
| 145 |
<TableBody>
|
| 146 |
+
{sortedData.map((user) => (
|
| 147 |
<TableRow key={user.id}>
|
| 148 |
<TableCell className="font-medium">{user.id}</TableCell>
|
| 149 |
<TableCell>{user.name}</TableCell>
|