Fixed details dialog size Added map location setting by click Reorganized hooks and components imports with index.js Removed orphane error indication on homepage
205 lines
9.3 KiB
JavaScript
205 lines
9.3 KiB
JavaScript
import { useEffect, useState } from "react"
|
||
import { Form, Button, Card } from "react-bootstrap"
|
||
import { MapContainer, TileLayer } from 'react-leaflet'
|
||
import { latLng } from "leaflet"
|
||
|
||
import { ClickHandler, LocationMarker, TrashboxMarkers } from "../components"
|
||
import { useAddAnnouncement, useTrashboxes } from "../hooks/api"
|
||
|
||
import { categoryNames } from "../assets/category"
|
||
import { stations, lines } from "../assets/metro"
|
||
|
||
function AddPage() {
|
||
const [addressPosition, setAddressPosition] = useState(latLng(59.972, 30.3227))
|
||
const [address, setAddress] = useState('')
|
||
|
||
const { data: trashboxes, trashboxes_loading, trashboxes_error } = useTrashboxes(addressPosition)
|
||
const [selectedTrashbox, setSelectedTrashbox] = useState({ index: -1, category: '' })
|
||
|
||
useEffect(() => {
|
||
(async () => {
|
||
try {
|
||
const res = await fetch(location.protocol + "//nominatim.openstreetmap.org/search?format=json&q=" + address)
|
||
|
||
const fetchData = await res.json()
|
||
|
||
console.log("f", fetchData)
|
||
|
||
} catch (err) {
|
||
console.error(err)
|
||
}
|
||
})()
|
||
}, [address])
|
||
|
||
useEffect(() => {
|
||
(async () => {
|
||
try {
|
||
const res = await fetch(location.protocol + "//nominatim.openstreetmap.org/reverse?format=json&accept-language=ru&lat=" + addressPosition.lat + "&lon=" + addressPosition.lng)
|
||
|
||
const fetchData = await res.json()
|
||
|
||
setAddress(fetchData.display_name)
|
||
|
||
} catch (err) {
|
||
console.error(err)
|
||
}
|
||
})()
|
||
}, [addressPosition])
|
||
|
||
const { doAdd, status } = useAddAnnouncement()
|
||
|
||
const handleSubmit = (event) => {
|
||
event.preventDefault()
|
||
event.stopPropagation()
|
||
|
||
const formData = new FormData(event.target)
|
||
|
||
formData.append("latitude", addressPosition.lat)
|
||
formData.append("longtitude", addressPosition.lng)
|
||
formData.append("address", address)
|
||
formData.set("bestBy", new Date(formData.get("bestBy")).getTime())
|
||
|
||
doAdd(formData)
|
||
}
|
||
|
||
return (
|
||
<Card className="m-4" style={{ height: 'calc(100vh - 3rem)' }}>
|
||
<Card.Body style={{ overflowY: "auto" }} >
|
||
<Form onSubmit={handleSubmit}>
|
||
<Form.Group className="mb-3" controlId="name">
|
||
<Form.Label>Заголовок объявления</Form.Label>
|
||
<Form.Control type="text" required name="name" />
|
||
</Form.Group>
|
||
|
||
<Form.Group className="mb-3" controlId="category">
|
||
<Form.Label>Категория</Form.Label>
|
||
<Form.Select required name="category">
|
||
<option value="" hidden>
|
||
Выберите категорию
|
||
</option>
|
||
{Array.from(categoryNames).map(
|
||
([category, categoryName]) =>
|
||
<option key={category} value={category}>{categoryName}</option>
|
||
)}
|
||
</Form.Select>
|
||
</Form.Group>
|
||
|
||
<Form.Group className="mb-3" controlId="bestBy">
|
||
<Form.Label>Срок годности</Form.Label>
|
||
<Form.Control type="date" required name="bestBy" />
|
||
</Form.Group>
|
||
|
||
<Form.Group className="mb-3" controlId="address">
|
||
<Form.Label>Адрес выдачи</Form.Label>
|
||
<div className="mb-3">
|
||
<MapContainer
|
||
scrollWheelZoom={false}
|
||
style={{ width: "100%", height: 400 }}
|
||
center={addressPosition}
|
||
zoom={13}
|
||
>
|
||
<TileLayer
|
||
attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
||
/>
|
||
<LocationMarker
|
||
address={address}
|
||
position={addressPosition}
|
||
setPosition={setAddressPosition}
|
||
/>
|
||
<ClickHandler
|
||
setPosition={setAddressPosition}
|
||
/>
|
||
</MapContainer>
|
||
</div>
|
||
<p>Адрес: {address}</p>
|
||
</Form.Group>
|
||
|
||
<Form.Group className="mb-3" controlId="description">
|
||
<Form.Label>Описание</Form.Label>
|
||
<Form.Control as="textarea" name="description" rows={3} placeholder="Укажите свои контакты, а так же, когда вам будет удобно передать продукт" />
|
||
</Form.Group>
|
||
|
||
<Form.Group className="mb-3" controlId="src">
|
||
<Form.Label>Иллюстрация (фото или видео)</Form.Label>
|
||
<Form.Control
|
||
type="file"
|
||
name="src"
|
||
accept="video/mp4,video/mkv, video/x-m4v,video/*, image/*"
|
||
capture="environment"
|
||
/>
|
||
</Form.Group>
|
||
<Form.Group className="mb-3" controlId="metro">
|
||
<Form.Label>
|
||
Станция метро
|
||
</Form.Label>
|
||
<Form.Select name="metro">
|
||
<option value="">
|
||
Укажите ближайщую станцию метро
|
||
</option>
|
||
{Object.entries(stations).map(
|
||
([line, stations]) =>
|
||
<optgroup key={line} label={lines[line]}>
|
||
{Array.from(stations).map(metro =>
|
||
<option key={metro} value={metro}>{metro}</option>
|
||
)}
|
||
</optgroup>
|
||
)}
|
||
</Form.Select>
|
||
</Form.Group>
|
||
|
||
<Form.Group className="mb-3" controlId="password">
|
||
<Form.Label>Пункт сбора мусора</Form.Label>
|
||
<div className="mb-3">
|
||
{trashboxes_loading
|
||
? (
|
||
<div style={{ height: 400 }}>
|
||
<p>Загрузка</p>
|
||
</div>
|
||
) : (
|
||
trashboxes_error ? (
|
||
<p
|
||
style={{ height: 400 }}
|
||
className="text-danger"
|
||
>{trashboxes_error}</p>
|
||
) : (
|
||
<MapContainer
|
||
scrollWheelZoom={false}
|
||
style={{ width: "100%", height: 400 }}
|
||
center={addressPosition}
|
||
zoom={13}
|
||
className=""
|
||
>
|
||
<TileLayer
|
||
attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
||
/>
|
||
<TrashboxMarkers
|
||
trashboxes={trashboxes}
|
||
selectTrashbox={setSelectedTrashbox}
|
||
/>
|
||
</MapContainer>
|
||
)
|
||
)
|
||
}
|
||
</div>
|
||
{selectedTrashbox.index > -1 ? (
|
||
<p>Выбран пункт сбора мусора на {
|
||
trashboxes[selectedTrashbox.index].Address
|
||
} с категорией {selectedTrashbox.category}</p>
|
||
) : (
|
||
<p>Выберите пунк сбора мусора и категорию</p>
|
||
)}
|
||
</Form.Group>
|
||
|
||
<Button variant="success" type="submit">
|
||
{status}
|
||
</Button>
|
||
</Form>
|
||
</Card.Body>
|
||
</Card>
|
||
)
|
||
}
|
||
|
||
export default AddPage
|