Compare commits
15 commits
Author | SHA1 | Date | |
---|---|---|---|
e7ae74c728 | |||
ad6434093a | |||
7f1770d442 | |||
cd2af77dfb | |||
716b5535ae | |||
aa828d3f78 | |||
fa362dc0ee | |||
7c8be0ccb9 | |||
28337cd80f | |||
2a90f19178 | |||
20ff5d9f2c | |||
e718f3fe35 | |||
af10b7d238 | |||
5e2fd6f682 | |||
900203c845 |
22 changed files with 9636 additions and 6234 deletions
|
@ -1,4 +1,4 @@
|
||||||
FROM node:18-alpine AS build
|
FROM node:22-alpine AS build
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ COPY . /app
|
||||||
|
|
||||||
RUN npm run build
|
RUN npm run build
|
||||||
|
|
||||||
FROM node:18-alpine AS prod
|
FROM node:22-alpine AS prod
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
|
14
app.vue
14
app.vue
|
@ -3,19 +3,13 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import calculateTitle from "./composables/calculateTitle";
|
const { seo, title } = useGlobal();
|
||||||
import provideGlobal from "./composables/provideGlobal";
|
|
||||||
|
|
||||||
const { SEO } = await provideGlobal();
|
|
||||||
const title = await calculateTitle();
|
|
||||||
|
|
||||||
const { metaDescription, keywords } = SEO ?? {};
|
|
||||||
|
|
||||||
useHead({
|
useHead({
|
||||||
title: title,
|
title: title.value,
|
||||||
meta: [
|
meta: [
|
||||||
{ name: "description", content: metaDescription },
|
{ name: "description", content: seo.value?.metaDescription },
|
||||||
{ name: "keywords", content: keywords },
|
{ name: "keywords", content: seo.value?.keywords ?? "" },
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
@tailwind base;
|
@import "tailwindcss";
|
||||||
@tailwind components;
|
|
||||||
@tailwind utilities;
|
@theme {
|
||||||
|
--color-primary: #b22222;
|
||||||
|
--color-darkgray: #2b292a;
|
||||||
|
--color-lightgray: #e3dfdf;
|
||||||
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
font-family: "ConthraxSemiBold";
|
font-family: "ConthraxSemiBold";
|
||||||
|
|
|
@ -29,7 +29,6 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
const title = await calculateTitle();
|
const { footer, title } = useGlobal();
|
||||||
const { footer } = await provideGlobal();
|
const { links, maintained_by, copyright } = footer.value ?? {};
|
||||||
const { links, maintained_by, copyright } = footer ?? {};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -54,7 +54,7 @@
|
||||||
v-for="sublink in navbar_sub_items"
|
v-for="sublink in navbar_sub_items"
|
||||||
:key="sublink.id"
|
:key="sublink.id"
|
||||||
:to="`/${params?.[0]}/${sublink.URL}`"
|
:to="`/${params?.[0]}/${sublink.URL}`"
|
||||||
:class="sublink.URL == params?.[1] && !params[2] ? 'active' : ''"
|
:class="sublink.URL == params?.[1] ? 'active' : ''"
|
||||||
class="w-fit"
|
class="w-fit"
|
||||||
>
|
>
|
||||||
{{ sublink.name }}
|
{{ sublink.name }}
|
||||||
|
@ -64,8 +64,6 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import provideGlobal from "../composables/provideGlobal";
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
params: { slug: params },
|
params: { slug: params },
|
||||||
} = useRoute();
|
} = useRoute();
|
||||||
|
@ -73,12 +71,12 @@ const {
|
||||||
const runtimeConfig = useRuntimeConfig();
|
const runtimeConfig = useRuntimeConfig();
|
||||||
const baseUrl = runtimeConfig.public.strapi.url;
|
const baseUrl = runtimeConfig.public.strapi.url;
|
||||||
|
|
||||||
const { logo, navbar } = await provideGlobal();
|
const { logo, navbar } = useGlobal();
|
||||||
|
|
||||||
const open = ref(false);
|
const open = ref(false);
|
||||||
|
|
||||||
const navbar_sub_items = computed(() => {
|
const navbar_sub_items = computed(() => {
|
||||||
if (!navbar) return [];
|
if (!navbar.value) return [];
|
||||||
return navbar.navbar_items.find((ni) => ni.URL == params?.[0])?.navbar_sub_items;
|
return navbar.value.navbar_items.find((ni) => ni.URL == params?.[0])?.navbar_sub_items;
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -4,27 +4,27 @@
|
||||||
:class="allowNavigation ? '' : 'pointer-events-none'"
|
:class="allowNavigation ? '' : 'pointer-events-none'"
|
||||||
:to="`${urlOverwrite ?? $route.path}/${data?.slug}`"
|
:to="`${urlOverwrite ?? $route.path}/${data?.slug}`"
|
||||||
>
|
>
|
||||||
<div class="w-full h-56 relative">
|
<div class="w-full h-56 min-h-56 relative">
|
||||||
<NuxtPicture
|
<NuxtPicture
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
class="w-full h-full object-cover object-center"
|
class="w-full h-full min-h-full object-cover object-center"
|
||||||
:src="data?.image?.url || logo?.url ? baseUrl + (data?.image?.url ?? logo?.url) : '/favicon.png'"
|
:src="data?.image?.url || logo?.url ? baseUrl + (data?.image?.url ?? logo?.url) : '/favicon.png'"
|
||||||
:imgAttrs="{ class: 'w-full h-full object-cover object-center' }"
|
:imgAttrs="{ class: 'w-full h-full object-cover object-center' }"
|
||||||
/>
|
/>
|
||||||
<h1
|
<h1
|
||||||
v-if="itemIndex"
|
v-if="itemIndex"
|
||||||
class="text-center text-black text-4xl my-auto absolute bottom-2 left-2"
|
class="text-center text-black text-4xl! my-auto absolute bottom-2 left-2"
|
||||||
style="text-shadow: 2px 2px 4px white"
|
style="text-shadow: 2px 2px 4px white"
|
||||||
>
|
>
|
||||||
{{ itemIndex }}.
|
{{ itemIndex }}.
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-full h-44 relative bg-white px-2 py-5 flex flex-col justify-start items-start gap-2 overflow-y-auto">
|
<div class="w-full grow relative bg-white p-2 pb-4 flex flex-col justify-start items-start gap-2 overflow-y-auto">
|
||||||
<h1>
|
<h1>
|
||||||
{{ data?.title }}
|
{{ data?.title }}
|
||||||
</h1>
|
</h1>
|
||||||
<p v-if="itemDate && lookup?.show_date" class="w-full text-[#5c5c5c]">
|
<p class="w-full text-[#5c5c5c] line-clamp-2 overflow-hidden">
|
||||||
{{ itemDate }}
|
{{ itemDate }}
|
||||||
</p>
|
</p>
|
||||||
<p class="w-full text-[#5c5c5c] line-clamp-2 overflow-hidden">
|
<p class="w-full text-[#5c5c5c] line-clamp-2 overflow-hidden">
|
||||||
|
@ -42,7 +42,7 @@ import type Lookup from "../../types/collection/lookup";
|
||||||
const runtimeConfig = useRuntimeConfig();
|
const runtimeConfig = useRuntimeConfig();
|
||||||
const baseUrl = runtimeConfig.public.strapi.url;
|
const baseUrl = runtimeConfig.public.strapi.url;
|
||||||
|
|
||||||
const { logo } = await provideGlobal();
|
const { logo } = useGlobal();
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
data: Object as PropType<BaseCollection>,
|
data: Object as PropType<BaseCollection>,
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
:class="allowNavigation ? '' : 'pointer-events-none'"
|
:class="allowNavigation ? '' : 'pointer-events-none'"
|
||||||
:to="`${urlOverwrite ?? $route.path}/${data?.slug}`"
|
:to="`${urlOverwrite ?? $route.path}/${data?.slug}`"
|
||||||
>
|
>
|
||||||
<h1 v-if="itemIndex" class="min-w-20 w-20 sm:min-w-24 sm:w-24 text-center text-black text-4xl my-auto">
|
<h1 v-if="itemIndex" class="min-w-20 w-20 sm:min-w-24 sm:w-24 text-center text-black text-4xl! my-auto">
|
||||||
{{ itemIndex }}.
|
{{ itemIndex }}.
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ import type SharedEmphasiseArticle from "../../types/component/shared/emphasiseA
|
||||||
import type Lookup from "../../types/collection/lookup";
|
import type Lookup from "../../types/collection/lookup";
|
||||||
|
|
||||||
const { find } = useStrapi();
|
const { find } = useStrapi();
|
||||||
const { data: lookup } = await useAsyncData("lookup", () =>
|
const { data: lookup } = await useAsyncData(() =>
|
||||||
find<Lookup>("collection-lookups", {
|
find<Lookup>("collection-lookups", {
|
||||||
filters: {
|
filters: {
|
||||||
collection: "articles",
|
collection: "articles",
|
||||||
|
|
|
@ -113,13 +113,13 @@ const pagination = ref<Meta>({ page: 0, pageSize: 0, pageCount: 0, total: 0 });
|
||||||
const activeYear = ref<number>(0);
|
const activeYear = ref<number>(0);
|
||||||
|
|
||||||
if (props.data?.lookup.list_with_date != "none") {
|
if (props.data?.lookup.list_with_date != "none") {
|
||||||
const { data: year } = await useAsyncData<Array<number>>("distinct-years", () =>
|
const { data: year } = await useAsyncData<Array<number>>(() =>
|
||||||
$fetch(`${baseUrl}/api/custom/${props.data?.lookup.collection}/distinct-years`)
|
$fetch(`${baseUrl}/api/custom/${props.data?.lookup.collection}/distinct-years`)
|
||||||
);
|
);
|
||||||
years.value = year.value ?? [];
|
years.value = year.value ?? [];
|
||||||
activeYear.value = years.value[0] ?? 0;
|
activeYear.value = years.value[0] ?? 0;
|
||||||
}
|
}
|
||||||
const { data: collections } = await useAsyncData("collection", () =>
|
const { data: collections } = await useAsyncData(() =>
|
||||||
find<BaseCollection>(props.data?.lookup.collection ?? "", {
|
find<BaseCollection>(props.data?.lookup.collection ?? "", {
|
||||||
...(props.data?.lookup?.list_with_date != "none"
|
...(props.data?.lookup?.list_with_date != "none"
|
||||||
? {
|
? {
|
||||||
|
@ -235,7 +235,7 @@ async function changeTimedData(year: number) {
|
||||||
withCount: true,
|
withCount: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
console.log(data);
|
|
||||||
collection.value = data?.data;
|
collection.value = data?.data;
|
||||||
pagination.value = (data?.meta.pagination as unknown as {
|
pagination.value = (data?.meta.pagination as unknown as {
|
||||||
page: number;
|
page: number;
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
import provideGlobal from "./provideGlobal";
|
|
||||||
|
|
||||||
export default async function () {
|
|
||||||
const runtimeConfig = useRuntimeConfig();
|
|
||||||
const appTitle = runtimeConfig.public.app.title;
|
|
||||||
|
|
||||||
const { SEO } = await provideGlobal();
|
|
||||||
const { metaTitle } = SEO ?? {};
|
|
||||||
|
|
||||||
return metaTitle ?? appTitle;
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
import type Global from "../types/single/global";
|
|
||||||
|
|
||||||
export default async function () {
|
|
||||||
const { findOne } = useStrapi();
|
|
||||||
const { data: global } = await useAsyncData("global", () => findOne<Global>("global"));
|
|
||||||
const { logo, navbar, footer, SEO } = global.value?.data ?? {};
|
|
||||||
|
|
||||||
return { logo, navbar, footer, SEO };
|
|
||||||
}
|
|
26
composables/useGlobal.ts
Normal file
26
composables/useGlobal.ts
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
import type BaseFile from "../types/component/baseFile";
|
||||||
|
import type Footer from "../types/component/global/footer";
|
||||||
|
import type Navbar from "../types/component/global/navbar";
|
||||||
|
import type SEO from "../types/component/global/seo";
|
||||||
|
import type Global from "../types/single/global";
|
||||||
|
|
||||||
|
export const useGlobal = () => {
|
||||||
|
const global = useState<Global | null>("global");
|
||||||
|
const runtimeConfig = useRuntimeConfig();
|
||||||
|
const appTitle = runtimeConfig.public.app.title;
|
||||||
|
|
||||||
|
const logo = computed<BaseFile | null>(() => global.value?.logo ?? null);
|
||||||
|
const navbar = computed<Navbar | null>(() => global.value?.navbar ?? null);
|
||||||
|
const footer = computed<Footer | null>(() => global.value?.footer ?? null);
|
||||||
|
const seo = computed<SEO | null>(() => global.value?.SEO ?? null);
|
||||||
|
const title = computed<string>(() => seo.value?.metaTitle ?? appTitle);
|
||||||
|
|
||||||
|
return {
|
||||||
|
logo,
|
||||||
|
global,
|
||||||
|
navbar,
|
||||||
|
footer,
|
||||||
|
seo,
|
||||||
|
title,
|
||||||
|
};
|
||||||
|
};
|
63
composables/useSitemap.ts
Normal file
63
composables/useSitemap.ts
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
import type Page from "../types/collection/page";
|
||||||
|
import type { ComponentTypes } from "../types/component/baseComponent";
|
||||||
|
|
||||||
|
export const useSitemap = () => {
|
||||||
|
const { navbar, footer } = useGlobal();
|
||||||
|
const pages = useState<Page[]>("sitemap_pages");
|
||||||
|
|
||||||
|
const sitemap = ref<sitemap>([]);
|
||||||
|
|
||||||
|
for (const element of navbar.value?.navbar_items ?? []) {
|
||||||
|
if (!element.default_active_child) {
|
||||||
|
sitemap.value.push({
|
||||||
|
path: element.URL.startsWith("/") ? element.URL : `/${element.URL}`,
|
||||||
|
origin: "navbar",
|
||||||
|
document: element?.page?.documentId,
|
||||||
|
hasCollection: element.page.content.filter((c: ComponentTypes) => c.__component == "shared.list").length != 0,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
for (const subelement of element.navbar_sub_items) {
|
||||||
|
let url = `${element.URL}/${subelement.URL}`;
|
||||||
|
sitemap.value.push({
|
||||||
|
path: url.startsWith("/") ? url : `/${url}`,
|
||||||
|
origin: "navbar",
|
||||||
|
document: subelement?.page?.documentId,
|
||||||
|
hasCollection:
|
||||||
|
subelement?.page?.content.filter((c: ComponentTypes) => c.__component == "shared.list").length != 0,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const element of pages.value) {
|
||||||
|
let url = element.slug.replaceAll("~", "/");
|
||||||
|
if (!sitemap.value.find((a) => a.path == url)) {
|
||||||
|
sitemap.value.push({
|
||||||
|
path: url.startsWith("/") ? url : `/${url}`,
|
||||||
|
origin: "page",
|
||||||
|
document: element.documentId,
|
||||||
|
hasCollection: element.content.filter((c: ComponentTypes) => c.__component == "shared.list").length != 0,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const element of footer.value?.links ?? []) {
|
||||||
|
let url = element.URL.startsWith("/") ? element.URL : `/${element.URL}`;
|
||||||
|
if (!sitemap.value.find((a) => a.path == url) && !element.URL.startsWith("http")) {
|
||||||
|
sitemap.value.push({
|
||||||
|
path: url,
|
||||||
|
origin: "footer",
|
||||||
|
document: undefined,
|
||||||
|
hasCollection: undefined,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sitemap;
|
||||||
|
};
|
||||||
|
|
||||||
|
type sitemap = Array<{
|
||||||
|
path: string;
|
||||||
|
origin: string;
|
||||||
|
document?: string;
|
||||||
|
hasCollection?: boolean;
|
||||||
|
}>;
|
|
@ -22,14 +22,13 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import provideGlobal from "../composables/provideGlobal";
|
|
||||||
import type Homepage from "../types/single/homepage";
|
import type Homepage from "../types/single/homepage";
|
||||||
|
|
||||||
const runtimeConfig = useRuntimeConfig();
|
const runtimeConfig = useRuntimeConfig();
|
||||||
const baseUrl = runtimeConfig.public.strapi.url;
|
const baseUrl = runtimeConfig.public.strapi.url;
|
||||||
const { findOne } = useStrapi();
|
const { findOne } = useStrapi();
|
||||||
|
|
||||||
const { logo } = await provideGlobal();
|
const { logo } = useGlobal();
|
||||||
|
|
||||||
const { data: homepage } = await useAsyncData("homepage", () => findOne<Homepage>("homepage"));
|
const { data: homepage } = await useAsyncData("homepage", () => findOne<Homepage>("homepage"));
|
||||||
const { backdrop } = homepage.value?.data ?? {};
|
const { backdrop } = homepage.value?.data ?? {};
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import tailwindcss from "@tailwindcss/vite";
|
||||||
|
|
||||||
// https://nuxt.com/docs/api/configuration/nuxt-config
|
// https://nuxt.com/docs/api/configuration/nuxt-config
|
||||||
export default defineNuxtConfig({
|
export default defineNuxtConfig({
|
||||||
app: {
|
app: {
|
||||||
|
@ -18,17 +20,14 @@ export default defineNuxtConfig({
|
||||||
|
|
||||||
css: ["~/assets/app.css", "~/assets/ConthraxSemiBold.css"],
|
css: ["~/assets/app.css", "~/assets/ConthraxSemiBold.css"],
|
||||||
|
|
||||||
postcss: {
|
|
||||||
plugins: {
|
|
||||||
tailwindcss: {},
|
|
||||||
autoprefixer: {},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
compatibilityDate: "2024-04-03",
|
compatibilityDate: "2024-04-03",
|
||||||
devtools: { enabled: false },
|
devtools: { enabled: false },
|
||||||
modules: ["@nuxtjs/strapi", "@nuxt/image"],
|
modules: ["@nuxtjs/strapi", "@nuxt/image"],
|
||||||
|
|
||||||
|
vite: {
|
||||||
|
plugins: [tailwindcss()],
|
||||||
|
},
|
||||||
|
|
||||||
strapi: {
|
strapi: {
|
||||||
url: process.env.PUBLIC_STRAPI_URL,
|
url: process.env.PUBLIC_STRAPI_URL,
|
||||||
prefix: "/api",
|
prefix: "/api",
|
||||||
|
|
15483
package-lock.json
generated
15483
package-lock.json
generated
File diff suppressed because it is too large
Load diff
14
package.json
14
package.json
|
@ -1,6 +1,8 @@
|
||||||
{
|
{
|
||||||
"name": "nuxt-app",
|
"name": "ff-webpage-landing",
|
||||||
|
"version": "1.3.2",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
"description": "Feuerwehr/Verein Webseite",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "nuxt build",
|
"build": "nuxt build",
|
||||||
|
@ -12,14 +14,12 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nuxt/image": "^1.8.1",
|
"@nuxt/image": "^1.8.1",
|
||||||
"@nuxtjs/strapi": "^2.0.0",
|
"@nuxtjs/strapi": "^2.0.0",
|
||||||
"nuxt": "^3.13.2",
|
"@tailwindcss/vite": "^4.1.4",
|
||||||
|
"nuxt": "^3.16.2",
|
||||||
"vue": "latest",
|
"vue": "latest",
|
||||||
"vue-router": "latest"
|
"vue-router": "latest"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"autoprefixer": "^10.4.20",
|
"tailwindcss": "^4.1.4"
|
||||||
"postcss": "^8.4.47",
|
}
|
||||||
"tailwindcss": "^3.4.14"
|
|
||||||
},
|
|
||||||
"version": "1.2.2"
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,56 +12,87 @@ import type Event from "../types/collection/event";
|
||||||
import type Operation from "../types/collection/operation";
|
import type Operation from "../types/collection/operation";
|
||||||
import type Vehicle from "../types/collection/vehicle";
|
import type Vehicle from "../types/collection/vehicle";
|
||||||
import type Page from "../types/collection/page";
|
import type Page from "../types/collection/page";
|
||||||
import provideGlobal from "../composables/provideGlobal";
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
params: { slug: params },
|
params: { slug: params },
|
||||||
} = useRoute();
|
} = useRoute();
|
||||||
const { findOne, find } = useStrapi();
|
const { findOne, find } = useStrapi();
|
||||||
|
|
||||||
const { navbar } = await provideGlobal();
|
const sitemap = useSitemap();
|
||||||
const navbar_items = computed(() => {
|
|
||||||
return navbar?.navbar_items ?? [];
|
const detail = ref<Article | Operation | Event | Vehicle | undefined>(undefined);
|
||||||
|
|
||||||
|
const activePath = computed(() => {
|
||||||
|
return "/" + (Array.isArray(params) ? params.join("/") : params);
|
||||||
});
|
});
|
||||||
const navbar_sub_items = computed(() => {
|
const activePageBySitemap = computed(() => {
|
||||||
return navbar_items.value.find((ni) => ni.URL == params[0])?.navbar_sub_items ?? [];
|
return sitemap.value.find((s) => s.path == activePath.value);
|
||||||
});
|
});
|
||||||
const active_item = computed(() => {
|
const similarestPage = computed(() => {
|
||||||
return navbar_items.value.find((ni) => ni.URL == params[0])?.page;
|
return sitemap.value.reduce(
|
||||||
});
|
(bestMatch, current) => {
|
||||||
const active_sub_item = computed(() => {
|
const currentMatchLength = current.path
|
||||||
return navbar_sub_items.value.find((si) => si.URL == params[1])?.page;
|
.split("/")
|
||||||
});
|
.filter((segment, index) => segment != "" && segment == activePath.value.split("/")[index]).length;
|
||||||
const active_page_id = computed(() => {
|
const bestMatchLength = bestMatch.path
|
||||||
return active_sub_item.value?.documentId ?? active_item.value?.documentId ?? "";
|
.split("/")
|
||||||
|
.filter((segment, index) => segment != "" && segment == activePath.value.split("/")[index]).length;
|
||||||
|
|
||||||
|
if (currentMatchLength > bestMatchLength) {
|
||||||
|
return current;
|
||||||
|
} else {
|
||||||
|
return bestMatch;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ path: "", origin: "", hasCollection: false }
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
const { data: pages } = await useAsyncData("pages", () =>
|
const { data: pages } = await useAsyncData(
|
||||||
findOne<Page | Array<Page>>("pages", active_page_id.value, {
|
() =>
|
||||||
populate: {
|
findOne<Page | Array<Page>>("pages", similarestPage.value?.document, {
|
||||||
populate: "*",
|
populate: {
|
||||||
content: {
|
|
||||||
populate: "*",
|
populate: "*",
|
||||||
|
content: {
|
||||||
|
populate: "*",
|
||||||
|
},
|
||||||
|
hero: {
|
||||||
|
populate: "*",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
hero: {
|
filters: {
|
||||||
populate: "*",
|
...(!similarestPage.value?.document
|
||||||
|
? { slug: Array.isArray(params) ? params.join("~") : params, ref_only_access: false }
|
||||||
|
: {}),
|
||||||
},
|
},
|
||||||
},
|
}),
|
||||||
filters: {
|
{
|
||||||
...(active_page_id.value == "" ? { slug: params[0], ref_only_access: true } : {}),
|
default: () => null,
|
||||||
},
|
}
|
||||||
})
|
|
||||||
);
|
);
|
||||||
const page = computed(() => {
|
const page = computed(() => {
|
||||||
return Array.isArray(pages.value?.data) ? pages.value.data[0] : pages.value?.data;
|
return Array.isArray(pages.value?.data) ? pages.value.data[0] : pages.value?.data;
|
||||||
});
|
});
|
||||||
|
|
||||||
let detail = ref<Article | Operation | Event | Vehicle | undefined>(undefined);
|
const isCollectionDetail = computed(() => {
|
||||||
const searchDetail = computed(() => {
|
return activePath.value != similarestPage.value.path && similarestPage.value.hasCollection;
|
||||||
if (!active_sub_item.value) return params[1];
|
|
||||||
return params[2];
|
|
||||||
});
|
});
|
||||||
if (searchDetail.value) {
|
|
||||||
|
const notFound = computed(() => {
|
||||||
|
if (isCollectionDetail.value && detail.value) return !detail.value;
|
||||||
|
else
|
||||||
|
return (
|
||||||
|
!page.value ||
|
||||||
|
(page.value && !(page.value.content.length != 0 || (page.value.hero.title && page.value.hero.banner)))
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
const showContentBuilder = computed(() => {
|
||||||
|
if (isCollectionDetail.value && detail.value) return !detail.value;
|
||||||
|
else return page.value && (page.value.content.length != 0 || (page.value.hero.title && page.value.hero.banner));
|
||||||
|
});
|
||||||
|
|
||||||
|
if (isCollectionDetail) {
|
||||||
let collectionOfDetail = [
|
let collectionOfDetail = [
|
||||||
...new Set(
|
...new Set(
|
||||||
page.value?.content
|
page.value?.content
|
||||||
|
@ -72,11 +103,11 @@ if (searchDetail.value) {
|
||||||
];
|
];
|
||||||
|
|
||||||
for (const element of collectionOfDetail) {
|
for (const element of collectionOfDetail) {
|
||||||
const { data: details } = await useAsyncData("detail", () =>
|
const { data: details } = await useAsyncData(() =>
|
||||||
find<Article | Operation | Event | Vehicle>(element ?? "", {
|
find<Article | Operation | Event | Vehicle>(element ?? "", {
|
||||||
populate: "*",
|
populate: "*",
|
||||||
filters: {
|
filters: {
|
||||||
slug: params[2] ?? params[1],
|
slug: activePath.value.substring(activePath.value.lastIndexOf("/") + 1),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@ -86,14 +117,4 @@ if (searchDetail.value) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const notFound = computed(() => {
|
|
||||||
if (searchDetail.value) return !detail.value;
|
|
||||||
else return active_page_id.value == "" && !page.value?.content && !page.value?.hero;
|
|
||||||
});
|
|
||||||
|
|
||||||
const showContentBuilder = computed(() => {
|
|
||||||
if (searchDetail.value) return !detail.value;
|
|
||||||
else return !!page.value?.content || !!page.value?.hero;
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
15
pages/sitemap.vue
Normal file
15
pages/sitemap.vue
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
<template>
|
||||||
|
<NuxtLayout name="default">
|
||||||
|
<div class="min-h-[calc(100vh-9rem)] w-full">
|
||||||
|
<div class="container mx-auto py-12 px-2 min-h-[50vh] flex flex-col gap-2">
|
||||||
|
<NuxtLink v-for="item in sitemap" :key="item.path" :to="`${item.path}`">
|
||||||
|
{{ item.path }} {{ item.hasCollection ? "(...)" : "" }}
|
||||||
|
</NuxtLink>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</NuxtLayout>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
const sitemap = useSitemap();
|
||||||
|
</script>
|
15
plugins/global.ts
Normal file
15
plugins/global.ts
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
import type Global from "../types/single/global";
|
||||||
|
|
||||||
|
export default defineNuxtPlugin(async (nuxtApp) => {
|
||||||
|
const globalState = useState<Global | null>("global", () => null);
|
||||||
|
|
||||||
|
if (!globalState.value) {
|
||||||
|
const { findOne } = useStrapi();
|
||||||
|
const { data: global } = await useAsyncData("global", () => findOne<Global>("global"), {
|
||||||
|
server: true,
|
||||||
|
lazy: false,
|
||||||
|
default: () => {},
|
||||||
|
});
|
||||||
|
globalState.value = global.value?.data ?? null;
|
||||||
|
}
|
||||||
|
});
|
25
plugins/sitemap.ts
Normal file
25
plugins/sitemap.ts
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import type Page from "../types/collection/page";
|
||||||
|
import type Global from "../types/single/global";
|
||||||
|
|
||||||
|
export default defineNuxtPlugin(async (nuxtApp) => {
|
||||||
|
const pageState = useState<Page[]>("sitemap_pages", () => []);
|
||||||
|
|
||||||
|
if (!pageState.value) {
|
||||||
|
const { find } = useStrapi();
|
||||||
|
const { data: page_res } = await useAsyncData(
|
||||||
|
"sitemap_pages",
|
||||||
|
() =>
|
||||||
|
find<Page>("pages", {
|
||||||
|
filters: {
|
||||||
|
ref_only_access: false,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
server: true,
|
||||||
|
lazy: false,
|
||||||
|
default: () => {},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
pageState.value = page_res.value?.data ?? [];
|
||||||
|
}
|
||||||
|
});
|
|
@ -1,21 +0,0 @@
|
||||||
/** @type {import('tailwindcss').Config} */
|
|
||||||
export default {
|
|
||||||
content: [
|
|
||||||
"./components/**/*.{js,vue,ts}",
|
|
||||||
"./layouts/**/*.vue",
|
|
||||||
"./pages/**/*.vue",
|
|
||||||
"./plugins/**/*.{js,ts}",
|
|
||||||
"./app.vue",
|
|
||||||
"./error.vue",
|
|
||||||
],
|
|
||||||
theme: {
|
|
||||||
extend: {
|
|
||||||
colors: {
|
|
||||||
primary: "#B22222",
|
|
||||||
darkgray: "#2B292A",
|
|
||||||
lightgray: "#E3DFDF",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
plugins: [],
|
|
||||||
};
|
|
Loading…
Add table
Reference in a new issue