Fixes: 1) Correct file path imports by removing `.js` extensions in GraphQL fragments; 2) Resolve typo in `usePromocodeStore` composables to ensure consistent store usage; 3) Add missing `:type="submit"` to login form button for proper form submission handling; Extra: 1) Remove unused `.idea` and `README.md` files for repository cleanup; 2) Delete extraneous dependencies from `package-lock.json` for streamlined package management; 3) Refactor category slug handling with improved composable logic for cleaner route parameters and SEO alignment.
93 lines
No EOL
2.7 KiB
Vue
93 lines
No EOL
2.7 KiB
Vue
<template>
|
|
<div class="category">
|
|
<ui-title>{{ category?.name }}</ui-title>
|
|
<div class="container">
|
|
<div class="category__wrapper">
|
|
<div class="category__list" v-if="category?.children?.length">
|
|
<cards-category
|
|
v-for="cat in category?.children || []"
|
|
:key="cat.uuid"
|
|
:category="cat"
|
|
/>
|
|
</div>
|
|
<store v-else />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import type {ICategory} from "~/types";
|
|
import {usePageTitle} from "~/composables/utils";
|
|
import {useRouteParams} from "@vueuse/router";
|
|
import {useDefaultSeo} from "~/composables/seo";
|
|
import {useCategoryBySlugSeo} from "~/composables/categories/useCategoryBySlugSeo";
|
|
import {useAppConfig} from "~/composables/config";
|
|
|
|
const { locale } = useI18n();
|
|
const categoryStore = useCategoryStore();
|
|
|
|
const { APP_NAME } = useAppConfig();
|
|
const { setPageTitle } = usePageTitle();
|
|
|
|
const slug = useRouteParams<string>('slug');
|
|
const roots = computed(() => categoryStore.categories.map(e => e.node));
|
|
|
|
const category = computed(() => findBySlug(roots.value, slug.value));
|
|
|
|
const seoMeta = useCategoryBySlugSeo(category.value.slug)
|
|
|
|
const meta = useDefaultSeo(seoMeta || null);
|
|
|
|
if (meta) {
|
|
useSeoMeta({
|
|
title: meta.title || APP_NAME,
|
|
description: meta.description || meta.title || APP_NAME,
|
|
ogTitle: meta.og.title || undefined,
|
|
ogDescription: meta.og.description || meta.title || APP_NAME,
|
|
ogType: meta.og.type || undefined,
|
|
ogUrl: meta.og.url || undefined,
|
|
ogImage: meta.og.image || undefined,
|
|
twitterCard: meta.twitter.card || undefined,
|
|
twitterTitle: meta.twitter.title || undefined,
|
|
twitterDescription: meta.twitter.description || undefined,
|
|
robots: meta.robots,
|
|
});
|
|
|
|
useHead({
|
|
link: [
|
|
meta.canonical ? { rel: 'canonical', href: meta.canonical } : {},
|
|
].filter(Boolean) as any,
|
|
meta: [{ property: 'og:locale', content: locale.value }],
|
|
script: meta.jsonLd.map((obj: any) => ({
|
|
type: 'application/ld+json',
|
|
innerHTML: JSON.stringify(obj),
|
|
})),
|
|
__dangerouslyDisableSanitizersByTagID: Object.fromEntries(
|
|
meta.jsonLd.map((_, i: number) => [`ldjson-${i}`, ['innerHTML']])
|
|
),
|
|
});
|
|
}
|
|
|
|
setPageTitle(category.value?.name ?? 'Category');
|
|
|
|
function findBySlug(nodes: ICategory[], slug: string): ICategory | undefined {
|
|
for (const n of nodes) {
|
|
if (n.slug === slug) return n;
|
|
if (n.children?.length) {
|
|
const found = findBySlug(n.children, slug);
|
|
if (found) return found;
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
.category {
|
|
&__list {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
|
|
grid-gap: 20px;
|
|
}
|
|
}
|
|
</style> |