Updated contact form
This commit is contained in:
@@ -1,5 +1,4 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import Icon from '@/components/icon.vue';
|
|
||||||
import {momentum} from '@/services/momentum.service';
|
import {momentum} from '@/services/momentum.service';
|
||||||
import {ref} from 'vue';
|
import {ref} from 'vue';
|
||||||
|
|
||||||
@@ -30,14 +29,6 @@ function validateEmail(email: string) {
|
|||||||
return /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/.test(email);
|
return /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/.test(email);
|
||||||
}
|
}
|
||||||
|
|
||||||
function send(name: string, email: string, subject: string, message: string) {
|
|
||||||
return momentum.email.create({
|
|
||||||
to: ['zaktimson@gmail.com', email],
|
|
||||||
subject: `ZaksCode: ${subject}`,
|
|
||||||
body: `From: ${name} <${email}><br><br>${message}`
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function submit() {
|
function submit() {
|
||||||
disable.value = true;
|
disable.value = true;
|
||||||
const d = data.value;
|
const d = data.value;
|
||||||
@@ -51,7 +42,7 @@ function submit() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if(errors.value.name || errors.value.email || errors.value.subject || errors.value.message) return disable.value = false;
|
if(errors.value.name || errors.value.email || errors.value.subject || errors.value.message) return disable.value = false;
|
||||||
send(d.name, d.email, d.subject, d.message).then(() => {
|
momentum.data.create('Contact', d).then(() => {
|
||||||
done.value = true;
|
done.value = true;
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
@@ -62,43 +53,156 @@ function submit() {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
<div>
|
||||||
|
<!-- Contact Form -->
|
||||||
|
<form class="cf">
|
||||||
<!-- Success Banner -->
|
<!-- Success Banner -->
|
||||||
<div v-if="done" class="alert alert-success">
|
<div v-if="done" class="cf-banner cf-banner--success">
|
||||||
<span>Success! We will be intouch shortly.</span>
|
<i class="fa fa-check-circle"/> Success! We will be in touch shortly.
|
||||||
</div>
|
</div>
|
||||||
<!-- Error Banner -->
|
<!-- Error Banner -->
|
||||||
<div v-if="errors?.banner" class="alert alert-danger">
|
<div v-if="errors?.banner" class="cf-banner cf-banner--error">
|
||||||
Error: {{ (errors as any).banner }}
|
<i class="fa fa-exclamation-circle"/> Error: {{ (errors as any).banner }}
|
||||||
</div>
|
</div>
|
||||||
<!-- Contact Form -->
|
<div class="d-flex flex-c flex-md-r gap-2">
|
||||||
<form>
|
|
||||||
<div class="d-flex flex-column flex-md-row flex-wrap justify-content-between">
|
|
||||||
<!-- Name -->
|
<!-- Name -->
|
||||||
<div class="mb-2 p-0 pe-md-1 p-md-0" style="flex: 1 0 0;">
|
<div class="cf-field">
|
||||||
<div class="input-group">
|
<i class="fa fa-user cf-icon"/>
|
||||||
<span class="input-group-text"><icon name="user"/></span>
|
<input class="cf-input" type="text" placeholder="Name" v-model="data.name" :class="{'cf-input--error': errors?.name}" :disabled="disable" required>
|
||||||
<input class="form-control" type="text" placeholder="Name" v-model="data.name" v-bind:class="{'is-invalid': errors?.name}" :disabled="disable" required>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<!-- Email -->
|
<!-- Email -->
|
||||||
<div class="mb-2 p-0 ps-md-1" style="flex: 1 0 0;">
|
<div class="cf-field">
|
||||||
<div class="input-group">
|
<i class="fa fa-envelope cf-icon"/>
|
||||||
<span class="input-group-text"><icon name="envelope"/></span>
|
<input class="cf-input" type="email" placeholder="Email" v-model="data.email" :class="{'cf-input--error': errors?.email}" :disabled="disable" required>
|
||||||
<input class="form-control" type="email" placeholder="Email" v-model="data.email" v-bind:class="{'is-invalid': errors?.email}" :disabled="disable" required>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- Subject -->
|
<!-- Subject -->
|
||||||
<div class="input-group mb-2">
|
<div class="cf-field mt-2">
|
||||||
<span class="input-group-text"><icon name="book"/></span>
|
<i class="fa fa-book cf-icon"/>
|
||||||
<input class="form-control" type="text" placeholder="Subject" v-model="data.subject" v-bind:class="{'is-invalid': errors?.subject}" :disabled="disable" required>
|
<input class="cf-input" type="text" placeholder="Subject" v-model="data.subject" :class="{'cf-input--error': errors?.subject}" :disabled="disable" required>
|
||||||
</div>
|
</div>
|
||||||
<!-- Message Body -->
|
<!-- Message Body -->
|
||||||
<textarea class="form-control" placeholder="Message" rows="5" v-model="data.message" v-bind:class="{'is-invalid': errors?.message}" :disabled="disable" required></textarea>
|
<textarea class="cf-input cf-textarea mt-2" placeholder="Message" rows="5" v-model="data.message" :class="{'cf-input--error': errors?.message}" :disabled="disable" required></textarea>
|
||||||
<!-- Buttons -->
|
<!-- Buttons -->
|
||||||
<div class="text-end pt-3">
|
<div class="cf-actions">
|
||||||
<button type="button" class="btn rounded-pill ms-3" @click="reset()">Reset</button>
|
<button type="button" class="cf-btn" @click="reset()">Reset</button>
|
||||||
<button type="button" class="btn btn-primary rounded-pill ms-3" @click="submit" :disabled="disable">Send Message</button>
|
<button type="button" class="cf-btn cf-btn--primary" @click="submit" :disabled="disable">
|
||||||
|
<i class="fa fa-paper-plane"/> Send Message
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
/* Fields */
|
||||||
|
.cf-field {
|
||||||
|
flex: 1;
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cf-icon {
|
||||||
|
position: absolute;
|
||||||
|
left: 0.85rem;
|
||||||
|
color: #2c2c2c;
|
||||||
|
opacity: 0.4;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cf-input {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0.65rem 0.85rem 0.65rem 2.25rem;
|
||||||
|
background: #fff;
|
||||||
|
border: 1.5px solid rgba(44, 44, 44, 0.15);
|
||||||
|
border-radius: 0;
|
||||||
|
color: #2c2c2c;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
transition: border-color 0.2s, box-shadow 0.2s;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cf-input::placeholder {
|
||||||
|
color: rgba(44, 44, 44, 0.35);
|
||||||
|
}
|
||||||
|
|
||||||
|
.cf-input:focus {
|
||||||
|
border-color: var(--theme-primary);
|
||||||
|
box-shadow: 0 0 0 3px color-mix(in srgb, var(--theme-primary) 25%, transparent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.cf-input:disabled {
|
||||||
|
opacity: 0.5;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cf-input--error {
|
||||||
|
border-color: #c0392b !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cf-textarea {
|
||||||
|
padding-left: 0.85rem;
|
||||||
|
resize: vertical;
|
||||||
|
min-height: 130px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Banners */
|
||||||
|
.cf-banner {
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cf-banner--success {
|
||||||
|
background: #ecfdea;
|
||||||
|
border-left: 3px solid #55c02b;
|
||||||
|
color: #2c2c2c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cf-banner--error {
|
||||||
|
background: #fdecea;
|
||||||
|
border-left: 3px solid #c0392b;
|
||||||
|
color: #2c2c2c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Buttons */
|
||||||
|
.cf-actions {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 0.75rem;
|
||||||
|
margin-top: .5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cf-btn {
|
||||||
|
padding: 0.6rem 1.4rem;
|
||||||
|
border: 1.5px solid rgba(44, 44, 44, 0.2);
|
||||||
|
border-radius: 0;
|
||||||
|
background: transparent;
|
||||||
|
color: #2c2c2c;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background 0.2s, border-color 0.2s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
filter: brightness(0.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
opacity: 0.55;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cf-btn--primary {
|
||||||
|
position: relative;
|
||||||
|
background: var(--theme-primary);
|
||||||
|
border-color: var(--theme-primary);
|
||||||
|
color: var(--theme-primary-contrast);
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user