Files
web/src/app/(home)/@header/_client/provider.tsx

180 lines
5.5 KiB
TypeScript
Raw Normal View History

2025-03-28 15:00:46 +08:00
'use client'
import {createContext, ReactNode, useCallback, useContext, useEffect, useMemo, useState} from 'react'
2025-03-28 15:00:46 +08:00
import Link from 'next/link'
import Image from 'next/image'
import {LinkItem, MenuItem} from './navs'
import SolutionMenu from './solution'
import ProductMenu from './product'
import HelpMenu from './help'
import Wrap from '@/components/wrap'
import logo from '@/assets/logo.webp'
import {Button} from '@/components/ui/button'
import {useProfileStore} from '@/components/providers/StoreProvider'
import UserCenter from '@/components/composites/user-center'
2025-03-28 15:00:46 +08:00
export const HeaderContext = createContext<{
setMenu: (value: boolean) => void
} | null>(null)
export type ProviderProps = {}
2025-03-28 15:00:46 +08:00
export default function Provider(props: ProviderProps) {
// ======================
// 滚动条状态
// ======================
const [scroll, setScroll] = useState(false) // Changed to false for client-side rendering
const handleScroll = useCallback(() => {
setScroll(window.scrollY > 48)
}, [])
useEffect(() => {
// Initialize scroll state on client
setScroll(window.scrollY > 48)
window.addEventListener('scroll', handleScroll)
return () => {
window.removeEventListener('scroll', handleScroll)
}
}, [handleScroll])
// ======================
// 菜单状态
// ======================
const [menu, setMenu] = useState(false)
const [page, setPage] = useState(0)
const pages = useMemo(() => [
<ProductMenu key="product"/>,
<SolutionMenu key="solution"/>,
<HelpMenu key="help"/>,
2025-03-28 15:00:46 +08:00
], [])
// ======================
// 用户信息
// ======================
const profile = useProfileStore(store => store.profile)
// ======================
// render
2025-03-28 15:00:46 +08:00
// ======================
return (
<HeaderContext.Provider value={{setMenu}}>
<div className={[
`transition-[background, shadow] duration-200 ease-in-out`,
menu
? `bg-[#fffe] backdrop-blur-sm`
: scroll
? `bg-[#fffe] backdrop-blur-sm shadow-lg`
: `bg-transparent shadow-none`,
].join(' ')}>
<Wrap className="h-20 max-md:h-16 flex justify-between">
<div className="flex justify-between gap-8">
{/* logo */}
<Link href="/" className="flex items-center">
<Image src={logo} alt="logo" height={40} className="translate-y-0.5"/>
2025-03-28 15:00:46 +08:00
</Link>
{/* 菜单 */}
<nav>
<ul className="h-full flex items-stretch max-lg:hidden">
<LinkItem text="首页" href="/"/>
2025-03-28 15:00:46 +08:00
<MenuItem
text="产品订购"
2025-03-28 15:00:46 +08:00
active={menu && page === 0}
onEnter={() => {
setMenu(true)
setPage(0)
}}
onLeave={() => {
return setMenu(false)
}}
/>
<MenuItem
text="业务场景"
2025-03-28 15:00:46 +08:00
active={menu && page === 1}
onEnter={() => {
setMenu(true)
setPage(1)
}}
onLeave={() => {
return setMenu(false)
}}
/>
<MenuItem
text="帮助中心"
2025-03-28 15:00:46 +08:00
active={menu && page === 2}
onEnter={() => {
setMenu(true)
setPage(2)
}}
onLeave={() => {
return setMenu(false)
}}
/>
<LinkItem
text="企业服务"
href="#"/>
2025-03-28 15:00:46 +08:00
<LinkItem
text="推广返利"
href="#"/>
2025-03-28 15:00:46 +08:00
</ul>
</nav>
</div>
{/* 登录 */}
<div className="flex items-center">
{profile == undefined
? (
<>
<Link
href="/login"
className="w-24 h-12 flex items-center justify-center lg:text-lg"
>
<span></span>
</Link>
<Link
href="/login"
className={[
`w-20 lg:w-24 h-10 lg:h-12 bg-gradient-to-r rounded-sm flex items-center justify-center lg:text-lg text-white`,
`transition-colors duration-200 ease-in-out`,
`from-blue-500 to-cyan-400 hover:from-blue-500 hover:to-cyan-300`,
].join(' ')}
>
<span></span>
</Link>
</>
)
: (
// <Link href="/admin">
// <Button theme="gradient" className="h-12">
// 进入控制台
// </Button>
// </Link>
<UserCenter/>
)
}
</div>
2025-03-28 15:00:46 +08:00
</Wrap>
</div>
{/* 下拉菜单 */}
<div
className={[
`shadow-lg`,
`overflow-hidden bg-[#fffe] backdrop-blur-sm`,
`transition-[opacity,padding,height] transition-discrete duration-200 ease-in-out`,
menu
? `delay-[0s,0s,0s] opacity-100 py-8 h-auto`
: `delay-[0s,0s,0.2s] opacity-0 py-0 h-0`,
].join(' ')}
onPointerEnter={() => setMenu(true)}
onPointerLeave={() => setMenu(false)}
>
{pages[page]}
</div>
</HeaderContext.Provider>
)
}