mirror of
https://github.com/vercel/commerce.git
synced 2025-03-14 22:42:33 +00:00
Correct UI State
This commit is contained in:
parent
83725b3434
commit
42eb79d81f
@ -1,17 +1,22 @@
|
||||
import useSignup from '@lib/bigcommerce/use-signup'
|
||||
import { Layout } from '@components/core'
|
||||
import { FC, useEffect } from 'react'
|
||||
import { Logo, Modal, Button } from '@components/ui'
|
||||
import useSignup from '@lib/bigcommerce/use-signup'
|
||||
import useLogin from '@lib/bigcommerce/use-login'
|
||||
import useLogout from '@lib/bigcommerce/use-logout'
|
||||
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 login = useLogin()
|
||||
const logout = useLogout()
|
||||
// Data about the currently logged in customer, it will update
|
||||
// automatically after a signup/login/logout
|
||||
const { data } = useCustomer()
|
||||
// // Data about the currently logged in customer, it will update
|
||||
// // automatically after a signup/login/logout
|
||||
// const { data } = useCustomer()
|
||||
// TODO: use this method. It can take more than 5 seconds to do a signup
|
||||
const handleSignup = async () => {
|
||||
// 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 (
|
||||
<div className="pb-20">
|
||||
<Modal close={() => {}}>
|
||||
<div className="h-80 w-80 flex flex-col justify-between py-3 px-3">
|
||||
<div className="flex justify-center pb-12 ">
|
||||
<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>
|
||||
<Modal open={open}>
|
||||
<div className="h-80 w-80 flex flex-col justify-between py-3 px-3">
|
||||
<div className="flex justify-center pb-12 ">
|
||||
<Logo width="64px" height="64px" />
|
||||
</div>
|
||||
</Modal>
|
||||
</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>
|
||||
</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 { Avatar } from '@components/core'
|
||||
import { useUI } from '@components/ui/context'
|
||||
import { LoginView } from '@components/auth'
|
||||
import DropdownMenu from './DropdownMenu'
|
||||
import { Menu } from '@headlessui/react'
|
||||
import useCart from '@lib/bigcommerce/cart/use-cart'
|
||||
|
||||
import useCustomer from '@lib/bigcommerce/use-customer'
|
||||
interface Props {
|
||||
className?: string
|
||||
}
|
||||
@ -19,9 +20,10 @@ const countItems = (count: number, items: any[]) =>
|
||||
|
||||
const UserNav: FC<Props> = ({ className, children, ...props }) => {
|
||||
const { data } = useCart()
|
||||
const { data: customer } = useCustomer()
|
||||
|
||||
const { openSidebar, closeSidebar, displaySidebar } = useUI()
|
||||
const itemsCount = Object.values(data?.line_items ?? {}).reduce(countItems, 0)
|
||||
|
||||
return (
|
||||
<nav className={cn(s.root, className)}>
|
||||
<div className={s.mainContainer}>
|
||||
@ -45,7 +47,11 @@ const UserNav: FC<Props> = ({ className, children, ...props }) => {
|
||||
<Menu.Button className={s.avatarButton} aria-label="Menu">
|
||||
<Avatar />
|
||||
</Menu.Button>
|
||||
<DropdownMenu open={open} />
|
||||
{customer ? (
|
||||
<DropdownMenu open={open} />
|
||||
) : (
|
||||
<LoginView open={open} />
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</Menu>
|
||||
|
@ -2,21 +2,21 @@ import cn from 'classnames'
|
||||
import { FC, useRef } from 'react'
|
||||
import s from './Modal.module.css'
|
||||
import { useDialog } from '@react-aria/dialog'
|
||||
import { useOverlay, useModal } from '@react-aria/overlays'
|
||||
import { FocusScope } from '@react-aria/focus'
|
||||
|
||||
import { Transition } from '@headlessui/react'
|
||||
import { useOverlay, useModal, OverlayContainer } from '@react-aria/overlays'
|
||||
interface Props {
|
||||
className?: string
|
||||
children?: any
|
||||
show?: boolean
|
||||
close: () => void
|
||||
open?: boolean
|
||||
onClose?: () => void
|
||||
}
|
||||
|
||||
const Modal: FC<Props> = ({
|
||||
className,
|
||||
children,
|
||||
show = true,
|
||||
close,
|
||||
open = false,
|
||||
onClose,
|
||||
...props
|
||||
}) => {
|
||||
const rootClassName = cn(s.root, className)
|
||||
@ -26,19 +26,32 @@ const Modal: FC<Props> = ({
|
||||
let { dialogProps } = useDialog(props, ref)
|
||||
|
||||
return (
|
||||
<div className={rootClassName}>
|
||||
<FocusScope contain restoreFocus autoFocus>
|
||||
<div
|
||||
{...overlayProps}
|
||||
{...dialogProps}
|
||||
{...modalProps}
|
||||
ref={ref}
|
||||
className={s.modal}
|
||||
>
|
||||
{children}
|
||||
<Transition show={open}>
|
||||
<OverlayContainer>
|
||||
<div className={rootClassName} onClick={onClose}>
|
||||
<FocusScope contain restoreFocus autoFocus>
|
||||
<Transition.Child
|
||||
enter="transition-opacity ease-linear duration-300"
|
||||
enterFrom="opacity-0"
|
||||
enterTo="opacity-100"
|
||||
leave="transition-opacity ease-linear duration-300"
|
||||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
>
|
||||
<div
|
||||
{...overlayProps}
|
||||
{...dialogProps}
|
||||
{...modalProps}
|
||||
ref={ref}
|
||||
className={s.modal}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
</Transition.Child>
|
||||
</FocusScope>
|
||||
</div>
|
||||
</FocusScope>
|
||||
</div>
|
||||
</OverlayContainer>
|
||||
</Transition>
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -5,11 +5,13 @@ import { SSRProvider, OverlayProvider } from 'react-aria'
|
||||
export interface State {
|
||||
displaySidebar: boolean
|
||||
displayDropdown: boolean
|
||||
displayModal: boolean
|
||||
}
|
||||
|
||||
const initialState = {
|
||||
displaySidebar: false,
|
||||
displayDropdown: false,
|
||||
displayModal: false,
|
||||
}
|
||||
|
||||
type Action =
|
||||
@ -25,6 +27,12 @@ type Action =
|
||||
| {
|
||||
type: 'CLOSE_DROPDOWN'
|
||||
}
|
||||
| {
|
||||
type: 'OPEN_MODAL'
|
||||
}
|
||||
| {
|
||||
type: 'CLOSE_MODAL'
|
||||
}
|
||||
|
||||
export const UIContext = React.createContext<State | any>(initialState)
|
||||
|
||||
@ -56,6 +64,18 @@ function uiReducer(state: State, action: Action) {
|
||||
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 closeDropdown = () => dispatch({ type: 'CLOSE_DROPDOWN' })
|
||||
|
||||
const openModal = () => dispatch({ type: 'OPEN_MODAL' })
|
||||
const closeModal = () => dispatch({ type: 'CLOSE_MODAL' })
|
||||
|
||||
const value = {
|
||||
...state,
|
||||
openSidebar,
|
||||
closeSidebar,
|
||||
openDropdown,
|
||||
closeDropdown,
|
||||
openModal,
|
||||
closeModal,
|
||||
}
|
||||
|
||||
console.log('state', state)
|
||||
|
||||
return <UIContext.Provider value={value} {...props} />
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user