{isConnected && (
- {!walletIsVerified ? (
+ {!walletIsVerified && !eventCache?.finished ? (
) : null}
- {walletIsVerified || (!walletIsVerified && eventCache.finished) ? (
+ {((!session || isExpired) && walletIsVerified) || (isExpired && !walletIsVerified && eventCache.finished) ? (
) : null}
@@ -108,7 +138,7 @@ const Home: React.FC = () => {
alignItems="center"
sx={{
display: 'flex',
- order: '2',
+ order: '1',
}}
>
diff --git a/ui/summit-2023/src/pages/Leaderboard/Leaderboard.module.scss b/ui/summit-2023/src/pages/Leaderboard/Leaderboard.module.scss
index 0d60c1022..eb2ac9c25 100644
--- a/ui/summit-2023/src/pages/Leaderboard/Leaderboard.module.scss
+++ b/ui/summit-2023/src/pages/Leaderboard/Leaderboard.module.scss
@@ -1,4 +1,5 @@
.leaderboard {
+ width: 100%;
.description {
max-height: 110px;
margin-bottom: 40px !important;
@@ -63,4 +64,23 @@
background: #daeefb;
}
}
+
+ .masonryGrid {
+ display: -webkit-box;
+ display: -ms-flexbox;
+ display: flex;
+ width: auto;
+ }
+ .masonryGridColumn {
+ padding-left: 16px;
+ background-clip: padding-box;
+ @media only screen and (max-width: 600px) {
+ padding-left: 0px;
+ }
+ }
+
+ .masonryGridColumn > .MuiCard:root {
+ background: grey;
+ margin-bottom: 30px;
+ }
}
diff --git a/ui/summit-2023/src/pages/Leaderboard/Leaderboard.tsx b/ui/summit-2023/src/pages/Leaderboard/Leaderboard.tsx
index 48ca9d2c9..8d743e766 100644
--- a/ui/summit-2023/src/pages/Leaderboard/Leaderboard.tsx
+++ b/ui/summit-2023/src/pages/Leaderboard/Leaderboard.tsx
@@ -1,8 +1,9 @@
import React, { useCallback, useEffect, useMemo, useState } from 'react';
-import { Typography, Grid, Box } from '@mui/material';
+import { Typography, Grid, Box, styled } from '@mui/material';
import styles from './Leaderboard.module.scss';
import cn from 'classnames';
-
+import { i18n } from 'i18n';
+import { makeStyles } from 'tss-react/mui';
import { PieChart } from 'react-minimal-pie-chart';
import { ByCategoryStats } from 'types/voting-app-types';
import { EventPresentation } from 'types/voting-ledger-follower-types';
@@ -14,14 +15,79 @@ import { RootState } from '../../store';
import { StatsTile } from './components/StatsTile';
import SUMMIT2023CONTENT from '../../common/resources/data/summit2023Content.json';
import { CategoryContent } from 'pages/Categories/Category.types';
-import { LeaderboardContent } from './Leaderboard.types';
import { eventBus } from '../../utils/EventBus';
+import Masonry from 'react-masonry-css';
+import { AwardsTile } from './components/AwardsTile';
+import Tab from '@mui/material/Tab';
+import TabContext from '@mui/lab/TabContext';
+import TabList from '@mui/lab/TabList';
+import TabPanel from '@mui/lab/TabPanel';
+import WinnersIcon from '@mui/icons-material/EmojiEvents';
+import VotesIcon from '@mui/icons-material/DonutLarge';
+import BarChartIcon from '@mui/icons-material/BarChart';
+import { env } from '../../common/constants/env';
+import { HydraTile } from './components/HydraTile';
+import Tooltip, { tooltipClasses, TooltipProps } from '@mui/material/Tooltip';
+
+const useStyles = makeStyles()(() => ({
+ customTab: {
+ '& .MuiTab-root': {
+ color: '#03021f',
+ textTransform: 'capitalize',
+ height: 3,
+ '&.Mui-selected': {
+ color: '#106593',
+ '&.svg': {
+ fill: '#106593 !important',
+ },
+ },
+ '&:hover': {
+ backgroundColor: '#DAEEFB',
+ },
+ '&:active': {
+ backgroundColor: '#DAEEFB',
+ },
+ '&.Mui-selected:hover': {
+ backgroundColor: '#DAEEFB',
+ },
+ },
+ },
+ customeTabIndicator: {
+ '& .MuiTabs-indicator': {
+ width: '90px',
+ borderTopLeftRadius: '20px !important',
+ borderTopRightRadius: '20px !important',
+ backgroundColor: '#106593 !important',
+ height: '5px !important',
+ },
+ },
+}));
+
+const DisableTooltip = styled(({ className, ...props }: TooltipProps) => (
+
+))(({ theme }) => ({
+ [`& .${tooltipClasses.arrow}`]: {
+ color: theme.palette.primary.main,
+ },
+ [`& .${tooltipClasses.tooltip}`]: {
+ textAlign: 'center',
+ backgroundColor: theme.palette.primary.main,
+ },
+}));
const Leaderboard = () => {
- const event = useSelector((state: RootState) => state.user.event);
+ const classes = useStyles();
+ const summitEvent = useSelector((state: RootState) => state.user.event);
const [stats, setStats] = useState
();
+ const [value, setValue] = useState('2');
+ const [winnersAvailable, setWinnersAvailable] = useState(Boolean);
+ const [hydraTallyAvailable, setHydraTallyAvailable] = useState(Boolean);
+
const summit2023Categories: CategoryContent[] = SUMMIT2023CONTENT.categories;
- const summit2023Leaderboard: LeaderboardContent = SUMMIT2023CONTENT.leaderboard;
const init = useCallback(async () => {
try {
@@ -29,20 +95,30 @@ const Leaderboard = () => {
setStats(response.categories);
});
} catch (error) {
- const message = `Failed to fetch stats: ${error?.message || error?.toString()}`;
+ const message = `Failed to fecth stats: ${error?.message || error?.toString()}`;
if (process.env.NODE_ENV === 'development') {
console.log(message);
}
- eventBus.publish('showToast', 'Failed to fetch stats', 'error');
+ eventBus.publish('showToast', i18n.t('toast.failedToFecthStats'), 'error');
}
}, []);
useEffect(() => {
+ if (env?.SHOW_WINNERS === 'true') {
+ setWinnersAvailable(true);
+ } else {
+ setWinnersAvailable(false);
+ }
+ if (env?.SHOW_HYDRA_TALLY === 'true') {
+ setHydraTallyAvailable(true);
+ } else {
+ setHydraTallyAvailable(false);
+ }
init();
}, [init]);
const statsItems: StatItem[] =
- event?.categories?.map(({ id }, index) => ({
+ summitEvent?.categories?.map(({ id }, index) => ({
id,
label: id === summit2023Categories[index].id && summit2023Categories[index].presentationName,
})) || [];
@@ -56,6 +132,31 @@ const Leaderboard = () => {
color: categoryColorsMap[id],
}));
+ const handleChange = (event: React.SyntheticEvent, newValue: string) => {
+ setValue(newValue);
+ };
+
+ const breakpointColumnsObj = {
+ default: 3,
+ 1337: 2,
+ 909: 1,
+ };
+
+ const TabContextStyles = {
+ container: {
+ display: 'flex',
+ flexDirection: 'row',
+ justifyContent: 'center',
+ alignItems: 'center',
+ borderRadius: '40px',
+ background: '#F5F9FF',
+ boxShadow: '2px 2px 8px 0px rgba(67, 70, 86, 0.25)',
+ width: { xs: '100%', sm: '429px'},
+ height: { xs: '72px', sm: '76px' },
+ margin: '0 auto',
+ },
+ };
+
return (
{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
- marginTop: '20px',
- marginBottom: 20,
+ marginBottom: 48,
}}
>
{
fontWeight: '600',
}}
>
- Leaderboard
+ {i18n.t('leaderboard.title')}
-
-
- {summit2023Leaderboard.desc}
-
-
-
- {statsSum || placeholder}}
- >
-
+
+
+
+ {!winnersAvailable ? (
+
+
+ }
+ label={i18n.t('leaderboard.tabs.tab1.label')}
+ value="1"
+ disableRipple
+ disabled={!winnersAvailable}
+ />
+
+
+ ) : (
+ }
+ label={i18n.t('leaderboard.tabs.tab1.label')}
+ value="1"
+ disableRipple
+ />
+ )}
+ }
+ label={i18n.t('leaderboard.tabs.tab2.label')}
+ value="2"
+ disableRipple
+ />
+ {!hydraTallyAvailable ? (
+
+
+ }
+ label={i18n.t('leaderboard.tabs.tab3.label')}
+ value="3"
+ disableRipple
+ disabled={!hydraTallyAvailable}
+ />
+
+
+ ) : (
+ }
+ label={i18n.t('leaderboard.tabs.tab3.label')}
+ value="3"
+ />
+ )}
+
+
+
+ {winnersAvailable ? (
+
+ {statsItems.map((item, index) => (
+
+ ))}
+
+ ) : (
+
+ {i18n.t('leaderboard.tabs.tab1.tooltipText')}
+
+ )}
+
+
-
- Category
-
- {statsSum || placeholder}}
>
- Number of votes
-
-
- {statsItems.map(({ label, id }) => (
-
-
-
- {label}
-
-
- {stats?.find((category) => category.id === id).votes || placeholder}
-
+
+ {i18n.t('leaderboard.tabs.tab2.tiles.totalVotes.tableHeadings.column1')}
+
+
+ {i18n.t('leaderboard.tabs.tab2.tiles.totalVotes.tableHeadings.column2')}
+
+
+ {statsItems.map(({ label, id }) => (
+
+
+
+
+ {label}
+
+
+ {stats?.find((category) => category.id === id).votes || placeholder}
+
+
+
+ ))}
-
- ))}
-
-
- {statsSum || placeholder}}
- dataTestId="votes-per-category"
- >
-
-
- 0 ? chartData : [{ title: '', value: 1, color: '#BBBBBB' }]}
- />
-
-
-
-
+
- {statsItems.map(({ label, id }) => (
+
+ 0 ? chartData : [{ title: '', value: 1, color: '#BBBBBB' }]}
+ />
+
+
+
-
-
-
-
+ {statsItems.map(({ label, id }) => (
-
- {label}
-
-
-
- {stats && (
- <>
-
- {statsSum > 0
- ? getPercentage(
- stats?.find((category) => category.id === id)?.votes,
- statsSum
- ).toFixed(2)
- : '0'}{' '}
- %
-
- {' - '}
-
- {stats?.find((category) => category.id === id)?.votes}
-
- >
- )}
+
+
+
+
+
+
+ {label}
+
+
+
+ {stats && (
+ <>
+
+ {statsSum > 0
+ ? getPercentage(
+ stats?.find((category) => category.id === id)?.votes,
+ statsSum
+ ).toFixed(2)
+ : '0'}{' '}
+ %
+
+ {' - '}
+
+ {stats?.find((category) => category.id === id)?.votes}
+
+ >
+ )}
+
+
+
-
+ ))}
-
- ))}
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+ {hydraTallyAvailable ? (
+
+ {statsItems.map((item, index) => (
+
+ ))}
+
+ ) : (
+
+ {i18n.t('leaderboard.tabs.tab3.tooltipText')}
+
+ )}
+
+
+
);
};
diff --git a/ui/summit-2023/src/pages/Leaderboard/components/AwardsTile/AwardsTile.module.scss b/ui/summit-2023/src/pages/Leaderboard/components/AwardsTile/AwardsTile.module.scss
new file mode 100644
index 000000000..b02179fa4
--- /dev/null
+++ b/ui/summit-2023/src/pages/Leaderboard/components/AwardsTile/AwardsTile.module.scss
@@ -0,0 +1,70 @@
+.awardCard {
+ border-radius: 16px !important;
+ border: 1px solid transparent !important;
+ box-shadow: 2px 2px 5px 0px #061d3c40 !important;
+ display: flex !important;
+ flex-direction: column !important;
+ margin: 16px !important;
+ background-color: white;
+ @media only screen and (max-width: 600px) {
+ margin: 0 0 16px 0 !important;
+ }
+ .rankCard {
+ border: 1px solid transparent !important;
+ border-radius: 8px;
+ background: #fff;
+ text-align: center;
+ font-size: 12px;
+ margin: 10px !important;
+ padding: 10px;
+ display: 'flex';
+ text-align: left;
+ vertical-align: middle;
+ flex-shrink: 0;
+ width: 96% !important;
+ word-wrap: break-word;
+ box-shadow: 1px 2px 7px 0px rgba(67, 70, 86, 0.1);
+ .trophy {
+ display: flex;
+ margin: auto 6px;
+ }
+ .title {
+ max-width: 250px;
+ font-size: 20px !important;
+ color: var(---color-primary) !important;
+ font-weight: 600 !important;
+ }
+ }
+
+ .awardTitle {
+ color: var(---color-primary) !important;
+ text-align: center;
+ font-size: 18px !important;
+ font-weight: 600 !important;
+ line-height: 22px !important;
+ letter-spacing: 0em !important;
+ justify-content: center;
+ display: flex;
+ background-color: transparent;
+ margin: 0 auto;
+ align-items: center;
+ }
+
+ .listTitle {
+ color: var(---color-primary) !important;
+ font-size: 18px !important;
+ font-weight: 600 !important;
+ line-height: 22px !important;
+ letter-spacing: 0em !important;
+ }
+
+ .statTitle {
+ font-size: 16px !important;
+ color: var(---color-primary) !important;
+ font-weight: 400 !important;
+ }
+ .divider {
+ height: 0.5px;
+ background: #f0f0f0;
+ }
+}
diff --git a/ui/summit-2023/src/pages/Leaderboard/components/AwardsTile/AwardsTile.tsx b/ui/summit-2023/src/pages/Leaderboard/components/AwardsTile/AwardsTile.tsx
new file mode 100644
index 000000000..323aecc66
--- /dev/null
+++ b/ui/summit-2023/src/pages/Leaderboard/components/AwardsTile/AwardsTile.tsx
@@ -0,0 +1,277 @@
+import React, { useCallback, useEffect, useState } from 'react';
+import { Avatar, Box, Button, CardActions, Chip, CircularProgress, Grid, Typography } from '@mui/material';
+import { Link } from 'react-router-dom';
+import Card from '@mui/material/Card';
+import { i18n } from 'i18n';
+import CardContent from '@mui/material/CardContent';
+import * as leaderboardService from '../../../../common/api/leaderboardService';
+import { eventBus } from 'utils/EventBus';
+import SUMMIT2023CONTENT from '../../../../common/resources/data/summit2023Content.json';
+import { ProposalContent } from 'pages/Nominees/Nominees.type';
+import { CategoryContent } from 'pages/Categories/Category.types';
+import styles from './AwardsTile.module.scss';
+import cn from 'classnames';
+import CATEGORY_IMAGES from '../../../../common/resources/data/categoryImages.json';
+
+const AwardsTile = ({ counter, title, categoryId }) => {
+ const summit2023Category: CategoryContent = SUMMIT2023CONTENT.categories.find(
+ (category) => category.id === categoryId
+ );
+ const summit2023Proposals: ProposalContent[] = summit2023Category.proposals;
+ const [awards, setAwards] = useState([]);
+ const [loaded, setLoaded] = useState(false);
+
+ const init = useCallback(async () => {
+ try {
+ await leaderboardService.getCategoryLevelStats(categoryId).then((response) => {
+ const updatedAwards = summit2023Proposals.map((proposal) => {
+ const id = proposal.id;
+ const votes = response?.proposals[id] ? response?.proposals[id].votes : 0;
+ const rank = 0;
+ return { ...proposal, votes, rank };
+ });
+
+ updatedAwards.sort((a, b) => b.votes - a.votes);
+
+ updatedAwards.forEach((item, index, array) => {
+ if (index > 0 && item.votes === array[index - 1].votes) {
+ item.rank = array[index - 1].rank;
+ } else {
+ item.rank = index + 1;
+ }
+ });
+ setAwards(updatedAwards);
+ });
+ setLoaded(true);
+ } catch (error) {
+ const message = `Failed to fecth Nominee stats: ${error?.message || error?.toString()}`;
+ if (process.env.NODE_ENV === 'development') {
+ console.log(message);
+ }
+ eventBus.publish('showToast', i18n.t('toast.failedToFecthNomineeStats'), 'error');
+ }
+ }, []);
+
+ useEffect(() => {
+ init();
+ }, [init]);
+
+ return (
+
+ {loaded ? (
+
+
+
+ }
+ color="default"
+ label={title}
+ className={styles.awardTitle}
+ variant="filled"
+ />
+ {awards.length > 0 && (
+
+
+ {awards.slice(0, 2).map((proposal, index) => (
+
+ {(proposal.rank === 1 && proposal.votes > 0 ) && (
+
+
+
+
+
+
+
+ {proposal.presentationName}
+
+
+ {proposal.votes} {i18n.t('leaderboard.tabs.tab1.tile.votesLabel')}
+
+
+
+
+ )}
+
+ ))}
+
+
+ )}
+
+
+
+
+
+ {i18n.t('leaderboard.tabs.tab1.tile.tableHeadings.column1')}
+
+
+
+
+ {i18n.t('leaderboard.tabs.tab1.tile.tableHeadings.column2')}
+
+
+
+
+ {i18n.t('leaderboard.tabs.tab1.tile.tableHeadings.column3')}
+
+
+
+ {awards.map((proposal, index) => (
+
+ {proposal.rank !== 1 && (
+
+
+
+ {proposal.rank}
+
+
+
+
+ {proposal.presentationName}
+
+
+
+
+ {proposal.votes}
+
+
+
+ )}
+
+ ))}
+
+
+
+ {i18n.t('button.viewAllNominees')}
+
+
+
+
+ ) : (
+
+
+
+ )}
+
+ );
+};
+
+export { AwardsTile };
\ No newline at end of file
diff --git a/ui/summit-2023/src/pages/Leaderboard/components/AwardsTile/index.ts b/ui/summit-2023/src/pages/Leaderboard/components/AwardsTile/index.ts
new file mode 100644
index 000000000..a9e00d3bf
--- /dev/null
+++ b/ui/summit-2023/src/pages/Leaderboard/components/AwardsTile/index.ts
@@ -0,0 +1 @@
+export * from './AwardsTile';
\ No newline at end of file
diff --git a/ui/summit-2023/src/pages/Leaderboard/components/HydraTile/HydraTile.module.scss b/ui/summit-2023/src/pages/Leaderboard/components/HydraTile/HydraTile.module.scss
new file mode 100644
index 000000000..ee98be0ca
--- /dev/null
+++ b/ui/summit-2023/src/pages/Leaderboard/components/HydraTile/HydraTile.module.scss
@@ -0,0 +1,45 @@
+.hydraCard {
+ border-radius: 16px !important;
+ border: 1px solid transparent !important;
+ box-shadow: 2px 2px 5px 0px #061d3c40 !important;
+ display: flex !important;
+ flex-direction: column !important;
+ margin: 10px !important;
+ background-color: white;
+ @media only screen and (max-width: 600px) {
+ margin: 0 0 10px 0 !important;
+ }
+
+ .hydraTallyTitle {
+ color: var(---color-primary) !important;
+ text-align: center;
+ font-size: 18px !important;
+ font-weight: 600 !important;
+ line-height: 22px !important;
+ letter-spacing: 0em !important;
+ justify-content: center;
+ display: flex;
+ background-color: transparent;
+ margin: 0 auto;
+ align-items: center;
+ }
+
+ .listTitle {
+ color: var(---color-primary) !important;
+ font-size: 18px !important;
+ font-weight: 600 !important;
+ line-height: 22px !important;
+ letter-spacing: 0em !important;
+ text-align: left;
+ }
+
+ .statTitle {
+ font-size: 16px !important;
+ color: var(---color-primary) !important;
+ font-weight: 400 !important;
+ }
+ .divider {
+ height: 1px;
+ background: #dfdfdf;
+ }
+}
diff --git a/ui/summit-2023/src/pages/Leaderboard/components/HydraTile/HydraTile.tsx b/ui/summit-2023/src/pages/Leaderboard/components/HydraTile/HydraTile.tsx
new file mode 100644
index 000000000..bfebf47e1
--- /dev/null
+++ b/ui/summit-2023/src/pages/Leaderboard/components/HydraTile/HydraTile.tsx
@@ -0,0 +1,177 @@
+import React, { useCallback, useEffect, useState } from 'react';
+import { Avatar, Box, Button, CardActions, Chip, CircularProgress, Grid, Typography } from '@mui/material';
+import { Link } from 'react-router-dom';
+import Card from '@mui/material/Card';
+import CardContent from '@mui/material/CardContent';
+import * as leaderboardService from '../../../../common/api/leaderboardService';
+import { eventBus } from 'utils/EventBus';
+import SUMMIT2023CONTENT from '../../../../common/resources/data/summit2023Content.json';
+import { ProposalContent } from 'pages/Nominees/Nominees.type';
+import { CategoryContent } from 'pages/Categories/Category.types';
+import styles from './HydraTile.module.scss';
+import cn from 'classnames';
+import { i18n } from 'i18n';
+import CATEGORY_IMAGES from '../../../../common/resources/data/categoryImages.json';
+
+const HydraTile = ({ counter, title, categoryId }) => {
+ const summit2023Category: CategoryContent = SUMMIT2023CONTENT.categories.find(
+ (category) => category.id === categoryId
+ );
+ const summit2023Proposals: ProposalContent[] = summit2023Category.proposals;
+ const [awards, setAwards] = useState([]);
+ const [loaded, setLoaded] = useState(false);
+
+ const init = useCallback(async () => {
+ try {
+ await leaderboardService.getHydraTallyStats(categoryId).then((response) => {
+ const updatedAwards = summit2023Proposals.map((proposal) => {
+ const id = proposal.id;
+ const votes = response?.proposals[id] ? response?.proposals[id].votes : 0;
+ const rank = 0;
+ return { ...proposal, votes, rank };
+ });
+
+ updatedAwards.sort((a, b) => b.votes - a.votes);
+ updatedAwards.forEach((item, index, array) => {
+ if (index > 0 && item.votes === array[index - 1].votes) {
+ item.rank = array[index - 1].rank;
+ } else {
+ item.rank = index + 1;
+ }
+ });
+ setAwards(updatedAwards);
+ });
+ setLoaded(true);
+ } catch (error) {
+ const message = `Failed to fecth Nominee stats: ${error?.message || error?.toString()}`;
+ if (process.env.NODE_ENV === 'development') {
+ console.log(message);
+ }
+ eventBus.publish('showToast', i18n.t('toast.failedToFecthNomineeStats'), 'error');
+ }
+ }, []);
+
+ useEffect(() => {
+ init();
+ }, [init]);
+
+ return (
+
+ {loaded ? (
+
+
+
+ }
+ color="default"
+ label={title}
+ className={styles.hydraTallyTitle}
+ variant="filled"
+ />
+
+
+
+
+ {i18n.t('leaderboard.tabs.tab3.tile.tableHeadings.column1')}
+
+
+ {i18n.t('leaderboard.tabs.tab3.tile.tableHeadings.column2')}
+
+
+ {awards.slice(0, 2).map((proposal, index) => (
+
+ {(proposal.rank === 1 && proposal.votes > 0 ) && (
+
+
+ {proposal.presentationName}
+
+
+ {proposal.votes}
+
+
+ )}
+
+ ))}
+
+
+
+ {i18n.t('button.viewAllNominees')}
+
+
+
+
+ ) : (
+
+
+
+ )}
+
+ );
+};
+
+export { HydraTile };
diff --git a/ui/summit-2023/src/pages/Leaderboard/components/HydraTile/index.ts b/ui/summit-2023/src/pages/Leaderboard/components/HydraTile/index.ts
new file mode 100644
index 000000000..d237e707f
--- /dev/null
+++ b/ui/summit-2023/src/pages/Leaderboard/components/HydraTile/index.ts
@@ -0,0 +1 @@
+export * from './HydraTile';
\ No newline at end of file
diff --git a/ui/summit-2023/src/pages/Leaderboard/components/StatsTile.module.scss b/ui/summit-2023/src/pages/Leaderboard/components/StatsTile/StatsTile.module.scss
similarity index 100%
rename from ui/summit-2023/src/pages/Leaderboard/components/StatsTile.module.scss
rename to ui/summit-2023/src/pages/Leaderboard/components/StatsTile/StatsTile.module.scss
diff --git a/ui/summit-2023/src/pages/Leaderboard/components/StatsTile.tsx b/ui/summit-2023/src/pages/Leaderboard/components/StatsTile/StatsTile.tsx
similarity index 84%
rename from ui/summit-2023/src/pages/Leaderboard/components/StatsTile.tsx
rename to ui/summit-2023/src/pages/Leaderboard/components/StatsTile/StatsTile.tsx
index fd9eee6c0..9892e6bc2 100644
--- a/ui/summit-2023/src/pages/Leaderboard/components/StatsTile.tsx
+++ b/ui/summit-2023/src/pages/Leaderboard/components/StatsTile/StatsTile.tsx
@@ -4,12 +4,12 @@ import styles from './StatsTile.module.scss';
type StatsTilePorps = {
title: string | React.ReactElement;
- summary: string | React.ReactElement;
+ summary?: string | React.ReactElement;
children: React.ReactNode;
dataTestId: string;
};
-export const StatsTile = ({ title, summary, children, dataTestId }: StatsTilePorps) => {
+const StatsTile = ({ title, summary, children, dataTestId }: StatsTilePorps) => {
return (
);
};
+
+
+export { StatsTile };
\ No newline at end of file
diff --git a/ui/summit-2023/src/pages/Leaderboard/components/StatsTile/index.ts b/ui/summit-2023/src/pages/Leaderboard/components/StatsTile/index.ts
new file mode 100644
index 000000000..5ef1e85eb
--- /dev/null
+++ b/ui/summit-2023/src/pages/Leaderboard/components/StatsTile/index.ts
@@ -0,0 +1 @@
+export * from './StatsTile';
\ No newline at end of file
diff --git a/ui/summit-2023/src/pages/Leaderboard/index.ts b/ui/summit-2023/src/pages/Leaderboard/index.ts
index 8adbc3e2f..4091b2433 100644
--- a/ui/summit-2023/src/pages/Leaderboard/index.ts
+++ b/ui/summit-2023/src/pages/Leaderboard/index.ts
@@ -1 +1 @@
-export * from './Leaderboard';
+export * from './Leaderboard';
\ No newline at end of file
diff --git a/ui/summit-2023/src/pages/Legal/PrivacyPolicy/PrivacyPolicy.tsx b/ui/summit-2023/src/pages/Legal/PrivacyPolicy/PrivacyPolicy.tsx
index 6370f3cce..295f8d3e6 100644
--- a/ui/summit-2023/src/pages/Legal/PrivacyPolicy/PrivacyPolicy.tsx
+++ b/ui/summit-2023/src/pages/Legal/PrivacyPolicy/PrivacyPolicy.tsx
@@ -10,8 +10,21 @@ const PrivacyPolicy = () => {
{/* Privacy Policy */}
{privacyData.title}
diff --git a/ui/summit-2023/src/pages/Legal/TermsAndConditions/TermsAndConditions.tsx b/ui/summit-2023/src/pages/Legal/TermsAndConditions/TermsAndConditions.tsx
index aa93c393c..f2d90bd0d 100644
--- a/ui/summit-2023/src/pages/Legal/TermsAndConditions/TermsAndConditions.tsx
+++ b/ui/summit-2023/src/pages/Legal/TermsAndConditions/TermsAndConditions.tsx
@@ -15,8 +15,21 @@ const TermsAndConditions = () => {
{/* Terms and Conditions 1 */}
{termsData.title}
diff --git a/ui/summit-2023/src/pages/Nominees/Nominees.scss b/ui/summit-2023/src/pages/Nominees/Nominees.scss
index 67090f7f6..ffa177065 100644
--- a/ui/summit-2023/src/pages/Nominees/Nominees.scss
+++ b/ui/summit-2023/src/pages/Nominees/Nominees.scss
@@ -1,3 +1,6 @@
+.nominees-page {
+ width: 100%;
+}
.nominees-page-title {
color: var(--color-dark-grey);
font-style: normal;
@@ -20,22 +23,27 @@
}
.nominee-card.MuiPaper-root {
- width: 414px;
- flex-shrink: 0;
- border-radius: 8px;
box-shadow: 2px 3px 10px 0px rgba(67, 70, 86, 0.45);
+ border-radius: 16px !important;
+ border: 1px solid transparent !important;
+ box-shadow: 2px 2px 5px 0px #061d3c40 !important;
+ display: flex !important;
+ flex-direction: column !important;
+ margin: 10px !important;
+ background-color: white;
+ @media only screen and (max-width: 600px) {
+ margin: 0 0 10px 0 !important;
+ }
.nominee-title {
- color: var(--color-ultra-dark-blue);
- font-size: 36px;
+ color: var(---color-primary);
font-style: normal;
- font-weight: 600 !important;
line-height: normal;
}
.nominee-description {
margin-top: 20px;
margin-right: 50px;
- color: var(--color-medium-grey);
+ margin-bottom: 20px !important;
font-size: 16px;
font-style: normal;
font-weight: 400;
@@ -183,3 +191,33 @@
color: red;
}
}
+
+.selected {
+ background-color: #daeefb !important;
+ border: 2px var(--color-primary) !important;
+ border-radius: 8px !important;
+}
+.unSelected {
+ background-color: transparent !important;
+ border: 2px var(--color-primary) !important;
+ border-radius: 8px !important;
+}
+
+.masonryGrid {
+ display: -webkit-box;
+ display: -ms-flexbox;
+ display: flex;
+ width: auto;
+}
+.masonryGridColumn {
+ padding-left: 10px;
+ background-clip: padding-box;
+ @media only screen and (max-width: 600px) {
+ padding-left: 0px;
+ }
+}
+
+.masonryGridColumn > .MuiCard:root {
+ background: grey;
+ margin-bottom: 30px;
+}
\ No newline at end of file
diff --git a/ui/summit-2023/src/pages/Nominees/Nominees.tsx b/ui/summit-2023/src/pages/Nominees/Nominees.tsx
index 399c067d0..a3813b3a6 100644
--- a/ui/summit-2023/src/pages/Nominees/Nominees.tsx
+++ b/ui/summit-2023/src/pages/Nominees/Nominees.tsx
@@ -1,6 +1,8 @@
import React, { useState, useEffect, useMemo, ReactElement } from 'react';
import { useParams } from 'react-router-dom';
+import { useDispatch, useSelector } from 'react-redux';
import { v4 as uuidv4 } from 'uuid';
+import { i18n } from 'i18n';
import {
useTheme,
useMediaQuery,
@@ -15,10 +17,14 @@ import {
Accordion,
AccordionSummary,
AccordionDetails,
+ Button,
+ CardMedia,
+ Badge,
} from '@mui/material';
import { useNavigate } from 'react-router-dom';
import ViewModuleIcon from '@mui/icons-material/ViewModule';
import ViewListIcon from '@mui/icons-material/ViewList';
+import GppBadOutlinedIcon from '@mui/icons-material/GppBadOutlined';
import WarningAmberIcon from '@mui/icons-material/WarningAmber';
import VerifiedUserIcon from '@mui/icons-material/VerifiedUser';
import NotificationsIcon from '@mui/icons-material/Notifications';
@@ -26,18 +32,16 @@ import QrCodeIcon from '@mui/icons-material/QrCode';
import RefreshIcon from '@mui/icons-material/Refresh';
import InfoIcon from '@mui/icons-material/Info';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
-import EmojiEventsIcon from '@mui/icons-material/EmojiEvents';
import labelVoted from '../../common/resources/images/checkmark-green.png';
import AccountBalanceWalletIcon from '@mui/icons-material/AccountBalanceWallet';
+import CloseIcon from '@mui/icons-material/Close';
import { Fade } from '@mui/material';
-import './Nominees.scss';
+import { useCardano } from '@cardano-foundation/cardano-connect-with-wallet';
+import QRCode from 'react-qr-code';
import { CategoryContent } from '../Categories/Category.types';
import SUMMIT2023CONTENT from '../../common/resources/data/summit2023Content.json';
import { eventBus } from '../../utils/EventBus';
-import { useCardano } from '@cardano-foundation/cardano-connect-with-wallet';
-import CloseIcon from '@mui/icons-material/Close';
import { ROUTES } from '../../routes';
-import { useDispatch, useSelector } from 'react-redux';
import { RootState } from '../../store';
import {
buildCanonicalVoteInputJson,
@@ -50,34 +54,32 @@ import { copyToClipboard, getSignedMessagePromise, resolveCardanoNetwork, shorte
import { buildCanonicalLoginJson, submitLogin } from 'common/api/loginService';
import { getUserInSession, saveUserInSession, tokenIsExpired } from '../../utils/session';
import { setUserVotes, setVoteReceipt, setWalletIsLoggedIn } from '../../store/userSlice';
-import { FinalityScore } from '../../types/voting-ledger-follower-types';
import SidePage from '../../components/common/SidePage/SidePage';
import { useToggle } from 'common/hooks/useToggle';
import ReadMore from './ReadMore';
import Modal from '../../components/common/Modal/Modal';
-import QRCode from 'react-qr-code';
import { CustomButton } from '../../components/common/Button/CustomButton';
import { env } from 'common/constants/env';
import { parseError } from 'common/constants/errors';
import { categoryAlreadyVoted } from '../Categories';
import { ProposalPresentationExtended } from '../../store/types';
import { verifyVote } from 'common/api/verificationService';
+import './Nominees.scss';
+import Masonry from 'react-masonry-css';
+import { ReactComponent as WinnersIcon } from '../../common/resources/images/winner-badge-summit-2023.svg';
const Nominees = () => {
+ const dispatch = useDispatch();
const { categoryId } = useParams();
const navigate = useNavigate();
- const eventCache = useSelector((state: RootState) => state.user.event);
- const walletIsVerified = useSelector((state: RootState) => state.user.walletIsVerified);
- const walletIsLoggedIn = useSelector((state: RootState) => state.user.walletIsLoggedIn);
- const receipts = useSelector((state: RootState) => state.user.receipts);
+ const eventCache = useSelector((state: RootState) => state.user?.event);
+ const walletIsVerified = useSelector((state: RootState) => state.user?.walletIsVerified);
+ const receipts = useSelector((state: RootState) => state.user?.receipts);
const receipt = receipts && Object.keys(receipts).length && receipts[categoryId] ? receipts[categoryId] : undefined;
- const userVotes = useSelector((state: RootState) => state.user.userVotes);
- const winners = useSelector((state: RootState) => state.user.winners);
+ const userVotes = useSelector((state: RootState) => state.user?.userVotes);
+ const winners = useSelector((state: RootState) => state.user?.winners);
const categoryVoted = categoryAlreadyVoted(categoryId, userVotes);
-
- const dispatch = useDispatch();
-
const categories = eventCache?.categories;
const summit2023Category: CategoryContent = SUMMIT2023CONTENT.categories.find(
@@ -87,6 +89,7 @@ const Nominees = () => {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
const isBigScreen = useMediaQuery(theme.breakpoints.down('xl'));
+
const [viewMode, setViewMode] = useState<'grid' | 'list'>('grid');
const [isVisible, setIsVisible] = useState(true);
const [isToggleReadMore, toggleReadMore] = useToggle(false);
@@ -98,6 +101,7 @@ const Nominees = () => {
const [nominees, setNominees] = useState([]);
const session = getUserInSession();
+ const isExpired = !session || tokenIsExpired(session?.expiresAt);
const { isConnected, stakeAddress, signMessage } = useCardano({
limitNetwork: resolveCardanoNetwork(env.TARGET_NETWORK),
@@ -107,6 +111,12 @@ const Nominees = () => {
const signMessagePromisified = useMemo(() => getSignedMessagePromise(signMessage), [signMessage]);
+ const breakpointColumnsObj = {
+ default: 3,
+ 1337: 2,
+ 909: 1,
+ };
+
const loadNominees = () => {
if (categoryId) {
categories?.map((category) => {
@@ -115,7 +125,7 @@ const Nominees = () => {
}
});
} else {
- navigate(ROUTES.PAGENOTFOUND);
+ navigate(ROUTES.PAGE_NOT_FOUND);
}
};
@@ -282,9 +292,9 @@ const Nominees = () => {
const renderNomineeButtonLabel = () => {
if (isConnected) {
if (!walletIsVerified) {
- return 'Verify your wallet';
+ return 'Verify your Wallet';
} else {
- return 'Vote for nominee';
+ return 'Vote for Nominee';
}
} else {
return (
@@ -297,44 +307,102 @@ const Nominees = () => {
const handleCopyToClipboard = (text: string) => {
copyToClipboard(text)
- .then(() => eventBus.publish('showToast', 'Copied to clipboard'))
- .catch(() => eventBus.publish('showToast', 'Copied to clipboard failed', 'error'));
+ .then(() => eventBus.publish('showToast', i18n.t('toast.copy')))
+ .catch(() => eventBus.publish('showToast', i18n.t('toast.copyError'), 'error'));
};
- const getAssuranceTheme = () => {
- // TODO
+ const getStatusTheme = () => {
+ const finalityScore = receipt?.finalityScore;
- const finalityScore: FinalityScore = receipt?.finalityScore;
-
- switch (finalityScore) {
- case 'VERY_HIGH':
- return {
- backgroundColor: 'rgba(16, 101, 147, 0.07)',
- color: '#056122',
- };
- case 'HIGH':
- return {
- backgroundColor: 'rgba(16, 101, 147, 0.07)',
- color: '#056122',
- };
- case 'MEDIUM':
- return {
- backgroundColor: 'rgba(16, 101, 147, 0.07)',
- color: '#652701',
- };
- case 'LOW':
- return {
- backgroundColor: 'rgba(16, 101, 147, 0.07)',
- };
- case 'FINAL':
- return {
- backgroundColor: 'rgba(16, 101, 147, 0.07)',
- color: '#056122',
- };
- default:
- return {
- backgroundColor: 'rgba(16, 101, 147, 0.07)',
- color: '#106593',
- };
+ if (receipt?.status === 'FULL') {
+ switch (finalityScore) {
+ case 'VERY_HIGH':
+ return {
+ label: 'VERY HIGH',
+ backgroundColor: 'rgba(16, 101, 147, 0.07)',
+ border: 'border: 1px solid #106593',
+ color: '#056122',
+ icon: ,
+ description: i18n.t('nominees.receipt.status.FULL.VERY_HIGH.description'),
+ status: 'FULL',
+ };
+ case 'HIGH':
+ return {
+ label: 'HIGH',
+ backgroundColor: 'rgba(16, 101, 147, 0.07)',
+ border: 'border: 1px solid #106593',
+ color: '#056122',
+ icon: ,
+ description: i18n.t('nominees.receipt.status.FULL.HIGH.description'),
+ status: 'FULL',
+ };
+ case 'MEDIUM':
+ return {
+ label: 'MEDIUM',
+ backgroundColor: 'rgba(16, 101, 147, 0.07)',
+ border: 'border: 1px solid #106593',
+ color: '#652701',
+ icon: ,
+ description: i18n.t('nominees.receipt.status.FULL.MEDIUM.description'),
+ status: 'FULL',
+ };
+ case 'LOW':
+ return {
+ label: 'LOW',
+ backgroundColor: 'rgba(16, 101, 147, 0.07)',
+ border: 'border: 1px solid #106593',
+ color: '#C20024',
+ icon: ,
+ description: i18n.t('nominees.receipt.status.FULL.LOW.description'),
+ status: 'FULL',
+ };
+ case 'FINAL':
+ return {
+ label: 'FINAL',
+ backgroundColor: 'rgba(5, 97, 34, 0.07)',
+ border: '1px solid #056122',
+ icon: ,
+ description: '',
+ status: 'FULL',
+ };
+ default:
+ return {
+ backgroundColor: 'rgba(16, 101, 147, 0.07)',
+ color: '#24262E',
+ icon: ,
+ description: i18n.t('nominees.receipt.status.FULL.DEFAULT.description'),
+ status: 'FULL',
+ };
+ }
+ } else if (receipt?.status === 'PARTIAL') {
+ return {
+ label: 'Vote in progress',
+ backgroundColor: 'rgba(253, 135, 60, 0.07)',
+ border: '1px solid #FD873C',
+ color: '#24262E',
+ icon: ,
+ description: i18n.t('nominees.receipt.status.PARTIAL.description'),
+ status: 'PARTIAL',
+ };
+ } else if (receipt?.status === 'ROLLBACK') {
+ return {
+ label: 'There’s been a rollback',
+ backgroundColor: 'rgba(194, 0, 36, 0.07)',
+ border: '1px solid #C20024',
+ color: '#24262E',
+ icon: ,
+ description: i18n.t('nominees.receipt.status.ROLLBACK.description'),
+ status: 'ROLLBACK',
+ };
+ } else {
+ // BASIC
+ return {
+ label: 'Vote not ready for verification',
+ backgroundColor: 'rgba(16, 101, 147, 0.07)',
+ border: '1px solid #106593',
+ color: '#24262E',
+ icon: ,
+ description: i18n.t('nominees.receipt.status.BASIC.description'),
+ };
}
};
@@ -344,7 +412,7 @@ const Nominees = () => {
};
const handleViewVoteReceipt = () => {
- if (isConnected && walletIsLoggedIn && !tokenIsExpired(session?.expiresAt)) {
+ if (isConnected && !isExpired) {
viewVoteReceipt(true, true);
} else {
login();
@@ -404,9 +472,9 @@ const Nominees = () => {
verifyVote(body)
.then((result) => {
if ('verified' in result && result.verified) {
- eventBus.publish('showToast', 'Vote proof verified', 'verified');
+ eventBus.publish('showToast', i18n.t('toast.voteVerified'), 'verified');
} else {
- eventBus.publish('showToast', 'Vote proof not verified', 'error');
+ eventBus.publish('showToast', i18n.t('toast.voteNotVerified'), 'error');
}
})
.catch((e) => {
@@ -433,23 +501,213 @@ const Nominees = () => {
key={nominee.id}
>
+ }
+ invisible={!isWinner}
+ anchorOrigin={{
+ vertical: 'top',
+ horizontal: 'right',
+ }}
+ >
+
+
+
+ {voted ? (
+
+
+
+ ) : null}
+
+
+
+
+
+
+ {nominee.presentationName}
+
+
+
+
+ {shortenString(nominee.desc, 210)}
+
+
+ {!eventCache?.finished && !categoryVoted ? (
+
+ handleNomineeButton(nominee)}
+ />
+
+ ) : null}
+
+
+ {isWinner ? (
+
+
+
+ ) : null}
+
+
+ handleReadMore(nominee)}
+ />
+
+
+
+
+
+
+ );
+ })}
+
+ >
+ );
+ };
+ const renderResponsiveGrid = (): ReactElement => {
+ return (
+ <>
+
+
+ {sortNominees(nominees).map((nominee) => {
+ const voted = nomineeAlreadyVoted(nominee);
+ const isWinner = nomineeIsWinner(nominee);
+
+ return (
+ }
+ invisible={!isWinner}
+ key={nominee.id}
+ anchorOrigin={{
+ vertical: 'top',
+ horizontal: 'right',
+ }}
+ >
-
-
- {voted ? (
-
+
+ {voted ? (
+
+
{
}}
/>
- ) : null}
-
+
+ ) : null}
{nominee.presentationName}
- {isWinner ? (
-
-
-
- ) : null}
+ {isWinner ? (
+
+ ) : null}
- {shortenString(nominee.desc, 210)}
+ {shortenString(nominee.desc, 200)}
- {!eventCache?.finished && !categoryVoted ? (
-
+
+ handleReadMore(nominee)}
+ fullWidth={true}
+ />
+
+ {!eventCache?.finished && !categoryVoted ? (
handleNomineeButton(nominee)}
+ fullWidth={true}
/>
-
- ) : null}
+ ) : null}
+
-
- handleReadMore(nominee)}
- fullWidth={true}
- />
-
-
- );
- })}
-
- >
- );
- };
- const renderResponsiveGrid = (): ReactElement => {
- return (
- <>
-
-
- {sortNominees(nominees).map((nominee) => {
- const voted = nomineeAlreadyVoted(nominee);
- const isWinner = nomineeIsWinner(nominee);
-
- return (
-
-
-
-
-
- {voted ? (
-
-
-
- ) : null}
-
-
- {nominee.presentationName}
- {isWinner ? (
-
-
-
- ) : null}
-
-
-
-
- {shortenString(nominee.desc, 210)}
-
-
-
-
- handleReadMore(nominee)}
- fullWidth={true}
- />
-
- {!eventCache?.finished && !categoryVoted ? (
- handleNomineeButton(nominee)}
- fullWidth={true}
- />
- ) : null}
-
-
-
-
+
);
})}
-
+
>
);
};
+ const showBanner = isConnected && (isExpired || (!isExpired && categoryVoted));
+
return (
<>
{
{!isMobile && (
- handleListView('grid')}>
+ handleListView('grid')}
+ className={viewMode === 'grid' ? 'selected' : 'un-selected'}
+ >
- handleListView('list')}>
+ handleListView('list')}
+ className={viewMode === 'list' ? 'selected' : 'un-selected'}
+ >
@@ -716,25 +882,23 @@ const Nominees = () => {
{summit2023Category.desc}
- {isConnected && (categoryVoted || eventCache?.finished || (receipt && categoryId === receipt?.category)) ? (
+ {showBanner ? (
- {!tokenIsExpired(session?.expiresAt) ? (
+ {!isExpired ? (
) : (
@@ -750,9 +914,9 @@ const Nominees = () => {
lineHeight: '22px',
}}
>
- {!tokenIsExpired(session?.expiresAt)
- ? `You have successfully cast a vote for ${votedNominee?.presentationName} in the ${summit2023Category.presentationName} category.`
- : 'To see you vote receipt, please sign with your wallet'}
+ {!isExpired
+ ? `${i18n.t('nominees.successfullyVoteCast')} ${summit2023Category.presentationName} category.`
+ : `${i18n.t('nominees.signIn')}`}
{
color: '#F6F9FF',
width: 'auto',
}}
- label={!tokenIsExpired(session?.expiresAt) ? 'View vote receipt' : 'Login with wallet'}
+ label={!isExpired ? i18n.t('nominees.viewReceipt') : i18n.t('nominees.loginWithWallet')}
onClick={() => handleViewVoteReceipt()}
fullWidth={true}
/>
@@ -824,7 +988,7 @@ const Nominees = () => {
lineHeight: '36px',
}}
>
- Vote Receipt
+ {i18n.t('nominees.receipt.voteReceipt')}
{receipt?.finalityScore === 'FINAL' ? (
@@ -856,8 +1020,8 @@ const Nominees = () => {
lineHeight: '22px',
}}
>
- Verified:
-
+ {i18n.t('nominees.receipt.verified')}:
+
{
maxWidth: '406px',
}}
>
- Your vote has been successfully submitted. You might have to wait up to 30 minutes for this to be
- visible on chain. Please check back later to verify your vote.
+ {i18n.t('nominees.receipt.status.FINAL.description')}
) : (
@@ -913,16 +1076,16 @@ const Nominees = () => {
alignItems: 'center',
padding: '10px 20px',
borderRadius: '8px',
- border: '1px solid #106593',
- color: 'white',
+ border: getStatusTheme()?.border,
+ color: getStatusTheme()?.color,
width: '100%',
marginBottom: '20px',
- backgroundColor: getAssuranceTheme()?.backgroundColor,
+ backgroundColor: getStatusTheme()?.backgroundColor,
}}
>
-
+ {getStatusTheme()?.icon}
{
>
{receipt?.finalityScore ? (
<>
- Assurance: {receipt?.finalityScore}
+ Assurance: {getStatusTheme()?.label}
>
) : (
- 'Vote not ready for verification'
+ <>{getStatusTheme()?.label}>
)}
-
+
{
maxWidth: '406px',
}}
>
- Your vote has been successfully submitted. You might have to wait up to 30 minutes for this to be
- visible on chain. Please check back later to verify your vote.
+ {getStatusTheme()?.description}
)}
@@ -1007,20 +1169,8 @@ const Nominees = () => {
lineHeight: '22px',
}}
>
- Event
+ {i18n.t('nominees.receipt.event')}:
-
-
-
{
lineHeight: '22px',
}}
>
- Proposal
+ {i18n.t('nominees.receipt.nominee')}:
-
+
{
lineHeight: '22px',
}}
>
- Voter Staking Address
+ {i18n.t('nominees.receipt.stakingAddress')}:
-
+
{
lineHeight: '22px',
}}
>
- Status
+ {i18n.t('nominees.receipt.statusTitle')}:
-
+
{
lineHeight: 'normal',
}}
>
- Show Advanced Information
+ {i18n.t('nominees.receipt.showAdvancedInfo')}:
@@ -1208,7 +1358,7 @@ const Nominees = () => {
>
ID
-
+
{
lineHeight: '22px',
}}
>
- Voted at Slot
+ {i18n.t('nominees.receipt.votedAtSlot')}:
-
+
{
lineHeight: '22px',
}}
>
- Vote Proof
+ {i18n.t('nominees.receipt.voteProof')}:
-
+
{
variant="body2"
sx={{ pointer: 'cursor' }}
>
- {receipt?.merkleProof ? JSON.stringify(receipt?.merkleProof || '', null, 4) : 'Not available yet'}
+ {receipt?.merkleProof
+ ? JSON.stringify(receipt?.merkleProof || '', null, 4)
+ : i18n.t('nominees.notAvailable')}
{receipt?.merkleProof ? (
@@ -1334,7 +1486,7 @@ const Nominees = () => {
color: '#03021F',
width: 'auto',
}}
- label="Verify vote proof"
+ label={i18n.t('nominees.verifyVoteProof')}
onClick={verifyVoteProof}
/>
) : null}
@@ -1347,7 +1499,7 @@ const Nominees = () => {
{
lineHeight: '22px',
}}
>
- Your vote has been successfully verified. Click the link or scan the QR code to view the transaction.
+ {i18n.t('nominees.successfullyVerified')}
-
+
+ handleCopyToClipboard(
+ `https://beta.explorer.cardano.org/en/transaction/${receipt?.merkleProof?.transactionHash}`
+ )
+ }
+ style={{ display: 'flex', justifyContent: 'center', width: '100%', marginTop: '24px', cursor: 'pointer' }}
+ >
@@ -1378,7 +1537,7 @@ const Nominees = () => {
color: '#03021F',
width: 'auto',
}}
- label="Done"
+ label={i18n.t('nominees.done')}
onClick={toggleViewFinalReceipt}
/>
@@ -1386,28 +1545,70 @@ const Nominees = () => {
- handleVoteNomineeButton()}
- />
-
+ >
+ {i18n.t('nominees.confirmVoteFor')} {votedNominee?.presentationName} [{selectedNomineeToVote?.id}]
+
+
+
+ {i18n.t('nominees.cancel')}
+
+ handleVoteNomineeButton()}
+ sx={{
+ display: 'flex',
+ width: '162px',
+ padding: '16px 24px',
+ justifyContent: 'center',
+ alignItems: 'center',
+ gap: '10px',
+ borderRadius: '8px',
+ background: '#ACFCC5',
+ textTransform: 'none',
+ color: '#03021F',
+ fontSize: '16px',
+ fontStyle: 'normal',
+ fontWeight: '600',
+ lineHeight: 'normal',
+ '&:hover': { backgroundColor: '#ACFCC5' },
+ }}
+ >
+ {i18n.t('nominees.confirmVote')}
+
+
>
);
diff --git a/ui/summit-2023/src/pages/Nominees/ReadMore.tsx b/ui/summit-2023/src/pages/Nominees/ReadMore.tsx
index 79e7e4468..7447f7ff6 100644
--- a/ui/summit-2023/src/pages/Nominees/ReadMore.tsx
+++ b/ui/summit-2023/src/pages/Nominees/ReadMore.tsx
@@ -4,6 +4,7 @@ import { Typography, Button, Container, IconButton } from '@mui/material';
import CloseIcon from '@mui/icons-material/Close';
import xIcon from '../../common/resources/images/x-icon.svg';
import linkedinIcon from '../../common/resources/images/linkedin-icon.svg';
+import gitHubIcon from '../../common/resources/images/github-icon.svg';
const ReadMore = (props) => {
const { nominee, closeSidePage } = props;
@@ -12,7 +13,9 @@ const ReadMore = (props) => {
closeSidePage(false);
};
- const shouldDisplayGrid = nominee.url.includes('twitter.com') || nominee.url.includes('linkedin.com');
+ const shouldDisplayGrid = nominee.urls.some(
+ (url) => url.includes('twitter.com') || url.includes('linkedin.com') || url.includes('github.com')
+ );
return (
<>
@@ -54,36 +57,58 @@ const ReadMore = (props) => {
marginTop={1}
marginBottom={2}
>
- {nominee.url.includes('twitter.com') ? (
-
-
-
-
-
- ) : null}
- {nominee.url.includes('linkedin.com') ? (
-
-
-
-
+ {nominee.urls.map((url, index) => (
+
+ {url.includes('twitter.com') ? (
+
+
+
+
+
+ ) : null}
+ {url.includes('linkedin.com') ? (
+
+
+
+
+
+ ) : null}
+ {url.includes('github.com') ? (
+
+
+
+
+
+ ) : null}
- ) : null}
+ ))}
) : null}
@@ -97,13 +122,18 @@ const ReadMore = (props) => {
{!shouldDisplayGrid ? (
-
- {nominee.url}
-
+ <>
+ {nominee.urls.map((url, index) => (
+
+ {url}
+
+ ))}
+ >
) : null}
>
diff --git a/ui/summit-2023/src/pages/UserGuide/UserGuide.module.scss b/ui/summit-2023/src/pages/UserGuide/UserGuide.module.scss
index da010bc28..d13e08507 100644
--- a/ui/summit-2023/src/pages/UserGuide/UserGuide.module.scss
+++ b/ui/summit-2023/src/pages/UserGuide/UserGuide.module.scss
@@ -1,5 +1,4 @@
.userguide {
- margin-left: 20px;
.sectionTitle {
max-height: 110px;
margin-top: 40px !important;
diff --git a/ui/summit-2023/src/pages/UserGuide/UserGuide.tsx b/ui/summit-2023/src/pages/UserGuide/UserGuide.tsx
index f8836c259..d728e51aa 100644
--- a/ui/summit-2023/src/pages/UserGuide/UserGuide.tsx
+++ b/ui/summit-2023/src/pages/UserGuide/UserGuide.tsx
@@ -1,8 +1,8 @@
import { Grid, Typography, useMediaQuery, useTheme } from '@mui/material';
import React, { useEffect, useState } from 'react';
+import { i18n } from 'i18n';
import { GuideTile } from './components/GuideTile';
import styles from './UserGuide.module.scss';
-import { i18n } from 'i18n';
import SvgIcon from '@mui/material/SvgIcon';
import { ReactComponent as StepOneIcon } from '../../common/resources/images/step1.svg';
import { ReactComponent as StepTwoIcon } from '../../common/resources/images/step2.svg';
@@ -15,18 +15,19 @@ import Modal from '../../components/common/Modal/Modal';
import SupportedWalletsList from '../../components/SupportedWalletsList/SupportedWalletsList';
const UserGuide = () => {
- const [openSupportedWalletsModal, setOpenSupportedWalletsModal] = useState
(false);
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
+ const [openSupportedWalletsModal, setOpenSupportedWalletsModal] = useState(false);
+
useEffect(() => {
- const openConnectWalletModal = () => {
+ const openSupportedWalletModal = () => {
setOpenSupportedWalletsModal(true);
};
- eventBus.subscribe('openSupportedWalletModal', openConnectWalletModal);
+ eventBus.subscribe('openSupportedWalletModal', openSupportedWalletModal);
return () => {
- eventBus.unsubscribe('openSupportedWalletModal', openConnectWalletModal);
+ eventBus.unsubscribe('openSupportedWalletModal', openSupportedWalletModal);
};
}, []);
diff --git a/ui/summit-2023/src/pages/UserGuide/components/GuideTile.module.scss b/ui/summit-2023/src/pages/UserGuide/components/GuideTile.module.scss
index ced5832ef..2ceec2552 100644
--- a/ui/summit-2023/src/pages/UserGuide/components/GuideTile.module.scss
+++ b/ui/summit-2023/src/pages/UserGuide/components/GuideTile.module.scss
@@ -3,7 +3,7 @@
box-shadow: 2px 2px 5px 0px #061d3c40 !important;
display: flex !important;
flex-direction: column !important;
- margin: 20px !important;
+ margin: 0px 10px 10px 0px !important;
max-width: 630px;
background-color: white;
diff --git a/ui/summit-2023/src/routes/index.tsx b/ui/summit-2023/src/routes/index.tsx
index c2ac183f2..7ce35fef9 100644
--- a/ui/summit-2023/src/routes/index.tsx
+++ b/ui/summit-2023/src/routes/index.tsx
@@ -16,11 +16,11 @@ export const ROUTES = {
CATEGORIES: `${PAGE_PATH}categories`,
NOMINEES: `${PAGE_PATH}nominees`,
LEADERBOARD: `${PAGE_PATH}leaderboard`,
- USERGUIDE: `${PAGE_PATH}user-guide`,
- TERMSANDCONDITIONS: `${PAGE_PATH}termsandconditions`,
- PRIVACYPOLICY: `${PAGE_PATH}privacypolicy`,
+ USER_GUIDE: `${PAGE_PATH}user-guide`,
+ TERMS_AND_CONDITIONS: `${PAGE_PATH}terms-and-conditions`,
+ PRIVACY_POLICY: `${PAGE_PATH}privacy-policy`,
NOMINEES_BY_ID: `${PAGE_PATH}nominees/:categoryId`,
- PAGENOTFOUND: `${PAGE_PATH}404`,
+ PAGE_NOT_FOUND: `${PAGE_PATH}404`,
};
const PageRouter = () => {
@@ -48,19 +48,19 @@ const PageRouter = () => {
element={}
/>
}
/>
}
/>
}
/>
}
/>
) => {
- state.connectedWallet = action.payload.wallet;
- },
setConnectedPeerWallet: (state, action: PayloadAction<{ peerWallet: boolean }>) => {
state.connectedPeerWallet = action.payload.peerWallet;
},
@@ -61,6 +57,10 @@ export const userSlice = createSlice({
state.walletIsLoggedIn = action.payload.isLoggedIn;
},
setVoteReceipt: (state, action: PayloadAction<{ categoryId: string; receipt: VoteReceipt }>) => {
+ if (!action.payload.categoryId.length) {
+ state.receipts = {};
+ return;
+ }
state.receipts = {
...state.receipts,
[action.payload.categoryId]: action.payload.receipt,
@@ -79,7 +79,11 @@ export const userSlice = createSlice({
state.event = action.payload.event;
},
setWinners: (state, action: PayloadAction<{ winners: { categoryId: string; proposalId: string }[] }>) => {
- state.winners = action.payload.winners;
+ let filteredWinners = state.winners.filter(
+ (oldWinner) => !action.payload.winners.some((winner) => winner.categoryId === oldWinner.categoryId)
+ );
+ filteredWinners = [...filteredWinners, ...action.payload.winners];
+ state.winners = filteredWinners;
},
setUserStartsVerification: (
state,
diff --git a/ui/summit-2023/src/utils/dateUtils.ts b/ui/summit-2023/src/utils/dateUtils.ts
index 9ebb246b8..807d469ae 100644
--- a/ui/summit-2023/src/utils/dateUtils.ts
+++ b/ui/summit-2023/src/utils/dateUtils.ts
@@ -1,9 +1,3 @@
-export const formatUTCDate = (date: string) => {
- if (!date) return '';
- const isoDate = new Date(date).toISOString();
- return `${isoDate.substring(0, 10)} ${isoDate.substring(11, 16)} UTC`;
-};
-
export const monthNames = [
'January',
'February',
@@ -19,6 +13,16 @@ export const monthNames = [
'December',
];
+export const formatUTCDate = (date: string) => {
+ if (!date) return '';
+
+ const parsedDate = new Date(date);
+ const monthName = monthNames[parsedDate.getUTCMonth()];
+
+ const isoDate = parsedDate.toISOString();
+ return `${isoDate.substring(0, 4)} ${monthName} ${isoDate.substring(8, 10)}th ${isoDate.substring(11, 16)} UTC`;
+};
+
export const getMonthName = (index: number) => monthNames[index];
export const getDateAndMonth = (date: string) => {
diff --git a/ui/summit-2023/src/utils/session.ts b/ui/summit-2023/src/utils/session.ts
index 7f03999ed..f4766b689 100644
--- a/ui/summit-2023/src/utils/session.ts
+++ b/ui/summit-2023/src/utils/session.ts
@@ -14,6 +14,7 @@ const clearUserInSessionStorage = () => {
};
const tokenIsExpired = (expiresAt: string) => {
+ if (!expiresAt) return true;
const currentDate = new Date();
const givenDate = new Date(expiresAt);
return givenDate < currentDate;
diff --git a/ui/summit-2023/tsconfig.json b/ui/summit-2023/tsconfig.json
index ed78914d4..36112286a 100644
--- a/ui/summit-2023/tsconfig.json
+++ b/ui/summit-2023/tsconfig.json
@@ -19,7 +19,7 @@
"noUnusedLocals": true,
"removeComments": true,
"preserveConstEnums": true,
- "sourceMap": true,
+ "sourceMap": false,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,