diff --git a/src/admin/AdminGrid.tsx b/src/admin/AdminGrid.tsx new file mode 100644 index 00000000..16cf493c --- /dev/null +++ b/src/admin/AdminGrid.tsx @@ -0,0 +1,26 @@ +import { cc } from '@/utility/css'; +import { ReactNode } from 'react'; + +export default function AdminGrid ({ + title, + children, +}: { + title?: string, + children: ReactNode, +}) { + return
+ {title && +
+ {title} +
} +
+
+ {children} +
+
+
; +} diff --git a/src/admin/AdminNav.tsx b/src/admin/AdminNav.tsx index be8c544d..250f1897 100644 --- a/src/admin/AdminNav.tsx +++ b/src/admin/AdminNav.tsx @@ -1,5 +1,6 @@ 'use client'; +import SiteGrid from '@/components/SiteGrid'; import { cc } from '@/utility/css'; import Link from 'next/link'; import { usePathname } from 'next/navigation'; @@ -16,25 +17,29 @@ export default function AdminNav({ const pathname = usePathname(); return ( -
-
- {items.map(({ label, href, count }) => - - {label} - ({count}) - )} -
-
+ +
+ {items.map(({ label, href, count }) => + + {label} + ({count}) + )} +
+ + } + /> ); } diff --git a/src/admin/DeleteButton.tsx b/src/admin/DeleteButton.tsx new file mode 100644 index 00000000..4709a58e --- /dev/null +++ b/src/admin/DeleteButton.tsx @@ -0,0 +1,10 @@ +import SubmitButtonWithStatus from '@/components/SubmitButtonWithStatus'; + +export default function DeleteButton () { + return ×} + > + Delete + ; +} diff --git a/src/admin/EditButton.tsx b/src/admin/EditButton.tsx new file mode 100644 index 00000000..fc9e1967 --- /dev/null +++ b/src/admin/EditButton.tsx @@ -0,0 +1,23 @@ +import Link from 'next/link'; +import { FaRegEdit } from 'react-icons/fa'; + +export default function EditButton ({ + href, + label = 'Edit', +}: { + href: string, + label?: string, +}) { + return ( + + + + {label} + + + ); +} diff --git a/src/app/(auth-state)/admin/photos/page.tsx b/src/app/(auth-state)/admin/photos/page.tsx index 3555ec3e..91a935b8 100644 --- a/src/app/(auth-state)/admin/photos/page.tsx +++ b/src/app/(auth-state)/admin/photos/page.tsx @@ -1,4 +1,4 @@ -import { Fragment, ReactNode } from 'react'; +import { Fragment } from 'react'; import PhotoUploadInput from '@/photo/PhotoUploadInput'; import Link from 'next/link'; import PhotoTiny from '@/photo/PhotoTiny'; @@ -11,7 +11,6 @@ import { deleteBlobPhotoAction, syncCacheAction, } from '@/photo/actions'; -import { FaRegEdit } from 'react-icons/fa'; import SubmitButtonWithStatus from '@/components/SubmitButtonWithStatus'; import { pathForBlobUrl } from '@/services/blob'; import { @@ -33,12 +32,17 @@ import { PaginationParams, getPaginationForSearchParams, } from '@/site/pagination'; +import AdminGrid from '@/admin/AdminGrid'; +import DeleteButton from '@/admin/DeleteButton'; +import EditButton from '@/admin/EditButton'; export const runtime = 'edge'; const DEBUG_PHOTO_BLOBS = false; -export default async function AdminPage({ searchParams }: PaginationParams) { +export default async function AdminTagsPage({ + searchParams, +}: PaginationParams) { const { offset, limit } = getPaginationForSearchParams(searchParams); const [ @@ -85,7 +89,7 @@ export default async function AdminPage({ searchParams }: PaginationParams) { label={`Photos Files (${blobPhotoUrls.length})`} />}
- + {photos.map(photo => -
- {title} -
-
-
- {children} -
-
-
; -} - -function EditButton ({ - href, - label = 'Edit', -}: { - href: string, - label?: string, -}) { - return ( - - - - {label} - - - ); -} - -function DeleteButton () { - return ×} - > - Delete - ; -} - function BlobUrls ({ blobUrls, label, diff --git a/src/app/(auth-state)/admin/tags/page.tsx b/src/app/(auth-state)/admin/tags/page.tsx new file mode 100644 index 00000000..d1cbeff4 --- /dev/null +++ b/src/app/(auth-state)/admin/tags/page.tsx @@ -0,0 +1,42 @@ +import FormWithConfirm from '@/components/FormWithConfirm'; +import SiteGrid from '@/components/SiteGrid'; +import { deletePhotoTagGloballyAction } from '@/photo/actions'; +import { getUniqueTagsCached } from '@/cache'; +import AdminGrid from '@/admin/AdminGrid'; +import { Fragment } from 'react'; +import DeleteButton from '@/admin/DeleteButton'; + +export const runtime = 'edge'; + +export default async function AdminPhotosPage() { + const tags = await getUniqueTagsCached(); + + return ( + +
+ + {tags.map(tag => + +
+ {tag} +
+
+
+ + + + + )} + +
+
} + /> + ); +}