@indirecttek/essentials-engine 1.1.3 → 1.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -16,7 +16,20 @@ const { config } = Astro.props;
16
16
  <p class="text-center text-[color:var(--color-foreground)] opacity-80 mb-8 md:mb-12">
17
17
  Get in touch with {config.businessName} today
18
18
  </p>
19
- <form class="space-y-6">
19
+
20
+ <!-- Success Message (hidden by default) -->
21
+ <div id="contact-success" class="hidden bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded-md mb-6">
22
+ <p class="font-medium">Message sent successfully!</p>
23
+ <p class="text-sm">We'll get back to you within 24 hours.</p>
24
+ </div>
25
+
26
+ <!-- Error Message (hidden by default) -->
27
+ <div id="contact-error" class="hidden bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded-md mb-6">
28
+ <p class="font-medium">Something went wrong</p>
29
+ <p class="text-sm" id="contact-error-message">Please try again or contact us directly.</p>
30
+ </div>
31
+
32
+ <form id="contact-form" class="space-y-6">
20
33
  <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
21
34
  <div>
22
35
  <label
@@ -84,9 +97,11 @@ const { config } = Astro.props;
84
97
  </div>
85
98
  <button
86
99
  type="submit"
87
- class="w-full bg-[color:var(--color-primary)] text-[color:var(--color-background)] py-3 md:py-4 rounded-md font-semibold text-lg hover:opacity-90 transition-opacity"
100
+ id="contact-submit"
101
+ class="w-full bg-[color:var(--color-primary)] text-[color:var(--color-background)] py-3 md:py-4 rounded-md font-semibold text-lg hover:opacity-90 transition-opacity disabled:opacity-50 disabled:cursor-not-allowed"
88
102
  >
89
- Send Message
103
+ <span id="submit-text">Send Message</span>
104
+ <span id="submit-loading" class="hidden">Sending...</span>
90
105
  </button>
91
106
  </form>
92
107
  <div class="mt-12 text-center space-y-2 text-[color:var(--color-foreground)] opacity-80">
@@ -104,3 +119,70 @@ const { config } = Astro.props;
104
119
  </div>
105
120
  </div>
106
121
  </section>
122
+
123
+ <script>
124
+ const form = document.getElementById('contact-form') as HTMLFormElement;
125
+ const submitBtn = document.getElementById('contact-submit') as HTMLButtonElement;
126
+ const submitText = document.getElementById('submit-text') as HTMLSpanElement;
127
+ const submitLoading = document.getElementById('submit-loading') as HTMLSpanElement;
128
+ const successMsg = document.getElementById('contact-success') as HTMLDivElement;
129
+ const errorMsg = document.getElementById('contact-error') as HTMLDivElement;
130
+ const errorText = document.getElementById('contact-error-message') as HTMLParagraphElement;
131
+
132
+ form?.addEventListener('submit', async (e) => {
133
+ e.preventDefault();
134
+
135
+ // Hide any previous messages
136
+ successMsg.classList.add('hidden');
137
+ errorMsg.classList.add('hidden');
138
+
139
+ // Show loading state
140
+ submitBtn.disabled = true;
141
+ submitText.classList.add('hidden');
142
+ submitLoading.classList.remove('hidden');
143
+
144
+ const formData = new FormData(form);
145
+ const data = {
146
+ name: formData.get('name'),
147
+ email: formData.get('email'),
148
+ phone: formData.get('phone') || undefined,
149
+ message: formData.get('message'),
150
+ };
151
+
152
+ try {
153
+ const response = await fetch('/api/contact', {
154
+ method: 'POST',
155
+ headers: {
156
+ 'Content-Type': 'application/json',
157
+ },
158
+ body: JSON.stringify(data),
159
+ });
160
+
161
+ const result = await response.json();
162
+
163
+ if (result.success) {
164
+ // Show success message
165
+ successMsg.classList.remove('hidden');
166
+ form.reset();
167
+
168
+ // Scroll to success message
169
+ successMsg.scrollIntoView({ behavior: 'smooth', block: 'center' });
170
+ } else {
171
+ // Show error message
172
+ errorText.textContent = result.error || 'Please try again or contact us directly.';
173
+ errorMsg.classList.remove('hidden');
174
+ errorMsg.scrollIntoView({ behavior: 'smooth', block: 'center' });
175
+ }
176
+ } catch (error) {
177
+ // Show generic error
178
+ errorText.textContent = 'Network error. Please check your connection and try again.';
179
+ errorMsg.classList.remove('hidden');
180
+ errorMsg.scrollIntoView({ behavior: 'smooth', block: 'center' });
181
+ } finally {
182
+ // Reset button state
183
+ submitBtn.disabled = false;
184
+ submitText.classList.remove('hidden');
185
+ submitLoading.classList.add('hidden');
186
+ }
187
+ });
188
+ </script>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@indirecttek/essentials-engine",
3
- "version": "1.1.3",
3
+ "version": "1.1.4",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/types.d.ts",