Skip to content

Commit

Permalink
merge v2
Browse files Browse the repository at this point in the history
  • Loading branch information
ninibear030 committed Sep 26, 2024
2 parents c1e41e8 + 4660760 commit 9a5d5a3
Show file tree
Hide file tree
Showing 15 changed files with 186 additions and 96 deletions.
28 changes: 19 additions & 9 deletions apps/hub/src/app/governance/[genre]/components/delegate-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { Skeleton } from "@bera/ui/skeleton";
import Identicon from "@bera/shared-ui/src/identicon";
import { useGovernance } from "./governance-provider";
import { InputWithLabel } from "@bera/ui/input";
import { cn } from "@bera/ui";

export const DelegateModal = ({
isOpen,
Expand Down Expand Up @@ -85,7 +86,12 @@ export const DelegateModal = ({
</div>
</div>
<div
className="flex cursor-pointer gap-2 rounded-sm p-2 hover:bg-muted border border-border "
className={cn(
"flex cursor-pointer gap-2 rounded-sm p-2 hover:bg-muted border",
delegate === account
? "border-info-foreground"
: "border-border",
)}
onClick={() => {
setInput(false);
setDelegate(account as Address);
Expand All @@ -102,7 +108,12 @@ export const DelegateModal = ({
</div>
</div>
<div
className="flex cursor-pointer gap-2 rounded-sm p-2 hover:bg-muted border border-border "
className={cn(
"flex cursor-pointer gap-2 rounded-sm p-2 hover:bg-muted border",
delegate === account
? "border-border"
: "border-info-foreground",
)}
onClick={() => {
setInput(true);
setDelegate("");
Expand All @@ -119,9 +130,10 @@ export const DelegateModal = ({
</div>
</div>

<div className="px-2">
<div className="font-bold text-foreground">Delegate to: </div>
{input ? (
{input ? (
<div className="px-2">
<div className="font-bold text-foreground">Delegate to: </div>

<InputWithLabel
variant="black"
className="w-full "
Expand All @@ -136,10 +148,8 @@ export const DelegateModal = ({
value={delegate}
onChange={(e) => setDelegate(e.target.value)}
/>
) : (
"My Self"
)}
</div>
</div>
) : null}

<Button
className="mt-4"
Expand Down
13 changes: 3 additions & 10 deletions apps/hub/src/app/governance/[genre]/components/proposal-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
import { StatusEnum } from "../../types";
import { ProgressBarChart } from "./progress-bar-chart";
import { QuorumStatus } from "./quorum-status";
import { StatusBadge } from "../../components/status-badge";

export function ProposalCard({
proposal,
Expand All @@ -37,17 +38,9 @@ export function ProposalCard({
)}
{...props}
>
<div className="flex-1 ">
<div className="flex-1">
<ProposalHeading frontmatter={fm} size="sm" />
<div className="mt-1 text-xs font-medium leading-6 text-muted-foreground md:mt-3">
<Badge
variant={getBadgeColor(proposal.status as StatusEnum)}
className="mr-3 select-none rounded-xs px-2 py-1 text-sm font-semibold capitalize leading-none"
>
{proposal.status}
</Badge>
<span className="inline-block">{getTimeText(proposal)}</span>
</div>
<StatusBadge proposal={proposal} className="mt-1 md:mt-3" />
</div>

{/* {![
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import Image from "next/image";
import { useRouter } from "next/navigation";
import { useQuery } from "@apollo/client";
import { usePollAllProposals, type Proposal } from "@bera/berajs";
import { cloudinaryUrl } from "@bera/config";
import { cloudinaryUrl, isIPFS } from "@bera/config";
import { getProposals } from "@bera/graphql";
import { SearchInput } from "@bera/shared-ui";
import { Skeleton } from "@bera/ui/skeleton";
Expand Down Expand Up @@ -61,6 +61,19 @@ export const ProposalsList = ({
proposal={proposal}
key={`proposal-${proposal.id}`}
dappConfig={dappConfig}
className="hover:cursor-pointer"
// onMouseOver={() => {
// if (!isIPFS) {
// router.prefetch(`/governance/proposal/${proposal.id}`);
// }
// }}
// onClick={() => {
// router.push(
// isIPFS
// ? `/governance/proposal/?id=${proposal.id}`
// : `/governance/proposal/${proposal.id}`,
// );
// }}
/>
))
)}
Expand Down
38 changes: 38 additions & 0 deletions apps/hub/src/app/governance/components/status-badge.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Badge } from "@bera/ui/badge";
import { StatusEnum } from "~/app/governance/types";
import { formatTimeLeft, getBadgeColor, getTimeLeft } from "../helper";
import { Proposal } from "@bera/berajs";
import { cn } from "@bera/ui";

export const StatusBadge = ({
proposal,
className,
}: { proposal: Proposal; className?: string }) => {
return (
<div
className={cn(
"text-xs col-span-full font-medium leading-6 text-muted-foreground",
className,
)}
>
<Badge
variant={getBadgeColor(proposal.status as StatusEnum)}
className="mr-3 select-none rounded-xs px-2 py-1 text-sm leading-none font-semibold capitalize"
>
{proposal.status}
</Badge>
{proposal.status === StatusEnum.PENDING && (
// TODO: get end time from proposal
<span className="whitespace-nowrap">
{formatTimeLeft(getTimeLeft(new Date(proposal.start.timestamp)))} left
</span>
)}
{proposal.status === StatusEnum.ACTIVE && (
// TODO: get end time from proposal
<span className="whitespace-nowrap">
{formatTimeLeft(getTimeLeft(new Date(proposal.end.timestamp)))} left
</span>
)}
</div>
);
};
2 changes: 1 addition & 1 deletion apps/hub/src/app/governance/governance-genre-helper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export const NativeDapps: GovernanceTopic[] = [
export const Others: GovernanceTopic[] = [
{
id: "general",
color: "#2F2F2F",
color: "#AFABAB",
icon: <Icons.ecoFav className="h-16 w-16" />,
name: "General",
slug: "general",
Expand Down
33 changes: 29 additions & 4 deletions apps/hub/src/app/governance/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,34 @@ export const getThemeColor = (ProposalType: ProposalTypeEnum) => {
export const getTopicColor = (topic: string) => {
return [...NativeDapps, ...Others].find((dapp) => dapp.id === topic)?.color;
};
export const getTimeText = (proposal: Proposal) => {

export const getTimeLeft = (date: Date) => {
const now = Date.now();
const targetTimestamp = date.getTime();
const diffInMilliseconds = targetTimestamp - now;
const diffInSeconds = Math.round(diffInMilliseconds / 1000);
return diffInSeconds;
};

/**
* Formats the time left into a string like "8 hours, 23 minutes".
*
* @param timeLeftInSeconds - The time left in seconds.
* @returns A formatted string representing the time left.
*/
export function formatTimeLeft(timeLeftInSeconds: number): string {
const hours = Math.floor(timeLeftInSeconds / 3600);
const minutes = Math.floor((timeLeftInSeconds % 3600) / 60);

const hoursDisplay =
hours > 0 ? `${hours} hour${hours !== 1 ? "s" : ""}` : "";
const minutesDisplay = `${minutes} minute${minutes !== 1 ? "s" : ""}`;

return [hoursDisplay, minutesDisplay].filter(Boolean).join(", ");
}
export const getTimeText = (date: Date) => {
const now = Date.now();
const targetTimestamp = new Date(proposal.createdAt).getTime();
const targetTimestamp = date.getTime();
const diffInMilliseconds = targetTimestamp - now;
const diffInSeconds = Math.round(diffInMilliseconds / 1000);

Expand Down Expand Up @@ -254,13 +279,13 @@ export const getProposalStatus = (proposal: Proposal, currentBlock: number) => {
Number(proposal.proposalVotes[0].for) >=
Number(proposal.proposalVotes[0].against);
if (succeeded) return StatusEnum.PENDING_QUEUE;
else return StatusEnum.DEFEATED;
return StatusEnum.DEFEATED;
}
}
if (proposal.status === "queued") {
const timestamp = new Date().getTime() / 1000;
if (timestamp < proposal.queueEnd) return StatusEnum.IN_QUEUE;
else return StatusEnum.PENDING_EXECUTION;
return StatusEnum.PENDING_EXECUTION;
}
if (proposal.status === "executed") return StatusEnum.EXECUTED;
if (proposal.status === "canceled") return StatusEnum.CANCELED_BY_USER;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,7 @@ export const CancelButton = ({ proposal }: { proposal: Proposal }) => {
<div>Execution in queue</div>
)}
</ActionButton>
) : (
<div>Canceled</div>
)}
) : null}
</>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ import { Card } from "@bera/ui/card";
import { Icons } from "@bera/ui/icons";

import {
getBadgeColor,
getTimeText,
getTotalVotes,
getVotesDataList,
parseProposalBody,
Expand All @@ -32,6 +30,7 @@ import { unstable_serialize } from "swr";
import { ProposalTimeline } from "./proposal-timeline";
import { ProposalHeading } from "~/app/governance/components/proposal-heading";
import { cn } from "@bera/ui";
import { StatusBadge } from "~/app/governance/components/status-badge";

export const ProposalDetailsWrapper = ({
children,
Expand Down Expand Up @@ -92,15 +91,7 @@ export default function ProposalDetails({
<ProposalHeading frontmatter={fm} size="md" />
</div>
<div className="sm:flex grid grid-cols-2 col-span-full items-center justify-between text-sm gap-4 md:gap-6">
<div className="text-xs col-span-full font-medium leading-6 text-muted-foreground">
<Badge
variant={getBadgeColor(proposal.status as StatusEnum)}
className="mr-3 rounded-xs px-2 py-1 text-sm leading-none font-semibold capitalize"
>
{proposal.status}
</Badge>
{getTimeText(proposal)}
</div>
<StatusBadge proposal={proposal} />

<div className="col-span-full text-muted-foreground ">
<VoteInfo
Expand Down Expand Up @@ -186,7 +177,7 @@ export default function ProposalDetails({
</div>
</div>

{[StatusEnum.PENDING, StatusEnum.CANCELED_BY_USER].includes(
{![StatusEnum.PENDING, StatusEnum.CANCELED_BY_USER].includes(
proposal.status as StatusEnum,
) && (
<>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,52 +58,52 @@ export const ProposalTimeline = ({ proposal }: { proposal: Proposal }) => {
date: new Date(proposal.start.timestamp),
isActive: proposal.status === StatusEnum.ACTIVE,
});
}

if (proposal.status === StatusEnum.ACTIVE) {
steps.push({
title: "Voting Period Ends",
date: new Date(proposal.start.timestamp),
isActive: false,
});
} else if (proposal.status === StatusEnum.DEFEATED) {
steps.push({
title: "Proposal Defeated",
date: new Date(0),
isActive: true,
});
} else {
steps.push({
title: "Proposal Passed",
date: new Date(0),
isActive: proposal.status === StatusEnum.PENDING_QUEUE,
});

if (proposal.status !== StatusEnum.PENDING_QUEUE) {
if (proposal.status === StatusEnum.ACTIVE) {
steps.push({
title: "Proposal Queued",
title: "Voting Period Ends",
date: new Date(proposal.start.timestamp),
isActive: false,
});
} else if (proposal.status === StatusEnum.DEFEATED) {
steps.push({
title: "Proposal Defeated",
date: new Date(0),
isActive: true,
});
} else {
steps.push({
title: "Proposal Passed",
date: new Date(0),
isActive: proposal.status === StatusEnum.PENDING_EXECUTION,
isActive: proposal.status === StatusEnum.PENDING_QUEUE,
});

if (proposal.status === StatusEnum.CANCELED_BY_GUARDIAN) {
if (proposal.status !== StatusEnum.PENDING_QUEUE) {
steps.push({
title: "Canceled by guardian",
title: "Proposal Queued",
date: new Date(0),
isActive: true,
});
} else if (proposal.status === StatusEnum.EXECUTED) {
steps.push({
title: "Proposal Executed",
date: new Date(0),
isActive: proposal.status === StatusEnum.EXECUTED,
});
} else if (proposal.status === StatusEnum.PENDING_EXECUTION) {
steps.push({
title: "Proposal Executs",
date: new Date(0),
isActive: true,
isActive: proposal.status === StatusEnum.PENDING_EXECUTION,
});

if (proposal.status === StatusEnum.CANCELED_BY_GUARDIAN) {
steps.push({
title: "Canceled by guardian",
date: new Date(0),
isActive: true,
});
} else if (proposal.status === StatusEnum.EXECUTED) {
steps.push({
title: "Proposal Executed",
date: new Date(0),
isActive: proposal.status === StatusEnum.EXECUTED,
});
} else if (proposal.status === StatusEnum.PENDING_EXECUTION) {
steps.push({
title: "Proposal Executs",
date: new Date(0),
isActive: true,
});
}
}
}
}
Expand Down
22 changes: 15 additions & 7 deletions apps/hub/src/app/governance/proposal/[proposalId]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,25 @@ export default async function Page({
config: defaultBeraConfig,
});

if (!proposal) {
return notFound();
}

return (
<ProposalDetailsWrapper id={params.proposalId} content={proposal}>
<ProposalDetails proposalId={params.proposalId} />
</ProposalDetailsWrapper>
);
}

export function generateStaticParams() {
return [
{
proposalId: "0x",
},
];
}
export const generateStaticParams = async () => {
if (isIPFS) {
return [
{
proposalId: "0x",
},
];
}

return [];
};
Loading

0 comments on commit 9a5d5a3

Please sign in to comment.