-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Griko Nibras <[email protected]>
- Loading branch information
Showing
11 changed files
with
875 additions
and
13 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
import { ArrowLeftIcon, EnvelopeIcon } from "@heroicons/react/20/solid"; | ||
import * as Dialog from "@radix-ui/react-dialog"; | ||
import { clsx } from "clsx"; | ||
import { FormEvent } from "react"; | ||
import toast from "react-hot-toast"; | ||
|
||
import { useDisclosureKey } from "@/context/disclosures"; | ||
|
||
export function ContactDialog() { | ||
const [isOpen, { close }] = useDisclosureKey("contactDialog"); | ||
return ( | ||
<Dialog.Root modal={false} open={isOpen}> | ||
<Dialog.Content className="absolute inset-0 bg-white rounded-3xl animate-fade-zoom-in"> | ||
<form | ||
className={clsx( | ||
"flex flex-col h-full px-4 py-6 text-sm", | ||
"[&_input]:border-neutral-300 [&_input]:rounded-md [&_input]:text-sm", | ||
"[&_textarea]:border-neutral-300 [&_textarea]:rounded-md [&_textarea]:text-sm", | ||
)} | ||
onSubmit={handleSubmit} | ||
> | ||
<div className="flex items-center gap-4 pb-4"> | ||
<button | ||
className="hover:bg-neutral-100 w-8 h-8 rounded-full flex items-center justify-center transition-colors" | ||
onClick={close} | ||
> | ||
<ArrowLeftIcon className="w-6 h-6" /> | ||
</button> | ||
<h3 className="font-bold text-xl">Contact Us</h3> | ||
</div> | ||
<label htmlFor="txHash"> | ||
Transaction Hash <span className="text-red-500">*</span> | ||
</label> | ||
<input | ||
type="text" | ||
id="txHash" | ||
name="txHash" | ||
placeholder="C1CEA71D07932CEE8F4DC691..." | ||
className="form-input rounded mb-2" | ||
required | ||
/> | ||
<label htmlFor="submitChain"> | ||
Submitted Transaction Chain <span className="text-red-500">*</span> | ||
</label> | ||
<input | ||
type="text" | ||
id="submitChain" | ||
name="submitChain" | ||
placeholder="cosmoshub-4" | ||
className="form-input rounded mb-2" | ||
required | ||
/> | ||
<label htmlFor="signerAddress"> | ||
Signer Account Address <span className="text-red-500">*</span> | ||
</label> | ||
<input | ||
type="text" | ||
id="signerAddress" | ||
name="signerAddress" | ||
placeholder="cosmos1kpzxx2lxg05xxn8mf..." | ||
className="form-input rounded mb-2" | ||
required | ||
/> | ||
<div className="grid grid-cols-1 sm:grid-cols-2 sm:gap-4 mb-2"> | ||
<div className="grid grid-flow-row"> | ||
<label htmlFor="Name"> | ||
Name <span className="text-red-500">*</span> | ||
</label> | ||
<input | ||
type="text" | ||
id="name" | ||
name="name" | ||
placeholder="Skippy McSkipper" | ||
className="form-input rounded mb-2" | ||
required | ||
/> | ||
</div> | ||
<div className="grid grid-flow-row"> | ||
<label htmlFor="email"> | ||
Email <span className="text-red-500">*</span> | ||
</label> | ||
<input | ||
type="email" | ||
id="email" | ||
name="email" | ||
placeholder="[email protected]" | ||
className="form-input rounded mb-2" | ||
required | ||
/> | ||
</div> | ||
</div> | ||
|
||
<label htmlFor="message">Describe your issue</label> | ||
<textarea name="message" id="message" className="form-textarea" /> | ||
<div className="flex-grow" /> | ||
<button | ||
type="submit" | ||
className="flex items-center gap-2 bg-[#FF486E] rounded-md font-medium p-2 text-white justify-center text-base" | ||
> | ||
<EnvelopeIcon className="w-5 h-5" /> | ||
<span>Send Message</span> | ||
</button> | ||
</form> | ||
</Dialog.Content> | ||
</Dialog.Root> | ||
); | ||
} | ||
|
||
async function handleSubmit(event: FormEvent<HTMLFormElement>) { | ||
event.preventDefault(); | ||
await toast.promise( | ||
fetch("/api/contact", { | ||
method: "POST", | ||
body: new FormData(event.currentTarget), | ||
}), | ||
{ | ||
loading: "Sending message...", | ||
success: "Message sent!", | ||
error: ( | ||
<p> | ||
<strong>Something went wrong!</strong> | ||
<br /> | ||
Please try again later, or contact us directly at{" "} | ||
<a | ||
href="mailto:[email protected]" | ||
className="text-red-500 hover:underline" | ||
> | ||
[email protected] | ||
</a> | ||
</p> | ||
), | ||
}, | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { ChatBubbleOvalLeftIcon as ContactIcon } from "@heroicons/react/16/solid"; | ||
import { clsx } from "clsx"; | ||
|
||
import { useDisclosureKey } from "@/context/disclosures"; | ||
|
||
export function Footer() { | ||
const [isOpen, { open }] = useDisclosureKey("contactDialog"); | ||
return ( | ||
<footer | ||
className={clsx( | ||
"z-10 pt-8", | ||
"sm:fixed sm:bottom-0 sm:right-4", | ||
// | ||
)} | ||
> | ||
<button | ||
className={clsx( | ||
"group px-4 py-2 flex items-center gap-2 sm:shadow-xl rounded-t-lg", | ||
"bg-white text-[#FF486E] hover:bg-red-50 sm:hover:pb-3 sm:active:pb-2.5", | ||
"transition-[background,padding,transform] ease-[cubic-bezier(0.08,0.82,0.17,1)] duration-500", | ||
"sm:data-[open=true]:translate-y-full sm:data-[open=false]:translate-y-0", | ||
)} | ||
onClick={() => open({ closeAll: true })} | ||
data-open={isOpen} | ||
> | ||
<ContactIcon className="w-4 h-4" /> | ||
<span>Contact Us</span> | ||
</button> | ||
</footer> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import { PageConfig } from "next"; | ||
import { NextRequest } from "next/server"; | ||
import { Resend } from "resend"; | ||
|
||
import { contactFormSchema } from "@/schemas/contact"; | ||
|
||
export const page: PageConfig = { | ||
runtime: "edge", | ||
}; | ||
|
||
if (!process.env.RESEND_API_KEY) { | ||
throw new Error("RESEND_API_KEY is not set"); | ||
} | ||
|
||
const resend = new Resend(process.env.RESEND_API_KEY); | ||
|
||
export default async function handler(req: NextRequest) { | ||
if (req.method !== "POST") { | ||
return new Response(null, { status: 405 }); // Method Not Allowed | ||
} | ||
|
||
const formData = await req.formData(); | ||
const entries = Object.fromEntries(formData.entries()); | ||
const payload = await contactFormSchema.parseAsync(entries); | ||
|
||
const emails = (process.env.CONTACT_FORM_DEST || "[email protected]") | ||
.split(",") | ||
.filter(Boolean); | ||
|
||
const { data, error } = await resend.emails.send({ | ||
from: `${payload.name} <${payload.email}>`, | ||
to: emails, | ||
subject: `ibc.fun issue on ${payload.submitChain}`, | ||
text: `Transaction Hash: ${payload.txHash} | ||
Signer Account Address: ${payload.signerAddress} | ||
Message: ${!payload.message ? "-" : ""} | ||
${payload.message || ""}`, | ||
}); | ||
|
||
if (!data || error) { | ||
console.error(error); | ||
return new Response(null, { status: 500 }); // Internal Server Error | ||
} | ||
|
||
console.log(data); | ||
return new Response(null, { status: 200 }); // OK | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { z } from "zod"; | ||
|
||
export const contactFormSchema = z.object({ | ||
txHash: z.string(), | ||
submitChain: z.string().min(4), | ||
signerAddress: z.string(), | ||
name: z.string(), | ||
email: z.string().email(), | ||
message: z.string().optional(), | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters