Added TypeScript for frontend

Added type definitions for components, functions, data
Added guards for network responses
fixes #8
This commit is contained in:
2023-07-12 18:59:17 +03:00
parent 8fc85e415f
commit a8b7cfbffa
52 changed files with 1616 additions and 1651 deletions

View File

@ -4,8 +4,14 @@ import { MapContainer, Marker, Popup, TileLayer } from 'react-leaflet'
import LineDot from './LineDot'
import { categoryNames } from '../assets/category'
import { useBook } from '../hooks/api'
import { Announcement } from '../hooks/api/useHomeAnnouncementList'
function AnnouncementDetails({ close, announcement: { id, name, category, bestBy, description, lat, lng, address, metro } }) {
type AnnouncementDetailsProps = {
close: () => void,
announcement: Announcement
}
function AnnouncementDetails({ close, announcement: { id, name, category, bestBy, description, lat, lng, address, metro } }: AnnouncementDetailsProps) {
const { handleBook, status: bookStatus } = useBook(id)
return (
@ -46,7 +52,7 @@ function AnnouncementDetails({ close, announcement: { id, name, category, bestBy
</Modal.Body>
<Modal.Footer>
<Button variant='success' onClick={handleBook}>
<Button variant='success' onClick={() => void handleBook()}>
{bookStatus || "Забронировать"}
</Button>
</Modal.Footer>

View File

@ -4,20 +4,20 @@ import addIcon from '../assets/addIcon.svg'
import filterIcon from '../assets/filterIcon.svg'
import userIcon from '../assets/userIcon.svg'
const navBarStyles = {
const navBarStyles: React.CSSProperties = {
backgroundColor: 'var(--bs-success)',
height: 56,
width: "100%",
}
const navBarGroupStyles = {
const navBarGroupStyles: React.CSSProperties = {
display: "flex",
flexDirection: "row",
height: "100%",
margin: "auto"
}
const navBarElementStyles = {
const navBarElementStyles: React.CSSProperties = {
width: "100%",
height: "100%",
display: "flex",
@ -25,7 +25,12 @@ const navBarElementStyles = {
justifyContent: "center"
}
function BottomNavBar({ width, toggleFilters }) {
type BottomNavBarProps = {
width: number,
toggleFilters: (p: boolean) => void
}
function BottomNavBar({ width, toggleFilters }: BottomNavBarProps) {
return (
<div style={navBarStyles}>
<div style={{ ...navBarGroupStyles, width: width }}>
@ -47,4 +52,4 @@ function BottomNavBar({ width, toggleFilters }) {
)
}
export default BottomNavBar
export default BottomNavBar

View File

@ -1,12 +0,0 @@
import { useMapEvent } from "react-leaflet"
function ClickHandler({ setPosition }) {
const map = useMapEvent('click', (e) => {
setPosition(e.latlng)
map.setView(e.latlng)
})
return null
}
export default ClickHandler

View File

@ -0,0 +1,14 @@
import { useMapEvent } from "react-leaflet"
import { SetState } from "../utils/types"
import { LatLng } from "leaflet"
function ClickHandler({ setPosition }: { setPosition: SetState<LatLng> }) {
const map = useMapEvent('click', (e) => {
setPosition(e.latlng)
map.setView(e.latlng)
})
return null
}
export default ClickHandler

View File

@ -1,11 +1,21 @@
import { Button, Form, Modal } from "react-bootstrap"
import { categoryNames } from "../assets/category"
import { stations, lines } from '../assets/metro'
import { stations, lines, lineNames } from '../assets/metro'
import { FiltersType } from "../utils/filters"
import { SetState } from "../utils/types"
import { FormEventHandler } from "react"
function Filters({ filter, setFilter, filterShown, setFilterShown }) {
type FiltersProps = {
filter: FiltersType,
setFilter: SetState<FiltersType>,
filterShown: boolean,
setFilterShown: SetState<boolean>
}
const handleSubmit = (event) => {
function Filters({ filter, setFilter, filterShown, setFilterShown }: FiltersProps) {
const handleSubmit: FormEventHandler<HTMLFormElement> = (event) => {
event.preventDefault();
event.stopPropagation();
@ -13,8 +23,8 @@ function Filters({ filter, setFilter, filterShown, setFilterShown }) {
setFilter(prev => ({
...prev,
category: formData.get("category") || null,
metro: formData.get("metro") || null
category: (formData.get("category") as (FiltersType['category'] | null)) || undefined,
metro: (formData.get("metro") as (FiltersType['metro'] | null)) || undefined
}))
setFilterShown(false)
@ -55,10 +65,10 @@ function Filters({ filter, setFilter, filterShown, setFilterShown }) {
<option value="">
Выберите станцию метро
</option>
{Object.entries(stations).map(
([line, stations]) =>
<optgroup key={line} label={lines[line]}>
{Array.from(stations).map(metro =>
{lines.map(
line =>
<optgroup key={line} label={lineNames[line]}>
{Array.from(stations[line]).map(metro =>
<option key={metro} value={metro}>{metro}</option>
)}
</optgroup>

View File

@ -1,9 +1,13 @@
import { colors, lines } from '../assets/metro'
import { colors, lineNames } from '../assets/metro'
import { lineByName } from '../utils/metro'
function LineDot({ station }) {
function LineDot({ station }: { station: string }) {
const line = lineByName(station)
const lineTitle = lines[line]
if (line == undefined)
return <></>
const lineTitle = lineNames[line]
const color = colors[line]
return <span title={`${lineTitle} ветка`} style={{ color: color }}>&#11044;</span>

View File

@ -1,6 +1,14 @@
import { Marker, Popup, useMapEvents } from "react-leaflet"
import { LatLng } from 'leaflet'
import { SetState } from "../utils/types"
const LocationMarker = ({ address, position, setPosition }) => {
type LocationMarkerProps = {
address: string,
position: LatLng,
setPosition: SetState<LatLng>
}
const LocationMarker = ({ address, position, setPosition }: LocationMarkerProps) => {
const map = useMapEvents({
dragend: () => {

View File

@ -1,9 +1,15 @@
import { Marker, Popup } from "react-leaflet"
import { Trashbox } from "../hooks/api/useTrashboxes"
const TrashboxMarkers = ({ trashboxes, selectTrashbox }) => {
type TrashboxMarkersProps = {
trashboxes: Trashbox[],
selectTrashbox: ({ index, category }: { index: number, category: string }) => void
}
const TrashboxMarkers = ({ trashboxes, selectTrashbox }: TrashboxMarkersProps) => {
return (
<>{trashboxes.map((trashbox, index) => (
<Marker key={trashbox.Lat + "" + trashbox.Lng} position={[trashbox.Lat, trashbox.Lng]}>
<Marker key={`${trashbox.Lat}${trashbox.Lng}`} position={[trashbox.Lat, trashbox.Lng]}>
<Popup>
<p>{trashbox.Address}</p>
<p>Тип мусора: <>
@ -23,4 +29,4 @@ const TrashboxMarkers = ({ trashboxes, selectTrashbox }) => {
)
}
export default TrashboxMarkers
export default TrashboxMarkers

View File

@ -1,8 +1,8 @@
import { useEffect } from "react"
import { PropsWithChildren, useEffect } from "react"
import { getToken } from "../utils/auth"
import { useNavigate } from "react-router-dom"
function WithToken({ children }) {
function WithToken({ children }: PropsWithChildren) {
const navigate = useNavigate()
useEffect(() => {
@ -10,10 +10,10 @@ function WithToken({ children }) {
return navigate("/login")
}
}, [navigate])
return (
<>{children}</>
)
}
export default WithToken
export default WithToken