about, contact, blog
This commit is contained in:
127
src/components/contactform.astro
Normal file
127
src/components/contactform.astro
Normal file
@@ -0,0 +1,127 @@
|
||||
---
|
||||
import Button from "./ui/button.astro";
|
||||
---
|
||||
|
||||
<!-- To make this contact form work, create your free access key from https://web3forms.com/
|
||||
Then you will get all form submissions in your email inbox. -->
|
||||
<form
|
||||
action="https://api.web3forms.com/submit"
|
||||
method="POST"
|
||||
id="form"
|
||||
class="needs-validation"
|
||||
novalidate>
|
||||
<input type="hidden" name="access_key" value="YOUR_ACCESS_KEY_HERE" />
|
||||
<!-- Create your free access key from https://web3forms.com/ -->
|
||||
<input type="checkbox" class="hidden" style="display:none" name="botcheck" />
|
||||
<div class="mb-5">
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Full Name"
|
||||
required
|
||||
class="w-full px-4 py-3 border-2 placeholder:text-gray-800 rounded-md outline-none focus:ring-4 border-gray-300 focus:border-gray-600 ring-gray-100"
|
||||
name="name"
|
||||
/>
|
||||
<div class="empty-feedback invalid-feedback text-red-400 text-sm mt-1">
|
||||
Please provide your full name.
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-5">
|
||||
<label for="email_address" class="sr-only">Email Address</label><input
|
||||
id="email_address"
|
||||
type="email"
|
||||
placeholder="Email Address"
|
||||
name="email"
|
||||
required
|
||||
class="w-full px-4 py-3 border-2 placeholder:text-gray-800 rounded-md outline-none focus:ring-4 border-gray-300 focus:border-gray-600 ring-gray-100"
|
||||
/>
|
||||
<div class="empty-feedback text-red-400 text-sm mt-1">
|
||||
Please provide your email address.
|
||||
</div>
|
||||
<div class="invalid-feedback text-red-400 text-sm mt-1">
|
||||
Please provide a valid email address.
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<textarea
|
||||
name="message"
|
||||
required
|
||||
placeholder="Your Message"
|
||||
class="w-full px-4 py-3 border-2 placeholder:text-gray-800 rounded-md outline-none h-36 focus:ring-4 border-gray-300 focus:border-gray-600 ring-gray-100"
|
||||
></textarea>
|
||||
<div class="empty-feedback invalid-feedback text-red-400 text-sm mt-1">
|
||||
Please enter your message.
|
||||
</div>
|
||||
</div>
|
||||
<Button type="submit" size="lg" block>Send Message</Button>
|
||||
<div id="result" class="mt-3 text-center"></div>
|
||||
</form>
|
||||
|
||||
<style>
|
||||
.invalid-feedback,
|
||||
.empty-feedback {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.was-validated :placeholder-shown:invalid ~ .empty-feedback {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.was-validated :not(:placeholder-shown):invalid ~ .invalid-feedback {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.is-invalid,
|
||||
.was-validated :invalid {
|
||||
border-color: #dc3545;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script is:inline>
|
||||
const form = document.getElementById("form");
|
||||
const result = document.getElementById("result");
|
||||
|
||||
form.addEventListener("submit", function (e) {
|
||||
e.preventDefault();
|
||||
form.classList.add("was-validated");
|
||||
if (!form.checkValidity()) {
|
||||
form.querySelectorAll(":invalid")[0].focus();
|
||||
return;
|
||||
}
|
||||
const formData = new FormData(form);
|
||||
const object = Object.fromEntries(formData);
|
||||
const json = JSON.stringify(object);
|
||||
|
||||
result.innerHTML = "Sending...";
|
||||
|
||||
fetch("https://api.web3forms.com/submit", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Accept: "application/json",
|
||||
},
|
||||
body: json,
|
||||
})
|
||||
.then(async (response) => {
|
||||
let json = await response.json();
|
||||
if (response.status == 200) {
|
||||
result.classList.add("text-green-500");
|
||||
result.innerHTML = json.message;
|
||||
} else {
|
||||
console.log(response);
|
||||
result.classList.add("text-red-500");
|
||||
result.innerHTML = json.message;
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
result.innerHTML = "Something went wrong!";
|
||||
})
|
||||
.then(function () {
|
||||
form.reset();
|
||||
form.classList.remove("was-validated");
|
||||
setTimeout(() => {
|
||||
result.style.display = "none";
|
||||
}, 5000);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
12
src/components/sectionhead.astro
Normal file
12
src/components/sectionhead.astro
Normal file
@@ -0,0 +1,12 @@
|
||||
---
|
||||
const { align = "center" } = Astro.props;
|
||||
---
|
||||
|
||||
<div class:list={["mt-16", align === "center" && "text-center"]}>
|
||||
<h1 class="text-4xl lg:text-5xl font-bold lg:tracking-tight">
|
||||
<slot name="title">Title</slot>
|
||||
</h1>
|
||||
<p class="text-lg mt-4 text-slate-600">
|
||||
<slot name="desc">Some description goes here</slot>
|
||||
</p>
|
||||
</div>
|
||||
@@ -1,13 +1,22 @@
|
||||
---
|
||||
interface Props {
|
||||
size?: "md" | "lg";
|
||||
style?: "outline" | "primary" | "inverted";
|
||||
class?: string;
|
||||
[x: string]: any;
|
||||
}
|
||||
|
||||
const {
|
||||
size = "lg",
|
||||
size = "md",
|
||||
style = "primary",
|
||||
block,
|
||||
class: className,
|
||||
...rest
|
||||
} = Astro.props;
|
||||
|
||||
const sizes = {
|
||||
lg: "px-5 py-2.5",
|
||||
md: "px-5 py-2.5",
|
||||
lg: "px-6 py-3",
|
||||
};
|
||||
|
||||
const styles = {
|
||||
@@ -21,6 +30,7 @@ const styles = {
|
||||
{...rest}
|
||||
class:list={[
|
||||
"rounded text-center transition focus-visible:ring-2 ring-offset-2 ring-gray-200",
|
||||
block && "w-full",
|
||||
sizes[size],
|
||||
styles[style],
|
||||
className,
|
||||
|
||||
Reference in New Issue
Block a user