Skip to content

Commit

Permalink
wip: combine separate pages into one
Browse files Browse the repository at this point in the history
  • Loading branch information
viet nguyen committed Nov 24, 2023
1 parent 8a91296 commit 6dbb1f7
Show file tree
Hide file tree
Showing 22 changed files with 164 additions and 107 deletions.
38 changes: 17 additions & 21 deletions src/app/editArea/[slug]/SidebarNav.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use client'
import Link from 'next/link'
import { usePathname } from 'next/navigation'
import { MapPinLine, Graph, Article, FolderSimplePlus } from '@phosphor-icons/react/dist/ssr'
import { Article, FolderSimplePlus } from '@phosphor-icons/react/dist/ssr'

/**
* Sidebar navigation for area edit
Expand All @@ -14,28 +14,24 @@ export const SidebarNav: React.FC<{ slug: string }> = ({ slug }) => {
const classForActivePage = (myPath: string): string => activePath.endsWith(myPath) ? 'bg-base-300/60 pointer-events-none' : ''
return (
<nav className='px-6'>
<ul className='menu w-56'>
<li>
<Link href={`/editArea/${slug}/general`} className={classForActivePage('general')}>
<Article size={24} /> General
</Link>
</li>
<li>
<Link href={`/editArea/${slug}/location`} className={classForActivePage('location')}>
<MapPinLine size={24} /> Location
</Link>
</li>
<li>
<Link href={`/editArea/${slug}/manage`} className={classForActivePage('manage')}>
<Graph size={24} weight='duotone' /> Manage areas
<div className='sticky top-0'>
<ul className='menu w-56'>
<li>
<Link href={`/editArea/${slug}/general`} className={classForActivePage('general')}>
<Article size={24} /> General
</Link>
</li>
</ul>

<div className='p-2 w-56 mt-4'>
<hr className='border-t' />
<Link href={`/editArea/${slug}/general#addArea`} className='block py-4'>
<button className='btn btn-primary btn-block justify-start'> <FolderSimplePlus size={24} /> Add area</button>
</Link>
</li>
</ul>

<div className='p-2 w-56'>
<Link href={`/editArea/${slug}/attributes`}>
<button className='btn btn-primary btn-block justify-start'> <FolderSimplePlus size={24} /> Add area</button>
</Link>
<hr className='border-t' />

</div>
</div>
</nav>
)
Expand Down
2 changes: 1 addition & 1 deletion src/app/editArea/[slug]/components/SingleEntryForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export function SingleEntryForm<T extends FieldValues> ({
>
<div className={clx('card card-bordered border-base-300/40 overflow-hidden w-full bg-base-100', className)}>
<div className='card-body'>
<h2 className='font-semibold text-2xl'>{title}</h2>
<h4 className='font-semibold text-2xl'>{title}</h4>
<div className='pt-2 flex flex-col gap-y-4'>
{children}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { AreaDesignationRadioGroup, areaDesignationToDb, AreaTypeFormProp } from
import { AREA_NAME_FORM_VALIDATION_RULES } from '@/components/edit/EditAreaForm'

/**
*
* Add a new area/crag/boulder
*/
export const AddAreaForm: React.FC<{ area: AreaType }> = ({ area }) => {
const { uuid } = area
Expand All @@ -32,7 +32,7 @@ export const AddAreaForm: React.FC<{ area: AreaType }> = ({ area }) => {
await addOneAreaCmd({ name: areaName, parentUuid: uuid, isBoulder, isLeaf })
router.refresh() // Ask Next to refresh props from the server
}}
className='border-primary border-2'
className='outline outline-2 outline-accent outline-offset-2'
>
<DashboardInput
name='areaName'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { Icon, IconProps } from '@phosphor-icons/react'
import { AreaType } from '@/js/types'
import { DeleteAreaTrigger, DeleteAreaTriggerButtonSm } from '@/components/edit/Triggers'

type EType = 'area' | 'crag' | 'boulder' | 'climb'
export type EType = 'area' | 'crag' | 'boulder' | 'climb'

const CragIcon = forwardRef<any, IconProps>((props, ref) => <ShareNetwork ref={ref} {...props} className='p-1 rotate-90' />)

Expand All @@ -20,12 +20,12 @@ const IconMap: Record<EType, Icon> = {
climb: LineSegments
}

export const EntityIcon: React.FC<{ type: EType, withLabel?: boolean, className?: string }> = ({ type, withLabel = true, className = '' }) => {
export const EntityIcon: React.FC<{ type: EType, withLabel?: boolean, size?: 20 | 24 | 28, className?: string }> = ({ type, withLabel = true, size = 24, className = '' }) => {
const IconComponent = IconMap?.[type]
if (IconComponent == null) return null
return (
<div className='flex gap-1.5 items-center'>
<IconComponent size={20} weight='duotone' className={className} />
<IconComponent size={size} weight='duotone' className={className} />
{withLabel && <span className='text-xs font-light'>{type.toUpperCase()}</span>}
</div>
)
Expand All @@ -41,10 +41,10 @@ export const AreaItem: React.FC<{ area: AreaType, parentUuid: string, index: num
<div className='break-inside-avoid-column break-inside-avoid pb-8'>
<div className='card card-compact card-bordered border-base-300/80 w-full bg-base-100 shadow p-2'>
<div className='flex items-center gap-4 justify-between'>
<div>
<div className='px-2'>
<div className='area-entity-box'>{index}</div>
</div>
<div className='grow space-y-2'>
<div className='grow'>
<Link
className='uppercase font-semibold hover:underline underline-offset-4
'
Expand All @@ -68,12 +68,12 @@ export const AreaItem: React.FC<{ area: AreaType, parentUuid: string, index: num
export const AreaIcon: React.FC<{ area: AreaType }> =
({ area: { climbs, metadata: { isBoulder } } }) => {
if ((climbs?.length ?? 0) > 0) {
return <EntityIcon type='crag' />
return <EntityIcon type='crag' size={20} />
}
if (isBoulder) {
return <EntityIcon type='boulder' />
return <EntityIcon type='boulder' size={20} />
}
return <EntityIcon type='area' className='text-secondary' />
return <EntityIcon type='area' size={20} />
}

const Actions: React.FC<{
Expand All @@ -85,10 +85,10 @@ const Actions: React.FC<{
return (
<div className='flex items-center divide-x'>
<Link className='px-4' href={`/editArea/${uuid}`}>
<button className='btn btn-link btn-primary btn-sm text-secondary'>Edit</button>
<button className='btn btn-link btn-primary btn-sm text-secondary font-semibold'>Edit</button>
</Link>
<Link className='px-4' href={`/area/${uuid}`} target='_new'>
<button className='btn btn-link btn-primary btn-sm text-secondary'>View</button>
<button className='btn btn-link btn-primary btn-sm text-secondary font-light'>View</button>
</Link>
<div className='px-4 relative'>
<DeleteAreaTrigger
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ type AreaListProps = Pick<AreaType, 'uuid' | 'areaName' | 'pathTokens' | 'ancest

export const AreaList: React.FC<AreaListProps> = ({ areaName, uuid, pathTokens, ancestors, areas }) => {
return (
<div className='card card-compact card-bordered border-base-300/50 overflow-hidden w-full'>
<div id='children' className='card card-compact card-bordered border-base-300/50 overflow-hidden w-full'>
<div className='form-control'>
<div className='p-6'>
{/* Heading */}
<label className='flex flex-col items-start justify-start gap-2 pb-2'>
<div className='flex items-baseline gap-4'>
<h2 className='font-semibold text-2xl'>Child areas</h2>
<h4 className='font-semibold text-2xl'>Child areas</h4>
<div className='text-secondary text-sm'>Total: <span>{areas.length}</span></div>
</div>
</label>
Expand Down
44 changes: 44 additions & 0 deletions src/app/editArea/[slug]/general/components/AreaTypeForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
'use client'
import { useSession } from 'next-auth/react'
import { useRouter } from 'next/navigation'

import { SingleEntryForm } from 'app/editArea/[slug]/components/SingleEntryForm'
import useUpdateAreasCmd from '@/js/hooks/useUpdateAreasCmd'
import { AreaType } from '@/js/types'
import { AreaDesignationRadioGroup, areaDesignationToDb, areaDesignationToForm, AreaTypeFormProp } from '@/components/edit/form/AreaDesignationRadioGroup'

/**
* Set area type: general area | crag | boulder
*/
export const AreaTypeForm: React.FC<{ area: AreaType }> = ({ area }) => {
const { uuid, climbs, children } = area
const session = useSession({ required: true })
const router = useRouter()
const { updateOneAreaCmd } = useUpdateAreasCmd({
areaId: uuid,
accessToken: session?.data?.accessToken as string
}
)

const areaType = areaDesignationToForm(area.metadata)

// we're allowed to change area designation when the area has neither climbs nor areas.
const canChangeAreaType =
climbs.length === 0 &&
children.length === 0
return (
<SingleEntryForm<{ areaType: AreaTypeFormProp }>
initialValues={{ areaType }}
keepValuesAfterReset={false}
title='Area Type'
helperText='You can not change the type if this area contains subareas or climbs.'
submitHandler={async ({ areaType }) => {
const { isBoulder, isLeaf } = areaDesignationToDb(areaType)
await updateOneAreaCmd({ uuid, isBoulder, isLeaf })
router.refresh() // Ask Next to refresh props from the server
}}
>
<AreaDesignationRadioGroup disabled={!canChangeAreaType} />
</SingleEntryForm>
)
}
69 changes: 58 additions & 11 deletions src/app/editArea/[slug]/general/page.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,81 @@
import { notFound } from 'next/navigation'
import { validate } from 'uuid'
import { ReactNode } from 'react'
import { Metadata } from 'next'

import { AreaPageDataProps, getArea } from '@/js/graphql/getArea'
import { AreaNameForm } from './AreaNameForm'
import { AreaDescriptionForm } from './AreaDescriptionForm'
import { AreaNameForm } from './components/AreaNameForm'
import { AreaDescriptionForm } from './components/AreaDescriptionForm'
import { AreaLatLngForm } from './components/AreaLatLngForm'
import { AddAreaForm } from './components/AddAreaForm'
import { AreaList } from './components/AreaList'
import { AreaTypeForm } from './components/AreaTypeForm'

// Opt out of caching for all data requests in the route segment
export const dynamic = 'force-dynamic'

// Page metadata
export async function generateMetadata ({ params }: DashboardPageProps): Promise<Metadata> {
const { area: { areaName } } = await getPageDataForEdit(params.slug)
return {
title: `Editing area ${areaName}`
}
}

export interface DashboardPageProps {
params: {
slug: string
}
}

export default async function AreaEditPage ({ params }: DashboardPageProps): Promise<any> {
const { area: { areaName, uuid, content: { description } } } = await getPageDataForEdit(params.slug)
const { area } = await getPageDataForEdit(params.slug)
const {
areaName, uuid, ancestors, pathTokens, children,
content: { description },
metadata: { lat, lng }
} = area
return (
<PageContainer>
<AreaNameForm initialValue={areaName} uuid={uuid} />
<AreaDescriptionForm initialValue={description} uuid={uuid} />
</PageContainer>
<div className='grid grid-cols-1 gap-y-8'>
<PageContainer id='general'>
<AreaNameForm initialValue={areaName} uuid={uuid} />
</PageContainer>

<PageContainer id='general'>
<AreaDescriptionForm initialValue={description} uuid={uuid} />
</PageContainer>

<PageContainer id='location'>
<AreaLatLngForm initLat={lat} initLng={lng} uuid={uuid} />
</PageContainer>

<PageContainer id='areaType'>
<AreaTypeForm area={area} />
</PageContainer>

<PageContainer id='addArea'>
<AddAreaForm area={area} />
</PageContainer>

<PageContainer id='children'>
<AreaList
areaName={areaName}
uuid={uuid}
ancestors={ancestors}
pathTokens={pathTokens}
areas={children}
/>
</PageContainer>
</div>
)
}

export const PageContainer: React.FC<{ children: ReactNode } > = ({ children }) => (
<section className='w-full flex flex-col gap-y-8'>
{children}
</section>
export const PageContainer: React.FC<{ children: ReactNode, id: string }> = ({ id, children }) => (
<div id={id}>
<section className='mt-2 w-full flex flex-col gap-y-8'>
{children}
</section>
</div>
)

export const getPageDataForEdit = async (pageSlug: string): Promise<AreaPageDataProps> => {
Expand Down
14 changes: 8 additions & 6 deletions src/app/editArea/[slug]/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import { SidebarNav } from './SidebarNav'
import { getPageDataForEdit } from './general/page'
import { GluttenFreeCrumbs } from '@/components/ui/BreadCrumbs'

// Opt out of caching for all data requests in the route segment
export const dynamic = 'force-dynamic'

/**
* Layout for edit area dashboard
*/
Expand All @@ -12,23 +15,22 @@ export default async function RootLayout ({
children: React.ReactNode
params: { slug: string }
}): Promise<any> {
const { area: { areaName, uuid, pathTokens, ancestors } } = await getPageDataForEdit(params.slug)
const { area: { uuid, pathTokens, ancestors } } = await getPageDataForEdit(params.slug)
return (
<div>
<div className='px-12 pt-8 pb-4'>
<div className='flex items-center justify-between'>
<h1 className='text-4xl tracking-tight'>Edit area <span className='text-secondary'>{areaName}</span>
</h1>
</div>
<div className='text-3xl tracking-tight font-semibold'>Edit area</div>

<GluttenFreeCrumbs pathTokens={pathTokens} ancestors={ancestors} />
<div className='text-sm flex justify-end'>
<a href={`/area/${uuid}`} className='flex items-center gap-2'>
<a href={`/area/${uuid}`} className='flex items-center gap-2 hover:underline'>
Return to public version <ArrowUUpLeft size={18} />
</a>
</div>
</div>

<hr className='border-1' />

<div className='pt-12 flex bg-base-200 flex-col lg:flex-row'>
<SidebarNav slug={params.slug} />
<main className='w-full px-2 lg:px-16'>
Expand Down
5 changes: 4 additions & 1 deletion src/app/editArea/[slug]/loading.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { PageContainer } from './general/page'

/**
* Loading skeleton
*/
export default function Loading (): JSX.Element {
return (
<PageContainer>
<PageContainer id='loading'>
<div className='card card-compact card-bordered w-full h-56 bg-base-300/20' />
<div className='card card-compact card-bordered w-full h-56 bg-base-300/20' />
<div className='card card-compact card-bordered w-full h-56 bg-base-300/20' />
Expand Down
12 changes: 0 additions & 12 deletions src/app/editArea/[slug]/location/page.tsx

This file was deleted.

28 changes: 0 additions & 28 deletions src/app/editArea/[slug]/manage/page.tsx

This file was deleted.

Loading

0 comments on commit 6dbb1f7

Please sign in to comment.