Skip to content

Commit

Permalink
Merge pull request #53 from game-node-app/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
Lamarcke authored Mar 31, 2024
2 parents d701b79 + a92ff52 commit 86fed16
Show file tree
Hide file tree
Showing 16 changed files with 265 additions and 202 deletions.
76 changes: 18 additions & 58 deletions src/components/explore/ExploreScreenFilters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,13 @@ import { IconAdjustments } from "@tabler/icons-react";
import { useDisclosure } from "@mantine/hooks";
import period = FindStatisticsTrendingReviewsDto.period;
import { ParsedUrlQuery } from "querystring";
import { DEFAULT_EXPLORE_TRENDING_GAMES_DTO } from "@/pages/explore";
import { QueryKey, useQueryClient } from "@tanstack/react-query";
import { GameResourceFilter } from "@/components/game/util/types";
import {
DEFAULT_EXPLORE_TRENDING_GAMES_DTO,
exploreScreenDtoToSearchParams,
exploreScreenUrlQueryToDto,
} from "@/components/explore/utils";

export const DEFAULT_EXPLORE_SCREEN_PERIOD = period.MONTH.valueOf();

Expand Down Expand Up @@ -66,77 +71,35 @@ type FilterFormValues = z.infer<typeof FilterFormSchema>;
/**
* PS: DO NOT use this as 'data' for the MultiSelect component. This is only for reference when building the JSX below.
*/
const resources: ComboboxItem[] = [
const resources: GameResourceFilter[] = [
{
label: "Themes",
value: "themes",
resource: "themes",
},
{
label: "Genres",
value: "genres",
resource: "genres",
},
{
label: "Platforms",
value: "platforms",
resource: "platforms",
},
{
label: "Modes",
value: "gameModes",
resource: "gameModes",
},
];

export const exploreScreenUrlQueryToDto = (query: ParsedUrlQuery) => {
const dto: FindStatisticsTrendingGamesDto = structuredClone(
DEFAULT_EXPLORE_TRENDING_GAMES_DTO,
);
for (const [k, v] of Object.entries(query)) {
if (k !== "period" && typeof v === "string" && v.length > 0) {
if (v.includes(",")) {
//@ts-ignore
dto.criteria[k] = v.split(",");
} else {
//@ts-ignore
dto.criteria[k] = [v];
}
} else if (typeof v === "string" && v.length > 0) {
// @ts-ignore
dto[k] = v;
}
}
return dto;
};

export const exploreScreenDtoToSearchParams = (
dto: FindStatisticsTrendingGamesDto,
) => {
const params = new URLSearchParams();
const { period, criteria } = dto;
params.set("period", period);
if (criteria) {
for (const [k, v] of Object.entries(criteria)) {
params.set(k, `${v}`);
}
}
return params;
};

interface Props {
setTrendingGamesDto: Dispatch<
SetStateAction<FindStatisticsTrendingGamesDto>
>;
onFilterChange: Dispatch<SetStateAction<FindStatisticsTrendingGamesDto>>;
hasLoadedQueryParams: boolean;
setHasLoadedQueryParams: Dispatch<SetStateAction<boolean>>;
invalidateQuery: () => void;
}

const ExploreScreenFilters = ({
setTrendingGamesDto,
onFilterChange,
hasLoadedQueryParams,
setHasLoadedQueryParams,
invalidateQuery,
}: Props) => {
const router = useRouter();
const queryClient = useQueryClient();
const [drawerOpened, drawerUtils] = useDisclosure();

const { handleSubmit, register, setValue, watch, formState } =
Expand All @@ -150,7 +113,7 @@ const ExploreScreenFilters = ({

const onSubmit = async (data: FilterFormValues) => {
const { period, ...criteria } = data;
setTrendingGamesDto((previousState) => {
onFilterChange((previousState) => {
const updatedState = {
...previousState,
period: period as period,
Expand All @@ -162,11 +125,10 @@ const ExploreScreenFilters = ({
query: searchParams.toString(),
},
undefined,
{ shallow: true },
{ shallow: false },
);
return updatedState;
});
invalidateQuery();
drawerUtils.close();
};

Expand All @@ -180,15 +142,13 @@ const ExploreScreenFilters = ({
}
}
setValue("period", dto.period);
setTrendingGamesDto((prevState) => ({ ...prevState, ...dto }));
setHasLoadedQueryParams(true);
onFilterChange((prevState) => ({ ...prevState, ...dto }));
}
}, [
hasLoadedQueryParams,
router.isReady,
router.query,
setHasLoadedQueryParams,
setTrendingGamesDto,
onFilterChange,
setValue,
]);

Expand All @@ -205,7 +165,7 @@ const ExploreScreenFilters = ({
>
<SimpleGrid cols={2}>
{resources.map((resourceReference) => {
const valueName = resourceReference.value as any;
const valueName = resourceReference.resource as any;
return (
<ExploreScreenResourceSelector
label={resourceReference.label}
Expand Down
13 changes: 12 additions & 1 deletion src/components/explore/ExploreScreenResourceSelector.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { useMemo } from "react";
import {
ComboboxItem,
LoadingOverlay,
MultiSelect,
MultiSelectProps,
SelectProps,
Expand All @@ -27,7 +28,17 @@ const ExploreScreenResourceSelector = ({ resourceName, ...others }: Props) => {
};
});
}, [resourceQuery.data]);
return <MultiSelect data={data} {...others} />;
return (
<MultiSelect
pos={"relative"}
placeholder={resourceQuery.isLoading ? "Loading..." : undefined}
data={data}
searchable
clearable
{...others}
maxValues={5}
></MultiSelect>
);
};

export default ExploreScreenResourceSelector;
48 changes: 48 additions & 0 deletions src/components/explore/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { ParsedUrlQuery } from "querystring";
import { FindStatisticsTrendingGamesDto } from "@/wrapper/server";
import period = FindStatisticsTrendingGamesDto.period;

export const DEFAULT_EXPLORE_RESULT_LIMIT = 20;
export const DEFAULT_EXPLORE_SCREEN_PERIOD = period.MONTH.valueOf();

export const DEFAULT_EXPLORE_TRENDING_GAMES_DTO: FindStatisticsTrendingGamesDto =
{
limit: DEFAULT_EXPLORE_RESULT_LIMIT,
criteria: {},
period: DEFAULT_EXPLORE_SCREEN_PERIOD as period,
};

export const exploreScreenUrlQueryToDto = (query: ParsedUrlQuery) => {
const dto: FindStatisticsTrendingGamesDto = structuredClone(
DEFAULT_EXPLORE_TRENDING_GAMES_DTO,
);
for (const [k, v] of Object.entries(query)) {
if (k !== "period" && typeof v === "string" && v.length > 0) {
if (v.includes(",")) {
//@ts-ignore
dto.criteria[k] = v.split(",");
} else {
//@ts-ignore
dto.criteria[k] = [v];
}
} else if (typeof v === "string" && v.length > 0) {
// @ts-ignore
dto[k] = v;
}
}
return dto;
};

export const exploreScreenDtoToSearchParams = (
dto: FindStatisticsTrendingGamesDto,
) => {
const params = new URLSearchParams();
const { period, criteria } = dto;
params.set("period", period);
if (criteria) {
for (const [k, v] of Object.entries(criteria)) {
params.set(k, `${v}`);
}
}
return params;
};
58 changes: 43 additions & 15 deletions src/components/game/info/GameExtraInfoView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,43 +9,71 @@ interface IGameExtraInfoViewProps {
id: number;
}

export const DEFAULT_GAME_EXTRA_INFO_DTO = {
const DEFAULT_SIMILAR_GAMES_DTO = {
relations: {
similarGames: {
cover: true,
},
},
};

const DEFAULT_DLCS_GAMES_DTO = {
relations: {
dlcs: {
cover: true,
},
similarGames: {
},
};

const DEFAULT_DLC_OF_GAMES_DTO = {
relations: {
dlcOf: {
cover: true,
},
},
};

const GameExtraInfoView = ({ id }: IGameExtraInfoViewProps) => {
const gameQuery = useGame(id, DEFAULT_GAME_EXTRA_INFO_DTO);
const similarGamesQuery = useGame(id, DEFAULT_SIMILAR_GAMES_DTO);
const dlcsGamesQuery = useGame(id, DEFAULT_DLCS_GAMES_DTO);
const dlcsOfGamesQuery = useGame(id, DEFAULT_DLC_OF_GAMES_DTO);
const hasDlcsOf =
dlcsOfGamesQuery.data != undefined &&
dlcsOfGamesQuery.data.dlcOf != undefined &&
dlcsOfGamesQuery.data.dlcOf.length > 0;
const hasDlcs =
gameQuery.data != undefined &&
gameQuery.data.dlcs != undefined &&
gameQuery.data.dlcs.length > 0;
dlcsGamesQuery.data != undefined &&
dlcsGamesQuery.data.dlcs != undefined &&
dlcsGamesQuery.data.dlcs.length > 0;

const hasSimilarGames =
gameQuery.data != undefined &&
gameQuery.data.similarGames != undefined &&
gameQuery.data.similarGames.length > 0;
similarGamesQuery.data != undefined &&
similarGamesQuery.data.similarGames != undefined &&
similarGamesQuery.data.similarGames.length > 0;
return (
<Paper w={"100%"} h={"100%"} suppressHydrationWarning>
<Flex w={"100%"} h={"100%"} wrap={"wrap"}>
<DetailsBox enabled={hasDlcsOf} title={"DLC of"}>
<GameInfoCarousel
games={dlcsOfGamesQuery.data?.dlcOf}
isLoading={dlcsOfGamesQuery.isLoading}
isError={dlcsOfGamesQuery.isError}
/>
</DetailsBox>
<Break />
<DetailsBox enabled={hasDlcs} title={"DLCs"}>
<GameInfoCarousel
games={gameQuery.data?.dlcs}
isLoading={gameQuery.isLoading}
isError={gameQuery.isError}
games={dlcsGamesQuery.data?.dlcs}
isLoading={dlcsGamesQuery.isLoading}
isError={dlcsGamesQuery.isError}
/>
</DetailsBox>
<Break />
<DetailsBox enabled={hasSimilarGames} title={"Similar games"}>
<GameInfoCarousel
games={gameQuery.data?.similarGames}
isLoading={gameQuery.isLoading}
isError={gameQuery.isError}
games={similarGamesQuery.data?.similarGames}
isLoading={similarGamesQuery.isLoading}
isError={similarGamesQuery.isError}
/>
</DetailsBox>
</Flex>
Expand Down
4 changes: 2 additions & 2 deletions src/components/game/info/GameInfoDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@ const GameInfoDetails = ({ game }: IGameInfoDetailsProps) => {
<SimpleGrid cols={{ base: 1, lg: 2 }}>
<DetailsBox withBorder withDimmedTitle title={"Launch date"}>
{getLocalizedFirstReleaseDate(game.firstReleaseDate) ??
"Unknown"}
"Not available"}
</DetailsBox>
<GameInfoDetailsDeveloperInfo gameId={game.id} />
<GameInfoDetailsTags gameId={game.id} />
<DetailsBox withBorder withDimmedTitle title={"Summary"}>
{game.summary ?? "Unknown"}
{game.summary ?? "Not available"}
</DetailsBox>
<DetailsBox title={"Where to play"} withBorder withDimmedTitle>
<GameInfoPlatforms
Expand Down
20 changes: 15 additions & 5 deletions src/components/game/info/GameInfoDetailsDeveloperInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,34 @@ const GameInfoDetailsDeveloperInfo = ({ gameId }: IProps) => {
});
const involvedCompanies = game.data?.involvedCompanies;
const developers = useMemo(() => {
if (involvedCompanies && involvedCompanies.length > 0) {
const hasDevelopers =
involvedCompanies != undefined &&
involvedCompanies.some((company) => company.developer);
if (hasDevelopers) {
return involvedCompanies
.filter((ic) => ic.developer)
.map((ic) => ic.company);
}
return undefined;
return null;
}, [involvedCompanies]);
const publishers = useMemo(() => {
if (involvedCompanies && involvedCompanies.length > 0) {
const hasPublishers =
involvedCompanies != undefined &&
involvedCompanies.some((company) => company.publisher);

if (hasPublishers) {
return involvedCompanies
.filter((ic) => ic.publisher)
.map((ic) => ic.company);
}
return null;
}, [involvedCompanies]);
const developersNames =
developers?.map((company) => company.name)?.join(", ") ?? "Unknown";
developers?.map((company) => company.name)?.join(", ") ??
"Not available";
const publishersNames =
publishers?.map((company) => company.name).join(", ") ?? "Unknown";
publishers?.map((company) => company.name).join(", ") ??
"Not available";

return (
<>
Expand Down
3 changes: 1 addition & 2 deletions src/components/game/info/GameInfoDetailsTags.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,14 +87,13 @@ const GameInfoDetailsTags = ({ gameId }: IProps) => {

const badges: ReactNode[] = useMemo(() => {
const tags = getGameTags(game);
console.log(tags);

return tags
.filter((tag) => tag != undefined)
.map((tag) => {
return (
<Link
key={tag.category}
key={`tag-${tag.category}-${tag.id}`}
href={`/explore?${tag.category}=${tag.id}`}
>
<Badge>{tag.name}</Badge>
Expand Down
2 changes: 1 addition & 1 deletion src/components/game/info/GameInfoOwnedPlatforms.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ const GameInfoOwnedPlatforms = ({
{iconsQuery.isLoading && (
<Skeleton className={"w-10/12 lg:w-4/12 h-10"} />
)}
{isEmpty && "Unknown"}
{isEmpty && "Not available"}
{icons}
</Group>
</Popover.Target>
Expand Down
Loading

0 comments on commit 86fed16

Please sign in to comment.