This repository was archived by the owner on Feb 10, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathProjectReviewList.tsx
119 lines (113 loc) · 3.19 KB
/
ProjectReviewList.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import { Address } from "viem";
import { DefaultLogo } from "@/assets";
import { IconLabel } from "@/components/IconLabel";
import { Button } from "@/primitives/Button";
import { CircleStat } from "@/primitives/Indicators";
import { ListGrid, ListGridColumn } from "@/primitives/ListGrid";
import { ProjectReview } from "~checker/types";
import { getReviewsCount } from "~checker/utils/getReviewsCount";
import { ReviewsCounterLabel } from "../ReviewsCounterLabel";
export interface ProjectReviewListProps {
projects: ProjectReview[];
reviewer?: Address;
action?: (projectId: string) => void;
actionLabel?: string;
keepAction?: boolean;
}
export const ProjectReviewList = ({
reviewer,
projects,
action,
actionLabel,
keepAction,
}: ProjectReviewListProps) => {
const columns: ListGridColumn<ProjectReview>[] = [
{
header: "Project",
key: "project",
width: "2fr",
render: (item) => (
<div className="flex items-center gap-4">
<img
src={item.avatarUrl}
alt={item.name}
className="aspect-square size-12 rounded-sm"
onError={(event: React.SyntheticEvent<HTMLImageElement, Event>) => {
event.currentTarget.src = DefaultLogo;
}}
/>
<span>{item.name}</span>
</div>
),
},
{
header: "Date Submitted",
key: "date",
width: "1.3fr",
render: (item) => <IconLabel type="date" date={item.date} />,
},
{
header: "Reviews",
key: "reviews",
width: "1fr",
render: (item) => {
const { nApproved, nRejected } = getReviewsCount(item.reviews);
return <ReviewsCounterLabel positiveReviews={nApproved} negativeReviews={nRejected} />;
},
},
{
header: "AI Suggestion",
key: "aiSuggestion",
width: "0.9fr",
render: (item) => {
return item.aiSuggestion !== 0 ? (
<IconLabel type="ai-evaluation" percent={item.aiSuggestion} />
) : (
<ReviewsCounterLabel negativeReviews={0} positiveReviews={0} />
);
},
},
{
header: "Score Average",
key: "scoreAverage",
width: "0.8fr",
position: "center",
render: (item) => (
<div className="flex items-center justify-center">
<CircleStat value={item.scoreAverage.toFixed(0)} />
</div>
),
},
{
header: "Action",
key: "action",
width: "1fr",
position: "center",
render: (item) => {
const isReviewed = item.reviews.some((review) => review.reviewer === reviewer) || !reviewer;
return (
<div className="flex items-center justify-center">
<Button
variant="outlined-secondary"
value={actionLabel ?? "Evaluate project"}
disabled={keepAction ? false : isReviewed}
onClick={() => {
if (action) {
action(item.id);
}
}}
/>
</div>
);
},
},
];
return (
<ListGrid
data={projects}
columns={columns}
rowClassName="h-[72px]"
getRowKey={(item: ProjectReview) => item.id.toString()}
/>
);
};