diff --git a/src/app/editArea/[slug]/layout.tsx b/src/app/editArea/[slug]/layout.tsx index 01169b64b..3d3c842bc 100644 --- a/src/app/editArea/[slug]/layout.tsx +++ b/src/app/editArea/[slug]/layout.tsx @@ -1,14 +1,33 @@ +import { ArrowUUpLeft } from '@phosphor-icons/react/dist/ssr' import { SidebarNav } from './SidebarNav' +import { getPageDataForEdit } from './general/page' +import { GluttenFreeCrumbs } from '@/components/ui/BreadCrumbs' -export default function RootLayout ({ +/** + * Layout for edit area dashboard + */ +export default async function RootLayout ({ children, params }: { children: React.ReactNode params: { slug: string } -}): any { +}): Promise { + const { area: { areaName, uuid, pathTokens, ancestors } } = await getPageDataForEdit(params.slug) return (
-

Edit area

+
+
+

Edit area {areaName} +

+
+ +
+ + Return to public version + +
+
+
diff --git a/src/app/editArea/[slug]/manage/components/AreaItem.tsx b/src/app/editArea/[slug]/manage/components/AreaItem.tsx index fa41b2f63..c54a094f0 100644 --- a/src/app/editArea/[slug]/manage/components/AreaItem.tsx +++ b/src/app/editArea/[slug]/manage/components/AreaItem.tsx @@ -10,6 +10,9 @@ type EType = 'area' | 'crag' | 'boulder' | 'climb' const CragIcon = forwardRef((props, ref) => ) +// type MyIconProps = Icon & { +// class +// } const IconMap: Record = { area: Graph, crag: CragIcon, @@ -17,60 +20,86 @@ const IconMap: Record = { climb: LineSegments } -export const EntityIcon: React.FC<{ type: EType, withLabel?: boolean }> = ({ type, withLabel = true }) => { +export const EntityIcon: React.FC<{ type: EType, withLabel?: boolean, className?: string }> = ({ type, withLabel = true, className = '' }) => { const IconComponent = IconMap?.[type] if (IconComponent == null) return null return (
- - {type.toUpperCase()} + + {withLabel && {type.toUpperCase()}}
) } export const AreaItem: React.FC<{ area: AreaType, parentUuid: string, index: number }> = ({ area, index, parentUuid }) => { - const { uuid, areaName } = area + const { uuid, areaName, children, climbs } = area + + // undefined array can mean we forget to include the field in GQL so let's make it not editable + const canDelete = (children?.length ?? 1) === 0 && (climbs?.length ?? 1) === 0 + return ( -
-
-
{index}
-
-
{areaName}
- +
+
+
+
+
{index}
+
+
+ + {areaName} + +
+ +
+
- +
+
+
) } -export const AreaIcon: React.FC<{ area: AreaType }> = ({ area: { climbs, metadata: { isBoulder } } }) => { - if ((climbs?.length ?? 0) > 0) { - return - } - if (isBoulder) { - return +export const AreaIcon: React.FC<{ area: AreaType }> = + ({ area: { climbs, metadata: { isBoulder } } }) => { + if ((climbs?.length ?? 0) > 0) { + return + } + if (isBoulder) { + return + } + return } - return -} -const Actions: React.FC<{ uuid: string, areaName: string, parentUuid: string }> = ({ uuid, parentUuid, areaName }) => { +const Actions: React.FC<{ + uuid: string + areaName: string + parentUuid: string + canDelete?: boolean +}> = ({ uuid, parentUuid, areaName, canDelete = false }) => { return (
- + + + + - - +
- + - +
) } diff --git a/src/app/editArea/[slug]/manage/components/AreaList.tsx b/src/app/editArea/[slug]/manage/components/AreaList.tsx index 4502393b0..a6c99e6ac 100644 --- a/src/app/editArea/[slug]/manage/components/AreaList.tsx +++ b/src/app/editArea/[slug]/manage/components/AreaList.tsx @@ -1,6 +1,7 @@ 'use client' import { AreaType } from '@/js/types' import { AreaItem } from './AreaItem' +import { GluttenFreeCrumbs } from '@/components/ui/BreadCrumbs' type AreaListProps = Pick & { areas: AreaType[] @@ -8,24 +9,27 @@ type AreaListProps = Pick = ({ areaName, uuid, pathTokens, ancestors, areas }) => { return ( -
- +
+ {/* Heading */} + + +
+ + {/* Child area list */}
{areas.map((item, index) => )}
- {/* */} -
) } diff --git a/src/app/global.css b/src/app/global.css index 85710f51a..278124ebe 100644 --- a/src/app/global.css +++ b/src/app/global.css @@ -27,11 +27,11 @@ h3 { } .text-primary { - @apply text-base-content; + @apply text-base-content !important; } .text-secondary { - @apply text-base-content/60; + @apply text-base-content/60 !important; } /* .card-body { @@ -85,6 +85,23 @@ h3 { @apply rounded h-8 w-8 grid place-content-center bg-area-cue text-base-100 text-sm hover:decoration-0 hover:no-underline; } -.thick-link { - @apply hover:underline underline-offset-4 decoration-4; -} +@layer utilities { + .dialog-center { + @apply top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 rounded-box !important; + } + + .dialog-default { + @apply top-0 left-0 h-screen md:dialog-center fixed z-50 w-screen max-w-screen-md bg-base-100 lg:drop-shadow-lg overflow-y-auto h-fit max-h-screen lg:max-h-[95vh]; + } + .dialog-title { + @apply py-4 lg:py-5 left-0 top-0 w-full text-center fixed bg-base-100 bg-opacity-80 backdrop-blur-sm z-50 leading-none; + } + + .dialog-close-button { + @apply fixed top-0.5 left-0.5 lg:top-1 lg:left-1 z-50; + } + + .dialog-form-default { + @apply mt-16 lg:mt-20 px-2 lg:px-4 mb-6 !important; + } +} \ No newline at end of file diff --git a/src/components/edit/DeleteAreaForm.tsx b/src/components/edit/DeleteAreaForm.tsx index 256da6ec1..3d39516da 100644 --- a/src/components/edit/DeleteAreaForm.tsx +++ b/src/components/edit/DeleteAreaForm.tsx @@ -28,7 +28,7 @@ interface HtmlFormProps { * @param returnToParentPageAfterDelete true to be redirected to parent area page * @param onSuccess Optional callback */ -export default function DeleteAreaForm ({ areaUuid, areaName, parentUuid, returnToParentPageAfterDelete = true, onSuccess }: DeleteAreaProps): JSX.Element { +export default function DeleteAreaForm ({ areaUuid, areaName, parentUuid, returnToParentPageAfterDelete = false, onSuccess }: DeleteAreaProps): JSX.Element { const session = useSession() const router = useRouter() @@ -39,6 +39,7 @@ export default function DeleteAreaForm ({ areaUuid, areaName, parentUuid, return }, [session]) const onSuccessHandler = (): void => { + router.refresh() if (onSuccess != null) { onSuccess() } diff --git a/src/components/ui/BreadCrumbs.tsx b/src/components/ui/BreadCrumbs.tsx index d85bb2ca2..478eecba6 100644 --- a/src/components/ui/BreadCrumbs.tsx +++ b/src/components/ui/BreadCrumbs.tsx @@ -121,3 +121,36 @@ const Item = ({ path, highlight, current, length }: ItemProps): JSX.Element => ( {sanitizeName(path)} {current < length - 1 ? {SEPARATOR} : null} ) + +/** + * Area path crumbs based on DaisyUI. + */ +export const GluttenFreeCrumbs: React.FC<{ + pathTokens: string[] + ancestors: string[] +}> = ({ pathTokens, ancestors }) => { + return ( +
+
    +
  • Home
  • + {pathTokens.map((path, index) => { + const uuid = ancestors[index] + const url = `/editArea/${uuid}` + return + })} +
+
+ ) +} + +const GFItem: React.FC<{ path: string, url: string, isLast: boolean }> = + ({ path, url, isLast }) => ( +
  • + + {path} + +
  • + ) diff --git a/src/js/graphql/gql/areaById.ts b/src/js/graphql/gql/areaById.ts index 67d26575a..31e20f62e 100644 --- a/src/js/graphql/gql/areaById.ts +++ b/src/js/graphql/gql/areaById.ts @@ -103,6 +103,9 @@ export const QUERY_AREA_BY_ID = gql` children { uuid } + climbs { + id + } } content { description diff --git a/src/js/hooks/useUpdateAreasCmd.tsx b/src/js/hooks/useUpdateAreasCmd.tsx index 409f3d90f..daa758f23 100644 --- a/src/js/hooks/useUpdateAreasCmd.tsx +++ b/src/js/hooks/useUpdateAreasCmd.tsx @@ -158,7 +158,9 @@ export default function useUpdateAreasCmd ({ areaId, accessToken = '', ...props MUTATION_REMOVE_AREA, { client: graphqlClient, onCompleted: (data) => { - void refreshPage(`/api/revalidate?s=${areaId}`) // rebuild parent area page + // void refreshPage(`/api/revalidate?s=${areaId}`) // rebuild parent area page + + void updateAreaPageCache(areaId) if (onDeleteCompleted != null) { onDeleteCompleted(data)