mirror of
https://github.com/Drop-OSS/drop.git
synced 2025-11-12 07:42:40 +10:00
feat: refactor & redesign parts of UI
This commit is contained in:
@ -31,16 +31,7 @@
|
||||
:src="useObject(game.mCoverId)"
|
||||
/>
|
||||
<div class="flex items-center gap-x-2">
|
||||
<AddLibraryButton
|
||||
:gameId="game.id"
|
||||
:isProcessing="isAddingToLibrary"
|
||||
:isInLibrary="isInLibrary"
|
||||
:collections="collections"
|
||||
:collectionStates="collectionStates"
|
||||
@add-to-library="addToLibrary"
|
||||
@toggle-collection="toggleCollection"
|
||||
@create-collection="showCreateCollectionModal = true"
|
||||
/>
|
||||
<AddLibraryButton :gameId="game.id" />
|
||||
</div>
|
||||
<NuxtLink
|
||||
v-if="user?.admin"
|
||||
@ -125,7 +116,9 @@
|
||||
/>
|
||||
</VueSlide>
|
||||
<VueSlide v-if="game.mImageCarousel.length == 0">
|
||||
<div class="h-48 lg:h-96 aspect-[1/2] flex items-center justify-center text-zinc-700 font-bold font-display">
|
||||
<div
|
||||
class="h-48 lg:h-96 aspect-[1/2] flex items-center justify-center text-zinc-700 font-bold font-display"
|
||||
>
|
||||
No images
|
||||
</div>
|
||||
</VueSlide>
|
||||
@ -165,40 +158,18 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Add this modal at the end of the template -->
|
||||
<CreateCollectionModal
|
||||
:show="showCreateCollectionModal"
|
||||
:gameId="game.id"
|
||||
@close="showCreateCollectionModal = false"
|
||||
@created="handleCollectionCreated"
|
||||
/>
|
||||
|
||||
<!-- Delete Collection Confirmation Modal -->
|
||||
<DeleteCollectionModal
|
||||
:show="showDeleteModal"
|
||||
:collection="collectionToDelete"
|
||||
@close="showDeleteModal = false"
|
||||
@deleted="handleCollectionDeleted"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { IconsLinuxLogo, IconsWindowsLogo } from "#components";
|
||||
import { PlusIcon, EllipsisVerticalIcon, TrashIcon, ChevronDownIcon } from "@heroicons/vue/20/solid";
|
||||
import { ArrowTopRightOnSquareIcon } from "@heroicons/vue/24/outline";
|
||||
import { StarIcon, CheckIcon } from "@heroicons/vue/24/solid";
|
||||
import { StarIcon } from "@heroicons/vue/24/solid";
|
||||
import { type Game, type GameVersion } from "@prisma/client";
|
||||
import { micromark } from "micromark";
|
||||
import moment from "moment";
|
||||
import { PlatformClient } from "~/composables/types";
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { Menu, MenuButton, MenuItems, MenuItem } from "@headlessui/vue";
|
||||
import { TransitionRoot, Dialog, DialogPanel, DialogTitle, TransitionChild } from "@headlessui/vue";
|
||||
import { ref } from "vue";
|
||||
import AddLibraryButton from "~/components/AddLibraryButton.vue";
|
||||
import CreateCollectionModal from "~/components/CreateCollectionModal.vue";
|
||||
import DeleteCollectionModal from "~/components/DeleteCollectionModal.vue";
|
||||
|
||||
const route = useRoute();
|
||||
const gameId = route.params.id.toString();
|
||||
@ -245,102 +216,6 @@ const ratingArray = Array(5)
|
||||
.fill(null)
|
||||
.map((_, i) => i + 1 <= rating);
|
||||
|
||||
const isAddingToLibrary = ref(false);
|
||||
|
||||
const collections = ref<Collection[]>([]);
|
||||
const collectionStates = ref<{ [key: string]: boolean }>({});
|
||||
const isInLibrary = ref(false);
|
||||
|
||||
const showCreateCollectionModal = ref(false);
|
||||
const newCollectionName = ref('');
|
||||
const isCreatingCollection = ref(false);
|
||||
|
||||
const showDeleteModal = ref(false)
|
||||
const collectionToDelete = ref<Collection | null>(null)
|
||||
|
||||
onMounted(async () => {
|
||||
try {
|
||||
// Fetch collections with their entries
|
||||
collections.value = await $fetch<Collection[]>('/api/v1/collection', { headers })
|
||||
|
||||
// Check which collections have this game
|
||||
for (const collection of collections.value) {
|
||||
const hasGame = collection.entries?.some(entry => entry.gameId === game.id)
|
||||
collectionStates.value[collection.id] = !!hasGame
|
||||
// If it's in the default collection, update isInLibrary
|
||||
if (collection.isDefault && hasGame) {
|
||||
isInLibrary.value = true
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch collections:', error)
|
||||
}
|
||||
});
|
||||
|
||||
const toggleCollection = async (collectionId: string) => {
|
||||
try {
|
||||
if (collectionStates.value[collectionId]) {
|
||||
// Remove from collection
|
||||
await $fetch(`/api/v1/collection/${collectionId}/entry`, {
|
||||
method: 'DELETE',
|
||||
body: { id: game.id }
|
||||
})
|
||||
} else {
|
||||
// Add to collection
|
||||
await $fetch(`/api/v1/collection/${collectionId}/entry`, {
|
||||
method: 'POST',
|
||||
body: { id: game.id }
|
||||
})
|
||||
}
|
||||
// Toggle state
|
||||
collectionStates.value[collectionId] = !collectionStates.value[collectionId]
|
||||
} catch (error) {
|
||||
console.error('Failed to toggle collection:', error)
|
||||
}
|
||||
}
|
||||
|
||||
const addToLibrary = async () => {
|
||||
if (isAddingToLibrary.value) return;
|
||||
|
||||
try {
|
||||
isAddingToLibrary.value = true;
|
||||
const defaultCollection = collections.value.find(c => c.isDefault);
|
||||
if (!defaultCollection) return;
|
||||
|
||||
if (isInLibrary.value) {
|
||||
// Remove from library
|
||||
await $fetch(`/api/v1/collection/${defaultCollection.id}/entry`, {
|
||||
method: "DELETE",
|
||||
body: { id: game.id }
|
||||
});
|
||||
} else {
|
||||
// Add to library
|
||||
await $fetch(`/api/v1/collection/default/entry`, {
|
||||
method: "POST",
|
||||
body: { id: game.id }
|
||||
});
|
||||
}
|
||||
// Toggle state
|
||||
isInLibrary.value = !isInLibrary.value;
|
||||
} catch (error) {
|
||||
console.error("Failed to modify library:", error);
|
||||
} finally {
|
||||
isAddingToLibrary.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const handleCollectionCreated = async (collectionId: string) => {
|
||||
// Refresh collections
|
||||
collections.value = await $fetch<Collection[]>('/api/v1/collection', { headers });
|
||||
// Set initial state for the new collection
|
||||
collectionStates.value[collectionId] = true;
|
||||
};
|
||||
|
||||
const handleCollectionDeleted = (collectionId: string) => {
|
||||
collections.value = collections.value.filter(c => c.id !== collectionId);
|
||||
collectionToDelete.value = null;
|
||||
};
|
||||
|
||||
useHead({
|
||||
title: game.mName,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user