diff --git a/app/hooks/administrative-areas/index.ts b/app/hooks/administrative-areas/index.ts index 0a1e24c367..72b6653f18 100644 --- a/app/hooks/administrative-areas/index.ts +++ b/app/hooks/administrative-areas/index.ts @@ -1,25 +1,19 @@ -import { useMemo } from 'react'; - import { useQuery } from 'react-query'; import { useSession } from 'next-auth/react'; -import { Region } from 'types/country-model'; +import { Region, SubRegion } from 'types/api/location'; import ADMINISTRATIVE_AREAS from 'services/administrative-areas'; -import { UseAdministrativeAreasProps, UseAdministrativeAreasResponse } from './types'; - -export function useAdministrativeAreas( - props: UseAdministrativeAreasProps -): UseAdministrativeAreasResponse { +export function useAdministrativeAreas(props: { id: Region['id']; includeAll?: boolean }) { const { data: session } = useSession(); const { includeAll, id } = props; - const query = useQuery( + return useQuery( ['administrative areas', id], async () => - ADMINISTRATIVE_AREAS.request({ + ADMINISTRATIVE_AREAS.request<{ data: SubRegion[] }>({ method: 'GET', url: `/${id}/subdivisions`, params: { @@ -33,26 +27,18 @@ export function useAdministrativeAreas( }), { enabled: !!id, + select: (data) => { + const parsedData = Array.isArray(data?.data?.data) ? data?.data?.data : []; + + return parsedData.map((r) => ({ + name: r.name2, + id: r.id, + level: 2, + bbox: r.bbox, + minPuAreaSize: r.minPuAreaSize, + maxPuAreaSize: r.maxPuAreaSize, + })); + }, } ); - - const { data } = query; - - return useMemo(() => { - const parsedData = Array.isArray(data?.data?.data) ? data?.data?.data : []; - - const regions: Region[] = parsedData.map((r) => ({ - name: r.name2, - id: r.id, - level: 2, - bbox: r.bbox, - minPuAreaSize: r.minPuAreaSize, - maxPuAreaSize: r.maxPuAreaSize, - })); - - return { - ...query, - data: regions, - }; - }, [query, data?.data?.data]); } diff --git a/app/hooks/administrative-areas/types.ts b/app/hooks/administrative-areas/types.ts deleted file mode 100644 index 1658f5b74e..0000000000 --- a/app/hooks/administrative-areas/types.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Response } from 'types/api-model'; -import { Region } from 'types/country-model'; - -export interface UseAdministrativeAreasProps { - id: string; - includeAll?: boolean; -} - -export interface UseAdministrativeAreasResponse extends Response { - data: Region[]; -} diff --git a/app/hooks/countries/index.ts b/app/hooks/countries/index.ts index 991925ce88..bf20b35b0b 100644 --- a/app/hooks/countries/index.ts +++ b/app/hooks/countries/index.ts @@ -1,67 +1,57 @@ -import { useMemo } from 'react'; - import { useQuery } from 'react-query'; import { useSession } from 'next-auth/react'; -import { Country, Region } from 'types/country-model'; +import { Country, Region, RegionLevel } from 'types/api/location'; import COUNTRIES from 'services/countries'; -import { - UseCountriesProps, - UseCountriesResponse, - UseCountryRegionsProps, - UseCountryRegionsResponse, -} from './types'; - -export function useCountries(filters: UseCountriesProps): UseCountriesResponse { +export function useCountries(filters: { includeAll?: boolean }) { const { data: session } = useSession(); const { includeAll } = filters; - const query = useQuery('countries', async () => - COUNTRIES.request({ - method: 'GET', - url: '/', - params: { - ...(includeAll && { disablePagination: true }), - sort: 'name0', - omitFields: 'theGeom', - }, - headers: { - Authorization: `Bearer ${session.accessToken}`, + return useQuery( + ['countries'], + async () => + COUNTRIES.request<{ data: Country[] }>({ + method: 'GET', + params: { + ...(includeAll && { disablePagination: true }), + sort: 'name0', + omitFields: 'theGeom', + }, + headers: { + Authorization: `Bearer ${session.accessToken}`, + }, + }), + { + select: (data) => { + const parsedData = Array.isArray(data?.data?.data) ? data?.data?.data : []; + + return parsedData.map((c) => ({ + name: c.name0, + id: c.gid0, + bbox: c.bbox, + minPuAreaSize: c.minPuAreaSize, + maxPuAreaSize: c.maxPuAreaSize, + })); }, - }) + } ); - - const { data } = query; - - return useMemo(() => { - const parsedData = Array.isArray(data?.data?.data) ? data?.data?.data : []; - - const countries: Country[] = parsedData.map((c) => ({ - name: c.name0, - id: c.gid0, - bbox: c.bbox, - minPuAreaSize: c.minPuAreaSize, - maxPuAreaSize: c.maxPuAreaSize, - })); - - return { - ...query, - data: countries, - }; - }, [query, data?.data?.data]); } -export function useCountryRegions(props: UseCountryRegionsProps): UseCountryRegionsResponse { +export function useCountryRegions(props: { + id: Region['id']; + includeAll?: boolean; + level: RegionLevel; +}) { const { data: session } = useSession(); const { includeAll, id, level } = props; - const query = useQuery( + return useQuery( ['country regions', id], async () => - COUNTRIES.request({ + COUNTRIES.request<{ data: Region[] }>({ method: 'GET', url: `/${id}/administrative-areas`, params: { @@ -76,26 +66,18 @@ export function useCountryRegions(props: UseCountryRegionsProps): UseCountryRegi }), { enabled: !!id, + select: (data) => { + const parsedData = Array.isArray(data?.data?.data) ? data?.data?.data : []; + + return parsedData.map((r) => ({ + name: r.name1, + id: r.id, + level: 1, + bbox: r.bbox, + minPuAreaSize: r.minPuAreaSize, + maxPuAreaSize: r.maxPuAreaSize, + })); + }, } ); - - const { data } = query; - - return useMemo(() => { - const parsedData = Array.isArray(data?.data?.data) ? data?.data?.data : []; - - const regions: Region[] = parsedData.map((r) => ({ - name: r.name1, - id: r.id, - level: 1, - bbox: r.bbox, - minPuAreaSize: r.minPuAreaSize, - maxPuAreaSize: r.maxPuAreaSize, - })); - - return { - ...query, - data: regions, - }; - }, [query, data?.data?.data]); } diff --git a/app/hooks/countries/types.ts b/app/hooks/countries/types.ts deleted file mode 100644 index ea45399ce3..0000000000 --- a/app/hooks/countries/types.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Response } from 'types/api-model'; -import { Country, Region, RegionLevel } from 'types/country-model'; - -export interface UseCountriesProps { - includeAll?: boolean; -} - -export interface UseCountryRegionsProps { - id: string; - includeAll?: boolean; - level: RegionLevel; -} - -export interface UseCountriesResponse extends Response { - data: Country[]; -} - -export interface UseCountryRegionsResponse extends Response { - data: Region[]; -} diff --git a/app/hooks/projects/index.ts b/app/hooks/projects/index.ts index a28342b430..997b8be2e5 100644 --- a/app/hooks/projects/index.ts +++ b/app/hooks/projects/index.ts @@ -17,7 +17,6 @@ import UPLOADS from 'services/uploads'; import { UseProjectsOptionsProps, - UseProjectsResponse, UseSaveProjectProps, SaveProjectProps, UseDeleteProjectProps, @@ -52,7 +51,7 @@ import { LegacyProjectValidationResultsProps, } from './types'; -export function useProjects(options: UseProjectsOptionsProps): UseProjectsResponse { +export function useProjects(options: UseProjectsOptionsProps) { const { push } = useRouter(); const { data: session } = useSession(); diff --git a/app/hooks/projects/types.ts b/app/hooks/projects/types.ts index fa0d18c55e..c8e550b5ed 100644 --- a/app/hooks/projects/types.ts +++ b/app/hooks/projects/types.ts @@ -1,14 +1,11 @@ import { AxiosRequestConfig } from 'axios'; -import { Response } from 'types/api-model'; - // useProjects export interface UseProjectsOptionsProps { search?: string; sort?: string; filters?: Record; } -export type UseProjectsResponse = Response; // useSaveProject export interface UseSaveProjectProps { diff --git a/app/hooks/scenarios/index.ts b/app/hooks/scenarios/index.ts index d9d661f8e1..d6719c46dd 100644 --- a/app/hooks/scenarios/index.ts +++ b/app/hooks/scenarios/index.ts @@ -20,7 +20,7 @@ import { useMe } from 'hooks/me'; import { useProjectUsers } from 'hooks/project-users'; import { ItemProps } from 'components/scenarios/item/component'; -import type { Project } from 'types/project-model'; +import type { Project } from 'types/api/project'; import DOWNLOADS from 'services/downloads'; import PROJECTS from 'services/projects'; diff --git a/app/hooks/solutions/mock.ts b/app/hooks/solutions/mock.ts index eabf35448a..f299cbf81c 100644 --- a/app/hooks/solutions/mock.ts +++ b/app/hooks/solutions/mock.ts @@ -1,4 +1,4 @@ -import { Solution } from 'types/project-model'; +import { Solution } from 'types/api/project'; const ITEMS: Solution[] = [ { diff --git a/app/layout/projects/all/list/item/component.tsx b/app/layout/projects/all/list/item/component.tsx index 2bd2d46679..c50ddfd31e 100644 --- a/app/layout/projects/all/list/item/component.tsx +++ b/app/layout/projects/all/list/item/component.tsx @@ -11,7 +11,7 @@ import { useProjectUsers } from 'hooks/project-users'; import Avatar from 'components/avatar'; import Button from 'components/button'; import Icon from 'components/icon'; -import type { Project } from 'types/project-model'; +import type { Project } from 'types/api/project'; import { ROLES } from 'utils/constants-roles'; import ARROW_RIGHT_2_SVG from 'svgs/ui/arrow-right-2.svg?sprite'; diff --git a/app/layout/projects/new/form/constants.ts b/app/layout/projects/new/form/constants.ts index d766efbef8..b32fa86113 100644 --- a/app/layout/projects/new/form/constants.ts +++ b/app/layout/projects/new/form/constants.ts @@ -1,8 +1,8 @@ -import { PlanningUnit } from 'types/project-model'; +import { PlanningArea } from 'types/api/project'; -export const DEFAULT_AREA = { +export const DEFAULT_AREA: Omit = { planningUnitAreakm2: 10, - planningUnitGridShape: PlanningUnit.HEXAGON, + planningUnitGridShape: 'hexagon', }; export const PA_OPTIONS = [ diff --git a/app/layout/projects/new/form/country-region-selector/index.ts b/app/layout/projects/new/form/country-region-selector/index.ts deleted file mode 100644 index b404d7fd44..0000000000 --- a/app/layout/projects/new/form/country-region-selector/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './component'; diff --git a/app/layout/projects/new/form/country-region-selector/component.tsx b/app/layout/projects/new/form/country-region-selector/index.tsx similarity index 95% rename from app/layout/projects/new/form/country-region-selector/component.tsx rename to app/layout/projects/new/form/country-region-selector/index.tsx index 3cd513254a..547d2f18f1 100644 --- a/app/layout/projects/new/form/country-region-selector/component.tsx +++ b/app/layout/projects/new/form/country-region-selector/index.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import { useEffect, useState, MouseEvent } from 'react'; import { Field as FieldRFF } from 'react-final-form'; import { useDispatch } from 'react-redux'; @@ -12,16 +12,19 @@ import Field from 'components/forms/field'; import Select from 'components/forms/select'; import { composeValidators } from 'components/forms/validations'; import Loading from 'components/loading'; -import { RegionLevel } from 'types/country-model'; +import { Country, Region, SubRegion } from 'types/api/location'; -import CountryRegionSelectorProps from './types'; - -export const CountryRegionSelector: React.FC = ({ +export const CountryRegionSelector = ({ country, region, subRegion, onClick, -}: CountryRegionSelectorProps) => { +}: { + country?: Country['id']; + region?: Region['id']; + subRegion?: SubRegion['id']; + onClick?: (evt: MouseEvent) => void; +}): JSX.Element => { const [selectedCountry, setSelectedCountry] = useState(country); const [selectedRegion, setSelectedRegion] = useState(region); const [selectedSubRegion, setSelectedSubRegion] = useState(subRegion); @@ -37,7 +40,7 @@ export const CountryRegionSelector: React.FC = ({ data: regionsData, isFetching: isFetchingRegions, isFetched: isFetchedRegions, - } = useCountryRegions({ id: selectedCountry, includeAll: true, level: RegionLevel.ONE }); + } = useCountryRegions({ id: selectedCountry, includeAll: true, level: 1 }); const { data: subRegionsData, diff --git a/app/layout/projects/new/form/country-region-selector/types.ts b/app/layout/projects/new/form/country-region-selector/types.ts deleted file mode 100644 index 50ef97465a..0000000000 --- a/app/layout/projects/new/form/country-region-selector/types.ts +++ /dev/null @@ -1,6 +0,0 @@ -export default interface CountryRegionSelectorProps { - country?: string; - region?: string; - subRegion?: string; - onClick?: () => void; -} diff --git a/app/layout/projects/new/form/planning-area-selector/planning-unit-grid/component.tsx b/app/layout/projects/new/form/planning-area-selector/planning-unit-grid/component.tsx index 766178e2cf..cca564a9cc 100644 --- a/app/layout/projects/new/form/planning-area-selector/planning-unit-grid/component.tsx +++ b/app/layout/projects/new/form/planning-area-selector/planning-unit-grid/component.tsx @@ -2,18 +2,20 @@ import React, { useState } from 'react'; import Label from 'components/forms/label'; import InfoButton from 'components/info-button'; -import { PlanningUnit } from 'types/project-model'; +import { PlanningUnit } from 'types/api/project'; -import PlanningUnitButton from './planning-unit-button/component'; -import { PlanningUnitButtonSizeProps } from './planning-unit-button/types'; -import { PlanningUnitGridProps } from './types'; +import PlanningUnitButton from './planning-unit-button'; +import { PlanningUnitButtonProps } from './planning-unit-button/types'; -export const PlanningUnitGrid: React.FC = ({ +export const PlanningUnitGrid = ({ unit, onChange, -}: PlanningUnitGridProps) => { +}: { + unit: PlanningUnit; + onChange?: (value: PlanningUnit) => void; +}) => { const [unitSelected, setUnitSelected] = useState(unit); - const handleClick = (value) => { + const handleClick = (value: Parameters[0]) => { setUnitSelected(value); if (onChange) { onChange(value); @@ -40,15 +42,15 @@ export const PlanningUnitGrid: React.FC = ({
diff --git a/app/layout/projects/new/form/planning-area-selector/planning-unit-grid/planning-unit-button/index.ts b/app/layout/projects/new/form/planning-area-selector/planning-unit-grid/planning-unit-button/index.ts deleted file mode 100644 index b404d7fd44..0000000000 --- a/app/layout/projects/new/form/planning-area-selector/planning-unit-grid/planning-unit-button/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './component'; diff --git a/app/layout/projects/new/form/planning-area-selector/planning-unit-grid/planning-unit-button/component.tsx b/app/layout/projects/new/form/planning-area-selector/planning-unit-grid/planning-unit-button/index.tsx similarity index 78% rename from app/layout/projects/new/form/planning-area-selector/planning-unit-grid/planning-unit-button/component.tsx rename to app/layout/projects/new/form/planning-area-selector/planning-unit-grid/planning-unit-button/index.tsx index b9e5daf4f1..e1d274fb94 100644 --- a/app/layout/projects/new/form/planning-area-selector/planning-unit-grid/planning-unit-button/component.tsx +++ b/app/layout/projects/new/form/planning-area-selector/planning-unit-grid/planning-unit-button/index.tsx @@ -1,9 +1,7 @@ import React from 'react'; -import cx from 'classnames'; - import Icon from 'components/icon'; -import { PlanningUnit } from 'types/project-model'; +import { cn } from 'utils/cn'; import HEXAGON_SELECTED_SVG from 'svgs/project/hexagon-selected.svg?sprite'; import HEXAGON_SVG from 'svgs/project/hexagon.svg?sprite'; @@ -13,7 +11,7 @@ import SQUARE_SVG from 'svgs/project/square.svg?sprite'; // import UPLOAD_SVG from 'svgs/project/upload.svg?sprite'; // import UPLOAD_SVG_SELECTED from 'svgs/project/upload-selected.svg?sprite'; -import { PlanningUnitButtonSizeProps, PlanningUnitButtonProps } from './types'; +import { PlanningUnitButtonProps } from './types'; export const PlanningUnitButton: React.FC = ({ unit, @@ -22,15 +20,15 @@ export const PlanningUnitButton: React.FC = ({ onClick, }: PlanningUnitButtonProps) => { const getButtonClassName = () => - cx({ + cn({ 'mb-2': true, - 'w-8 h-8': size === PlanningUnitButtonSizeProps.MEDIUM, - 'w-16 h-16': size === PlanningUnitButtonSizeProps.LARGE, - 'w-4 h-4': size === PlanningUnitButtonSizeProps.SMALL, + 'w-8 h-8': size === 'md', + 'w-16 h-16': size === 'lg', + 'w-4 h-4': size === 'sm', }); return (
= ({ onKeyPress={() => onClick && onClick(unit)} onClick={() => onClick && onClick(unit)} > - {unit === PlanningUnit.HEXAGON && ( + {unit === 'hexagon' && ( <> = ({ Hexagon )} - {unit === PlanningUnit.SQUARE && ( + {unit === 'square' && ( <> void; } - -export enum PlanningUnitButtonSizeProps { - SMALL = 'sm', - MEDIUM = 'md', - LARGE = 'lg', -} diff --git a/app/layout/projects/new/form/planning-area-selector/planning-unit-grid/types.ts b/app/layout/projects/new/form/planning-area-selector/planning-unit-grid/types.ts deleted file mode 100644 index bbc06bcb6a..0000000000 --- a/app/layout/projects/new/form/planning-area-selector/planning-unit-grid/types.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { PlanningUnit } from 'types/project-model'; - -export interface PlanningUnitGridProps { - unit: PlanningUnit; - onChange?: (value: PlanningUnit) => void; -} diff --git a/app/layout/scenarios/edit/solutions/overview/table/types.ts b/app/layout/scenarios/edit/solutions/overview/table/types.ts index f7809434a6..4a023f2e39 100644 --- a/app/layout/scenarios/edit/solutions/overview/table/types.ts +++ b/app/layout/scenarios/edit/solutions/overview/table/types.ts @@ -1,5 +1,5 @@ import { TableRow } from 'components/table/types'; -import { Solution } from 'types/project-model'; +import { Solution } from 'types/api/project'; export interface SolutionRow extends TableRow, Solution { 'view-on-map': boolean; diff --git a/app/store/slices/scenarios/detail.ts b/app/store/slices/scenarios/detail.ts index 220f18f83b..1663966fc4 100644 --- a/app/store/slices/scenarios/detail.ts +++ b/app/store/slices/scenarios/detail.ts @@ -1,7 +1,7 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'; import { injectReducer } from 'store'; -import { Solution } from 'types/project-model'; +import { Solution } from 'types/api/project'; import { ScenarioSidebarTabs } from 'utils/tabs'; interface ScenarioShowStateProps { diff --git a/app/store/slices/scenarios/edit.ts b/app/store/slices/scenarios/edit.ts index b650cfed37..e612a8d980 100644 --- a/app/store/slices/scenarios/edit.ts +++ b/app/store/slices/scenarios/edit.ts @@ -3,7 +3,7 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'; import type { ScenarioPlanningUnit } from 'hooks/scenarios/types'; import { injectReducer } from 'store'; -import { Solution } from 'types/project-model'; +import { Solution } from 'types/api/project'; import { ScenarioSidebarTabs } from 'utils/tabs'; import type { PUAction } from './types'; diff --git a/app/types/api-model.ts b/app/types/api-model.ts deleted file mode 100644 index b90308d29d..0000000000 --- a/app/types/api-model.ts +++ /dev/null @@ -1,5 +0,0 @@ -export interface Response { - isFetching: boolean; - isFetched: boolean; - data: any; -} diff --git a/app/types/api/location.ts b/app/types/api/location.ts new file mode 100644 index 0000000000..a020e9366e --- /dev/null +++ b/app/types/api/location.ts @@ -0,0 +1,22 @@ +export interface Location { + id: string; + gid0: string; + name0: string; + minPuAreaSize: number; + maxPuAreaSize: number; + bbox: [number, number, number, number]; +} + +export type Country = Location; + +export interface Region extends Location { + gid1: string; + name1: string; +} + +export interface SubRegion extends Location, Region { + gid2: string; + name2: string; +} + +export type RegionLevel = 1 | 2; diff --git a/app/types/project-model.ts b/app/types/api/project.ts similarity index 75% rename from app/types/project-model.ts rename to app/types/api/project.ts index ed001a4355..ccd6ebefc2 100644 --- a/app/types/project-model.ts +++ b/app/types/api/project.ts @@ -6,6 +6,8 @@ export interface Project { contributors?: Record[]; } +export type PlanningUnit = 'square' | 'hexagon' | 'from_shapefile'; + export interface PlanningArea { planningUnitGridShape: PlanningUnit; planningUnitAreakm2: number; @@ -13,17 +15,6 @@ export interface PlanningArea { region?: Object; } -export enum PlanningUnit { - SQUARE = 'square', - HEXAGON = 'hexagon', - FROM_SHAPEFILE = 'from_shapefile', -} - -export enum PlanningUnitAreaSizeUnit { - KM2 = 'KM2', - ML2 = 'ML2', -} - export interface Area { planningUnitGridShape?: string; planningUnitAreakm2: number; diff --git a/app/types/country-model.ts b/app/types/country-model.ts deleted file mode 100644 index 2f75a635bf..0000000000 --- a/app/types/country-model.ts +++ /dev/null @@ -1,21 +0,0 @@ -export interface Country { - name: string; - id: string; - bbox: number[]; - minPuAreaSize: number; - maxPuAreaSize: number; -} - -export interface Region { - name: string; - id: string; - level: RegionLevel; - bbox: number[]; - minPuAreaSize: number; - maxPuAreaSize: number; -} - -export enum RegionLevel { - ONE = 1, - TWO = 2, -}