From 2cebc73789bcc656f2d3e429d010d40afc992b9e Mon Sep 17 00:00:00 2001 From: Chubby Granny Chaser Date: Sun, 28 Sep 2025 00:50:51 +0100 Subject: [PATCH] feat: adding profile sorting --- .../profile-content/profile-content.scss | 86 ---------- .../profile-content/profile-content.tsx | 158 ++---------------- 2 files changed, 16 insertions(+), 228 deletions(-) diff --git a/src/renderer/src/pages/profile/profile-content/profile-content.scss b/src/renderer/src/pages/profile/profile-content/profile-content.scss index 7faae2db..2f274e11 100644 --- a/src/renderer/src/pages/profile/profile-content/profile-content.scss +++ b/src/renderer/src/pages/profile/profile-content/profile-content.scss @@ -77,92 +77,6 @@ flex-shrink: 0; } - &__sort-container { - display: flex; - flex-direction: column; - align-items: flex-start; - gap: calc(globals.$spacing-unit); - margin-bottom: calc(globals.$spacing-unit * 2); - } - - &__sort-label { - color: rgba(255, 255, 255, 0.6); - font-size: 14px; - font-weight: 400; - } - - &__sort-options { - display: flex; - align-items: center; - gap: calc(globals.$spacing-unit); - font-size: 14px; - } - - &__sort-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; - } - - &.loading { - color: rgba(201, 170, 113, 0.8); - font-weight: 500; - position: relative; - - &::after { - content: ""; - position: absolute; - right: -20px; - top: 50%; - transform: translateY(-50%); - width: 12px; - height: 12px; - border: 2px solid rgba(201, 170, 113, 0.3); - border-top: 2px solid rgba(201, 170, 113, 0.8); - border-radius: 50%; - animation: spin 1s linear infinite; - } - } - - &:disabled { - cursor: not-allowed; - opacity: 0.6; - } - - span { - display: inline-block; - } - } - - @keyframes spin { - 0% { - transform: translateY(-50%) rotate(0deg); - } - 100% { - transform: translateY(-50%) rotate(360deg); - } - } - - &__sort-separator { - color: rgba(255, 255, 255, 0.3); - font-size: 14px; - } &__collapse-button { background: none; diff --git a/src/renderer/src/pages/profile/profile-content/profile-content.tsx b/src/renderer/src/pages/profile/profile-content/profile-content.tsx index f330bf97..8de16d3d 100644 --- a/src/renderer/src/pages/profile/profile-content/profile-content.tsx +++ b/src/renderer/src/pages/profile/profile-content/profile-content.tsx @@ -3,13 +3,7 @@ import { useContext, useEffect, useMemo, useRef, useState } from "react"; import { ProfileHero } from "../profile-hero/profile-hero"; import { useAppDispatch, useFormat } from "@renderer/hooks"; import { setHeaderTitle } from "@renderer/features"; -import { - TelescopeIcon, - ChevronRightIcon, - TrophyIcon, - ClockIcon, - HistoryIcon, -} from "@primer/octicons-react"; +import { TelescopeIcon, ChevronRightIcon } from "@primer/octicons-react"; import { useTranslation } from "react-i18next"; import { UserGame } from "@types"; import { LockedProfile } from "./locked-profile"; @@ -18,102 +12,18 @@ import { FriendsBox } from "./friends-box"; import { RecentGamesBox } from "./recent-games-box"; import { UserStatsBox } from "./user-stats-box"; import { UserLibraryGameCard } from "./user-library-game-card"; +import { SortOptions } from "./sort-options"; import { useSectionCollapse } from "@renderer/hooks/use-section-collapse"; import { motion, AnimatePresence } from "framer-motion"; +import { + sectionVariants, + gameCardVariants, + gameGridVariants, + chevronVariants, + GAME_STATS_ANIMATION_DURATION_IN_MS, +} from "./profile-animations"; import "./profile-content.scss"; -const GAME_STATS_ANIMATION_DURATION_IN_MS = 3500; - -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 }, - }, - }, -}; - -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], - }, - }, -}; - -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, - }, - }, -}; - -const chevronVariants = { - collapsed: { - rotate: 0, - transition: { - duration: 0.2, - ease: "easeInOut", - }, - }, - expanded: { - rotate: 90, - transition: { - duration: 0.2, - ease: "easeInOut", - }, - }, -}; - type SortOption = "playtime" | "achievementCount" | "playedRecently"; export function ProfileContent() { @@ -128,7 +38,6 @@ export function ProfileContent() { const [statsIndex, setStatsIndex] = useState(0); const [isAnimationRunning, setIsAnimationRunning] = useState(true); const [sortBy, setSortBy] = useState("playedRecently"); - const [isLoadingSort, setIsLoadingSort] = useState(false); const [prevLibraryGames, setPrevLibraryGames] = useState([]); const [prevPinnedGames, setPrevPinnedGames] = useState([]); const statsAnimation = useRef(-1); @@ -148,10 +57,7 @@ export function ProfileContent() { useEffect(() => { if (userProfile) { - setIsLoadingSort(true); - getUserLibraryGames(sortBy).finally(() => { - setIsLoadingSort(false); - }); + getUserLibraryGames(sortBy); } }, [sortBy, getUserLibraryGames, userProfile]); @@ -186,7 +92,6 @@ export function ProfileContent() { const { numberFormatter } = useFormat(); - // Function to check if game lists have changed const gamesHaveChanged = ( current: UserGame[], previous: UserGame[] @@ -197,11 +102,9 @@ export function ProfileContent() { ); }; - // Check if animations should run const shouldAnimateLibrary = gamesHaveChanged(libraryGames, prevLibraryGames); const shouldAnimatePinned = gamesHaveChanged(pinnedGames, prevPinnedGames); - // Update previous games when lists change useEffect(() => { setPrevLibraryGames(libraryGames); }, [libraryGames]); @@ -214,40 +117,6 @@ export function ProfileContent() { return userProfile?.relation?.status === "ACCEPTED"; }, [userProfile]); - const SortOptions = () => ( -
- Sort by: -
- - | - - | - -
-
- ); - const content = useMemo(() => { if (!userProfile) return null; @@ -269,7 +138,9 @@ export function ProfileContent() { return (
- {hasAnyGames && } + {hasAnyGames && ( + + )} {!hasAnyGames && (
@@ -467,6 +338,9 @@ export function ProfileContent() { pinnedGames, isPinnedCollapsed, toggleSection, + shouldAnimateLibrary, + shouldAnimatePinned, + sortBy, ]); return (