Skip to content

Commit

Permalink
WIP - DAO Proposal Details Page
Browse files Browse the repository at this point in the history
  • Loading branch information
ashutoshpw committed Dec 17, 2024
1 parent d56da98 commit 368e249
Show file tree
Hide file tree
Showing 12 changed files with 520 additions and 118 deletions.
4 changes: 4 additions & 0 deletions src/assets/logos/members.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
39 changes: 39 additions & 0 deletions src/components/ui/Badge.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React from "react"
import { Grid, GridProps, Typography } from "@material-ui/core"
import { styled, Theme } from "@material-ui/core/styles"
import hexToRgba from "hex-to-rgba"
import { theme } from "theme"

const getStatusColor = (status: string, theme: Theme): string => {
return "#85c4ff"
}

const StyledGrid = styled(Grid)(({ status, theme }: { status: string; theme: Theme }) => ({
"borderRadius": 50,
"boxSizing": "border-box",
"minWidth": 87,
"textAlign": "center",
"padding": "4px 16px",

"background": hexToRgba(getStatusColor(status, theme), 0.4),
"color": getStatusColor(status, theme),
"& > div": {
height: "100%"
}
}))

const Text = styled(Typography)({
fontWeight: 500,
fontSize: 16,
textTransform: "capitalize"
})

export const Badge: React.FC<{ status: string } & GridProps> = ({ status }) => (
<StyledGrid theme={theme} status={status}>
<Grid container alignItems="center" justifyContent="center">
<Grid item>
<Text> {status} </Text>
</Grid>
</Grid>
</StyledGrid>
)
20 changes: 20 additions & 0 deletions src/components/ui/LinearProgress.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Button, Grid, Theme, LinearProgress as MuiLinearProgress } from "@material-ui/core"
import { styled } from "@mui/material/styles"
import { withStyles } from "@material-ui/core/styles"

const StyledLinearProgress = withStyles((theme: Theme) => ({
root: (props: { variant: "success" | "error" }) => ({
"height": 10,
"backgroundColor": theme.palette.primary.light,
"color": theme.palette.primary.light,
"& .MuiLinearProgress-bar": {
backgroundColor: `${
props.variant === "success" ? theme.palette.secondary.main : theme.palette.error.main
} !important`
}
})
}))((props: { value: number }) => <MuiLinearProgress {...props} value={props.value} variant="determinate" />)

export const LinearProgress = ({ value, variant }: { value: number; variant: "success" | "error" }) => {
return <StyledLinearProgress value={value} variant={variant} />
}
92 changes: 92 additions & 0 deletions src/modules/etherlink/components/EvmProposalCountdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { Grid } from "@material-ui/core"
import { Timer } from "@mui/icons-material"
import { Box } from "@mui/material"
import { Typography } from "@mui/material"
import dayjs from "dayjs"
import React, { useContext, useEffect, useState } from "react"
import { EtherlinkContext } from "services/wagmi/context"
import { GridContainer } from "modules/common/GridContainer"

interface TimeLeft {
days: number
hours: number
minutes: number
seconds: number
}

export const EvmProposalCountdown = () => {
const [timeLeft, setTimeLeft] = useState<TimeLeft>({ days: 0, hours: 0, minutes: 0, seconds: 0 })
const { daoProposalSelected } = useContext(EtherlinkContext)
const targetDate = daoProposalSelected?.votingExpiresAt

useEffect(() => {
const calculateTimeLeft = () => {
const now = dayjs()
const target = dayjs(targetDate)
const diff = target.diff(now, "second")

if (diff <= 0) {
setTimeLeft({ days: 0, hours: 0, minutes: 0, seconds: 0 })
return
}

const days = Math.floor(diff / (24 * 60 * 60))
const hours = Math.floor((diff % (24 * 60 * 60)) / (60 * 60))
const minutes = Math.floor((diff % (60 * 60)) / 60)
const seconds = diff % 60

setTimeLeft({ days, hours, minutes, seconds })
}

calculateTimeLeft()
const timer = setInterval(calculateTimeLeft, 1000)

return () => clearInterval(timer)
}, [targetDate])

if (!targetDate) return null

const TimeUnit = ({ value, unit }: { value: number; unit: string }) => (
<Grid
direction="column"
alignItems="center"
style={{ marginRight: 20, backgroundColor: "#222", borderRadius: 8, paddingBottom: 8, paddingTop: 8 }}
>
<Box
sx={{
fontSize: "24px",
fontFamily: "monospace",
fontWeight: "bold",
borderRadius: 1,
boxShadow: 1,
px: 2,
py: 1,
minWidth: "80px",
textAlign: "center"
}}
>
{value.toString().padStart(2, "0")}
</Box>
<Typography sx={{ color: "white", mt: 1 }} style={{ fontSize: "14px", marginTop: "4px", textAlign: "center" }}>
{unit}
</Typography>
</Grid>
)

return (
<GridContainer container direction="column" style={{ maxWidth: 200 }}>
<Box sx={{ display: "flex", alignItems: "center" }}>
<Timer sx={{ width: 24, height: 24, mr: 2, color: "white" }} />
<Typography variant="h3" color="white" sx={{ fontWeight: 600, fontSize: 18 }}>
Time Left to Vote
</Typography>
</Box>
<Box sx={{ display: "flex", alignItems: "center", justifyContent: "center", color: "white" }}>
{timeLeft.days > 0 && <TimeUnit value={timeLeft.days} unit="Days" />}
<TimeUnit value={timeLeft.hours} unit="Hours" />
<TimeUnit value={timeLeft.minutes} unit="Minutes" />
<TimeUnit value={timeLeft.seconds} unit="Seconds" />
</Box>
</GridContainer>
)
}
35 changes: 22 additions & 13 deletions src/modules/etherlink/components/EvmProposalDetailCard.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from "react"
import React, { useContext } from "react"
import { Grid, styled, Typography, Link, useTheme, useMediaQuery, Popover, withStyles } from "@material-ui/core"
import { GridContainer } from "modules/common/GridContainer"
import { ProposalStatus, TableStatusBadge } from "modules/lite/explorer/components/ProposalTableRowStatusBadge"
Expand All @@ -11,6 +11,8 @@ import { Poll } from "models/Polls"
import dayjs from "dayjs"
import { useNotification } from "modules/common/hooks/useNotification"
import ReactHtmlParser from "react-html-parser"
import { EtherlinkContext } from "services/wagmi/context"
import { Badge } from "components/ui/Badge"

const LogoItem = styled("img")(({ theme }) => ({
cursor: "pointer",
Expand Down Expand Up @@ -84,6 +86,7 @@ const CustomPopover = withStyles({
export const EvmProposalDetailCard: React.FC<{ poll: Poll | undefined }> = ({ poll }) => {
const theme = useTheme()
const isMobileSmall = useMediaQuery(theme.breakpoints.down("sm"))
const { daoProposalSelected } = useContext(EtherlinkContext)
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null)
const openNotification = useNotification()

Expand Down Expand Up @@ -123,7 +126,7 @@ export const EvmProposalDetailCard: React.FC<{ poll: Poll | undefined }> = ({ po
>
<Grid item>
<Typography variant="h1" color="textPrimary">
{poll?.name}
{daoProposalSelected?.title}
</Typography>
</Grid>
<Grid item>
Expand Down Expand Up @@ -172,42 +175,48 @@ export const EvmProposalDetailCard: React.FC<{ poll: Poll | undefined }> = ({ po
<Grid item>
<TableStatusBadge status={poll?.isActive || ProposalStatus.ACTIVE} />
</Grid>
<Grid item>{/* <CommunityBadge id={"DAOID"} /> */}</Grid>
<Grid item>
<CreatorBadge address={poll?.author} />
<Badge status={daoProposalSelected?.type} />
</Grid>
<Grid item>{/* <CommunityBadge id={"DAOID"} /> */}</Grid>
<Grid item direction="row" style={{ gap: 10 }}>
<TextContainer color="textPrimary" variant="body2" style={{ fontSize: 14, marginBottom: 4 }}>
Posted by:
</TextContainer>
<CreatorBadge address={daoProposalSelected?.author} />
</Grid>
</Grid>
</Grid>
</Grid>
<Grid container direction="row">
<Grid item container direction="row" spacing={2} alignItems="center">
<Grid item container direction="row" alignItems="center">
<TextContainer color="textPrimary" variant="body2">
Start date:{" "}
</TextContainer>
<EndText variant="body2" color="textPrimary">
{dayjs(Number(poll?.startTime)).format("lll")}
<EndText variant="body2" color="textPrimary" style={{ fontWeight: 600, borderBottom: "1px solid white" }}>
{dayjs(Number(daoProposalSelected?.createdAt?.seconds)).format("lll")}
</EndText>
<Divider color="textPrimary">-</Divider>
<EndTextContainer color="textPrimary" variant="body2">
End date:{" "}
</EndTextContainer>
<EndText variant="body2" color="textPrimary">
{dayjs(Number(poll?.endTime)).format("lll")}
<EndText variant="body2" color="textPrimary" style={{ fontWeight: 600, borderBottom: "1px solid white" }}>
{daoProposalSelected?.votingExpiresAt?.format("lll")}
</EndText>
</Grid>
</Grid>

<Grid container>
<Typography variant="body2" color="textPrimary" className="proposal-details">
{ReactHtmlParser(poll?.description ? poll?.description : "")}
{ReactHtmlParser(daoProposalSelected?.description ? daoProposalSelected?.description : "")}
</Typography>
</Grid>

{poll?.externalLink ? (
{daoProposalSelected?.externalResource ? (
<Grid style={{ display: isMobileSmall ? "block" : "flex" }} container alignItems="center">
<LogoItem src={LinkIcon} />
<StyledLink color="secondary" href={poll?.externalLink} target="_">
{poll?.externalLink}
<StyledLink color="secondary" href={daoProposalSelected?.externalResource} target="_">
{daoProposalSelected?.externalResource}
</StyledLink>
</Grid>
) : null}
Expand Down
Loading

0 comments on commit 368e249

Please sign in to comment.