feat: update achievements on sidebar

This commit is contained in:
Zamitto 2024-10-08 15:17:53 -03:00
parent 446b03eeff
commit ffac677e3f
9 changed files with 143 additions and 57 deletions

View file

@ -39,6 +39,7 @@ export function Header({ onSearch, onClear, search }: HeaderProps) {
const title = useMemo(() => {
if (location.pathname.startsWith("/game")) return headerTitle;
if (location.pathname.startsWith("/achievements")) return headerTitle;
if (location.pathname.startsWith("/profile")) return headerTitle;
if (location.pathname.startsWith("/search")) return t("search_results");

View file

@ -1,4 +1,5 @@
import { useDate } from "@renderer/hooks";
import { setHeaderTitle } from "@renderer/features";
import { useAppDispatch, useDate } from "@renderer/hooks";
import { SPACING_UNIT } from "@renderer/theme.css";
import { GameAchievement, GameShop } from "@types";
import { useEffect, useState } from "react";
@ -8,10 +9,13 @@ export function Achievement() {
const [searchParams] = useSearchParams();
const objectId = searchParams.get("objectId");
const shop = searchParams.get("shop");
const title = searchParams.get("title");
const userId = searchParams.get("userId");
const { format } = useDate();
const dispatch = useAppDispatch();
const [achievements, setAchievements] = useState<GameAchievement[]>([]);
useEffect(() => {
@ -24,6 +28,12 @@ export function Achievement() {
}
}, [objectId, shop, userId]);
useEffect(() => {
if (title) {
dispatch(setHeaderTitle(title + " Achievements"));
}
}, [dispatch, title]);
return (
<div>
<h1>Achievement</h1>
@ -61,6 +71,7 @@ export function Achievement() {
/>
<div>
<p>{achievement.displayName}</p>
<p>{achievement.description}</p>
{achievement.unlockTime && format(achievement.unlockTime)}
</div>
</div>

View file

@ -1,6 +1,7 @@
import { globalStyle, style } from "@vanilla-extract/css";
import { SPACING_UNIT, vars } from "../../../theme.css";
import { recipe } from "@vanilla-extract/recipes";
export const contentSidebar = style({
borderLeft: `solid 1px ${vars.color.border}`,
@ -110,3 +111,46 @@ globalStyle(`${requirementsDetails} a`, {
display: "flex",
color: vars.color.body,
});
export const list = style({
listStyle: "none",
margin: "0",
display: "flex",
flexDirection: "column",
gap: `${SPACING_UNIT * 2}px`,
padding: `${SPACING_UNIT * 2}px`,
});
export const listItem = style({
display: "flex",
cursor: "pointer",
transition: "all ease 0.1s",
color: vars.color.muted,
width: "100%",
overflow: "hidden",
borderRadius: "4px",
padding: `${SPACING_UNIT}px ${SPACING_UNIT}px`,
gap: `${SPACING_UNIT * 2}px`,
alignItems: "center",
textAlign: "left",
":hover": {
backgroundColor: "rgba(255, 255, 255, 0.15)",
textDecoration: "none",
},
});
export const listItemImage = recipe({
base: {
width: "54px",
height: "54px",
borderRadius: "4px",
objectFit: "cover",
},
variants: {
unlocked: {
false: {
filter: "grayscale(100%)",
},
},
},
});

View file

@ -7,10 +7,10 @@ import * as styles from "./sidebar.css";
import { gameDetailsContext } from "@renderer/context";
import { useDate, useFormat } from "@renderer/hooks";
import { DownloadIcon, PeopleIcon } from "@primer/octicons-react";
import { SPACING_UNIT } from "@renderer/theme.css";
import { HowLongToBeatSection } from "./how-long-to-beat-section";
import { howLongToBeatEntriesTable } from "@renderer/dexie";
import { SidebarSection } from "../sidebar-section/sidebar-section";
import { useNavigate } from "react-router-dom";
export function Sidebar() {
const [howLongToBeat, setHowLongToBeat] = useState<{
@ -30,7 +30,12 @@ export function Sidebar() {
const { numberFormatter } = useFormat();
const buildGameAchievementPath = () => {
const urlParams = new URLSearchParams({ objectId: objectId!, shop });
const urlParams = new URLSearchParams({
objectId: objectId!,
shop,
title: gameTitle,
});
return `/achievements?${urlParams.toString()}`;
};
@ -80,49 +85,43 @@ export function Sidebar() {
achievementsCount: achievements.length,
})}
>
<span>
<Link to={buildGameAchievementPath()}>Ver todas</Link>
</span>
<div
style={{
display: "flex",
flexDirection: "column",
gap: `${SPACING_UNIT}px`,
padding: `${SPACING_UNIT * 2}px`,
}}
>
{achievements.slice(0, 6).map((achievement, index) => (
<div
key={index}
style={{
display: "flex",
flexDirection: "row",
alignItems: "center",
gap: `${SPACING_UNIT}px`,
}}
title={achievement.description}
>
<img
style={{
height: "60px",
width: "60px",
filter: achievement.unlocked ? "none" : "grayscale(100%)",
}}
src={
achievement.unlocked
? achievement.icon
: achievement.icongray
}
alt={achievement.displayName}
loading="lazy"
/>
<div>
<p>{achievement.displayName}</p>
{achievement.unlockTime && format(achievement.unlockTime)}
</div>
</div>
<ul className={styles.list}>
{achievements.slice(0, 4).map((achievement, index) => (
<li key={index}>
<Link
to={buildGameAchievementPath()}
className={styles.listItem}
title={achievement.description}
>
<img
className={styles.listItemImage({
unlocked: achievement.unlocked,
})}
src={
achievement.unlocked
? achievement.icon
: achievement.icongray
}
alt={achievement.displayName}
loading="lazy"
/>
<div>
<p>{achievement.displayName}</p>
<small>
{achievement.unlockTime && format(achievement.unlockTime)}
</small>
</div>
</Link>
</li>
))}
</div>
<Link
style={{ textAlign: "center" }}
to={buildGameAchievementPath()}
>
{t("see_all_achievements")}
</Link>
</ul>
</SidebarSection>
)}