Social handles CRUD (admin side, nothing user-facing)
This commit is contained in:
@@ -1,13 +0,0 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react'
|
||||
|
||||
import AccountbarLayout from './AccountbarLayout'
|
||||
|
||||
const meta: Meta<typeof AccountbarLayout> = {
|
||||
component: AccountbarLayout,
|
||||
}
|
||||
|
||||
export default meta
|
||||
|
||||
type Story = StoryObj<typeof AccountbarLayout>
|
||||
|
||||
export const Primary: Story = {}
|
||||
@@ -1,14 +0,0 @@
|
||||
import { render } from '@redwoodjs/testing/web'
|
||||
|
||||
import AccountbarLayout from './AccountbarLayout'
|
||||
|
||||
// Improve this test with help from the Redwood Testing Doc:
|
||||
// https://redwoodjs.com/docs/testing#testing-pages-layouts
|
||||
|
||||
describe('AccountbarLayout', () => {
|
||||
it('renders successfully', () => {
|
||||
expect(() => {
|
||||
render(<AccountbarLayout />)
|
||||
}).not.toThrow()
|
||||
})
|
||||
})
|
||||
@@ -25,7 +25,7 @@ const AccountbarLayout = ({ title, children }: AccountbarLayoutProps) => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="font-inter">
|
||||
<div className="p-2 font-inter">
|
||||
<main>{children}</main>
|
||||
</div>
|
||||
</>
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react'
|
||||
|
||||
import NavbarLayout from './NavbarLayout'
|
||||
|
||||
const meta: Meta<typeof NavbarLayout> = {
|
||||
component: NavbarLayout,
|
||||
}
|
||||
|
||||
export default meta
|
||||
|
||||
type Story = StoryObj<typeof NavbarLayout>
|
||||
|
||||
export const Primary: Story = {}
|
||||
@@ -1,14 +0,0 @@
|
||||
import { render } from '@redwoodjs/testing/web'
|
||||
|
||||
import NavbarLayout from './NavbarLayout'
|
||||
|
||||
// Improve this test with help from the Redwood Testing Doc:
|
||||
// https://redwoodjs.com/docs/testing#testing-pages-layouts
|
||||
|
||||
describe('NavbarLayout', () => {
|
||||
it('renders successfully', () => {
|
||||
expect(() => {
|
||||
render(<NavbarLayout />)
|
||||
}).not.toThrow()
|
||||
})
|
||||
})
|
||||
@@ -1,4 +1,4 @@
|
||||
import { mdiMenu, mdiLogout } from '@mdi/js'
|
||||
import { mdiMenu, mdiLogout, mdiCog } from '@mdi/js'
|
||||
import Icon from '@mdi/react'
|
||||
|
||||
import { Link, routes } from '@redwoodjs/router'
|
||||
@@ -27,6 +27,13 @@ const NavbarLayout = ({ children }: NavbarLayoutProps) => {
|
||||
},
|
||||
]
|
||||
|
||||
const navbarAdminRoutes: NavbarRoute[] = [
|
||||
{
|
||||
name: 'Socials',
|
||||
path: routes.socials(),
|
||||
},
|
||||
]
|
||||
|
||||
const navbarButtons = () =>
|
||||
navbarRoutes.map((route, i) => (
|
||||
<Link key={i} to={route.path} className="btn btn-ghost btn-sm">
|
||||
@@ -34,6 +41,15 @@ const NavbarLayout = ({ children }: NavbarLayoutProps) => {
|
||||
</Link>
|
||||
))
|
||||
|
||||
const navbarAdminButtons = () =>
|
||||
navbarAdminRoutes.map((route, i) => (
|
||||
<li key={i}>
|
||||
<Link to={route.path} className="btn btn-ghost btn-sm">
|
||||
{route.name}
|
||||
</Link>
|
||||
</li>
|
||||
))
|
||||
|
||||
return (
|
||||
<>
|
||||
<ToasterWrapper />
|
||||
@@ -44,19 +60,39 @@ const NavbarLayout = ({ children }: NavbarLayoutProps) => {
|
||||
<div
|
||||
tabIndex={0}
|
||||
role="button"
|
||||
className="btn btn-ghost lg:hidden"
|
||||
className="btn btn-square btn-ghost lg:hidden"
|
||||
>
|
||||
<Icon
|
||||
path={mdiMenu}
|
||||
className="text-base-content-100 h-8 w-8"
|
||||
/>
|
||||
<Icon path={mdiMenu} className="text-base-content-100 size-8" />
|
||||
</div>
|
||||
<div
|
||||
// eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex
|
||||
tabIndex={0}
|
||||
className="menu dropdown-content -ml-2 mt-4 w-36 space-y-2 rounded-box bg-base-200 shadow-xl"
|
||||
className="menu dropdown-content -ml-2 mt-4 w-36 space-y-2 rounded-box bg-base-200 shadow-xl last:space-y-0"
|
||||
>
|
||||
{navbarButtons()}
|
||||
{isAuthenticated && (
|
||||
<div className="dropdown sm:hidden">
|
||||
<div
|
||||
// eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex
|
||||
tabIndex={0}
|
||||
className="menu dropdown-content -ml-2 mt-4 w-36 space-y-2 rounded-box bg-base-200 shadow-xl"
|
||||
>
|
||||
<p className="btn btn-active no-animation btn-sm btn-block">
|
||||
Admin
|
||||
</p>
|
||||
|
||||
{navbarAdminButtons()}
|
||||
<li>
|
||||
<button
|
||||
onClick={logOut}
|
||||
className="btn btn-ghost btn-sm"
|
||||
>
|
||||
Logout
|
||||
</button>
|
||||
</li>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<Link
|
||||
@@ -78,18 +114,36 @@ const NavbarLayout = ({ children }: NavbarLayoutProps) => {
|
||||
<div className="space-x-2 font-syne">{navbarButtons()}</div>
|
||||
</div>
|
||||
<div className="navbar-end space-x-2">
|
||||
{isAuthenticated ? (
|
||||
<button className="btn btn-square btn-ghost" onClick={logOut}>
|
||||
<Icon path={mdiLogout} className="h-8 w-8" />
|
||||
</button>
|
||||
) : (
|
||||
<></>
|
||||
{isAuthenticated && (
|
||||
<div className="hidden space-x-2 sm:flex">
|
||||
<button className="btn btn-square btn-ghost" onClick={logOut}>
|
||||
<Icon path={mdiLogout} className="size-8" />
|
||||
</button>
|
||||
<div className="dropdown">
|
||||
<div
|
||||
tabIndex={0}
|
||||
role="button"
|
||||
className="btn btn-square btn-ghost"
|
||||
>
|
||||
<Icon path={mdiCog} className="size-8" />
|
||||
</div>
|
||||
<ul
|
||||
// eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex
|
||||
tabIndex={0}
|
||||
className="menu dropdown-content -ml-8 mt-4 w-36 space-y-2 rounded-box bg-base-200 shadow-xl"
|
||||
>
|
||||
{navbarAdminButtons()}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<ThemeToggle />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="font-inter">{children}</div>
|
||||
<div className="p-2 font-inter">
|
||||
<main>{children}</main>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
65
web/src/layouts/ScaffoldLayout/ScaffoldLayout.tsx
Normal file
65
web/src/layouts/ScaffoldLayout/ScaffoldLayout.tsx
Normal file
@@ -0,0 +1,65 @@
|
||||
import { mdiHome, mdiPlus } from '@mdi/js'
|
||||
import Icon from '@mdi/react'
|
||||
|
||||
import { Link, routes } from '@redwoodjs/router'
|
||||
|
||||
import ThemeToggle from 'src/components/ThemeToggle/ThemeToggle'
|
||||
import ToasterWrapper from 'src/components/ToasterWrapper/ToasterWrapper'
|
||||
|
||||
type ScaffoldLayoutProps = {
|
||||
title: string
|
||||
titleTo: string
|
||||
buttonLabel: string
|
||||
buttonTo: string
|
||||
children: React.ReactNode
|
||||
}
|
||||
|
||||
const ScaffoldLayout = ({
|
||||
title,
|
||||
titleTo,
|
||||
buttonLabel,
|
||||
buttonTo,
|
||||
children,
|
||||
}: ScaffoldLayoutProps) => {
|
||||
return (
|
||||
<>
|
||||
<ToasterWrapper />
|
||||
<div className="sticky top-0 z-50 p-2">
|
||||
<div className="navbar rounded-xl bg-base-300 font-syne shadow-xl">
|
||||
<div className="navbar-start space-x-2">
|
||||
<Link to={routes.home()} className="btn btn-square btn-ghost">
|
||||
<Icon className="size-8" path={mdiHome} />
|
||||
</Link>
|
||||
<Link to={routes[titleTo]()} className="btn btn-ghost text-xl">
|
||||
{title}
|
||||
</Link>
|
||||
</div>
|
||||
<div className="navbar-end space-x-2">
|
||||
<ThemeToggle />
|
||||
{buttonLabel && buttonTo && (
|
||||
<>
|
||||
<Link
|
||||
to={routes[buttonTo]()}
|
||||
className="btn btn-primary hidden sm:flex"
|
||||
>
|
||||
<Icon className="size-6" path={mdiPlus} /> {buttonLabel}
|
||||
</Link>
|
||||
<Link
|
||||
to={routes[buttonTo]()}
|
||||
className="btn btn-square btn-primary sm:hidden"
|
||||
>
|
||||
<Icon className="size-8" path={mdiPlus} />
|
||||
</Link>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-2 font-inter">
|
||||
<main>{children}</main>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default ScaffoldLayout
|
||||
Reference in New Issue
Block a user