365 lines
10 KiB
TypeScript
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
|
|
}
|
|
},
|
|
},
|
|
})
|