Skip to content

Commit

Permalink
fix: contact modal does not show up correctly on mobile
Browse files Browse the repository at this point in the history
Signed-off-by: GitHub <[email protected]>
  • Loading branch information
virtual-designer authored Aug 28, 2024
1 parent 6996702 commit 06a2069
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 143 deletions.
113 changes: 36 additions & 77 deletions src/components/ContactMail/ContactMail.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
"use client";

import { Box, Button, Divider } from "@mui/material";
import clsx from "clsx";
import { AnimatePresence, motion } from "framer-motion";
import { Modal, ModalBody, ModalContent, ModalHeader } from "@nextui-org/react";
import { type FC } from "react";
import { HiOutlineEnvelope } from "react-icons/hi2";
import { MdClose } from "react-icons/md";
import ContactMailForm from "./ContactMailForm";
import { useContactMail } from "./useContactMail";

Expand All @@ -22,79 +19,41 @@ const ContactMail: FC<ContactMailProps> = ({
const isOpen = propsIsOpen ?? context.isOpen;

return (
<>
{isOpen && (
<Box
className="fixed inset-0 bg-black/40 z-[9999] top-0 left-0 w-screen h-screen lg:hidden"
onClick={context.close}
/>
)}
<AnimatePresence>
{isOpen ? (
<motion.div
className={clsx(
"z-[10000] bg-white fixed max-lg:bottom-3 max-lg:left-3 lg:absolute dark:bg-neutral-900 shadow dark:shadow-neutral-400/40 w-[calc(100%-1.5rem)] lg:w-[30rem] rounded-lg mt-3",
{
"bottom-7": direction === "bottom",
"top-7": direction === "top",
},
)}
initial={{
opacity: 0,
y: (direction === "top" ? -1 : 1) * 10,
}}
animate={{ opacity: 1, y: 0 }}
exit={{
opacity: 0,
y: (direction === "top" ? -1 : 1) * 10,
}}
>
<Box
display="flex"
justifyContent="space-between"
alignItems="center"
pt={2}
px={2}
>
<h3 className="text-lg font-semibold bg-gradient-to-r from-blue-600 to-cyan-500 bg-clip-text text-transparent flex items-center gap-2">
<svg width="0" height="0">
<linearGradient
id="mail-icon-gradient"
x1="100%"
y1="100%"
x2="0%"
y2="0%"
>
<stop stopColor="#007bff" offset="0%" />
<stop
stopColor="#19dafa"
offset="100%"
/>
</linearGradient>
</svg>
<HiOutlineEnvelope
style={{
stroke: "url(#mail-icon-gradient)",
}}
size="1.5em"
/>
<span>Contact Support</span>
</h3>
<Button
className="text-neutral-500 dark:text-neutral-400 min-w-0 bg-neutral-50 dark:bg-neutral-800"
onClick={context.close}
>
<MdClose />
</Button>
</Box>
<Divider className="mt-3" />
<div className="pb-2">
<ContactMailForm />
</div>
</motion.div>
) : null}
</AnimatePresence>
</>
<Modal isOpen={isOpen} placement="auto" onOpenChange={context.setOpen}>
<ModalContent>
{(onClose) => (
<>
<ModalHeader className="flex items-center">
<svg width="0" height="0">
<linearGradient
id="mail-icon-gradient"
x1="100%"
y1="100%"
x2="0%"
y2="0%"
>
<stop stopColor="#007bff" offset="0%" />
<stop stopColor="#19dafa" offset="100%" />
</linearGradient>
</svg>
<HiOutlineEnvelope
style={{
stroke: "url(#mail-icon-gradient)",
}}
size="1.5em"
/>
<span className="bg-gradient-to-l from-blue-600 to-cyan-500 bg-clip-text text-transparent ml-2.5 block">
Contact Support
</span>
</ModalHeader>

<ModalBody>
<ContactMailForm onClose={onClose} />
</ModalBody>
</>
)}
</ModalContent>
</Modal>
);
};

Expand Down
102 changes: 54 additions & 48 deletions src/components/ContactMail/ContactMailForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,8 @@ import {
ContactMailFormData,
ContactMailFormSchema,
} from "./ContactMailFormSchema";
import { useContactMail } from "./useContactMail";

const ContactMailForm: FC = () => {
const { close } = useContactMail();
const ContactMailForm: FC<{ onClose: () => void }> = ({ onClose: close }) => {
const {
control,
register,
Expand Down Expand Up @@ -90,53 +88,61 @@ const ContactMailForm: FC = () => {
{isPending && <LinearProgress />}
<Spacer y={2} />

<div className="px-3">
{" "}
<Input
label="Name"
isInvalid={!!errors.name}
errorMessage={errors.name?.message}
placeholder="Enter your name"
variant="flat"
isDisabled={isPending}
{...register("name")}
/>
<Spacer y={2} />
<Input
label="Email"
isInvalid={!!errors.email}
errorMessage={errors.email?.message}
placeholder="Enter your email"
variant="flat"
isDisabled={isPending}
{...register("email")}
/>
<p className="text-xs text-neutral-500 dark:text-neutral-400 pt-1 pl-1">
We will use this email to contact you back. This will be
kept private.
</p>
<Spacer y={3} />
<Textarea
label="Message"
isInvalid={!!errors.message}
errorMessage={errors.message?.message}
placeholder="Type your message here..."
<Input
label="Name"
isInvalid={!!errors.name}
errorMessage={errors.name?.message}
placeholder="Enter your name"
variant="flat"
isDisabled={isPending}
{...register("name")}
/>
<Spacer y={2} />
<Input
label="Email"
isInvalid={!!errors.email}
errorMessage={errors.email?.message}
placeholder="Enter your email"
variant="flat"
isDisabled={isPending}
{...register("email")}
/>
<p className="text-xs text-neutral-500 dark:text-neutral-400 pt-1 pl-1">
We will use this email to contact you back. This will be kept
private.
</p>
<Spacer y={3} />
<Input
label="Subject"
isInvalid={!!errors.subject}
errorMessage={errors.subject?.message}
placeholder="What do you need help with?"
variant="flat"
isDisabled={isPending}
{...register("subject")}
/>
<Spacer y={2} />
<Textarea
label="Message"
isInvalid={!!errors.message}
errorMessage={errors.message?.message}
placeholder="Type your message here..."
variant="flat"
isDisabled={isPending}
{...register("message")}
/>
<Spacer y={2} />
<div className="flex justify-end items-center">
<Button
type="submit"
variant="flat"
isDisabled={isPending}
{...register("message")}
/>
<Spacer y={2} />
<div className="flex justify-end items-center">
<Button
type="submit"
variant="flat"
endContent={<BsSend />}
isLoading={isPending}
>
Send
</Button>
</div>
endContent={<BsSend />}
isLoading={isPending}
>
Send
</Button>
</div>
<Spacer y={2} />
</Form>
);
};
Expand Down
4 changes: 4 additions & 0 deletions src/components/ContactMail/ContactMailFormSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ export const ContactMailFormSchema = z.object({
.string({ required_error: "Please enter your name!" })
.min(1, "Please enter your name!")
.max(128, "Your name must be at most 128 characters long!"),
subject: z
.string({ required_error: "Please enter a subject!" })
.min(1, "Please enter a subject!")
.max(256, "Your subject must be at most 256 characters long!"),
email: z
.string({
required_error:
Expand Down
2 changes: 1 addition & 1 deletion src/components/ContactMail/EmailSupportLinkWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const EmailSupportLinkWrapper: FC<EmailSupportLinkWrapperProps> = ({
<ContactMailTrigger as="a" href="#">
{link.title}
</ContactMailTrigger>
<ContactMail direction="bottom" />
<ContactMail />
</div>
);
};
Expand Down
21 changes: 8 additions & 13 deletions src/components/ContactMail/useContactMail.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,23 @@
import { useAppDispatch, useAppSelector } from "@/redux/hooks/AppStoreHooks";
import {
closeDialog,
openDialog,
toggleDialog,
} from "@/redux/slice/ContactMailSlice";
import { setOpenDialog, toggleDialog } from "@/redux/slice/ContactMailSlice";
import { useCallback } from "react";

export const useContactMail = () => {
const state = useAppSelector((state) => state.contactMail);
const dispatch = useAppDispatch();
const open = useCallback(() => {
dispatch(openDialog());
}, [dispatch]);
const close = useCallback(() => {
dispatch(closeDialog());
}, [dispatch]);
const toggle = useCallback(() => {
dispatch(toggleDialog());
}, [dispatch]);
const setOpen = useCallback(
(value: boolean) => {
dispatch(setOpenDialog(value));
},
[dispatch],
);

return {
open,
close,
toggle,
setOpen,
isOpen: state.dialogOpen,
};
};
5 changes: 4 additions & 1 deletion src/redux/slice/ContactMailSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,12 @@ const ContactMailSlice = createSlice({
toggleDialog: (state) => {
state.dialogOpen = !state.dialogOpen;
},
setOpenDialog: (state, action) => {
state.dialogOpen = action.payload;
},
},
});

export const { openDialog, closeDialog, toggleDialog } =
export const { openDialog, closeDialog, toggleDialog, setOpenDialog } =
ContactMailSlice.actions;
export default ContactMailSlice.reducer;
3 changes: 2 additions & 1 deletion src/server/contact.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
ContactMailFormSchema,
} from "@/components/ContactMail/ContactMailFormSchema";
import env from "@/utils/env";
import { escapeMarkdown } from "@/utils/utils";
import axios from "axios";
import { headers } from "next/headers";
import { v4 as uuid } from "uuid";
Expand Down Expand Up @@ -64,7 +65,7 @@ export async function sendContactMessage(data: ContactMailFormData) {
form.set(
"payload_json",
JSON.stringify({
content: `# New Support Ticket\n**Ticket ID**: ${id}\n**Assigned To**: None\n### Submitter Information\n**Name:** ${data.name}\n**Email:** ${data.email}\n\n-# Always be careful with file attachments.`,
content: `# New Support Ticket\n**Ticket ID**: ${id}\n**Subject**: ${escapeMarkdown(data.subject)}\n**Assigned To**: None\n### Submitter Information\n**Name:** ${data.name}\n**Email:** ${data.email}\n\n-# Always be careful with file attachments.`,
}),
);

Expand Down
13 changes: 11 additions & 2 deletions src/utils/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
export function isDashboardPath(pathname: string) {
return pathname.startsWith("/dashboard") || pathname.startsWith("/account") || pathname.startsWith("/settings");
return (
pathname.startsWith("/dashboard") ||
pathname.startsWith("/account") ||
pathname.startsWith("/settings")
);
}

export const unreachable = (): never => {
Expand All @@ -16,4 +20,9 @@ export const loop = <T>(times: number, callback: (index: number) => T): T[] => {
return result;
};

export const isDevMode = () => process.env.NEXT_PUBLIC_NODE_ENV === "development";
export const isDevMode = () =>
process.env.NEXT_PUBLIC_NODE_ENV === "development";

export const escapeMarkdown = (text: string) => {
return text.replace(/([\\`*_~])/g, "\\$1");
};

0 comments on commit 06a2069

Please sign in to comment.