Tạo sign up && xử lý click trigger hay handleClickOutside (ok)
PreviousTạo một menu để useRegisterModal và sử dụng React.FC đăng ký Generic (ok)NextTạo login && ToasterProvider (ok)
Last updated
Was this helpful?
Last updated
Was this helpful?
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
const menu = document.getElementById("user-menu");
if (menu && !menu.contains(event.target as Node)) {
setIsOpen(false);
}
}
document.addEventListener("click", handleClickOutside);
return () => {
document.removeEventListener("click", handleClickOutside);
};
}, []);
app\components\navbar\UserMenu.tsx
'use client';
import { SafeUser } from "@/app/types";
import MenuItem from "./MenuItem";
import { AiOutlineMenu } from "react-icons/ai";
import Avatar from "../elementsUi/Avatar";
import useRegisterModal from "@/app/hooks/useRegisterModal";
import useLoginModal from "@/app/hooks/useLoginModal";
import useRentModal from "@/app/hooks/useRentModal";
import { useCallback, useEffect, useState } from "react";
import { signOut } from "next-auth/react";
interface UserMenuProps {
currentUser?: SafeUser | null
}
const UserMenu: React.FC<UserMenuProps> = ({ currentUser }) => {
const registerModal = useRegisterModal();
const loginModal = useLoginModal();
const rentModal = useRentModal();
const [isOpen, setIsOpen] = useState(false);
const toggleOpen = useCallback(() => {
setIsOpen((value) => !value);
}, []);
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
const menu = document.getElementById("user-menu");
if (menu && !menu.contains(event.target as Node)) {
setIsOpen(false);
}
}
document.addEventListener("click", handleClickOutside);
return () => {
document.removeEventListener("click", handleClickOutside);
};
}, []);
const onRent = useCallback(() => {
if (!currentUser) {
return loginModal.onOpen();
}
rentModal.onOpen();
}, [loginModal, rentModal, currentUser]);
return (
<div className="relative">
<div className="flex flex-row items-center gap-3">
<div
onClick={onRent}
className=" hidden md:block text-sm font-semibold py-3 px-4 rounded-full hover:bg-neutral-100 transition cursor-pointer"
>
Reserve your home
</div>
<div
id="user-menu"
onClick={toggleOpen}
className="p-4 md:py-1 md:px-2 border-[1px] border-neutral-200 flex flex-row items-center gap-3 rounded-full cursor-pointer hover:shadow-md transition"
>
<AiOutlineMenu />
<div className="hidden md:block">
<Avatar src={currentUser?.image} />
</div>
</div>
</div>
<div className="absolute rounded-xl shadow-md w-[40vw] md:w-3/4 bg-white overflow-hidden right-0 top-12 text-sm">
<div className="flex flex-col cursor-pointer">
{
isOpen ? (
<>
<MenuItem
label="Logout"
onClick={() => signOut()}
/>
</>
) : (
<>
<MenuItem
label="Login"
onClick={loginModal.onOpen}
/>
<MenuItem
label="Sign up"
onClick={registerModal.onOpen}
/>
</>
)
}
</div>
</div>
</div>
)
}
export default UserMenu;
app\hooks\useRentModal.ts
import { create } from 'zustand';
interface RentModalStore {
isOpen: boolean;
onOpen: () => void;
onClose: () => void;
}
const useRentModal = create<RentModalStore>((set) => ({
isOpen: false,
onOpen: () => set({ isOpen: true }),
onClose: () => set({ isOpen: false })
}));
export default useRentModal;