Skip to content

Commit bbc7f64

Browse files
committed
Add props, mappings and translations
1 parent 71673c8 commit bbc7f64

File tree

6 files changed

+182
-92
lines changed

6 files changed

+182
-92
lines changed

src/components/v2/ProgressBar/index.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export interface IProgressBarProps {
1919
markTooltip?: ITooltipProps['title'];
2020
className?: string;
2121
tooltipPlacement?: ITooltipProps['placement'];
22+
progressColorOverride?: string;
2223
}
2324

2425
export const ProgressBar = ({
@@ -33,13 +34,15 @@ export const ProgressBar = ({
3334
markTooltip,
3435
className,
3536
tooltipPlacement = 'top',
37+
progressColorOverride,
3638
}: IProgressBarProps) => {
3739
const safeValue = value < max ? value : max;
3840

3941
const marks = mark ? [{ value: mark }] : undefined;
4042
const styles = useStyles({
4143
over: mark ? safeValue > mark : false,
4244
secondaryOver: mark ? !!(secondaryValue && secondaryValue > mark) : false,
45+
progressColorOverride,
4346
});
4447

4548
const renderMark = (props?: NonNullable<SliderTypeMap['props']['componentsProps']>['mark']) => (

src/components/v2/ProgressBar/styles.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,33 @@
11
import { css } from '@emotion/react';
22
import { useTheme } from '@mui/material';
33

4-
export const useStyles = ({ over, secondaryOver }: { over: boolean; secondaryOver: boolean }) => {
4+
export const useStyles = ({
5+
over,
6+
secondaryOver,
7+
progressColorOverride,
8+
}: {
9+
over: boolean;
10+
secondaryOver: boolean;
11+
progressColorOverride?: string;
12+
}) => {
513
const theme = useTheme();
614
return {
715
slider: css`
816
display: block;
917
color: ${over ? theme.palette.interactive.error50 : theme.palette.interactive.success};
18+
color: ${progressColorOverride};
1019
background-color: ${theme.palette.background.default};
1120
height: ${theme.spacing(2)};
1221
padding: 0 !important;
1322
&.Mui-disabled {
1423
color: ${over ? theme.palette.interactive.error50 : theme.palette.interactive.success};
24+
color: ${progressColorOverride};
1525
}
1626
.MuiSlider-track {
1727
background-color: ${over
1828
? theme.palette.interactive.error50
1929
: theme.palette.interactive.success};
30+
background-color: ${progressColorOverride};
2031
height: ${theme.spacing(2)};
2132
border-radius: ${theme.spacing(1)};
2233
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/** @jsxImportSource @emotion/react */
2+
import React, { useMemo } from 'react';
3+
import Typography from '@mui/material/Typography';
4+
import { useTranslation } from 'translation';
5+
import { PALETTE } from 'theme/MuiThemeProvider/muiTheme';
6+
import { ProgressBar } from '../../ProgressBar';
7+
import { useStyles } from '../styles';
8+
9+
interface IActiveVotingProgressProps {
10+
votedFor?: string;
11+
votedAgainst?: string;
12+
abstain?: string;
13+
}
14+
15+
export const ActiveVotingProgress: React.FC<IActiveVotingProgressProps> = ({
16+
votedFor,
17+
votedAgainst,
18+
abstain,
19+
}) => {
20+
const styles = useStyles();
21+
const { t } = useTranslation();
22+
23+
const activeProposalVotingData = useMemo(
24+
() => [
25+
{
26+
id: 'for',
27+
label: t('voteProposalUi.statusCard.for'),
28+
value: votedFor,
29+
progressBarProps: {
30+
// TODO: calculating progress
31+
ariaLabel: 'votes for',
32+
value: 20,
33+
step: 1,
34+
min: 1,
35+
max: 100,
36+
},
37+
},
38+
{
39+
id: 'against',
40+
label: t('voteProposalUi.statusCard.against'),
41+
value: votedAgainst,
42+
progressBarProps: {
43+
// TODO: calculating progress
44+
progressColorOverride: PALETTE.interactive.error50,
45+
ariaLabel: 'votes against',
46+
value: 20,
47+
step: 1,
48+
min: 1,
49+
max: 100,
50+
},
51+
},
52+
{
53+
id: 'abstain',
54+
label: t('voteProposalUi.statusCard.abstain'),
55+
value: abstain,
56+
progressBarProps: {
57+
// TODO: calculating progress
58+
progressColorOverride: PALETTE.text.secondary,
59+
ariaLabel: 'votes abstain',
60+
value: 20,
61+
step: 1,
62+
min: 1,
63+
max: 100,
64+
},
65+
},
66+
],
67+
[votedFor, votedAgainst, abstain],
68+
);
69+
70+
return (
71+
<>
72+
{activeProposalVotingData.map(({ id, label, value, progressBarProps }) => {
73+
if (!value) {
74+
return null;
75+
}
76+
return (
77+
<React.Fragment key={id}>
78+
<div css={styles.voteRow}>
79+
<Typography variant="small2" color="textPrimary">
80+
{label}
81+
</Typography>
82+
83+
<Typography variant="small2" color="textPrimary">
84+
{value}
85+
</Typography>
86+
</div>
87+
<ProgressBar {...progressBarProps} />
88+
</React.Fragment>
89+
);
90+
})}
91+
</>
92+
);
93+
};

src/components/v2/VoteProposalUi/index.stories.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export const Active = () => (
2121
votedAgainst="2130.02 XVS"
2222
abstain="100 XVS"
2323
voteStatus="votedFor"
24+
cancelDate="27 Jun 13:54"
2425
/>
2526
);
2627
export const Queued = () => (

src/components/v2/VoteProposalUi/index.tsx

Lines changed: 70 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,110 +1,82 @@
11
/** @jsxImportSource @emotion/react */
22
import React, { useMemo } from 'react';
3+
import { SerializedStyles } from '@emotion/react';
34
import Paper from '@mui/material/Paper';
45
import Grid from '@mui/material/Grid';
56
import Typography from '@mui/material/Typography';
67

78
import { useTranslation } from 'translation';
8-
import { Icon } from '../Icon';
9-
import { ProgressBar } from '../ProgressBar';
9+
import { Icon, IconName } from '../Icon';
10+
import { Spinner } from '../Spinner';
11+
import { ActiveVotingProgress } from './ActiveVotingProgress';
1012
import { useStyles } from './styles';
1113

12-
type ProposalStatus = 'active' | 'queued' | 'readyToExecute' | 'executed' | 'cancelled';
14+
type ProposalCardStatus = 'queued' | 'readyToExecute' | 'executed' | 'cancelled';
15+
type ProposalStatus = 'active' | ProposalCardStatus;
1316

1417
interface IStatusCard {
15-
status: ProposalStatus;
16-
votedFor?: string;
17-
votedAgainst?: string;
18-
abstain?: string;
18+
status: ProposalCardStatus;
1919
}
2020

21-
const StatusCard: React.FC<IStatusCard> = ({ status, votedFor, votedAgainst, abstain }) => {
21+
const StatusCard: React.FC<IStatusCard> = ({ status }) => {
2222
const styles = useStyles();
2323
const { t } = useTranslation();
2424

25-
switch (status) {
26-
case 'active':
27-
return (
28-
<>
29-
<div css={styles.voteRow}>
30-
<Typography variant="small2" color="textPrimary">
31-
{t('voteProposalUi.statusCard.for')}
32-
</Typography>
33-
34-
<Typography variant="small2" color="textPrimary">
35-
{votedFor}
36-
</Typography>
37-
</div>
38-
<ProgressBar value={20} step={1} ariaLabel="progress" min={1} max={100} />
39-
40-
<div css={styles.voteRow}>
41-
<Typography variant="small2" color="textPrimary">
42-
{t('voteProposalUi.statusCard.against')}
43-
</Typography>
44-
45-
<Typography variant="small2" color="textPrimary">
46-
{votedAgainst}
47-
</Typography>
48-
</div>
49-
<ProgressBar value={20} step={1} ariaLabel="progress" min={1} max={100} />
50-
51-
<div css={styles.voteRow}>
52-
<Typography variant="small2" color="textPrimary">
53-
{t('voteProposalUi.statusCard.abstain')}
54-
</Typography>
25+
const statusContent: Record<
26+
ProposalCardStatus,
27+
{
28+
iconWrapperCss: SerializedStyles | SerializedStyles[];
29+
iconName: IconName;
30+
iconCss: SerializedStyles | SerializedStyles[];
31+
label: string;
32+
}
33+
> = useMemo(
34+
() => ({
35+
queued: {
36+
iconWrapperCss: [styles.iconWrapper, styles.iconDotsWrapper],
37+
iconName: 'dots',
38+
iconCss: styles.icon,
39+
label: t('voteProposalUi.statusCard.queued'),
40+
},
41+
readyToExecute: {
42+
iconWrapperCss: [styles.iconWrapper, styles.iconInfoWrapper],
43+
iconName: 'exclamation',
44+
iconCss: styles.icon,
45+
label: t('voteProposalUi.statusCard.readyToExecute'),
46+
},
47+
executed: {
48+
iconWrapperCss: [styles.iconWrapper, styles.iconMarkWrapper],
49+
iconName: 'mark',
50+
iconCss: [styles.icon, styles.iconCheck],
51+
label: t('voteProposalUi.statusCard.executed'),
52+
},
53+
cancelled: {
54+
iconWrapperCss: [styles.iconWrapper, styles.iconCloseWrapper],
55+
iconName: 'close',
56+
iconCss: styles.icon,
57+
label: t('voteProposalUi.statusCard.cancelled'),
58+
},
59+
}),
60+
[],
61+
);
5562

56-
<Typography variant="small2" color="textPrimary">
57-
{abstain}
58-
</Typography>
59-
</div>
60-
<ProgressBar value={5} step={1} ariaLabel="progress" min={1} max={100} />
61-
</>
62-
);
63+
switch (status) {
6364
case 'queued':
64-
return (
65-
<>
66-
<div css={[styles.iconWrapper, styles.iconDotsWrapper]}>
67-
<Icon css={styles.icon} name="dots" />
68-
</div>
69-
<Typography css={styles.statusText} variant="body2">
70-
{t('voteProposalUi.statusCard.queued')}
71-
</Typography>
72-
</>
73-
);
7465
case 'readyToExecute':
75-
return (
76-
<>
77-
<div css={[styles.iconWrapper, styles.iconInfoWrapper]}>
78-
<Icon css={styles.icon} name="exclamation" />
79-
</div>
80-
<Typography css={styles.statusText} variant="body2">
81-
{t('voteProposalUi.statusCard.readyToExecute')}
82-
</Typography>
83-
</>
84-
);
8566
case 'executed':
86-
return (
87-
<>
88-
<div css={[styles.iconWrapper, styles.iconMarkWrapper]}>
89-
<Icon css={[styles.icon, styles.iconCheck]} name="mark" />
90-
</div>
91-
<Typography css={styles.statusText} variant="body2">
92-
{t('voteProposalUi.statusCard.executed')}
93-
</Typography>
94-
</>
95-
);
96-
default:
9767
case 'cancelled':
9868
return (
9969
<>
100-
<div css={[styles.iconWrapper, styles.iconCloseWrapper]}>
101-
<Icon css={styles.icon} name="close" />
70+
<div css={statusContent[status].iconWrapperCss}>
71+
<Icon css={statusContent[status].iconCss} name={statusContent[status].iconName} />
10272
</div>
10373
<Typography css={styles.statusText} variant="body2">
104-
{t('voteProposalUi.statusCard.cancelled')}
74+
{statusContent[status].label}
10575
</Typography>
10676
</>
10777
);
78+
default:
79+
return <Spinner variant="small" />;
10880
}
10981
};
11082

@@ -115,6 +87,7 @@ interface IVoteProposalUiProps {
11587
proposalNumber: number;
11688
proposalText: string;
11789
proposalStatus: ProposalStatus;
90+
cancelDate?: string;
11891
voteStatus?: VoteStatus;
11992
votedFor?: string;
12093
votedAgainst?: string;
@@ -126,6 +99,7 @@ export const VoteProposalUi: React.FC<IVoteProposalUiProps> = ({
12699
proposalNumber,
127100
proposalText,
128101
proposalStatus,
102+
cancelDate,
129103
voteStatus,
130104
votedFor,
131105
votedAgainst,
@@ -179,25 +153,30 @@ export const VoteProposalUi: React.FC<IVoteProposalUiProps> = ({
179153
</Typography>
180154

181155
<div css={styles.cardFooter}>
182-
<Typography variant="small2">
183-
{t('voteProposalUi.activeUntil')}
184-
<Typography variant="small2" color="textPrimary">
185-
27 Jun 13:54
156+
{cancelDate && (
157+
<Typography variant="small2">
158+
{t('voteProposalUi.activeUntil')}
159+
<Typography css={styles.activeUntilDate} variant="small2" color="textPrimary">
160+
{cancelDate}
161+
</Typography>
186162
</Typography>
187-
</Typography>
163+
)}
188164

189165
<Typography color="textPrimary" variant="small2">
190-
27h : 13m : 54s
166+
27h : 13m : 54s {/* // TODO: countdown calculating */}
191167
</Typography>
192168
</div>
193169
</Grid>
194170
<Grid css={[styles.gridItem, styles.gridItemRight]} item xs={12} sm={4}>
195-
<StatusCard
196-
status={proposalStatus}
197-
votedFor={votedFor}
198-
votedAgainst={votedAgainst}
199-
abstain={abstain}
200-
/>
171+
{proposalStatus === 'active' ? (
172+
<ActiveVotingProgress
173+
votedFor={votedFor}
174+
votedAgainst={votedAgainst}
175+
abstain={abstain}
176+
/>
177+
) : (
178+
<StatusCard status={proposalStatus} />
179+
)}
201180
</Grid>
202181
</Grid>
203182
</Paper>

src/components/v2/VoteProposalUi/styles.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ export const useStyles = () => {
5454
display: flex;
5555
justify-content: space-between;
5656
`,
57+
activeUntilDate: css`
58+
margin-left: ${theme.spacing(1)};
59+
`,
5760
gridItemRight: css`
5861
padding-left: ${theme.spacing(6)};
5962
border-left: 1px solid ${theme.palette.secondary.light};

0 commit comments

Comments
 (0)