diff options
| author | Tyler Hoang <tyler@tylerhoang.xyz> | 2026-05-26 00:56:58 -0700 |
|---|---|---|
| committer | Tyler Hoang <tyler@tylerhoang.xyz> | 2026-05-26 00:56:58 -0700 |
| commit | ed4a9b7efaedc2d528df01aa7bef7233cfc1df61 (patch) | |
| tree | 79cf85607058734c30a052e7746a71177dc33495 | |
| parent | 687ba8de403042487de1a126f94500bd10d19392 (diff) | |
contact: wire send button to tylerhoang.xyz/api/contact
adds name + email inputs (api requires them) and POSTs json to the
portfolio's existing contact endpoint. surfaces server errors.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
| -rwxr-xr-x | index.html | 38 |
1 files changed, 31 insertions, 7 deletions
@@ -247,7 +247,9 @@ </div> <div style="margin-top: 14px; padding-top: 10px; border-top: 1px dotted oklch(70% 0.05 220);"> <div style="font-size: 10px; opacity: 0.65; text-transform: uppercase; letter-spacing: 1.5px; margin-bottom: 6px;">— leave a quick note —</div> - <textarea id="gb-msg" placeholder="say hi…" style="width: 100%; min-height: 56px; resize: vertical; padding: 8px 10px; border-radius: 10px; border: 1px solid rgba(120,160,200,0.4); background: rgba(255,255,255,0.7); font: 12px 'Segoe UI', Tahoma, sans-serif; color: oklch(25% 0.05 230); box-sizing: border-box;"></textarea> + <input id="gb-name" placeholder="your name" class="no-drag" style="width: 100%; padding: 7px 10px; margin-bottom: 6px; border-radius: 10px; border: 1px solid rgba(120,160,200,0.4); background: rgba(255,255,255,0.7); font: 12px 'Segoe UI', Tahoma, sans-serif; color: oklch(25% 0.05 230); box-sizing: border-box;" /> + <input id="gb-email" type="email" placeholder="your email" class="no-drag" style="width: 100%; padding: 7px 10px; margin-bottom: 6px; border-radius: 10px; border: 1px solid rgba(120,160,200,0.4); background: rgba(255,255,255,0.7); font: 12px 'Segoe UI', Tahoma, sans-serif; color: oklch(25% 0.05 230); box-sizing: border-box;" /> + <textarea id="gb-msg" placeholder="say hi…" class="no-drag" style="width: 100%; min-height: 56px; resize: vertical; padding: 8px 10px; border-radius: 10px; border: 1px solid rgba(120,160,200,0.4); background: rgba(255,255,255,0.7); font: 12px 'Segoe UI', Tahoma, sans-serif; color: oklch(25% 0.05 230); box-sizing: border-box;"></textarea> <div style="display:flex; justify-content: space-between; align-items: center; margin-top: 6px;"> <span id="gb-status" style="font-size: 10px; opacity: 0.65; font-style: italic;">— takes ~2 days for a reply —</span> <button class="aqua sm no-drag" id="gb-send">send</button> @@ -425,13 +427,35 @@ // guestbook send (fake but cute) const gbBtn = document.getElementById('gb-send'); if (gbBtn) { - gbBtn.addEventListener('click', () => { - const msg = document.getElementById('gb-msg').value.trim(); + gbBtn.addEventListener('click', async () => { + const name = document.getElementById('gb-name').value.trim(); + const email = document.getElementById('gb-email').value.trim(); + const message = document.getElementById('gb-msg').value.trim(); const status = document.getElementById('gb-status'); - if (!msg) { status.textContent = '— type something first —'; return; } - status.textContent = '✓ sent! talk soon'; - document.getElementById('gb-msg').value = ''; - setTimeout(() => { status.textContent = '— takes ~2 days for a reply —'; }, 4000); + if (!name || !email || !message) { status.textContent = '— fill in all three fields —'; return; } + status.textContent = 'sending…'; + gbBtn.disabled = true; + try { + const res = await fetch('https://tylerhoang.xyz/api/contact', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ name, email, message }), + }); + const data = await res.json().catch(() => ({})); + if (res.ok) { + status.textContent = '✓ sent! talk soon'; + document.getElementById('gb-name').value = ''; + document.getElementById('gb-email').value = ''; + document.getElementById('gb-msg').value = ''; + } else { + status.textContent = data.error || '✗ something went wrong'; + } + } catch { + status.textContent = '✗ could not reach server'; + } finally { + gbBtn.disabled = false; + setTimeout(() => { status.textContent = '— takes ~2 days for a reply —'; }, 5000); + } }); } |
