Add sections to admin menus
This commit is contained in:
parent
db14acabdf
commit
d32fa39aab
@ -29,6 +29,7 @@ import { IoMdCheckboxOutline } from 'react-icons/io';
|
|||||||
import Spinner from '@/components/Spinner';
|
import Spinner from '@/components/Spinner';
|
||||||
import IconBroom from '@/components/icons/IconBroom';
|
import IconBroom from '@/components/icons/IconBroom';
|
||||||
import InsightsIndicatorDot from './insights/InsightsIndicatorDot';
|
import InsightsIndicatorDot from './insights/InsightsIndicatorDot';
|
||||||
|
import MoreMenuItem from '@/components/more/MoreMenuItem';
|
||||||
|
|
||||||
export default function AdminAppMenu({
|
export default function AdminAppMenu({
|
||||||
active,
|
active,
|
||||||
@ -60,17 +61,21 @@ export default function AdminAppMenu({
|
|||||||
|
|
||||||
const showAppInsightsLink = photosCountTotal > 0 && !isAltPressed;
|
const showAppInsightsLink = photosCountTotal > 0 && !isAltPressed;
|
||||||
|
|
||||||
const items: ComponentProps<typeof MoreMenu>['items'] = [{
|
const sectionUpload: ComponentProps<typeof MoreMenuItem>[] = [];
|
||||||
|
const sectionMain: ComponentProps<typeof MoreMenuItem>[] = [];
|
||||||
|
const sectionSignOut: ComponentProps<typeof MoreMenuItem>[] = [];
|
||||||
|
|
||||||
|
sectionUpload.push({
|
||||||
label: 'Upload Photos',
|
label: 'Upload Photos',
|
||||||
icon: <IconUpload
|
icon: <IconUpload
|
||||||
size={15}
|
size={15}
|
||||||
className="translate-x-[0.5px] translate-y-[0.5px]"
|
className="translate-x-[0.5px] translate-y-[0.5px]"
|
||||||
/>,
|
/>,
|
||||||
action: startUpload,
|
action: startUpload,
|
||||||
}];
|
});
|
||||||
|
|
||||||
if (uploadsCount) {
|
if (uploadsCount) {
|
||||||
items.push({
|
sectionMain.push({
|
||||||
label: 'Uploads',
|
label: 'Uploads',
|
||||||
annotation: `${uploadsCount}`,
|
annotation: `${uploadsCount}`,
|
||||||
icon: <IconFolder
|
icon: <IconFolder
|
||||||
@ -81,7 +86,7 @@ export default function AdminAppMenu({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (photosCountNeedSync) {
|
if (photosCountNeedSync) {
|
||||||
items.push({
|
sectionMain.push({
|
||||||
label: 'Updates',
|
label: 'Updates',
|
||||||
annotation: <>
|
annotation: <>
|
||||||
<span className="mr-3">
|
<span className="mr-3">
|
||||||
@ -100,7 +105,7 @@ export default function AdminAppMenu({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (photosCountTotal) {
|
if (photosCountTotal) {
|
||||||
items.push({
|
sectionMain.push({
|
||||||
label: 'Manage Photos',
|
label: 'Manage Photos',
|
||||||
...photosCountTotal && {
|
...photosCountTotal && {
|
||||||
annotation: `${photosCountTotal}`,
|
annotation: `${photosCountTotal}`,
|
||||||
@ -113,7 +118,7 @@ export default function AdminAppMenu({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (tagsCount) {
|
if (tagsCount) {
|
||||||
items.push({
|
sectionMain.push({
|
||||||
label: 'Manage Tags',
|
label: 'Manage Tags',
|
||||||
annotation: `${tagsCount}`,
|
annotation: `${tagsCount}`,
|
||||||
icon: <IconTag
|
icon: <IconTag
|
||||||
@ -124,7 +129,7 @@ export default function AdminAppMenu({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (recipesCount) {
|
if (recipesCount) {
|
||||||
items.push({
|
sectionMain.push({
|
||||||
label: 'Manage Recipes',
|
label: 'Manage Recipes',
|
||||||
annotation: `${recipesCount}`,
|
annotation: `${recipesCount}`,
|
||||||
icon: <IconRecipe
|
icon: <IconRecipe
|
||||||
@ -135,7 +140,7 @@ export default function AdminAppMenu({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (photosCountTotal) {
|
if (photosCountTotal) {
|
||||||
items.push({
|
sectionMain.push({
|
||||||
label: isSelecting
|
label: isSelecting
|
||||||
? 'Exit Batch Edit'
|
? 'Exit Batch Edit'
|
||||||
: 'Batch Edit ...',
|
: 'Batch Edit ...',
|
||||||
@ -163,7 +168,7 @@ export default function AdminAppMenu({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
items.push({
|
sectionMain.push({
|
||||||
label: showAppInsightsLink
|
label: showAppInsightsLink
|
||||||
? 'App Insights'
|
? 'App Insights'
|
||||||
: 'App Configuration',
|
: 'App Configuration',
|
||||||
@ -174,7 +179,9 @@ export default function AdminAppMenu({
|
|||||||
href: showAppInsightsLink
|
href: showAppInsightsLink
|
||||||
? PATH_ADMIN_INSIGHTS
|
? PATH_ADMIN_INSIGHTS
|
||||||
: PATH_ADMIN_CONFIGURATION,
|
: PATH_ADMIN_CONFIGURATION,
|
||||||
}, {
|
});
|
||||||
|
|
||||||
|
sectionSignOut.push({
|
||||||
label: 'Sign Out',
|
label: 'Sign Out',
|
||||||
icon: <IconSignOut size={15} />,
|
icon: <IconSignOut size={15} />,
|
||||||
action: () => signOutAction().then(clearAuthStateAndRedirectIfNecessary),
|
action: () => signOutAction().then(clearAuthStateAndRedirectIfNecessary),
|
||||||
@ -235,7 +242,11 @@ export default function AdminAppMenu({
|
|||||||
'[&>*>*]:translate-y-[6px]',
|
'[&>*>*]:translate-y-[6px]',
|
||||||
!animateMenuClose && '[&>*>*]:duration-300',
|
!animateMenuClose && '[&>*>*]:duration-300',
|
||||||
)}
|
)}
|
||||||
items={items}
|
sections={[
|
||||||
|
sectionUpload,
|
||||||
|
sectionMain,
|
||||||
|
sectionSignOut,
|
||||||
|
]}
|
||||||
ariaLabel="Admin Menu"
|
ariaLabel="Admin Menu"
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -31,7 +31,7 @@ export default function AdminPhotoMenu({
|
|||||||
revalidatePhoto,
|
revalidatePhoto,
|
||||||
includeFavorite = true,
|
includeFavorite = true,
|
||||||
...props
|
...props
|
||||||
}: Omit<ComponentProps<typeof MoreMenu>, 'items'> & {
|
}: Omit<ComponentProps<typeof MoreMenu>, 'sections'> & {
|
||||||
photo: Photo
|
photo: Photo
|
||||||
revalidatePhoto?: RevalidatePhoto
|
revalidatePhoto?: RevalidatePhoto
|
||||||
includeFavorite?: boolean
|
includeFavorite?: boolean
|
||||||
@ -43,8 +43,8 @@ export default function AdminPhotoMenu({
|
|||||||
const shouldRedirectFav = isPathFavs(path) && isFav;
|
const shouldRedirectFav = isPathFavs(path) && isFav;
|
||||||
const shouldRedirectDelete = pathForPhoto({ photo: photo.id }) === path;
|
const shouldRedirectDelete = pathForPhoto({ photo: photo.id }) === path;
|
||||||
|
|
||||||
const items = useMemo(() => {
|
const sections = useMemo(() => {
|
||||||
const items: ComponentProps<typeof MoreMenuItem>[] = [{
|
const sectionMain: ComponentProps<typeof MoreMenuItem>[] = [{
|
||||||
label: 'Edit',
|
label: 'Edit',
|
||||||
icon: <IconEdit
|
icon: <IconEdit
|
||||||
size={15}
|
size={15}
|
||||||
@ -53,7 +53,7 @@ export default function AdminPhotoMenu({
|
|||||||
href: pathForAdminPhotoEdit(photo.id),
|
href: pathForAdminPhotoEdit(photo.id),
|
||||||
}];
|
}];
|
||||||
if (includeFavorite) {
|
if (includeFavorite) {
|
||||||
items.push({
|
sectionMain.push({
|
||||||
label: isFav ? 'Unfavorite' : 'Favorite',
|
label: isFav ? 'Unfavorite' : 'Favorite',
|
||||||
icon: <IconFavs
|
icon: <IconFavs
|
||||||
size={14}
|
size={14}
|
||||||
@ -66,7 +66,7 @@ export default function AdminPhotoMenu({
|
|||||||
).then(() => revalidatePhoto?.(photo.id)),
|
).then(() => revalidatePhoto?.(photo.id)),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
items.push({
|
sectionMain.push({
|
||||||
label: 'Download',
|
label: 'Download',
|
||||||
icon: <MdOutlineFileDownload
|
icon: <MdOutlineFileDownload
|
||||||
size={17}
|
size={17}
|
||||||
@ -75,7 +75,7 @@ export default function AdminPhotoMenu({
|
|||||||
href: photo.url,
|
href: photo.url,
|
||||||
hrefDownloadName: downloadFileNameForPhoto(photo),
|
hrefDownloadName: downloadFileNameForPhoto(photo),
|
||||||
});
|
});
|
||||||
items.push({
|
sectionMain.push({
|
||||||
label: 'Sync',
|
label: 'Sync',
|
||||||
labelComplex: <span className="inline-flex items-center gap-2">
|
labelComplex: <span className="inline-flex items-center gap-2">
|
||||||
<span>Sync</span>
|
<span>Sync</span>
|
||||||
@ -90,7 +90,7 @@ export default function AdminPhotoMenu({
|
|||||||
action: () => syncPhotoAction(photo.id)
|
action: () => syncPhotoAction(photo.id)
|
||||||
.then(() => revalidatePhoto?.(photo.id)),
|
.then(() => revalidatePhoto?.(photo.id)),
|
||||||
});
|
});
|
||||||
items.push({
|
const sectionDelete = [{
|
||||||
label: 'Delete',
|
label: 'Delete',
|
||||||
icon: <BiTrash
|
icon: <BiTrash
|
||||||
size={15}
|
size={15}
|
||||||
@ -109,8 +109,8 @@ export default function AdminPhotoMenu({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
}];
|
||||||
return items;
|
return [sectionMain, sectionDelete];
|
||||||
}, [
|
}, [
|
||||||
photo,
|
photo,
|
||||||
includeFavorite,
|
includeFavorite,
|
||||||
@ -124,7 +124,7 @@ export default function AdminPhotoMenu({
|
|||||||
return (
|
return (
|
||||||
isUserSignedIn
|
isUserSignedIn
|
||||||
? <MoreMenu {...{
|
? <MoreMenu {...{
|
||||||
items,
|
sections,
|
||||||
...props,
|
...props,
|
||||||
}}/>
|
}}/>
|
||||||
: null
|
: null
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import { FiMoreHorizontal } from 'react-icons/fi';
|
|||||||
import MoreMenuItem from './MoreMenuItem';
|
import MoreMenuItem from './MoreMenuItem';
|
||||||
|
|
||||||
export default function MoreMenu({
|
export default function MoreMenu({
|
||||||
items,
|
sections,
|
||||||
icon,
|
icon,
|
||||||
header,
|
header,
|
||||||
className,
|
className,
|
||||||
@ -24,7 +24,7 @@ export default function MoreMenu({
|
|||||||
onOpen,
|
onOpen,
|
||||||
...props
|
...props
|
||||||
}: {
|
}: {
|
||||||
items: ComponentProps<typeof MoreMenuItem>[]
|
sections: ComponentProps<typeof MoreMenuItem>[][]
|
||||||
icon?: ReactNode
|
icon?: ReactNode
|
||||||
header?: ReactNode
|
header?: ReactNode
|
||||||
className?: string
|
className?: string
|
||||||
@ -71,7 +71,7 @@ export default function MoreMenu({
|
|||||||
'z-10',
|
'z-10',
|
||||||
'min-w-[8rem]',
|
'min-w-[8rem]',
|
||||||
'component-surface',
|
'component-surface',
|
||||||
'p-1',
|
'py-1',
|
||||||
'shadow-lg',
|
'shadow-lg',
|
||||||
'data-[side=top]:dark:shadow-[0_0px_40px_rgba(0,0,0,0.6)]',
|
'data-[side=top]:dark:shadow-[0_0px_40px_rgba(0,0,0,0.6)]',
|
||||||
'data-[side=bottom]:dark:shadow-[0_10px_40px_rgba(0,0,0,0.6)]',
|
'data-[side=bottom]:dark:shadow-[0_10px_40px_rgba(0,0,0,0.6)]',
|
||||||
@ -86,13 +86,26 @@ export default function MoreMenu({
|
|||||||
)}>
|
)}>
|
||||||
{header}
|
{header}
|
||||||
</div>}
|
</div>}
|
||||||
{items.map(props =>
|
<div className="divide-y divide-medium">
|
||||||
<MoreMenuItem
|
{sections.map((section, index) =>
|
||||||
key={`${props.label}`}
|
<div
|
||||||
{...props}
|
key={index}
|
||||||
dismissMenu={dismissMenu}
|
className={clsx(
|
||||||
/>,
|
'[&:not(:first-child)]:pt-1',
|
||||||
)}
|
'[&:not(:last-child)]:pb-1',
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{section.map(props =>
|
||||||
|
<div key={props.label} className="px-1">
|
||||||
|
<MoreMenuItem
|
||||||
|
dismissMenu={dismissMenu}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
</div>,
|
||||||
|
)}
|
||||||
|
</div>,
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</DropdownMenu.Content>
|
</DropdownMenu.Content>
|
||||||
</DropdownMenu.Portal>
|
</DropdownMenu.Portal>
|
||||||
</DropdownMenu.Root>
|
</DropdownMenu.Root>
|
||||||
|
|||||||
@ -110,7 +110,9 @@ export default function MoreMenuItem({
|
|||||||
styleAs="link-without-hover"
|
styleAs="link-without-hover"
|
||||||
className="translate-y-[1px]"
|
className="translate-y-[1px]"
|
||||||
>
|
>
|
||||||
{labelComplex ?? label}
|
<span>
|
||||||
|
{labelComplex ?? label}
|
||||||
|
</span>
|
||||||
{annotation &&
|
{annotation &&
|
||||||
<span className="text-dim ml-3">
|
<span className="text-dim ml-3">
|
||||||
{annotation}
|
{annotation}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user