feat: refactor project structure

Refactored the project structure so that each page has its own tree of components and a global "Components" folder for the components that is used by more than one page.
- Added an "assets" directory that exports all static images/icons/fonts/...etc
This commit is contained in:
MTG2000
2021-12-30 15:12:40 +02:00
parent 5ae1da6369
commit 43bfab177e
51 changed files with 71 additions and 60 deletions

View File

@@ -0,0 +1,17 @@
import { ComponentStory, ComponentMeta } from '@storybook/react';
import Login_ExternalWalletCard from './Login_ExternalWalletCard';
import { ModalsDecorator } from '.storybook/helpers'
export default {
title: 'Login/External Wallet Card',
component: Login_ExternalWalletCard,
decorators: [ModalsDecorator]
} as ComponentMeta<typeof Login_ExternalWalletCard>;
const Template: ComponentStory<typeof Login_ExternalWalletCard> = (args) => <Login_ExternalWalletCard {...args} />;
export const Default = Template.bind({});

View File

@@ -0,0 +1,61 @@
import { motion } from 'framer-motion'
import { Direction, ModalId, replaceModal } from 'src/redux/features/modals.slice';
import { useAppDispatch } from 'src/utils/hooks';
import { ModalCard, modalCardVariants } from 'src/Components/Modals/ModalsContainer/ModalsContainer'
import { AiFillThunderbolt } from 'react-icons/ai';
import CopyToClipboard from 'src/Components/CopyToClipboard/CopyToClipboard';
import { useCallback, useEffect } from 'react';
import { IoClose } from 'react-icons/io5';
export default function Login_ExternalWalletCard({ onClose, direction, ...props }: ModalCard) {
const dispatch = useAppDispatch();
const handleNext = useCallback(() => {
dispatch(replaceModal({
modalId: ModalId.Login_Success,
direction: Direction.NEXT
}))
}, [dispatch])
useEffect(() => {
}, [handleNext])
const onCopy = () => {
// Copy to Clipboard
setTimeout(handleNext, 1000)
}
return (
<motion.div
custom={direction}
variants={modalCardVariants}
initial='initial'
animate="animate"
exit='exit'
className="modal-card max-w-[343px] p-24 rounded-xl relative"
>
<IoClose className='absolute text-body2 top-24 right-24 hover:cursor-pointer' onClick={onClose} />
<h2 className='text-h5 font-bold'>Log in with Lightning <AiFillThunderbolt className='inline-block text-thunder transform scale-125' /></h2>
<div className='flex justify-center mt-32'>
<img
onClick={onCopy}
className='w-full max-w-[160px]'
src="assets/images/barcode.jpg"
alt="barcode" />
</div>
<p className="text-body4 text-center mt-16">
Scan this code or copy the address below to login using Inurl-auth
</p>
<div className="input-wrapper mt-16 relative">
<input
className="input-field overflow-ellipsis"
value={"Inurldp-3234234-ahhsdfm-dssdf-uooiRS-TTRASssa-334Qaas-UUI"}
/>
<CopyToClipboard text='Inurldp-3234234-ahhsdfm-dssdf-uooiRS-TTRASssa-334Qaas-UUI' direction='top' />
</div>
</motion.div>
)
}

View File

@@ -0,0 +1,17 @@
import { ComponentStory, ComponentMeta } from '@storybook/react';
import Login_NativeWalletCard from './Login_NativeWalletCard';
import { ModalsDecorator } from '.storybook/helpers'
export default {
title: 'Login/Native Wallet Card',
component: Login_NativeWalletCard,
decorators: [ModalsDecorator]
} as ComponentMeta<typeof Login_NativeWalletCard>;
const Template: ComponentStory<typeof Login_NativeWalletCard> = (args) => <Login_NativeWalletCard {...args} />;
export const Default = Template.bind({});

View File

@@ -0,0 +1,51 @@
import { motion } from 'framer-motion'
import { Direction, ModalId, replaceModal } from 'src/redux/features/modals.slice';
import { useAppDispatch } from 'src/utils/hooks';
import { ModalCard, modalCardVariants } from 'src/Components/Modals/ModalsContainer/ModalsContainer'
import { IoLockClosed, } from 'react-icons/io5'
import Button from 'src/Components/Button/Button';
export default function Login_NativeWalletCard({ onClose, direction, ...props }: ModalCard) {
const dispatch = useAppDispatch();
const handleNext = () => {
dispatch(replaceModal({
modalId: ModalId.Login_ExternalWallet,
direction: Direction.NEXT
}))
}
return (
<motion.div
custom={direction}
variants={modalCardVariants}
initial='initial'
animate="animate"
exit='exit'
className="modal-card max-w-[343px] p-24 rounded-xl relative"
>
<div className="flex justify-center">
<img
src="assets/icons/lightning-big.svg"
className='w-80 h-80'
alt="lightning" />
</div>
<p className="text-body4 text-center mt-16">
<IoLockClosed className='align-middle' /> bolt.fun/maker
</p>
<div className="mt-32 text-center">
<h3 className="text-h4 font-bold">Login to this site?</h3>
<p className='text-body4 mt-8'>By clicking login, you allow ALBY wallet to anonymously login into bolt.fun/makers</p>
</div>
<div className="grid gap-16 grid-cols-2 mt-32">
<Button onClick={onClose}>Cancel</Button>
<Button color='primary' onClick={handleNext}>Login</Button>
</div>
</motion.div>
)
}

View File

@@ -0,0 +1,17 @@
import { ComponentStory, ComponentMeta } from '@storybook/react';
import Login_ScanningWalletCard from './Login_ScanningWalletCard';
import { ModalsDecorator } from '.storybook/helpers'
export default {
title: 'Login/Scanning Wallet Card',
component: Login_ScanningWalletCard,
decorators: [ModalsDecorator]
} as ComponentMeta<typeof Login_ScanningWalletCard>;
const Template: ComponentStory<typeof Login_ScanningWalletCard> = (args) => <Login_ScanningWalletCard {...args} />;
export const Default = Template.bind({});

View File

@@ -0,0 +1,53 @@
import { motion } from 'framer-motion'
import { Direction, ModalId, replaceModal } from 'src/redux/features/modals.slice';
import { useAppDispatch } from 'src/utils/hooks';
import { ModalCard, modalCardVariants } from 'src/Components/Modals/ModalsContainer/ModalsContainer'
import { AiFillThunderbolt } from 'react-icons/ai';
import Loader from 'react-loader-spinner';
import { useCallback, useEffect } from 'react';
import { IoClose } from 'react-icons/io5';
export default function Login_ScanningWalletCard({ onClose, direction, ...props }: ModalCard) {
const dispatch = useAppDispatch();
const handleNext = useCallback(() => {
dispatch(replaceModal({
modalId: ModalId.Login_NativeWallet,
direction: Direction.NEXT
}))
}, [dispatch])
useEffect(() => {
const timeout = setTimeout(handleNext, 3000)
return () => clearTimeout(timeout)
}, [handleNext])
return (
<motion.div
custom={direction}
variants={modalCardVariants}
initial='initial'
animate="animate"
exit='exit'
className="modal-card max-w-[343px] p-24 rounded-xl relative"
>
<IoClose className='absolute text-body2 top-24 right-24 hover:cursor-pointer' onClick={onClose} />
<h2 className='text-h5 font-bold'>Log in with Lightning <AiFillThunderbolt className='inline-block text-thunder transform scale-125' /></h2>
<div className="mt-24 py-24 ">
<div className="flex justify-center">
<Loader
type="Rings"
color="black"
height={60}
width={60}
/>
</div>
<p className="text-body5 text-center mt-24">
Scanning browser for native wallet...
</p>
</div>
</motion.div>
)
}

View File

@@ -0,0 +1,17 @@
import { ComponentStory, ComponentMeta } from '@storybook/react';
import Login_SuccessCard from './Login_SuccessCard';
import { ModalsDecorator } from '.storybook/helpers'
export default {
title: 'Login/Success Card',
component: Login_SuccessCard,
decorators: [ModalsDecorator]
} as ComponentMeta<typeof Login_SuccessCard>;
const Template: ComponentStory<typeof Login_SuccessCard> = (args) => <Login_SuccessCard {...args} />;
export const Default = Template.bind({});

View File

@@ -0,0 +1,49 @@
import { motion } from 'framer-motion'
import { useAppDispatch } from 'src/utils/hooks';
import { ModalCard, modalCardVariants } from 'src/Components/Modals/ModalsContainer/ModalsContainer'
import { useCallback, useEffect } from 'react';
import { closeModal, openSceduledModal } from 'src/redux/features/modals.slice';
import { connectWallet } from 'src/redux/features/wallet.slice';
export default function Login_SuccessCard({ onClose, direction, ...props }: ModalCard) {
const dispatch = useAppDispatch();
const handleNext = useCallback(() => {
dispatch(closeModal())
dispatch(openSceduledModal())
}, [dispatch])
useEffect(() => {
//dispatch(connectWallet());
const timeout = setTimeout(handleNext, 3000)
return () => clearTimeout(timeout)
}, [handleNext, dispatch])
return (
<motion.div
custom={direction}
variants={modalCardVariants}
initial='initial'
animate="animate"
exit='exit'
className="modal-card max-w-[343px] p-24 rounded-xl relative"
>
<h2 className='text-h5 font-bold'>Login success</h2>
<div className="flex justify-center my-32">
<img
src="assets/icons/success-icon.svg"
className='w-80 h-80'
alt="success" />
</div>
<p className="text-body4 text-center">
Welcome <span className="font-bold">bc104NhPs...2oGnSKTs</span>
</p>
</motion.div>
)
}

View File

@@ -0,0 +1,34 @@
import { motion } from "framer-motion";
import { ReactElement } from "react";
interface Props {
onClose: () => void;
children: ReactElement
[key: string]: any;
}
export default function Modal({ onClose, children, ...props }: Props) {
return (
<motion.div
initial={false}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
className='fixed w-full h-full items-center overflow-x-hidden no-scrollbar'
{...props}
>
<div
className='w-screen min-h-screen relative flex flex-col justify-center items-center md:py-64 md:px-16 overflow-x-hidden no-scrollbar'
>
<div
className={`absolute w-full h-full top-0 left-0 bg-gray-300 bg-opacity-50 ${props.isPageModal && "hidden md:block"}`}
onClick={onClose}
></div>
{children}
</div>
</motion.div>
)
}

View File

@@ -0,0 +1,125 @@
import { AnimatePresence, motion } from "framer-motion";
import { useEffect } from "react";
import { closeModal, Direction, ModalId, removeScheduledModal } from "src/redux/features/modals.slice";
import { useAppDispatch, useAppSelector } from "src/utils/hooks";
import Claim_CopySignatureCard from "src/pages/ProjectPage/ClaimProject/Claim_CopySignatureCard";
import Claim_GenerateSignatureCard from "src/pages/ProjectPage/ClaimProject/Claim_GenerateSignatureCard";
import Login_ExternalWalletCard from "src/Components/Modals/Login/Login_ExternalWalletCard";
import Login_NativeWalletCard from "src/Components/Modals/Login/Login_NativeWalletCard";
import Login_SuccessCard from "src/Components/Modals/Login/Login_SuccessCard";
import Login_ScanningWalletCard from "src/Components/Modals/Login/Login_ScanningWalletCard";
import ProjectCard from "src/pages/ProjectPage/ProjectCard/ProjectCard";
import TipCard from "src/pages/ProjectPage/Tip/TipCard";
import Modal from "../Modal/Modal";
import { Portal } from "../../Portal/Portal";
import Claim_SubmittedCard from "src/pages/ProjectPage/ClaimProject/Claim_SubmittedCard";
import Claim_FundWithdrawCard from "src/pages/ProjectPage/ClaimProject/Claim_FundWithdrawCard";
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.Login_ScanWallet:
return Login_ScanningWalletCard;
case ModalId.Login_NativeWallet:
return Login_NativeWalletCard;
case ModalId.Login_Success:
return Login_SuccessCard;
case ModalId.Login_ExternalWallet:
return Login_ExternalWalletCard;
case ModalId.Tip:
return TipCard;
case ModalId.Claim_GenerateSignature:
return Claim_GenerateSignatureCard;
case ModalId.Claim_CopySignature:
return Claim_CopySignatureCard;
case ModalId.Claim_Submitted:
return Claim_SubmittedCard;
case ModalId.Claim_FundWithdraw:
return Claim_FundWithdrawCard;
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(removeScheduledModal());
dispatch(closeModal());
}
useEffect(() => {
if (isOpen) document.body.style.overflowY = "hidden";
else document.body.style.overflowY = "initial";
}, [isOpen]);
return (
<Portal>
<AnimatePresence exitBeforeEnter>
{isOpen &&
<motion.div
className="w-screen fixed inset-0 overflow-x-hidden z-[2020]"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{
opacity: 0,
transition: { ease: "easeInOut" },
}}
>
<AnimatePresence>
{openModals.map(modal => {
const Child = ModalsMap(modal.modalId);
return (
<Modal key={modal.modalId} onClose={onClose} direction={direction} isPageModal={modal.isPageModal}>
<Child onClose={onClose} direction={direction} isPageModal={modal.isPageModal} {...modal.propsToPass} />
</Modal>)
})}
</AnimatePresence>
</motion.div>}
</AnimatePresence>
</Portal>
)
}