Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat(web)/dispute details page #309

Merged
merged 20 commits into from
Sep 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
874e1d1
feat(web): add dispute overview page and routing
alcercu Sep 21, 2022
def60d1
chore: update kleros ui components and add react skeleton
alcercu Sep 26, 2022
ba3c50b
feat(web, wip): add tabs to dispute details page
alcercu Sep 26, 2022
90ab2dc
feat(web, wip): add evidence tab to dispute details page
alcercu Sep 26, 2022
05140c7
feat(web, wip): improve evidence showing
alcercu Sep 27, 2022
53940b4
fix(web): fix current period index on disputes without hidden votes
alcercu Sep 27, 2022
9634539
feat(web, wip): add policy to dispute overview, fix voting bug
alcercu Sep 27, 2022
f450cb3
fix(web): fix broken links to court and dispute policy
alcercu Sep 27, 2022
ca0618f
chore(web): remove console.log
alcercu Sep 27, 2022
32d4e3e
fix(web): spelling mistake
alcercu Sep 27, 2022
8e070df
feat(web, wip): add details to dispute overview
alcercu Sep 27, 2022
f7e2252
fix(web): correctly check undefined on DisputeInfo for period
alcercu Sep 28, 2022
772c802
fix(web): allow undefined value for props Overview page
alcercu Sep 28, 2022
af0a355
feat(web): correctly set active tab when path changes
alcercu Sep 28, 2022
528caef
feat(web): add loading animation to switch chain page
alcercu Sep 28, 2022
13ea657
feat(web): implement refuse to arbitrate
alcercu Sep 28, 2022
ab390bf
feat(web): improve timeline titles and subtitles
alcercu Sep 28, 2022
06f0ca5
feat(web): add PNK contract to getContract
alcercu Sep 28, 2022
fac2d9e
fix(web): change court policy link
alcercu Sep 28, 2022
9e802ba
fix: lock file
jaybuidl Sep 30, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@
"@graphql-codegen/typescript": "^2.7.3",
"@graphql-codegen/typescript-operations": "^2.5.3",
"@kleros/kleros-v2-contracts": "workspace:^",
"@kleros/ui-components-library": "^1.7.0",
"@kleros/ui-components-library": "^1.8.1",
"@types/react-modal": "^3.13.1",
"@web3-react/core": "^6.1.9",
"@web3-react/injected-connector": "^6.0.7",
"@web3-react/types": "^6.0.7",
Expand All @@ -74,7 +75,10 @@
"react-dom": "^18.2.0",
"react-error-boundary": "^3.1.4",
"react-is": "^18.2.0",
"react-router-dom": "6",
"react-jazzicon": "^1.0.4",
"react-loading-skeleton": "^3.1.0",
"react-modal": "^3.15.1",
"react-router-dom": "^6.4.0",
"styled-components": "^5.3.5",
"swr": "^1.3.0"
}
Expand Down
5 changes: 3 additions & 2 deletions web/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from "react";
import { SWRConfig } from "swr";
import { request } from "graphql-request";
import { Routes, Route } from "react-router-dom";
import "react-loading-skeleton/dist/skeleton.css";
import Web3Provider from "context/Web3Provider";
import StyledComponentsProvider from "context/StyledComponentsProvider";
import WrongChainBoundary from "components/WrongChainBoundary";
Expand All @@ -13,7 +14,7 @@ import Dashboard from "./pages/Dashboard";
const fetcherBuilder =
(url: string) =>
({ query, variables }: { query: string; variables?: any }) => {
console.log("fetch");
console.log("fetching subgraph");
return request(url, query, variables);
};

Expand All @@ -32,7 +33,7 @@ const App: React.FC = () => {
<Routes>
<Route path="/" element={<Layout />}>
<Route index element={<Home />} />
<Route path="cases" element={<Cases />} />
<Route path="cases/*" element={<Cases />} />
<Route path="courts" element={<h1>Courts</h1>} />
<Route path="dashboard" element={<Dashboard />} />
<Route
Expand Down
10 changes: 10 additions & 0 deletions web/src/assets/svgs/icons/attachment.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions web/src/assets/svgs/icons/bullhorn.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions web/src/assets/svgs/icons/doc.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions web/src/assets/svgs/icons/eye.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions web/src/assets/svgs/icons/policy.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
59 changes: 26 additions & 33 deletions web/src/components/CasesDisplay/CasesGrid.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from "react";
import styled from "styled-components";
import { StandardPagination } from "@kleros/ui-components-library";
import { CasesPageQuery } from "queries/useCasesQuery";
import DisputeCard from "components/DisputeCard";

const Container = styled.div`
Expand All @@ -18,42 +19,34 @@ const StyledPagination = styled(StandardPagination)`
`;

export interface ICasesGrid {
disputes: CasesPageQuery["disputes"];
currentPage: number;
setCurrentPage: (newPage: number) => void;
numberDisputes: number;
casesPerPage: number;
}

const CasesGrid: React.FC<ICasesGrid> = ({ casesPerPage }) => (
<>
<Container>
<DisputeCard
title="Register Profile in Proof of Humanity"
id={600}
period={1}
court="Humanity"
category="Identity"
rewards="≥ 0.3 ETH"
date={1651244935}
const CasesGrid: React.FC<ICasesGrid> = ({
disputes,
currentPage,
setCurrentPage,
numberDisputes,
casesPerPage,
}) => {
return (
<>
<Container>
{disputes.map((dispute, i) => {
return <DisputeCard key={i} {...dispute} />;
})}
</Container>
<StyledPagination
{...{ currentPage }}
numPages={Math.ceil(numberDisputes / casesPerPage)}
callback={(page: number) => setCurrentPage(page)}
/>
<DisputeCard
title="Register Profile in Proof of Humanity"
id={600}
period={3}
court="Humanity"
category="Identity"
rewards="≥ 0.3 ETH"
date={1651244935}
/>
<DisputeCard
title="Register Profile in Proof of Humanity"
id={600}
period={4}
court="Humanity"
category="Identity"
rewards="≥ 0.3 ETH"
date={1651244935}
/>
</Container>
<StyledPagination currentPage={1} numPages={1} callback={() => {}} />
</>
);
</>
);
};

export default CasesGrid;
14 changes: 13 additions & 1 deletion web/src/components/CasesDisplay/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ interface ICasesDisplay extends ICasesGrid {
}

const CasesDisplay: React.FC<ICasesDisplay> = ({
disputes,
currentPage,
setCurrentPage,
numberDisputes,
casesPerPage,
title = "Cases",
className,
Expand All @@ -24,7 +28,15 @@ const CasesDisplay: React.FC<ICasesDisplay> = ({
<Search />
<StatsAndFilters />
<StyledHR />
<CasesGrid {...{ casesPerPage }} />
<CasesGrid
{...{
disputes,
currentPage,
setCurrentPage,
numberDisputes,
casesPerPage,
}}
/>
</div>
);

Expand Down
36 changes: 21 additions & 15 deletions web/src/components/DisputeCard/DisputeInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,21 +45,23 @@ const Container = styled.div`

const getPeriodPhrase = (period: Periods) => {
switch (period) {
case Periods.appeal:
case Periods.Evidence:
return "Voting Starts";
case Periods.Appeal:
return "Appeal Deadline";
case Periods.execution:
case Periods.Execution:
return "Final Decision";
default:
return "Voting Deadline";
}
};

export interface IDisputeInfo {
court: string;
category: string;
rewards: string;
period: Periods;
date: number;
court?: string;
category?: string;
rewards?: string;
period?: Periods;
date?: number;
}

const DisputeInfo: React.FC<IDisputeInfo> = ({
Expand All @@ -70,14 +72,18 @@ const DisputeInfo: React.FC<IDisputeInfo> = ({
date,
}) => (
<Container>
<Field icon={LawBalanceIcon} name="Court" value={court} />
<Field icon={BookmarkIcon} name="Category" value={category} />
<Field icon={PileCoinsIcon} name="Juror Rewards" value={rewards} />
<Field
icon={CalendarIcon}
name={getPeriodPhrase(period)}
value={new Date(date * 1000).toLocaleString()}
/>
{category && <Field icon={BookmarkIcon} name="Category" value={category} />}
{court && <Field icon={LawBalanceIcon} name="Court" value={court} />}
{rewards && (
<Field icon={PileCoinsIcon} name="Juror Rewards" value={rewards} />
)}
{typeof period !== "undefined" && date && (
<Field
icon={CalendarIcon}
name={getPeriodPhrase(period)}
value={new Date(date * 1000).toLocaleString()}
/>
)}
</Container>
);

Expand Down
8 changes: 4 additions & 4 deletions web/src/components/DisputeCard/PeriodBanner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ export interface IPeriodBanner {

const getPeriodColors = (period: Periods, theme: Theme): [string, string] => {
switch (period) {
case Periods.appeal:
case Periods.Appeal:
return [theme.tint, theme.tintMedium];
case Periods.execution:
case Periods.Execution:
return [theme.secondaryPurple, theme.mediumPurple];
default:
return [theme.primaryBlue, theme.mediumBlue];
Expand Down Expand Up @@ -56,9 +56,9 @@ const Container = styled.div<Omit<IPeriodBanner, "id">>`

const getPeriodLabel = (period: Periods) => {
switch (period) {
case Periods.appeal:
case Periods.Appeal:
return "Crowdfunding Appeal";
case Periods.execution:
case Periods.Execution:
return "Closed";
default:
return "In Progress";
Expand Down
74 changes: 54 additions & 20 deletions web/src/components/DisputeCard/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
import React from "react";
import styled from "styled-components";
import { useNavigate } from "react-router-dom";
import { utils } from "ethers";
import Skeleton from "react-loading-skeleton";
import { Card } from "@kleros/ui-components-library";
import PeriodBanner, { IPeriodBanner } from "./PeriodBanner";
import DisputeInfo, { IDisputeInfo } from "./DisputeInfo";
import { Periods } from "consts/periods";
import { useGetMetaEvidence } from "queries/useGetMetaEvidence";
import { useCourtPolicy } from "queries/useCourtPolicy";
import { useIPFSQuery } from "hooks/useIPFSQuery";
import { CasesPageQuery } from "queries/useCasesQuery";
import PeriodBanner from "./PeriodBanner";
import DisputeInfo from "./DisputeInfo";

const StyledCard = styled(Card)`
max-width: 380px;
Expand All @@ -22,26 +30,52 @@ const Container = styled.div`
}
`;

interface IDisputeCard extends IPeriodBanner, Omit<IDisputeInfo, "period"> {
title: string;
}
const getTimeLeft = (
lastPeriodChange: string,
currentPeriodIndex: number,
timesPerPeriod: string[]
) => {
const durationCurrentPeriod = parseInt(timesPerPeriod[currentPeriodIndex]);
return parseInt(lastPeriodChange) + durationCurrentPeriod;
};

const DisputeCard: React.FC<IDisputeCard> = ({
const DisputeCard: React.FC<CasesPageQuery["disputes"][number]> = ({
id,
arbitrated,
period,
title,
court,
category,
rewards,
date,
}) => (
<StyledCard>
<PeriodBanner {...{ id, period }} />
<Container>
<h3>{title}</h3>
<DisputeInfo {...{ court, category, rewards, period, date }} />
</Container>
</StyledCard>
);
lastPeriodChange,
subcourtID,
}) => {
const currentPeriodIndex = Periods[period];
const rewards = `≥ ${utils.formatEther(subcourtID.feeForJuror)} ETH`;
const date =
currentPeriodIndex === 4
? lastPeriodChange
: getTimeLeft(
lastPeriodChange,
currentPeriodIndex,
subcourtID.timesPerPeriod
);
const { data: metaEvidence } = useGetMetaEvidence(id, arbitrated);
const title = metaEvidence ? metaEvidence.title : <Skeleton />;
const { data: courtPolicyPath } = useCourtPolicy(parseInt(subcourtID.id));
const { data: courtPolicy } = useIPFSQuery(courtPolicyPath?.args._policy);
const courtName = courtPolicy?.name;
const category = metaEvidence ? metaEvidence.category : undefined;
const navigate = useNavigate();
return (
<StyledCard hover onClick={() => navigate(`/cases/${id.toString()}`)}>
<PeriodBanner id={parseInt(id)} period={currentPeriodIndex} />
<Container>
<h3>{title}</h3>
<DisputeInfo
court={courtName}
period={currentPeriodIndex}
{...{ category, rewards, date }}
/>
</Container>
</StyledCard>
);
};

export default DisputeCard;
Loading