86 lines
2.8 KiB
Vue
86 lines
2.8 KiB
Vue
<script setup lang="ts">
|
|
import { computed } from 'vue';
|
|
import { useRoute } from 'vue-router';
|
|
// @ts-ignore
|
|
import dashboardData from '~/dashboard.yml';
|
|
|
|
const route = useRoute();
|
|
const slugPath = Array.isArray(route.params.slug) ? route.params.slug.filter(Boolean) : (route.params.slug ? route.params.slug.split('/').filter(Boolean) : []);
|
|
|
|
// The imported data is an array of items
|
|
const allItems = computed(() => dashboardData || []);
|
|
|
|
let currentFolderId: string | null = null;
|
|
let currentFolder: any = null;
|
|
|
|
// Resolve current folder based on the slug path
|
|
for (const part of slugPath) {
|
|
const folder = allItems.value.find((item: any) => item.type === 'folder' && item.slug === part && item.parentId === currentFolderId);
|
|
if (folder) {
|
|
currentFolder = folder;
|
|
currentFolderId = folder.id;
|
|
}
|
|
}
|
|
|
|
// Get children of the current folder
|
|
const items = computed(() => {
|
|
return allItems.value
|
|
.filter((item: any) => item.parentId === currentFolderId)
|
|
.sort((a: any, b: any) => (a.order || 0) - (b.order || 0));
|
|
});
|
|
|
|
const breadcrumbs = computed(() => {
|
|
let path = '';
|
|
const crumbs = [{ label: 'Desktop', to: '/' }];
|
|
|
|
slugPath.forEach(part => {
|
|
path += `/${part}`;
|
|
crumbs.push({ label: part, to: path });
|
|
});
|
|
|
|
return crumbs;
|
|
});
|
|
const backUrl = computed(() => {
|
|
if (slugPath.length <= 1) return '/';
|
|
return '/' + slugPath.slice(0, -1).join('/');
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<div class="h-full flex flex-col p-6">
|
|
<div class="flex items-center justify-between mb-8">
|
|
<UBreadcrumb :items="breadcrumbs" class="text-xl" />
|
|
</div>
|
|
|
|
<!-- Grid -->
|
|
<div class="flex-1 overflow-auto">
|
|
<div class="grid grid-cols-4 md:grid-cols-6 lg:grid-cols-8 xl:grid-cols-10 gap-6">
|
|
<!-- Back Button -->
|
|
<NuxtLink
|
|
v-if="slugPath.length > 0"
|
|
:to="backUrl"
|
|
class="flex flex-col items-center justify-center p-5 rounded-2xl bg-white/10 hover:bg-white/20 backdrop-blur-md border border-white/10 transition-all cursor-pointer group select-none shadow-lg hover:shadow-xl"
|
|
>
|
|
<UIcon
|
|
name="i-lucide-arrow-left"
|
|
class="w-20 h-20 mb-3 drop-shadow-lg transition-transform group-hover:-translate-x-1 text-white/80"
|
|
/>
|
|
<span class="text-sm font-medium text-center text-white break-words line-clamp-2 w-full text-shadow">
|
|
Back
|
|
</span>
|
|
</NuxtLink>
|
|
|
|
<!-- Grid Items -->
|
|
<template v-for="item in items" :key="item.id">
|
|
<ModuleItem v-if="item.type === 'module'" :item="item" />
|
|
<DesktopItem v-else :item="item" />
|
|
</template>
|
|
</div>
|
|
|
|
<div v-if="items.length === 0 && slugPath.length === 0" class="text-white/50 flex items-center justify-center h-64 text-lg">
|
|
This folder is empty.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|