diff options
| author | Danilo M. <danix@danix.xyz> | 2026-04-15 15:52:17 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-04-15 15:52:17 +0200 |
| commit | ae9e63e0a6eb54209520222c27fc167f313ea376 (patch) | |
| tree | 9eaa56aa6a84b747876cbba41fd500040d7e3117 | |
| parent | a8fbf11234c612d246840c66467066475d17b6e5 (diff) | |
| download | danixxyz-ae9e63e0a6eb54209520222c27fc167f313ea376.tar.gz danixxyz-ae9e63e0a6eb54209520222c27fc167f313ea376.zip | |
feat: create contact-form shortcode with Alpine.js AJAX
| -rw-r--r-- | themes/danix-xyz-hacker/shortcodes/contact-form.html | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/themes/danix-xyz-hacker/shortcodes/contact-form.html b/themes/danix-xyz-hacker/shortcodes/contact-form.html new file mode 100644 index 0000000..19884aa --- /dev/null +++ b/themes/danix-xyz-hacker/shortcodes/contact-form.html @@ -0,0 +1,114 @@ +{{- $contactFormData := dict -}} + +<form id="contact-form" x-data="contactForm()" @submit.prevent="submitContactForm" class="space-y-6"> + <!-- Name Field --> + <div> + <label for="name" class="block text-sm font-medium text-text mb-2"> + {{ i18n "name" }} + </label> + <input + id="name" + type="text" + x-model="formData.name" + required + class="w-full px-4 py-2 bg-bg border border-border/50 rounded-lg text-text placeholder-text-dim focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent transition-colors" + :aria-busy="isSubmitting" + /> + </div> + + <!-- Email Field --> + <div> + <label for="email" class="block text-sm font-medium text-text mb-2"> + {{ i18n "email" }} + </label> + <input + id="email" + type="email" + x-model="formData.email" + required + class="w-full px-4 py-2 bg-bg border border-border/50 rounded-lg text-text placeholder-text-dim focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent transition-colors" + :aria-busy="isSubmitting" + /> + </div> + + <!-- Message Field --> + <div> + <label for="message" class="block text-sm font-medium text-text mb-2"> + {{ i18n "message" }} + </label> + <textarea + id="message" + x-model="formData.message" + rows="5" + required + class="w-full px-4 py-2 bg-bg border border-border/50 rounded-lg text-text placeholder-text-dim focus:outline-none focus:border-accent focus:ring-1 focus:ring-accent transition-colors resize-none" + :aria-busy="isSubmitting" + ></textarea> + </div> + + <!-- Status Message --> + <div + x-show="statusMessage" + x-text="statusMessage" + :class="statusClass" + class="px-4 py-3 rounded-lg text-sm transition-all" + ></div> + + <!-- Submit Button --> + <button + type="submit" + :disabled="isSubmitting" + class="w-full px-4 py-2 bg-accent text-bg font-medium rounded-lg hover:bg-accent/90 disabled:opacity-50 disabled:cursor-not-allowed transition-colors" + > + <span x-show="!isSubmitting">{{ i18n "submit" }}</span> + <span x-show="isSubmitting">{{ i18n "sending" }}</span> + </button> +</form> + +<script> +document.addEventListener('alpine:init', () => { + Alpine.data('contactForm', () => ({ + formData: { + name: '', + email: '', + message: '' + }, + isSubmitting: false, + statusMessage: '', + statusClass: '', + + async submitContactForm() { + this.isSubmitting = true; + this.statusMessage = ''; + this.statusClass = ''; + + try { + const response = await fetch('/contact.php', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(this.formData) + }); + + const data = await response.json(); + + if (response.ok) { + this.statusMessage = '{{ i18n "form_success" | default "Message sent successfully!" }}'; + this.statusClass = 'bg-green-100 text-green-800 border border-green-300'; + this.formData = { name: '', email: '', message: '' }; + } else { + this.statusMessage = data.error || '{{ i18n "form_error" | default "An error occurred. Please try again." }}'; + this.statusClass = 'bg-red-100 text-red-800 border border-red-300'; + } + } catch (error) { + this.statusMessage = '{{ i18n "form_error" | default "An error occurred. Please try again." }}'; + this.statusClass = 'bg-red-100 text-red-800 border border-red-300'; + console.error('Form submission error:', error); + } finally { + this.isSubmitting = false; + } + } + })); +}); +</script> |
