Skip to content

Commit

Permalink
refactor: change from pagination to scroll on badgedex (#578)
Browse files Browse the repository at this point in the history
  • Loading branch information
Darguima authored Dec 7, 2023
1 parent 96c1c7e commit 4152abe
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 44 deletions.
45 changes: 42 additions & 3 deletions components/Badge/index.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,57 @@
import Link from "next/link";
import { ReactEventHandler, useState } from "react";

interface BadgeProps {
name: string;
id: string | number;
avatar: string;
tokens: string | number;
owned: boolean;
}

export default function Badge({ name, id, avatar, tokens, owned }: BadgeProps) {
const [badgeLoaded, setBadgeLoaded] = useState(false);
const [fallbackRan, setFallbackRan] = useState(false)

const imageOnError: ReactEventHandler<HTMLImageElement> = (e) => {
// prevent infinite loop fallback
if (fallbackRan) {
setBadgeLoaded(true);
return
}

setBadgeLoaded(false);
e.currentTarget.src = "/images/badges/badge-not-found.svg";
setFallbackRan(true)
};

export default function Badge({ name, id, avatar, tokens, owned }) {
return (
<Link
href={`/badge/${id}`}
className={`h-full w-full ${owned ? "opacity-100" : "opacity-30"}`}
>
<div className="select-none">
<img src={avatar} alt={name}></img>
<div className="flex justify-center items-center w-full aspect-square select-none">

{!badgeLoaded && <BadgeSkeleton />}

<img
src={avatar}
alt={name}
onLoad={() => setBadgeLoaded(true)}
onError={imageOnError}
/>
</div>

<div className="flex flex-col justify-items-center text-center font-iregular">
<div>{name}</div>
<div>{tokens} 💰 </div>
</div>
</Link>
);
}

const BadgeSkeleton = () => {
return (
<div className="w-10/12 aspect-square rounded-full bg-gray-500 animate-pulse opacity-10"/>
);
};
35 changes: 35 additions & 0 deletions components/GoToTop/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { faArrowUp } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { useEffect, useState } from "react";

export default function GoToTop() {
const [showButton, setShowButton] = useState(false);

useEffect(() => {
window.addEventListener("scroll", () => {
if (window.scrollY > 400) {
setShowButton(true);
} else {
setShowButton(false);
}
});
}, []);

const goToTop = () => {
window.scrollTo({
top: 0,
behavior: "smooth",
});
};

return (
<button
className={`transition-translate fixed right-5 bottom-5 h-12 w-12 cursor-pointer rounded-full bg-white duration-300 ${
showButton ? "" : "translate-y-52"
}`}
onClick={goToTop}
>
<FontAwesomeIcon icon={faArrowUp} className="text-3xl text-black" />
</button>
);
}
80 changes: 39 additions & 41 deletions layout/Attendee/Badgedex/Badgedex.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,38 +5,35 @@ import { getAllBadges } from "@lib/api";

import Layout from "@components/Layout";

import Pagination from "./components/Pagination";
import ErrorMessage from "@components/ErrorMessage";
import Badge from "@components/Badge";
import BadgeFilter from "@components/BadgeFilter";
import GoToTop from "@components/GoToTop";

interface Badges {
id: string;
type: string;
name: string;
export interface Badges {
avatar: string;
begin: string;
description: string;
end: string;
id: number;
name: string;
tokens: number;
type: number;
}

interface UserWithBadges {
user: {
badges: Badges[];
};
}

function Badgedex() {
const { user } = useAuth();
const { user }: UserWithBadges = useAuth();
const [allBadges, updateAllBadges] = useState<Badges[]>([]);
const [all, updateAll] = useState(true);
const [filter, updateFilter] = useState(null);
const [error, setError] = useState();
const [currentPage, setCurrentPage] = useState(1);
const [badgesPerPage] = useState(10);

const indexOfLastVisitor = currentPage * badgesPerPage;
const indexOfFirstVisitor = indexOfLastVisitor - badgesPerPage;
const currentBadges: any = allBadges.slice(
indexOfFirstVisitor,
indexOfLastVisitor
);

const paginate = (pageNumber) => setCurrentPage(pageNumber);
if (currentBadges.length === 0 && currentPage !== 1) {
paginate(0);
}
const [currentBadges, setCurrentBadges] = useState(allBadges);

useEffect(() => {
getAllBadges()
Expand All @@ -46,6 +43,13 @@ function Badgedex() {
});
}, []);

useEffect(() => {
const badges = all ? allBadges : user.badges;
setCurrentBadges(
badges.filter((badge) => badge.type == filter || filter == null)
);
}, [user, allBadges, filter, all]);

return (
<Layout title="BadgeDex" description="Explore all existing badges">
<div className="border-slate-400 pt-10 text-white xl:flex xl:flex-auto">
Expand Down Expand Up @@ -80,31 +84,25 @@ function Badgedex() {
</div>
</div>
<div className="mt-8 grid grid-cols-1 gap-x-10 gap-y-5 text-white xs:grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-6">
{all
? currentBadges
.filter((badge) => badge.type == filter || filter == null)
.map((badge) => (
<Badge
key={badge.id}
owned={user.badges.map((b) => b.id).includes(badge.id)}
{...badge}
/>
))
: user.badges
.filter((badge) => badge.type == filter || filter == null)
.map((badge) => <Badge key={badge.id} owned={true} {...badge} />)}
</div>
{all && (
<div className="mt-5">
<Pagination
badgesPerPage={badgesPerPage}
totalBadges={allBadges.length}
paginate={paginate}
currentPage={currentPage}
{currentBadges.map((badge) => (
<Badge
key={badge.id}
owned={!all || user.badges.map((b) => b.id).includes(badge.id)}
{...badge}
/>
))}
</div>

{currentBadges.length == 0 && (
<div className="flex h-full w-full items-center justify-center">
<h2 className="mt-2 text-lg font-medium text-white">
No Badges to show!
</h2>
</div>
)}

{error && <ErrorMessage />}
<GoToTop />
</Layout>
);
}
Expand Down
1 change: 1 addition & 0 deletions public/images/badges/badge-not-found.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 4152abe

Please sign in to comment.