diff --git a/public/css/wizard.css b/public/css/wizard.css index 3c524a5..3a8b207 100644 --- a/public/css/wizard.css +++ b/public/css/wizard.css @@ -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; diff --git a/public/index.html b/public/index.html index 667206c..7dd8cc9 100644 --- a/public/index.html +++ b/public/index.html @@ -43,9 +43,64 @@

Identita a kontakt

-

Základné informácie o vašej firme a GDPR súhlas.

-
-

Obsah pre krok 2...

+

Základné informácie o vašej firme a povinný GDPR súhlas.

+ +
+

Identita firmy

+
+ + +
+
+ + +
+
+ + +
+
+ +
+

Kontaktné údaje

+
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+

* Aspoň jeden z údajov (Email / Telefón) je povinný.

+
+ +
+
+ + +
diff --git a/public/js/wizard.js b/public/js/wizard.js index c324a51..68aa8cf 100644 --- a/public/js/wizard.js +++ b/public/js/wizard.js @@ -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 { diff --git a/src/Actions/ProjectActions.php b/src/Actions/ProjectActions.php index e661f71..c68d1b0 100644 --- a/src/Actions/ProjectActions.php +++ b/src/Actions/ProjectActions.php @@ -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 }