summaryrefslogblamecommitdiff
path: root/frontend/app.jsx
blob: 60bdcf4c8a0416342b4d557f94dc864359248e6d (plain) (tree)














































































































































































































                                                                                                                                  
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;