UI updates

This commit is contained in:
Michael Rausch
2025-10-12 00:58:56 +13:00
parent 237668fd31
commit 1a40e6e718
4 changed files with 151 additions and 35 deletions
+120
View File
@@ -0,0 +1,120 @@
---
// Contact Form Component
---
<div id="form-message" class="hidden mb-4"></div>
<form id="contact-form" class="space-y-6 contact-form-wrapper">
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div class="space-y-2">
<label for="name" class="block text-sm text-black/70 dark:text-white/60">
Name
</label>
<input
type="text"
id="name"
name="name"
required
class="w-full px-4 py-3 rounded-md border border-black/5 dark:border-white/5 bg-transparent text-black dark:text-white placeholder-black/30 dark:placeholder-white/30 focus:outline-none focus:border-black/20 dark:focus:border-white/20 transition-all duration-300"
placeholder="Your name"
/>
</div>
<div class="space-y-2">
<label for="email" class="block text-sm text-black/70 dark:text-white/60">
Email
</label>
<input
type="email"
id="email"
name="email"
required
class="w-full px-4 py-3 rounded-md border border-black/5 dark:border-white/5 bg-transparent text-black dark:text-white placeholder-black/30 dark:placeholder-white/30 focus:outline-none focus:border-black/20 dark:focus:border-white/20 transition-all duration-300"
placeholder="your.email@example.com"
/>
</div>
</div>
<div class="space-y-2">
<label for="message" class="block text-sm text-black/70 dark:text-white/60">
Message
</label>
<textarea
id="message"
name="message"
required
rows="5"
class="w-full px-4 py-3 rounded-md border border-black/5 dark:border-white/5 bg-transparent text-black dark:text-white placeholder-black/30 dark:placeholder-white/30 focus:outline-none focus:border-black/20 dark:focus:border-white/20 transition-all duration-300 resize-none"
placeholder="Your message..."
></textarea>
</div>
<div>
<button
type="submit"
class="px-8 py-3 rounded-md bg-black/90 dark:bg-white/90 text-white dark:text-black font-medium hover:bg-black dark:hover:bg-white focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-black/50 dark:focus:ring-white/50 transition-all duration-300 disabled:opacity-40 disabled:cursor-not-allowed"
>
<span id="button-text">Send Message</span>
</button>
</div>
</form>
<script>
document.addEventListener('DOMContentLoaded', () => {
const form = document.getElementById('contact-form') as HTMLFormElement;
const buttonText = document.getElementById('button-text') as HTMLSpanElement;
const formMessage = document.getElementById('form-message') as HTMLDivElement;
if (form) {
form.addEventListener('submit', async (e) => {
e.preventDefault();
// Get form data
const formData = new FormData(form);
const name = formData.get('name') as string;
const email = formData.get('email') as string;
const message = formData.get('message') as string;
// Disable button and show loading state
const submitButton = form.querySelector('button[type="submit"]') as HTMLButtonElement;
submitButton.disabled = true;
buttonText.textContent = 'Sending...';
formMessage.className = 'hidden';
try {
// Send to API
const response = await fetch('https://notify.api.standard.nz/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
name,
email,
message,
destination: 'michael'
}),
});
if (response.ok) {
// Success
formMessage.textContent = 'Message sent successfully! I\'ll get back to you soon.';
formMessage.className = 'text-sm px-4 py-2.5 rounded-md bg-green-50 dark:bg-green-900/20 text-green-700 dark:text-green-300 border border-green-200 dark:border-green-800/30';
form.style.display = 'none';
} else {
// Error response
throw new Error('Failed to send message');
}
} catch (error) {
// Network or other error
formMessage.textContent = 'Failed to send message. Please try again or email me directly.';
formMessage.className = 'text-sm px-4 py-2.5 rounded-md bg-red-50 dark:bg-red-900/20 text-red-700 dark:text-red-300 border border-red-200 dark:border-red-800/30';
} finally {
// Re-enable button
submitButton.disabled = false;
buttonText.textContent = 'Send Message';
}
});
}
});
</script>
-6
View File
@@ -18,12 +18,6 @@ const isHomepage = Astro.url.pathname === '/';
</Link>
)}
<nav class="flex gap-1">
<Link href="/blog">
blog
</Link>
<span>
{`/`}
</span>
<Link href="/work">
work
</Link>
+1 -1
View File
@@ -2,7 +2,7 @@ import type { Site, Metadata, Socials } from "@types";
export const SITE: Site = {
NAME: "Michael Rausch",
EMAIL: "michael@rausch.nz",
EMAIL: "m@michaelraus.ch",
NUM_POSTS_ON_HOMEPAGE: 3,
NUM_WORKS_ON_HOMEPAGE: 2,
NUM_PROJECTS_ON_HOMEPAGE: 3,
+30 -28
View File
@@ -5,6 +5,7 @@ import PageLayout from "@layouts/PageLayout.astro";
import ArrowCard from "@components/ArrowCard.astro";
import WorkCard from "@components/WorkCard.astro";
import Link from "@components/Link.astro";
import ContactForm from "@components/ContactForm.astro";
import { dateRange } from "@lib/utils";
import { SITE, HOME, SOCIALS } from "@consts";
import EmojiScroller from "@components/EmojiScroller.astro";
@@ -35,13 +36,13 @@ const work = await Promise.all(
<PageLayout title={HOME.TITLE} description={HOME.DESCRIPTION}>
<Container>
<h1 class="animate font-bold text-black dark:text-white text-4xl md:text-5xl font-serif leading-tight">
<h1 class="animate font-bold text-black dark:text-white text-4xl md:text-5xl font-serif leading-tight mb-5">
Hi, I'm Michael <EmojiScroller/>
</h1>
<div class="space-y-16">
<section>
<article class="space-y-4">
<p class="animate">
<p class="animate text-lg">
I'm a software engineer at the University of Canterbury, working on <Link href="https://uconline.ac.nz" external class="text-blue-600 dark:text-blue-400 hover:text-blue-700 dark:hover:text-blue-300">Tuihono UC | UC Online</Link>.
I specialize in full-stack development. While my primary expertise is in software engineering, I also have a strong interest in cloud infrastructure and DevOps. Based in Christchurch, New Zealand
@@ -108,32 +109,33 @@ const work = await Promise.all(
</ul>
</section>
<section class="animate space-y-4">
<h4 class="font-semibold text-black dark:text-white text-xl">
Let's Connect
</h4>
<article>
<p>
If you want to get in touch with me about something or just to say hi,
reach out on social media or send me an email.
</p>
</article>
<ul class="flex flex-wrap gap-2">
{SOCIALS.map(SOCIAL => (
<li class="flex gap-x-2 text-nowrap">
<Link href={SOCIAL.HREF} external aria-label={`${SITE.NAME} on ${SOCIAL.NAME}`}>
{SOCIAL.NAME}
</Link>
{"/"}
</li>
))}
<li class="line-clamp-1">
<Link href={`mailto:${SITE.EMAIL}`} aria-label={`Email ${SITE.NAME}`} confetti>
{SITE.EMAIL}
</Link>
</li>
</ul>
</section>
<section class="animate space-y-4">
<h4 class="font-semibold text-black dark:text-white text-xl">
Let's Connect
</h4>
<article>
<p>
If you want to get in touch with me about something or just to say hi,
reach out on social media or send me an email.
</p>
</article>
<ContactForm />
<ul class="flex flex-wrap gap-2 pt-5">
{SOCIALS.map(SOCIAL => (
<li class="flex gap-x-2 text-nowrap">
<Link href={SOCIAL.HREF} external aria-label={`${SITE.NAME} on ${SOCIAL.NAME}`}>
{SOCIAL.NAME}
</Link>
{"/"}
</li>
))}
<li class="line-clamp-1">
<Link href={`mailto:${SITE.EMAIL}`} aria-label={`Email ${SITE.NAME}`} confetti>
{SITE.EMAIL}
</Link>
</li>
</ul>
</section>
</div>
</Container>
</PageLayout>