Skip to content

Commit da2e0f3

Browse files
authored
Merge pull request #39 from kleros/refactor(frontend)/cooperative-page
Refactor(frontend)/cooperative page
2 parents cc78953 + f67b40b commit da2e0f3

File tree

12 files changed

+18913
-13337
lines changed

12 files changed

+18913
-13337
lines changed

frontend/.husky/pre-commit

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
cd frontend
22
yarn tsc
3-
yarn lint
3+
yarn lint --fix

frontend/src/components/Button.tsx

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,34 +7,45 @@ const baseStyle = clsx("px-8 py-2 rounded-full transition duration-75");
77
const primaryStyle = clsx(
88
baseStyle,
99
"bg-primary-blue",
10-
"hover:bg-primary-blue/90"
10+
"hover:bg-primary-blue/90",
11+
"disabled:bg-stroke"
1112
);
1213

1314
const secondaryStyle = clsx(
15+
baseStyle,
16+
"bg-transparent border-2 border-white",
17+
"hover:bg-primary-blue hover:border-primary-blue hover:text-background-2"
18+
);
19+
20+
const tertiaryStyle = clsx(
1421
baseStyle,
1522
"bg-transparent border-2 border-white",
1623
"hover:bg-white/10"
1724
);
1825

1926

20-
interface IButton {
27+
interface IButton extends React.ComponentProps<"button"> {
2128
children: React.ReactNode;
2229
onClick?: () => void;
23-
variant?: "primary" | "secondary";
30+
variant?: "primary" | "secondary" | "tertiary";
2431
className?: string;
2532
}
2633

2734
const Button: React.FC<IButton> = ({
2835
children,
2936
onClick,
3037
className,
31-
variant = "primary"
38+
variant = "primary",
39+
...props
3240
}) => (
3341
<button
34-
className={
35-
clsx(variant === "primary" ? primaryStyle : secondaryStyle, className)
36-
}
37-
{...{ onClick }}
42+
className={clsx(
43+
variant === "primary" && primaryStyle,
44+
variant === "secondary" && secondaryStyle,
45+
variant === "tertiary" && tertiaryStyle,
46+
className
47+
)}
48+
{...{ onClick, ...props }}
3849
>
3950
{children}
4051
</button>

frontend/src/components/Cooperative/MemberSection/LearnMore.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
11
import React from "react";
22

3+
import Image from "next/image";
34
import Link from "next/link";
45

56
import Button from "@/components/Button";
67
import { CooperativeLearnMoreSection } from "@/queries/cooperative/member-section";
7-
import Image from "next/image";
88

99
const LearnMore: React.FC<CooperativeLearnMoreSection> = ({
1010
title,
1111
button,
1212
background,
1313
}) => {
1414
return (
15-
<div className="relative w-full flex flex-col items-center justify-center mt-16 p-8 ">
15+
<div className={
16+
"relative w-full flex flex-col items-center justify-center mt-16 p-8"
17+
}>
1618
<h2 className="text-primary-text text-xl mb-8 z-[1]">{title}</h2>
1719
<Link
1820
href={button.link.url}

frontend/src/components/Cooperative/ReportSection/DropdownContainer.tsx

Lines changed: 36 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,77 +1,85 @@
1-
import Dropdown from "@/components/Dropdown";
2-
import { Reports } from "./ReportCard";
31
import { useEffect, useMemo, useState } from "react";
2+
3+
import Dropdown from "@/components/Dropdown";
44
import { Report } from "@/queries/cooperative/report-section";
55

6+
import { Reports } from "./ReportCard";
7+
68
interface IDropdownContainer
79
extends Pick<Report, "yearDropdownLabel" | "monthDropdownLabel"> {
810
reports: Reports;
911
setReportUrl: (url?: string) => void;
1012
}
1113

14+
type IProcessedReports = Record<number, Array<string>>;
15+
1216
const DropdownContainer: React.FC<IDropdownContainer> = ({
1317
reports,
1418
setReportUrl,
1519
yearDropdownLabel,
1620
monthDropdownLabel,
1721
}) => {
18-
const [year, setYear] = useState<number>();
19-
const [month, setMonth] = useState<string>();
20-
21-
const yearsSet = useMemo(
22+
const processedReports = useMemo<IProcessedReports>(
2223
() =>
23-
reports.reduce<Set<number>>((acc, current) => {
24-
acc.add(current.year);
24+
reports.reduce<IProcessedReports>((acc, report: Reports[number]) => {
25+
const months = acc[report.year] ?? [];
26+
if (report.month) {
27+
acc[report.year] = [...months, report.month];
28+
} else {
29+
acc[report.year] = months;
30+
}
2531
return acc;
26-
}, new Set([])),
32+
}, {}),
2733
[reports]
2834
);
2935

3036
const years = useMemo(
3137
() =>
32-
Array.from(new Set(yearsSet))
33-
.sort((a, b) => a - b)
38+
Object.keys(processedReports)
39+
.map((key) => parseInt(key))
40+
.sort((a, b) => b - a)
3441
.map((year) => ({
3542
key: year,
3643
value: year,
3744
})),
38-
[yearsSet]
45+
[processedReports]
3946
);
4047

41-
const monthsSet = useMemo(
42-
() =>
43-
reports.reduce<Set<string>>((acc, current) => {
44-
if (current.month) {
45-
acc.add(current.month);
46-
}
47-
return acc;
48-
}, new Set([])),
49-
[reports]
50-
);
48+
const firstYear = years[0].value;
49+
50+
const [year, setYear] = useState<number>(firstYear);
5151

5252
const months = useMemo(
5353
() =>
54-
Array.from(new Set(monthsSet))
54+
processedReports[year]
5555
.sort((a, b) => monthOrder.indexOf(a) - monthOrder.indexOf(b))
5656
.map((month) => ({
5757
key: month,
5858
value: month,
5959
})),
60-
[monthsSet]
60+
[year, processedReports]
6161
);
6262

63-
const isMonthInfo = months.length !== 0;
63+
const [month, setMonth] = useState<string>();
64+
65+
const isMonthInfo = months.length > 0;
66+
67+
useEffect(() => {
68+
setMonth(undefined);
69+
}, [year]);
6470

6571
useEffect(() => {
6672
const selectedReport = reports.find(
6773
(report) =>
6874
(isMonthInfo ? report.month === month : true) && report.year === year
6975
);
7076
setReportUrl(selectedReport?.url);
71-
}, [month, year]);
77+
}, [isMonthInfo, month, year, reports, setReportUrl]);
7278

7379
return (
74-
<div className="flex flex-col md:flex-row gap-8 items-start md:items-center">
80+
<div className={
81+
"flex flex-col md:flex-row gap-8 items-start md:items-center"
82+
}>
7583
<div className="flex gap-4 items-center">
7684
<label className="text-lg text-secondary-text">
7785
{yearDropdownLabel}
@@ -112,4 +120,5 @@ const monthOrder = [
112120
"November",
113121
"December",
114122
];
123+
115124
export default DropdownContainer;

frontend/src/components/Cooperative/ReportSection/ReportCard.tsx

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1+
import { useState } from "react";
2+
3+
import clsx from "clsx";
14
import Image from "next/image";
5+
import Link from "next/link";
26

37
import Button from "@/components/Button";
48
import { Report } from "@/queries/cooperative/report-section";
5-
import { useState } from "react";
9+
610
import DropdownContainer from "./DropdownContainer";
7-
import Link from "next/link";
811

912
export type Reports = {
1013
url: string;
@@ -27,7 +30,10 @@ const ReportCard: React.FC<IReportCard> = ({
2730
const [reportUrl, setReportUrl] = useState<string>();
2831

2932
return (
30-
<div className="bg-background-2 flex flex-col md:flex-row gap-16 pb-7 justify-between">
33+
<div className={clsx(
34+
"bg-background-2 md:pb-7",
35+
"flex flex-col md:flex-row gap-16 justify-between"
36+
)}>
3137
<div className="flex flex-col gap-8 items-start">
3238
<h2 className="text-2xl md:text-3xl font-medium text-primary-text">
3339
{title}
@@ -44,16 +50,23 @@ const ReportCard: React.FC<IReportCard> = ({
4450
/>
4551

4652
<Link href={reportUrl ?? ""} target="_blank" rel="noreferrer noopenner">
47-
<Button variant="primary" className="text-background-1">
53+
<Button
54+
variant="primary"
55+
className="text-background-1"
56+
disabled={typeof reportUrl === "undefined"}
57+
>
4858
{downloadButtonText}
4959
</Button>
5060
</Link>
5161
</div>
5262

53-
<div className="relative w-32 h-32 md:w-56 md:h-56 flex-shrink-0">
63+
<div className={
64+
"relative w-32 h-32 md:w-56 md:h-56 flex-shrink-0 hidden md:block"
65+
}>
5466
<Image src={icon.url} alt={icon.name} fill className="object-contain" />
5567
</div>
5668
</div>
5769
);
5870
};
71+
5972
export default ReportCard;

frontend/src/components/Cooperative/ReportSection/index.tsx

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
1-
import ReportCard from "./ReportCard";
1+
import { useCallback } from "react";
2+
3+
import clsx from "clsx";
24

35
import {
46
CooperativePageReportQueryType,
57
ReportType,
68
} from "@/queries/cooperative/report-section";
79

10+
import ReportCard from "./ReportCard";
11+
812
interface IReportSection {
913
reportsData: CooperativePageReportQueryType;
1014
}
1115

1216
const ReportSection: React.FC<IReportSection> = ({ reportsData }) => {
13-
const getReports = (reportType: ReportType) => {
17+
const getReports = useCallback((reportType: ReportType) => {
1418
switch (reportType) {
1519
case "annual":
1620
return reportsData.annualReports;
@@ -19,9 +23,13 @@ const ReportSection: React.FC<IReportSection> = ({ reportsData }) => {
1923
default:
2024
return reportsData.treasuryReports;
2125
}
22-
};
26+
}, [reportsData]);
27+
2328
return (
24-
<div className="bg-background-2 py-12 lg:py-24 px-6 lg:px-32 flex flex-col gap-24">
29+
<div className={clsx(
30+
"bg-background-2 py-12 lg:py-24 px-6 lg:px-32",
31+
"flex flex-col gap-12 md:gap-24"
32+
)}>
2533
{reportsData.cooperativePageReportSection.reports.map((report, i) => (
2634
<ReportCard
2735
key={i}

frontend/src/components/Cooperative/hero.tsx

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@ import React from "react";
33
import Image from "next/image";
44
import Link from "next/link";
55

6-
import ExternalLink from "../ExternalLink";
7-
86
import Button from "@/components/Button";
7+
import ExternalLink from "@/components/ExternalLink";
98
import { HeroQueryType } from "@/queries/cooperative/hero";
109

1110
interface IHero {
@@ -27,10 +26,7 @@ const Hero: React.FC<IHero> = ({ heroData }) => {
2726
target="_blank"
2827
rel="noopener noreferrer"
2928
>
30-
<Button
31-
variant="secondary"
32-
className=" hover:!bg-primary-blue hover:!border-primary-blue hover:!text-background-2"
33-
>
29+
<Button variant="secondary">
3430
<span>{button.text}</span>
3531
</Button>
3632
</Link>

frontend/src/components/Dropdown/DropdownItemButton.tsx

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,6 @@
11
import clsx from "clsx";
2-
import { DropdownItem } from ".";
32

4-
const dropwdownItemBaseStyle = clsx(
5-
"w-full rounded-lg text-secondary-text text-left py-3 px-4"
6-
);
7-
const selectedStyle = clsx("!text-primary-blue bg-background-2");
8-
const dropdownItemHoverStyle = clsx(
9-
"hover:text-primary-blue hover:bg-background-2 cursor-pointer"
10-
);
3+
import { DropdownItem } from ".";
114

125
interface IDropdownItem {
136
item: DropdownItem;
@@ -21,9 +14,11 @@ const DropdownItemButton: React.FC<IDropdownItem> = ({
2114
}) => (
2215
<button
2316
className={clsx(
24-
dropwdownItemBaseStyle,
25-
dropdownItemHoverStyle,
26-
value === item.value ? selectedStyle : ""
17+
"w-full rounded-lg text-left py-3 px-4",
18+
value === item.value
19+
? "text-primary-blue bg-background-2"
20+
: "text-secondary-text",
21+
"hover:text-primary-blue hover:bg-background-2 cursor-pointer"
2722
)}
2823
onClick={() => handleClick(item.value)}
2924
>

0 commit comments

Comments
 (0)