137 lines
3.7 KiB
Vue
137 lines
3.7 KiB
Vue
<script setup lang="ts">
|
|
import { computed, reactive, ref } from "vue";
|
|
import NychInputText from "@/components/design/NychInputText.vue";
|
|
import NychTextarea from "@/components/design/NychTextarea.vue";
|
|
import NychButton from "@/components/design/NychButton.vue";
|
|
import NychMessage from "@/components/design/NychMessage.vue";
|
|
import LaurelDivider from "@/components/design/LaurelDivider.vue";
|
|
import type { ComponentProps } from "@/data/portfolio";
|
|
|
|
const { portfolioData } = defineProps<ComponentProps>();
|
|
|
|
const form = reactive({ name: "", email: "", message: "" });
|
|
const sent = ref(false);
|
|
|
|
const valid = computed(() => Boolean(form.name && form.email && form.message));
|
|
|
|
const socialLinks = computed(() => [
|
|
{ icon: "github", label: "GitHub", href: portfolioData?.social.github },
|
|
{ icon: "linkedin", label: "LinkedIn", href: portfolioData?.social.linkedin },
|
|
{
|
|
icon: "envelope",
|
|
label: portfolioData?.social.email,
|
|
href: `mailto:${portfolioData?.social.email}`,
|
|
},
|
|
]);
|
|
|
|
const send = () => {
|
|
sent.value = true;
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<section id="contact" class="port-section" style="scroll-margin-top: 68px">
|
|
<LaurelDivider style="margin-bottom: 3.5rem" />
|
|
<div class="port-2col" style="gap: 64px">
|
|
<div class="port-contact-form">
|
|
<h2 class="port-title" style="margin-bottom: 0">Get in Touch</h2>
|
|
<NychMessage v-if="sent" severity="success"
|
|
>Offering received. I'll reply before the next dawn.</NychMessage
|
|
>
|
|
<template v-else>
|
|
<div class="port-contact-fields">
|
|
<NychInputText v-model="form.name" placeholder="Your name" />
|
|
<NychInputText v-model="form.email" placeholder="Your email" type="email" />
|
|
<NychTextarea v-model="form.message" placeholder="Your message…" :rows="4" />
|
|
</div>
|
|
<div>
|
|
<NychButton :disabled="!valid" @click="send">
|
|
<template #icon
|
|
><i class="pi pi-send" style="font-size: 12px; margin-right: 8px"
|
|
/></template>
|
|
Send Offering
|
|
</NychButton>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
<div class="port-contact-aside">
|
|
<p class="port-contact-blurb">
|
|
Prefer direct contact? Find me on the platforms below or send a dispatch by post.
|
|
</p>
|
|
<div class="port-contact-links">
|
|
<a
|
|
v-for="link in socialLinks"
|
|
:key="link.icon"
|
|
:href="link.href"
|
|
class="port-contact-link"
|
|
>
|
|
<i :class="`pi pi-${link.icon}`" class="port-contact-link-icon" />
|
|
<span>{{ link.label }}</span>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.port-contact-form {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 18px;
|
|
}
|
|
|
|
.port-contact-fields {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 12px;
|
|
}
|
|
|
|
.port-contact-aside {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 16px;
|
|
justify-content: center;
|
|
}
|
|
|
|
.port-contact-blurb {
|
|
font-family: var(--font-sans);
|
|
color: var(--text-muted);
|
|
line-height: 1.75;
|
|
margin: 0;
|
|
text-wrap: pretty;
|
|
}
|
|
|
|
.port-contact-links {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 12px;
|
|
}
|
|
|
|
.port-contact-link {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 14px;
|
|
color: var(--text-body);
|
|
text-decoration: none;
|
|
font-family: var(--font-sans);
|
|
font-size: 0.93rem;
|
|
padding: 12px 16px;
|
|
background: var(--surface-1);
|
|
border: 1px solid var(--border);
|
|
border-radius: var(--radius-lg);
|
|
transition: border-color 0.2s ease;
|
|
}
|
|
|
|
.port-contact-link:hover {
|
|
border-color: var(--primary);
|
|
}
|
|
|
|
.port-contact-link-icon {
|
|
color: var(--primary);
|
|
font-size: 16px;
|
|
width: 20px;
|
|
text-align: center;
|
|
flex-shrink: 0;
|
|
}
|
|
</style>
|