import React, { useState, useEffect } from "react";
import GlMap, { Source, Marker, Layer } from "react-map-gl/maplibre";
import {
Flex,
Layout,
Col,
Row,
Modal,
Form,
Input,
Button,
Image,
Card,
} from "antd";
const { Header, Content } = Layout;
const layout = {
labelCol: { span: 8 },
wrapperCol: { span: 16 },
};
const geostyle = {
id: "data",
type: "line",
paint: {
"line-color": "red",
"line-width": 3,
},
};
const App = () => {
const [state, setState] = useState({});
const [selected, setSelected] = useState(null);
const [guess, setGuess] = useState(null);
const [loading, setLoading] = useState(true);
const [form] = Form.useForm();
useEffect(() => {
fetch("/api/state")
.then((x) => x.json())
.then(setState)
.then(() => setLoading(false));
}, []);
useEffect(() => {
if (guess != null) {
setState(guess.state);
}
}, [guess]);
const onFinish = (values) => {
fetch("/api/state", {
method: "POST",
body: JSON.stringify(values),
headers: { "content-type": "application/json" },
})
.then((x) => x.json())
.then(setState);
};
const onReset = () => {
form.resetFields();
};
const onNext = () => {
setSelected(null);
setGuess(null);
setLoading(true);
fetch("/api/next", {
method: "POST",
headers: { "content-type": "application/json" },
})
.then((x) => x.json())
.then(setState)
.then(() => setLoading(false));
};
const onMapClick = (e) => {
if (state.current_guid) {
setSelected(e.lngLat);
}
};
const onGuess = () => {
setLoading(true);
fetch("/api/guess", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify(selected),
})
.then((x) => x.json())
.then(setGuess)
.then(() => setLoading(false));
};
return (
<>
<Layout>
<Content>
<Row style={{ height: "100vh" }}>
<Col sm={16}>
<GlMap
initialViewState={{
longitude: 49.106414,
latitude: 55.796127,
zoom: 11,
}}
onClick={onMapClick}
style={{ width: "100%", height: "100%" }}
mapStyle="https://tiles.openfreemap.org/styles/liberty"
>
{selected ? (
<Marker
latitude={selected.lat}
longitude={selected.lng}
/>
) : null}
{guess ? (
<Source
type="geojson"
data={JSON.parse(guess.geojson)}
>
<Layer {...geostyle} />
</Source>
) : null}
</GlMap>
</Col>
<Col sm={8}>
{state.username ? (
<Card>
<h1>{state.username}</h1>
<h2>{state.points} очков</h2>
</Card>
) : null}
<Card>
{!loading && !state.current_guid ? (
<Button
type="primary"
onClick={onNext}
block
size="large"
>
Новое задание
</Button>
) : null}
{!loading && state.current_guid ? (
<Image src={state.image} />
) : null}
{!loading && guess ? (
<>
<h2>{guess.name}</h2>
<Image src={guess.image} />
<h3>Расстояние: {guess.distance / 1000}км.</h3>
</>
) : null}
{state.current_guid && !selected ? (
<p>
Нажмите на карте на точку, где по вашему
мнение находится то, что на фотографии
</p>
) : null}
{state.current_guid && selected ? (
<Button
type="primary"
onClick={onGuess}
block
size="large"
>
Проверить
</Button>
) : null}
</Card>
<p>Сделал <a href="https://neonxp.ru">Александр Кирюхин</a> в 2024 году</p>
</Col>
</Row>
</Content>
</Layout>
<Modal
title="Представьтесь"
open={!loading && !state.username}
onOk={form.submit}
onCancel={onReset}
>
<p>Для начала игры необходимо представиться</p>
<Form
{...layout}
form={form}
name="control-hooks"
onFinish={onFinish}
style={{ maxWidth: 600 }}
>
<Form.Item
name="username"
label="Имя"
rules={[{ required: true }]}
>
<Input />
</Form.Item>
</Form>
</Modal>
</>
);
};
export default App;