Skip to content

Commit 723d478

Browse files
authored
Merge pull request #3457 from Northeastern-Electric-Racing/#3392-filter-and-searching
#3392 filter and searching
2 parents dcbe73d + f2d86d2 commit 723d478

5 files changed

Lines changed: 416 additions & 226 deletions

File tree

src/frontend/src/components/DownloadButton.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,17 @@ import { useDownloadFile } from '../hooks/part-review.hooks';
66
interface DownloadButtonProps {
77
fileId: string;
88
filename: string;
9+
stopPropagation?: boolean;
910
}
1011

11-
const DownloadButton: React.FC<DownloadButtonProps> = ({ fileId, filename = 'download' }) => {
12+
const DownloadButton: React.FC<DownloadButtonProps> = ({ fileId, filename = 'download', stopPropagation = false }) => {
1213
const { data: blobData } = useDownloadFile(fileId);
1314

14-
const handleDownload = () => {
15+
const handleDownload = (e: React.MouseEvent<HTMLButtonElement>) => {
16+
if (stopPropagation) {
17+
e.stopPropagation();
18+
e.preventDefault();
19+
}
1520
if (!blobData) return;
1621
const url = URL.createObjectURL(blobData);
1722
const link = document.createElement('a');

src/frontend/src/pages/ProjectDetailPage/ProjectViewContainer/PartReview/PartReviewComponents/PartFormModels/CreateMenu.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ const CreateMenu: React.FC<CreateMenuProps> = ({ wbsNum, partsInProject }: Creat
5353
disabled={isGuest(user.role)}
5454
onClick={handleClick}
5555
sx={{
56-
border: 1
56+
border: 1,
57+
height: '2.25rem'
5758
}}
5859
>
5960
<AddIcon fontSize="small" />
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import React from 'react';
2+
import { PartPreview } from 'shared';
3+
import { grey } from '@mui/material/colors';
4+
import { Card, CardContent, Typography, Box, Chip, Link } from '@mui/material';
5+
import { useGetImageUrl } from '../../../../../hooks/onboarding.hook';
6+
import { Link as RouterLink } from 'react-router-dom';
7+
import DownloadButton from '../../../../../components/DownloadButton';
8+
import { formatPartStatus, getStatusColor } from '../../../../../utils/part.utils';
9+
10+
interface PartPreviewCardProps {
11+
partPreview: PartPreview;
12+
projectName: string;
13+
redirectUrl: string;
14+
}
15+
16+
export function PartPreviewCard({ partPreview, projectName, redirectUrl }: PartPreviewCardProps) {
17+
const { commonName, index, previewImageId, status, assignees, reviewRequests } = partPreview;
18+
const { data: previewUrl } = useGetImageUrl(previewImageId ?? null);
19+
20+
return (
21+
<Link component={RouterLink} to={redirectUrl} sx={{ textDecoration: 'none', color: 'inherit' }}>
22+
<Card
23+
sx={{
24+
maxWidth: 400,
25+
border: '0.5px solid rgb(193, 193, 193)',
26+
borderRadius: '8px',
27+
bgcolor: grey[800],
28+
overflow: 'hidden',
29+
cursor: redirectUrl ? 'pointer' : 'default',
30+
'&:hover': redirectUrl
31+
? {
32+
boxShadow: '0 4px 8px rgba(0,0,0,0.2)',
33+
transform: 'translateY(-2px)',
34+
transition: 'all 0.2s ease-in-out'
35+
}
36+
: {}
37+
}}
38+
>
39+
<Box sx={{ px: 2, pt: 2, bgcolor: grey[800] }}>
40+
{previewImageId && previewUrl ? (
41+
<Box
42+
sx={{
43+
height: 200,
44+
display: 'flex',
45+
alignItems: 'center',
46+
justifyContent: 'center',
47+
border: '0.5px solid rgb(193, 193, 193)',
48+
bgcolor: grey[600]
49+
}}
50+
>
51+
<Box
52+
component="img"
53+
sx={{ display: 'block', maxWidth: '200px', mb: 1 }}
54+
alt={`${commonName} Preview`}
55+
src={previewUrl}
56+
/>
57+
</Box>
58+
) : (
59+
<Box
60+
sx={{
61+
height: 200,
62+
display: 'flex',
63+
alignItems: 'center',
64+
justifyContent: 'center',
65+
border: '0.5px solid rgb(193, 193, 193)',
66+
bgcolor: grey[600]
67+
}}
68+
/>
69+
)}
70+
</Box>
71+
<CardContent sx={{ bgcolor: grey[800], color: 'white', px: 2, py: 1 }}>
72+
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 1 }}>
73+
<Typography variant="subtitle1" sx={{ fontWeight: 'bold' }}>
74+
{`${projectName}_${commonName}_${index.toString().padStart(5, '0')}`}
75+
</Typography>
76+
<Chip
77+
label={formatPartStatus(status)}
78+
size="small"
79+
sx={{
80+
bgcolor: getStatusColor(status),
81+
color: 'white',
82+
borderRadius: '16px',
83+
fontWeight: 500,
84+
px: 1,
85+
py: 0.5
86+
}}
87+
/>
88+
</Box>
89+
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
90+
<Box>
91+
<Typography variant="body2" sx={{ color: grey[300] }}>
92+
<strong>Assignees:</strong>{' '}
93+
{assignees && assignees.length
94+
? assignees.map((a) => `${a.firstName} ${a.lastName}`).join(', ')
95+
: 'None assigned'}
96+
</Typography>
97+
<Typography variant="body2" sx={{ color: grey[300] }}>
98+
<strong>Reviewers:</strong>{' '}
99+
{reviewRequests && reviewRequests.length
100+
? reviewRequests.map((r) => `${r.reviewerRequested.firstName} ${r.reviewerRequested.lastName}`).join(', ')
101+
: 'No reviewers'}
102+
</Typography>
103+
</Box>
104+
{previewImageId && (
105+
<DownloadButton fileId={previewImageId} filename={`${commonName}.png`} stopPropagation={true} />
106+
)}
107+
</Box>
108+
</CardContent>
109+
</Card>
110+
</Link>
111+
);
112+
}

0 commit comments

Comments
 (0)