2dd0922a63
Removed 34 lines of JavaScript (IIFE, MutationObserver, DOMContentLoaded) and replaced with 2 lines of hyperscript in the existing 'on show' handler.
165 lines
7.5 KiB
HTML
165 lines
7.5 KiB
HTML
{{define "contact-modal"}}
|
|
<!-- Contact Form Modal - Native Dialog -->
|
|
<dialog id="contact-modal" class="info-modal no-print"
|
|
_="on click call closeOnBackdrop(me, event)
|
|
on show
|
|
-- Reset form state when modal opens
|
|
set form to getElementById('contact-form')
|
|
if form
|
|
call form.reset()
|
|
set formFields to querySelectorAll('.form-group') in form
|
|
repeat for field in formFields
|
|
remove .hidden from field
|
|
end
|
|
remove .hidden from querySelector('.form-actions') in form
|
|
remove .hidden from querySelector('.form-note') in form
|
|
set responseDiv to getElementById('contact-response')
|
|
if responseDiv set responseDiv.innerHTML to ''
|
|
end
|
|
-- Set timestamp for bot protection
|
|
set tsField to getElementById('contact-form-loaded-at')
|
|
if tsField set tsField.value to Date.now()">
|
|
<div class="info-modal-content">
|
|
<button class="info-modal-close" commandfor="contact-modal" command="close" aria-label="{{.UI.ContactModal.Close}}">
|
|
<iconify-icon icon="mdi:close" width="24" height="24"></iconify-icon>
|
|
</button>
|
|
|
|
<div class="info-modal-header">
|
|
<h2>{{.UI.ContactModal.Title}}</h2>
|
|
<div class="info-modal-cv-title">
|
|
<iconify-icon icon="mdi:email-outline" width="32" height="32"></iconify-icon>
|
|
{{.UI.ContactModal.Subtitle}}
|
|
</div>
|
|
</div>
|
|
|
|
<div class="info-modal-body">
|
|
<p class="contact-modal-description">
|
|
{{.UI.ContactModal.Description}}
|
|
</p>
|
|
|
|
<form id="contact-form"
|
|
hx-post="/api/contact?lang={{.Lang}}"
|
|
hx-target="#contact-response"
|
|
hx-swap="innerHTML"
|
|
hx-indicator="#contact-spinner"
|
|
hx-headers='{"X-Requested-With": "XMLHttpRequest"}'
|
|
_="on htmx:afterRequest
|
|
-- Check if response contains success message (not validation error)
|
|
set responseDiv to document.getElementById('contact-response')
|
|
if responseDiv is not null and responseDiv.querySelector('.contact-success') is not null
|
|
-- Hide all form fields and show only success message
|
|
set formFields to me.querySelectorAll('.form-group')
|
|
repeat for field in formFields
|
|
add .hidden to field
|
|
end
|
|
add .hidden to me.querySelector('.form-actions')
|
|
add .hidden to me.querySelector('.form-note')
|
|
-- Close modal after 3 seconds
|
|
wait 3s then call document.getElementById('contact-modal').close()
|
|
end">
|
|
|
|
<!-- Honeypot field - hidden, should be empty -->
|
|
<div style="position: absolute; left: -9999px;" aria-hidden="true">
|
|
<label for="contact-website">Website</label>
|
|
<input type="text"
|
|
name="website"
|
|
id="contact-website"
|
|
tabindex="-1"
|
|
autocomplete="off">
|
|
</div>
|
|
|
|
<!-- Timing field - set via JavaScript on page load -->
|
|
<input type="hidden" name="form_loaded_at" id="contact-form-loaded-at">
|
|
|
|
<!-- Email (required) -->
|
|
<div class="form-group">
|
|
<label for="contact-email" class="form-label">
|
|
{{.UI.ContactModal.Form.Email}} <span class="required-indicator">*</span>
|
|
</label>
|
|
<input type="email"
|
|
id="contact-email"
|
|
name="email"
|
|
class="form-input"
|
|
required
|
|
autocomplete="email"
|
|
placeholder="{{.UI.ContactModal.Form.EmailPlaceholder}}"
|
|
aria-required="true">
|
|
</div>
|
|
|
|
<!-- Name (optional) -->
|
|
<div class="form-group">
|
|
<label for="contact-name" class="form-label">
|
|
{{.UI.ContactModal.Form.Name}}
|
|
</label>
|
|
<input type="text"
|
|
id="contact-name"
|
|
name="name"
|
|
class="form-input"
|
|
autocomplete="name"
|
|
placeholder="{{.UI.ContactModal.Form.NamePlaceholder}}">
|
|
</div>
|
|
|
|
<!-- Company (optional) -->
|
|
<div class="form-group">
|
|
<label for="contact-company" class="form-label">
|
|
{{.UI.ContactModal.Form.Company}}
|
|
</label>
|
|
<input type="text"
|
|
id="contact-company"
|
|
name="company"
|
|
class="form-input"
|
|
autocomplete="organization"
|
|
placeholder="{{.UI.ContactModal.Form.CompanyPlaceholder}}">
|
|
</div>
|
|
|
|
<!-- Subject (optional) -->
|
|
<div class="form-group">
|
|
<label for="contact-subject" class="form-label">
|
|
{{.UI.ContactModal.Form.Subject}}
|
|
</label>
|
|
<input type="text"
|
|
id="contact-subject"
|
|
name="subject"
|
|
class="form-input"
|
|
placeholder="{{.UI.ContactModal.Form.SubjectPlaceholder}}">
|
|
</div>
|
|
|
|
<!-- Message (required) -->
|
|
<div class="form-group">
|
|
<label for="contact-message" class="form-label">
|
|
{{.UI.ContactModal.Form.Message}} <span class="required-indicator">*</span>
|
|
</label>
|
|
<textarea id="contact-message"
|
|
name="message"
|
|
class="form-textarea"
|
|
required
|
|
rows="5"
|
|
placeholder="{{.UI.ContactModal.Form.MessagePlaceholder}}"
|
|
aria-required="true"></textarea>
|
|
</div>
|
|
|
|
<!-- Response area for success/error messages -->
|
|
<div id="contact-response" class="contact-response" role="status" aria-live="polite"></div>
|
|
|
|
<!-- Submit button with loading indicator -->
|
|
<div class="form-actions">
|
|
<button type="submit" class="contact-submit-btn">
|
|
<iconify-icon icon="mdi:send" width="20" height="20"></iconify-icon>
|
|
<span>{{.UI.ContactModal.Form.Submit}}</span>
|
|
<iconify-icon id="contact-spinner"
|
|
icon="mdi:loading"
|
|
class="htmx-indicator spinning"
|
|
width="20"
|
|
height="20"
|
|
aria-label="{{.UI.ContactModal.Form.Sending}}"></iconify-icon>
|
|
</button>
|
|
</div>
|
|
|
|
<p class="form-note">{{.UI.ContactModal.Form.Note}}</p>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</dialog>
|
|
|
|
{{end}}
|