Skip to content

Commit

Permalink
Merge branch 'testnet' into margin-bug
Browse files Browse the repository at this point in the history
  • Loading branch information
ayushtom authored Jul 2, 2024
2 parents ba7b374 + ac04049 commit dcb2d0c
Show file tree
Hide file tree
Showing 83 changed files with 5,400 additions and 455 deletions.
3 changes: 2 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
],
"parser": "@typescript-eslint/parser",
"rules": {
"@next/next/no-img-element": "off"
"@next/next/no-img-element": "off",
"@next/next/no-document-import-in-page": "off"
},
"overrides": [
{
Expand Down
84 changes: 48 additions & 36 deletions app/[addressOrDomain]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import ProfileCard from "@components/UI/profileCard/profileCard";
import {
fetchLeaderboardRankings,
fetchLeaderboardToppers,
getBoosts,
getCompletedQuests,
getPendingBoostClaims,
} from "@services/apiService";
import { useAccount } from "@starknet-react/core";
import Blur from "@components/shapes/blur";
Expand All @@ -18,17 +18,18 @@ import ProfileCardSkeleton from "@components/skeletons/profileCardSkeleton";
import { getDataFromId } from "@services/starknetIdService";
import { usePathname, useRouter } from "next/navigation";
import ErrorScreen from "@components/UI/screens/errorScreen";
import { ClaimableQuestDocument, CompletedQuests, PendingBoostClaim, QuestDocument } from "../../types/backTypes";
import { CompletedQuests } from "../../types/backTypes";
import QuestSkeleton from "@components/skeletons/questsSkeleton";
import QuestCardCustomised from "@components/dashboard/CustomisedQuestCard";
import QuestStyles from "@styles/Home.module.css";
import { QuestsContext } from "@context/QuestsProvider";
import { Tab, Tabs } from "@mui/material";
import { CustomTabPanel, a11yProps } from "@components/pages/home/questAndCollectionTabs";
import { getClaimableQuests } from "@utils/quest";
import QuestClaim from "@components/quests/questClaim";
import { MILLISECONDS_PER_WEEK } from "@constants/common";
import useBoost from "@hooks/useBoost";
import BoostCard from "@components/quest-boost/boostCard";
import Typography from "@components/UI/typography/typography";
import { TEXT_TYPE } from "@constants/typography";
import { a11yProps } from "@components/UI/tabs/a11y";
import { CustomTabPanel } from "@components/UI/tabs/customTab";

type AddressOrDomainProps = {
params: {
Expand All @@ -42,6 +43,7 @@ export default function Page({ params }: AddressOrDomainProps) {
const { address } = useAccount();
const { starknetIdNavigator } = useContext(StarknetIdJsContext);
const [initProfile, setInitProfile] = useState(false);
const { getBoostClaimStatus } = useBoost();
const [leaderboardData, setLeaderboardData] =
useState<LeaderboardToppersData>({
best_users: [],
Expand All @@ -58,10 +60,7 @@ export default function Page({ params }: AddressOrDomainProps) {
const dynamicRoute = usePathname();
const [questsLoading, setQuestsLoading] = useState(true);
const [tabIndex, setTabIndex] = React.useState(0);
const [claimableQuests, setClaimableQuests] = useState<ClaimableQuestDocument[]>([]);
const [pendingBoostClaims, setPendingBoostClaims] = useState<
PendingBoostClaim[] | undefined
>([]);
const [claimableQuests, setClaimableQuests] = useState<Boost[]>([]);

const handleChangeTab = useCallback(
(event: React.SyntheticEvent, newValue: number) => {
Expand All @@ -70,8 +69,6 @@ export default function Page({ params }: AddressOrDomainProps) {
[]
);

const { quests } = useContext(QuestsContext);

useEffect(() => {
if (!address) setIsOwner(false);
}, [address]);
Expand All @@ -90,26 +87,46 @@ export default function Page({ params }: AddressOrDomainProps) {
[address, identity]
);

const fetchBoosts = useCallback(async () => {
if (!address) return;
try {
const boosts = await getBoosts();
if (
!boosts ||
!completedQuests ||
boosts.length === 0 ||
completedQuests.length === 0
)
return;

useEffect(() => {
const getAllPendingBoostClaims = async () => {
const allPendingClaims = await getPendingBoostClaims(
hexToDecimal(address)
);
if (allPendingClaims) {
setPendingBoostClaims(allPendingClaims);
}
};
const filteredBoosts = boosts.filter((boost) => {
const userBoostCompletionCheck = boost.quests.every((quest) =>
completedQuests.includes(quest)
);
const userBoostCheckStatus = getBoostClaimStatus(address, boost.id);
const isBoostExpired =
(new Date().getTime() - boost.expiry) / MILLISECONDS_PER_WEEK <= 3 &&
boost.expiry < Date.now();

getAllPendingBoostClaims();
}, [address]);
return (
userBoostCompletionCheck &&
!userBoostCheckStatus &&
isBoostExpired &&
boost.winner != null
);
});

useEffect(() => {
const data = getClaimableQuests(quests, pendingBoostClaims);
if (data) {
setClaimableQuests(data);
if (filteredBoosts.length > 0) {
setClaimableQuests(filteredBoosts);
}
} catch (err) {
console.log("Error while fetching boosts", err);
}
}, [address, pendingBoostClaims, quests]);
}, [address, completedQuests]);

useEffect(() => {
fetchBoosts();
}, [address, completedQuests]);

const fetchRanking = useCallback(
async (addr: string) => {
Expand Down Expand Up @@ -382,15 +399,10 @@ export default function Page({ params }: AddressOrDomainProps) {
<div className="flex flex-wrap gap-10 justify-center lg:justify-start">
{claimableQuests &&
claimableQuests.map((quest) => (
<QuestClaim
<BoostCard
key={quest.id}
title={quest.title_card}
onClick={() => router.push(`/quest-boost/${quest.boostId}`)}
imgSrc={quest.img_card}
name={quest.issuer}
reward={quest.rewards_title}
id={quest.boostId}
expired={quest.expired}
boost={quest}
completedQuests={completedQuests}
/>
))}
</div>
Expand Down
65 changes: 65 additions & 0 deletions app/admin/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
"use client";

import React, { useCallback, useEffect, useRef } from "react";
import styles from "@styles/admin.module.css";
import Button from "@components/UI/button";
import { useRouter } from "next/navigation";
import { AdminService } from "@services/authService";
import { useNotification } from "@context/NotificationProvider";
import { getExpireTimeFromJwt } from "@utils/jwt";

export default function Page() {
const router = useRouter();
const password = useRef<HTMLInputElement>(null);
const { showNotification } = useNotification();

useEffect(() => {
const tokenExpiryTime = getExpireTimeFromJwt();
if (tokenExpiryTime && tokenExpiryTime > new Date().getTime()) {
router.push("/admin/quests");
}
}, []);

const handleAdminLogin = useCallback(async () => {
try {
if (!password.current) return console.error("Password field not found");
const passcode = password?.current.value;
const response = await AdminService.login({ passcode });
if (!response) showNotification("Invalid passcode", "error");
localStorage.setItem("token", response.token);
router.push("/admin/quests");
} catch (error) {
console.log("Error while logging in", error);
}
}, [password]);

return (
<div className={styles.screen}>
<div className={styles.banner}>
<div className="flex flex-1 w-full p-6">
<div className="flex flex-col justify-evenly gap-4">
<div className="flex flex-col gap-4">
<p className={styles.subtitleText}>Quest Overview</p>
<h1 className={styles.headingText}>Admin quest control</h1>
</div>
<div className="flex flex-col gap-2">
<label htmlFor="fname">Passcode:</label>
<input
ref={password}
className={styles.input}
id="fname"
type="password"
/>
</div>
<div className="w-fit">
<Button onClick={handleAdminLogin}>
Access the admin dashboard
</Button>
</div>
</div>
</div>
<div className={styles.image}></div>
</div>
</div>
);
}
Loading

0 comments on commit dcb2d0c

Please sign in to comment.