244 lines
6.5 KiB
TypeScript

import { defineStore } from 'pinia'
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 // Achtung: Schreibfehler wird so übernommen
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[]
}
interface Customer {
id: number
company: string
city: string
logo?: CompanyLogo | null
invertLogo?: CompanyLogo | null
projects: CustomerProject[]
}
export const useMainStore = defineStore('main', {
state: () => ({
menuOpen: false,
contactBoxOpen: false,
scrollPosition: 0,
screenWidth: 1440,
companyinfo: null as CompanyInfo | null,
pages: [] as Page[],
customers: [] as Customer[],
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 ?? [];
}
},
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
},
async fetchInitialData() {
if (this.dataFetched) return
this.loading = true
const { public: cfg } = useRuntimeConfig()
try {
const [companyRes, pagesRes, customersRes] = 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}` },
}),
])
// CompanyInfo (Single Type)
this.companyinfo = companyRes.data?.attributes ?? companyRes
// Pages
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, // Fehler absichtlich
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,
})) ?? [],
}
})
// Customers
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: (a.projects?.data ?? []).map((p: any) => ({
id: p.id,
projectTitle: p.attributes.projectTitle,
projectImages: p.attributes.projectImages?.data?.map((img: any) => ({
url: img.attributes.url,
alternativeText: img.attributes.alternativeText,
})) ?? [],
launchDate: p.attributes.launchDate,
projectDescription: p.attributes.projectDescription,
link: p.attributes.link,
webpage: p.attributes.webpage,
technologies: p.attributes.Technologien?.data?.map((t: any) => ({
titel: t.attributes.titel,
icon: t.attributes.icon,
})) ?? [],
})),
}
})
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
}
},
},
})