Skip to content

Commit

Permalink
feat: add parent area data to the popup area
Browse files Browse the repository at this point in the history
  • Loading branch information
fityannugroho committed Feb 27, 2024
1 parent 26da033 commit 0c69725
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 4 deletions.
46 changes: 42 additions & 4 deletions components/geojson-area.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
'use client'

import { Areas as BaseAreas, singletonArea } from '@/lib/const'
import { GetSpecificDataReturn, getSpecificData } from '@/lib/data'
import { addDotSeparator, getAllParents, ucFirstStr } from '@/lib/utils'
import dynamic from 'next/dynamic'
import { useEffect, useState } from 'react'
import { GeoJSONProps } from 'react-leaflet'
Expand Down Expand Up @@ -39,6 +41,8 @@ export default function GeoJsonArea<A extends Areas>({
}: GeoJsonAreaProps<A>) {
const [geoJson, setGeoJson] =
useState<GeoJSON.Feature<GeoJSON.MultiPolygon>>()
const [areaData, setAreaData] = useState<GetSpecificDataReturn<A>['data']>()
const parents = getAllParents(area)

useEffect(() => {
setGeoJson(undefined)
Expand All @@ -63,16 +67,50 @@ export default function GeoJsonArea<A extends Areas>({
closeButton: true,
})
})

getSpecificData(area, code)
.then((res) => {
if ('data' in res) return setAreaData(res.data)
throw new Error(
Array.isArray(res.message) ? res.message[0] : res.message,
)
})
.catch((err) => {
toast.error(`Failed to fetch ${singletonArea[area]} data`, {
description: err.message,
closeButton: true,
})
})
}
}, [area, code])

return geoJson && !hide ? (
<GeoJSON key={code} data={geoJson} {...props}>
<Popup>
<b className="mb-2">{geoJson.properties?.name}</b>
<span className="block text-gray-500">
Code: {geoJson.properties?.code}
</span>
{areaData ? (
<>
<span className="block font-bold text-sm">{areaData.name}</span>
<span className="text-sm">{addDotSeparator(areaData.code)}</span>

{parents.map((parent) => {
const parentData = areaData.parent[singletonArea[parent]]

if (!parentData) return null

return (
<div key={parent} className="mt-1">
<span className="text-xs text-gray-500">
{ucFirstStr(singletonArea[parent])} :
</span>
<br />
<span className="text-xs">{parentData.name}</span>
</div>
)
})}
</>
) : (
<span className="block text-gray-500">Loading...</span>
)}
</Popup>
</GeoJSON>
) : (
Expand Down
19 changes: 19 additions & 0 deletions lib/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,22 @@ export async function getData<Area extends Areas>(

return await res.json()
}

export type GetSpecificDataReturn<Area extends Areas> = {
statusCode: number
message: string
data: GetArea<Area> & {
parent: {
[P in Areas as (typeof singletonArea)[P]]?: GetArea<P>
}
}
}

export async function getSpecificData<Area extends Areas>(
area: Area,
code: string,
): Promise<GetSpecificDataReturn<Area> | GetDataReturnError> {
const res = await fetch(`${baseUrl}/${area}/${code}`)

return await res.json()
}
12 changes: 12 additions & 0 deletions lib/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { type ClassValue, clsx } from 'clsx'
import { twMerge } from 'tailwind-merge'
import { Areas, parentArea } from './const'

/**
* Add dot separator for the area code.
Expand Down Expand Up @@ -50,3 +51,14 @@ export function debounce<T extends any[]>(
export function ucFirstStr(str: string): string {
return str.charAt(0).toUpperCase() + str.slice(1)
}

/**
* Get all parents of an area.
*/
export function getAllParents<Area extends Areas>(area: Area): Areas[] {
const parent = parentArea[area]

if (!parent) return []

return [parent, ...getAllParents(parent)]
}

0 comments on commit 0c69725

Please sign in to comment.