This commit is contained in:
Gustavo Francisco 2025-02-02 14:58:43 -03:00 committed by GitHub
commit 896efcd651
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 119 additions and 5 deletions

View file

@ -1,2 +1,2 @@
MAIN_VITE_API_URL=API_URL MAIN_VITE_API_URL=API_URL
MAIN_VITE_AUTH_URL=AUTH_URL MAIN_VITE_AUTH_URL=AUTH_URL

View file

@ -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({ export const gameCardStats = style({
width: "100%", width: "100%",
height: "100%", height: "100%",
@ -236,3 +255,25 @@ export const gameCardStats = style({
flexShrink: "0", flexShrink: "0",
flexGrow: "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",
});

View file

@ -1,11 +1,16 @@
import { userProfileContext } from "@renderer/context"; 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 { ProfileHero } from "../profile-hero/profile-hero";
import { useAppDispatch, useFormat } from "@renderer/hooks"; import { useAppDispatch, useFormat } from "@renderer/hooks";
import { setHeaderTitle } from "@renderer/features"; import { setHeaderTitle } from "@renderer/features";
import { SPACING_UNIT } from "@renderer/theme.css"; import { SPACING_UNIT } from "@renderer/theme.css";
import * as styles from "./profile-content.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 { useTranslation } from "react-i18next";
import { LockedProfile } from "./locked-profile"; import { LockedProfile } from "./locked-profile";
import { ReportProfile } from "../report-profile/report-profile"; import { ReportProfile } from "../report-profile/report-profile";
@ -13,6 +18,7 @@ import { FriendsBox } from "./friends-box";
import { RecentGamesBox } from "./recent-games-box"; import { RecentGamesBox } from "./recent-games-box";
import { UserStatsBox } from "./user-stats-box"; import { UserStatsBox } from "./user-stats-box";
import { UserLibraryGameCard } from "./user-library-game-card"; import { UserLibraryGameCard } from "./user-library-game-card";
import { sortBy } from "lodash-es";
const GAME_STATS_ANIMATION_DURATION_IN_MS = 3500; const GAME_STATS_ANIMATION_DURATION_IN_MS = 3500;
@ -26,6 +32,8 @@ export function ProfileContent() {
const { t } = useTranslation("user_profile"); const { t } = useTranslation("user_profile");
const [sortOption, setSortOption] = useState("lastPlayed"); // Estado para o critério de ordenação
useEffect(() => { useEffect(() => {
dispatch(setHeaderTitle("")); dispatch(setHeaderTitle(""));
@ -69,6 +77,25 @@ export function ProfileContent() {
return userProfile?.relation?.status === "ACCEPTED"; return userProfile?.relation?.status === "ACCEPTED";
}, [userProfile]); }, [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(() => { const content = useMemo(() => {
if (!userProfile) return null; if (!userProfile) return null;
@ -84,6 +111,8 @@ export function ProfileContent() {
const shouldShowRightContent = hasGames || userProfile.friends.length > 0; const shouldShowRightContent = hasGames || userProfile.friends.length > 0;
const sortedGames = sortGames(userProfile.libraryGames || []); // Ordena os jogos conforme o critério
return ( return (
<section <section
style={{ style={{
@ -113,8 +142,51 @@ export function ProfileContent() {
)} )}
</div> </div>
<div className={styles.gridSorting}>
<div>
<label htmlFor="sort-options">Ordenar por: </label>
</div>
<div className={styles.sortOptionsWrapper}>
<button
className={`${sortOption === "lastPlayed" ? styles.selectedSortOption : styles.sortOption}`}
onClick={() => setSortOption("lastPlayed")}
onKeyDown={(e) =>
e.key === "Enter" && setSortOption("lastPlayed")
} // Add keyboard support
tabIndex={0} // Optional if you keep using <span>
>
<HistoryIcon size={14} />
Jogados recentemente
</button>
<div className={styles.sortDivider} />
<button
className={`${sortOption === "playtime" ? styles.selectedSortOption : styles.sortOption}`}
onClick={() => setSortOption("playtime")}
onKeyDown={(e) =>
e.key === "Enter" && setSortOption("playtime")
} // Add keyboard support
tabIndex={0} // Optional if you keep using <span>
>
<ClockIcon size={14} />
Tempo jogado
</button>
<div className={styles.sortDivider} />
<button
className={`${sortOption === "achievements" ? styles.selectedSortOption : styles.sortOption}`}
onClick={() => setSortOption("achievements")}
onKeyDown={(e) =>
e.key === "Enter" && setSortOption("achievements")
} // Add keyboard support
tabIndex={0} // Optional if you keep using <span>
>
<TrophyIcon size={14} />
Conquistas obtidas
</button>
</div>
</div>
<ul className={styles.gamesGrid}> <ul className={styles.gamesGrid}>
{userProfile?.libraryGames?.map((game) => ( {sortedGames.map((game) => (
<UserLibraryGameCard <UserLibraryGameCard
game={game} game={game}
key={game.objectId} key={game.objectId}
@ -146,6 +218,7 @@ export function ProfileContent() {
numberFormatter, numberFormatter,
t, t,
statsIndex, statsIndex,
sortOption,
]); ]);
return ( return (

View file

@ -23,4 +23,4 @@
"@shared": ["src/shared/index.ts"] "@shared": ["src/shared/index.ts"]
} }
} }
} }