feat: rearchitecture of database schemas, migration reset, and #180

This commit is contained in:
DecDuck
2025-08-20 20:35:50 +10:00
parent 6853383e86
commit 322af0b4ca
125 changed files with 1384 additions and 1837 deletions

View File

@ -51,7 +51,11 @@
@update="() => updateVersionOrder()"
>
<template
#item="{ element: item }: { element: GameVersionModel }"
#item="{
element: item,
}: {
element: VersionModel & { gameVersion: GameVersionModel };
}"
>
<div
class="w-full inline-flex items-center px-4 py-2 bg-zinc-800 rounded justify-between"
@ -60,7 +64,11 @@
{{ item.versionName }}
</div>
<div class="text-zinc-400">
{{ item.delta ? $t("library.admin.version.delta") : "" }}
{{
item.gameVersion.delta
? $t("library.admin.version.delta")
: ""
}}
</div>
<div class="inline-flex items-center gap-x-2">
<component
@ -70,7 +78,7 @@
<Bars3Icon
class="cursor-move w-6 h-6 text-zinc-400 handle"
/>
<button @click="() => deleteVersion(item.versionName)">
<button @click="() => deleteVersion(item.versionId)">
<TrashIcon class="w-5 h-5 text-red-600" />
</button>
</div>
@ -112,7 +120,11 @@
</template>
<script setup lang="ts">
import type { GameModel, GameVersionModel } from "~/prisma/client/models";
import type {
GameModel,
GameVersionModel,
VersionModel,
} from "~/prisma/client/models";
import { Bars3Icon, TrashIcon } from "@heroicons/vue/24/solid";
import type { SerializeObject } from "nitropack";
import type { H3Error } from "h3";
@ -130,7 +142,9 @@ const canImport = computed(
() => hasDeleted.value || props.unimportedVersions.length > 0,
);
type GameAndVersions = GameModel & { versions: GameVersionModel[] };
type GameAndVersions = GameModel & {
versions: (VersionModel & { gameVersion: GameVersionModel })[];
};
const game = defineModel<SerializeObject<GameAndVersions>>() as Ref<
SerializeObject<GameAndVersions>
>;
@ -146,7 +160,7 @@ async function updateVersionOrder() {
method: "PATCH",
body: {
id: game.value.id,
versions: game.value.versions.map((e) => e.versionName),
versions: game.value.versions.map((e) => e.versionId),
},
});
game.value.versions = newVersions;
@ -165,32 +179,18 @@ async function updateVersionOrder() {
}
}
async function deleteVersion(versionName: string) {
try {
await $dropFetch("/api/v1/admin/game/version", {
method: "DELETE",
body: {
id: game.value.id,
versionName: versionName,
},
});
game.value.versions.splice(
game.value.versions.findIndex((e) => e.versionName === versionName),
1,
);
hasDeleted.value = true;
} catch (e) {
createModal(
ModalType.Notification,
{
title: t("errors.version.delete.title"),
description: t("errors.version.delete.desc", {
error: (e as H3Error)?.statusMessage ?? t("errors.unknown"),
}),
buttonText: t("common.close"),
},
(e, c) => c(),
);
}
async function deleteVersion(versionId: string) {
await $dropFetch("/api/v1/admin/game/version", {
method: "DELETE",
body: {
id: versionId,
},
failTitle: "Failed to delete version.",
});
game.value.versions.splice(
game.value.versions.findIndex((e) => e.versionId === versionId),
1,
);
hasDeleted.value = true;
}
</script>

View File

@ -32,7 +32,7 @@
class="absolute z-10 mt-1 max-h-56 w-full overflow-auto rounded-md bg-zinc-900 py-1 text-base shadow-lg ring-1 ring-zinc-950 ring-opacity-5 focus:outline-none sm:text-sm"
>
<ListboxOption
v-for="[name, value] in Object.entries(values)"
v-for="[name, value] in values"
:key="value"
v-slot="{ active, selected }"
as="template"
@ -82,10 +82,11 @@ import {
ListboxOptions,
} from "@headlessui/vue";
import { CheckIcon, ChevronUpDownIcon } from "@heroicons/vue/20/solid";
import { Platform } from "~/prisma/client/enums";
const model = defineModel<PlatformClient | undefined>();
const model = defineModel<Platform | undefined>();
const typedModel = computed<PlatformClient | null>({
const typedModel = computed<Platform | null>({
get() {
return model.value || null;
},
@ -95,5 +96,5 @@ const typedModel = computed<PlatformClient | null>({
},
});
const values = Object.fromEntries(Object.entries(PlatformClient));
const values = Object.entries(Platform);
</script>

View File

@ -361,6 +361,7 @@ import {
import type { SerializeObject } from "nitropack";
import type { GameModel, GameTagModel } from "~/prisma/client/models";
import MultiItemSelector from "./MultiItemSelector.vue";
import { Platform } from "~/prisma/client/enums";
const { showGamePanelTextDecoration } = await $dropFetch(`/api/v1/settings`);
const mobileFiltersOpen = ref(false);
@ -407,7 +408,7 @@ const options: Array<StoreFilterOption> = [
name: "Platform",
param: "platform",
multiple: true,
options: Object.values(PlatformClient).map((e) => ({ name: e, param: e })),
options: Object.values(Platform).map((e) => ({ name: e, param: e })),
},
...(props.extraOptions ?? []),
];