Compare commits

...

10 commits
v1.2.2 ... main

12 changed files with 9546 additions and 6173 deletions

View file

@ -1,4 +1,4 @@
FROM node:18-alpine AS build
FROM node:22-alpine AS build
WORKDIR /app
@ -10,7 +10,7 @@ COPY . /app
RUN npm run build
FROM node:18-alpine AS prod
FROM node:22-alpine AS prod
WORKDIR /app

View file

@ -1,6 +1,10 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@import "tailwindcss";
@theme {
--color-primary: #b22222;
--color-darkgray: #2b292a;
--color-lightgray: #e3dfdf;
}
* {
font-family: "ConthraxSemiBold";

View file

@ -54,7 +54,7 @@
v-for="sublink in navbar_sub_items"
:key="sublink.id"
:to="`/${params?.[0]}/${sublink.URL}`"
:class="sublink.URL == params?.[1] && !params[2] ? 'active' : ''"
:class="sublink.URL == params?.[1] ? 'active' : ''"
class="w-fit"
>
{{ sublink.name }}

View file

@ -13,7 +13,7 @@
/>
<h1
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"
>
{{ itemIndex }}.

View file

@ -4,7 +4,7 @@
:class="allowNavigation ? '' : 'pointer-events-none'"
: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 }}.
</h1>

View file

@ -0,0 +1,71 @@
import type Article from "../types/collection/article";
import type Page from "../types/collection/page";
import type { ComponentTypes } from "../types/component/baseComponent";
import type SharedList from "../types/component/shared/list";
import type Global from "../types/single/global";
export default async function () {
const { find } = useStrapi();
const nuxtApp = useNuxtApp();
const { navbar, footer } = await nuxtApp.runWithContext(() => provideGlobal());
const { data: page_res } = await nuxtApp.runWithContext(() =>
useAsyncData("sitemap_pages", () =>
find<Page>("pages", {
filters: {
ref_only_access: false,
},
})
)
);
const pages = page_res.value?.data ?? [];
const accessableURLs: Array<{ path: string; origin: string; document?: string; hasCollection?: boolean }> = [];
for (const element of navbar?.navbar_items ?? []) {
if (!element.default_active_child) {
accessableURLs.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}`;
accessableURLs.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) {
let url = element.slug.replaceAll("~", "/");
if (!accessableURLs.find((a) => a.path == url)) {
accessableURLs.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?.links ?? []) {
let url = element.URL.startsWith("/") ? element.URL : `/${element.URL}`;
if (!accessableURLs.find((a) => a.path == url) && !element.URL.startsWith("http")) {
accessableURLs.push({
path: url,
origin: "footer",
document: undefined,
hasCollection: undefined,
});
}
}
return accessableURLs;
}

View file

@ -1,3 +1,5 @@
import tailwindcss from "@tailwindcss/vite";
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
app: {
@ -18,17 +20,14 @@ export default defineNuxtConfig({
css: ["~/assets/app.css", "~/assets/ConthraxSemiBold.css"],
postcss: {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
},
compatibilityDate: "2024-04-03",
devtools: { enabled: false },
modules: ["@nuxtjs/strapi", "@nuxt/image"],
vite: {
plugins: [tailwindcss()],
},
strapi: {
url: process.env.PUBLIC_STRAPI_URL,
prefix: "/api",

15465
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,8 @@
{
"name": "nuxt-app",
"name": "ff-webpage-landing",
"version": "1.3.1",
"private": true,
"description": "Feuerwehr/Verein Webseite",
"type": "module",
"scripts": {
"build": "nuxt build",
@ -12,14 +14,12 @@
"dependencies": {
"@nuxt/image": "^1.8.1",
"@nuxtjs/strapi": "^2.0.0",
"nuxt": "^3.13.2",
"@tailwindcss/vite": "^4.1.4",
"nuxt": "^3.16.2",
"vue": "latest",
"vue-router": "latest"
},
"devDependencies": {
"autoprefixer": "^10.4.20",
"postcss": "^8.4.47",
"tailwindcss": "^3.4.14"
},
"version": "1.2.2"
"tailwindcss": "^4.1.4"
}
}

View file

@ -19,25 +19,38 @@ const {
} = useRoute();
const { findOne, find } = useStrapi();
const { navbar } = await provideGlobal();
const navbar_items = computed(() => {
return navbar?.navbar_items ?? [];
const sitemap = await calculateSitemap();
const detail = ref<Article | Operation | Event | Vehicle | undefined>(undefined);
const activePath = computed(() => {
return "/" + (Array.isArray(params) ? params.join("/") : params);
});
const navbar_sub_items = computed(() => {
return navbar_items.value.find((ni) => ni.URL == params[0])?.navbar_sub_items ?? [];
const activePageBySitemap = computed(() => {
return sitemap.find((s) => s.path == activePath.value);
});
const active_item = computed(() => {
return navbar_items.value.find((ni) => ni.URL == params[0])?.page;
});
const active_sub_item = computed(() => {
return navbar_sub_items.value.find((si) => si.URL == params[1])?.page;
});
const active_page_id = computed(() => {
return active_sub_item.value?.documentId ?? active_item.value?.documentId ?? "";
const similarestPage = computed(() => {
return sitemap.reduce(
(bestMatch, current) => {
const currentMatchLength = current.path
.split("/")
.filter((segment, index) => segment != "" && segment == activePath.value.split("/")[index]).length;
const bestMatchLength = bestMatch.path
.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", () =>
findOne<Page | Array<Page>>("pages", active_page_id.value, {
findOne<Page | Array<Page>>("pages", similarestPage.value?.document, {
populate: {
populate: "*",
content: {
@ -48,7 +61,9 @@ const { data: pages } = await useAsyncData("pages", () =>
},
},
filters: {
...(active_page_id.value == "" ? { slug: params[0], ref_only_access: true } : {}),
...(!similarestPage.value?.document
? { slug: Array.isArray(params) ? params.join("~") : params, ref_only_access: false }
: {}),
},
})
);
@ -56,12 +71,25 @@ const page = computed(() => {
return Array.isArray(pages.value?.data) ? pages.value.data[0] : pages.value?.data;
});
let detail = ref<Article | Operation | Event | Vehicle | undefined>(undefined);
const searchDetail = computed(() => {
if (!active_sub_item.value) return params[1];
return params[2];
const isCollectionDetail = computed(() => {
return activePath.value != similarestPage.value.path && similarestPage.value.hasCollection;
});
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 = [
...new Set(
page.value?.content
@ -76,7 +104,7 @@ if (searchDetail.value) {
find<Article | Operation | Event | Vehicle>(element ?? "", {
populate: "*",
filters: {
slug: params[2] ?? params[1],
slug: activePath.value.substring(activePath.value.lastIndexOf("/") + 1),
},
})
);
@ -86,14 +114,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>

17
pages/sitemap.vue Normal file
View file

@ -0,0 +1,17 @@
<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">
import calculateSitemap from "~/composables/calculateSitemap";
const sitemap = await calculateSitemap();
</script>

View file

@ -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: [],
};