mirror of
https://github.com/vercel/commerce.git
synced 2025-07-22 20:26:49 +00:00
✨ feat: show message common
:%s
This commit is contained in:
@@ -1,35 +1,16 @@
|
|||||||
import { Layout, MessageCommon } from 'src/components/common'
|
import { Layout } from 'src/components/common'
|
||||||
import { MessageItemProps } from 'src/components/common/MessageCommon/MessageItem/MessageItem'
|
import { useMessage } from 'src/components/contexts'
|
||||||
|
|
||||||
const data: MessageItemProps[] = [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
content: 'Create account successfully',
|
|
||||||
type: 'error',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
content: 'Create account successfully',
|
|
||||||
type: 'success',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
content: 'Create account successfully',
|
|
||||||
type: 'warning',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
content: 'Create account successfully',
|
|
||||||
type: 'info',
|
|
||||||
},
|
|
||||||
]
|
|
||||||
export default function Test() {
|
export default function Test() {
|
||||||
|
const { showMessageSuccess } = useMessage()
|
||||||
|
|
||||||
|
const handleClick = () => {
|
||||||
|
showMessageSuccess("Create account successfully")
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<MessageCommon messages={data} />
|
<button onClick={handleClick}>Click me</button>
|
||||||
{/* <MessageCommon type='error'>Create account successfully</MessageCommon>
|
|
||||||
<MessageCommon type='info'>Create account successfully</MessageCommon>
|
|
||||||
<MessageCommon type='warning'>Create account successfully</MessageCommon> */}
|
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@@ -1,25 +1,24 @@
|
|||||||
import { CommerceProvider } from '@framework'
|
import { CommerceProvider } from '@framework'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import { FC } from 'react'
|
import { FC } from 'react'
|
||||||
import { CartDrawerProvider } from 'src/components/contexts'
|
import { CartDrawerProvider, MessageProvider } from 'src/components/contexts'
|
||||||
import LayoutContent from './LayoutContent/LayoutContent'
|
import LayoutContent from './LayoutContent/LayoutContent'
|
||||||
interface Props {
|
interface Props {
|
||||||
className?: string
|
className?: string
|
||||||
children?: any
|
children?: any
|
||||||
}
|
}
|
||||||
|
|
||||||
const Layout: FC<Props> = ({ children }) => {
|
const Layout: FC<Props> = ({ children }) => {
|
||||||
const { locale = 'en-US' } = useRouter()
|
const { locale = 'en-US' } = useRouter()
|
||||||
return (
|
return (
|
||||||
<CommerceProvider locale={locale}>
|
<CommerceProvider locale={locale}>
|
||||||
<CartDrawerProvider>
|
<CartDrawerProvider>
|
||||||
<LayoutContent>
|
<MessageProvider>
|
||||||
{children}
|
<LayoutContent>{children}</LayoutContent>
|
||||||
</LayoutContent>
|
</MessageProvider>
|
||||||
</CartDrawerProvider>
|
</CartDrawerProvider>
|
||||||
</CommerceProvider>
|
</CommerceProvider>
|
||||||
|
)
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Layout
|
export default Layout
|
||||||
|
@@ -1,8 +1,9 @@
|
|||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import { FC } from 'react'
|
import { FC } from 'react'
|
||||||
|
import { useMessage } from 'src/components/contexts'
|
||||||
import { useModalCommon } from 'src/components/hooks'
|
import { useModalCommon } from 'src/components/hooks'
|
||||||
import { BRAND, CATEGORY, FEATURED, FILTER_PAGE, ROUTE } from 'src/utils/constanst.utils'
|
import { BRAND, CATEGORY, FEATURED, FILTER_PAGE, ROUTE } from 'src/utils/constanst.utils'
|
||||||
import { CartDrawer, Footer, ScrollToTop } from '../..'
|
import { CartDrawer, Footer, MessageCommon, ScrollToTop } from '../..'
|
||||||
import Header from '../../Header/Header'
|
import Header from '../../Header/Header'
|
||||||
import MenuNavigationProductList from '../../MenuNavigationProductList/MenuNavigationProductList'
|
import MenuNavigationProductList from '../../MenuNavigationProductList/MenuNavigationProductList'
|
||||||
import s from './LayoutContent.module.scss'
|
import s from './LayoutContent.module.scss'
|
||||||
@@ -16,6 +17,7 @@ const LayoutContent: FC<Props> = ({ children }) => {
|
|||||||
const { pathname } = useRouter()
|
const { pathname } = useRouter()
|
||||||
const { visible: visibleFilter, openModal: openFilter, closeModal: closeFilter } = useModalCommon({ initialValue: false })
|
const { visible: visibleFilter, openModal: openFilter, closeModal: closeFilter } = useModalCommon({ initialValue: false })
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const {messages, removeMessage} = useMessage()
|
||||||
|
|
||||||
const toggleFilter = () => {
|
const toggleFilter = () => {
|
||||||
if (visibleFilter) {
|
if (visibleFilter) {
|
||||||
@@ -44,6 +46,7 @@ const LayoutContent: FC<Props> = ({ children }) => {
|
|||||||
<Footer />
|
<Footer />
|
||||||
</div>
|
</div>
|
||||||
<CartDrawer />
|
<CartDrawer />
|
||||||
|
<MessageCommon messages={messages} onRemove={removeMessage}/>
|
||||||
</>
|
</>
|
||||||
|
|
||||||
)
|
)
|
||||||
|
@@ -1,21 +1,29 @@
|
|||||||
import React, { memo } from 'react'
|
import React, { memo, useEffect } from 'react'
|
||||||
import s from './MessageCommon.module.scss'
|
import s from './MessageCommon.module.scss'
|
||||||
import MessageItem, { MessageItemProps } from './MessageItem/MessageItem'
|
import MessageItem, { MessageItemProps } from './MessageItem/MessageItem'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
messages: MessageItemProps[]
|
messages: MessageItemProps[]
|
||||||
onRemove?: (id?: number) => void
|
onRemove?: (id: number) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const MessageCommon = memo(({ messages, onRemove }: Props) => {
|
const MessageCommon = memo(({ messages, onRemove }: Props) => {
|
||||||
|
useEffect(() => {
|
||||||
|
console.log("this fun change; onRemove")
|
||||||
|
}, [onRemove])
|
||||||
|
|
||||||
|
const handleRemove = (id: number) => {
|
||||||
|
onRemove && onRemove(id)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={s.messageCommon}>
|
<div className={s.messageCommon}>
|
||||||
{messages.map((item) => (
|
{messages.reverse().map((item) => (
|
||||||
<MessageItem
|
<MessageItem
|
||||||
key={item.id}
|
key={item.id}
|
||||||
id={item.id}
|
id={item.id}
|
||||||
content={item.content}
|
content={item.content}
|
||||||
onRemove={onRemove}
|
onRemove={handleRemove}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
@@ -53,7 +53,7 @@
|
|||||||
|
|
||||||
@keyframes showMessage {
|
@keyframes showMessage {
|
||||||
0% {
|
0% {
|
||||||
transform: translateY(-6rem);
|
transform: translateY(-2rem);
|
||||||
opacity: .5;
|
opacity: .5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -8,7 +8,7 @@ export interface MessageItemProps {
|
|||||||
content?: React.ReactNode
|
content?: React.ReactNode
|
||||||
type?: 'info' | 'success' | 'error' | 'warning'
|
type?: 'info' | 'success' | 'error' | 'warning'
|
||||||
timeout?: number
|
timeout?: number
|
||||||
onRemove?: (id?: number) => void
|
onRemove?: (id: number) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const MessageItem = memo(
|
const MessageItem = memo(
|
||||||
@@ -40,7 +40,7 @@ const MessageItem = memo(
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isHide && !isMouseOver && onRemove) {
|
if (isHide && !isMouseOver && onRemove) {
|
||||||
onRemove(id)
|
onRemove(id || 0)
|
||||||
}
|
}
|
||||||
}, [isHide, isMouseOver, onRemove, id])
|
}, [isHide, isMouseOver, onRemove, id])
|
||||||
|
|
||||||
|
27
src/components/contexts/Message/MessageContext.tsx
Normal file
27
src/components/contexts/Message/MessageContext.tsx
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import { createContext, useContext } from 'react'
|
||||||
|
import { MessageItemProps } from 'src/components/common/MessageCommon/MessageItem/MessageItem'
|
||||||
|
|
||||||
|
export type MessageContextType = {
|
||||||
|
messages: MessageItemProps[]
|
||||||
|
removeMessage: (id: number) => void
|
||||||
|
showMessageSuccess: (content: string, timeout?: number) => void
|
||||||
|
showMessageInfo: (content: string, timeout?: number) => void
|
||||||
|
showMessageError: (content: string, timeout?: number) => void
|
||||||
|
showMessageWarning: (content: string, timeout?: number) => void
|
||||||
|
}
|
||||||
|
export const DEFAULT_MESSAGE_CONTEXT: MessageContextType = {
|
||||||
|
messages: [],
|
||||||
|
removeMessage: () => {},
|
||||||
|
showMessageSuccess: () => {},
|
||||||
|
showMessageInfo: () => {},
|
||||||
|
showMessageError: () => {},
|
||||||
|
showMessageWarning: () => {},
|
||||||
|
}
|
||||||
|
|
||||||
|
export const MessageContext = createContext<MessageContextType>(
|
||||||
|
DEFAULT_MESSAGE_CONTEXT
|
||||||
|
)
|
||||||
|
|
||||||
|
export function useMessage() {
|
||||||
|
return useContext(MessageContext)
|
||||||
|
}
|
67
src/components/contexts/Message/MessageProvider.tsx
Normal file
67
src/components/contexts/Message/MessageProvider.tsx
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
import { ReactNode, useCallback, useState } from 'react'
|
||||||
|
import { MessageItemProps } from 'src/components/common/MessageCommon/MessageItem/MessageItem'
|
||||||
|
import { MessageContext } from './MessageContext'
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
children: ReactNode
|
||||||
|
}
|
||||||
|
|
||||||
|
export function MessageProvider({ children }: Props) {
|
||||||
|
const [currentId, setCurrentId] = useState<number>(0)
|
||||||
|
const [messages, setMessages] = useState<MessageItemProps[]>([])
|
||||||
|
|
||||||
|
const createNewMessage = (
|
||||||
|
content: string,
|
||||||
|
timeout?: number,
|
||||||
|
type?: 'info' | 'success' | 'error' | 'warning'
|
||||||
|
) => {
|
||||||
|
const item: MessageItemProps = {
|
||||||
|
id: currentId + 1,
|
||||||
|
content: currentId + 1 + content,
|
||||||
|
type,
|
||||||
|
timeout,
|
||||||
|
}
|
||||||
|
setCurrentId(currentId + 1)
|
||||||
|
setMessages([...messages, item])
|
||||||
|
}
|
||||||
|
|
||||||
|
const showMessageSuccess = (content: string, timeout?: number) => {
|
||||||
|
createNewMessage(content, timeout, 'success')
|
||||||
|
}
|
||||||
|
|
||||||
|
const showMessageInfo = (content: string, timeout?: number) => {
|
||||||
|
createNewMessage(content, timeout, 'info')
|
||||||
|
}
|
||||||
|
|
||||||
|
const showMessageError = (content: string, timeout?: number) => {
|
||||||
|
createNewMessage(content, timeout, 'error')
|
||||||
|
}
|
||||||
|
|
||||||
|
const showMessageWarning = (content: string, timeout?: number) => {
|
||||||
|
createNewMessage(content, timeout, 'warning')
|
||||||
|
}
|
||||||
|
|
||||||
|
const removeMessage = (id: number) => {
|
||||||
|
const newMessages = messages.filter((item) => item.id !== id)
|
||||||
|
setMessages(newMessages)
|
||||||
|
|
||||||
|
if (newMessages.length === 0) {
|
||||||
|
setCurrentId(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MessageContext.Provider
|
||||||
|
value={{
|
||||||
|
messages,
|
||||||
|
removeMessage,
|
||||||
|
showMessageSuccess,
|
||||||
|
showMessageInfo,
|
||||||
|
showMessageError,
|
||||||
|
showMessageWarning,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</MessageContext.Provider>
|
||||||
|
)
|
||||||
|
}
|
@@ -1,2 +1,5 @@
|
|||||||
export * from './CartDrawer/CartDrawerContext'
|
export * from './CartDrawer/CartDrawerContext'
|
||||||
export * from './CartDrawer/CartDrawerProvider'
|
export * from './CartDrawer/CartDrawerProvider'
|
||||||
|
|
||||||
|
export * from './Message/MessageContext'
|
||||||
|
export * from './Message/MessageProvider'
|
||||||
|
Reference in New Issue
Block a user