Skip to content

Commit

Permalink
feat: improve modal control
Browse files Browse the repository at this point in the history
  • Loading branch information
AntonioErdeljac committed Mar 4, 2023
1 parent 634003e commit b269a5e
Show file tree
Hide file tree
Showing 16 changed files with 224 additions and 73 deletions.
12 changes: 8 additions & 4 deletions components/Form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import { BiImage } from 'react-icons/bi';
import { HiOutlineGif } from 'react-icons/hi2';
import { IoLocationSharp } from 'react-icons/io5';

import useLoginModal from '@/hooks/useLoginModal';
import useRegisterModal from '@/hooks/useRegisterModal';

import Avatar from './Avatar';
import Button from './Button';
import LoginModal from './modals/LoginModal';
import RegisterModal from './modals/RegisterModal';

const isLoggedIn = false;

Expand All @@ -14,6 +15,9 @@ interface FormProps {
}

const Form: React.FC<FormProps> = ({ placeholder }) => {
const registerModal = useRegisterModal();
const loginModal = useLoginModal();

return (
<div className="border-b-[1px] border-neutral-800 px-5 py-2">
{isLoggedIn ? (
Expand Down Expand Up @@ -67,8 +71,8 @@ const Form: React.FC<FormProps> = ({ placeholder }) => {
<div className="py-8">
<h1 className="text-white text-2xl text-center mb-4 font-bold">Welcome to Twitter</h1>
<div className="flex flex-row items-center justify-center gap-4">
<LoginModal />
<RegisterModal />
<Button label="Login" onClick={loginModal.onOpen} />
<Button label="Register" onClick={registerModal.onOpen} secondary />
</div>
</div>
)}
Expand Down
3 changes: 3 additions & 0 deletions components/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ const Input: React.FC<InputProps> = ({ placeholder, value, type = "text" }) => {
rounded-md
outline-none
text-white
focus:border-sky-500
focus:border-2
transition
"
/>
);
Expand Down
4 changes: 3 additions & 1 deletion components/Modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ interface ModalProps {
onSubmit: () => void;
title?: string;
body?: React.ReactElement;
footer?: React.ReactElement;
actionLabel: string;
}

const Modal: React.FC<ModalProps> = ({ isOpen, onClose, onSubmit, title, body, actionLabel }) => {
const Modal: React.FC<ModalProps> = ({ isOpen, onClose, onSubmit, title, body, actionLabel, footer }) => {
const handleClose = useCallback(() => {
onClose();
}, [onClose]);
Expand Down Expand Up @@ -92,6 +93,7 @@ const Modal: React.FC<ModalProps> = ({ isOpen, onClose, onSubmit, title, body, a
{/*footer*/}
<div className="flex flex-col gap-2 p-10">
<Button label={actionLabel} secondary fullWidth large onClick={handleSubmit} />
{footer}
</div>
</div>
</div>
Expand Down
19 changes: 4 additions & 15 deletions components/layout/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,32 +34,21 @@ const items = [
]

const Sidebar = () => {
const filteredItems = useMemo(() => {
return items.filter((item) => {
if (!isLoggedIn && item.auth) {
return null;
}

return item;
})
}, []);

return (
<div className="col-span-1 h-full pr-4 md:pr-6">
<div className="flex flex-col items-end">
<div className="space-y-2 lg:w-[230px]">
<SidebarLogo />
{filteredItems.map((item) => (
<SidebarItem
{items.map((item) => (
<SidebarItem
key={item.href}
auth={item.auth}
href={item.href}
icon={item.icon}
label={item.label}
/>
))}
{isLoggedIn && (
<SidebarTweetButton />
)}
<SidebarTweetButton />
</div>
</div>
</div>
Expand Down
16 changes: 12 additions & 4 deletions components/layout/SidebarItem.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,27 @@
import { useRouter } from 'next/router';
import React, { useCallback } from 'react';
import { IconType } from "react-icons";
import { useRouter } from 'next/router';

import useLoginModal from '@/hooks/useLoginModal';

interface SidebarItemProps {
label: string;
icon: IconType;
href: string;
auth?: boolean;
}

const SidebarItem: React.FC<SidebarItemProps> = ({ label, icon: Icon, href }) => {
const SidebarItem: React.FC<SidebarItemProps> = ({ label, icon: Icon, href, auth }) => {
const router = useRouter();
const loginModal = useLoginModal();

const onClick = useCallback(() => {
router.push(href);
}, [router, href]);
if (auth) {
loginModal.onOpen();
} else {
router.push(href);
}
}, [router, href, auth, loginModal]);

return (
<div onClick={onClick} className="flex flex-row items-center">
Expand Down
6 changes: 5 additions & 1 deletion components/layout/SidebarTweetButton.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import { FaFeather } from "react-icons/fa";

import useLoginModal from "@/hooks/useLoginModal";

const SidebarTweetButton = () => {
const loginModal = useLoginModal();

return (
<div>
<div onClick={loginModal.onOpen}>
<div className="
mt-6
lg:hidden
Expand Down
52 changes: 38 additions & 14 deletions components/modals/LoginModal.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useState } from "react";
import Button from "../Button";
import useLoginModal from "@/hooks/useLoginModal";
import useRegisterModal from "@/hooks/useRegisterModal";
import { useCallback } from "react";

import Input from "../Input";
import Modal from "../Modal";
Expand All @@ -13,21 +14,44 @@ const ModalBody = () => {
)
}

const ModalFooter = () => {
const loginModal = useLoginModal();
const registerModal = useRegisterModal();

const onClick = useCallback(() => {
loginModal.onClose();
registerModal.onOpen();
}, [loginModal, registerModal]);

return (
<div className="text-neutral-400 text-center mt-4">
<p>First time using Twitter?
<span
onClick={onClick}
className="
text-white
cursor-pointer
hover:underline
"
> Create an account</span>
</p>
</div>
)
}

const LoginModal = () => {
const [showModal, setShowModal] = useState(false);
const loginModal = useLoginModal();

return (
<>
<Button onClick={() => setShowModal(true)} label="Sign in" />
<Modal
isOpen={showModal}
title="Login"
actionLabel="Sign in"
onClose={() => setShowModal(false)}
onSubmit={() => setShowModal(false)}
body={<ModalBody />}
/>
</>
<Modal
isOpen={loginModal.isOpen}
title="Login"
actionLabel="Sign in"
onClose={loginModal.onClose}
onSubmit={loginModal.onClose}
body={<ModalBody />}
footer={<ModalFooter />}
/>
);
}

Expand Down
53 changes: 39 additions & 14 deletions components/modals/RegisterModal.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { useState } from "react";
import Button from "../Button";
import { useCallback } from "react";

import useLoginModal from "@/hooks/useLoginModal";
import useRegisterModal from "@/hooks/useRegisterModal";

import Input from "../Input";
import Modal from "../Modal";
Expand All @@ -15,21 +17,44 @@ const ModalBody = () => {
)
}

const ModalFooter = () => {
const loginModal = useLoginModal();
const registerModal = useRegisterModal();

const onClick = useCallback(() => {
registerModal.onClose();
loginModal.onOpen();
}, [loginModal, registerModal]);

return (
<div className="text-neutral-400 text-center mt-4">
<p>Already have an account?
<span
onClick={onClick}
className="
text-white
cursor-pointer
hover:underline
"
> Sign in</span>
</p>
</div>
)
}

const RegisterModal = () => {
const [showModal, setShowModal] = useState(false);
const registerModal = useRegisterModal();

return (
<>
<Button onClick={() => setShowModal(true)} label="Register" secondary />
<Modal
isOpen={showModal}
title="Create an account"
actionLabel="Register"
onClose={() => setShowModal(false)}
onSubmit={() => setShowModal(false)}
body={<ModalBody />}
/>
</>
<Modal
isOpen={registerModal.isOpen}
title="Create an account"
actionLabel="Register"
onClose={registerModal.onClose}
onSubmit={registerModal.onClose}
body={<ModalBody />}
footer={<ModalFooter />}
/>
);
}

Expand Down
9 changes: 6 additions & 3 deletions components/posts/PostItem.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import { useRouter } from 'next/router';
import { useCallback } from 'react';
import { AiOutlineHeart, AiOutlineMessage } from 'react-icons/ai';

import useLoginModal from '@/hooks/useLoginModal';

import Avatar from '../Avatar';

const PostItem = () => {
const router = useRouter();
const loginModal = useLoginModal();

const goToProfile = useCallback((ev: any) => {
ev.stopPropagation();
Expand All @@ -17,9 +21,8 @@ const PostItem = () => {

const onLike = useCallback((ev: any) => {
ev.stopPropagation();

return;
}, []);
loginModal.onOpen();
}, [loginModal]);

return (
<div
Expand Down
17 changes: 5 additions & 12 deletions components/profiles/ProfileBio.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,16 @@
import { BiCalendar } from "react-icons/bi";

import Button from "../Button";
import LoginModal from "../modals/LoginModal";
import RegisterModal from "../modals/RegisterModal";
import useLoginModal from "@/hooks/useLoginModal";

const isLoggedIn = false;
import Button from "../Button";

const ProfileBio = () => {
const loginModal = useLoginModal();

return (
<div className="border-b-[1px] border-neutral-800 pb-4">
<div className="flex justify-end p-2">
{isLoggedIn ? (
<Button onClick={() => {}} secondary label="Follow" />
) : (
<div className="flex flex-row items-center gap-2">
<LoginModal />
<RegisterModal />
</div>
)}
<Button onClick={loginModal.onOpen} secondary label="Follow" />
</div>
<div className="mt-8 px-4">
<div className="flex flex-col">
Expand Down
16 changes: 16 additions & 0 deletions hooks/useLoginModal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { create } from 'zustand';

interface LoginModalStore {
isOpen: boolean;
onOpen: () => void;
onClose: () => void;
}

const useLoginModal = create<LoginModalStore>((set) => ({
isOpen: false,
onOpen: () => set({ isOpen: true }),
onClose: () => set({ isOpen: false })
}));


export default useLoginModal;
16 changes: 16 additions & 0 deletions hooks/useRegisterModal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { create } from 'zustand';

interface RegisterModalStore {
isOpen: boolean;
onOpen: () => void;
onClose: () => void;
}

const useRegisterModal = create<RegisterModalStore>((set) => ({
isOpen: false,
onOpen: () => set({ isOpen: true }),
onClose: () => set({ isOpen: false })
}));


export default useRegisterModal;
Loading

0 comments on commit b269a5e

Please sign in to comment.