From 7d14a50cefd8b57c45179af8fbc31b10803c8fd1 Mon Sep 17 00:00:00 2001 From: =Mtg_Dev <=mtg0987654321@gmail.com> Date: Wed, 17 Nov 2021 19:10:09 +0200 Subject: [PATCH] improved Modals Container store structure --- src/App.tsx | 4 +- src/Components/ClaimProject/Step1.tsx | 2 +- src/Components/Login/LoginCard-1.tsx | 2 +- src/Components/Project/ProjectCard.tsx | 38 ++++--- src/Components/Shared/Modal/Modal copy.tsx | 75 ------------- src/Components/Shared/Modal/Modal.tsx | 104 ++---------------- .../ModalsContainer/ModalsContainer.tsx | 92 ++++++++++++++++ src/Components/Vote/VoteCard.tsx | 21 ++++ src/index.css | 15 ++- src/redux/features/modals.slice.ts | 46 ++++++-- 10 files changed, 204 insertions(+), 195 deletions(-) delete mode 100644 src/Components/Shared/Modal/Modal copy.tsx create mode 100644 src/Components/Shared/ModalsContainer/ModalsContainer.tsx create mode 100644 src/Components/Vote/VoteCard.tsx diff --git a/src/App.tsx b/src/App.tsx index bc19b53..3c83468 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,13 +1,13 @@ import Navbar from "./Components/Shared/Navbar/Navbar"; import ExplorePage from "./Components/ExplorePage/ExplorePage"; -import Modal from "./Components/Shared/Modal/Modal"; +import ModalsContainer from "./Components/Shared/ModalsContainer/ModalsContainer"; function App() { return
- +
; } diff --git a/src/Components/ClaimProject/Step1.tsx b/src/Components/ClaimProject/Step1.tsx index e7ed782..eb72323 100644 --- a/src/Components/ClaimProject/Step1.tsx +++ b/src/Components/ClaimProject/Step1.tsx @@ -1,5 +1,5 @@ import { motion } from "framer-motion"; -import { ModalCard, modalCardVariants } from "../Shared/Modal/Modal"; +import { ModalCard, modalCardVariants } from "../Shared/ModalsContainer/ModalsContainer"; interface Props extends ModalCard { diff --git a/src/Components/Login/LoginCard-1.tsx b/src/Components/Login/LoginCard-1.tsx index 26bbee4..5d06d60 100644 --- a/src/Components/Login/LoginCard-1.tsx +++ b/src/Components/Login/LoginCard-1.tsx @@ -1,5 +1,5 @@ import { motion } from 'framer-motion' -import { ModalCard, modalCardVariants } from '../Shared/Modal/Modal' +import { ModalCard, modalCardVariants } from '../Shared/ModalsContainer/ModalsContainer' export default function LoginCard_1({ onClose, direction, ...props }: ModalCard) { return ( diff --git a/src/Components/Project/ProjectCard.tsx b/src/Components/Project/ProjectCard.tsx index 084c4de..46e693d 100644 --- a/src/Components/Project/ProjectCard.tsx +++ b/src/Components/Project/ProjectCard.tsx @@ -2,11 +2,11 @@ import { motion } from 'framer-motion' import { BiArrowBack } from 'react-icons/bi' import { BsJoystick } from 'react-icons/bs' import { MdLocalFireDepartment } from 'react-icons/md'; -import { ModalCard, modalCardVariants } from '../Shared/Modal/Modal'; +import { ModalCard, modalCardVariants } from '../Shared/ModalsContainer/ModalsContainer'; import { useQuery } from 'react-query'; import { getProjectById } from '../../api'; import { useAppDispatch } from '../../utils/hooks'; -import { Direction, ModalId, openModal, setDirection } from '../../redux/features/modals.slice'; +import { ModalId, openModal } from '../../redux/features/modals.slice'; export default function ProjectCard({ onClose, direction, ...props }: ModalCard) { @@ -19,9 +19,16 @@ export default function ProjectCard({ onClose, direction, ...props }: ModalCard) if (isLoading || !project) return <>; + const onVote = () => { + + dispatch(openModal({ modalId: ModalId.Vote, initialModalProps: { projectId: props.projectId } })) + } + const onClaim = () => { - dispatch(setDirection(Direction.NEXT)); - dispatch(openModal({ modalId: ModalId.Login1, initialModalProps: { projectId: props.projectId } })) + dispatch(openModal({ + modalId: ModalId.Login1, + initialModalProps: { projectId: props.projectId }, + })) } return ( @@ -31,7 +38,7 @@ export default function ProjectCard({ onClose, direction, ...props }: ModalCard) initial='initial' animate="animate" exit='exit' - className="modal-card" + className="modal-card max-w-[710px]" >
@@ -47,9 +54,9 @@ export default function ProjectCard({ onClose, direction, ...props }: ModalCard)

{project.title}

{project.website}
-
+
- +

{project.description}

@@ -57,20 +64,23 @@ export default function ProjectCard({ onClose, direction, ...props }: ModalCard) payments lightining - +
+ + +
-

Screen Shots

+

Screenshots

-
-
-
-
+
+
+
+

Are you the creator of this project?

- +
diff --git a/src/Components/Shared/Modal/Modal copy.tsx b/src/Components/Shared/Modal/Modal copy.tsx deleted file mode 100644 index 99aa88e..0000000 --- a/src/Components/Shared/Modal/Modal copy.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import { AnimatePresence, motion } from "framer-motion"; -import { ReactElement, useEffect, useRef } from "react"; -import { Direction } from "../../../redux/features/modals.slice"; -import { Portal } from "../Portal/Portal"; - -export interface ModalCard { - onClose?: () => void; - direction: number; - modalCard: ReactElement -} - -export const modalCardVariants = { - initial: (direction: any) => { - if (direction === Direction.START) return { opacity: 0, y: 300 }; - else if (direction === Direction.NEXT) return { opacity: 0, x: 300 }; - else if (direction === Direction.PREVIOUS) return { opacity: 0, x: -300 }; - return {} - }, - animate: { - x: 0, y: 0, opacity: 1, transition: { type: "spring" } - }, - exit: (direction: Direction) => { - const transition = { ease: "easeIn" } - if (direction === Direction.EXIT) return { transition, opacity: 0, y: 300 }; - else if (direction === Direction.NEXT) return { transition, opacity: 0, x: -300 }; - else if (direction === Direction.PREVIOUS) return { transition, opacity: 0, x: 300 }; - return {} - }, - -} - -interface Props { - isOpen?: boolean; - onClose?: () => void, - maxWidth?: string; - children: ReactElement -} - -export default function Modal({ children, isOpen = true, onClose = () => { }, maxWidth = "max-w-[600px]" }: Props) { - - const ref = useRef(null); - const handleOutsideClick = (e: any) => { - if (e.target === ref.current) onClose(); - } - - useEffect(() => { - if (isOpen) document.body.style.overflowY = "hidden"; - else document.body.style.overflowY = "initial"; - }, [isOpen]) - - - return ( - - - {isOpen && -
- {children} -
-
} -
-
- ) -} diff --git a/src/Components/Shared/Modal/Modal.tsx b/src/Components/Shared/Modal/Modal.tsx index b157e4b..c04885f 100644 --- a/src/Components/Shared/Modal/Modal.tsx +++ b/src/Components/Shared/Modal/Modal.tsx @@ -1,100 +1,20 @@ -import { AnimatePresence, motion } from "framer-motion"; -import { useEffect, useRef } from "react"; -import { closeModal, Direction, ModalId } from "../../../redux/features/modals.slice"; -import { useAppDispatch, useAppSelector } from "../../../utils/hooks"; -import LoginCard_1 from "../../Login/LoginCard-1"; -import ProjectCard from "../../Project/ProjectCard"; -import { Portal } from "../Portal/Portal"; +import { ReactElement } from "react"; -export interface ModalCard { - onClose?: () => void; - direction: number; - [key: string]: any; -} - -export const modalCardVariants = { - initial: (direction: any) => { - if (direction === Direction.START) return { opacity: 0, y: 300 }; - else if (direction === Direction.NEXT) return { opacity: 0, x: 300 }; - else if (direction === Direction.PREVIOUS) return { opacity: 0, x: -300 }; - return {} - }, - animate: { - x: 0, y: 0, opacity: 1, transition: { type: "spring" } - }, - exit: (direction: Direction) => { - const transition = { ease: "easeIn" } - if (direction === Direction.EXIT) return { transition, opacity: 0, y: 300 }; - else if (direction === Direction.NEXT) return { transition, opacity: 0, x: -300 }; - else if (direction === Direction.PREVIOUS) return { transition, opacity: 0, x: 300 }; - return {} - }, +interface Props { + onClose: () => void; + children: ReactElement } - -const ModalsMap = (modalId: ModalId) => { - switch (modalId) { - case ModalId.Project: - return ProjectCard; - case ModalId.Login1: - return LoginCard_1; - default: - return () => <> - } - -} - - -export default function Modal() { - - const { isOpen, modalId, direction, initialModalProps } = useAppSelector(state => ({ isOpen: state.modals.isOpen, modalId: state.modals.openModalId, direction: state.modals.direction, initialModalProps: state.modals.initialModalProps })) - - const ref = useRef(null); - - const dispatch = useAppDispatch(); - const onClose = () => dispatch(closeModal()); - - const handleOutsideClick = (e: any) => { - console.log(e.target); - - if (e.target === ref.current) onClose(); - } - - useEffect(() => { - if (isOpen) document.body.style.overflowY = "hidden"; - else document.body.style.overflowY = "initial"; - }, [isOpen]); - - - const Child = ModalsMap(modalId); - - +export default function Modal(props: Props) { return ( - - - {isOpen && -
- - - -
-
} -
-
+
+
+ {props.children} +
) } diff --git a/src/Components/Shared/ModalsContainer/ModalsContainer.tsx b/src/Components/Shared/ModalsContainer/ModalsContainer.tsx new file mode 100644 index 0000000..d62857b --- /dev/null +++ b/src/Components/Shared/ModalsContainer/ModalsContainer.tsx @@ -0,0 +1,92 @@ +import { AnimatePresence, motion } from "framer-motion"; +import { useEffect, useRef } from "react"; +import { closeModal, Direction, ModalId } from "../../../redux/features/modals.slice"; +import { useAppDispatch, useAppSelector } from "../../../utils/hooks"; +import LoginCard_1 from "../../Login/LoginCard-1"; +import ProjectCard from "../../Project/ProjectCard"; +import VoteCard from "../../Vote/VoteCard"; +import Modal from "../Modal/Modal"; +import { Portal } from "../Portal/Portal"; + +export interface ModalCard { + onClose?: () => void; + direction: number; + [key: string]: any; +} + +export const modalCardVariants = { + initial: (direction: any) => { + if (direction === Direction.START) return { opacity: 0, y: 300 }; + else if (direction === Direction.NEXT) return { opacity: 0, x: 300 }; + else if (direction === Direction.PREVIOUS) return { opacity: 0, x: -300 }; + return {} + }, + animate: { + x: 0, y: 0, opacity: 1, transition: { type: "spring" } + }, + exit: (direction: Direction) => { + const transition = { ease: "easeIn" } + if (direction === Direction.EXIT) return { transition, opacity: 0, y: 300 }; + else if (direction === Direction.NEXT) return { transition, opacity: 0, x: -300 }; + else if (direction === Direction.PREVIOUS) return { transition, opacity: 0, x: 300 }; + return {} + }, + +} + + + +const ModalsMap = (modalId: ModalId) => { + switch (modalId) { + case ModalId.Project: + return ProjectCard; + case ModalId.Login1: + return LoginCard_1; + case ModalId.Vote: + return VoteCard; + default: + return () => <> + } + +} + + +export default function ModalsContainer() { + + const { isOpen, openModals, direction } = useAppSelector(state => ({ isOpen: state.modals.isOpen, openModals: state.modals.openModals, direction: state.modals.direction })) + + const dispatch = useAppDispatch(); + const onClose = () => dispatch(closeModal()); + + useEffect(() => { + if (isOpen) document.body.style.overflowY = "hidden"; + else document.body.style.overflowY = "initial"; + }, [isOpen]); + + + return ( + + + {isOpen && + + + {openModals.map(modal => { + const Child = ModalsMap(modal.modalId); + return ( + + + ) + })} + } + + + ) +} diff --git a/src/Components/Vote/VoteCard.tsx b/src/Components/Vote/VoteCard.tsx new file mode 100644 index 0000000..21ea49c --- /dev/null +++ b/src/Components/Vote/VoteCard.tsx @@ -0,0 +1,21 @@ +import { motion } from 'framer-motion' +import { ModalCard, modalCardVariants } from '../Shared/ModalsContainer/ModalsContainer' + +export default function VoteCard({ onClose, direction, ...props }: ModalCard) { + return ( + +
+

Vote Modal

+

WIP

+
+
+ ) +} diff --git a/src/index.css b/src/index.css index c14447c..62210ec 100644 --- a/src/index.css +++ b/src/index.css @@ -12,6 +12,10 @@ @apply bg-primary-600 hover:bg-primary-500 text-white; } + .btn-gray { + @apply bg-gray-200 hover:bg-gray-100 text-gray-900; + } + .chip { @apply bg-gray-100 text-body4 px-16 py-8 rounded-24 font-regular; } @@ -20,7 +24,7 @@ } .modal-card { - @apply rounded-[40px] bg-gray-50 overflow-hidden w-full max-w-[600px] shadow-xl; + @apply rounded-[40px] bg-gray-50 overflow-y-scroll w-full max-w-[600px] shadow-xl z-10; } } @@ -52,3 +56,12 @@ svg { ::-webkit-scrollbar-thumb:hover { background-color: #999; } + +.no-scrollbar { + -ms-overflow-style: none; /* Internet Explorer 10+ */ + scrollbar-width: none; /* Firefox */ +} + +.no-scrollbar ::-webkit-scrollbar { + display: none; /* Safari and Chrome */ +} diff --git a/src/redux/features/modals.slice.ts b/src/redux/features/modals.slice.ts index 3753bee..d402857 100644 --- a/src/redux/features/modals.slice.ts +++ b/src/redux/features/modals.slice.ts @@ -12,21 +12,26 @@ export enum ModalId { Project, Login1, Login2, + Vote, +} + +interface OpenModal { + modalId: ModalId; + propsToPass: any; } interface StoreState { isOpen: boolean; isLoading: boolean; direction: Direction; - openModalId: ModalId; - initialModalProps: any; + openModals: OpenModal[]; } const initialState = { isOpen: false, isLoading: false, direction: Direction.START, - openModalId: ModalId.None, + openModals: [] as OpenModal[], } as StoreState; export const modalSlice = createSlice({ @@ -41,20 +46,43 @@ export const modalSlice = createSlice({ state, action: PayloadAction<{ modalId: ModalId; initialModalProps: any }> ) { - if (!state.isOpen) state.direction = Direction.START; + state.direction = Direction.START; state.isOpen = true; - state.openModalId = action.payload.modalId; - state.initialModalProps = action.payload.initialModalProps; + state.openModals.push({ + modalId: action.payload.modalId, + propsToPass: action.payload.initialModalProps, + }); + }, + + replaceModal( + state, + action: PayloadAction<{ + modalId: ModalId; + initialModalProps: any; + direction: Direction; + }> + ) { + state.direction = action.payload.direction; + state.openModals.pop(); + state.openModals.push({ + modalId: action.payload.modalId, + propsToPass: action.payload.initialModalProps || {}, + }); }, closeModal(state) { state.direction = Direction.EXIT; - state.isOpen = false; - state.openModalId = ModalId.None; + state.openModals.pop(); + state.isOpen = Boolean(state.openModals.length); }, }, }); -export const { closeModal, openModal, setDirection } = modalSlice.actions; +export const { + closeModal, + openModal, + replaceModal, + setDirection, +} = modalSlice.actions; export default modalSlice.reducer;