-
+ {logo ? (
+
+ ) : companyName ? (
+ {companyName}
+ ) : null}
{footerTagline && (
diff --git a/src/components/Header.tsx b/src/components/Header.tsx
index 2f8d59c..285ed53 100644
--- a/src/components/Header.tsx
+++ b/src/components/Header.tsx
@@ -5,6 +5,8 @@ import { ArrowRight, Globe, ChevronDown } from 'lucide-react'
import { usePathname } from 'next/navigation'
import { Logo } from '@/components/Logo'
+import type { Media } from '@/payload-types'
+
export interface NavItem {
id?: string
label: string
@@ -21,6 +23,8 @@ interface HeaderProps {
contactHref?: string | null
contactLabel?: string | null
phoneLabel?: string | null
+ logo?: Media | { url?: string | null; alt?: string | null } | null
+ locales?: readonly { code: string; label: string }[] | { code: string; label: string }[]
}
export function Header({
@@ -33,6 +37,8 @@ export function Header({
contactHref,
contactLabel,
phoneLabel,
+ logo,
+ locales,
}: HeaderProps) {
const pathname = usePathname() || ''
const [langDropdownOpen, setLangDropdownOpen] = useState(false)
@@ -63,10 +69,10 @@ export function Header({
(item) => !contactLabel || item.label.trim().toLowerCase() !== contactLabel.trim().toLowerCase()
)
- const languages = ['pl', 'en'].map((code) => ({
- code,
- label: code.toUpperCase(),
- }))
+ const languages =
+ locales && locales.length > 0
+ ? locales
+ : [{ code: currentLocale, label: currentLocale.toUpperCase() }]
const activeLang = languages.find((l) => l.code === currentLocale) || languages[0]
@@ -106,7 +112,11 @@ export function Header({
{/* Main Navigation Bar */}
-
+ {logo ? (
+
+ ) : companyName ? (
+ {companyName}
+ ) : null}
{/* Navigation Items */}
diff --git a/src/components/Logo.tsx b/src/components/Logo.tsx
index c1271fd..f155ebc 100644
--- a/src/components/Logo.tsx
+++ b/src/components/Logo.tsx
@@ -1,5 +1,6 @@
import React from 'react'
import Image from 'next/image'
+import type { Media } from '@/payload-types'
interface LogoProps {
className?: string
@@ -8,13 +9,29 @@ interface LogoProps {
width?: number
priority?: boolean
alt?: string
+ media?: Media | { url?: string | null; alt?: string | null } | null
+ src?: string | null
}
-export function LogoIcon({ className = 'h-11 w-auto', alt = '', ...props }: { className?: string; alt?: string }) {
+export function LogoIcon({
+ className = 'h-11 w-auto',
+ alt = '',
+ media,
+ ...props
+}: {
+ className?: string
+ alt?: string
+ media?: Media | { url?: string | null; alt?: string | null } | null
+}) {
+ const src = (typeof media === 'object' && media?.url) || null
+ const mediaAlt = (typeof media === 'object' && media?.alt) || alt || ''
+
+ if (!src) return null
+
return (
)
}
+
+
diff --git a/src/i18n.config.ts b/src/i18n.config.ts
index c2e4f5c..0c05d73 100644
--- a/src/i18n.config.ts
+++ b/src/i18n.config.ts
@@ -4,6 +4,7 @@ export const i18nConfig = {
defaultLocale: 'pl',
locales: [
{ code: 'pl', label: 'PL' },
- { code: 'en', label: 'UK' },
+ { code: 'de', label: 'DE' },
],
} as const satisfies I18nConfig
+
diff --git a/src/lib/payload.ts b/src/lib/payload.ts
index 7368cbc..b4aef1f 100644
--- a/src/lib/payload.ts
+++ b/src/lib/payload.ts
@@ -1,7 +1,9 @@
import { cache } from 'react'
import { getSiteSettings } from '@intecion/ipal-kit'
+import type { SiteSetting } from '@/payload-types'
import { getCachedPayload } from './content'
export const getSettings = cache(async (locale: string) =>
- getSiteSettings(await getCachedPayload(), { locale: locale as never, depth: 2 }),
+ getSiteSettings
(await getCachedPayload(), { locale: locale as never, depth: 2 }),
)
+
diff --git a/src/seed/index.ts b/src/seed/index.ts
index 9ee4967..75f9337 100644
--- a/src/seed/index.ts
+++ b/src/seed/index.ts
@@ -1,3 +1,5 @@
+import path from 'path'
+import fs from 'fs'
import type { Payload } from 'payload'
export async function seed(payload: Payload) {
@@ -130,18 +132,95 @@ export async function seed(payload: Payload) {
contactForm = { id: Number(existingForms.docs[0].id) }
}
- // 4. Sprawdź czy strony już istnieją
- const existingPages = await payload.find({
- collection: 'pages',
+ // 4. Seedowanie mediów (logo oraz favicon)
+ let logoMediaId: number | null = null
+ let faviconMediaId: number | null = null
+
+ const existingLogo = await payload.find({
+ collection: 'media',
+ locale: 'pl',
+ where: {
+ or: [
+ { filename: { contains: 'logo-poi' } },
+ { alt: { equals: 'Logo POI Clean House' } },
+ ],
+ },
limit: 1,
})
- if (existingPages.totalDocs > 0) {
- payload.logger.info('Strony już istnieją w bazie. Pomijam seedowanie stron.')
- return
+ if (existingLogo.totalDocs === 0) {
+ payload.logger.info('Tworzę logo w kolekcji Media...')
+ const filePath = path.resolve(process.cwd(), 'public/images/logo-poi.svg')
+ if (fs.existsSync(filePath)) {
+ const createdLogo = await payload.create({
+ collection: 'media',
+ locale: 'pl',
+ filePath,
+ data: {
+ alt: 'Logo POI Clean House',
+ },
+ })
+ logoMediaId = Number(createdLogo.id)
+ }
+ } else {
+ logoMediaId = Number(existingLogo.docs[0].id)
}
- payload.logger.info('Tworzę strony serwisu...')
+ const existingFavicon = await payload.find({
+ collection: 'media',
+ locale: 'pl',
+ where: {
+ or: [
+ { filename: { contains: 'favicon-poi' } },
+ { alt: { equals: 'Favicon icon POI Clean House' } },
+ ],
+ },
+ limit: 1,
+ })
+
+ if (existingFavicon.totalDocs === 0) {
+ payload.logger.info('Tworzę favicon w kolekcji Media...')
+ const filePath = path.resolve(process.cwd(), 'public/images/favicon-poi.svg')
+ if (fs.existsSync(filePath)) {
+ const createdFavicon = await payload.create({
+ collection: 'media',
+ locale: 'pl',
+ filePath,
+ data: {
+ alt: 'Favicon icon POI Clean House',
+ },
+ })
+ faviconMediaId = Number(createdFavicon.id)
+ }
+ } else {
+ faviconMediaId = Number(existingFavicon.docs[0].id)
+ }
+
+ // 5. Sprawdź czy strony już istnieją
+ const existingPages = await payload.find({
+ collection: 'pages',
+ limit: 20,
+ })
+
+ let homePageId: number | null = null
+ let privacyPageId: number | null = null
+ let cookiePageId: number | null = null
+ let realizacjePageId: number | null = null
+ let blogPageId: number | null = null
+ let kontaktPageId: number | null = null
+
+ if (existingPages.totalDocs > 0) {
+ payload.logger.info('Strony już istnieją w bazie. Odczytuję ID stron...')
+ for (const page of existingPages.docs) {
+ if (page.slug === 'home') homePageId = Number(page.id)
+ if (page.slug === 'polityka-prywatnosci') privacyPageId = Number(page.id)
+ if (page.slug === 'polityka-cookies') cookiePageId = Number(page.id)
+ if (page.slug === 'realizacje') realizacjePageId = Number(page.id)
+ if (page.slug === 'blog') blogPageId = Number(page.id)
+ if (page.slug === 'kontakt') kontaktPageId = Number(page.id)
+ }
+ } else {
+ payload.logger.info('Tworzę strony serwisu...')
// A. Strona Główna
const homePage = await payload.create({
@@ -578,24 +657,36 @@ W każdej chwili możesz zmienić swoje preferencje dotyczące plików cookies k
},
})
- // 4. Przypisanie stron systemowych do globala site-settings
- payload.logger.info('Konfiguruję strony systemowe w SiteSettings...')
+ homePageId = Number(homePage.id)
+ privacyPageId = Number(privacyPage.id)
+ cookiePageId = Number(cookiePage.id)
+ realizacjePageId = Number(realizacjePage.id)
+ blogPageId = Number(blogPage.id)
+ kontaktPageId = Number(kontaktPage.id)
+ }
+
+ // 6. Przypisanie stron systemowych oraz mediów do globala site-settings
+ payload.logger.info('Konfiguruję SiteSettings (logo, favicon, defaultShareImage, strony systemowe)...')
try {
await payload.updateGlobal({
slug: 'site-settings',
locale: 'pl',
data: {
siteName: 'POI Clean House',
- homepage: homePage.id,
- privacyPolicy: privacyPage.id,
- cookiePolicy: cookiePage.id,
+ titleOrder: 'page-first',
+ titleSeparator: '|',
+ ...(logoMediaId ? { logo: logoMediaId, defaultShareImage: logoMediaId } : {}),
+ ...(faviconMediaId ? { favicon: faviconMediaId } : {}),
+ ...(homePageId ? { homepage: homePageId } : {}),
+ ...(privacyPageId ? { privacyPolicy: privacyPageId } : {}),
+ ...(cookiePageId ? { cookiePolicy: cookiePageId } : {}),
} as never,
})
} catch (err) {
payload.logger.warn(`Nie udało się automatycznie zaktualizować siteSettings: ${err}`)
}
- // 5. Przypisanie menu do globala navigation
+ // 7. Przypisanie menu do globala navigation
payload.logger.info('Konfiguruję menu w Navigation...')
try {
await payload.updateGlobal({
@@ -611,42 +702,24 @@ W każdej chwili możesz zmienić swoje preferencje dotyczące plików cookies k
label: 'Cennik',
url: '#cennik',
},
- {
- label: 'Realizacje',
- page: realizacjePage.id,
- },
- {
- label: 'Blog',
- page: blogPage.id,
- },
+ ...(realizacjePageId ? [{ label: 'Realizacje', page: realizacjePageId }] : []),
+ ...(blogPageId ? [{ label: 'Blog', page: blogPageId }] : []),
],
ctaButton: {
label: 'Kontakt',
- page: kontaktPage.id,
+ ...(kontaktPageId ? { page: kontaktPageId } : { url: '/kontakt' }),
},
footerTagline:
'Wyspecjalizowane usługi mycia gorącowodnego, usuwania mchu, odplamiania oleju, spoinowania i impregnacji hydrofobowej nawierzchni brukowych.',
footerItems: [
- {
- label: 'Strona główna',
- page: homePage.id,
- },
+ ...(homePageId ? [{ label: 'Strona główna', page: homePageId }] : []),
{
label: 'Cennik usług',
url: '#cennik',
},
- {
- label: 'Galeria realizacji',
- page: realizacjePage.id,
- },
- {
- label: 'Poradnik i Blog',
- page: blogPage.id,
- },
- {
- label: 'Kontakt i wycena',
- page: kontaktPage.id,
- },
+ ...(realizacjePageId ? [{ label: 'Galeria realizacji', page: realizacjePageId }] : []),
+ ...(blogPageId ? [{ label: 'Poradnik i Blog', page: blogPageId }] : []),
+ ...(kontaktPageId ? [{ label: 'Kontakt i wycena', page: kontaktPageId }] : []),
],
} as never,
})
@@ -656,3 +729,4 @@ W każdej chwili możesz zmienić swoje preferencje dotyczące plików cookies k
payload.logger.info('Seedowanie zakończone pomyślnie!')
}
+