Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 86337f9

Browse files
committed
merge: main
2 parents 3414745 + e4a649d commit 86337f9

File tree

51 files changed

+655
-311
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+655
-311
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ documentation](https://nextjs.org/docs/deployment) for more details.
3838
<img src=".github/brand/cesium-DARK.svg#gh-light-mode-only" width="300">
3939
<img src=".github/brand/cesium-LIGHT.svg#gh-dark-mode-only" width="300">
4040

41-
Copyright (c) 2023, CeSIUM.
41+
Copyright (c) 2024, CeSIUM.
4242

4343
This project is licensed under the MIT License - see the [LICENSE][license]
4444
file for details.

components/Badge/index.tsx

+14-18
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import Link from "next/link";
2-
import { AllHTMLAttributes, ReactEventHandler, useState } from "react";
2+
import { AllHTMLAttributes, memo, useState } from "react";
33

44
interface BadgeProps
55
extends Omit<AllHTMLAttributes<HTMLDivElement>, "id" | "name" | "type"> {
66
name: string;
77
id: string | number;
88
avatar: string;
99
tokens: string | number;
10-
owned?: boolean;
10+
owned: boolean;
1111
disableLink?: boolean;
1212
disableOwnedHighlight?: boolean;
1313
}
@@ -23,21 +23,9 @@ const Badge: React.FC<BadgeProps> = ({
2323
...rest
2424
}) => {
2525
const [badgeLoaded, setBadgeLoaded] = useState(false);
26-
const [fallbackRan, setFallbackRan] = useState(false);
26+
const [badge404, setBadge404] = useState(false);
2727

28-
const highlightBadge = owned || !disableOwnedHighlight || !badgeLoaded;
29-
30-
const imageOnError: ReactEventHandler<HTMLImageElement> = (e) => {
31-
// prevent infinite loop fallback
32-
if (fallbackRan) {
33-
setBadgeLoaded(true);
34-
return;
35-
}
36-
37-
setBadgeLoaded(false);
38-
e.currentTarget.src = "/images/badges/badge-not-found.svg";
39-
setFallbackRan(true);
40-
};
28+
const highlightBadge = owned || disableOwnedHighlight || !badgeLoaded;
4129

4230
return (
4331
<div
@@ -51,11 +39,19 @@ const Badge: React.FC<BadgeProps> = ({
5139
<div className="flex aspect-square w-full select-none items-center justify-center">
5240
{!badgeLoaded && <BadgeSkeleton />}
5341

42+
{badge404 && (
43+
<img src={"/images/badges/badge-not-found.svg"} alt={name} />
44+
)}
45+
5446
<img
5547
src={avatar}
5648
alt={name}
5749
onLoad={() => setBadgeLoaded(true)}
58-
onError={imageOnError}
50+
onError={() => {
51+
setBadge404(true);
52+
setBadgeLoaded(true);
53+
}}
54+
hidden={!badgeLoaded || badge404}
5955
/>
6056
</div>
6157

@@ -68,7 +64,7 @@ const Badge: React.FC<BadgeProps> = ({
6864
);
6965
};
7066

71-
export default Badge;
67+
export default memo(Badge);
7268

7369
const BadgeSkeleton = () => {
7470
return (

components/Layout/Layout.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ const roleNavigations = {
2020
"identifier",
2121
],
2222
admin: ["scanner", "visitors", "badges", "leaderboard", "users", "events"],
23-
staff: ["badges", "leaderboard", "prizes", "identifier"],
23+
staff: ["badges", "leaderboard", "prizes", "identifier", "cv"],
2424
};
2525

2626
type LayoutProps = {

components/Navbar/index.jsx

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ const userNavigation = (type) => {
3030
{ name: "Leaderboard", slug: "/staff/leaderboard" },
3131
{ name: "Give Badges", slug: "/staff/badges" },
3232
{ name: "Give Prizes", slug: "/staff/prizes" },
33+
{ name: "Upload CV", slug: "/staff/cv" },
3334
];
3435
case USER.ROLES.SPONSOR:
3536
return [
+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import React, { useEffect } from "react";
2+
3+
interface INotificationProps {
4+
title: string;
5+
onClose: () => void;
6+
}
7+
8+
const Notification: React.FC<INotificationProps> = ({ title, onClose }) => {
9+
useEffect(() => {
10+
const timer = setTimeout(() => {
11+
onClose();
12+
}, 2500);
13+
14+
return () => clearTimeout(timer);
15+
}, [onClose]);
16+
17+
return (
18+
<div className="fixed right-4 top-0 z-50 h-16 w-72">
19+
<div className="pointer-events-auto min-w-full overflow-hidden rounded-lg bg-quinary shadow-lg ring-1 ring-black ring-opacity-5 ">
20+
<div className="min-w-full p-4 ">
21+
<div className="flex items-start">
22+
<div className="flex-shrink-0"></div>
23+
<div className="ml-3 w-0 flex-1 pt-0.5">
24+
<p className="text-md font-medium text-white">{title}</p>
25+
</div>
26+
<div className="ml-4 flex flex-shrink-0">
27+
<button
28+
onClick={onClose}
29+
className="inline-flex rounded-md bg-quinary text-white hover:text-primary focus:outline-none"
30+
>
31+
<span className="sr-only">Close</span>
32+
<span className="h-5 w-5">X</span>
33+
</button>
34+
</div>
35+
</div>
36+
</div>
37+
</div>
38+
</div>
39+
);
40+
};
41+
42+
export default Notification;

components/Notification/index.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default } from "./Notification";

components/ResetPassword/index.tsx

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { useState } from "react";
2+
import { resetPassword } from "@lib/api";
3+
import Notification from "@components/Notification";
4+
5+
export default function ResetPassword(user: any) {
6+
const [showNotification, setShowNotification] = useState(false);
7+
8+
const onResetPassword = (user: any) => {
9+
resetPassword(user.email)
10+
.then((_) => {
11+
setShowNotification(true);
12+
})
13+
.catch((_) => {
14+
setShowNotification(false);
15+
});
16+
};
17+
18+
const handleNotificationClose = () => {
19+
setShowNotification(false);
20+
};
21+
22+
return (
23+
<>
24+
<button
25+
className="inline-block h-auto pl-6 pb-5 text-quinary underline"
26+
onClick={(e) => {
27+
e.preventDefault();
28+
onResetPassword(user);
29+
}}
30+
>
31+
Reset Password
32+
</button>
33+
{showNotification && (
34+
<Notification
35+
title="Password reset email sent"
36+
onClose={handleNotificationClose}
37+
/>
38+
)}
39+
</>
40+
);
41+
}

0 commit comments

Comments
 (0)