Skip to content

Commit

Permalink
Merge pull request #2093 from jk-labs-inc/staging
Browse files Browse the repository at this point in the history
patch PR 2 of week ending 8/20/24
  • Loading branch information
Sean McCaffery authored Aug 14, 2024
2 parents 5fe3a25 + b5ac860 commit 9406040
Show file tree
Hide file tree
Showing 20 changed files with 393 additions and 85 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,6 @@
"dependencies": {},
"devDependencies": {
"husky": "9.1.4",
"turbo": "2.0.12"
"turbo": "2.0.13"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ const Comment: FC<CommentProps> = ({ comment, selectedCommentIds, toggleCommentS
<TrashIcon
className={`
${isSelected ? "hidden" : "block"}
h-7 w-7 text-negative-11 bg-true-black hover:text-negative-10`}
h-7 w-7 text-negative-11 bg-true-black hover:text-negative-10 transition-colors duration-300 ease-in-out`}
/>
</div>
)}
Expand Down
23 changes: 23 additions & 0 deletions packages/react-app-revamp/components/UI/GradientText/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React, { FC } from "react";

interface GradientTextProps {
text: string;
isStrikethrough: boolean;
}

const GradientText: FC<GradientTextProps> = ({ text, isStrikethrough }) => {
return (
<div className="relative inline-block">
<span className="text-[24px] md:text-[31px] font-sabo inline-block">
{isStrikethrough && (
<span className="absolute inset-0 flex items-center overflow-hidden">
<span className="w-full h-0.5 bg-gradient-purple"></span>
</span>
)}
<span className="relative z-10 bg-gradient-purple text-transparent bg-clip-text inline-block">{text}</span>
</span>
</div>
);
};

export default GradientText;
5 changes: 5 additions & 0 deletions packages/react-app-revamp/components/Voting/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { formatNumber } from "@helpers/formatNumber";
import { ChevronRightIcon } from "@heroicons/react/24/outline";
import { useCastVotesStore } from "@hooks/useCastVotes/store";
import { useContestStore } from "@hooks/useContest/store";
import { ContestStateEnum, useContestStateStore } from "@hooks/useContestState/store";
import { useFetchUserVotesOnProposal } from "@hooks/useFetchUserVotesOnProposal";
import { switchChain } from "@wagmi/core";
import { usePathname } from "next/navigation";
Expand Down Expand Up @@ -41,6 +42,8 @@ const VotingWidget: FC<VotingWidgetProps> = ({ proposalId, amountOfVotes, downvo
const isCorrectNetwork = chainId === accountChainId;
const showVoteCharge = charge && charge.type.costToVote && accountData && isCorrectNetwork;
const { currentUserVotesOnProposal } = useFetchUserVotesOnProposal(contestAddress, proposalId);
const { contestState } = useContestStateStore(state => state);
const isContestCanceled = contestState === ContestStateEnum.Canceled;

const handleClick = (value: boolean) => {
setIsUpvote(value);
Expand Down Expand Up @@ -113,6 +116,8 @@ const VotingWidget: FC<VotingWidgetProps> = ({ proposalId, amountOfVotes, downvo
await switchChain(config, { chainId });
};

if (isContestCanceled) return null;

return (
<div className="flex flex-col gap-6 md:w-60">
<hr className="border border-neutral-9" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import DialogModalSendProposal from "@components/_pages/DialogModalSendProposal"
import ListProposals from "@components/_pages/ListProposals";
import useContest from "@hooks/useContest";
import { useContestStore } from "@hooks/useContest/store";
import { ContestStateEnum, useContestStateStore } from "@hooks/useContestState/store";
import { ContestStatus, useContestStatusStore } from "@hooks/useContestStatus/store";
import { useProposalStore } from "@hooks/useProposal/store";
import { useSubmitProposalStore } from "@hooks/useSubmitProposal/store";
Expand Down Expand Up @@ -38,8 +39,12 @@ const ContestTab = () => {
const isMobile = useMediaQuery({ maxWidth: 768 });
const [blurProposals, setBlurProposals] = useState(false);
const isInPwaMode = window.matchMedia("(display-mode: standalone)").matches;
const { contestState } = useContestStateStore(state => state);
const isContestCanceled = contestState === ContestStateEnum.Canceled;

const renderSubmitButton = () => {
if (isContestCanceled) return null;

if (!isConnected) {
return (
<ButtonV3
Expand Down Expand Up @@ -71,8 +76,21 @@ const ContestTab = () => {

return (
<div className="animate-reveal">
<div className="mt-12">
<ContestPrompt prompt={contestPrompt} type="page" />
<div className="mt-6">
<div className="flex flex-col gap-6">
{isContestCanceled ? (
<div className="flex">
<div className="inline-block border border-negative-11 py-2 px-4 rounded-lg">
<p className="text-negative-11 text-[16px] md:text-[20px] font-bold text-center">
{isMobile
? "this contest was canceled by the creator"
: "This contest was canceled by the creator and is no longer active"}
</p>
</div>
</div>
) : null}
<ContestPrompt prompt={contestPrompt} type="page" />
</div>
</div>
{contestStatus === ContestStatus.SubmissionOpen && <div className="mt-8">{renderSubmitButton()}</div>}
<ContestStickyCards />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const FundPoolTokenList: FC<FundPoolTokenListProps> = ({ tokens, onRemoveToken }
<TrashIcon
width={26}
height={26}
className="text-negative-11 cursor-pointer hover:text-negative-10 transition-colors duration-300"
className="text-negative-11 cursor-pointer hover:text-negative-10 transition-colors duration-300 ease-in-out"
onClick={() => handleRemoveToken(token.address)}
/>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { Dialog, DialogBackdrop, DialogPanel } from "@headlessui/react";
import Image from "next/image";
import { FC } from "react";

interface CancelContestModalProps {
isCloseContestModalOpen: boolean;
setIsCloseContestModalOpen: (isOpen: boolean) => void;
cancelContestHandler: () => void;
}

const CancelContestModal: FC<CancelContestModalProps> = ({
isCloseContestModalOpen,
setIsCloseContestModalOpen,
cancelContestHandler,
}) => {
return (
<Dialog open={isCloseContestModalOpen} onClose={setIsCloseContestModalOpen} className="relative z-10">
<DialogBackdrop
transition
className="fixed inset-0 bg-neutral-8 bg-opacity-40 transition-opacity data-[closed]:opacity-0 data-[enter]:duration-300 data-[leave]:duration-200 data-[enter]:ease-out data-[leave]:ease-in"
/>

<div className="fixed inset-0 z-10 w-screen overflow-y-auto">
<div className="flex min-h-full items-end justify-center text-center sm:items-center sm:p-0">
<DialogPanel
transition
className="relative mb-14 md:mb-0 transform overflow-hidden rounded-t-[40px] border-t border-neutral-9 md:border-none md:rounded-[10px] bg-true-black text-left shadow-xl transition-all data-[closed]:translate-y-4 data-[closed]:opacity-0 data-[enter]:duration-300 data-[leave]:duration-200 data-[enter]:ease-out data-[leave]:ease-in sm:my-8 sm:w-full sm:max-w-lg sm:p-6 data-[closed]:sm:translate-y-0 data-[closed]:sm:scale-95"
>
<div className="flex flex-col gap-8 py-6 md:py-16 pl-8 md:pl-32 pr-4 md:pr-16">
<div className="flex justify-between items-center">
<p className="text-[24px] text-neutral-11 font-bold">cancel contest?? 😬</p>
<Image
src="/modal/modal_close.svg"
width={39}
height={33}
alt="close"
className="hidden md:block cursor-pointer"
onClick={() => setIsCloseContestModalOpen(false)}
/>
</div>
<div className="flex flex-col gap-4 text-neutral-11 text-[16px]">
<p>if you proceed, you will cancel this contest.</p>
<p className="font-bold">🚨 players will not be able to keep playing.</p>
<p>
🚨 the contest and entries <i>will</i> remain visible on our site.
</p>
<p>🚨 you can withdraw any funds on the rewards page.</p>
<p>are you really, really, really sure you want to proceed?</p>
</div>
<button
className="mt-4 bg-negative-11 rounded-[40px] w-80 h-10 text-center text-true-black text-[16px] font-bold hover:opacity-80 transition-opacity duration-300 ease-in-out"
onClick={cancelContestHandler}
>
cancel contest 😈
</button>
</div>
</DialogPanel>
</div>
</div>
</Dialog>
);
};

export default CancelContestModal;
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { chains, config } from "@config/wagmi";
import { extractPathSegments } from "@helpers/extractPath";
import { TrashIcon } from "@heroicons/react/24/outline";
import { useContestStore } from "@hooks/useContest/store";
import { useContestState } from "@hooks/useContestState";
import { ContestStateEnum, useContestStateStore } from "@hooks/useContestState/store";
import { switchChain } from "@wagmi/core";
import { usePathname } from "next/navigation";
import { useState } from "react";
import { useAccount } from "wagmi";
import CancelContestModal from "./components/Modal";

const CancelContest = () => {
const pathname = usePathname();
const { chainName } = extractPathSegments(pathname);
const contestChainId = chains.find(chain => chain.name.toLowerCase() === chainName.toLowerCase())?.id;
const { address, chainId } = useAccount();
const isUserOnCorrectChain = contestChainId === chainId;
const { contestAuthorEthereumAddress } = useContestStore(state => state);
const { cancelContest, isLoading, isConfirmed } = useContestState();
const { contestState } = useContestStateStore(state => state);
const [isCloseContestModalOpen, setIsCloseContestModalOpen] = useState(false);
const isAuthor = address === contestAuthorEthereumAddress;
const isNotCanceled = contestState !== ContestStateEnum.Canceled;
const shouldRender = isAuthor && isNotCanceled && (!isConfirmed || isLoading);

if (!shouldRender) return null;

const handleOpenModal = () => setIsCloseContestModalOpen(true);

const handleCancelContest = async () => {
if (!contestChainId) return;

if (!isUserOnCorrectChain) {
await switchChain(config, { chainId: contestChainId });
}

cancelContest();
setIsCloseContestModalOpen(false);
};

return (
<>
<button disabled={isLoading} onClick={handleOpenModal}>
<TrashIcon className="w-6 h-6 text-negative-11 hover:text-negative-10 transition-colors duration-300 ease-in-out" />
</button>

<CancelContestModal
isCloseContestModalOpen={isCloseContestModalOpen}
setIsCloseContestModalOpen={setIsCloseContestModalOpen}
cancelContestHandler={handleCancelContest}
/>
</>
);
};

export default CancelContest;
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import GradientText from "@components/UI/GradientText";
import { ContestStateEnum, useContestStateStore } from "@hooks/useContestState/store";
import { FC } from "react";
import CancelContest from "../CancelContest";

interface ContestNameProps {
contestName: string;
address: string;
chainName: string;
}

const ContestName: FC<ContestNameProps> = ({ contestName, address, chainName }) => {
const { contestState } = useContestStateStore(state => state);
const isContestCanceled = contestState === ContestStateEnum.Canceled;

return (
<div className="flex items-center justify-between">
<GradientText text={contestName} isStrikethrough={isContestCanceled} />
<CancelContest />
</div>
);
};

export default ContestName;
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ChevronUpIcon } from "@heroicons/react/24/outline";
import { useContestStore } from "@hooks/useContest/store";
import { ContestStateEnum, useContestStateStore } from "@hooks/useContestState/store";
import { ContestStatus, useContestStatusStore } from "@hooks/useContestStatus/store";
import { Interweave } from "interweave";
import { UrlMatcher } from "interweave-autolink";
Expand All @@ -16,6 +17,8 @@ const ContestPromptPageV3Layout: FC<ContestPromptPageV3LayoutProps> = ({ prompt
const [isDescriptionOpen, setIsDescriptionOpen] = useState(true);
const [isExpanded, setIsExpanded] = useState(false);
const { contestStatus } = useContestStatusStore(state => state);
const { contestState } = useContestStateStore(state => state);
const isContestCanceled = contestState === ContestStateEnum.Canceled;
const [contestType, contestTitle, contestSummary, contestEvaluate, contestContactDetails] = prompt.split("|");
const isVotingOpenOrClosed =
contestStatus === ContestStatus.VotingOpen || contestStatus === ContestStatus.VotingClosed;
Expand Down Expand Up @@ -86,7 +89,11 @@ const ContestPromptPageV3Layout: FC<ContestPromptPageV3LayoutProps> = ({ prompt
return (
<div className="flex flex-col gap-4">
<div className="flex gap-4 items-center">
<p className="text-[20px] md:text-[24px] text-neutral-11 font-bold">{contestTitle}</p>
<p
className={`text-[20px] md:text-[24px] text-neutral-11 font-bold ${isContestCanceled ? "line-through" : ""}`}
>
{contestTitle}
</p>
<div className="hidden md:flex items-center px-4 leading-tight py-[1px] bg-neutral-10 rounded-[5px] text-true-black text-[16px] font-bold">
{contestType}
</div>
Expand All @@ -101,7 +108,7 @@ const ContestPromptPageV3Layout: FC<ContestPromptPageV3LayoutProps> = ({ prompt
<div className="pl-5">
<div className="border-l border-true-white">
<div
className="overflow-hidden"
className={`overflow-hidden ${isContestCanceled ? "line-through" : ""}`}
style={{ maxHeight: isVotingOpenOrClosed ? "none" : isExpanded ? "none" : "150px" }}
>
<div className="prose prose-invert pl-5 flex flex-col">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { SortOptions, useProposalStore } from "@hooks/useProposal/store";
import { FC, useMemo } from "react";
import ProposalStatisticsPanel from "./components/Panel";
import SortProposalsDropdown from "./components/SortDropdown";
import { ContestStateEnum, useContestStateStore } from "@hooks/useContestState/store";

interface ProposalStatisticsProps {
contestStatus: ContestStatus;
Expand All @@ -15,6 +16,8 @@ const ProposalStatistics: FC<ProposalStatisticsProps> = ({ contestStatus, onMenu
const { sortProposalData } = useProposal();
const isSubmissionOrVotingOpen =
contestStatus === ContestStatus.SubmissionOpen || contestStatus === ContestStatus.VotingOpen;
const { contestState } = useContestStateStore(state => state);
const isContestCanceled = contestState === ContestStateEnum.Canceled;

const handleSortTypeChange = (value: string) => {
sortProposalData(value as SortOptions);
Expand All @@ -37,15 +40,17 @@ const ProposalStatistics: FC<ProposalStatisticsProps> = ({ contestStatus, onMenu

return (
<div className="flex flex-col">
<div className="flex gap-2 items-center">
{isSubmissionOrVotingOpen ? (
<span className="relative flex h-3 w-3">
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-positive-10 opacity-75"></span>
<span className="relative inline-flex rounded-full h-3 w-3 bg-positive-11"></span>
</span>
) : null}
<p className="text-[24px] text-neutral-11 font-bold normal-case">{contestStatusTitle}</p>
</div>
{!isContestCanceled ? (
<div className="flex gap-2 items-center">
{isSubmissionOrVotingOpen ? (
<span className="relative flex h-3 w-3">
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-positive-10 opacity-75"></span>
<span className="relative inline-flex rounded-full h-3 w-3 bg-positive-11"></span>
</span>
) : null}
<p className="text-[24px] text-neutral-11 font-bold normal-case">{contestStatusTitle}</p>
</div>
) : null}
<div className="flex flex-col md:flex-row gap-4 md:justify-between md:items-center border-b border-primary-2 pb-4">
<ProposalStatisticsPanel submissionsCount={submissionsCount} contestStatus={contestStatus} />
{submissionsCount > 1 ? (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
import useContestEvents from "@hooks/useContestEvents";
import { ContestStateEnum, useContestStateStore } from "@hooks/useContestState/store";
import { ContestStatus, useContestStatusStore } from "@hooks/useContestStatus/store";
import ContestCountdown from "./components/Countdown";
import VotingContestQualifier from "./components/VotingQualifier";

const ContestStickyCards = () => {
const contestStatus = useContestStatusStore(state => state.contestStatus);
const { contestState } = useContestStateStore(state => state);
const isContestCanceled = contestState === ContestStateEnum.Canceled;
const { displayReloadBanner } = useContestEvents();

if (contestStatus === ContestStatus.VotingClosed) return null;
if (isContestCanceled || contestStatus === ContestStatus.VotingClosed) {
return (
<div className="mt-8">
<hr className="border-primary-2 border" />
</div>
);
}

return (
<div
Expand Down
Loading

0 comments on commit 9406040

Please sign in to comment.