diff --git a/.env.example b/.env.example deleted file mode 100644 index 34502a20..00000000 --- a/.env.example +++ /dev/null @@ -1,5 +0,0 @@ -MAIN_VITE_API_URL=API_URL -MAIN_VITE_AUTH_URL=AUTH_URL -MAIN_VITE_STEAMGRIDDB_API_KEY=YOUR_API_KEY -MAIN_VITE_SENTRY_DSN=YOUR_SENTRY_DSN -SENTRY_AUTH_TOKEN= diff --git a/package.json b/package.json index 3e9fc302..bacf40eb 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "@vanilla-extract/recipes": "^0.5.2", "auto-launch": "^5.0.6", "axios": "^1.7.7", - "better-sqlite3": "^11.3.0", + "better-sqlite3": "^11.5.0", "check-disk-space": "^3.4.0", "classnames": "^2.5.1", "color": "^4.2.3", 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 00fe97e3..f70d8c1c 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 @@ -203,3 +203,44 @@ export const achievementsProgressBar = style({ borderRadius: "4px", }, }); + +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 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 d6b55490..4b91edc1 100644 --- a/src/renderer/src/pages/profile/profile-content/profile-content.tsx +++ b/src/renderer/src/pages/profile/profile-content/profile-content.tsx @@ -1,5 +1,5 @@ import { userProfileContext } from "@renderer/context"; -import { useCallback, useContext, useEffect, useMemo } from "react"; +import { useCallback, useContext, useEffect, useMemo, useState } from "react"; import { ProfileHero } from "../profile-hero/profile-hero"; import { useAppDispatch, useFormat } from "@renderer/hooks"; import { setHeaderTitle } from "@renderer/features"; @@ -7,7 +7,12 @@ import { steamUrlBuilder } from "@shared"; import { SPACING_UNIT, vars } from "@renderer/theme.css"; import * as styles from "./profile-content.css"; -import { ClockIcon, TelescopeIcon, TrophyIcon } 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"; @@ -21,6 +26,7 @@ import { formatDownloadProgress, } from "@renderer/helpers"; import { MAX_MINUTES_TO_SHOW_IN_PLAYTIME } from "@renderer/constants"; +import { sortBy } from "lodash-es"; export function ProfileContent() { const { userProfile, isMe, userStats } = useContext(userProfileContext); @@ -29,6 +35,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("")); @@ -78,6 +86,25 @@ export function ProfileContent() { [numberFormatter, t] ); + 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; @@ -93,6 +120,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) => (