「10」next-shopping:admin页面布局、用户组件调整

我们先来调整一下C端页面,把app/(normal-layout) 改名叫app/(client-layout),虽然对实际没有影响,但是对开发者更好识别

我们现在可以把layout抽成通用的:

新建components/Layouts/ClientLayout.jsx

jsx 复制代码
import { Navbar } from '@/components'

export default function Layout({ children }) {
  return (
    <>
      <Navbar />
      {children}
    </>
  )
}

这是客户端的页面通用布局,header部分需要nav

新建components/Layouts/DashboardLayout.jsx

jsx 复制代码
export default function Layout({ children }) {
  return <div>{children} </div>
}

目前仅最简单的包一层,后面会添加Nav和Footer的

新建components/Layouts/ProfileLayout.jsx

jsx 复制代码
export default function Layout({ children }) {
  return <div>{children}</div>
}

这个个人中心也是组简单的布局

在components/index.js中导出

jsx 复制代码
export { default as Icons } from './share/Icons'
export { default as Loading } from './share/Loading'
export { default as DisplayError } from './share/DisplayError'
export { default as Navbar } from './Navbar'
export { default as User } from './User'
export { default as Cart } from './Cart'
export { default as Search } from './Search'
export { default as ClientLayout } from './Layouts/ClientLayout'
export { default as DashboardLayout } from './Layouts/DashboardLayout'
export { default as ProfileLayout } from './Layouts/ProfileLayout'

然后我们用ClientLayout来代替app/(main)/(client-layout)/layout.js的布局

jsx 复制代码
'use client'

import { ClientLayout } from '@/components'
import { useRefreshToken } from '@/hooks'

export default function Layout({ children }) {
  useRefreshToken()
  return (
    <>
      <ClientLayout>{children}</ClientLayout>
    </>
  )
}

效果如下:

然后我们新建app/(dashboard-layout)/layout.js

jsx 复制代码
'use client'

import { DashboardLayout } from '@/components'

export default function Layout({ children }) {
  return (
    <>
      <DashboardLayout>{children}</DashboardLayout>
    </>
  )
}

新建app/(dashboard-layout)/dashboard/page.jsx

jsx 复制代码
export default function Page() {
  return <div>这是管理页面</div>
}

效果如下:

注销页面

我们先来实现两个通用组件BoxLink和ArrowLink

新建components/share/BoxLink.jsx

jsx 复制代码
import Link from 'next/link'
import { useRouter } from 'next/navigation'
import { Icons } from '@/components'

export default function BoxLink({ children, path, name }) {
  const router = useRouter()

  return (
    <div
      className={`transition-colors hover:bg-gray-200 px-3 ${
        router.asPath === path ? 'border-r-4 border-red-600' : 'border-r-4 border-white'
      }`}
    >
      <Link href={path}>
        <span className="flex justify-between mx-4 py-4 gap-x-2 border-t border-gray-300">
          {children}
          <span className="ml-auto mr-3">{name}</span>
          <Icons.ArrowLeft className="icon" />
        </span>
      </Link>
    </div>
  )
}

新建components/share/ArrowLink.jsx

jsx 复制代码
import Link from 'next/link'
import { Icons } from '@/components'

export default function ArrowLink({ children, path }) {
  return (
    <Link href={path}>
      <span className="inline-flex items-center text-blue-400 text-sm max-w-max">
        <span className="uppercase">{children}</span>
        <Icons.ArrowLeft className="icon text-blue-400" />
      </span>
    </Link>
  )
}

然后我们来写退出登录组件:

新建components/Logout.jsx

jsx 复制代码
import { useRouter } from 'next/navigation'
import { useDispatch } from 'react-redux'
import { userLogout } from '@/store/slices/authSlice'
import { Icons } from '@/components'
import alert from '@/utils/alert'

export default function Logout() {
  const dispatch = useDispatch()
  const router = useRouter()

  const handleLogout = () => {
    router.push('/')
    dispatch(userLogout())
    alert('success', '退出成功')
  }

  return (
    <div className="transition-colors hover:bg-gray-200 px-3">
      <div
        role="button"
        className="flex justify-between cursor-pointer py-4 gap-x-2 mx-4  border-t border-gray-300"
        onClick={() => handleLogout()}
      >
        <Icons.Logout className="icon text-black" />
        <span className="ml-auto mr-3">其他组织者</span>
      </div>
    </div>
  )
}

先在components/index.js中导出组件:

jsx 复制代码
export { default as Icons } from './share/Icons'
export { default as Loading } from './share/Loading'
export { default as DisplayError } from './share/DisplayError'
export { default as Navbar } from './Navbar'
export { default as User } from './User'
export { default as Cart } from './Cart'
export { default as Search } from './Search'
export { default as ClientLayout } from './Layouts/ClientLayout'
export { default as DashboardLayout } from './Layouts/DashboardLayout'
export { default as ProfileLayout } from './Layouts/ProfileLayout'
export { default as ArrowLink } from './share/ArrowLink'
export { default as BoxLink } from './share/BoxLink'
export { default as Logout } from './Lagout'

现在来修改User组件,我们先看看当前的效果:

修改components/User.jsx

jsx 复制代码
import Image from 'next/image'
import Link from 'next/link'
import { useState } from 'react'

import { useSelector } from 'react-redux'
import { BoxLink, Icons, Logout } from './index'

export default function User() {
  const { user } = useSelector(state => state.auth)

  const [isOpen, setIsOpen] = useState(false)

  if (!user) {
    return (
      <div className="flex items-center gap-x-2 lg:border lg:border-gray-300 lg:rounded-md lg:py-2 lg:px-3 text-sm">
        <Link href="/login">
          <span className="flex items-center gap-x-1">
            <Icons.Login className="icon" />
            登录
          </span>
        </Link>
        <span className="hidden lg:block lg:border lg:border-gray-300 lg:h-6"></span>
        <Link href="/register">
          <span className="hidden lg:block px-2">注册</span>
        </Link>
      </div>
    )
  }

  return (
    <>
      <div className="lg:hidden">
        <Link href="/profile">
          <span>
            <Icons.User className="icon" />
          </span>
        </Link>
      </div>
      <div
        className={`hidden lg:cursor-pointer lg:relative lg:flex lg:rounded lg:p-1.5 lg:transition ${isOpen && 'bg-red-100'}`}
        onClick={() => setIsOpen(!isOpen)}
      >
        <Icons.User className="icon" />
        <Icons.ArrowDown className="icon" />
        <div
          className={` bg-white shadow-md rounded overflow-hidden absolute top-full left-0 w-60
                   border border-gray-100 ${isOpen ? 'block' : 'hidden'}`}
        >
          <BoxLink path="/profile" name={user.name} className="border-t-0">
            <div className="realative w-6 h-6">
              <Image src={'/avatar.png'} alt="user" width={200} height={200} />
            </div>
          </BoxLink>
          <Logout />
        </div>
      </div>
    </>
  )
}

主要是用BoxLink套了一层,省略很多代码,然后把退出登录的逻辑单独抽出来的Logout.jsx

代码地址:github.com/liyunfu1998...

相关推荐
陈随易3 分钟前
从今天起,你只需要一个浏览器之Ego lite
前端·后端·程序员
怕浪猫7 分钟前
Step 5 Preview 模型写 3D 象棋,两个小时上线
前端·javascript·面试
Highcharts.js32 分钟前
Highcharts甘特图开发带导航功能的项目管理图示例
开发语言·前端·javascript·甘特图·highcharts·项目管理图
Hilaku1 小时前
前端不懂业务有多可怕?
前端·javascript·程序员
涛涛ing1 小时前
模型吐出半截JSON,前端如何边收边渲染?2026年AI应用必须闯过的工程关
前端
aixingpan1 小时前
aixingpan.cnAPI开发文档:api_docs_trichart_natal_solar_return_transit2接口指南
前端·php
FRing031 小时前
JavaScript入门到精通二十八(forEach遍历、创建对象的三种方式、构造函数、new实例化执行过程、实例成员和静态成员)
开发语言·前端·javascript
燕落南枝2 小时前
CSS 表单选择器与伪元素选择器详解
前端·css
拖孩2 小时前
一个人 + AI 做的小程序,今天,正式回本了
前端·后端·微信小程序
进击的丸子2 小时前
APP 人脸识别增值版 SDK:Camera2 无缝接入指南
前端·前端框架·代码规范