Skip to content

Commit

Permalink
pass close fn/forwardref to promptlink (#698)
Browse files Browse the repository at this point in the history
Co-authored-by: Niall Maher <[email protected]>
  • Loading branch information
John-Paul-Larkin and NiallJoeMaher authored Jan 17, 2024
1 parent 7db81a6 commit 433357c
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 52 deletions.
22 changes: 19 additions & 3 deletions components/Nav/MobileNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { type UserNavigationItem } from "@/types/types";
import { Disclosure, Transition } from "@headlessui/react";
import { type Session } from "next-auth";
import { PromptLink as Link } from "../PromptService/PromptLink";
import { type FunctionComponent } from "react";
import { MutableRefObject, useRef, type FunctionComponent } from "react";
import { navigation, subNav, userSubNav } from "../../config/site_settings";

function classNames(...classes: string[]) {
Expand All @@ -12,11 +12,18 @@ function classNames(...classes: string[]) {
interface MobileNavProps {
session: Session | null;
userNavigation: UserNavigationItem[];
close?: (
focusableElement?:
| HTMLElement
| MutableRefObject<HTMLElement | null>
| undefined,
) => void;
}

const MobileNav: FunctionComponent<MobileNavProps> = ({
session,
userNavigation,
close,
}) => {
return (
<Transition
Expand All @@ -31,7 +38,7 @@ const MobileNav: FunctionComponent<MobileNavProps> = ({
<NavItem item={item} key={item.name} />
))}
<div className="flex flex-col space-y-1 border-t border-neutral-400 pb-3 pt-3 dark:border-neutral-600">
<SubNav session={session} />
<SubNav session={session} close={close} />
</div>
</div>

Expand Down Expand Up @@ -123,9 +130,16 @@ const NavItem: FunctionComponent<NavItemProps> = ({ item }) => {

interface SubNavProps {
session: Session | null;
close?: (
focusableElement?:
| HTMLElement
| MutableRefObject<HTMLElement | null>
| undefined,
) => void;
}

const SubNav: FunctionComponent<SubNavProps> = ({ session }) => {
const SubNav: FunctionComponent<SubNavProps> = ({ session, close }) => {
const disclosureButtonRef = useRef(null);
const data = session ? userSubNav : subNav;
return (
<>
Expand All @@ -134,6 +148,8 @@ const SubNav: FunctionComponent<SubNavProps> = ({ session }) => {
<Disclosure.Button
as={Link}
to={item.href}
close={close}
ref={disclosureButtonRef}
className={classNames(
item.fancy
? "block justify-center bg-gradient-to-r from-orange-400 to-pink-600 px-4 text-white shadow-sm hover:from-orange-300 hover:to-pink-500 focus:outline-none focus:ring-2 focus:ring-offset-2"
Expand Down
8 changes: 6 additions & 2 deletions components/Nav/Nav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const Nav = ({ session }: { session: Session | null }) => {

return (
<Disclosure as="nav" className="bg-neutral-100 dark:bg-black">
{({ open }) => (
{({ close, open }) => (
<>
<div className="relative z-20 mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex h-16 items-center justify-between">
Expand Down Expand Up @@ -197,7 +197,11 @@ const Nav = ({ session }: { session: Session | null }) => {
</div>
</div>
</div>
<MobileNav session={session} userNavigation={userNavigation} />
<MobileNav
session={session}
userNavigation={userNavigation}
close={close}
/>
</>
)}
</Disclosure>
Expand Down
118 changes: 71 additions & 47 deletions components/PromptService/PromptLink.tsx
Original file line number Diff line number Diff line change
@@ -1,66 +1,90 @@
import { useRouter } from "next/navigation";
import { usePrompt } from "@/components/PromptService/PromptContext";
import type { ReactNode } from "react";
import type { MutableRefObject, ReactNode } from "react";
import { useEffect, useState } from "react";
import Link from "next/link";
import { PromptDialog } from "./PromptDialog";
import React from "react";

interface LinkProps {
to: string;
children: ReactNode;
className?: string;
close?: (
focusableElement?:
| HTMLElement
| MutableRefObject<HTMLElement | null>
| undefined,
) => void;
}

export const PromptLink = ({ to, children, className }: LinkProps) => {
const router = useRouter();
const { unsavedChanges } = usePrompt();
const [hasPrompt, setHasPrompt] = useState(false);
const [showModal, setShowModal] = useState(false);
const PromptLink = React.forwardRef(
(
{ to, children, className, close }: LinkProps,
ref: React.Ref<HTMLAnchorElement>,
) => {
const router = useRouter();
const { unsavedChanges } = usePrompt();
const [hasPrompt, setHasPrompt] = useState(false);
const [showModal, setShowModal] = useState(false);

const handleNavigation = (event) => {
event.preventDefault();
const handleNavigation = (
event: React.MouseEvent<HTMLAnchorElement, MouseEvent>,
) => {
event.preventDefault();

if (unsavedChanges) {
setHasPrompt(true);
setShowModal(true);
return false;
} else {
if (unsavedChanges) {
setHasPrompt(true);
setShowModal(true);
return false;
} else {
if (close !== undefined) close();
router.push(to);
}
};

const confirmNavigation = () => {
setShowModal(false);
setHasPrompt(false);
if (close !== undefined) close();
router.push(to);
}
};
};

const confirmNavigation = () => {
setShowModal(false);
setHasPrompt(false);
router.push(to);
};
const cancelNavigation = () => {
setShowModal(false);
return false;
};

const cancelNavigation = () => {
setShowModal(false);
return false;
};
useEffect(() => {
if (hasPrompt === true) {
setHasPrompt(false);
}
}, [hasPrompt]);

useEffect(() => {
if (hasPrompt === true) {
setHasPrompt(false);
}
}, [hasPrompt]);
return (
<>
<Link
href={to}
onClick={handleNavigation}
className={className}
ref={ref}
>
{children}
</Link>
{showModal && (
<PromptDialog
title="Unsaved Changes"
subTitle="You have unsaved changes. Are you sure you want to leave?"
confirm={confirmNavigation}
cancel={cancelNavigation}
confirmText="Continue without saving"
cancelText="Keep editing"
/>
)}
</>
);
},
);

return (
<>
<Link href={to} onClick={handleNavigation} className={className}>
{children}
</Link>
{showModal && (
<PromptDialog
title="Unsaved Changes"
subTitle="You have unsaved changes. Are you sure you want to leave?"
confirm={confirmNavigation}
cancel={cancelNavigation}
confirmText="Continue without saving"
cancelText="Keep editing"
/>
)}
</>
);
};
PromptLink.displayName = "PromptLink";
export { PromptLink };

0 comments on commit 433357c

Please sign in to comment.