mirror of
https://github.com/aljazceru/landscape-template.git
synced 2025-12-28 03:24:28 +01:00
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:
@@ -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({});
|
||||
|
||||
61
src/Components/Modals/Login/Login_ExternalWalletCard.tsx
Normal file
61
src/Components/Modals/Login/Login_ExternalWalletCard.tsx
Normal 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>
|
||||
)
|
||||
}
|
||||
@@ -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({});
|
||||
|
||||
51
src/Components/Modals/Login/Login_NativeWalletCard.tsx
Normal file
51
src/Components/Modals/Login/Login_NativeWalletCard.tsx
Normal 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>
|
||||
)
|
||||
}
|
||||
@@ -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({});
|
||||
|
||||
53
src/Components/Modals/Login/Login_ScanningWalletCard.tsx
Normal file
53
src/Components/Modals/Login/Login_ScanningWalletCard.tsx
Normal 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>
|
||||
)
|
||||
}
|
||||
17
src/Components/Modals/Login/Login_SuccessCard.stories.tsx
Normal file
17
src/Components/Modals/Login/Login_SuccessCard.stories.tsx
Normal 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({});
|
||||
|
||||
49
src/Components/Modals/Login/Login_SuccessCard.tsx
Normal file
49
src/Components/Modals/Login/Login_SuccessCard.tsx
Normal 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>
|
||||
)
|
||||
}
|
||||
34
src/Components/Modals/Modal/Modal.tsx
Normal file
34
src/Components/Modals/Modal/Modal.tsx
Normal 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>
|
||||
)
|
||||
}
|
||||
125
src/Components/Modals/ModalsContainer/ModalsContainer.tsx
Normal file
125
src/Components/Modals/ModalsContainer/ModalsContainer.tsx
Normal 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>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user