implemented step 08 by Gemini

addes 2. step of wizard
This commit is contained in:
2026-06-14 04:47:56 +02:00
parent 0e0670574d
commit aeeaddd3bc
4 changed files with 224 additions and 14 deletions

View File

@ -216,7 +216,7 @@ label {
font-size: 0.875rem;
}
textarea, input[type="text"] {
textarea, input[type="text"], input[type="email"] {
width: 100%;
padding: 0.75rem;
border: 1px solid var(--border-color);
@ -225,12 +225,58 @@ textarea, input[type="text"] {
font-size: 0.875rem;
}
textarea:focus, input[type="text"]:focus {
textarea:focus, input[type="text"]:focus, input[type="email"]:focus {
outline: none;
border-color: var(--primary-color);
box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);
}
.form-section {
margin-bottom: 2.5rem;
}
.form-section h3 {
font-size: 1.125rem;
margin-bottom: 1.25rem;
padding-bottom: 0.5rem;
border-bottom: 1px solid var(--border-color);
}
.form-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem;
}
.form-hint {
font-size: 0.75rem;
color: var(--text-muted);
margin-top: 0.5rem;
}
.checkbox-group {
display: flex;
align-items: flex-start;
gap: 0.75rem;
padding: 1rem;
background-color: #f8fafc;
border-radius: 0.375rem;
border: 1px solid var(--border-color);
}
.checkbox-group input[type="checkbox"] {
margin-top: 0.25rem;
width: 1rem;
height: 1rem;
cursor: pointer;
}
.checkbox-group label {
margin-bottom: 0;
cursor: pointer;
font-weight: 400;
}
button:disabled {
opacity: 0.5;
cursor: not-allowed;

View File

@ -43,9 +43,64 @@
<!-- Step 2: Identita, kontakt a GDPR -->
<div class="step" data-step="2">
<h2>Identita a kontakt</h2>
<p class="step-description">Základné informácie o vašej firme a GDPR súhlas.</p>
<div class="form-placeholder">
<p>Obsah pre krok 2...</p>
<p class="step-description">Základné informácie o vašej firme a povinný GDPR súhlas.</p>
<div class="form-section">
<h3>Identita firmy</h3>
<div class="form-group">
<label for="business-name">Názov firmy / Značky *</label>
<input type="text" id="business-name" placeholder="Napr. Pizza Marco" required>
</div>
<div class="form-group">
<label for="business-tagline">Slogan (voliteľné)</label>
<input type="text" id="business-tagline" placeholder="Napr. Najlepšia pizza v meste">
</div>
<div class="form-group">
<label for="business-description">Stručný popis podnikania</label>
<textarea id="business-description" rows="2" placeholder="Napr. Rodinná pizzeria so zameraním na tradičné recepty."></textarea>
</div>
</div>
<div class="form-section">
<h3>Kontaktné údaje</h3>
<div class="form-grid">
<div class="form-group">
<label for="contact-email">Email</label>
<input type="email" id="contact-email" placeholder="email@priklad.sk">
</div>
<div class="form-group">
<label for="contact-phone">Telefón</label>
<input type="text" id="contact-phone" placeholder="+421 ...">
</div>
</div>
<div class="form-grid">
<div class="form-group">
<label for="contact-address">Adresa (ulica a číslo)</label>
<input type="text" id="contact-address" placeholder="Hlavná 123">
</div>
<div class="form-group">
<label for="contact-city">Mesto</label>
<input type="text" id="contact-city" placeholder="Bratislava">
</div>
</div>
<div class="form-grid">
<div class="form-group">
<label for="contact-facebook">Facebook (URL)</label>
<input type="text" id="contact-facebook" placeholder="https://facebook.com/...">
</div>
<div class="form-group">
<label for="contact-instagram">Instagram (URL)</label>
<input type="text" id="contact-instagram" placeholder="https://instagram.com/...">
</div>
</div>
<p class="form-hint">* Aspoň jeden z údajov (Email / Telefón) je povinný.</p>
</div>
<div class="form-section gdpr-section">
<div class="checkbox-group">
<input type="checkbox" id="gdpr-consent">
<label for="gdpr-consent">Súhlasím so spracovaním zadaných údajov za účelom vytvorenia webovej stránky. *</label>
</div>
</div>
</div>

View File

@ -57,16 +57,36 @@ const App = {
},
syncSelectionWithProject() {
if (this.state.project && this.state.project.wizard_data.business_category) {
const bc = this.state.project.wizard_data.business_category;
this.state.selection.category = bc.group;
this.state.selection.subcategory = bc.subcategory;
this.state.selection.customDescription = bc.custom_description || '';
if (this.state.project && this.state.project.wizard_data) {
const wd = this.state.project.wizard_data;
if (this.state.selection.category) {
this.selectCategory(this.state.selection.category);
this.state.selection.subcategory = bc.subcategory; // restore after selectCategory resets it
this.renderSubcategories(this.state.selection.category);
// Step 1
if (wd.business_category) {
const bc = wd.business_category;
this.state.selection.category = bc.group;
this.state.selection.subcategory = bc.subcategory;
this.state.selection.customDescription = bc.custom_description || '';
if (this.state.selection.category) {
this.selectCategory(this.state.selection.category);
this.state.selection.subcategory = bc.subcategory;
this.renderSubcategories(this.state.selection.category);
}
}
// Step 2
if (wd.identity) {
document.getElementById('business-name').value = wd.identity.business_name || '';
document.getElementById('business-tagline').value = wd.identity.tagline || '';
document.getElementById('business-description').value = wd.identity.description || '';
}
if (wd.contact) {
document.getElementById('contact-email').value = wd.contact.email || '';
document.getElementById('contact-phone').value = wd.contact.phone || '';
document.getElementById('contact-address').value = wd.contact.address || '';
document.getElementById('contact-city').value = wd.contact.city || '';
document.getElementById('contact-facebook').value = wd.contact.socials?.facebook || '';
document.getElementById('contact-instagram').value = wd.contact.socials?.instagram || '';
}
}
},
@ -145,6 +165,15 @@ const App = {
document.getElementById('custom-description').addEventListener('input', (e) => {
this.state.selection.customDescription = e.target.value;
});
// Step 2 validation listeners
['business-name', 'gdpr-consent', 'contact-email', 'contact-phone'].forEach(id => {
const el = document.getElementById(id);
if (el) {
el.addEventListener('input', () => this.updateUI());
el.addEventListener('change', () => this.updateUI());
}
});
},
renderCategories() {
@ -248,6 +277,53 @@ const App = {
alert('Nepodarilo sa uložiť dáta.');
return;
}
} else if (this.state.currentStep === 2) {
const businessName = document.getElementById('business-name').value;
const tagline = document.getElementById('business-tagline').value;
const description = document.getElementById('business-description').value;
const email = document.getElementById('contact-email').value;
const phone = document.getElementById('contact-phone').value;
const address = document.getElementById('contact-address').value;
const city = document.getElementById('contact-city').value;
const gdpr = document.getElementById('gdpr-consent').checked;
if (!businessName || !gdpr || (!email && !phone)) {
alert('Prosím, vyplňte povinné údaje a zaškrtnite GDPR súhlas.');
return;
}
try {
// 1. Save Consent
await this.apiCall('saveConsent', {
consent_text: document.querySelector('label[for="gdpr-consent"]').textContent
});
// 2. Save Step 2
await this.apiCall('saveStep', {
step: 2,
data: {
identity: {
business_name: businessName,
tagline: tagline,
description: description
},
contact: {
email: email,
phone: phone,
address: address,
city: city,
socials: {
facebook: document.getElementById('contact-facebook').value,
instagram: document.getElementById('contact-instagram').value
}
}
}
});
} catch (error) {
console.error('Save step 2 failed:', error);
alert('Nepodarilo sa uložiť dáta: ' + error.message);
return;
}
}
if (this.state.currentStep < this.state.totalSteps) {
@ -267,6 +343,20 @@ const App = {
btnPrev.disabled = this.state.currentStep === 1;
// Validation for Next button
let nextDisabled = false;
if (this.state.currentStep === 1) {
nextDisabled = !this.state.selection.category || !this.state.selection.subcategory;
} else if (this.state.currentStep === 2) {
const name = document.getElementById('business-name').value;
const email = document.getElementById('contact-email').value;
const phone = document.getElementById('contact-phone').value;
const gdpr = document.getElementById('gdpr-consent').checked;
nextDisabled = !name || !gdpr || (!email && !phone);
}
btnNext.disabled = nextDisabled;
if (this.state.currentStep === this.state.totalSteps) {
btnNext.textContent = 'Dokončiť';
} else {

View File

@ -137,6 +137,25 @@ class ProjectActions
$projectData['wizard_data']['business_category'] = $data['business_category'];
break;
case 2:
// Verify GDPR consent
$consentService = new \App\Services\ConsentService();
if (!$consentService->hasConsent($projectId)) {
throw new Exception("GDPR consent is required before saving identity and contact data.", 403);
}
if (empty($data['identity']['business_name'])) {
throw new Exception("Business name is required.", 400);
}
if (empty($data['contact']['email']) && empty($data['contact']['phone'])) {
throw new Exception("Either email or phone is required.", 400);
}
$projectData['wizard_data']['identity'] = $data['identity'];
$projectData['wizard_data']['contact'] = $data['contact'];
break;
// More steps will be added later
}