244 lines
6.5 KiB
TypeScript
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
|
|
}
|
|
},
|
|
},
|
|
})
|