forked from crowetic/commerce
Correct UI State
This commit is contained in:
parent
83725b3434
commit
42eb79d81f
@ -1,17 +1,22 @@
|
|||||||
import useSignup from '@lib/bigcommerce/use-signup'
|
import { FC, useEffect } from 'react'
|
||||||
import { Layout } from '@components/core'
|
|
||||||
import { Logo, Modal, Button } from '@components/ui'
|
import { Logo, Modal, Button } from '@components/ui'
|
||||||
|
import useSignup from '@lib/bigcommerce/use-signup'
|
||||||
import useLogin from '@lib/bigcommerce/use-login'
|
import useLogin from '@lib/bigcommerce/use-login'
|
||||||
import useLogout from '@lib/bigcommerce/use-logout'
|
import useLogout from '@lib/bigcommerce/use-logout'
|
||||||
import useCustomer from '@lib/bigcommerce/use-customer'
|
import useCustomer from '@lib/bigcommerce/use-customer'
|
||||||
|
import { useUI } from '@components/ui/context'
|
||||||
|
|
||||||
export default function Login() {
|
interface Props {
|
||||||
|
open: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
const LoginView: FC<Props> = ({ open }) => {
|
||||||
const signup = useSignup()
|
const signup = useSignup()
|
||||||
const login = useLogin()
|
const login = useLogin()
|
||||||
const logout = useLogout()
|
const logout = useLogout()
|
||||||
// Data about the currently logged in customer, it will update
|
// // Data about the currently logged in customer, it will update
|
||||||
// automatically after a signup/login/logout
|
// // automatically after a signup/login/logout
|
||||||
const { data } = useCustomer()
|
// const { data } = useCustomer()
|
||||||
// TODO: use this method. It can take more than 5 seconds to do a signup
|
// TODO: use this method. It can take more than 5 seconds to do a signup
|
||||||
const handleSignup = async () => {
|
const handleSignup = async () => {
|
||||||
// TODO: validate the password and email before calling the signup
|
// TODO: validate the password and email before calling the signup
|
||||||
@ -51,41 +56,44 @@ export default function Login() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { openModal, closeModal } = useUI()
|
||||||
|
useEffect(() => {
|
||||||
|
open ? openModal() : closeModal()
|
||||||
|
}, [open])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="pb-20">
|
<Modal open={open}>
|
||||||
<Modal close={() => {}}>
|
<div className="h-80 w-80 flex flex-col justify-between py-3 px-3">
|
||||||
<div className="h-80 w-80 flex flex-col justify-between py-3 px-3">
|
<div className="flex justify-center pb-12 ">
|
||||||
<div className="flex justify-center pb-12 ">
|
<Logo width="64px" height="64px" />
|
||||||
<Logo width="64px" height="64px" />
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-col space-y-3">
|
|
||||||
<div className="border border-accents-3 text-accents-6">
|
|
||||||
<input
|
|
||||||
placeholder="Email"
|
|
||||||
className="focus:outline-none bg-primary focus:shadow-outline-gray border-none py-2 px-6 w-full appearance-none transition duration-150 ease-in-out placeholder-accents-5 pr-10"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="border border-accents-3 text-accents-6">
|
|
||||||
<input
|
|
||||||
placeholder="Password"
|
|
||||||
className="bg-primary focus:outline-none focus:shadow-outline-gray border-none py-2 px-6 w-full appearance-none transition duration-150 ease-in-out placeholder-accents-5 pr-10"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<Button variant="slim" onClick={handleSignup}>
|
|
||||||
Log In
|
|
||||||
</Button>
|
|
||||||
<span className="pt-3 text-center text-sm">
|
|
||||||
<span className="text-accents-7">Don't have an account?</span>
|
|
||||||
{` `}
|
|
||||||
<a className="text-accent-9 font-bold hover:underline cursor-pointer">
|
|
||||||
Sign Up
|
|
||||||
</a>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</Modal>
|
<div className="flex flex-col space-y-3">
|
||||||
</div>
|
<div className="border border-accents-3 text-accents-6">
|
||||||
|
<input
|
||||||
|
placeholder="Email"
|
||||||
|
className="focus:outline-none bg-primary focus:shadow-outline-gray border-none py-2 px-6 w-full appearance-none transition duration-150 ease-in-out placeholder-accents-5 pr-10"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="border border-accents-3 text-accents-6">
|
||||||
|
<input
|
||||||
|
placeholder="Password"
|
||||||
|
className="bg-primary focus:outline-none focus:shadow-outline-gray border-none py-2 px-6 w-full appearance-none transition duration-150 ease-in-out placeholder-accents-5 pr-10"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<Button variant="slim" onClick={handleSignup}>
|
||||||
|
Log In
|
||||||
|
</Button>
|
||||||
|
<span className="pt-3 text-center text-sm">
|
||||||
|
<span className="text-accents-7">Don't have an account?</span>
|
||||||
|
{` `}
|
||||||
|
<a className="text-accent-9 font-bold hover:underline cursor-pointer">
|
||||||
|
Sign Up
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Login.Layout = Layout
|
export default LoginView
|
1
components/auth/index.ts
Normal file
1
components/auth/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { default as LoginView } from './LoginView'
|
@ -5,10 +5,11 @@ import { FC } from 'react'
|
|||||||
import { Heart, Bag } from '@components/icon'
|
import { Heart, Bag } from '@components/icon'
|
||||||
import { Avatar } from '@components/core'
|
import { Avatar } from '@components/core'
|
||||||
import { useUI } from '@components/ui/context'
|
import { useUI } from '@components/ui/context'
|
||||||
|
import { LoginView } from '@components/auth'
|
||||||
import DropdownMenu from './DropdownMenu'
|
import DropdownMenu from './DropdownMenu'
|
||||||
import { Menu } from '@headlessui/react'
|
import { Menu } from '@headlessui/react'
|
||||||
import useCart from '@lib/bigcommerce/cart/use-cart'
|
import useCart from '@lib/bigcommerce/cart/use-cart'
|
||||||
|
import useCustomer from '@lib/bigcommerce/use-customer'
|
||||||
interface Props {
|
interface Props {
|
||||||
className?: string
|
className?: string
|
||||||
}
|
}
|
||||||
@ -19,9 +20,10 @@ const countItems = (count: number, items: any[]) =>
|
|||||||
|
|
||||||
const UserNav: FC<Props> = ({ className, children, ...props }) => {
|
const UserNav: FC<Props> = ({ className, children, ...props }) => {
|
||||||
const { data } = useCart()
|
const { data } = useCart()
|
||||||
|
const { data: customer } = useCustomer()
|
||||||
|
|
||||||
const { openSidebar, closeSidebar, displaySidebar } = useUI()
|
const { openSidebar, closeSidebar, displaySidebar } = useUI()
|
||||||
const itemsCount = Object.values(data?.line_items ?? {}).reduce(countItems, 0)
|
const itemsCount = Object.values(data?.line_items ?? {}).reduce(countItems, 0)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<nav className={cn(s.root, className)}>
|
<nav className={cn(s.root, className)}>
|
||||||
<div className={s.mainContainer}>
|
<div className={s.mainContainer}>
|
||||||
@ -45,7 +47,11 @@ const UserNav: FC<Props> = ({ className, children, ...props }) => {
|
|||||||
<Menu.Button className={s.avatarButton} aria-label="Menu">
|
<Menu.Button className={s.avatarButton} aria-label="Menu">
|
||||||
<Avatar />
|
<Avatar />
|
||||||
</Menu.Button>
|
</Menu.Button>
|
||||||
<DropdownMenu open={open} />
|
{customer ? (
|
||||||
|
<DropdownMenu open={open} />
|
||||||
|
) : (
|
||||||
|
<LoginView open={open} />
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</Menu>
|
</Menu>
|
||||||
|
@ -2,21 +2,21 @@ import cn from 'classnames'
|
|||||||
import { FC, useRef } from 'react'
|
import { FC, useRef } from 'react'
|
||||||
import s from './Modal.module.css'
|
import s from './Modal.module.css'
|
||||||
import { useDialog } from '@react-aria/dialog'
|
import { useDialog } from '@react-aria/dialog'
|
||||||
import { useOverlay, useModal } from '@react-aria/overlays'
|
|
||||||
import { FocusScope } from '@react-aria/focus'
|
import { FocusScope } from '@react-aria/focus'
|
||||||
|
import { Transition } from '@headlessui/react'
|
||||||
|
import { useOverlay, useModal, OverlayContainer } from '@react-aria/overlays'
|
||||||
interface Props {
|
interface Props {
|
||||||
className?: string
|
className?: string
|
||||||
children?: any
|
children?: any
|
||||||
show?: boolean
|
open?: boolean
|
||||||
close: () => void
|
onClose?: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const Modal: FC<Props> = ({
|
const Modal: FC<Props> = ({
|
||||||
className,
|
className,
|
||||||
children,
|
children,
|
||||||
show = true,
|
open = false,
|
||||||
close,
|
onClose,
|
||||||
...props
|
...props
|
||||||
}) => {
|
}) => {
|
||||||
const rootClassName = cn(s.root, className)
|
const rootClassName = cn(s.root, className)
|
||||||
@ -26,19 +26,32 @@ const Modal: FC<Props> = ({
|
|||||||
let { dialogProps } = useDialog(props, ref)
|
let { dialogProps } = useDialog(props, ref)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={rootClassName}>
|
<Transition show={open}>
|
||||||
<FocusScope contain restoreFocus autoFocus>
|
<OverlayContainer>
|
||||||
<div
|
<div className={rootClassName} onClick={onClose}>
|
||||||
{...overlayProps}
|
<FocusScope contain restoreFocus autoFocus>
|
||||||
{...dialogProps}
|
<Transition.Child
|
||||||
{...modalProps}
|
enter="transition-opacity ease-linear duration-300"
|
||||||
ref={ref}
|
enterFrom="opacity-0"
|
||||||
className={s.modal}
|
enterTo="opacity-100"
|
||||||
>
|
leave="transition-opacity ease-linear duration-300"
|
||||||
{children}
|
leaveFrom="opacity-100"
|
||||||
|
leaveTo="opacity-0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
{...overlayProps}
|
||||||
|
{...dialogProps}
|
||||||
|
{...modalProps}
|
||||||
|
ref={ref}
|
||||||
|
className={s.modal}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
</Transition.Child>
|
||||||
|
</FocusScope>
|
||||||
</div>
|
</div>
|
||||||
</FocusScope>
|
</OverlayContainer>
|
||||||
</div>
|
</Transition>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,11 +5,13 @@ import { SSRProvider, OverlayProvider } from 'react-aria'
|
|||||||
export interface State {
|
export interface State {
|
||||||
displaySidebar: boolean
|
displaySidebar: boolean
|
||||||
displayDropdown: boolean
|
displayDropdown: boolean
|
||||||
|
displayModal: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
displaySidebar: false,
|
displaySidebar: false,
|
||||||
displayDropdown: false,
|
displayDropdown: false,
|
||||||
|
displayModal: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
type Action =
|
type Action =
|
||||||
@ -25,6 +27,12 @@ type Action =
|
|||||||
| {
|
| {
|
||||||
type: 'CLOSE_DROPDOWN'
|
type: 'CLOSE_DROPDOWN'
|
||||||
}
|
}
|
||||||
|
| {
|
||||||
|
type: 'OPEN_MODAL'
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: 'CLOSE_MODAL'
|
||||||
|
}
|
||||||
|
|
||||||
export const UIContext = React.createContext<State | any>(initialState)
|
export const UIContext = React.createContext<State | any>(initialState)
|
||||||
|
|
||||||
@ -56,6 +64,18 @@ function uiReducer(state: State, action: Action) {
|
|||||||
displayDropdown: false,
|
displayDropdown: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case 'OPEN_MODAL': {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
displayModal: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 'CLOSE_MODAL': {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
displayModal: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,14 +88,21 @@ export const UIProvider: FC = (props) => {
|
|||||||
const openDropdown = () => dispatch({ type: 'OPEN_DROPDOWN' })
|
const openDropdown = () => dispatch({ type: 'OPEN_DROPDOWN' })
|
||||||
const closeDropdown = () => dispatch({ type: 'CLOSE_DROPDOWN' })
|
const closeDropdown = () => dispatch({ type: 'CLOSE_DROPDOWN' })
|
||||||
|
|
||||||
|
const openModal = () => dispatch({ type: 'OPEN_MODAL' })
|
||||||
|
const closeModal = () => dispatch({ type: 'CLOSE_MODAL' })
|
||||||
|
|
||||||
const value = {
|
const value = {
|
||||||
...state,
|
...state,
|
||||||
openSidebar,
|
openSidebar,
|
||||||
closeSidebar,
|
closeSidebar,
|
||||||
openDropdown,
|
openDropdown,
|
||||||
closeDropdown,
|
closeDropdown,
|
||||||
|
openModal,
|
||||||
|
closeModal,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log('state', state)
|
||||||
|
|
||||||
return <UIContext.Provider value={value} {...props} />
|
return <UIContext.Provider value={value} {...props} />
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user