Skip to content

Commit bbf6ee4

Browse files
authored
Overall pass on coding inconsistencies, 3 features from Ricky (#87)
1 parent 0dc8c83 commit bbf6ee4

File tree

7 files changed

+628
-67
lines changed

7 files changed

+628
-67
lines changed

ui/src/components/custom/search/matrixExplorer.tsx

Lines changed: 53 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ interface CarverMatrix {
2727
hosts: string[];
2828
participants: string[];
2929
roleBased: boolean;
30+
createdAt: string;
3031
}
3132

3233
const MatrixExplorer: React.FC = () => {
@@ -86,15 +87,16 @@ const MatrixExplorer: React.FC = () => {
8687
const filteredMatrices = matrices.filter((matrix) => {
8788
// Text search filter
8889
const term = searchTerm.toLowerCase();
89-
const matchesSearch = matrix.name.toLowerCase().includes(term) ||
90+
const matchesSearch =
91+
matrix.name.toLowerCase().includes(term) ||
9092
matrix.description.toLowerCase().includes(term);
9193

9294
// Role-based matrix filter
93-
if (roleBasedFilter !== 'all') {
94-
if (roleBasedFilter === 'enabled' && !matrix.roleBased) {
95+
if (roleBasedFilter !== "all") {
96+
if (roleBasedFilter === "enabled" && !matrix.roleBased) {
9597
return false;
9698
}
97-
if (roleBasedFilter === 'disabled' && matrix.roleBased) {
99+
if (roleBasedFilter === "disabled" && matrix.roleBased) {
98100
return false;
99101
}
100102
}
@@ -111,7 +113,7 @@ const MatrixExplorer: React.FC = () => {
111113

112114
// Role-based filtering
113115
if (!userEmail) {
114-
console.log('No user email available');
116+
console.log("No user email available");
115117
return false;
116118
}
117119

@@ -125,19 +127,33 @@ const MatrixExplorer: React.FC = () => {
125127
matchesRole = isBoth;
126128
} else {
127129
if (roleFilters.host) {
128-
matchesRole = isHost;
130+
matchesRole = isHost; // Show all matrices where user is a host, including those where they are both
129131
}
130132
if (roleFilters.participant) {
131-
matchesRole = matchesRole || isParticipant;
133+
matchesRole = matchesRole || isParticipant; // Show all matrices where user is a participant, including those where they are both
132134
}
133135
if (!roleFilters.host && !roleFilters.participant) {
134-
matchesRole = true;
136+
matchesRole = true; // No role filters selected
135137
}
136138
}
137139

138140
return matchesSearch && matchesRole;
139141
});
140142

143+
// Sort matrices by timestamp (newest first)
144+
const sortedMatrices = [...filteredMatrices].sort((a, b) => {
145+
return new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime();
146+
});
147+
148+
// Helper functions to check if user is host or participant
149+
const isHost = (matrix: CarverMatrix): boolean => {
150+
return userEmail ? matrix.hosts?.includes(userEmail) || false : false;
151+
};
152+
153+
const isParticipant = (matrix: CarverMatrix): boolean => {
154+
return userEmail ? matrix.participants?.includes(userEmail) || false : false;
155+
};
156+
141157
const handleMatrixSelect = (matrixId: number) => {
142158
window.location.href = `/EditMatrix?matrixId=${matrixId}`;
143159
};
@@ -381,16 +397,37 @@ const MatrixExplorer: React.FC = () => {
381397
gap: 1.5,
382398
boxSizing: 'border-box',
383399
pr: 0.5,
400+
'&::-webkit-scrollbar': {
401+
width: '6px',
402+
},
403+
'&::-webkit-scrollbar-track': {
404+
background: 'rgba(255, 255, 255, 0.05)',
405+
borderRadius: '3px',
406+
},
407+
'&::-webkit-scrollbar-thumb': {
408+
background: 'rgba(255, 255, 255, 0.2)',
409+
borderRadius: '3px',
410+
'&:hover': {
411+
background: 'rgba(255, 255, 255, 0.3)',
412+
},
413+
},
384414
}}
385415
>
386-
{filteredMatrices.map((matrix) => (
387-
<MiniMatrixCard
388-
key={matrix.matrixId}
389-
title={matrix.name}
390-
onSelectMatrix={() => handleMatrixSelect(matrix.matrixId)}
391-
titleColor="#ffffff"
392-
/>
393-
))}
416+
{sortedMatrices.length > 0 ? (
417+
sortedMatrices.map((matrix) => (
418+
<MiniMatrixCard
419+
key={matrix.matrixId}
420+
title={matrix.name}
421+
onSelectMatrix={() => handleMatrixSelect(matrix.matrixId)}
422+
isHost={isHost(matrix)}
423+
isParticipant={isParticipant(matrix)}
424+
/>
425+
))
426+
) : (
427+
<Typography variant="body2" color="text.secondary" align="center">
428+
No matrices found
429+
</Typography>
430+
)}
394431
</Box>
395432
</Box>
396433
);

ui/src/components/custom/search/miniMatrixCard.tsx

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
11
import React from "react";
2-
import { Typography, Paper } from "@mui/material";
2+
import { Typography, Paper, Box } from "@mui/material";
3+
import AdminPanelSettingsIcon from '@mui/icons-material/AdminPanelSettings';
4+
import PersonIcon from '@mui/icons-material/Person';
35

46
interface MiniMatrixCardProps {
57
title: string;
68
onSelectMatrix: () => void;
7-
titleColor?: string;
9+
isHost?: boolean;
10+
isParticipant?: boolean;
811
}
912

1013
const MiniMatrixCard: React.FC<MiniMatrixCardProps> = ({
1114
title,
1215
onSelectMatrix,
13-
titleColor = "#ffffff",
16+
isHost = false,
17+
isParticipant = false,
1418
}) => {
1519
return (
1620
<Paper
@@ -37,19 +41,32 @@ const MiniMatrixCard: React.FC<MiniMatrixCardProps> = ({
3741
}}
3842
onClick={onSelectMatrix}
3943
>
40-
<Typography
41-
variant="subtitle2"
42-
fontWeight="bold"
43-
color={titleColor}
44-
sx={{
45-
fontSize: "0.9rem",
46-
fontFamily: "'Roboto Condensed', sans-serif",
47-
textTransform: "uppercase",
48-
letterSpacing: "0.5px",
49-
}}
50-
>
51-
{title || ""}
52-
</Typography>
44+
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
45+
{isHost && (
46+
<AdminPanelSettingsIcon sx={{ color: '#4D9FFF', fontSize: 20 }} />
47+
)}
48+
{!isHost && isParticipant && (
49+
<PersonIcon sx={{ color: '#00E676', fontSize: 20 }} />
50+
)}
51+
<Typography
52+
variant="subtitle2"
53+
fontWeight="bold"
54+
sx={{
55+
fontSize: "0.9rem",
56+
fontFamily: "'Roboto Condensed', sans-serif",
57+
textTransform: "uppercase",
58+
letterSpacing: "0.5px",
59+
overflow: "hidden",
60+
textOverflow: "ellipsis",
61+
display: "-webkit-box",
62+
WebkitLineClamp: 2,
63+
WebkitBoxOrient: "vertical",
64+
color: "#ffffff",
65+
}}
66+
>
67+
{title || ""}
68+
</Typography>
69+
</Box>
5370
</Paper>
5471
);
5572
};

ui/src/components/navigation/Redirect.tsx

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { useContext, useEffect, useState } from "react";
22
import { useLocation, useNavigate } from "react-router-dom";
33
import { GlobalContext } from "../../context/GlobalContext";
4+
import { useUnsavedChanges } from "../../context/UnsavedChangesContext";
45
import {
56
ADMIN_ROUTES,
67
blueTheme,
@@ -39,6 +40,7 @@ export const Redirect: React.FC<RedirectProps> = ({ children }) => {
3940
const location = useLocation();
4041
const [height, setHeight] = useState<number>(window.innerHeight);
4142
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
43+
const { hasUnsavedChanges, showUnsavedChangesDialog } = useUnsavedChanges();
4244

4345
// Map routes to display names for breadcrumbs
4446
const routeNames = {
@@ -65,7 +67,11 @@ export const Redirect: React.FC<RedirectProps> = ({ children }) => {
6567

6668
const handleProfile = () => {
6769
handleProfileMenuClose();
68-
navigate(ROUTES.profile);
70+
if (hasUnsavedChanges) {
71+
showUnsavedChangesDialog(() => navigate(ROUTES.profile));
72+
} else {
73+
navigate(ROUTES.profile);
74+
}
6975
};
7076

7177
const handleLogout = () => {
@@ -134,7 +140,7 @@ export const Redirect: React.FC<RedirectProps> = ({ children }) => {
134140
const getBreadcrumbs = () => {
135141
const pathnames = location.pathname.split('/').filter((x) => x);
136142
let currentPath = '';
137-
let breadcrumbPaths: string[] = [];
143+
const breadcrumbPaths: string[] = [];
138144

139145
// Build the breadcrumb paths array
140146
pathnames.forEach((value) => {
@@ -150,14 +156,22 @@ export const Redirect: React.FC<RedirectProps> = ({ children }) => {
150156
breadcrumbPaths.push(currentPath);
151157
});
152158

159+
const handleNavigation = (path: string) => {
160+
if (hasUnsavedChanges) {
161+
showUnsavedChangesDialog(() => navigate(path));
162+
} else {
163+
navigate(path);
164+
}
165+
};
166+
153167
return (
154168
<Breadcrumbs
155169
separator={<NavigateNextIcon sx={{ color: 'rgba(255, 255, 255, 0.7)', fontSize: '1.2rem' }} />}
156170
sx={{ ml: 2 }}
157171
>
158172
<Link
159173
component="button"
160-
onClick={() => navigate(ROUTES.landing)}
174+
onClick={() => handleNavigation(ROUTES.landing)}
161175
sx={{
162176
color: '#ffffff',
163177
textDecoration: 'none',
@@ -189,7 +203,7 @@ export const Redirect: React.FC<RedirectProps> = ({ children }) => {
189203
<Link
190204
key={path}
191205
component="button"
192-
onClick={() => navigate(path)}
206+
onClick={() => handleNavigation(path)}
193207
sx={{
194208
color: '#ffffff',
195209
textDecoration: 'none',
@@ -234,7 +248,13 @@ export const Redirect: React.FC<RedirectProps> = ({ children }) => {
234248
flex: 1,
235249
}}
236250
>
237-
<IconButton onClick={() => navigate(ROUTES.landing)}>
251+
<IconButton onClick={() => {
252+
if (hasUnsavedChanges) {
253+
showUnsavedChangesDialog(() => navigate(ROUTES.landing));
254+
} else {
255+
navigate(ROUTES.landing);
256+
}
257+
}}>
238258
<img src="/AIDIV-logo.svg" />
239259
</IconButton>
240260
{getBreadcrumbs()}
@@ -252,7 +272,13 @@ export const Redirect: React.FC<RedirectProps> = ({ children }) => {
252272
<>
253273
<Typography variant="h6">Dashboard</Typography>
254274
<Stack>
255-
<IconButton onClick={() => navigate(ROUTES.admin)}>
275+
<IconButton onClick={() => {
276+
if (hasUnsavedChanges) {
277+
showUnsavedChangesDialog(() => navigate(ROUTES.admin));
278+
} else {
279+
navigate(ROUTES.admin);
280+
}
281+
}}>
256282
<SpaceDashboardOutlined
257283
sx={{ color: "#FFF" }}
258284
></SpaceDashboardOutlined>

0 commit comments

Comments
 (0)