diff --git a/src/components/sections/DinoPageContent.tsx b/src/components/sections/DinoPageContent.tsx
index 21b468b..fcf22e2 100644
--- a/src/components/sections/DinoPageContent.tsx
+++ b/src/components/sections/DinoPageContent.tsx
@@ -298,6 +298,7 @@ const DYNO_CSS = `
.dino-page .hero-dino{
position:absolute;top:12px;right:-60px;height:1096px;width:auto;max-width:none;
z-index:0;pointer-events:none;
+ filter:contrast(1.08) saturate(1.12);
}
.dino-page .hero-text{position:relative;z-index:2;max-width:608px;padding:60px 0 40px;}
.dino-page .hero-text h1{
diff --git a/src/components/sections/DyvoLisHero.tsx b/src/components/sections/DyvoLisHero.tsx
index 52fbfd5..01d905c 100644
--- a/src/components/sections/DyvoLisHero.tsx
+++ b/src/components/sections/DyvoLisHero.tsx
@@ -142,7 +142,7 @@ export function DyvoLisHero({
}}
/>
- {/* Cat */}
+ {/* Cat — screen blend removes black JPEG background, shows ellipse behind */}
diff --git a/src/seed.ts b/src/seed.ts
index 8bd7bfa..5c00949 100644
--- a/src/seed.ts
+++ b/src/seed.ts
@@ -5,6 +5,15 @@ import config from '../payload.config.js'
async function seed(): Promise {
const payload = await getPayload({ config })
+ // FORCE_SEED=true is required to overwrite globals that may have been edited in the admin UI.
+ // Without it, only empty collections (users, blog posts, tariffs, locations) are seeded.
+ const force = process.env['FORCE_SEED'] === 'true'
+
+ if (!force) {
+ console.log('Running in safe mode — globals will NOT be overwritten.')
+ console.log('Set FORCE_SEED=true to re-seed all globals (will overwrite admin changes).')
+ }
+
// Admin user
const { totalDocs } = await payload.find({
collection: 'users',
@@ -28,115 +37,123 @@ async function seed(): Promise {
console.log('Users already exist, skipping user seed.')
}
+ if (!force) {
+ console.log('Skipping globals seed — run with FORCE_SEED=true to overwrite.')
+ }
+
// Home page global with real content
- await payload.updateGlobal({
- slug: 'home-page',
- data: {
- hero: {
- title: 'Започаткуйте традицію:',
- subtitle: 'щороку фотографуйтесь біля улюбленого динозавра',
+ if (force) {
+ await payload.updateGlobal({
+ slug: 'home-page',
+ data: {
+ hero: {
+ title: 'Започаткуйте традицію:',
+ subtitle: 'щороку фотографуйтесь біля улюбленого динозавра',
+ ctaLabel: 'Купити квиток',
+ ctaHref: '/kvytky',
+ },
+ sectionTitles: {
+ locations: 'ЛАСКАВО ПРОСИМО ДО ШУМІЛЕНДУ',
+ whyParents: 'ЧОМУ БАТЬКИ ОБИРАЮТЬ ШУМІЛЕНД',
+ birthday: 'ДЕНЬ НАРОДЖЕННЯ В ШУМІЛЕНДІ',
+ gallery: 'ФОТОГАЛЕРЕЯ',
+ reviews: 'ВІДГУКИ',
+ news: 'НОВИНИ',
+ },
+ locations: [
+ {
+ name: 'ДиноПарк',
+ shortDesc: 'Прогуляйтесь серед реалістичних динозаврів у повний зріст',
+ href: '/lokatsii',
+ },
+ {
+ name: 'Диво Ліс',
+ shortDesc: 'Чарівний ліс з інтерактивними атракціонами та мотузковими парками',
+ href: '/lokatsii',
+ },
+ {
+ name: 'Дзеркальний Лабіринт',
+ shortDesc: 'Захоплюючий лабіринт з дзеркалами та оптичними ілюзіями',
+ href: '/lokatsii',
+ },
+ ],
+ features: [
+ {
+ icon: '🦕',
+ title: 'Безпека',
+ description: 'Атракціони сертифіковані, майданчик під постійним наглядом',
+ },
+ { icon: '🌲', title: 'Природа', description: 'Парк розташований серед живої природи' },
+ {
+ icon: '🎉',
+ title: 'Свята',
+ description: 'Дні народження, корпоративи та шкільні екскурсії',
+ },
+ {
+ icon: '🎟️',
+ title: 'Квитки онлайн',
+ description: 'Купуйте квитки онлайн без черги на касі',
+ },
+ {
+ icon: '🍕',
+ title: 'Кафе та їжа',
+ description: 'Власне кафе з дитячим меню та легкими закусками',
+ },
+ { icon: '🅿️', title: 'Парковка', description: 'Безкоштовна парковка для відвідувачів' },
+ ],
+ news: { title: 'Новини', limit: 3 },
+ } as never,
+ overrideAccess: true,
+ })
+ console.log('Seeded home-page global')
+ }
+
+ if (force) {
+ // Header global
+ await payload.updateGlobal({
+ slug: 'header',
+ data: {
+ navLinks: [
+ { label: 'Головна', href: '/' },
+ { label: 'Локації', href: '/lokatsii' },
+ { label: 'Блог', href: '/blog' },
+ { label: 'Дні народження', href: '/dni-narodzhennia' },
+ { label: 'Групові відвідування', href: '/grupovi-vidviduvannia' },
+ ],
ctaLabel: 'Купити квиток',
ctaHref: '/kvytky',
- },
- sectionTitles: {
- locations: 'ЛАСКАВО ПРОСИМО ДО ШУМІЛЕНДУ',
- whyParents: 'ЧОМУ БАТЬКИ ОБИРАЮТЬ ШУМІЛЕНД',
- birthday: 'ДЕНЬ НАРОДЖЕННЯ В ШУМІЛЕНДІ',
- gallery: 'ФОТОГАЛЕРЕЯ',
- reviews: 'ВІДГУКИ',
- news: 'НОВИНИ',
- },
- locations: [
- {
- name: 'ДиноПарк',
- shortDesc: 'Прогуляйтесь серед реалістичних динозаврів у повний зріст',
- href: '/lokatsii',
- },
- {
- name: 'Диво Ліс',
- shortDesc: 'Чарівний ліс з інтерактивними атракціонами та мотузковими парками',
- href: '/lokatsii',
- },
- {
- name: 'Дзеркальний Лабіринт',
- shortDesc: 'Захоплюючий лабіринт з дзеркалами та оптичними ілюзіями',
- href: '/lokatsii',
- },
- ],
- features: [
- {
- icon: '🦕',
- title: 'Безпека',
- description: 'Атракціони сертифіковані, майданчик під постійним наглядом',
- },
- { icon: '🌲', title: 'Природа', description: 'Парк розташований серед живої природи' },
- {
- icon: '🎉',
- title: 'Свята',
- description: 'Дні народження, корпоративи та шкільні екскурсії',
- },
- {
- icon: '🎟️',
- title: 'Квитки онлайн',
- description: 'Купуйте квитки онлайн без черги на касі',
- },
- {
- icon: '🍕',
- title: 'Кафе та їжа',
- description: 'Власне кафе з дитячим меню та легкими закусками',
- },
- { icon: '🅿️', title: 'Парковка', description: 'Безкоштовна парковка для відвідувачів' },
- ],
- news: { title: 'Новини', limit: 3 },
- } as never,
- overrideAccess: true,
- })
- console.log('Seeded home-page global')
+ } as never,
+ overrideAccess: true,
+ })
+ console.log('Seeded header global')
- // Header global
- await payload.updateGlobal({
- slug: 'header',
- data: {
- navLinks: [
- { label: 'Головна', href: '/' },
- { label: 'Локації', href: '/lokatsii' },
- { label: 'Блог', href: '/blog' },
- { label: 'Дні народження', href: '/dni-narodzhennia' },
- { label: 'Групові відвідування', href: '/grupovi-vidviduvannia' },
- ],
- ctaLabel: 'Купити квиток',
- ctaHref: '/kvytky',
- } as never,
- overrideAccess: true,
- })
- console.log('Seeded header global')
+ // Footer global
+ await payload.updateGlobal({
+ slug: 'footer',
+ data: { copyrightText: `© Шуміленд ${new Date().getFullYear()}` } as never,
+ overrideAccess: true,
+ })
+ console.log('Seeded footer global')
- // Footer global
- await payload.updateGlobal({
- slug: 'footer',
- data: { copyrightText: `© Шуміленд ${new Date().getFullYear()}` } as never,
- overrideAccess: true,
- })
- console.log('Seeded footer global')
+ // Site settings
+ await payload.updateGlobal({
+ slug: 'site-settings',
+ data: {
+ siteName: 'Шуміленд',
+ siteURL: process.env['NEXT_PUBLIC_SITE_URL'] ?? 'https://shumiland.ua',
+ } as never,
+ overrideAccess: true,
+ })
+ console.log('Seeded site-settings global')
- // Site settings
- await payload.updateGlobal({
- slug: 'site-settings',
- data: {
- siteName: 'Шуміленд',
- siteURL: process.env['NEXT_PUBLIC_SITE_URL'] ?? 'https://shumiland.ua',
- } as never,
- overrideAccess: true,
- })
- console.log('Seeded site-settings global')
-
- // Remaining globals — initialize empty
- for (const slug of ['checkout-page', 'thank-you-page'] as const) {
- try {
- await payload.updateGlobal({ slug, data: {} as never, overrideAccess: true })
- console.log(`Initialized global: ${slug}`)
- } catch (err) {
- console.warn(`Could not initialize global ${slug}:`, err)
+ // Remaining globals — initialize empty
+ for (const slug of ['checkout-page', 'thank-you-page'] as const) {
+ try {
+ await payload.updateGlobal({ slug, data: {} as never, overrideAccess: true })
+ console.log(`Initialized global: ${slug}`)
+ } catch (err) {
+ console.warn(`Could not initialize global ${slug}:`, err)
+ }
}
}
@@ -180,94 +197,98 @@ async function seed(): Promise {
console.log('Blog posts already exist, skipping.')
}
- // Tariffs — update to match Figma designs
+ // Tariffs — seed only if none exist (never delete admin-managed tariffs)
{
- // Delete old tariffs and re-seed with correct data
- const existing = await payload.find({ collection: 'tariffs', limit: 100, overrideAccess: true })
- for (const t of existing.docs) {
- await payload.delete({ collection: 'tariffs', id: t.id, overrideAccess: true })
- }
+ const { totalDocs: tariffCount } = await payload.find({
+ collection: 'tariffs',
+ limit: 1,
+ overrideAccess: true,
+ })
- const tariffs = [
- // Individual dino-park tickets (shown on both Dino and DyvoLis pages)
- {
- ezy_id: 1001,
- last_synced_name: 'Вхід до Динопарку',
- display_name: 'Вхід до Динопарку',
- last_synced_price: 300,
- category_tag: 'dyno',
- sort: 1,
- visible: true,
- },
- {
- ezy_id: 1002,
- last_synced_name: 'Звичайна екскурсія',
- display_name: 'Звичайна екскурсія',
- last_synced_price: 150,
- category_tag: 'dyno',
- sort: 2,
- visible: true,
- },
- {
- ezy_id: 1003,
- last_synced_name: 'Палеонтологічна екскурсія',
- display_name: 'Палеонтологічна екскурсія',
- last_synced_price: 300,
- category_tag: 'dyno',
- sort: 3,
- visible: true,
- },
- {
- ezy_id: 1004,
- last_synced_name: 'ДиноРодо',
- display_name: 'ДиноРодо',
- last_synced_price: 50,
- category_tag: 'dyno',
- sort: 4,
- visible: true,
- },
- // Combo tickets
- {
- ezy_id: 3001,
- last_synced_name: 'Комбо на 1 людину',
- display_name: 'Комбо на 1 людину',
- last_synced_price: 600,
- category_tag: 'combo',
- sort: 1,
- visible: true,
- },
- {
- ezy_id: 3002,
- last_synced_name: 'Комбо на 3 людини',
- display_name: 'Комбо на 3 людини',
- last_synced_price: 1500,
- category_tag: 'combo',
- sort: 2,
- visible: true,
- },
- {
- ezy_id: 3003,
- last_synced_name: 'Комбо на 4 людини',
- display_name: 'Комбо на 4 людини',
- last_synced_price: 1800,
- category_tag: 'combo',
- sort: 3,
- visible: true,
- },
- {
- ezy_id: 3004,
- last_synced_name: 'Комбо на 5 людин',
- display_name: 'Комбо на 5 людин',
- last_synced_price: 2000,
- category_tag: 'combo',
- sort: 4,
- visible: true,
- },
- ]
- for (const t of tariffs) {
- await payload.create({ collection: 'tariffs', data: t as never, overrideAccess: true })
+ if (tariffCount > 0) {
+ console.log('Tariffs already exist, skipping.')
+ } else {
+ const tariffs = [
+ // Individual dino-park tickets (shown on both Dino and DyvoLis pages)
+ {
+ ezy_id: 1001,
+ last_synced_name: 'Вхід до Динопарку',
+ display_name: 'Вхід до Динопарку',
+ last_synced_price: 300,
+ category_tag: 'dyno',
+ sort: 1,
+ visible: true,
+ },
+ {
+ ezy_id: 1002,
+ last_synced_name: 'Звичайна екскурсія',
+ display_name: 'Звичайна екскурсія',
+ last_synced_price: 150,
+ category_tag: 'dyno',
+ sort: 2,
+ visible: true,
+ },
+ {
+ ezy_id: 1003,
+ last_synced_name: 'Палеонтологічна екскурсія',
+ display_name: 'Палеонтологічна екскурсія',
+ last_synced_price: 300,
+ category_tag: 'dyno',
+ sort: 3,
+ visible: true,
+ },
+ {
+ ezy_id: 1004,
+ last_synced_name: 'ДиноРодо',
+ display_name: 'ДиноРодо',
+ last_synced_price: 50,
+ category_tag: 'dyno',
+ sort: 4,
+ visible: true,
+ },
+ // Combo tickets
+ {
+ ezy_id: 3001,
+ last_synced_name: 'Комбо на 1 людину',
+ display_name: 'Комбо на 1 людину',
+ last_synced_price: 600,
+ category_tag: 'combo',
+ sort: 1,
+ visible: true,
+ },
+ {
+ ezy_id: 3002,
+ last_synced_name: 'Комбо на 3 людини',
+ display_name: 'Комбо на 3 людини',
+ last_synced_price: 1500,
+ category_tag: 'combo',
+ sort: 2,
+ visible: true,
+ },
+ {
+ ezy_id: 3003,
+ last_synced_name: 'Комбо на 4 людини',
+ display_name: 'Комбо на 4 людини',
+ last_synced_price: 1800,
+ category_tag: 'combo',
+ sort: 3,
+ visible: true,
+ },
+ {
+ ezy_id: 3004,
+ last_synced_name: 'Комбо на 5 людин',
+ display_name: 'Комбо на 5 людин',
+ last_synced_price: 2000,
+ category_tag: 'combo',
+ sort: 4,
+ visible: true,
+ },
+ ]
+ for (const t of tariffs) {
+ await payload.create({ collection: 'tariffs', data: t as never, overrideAccess: true })
+ }
+ console.log('Seeded tariffs')
}
- console.log('Seeded tariffs (updated to match Figma)')
}
// Locations