buildComboCards now uses ezy tariffs as primary source when available.
Static cards are only used for descriptions and as fallback when ezy is down.
This removes test/placeholder cards and fixes mismatched prices from CMS.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
At Docker build time Next.js renders /kvytky statically before the server
starts, so getTariffs() gets empty array. KvytkyTicketsClient now fetches
/api/tickets/tariffs on mount when serverTariffs is empty.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- revalidatePath + kvytky page: use http://localhost:3000 for server-to-self
fetches (was using NEXT_PUBLIC_SITE_URL with self-signed HTTPS → Node rejected cert)
- Footer: strip hostname from Payload media URL (same fix as Header)
- DyvoLisTickets: show zone ticket named 'Диво' for individual dyvolis tickets
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Header: strip hostname from Payload media URL in resolveLogoUrl (was showing IP)
- DyvoLisTickets: prefer 'dyvolis' category over 'dyno' for single tickets
- DyvoLisWhyVisit: narrow accordion (628→480px), remove video max-w cap
- migration 0017: seed 3 extra birthday package items (rows 4-6) so CMS block is editable
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ALTER TABLE home_page + _home_page_v to add the new varchar column
for the Google review URL field added to sectionTitles group.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add googleReviewUrl text field to HomePage.sectionTitles group so editors
can update the Google review link without a deploy. Falls back to the
hardcoded URL when the field is empty.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Copy original lossless PNG to public/images/locations/ as hero bg fallback
(bypasses Payload WebP compression entirely when CMS has no image)
- Fallback heroBgUrl to static PNG so the banner always renders
- Raise Media collection WebP quality: 82→88 (mobile/tablet), 85→92 (original+desktop)
Future re-uploads will have noticeably better quality
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Terminates HTTPS on port 443 with self-signed cert, redirects :80 to HTTPS.
Required for Payload admin CSRF (browsers only send Sec-Fetch-Site in secure context).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace hardcoded video-only VideoSlider with SideSlider that accepts
any images array. If CMS sideGallery images exist, show them without
the play button; otherwise fall back to static video thumbnail with
play button as before.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Allow editors to upload custom background pattern images for the birthday
section cards (green cards and featured orange card) from the CMS admin.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Switch prod setup from traefik (external network) to self-contained
Caddy container that terminates HTTPS at the IP. Self-signed cert is
needed so browsers send Sec-Fetch-Site (only in secure contexts) and
Payload admin cookie auth works over http-by-IP won't.
- Add caddy:2-alpine service with ports 80/443 and Caddyfile mount
- Mount ./certs volume to app (NODE_EXTRA_CA_CERTS) so next/image can
optimise absolute https://IP media URLs without cert rejection
- Remove traefik-public external network + labels
- Update build arg NEXT_PUBLIC_SITE_URL to https://147.135.209.100
- Add postgres-data/backups/certs to .dockerignore
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
extraItems was simplified to always use FALLBACK_EXTRA_ITEMS in the
previous refactor, breaking CMS editability for Костюмованих ведучих,
Аквагрим, Затишну альтанку. Restore CMS-first logic: use
cmsPackageItems[3+] when available, fallback otherwise.
Replace wrong gallery-shumi-6.webp (DyvoLis topiary arch) with null
so the placeholder SVG shows until a real photo is uploaded via CMS.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
heroBgUrl was never populated — page.tsx queried only the dinosaur-page
global and didn't read the Location's heroBackground upload field.
Now fetches the locations collection in parallel and passes heroBgUrl to
DinoPageContent, which already handles the conditional hero-bg render.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove 10 CMS global fields that had data+fallbacks but were never rendered:
workingHours, pricingPackages, entrancePrices, freeInclusions, entertainmentPackages
plus heroCta, packageSectionSubtitle, and their title fields.
In page.tsx: remove TicketCard component, TicketCardData interface, and all
corresponding variable declarations (~80 lines). Simplify extraItems to always
use FALLBACK_EXTRA_ITEMS (removes fragile cmsHasPhotos && length>3 condition).
Fix typo in packageItems defaultValue: 'ДинопаркArk' → 'ДиноПарк'
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- DinoPageContent: add isolation:isolate to .hero so z-index:-1 hero-bg
is visible (was painted behind the page background color)
- Gallery: pad CMS images with static fallbacks when fewer than 9 entries,
so the slider always shows a full set even if CMS only has 2 photos
- Birthday page: replace null altanka image with gallery-shumi-6.webp placeholder
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Payload media served from the deployment host (e.g. http://147.135.209.100)
was blocked by Next.js image optimiser with 400 because the host was absent
from remotePatterns. Now parsed at build time from NEXT_PUBLIC_SITE_URL so
it works for any environment (localhost, IP, or domain) without hardcoding.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Payload 3 + PostgreSQL rejects string IDs for upload field relationships;
helpers were returning String(doc.id) which caused ValidationError on
every location/post create that referenced an already-existing media record.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
On video upload, fires FFmpeg in the background to re-encode to
H.264/AAC with CRF 28 (50-80% size reduction vs phone recordings).
Adds FFmpeg to runner Docker image. Original file is replaced
in-place so URL never changes.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace text src/poster in whyVideos with media upload pickers so
admins can upload video files directly from the CMS instead of
entering raw URLs.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
extraItems now uses slice(3) without end limit — items 4-N all appear
in the "Також можна додатково замовити" grid instead of being silently dropped.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Admins can now upload custom pattern images for green and orange
pricing cards via Home Page → День народження → Паттерн зелених/оранжевої карток.
Falls back to static /images/figma/card-pattern-*.png if not set.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove DyvoLisPage global from Payload config (was not connected to website,
website reads from locations collection instead)
- Fix docker-compose.prod.yml migrate service volume path:
/app/migrations -> /migrations to match Dockerfile.migrator WORKDIR
- Wrap seed route in try/catch to return proper error instead of silent 500
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add missing version_faq_title column to _home_page_v and create
_home_page_v_version_faq_items table; Payload versions: {max:20}
requires both the main table and the versions table to be in sync.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add FAQ accordion section (FAQ.tsx) after Reviews on home page
- Add faq group field to HomePage global (title + items array)
- Add HomePageFaq types to types/globals.ts
- Seed whyParents.items with 6 items from static fallback texts
- Seed faq with 6 Q&A items about the park
- Migration 0012: create home_page_faq_items table for Payload array field
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- CookieBanner: bottom-fixed, stores consent in localStorage,
links to privacy policy, green brand colors
- Privacy policy + Data processing: replace GDPR as primary
reference with ЗУ «Про захист персональних даних» № 2297-VI,
correct article references (ст. 6, 8, 16, 24 Закону),
supervisory authority: Уповноважений ВРУ з прав людини
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- CheckoutPage: pass instructions and terms from CMS global to frontend;
instructions shown above form, terms below button
- ThankYouPage: fetch title/message/contactPhone/contactEmail from CMS;
contact info shown if set, falls back to hardcoded defaults
- Hero: use backgroundImageUrl text field as fallback for media upload
- Add lexicalToText util for plain-text extraction from Payload Lexical JSON
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>