diff --git a/.env.example b/.env.example index 3ef399f73..90a1a76bb 100644 --- a/.env.example +++ b/.env.example @@ -1,2 +1,2 @@ MAIN_VITE_API_URL=API_URL -MAIN_VITE_AUTH_URL=AUTH_URL +MAIN_VITE_AUTH_URL=AUTH_URL \ No newline at end of file diff --git a/src/renderer/src/pages/profile/profile-content/profile-content.css.ts b/src/renderer/src/pages/profile/profile-content/profile-content.css.ts index 847e94920..185ad85ba 100644 --- a/src/renderer/src/pages/profile/profile-content/profile-content.css.ts +++ b/src/renderer/src/pages/profile/profile-content/profile-content.css.ts @@ -229,6 +229,25 @@ export const link = style({ }, }); +export const gridSorting = style({ + display: "flex", // Usa flexbox para organizar o layout + justifyContent: "space-between", // Espaça o label e os botões + alignItems: "center", // Centraliza verticalmente + marginBottom: `${SPACING_UNIT * 2}px`, +}); + +export const sortOption = style({ + transition: "all ease 0.2s", + display: "inline-flex", // Altera para inline-flex para alinhar itens no botão + alignItems: "center", // Centraliza o ícone e o texto verticalmente + gap: "10px", // Define o espaçamento entre o ícone e o texto + color: vars.color.body, + ":hover": { + color: "white", + cursor: "pointer", + }, +}); + export const gameCardStats = style({ width: "100%", height: "100%", @@ -236,3 +255,25 @@ export const gameCardStats = style({ flexShrink: "0", flexGrow: "0", }); + +export const selectedSortOption = style({ + transition: "all ease 0.2s", + display: "inline-flex", // Altera para inline-flex para alinhar itens no botão + alignItems: "center", // Centraliza o ícone e o texto verticalmente + color: "white", + gap: "10px", // Define o espaçamento entre o ícone e o texto + ":hover": { + cursor: "pointer", + }, +}); + +export const sortOptionsWrapper = style({ + display: "flex", + flexDirection: "row", + gap: "5px", +}); + +export const sortDivider = style({ + border: `0.5px solid ${vars.color.body}`, + margin: "0px 5px", +}); 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 951eb41bf..96275fa9f 100644 --- a/src/renderer/src/pages/profile/profile-content/profile-content.tsx +++ b/src/renderer/src/pages/profile/profile-content/profile-content.tsx @@ -1,11 +1,16 @@ import { userProfileContext } from "@renderer/context"; -import { useContext, useEffect, useMemo, useRef, useState } from "react"; +import { useContext, useEffect, useMemo, useState, useRef } from "react"; import { ProfileHero } from "../profile-hero/profile-hero"; import { useAppDispatch, useFormat } from "@renderer/hooks"; import { setHeaderTitle } from "@renderer/features"; import { SPACING_UNIT } from "@renderer/theme.css"; import * as styles from "./profile-content.css"; -import { TelescopeIcon } from "@primer/octicons-react"; +import { + ClockIcon, + TelescopeIcon, + TrophyIcon, + HistoryIcon, +} from "@primer/octicons-react"; import { useTranslation } from "react-i18next"; import { useNavigate } from "react-router-dom"; import { LockedProfile } from "./locked-profile"; @@ -14,6 +19,7 @@ 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 { sortBy } from "lodash-es"; const GAME_STATS_ANIMATION_DURATION_IN_MS = 3500; @@ -27,6 +33,8 @@ export function ProfileContent() { const { t } = useTranslation("user_profile"); + const [sortOption, setSortOption] = useState("lastPlayed"); // Estado para o critério de ordenação + useEffect(() => { dispatch(setHeaderTitle("")); @@ -72,6 +80,25 @@ export function ProfileContent() { return userProfile?.relation?.status === "ACCEPTED"; }, [userProfile]); + const sortGames = (games) => { + if (sortOption === "playtime") { + return sortBy(games, (game) => -game.playTimeInSeconds); + } else if (sortOption === "achievements") { + return sortBy(games, (game) => { + return game.achievementCount > 0 + ? -(game.unlockedAchievementCount / game.achievementCount) + : 0; + }); + } else if (sortOption === "lastPlayed") { + return sortBy(games, (game) => { + return game.lastTimePlayed + ? -new Date(game.lastTimePlayed).getTime() + : 0; + }); + } + return games; + }; + const content = useMemo(() => { if (!userProfile) return null; @@ -87,6 +114,8 @@ export function ProfileContent() { const shouldShowRightContent = hasGames || userProfile.friends.length > 0; + const sortedGames = sortGames(userProfile.libraryGames || []); // Ordena os jogos conforme o critério + return (
+
+
+ +
+
+ +
+ +
+ +
+
+
    - {userProfile?.libraryGames?.map((game) => ( + {sortedGames.map((game) => (