From d3acd9377c8fedf5986b3ff30410ac13eaa00846 Mon Sep 17 00:00:00 2001 From: Polaris Date: Thu, 1 Aug 2024 21:42:14 -0400 Subject: [PATCH] added update functions --- .example.env | 1 + .../avatarcustomization/actions.ts | 47 ++++- .../avatarcustomization/page.tsx | 167 +++++++++++------- .../mapiconcustomization/actions.ts | 39 +++- .../mapiconcustomization/page.tsx | 45 +++-- .../nameplatecustomization/actions.ts | 41 ++++- .../nameplatecustomization/page.tsx | 44 +++-- .../systemvoicecustomization/actions.ts | 41 ++++- .../systemvoicecustomization/page.tsx | 40 +++-- .../trophycustomization/actions.ts | 38 +++- .../trophycustomization/page.tsx | 16 +- lib/helpers.ts | 4 + 12 files changed, 391 insertions(+), 132 deletions(-) diff --git a/.example.env b/.example.env index f2387ab..03969a8 100644 --- a/.example.env +++ b/.example.env @@ -1,3 +1,4 @@ DATABASE_URL="mysql://root:password@localhost:3306/daphnis" DATABASE_AIME_URL = "mysql://root:password@localhost:3306/aime" NEXT_PUBLIC_RESEND_API_KEY="" +SUPPORTED_CHUNITHM_VERSION_NUMBER=15 \ No newline at end of file diff --git a/components/(customization)/avatarcustomization/actions.ts b/components/(customization)/avatarcustomization/actions.ts index b3d615b..182325e 100644 --- a/components/(customization)/avatarcustomization/actions.ts +++ b/components/(customization)/avatarcustomization/actions.ts @@ -1,11 +1,8 @@ "use server"; import { getAuth } from "@/auth/queries/getauth"; -import { artemis, daphnis } from "@/lib/prisma"; -import type * as Prisma from "@prisma/client"; - -// type ChuniScorePlaylog = Prisma.PrismaClient; -// type ChuniStaticMusic = Prisma.PrismaClient; +import { supportedVersionNumber } from "@/lib/helpers"; +import { artemis } from "@/lib/prisma"; export async function getCurrentAvatarParts() { const { user } = await getAuth(); @@ -17,6 +14,7 @@ export async function getCurrentAvatarParts() { const CurrentAvatarParts = await artemis.chuni_profile_data.findMany({ where: { user: user.UserId, + version: supportedVersionNumber, // TODO: eventually change this so the user can set their own version }, select: { avatarSkin: true, @@ -30,7 +28,46 @@ export async function getCurrentAvatarParts() { }); return CurrentAvatarParts; } +export async function updateAvatarParts( + avatarHead?: number, + avatarFace?: number, + avatarBack?: number, + avatarWear?: number, + avatarItem?: number, +) { + const { user } = await getAuth(); + if (!user || !user.accessCode) { + throw new Error("User is not authenticated or accessCode is missing"); + } + + try { + // only including the values that aren't undefined i.e 0 + const AvatarPartData: any = {}; + if (avatarHead !== undefined) AvatarPartData.avatarHead = avatarHead; + if (avatarFace !== undefined) AvatarPartData.avatarFace = avatarFace; + if (avatarBack !== undefined) AvatarPartData.avatarBack = avatarBack; + if (avatarWear !== undefined) AvatarPartData.avatarWear = avatarWear; + if (avatarItem !== undefined) AvatarPartData.avatarItem = avatarItem; + + const UpdateAvatarHead = await artemis.chuni_profile_data.update({ + where: { + user_version: { + user: user.UserId, + version: supportedVersionNumber, + }, + }, + data: AvatarPartData, + }); + + console.log(UpdateAvatarHead); + + return UpdateAvatarHead; + } catch (error) { + console.error("Error updating avatar parts:", error); + throw error; + } +} export async function getAllAvatarParts(category: number) { const { user } = await getAuth(); diff --git a/components/(customization)/avatarcustomization/page.tsx b/components/(customization)/avatarcustomization/page.tsx index d25e2b0..fe9a6fa 100644 --- a/components/(customization)/avatarcustomization/page.tsx +++ b/components/(customization)/avatarcustomization/page.tsx @@ -37,6 +37,7 @@ const getAvatarTextureSrc = (id: number | undefined) => { return `avatarAccessory/CHU_UI_Avatar_Tex_0${id}.png`; }; +import { updateAvatarParts } from "./actions"; type chunithm_avatar = chuni_static_avatar; type AvatarSelectionProps = { @@ -65,21 +66,11 @@ export const AvatarCustomization: FC = ({ avatarWearSelectionData, }) => { const FormSchema = z.object({ - AvatarHeadAccessory: z.number({ - required_error: "Please select an Avatar Head Item.", - }), - AvatarFaceAccessory: z.number({ - required_error: "Please select an Avatar Face Item.", - }), - AvatarItemAccessory: z.number({ - required_error: "Please select an Avatar Item.", - }), - AvatarBackAccessory: z.number({ - required_error: "Please select an Avatar Back Item.", - }), - AvatarWearAccessory: z.number({ - required_error: "Please select an Avatar Wear Item.", - }), + AvatarHeadAccessory: z.number().optional(), + AvatarFaceAccessory: z.number().optional(), + AvatarItemAccessory: z.number().optional(), + AvatarBackAccessory: z.number().optional(), + AvatarWearAccessory: z.number().optional(), }); const form = useForm>({ @@ -87,37 +78,35 @@ export const AvatarCustomization: FC = ({ }); const [avatarFaceId, setAvatarFaceId] = useState( - undefined + undefined, ); const [avatarSkinId, setAvatarSkinId] = useState( - undefined + undefined, ); const [avatarHeadId, setAvatarHeadId] = useState( - undefined + undefined, ); const [avatarWearId, setAvatarWearId] = useState( - undefined + undefined, ); const [avatarBackId, setAvatarBackId] = useState( - undefined + undefined, ); const [avatarItemId, setAvatarItemId] = useState( - undefined + undefined, ); useEffect(() => { const fetchAvatarParts = async () => { try { const data = await getCurrentAvatarParts(); - if (data.length > 0) { - setAvatarFaceId(data[0].avatarFace!); - setAvatarSkinId(data[0].avatarSkin!); - setAvatarHeadId(data[0].avatarHead!); - setAvatarWearId(data[0].avatarWear!); - setAvatarBackId(data[0].avatarBack!); - setAvatarItemId(data[0].avatarItem!); - } + setAvatarFaceId(data[0].avatarFace!); + setAvatarSkinId(data[0].avatarSkin!); + setAvatarHeadId(data[0].avatarHead!); + setAvatarWearId(data[0].avatarWear!); + setAvatarBackId(data[0].avatarBack!); + setAvatarItemId(data[0].avatarItem!); } catch (error) { console.error("Error fetching avatar parts:", error); } @@ -125,18 +114,59 @@ export const AvatarCustomization: FC = ({ fetchAvatarParts(); }, []); - function onSubmit(data: z.infer) { - toast({ - title: "You submitted the following values:", - description: ( -
-          {JSON.stringify(data, null, 2)}
-        
- ), - }); + // Existing state + const unchangedHeadId = avatarHeadId; + const unchangedFaceId = avatarFaceId; + const unchangedBackId = avatarBackId; + const unchangedWearId = avatarWearId; + const unchangedItemId = avatarItemId; + + // either change to the new body part id or fallback to the unchanged if nothing has changed + const newHeadId = data.AvatarHeadAccessory ?? unchangedHeadId; + const newFaceId = data.AvatarFaceAccessory ?? unchangedFaceId; + const newBackId = data.AvatarBackAccessory ?? unchangedBackId; + const newWearId = data.AvatarWearAccessory ?? unchangedWearId; + const newItemId = data.AvatarItemAccessory ?? unchangedItemId; + + updateAvatarParts(newHeadId, newFaceId, newBackId, newWearId, newItemId) + .then(() => { + setAvatarHeadId(newHeadId); + setAvatarFaceId(newFaceId); + setAvatarBackId(newBackId); + setAvatarWearId(newWearId); + setAvatarItemId(newItemId); + + toast({ + title: "Avatar updated successfully!", + description: ( +
+              
+                {JSON.stringify(data, null, 2)}
+              
+            
+ ), + }); + resetFormValues(); + }) + .catch((error) => { + toast({ + title: "Error updating avatar", + description: error.message, + variant: "destructive", + }); + }); } + function resetFormValues() { + form.reset({ + AvatarHeadAccessory: undefined, + AvatarFaceAccessory: undefined, + AvatarItemAccessory: undefined, + AvatarBackAccessory: undefined, + AvatarWearAccessory: undefined, + }); + } const getTexture = (id: number | undefined, defaultSrc: string) => { return id ? getAvatarTextureSrc(id) : defaultSrc; }; @@ -145,49 +175,49 @@ export const AvatarCustomization: FC = ({ AvatarHeadAccessory: { src: getTexture( form.watch("AvatarHeadAccessory"), - `avatarAccessory/CHU_UI_Avatar_Tex_0${avatarHeadId}.png` + `avatarAccessory/CHU_UI_Avatar_Tex_0${avatarHeadId}.png`, ), className: "avatar_head", }, AvatarFaceAccessory: { src: getTexture( form.watch("AvatarFaceAccessory"), - `avatarAccessory/CHU_UI_Avatar_Tex_0${avatarFaceId}.png` + `avatarAccessory/CHU_UI_Avatar_Tex_0${avatarFaceId}.png`, ), className: "avatar_face", }, AvatarItemAccessoryR: { src: getTexture( form.watch("AvatarItemAccessory"), - `avatarAccessory/CHU_UI_Avatar_Tex_0${avatarItemId}.png` + `avatarAccessory/CHU_UI_Avatar_Tex_0${avatarItemId}.png`, ), className: "avatar_item_r ", }, AvatarItemAccessoryL: { src: getTexture( form.watch("AvatarItemAccessory"), - `avatarAccessory/CHU_UI_Avatar_Tex_0${avatarItemId}.png` + `avatarAccessory/CHU_UI_Avatar_Tex_0${avatarItemId}.png`, ), className: "avatar_item_l ", }, AvatarBackAccessory: { src: getTexture( form.watch("AvatarBackAccessory"), - `avatarAccessory/CHU_UI_Avatar_Tex_0${avatarBackId}.png` + `avatarAccessory/CHU_UI_Avatar_Tex_0${avatarBackId}.png`, ), className: "avatar_back", }, AvatarWearAccessory: { src: getTexture( form.watch("AvatarWearAccessory"), - `avatarAccessory/CHU_UI_Avatar_Tex_0${avatarWearId}.png` + `avatarAccessory/CHU_UI_Avatar_Tex_0${avatarWearId}.png`, ), className: "avatar_wear", }, avatarSkinAccessory: { src: getTexture( avatarSkinId, - `avatarAccessory/CHU_UI_Avatar_Tex_0${avatarSkinId}.png` + `avatarAccessory/CHU_UI_Avatar_Tex_0${avatarSkinId}.png`, ), className: "avatar_skin", }, @@ -218,7 +248,7 @@ export const AvatarCustomization: FC = ({ return (
{/* Avatar Customization Section */} -
+
{Object.entries(AvatarTextures).map(([key, { className, src }]) => (
@@ -244,12 +274,13 @@ export const AvatarCustomization: FC = ({ role="combobox" className={cn( "w-[300px] justify-between", - !field.value && "text-muted-foreground" + !field.value && "text-muted-foreground", )} > {field.value ? avatarHeadSelectionData.avatarParts.find( - (part) => part.avatarAccessoryId === field.value + (part) => + part.avatarAccessoryId === field.value, )?.name : "Select Avatar Head Item"} @@ -268,7 +299,7 @@ export const AvatarCustomization: FC = ({ onSelect={() => { form.setValue( "AvatarHeadAccessory", - part.avatarAccessoryId! + part.avatarAccessoryId!, ); }} > @@ -277,7 +308,7 @@ export const AvatarCustomization: FC = ({ "mr-2 h-4 w-4", part.avatarAccessoryId === field.value ? "opacity-100" - : "opacity-0" + : "opacity-0", )} /> {part.name} @@ -308,12 +339,13 @@ export const AvatarCustomization: FC = ({ role="combobox" className={cn( "w-[300px] justify-between", - !field.value && "text-muted-foreground" + !field.value && "text-muted-foreground", )} > {field.value ? avatarFaceSelectionData.avatarParts.find( - (part) => part.avatarAccessoryId === field.value + (part) => + part.avatarAccessoryId === field.value, )?.name : "Select Avatar Face Item"} @@ -332,7 +364,7 @@ export const AvatarCustomization: FC = ({ onSelect={() => { form.setValue( "AvatarFaceAccessory", - part.avatarAccessoryId! + part.avatarAccessoryId!, ); }} > @@ -341,7 +373,7 @@ export const AvatarCustomization: FC = ({ "mr-2 h-4 w-4", part.avatarAccessoryId === field.value ? "opacity-100" - : "opacity-0" + : "opacity-0", )} /> {part.name} @@ -372,12 +404,13 @@ export const AvatarCustomization: FC = ({ role="combobox" className={cn( "w-[300px] justify-between", - !field.value && "text-muted-foreground" + !field.value && "text-muted-foreground", )} > {field.value ? avatarItemSelectionData.avatarParts.find( - (part) => part.avatarAccessoryId === field.value + (part) => + part.avatarAccessoryId === field.value, )?.name : "Select Avatar Face Item"} @@ -396,7 +429,7 @@ export const AvatarCustomization: FC = ({ onSelect={() => { form.setValue( "AvatarItemAccessory", - part.avatarAccessoryId! + part.avatarAccessoryId!, ); }} > @@ -405,7 +438,7 @@ export const AvatarCustomization: FC = ({ "mr-2 h-4 w-4", part.avatarAccessoryId === field.value ? "opacity-100" - : "opacity-0" + : "opacity-0", )} /> {part.name} @@ -436,12 +469,13 @@ export const AvatarCustomization: FC = ({ role="combobox" className={cn( "w-[300px] justify-between", - !field.value && "text-muted-foreground" + !field.value && "text-muted-foreground", )} > {field.value ? avatarBackSelectionData.avatarParts.find( - (part) => part.avatarAccessoryId === field.value + (part) => + part.avatarAccessoryId === field.value, )?.name : "Select Avatar Back Item"} @@ -460,7 +494,7 @@ export const AvatarCustomization: FC = ({ onSelect={() => { form.setValue( "AvatarBackAccessory", - part.avatarAccessoryId! + part.avatarAccessoryId!, ); }} > @@ -469,7 +503,7 @@ export const AvatarCustomization: FC = ({ "mr-2 h-4 w-4", part.avatarAccessoryId === field.value ? "opacity-100" - : "opacity-0" + : "opacity-0", )} /> {part.name} @@ -500,12 +534,13 @@ export const AvatarCustomization: FC = ({ role="combobox" className={cn( "w-[300px] justify-between", - !field.value && "text-muted-foreground" + !field.value && "text-muted-foreground", )} > {field.value ? avatarWearSelectionData.avatarParts.find( - (part) => part.avatarAccessoryId === field.value + (part) => + part.avatarAccessoryId === field.value, )?.name : "Select Avatar Clothing Item"} @@ -524,7 +559,7 @@ export const AvatarCustomization: FC = ({ onSelect={() => { form.setValue( "AvatarWearAccessory", - part.avatarAccessoryId! + part.avatarAccessoryId!, ); }} > @@ -533,7 +568,7 @@ export const AvatarCustomization: FC = ({ "mr-2 h-4 w-4", part.avatarAccessoryId === field.value ? "opacity-100" - : "opacity-0" + : "opacity-0", )} /> {part.name} diff --git a/components/(customization)/mapiconcustomization/actions.ts b/components/(customization)/mapiconcustomization/actions.ts index 81c09c9..b9ee342 100644 --- a/components/(customization)/mapiconcustomization/actions.ts +++ b/components/(customization)/mapiconcustomization/actions.ts @@ -1,11 +1,8 @@ "use server"; import { getAuth } from "@/auth/queries/getauth"; -import { artemis, daphnis } from "@/lib/prisma"; -import type * as Prisma from "@prisma/client"; - -// type ChuniScorePlaylog = Prisma.PrismaClient; -// type ChuniStaticMusic = Prisma.PrismaClient; +import { supportedVersionNumber } from "@/lib/helpers"; +import { artemis } from "@/lib/prisma"; export async function getCurrentMapIcon() { const { user } = await getAuth(); @@ -17,6 +14,7 @@ export async function getCurrentMapIcon() { const currentMapIcon = await artemis.chuni_profile_data.findMany({ where: { user: user.UserId, + version: supportedVersionNumber, }, select: { mapIconId: true, @@ -25,6 +23,37 @@ export async function getCurrentMapIcon() { return currentMapIcon; } +export async function updatePlayerMapIcon(mapIconId?: number) { + const { user } = await getAuth(); + + if (!user || !user.accessCode) { + throw new Error("User is not authenticated or accessCode is missing"); + } + + if (mapIconId === undefined) { + throw new Error("nameplateId is required"); + } + + try { + const updatePlayerMapIconId = await artemis.chuni_profile_data.update({ + where: { + user_version: { + user: user.UserId, + version: supportedVersionNumber, + }, + }, + data: { + mapIconId, + }, + }); + + return updatePlayerMapIconId; + } catch (error) { + console.error("Error updating nameplate:", error); + throw error; + } +} + export async function getMapIcons() { const { user } = await getAuth(); diff --git a/components/(customization)/mapiconcustomization/page.tsx b/components/(customization)/mapiconcustomization/page.tsx index 8fc96df..755f326 100644 --- a/components/(customization)/mapiconcustomization/page.tsx +++ b/components/(customization)/mapiconcustomization/page.tsx @@ -1,7 +1,6 @@ "use client"; import React, { FC, useEffect, useState } from "react"; -import { chuni_static_avatar } from "@/prisma/schemas/artemis/generated/artemis"; import { Check, ChevronsUpDown } from "lucide-react"; import { cn } from "@/lib/utils"; import { Button } from "@/components/ui/button"; @@ -15,7 +14,6 @@ import { import { Form, FormControl, - FormDescription, FormField, FormItem, FormLabel, @@ -31,10 +29,10 @@ import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import { toast } from "../../ui/use-toast"; import { cozynet_chuni_static_mapicon } from "@/prisma/schemas/artemis/generated/artemis"; -import { getCurrentMapIcon } from "./actions"; +import { getCurrentMapIcon, updatePlayerMapIcon } from "./actions"; + const getNamePlateTextures = (id: number | undefined) => { if (id === undefined) return ""; - // Pad the id to be 8 digits long, using leading zeros const paddedId = id.toString().padStart(8, "0"); return `mapIcon/CHU_UI_MapIcon_${paddedId}.png`; }; @@ -51,7 +49,7 @@ export const MapIconCustomization: FC = ({ playerMapIconCustomization, }) => { const FormSchema = z.object({ - PlayerMapIcon: z.number({ + mapIconId: z.number({ required_error: "Please select an Avatar Head Item.", }), }); @@ -78,6 +76,14 @@ export const MapIconCustomization: FC = ({ }, []); function onSubmit(data: z.infer) { + const uncangedMapIconId = mapIconId; + const newMapIconId = data.mapIconId ?? uncangedMapIconId; + + updatePlayerMapIcon(newMapIconId).then(() => { + setMapIconId(newMapIconId); + }); + resetFormValues(); + toast({ title: "You submitted the following values:", description: ( @@ -86,18 +92,24 @@ export const MapIconCustomization: FC = ({ ), }); + + function resetFormValues() { + form.reset({ + mapIconId: undefined, + }); + } } const getTexture = (id: number | undefined, defaultSrc: string) => { return id ? getNamePlateTextures(id) : defaultSrc; }; - const AvatarTextures = { - AvatarHeadAccessory: { + const MapIconTextures = { + mapIconId: { src: mapIconId ? getTexture( - form.watch("PlayerMapIcon"), - `mapIcon/CHU_UI_MapIcon_${mapIconId.toString().padStart(8, "0")}.png` + form.watch("mapIconId"), + `mapIcon/CHU_UI_MapIcon_${mapIconId.toString().padStart(8, "0")}.png`, ) : `systemVoiceThumbnails/CHU_UI_SystemVoice_Default.png`, }, @@ -105,10 +117,9 @@ export const MapIconCustomization: FC = ({ return (
- {/* Avatar Customization Section */} -
+
- {Object.entries(AvatarTextures).map(([key, { src }]) => ( + {Object.entries(MapIconTextures).map(([key, { src }]) => (
{""}
@@ -119,7 +130,7 @@ export const MapIconCustomization: FC = ({
( Select Map Icon @@ -131,12 +142,12 @@ export const MapIconCustomization: FC = ({ role="combobox" className={cn( "w-[300px] justify-between", - !field.value && "text-muted-foreground" + !field.value && "text-muted-foreground", )} > {field.value ? playerMapIconCustomization.mapIcon.find( - (part) => part.id === field.value + (part) => part.id === field.value, )?.str : "Select Map Icon"} @@ -153,7 +164,7 @@ export const MapIconCustomization: FC = ({ value={part.str ?? ""} key={part.id} onSelect={() => { - form.setValue("PlayerMapIcon", part.id!); + form.setValue("mapIconId", part.id!); }} > = ({ "mr-2 h-4 w-4", part.id === field.value ? "opacity-100" - : "opacity-0" + : "opacity-0", )} /> {part.str} diff --git a/components/(customization)/nameplatecustomization/actions.ts b/components/(customization)/nameplatecustomization/actions.ts index 377007d..96dc5a0 100644 --- a/components/(customization)/nameplatecustomization/actions.ts +++ b/components/(customization)/nameplatecustomization/actions.ts @@ -1,11 +1,8 @@ "use server"; import { getAuth } from "@/auth/queries/getauth"; -import { artemis, daphnis } from "@/lib/prisma"; -import type * as Prisma from "@prisma/client"; - -// type ChuniScorePlaylog = Prisma.PrismaClient; -// type ChuniStaticMusic = Prisma.PrismaClient; +import { supportedVersionNumber } from "@/lib/helpers"; +import { artemis } from "@/lib/prisma"; export async function getCurrentNameplate() { const { user } = await getAuth(); @@ -17,6 +14,7 @@ export async function getCurrentNameplate() { const currentNameplate = await artemis.chuni_profile_data.findMany({ where: { user: user.UserId, + version: supportedVersionNumber, }, select: { nameplateId: true, @@ -25,6 +23,39 @@ export async function getCurrentNameplate() { return currentNameplate; } +export async function updatePlayerNamePlate(nameplateId?: number) { + const { user } = await getAuth(); + + if (!user || !user.accessCode) { + throw new Error("User is not authenticated or accessCode is missing"); + } + + if (nameplateId === undefined) { + throw new Error("nameplateId is required"); + } + + try { + const updatePlayerNameplate = await artemis.chuni_profile_data.update({ + where: { + user_version: { + user: user.UserId, + version: supportedVersionNumber, + }, + }, + data: { + nameplateId, + }, + }); + + console.log(updatePlayerNameplate); + + return updatePlayerNameplate; + } catch (error) { + console.error("Error updating nameplate:", error); + throw error; + } +} + export async function getNamePlates() { const { user } = await getAuth(); diff --git a/components/(customization)/nameplatecustomization/page.tsx b/components/(customization)/nameplatecustomization/page.tsx index 4a37aaa..7efba6d 100644 --- a/components/(customization)/nameplatecustomization/page.tsx +++ b/components/(customization)/nameplatecustomization/page.tsx @@ -2,7 +2,7 @@ import React, { FC, useEffect, useState } from "react"; import { Check, ChevronsUpDown } from "lucide-react"; -import { getCurrentNameplate } from "./actions"; +import { getCurrentNameplate, updatePlayerNamePlate } from "./actions"; import { cn } from "@/lib/utils"; import { Button } from "@/components/ui/button"; import { @@ -51,7 +51,7 @@ export const NameplateCustomization: FC = ({ playerNamePlateSelectionData, }) => { const FormSchema = z.object({ - PlayerNamePlateId: z.number({ + nameplateId: z.number({ required_error: "Please select an Avatar Head Item.", }), }); @@ -61,7 +61,6 @@ export const NameplateCustomization: FC = ({ }); const [nameplateId, setNameplateId] = useState(undefined); - useEffect(() => { const fetchNamePlates = async () => { try { @@ -78,6 +77,14 @@ export const NameplateCustomization: FC = ({ }, []); function onSubmit(data: z.infer) { + const unchangedNamePlateId = nameplateId; + const newNamePlateId = data.nameplateId ?? unchangedNamePlateId; + + updatePlayerNamePlate(newNamePlateId).then(() => { + setNameplateId(newNamePlateId); + }); + resetFormValues(); + toast({ title: "You submitted the following values:", description: ( @@ -86,18 +93,25 @@ export const NameplateCustomization: FC = ({ ), }); + + function resetFormValues() { + form.reset({ + nameplateId: undefined, + }); + } } const getTexture = (id: number | undefined, defaultSrc: string) => { return id ? getNamePlateTextures(id) : defaultSrc; }; - const AvatarTextures = { - AvatarHeadAccessory: { + const namePlateTextures = { + namePlateTexture: { src: nameplateId ? getTexture( - form.watch("PlayerNamePlateId"), - `namePlates/CHU_UI_NamePlate_${nameplateId.toString().padStart(8, "0")}.png` + form.watch("nameplateId"), + + `namePlates/CHU_UI_NamePlate_${nameplateId.toString().padStart(8, "0")}.png`, ) : `systemVoiceThumbnails/CHU_UI_SystemVoice_Default.png`, }, @@ -106,9 +120,9 @@ export const NameplateCustomization: FC = ({ return (
{/* Avatar Customization Section */} -
+
- {Object.entries(AvatarTextures).map(([key, { src }]) => ( + {Object.entries(namePlateTextures).map(([key, { src }]) => (
{""}
@@ -119,7 +133,7 @@ export const NameplateCustomization: FC = ({ ( Select Nameplate @@ -131,12 +145,12 @@ export const NameplateCustomization: FC = ({ role="combobox" className={cn( "w-[300px] justify-between", - !field.value && "text-muted-foreground" + !field.value && "text-muted-foreground", )} > {field.value ? playerNamePlateSelectionData.namePlates.find( - (part) => part.id === field.value + (part) => part.id === field.value, )?.str : "Select Name Plate"} @@ -154,7 +168,7 @@ export const NameplateCustomization: FC = ({ value={part.str ?? ""} key={part.id} onSelect={() => { - form.setValue("PlayerNamePlateId", part.id!); + form.setValue("nameplateId", part.id!); }} > = ({ "mr-2 h-4 w-4", part.id === field.value ? "opacity-100" - : "opacity-0" + : "opacity-0", )} /> {part.str} - ) + ), )} diff --git a/components/(customization)/systemvoicecustomization/actions.ts b/components/(customization)/systemvoicecustomization/actions.ts index 5691f68..23d6284 100644 --- a/components/(customization)/systemvoicecustomization/actions.ts +++ b/components/(customization)/systemvoicecustomization/actions.ts @@ -1,11 +1,8 @@ "use server"; import { getAuth } from "@/auth/queries/getauth"; -import { artemis, daphnis } from "@/lib/prisma"; -import type * as Prisma from "@prisma/client"; - -// type ChuniScorePlaylog = Prisma.PrismaClient; -// type ChuniStaticMusic = Prisma.PrismaClient; +import { supportedVersionNumber } from "@/lib/helpers"; +import { artemis } from "@/lib/prisma"; export async function getCurrentSystemVoice() { const { user } = await getAuth(); @@ -17,6 +14,7 @@ export async function getCurrentSystemVoice() { const currentSystemVoice = await artemis.chuni_profile_data.findMany({ where: { user: user.UserId, + version: supportedVersionNumber, }, select: { voiceId: true, @@ -25,6 +23,39 @@ export async function getCurrentSystemVoice() { return currentSystemVoice; } +export async function updatePlayerSystemVoiceId(voiceId: number) { + const { user } = await getAuth(); + + if (!user || !user.accessCode) { + throw new Error("User is not authenticated or accessCode is missing"); + } + + if (voiceId === undefined) { + throw new Error("nameplateId is required"); + } + + try { + const updatePlayerNameplate = await artemis.chuni_profile_data.update({ + where: { + user_version: { + user: user.UserId, + version: supportedVersionNumber, + }, + }, + data: { + voiceId, + }, + }); + + console.log(updatePlayerNameplate); + + return updatePlayerNameplate; + } catch (error) { + console.error("Error updating nameplate:", error); + throw error; + } +} + export async function getSystemVoices() { const { user } = await getAuth(); diff --git a/components/(customization)/systemvoicecustomization/page.tsx b/components/(customization)/systemvoicecustomization/page.tsx index cb6f85f..b7f5c04 100644 --- a/components/(customization)/systemvoicecustomization/page.tsx +++ b/components/(customization)/systemvoicecustomization/page.tsx @@ -31,7 +31,11 @@ import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import { toast } from "../../ui/use-toast"; import { cozynet_chuni_static_systemvoice } from "@/prisma/schemas/artemis/generated/artemis"; -import { getCurrentSystemVoice, getSystemVoices } from "./actions"; +import { + getCurrentSystemVoice, + getSystemVoices, + updatePlayerSystemVoiceId, +} from "./actions"; const getNamePlateTextures = (id: number | undefined) => { if (id === undefined) return ""; @@ -62,7 +66,7 @@ export const SystemVoiceCustomization: FC = ({ }); const [systemVoiceId, setSytemVoiceId] = useState( - undefined + undefined, ); useEffect(() => { @@ -81,6 +85,14 @@ export const SystemVoiceCustomization: FC = ({ }, []); function onSubmit(data: z.infer) { + const unchagedSystemVoiceId = systemVoiceId; + const newSystemVoiceId = data.PlayerSystemVoice ?? unchagedSystemVoiceId; + + updatePlayerSystemVoiceId(newSystemVoiceId).then(() => { + setSytemVoiceId(newSystemVoiceId); + }); + resetFormValues(); + toast({ title: "You submitted the following values:", description: ( @@ -89,18 +101,24 @@ export const SystemVoiceCustomization: FC = ({ ), }); + + function resetFormValues() { + form.reset({ + PlayerSystemVoice: undefined, + }); + } } const getTexture = (id: number | undefined, defaultSrc: string) => { return id ? getNamePlateTextures(id) : defaultSrc; }; - const AvatarTextures = { - AvatarHeadAccessory: { + const systemVoiceTextures = { + SystemVoice: { src: systemVoiceId ? getTexture( form.watch("PlayerSystemVoice"), - `systemVoiceThumbnails/CHU_UI_SystemVoice_${systemVoiceId.toString().padStart(8, "0")}.png` + `systemVoiceThumbnails/CHU_UI_SystemVoice_${systemVoiceId.toString().padStart(8, "0")}.png`, ) : `systemVoiceThumbnails/CHU_UI_SystemVoice_Default.png`, // Provide a default texture or handle the case when systemVoiceId is undefined }, @@ -109,9 +127,9 @@ export const SystemVoiceCustomization: FC = ({ return (
{/* Avatar Customization Section */} -
+
- {Object.entries(AvatarTextures).map(([key, { src }]) => ( + {Object.entries(systemVoiceTextures).map(([key, { src }]) => (
{""}
@@ -134,12 +152,12 @@ export const SystemVoiceCustomization: FC = ({ role="combobox" className={cn( "w-[300px] justify-between", - !field.value && "text-muted-foreground" + !field.value && "text-muted-foreground", )} > {field.value ? playerSystemVoiceSelectionData.systemVoices.find( - (part) => part.id === field.value + (part) => part.id === field.value, )?.str : "Select System Voice"} @@ -165,12 +183,12 @@ export const SystemVoiceCustomization: FC = ({ "mr-2 h-4 w-4", part.id === field.value ? "opacity-100" - : "opacity-0" + : "opacity-0", )} /> {part.str} - ) + ), )} diff --git a/components/(customization)/trophycustomization/actions.ts b/components/(customization)/trophycustomization/actions.ts index 135e582..c87238b 100644 --- a/components/(customization)/trophycustomization/actions.ts +++ b/components/(customization)/trophycustomization/actions.ts @@ -1,8 +1,8 @@ "use server"; import { getAuth } from "@/auth/queries/getauth"; -import { artemis, daphnis } from "@/lib/prisma"; -import type * as Prisma from "@prisma/client"; +import { supportedVersionNumber } from "@/lib/helpers"; +import { artemis } from "@/lib/prisma"; export async function getCurrentTrophies() { const { user } = await getAuth(); @@ -14,6 +14,7 @@ export async function getCurrentTrophies() { const CurrentTrophy = await artemis.chuni_profile_data.findMany({ where: { user: user.UserId, + version: supportedVersionNumber, }, select: { trophyId: true, @@ -22,6 +23,39 @@ export async function getCurrentTrophies() { return CurrentTrophy; } +export async function updatePlayerTrophy(trophyId: number) { + const { user } = await getAuth(); + + if (!user || !user.accessCode) { + throw new Error("User is not authenticated or accessCode is missing"); + } + + if (trophyId === undefined) { + throw new Error("nameplateId is required"); + } + + try { + const updatePlayerNameplate = await artemis.chuni_profile_data.update({ + where: { + user_version: { + user: user.UserId, + version: supportedVersionNumber, + }, + }, + data: { + trophyId, + }, + }); + + console.log(updatePlayerNameplate); + + return updatePlayerNameplate; + } catch (error) { + console.error("Error updating nameplate:", error); + throw error; + } +} + export async function getTrophies() { const { user } = await getAuth(); diff --git a/components/(customization)/trophycustomization/page.tsx b/components/(customization)/trophycustomization/page.tsx index 69143c5..30ae1aa 100644 --- a/components/(customization)/trophycustomization/page.tsx +++ b/components/(customization)/trophycustomization/page.tsx @@ -30,7 +30,7 @@ import { z } from "zod"; import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import { toast } from "../../ui/use-toast"; -import { getCurrentTrophies } from "./actions"; +import { getCurrentTrophies, updatePlayerTrophy } from "./actions"; import { cozynet_chuni_static_trophies } from "@/prisma/schemas/artemis/generated/artemis"; const getAvatarTextureSrc = (id: number | undefined) => { if (id === undefined) return ""; @@ -76,6 +76,14 @@ export const TrophyCustomization: FC = ({ }, []); function onSubmit(data: z.infer) { + const unchangedNamePlateId = trophyID; + const newNamePlateId = data.trophies ?? unchangedNamePlateId; + + updatePlayerTrophy(newNamePlateId).then(() => { + setTrophyId(newNamePlateId); + }); + resetFormValues(); + toast({ title: "You submitted the following values:", description: ( @@ -84,6 +92,12 @@ export const TrophyCustomization: FC = ({ ), }); + + function resetFormValues() { + form.reset({ + trophies: undefined, + }); + } } return ( diff --git a/lib/helpers.ts b/lib/helpers.ts index bbf37de..9beb192 100644 --- a/lib/helpers.ts +++ b/lib/helpers.ts @@ -51,3 +51,7 @@ export const getGrade = (score: number) => { if (score < 500000) return "D"; return ""; }; + +export const supportedVersionNumber = Number( + process.env.SUPPORTED_CHUNITHM_VERSION_NUMBER, +);