Skip to content

Commit

Permalink
feat(web): cases-grid-and-list-display
Browse files Browse the repository at this point in the history
  • Loading branch information
nhestrompia committed Sep 6, 2023
1 parent 6b6eaf4 commit caafd1d
Show file tree
Hide file tree
Showing 16 changed files with 345 additions and 62 deletions.
23 changes: 13 additions & 10 deletions web/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import "react-toastify/dist/ReactToastify.css";
import Web3Provider from "context/Web3Provider";
import QueryClientProvider from "context/QueryClientProvider";
import StyledComponentsProvider from "context/StyledComponentsProvider";
import { FilterProvider } from "context/FilterProvider";
import RefetchOnBlock from "context/RefetchOnBlock";
import Layout from "layout/index";
import Home from "./pages/Home";
Expand All @@ -20,16 +21,18 @@ const App: React.FC = () => {
<QueryClientProvider>
<RefetchOnBlock />
<Web3Provider>
<SentryRoutes>
<Route path="/" element={<Layout />}>
<Route index element={<Home />} />
<Route path="cases/*" element={<Cases />} />
<Route path="courts/*" element={<Courts />} />
<Route path="dashboard" element={<Dashboard />} />
<Route path="disputeTemplate" element={<DisputeTemplateView />} />
<Route path="*" element={<h1>Justice not found here ¯\_( ͡° ͜ʖ ͡°)_/¯</h1>} />
</Route>
</SentryRoutes>
<FilterProvider>
<SentryRoutes>
<Route path="/" element={<Layout />}>
<Route index element={<Home />} />
<Route path="cases/*" element={<Cases />} />
<Route path="courts/*" element={<Courts />} />
<Route path="dashboard" element={<Dashboard />} />
<Route path="disputeTemplate" element={<DisputeTemplateView />} />
<Route path="*" element={<h1>Justice not found here ¯\_( ͡° ͜ʖ ͡°)_/¯</h1>} />
</Route>
</SentryRoutes>
</FilterProvider>
</Web3Provider>
</QueryClientProvider>
</StyledComponentsProvider>
Expand Down
3 changes: 3 additions & 0 deletions web/src/assets/svgs/icons/grid.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/list.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
41 changes: 33 additions & 8 deletions web/src/components/CasesDisplay/CasesGrid.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,27 @@
import React from "react";
import styled from "styled-components";
import styled, { css } from "styled-components";
import { StandardPagination } from "@kleros/ui-components-library";
import { smallScreenStyle } from "styles/smallScreenStyle";
import { useFiltersContext } from "context/FilterProvider";
import { CasesPageQuery } from "queries/useCasesQuery";
import DisputeCard from "components/DisputeCard";
import CasesListHeader from "./CasesListHeader";

const Container = styled.div`
const GridContainer = styled.div`
display: grid;
gap: 16px;
grid-template-columns: repeat(3, minmax(50px, 1fr));
justify-content: center;
align-items: center;
gap: 8px;
${smallScreenStyle(css`
display: flex;
flex-wrap: wrap;
`)}
`;
const ListContainer = styled.div`
display: flex;
flex-wrap: wrap;
flex-direction: column;
justify-content: center;
gap: 8px;
`;
Expand All @@ -26,13 +41,23 @@ export interface ICasesGrid {
}

const CasesGrid: React.FC<ICasesGrid> = ({ disputes, currentPage, setCurrentPage, numberDisputes, casesPerPage }) => {
const { isList } = useFiltersContext();
return (
<>
<Container>
{disputes.map((dispute, i) => {
return <DisputeCard key={i} {...dispute} />;
})}
</Container>
{!isList ? (
<GridContainer>
{disputes.map((dispute, i) => {
return <DisputeCard key={i} {...dispute} />;
})}
</GridContainer>
) : (
<ListContainer>
{isList && <CasesListHeader />}
{disputes.map((dispute, i) => {
return <DisputeCard key={i} {...dispute} />;
})}
</ListContainer>
)}
<StyledPagination
{...{ currentPage }}
numPages={Math.ceil(numberDisputes / casesPerPage)}
Expand Down
79 changes: 79 additions & 0 deletions web/src/components/CasesDisplay/CasesListHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import React from "react";
import styled, { css } from "styled-components";
import { smallScreenStyle } from "styles/smallScreenStyle";
import WithHelpTooltip from "pages/Dashboard/WithHelpTooltip";

const Container = styled.div`
display: flex;
flex-direction: row;
justify-content: space-between;
gap: 40vw;
width: 100%;
`;

const CasesData = styled.div`
display: flex;
align-items: center;
width: 100%;
gap: 48px;
flex-wrap: wrap;
padding: 0 4%;
justify-content: space-between;
${smallScreenStyle(css`
margin-left: calc(0px + (33) * (100vw - 370px) / (1250 - 370));
gap: 12px;
`)}
`;

const CategoryLabel = styled.label`
margin-left: 32px;
`;

const RewardsContainer = styled.div`
margin-right: -16px;
`;

const CaseTitle = styled.div`
display: flex;
margin-left: 32px;
gap: 36px;
label {
font-weight: 400;
font-size: 14px;
line-height: 19px;
color: ${({ theme }) => theme.secondaryText} !important;
}
${smallScreenStyle(css`
display: none;
`)}
`;

const tooltipMsg =
"Users have an economic interest in serving as jurors in Kleros: " +
"collecting the Juror Rewards in exchange for their work. Each juror who " +
"is coherent with the final ruling receive the Juror Rewards composed of " +
"arbitration fees (ETH) + PNK redistribution between jurors.";

const CasesListHeader: React.FC = () => {
return (
<Container>
<CaseTitle>
<label>#</label>
<label>Title</label>
</CaseTitle>
<CasesData>
<label>Court</label>
<CategoryLabel>Category</CategoryLabel>
<RewardsContainer>
<WithHelpTooltip place="top" {...{ tooltipMsg }}>
<label> Rewards: </label>
</WithHelpTooltip>
</RewardsContainer>
<label>Next Deadline</label>
</CasesData>
</Container>
);
};

export default CasesListHeader;
32 changes: 32 additions & 0 deletions web/src/components/CasesDisplay/Filters.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import React from "react";
import styled, { useTheme } from "styled-components";
import { DropdownSelect } from "@kleros/ui-components-library";
import { useFiltersContext } from "context/FilterProvider";
import ListIcon from "svgs/icons/list.svg";
import GridIcon from "svgs/icons/grid.svg";

const Container = styled.div`
display: flex;
Expand All @@ -9,8 +12,33 @@ const Container = styled.div`
width: fit-content;
`;

const StyledGridIcon = styled(GridIcon)<{ isList: boolean }>`
cursor: pointer;
transition: fill 0.2s ease;
fill: ${({ theme, isList }) => (isList ? theme.secondaryText : theme.primaryBlue)};
width: 16px;
height: 16px;
`;

const IconsContainer = styled.div`
display: flex;
justify-content: center;
align-items: center;
gap: 4px;
`;

const StyledListIcon = styled(ListIcon)<{ isList: boolean }>`
cursor: pointer;
transition: fill 0.2s ease;
fill: ${({ theme, isList }) => (isList ? theme.primaryBlue : theme.secondaryText)};
width: 16px;
height: 17px;
`;

const Filters: React.FC = () => {
const theme = useTheme();
const { isList, setIsList } = useFiltersContext();

return (
<Container>
<DropdownSelect
Expand All @@ -35,6 +63,10 @@ const Filters: React.FC = () => {
defaultValue={0}
callback={() => {}}
/>
<IconsContainer>
<StyledGridIcon isList={isList} onClick={() => setIsList(false)} />
<StyledListIcon isList={isList} onClick={() => setIsList(true)} />
</IconsContainer>
</Container>
);
};
Expand Down
37 changes: 28 additions & 9 deletions web/src/components/DisputeCard/DisputeInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,14 @@ import LawBalanceIcon from "svgs/icons/law-balance.svg";
import PileCoinsIcon from "svgs/icons/pile-coins.svg";
import Field from "../Field";

const Container = styled.div`
const Container = styled.div<{ isCard: boolean }>`
display: flex;
flex-direction: column;
gap: 8px;
flex-direction: ${({ isCard }) => (isCard ? "column" : "row")};
gap: ${({ isCard }) => (isCard ? "8px" : "48px")};
justify-content: ${({ isCard }) => (isCard ? "center" : "space-between")};
align-items: center;
width: 100%;
height: 100%;
`;

const getPeriodPhrase = (period: Periods): string => {
Expand All @@ -33,16 +37,31 @@ export interface IDisputeInfo {
rewards?: string;
period?: Periods;
date?: number;
isCard?: boolean;
}

const DisputeInfo: React.FC<IDisputeInfo> = ({ courtId, court, category, rewards, period, date }) => {
const formatDate = (date: number) => {
const options: Intl.DateTimeFormatOptions = { year: "numeric", month: "long", day: "numeric" };
const startingDate = new Date(date * 1000);
const formattedDate = startingDate.toLocaleDateString("en-US", options);
return formattedDate;
};

const DisputeInfo: React.FC<IDisputeInfo> = ({ courtId, court, category, rewards, period, date, isCard = true }) => {
return (
<Container>
{category && <Field icon={BookmarkIcon} name="Category" value={category} />}
{court && courtId && <Field icon={LawBalanceIcon} name="Court" value={court} link={`/courts/${courtId}`} />}
{rewards && <Field icon={PileCoinsIcon} name="Juror Rewards" value={rewards} />}
<Container isCard={isCard}>
{court && courtId && (
<Field isCard={false} icon={LawBalanceIcon} name="Court" value={court} link={`/courts/${courtId}`} />
)}
{category && <Field isCard={false} icon={BookmarkIcon} name="Category" value={category} />}
{rewards && <Field isCard={false} icon={PileCoinsIcon} name="Juror Rewards" value={rewards} />}
{typeof period !== "undefined" && date && (
<Field icon={CalendarIcon} name={getPeriodPhrase(period)} value={new Date(date * 1000).toLocaleString()} />
<Field
isCard={false}
icon={CalendarIcon}
name={getPeriodPhrase(period)}
value={isCard ? new Date(date * 1000).toLocaleString() : formatDate(date)}
/>
)}
</Container>
);
Expand Down
15 changes: 8 additions & 7 deletions web/src/components/DisputeCard/PeriodBanner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import styled, { Theme } from "styled-components";
import { Periods } from "consts/periods";

const Container = styled.div<Omit<IPeriodBanner, "id">>`
height: 45px;
height: ${({ isCard }) => (isCard ? "45px" : "100%")};
width: auto;
border-top-right-radius: 3px;
border-top-left-radius: 3px;
Expand All @@ -21,11 +21,11 @@ const Container = styled.div<Omit<IPeriodBanner, "id">>`
margin-right: 8px;
}
}
${({ theme, period }) => {
${({ theme, period, isCard }) => {
const [frontColor, backgroundColor] = getPeriodColors(period, theme);
return `
border-top: 5px solid ${frontColor};
background-color: ${backgroundColor};
${isCard ? `border-top: 5px solid ${frontColor}` : `border-left: 5px solid ${frontColor}`};
${isCard && `background-color: ${backgroundColor}`};
.front-color {
color: ${frontColor};
}
Expand All @@ -41,6 +41,7 @@ const Container = styled.div<Omit<IPeriodBanner, "id">>`
export interface IPeriodBanner {
id: number;
period: Periods;
isCard?: boolean;
}

const getPeriodColors = (period: Periods, theme: Theme): [string, string] => {
Expand All @@ -65,9 +66,9 @@ const getPeriodLabel = (period: Periods): string => {
}
};

const PeriodBanner: React.FC<IPeriodBanner> = ({ id, period }) => (
<Container {...{ period }}>
<label className="front-color dot">{getPeriodLabel(period)}</label>
const PeriodBanner: React.FC<IPeriodBanner> = ({ id, period, isCard = true }) => (
<Container period={period} isCard={isCard}>
{isCard && <label className="front-color dot">{getPeriodLabel(period)}</label>}
<label className="front-color">#{id}</label>
</Container>
);
Expand Down
Loading

0 comments on commit caafd1d

Please sign in to comment.