imlemented step 16 by Gemini
- Template
This commit is contained in:
@ -6,6 +6,8 @@ namespace App\Services;
|
|||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
|
|
||||||
|
require_once __DIR__ . '/../Utils/Helpers.php';
|
||||||
|
|
||||||
class Renderer
|
class Renderer
|
||||||
{
|
{
|
||||||
private FileStorage $storage;
|
private FileStorage $storage;
|
||||||
@ -41,13 +43,27 @@ class Renderer
|
|||||||
$siteCssSource = $this->templatesPath . DIRECTORY_SEPARATOR . 'css' . DIRECTORY_SEPARATOR . 'site.css';
|
$siteCssSource = $this->templatesPath . DIRECTORY_SEPARATOR . 'css' . DIRECTORY_SEPARATOR . 'site.css';
|
||||||
copy($siteCssSource, $assetsDir . DIRECTORY_SEPARATOR . 'site.css');
|
copy($siteCssSource, $assetsDir . DIRECTORY_SEPARATOR . 'site.css');
|
||||||
|
|
||||||
// 3. Render HTML
|
// 3. Render Content Sections
|
||||||
|
$sectionsHtml = '';
|
||||||
|
$selectedSections = $projectData['wizard_data']['modules']['sections'] ?? [];
|
||||||
|
|
||||||
|
foreach ($selectedSections as $sectionId) {
|
||||||
|
try {
|
||||||
|
$sectionsHtml .= $this->renderTemplate("sections/{$sectionId}", [
|
||||||
|
'project' => $projectData
|
||||||
|
]);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
error_log("Renderer: Failed to render section $sectionId: " . $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. Render HTML base template
|
||||||
$html = $this->renderTemplate('base', [
|
$html = $this->renderTemplate('base', [
|
||||||
'project' => $projectData,
|
'project' => $projectData,
|
||||||
'content' => '<!-- Final content sections will go here -->'
|
'content' => $sectionsHtml
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// 4. Save to exports
|
// 5. Save to exports
|
||||||
return file_put_contents($projectExportDir . DIRECTORY_SEPARATOR . 'index.html', $html) !== false;
|
return file_put_contents($projectExportDir . DIRECTORY_SEPARATOR . 'index.html', $html) !== false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -8,13 +8,6 @@ $identity = $project['wizard_data']['identity'] ?? [];
|
|||||||
$contact = $project['wizard_data']['contact'] ?? [];
|
$contact = $project['wizard_data']['contact'] ?? [];
|
||||||
$visuals = $project['wizard_data']['visuals'] ?? [];
|
$visuals = $project['wizard_data']['visuals'] ?? [];
|
||||||
$assets = $project['wizard_data']['assets'] ?? [];
|
$assets = $project['wizard_data']['assets'] ?? [];
|
||||||
|
|
||||||
// Helper function for safe output
|
|
||||||
if (!function_exists('e')) {
|
|
||||||
function e($value) {
|
|
||||||
return htmlspecialchars((string)($value ?? ''), ENT_QUOTES, 'UTF-8');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
?>
|
?>
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="sk">
|
<html lang="sk">
|
||||||
|
|||||||
@ -81,3 +81,104 @@ footer {
|
|||||||
padding: 4rem 0;
|
padding: 4rem 0;
|
||||||
margin-top: 2rem;
|
margin-top: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Section specific */
|
||||||
|
.section-header {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hero */
|
||||||
|
.hero {
|
||||||
|
background-color: #f3f4f6;
|
||||||
|
text-align: center;
|
||||||
|
padding: 8rem 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero h1 {
|
||||||
|
font-size: 3rem;
|
||||||
|
font-weight: 800;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero .subtitle {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
color: #4b5563;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Services */
|
||||||
|
.services-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||||
|
gap: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.service-card {
|
||||||
|
padding: 2rem;
|
||||||
|
border: 1px solid #e5e7eb;
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
transition: transform 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.service-card:hover {
|
||||||
|
transform: translateY(-5px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.price {
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--primary-color);
|
||||||
|
margin-top: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Gallery */
|
||||||
|
.gallery-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gallery-item img {
|
||||||
|
width: 100%;
|
||||||
|
height: 250px;
|
||||||
|
object-fit: cover;
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FAQ */
|
||||||
|
.faq-list {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.faq-item {
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
border-bottom: 1px solid #e5e7eb;
|
||||||
|
padding-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Contact */
|
||||||
|
.contact-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-form .form-group {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-form input, .contact-form textarea {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0.75rem;
|
||||||
|
border: 1px solid #e5e7eb;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.contact-grid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
.hero h1 {
|
||||||
|
font-size: 2rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
16
src/Templates/sections/about.php
Normal file
16
src/Templates/sections/about.php
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @var array $project
|
||||||
|
*/
|
||||||
|
$about = $project['content']['generated']['about'] ?? [];
|
||||||
|
?>
|
||||||
|
<section id="about" class="about">
|
||||||
|
<div class="container">
|
||||||
|
<div class="section-header">
|
||||||
|
<h2><?= e($about['title'] ?? 'O nás') ?></h2>
|
||||||
|
</div>
|
||||||
|
<div class="about-content">
|
||||||
|
<?= nl2br(e($about['text'] ?? $project['wizard_data']['identity']['description'])) ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
51
src/Templates/sections/contact.php
Normal file
51
src/Templates/sections/contact.php
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @var array $project
|
||||||
|
*/
|
||||||
|
$contact = $project['wizard_data']['contact'] ?? [];
|
||||||
|
$formEnabled = $project['wizard_data']['modules']['contact_form']['enabled'] ?? false;
|
||||||
|
?>
|
||||||
|
<section id="contact" class="contact">
|
||||||
|
<div class="container">
|
||||||
|
<div class="section-header">
|
||||||
|
<h2>Kontakt</h2>
|
||||||
|
</div>
|
||||||
|
<div class="contact-grid">
|
||||||
|
<div class="contact-info">
|
||||||
|
<h3>Kde nás nájdete</h3>
|
||||||
|
<p><strong>Adresa:</strong> <?= e($contact['address']) ?>, <?= e($contact['city']) ?></p>
|
||||||
|
<p><strong>Email:</strong> <a href="mailto:<?= e($contact['email']) ?>"><?= e($contact['email']) ?></a></p>
|
||||||
|
<p><strong>Telefón:</strong> <a href="tel:<?= e($contact['phone']) ?>"><?= e($contact['phone']) ?></a></p>
|
||||||
|
|
||||||
|
<?php if (!empty($contact['socials']['facebook']) || !empty($contact['socials']['instagram'])): ?>
|
||||||
|
<div class="socials">
|
||||||
|
<?php if ($contact['socials']['facebook']): ?>
|
||||||
|
<a href="<?= e($contact['socials']['facebook']) ?>" target="_blank" class="social-link">Facebook</a>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php if ($contact['socials']['instagram']): ?>
|
||||||
|
<a href="<?= e($contact['socials']['instagram']) ?>" target="_blank" class="social-link">Instagram</a>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php if ($formEnabled): ?>
|
||||||
|
<div class="contact-form">
|
||||||
|
<h3>Napíšte nám</h3>
|
||||||
|
<form action="ajax.php" method="POST" id="site-contact-form">
|
||||||
|
<div class="form-group">
|
||||||
|
<input type="text" name="name" placeholder="Vaše meno" required>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<input type="email" name="email" placeholder="Váš email" required>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<textarea name="message" placeholder="Vaša správa" rows="4" required></textarea>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary">Odoslať správu</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
21
src/Templates/sections/faq.php
Normal file
21
src/Templates/sections/faq.php
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @var array $project
|
||||||
|
*/
|
||||||
|
$faq = $project['content']['generated']['faq'] ?? [];
|
||||||
|
?>
|
||||||
|
<section id="faq" class="faq">
|
||||||
|
<div class="container">
|
||||||
|
<div class="section-header">
|
||||||
|
<h2>Časté otázky (FAQ)</h2>
|
||||||
|
</div>
|
||||||
|
<div class="faq-list">
|
||||||
|
<?php foreach ($faq as $item): ?>
|
||||||
|
<div class="faq-item">
|
||||||
|
<h3><?= e($item['question']) ?></h3>
|
||||||
|
<p><?= e($item['answer']) ?></p>
|
||||||
|
</div>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
20
src/Templates/sections/gallery.php
Normal file
20
src/Templates/sections/gallery.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @var array $project
|
||||||
|
*/
|
||||||
|
$gallery = $project['wizard_data']['assets']['gallery'] ?? [];
|
||||||
|
?>
|
||||||
|
<section id="gallery" class="gallery">
|
||||||
|
<div class="container">
|
||||||
|
<div class="section-header">
|
||||||
|
<h2>Galéria</h2>
|
||||||
|
</div>
|
||||||
|
<div class="gallery-grid">
|
||||||
|
<?php foreach ($gallery as $imagePath): ?>
|
||||||
|
<div class="gallery-item">
|
||||||
|
<img src="<?= e($imagePath) ?>" alt="Galéria - <?= e($project['wizard_data']['identity']['business_name']) ?>" loading="lazy">
|
||||||
|
</div>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
18
src/Templates/sections/hero.php
Normal file
18
src/Templates/sections/hero.php
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @var array $project
|
||||||
|
*/
|
||||||
|
$hero = $project['content']['generated']['hero'] ?? [];
|
||||||
|
?>
|
||||||
|
<section id="hero" class="hero">
|
||||||
|
<div class="container">
|
||||||
|
<div class="hero-content">
|
||||||
|
<h1><?= e($hero['title'] ?? $project['wizard_data']['identity']['business_name']) ?></h1>
|
||||||
|
<p class="subtitle"><?= e($hero['subtitle'] ?? $project['wizard_data']['identity']['tagline']) ?></p>
|
||||||
|
<div class="hero-actions">
|
||||||
|
<a href="#contact" class="btn btn-primary">Kontaktujte nás</a>
|
||||||
|
<a href="#services" class="btn btn-secondary">Naše služby</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
13
src/Templates/sections/pricing.php
Normal file
13
src/Templates/sections/pricing.php
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @var array $project
|
||||||
|
*/
|
||||||
|
?>
|
||||||
|
<section id="pricing" class="pricing">
|
||||||
|
<div class="container">
|
||||||
|
<div class="section-header">
|
||||||
|
<h2>Cenník</h2>
|
||||||
|
</div>
|
||||||
|
<p>Informácie o cenách našich služieb nájdete v sekcii Služby alebo nás kontaktujte pre individuálnu ponuku.</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
28
src/Templates/sections/services.php
Normal file
28
src/Templates/sections/services.php
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @var array $project
|
||||||
|
*/
|
||||||
|
$services = $project['content']['generated']['services'] ?? [];
|
||||||
|
$pricingNote = $project['wizard_data']['services']['pricing_note'] ?? '';
|
||||||
|
?>
|
||||||
|
<section id="services" class="services">
|
||||||
|
<div class="container">
|
||||||
|
<div class="section-header">
|
||||||
|
<h2>Naše služby</h2>
|
||||||
|
</div>
|
||||||
|
<div class="services-grid">
|
||||||
|
<?php foreach ($services as $service): ?>
|
||||||
|
<article class="service-card">
|
||||||
|
<h3><?= e($service['title']) ?></h3>
|
||||||
|
<p><?= e($service['text']) ?></p>
|
||||||
|
<?php if (!empty($service['price_info'])): ?>
|
||||||
|
<div class="price"><?= e($service['price_info']) ?></div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</article>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</div>
|
||||||
|
<?php if ($pricingNote): ?>
|
||||||
|
<p class="pricing-note"><em><?= e($pricingNote) ?></em></p>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
15
src/Utils/Helpers.php
Normal file
15
src/Utils/Helpers.php
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Global helper functions for templates.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!function_exists('e')) {
|
||||||
|
/**
|
||||||
|
* Securely escapes a value for HTML output.
|
||||||
|
*/
|
||||||
|
function e($value): string
|
||||||
|
{
|
||||||
|
return htmlspecialchars((string)($value ?? ''), ENT_QUOTES, 'UTF-8');
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user