Skip to content

Commit

Permalink
Merge pull request #8 from game-node-app/dev
Browse files Browse the repository at this point in the history
Latest changes from dev
  • Loading branch information
Lamarcke authored Feb 25, 2024
2 parents 00ecf3d + 005294e commit b6de0f0
Show file tree
Hide file tree
Showing 109 changed files with 3,926 additions and 1,501 deletions.
4 changes: 0 additions & 4 deletions .typesafe-i18n.json

This file was deleted.

11 changes: 4 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,18 @@
"version": "0.1.0",
"private": true,
"scripts": {
"dev:all": "npm-run-all --parallel dev typesafe-i18n",
"dev": "yarn run wrapper:generate && next dev",
"dev:turbo": "next dev --turbo",
"dev:turbo": "yarn run wrapper:generate && next dev --turbo",
"build": "yarn run wrapper:generate && next build",
"start": "next start",
"wrapper:generate": "node src/wrapper/generate.js",
"lint": "next lint",
"typesafe-i18n": "typesafe-i18n"
"lint": "next lint"
},
"dependencies": {
"@hookform/resolvers": "^3.1.1",
"@mantine/carousel": "^7.1.7",
"@mantine/core": "^7.2.1",
"@mantine/dropzone": "^7.1.3",
"@mantine/dropzone": "^7.5.2",
"@mantine/hooks": "^7.2.1",
"@mantine/next": "^6.0.21",
"@mantine/notifications": "^7.1.3",
Expand All @@ -37,6 +35,7 @@
"prettier": "^3.0.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-easy-crop": "^5.0.5",
"react-hook-form": "^7.45.1",
"supertokens-auth-react": "^0.35.6",
"supertokens-node": "^16.3.2",
Expand All @@ -48,8 +47,6 @@
"@babel/generator": "^7.23.0",
"@babel/parser": "^7.23.0",
"@babel/traverse": "^7.23.2",
"@types/babel__generator": "^7.6.6",
"@types/babel__traverse": "^7.20.3",
"@types/bad-words": "^3.0.3",
"@types/node": "20.8.6",
"@types/react": "^18.2.38",
Expand Down
Binary file added public/favicon/android-chrome-192x192.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/favicon/android-chrome-512x512.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/favicon/apple-touch-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/favicon/favicon-16x16.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/favicon/favicon-32x32.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/favicon/favicon.ico
Binary file not shown.
1 change: 1 addition & 0 deletions public/favicon/site.webmanifest
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
Binary file modified public/img/game_placeholder.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
74 changes: 74 additions & 0 deletions src/components/achievement/AchievementItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import React from "react";
import {
Box,
Group,
Paper,
Stack,
Image,
Title,
Text,
Overlay,
} from "@mantine/core";
import { AchievementDto } from "@/wrapper/server";
import { useObtainedAchievement } from "@/components/achievement/hooks/useObtainedAchievement";
import { getServerStoredIcon } from "@/util/getServerStoredImages";
import AchievementLogo from "@/components/achievement/AchievementLogo";

interface Props {
targetUserId: string;
achievement: AchievementDto | undefined;
}

const AchievementItem = ({ targetUserId, achievement }: Props) => {
const obtainedAchievementQuery = useObtainedAchievement(
targetUserId,
achievement?.id,
);
if (!achievement) {
return null;
}
const obtainedAchievement = obtainedAchievementQuery.data;
const achievementNotYetObtained = obtainedAchievement == undefined;

const backgroundColor = achievementNotYetObtained
? "rgba(0,0,0,0.78)"
: "linear-gradient(90deg, rgba(30,30,30,1) 0%, rgba(30,30,30,0.85) 100%)";

const obtainedText = achievementNotYetObtained
? "Not yet obtained"
: `Obtained at ${new Date(obtainedAchievement?.createdAt).toLocaleDateString()}`;
const icon = getServerStoredIcon(achievement.id);

return (
<Paper
className={"border-4 border-[#282828]"}
w={"100%"}
bg={backgroundColor}
withBorder
pos={"relative"}
>
<Group
wrap={"nowrap"}
w={"100%"}
h={"100%"}
px={"1rem"}
py={"1.5rem"}
opacity={achievementNotYetObtained ? "0.78" : "1"}
>
<AchievementLogo achievementId={achievement.id} />
<Stack gap={"0.5rem"} w={"50%"}>
<Title fz={"1rem"}>{achievement.name}</Title>
<Text fz={"0.85rem"} className={"break-words"}>
{achievement.description}
</Text>
</Stack>
<Stack ml={"auto"} gap={0} justify={"center"} align={"center"}>
<Title fz={"1.5rem"}>{achievement.expGainAmount} XP</Title>
<Text fz={"0.5rem"}>{obtainedText}</Text>
</Stack>
</Group>
</Paper>
);
};

export default AchievementItem;
22 changes: 22 additions & 0 deletions src/components/achievement/AchievementLogo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import React from "react";
import { getServerStoredIcon } from "@/util/getServerStoredImages";
import { Image, ImageProps } from "@mantine/core";

interface Props extends ImageProps {
achievementId: string;
}

const AchievementLogo = ({ achievementId, ...others }: Props) => {
return (
<Image
className="w-[48px] h-[48px]"
src={getServerStoredIcon(achievementId)}
alt={achievementId}
height={48}
width={48}
{...others}
/>
);
};

export default AchievementLogo;
91 changes: 91 additions & 0 deletions src/components/achievement/AchievementsScreen.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import React, { useState } from "react";
import {
Box,
Button,
Center,
Divider,
Group,
Pagination,
Paper,
Progress,
SimpleGrid,
Stack,
} from "@mantine/core";
import { SessionAuth } from "supertokens-auth-react/recipe/session";
import useUserId from "@/components/auth/hooks/useUserId";
import { useAchievements } from "@/components/achievement/hooks/useAchievements";
import AchievementItem from "@/components/achievement/AchievementItem";
import UserLevelInfo from "@/components/user-level/UserLevelInfo";

interface Props {
targetUserId: string;
}

const AchievementsScreen = ({ targetUserId }: Props) => {
const userId = useUserId();
const [paginationData, setPaginationData] = useState({
offset: 0,
limit: 8,
});
const achievements = useAchievements(paginationData);
const isOwnUserId = userId != undefined && userId === targetUserId;
if (!targetUserId) return null;
return (
<Paper className={"w-full h-full"}>
<Stack w={"100%"} py={"3rem"} px={"2rem"}>
{achievements.isError && (
<Center className={"mt-10"}>
Something happened while loading achievements. Please
try again.
</Center>
)}
<Group
wrap={"nowrap"}
className={"justify-center lg:justify-between lg:mx-4"}
>
<Box className={"w-5/12 lg:w-4/12"}>
<UserLevelInfo targetUserId={targetUserId} />
</Box>

{isOwnUserId && (
<Button className={""}>Redeem a code</Button>
)}
</Group>
<Box className={"w-full"}>
<Divider />
</Box>
<SimpleGrid
cols={{
base: 1,
lg: 2,
}}
>
{achievements.data?.data?.map((achievement) => {
return (
<AchievementItem
key={achievement.id}
targetUserId={targetUserId}
achievement={achievement}
/>
);
})}
</SimpleGrid>
<Center mt={"1rem"}>
<Pagination
total={achievements.data?.pagination?.totalPages || 1}
onChange={(page) => {
const pageAsOffset =
paginationData.limit * (page - 1);
setPaginationData({
offset: pageAsOffset,
limit: paginationData.limit,
});
}}
/>
</Center>
</Stack>
</Paper>
);
};

export default AchievementsScreen;
26 changes: 26 additions & 0 deletions src/components/achievement/ObtainedAchievementItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React from "react";
import AchievementItem from "@/components/achievement/AchievementItem";
import { useAchievements } from "@/components/achievement/hooks/useAchievements";

interface Props {
targetUserId: string;
obtainedAchievementId: string;
}

const ObtainedAchievementItem = ({
obtainedAchievementId,
targetUserId,
}: Props) => {
const achievementsQuery = useAchievements({});
const achievementEntity = achievementsQuery.data?.data.find(
(achievement) => achievement.id === obtainedAchievementId,
);
return (
<AchievementItem
targetUserId={targetUserId}
achievement={achievementEntity}
/>
);
};

export default ObtainedAchievementItem;
19 changes: 19 additions & 0 deletions src/components/achievement/hooks/useAchievements.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { useQuery } from "@tanstack/react-query";
import { AchievementsService } from "@/wrapper/server/services/AchievementsService";

interface Props {
offset?: number;
limit?: number;
}

export function useAchievements({ offset = 0, limit = 1000 }: Props) {
return useQuery({
queryKey: ["achievements"],
queryFn: () => {
return AchievementsService.achievementsControllerGetAchievements(
offset,
limit,
);
},
});
}
37 changes: 37 additions & 0 deletions src/components/achievement/hooks/useAllObtainedAchievements.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { useQuery, useQueryClient } from "@tanstack/react-query";
import {
AchievementDto,
AchievementsService,
ObtainedAchievement,
} from "@/wrapper/server";
import { ExtendedUseQueryResult } from "@/util/types/ExtendedUseQueryResult";

export function useAllObtainedAchievements(
targetUserId: string | undefined,
): ExtendedUseQueryResult<ObtainedAchievement[] | null> {
const queryClient = useQueryClient();
const queryKey = ["obtained-achievement", "all", targetUserId];
const invalidate = () => queryClient.invalidateQueries({ queryKey });
return {
...useQuery({
queryKey,
queryFn: async () => {
if (!targetUserId) {
return null;
}
const achievements =
await AchievementsService.achievementsControllerGetAllObtainedAchievements(
targetUserId,
);
if (achievements == undefined || achievements.length === 0) {
return null;
}

return achievements;
},
enabled: !!targetUserId,
}),
invalidate,
queryKey,
};
}
37 changes: 37 additions & 0 deletions src/components/achievement/hooks/useFeaturedObtainedAchievement.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { useAchievements } from "@/components/achievement/hooks/useAchievements";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { AchievementsService, ObtainedAchievement } from "@/wrapper/server";
import { ExtendedUseQueryResult } from "@/util/types/ExtendedUseQueryResult";
import { useAllObtainedAchievements } from "@/components/achievement/hooks/useAllObtainedAchievements";

export function useFeaturedObtainedAchievement(
userId: string | undefined,
): ExtendedUseQueryResult<ObtainedAchievement | undefined> {
const queryClient = useQueryClient();
const queryKey = ["achievements", "featured", userId];

const obtainedAchievements = useAllObtainedAchievements(userId);

const invalidate = () => {
queryClient.invalidateQueries({
queryKey,
});
obtainedAchievements.invalidate();
};

return {
...useQuery({
queryKey,
queryFn: async () => {
const featuredAchievement = obtainedAchievements.data?.find(
(achievement) => achievement.isFeatured,
);
if (!featuredAchievement) return null;

return featuredAchievement;
},
}),
invalidate,
queryKey,
};
}
21 changes: 21 additions & 0 deletions src/components/achievement/hooks/useObtainedAchievement.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { useQuery } from "@tanstack/react-query";
import { AchievementsService } from "@/wrapper/server/services/AchievementsService";

export function useObtainedAchievement(
targetUserId: string,
achievementId: string | undefined,
) {
return useQuery({
queryKey: ["obtained-achievement", targetUserId, achievementId],
queryFn: () => {
if (!achievementId) {
return null;
}
return AchievementsService.achievementsControllerGetObtainedAchievement(
achievementId,
targetUserId,
);
},
retry: false,
});
}
1 change: 0 additions & 1 deletion src/components/auth/hooks/useUserId.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import React from "react";
import { useSessionContext } from "supertokens-auth-react/recipe/session";

const useUserId = (): string | undefined => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ const CollectionEntriesMoveForm = ({
(platform) => platform.id,
);
const replacePromise =
CollectionsEntriesService.collectionsEntriesControllerReplace(
CollectionsEntriesService.collectionsEntriesControllerCreateOrUpdate(
{
isFavorite: entry.isFavorite,
platformIds: ownedPlatformsIds as unknown as any,
Expand Down
Loading

0 comments on commit b6de0f0

Please sign in to comment.