365 lines
10 KiB
TypeScript

import { defineStore } from 'pinia'
import { useRuntimeConfig } from '#app'
interface CompanyLogo {
url: string
alternativeText?: string
}
interface CompanyInfo {
company: string
street: string
postalcode: string
city: string
phone: string
email: string
contact: string
district?: string
latitude?: number
longitude?: number
web: string
invertlogo?: {
data?: {
attributes?: CompanyLogo
}
}
}
interface SEO {
pageTitle: string
seoDescription: string
seoKeywords: string
type: string
seoImage?: CompanyLogo | null
}
interface PageSection {
id: number
sectionText: string
sectionImage?: CompanyLogo | null
}
interface FAQ {
question: string
answer: string
}
interface Page {
id: number
pageName: string
pageLink: string
header_image?: CompanyLogo | null
SEO?: SEO | null
faqs: FAQ[]
pageSections: PageSection[]
}
interface CustomerProject {
id: number
projectTitle: string
launchDate?: string
projectDescription?: string
link?: string
webpage?: string
technologies: { titel: string; icon?: string }[]
projectImages: CompanyLogo[]
customer?: {
id: number
company: string
city: string
} | null
}
interface Customer {
id: number
company: string
city: string
logo?: CompanyLogo | null
invertLogo?: CompanyLogo | null
projects: CustomerProject[]
}
interface NewsArticle {
id: number
header: string
teaser: string
content: any
slug: string
image?: CompanyLogo | null
createdAt: string
SEO?: SEO | null
author?: {
id: number
name: string
// optional: weitere Felder aus dem Team-Modell
} | null
}
interface ContactData {
name: string;
email?: string;
phone?: string;
company?: string;
message: string;
language: string;
}
export const useMainStore = defineStore('main', {
state: () => ({
menuOpen: false,
contactBoxOpen: false,
scrollPosition: 0,
screenWidth: 1440,
heroBoxHeight: 0,
darkHeroBack: false,
companyinfo: null as CompanyInfo | null,
pages: [] as Page[],
customers: [] as Customer[],
projects: [] as CustomerProject[],
articles: [] as NewsArticle[],
dataFetched: false,
loading: false,
error: null as { message: string; stack?: string } | null,
}),
getters: {
invertLogoUrl: (state) => {
const runtimeConfig = useRuntimeConfig()
const logoUrl = state.companyinfo?.invertlogo?.data?.attributes?.url
return logoUrl
? `${runtimeConfig.public.cmsBaseUrl}${logoUrl}`
: '/uploads/dummy_Image_4abc3f04dd.webp'
},
isMobile: (state) => state.screenWidth < 768,
getPageByLink: (state) => (link: string) =>
state.pages.find((p) => p.pageLink === link),
getCustomerById: (state) => (id: number) =>
state.customers.find((c) => c.id === id),
getFaqsByPageId: (state) => (pageId: number) =>
state.pages.find((p) => p.id === pageId)?.faqs ?? [],
getFaqsByPageLink: (state) => (link: string) => {
const page = state.pages.find(p => p.pageLink === link);
return page?.faqs ?? [];
},
getProjectByLink: (state) => (link: string) =>
state.projects.find(project => project.link === link),
getArticleBySlug: (state) => (slug: string) =>
state.articles.find((a) => a.slug === slug),
},
actions: {
toggleMenu() {
this.menuOpen = !this.menuOpen
},
closeMenu() {
this.menuOpen = false
},
toggleContactBubble() {
this.contactBoxOpen = !this.contactBoxOpen
},
setScrollPosition(pos: number) {
this.scrollPosition = pos
},
setScreenWidth(width: number) {
this.screenWidth = width
},
setHeroBoxHeight(height: number) {
this.heroBoxHeight = height
},
setDarkHeroBack(value: boolean) {
this.darkHeroBack = value
},
// SEND CONTACT REQUEST TO STRAPI
sendContactRequestToCMS: async (contactData: ContactData): Promise<void> => {
const router = useRouter()
const config = useRuntimeConfig()
try {
await $fetch(`${config.public.cmsBaseUrl}/api/contacts`, {
method: 'POST',
headers: {
Authorization: `Bearer ${config.public.cmsToken}`,
'Content-Type': 'application/json',
},
body: {
data: {
name: contactData.name,
email: contactData.email,
phone: contactData.phone,
company: contactData.company,
text: contactData.message,
page: router.currentRoute.value.fullPath,
language: contactData.language,
},
},
})
} catch (error) {
console.error('Fehler beim Senden der Kontaktanfrage:', error)
throw error
}
},
// FETCH ALL THE DATA FROM STRAPI
async fetchInitialData() {
if (this.dataFetched) return
this.loading = true
const { public: cfg } = useRuntimeConfig()
try {
const [companyRes, pagesRes, customersRes, projectsRes, articlesRes] = await Promise.all([
$fetch(`${cfg.cmsBaseUrl}/api/companyinfo?populate=*`, {
headers: { Authorization: `Bearer ${cfg.cmsToken}` },
}),
$fetch(`${cfg.cmsBaseUrl}/api/pages?populate=*`, {
headers: { Authorization: `Bearer ${cfg.cmsToken}` },
}),
$fetch(`${cfg.cmsBaseUrl}/api/customers?populate=*`, {
headers: { Authorization: `Bearer ${cfg.cmsToken}` },
}),
$fetch(`${cfg.cmsBaseUrl}/api/references?populate=projectImages,Technologien,customer&sort=launchDate:desc`, {
headers: { Authorization: `Bearer ${cfg.cmsToken}` },
}),
$fetch(`${cfg.cmsBaseUrl}/api/newsarticels?populate=image,SEO,author&locale=all&sort=createdAt:desc`, {
headers: { Authorization: `Bearer ${cfg.cmsToken}` },
}),
])
this.companyinfo = companyRes.data?.attributes ?? companyRes
this.pages = pagesRes.data.map((item: any) => {
const a = item.attributes
return {
id: item.id,
pageName: a.pageName,
pageLink: a.pageLink,
header_image: a.header_image?.data
? {
url: a.header_image.data.attributes.url,
alternativeText: a.header_image.data.attributes.alternativeText,
}
: null,
SEO: a.SEO
? {
pageTitle: a.SEO.pageTitle,
seoDescription: a.SEO.seoDesicription, // absichtlicher Fehler
seoKeywords: a.SEO.seoKeywords,
type: a.SEO.type,
seoImage: a.SEO.seoImage?.data
? {
url: a.SEO.seoImage.data.attributes.url,
alternativeText: a.SEO.seoImage.data.attributes.alternativeText,
}
: null,
}
: null,
faqs: a.faqs?.data?.map((f: any) => ({
question: f.attributes.question,
answer: f.attributes.answer,
})) ?? [],
pageSections: a.pageSections?.map((s: any) => ({
id: s.id,
sectionText: s.sectionText,
sectionImage: s.sectionImage?.data
? {
url: s.sectionImage.data.attributes.url,
alternativeText: s.sectionImage.data.attributes.alternativeText,
}
: null,
})) ?? [],
}
})
this.customers = customersRes.data.map((item: any) => {
const a = item.attributes
return {
id: item.id,
company: a.company,
city: a.city,
logo: a.logo?.data?.attributes ?? null,
invertLogo: a.invertLogo?.data?.attributes ?? null,
projects: [], // Wird durch references geladen
}
})
this.projects = projectsRes.data.map((item: any) => {
const a = item.attributes
return {
id: item.id,
projectTitle: a.projectTitle,
launchDate: a.launchDate,
projectDescription: a.projectDescription,
link: a.link,
webpage: a.webpage,
technologies: a.Technologien?.data?.map((t: any) => ({
titel: t.attributes.titel,
icon: t.attributes.icon,
})) ?? [],
projectImages: a.projectImages?.data?.map((img: any) => ({
url: img.attributes.url,
alternativeText: img.attributes.alternativeText,
})) ?? [],
customer: a.customer?.data
? {
id: a.customer.data.id,
company: a.customer.data.attributes.company,
city: a.customer.data.attributes.city,
}
: null,
}
})
this.articles = articlesRes.data.map((item: any) => {
const a = item.attributes
return {
id: item.id,
header: a.header,
teaser: a.teaser,
content: a.content,
slug: a.slug,
createdAt: a.createdAt,
image: a.image?.data
? {
url: a.image.data.attributes.url,
alternativeText: a.image.data.attributes.alternativeText,
}
: null,
SEO: a.SEO
? {
pageTitle: a.SEO.pageTitle,
seoDescription: a.SEO.seoDesicription,
seoKeywords: a.SEO.seoKeywords,
type: a.SEO.type,
seoImage: a.SEO.seoImage?.data
? {
url: a.SEO.seoImage.data.attributes.url,
alternativeText: a.SEO.seoImage.data.attributes.alternativeText,
}
: null,
}
: null,
author: a.author?.data
? {
id: a.author.data.id,
name: a.author.data.attributes.name,
}
: null,
}
})
this.dataFetched = true
} catch (err) {
const e = err as Error
this.error = { message: e.message, stack: e.stack }
console.error('Fetch-Fehler:', e)
} finally {
this.loading = false
}
},
},
})