Skip to content

Commit e1a97c7

Browse files
committed
feat(web): add submit-item wizard
1 parent ee5ea53 commit e1a97c7

File tree

21 files changed

+757
-14
lines changed

21 files changed

+757
-14
lines changed

web/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@
7373
},
7474
"dependencies": {
7575
"@filebase/client": "^0.0.5",
76-
"@kleros/ui-components-library": "^2.6.3",
76+
"@kleros/ui-components-library": "^2.7.1",
7777
"@sentry/react": "^7.93.0",
7878
"@sentry/tracing": "^7.93.0",
7979
"@supabase/supabase-js": "^2.39.3",

web/src/app.tsx

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import RefetchOnBlock from "context/RefetchOnBlock";
1111
import Layout from "layout/index";
1212
import Home from "./pages/Home";
1313
import AllLists from "./pages/AllLists";
14+
import SubmitItem from "./pages/SubmitItem";
15+
import { SubmitItemProvider } from "./context/SubmitItemContext";
1416

1517
const App: React.FC = () => {
1618
return (
@@ -19,13 +21,16 @@ const App: React.FC = () => {
1921
<RefetchOnBlock />
2022
<Web3Provider>
2123
<IsListProvider>
22-
<SentryRoutes>
23-
<Route path="/" element={<Layout />}>
24-
<Route index element={<Home />} />
25-
<Route path="lists/*" element={<AllLists />} />
26-
<Route path="*" element={<h1>404 not found</h1>} />
27-
</Route>
28-
</SentryRoutes>
24+
<SubmitItemProvider>
25+
<SentryRoutes>
26+
<Route path="/" element={<Layout />}>
27+
<Route index element={<Home />} />
28+
<Route path="lists/*" element={<AllLists />} />
29+
<Route path="submitItem/*" element={<SubmitItem />} />
30+
<Route path="*" element={<h1>404 not found</h1>} />
31+
</Route>
32+
</SentryRoutes>
33+
</SubmitItemProvider>
2934
</IsListProvider>
3035
</Web3Provider>
3136
</QueryClientProvider>
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import React, { createContext, useContext, useMemo } from "react";
2+
import { useLocalStorage } from "hooks/useLocalStorage";
3+
4+
export interface ISubmitItemContext {
5+
fieldOne: string;
6+
setFieldOne: (title: string) => void;
7+
resetItemData: () => void;
8+
isPolicyRead: boolean;
9+
setIsPolicyRead: (isRead: boolean) => void;
10+
}
11+
12+
const initialSubmitItemContext: ISubmitItemContext = {
13+
fieldOne: "",
14+
setFieldOne: () => {},
15+
resetItemData: () => {},
16+
isPolicyRead: false,
17+
setIsPolicyRead: () => {},
18+
};
19+
20+
const SubmitItemContext = createContext<ISubmitItemContext>(initialSubmitItemContext);
21+
22+
export const useSubmitItemContext = () => useContext(SubmitItemContext);
23+
24+
export const SubmitItemProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
25+
const [fieldOne, setFieldOne] = useLocalStorage<string>("fieldOne", initialSubmitItemContext.fieldOne);
26+
const [isPolicyRead, setIsPolicyRead] = useLocalStorage<boolean>(
27+
"isPolicyRead",
28+
initialSubmitItemContext.isPolicyRead
29+
);
30+
31+
const resetItemData = () => {
32+
setFieldOne(initialSubmitItemContext.fieldOne);
33+
setIsPolicyRead(initialSubmitItemContext.isPolicyRead);
34+
};
35+
36+
const contextValues = useMemo(
37+
() => ({
38+
fieldOne,
39+
setFieldOne,
40+
resetItemData,
41+
isPolicyRead,
42+
setIsPolicyRead,
43+
}),
44+
[fieldOne, isPolicyRead]
45+
);
46+
47+
return <SubmitItemContext.Provider value={contextValues}>{children}</SubmitItemContext.Provider>;
48+
};

web/src/pages/AllLists/RegistryDetails/Search.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ const Search: React.FC = () => {
8484
defaultValue={1}
8585
callback={() => {}}
8686
/>
87-
<Button Icon={StyledPlusIcon} text="Submit Item" />
87+
<Button Icon={StyledPlusIcon} text="Submit Item" onClick={() => navigate("/submitItem")} />
8888
</Container>
8989
);
9090
};
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
import React from "react";
2+
import styled, { css } from "styled-components";
3+
import { landscapeStyle } from "styles/landscapeStyle";
4+
import { responsiveSize } from "styles/responsiveSize";
5+
import { Card } from "@kleros/ui-components-library";
6+
import GnosisIcon from "svgs/chains/gnosis.svg";
7+
import PileCoinsIcon from "svgs/icons/pile-coins.svg";
8+
9+
const Container = styled.div`
10+
display: flex;
11+
justify-content: center;
12+
`;
13+
14+
const StyledCard = styled(Card)`
15+
display: flex;
16+
margin-top: 60px;
17+
margin-bottom: ${responsiveSize(36, 36)};
18+
padding: 24px ${responsiveSize(24, 32)};
19+
width: 80vw;
20+
height: auto;
21+
justify-content: space-between;
22+
gap: 24px;
23+
flex-wrap: wrap;
24+
25+
${landscapeStyle(
26+
() => css`
27+
width: 91vw;
28+
`
29+
)}
30+
`;
31+
32+
const LeftContent = styled.div`
33+
display: flex;
34+
gap: 8px;
35+
flex-wrap: wrap;
36+
`;
37+
38+
const Title = styled.p`
39+
font-size: 24px;
40+
font-weight: 600;
41+
margin: 0;
42+
color: ${({ theme }) => theme.primaryText};
43+
`;
44+
45+
const ListName = styled.p`
46+
font-size: 24px;
47+
font-weight: 600;
48+
margin: 0;
49+
color: ${({ theme }) => theme.secondaryPurple};
50+
`;
51+
52+
const RightContent = styled.div`
53+
display: flex;
54+
gap: 16px 48px;
55+
align-items: center;
56+
flex-wrap: wrap;
57+
`;
58+
59+
const DepositRequired = styled.div`
60+
display: flex;
61+
flex-wrap: wrap;
62+
63+
svg {
64+
fill: ${({ theme }) => theme.secondaryPurple};
65+
margin-right: 8px;
66+
width: 16px;
67+
}
68+
`;
69+
70+
const StyledP = styled.p`
71+
margin: 0;
72+
color: ${({ theme }) => theme.primaryText};
73+
`;
74+
75+
const Amount = styled.p`
76+
margin: 0;
77+
`;
78+
79+
const Chain = styled.div`
80+
display: flex;
81+
flex-direction: row;
82+
83+
svg {
84+
margin-right: 8px;
85+
width: 24px;
86+
}
87+
`;
88+
89+
interface IHeader {}
90+
91+
const Header: React.FC<IHeader> = ({}) => {
92+
return (
93+
<Container>
94+
<StyledCard>
95+
<LeftContent>
96+
<Title>Submit Item to</Title>
97+
<ListName>Address Tags List</ListName>
98+
</LeftContent>
99+
<RightContent>
100+
<DepositRequired>
101+
<PileCoinsIcon />
102+
<StyledP>Deposit required:&nbsp;</StyledP>
103+
<Amount>0.003 ETH</Amount>
104+
</DepositRequired>
105+
<Chain>
106+
<GnosisIcon />
107+
<StyledP>Gnosis</StyledP>
108+
</Chain>
109+
</RightContent>
110+
</StyledCard>
111+
</Container>
112+
);
113+
};
114+
115+
export default Header;
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import React from "react";
2+
import styled, { css } from "styled-components";
3+
import { landscapeStyle } from "styles/landscapeStyle";
4+
import { responsiveSize } from "styles/responsiveSize";
5+
import { Field } from "@kleros/ui-components-library";
6+
import { useSubmitItemContext } from "context/SubmitItemContext";
7+
import Title from "../Title";
8+
import NavigationButtons from "../NavigationButtons";
9+
10+
const Container = styled.div`
11+
display: flex;
12+
flex-direction: column;
13+
align-items: center;
14+
`;
15+
16+
const StyledField = styled(Field)`
17+
width: 80vw;
18+
margin-bottom: ${responsiveSize(68, 40)};
19+
20+
input {
21+
font-size: 16px;
22+
}
23+
24+
small {
25+
margin-top: 6px;
26+
svg {
27+
margin-top: 8px;
28+
}
29+
}
30+
31+
${landscapeStyle(
32+
() => css`
33+
width: ${responsiveSize(200, 720)};
34+
`
35+
)};
36+
`;
37+
38+
const ItemField: React.FC = () => {
39+
const { fieldOne, setFieldOne } = useSubmitItemContext();
40+
41+
const handleWrite = (event: React.ChangeEvent<HTMLInputElement>) => {
42+
setFieldOne(event.target.value);
43+
};
44+
45+
return (
46+
<Container>
47+
<Title text="Item Field 1" />
48+
<StyledField
49+
value={fieldOne}
50+
onChange={handleWrite}
51+
variant={"info"}
52+
message={"Item Field 1 description requirements go here"}
53+
/>
54+
<NavigationButtons prevRoute="/lists/1/list/1/desc/all" nextRoute="/submitItem/policy" />
55+
</Container>
56+
);
57+
};
58+
59+
export default ItemField;
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import React from "react";
2+
import { Button } from "@kleros/ui-components-library";
3+
import { useLocation, useNavigate } from "react-router-dom";
4+
import { useSubmitItemContext } from "context/SubmitItemContext";
5+
6+
interface INextButton {
7+
nextRoute: string;
8+
}
9+
10+
const NextButton: React.FC<INextButton> = ({ nextRoute }) => {
11+
const navigate = useNavigate();
12+
const { fieldOne, isPolicyRead } = useSubmitItemContext();
13+
const location = useLocation();
14+
15+
const isButtonDisabled =
16+
(location.pathname.includes("/submitItem/itemField1") && !fieldOne) ||
17+
(location.pathname.includes("/submitItem/policy") && !isPolicyRead);
18+
19+
return <Button disabled={isButtonDisabled} onClick={() => navigate(nextRoute)} text="Next" />;
20+
};
21+
22+
export default NextButton;
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import React from "react";
2+
import styled from "styled-components";
3+
import { Button } from "@kleros/ui-components-library";
4+
import { useNavigate } from "react-router-dom";
5+
6+
const StyledButton = styled(Button)<{ prevRoute: string }>`
7+
display: ${({ prevRoute }) => (prevRoute === "" ? "none" : "flex")};
8+
`;
9+
10+
interface IReturnButton {
11+
prevRoute: string;
12+
}
13+
14+
const ReturnButton: React.FC<IReturnButton> = ({ prevRoute }) => {
15+
const navigate = useNavigate();
16+
17+
return (
18+
<StyledButton
19+
prevRoute={prevRoute}
20+
onClick={() => navigate(prevRoute)}
21+
text="Return"
22+
variant="secondary"
23+
></StyledButton>
24+
);
25+
};
26+
27+
export default ReturnButton;

0 commit comments

Comments
 (0)