feat: add store nav and fixes

This commit is contained in:
DecDucK
2026-01-24 20:25:08 +11:00
parent 00adab21c2
commit aea9a2766d
8 changed files with 69 additions and 28 deletions

View File

@@ -59,7 +59,6 @@ const emit = defineEmits<{
const open = defineModel<boolean>({ required: true });
const { t } = useI18n();
const collectionName = ref("");
const createCollectionLoading = ref(false);
const collections = await useCollections();
@@ -74,6 +73,7 @@ async function createCollection() {
const response = await $dropFetch("/api/v1/collection", {
method: "POST",
body: { name: collectionName.value },
failTitle: "Failed to create collection",
});
// Add the game if provided
@@ -83,6 +83,7 @@ async function createCollection() {
>(`/api/v1/collection/${response.id}/entry`, {
method: "POST",
body: { id: props.gameId },
failTitle: "Failed to add game to collection",
});
response.entries.push(entry);
}
@@ -94,20 +95,6 @@ async function createCollection() {
open.value = false;
emit("created", response.id);
} catch (error) {
console.error("Failed to create collection:", error);
const err = error as { statusMessage?: string };
createModal(
ModalType.Notification,
{
title: t("errors.library.collection.create.title"),
description: t("errors.library.collection.create.desc", [
err?.statusMessage ?? t("errors.unknown"),
]),
},
(_, c) => c(),
);
} finally {
createCollectionLoading.value = false;
}

View File

@@ -0,0 +1,39 @@
<template>
<div
class="w-full bg-zinc-950 p-1 inline-flex items-center gap-x-2 fixed inset-x-0 top-0 z-100"
>
<button
class="p-1 text-zinc-300 hover:text-zinc-100 hover:bg-zinc-900 transition-all rounded"
@click="() => router.back()"
>
<ChevronLeftIcon class="size-4" />
</button>
<button
class="p-1 text-zinc-300 hover:text-zinc-100 hover:bg-zinc-900 transition-all rounded"
@click="() => router.forward()"
>
<ChevronRightIcon class="size-4" />
</button>
<span class="text-zinc-400 text-sm">
{{ title }}
</span>
</div>
</template>
<script setup lang="ts">
import { ChevronLeftIcon, ChevronRightIcon } from "@heroicons/vue/24/outline";
const router = useRouter();
const title = ref("Loading...");
onMounted(() => {
title.value = document.title;
});
router.afterEach(() => {
title.value = "Loading...";
// TODO: more robust after-render "detection"
setTimeout(() => {
title.value = document.title;
}, 500);
});
</script>

View File

@@ -1,12 +1,14 @@
services:
postgres:
image: postgres:14-alpine
user: "1000:1000"
ports:
- 5432:5432
volumes:
- ../.data/db:/var/lib/postgresql/data
- postgres-data:/var/lib/postgresql/data
environment:
- POSTGRES_PASSWORD=drop
- POSTGRES_USER=drop
- POSTGRES_DB=drop
volumes:
postgres-data:

View File

@@ -9,8 +9,9 @@
</div>
<LazyUserFooter class="z-50" hydrate-on-interaction />
</div>
<div v-else class="flex w-full min-h-screen bg-zinc-900">
<div v-else class="flex flex-col w-full min-h-screen bg-zinc-900">
<NuxtPage />
<LazyUserHeaderStoreNav />
</div>
</template>

View File

@@ -250,7 +250,7 @@ export default defineNuxtConfig({
"https://images.pcgamingwiki.com",
"https://images.igdb.com",
"https://*.steamstatic.com",
],
]
},
strictTransportSecurity: false,
},

View File

@@ -39,7 +39,7 @@
<AddLibraryButton :game-id="game.id" />
</div>
<NuxtLink
v-if="user?.admin"
v-if="user?.admin && !isClient"
:href="`/admin/library/${game.id}`"
type="button"
class="inline-flex items-center gap-x-2 rounded-md bg-zinc-800 px-3 py-1 text-sm font-semibold font-display text-white shadow-sm hover:bg-zinc-700 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600 duration-200 hover:scale-105 active:scale-95"
@@ -254,6 +254,8 @@ const user = useUser();
const { game, rating, size } = await $dropFetch(`/api/v1/games/${gameId}`);
const isClient = isClientRequest();
const descriptionHTML = micromark(game.mDescription);
const platforms = game.versions

View File

@@ -12,9 +12,17 @@ export default defineClientEventHandler(
const acls: UserACL = [
"read",
"store:read",
"collections:read",
"object:read",
"settings:read",
"collections:read",
"collections:new",
"collections:add",
"collections:remove",
"collections:delete",
"library:add",
"library:remove"
];
const token = await prisma.aPIToken.create({

View File

@@ -1,20 +1,22 @@
import { type } from "arktype";
import { readDropValidatedBody, throwingArktype } from "~/server/arktype";
import aclManager from "~/server/internal/acls";
import userLibraryManager from "~/server/internal/userlibrary";
const CreateCollection = type({
name: "string"
}).configure(throwingArktype);
export default defineEventHandler(async (h3) => {
const userId = await aclManager.getUserIdACL(h3, ["collections:read"]);
const userId = await aclManager.getUserIdACL(h3, ["collections:new"]);
if (!userId)
throw createError({
statusCode: 403,
});
const body = await readBody(h3);
const name = body.name;
if (!name)
throw createError({ statusCode: 400, statusMessage: "Requires name" });
const body = await readDropValidatedBody(h3, CreateCollection);
// Create the collection using the manager
const newCollection = await userLibraryManager.collectionCreate(name, userId);
const newCollection = await userLibraryManager.collectionCreate(body.name, userId);
return newCollection;
});