This commit is contained in:
Zamitto 2024-06-14 18:23:57 -03:00
parent ca21d8afe6
commit e8a1aa0616
6 changed files with 78 additions and 21 deletions

View File

@ -224,5 +224,11 @@
},
"forms": {
"toggle_password_visibility": "Toggle password visibility"
},
"user_profile": {
"amount_hours": "{{amount}} hours",
"amount_minutes": "{{amount}} minutes",
"play_time": "Played for {{amount}}",
"last_time_played": "Last played {{period}}"
}
}

View File

@ -227,6 +227,9 @@
"toggle_password_visibility": "Alternar visibilidade da senha"
},
"user_profile": {
"amount_hours": "Jogou por {{amount}}"
"amount_hours": "{{amount}} horas",
"amount_minutes": "{{amount}} minutos",
"play_time": "Jogado por {{amount}}",
"last_time_played": "Jogou por último {{period}}"
}
}

View File

@ -25,6 +25,7 @@ const gamesArray = z.array(
export const userProfileSchema = z.object({
displayName: z.string(),
profileImageUrl: z.string().url().nullable(),
libraryGames: gamesArray,
recentGames: gamesArray,
});

View File

@ -4,8 +4,11 @@ import * as styles from "./profile.css";
import { SPACING_UNIT, vars } from "@renderer/theme.css";
import { useMemo } from "react";
import { useTranslation } from "react-i18next";
import { formatDistance } from "date-fns";
import SteamLogo from "@renderer/assets/steam-logo.svg?react";
import { useDate } from "@renderer/hooks";
import { useNavigate } from "react-router-dom";
import { buildGameDetailsPath } from "@renderer/helpers";
import { PersonIcon } from "@primer/octicons-react";
export interface ProfileContentProps {
userProfile: UserProfile;
}
@ -15,14 +18,17 @@ const MAX_MINUTES_TO_SHOW_IN_PLAYTIME = 120;
export const ProfileContent = ({ userProfile }: ProfileContentProps) => {
const { t, i18n } = useTranslation("user_profile");
const navigate = useNavigate();
const numberFormatter = useMemo(() => {
return new Intl.NumberFormat(i18n.language, {
maximumFractionDigits: 0,
});
}, [i18n.language]);
const { formatDistance } = useDate();
const formatPlayTime = (game: ProfileGame) => {
console.log(game);
const seconds = game.playTimeInSeconds;
const minutes = seconds / 60;
@ -36,17 +42,28 @@ export const ProfileContent = ({ userProfile }: ProfileContentProps) => {
return t("amount_hours", { amount: numberFormatter.format(hours) });
};
const handleGameClick = (game: ProfileGame) => {
navigate(buildGameDetailsPath(game));
};
console.log(userProfile);
return (
<>
<section
className={styles.profileContentBox}
style={{ padding: `${SPACING_UNIT * 2}px ${SPACING_UNIT * 2}px` }}
>
<img
alt={userProfile.displayName + " profile image"}
className={styles.profileAvatar}
src="https://cdn.losbroxas.org/3918aa27-9b96-4fdf-b066-4c545d6667ab.png"
/>
<div className={styles.profileAvatarContainer}>
{userProfile.profileImageUrl ? (
<img
className={styles.profileAvatar}
alt={userProfile.displayName}
src={userProfile.profileImageUrl}
/>
) : (
<PersonIcon size={72} />
)}
</div>
<div className={styles.profileInformation}>
<h2 style={{ fontWeight: "bold" }}>{userProfile.displayName}</h2>
@ -67,24 +84,25 @@ export const ProfileContent = ({ userProfile }: ProfileContentProps) => {
>
{userProfile.recentGames.map((game) => {
return (
<div
<button
key={game.objectID}
className={cn(styles.feedItem, styles.profileContentBox)}
onClick={() => handleGameClick(game)}
>
<img
className={styles.feedGameIcon}
src={game.cover}
alt={"Icon for " + game.title}
alt={game.title}
/>
<div className={styles.gameInformation}>
<p>{game.title}</p>
<p>
<h4>{game.title}</h4>
<small>
{formatDistance(game.lastTimePlayed!, new Date(), {
addSuffix: true,
})}
</p>
</small>
</div>
</div>
</button>
);
})}
</div>
@ -120,12 +138,13 @@ export const ProfileContent = ({ userProfile }: ProfileContentProps) => {
>
{userProfile.libraryGames.map((game) => {
return (
<div
<button
key={game.objectID}
className={cn(styles.gameListItem, styles.profileContentBox)}
style={{
padding: `${SPACING_UNIT}px ${SPACING_UNIT}px`,
padding: `${SPACING_UNIT + SPACING_UNIT / 2}px`,
}}
onClick={() => handleGameClick(game)}
>
{game.iconUrl ? (
<img
@ -138,10 +157,15 @@ export const ProfileContent = ({ userProfile }: ProfileContentProps) => {
)}
<div className={styles.gameInformation}>
<p>{game.title}</p>
<p>{formatPlayTime(game)}</p>
<h4>{game.title}</h4>
<small>
{t("play_time", {
amount: formatPlayTime(game),
})}
</small>
</div>
</div>
</button>
);
})}
</div>

View File

@ -16,9 +16,10 @@ export const profileContentBox = style({
borderRadius: "4px",
border: `solid 1px ${vars.color.border}`,
width: "100%",
overflow: "hidden",
});
export const profileAvatar = style({
export const profileAvatarContainer = style({
width: "96px",
height: "96px",
borderRadius: "50%",
@ -27,6 +28,12 @@ export const profileAvatar = style({
alignItems: "center",
backgroundColor: vars.color.background,
position: "relative",
overflow: "hidden",
});
export const profileAvatar = style({
width: "96px",
height: "96px",
});
export const profileInformation = style({
@ -84,25 +91,40 @@ export const libraryGameIcon = style({
});
export const feedItem = style({
color: vars.color.body,
display: "flex",
flexDirection: "row",
gap: `${SPACING_UNIT}px`,
gap: `${SPACING_UNIT * 2}px`,
width: "100%",
height: "72px",
transition: "all ease 0.2s",
cursor: "pointer",
zIndex: "1",
":hover": {
backgroundColor: "rgba(255, 255, 255, 0.15)",
},
});
export const gameListItem = style({
color: vars.color.body,
display: "flex",
flexDirection: "row",
gap: `${SPACING_UNIT}px`,
width: "100%",
height: "60px",
transition: "all ease 0.2s",
cursor: "pointer",
zIndex: "1",
":hover": {
backgroundColor: "rgba(255, 255, 255, 0.15)",
},
});
export const gameInformation = style({
display: "flex",
flexDirection: "column",
alignItems: "flex-start",
gap: `${SPACING_UNIT / 2}px`,
});
export const profileHeaderSkeleton = style({

View File

@ -246,6 +246,7 @@ export interface RealDebridUser {
export interface UserProfile {
displayName: string;
profileImageUrl: string | null;
libraryGames: ProfileGame[];
recentGames: ProfileGame[];
}