Files
dashlio/app/pages/[...slug].vue
2026-04-19 18:15:39 +01:00

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>