-
-
Notifications
You must be signed in to change notification settings - Fork 132
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: add and setup form * feat: add daisyui classes and logic * feat: refactor form code * feat: add contact links to footer and nav * feat: add form error types * feat: add animations * feat: add successful submission notification * feat: code cleanup * feat: add form submission error notification * feat: finishing up * feat: modify notifcation logic * feat:remove console.log Co-authored-by: Joseph Maramba <[email protected]>
- Loading branch information
1 parent
0a57e13
commit bd5360c
Showing
8 changed files
with
273 additions
and
0 deletions.
There are no files selected for viewing
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,78 @@ | ||
/* ---------------------------------------------- | ||
* Generated by Animista on 2022-8-20 10:9:37 | ||
* Licensed under FreeBSD License. | ||
* See http://animista.net/license for more info. | ||
* w: http://animista.net, t: @cssanimista | ||
* ---------------------------------------------- */ | ||
|
||
.slide-in-fwd-left { | ||
-webkit-animation: slide-in-fwd-left 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94) | ||
both; | ||
animation: slide-in-fwd-left 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94) both; | ||
} | ||
|
||
.tracking-in-expand-fwd { | ||
-webkit-animation: tracking-in-expand-fwd 0.8s | ||
cubic-bezier(0.215, 0.61, 0.355, 1) both; | ||
animation: tracking-in-expand-fwd 0.8s cubic-bezier(0.215, 0.61, 0.355, 1) | ||
both; | ||
} | ||
|
||
@-webkit-keyframes slide-in-fwd-left { | ||
0% { | ||
-webkit-transform: translateZ(-1400px) translateX(-1000px); | ||
transform: translateZ(-1400px) translateX(-1000px); | ||
opacity: 0; | ||
} | ||
100% { | ||
-webkit-transform: translateZ(0) translateX(0); | ||
transform: translateZ(0) translateX(0); | ||
opacity: 1; | ||
} | ||
} | ||
@keyframes slide-in-fwd-left { | ||
0% { | ||
-webkit-transform: translateZ(-1400px) translateX(-1000px); | ||
transform: translateZ(-1400px) translateX(-1000px); | ||
opacity: 0; | ||
} | ||
100% { | ||
-webkit-transform: translateZ(0) translateX(0); | ||
transform: translateZ(0) translateX(0); | ||
opacity: 1; | ||
} | ||
} | ||
|
||
@-webkit-keyframes tracking-in-expand-fwd { | ||
0% { | ||
letter-spacing: -0.5em; | ||
-webkit-transform: translateZ(-700px); | ||
transform: translateZ(-700px); | ||
opacity: 0; | ||
} | ||
40% { | ||
opacity: 0.6; | ||
} | ||
100% { | ||
-webkit-transform: translateZ(0); | ||
transform: translateZ(0); | ||
opacity: 1; | ||
} | ||
} | ||
|
||
@keyframes tracking-in-expand-fwd { | ||
0% { | ||
letter-spacing: -0.5em; | ||
-webkit-transform: translateZ(-700px); | ||
transform: translateZ(-700px); | ||
opacity: 0; | ||
} | ||
40% { | ||
opacity: 0.6; | ||
} | ||
100% { | ||
-webkit-transform: translateZ(0); | ||
transform: translateZ(0); | ||
opacity: 1; | ||
} | ||
} |
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,104 @@ | ||
import { PawHubContainer } from "components/layout/Grid/PetCardFlex"; | ||
import { SubmitHandler, useForm } from "react-hook-form"; | ||
import { ToastContainer, toast } from "react-toastify"; | ||
import "react-toastify/dist/ReactToastify.css"; | ||
|
||
import "./Contact.css"; | ||
import { EmailInput, MessageInput, NameInput } from "./Inputs"; | ||
|
||
export interface FormData { | ||
names: string; | ||
email: string; | ||
message: string; | ||
} | ||
|
||
const Contact = () => { | ||
const { | ||
register, | ||
handleSubmit, | ||
reset, | ||
formState: { errors }, | ||
} = useForm<FormData>(); | ||
|
||
const onSubmit: SubmitHandler<FormData> = (data) => { | ||
// TODO: tie the success/error notification to the respective submission states | ||
if (data) { | ||
reset(); | ||
successNotification(); | ||
return; | ||
} | ||
|
||
errorNotification(); | ||
}; | ||
|
||
/* form submission notification */ | ||
const inputClasses = errors.names | ||
? "input input-error text-lg w-full max-w-3xl bg-white my-2" | ||
: "input input-bordered text-lg w-full max-w-3xl bg-white my-2"; | ||
|
||
const successNotification = () => | ||
toast.success("Sent successfully! 🐿🐿🐿", { | ||
position: "top-center", | ||
autoClose: 5000, | ||
hideProgressBar: false, | ||
closeOnClick: true, | ||
pauseOnHover: false, | ||
draggable: true, | ||
progress: undefined, | ||
}); | ||
|
||
const errorNotification = () => | ||
toast.error("An error occurred! ⛔⛔⛔", { | ||
position: "top-center", | ||
autoClose: 5000, | ||
hideProgressBar: false, | ||
closeOnClick: true, | ||
pauseOnHover: false, | ||
draggable: true, | ||
progress: undefined, | ||
}); | ||
|
||
return ( | ||
<PawHubContainer> | ||
<section> | ||
<h1 className="tracking-in-expand-fwd font-amatic text-5xl font-bold py-10"> | ||
Contact Us | ||
</h1> | ||
<form | ||
onSubmit={handleSubmit(onSubmit)} | ||
className="slide-in-fwd-left form-control max-w-lg" | ||
> | ||
<label className="text-lg"> | ||
Names | ||
<NameInput | ||
register={register} | ||
inputClasses={inputClasses} | ||
errors={errors} | ||
/> | ||
</label> | ||
|
||
<label className="text-lg"> | ||
<EmailInput | ||
register={register} | ||
inputClasses={inputClasses} | ||
errors={errors} | ||
/> | ||
</label> | ||
|
||
<label htmlFor="message" className="text-lg py-2"> | ||
Message | ||
</label> | ||
<MessageInput register={register} errors={errors} /> | ||
|
||
<button className="btn btn-primary rounded-full w-28 mt-4"> | ||
Submit | ||
</button> | ||
</form> | ||
</section> | ||
<ToastContainer /> | ||
</PawHubContainer> | ||
); | ||
}; | ||
|
||
export default Contact; |
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,72 @@ | ||
import { FieldErrorsImpl, UseFormRegister } from "react-hook-form"; | ||
|
||
import { FormData } from "./Contact"; | ||
|
||
interface InputProps { | ||
inputClasses?: string; | ||
register: UseFormRegister<FormData>; | ||
errors: FieldErrorsImpl<FormData>; | ||
} | ||
|
||
export const NameInput = ({ inputClasses, register, errors }: InputProps) => { | ||
return ( | ||
<> | ||
<input | ||
placeholder="Names" | ||
{...register("names", { | ||
required: "This field is required.", | ||
maxLength: 50, | ||
minLength: 6, | ||
})} | ||
className={inputClasses} | ||
/> | ||
<div className="py-4 text-red-500 text-sm"> | ||
{errors && <span>{errors.names?.message}</span>} | ||
{errors.names?.type === "minLength" && ( | ||
<span> Enter atleast 6 characters</span> | ||
)} | ||
</div> | ||
</> | ||
); | ||
}; | ||
|
||
export const EmailInput = ({ inputClasses, register, errors }: InputProps) => { | ||
return ( | ||
<> | ||
<input | ||
placeholder="Email" | ||
{...register("email", { | ||
required: "This field is required.", | ||
pattern: /^\S+@\S+$/i, | ||
})} | ||
className={inputClasses} | ||
/> | ||
<div className="py-4 text-red-500 text-sm"> | ||
{errors && <span>{errors.email?.message}</span>} | ||
{errors.email?.type === "pattern" && ( | ||
<span> Enter a valid email address</span> | ||
)} | ||
</div> | ||
</> | ||
); | ||
}; | ||
|
||
export const MessageInput = ({ register, errors }: InputProps) => { | ||
return ( | ||
<> | ||
<textarea | ||
{...register("message", { required: "This field is required." })} | ||
className={ | ||
errors.message | ||
? "textarea textarea-error h-40 text-lg bg-white rounded-lg" | ||
: "textarea textarea-bordered h-40 text-lg bg-white rounded-lg" | ||
} | ||
placeholder="Message" | ||
id="message" | ||
/> | ||
<div className="py-4 text-red-500 text-sm"> | ||
{errors && <span>{errors.message?.message}</span>} | ||
</div> | ||
</> | ||
); | ||
}; |
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