Updated api endpoint structure, fixed issues, worked on admin page

This commit is contained in:
2023-11-21 11:00:01 -05:00
parent cb9db1f3ba
commit 2e048fb1a0
12 changed files with 326 additions and 137 deletions

View File

@@ -1,6 +1,6 @@
import { getAirports, importAirports, removeAirport } from "@/api/airport";
import { Airport, AirportCategory, AirportOrderField, airportCategoryToText } from "@/api/airport.types";
import { Text, Button, Card, Group, Pagination, ScrollArea, Table, TextInput, rem, UnstyledButton, Center } from "@mantine/core";
import { Airport, airportCategoryToText } from "@/api/airport.types";
import { Text, Button, Card, Group, Pagination, Table, TextInput, rem, UnstyledButton, Center, Flex, Container, Grid, Space } from "@mantine/core";
import { HiChevronUp, HiChevronDown, HiSelector } from "react-icons/hi";
import { useEffect, useState } from "react";
import { CiSearch } from "react-icons/ci";
@@ -14,6 +14,7 @@ export default function AirportTablePanel({ setAirport }: { setAirport: (airport
async function getAirportData() {
const response = await getAirports({
search,
page,
limit: 100
});
@@ -45,14 +46,12 @@ export default function AirportTablePanel({ setAirport }: { setAirport: (airport
<Table.Td>{airport.gps_code}</Table.Td>
<Table.Td>{airport.iata_code}</Table.Td>
<Table.Td>{airport.local_code}</Table.Td>
<Table.Td>{airport.point.x}</Table.Td>
<Table.Td>{airport.point.y}</Table.Td>
</Table.Tr>
))
return <Card shadow={'sm'} padding={'lg'} radius={'md'} withBorder>
<TextInput
placeholder="Search by ICAO"
placeholder="Search..."
mb="md"
leftSection={<CiSearch style={{ width: rem(16), height: rem(16) }} />}
value={search}
@@ -72,28 +71,36 @@ export default function AirportTablePanel({ setAirport }: { setAirport: (airport
<Table.Th>GPS Code</Table.Th>
<Table.Th>IATA Code</Table.Th>
<Table.Th>Local Code</Table.Th>
<Table.Th>Latitude</Table.Th>
<Table.Th>Longitude</Table.Th>
</Table.Tr>
</Table.Thead>
<Table.Tbody>{rows}</Table.Tbody>
</Table>
</Table.ScrollContainer>
<Group>
<Pagination value={page} total={totalPages} onChange={setPage} />
<PanelButton onClick={async () => {
await importAirports();
await getAirportData();
}}>
Import
</PanelButton>
<PanelButton color={'red'} onClick={async () => {
await removeAirport({});
await getAirportData();
}}>
Remove All
</PanelButton>
</Group>
<Grid mt={'md'} justify={'space-between'}>
<Grid.Col span={10}>
<Pagination value={page} total={totalPages} onChange={setPage} />
</Grid.Col>
<Grid.Col span={2}>
<Flex justify={'end'}>
<Space mr={'sm'}>
<PanelButton onClick={async () => {
await importAirports();
await getAirportData();
}}>
Import
</PanelButton>
</Space>
<Space>
<PanelButton color={'red'} onClick={async () => {
await removeAirport({});
await getAirportData();
}}>
Remove All
</PanelButton>
</Space>
</Flex>
</Grid.Col>
</Grid>
</Card>
}
@@ -103,7 +110,6 @@ function PanelButton({ children, color = 'blue', onClick }: {children: any, colo
loading={loading}
variant='light'
color={color}
mt={'md'}
radius={'md'}
onClick={() => {
setLoading(true);

View File

@@ -1,9 +1,10 @@
import { createAirport } from "@/api/airport";
import { Airport, AirportCategory } from "@/api/airport.types";
import { Card, TextInput, Select, Group, Flex, Space, Button } from "@mantine/core";
import { useForm } from "@mantine/form";
import { useEffect } from "react";
export default function CreateAirportPanel({ airport, setAirport } : { airport?: Airport, setAirport: (airport: Airport | undefined) => void }) {
export default function CreateAirportPanel() {
const form = useForm<Airport>({
initialValues: {
icao: '',
@@ -25,20 +26,12 @@ export default function CreateAirportPanel({ airport, setAirport } : { airport?:
}
});
useEffect(() => {
console.log(airport);
if (airport) {
form.setValues(airport);
}
}, [airport]);
return <Card shadow={'sm'} padding={'lg'} radius={'md'} withBorder>
Create Airport
<form onSubmit={form.onSubmit((values) => {
if (airport) {
console.log('update');
} else {
console.log('create');
<form onSubmit={form.onSubmit(async (values) => {
const response = await createAirport({ airport: values });
if (response.success) {
form.reset();
}
})}>
<TextInput
@@ -136,7 +129,7 @@ export default function CreateAirportPanel({ airport, setAirport } : { airport?:
color='blue'
radius={'md'}
>
{airport ? 'Update' : 'Create'}
Create
</Button>
</Space>
<Space>
@@ -145,10 +138,7 @@ export default function CreateAirportPanel({ airport, setAirport } : { airport?:
variant='light'
color='red'
radius={'md'}
onClick={() => {
form.reset();
setAirport(undefined);
}}
onClick={() => form.reset()}
>
Reset
</Button>

View File

@@ -0,0 +1,148 @@
import { removeAirport, updateAirport } from "@/api/airport";
import { Airport, AirportCategory } from "@/api/airport.types";
import { Button, Container, Flex, Group, Modal, Paper, Select, TextInput, Title } from "@mantine/core";
import { useForm } from "@mantine/form";
import { useEffect } from "react";
export default function UpdateAirportModal({ airport, setAirport }: { airport: Airport | undefined, setAirport: (airport: Airport | undefined) => void}) {
const form = useForm<Airport>({
initialValues: {
icao: airport?.icao || '',
category: airport?.category || AirportCategory.SMALL,
full_name: airport?.full_name || '',
elevation_ft: airport?.elevation_ft || 0,
continent: airport?.continent || '',
iso_country: airport?.iso_country || '',
iso_region: airport?.iso_region || '',
municipality: airport?.municipality || '',
gps_code: airport?.gps_code || '',
iata_code: airport?.iata_code || '',
local_code: airport?.local_code || '',
point: {
x: airport?.point.x || 0,
y: airport?.point.y || 0,
srid: airport?.point.srid || 4326
}
}
});
useEffect(() => {
if (airport) {
form.setValues(airport);
}
}, [airport]);
return (
<Modal opened={airport !== undefined} onClose={() => setAirport(undefined)} withCloseButton={false} size={'50%'}>
<Container>
<Title ta='center'>Update Airport</Title>
<Paper withBorder p={30} mt={30} radius={'md'} shadow={'sm'}>
<form onSubmit={form.onSubmit(async (values) => {
const response = await updateAirport({ airport: values });
if (response.success) {
setAirport(undefined);
}
})}>
<TextInput
required
label='ICAO'
placeholder='KHEF'
{...form.getInputProps('icao')}
/>
<Select
required
label='Category'
placeholder='Select category'
data={[
{ value: AirportCategory.SMALL, label: 'Small' },
{ value: AirportCategory.MEDIUM, label: 'Medium' },
{ value: AirportCategory.LARGE, label: 'Large' },
]}
{...form.getInputProps('category')}
/>
<TextInput
required
label='Full Name'
placeholder='Manassas Regional Airport/Harry P. Davis Field'
{...form.getInputProps('full_name')}
/>
<TextInput
required
label='Elevation (ft)'
placeholder='192'
{...form.getInputProps('elevation_ft')}
/>
<Group>
<TextInput
required
label='Continent'
placeholder='NA'
{...form.getInputProps('continent')}
/>
<TextInput
required
label='ISO Country'
placeholder='US'
{...form.getInputProps('iso_country')}
/>
<TextInput
required
label='ISO Region'
placeholder='US-VA'
{...form.getInputProps('iso_region')}
/>
<TextInput
required
label='Municipality'
placeholder='Manassas'
{...form.getInputProps('municipality')}
/>
</Group>
<Group>
<TextInput
required
label='GPS Code'
placeholder='KHEF'
{...form.getInputProps('gps_code')}
/>
<TextInput
required
label='IATA Code'
placeholder='HEF'
{...form.getInputProps('iata_code')}
/>
<TextInput
required
label='Local Code'
placeholder='HEF'
{...form.getInputProps('local_code')}
/>
</Group>
<Group>
<TextInput
required
label='Latitude'
placeholder='38.72140121'
{...form.getInputProps('point.x')}
/>
<TextInput
required
label='Longitude'
placeholder='-77.51540375'
{...form.getInputProps('point.y')}
/>
</Group>
<Flex justify={'end'} mt={'sm'}>
<Button type='submit' variant='light'>Update Airport</Button>
{airport && <Button variant='light' color='red' ml={10} onClick={async () => {
if (await removeAirport({icao: airport.icao})) {
setAirport(undefined);
}
}}>Delete</Button>}
</Flex>
</form>
</Paper>
</Container>
</Modal>
);
}

View File

@@ -53,7 +53,7 @@ export default function Header() {
async function onChange(value: string) {
setSearchValue(value);
const airportData = await getAirports({ name: value, icao: value });
const airportData = await getAirports({ search: value });
setAirports(
airportData.data.map((airport) => ({
key: airport.icao,