This commit is contained in:
2026-04-11 00:37:12 +02:00
parent 65d99059e0
commit 97778c38be
18 changed files with 1204 additions and 229 deletions

19
.paul/PROJECT.md Normal file
View File

@@ -0,0 +1,19 @@
# PROJECT: ostal.pl
## Description
WordPress theme (ostal_WP) for Ostal — firma realizująca ogrody zimowe, carporty, pergole, stolarkę aluminiową.
## Tech Stack
- WordPress with ACF Pro (Advanced Custom Fields)
- ACF Flexible Content for page sections
- Custom post type: realizacje
- Contact Form 7
- Vite build (ostal-front/dist)
## Value Proposition
Strona firmowa prezentująca ofertę i generująca leady przez formularze kontaktowe.
## Constraints
- ACF Pro must be active on the WordPress installation
- Content must be entered manually in WP admin after template migration
- Existing CSS classes and styles must be preserved

19
.paul/ROADMAP.md Normal file
View File

@@ -0,0 +1,19 @@
# ROADMAP: ostal.pl
## Milestone: v1.0 — ACF Migration
Migrate hardcoded page templates to ACF Flexible Content for CMS editability.
### Phases
1. **ACF Migration page-2707** — Migrate "Ogrody zimowe" (indywidualni) page to ACF Flexible Content
- Status: Complete
- Priority: High
2. **ACF Migration page-2598** — Migrate "Ogrody zimowe dla firm" page to ACF Flexible Content
- Status: Not started
- Priority: Medium
3. **ACF Migration page-2101** — Migrate remaining hardcoded page
- Status: Not started
- Priority: Low

26
.paul/STATE.md Normal file
View File

@@ -0,0 +1,26 @@
## Current Position
Milestone: v1.0 ACF Migration
Phase: 1 of 3 (ACF Migration page-2707) — Complete
Plan: 01-01 — complete
Status: Phase 1 complete, ready for next phase
Last activity: 2026-04-11 — UNIFY complete, loop closed
Progress:
- Milestone: [███░░░░░░░] 33%
- Phase 1: [██████████] 100%
## Loop Position
Current loop state:
```
PLAN ──▶ APPLY ──▶ UNIFY
✓ ✓ ✓ [Loop complete - ready for next PLAN]
```
## Session Continuity
Last session: 2026-04-11
Stopped at: Phase 1 complete
Next action: Run /paul:plan for Phase 2 (ACF Migration page-2598) or pause
Resume file: .paul/phases/01-acf-migration-2707/01-01-SUMMARY.md

View File

@@ -0,0 +1,22 @@
# 2026-04-11
## Co zrobiono
- [Phase 1, Plan 01] Migracja strony 2707 (Ogrody zimowe) z hardkodowanego HTML do ACF Flexible Content
- Dodano 3 brakujące layouty do sections.php (hero_with_form, gallery, collaboration_steps)
- Utworzono nowy partial section-collaboration-steps.php (numerowane kroki współpracy)
- Przepisano page-2707.php na Flexible Content (3 linie PHP)
- Utworzono skrypt migracyjny migrate-2707.php z pełną treścią (10 layoutów)
- Dodano layout collaboration_steps do ACF JSON (group_6494221367141.json)
- Poprawiono hero-with-form template (div zamiast p dla wielu paragrafów)
- Przyciemniono tło hero na stronie 2707 (custom.css)
## Zmienione pliki
- `wp-content/themes/ostal_WP/sections.php`
- `wp-content/themes/ostal_WP/page-2707.php`
- `wp-content/themes/ostal_WP/template-parts/sections/section-collaboration-steps.php`
- `wp-content/themes/ostal_WP/migrate-2707.php`
- `wp-content/themes/ostal_WP/template-parts/sections/section-hero-with-form.php`
- `wp-content/themes/ostal_WP/css/custom.css`
- `wp-content/themes/ostal_WP/acf-json/group_6494221367141.json`

View File

@@ -0,0 +1,14 @@
{"ts":"2026-04-10T21:51:40Z","tool":"Bash","cmd":"mkdir -p \"C:/visual studio code/projekty/ostal.pl/.paul/phases/01-acf-migration-2707\"\",\"description\":\"Create PAUL directory structure\"},\"tool_response\":{\"stdout\":\"\",\"stderr\":\"\",\"inte","cwd":"/c/visual studio code/projekty/ostal.pl"}
{"ts":"2026-04-10T21:52:00Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\ostal.pl\\\\.paul\\\\PROJECT.md","cwd":"/c/visual studio code/projekty/ostal.pl"}
{"ts":"2026-04-10T21:52:03Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\ostal.pl\\\\.paul\\\\ROADMAP.md","cwd":"/c/visual studio code/projekty/ostal.pl"}
{"ts":"2026-04-10T21:52:09Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\ostal.pl\\\\.paul\\\\STATE.md","cwd":"/c/visual studio code/projekty/ostal.pl"}
{"ts":"2026-04-10T21:53:15Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\ostal.pl\\\\.paul\\\\phases\\\\01-acf-migration-2707\\\\01-01-PLAN.md","cwd":"/c/visual studio code/projekty/ostal.pl"}
{"ts":"2026-04-10T21:53:30Z","tool":"Bash","cmd":"powershell -Command \"if (Test-Path 'C:/visual studio code/projekty/ostal.pl/.claude/memory') { 'Memory dir exists' } else { New-Item -ItemType Directory -Path 'C:/visual studio code/projekty/ostal.pl","cwd":"/c/visual studio code/projekty/ostal.pl"}
{"ts":"2026-04-10T21:54:01Z","tool":"Bash","cmd":"powershell -Command '$projectKey = \"C--visual-studio-code-projekty-ostal-pl\"; $junctionPath = \"$env:USERPROFILE\\\\.claude\\\\projects\\\\$projectKey\\\\memory\"; $targetPath = \"C:\\\\visual studi","cwd":"/c/visual studio code/projekty/ostal.pl"}
{"ts":"2026-04-10T21:57:09Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\ostal.pl\\\\.paul\\\\phases\\\\01-acf-migration-2707\\\\01-01-PLAN.md","cwd":"/c/visual studio code/projekty/ostal.pl"}
{"ts":"2026-04-10T21:57:23Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\ostal.pl\\\\.paul\\\\phases\\\\01-acf-migration-2707\\\\01-01-PLAN.md","cwd":"/c/visual studio code/projekty/ostal.pl"}
{"ts":"2026-04-10T21:57:36Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\ostal.pl\\\\.paul\\\\phases\\\\01-acf-migration-2707\\\\01-01-PLAN.md","cwd":"/c/visual studio code/projekty/ostal.pl"}
{"ts":"2026-04-10T21:58:27Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\ostal.pl\\\\.paul\\\\phases\\\\01-acf-migration-2707\\\\01-01-PLAN.md","cwd":"/c/visual studio code/projekty/ostal.pl"}
{"ts":"2026-04-10T21:58:42Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\ostal.pl\\\\.paul\\\\phases\\\\01-acf-migration-2707\\\\01-01-PLAN.md","cwd":"/c/visual studio code/projekty/ostal.pl"}
{"ts":"2026-04-10T21:59:02Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\ostal.pl\\\\.paul\\\\phases\\\\01-acf-migration-2707\\\\01-01-PLAN.md","cwd":"/c/visual studio code/projekty/ostal.pl"}
{"ts":"2026-04-10T21:59:19Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\ostal.pl\\\\.paul\\\\phases\\\\01-acf-migration-2707\\\\01-01-PLAN.md","cwd":"/c/visual studio code/projekty/ostal.pl"}

View File

@@ -0,0 +1,17 @@
{"ts":"2026-04-10T22:04:59Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\ostal.pl\\\\wp-content\\\\themes\\\\ostal_WP\\\\sections.php","cwd":"/c/visual studio code/projekty/ostal.pl"}
{"ts":"2026-04-10T22:05:18Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\ostal.pl\\\\wp-content\\\\themes\\\\ostal_WP\\\\template-parts\\\\sections\\\\section-collaboration-steps.php","cwd":"/c/visual studio code/projekty/ostal.pl"}
{"ts":"2026-04-10T22:05:26Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\ostal.pl\\\\wp-content\\\\themes\\\\ostal_WP\\\\page-2707.php","cwd":"/c/visual studio code/projekty/ostal.pl"}
{"ts":"2026-04-10T22:06:40Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\ostal.pl\\\\wp-content\\\\themes\\\\ostal_WP\\\\migrate-2707.php","cwd":"/c/visual studio code/projekty/ostal.pl"}
{"ts":"2026-04-10T22:06:54Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\ostal.pl\\\\.paul\\\\STATE.md","cwd":"/c/visual studio code/projekty/ostal.pl"}
{"ts":"2026-04-10T22:11:15Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\ostal.pl\\\\wp-content\\\\themes\\\\ostal_WP\\\\acf-json\\\\group_6494221367141.json","cwd":"/c/visual studio code/projekty/ostal.pl"}
{"ts":"2026-04-10T22:11:22Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\ostal.pl\\\\wp-content\\\\themes\\\\ostal_WP\\\\acf-json\\\\group_6494221367141.json","cwd":"/c/visual studio code/projekty/ostal.pl"}
{"ts":"2026-04-10T22:20:37Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\ostal.pl\\\\wp-content\\\\themes\\\\ostal_WP\\\\template-parts\\\\sections\\\\section-hero-with-form.php","cwd":"/c/visual studio code/projekty/ostal.pl"}
{"ts":"2026-04-10T22:21:00Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\ostal.pl\\\\wp-content\\\\themes\\\\ostal_WP\\\\migrate-2707.php","cwd":"/c/visual studio code/projekty/ostal.pl"}
{"ts":"2026-04-10T22:23:08Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\ostal.pl\\\\wp-content\\\\themes\\\\ostal_WP\\\\css\\\\custom.css","cwd":"/c/visual studio code/projekty/ostal.pl"}
{"ts":"2026-04-10T22:24:34Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\ostal.pl\\\\wp-content\\\\themes\\\\ostal_WP\\\\migrate-2707.php","cwd":"/c/visual studio code/projekty/ostal.pl"}
{"ts":"2026-04-10T22:30:37Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\ostal.pl\\\\.paul\\\\STATE.md","cwd":"/c/visual studio code/projekty/ostal.pl"}
{"ts":"2026-04-10T22:33:49Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\ostal.pl\\\\.paul\\\\phases\\\\01-acf-migration-2707\\\\01-01-SUMMARY.md","cwd":"/c/visual studio code/projekty/ostal.pl"}
{"ts":"2026-04-10T22:33:59Z","tool":"Bash","cmd":"mkdir -p \"C:/visual studio code/projekty/ostal.pl/.paul/changelog\"\",\"description\":\"Create changelog directory\"},\"tool_response\":{\"stdout\":\"\",\"stderr\":\"\",\"interrupted\":false,\"isImag","cwd":"/c/visual studio code/projekty/ostal.pl"}
{"ts":"2026-04-10T22:34:13Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\ostal.pl\\\\.paul\\\\changelog\\\\2026-04-11.md","cwd":"/c/visual studio code/projekty/ostal.pl"}
{"ts":"2026-04-10T22:34:24Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\ostal.pl\\\\.paul\\\\STATE.md","cwd":"/c/visual studio code/projekty/ostal.pl"}
{"ts":"2026-04-10T22:34:32Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\ostal.pl\\\\.paul\\\\ROADMAP.md","cwd":"/c/visual studio code/projekty/ostal.pl"}

View File

@@ -0,0 +1,339 @@
---
phase: 01-acf-migration-2707
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
- wp-content/themes/ostal_WP/sections.php
- wp-content/themes/ostal_WP/page-2707.php
- wp-content/themes/ostal_WP/template-parts/sections/section-collaboration-steps.php
- wp-content/themes/ostal_WP/migrate-2707.php
autonomous: false
delegation: off
---
<objective>
## Goal
Migrate hardcoded content from `page-2707.php` (Ogrody zimowe — klienci indywidualni) to ACF Flexible Content, making all text, images, and sections editable from WordPress admin.
## Purpose
Currently all content is hardcoded in PHP — any change requires developer intervention. After migration, the client can edit headings, texts, images, and section order directly in WP admin.
## Output
- `page-2707.php` rewritten to use ACF Flexible Content via `sections.php`
- Missing layouts added to `sections.php` dispatcher
- New `section-collaboration-steps.php` partial for the numbered steps section
- `migrate-2707.php` one-time script to populate ACF content programmatically
</objective>
<context>
## Project Context
@.paul/PROJECT.md
@.paul/ROADMAP.md
## Source Files
@wp-content/themes/ostal_WP/page-2707.php
@wp-content/themes/ostal_WP/sections.php
@wp-content/themes/ostal_WP/template-parts/sections/section-hero-with-form.php
@wp-content/themes/ostal_WP/template-parts/sections/section-two-col.php
@wp-content/themes/ostal_WP/template-parts/sections/section-two-col-with-bg.php
@wp-content/themes/ostal_WP/template-parts/sections/section-gallery.php
@wp-content/themes/ostal_WP/template-parts/sections/section-boxes_repeater_img_title_text_cta.php
</context>
<acceptance_criteria>
## AC-1: Flexible Content dispatcher complete
```gherkin
Given sections.php is loaded on page 2707
When the ACF flexible content field "sections" contains layouts
Then hero_with_form, gallery, and collaboration_steps layouts are dispatched to correct template-parts
```
## AC-2: Collaboration steps layout works
```gherkin
Given a "collaboration_steps" layout is added in ACF admin
When a repeater with step titles is filled in
Then the page renders numbered steps with connecting lines matching the current design
```
## AC-3: Page 2707 uses Flexible Content
```gherkin
Given page-2707.php is loaded
When the page renders
Then all content comes from ACF fields (no hardcoded text/images remain)
And the visual output matches the current hardcoded version when same content is entered in ACF
```
## AC-4: Migration script populates ACF content
```gherkin
Given migrate-2707.php is executed once (via browser or WP-CLI)
When the script runs with WordPress and ACF loaded
Then all 10 flexible content layouts are created for page 2707
And all text, headings, classes, shortcodes, and image URLs are populated
And the page renders with full content without manual data entry
```
</acceptance_criteria>
<tasks>
<task type="auto">
<name>Task 1: Add missing layouts to sections.php dispatcher</name>
<files>wp-content/themes/ostal_WP/sections.php</files>
<action>
Add three missing layout dispatchers to the flexible content loop in sections.php:
1. `hero_with_form` → loads `template-parts/sections/section-hero-with-form`
2. `gallery` → loads `template-parts/sections/section-gallery`
3. `collaboration_steps` → loads `template-parts/sections/section-collaboration-steps`
Follow the exact same pattern as existing entries (get_row_layout() check + get_template_part).
Do NOT modify any existing layout dispatchers.
</action>
<verify>sections.php contains all 11 layout dispatchers (8 existing + 3 new) with no syntax errors</verify>
<done>AC-1 satisfied: All needed layouts are dispatched from sections.php</done>
</task>
<task type="auto">
<name>Task 2: Create collaboration-steps section partial</name>
<files>wp-content/themes/ostal_WP/template-parts/sections/section-collaboration-steps.php</files>
<action>
Create new template partial for the numbered collaboration steps section.
ACF sub-fields to use (will need to be registered in ACF admin):
- `section_heading` (text) — section title, e.g. "Jak wygląda współpraca?"
- `steps` (repeater) with sub-field:
- `step_title` (text) — step name
- `bottom_text` (textarea) — text below the steps
HTML structure must match the current hardcoded version exactly:
- Outer: `<section id="collaboration" class="section-boxes-repeater">`
- Inner: `.wrapper.wrapper--inner` > `h2.section-heading.heading--md`
- Steps container: `.collaboration-steps` with max-width 900px, margin auto, padding 20px 0
- Each step: `.collaboration-step` with flex layout, gap 20px, margin-bottom 40px (except last)
- Step number: `.step-number` — circular green gradient (#88b14b#6a8f3a), 60x60, white text
- Connector line: `.step-connector` — 2px wide, gradient green to gray, between steps (not after last)
- Step content: `.step-content` — gray bg (#f8f9fa), 4px green left border, rounded
- Bottom text: `.col-text-content.mt-4.text-center` > `<p>`
Move inline styles to classes where possible, but keep them if removing would break existing CSS dependencies.
Include the existing hover/responsive CSS from page-2707.php as a <style> block in the partial.
</action>
<verify>Template renders numbered steps with ACF repeater data, matching current visual design</verify>
<done>AC-2 satisfied: Collaboration steps layout renders correctly from ACF data</done>
</task>
<task type="auto">
<name>Task 3: Rewrite page-2707.php to use Flexible Content</name>
<files>wp-content/themes/ostal_WP/page-2707.php</files>
<action>
Replace entire hardcoded content with ACF Flexible Content loader.
New page-2707.php should contain only:
```php
<?php get_header(); ?>
<?php include( locate_template( 'sections.php' ) ); ?>
<?php get_footer(); ?>
```
This delegates all section rendering to sections.php which dispatches based on ACF layouts.
The user will then need to configure the following layouts in WP admin for page 2707:
1. hero_with_form — heading, text (wysiwyg for multiple paragraphs + bold), form shortcode, bg image
2. two_col_section — "Nasze ogrody zimowe..." (imageLeft, bg-light)
3. two_col_section — "Co wyróżnia nasze ogrody zimowe" (imageLeft, bg-light)
4. collaboration_steps — 5 steps + bottom text
5. two_col_section — "Doświadczenie w systemach aluminiowych" (imageLeft, bg-light)
6. two_col_section — "Planowanie realizacji bez pośpiechu" (imageLeft, bg-light)
7. two_col_section — "Porozmawiajmy o twoim projekcie" (imageLeft, bg-light)
8. two_col_section_with_bg — CTA "Sprawdź orientacyjny budżet" (bg-dark)
9. two_col_section — "Funkcje ogrodów zimowych" (imageLeft, bg-light)
10. gallery — "Nasze realizacje ogrodów zimowych" (6 images)
NOTE on hero_with_form: Current template only outputs one <p> for text field.
The hardcoded page has 3 paragraphs (regular + strong/specs + CTA text).
If the ACF text field is wysiwyg type, all 3 paragraphs can be entered there.
If it's textarea, the template needs modification — check and adapt section-hero-with-form.php
to use wysiwyg or wrap text output in wpautop().
</action>
<verify>page-2707.php contains only header, sections.php include, and footer — no hardcoded content</verify>
<done>AC-3 satisfied: Page 2707 renders entirely from ACF Flexible Content</done>
</task>
<task type="auto">
<name>Task 4: Create migration script to populate ACF content</name>
<files>wp-content/themes/ostal_WP/migrate-2707.php</files>
<action>
Create a one-time PHP migration script that programmatically fills all ACF Flexible Content
data for page 2707 using `update_field()`.
Script structure:
1. WordPress bootstrap: require wp-load.php (relative path from theme dir)
2. Safety check: only run if GET param `?run=migrate-2707` is present
3. Safety check: abort if page 2707 already has sections data
4. Define $page_id = 2707
5. Build $sections array matching ACF Flexible Content structure
The $sections array must contain 10 layouts in this order:
Layout 1: hero_with_form
- acf_fc_layout: "hero_with_form"
- heading: "Całoroczne ogrody zimowe klasy premium"
- text: full HTML with 3 paragraphs (regular text, strong specs with <br>, CTA text)
- form_shortcode: '[contact-form-7 id="21a1143" title="Formularz kontaktowy"]'
- background_image: "/wp-content/uploads/2023/10/ogrody-zimowe.jpg"
- section_id: "hero_box"
Layout 2: two_col_section
- section_heading: "Nasze ogrody zimowe powstają z myślą o klientach, którzy szukają trwałego,<br>elastycznego i bezpiecznego rozwiązania na lata, a nie tymczasowej zabudowy."
- text: "<p>Każda realizacja jest projektowana indywidualnie...</p><p>Realizacje całorocznych ogrodów zimowych rozpoczynają się od około 100 000 zł netto.</p>"
- image: "https://ostal.pl/wp-content/uploads/2026/01/IMG_2832-scaled.jpg"
- additional_class: "imageLeft"
- additional_section_class: "bg-light"
- heading_position: "textRight"
- choose_heading: "h2"
Layout 3: two_col_section
- section_heading: "Co wyróżnia nasze ogrody zimowe"
- text: HTML <ul> list with 5 items + closing paragraph
- image: "https://ostal.pl/wp-content/uploads/2026/01/199-f27gxxl.jpg"
- additional_class: "imageLeft"
- additional_section_class: "bg-light"
- heading_position: "textRight"
- choose_heading: "h2"
Layout 4: collaboration_steps
- section_heading: "Jak wygląda współpraca?"
- steps: repeater with 5 rows:
1. "Rozmowa i analiza potrzeb."
2. "Koncepcja i dobór rozwiązań"
3. "Indywidualna oferta i harmonogram"
4. "Umowa i zaliczka rezerwująca termin"
5. "Produkcja i montaż"
- bottom_text: "Prowadzimy klienta przez cały proces - spokojnie krok po kroku."
Layout 5: two_col_section
- section_heading: "Doświadczenie w systemach aluminiowych"
- text: 2 paragraphs about aluminum systems experience
- image: "/wp-content/uploads/2026/02/att_698c47679eb9b4.14191582.jpeg"
- additional_class: "imageLeft", additional_section_class: "bg-light"
Layout 6: two_col_section
- section_heading: "Planowanie realizacji bez pośpiechu"
- text: paragraph about advance planning
- image: "/wp-content/uploads/2026/02/att_698c4767a04c46.41417006.jpg"
- additional_class: "imageLeft", additional_section_class: "bg-light"
Layout 7: two_col_section
- section_heading: "Porozmawiajmy o twoim projekcie"
- text: paragraph inviting contact
- image: "/wp-content/uploads/2026/02/att_698c47679ad0a0.33546122.jpeg"
- additional_class: "imageLeft", additional_section_class: "bg-light"
Layout 8: two_col_section_with_bg
- section_heading: "Sprawdź orientacyjny budżet projektu"
- cta: "#hero_box"
- cta_text: "Umów rozmowę"
- background_image: "https://ostal.pl/wp-content/uploads/2021/05/hero-about.jpg"
- additional_section_class: "bg-dark"
Layout 9: two_col_section
- section_heading: "Funkcje ogrodów zimowych"
- text: full paragraph about winter garden functions (preserve &nbsp; entities)
- image: "https://ostal.pl/wp-content/uploads/2023/10/DECORATION-PHOTO-1.jpg"
- additional_class: "imageLeft", additional_section_class: "bg-light"
Layout 10: gallery
- section_heading: "Nasze realizacje ogrodów zimowych"
- section_id: "galeria"
- gallery: For images, use helper function to find attachment IDs by URL:
function get_attachment_id_by_url($url) {
global $wpdb;
$path = parse_url($url, PHP_URL_PATH);
$path = preg_replace('/-\d+x\d+(?=\.\w+$)/', '', $path);
$sql = $wpdb->prepare("SELECT ID FROM $wpdb->posts WHERE guid LIKE %s", '%' . $wpdb->esc_like(basename($path)) . '%');
return (int) $wpdb->get_var($sql);
}
Gallery images (6 URLs from hardcoded page):
- https://ostal.pl/wp-content/uploads/2023/10/202-4c7gxxl.jpg
- https://ostal.pl/wp-content/uploads/2023/10/199-f27gxxl.jpg
- https://ostal.pl/wp-content/uploads/2023/10/20170608_142315-1024x576.jpg
- https://ostal.pl/wp-content/uploads/2023/10/IMG_0535-1-1024x768.jpg
- https://ostal.pl/wp-content/uploads/2023/10/IMG_3754-1-1-1024x768.jpg
- https://ostal.pl/wp-content/uploads/2023/10/Frame-36-1-1024x728.jpg
6. Call update_field('sections', $sections, $page_id)
7. Output success message with count of layouts created
8. Add prominent reminder at end: "DELETE THIS FILE after migration!"
IMPORTANT: Use exact text content from the hardcoded page-2707.php. Copy text verbatim
including HTML tags, <br>, &nbsp; entities, and <strong> formatting.
Script must be idempotent — if sections already exist, show warning and exit.
</action>
<verify>Script file exists, contains valid PHP, has safety checks, all 10 layouts defined</verify>
<done>AC-4 satisfied: Migration script ready to populate all ACF content for page 2707</done>
</task>
<task type="checkpoint:human-verify" gate="blocking">
<what-built>Page 2707 migrated to ACF Flexible Content with content populated by migration script</what-built>
<how-to-verify>
1. Visit: https://ostal.pl/wp-content/themes/ostal_WP/migrate-2707.php?run=migrate-2707
(or run via WP-CLI: wp eval-file wp-content/themes/ostal_WP/migrate-2707.php)
2. Open WordPress admin → Pages → page 2707 (Ogrody zimowe)
3. Verify "Sections" flexible content field shows all 10 layouts with content
4. Preview the page
5. Compare with the current live version — layout, spacing, styles should match
6. Test mobile responsiveness of collaboration steps section
7. DELETE migrate-2707.php after confirming
</how-to-verify>
<resume-signal>Type "approved" to continue, or describe issues to fix</resume-signal>
</task>
</tasks>
<boundaries>
## DO NOT CHANGE
- wp-content/themes/ostal_WP/template-parts/sections/section-hero-with-form.php (only modify if text field needs wpautop — minimal change)
- wp-content/themes/ostal_WP/template-parts/sections/section-two-col.php
- wp-content/themes/ostal_WP/template-parts/sections/section-two-col-with-bg.php
- wp-content/themes/ostal_WP/template-parts/sections/section-gallery.php
- wp-content/themes/ostal_WP/functions.php
- Any other page-*.php files
- wp-content/themes/ostal_WP/page-templates/*
## SCOPE LIMITS
- This plan only migrates page-2707.php
- ACF field group for "sections" Flexible Content must already exist in WP (it does — used by other pages)
- New layouts (hero_with_form, gallery, collaboration_steps) must be added to the field group in ACF admin
- No CSS/JS file changes — all existing styles continue to work
- No new dependencies
- migrate-2707.php must be DELETED after successful migration
</boundaries>
<verification>
Before declaring plan complete:
- [ ] sections.php has 11 layout dispatchers (no duplicates, no syntax errors)
- [ ] section-collaboration-steps.php exists and follows ACF sub_field pattern
- [ ] page-2707.php contains only get_header, sections.php include, get_footer
- [ ] No hardcoded content remains in page-2707.php
- [ ] migrate-2707.php exists with all 10 layouts and safety checks
- [ ] Migration script executed successfully (all content populated)
- [ ] User has verified visual match in WordPress admin (checkpoint)
- [ ] migrate-2707.php deleted after verification
</verification>
<success_criteria>
- All 4 auto tasks completed
- Human verification checkpoint approved
- Page 2707 renders identically from ACF content as it did hardcoded
- No regressions on other pages
</success_criteria>
<output>
After completion, create `.paul/phases/01-acf-migration-2707/01-01-SUMMARY.md`
</output>

View File

@@ -0,0 +1,120 @@
---
phase: 01-acf-migration-2707
plan: 01
subsystem: ui
tags: [wordpress, acf, flexible-content, php, migration]
requires:
- phase: none
provides: n/a
provides:
- ACF Flexible Content integration for page 2707
- collaboration_steps ACF layout (reusable)
- Migration script pattern for future pages
affects: [02-acf-migration-2598, 03-acf-migration-2101]
tech-stack:
added: []
patterns: [acf-flexible-content-migration, one-time-php-migration-script]
key-files:
created:
- wp-content/themes/ostal_WP/template-parts/sections/section-collaboration-steps.php
- wp-content/themes/ostal_WP/migrate-2707.php
modified:
- wp-content/themes/ostal_WP/sections.php
- wp-content/themes/ostal_WP/page-2707.php
- wp-content/themes/ostal_WP/template-parts/sections/section-hero-with-form.php
- wp-content/themes/ostal_WP/css/custom.css
- wp-content/themes/ostal_WP/acf-json/group_6494221367141.json
key-decisions:
- "Hero text field: changed <p> to <div> wrapper to support multi-paragraph WYSIWYG content"
- "Migration approach: one-time PHP script using update_field() instead of manual WP admin entry"
- "ACF JSON: added collaboration_steps layout directly to JSON sync file"
patterns-established:
- "ACF migration: create migrate-XXXX.php script with safety checks, run once, delete after"
- "New layouts: add to both sections.php dispatcher AND acf-json group file"
duration: ~45min
started: 2026-04-11
completed: 2026-04-11
---
# Phase 1 Plan 01: ACF Migration page-2707 Summary
**Migrated hardcoded "Ogrody zimowe" page (2707) to ACF Flexible Content with 10 layouts and auto-populated content via migration script.**
## Acceptance Criteria Results
| Criterion | Status | Notes |
|-----------|--------|-------|
| AC-1: Flexible Content dispatcher complete | Pass | 3 new layouts added to sections.php (hero_with_form, gallery, collaboration_steps) |
| AC-2: Collaboration steps layout works | Pass | New partial renders numbered steps with repeater, hover effects, responsive CSS |
| AC-3: Page 2707 uses Flexible Content | Pass | Page reduced to 3 lines (header + sections + footer) |
| AC-4: Migration script populates content | Pass | All 10 layouts populated programmatically, user verified |
## Accomplishments
- Page 2707 fully editable from WP admin (10 ACF Flexible Content layouts)
- New reusable `collaboration_steps` layout with ACF field group definition in JSON
- Migration script pattern established for future page migrations (2598, 2101)
## Files Created/Modified
| File | Change | Purpose |
|------|--------|---------|
| `sections.php` | Modified | Added 3 layout dispatchers (hero_with_form, gallery, collaboration_steps) |
| `page-2707.php` | Modified | Replaced ~225 lines of hardcoded content with 3-line Flexible Content loader |
| `section-collaboration-steps.php` | Created | New partial for numbered cooperation steps with repeater |
| `migrate-2707.php` | Created | One-time migration script populating all 10 layouts (TO DELETE) |
| `section-hero-with-form.php` | Modified | Changed `<p>` to `<div>` for multi-paragraph WYSIWYG support |
| `custom.css` | Modified | Added darker gradient overlay on hero for page 2707 |
| `group_6494221367141.json` | Modified | Added collaboration_steps layout definition to ACF JSON sync |
## Deviations from Plan
### Summary
| Type | Count | Impact |
|------|-------|--------|
| Auto-fixed | 3 | Essential fixes for visual fidelity |
| Deferred | 0 | — |
### Auto-fixed Issues
**1. Hero text rendering broken (nested `<p>` tags)**
- Found during: Checkpoint verification
- Issue: Template wrapped text in `<p>`, WYSIWYG content also had `<p>` tags — browsers broke layout
- Fix: Changed `<p class="hero-text">` to `<div class="hero-text">` in section-hero-with-form.php
- Verification: User confirmed hero displays correctly
**2. Hero background too bright for text readability**
- Found during: Checkpoint verification
- Issue: White text on light background image had poor contrast
- Fix: Added `body.page-id-2707 .hero-with-form .bg-filter` rule with darker gradient (55% → 25% opacity)
- Verification: User confirmed "Jest ok"
**3. Layout 3 column order incorrect**
- Found during: Checkpoint verification
- Issue: "Co wyróżnia" section had image-left layout, user wanted text-left/image-right
- Fix: Removed `imageLeft` class from layout 3 in migration script
- Verification: User confirmed correct order
## Next Phase Readiness
**Ready:**
- Migration pattern proven — same approach applies to page-2598 and page-2101
- All existing ACF layouts verified working (two_col, two_col_with_bg, hero_with_form, gallery)
- collaboration_steps layout reusable for page-2598 (which has identical section)
**Concerns:**
- `migrate-2707.php` must be deleted from server after verification (security risk)
- Gallery images require attachment IDs — if images aren't in Media Library, they won't appear
**Blockers:** None
---
*Phase: 01-acf-migration-2707, Plan: 01*
*Completed: 2026-04-11*

2
.serena/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
/cache
/project.local.yml

152
.serena/project.yml Normal file
View File

@@ -0,0 +1,152 @@
# the name by which the project can be referenced within Serena
project_name: "ostal.pl"
# list of languages for which language servers are started; choose from:
# al bash clojure cpp csharp
# csharp_omnisharp dart elixir elm erlang
# fortran fsharp go groovy haskell
# java julia kotlin lua markdown
# matlab nix pascal perl php
# php_phpactor powershell python python_jedi r
# rego ruby ruby_solargraph rust scala
# swift terraform toml typescript typescript_vts
# vue yaml zig
# (This list may be outdated. For the current list, see values of Language enum here:
# https://github.com/oraios/serena/blob/main/src/solidlsp/ls_config.py
# For some languages, there are alternative language servers, e.g. csharp_omnisharp, ruby_solargraph.)
# Note:
# - For C, use cpp
# - For JavaScript, use typescript
# - For Free Pascal/Lazarus, use pascal
# Special requirements:
# Some languages require additional setup/installations.
# See here for details: https://oraios.github.io/serena/01-about/020_programming-languages.html#language-servers
# When using multiple languages, the first language server that supports a given file will be used for that file.
# The first language is the default language and the respective language server will be used as a fallback.
# Note that when using the JetBrains backend, language servers are not used and this list is correspondingly ignored.
languages:
- php
# the encoding used by text files in the project
# For a list of possible encodings, see https://docs.python.org/3.11/library/codecs.html#standard-encodings
encoding: "utf-8"
# line ending convention to use when writing source files.
# Possible values: unset (use global setting), "lf", "crlf", or "native" (platform default)
# This does not affect Serena's own files (e.g. memories and configuration files), which always use native line endings.
line_ending:
# The language backend to use for this project.
# If not set, the global setting from serena_config.yml is used.
# Valid values: LSP, JetBrains
# Note: the backend is fixed at startup. If a project with a different backend
# is activated post-init, an error will be returned.
language_backend:
# whether to use project's .gitignore files to ignore files
ignore_all_files_in_gitignore: true
# advanced configuration option allowing to configure language server-specific options.
# Maps the language key to the options.
# Have a look at the docstring of the constructors of the LS implementations within solidlsp (e.g., for C# or PHP) to see which options are available.
# No documentation on options means no options are available.
ls_specific_settings: {}
# list of additional paths to ignore in this project.
# Same syntax as gitignore, so you can use * and **.
# Note: global ignored_paths from serena_config.yml are also applied additively.
ignored_paths: []
# whether the project is in read-only mode
# If set to true, all editing tools will be disabled and attempts to use them will result in an error
# Added on 2025-04-18
read_only: false
# list of tool names to exclude.
# This extends the existing exclusions (e.g. from the global configuration)
#
# Below is the complete list of tools for convenience.
# To make sure you have the latest list of tools, and to view their descriptions,
# execute `uv run scripts/print_tool_overview.py`.
#
# * `activate_project`: Activates a project by name.
# * `check_onboarding_performed`: Checks whether project onboarding was already performed.
# * `create_text_file`: Creates/overwrites a file in the project directory.
# * `delete_lines`: Deletes a range of lines within a file.
# * `delete_memory`: Deletes a memory from Serena's project-specific memory store.
# * `execute_shell_command`: Executes a shell command.
# * `find_referencing_code_snippets`: Finds code snippets in which the symbol at the given location is referenced.
# * `find_referencing_symbols`: Finds symbols that reference the symbol at the given location (optionally filtered by type).
# * `find_symbol`: Performs a global (or local) search for symbols with/containing a given name/substring (optionally filtered by type).
# * `get_current_config`: Prints the current configuration of the agent, including the active and available projects, tools, contexts, and modes.
# * `get_symbols_overview`: Gets an overview of the top-level symbols defined in a given file.
# * `initial_instructions`: Gets the initial instructions for the current project.
# Should only be used in settings where the system prompt cannot be set,
# e.g. in clients you have no control over, like Claude Desktop.
# * `insert_after_symbol`: Inserts content after the end of the definition of a given symbol.
# * `insert_at_line`: Inserts content at a given line in a file.
# * `insert_before_symbol`: Inserts content before the beginning of the definition of a given symbol.
# * `list_dir`: Lists files and directories in the given directory (optionally with recursion).
# * `list_memories`: Lists memories in Serena's project-specific memory store.
# * `onboarding`: Performs onboarding (identifying the project structure and essential tasks, e.g. for testing or building).
# * `prepare_for_new_conversation`: Provides instructions for preparing for a new conversation (in order to continue with the necessary context).
# * `read_file`: Reads a file within the project directory.
# * `read_memory`: Reads the memory with the given name from Serena's project-specific memory store.
# * `remove_project`: Removes a project from the Serena configuration.
# * `replace_lines`: Replaces a range of lines within a file with new content.
# * `replace_symbol_body`: Replaces the full definition of a symbol.
# * `restart_language_server`: Restarts the language server, may be necessary when edits not through Serena happen.
# * `search_for_pattern`: Performs a search for a pattern in the project.
# * `summarize_changes`: Provides instructions for summarizing the changes made to the codebase.
# * `switch_modes`: Activates modes by providing a list of their names
# * `think_about_collected_information`: Thinking tool for pondering the completeness of collected information.
# * `think_about_task_adherence`: Thinking tool for determining whether the agent is still on track with the current task.
# * `think_about_whether_you_are_done`: Thinking tool for determining whether the task is truly completed.
# * `write_memory`: Writes a named memory (for future reference) to Serena's project-specific memory store.
excluded_tools: []
# list of tools to include that would otherwise be disabled (particularly optional tools that are disabled by default).
# This extends the existing inclusions (e.g. from the global configuration).
included_optional_tools: []
# fixed set of tools to use as the base tool set (if non-empty), replacing Serena's default set of tools.
# This cannot be combined with non-empty excluded_tools or included_optional_tools.
fixed_tools: []
# list of mode names to that are always to be included in the set of active modes
# The full set of modes to be activated is base_modes + default_modes.
# If the setting is undefined, the base_modes from the global configuration (serena_config.yml) apply.
# Otherwise, this setting overrides the global configuration.
# Set this to [] to disable base modes for this project.
# Set this to a list of mode names to always include the respective modes for this project.
base_modes:
# list of mode names that are to be activated by default.
# The full set of modes to be activated is base_modes + default_modes.
# If the setting is undefined, the default_modes from the global configuration (serena_config.yml) apply.
# Otherwise, this overrides the setting from the global configuration (serena_config.yml).
# This setting can, in turn, be overridden by CLI parameters (--mode).
default_modes:
# initial prompt for the project. It will always be given to the LLM upon activating the project
# (contrary to the memories, which are loaded on demand).
initial_prompt: ""
# time budget (seconds) per tool call for the retrieval of additional symbol information
# such as docstrings or parameter information.
# This overrides the corresponding setting in the global configuration; see the documentation there.
# If null or missing, use the setting from the global configuration.
symbol_info_budget:
# list of regex patterns which, when matched, mark a memory entry as readonly.
# Extends the list from the global configuration, merging the two lists.
read_only_memory_patterns: []
# list of regex patterns for memories to completely ignore.
# Matching memories will not appear in list_memories or activate_project output
# and cannot be accessed via read_memory or write_memory.
# To access ignored memory files, use the read_file tool on the raw file path.
# Extends the list from the global configuration, merging the two lists.
# Example: ["_archive/.*", "_episodes/.*"]
ignored_memory_patterns: []

5
.vscode/ftp-kr.json vendored
View File

@@ -12,6 +12,9 @@
"ignoreRemoteModification": true,
"ignore": [
".git",
"/.vscode"
"/.vscode",
"/.paul",
"/.serena",
"/.claude"
]
}

View File

@@ -2815,6 +2815,115 @@
"acfe_flexible_category": false,
"acfe_layout_col": "auto",
"acfe_layout_allowed_col": false
},
"layout_680901a1b0001": {
"key": "layout_680901a1b0001",
"name": "collaboration_steps",
"label": "Kroki współpracy",
"display": "block",
"sub_fields": [
{
"key": "field_680901a1b0002",
"label": "Section Heading",
"name": "section_heading",
"aria-label": "",
"type": "text",
"instructions": "Nagłówek sekcji, np. Jak wygląda współpraca?",
"required": 0,
"conditional_logic": 0,
"wrapper": {
"width": "",
"class": "",
"id": ""
},
"default_value": "",
"placeholder": "",
"prepend": "",
"append": "",
"maxlength": "",
"acfe_field_group_condition": 0
},
{
"key": "field_680901a1b0003",
"label": "Steps",
"name": "steps",
"aria-label": "",
"type": "repeater",
"instructions": "Dodaj kroki współpracy (numerowane automatycznie)",
"required": 0,
"conditional_logic": 0,
"wrapper": {
"width": "",
"class": "",
"id": ""
},
"layout": "table",
"pagination": 0,
"min": 0,
"max": 0,
"collapsed": "field_680901a1b0004",
"button_label": "Dodaj krok",
"rows_per_page": 20,
"acfe_field_group_condition": 0,
"sub_fields": [
{
"key": "field_680901a1b0004",
"label": "Step Title",
"name": "step_title",
"aria-label": "",
"type": "text",
"instructions": "",
"required": 0,
"conditional_logic": 0,
"wrapper": {
"width": "",
"class": "",
"id": ""
},
"default_value": "",
"placeholder": "",
"prepend": "",
"append": "",
"maxlength": "",
"acfe_field_group_condition": 0
}
]
},
{
"key": "field_680901a1b0005",
"label": "Bottom Text",
"name": "bottom_text",
"aria-label": "",
"type": "textarea",
"instructions": "Tekst wyświetlany pod krokami",
"required": 0,
"conditional_logic": 0,
"wrapper": {
"width": "",
"class": "",
"id": ""
},
"default_value": "",
"placeholder": "",
"maxlength": "",
"rows": 3,
"new_lines": "",
"acfe_field_group_condition": 0
}
],
"min": "",
"max": "",
"acfe_flexible_render_template": false,
"acfe_flexible_render_style": false,
"acfe_flexible_render_script": false,
"acfe_flexible_thumbnail": false,
"acfe_flexible_settings": false,
"acfe_flexible_settings_size": "medium",
"acfe_layout_locations": [],
"acfe_flexible_modal_edit_size": false,
"acfe_flexible_category": false,
"acfe_layout_col": "auto",
"acfe_layout_allowed_col": false
}
},
"min": "",
@@ -2879,5 +2988,5 @@
"acfe_display_title": "",
"acfe_meta": "",
"acfe_note": "",
"modified": 1700652362
"modified": 1744329600
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,272 @@
<?php
/**
* One-time migration script for page 2707 (Ogrody zimowe - klienci indywidualni)
* Populates ACF Flexible Content fields with hardcoded content.
*
* Usage: Visit /wp-content/themes/ostal_WP/migrate-2707.php?run=migrate-2707
* Or via WP-CLI: wp eval-file wp-content/themes/ostal_WP/migrate-2707.php --run=migrate-2707
*
* ⚠️ DELETE THIS FILE AFTER MIGRATION!
*/
// Bootstrap WordPress
require_once dirname(__FILE__) . '/../../../wp-load.php';
// Safety check: require explicit parameter
if (!isset($_GET['run']) || $_GET['run'] !== 'migrate-2707') {
die('Safety check failed. Use ?run=migrate-2707 to execute.');
}
// Safety check: only admins
if (!current_user_can('manage_options')) {
die('Admin access required. Please log in first.');
}
$page_id = 2707;
// Safety check: don't overwrite existing data
$existing = get_field('sections', $page_id);
if (!empty($existing)) {
die('Page 2707 already has sections data (' . count($existing) . ' layouts). Aborting to prevent overwrite. Delete existing sections first if you want to re-run.');
}
/**
* Helper: find attachment ID by image URL
*/
function get_attachment_id_by_url($url) {
global $wpdb;
$path = parse_url($url, PHP_URL_PATH);
// Remove size suffix (e.g., -1024x576)
$path = preg_replace('/-\d+x\d+(?=\.\w+$)/', '', $path);
$filename = basename($path);
$sql = $wpdb->prepare(
"SELECT ID FROM $wpdb->posts WHERE post_type = 'attachment' AND guid LIKE %s LIMIT 1",
'%' . $wpdb->esc_like($filename) . '%'
);
return (int) $wpdb->get_var($sql);
}
// Build sections array
$sections = [];
// ── Layout 1: Hero with form ──────────────────────────────────────────
$sections[] = [
'acf_fc_layout' => 'hero_with_form',
'section_id' => 'hero_box',
'heading' => 'Całoroczne ogrody zimowe klasy premium',
'text' => '<p class="hero-text text-white m-0">Projektujemy i realizujemy indywidualne ogrody zimowe, które zwiększają komfort domu i pozwalają korzystać z przestrzeni przez cały rok - niezależnie od pogody.</p>
<p class="hero-text text-white m-0"><strong>Izolowane systemy aluminiowe<br>
Szyby Ug=1,1 lub 0,5<br>
Zintegrowane osłony przeciwsłoneczne</strong></p>
<p class="hero-text text-white m-0">Sprawdź orientacyjny budżet projektu<br>
Porozmawiajmy o twoim ogrodzie zimowym.</p>',
'form_shortcode' => '[contact-form-7 id="21a1143" title="Formularz kontaktowy"]',
'background_image' => '/wp-content/uploads/2023/10/ogrody-zimowe.jpg',
];
// ── Layout 2: Two-col — intro ─────────────────────────────────────────
$sections[] = [
'acf_fc_layout' => 'two_col_section',
'section_heading' => 'Nasze ogrody zimowe powstają z myślą o klientach, którzy szukają trwałego,<br>elastycznego i bezpiecznego rozwiązania na lata, a nie tymczasowej zabudowy.',
'text' => '<p>Każda realizacja jest projektowana indywidualnie - z uwzględnieniem architektury budynku, warunków technicznych i sposobu użytkowania.</p>
<p>Realizacje całorocznych ogrodów zimowych rozpoczynają się od około 100 000 zł netto.</p>',
'image' => 'https://ostal.pl/wp-content/uploads/2026/01/IMG_2832-scaled.jpg',
'choose_heading' => 'h2',
'heading_position' => 'textRight',
'additional_class' => 'imageLeft',
'additional_section_class' => 'bg-light',
'additional_wrapper_class' => '',
'cta' => '',
'cta_text' => '',
];
// ── Layout 3: Two-col — cechy wyróżniające ────────────────────────────
$sections[] = [
'acf_fc_layout' => 'two_col_section',
'section_heading' => 'Co wyróżnia nasze ogrody zimowe',
'text' => '<ul style="list-style: none; padding: 0;">
<li>- Komfort użytkowania przez cały rok.</li>
<li>- Stabilna izolowana termicznie konstrukcja aluminiowa.</li>
<li>- Wysokie parametry cieplne przeszkleń (Ug=1,1 - Ug=0,5)</li>
<li>- Ochrona przed słońcem dzięki zintegrowanym markizom i żaluzjom.</li>
<li>- Estetyka dopasowana do architektury budynku</li>
</ul>
<p>Nie pracujemy na gotowych schematach - każdy ogród zimowy powstaje jako spójny element domu, a nie dobudowany „dodatek".</p>',
'image' => 'https://ostal.pl/wp-content/uploads/2026/01/199-f27gxxl.jpg',
'choose_heading' => 'h2',
'heading_position' => 'textRight',
'additional_class' => '',
'additional_section_class' => 'bg-light',
'additional_wrapper_class' => '',
'cta' => '',
'cta_text' => '',
];
// ── Layout 4: Collaboration steps ─────────────────────────────────────
$sections[] = [
'acf_fc_layout' => 'collaboration_steps',
'section_heading' => 'Jak wygląda współpraca?',
'steps' => [
['step_title' => 'Rozmowa i analiza potrzeb.'],
['step_title' => 'Koncepcja i dobór rozwiązań'],
['step_title' => 'Indywidualna oferta i harmonogram'],
['step_title' => 'Umowa i zaliczka rezerwująca termin'],
['step_title' => 'Produkcja i montaż'],
],
'bottom_text' => 'Prowadzimy klienta przez cały proces - spokojnie krok po kroku.',
];
// ── Layout 5: Two-col — doświadczenie ─────────────────────────────────
$sections[] = [
'acf_fc_layout' => 'two_col_section',
'section_heading' => 'Doświadczenie w systemach aluminiowych',
'text' => '<p>Od wielu lat pracujemy na systemach aluminiowych stosowanych zarówno w budownictwie jednorodzinnym, jak i obiektach komercyjnych.</p>
<p>Realizujemy m.in. stolarkę okienną i drzwiową, żaluzje fasadowe, i rolety zewnętrzne, a ogrody zimowe są naturalnym rozszerzeniem tych rozwiązań w tym samym standardzie technicznym i wykonawczym.</p>',
'image' => '/wp-content/uploads/2026/02/att_698c47679eb9b4.14191582.jpeg',
'choose_heading' => 'h2',
'heading_position' => 'textRight',
'additional_class' => 'imageLeft',
'additional_section_class' => 'bg-light',
'additional_wrapper_class' => '',
'cta' => '',
'cta_text' => '',
];
// ── Layout 6: Two-col — planowanie ────────────────────────────────────
$sections[] = [
'acf_fc_layout' => 'two_col_section',
'section_heading' => 'Planowanie realizacji bez pośpiechu',
'text' => '<p>Wielu naszych klientów decyduje się na zaplanowanie ogrodu zimowego z wyprzedzeniem.<br>
Pozwala to spokojnie przygotować projekt i zarezerwować dogodny termin realizacji na wiosnę lub lato.</p>',
'image' => '/wp-content/uploads/2026/02/att_698c4767a04c46.41417006.jpg',
'choose_heading' => 'h2',
'heading_position' => 'textRight',
'additional_class' => 'imageLeft',
'additional_section_class' => 'bg-light',
'additional_wrapper_class' => '',
'cta' => '',
'cta_text' => '',
];
// ── Layout 7: Two-col — kontakt ───────────────────────────────────────
$sections[] = [
'acf_fc_layout' => 'two_col_section',
'section_heading' => 'Porozmawiajmy o twoim projekcie',
'text' => '<p>Jeśli rozważasz budowę całorocznego ogrodu zimowego i chcesz sprawdzić, czy to rozwiązanie ma sens w Twoim przypadku - zapraszamy do kontaktu.</p>',
'image' => '/wp-content/uploads/2026/02/att_698c47679ad0a0.33546122.jpeg',
'choose_heading' => 'h2',
'heading_position' => 'textRight',
'additional_class' => 'imageLeft',
'additional_section_class' => 'bg-light',
'additional_wrapper_class' => '',
'cta' => '',
'cta_text' => '',
];
// ── Layout 8: Two-col with BG — CTA ──────────────────────────────────
$sections[] = [
'acf_fc_layout' => 'two_col_section_with_bg',
'section_heading' => 'Sprawdź orientacyjny budżet projektu',
'text' => '',
'cta' => '#hero_box',
'cta_text' => 'Umów rozmowę',
'background_image' => 'https://ostal.pl/wp-content/uploads/2021/05/hero-about.jpg',
'image' => '',
'heading_position' => '',
'additional_class' => '',
'additional_section_class' => 'bg-dark',
'additional_wrapper_class' => '',
];
// ── Layout 9: Two-col — funkcje ogrodów ───────────────────────────────
$sections[] = [
'acf_fc_layout' => 'two_col_section',
'section_heading' => 'Funkcje ogrodów zimowych',
'text' => '<p>Nowoczesny ogród zimowy to&nbsp;nie&nbsp;tylko&nbsp;dodatkowe pomieszczenie wypoczynkowe pokój zimowy, w&nbsp;którym&nbsp;możesz przyjmować gości lub relaksować się po&nbsp;ciężkim dniu w&nbsp;otoczeniu ulubionych roślin. Przez&nbsp;cały rok i&nbsp;w&nbsp;każdą pogodę. Konstrukcja jaką posiada nowoczesny ogród zimowy:<br>
stanowi efektowne dopełnienie bryły domu, nadając mu&nbsp;nowoczesnego charakteru,<br>
chroni przed&nbsp;hałasem, który&nbsp;dochodzi z&nbsp;zewnątrz,<br>
ze&nbsp;względu na&nbsp;szczelność utrzymuje ciepło i&nbsp;pomaga obniżyć bilans energetyczny domu.</p>',
'image' => 'https://ostal.pl/wp-content/uploads/2023/10/DECORATION-PHOTO-1.jpg',
'choose_heading' => 'h2',
'heading_position' => 'textRight',
'additional_class' => 'imageLeft',
'additional_section_class' => 'bg-light',
'additional_wrapper_class' => '',
'cta' => '',
'cta_text' => '',
];
// ── Layout 10: Gallery ────────────────────────────────────────────────
$gallery_urls = [
'https://ostal.pl/wp-content/uploads/2023/10/202-4c7gxxl.jpg',
'https://ostal.pl/wp-content/uploads/2023/10/199-f27gxxl.jpg',
'https://ostal.pl/wp-content/uploads/2023/10/20170608_142315-1024x576.jpg',
'https://ostal.pl/wp-content/uploads/2023/10/IMG_0535-1-1024x768.jpg',
'https://ostal.pl/wp-content/uploads/2023/10/IMG_3754-1-1-1024x768.jpg',
'https://ostal.pl/wp-content/uploads/2023/10/Frame-36-1-1024x728.jpg',
];
$gallery_ids = [];
$gallery_warnings = [];
foreach ($gallery_urls as $url) {
$id = get_attachment_id_by_url($url);
if ($id > 0) {
$gallery_ids[] = $id;
} else {
$gallery_warnings[] = "Warning: Could not find attachment for: $url";
}
}
$sections[] = [
'acf_fc_layout' => 'gallery',
'section_id' => 'galeria',
'section_heading' => 'Nasze realizacje ogrodów zimowych',
'gallery' => $gallery_ids,
'additional_class' => '',
'additional_section_class' => '',
'additional_wrapper_class' => '',
];
// ── Execute migration ─────────────────────────────────────────────────
$result = update_field('sections', $sections, $page_id);
if ($result) {
echo "<h1 style='color: green;'>Migration successful!</h1>";
echo "<p>Created " . count($sections) . " layouts for page $page_id.</p>";
echo "<ul>";
echo "<li>1. hero_with_form</li>";
echo "<li>2. two_col_section (intro)</li>";
echo "<li>3. two_col_section (cechy)</li>";
echo "<li>4. collaboration_steps (5 kroków)</li>";
echo "<li>5. two_col_section (doświadczenie)</li>";
echo "<li>6. two_col_section (planowanie)</li>";
echo "<li>7. two_col_section (kontakt)</li>";
echo "<li>8. two_col_section_with_bg (CTA)</li>";
echo "<li>9. two_col_section (funkcje)</li>";
echo "<li>10. gallery (" . count($gallery_ids) . " images)</li>";
echo "</ul>";
if (!empty($gallery_warnings)) {
echo "<h3 style='color: orange;'>Gallery warnings:</h3>";
echo "<ul>";
foreach ($gallery_warnings as $w) {
echo "<li>$w</li>";
}
echo "</ul>";
echo "<p>Missing gallery images need to be added manually in WP admin.</p>";
}
echo "<hr>";
echo "<h2 style='color: red;'>⚠️ DELETE THIS FILE NOW!</h2>";
echo "<p>File location: " . __FILE__ . "</p>";
echo "<p><a href='/wp-admin/post.php?post=$page_id&action=edit'>Edit page $page_id in admin</a></p>";
echo "<p><a href='/?page_id=$page_id'>Preview page $page_id</a></p>";
} else {
echo "<h1 style='color: red;'>Migration failed!</h1>";
echo "<p>update_field() returned false. Check that:</p>";
echo "<ul>";
echo "<li>ACF Pro is active</li>";
echo "<li>The 'sections' field group exists and is assigned to page $page_id</li>";
echo "<li>The field group contains all required layouts (hero_with_form, two_col_section, two_col_section_with_bg, collaboration_steps, gallery)</li>";
echo "</ul>";
}

View File

@@ -1,225 +1,3 @@
<?php get_header(); ?>
<?php
$collaboration = [
"Rozmowa i analiza potrzeb.",
"Koncepcja i dobór rozwiązań",
"Indywidualna oferta i harmonogram",
"Umowa i zaliczka rezerwująca termin",
"Produkcja i montaż"
];
?>
<section id="hero_box" class="hero-with-form">
<div class="hero-wrapper wrapper--inner" style="background: url('/wp-content/uploads/2023/10/ogrody-zimowe.jpg');">
<span class="bg-filter"></span>
<div class="hero-content">
<h1 class="hero-heading heading--xl text-white">
Całoroczne ogrody zimowe klasy premium
</h1>
<p class="hero-text text-white m-0">
Projektujemy i realizujemy indywidualne ogrody zimowe, które zwiększają komfort domu i pozwalają korzystać z przestrzeni przez cały rok - niezależnie od pogody.
</p>
<p class="hero-text text-white m-0">
<strong>
Izolowane systemy aluminiowe<br>
Szyby Ug=1,1 lub 0,5<br>
Zintegrowane osłony przeciwsłoneczne
</strong>
</p>
<p class="hero-text text-white m-0">
Sprawdź orientacyjny budżet projektu<br>
Porozmawiajmy o twoim ogrodzie zimowym.
</p>
</div>
<div class="hero-form">
<?php echo do_shortcode('[contact-form-7 id="21a1143" title="Formularz kontaktowy"]'); ?>
</div>
</div>
</section>
<section class="two-cols bg-light">
<div class="wrapper wrapper--inner imageLeft">
<div class="col col-text">
<h2 class="section-heading heading heading--md textRight">
Nasze ogrody zimowe powstają z myślą o klientach, którzy szukają trwałego,<br>
elastycznego i bezpiecznego rozwiązania na lata, a nie tymczasowej zabudowy.
</h2>
<div class="col-text-content">
<p>Każda realizacja jest projektowana indywidualnie - z uwzględnieniem architektury budynku, warunków technicznych i sposobu użytkowania.</p>
<p>Realizacje całorocznych ogrodów zimowych rozpoczynają się od około 100 000 zł netto.</p>
</div>
</div>
<div class="col col-image">
<div class="image-wrapper">
<img src="https://ostal.pl/wp-content/uploads/2026/01/IMG_2832-scaled.jpg" alt="" class="img-auto section-image">
</div>
</div>
</div>
</section>
<section class="two-cols bg-light">
<div class="wrapper wrapper--inner imageLeft">
<div class="col col-image">
<div class="image-wrapper">
<img src="https://ostal.pl/wp-content/uploads/2026/01/199-f27gxxl.jpg" alt="" class="img-auto section-image">
</div>
</div>
<div class="col col-text">
<h2 class="section-heading heading heading--md textRight">Co wyróżnia nasze ogrody zimowe</h2>
<div class="col-text-content">
<ul style="list-style: none; padding: 0;">
<li>- Komfort użytkowania przez cały rok.</li>
<li>- Stabilna izolowana termicznie konstrukcja aluminiowa.</li>
<li>- Wysokie parametry cieplne przeszkleń (Ug=1,1 - Ug=0,5)</li>
<li>- Ochrona przed słońcem dzięki zintegrowanym markizom i żaluzjom.</li>
<li>- Estetyka dopasowana do architektury budynku</li>
</ul>
<p>Nie pracujemy na gotowych schematach - każdy ogród zimowy powstaje jako spójny element domu, a nie dobudowany „dodatek”.</p>
</div>
</div>
</div>
</section>
<section id="collaboration" class="section-boxes-repeater">
<div class="wrapper wrapper--inner">
<h2 class="section-heading heading--md">Jak wygląda współpraca?</h2>
<div class="collaboration-steps" style="max-width: 900px; margin: 0 auto; padding: 20px 0;">
<?php foreach ($collaboration as $index => $item) : ?>
<div class="collaboration-step" style="display: flex; align-items: flex-start; gap: 20px; margin-bottom: <?= ($index < count($collaboration) - 1) ? '40px' : '0' ?>; position: relative;">
<!-- Numer kroku -->
<div class="step-number" style="flex-shrink: 0; width: 60px; height: 60px; background: linear-gradient(135deg, #88b14b 0%, #6a8f3a 100%); color: white; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 24px; font-weight: 700; box-shadow: 0 4px 8px rgba(136, 177, 75, 0.3); position: relative; z-index: 2;">
<?= $index + 1 ?>
</div>
<!-- Linia łącząca (dla wszystkich oprócz ostatniego) -->
<?php if ($index < count($collaboration) - 1) : ?>
<div class="step-connector" style="position: absolute; left: 30px; top: 60px; width: 2px; height: 40px; background: linear-gradient(to bottom, #88b14b, #e0e0e0); z-index: 1;"></div>
<?php endif; ?>
<!-- Treść kroku -->
<div class="step-content" style="flex: 1; background-color: #f8f9fa; padding: 20px 25px; border-radius: 8px; border-left: 4px solid #88b14b; box-shadow: 0 2px 4px rgba(0,0,0,0.05); transition: all 0.3s ease;">
<h3 class="step-title" style="margin: 0; font-size: 18px; font-weight: 600; color: #333; line-height: 1.4;">
<?= $item; ?>
</h3>
</div>
</div>
<?php endforeach; ?>
</div>
<div class="col-text-content mt-4 text-center">
<p>Prowadzimy klienta przez cały proces - spokojnie krok po kroku.</p>
</div>
</div>
</section>
<section class="two-cols bg-light">
<div class="wrapper wrapper--inner imageLeft">
<div class="col col-text">
<h2 class="section-heading heading heading--md textRight">
Doświadczenie w systemach aluminiowych
</h2>
<div class="col-text-content">
<p>Od wielu lat pracujemy na systemach aluminiowych stosowanych zarówno w budownictwie jednorodzinnym, jak i obiektach komercyjnych.</p>
<p>Realizujemy m.in. stolarkę okienną i drzwiową, żaluzje fasadowe, i rolety zewnętrzne, a ogrody zimowe są naturalnym rozszerzeniem tych rozwiązań w tym samym standardzie technicznym i wykonawczym.</p>
</div>
</div>
<div class="col col-image">
<div class="image-wrapper">
<img src="/wp-content/uploads/2026/02/att_698c47679eb9b4.14191582.jpeg" alt="" class="img-auto section-image">
</div>
</div>
</div>
</section>
<section class="two-cols bg-light">
<div class="wrapper wrapper--inner imageLeft">
<div class="col col-image">
<div class="image-wrapper">
<img src="/wp-content/uploads/2026/02/att_698c4767a04c46.41417006.jpg" alt="" class="img-auto section-image">
</div>
</div>
<div class="col col-text">
<h2 class="section-heading heading heading--md textRight">Planowanie realizacji bez pośpiechu</h2>
<div class="col-text-content">
<p>
Wielu naszych klientów decyduje się na zaplanowanie ogrodu zimowego z wyprzedzeniem.<br>
Pozwala to spokojnie przygotować projekt i zarezerwować dogodny termin realizacji na wiosnę lub lato.
</p>
</div>
</div>
</div>
</section>
<section class="two-cols bg-light">
<div class="wrapper wrapper--inner imageLeft">
<div class="col col-text">
<h2 class="section-heading heading heading--md textRight">
Porozmawiajmy o twoim projekcie
</h2>
<div class="col-text-content">
<p>Jeśli rozważasz budowę całorocznego ogrodu zimowego i chcesz sprawdzić, czy to rozwiązanie ma sens w Twoim przypadku - zapraszamy do kontaktu.</p>
</div>
</div>
<div class="col col-image">
<div class="image-wrapper">
<img src="/wp-content/uploads/2026/02/att_698c47679ad0a0.33546122.jpeg" alt="" class="img-auto section-image">
</div>
</div>
</div>
</section>
<section id="garden-page-seo" class="two-cols-with-bg bg-dark" style="background-image: url('https://ostal.pl/wp-content/uploads/2021/05/hero-about.jpg');">
<span class="bg-filter"></span>
<div class="wrapper wrapper--inner">
<h2>Sprawdź orientacyjny budżet projektu</h2>
<a href="#hero_box" class="btn btn-primary">Umów rozmowę</a>
</div>
</section>
<section class="two-cols bg-light">
<div class="wrapper wrapper--inner imageLeft">
<div class="col col-image">
<div class="image-wrapper">
<img src="https://ostal.pl/wp-content/uploads/2023/10/DECORATION-PHOTO-1.jpg" alt="" class="img-auto section-image">
</div>
</div>
<div class="col col-text">
<h2 class="section-heading heading heading--md textRight">Funkcje ogrodów zimowych</h2>
<div class="col-text-content">
<p>Nowoczesny ogród zimowy to&nbsp;nie&nbsp;tylko&nbsp;dodatkowe pomieszczenie wypoczynkowe pokój zimowy, w&nbsp;którym&nbsp;możesz przyjmować gości lub relaksować się po&nbsp;ciężkim dniu w&nbsp;otoczeniu ulubionych roślin. Przez&nbsp;cały rok i&nbsp;w&nbsp;każdą pogodę. Konstrukcja jaką posiada nowoczesny ogród zimowy:<br>
stanowi efektowne dopełnienie bryły domu, nadając mu&nbsp;nowoczesnego charakteru,<br>
chroni przed&nbsp;hałasem, który&nbsp;dochodzi z&nbsp;zewnątrz,<br>
ze&nbsp;względu na&nbsp;szczelność utrzymuje ciepło i&nbsp;pomaga obniżyć bilans energetyczny domu.</p>
</div>
</div>
</div>
</section>
<section id="galeria" class="section-gallery ">
<div class="wrapper wrapper--inner ">
<h2 class="section-heading heading--md text-center">
Nasze realizacje ogrodów zimowych </h2>
<ul id="gallery-lightbox" class="gallery">
<li class="gallery-image">
<img src="https://ostal.pl/wp-content/uploads/2023/10/202-4c7gxxl.jpg" alt="">
</li>
<li class="gallery-image">
<img src="https://ostal.pl/wp-content/uploads/2023/10/199-f27gxxl.jpg" alt="">
</li>
<li class="gallery-image">
<img src="https://ostal.pl/wp-content/uploads/2023/10/20170608_142315-1024x576.jpg" alt="">
</li>
<li class="gallery-image">
<img src="https://ostal.pl/wp-content/uploads/2023/10/IMG_0535-1-1024x768.jpg" alt="">
</li>
<li class="gallery-image">
<img src="https://ostal.pl/wp-content/uploads/2023/10/IMG_3754-1-1-1024x768.jpg" alt="">
</li>
<li class="gallery-image">
<img src="https://ostal.pl/wp-content/uploads/2023/10/Frame-36-1-1024x728.jpg" alt="">
</li>
</ul>
<div id="lightbox" class="lightbox"></div>
</div>
</section>
<?php get_footer(); ?>
<?php include( locate_template( 'sections.php' ) ); ?>
<?php get_footer(); ?>

View File

@@ -24,5 +24,14 @@
<?php if (get_row_layout() == 'faq') : ?>
<?php get_template_part('template-parts/sections/section-faq', 'faq'); ?>
<?php endif; ?>
<?php if (get_row_layout() == 'hero_with_form') : ?>
<?php get_template_part('template-parts/sections/section-hero-with-form', 'hero_with_form'); ?>
<?php endif; ?>
<?php if (get_row_layout() == 'gallery') : ?>
<?php get_template_part('template-parts/sections/section-gallery', 'gallery'); ?>
<?php endif; ?>
<?php if (get_row_layout() == 'collaboration_steps') : ?>
<?php get_template_part('template-parts/sections/section-collaboration-steps', 'collaboration_steps'); ?>
<?php endif; ?>
<?php endwhile; ?>
<?php endif; ?>

View File

@@ -0,0 +1,74 @@
<?php
$steps = get_sub_field('steps');
$total = is_array($steps) ? count($steps) : 0;
?>
<section id="collaboration" class="section-boxes-repeater">
<div class="wrapper wrapper--inner">
<h2 class="section-heading heading--md"><?php the_sub_field('section_heading'); ?></h2>
<?php if ($total > 0) : ?>
<div class="collaboration-steps" style="max-width: 900px; margin: 0 auto; padding: 20px 0;">
<?php $index = 0; ?>
<?php while (have_rows('steps')) : the_row(); ?>
<div class="collaboration-step" style="display: flex; align-items: flex-start; gap: 20px; margin-bottom: <?= ($index < $total - 1) ? '40px' : '0' ?>; position: relative;">
<div class="step-number" style="flex-shrink: 0; width: 60px; height: 60px; background: linear-gradient(135deg, #88b14b 0%, #6a8f3a 100%); color: white; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 24px; font-weight: 700; box-shadow: 0 4px 8px rgba(136, 177, 75, 0.3); position: relative; z-index: 2;">
<?= $index + 1 ?>
</div>
<?php if ($index < $total - 1) : ?>
<div class="step-connector" style="position: absolute; left: 30px; top: 60px; width: 2px; height: 40px; background: linear-gradient(to bottom, #88b14b, #e0e0e0); z-index: 1;"></div>
<?php endif; ?>
<div class="step-content" style="flex: 1; background-color: #f8f9fa; padding: 20px 25px; border-radius: 8px; border-left: 4px solid #88b14b; box-shadow: 0 2px 4px rgba(0,0,0,0.05); transition: all 0.3s ease;">
<h3 class="step-title" style="margin: 0; font-size: 18px; font-weight: 600; color: #333; line-height: 1.4;">
<?php the_sub_field('step_title'); ?>
</h3>
</div>
</div>
<?php $index++; ?>
<?php endwhile; ?>
</div>
<?php endif; ?>
<?php if (get_sub_field('bottom_text')) : ?>
<div class="col-text-content mt-4 text-center">
<p><?php the_sub_field('bottom_text'); ?></p>
</div>
<?php endif; ?>
</div>
</section>
<style>
.collaboration-step:hover .step-content {
transform: translateX(5px);
box-shadow: 0 4px 12px rgba(136, 177, 75, 0.15);
}
.collaboration-step:hover .step-number {
transform: scale(1.1);
}
@media (max-width: 768px) {
.collaboration-step {
gap: 15px !important;
}
.step-number {
width: 50px !important;
height: 50px !important;
font-size: 20px !important;
}
.step-connector {
left: 25px !important;
top: 50px !important;
}
.step-content {
padding: 15px 20px !important;
}
.step-title {
font-size: 16px !important;
}
}
</style>

View File

@@ -10,9 +10,9 @@
<h1 class="hero-heading heading--xl text-white">
<?php the_sub_field('heading'); ?>
</h1>
<p class="hero-text text-white">
<div class="hero-text text-white">
<?php the_sub_field('text'); ?>
</p>
</div>
</div>
<div class="hero-form">
<?php echo do_shortcode($form_shortcode); ?>