Skip to content

Commit 9734d2d

Browse files
committed
feat(web): header-and-stat-ui
1 parent db457ac commit 9734d2d

File tree

6 files changed

+232
-1
lines changed

6 files changed

+232
-1
lines changed
Lines changed: 10 additions & 0 deletions
Loading
Lines changed: 10 additions & 0 deletions
Loading

web/src/components/StatDisplay.tsx

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import React, { useMemo } from "react";
2+
import { landscapeStyle } from "styles/landscapeStyle";
3+
import styled, { useTheme, css } from "styled-components";
4+
import { responsiveSize } from "styles/responsiveSize";
5+
import { Theme } from "styled-components";
6+
7+
const Container = styled.div`
8+
display: flex;
9+
max-width: 196px;
10+
align-items: center;
11+
gap: 8px;
12+
13+
${landscapeStyle(
14+
() => css`
15+
margin-bottom: ${responsiveSize(16, 30)};
16+
`
17+
)}
18+
`;
19+
20+
const SVGContainer = styled.div<{ iconColor: string; backgroundColor: string }>`
21+
height: 48px;
22+
width: 48px;
23+
border-radius: 50%;
24+
background-color: ${({ backgroundColor }) => backgroundColor};
25+
display: flex;
26+
align-items: center;
27+
justify-content: center;
28+
svg {
29+
fill: ${({ iconColor }) => iconColor};
30+
height: 21px;
31+
width: 21px;
32+
}
33+
`;
34+
35+
const TextContainer = styled.div`
36+
h1 {
37+
margin: 0;
38+
}
39+
`;
40+
41+
const SubtextLabel = styled.label`
42+
font-size: 12px;
43+
`;
44+
45+
const COLORS: Record<string, Array<keyof Theme>> = {
46+
green: ["success", "successLight"],
47+
blue: ["primaryBlue", "mediumBlue"],
48+
purple: ["secondaryPurple", "mediumPurple"],
49+
orange: ["warning", "warningLight"],
50+
};
51+
52+
export type IColors = keyof typeof COLORS;
53+
54+
interface IStatDisplay {
55+
title: string;
56+
text: string | React.ReactNode;
57+
subtext: string | React.ReactNode;
58+
icon: React.FunctionComponent<React.SVGAttributes<SVGElement>>;
59+
color: IColors;
60+
}
61+
62+
const StatDisplay: React.FC<IStatDisplay> = ({ title, text, subtext, icon: Icon, color, ...props }) => {
63+
const theme = useTheme();
64+
65+
const [iconColor, backgroundColor] = useMemo(() => {
66+
return COLORS[color].map((color) => theme[color]);
67+
}, [theme, color]);
68+
69+
return (
70+
<Container {...props}>
71+
<SVGContainer {...{ iconColor, backgroundColor }}>{<Icon />}</SVGContainer>
72+
<TextContainer>
73+
<label>{title}</label>
74+
<h1>{text}</h1>
75+
<SubtextLabel>{subtext}</SubtextLabel>
76+
</TextContainer>
77+
</Container>
78+
);
79+
};
80+
81+
export default StatDisplay;

web/src/pages/Home/Header.tsx

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import React, { useEffect, useState } from "react";
2+
import styled from "styled-components";
3+
import { responsiveSize } from "styles/responsiveSize";
4+
5+
const StyledHeader = styled.div`
6+
display: flex;
7+
justify-content: space-between;
8+
`;
9+
10+
const StyledH1 = styled.h1`
11+
font-size: ${responsiveSize(21, 24)};
12+
font-weight: 500;
13+
margin-bottom: 48px;
14+
letter-spacing: 1px;
15+
`;
16+
17+
const StyledSpan = styled.span`
18+
color: ${({ theme }) => theme.secondaryPurple};
19+
`;
20+
21+
const Header: React.FC = () => {
22+
const [currentWordIndex, setCurrentWordIndex] = useState(0);
23+
const words = ["Lists", "Knowledge"];
24+
25+
useEffect(() => {
26+
const intervalId = setInterval(() => {
27+
setCurrentWordIndex((prevIndex) => (prevIndex === 0 ? 1 : 0));
28+
}, 3000);
29+
30+
return () => clearInterval(intervalId);
31+
}, []);
32+
33+
return (
34+
<StyledHeader>
35+
<StyledH1>
36+
Community Curated <StyledSpan>{words[currentWordIndex]}</StyledSpan>
37+
</StyledH1>
38+
</StyledHeader>
39+
);
40+
};
41+
42+
export default Header;

web/src/pages/Home/Stats/index.tsx

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import React from "react";
2+
import styled, { css } from "styled-components";
3+
import { landscapeStyle } from "styles/landscapeStyle";
4+
import { Card } from "@kleros/ui-components-library";
5+
import StatDisplay, { IColors } from "components/StatDisplay";
6+
import PaperIcon from "svgs/icons/paper.svg";
7+
import ListIcon from "svgs/icons/list.svg";
8+
import DollarIcon from "svgs/icons/dollar.svg";
9+
import JurorIcon from "svgs/icons/user.svg";
10+
import { responsiveSize } from "styles/responsiveSize";
11+
12+
const StyledCard = styled(Card)`
13+
width: auto;
14+
height: fit-content;
15+
gap: 32px;
16+
padding: ${responsiveSize(16, 30)};
17+
padding-left: ${responsiveSize(16, 54)};
18+
padding-bottom: 16px;
19+
display: grid;
20+
grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
21+
22+
${landscapeStyle(
23+
() => css`
24+
padding-bottom: 0px;
25+
gap: 0px;
26+
`
27+
)}
28+
`;
29+
30+
interface IStat {
31+
title: string;
32+
coinId?: number;
33+
text: string;
34+
subtext: string;
35+
color: IColors;
36+
icon: React.FC<React.SVGAttributes<SVGElement>>;
37+
}
38+
39+
const stats: IStat[] = [
40+
{
41+
title: "Total",
42+
coinId: 0,
43+
text: "25 Lists",
44+
subtext: "in 3 Networks",
45+
color: "purple",
46+
icon: PaperIcon,
47+
},
48+
{
49+
title: "Total",
50+
coinId: 1,
51+
text: "345 Items",
52+
subtext: "Curated",
53+
color: "blue",
54+
icon: ListIcon,
55+
},
56+
{
57+
title: "All time deposits",
58+
coinId: 0,
59+
text: "$124,000",
60+
subtext: "100 ETH",
61+
color: "green",
62+
icon: DollarIcon,
63+
},
64+
{
65+
title: "Curators",
66+
text: "54",
67+
subtext: "36 active",
68+
color: "orange",
69+
icon: JurorIcon,
70+
},
71+
];
72+
73+
const Stats = () => {
74+
return (
75+
<StyledCard>
76+
{stats.map(({ title, coinId, text, subtext, color, icon }, i) => {
77+
return <StatDisplay key={i} {...{ title, color, icon, text, subtext }} />;
78+
})}
79+
</StyledCard>
80+
);
81+
};
82+
83+
export default Stats;

web/src/pages/Home/index.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import React from "react";
22
import styled from "styled-components";
33
import HeroImage from "components/HeroImage";
44
import { responsiveSize } from "styles/responsiveSize";
5+
import Header from "./Header";
6+
import Stats from "./Stats";
57

68
const Container = styled.div`
79
width: 100%;
@@ -15,7 +17,10 @@ const Home: React.FC = () => {
1517
return (
1618
<>
1719
<HeroImage />
18-
<Container>Home</Container>
20+
<Container>
21+
<Header />
22+
<Stats />
23+
</Container>
1924
</>
2025
);
2126
};

0 commit comments

Comments
 (0)