Skip to content

Commit 6d61751

Browse files
committed
✨ feat[contact]: integrate EmailJS for contact form submissions
Refactored ContactForm component to handle form submission logic with EmailJS integration, eliminating the need for separate API handlers. The component now includes built-in response handling and a complete UI.
1 parent 1f990a9 commit 6d61751

File tree

1 file changed

+114
-56
lines changed

1 file changed

+114
-56
lines changed

src/components/Kontakt/ContactForm.component.tsx

Lines changed: 114 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,32 @@
11
"use client";
22

3-
import React from "react";
3+
import React, { useState } from "react";
44
import { useForm } from "react-hook-form";
55
import { zodResolver } from "@hookform/resolvers/zod";
6+
import emailjs from "@emailjs/browser";
67

8+
import PageHeader from "@/components/UI/PageHeader.component";
79
import Button from "@/components/UI/Button.component";
810
import InputField from "@/components/UI/InputField.component";
911
import { formSchema, FormData } from "./config/formConfig";
1012

1113
interface ContactFormProps {
12-
onSubmit: (data: FormData) => Promise<void>;
1314
csrfToken?: string;
15+
onSubmit?: (data: FormData) => Promise<string>;
16+
initialResponse?: string;
1417
}
1518

1619
/**
17-
* A simplified contact form component that directly uses the form schema
18-
* without complex generic abstractions.
20+
* ContactForm component - A complete contact form with EmailJS integration
21+
* Handles both the form UI and submission logic in a single, clear component
1922
*/
20-
const ContactForm: React.FC<ContactFormProps> = ({ onSubmit, csrfToken }) => {
23+
const ContactForm: React.FC<ContactFormProps> = ({
24+
csrfToken = "",
25+
onSubmit: onSubmitProp,
26+
initialResponse = "",
27+
}) => {
28+
const [serverResponse, setServerResponse] = useState<string>(initialResponse);
29+
2130
const {
2231
register,
2332
handleSubmit,
@@ -26,63 +35,112 @@ const ContactForm: React.FC<ContactFormProps> = ({ onSubmit, csrfToken }) => {
2635
resolver: zodResolver(formSchema),
2736
});
2837

38+
/**
39+
* Default form submission handler using EmailJS.
40+
* @param {FormData} data - The form data.
41+
* @return {Promise<string>} A promise that resolves to a success or error message.
42+
*/
43+
const defaultOnSubmit = async (data: FormData): Promise<string> => {
44+
const EMAIL_API_KEY = process.env.NEXT_PUBLIC_EMAIL_API_KEY ?? "changeme";
45+
const TEMPLATE_KEY =
46+
process.env.NEXT_PUBLIC_EMAIL_TEMPLATE_KEY ?? "changeme";
47+
const SERVICE_KEY = process.env.NEXT_PUBLIC_EMAIL_SERVICE_KEY ?? "changeme";
48+
49+
try {
50+
emailjs.init(EMAIL_API_KEY);
51+
await emailjs.send(SERVICE_KEY, TEMPLATE_KEY, data);
52+
return "Takk for din beskjed";
53+
} catch {
54+
return "Feil under sending av skjema";
55+
}
56+
};
57+
58+
const handleFormSubmit = async (data: FormData): Promise<void> => {
59+
const submitHandler = onSubmitProp ?? defaultOnSubmit;
60+
const message = await submitHandler(data);
61+
setServerResponse(message);
62+
};
63+
2964
return (
30-
<form
31-
id="contact-form"
32-
className="text-center"
33-
onSubmit={handleSubmit(onSubmit)}
34-
method="POST"
35-
action="/api/form"
36-
aria-label="Contact Form"
37-
>
38-
{csrfToken && <input type="hidden" name="_csrf" value={csrfToken} />}
39-
<fieldset>
40-
<legend className="text-center mx-auto text-xl mt-4 sr-only">
41-
Kontaktskjema
42-
</legend>
65+
<main data-testid="kontaktcontent" id="maincontent">
66+
<div className="mt-32 bg-graybg">
67+
<PageHeader>Kontakt</PageHeader>
68+
<div className="px-4 lg:px-0 xl:px-0 md:px-0">
69+
<div className="container mx-auto bg-slate-700 rounded-sm shadow-sm sm:mb-4">
70+
<div className="p-4 mx-auto md:h-full mt-4 flex flex-col justify-center items-center min-h-[470px]">
71+
<div className="p-2 md:p-6 pt-8">
72+
{serverResponse ? (
73+
<h3 className="m-2 h-32 text-xl text-center text-gray-300">
74+
{serverResponse}
75+
</h3>
76+
) : (
77+
<div className="bg-gray-800 p-4 md:p-6 rounded-lg pt-8">
78+
<form
79+
id="contact-form"
80+
className="text-center"
81+
onSubmit={handleSubmit(handleFormSubmit)}
82+
method="POST"
83+
action="/api/form"
84+
aria-label="Contact Form"
85+
>
86+
{csrfToken && (
87+
<input type="hidden" name="_csrf" value={csrfToken} />
88+
)}
89+
<fieldset>
90+
<legend className="text-center mx-auto text-xl mt-4 sr-only">
91+
Kontaktskjema
92+
</legend>
4393

44-
<InputField<FormData>
45-
name="navn"
46-
label="Fullt navn"
47-
htmlFor="navn"
48-
register={register}
49-
error={errors.navn?.message}
50-
isRequired
51-
inputPattern={/^[a-zA-ZæøåÆØÅ ]+$/}
52-
title="Vennligst bruk norske bokstaver"
53-
/>
54-
<br />
94+
<InputField<FormData>
95+
name="navn"
96+
label="Fullt navn"
97+
htmlFor="navn"
98+
register={register}
99+
error={errors.navn?.message}
100+
isRequired
101+
inputPattern={/^[a-zA-ZæøåÆØÅ ]+$/}
102+
title="Vennligst bruk norske bokstaver"
103+
/>
104+
<br />
55105

56-
<InputField<FormData>
57-
name="telefon"
58-
label="Telefonnummer"
59-
htmlFor="telefon"
60-
register={register}
61-
error={errors.telefon?.message}
62-
isRequired
63-
inputPattern={/^\d{8}$/}
64-
title="Vennligst oppgi et gyldig telefonnummer"
65-
/>
66-
<br />
106+
<InputField<FormData>
107+
name="telefon"
108+
label="Telefonnummer"
109+
htmlFor="telefon"
110+
register={register}
111+
error={errors.telefon?.message}
112+
isRequired
113+
inputPattern={/^\d{8}$/}
114+
title="Vennligst oppgi et gyldig telefonnummer"
115+
/>
116+
<br />
67117

68-
<InputField<FormData>
69-
name="tekst"
70-
label="Hva ønsker du å si?"
71-
htmlFor="tekst"
72-
register={register}
73-
error={errors.tekst?.message}
74-
isRequired
75-
type="textarea"
76-
/>
77-
<br />
78-
</fieldset>
118+
<InputField<FormData>
119+
name="tekst"
120+
label="Hva ønsker du å si?"
121+
htmlFor="tekst"
122+
register={register}
123+
error={errors.tekst?.message}
124+
isRequired
125+
type="textarea"
126+
/>
127+
<br />
128+
</fieldset>
79129

80-
<div className="-mt-4">
81-
<Button disabled={isSubmitting} data-testid="submit-button">
82-
Send skjema
83-
</Button>
130+
<div className="-mt-4">
131+
<Button disabled={isSubmitting} data-testid="submit-button">
132+
Send skjema
133+
</Button>
134+
</div>
135+
</form>
136+
</div>
137+
)}
138+
</div>
139+
</div>
140+
</div>
141+
</div>
84142
</div>
85-
</form>
143+
</main>
86144
);
87145
};
88146

0 commit comments

Comments
 (0)