feat: showing first content on profile page

This commit is contained in:
Zamitto 2024-06-12 22:23:12 -03:00
parent b8895afc0a
commit 4e73009997
7 changed files with 116 additions and 25 deletions

View file

@ -2,20 +2,41 @@ import { registerEvent } from "../register-event";
import { userProfileSchema } from "../helpers/validators"; import { userProfileSchema } from "../helpers/validators";
import { logger } from "@main/services"; import { logger } from "@main/services";
import { HydraApi } from "@main/services/hydra-api"; import { HydraApi } from "@main/services/hydra-api";
import { steamGamesWorker } from "@main/workers";
import { LibraryGame, SteamGame, UserProfile } from "@types";
const getUserProfile = async ( const getUserProfile = async (
_event: Electron.IpcMainInvokeEvent, _event: Electron.IpcMainInvokeEvent,
username: string username: string
) => { ): Promise<UserProfile | null> => {
return HydraApi.get(`/profile/${username}`) try {
.then((response) => { const response = await HydraApi.get(`/profile/${username}`);
const profile = userProfileSchema.parse(response.data); const profile = userProfileSchema.parse(response.data);
return profile;
const recentGames = await Promise.all(
profile.recentGames.map(async (game) => {
const steamGame = await steamGamesWorker.run(Number(game.objectId), {
name: "getById",
});
return { ...game, title: steamGame.name, objectId: game.objectId };
}) })
.catch((err) => { );
const libraryGames = await Promise.all(
profile.game.map(async (game) => {
const steamGame = await steamGamesWorker.run(Number(game.objectId), {
name: "getById",
});
return { ...game, title: steamGame.name, objectID: game.objectId };
})
);
return { ...profile, game: libraryGames, recentGames };
} catch (err) {
logger.error(`getUserProfile: ${username}`, err); logger.error(`getUserProfile: ${username}`, err);
return null; return null;
}); }
}; };
registerEvent("getUserProfile", getUserProfile); registerEvent("getUserProfile", getUserProfile);

View file

@ -144,7 +144,7 @@ export function Sidebar() {
}; };
const handleClickProfile = () => { const handleClickProfile = () => {
navigate("/profile/brownie"); navigate("/profile/zamitto");
}; };
return ( return (

View file

@ -1,5 +1,6 @@
import { UserProfile } from "@types"; import { UserProfile } from "@types";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import * as styles from "./profile.css";
export interface ProfileContentProps { export interface ProfileContentProps {
userProfile: UserProfile; userProfile: UserProfile;
@ -8,9 +9,29 @@ export interface ProfileContentProps {
export const ProfileContent = ({ userProfile }: ProfileContentProps) => { export const ProfileContent = ({ userProfile }: ProfileContentProps) => {
const { t } = useTranslation("profile"); const { t } = useTranslation("profile");
console.log(userProfile.recentGames);
return ( return (
<> <>
<p>{userProfile.username}</p> <section className={styles.profileHeader}>
<img
className={styles.profileAvatar}
src="https://avatars.githubusercontent.com/u/167933696?v=4"
/>
<div className={styles.profileInformation}>
<h3 style={{ fontWeight: "bold" }}>{userProfile.username}</h3>
<p style={{ fontSize: 12 }}>Jogando ABC</p>
</div>
</section>
<h2>Feed</h2>
{userProfile.recentGames.map((game) => {
return <p key={game.objectID}>{game.title}</p>;
})}
<h2>Games</h2>
{userProfile.game.map((game) => {
return <p key={game.objectID}>{game.title}</p>;
})}
</> </>
); );
}; };

View file

@ -1,7 +1,11 @@
import Skeleton from "react-loading-skeleton";
import * as styles from "./profile.css";
export const ProfileSkeleton = () => { export const ProfileSkeleton = () => {
return ( return (
<> <>
<p>Loading....</p> <Skeleton className={styles.profileHeaderSkeleton} />
<Skeleton width={135} />
</> </>
); );
}; };

View file

@ -1,7 +1,41 @@
export const UserProfile = () => { import { SPACING_UNIT, vars } from "../../theme.css";
return ( import { style } from "@vanilla-extract/css";
<>
<p>Tela do usuarioooooooo</p> export const wrapper = style({
</> padding: "24px",
); width: "100%",
}; display: "flex",
flexDirection: "column",
});
export const profileHeader = style({
display: "flex",
gap: `${SPACING_UNIT + SPACING_UNIT / 2}px`,
alignItems: "center",
padding: `${SPACING_UNIT * 2}px ${SPACING_UNIT * 2}px`,
color: vars.color.muted,
borderRadius: "4px",
border: `solid 1px ${vars.color.border}`,
width: "100%",
});
export const profileAvatar = style({
width: "96px",
height: "96px",
borderRadius: "50%",
display: "flex",
justifyContent: "center",
alignItems: "center",
backgroundColor: vars.color.background,
position: "relative",
});
export const profileInformation = style({
display: "flex",
flexDirection: "column",
alignItems: "flex-start",
});
export const profileHeaderSkeleton = style({
height: "200px",
});

View file

@ -5,6 +5,9 @@ import { setHeaderTitle } from "@renderer/features";
import { useAppDispatch } from "@renderer/hooks"; import { useAppDispatch } from "@renderer/hooks";
import { ProfileSkeleton } from "./profile-skeleton"; import { ProfileSkeleton } from "./profile-skeleton";
import { ProfileContent } from "./profile-content"; import { ProfileContent } from "./profile-content";
import { SkeletonTheme } from "react-loading-skeleton";
import { vars } from "@renderer/theme.css";
import * as styles from "./profile.css";
export const Profile = () => { export const Profile = () => {
const { username } = useParams(); const { username } = useParams();
@ -21,7 +24,15 @@ export const Profile = () => {
}); });
}, [dispatch]); }, [dispatch]);
if (!userProfile) return <ProfileSkeleton />; return (
<SkeletonTheme baseColor={vars.color.background} highlightColor="#444">
return <ProfileContent userProfile={userProfile} />; <div className={styles.wrapper}>
{userProfile ? (
<ProfileContent userProfile={userProfile} />
) : (
<ProfileSkeleton />
)}
</div>
</SkeletonTheme>
);
}; };

View file

@ -236,8 +236,8 @@ export interface RealDebridUser {
export interface UserProfile { export interface UserProfile {
username: string; username: string;
game: any[]; game: Partial<CatalogueEntry>[];
recentGames: any[]; recentGames: Partial<CatalogueEntry>[];
} }
export interface DownloadSource { export interface DownloadSource {