Skip to content

Commit

Permalink
Merge pull request #129 from starknet-id/feat/add_timer
Browse files Browse the repository at this point in the history
feat: add timer
  • Loading branch information
fricoben authored Aug 11, 2023
2 parents 7176922 + d567931 commit 8801a00
Show file tree
Hide file tree
Showing 8 changed files with 247 additions and 27 deletions.
4 changes: 4 additions & 0 deletions components/quests/featuredQuest.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import styles from "../../styles/quests.module.css";
import Button from "../UI/button";
import { useMediaQuery } from "@mui/material";
import FeaturedQuestSkeleton from "../skeletons/featuredQuestSkeleton";
import Timer from "./timer";

type FeaturedQuestProps = {
onClick?: () => void;
Expand All @@ -11,6 +12,7 @@ type FeaturedQuestProps = {
issuer?: Issuer;
reward?: string;
desc?: string;
expiry: string | null | undefined;
};

const FeaturedQuest: FunctionComponent<FeaturedQuestProps> = ({
Expand All @@ -20,6 +22,7 @@ const FeaturedQuest: FunctionComponent<FeaturedQuestProps> = ({
issuer,
reward,
desc,
expiry,
}) => {
const isSmallScreen = useMediaQuery("(max-width: 1024px)");

Expand All @@ -38,6 +41,7 @@ const FeaturedQuest: FunctionComponent<FeaturedQuestProps> = ({
</div>
</div>
<img src={imgSrc} className={styles.featuredQuestImage} />
{expiry ? <Timer expiry={Number(expiry)} /> : null}
</div>
) : !onClick && !isSmallScreen ? (
<FeaturedQuestSkeleton />
Expand Down
55 changes: 55 additions & 0 deletions components/quests/timer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import React, { FunctionComponent, useEffect, useState } from "react";
import styles from "../../styles/components/timer.module.css";

type TimerProps = {
expiry: number;
fixed?: boolean;
};

const Timer: FunctionComponent<TimerProps> = ({ expiry, fixed = true }) => {
const [timeLeft, setTimeLeft] = useState(expiry - Date.now());

useEffect(() => {
const intervalId = setInterval(() => {
setTimeLeft(expiry - Date.now());
}, 1000);

return () => clearInterval(intervalId);
}, [expiry]);

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

return (
<>
{fixed ? <div className={styles.timerBackground} /> : null}
<div className={`${fixed ? `${styles.timerFixed}` : `${styles.timer}`}`}>
<div className={styles.title}>Expires in</div>
<div className={styles.categories}>
<div>days</div>
<div>hours</div>
<div>minutes</div>
<div>seconds</div>
</div>
<div className={styles.dates}>
<div>
<span className={styles.day}>{days}</span>:
</div>
<div>
<span className={styles.hour}>{hours}</span>:
</div>
<div>
<span className={styles.minute}>{minutes}</span>:
</div>
<div className={styles.second}>{seconds}</div>
</div>
</div>
</>
);
};

export default Timer;
20 changes: 10 additions & 10 deletions components/skeletons/tasksSkeleton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,33 @@ const TasksSkeleton: FunctionComponent = () => {
<>
<Skeleton
variant="rectangular"
width={728}
height={68}
sx={{ bgcolor: "grey.900" }}
sx={{ bgcolor: "grey.900", maxWidth: "768px", width: "90%" }}
/>
<Skeleton
variant="rectangular"
width={728}
height={68}
sx={{ bgcolor: "grey.900" }}
sx={{ bgcolor: "grey.900", maxWidth: "768px", width: "90%" }}
/>
<Skeleton
variant="rectangular"
width={728}
height={68}
sx={{ bgcolor: "grey.900" }}
sx={{ bgcolor: "grey.900", maxWidth: "768px", width: "90%" }}
/>
<Skeleton
variant="rectangular"
width={728}
height={68}
sx={{ bgcolor: "grey.900" }}
sx={{ bgcolor: "grey.900", maxWidth: "768px", width: "90%" }}
/>
<Skeleton
variant="rectangular"
width={728}
height={104}
sx={{ bgcolor: "grey.900", marginTop: "1.5rem" }}
sx={{
bgcolor: "grey.900",
marginTop: "1.5rem",
maxWidth: "768px",
width: "90%",
}}
/>
</>
);
Expand Down
34 changes: 17 additions & 17 deletions pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const Quests: NextPage = () => {
.then((data: QuestDocument[] | QueryError) => {
if (!(data as QueryError).error) {
setQuests(data as QuestDocument[]);
const activeQuests = (data as QuestDocument[]);
const activeQuests = data as QuestDocument[];
setFeaturedQuest(
activeQuests.length >= 1
? activeQuests[activeQuests.length - 1]
Expand All @@ -47,26 +47,26 @@ const Quests: NextPage = () => {
}}
reward={featuredQuest?.rewards_title}
desc={featuredQuest?.desc}
expiry={featuredQuest?.expiry_timestamp}
/>
<h1 className={styles.title}>Accomplish your Starknet Quests</h1>
<div className={styles.questContainer}>
{quests ? (
quests
.map((quest) => {
return (
<Quest
key={quest.id}
title={quest.title_card}
onClick={() => router.push(`/quest/${quest.id}`)}
imgSrc={quest.img_card}
issuer={{
name: quest.issuer,
logoFavicon: quest.logo,
}}
reward={quest.rewards_title}
/>
);
})
quests.map((quest) => {
return (
<Quest
key={quest.id}
title={quest.title_card}
onClick={() => router.push(`/quest/${quest.id}`)}
imgSrc={quest.img_card}
issuer={{
name: quest.issuer,
logoFavicon: quest.logo,
}}
reward={quest.rewards_title}
/>
);
})
) : (
<QuestsSkeleton />
)}
Expand Down
5 changes: 5 additions & 0 deletions pages/quest/[questPage].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import TasksSkeleton from "../../components/skeletons/tasksSkeleton";
import RewardSkeleton from "../../components/skeletons/rewardSkeleton";
import { generateCodeChallenge } from "../../utils/codeChallenge";
import ErrorScreen from "../../components/UI/screens/errorScreen";
import Timer from "../../components/quests/timer";

const splitByNftContract = (
rewards: EligibleReward[]
Expand Down Expand Up @@ -63,6 +64,7 @@ const QuestPage: NextPage = () => {
title_card: "",
hidden: false,
disabled: false,
expiry_timestamp: "loading",
});
const [tasks, setTasks] = useState<UserTask[]>([]);
const [rewardsEnabled, setRewardsEnabled] = useState<boolean>(false);
Expand Down Expand Up @@ -312,6 +314,9 @@ const QuestPage: NextPage = () => {
<p className="text-center max-w-lg">{quest.desc}</p>
)}
</div>
{quest?.expiry_timestamp && quest?.expiry_timestamp !== "loading" ? (
<Timer expiry={Number(quest?.expiry_timestamp)} fixed={false} />
) : null}
<div className={styles.taskContainer}>
{tasks.length === 0 || quest.rewards_title === "loading" ? (
<TasksSkeleton />
Expand Down
154 changes: 154 additions & 0 deletions styles/components/timer.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
.timerFixed {
position: absolute;
right: 24px;
bottom: 24px;
display: flex;
padding: 8px 12px;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 8px;
border-radius: 8px;
background: linear-gradient(90deg, var(--background), #070708);
box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.25);
width: 298px;
height: 84px;
z-index: 0;
}

.timer {
position: relative;
display: flex;
padding: 8px 12px;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 8px;
border-radius: 8px;
background: linear-gradient(90deg, var(--background), #070708);
box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.25);
width: 298px;
height: 84px;
margin: 48px auto;
}

.timer::after {
content: "";
position: absolute;
top: -10px;
right: -10px;
left: 0;
bottom: 0;
background: linear-gradient(5deg, var(--background) 70%, transparent);
border-radius: 8px;
z-index: -1;
}

.timer::before {
content: "";
position: absolute;
top: -1px;
right: -1px;
left: 1px;
bottom: 1px;
background: linear-gradient(
90deg,
#437aba 0%,
#59c2e8 45%,
#00ff77 60%,
#59c2e8 70%,
#437aba50 100%
);
border-radius: 8px;
z-index: -1;
}

.timerBackground {
position: absolute;
right: 23px;
bottom: 25px;
border-radius: 8px;
background: linear-gradient(
90deg,
#437aba 0%,
#59c2e8 45%,
#00ff77 60%,
#59c2e8 70%,
#437aba50 100%
);
width: 270px;
height: 84px;
mask: linear-gradient(3deg, transparent 80%, black);
}

.title {
text-align: center;
font-family: Sora;
font-size: 14px;
font-style: normal;
font-weight: 700;
line-height: 20px;
background: var(--primary-gradient, linear-gradient(90deg, #6AFFAF 0%, #5CE3FE 100%));
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}

.categories {
display: flex;
flex-direction: row;
color: var(--secondary);
text-align: center;
font-family: Sora;
font-size: 12px;
font-style: normal;
font-weight: 400;
line-height: 16px;
width: 296px;
padding: 0 12px;
}

.categories > div {
margin-right: 36px;
width: 68px;
text-align: left;
}

.dates {
display: flex;
flex-direction: row;
color: var(--secondary);
text-align: right;
font-family: Sora;
font-size: 16px;
font-style: normal;
font-weight: 700;
line-height: 20px;
letter-spacing: 0.16px;
}

.dates > div {
width: 65px;
text-align: left;
}

.space {
padding: 0 13px;
}

.day {
padding: 0 15px 0 12px;
}

.hour {
padding: 0 15px 0 12px;
}

.minute {
padding: 0 15px 0 27px;

}

.second {
text-align: right !important;
}
1 change: 1 addition & 0 deletions styles/quests.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@
align-items: center;
padding: 0.4rem;
gap: 0.5rem;
position: relative;
}

.featuredQuestInfos {
Expand Down
1 change: 1 addition & 0 deletions types/backTypes.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ type QuestDocument = {
title_card: string;
hidden: boolean;
disabled: boolean;
expiry_timestamp: string | null;
};

type NFTItem = {
Expand Down

1 comment on commit 8801a00

@vercel
Copy link

@vercel vercel bot commented on 8801a00 Aug 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.