feat: adding profile sorting

This commit is contained in:
Chubby Granny Chaser
2025-09-28 01:01:06 +01:00
parent 2cebc73789
commit 92af5c2b23
4 changed files with 192 additions and 1 deletions

View File

@@ -0,0 +1,91 @@
export const sectionVariants = {
collapsed: {
opacity: 0,
y: -20,
height: 0,
transition: {
duration: 0.3,
ease: [0.25, 0.1, 0.25, 1],
opacity: { duration: 0.1 },
y: { duration: 0.1 },
height: { duration: 0.2 },
},
},
expanded: {
opacity: 1,
y: 0,
height: "auto",
transition: {
duration: 0.3,
ease: [0.25, 0.1, 0.25, 1],
opacity: { duration: 0.2, delay: 0.1 },
y: { duration: 0.3 },
height: { duration: 0.3 },
},
},
};
export const gameCardVariants = {
hidden: {
opacity: 0,
y: 20,
scale: 0.95,
},
visible: {
opacity: 1,
y: 0,
scale: 1,
transition: {
duration: 0.4,
ease: [0.25, 0.1, 0.25, 1],
},
},
exit: {
opacity: 0,
y: -20,
scale: 0.95,
transition: {
duration: 0.3,
ease: [0.25, 0.1, 0.25, 1],
},
},
};
export const gameGridVariants = {
hidden: {
opacity: 0,
},
visible: {
opacity: 1,
transition: {
duration: 0.3,
staggerChildren: 0.1,
delayChildren: 0.1,
},
},
exit: {
opacity: 0,
transition: {
duration: 0.2,
},
},
};
export const chevronVariants = {
collapsed: {
rotate: 0,
transition: {
duration: 0.2,
ease: "easeInOut",
},
},
expanded: {
rotate: 90,
transition: {
duration: 0.2,
ease: "easeInOut",
},
},
};
export const GAME_STATS_ANIMATION_DURATION_IN_MS = 3500;

View File

@@ -77,7 +77,6 @@
flex-shrink: 0;
}
&__collapse-button {
background: none;
border: none;

View File

@@ -0,0 +1,56 @@
@use "../../../scss/globals.scss";
.sort-options {
&__container {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: calc(globals.$spacing-unit);
margin-bottom: calc(globals.$spacing-unit * 2);
}
&__label {
color: rgba(255, 255, 255, 0.6);
font-size: 14px;
font-weight: 400;
}
&__options {
display: flex;
align-items: center;
gap: calc(globals.$spacing-unit);
font-size: 14px;
}
&__option {
background: none;
border: none;
color: rgba(255, 255, 255, 0.4);
cursor: pointer;
padding: 4px 0;
font-size: 14px;
font-weight: 300;
transition: all ease 0.2s;
display: flex;
align-items: center;
gap: 6px;
&:hover:not(:disabled) {
color: rgba(255, 255, 255, 0.6);
}
&.active {
color: rgba(255, 255, 255, 0.9);
font-weight: 500;
}
span {
display: inline-block;
}
}
&__separator {
color: rgba(255, 255, 255, 0.3);
font-size: 14px;
}
}

View File

@@ -0,0 +1,45 @@
import { TrophyIcon, ClockIcon, HistoryIcon } from "@primer/octicons-react";
import { useTranslation } from "react-i18next";
import "./sort-options.scss";
type SortOption = "playtime" | "achievementCount" | "playedRecently";
interface SortOptionsProps {
sortBy: SortOption;
onSortChange: (sortBy: SortOption) => void;
}
export function SortOptions({ sortBy, onSortChange }: SortOptionsProps) {
const { t } = useTranslation("user_profile");
return (
<div className="sort-options__container">
<span className="sort-options__label">Sort by:</span>
<div className="sort-options__options">
<button
className={`sort-options__option ${sortBy === "achievementCount" ? "active" : ""}`}
onClick={() => onSortChange("achievementCount")}
>
<TrophyIcon size={16} />
<span>{t("achievements_earned")}</span>
</button>
<span className="sort-options__separator">|</span>
<button
className={`sort-options__option ${sortBy === "playedRecently" ? "active" : ""}`}
onClick={() => onSortChange("playedRecently")}
>
<HistoryIcon size={16} />
<span>{t("played_recently")}</span>
</button>
<span className="sort-options__separator">|</span>
<button
className={`sort-options__option ${sortBy === "playtime" ? "active" : ""}`}
onClick={() => onSortChange("playtime")}
>
<ClockIcon size={16} />
<span>{t("playtime")}</span>
</button>
</div>
</div>
);
}