diff --git a/front/.eslintrc.cjs b/front/.eslintrc.cjs index ec601b2..d46b749 100644 --- a/front/.eslintrc.cjs +++ b/front/.eslintrc.cjs @@ -11,5 +11,6 @@ module.exports = { plugins: ['react-refresh'], rules: { 'react-refresh/only-export-components': 'warn', + 'react/prop-types': 'off' }, } diff --git a/front/src/App.jsx b/front/src/App.jsx index aaf598f..6329f68 100644 --- a/front/src/App.jsx +++ b/front/src/App.jsx @@ -2,7 +2,7 @@ import { BrowserRouter as Router, Route, Routes, Link } from 'react-router-dom' import { HomePage, AddPage, LoginPage, UserPage } from './pages' -import WithToken from './components/WithToken' +import { WithToken } from './components' import 'leaflet/dist/leaflet.css' diff --git a/front/src/assets/metro.js b/front/src/assets/metro.js index 8b8172c..f577ae3 100644 --- a/front/src/assets/metro.js +++ b/front/src/assets/metro.js @@ -1,5 +1,5 @@ -const metros = { - red: [ +const stations = { + red: new Set([ "Девяткино", "Гражданский проспект", "Академическая", @@ -19,8 +19,8 @@ const metros = { "Автово", "Ленинский проспект", "Проспект Ветеранов" - ], - blue: [ + ]), + blue: new Set([ "Парнас", "Проспект Просвещения", "Озерки", @@ -39,8 +39,8 @@ const metros = { "Московская", "Звёздная", "Купчино" - ], - green: [ + ]), + green: new Set([ "Приморская", "Беговая", "Василеостровская", @@ -52,11 +52,9 @@ const metros = { "Пролетарская", "Обухово", "Рыбацкое" - ], - orange: [ + ]), + orange: new Set([ "Спасская", - "Горный институт", - "Театральная", "Достоевская", "Лиговский проспект", "Площадь Александра Невского", @@ -64,8 +62,8 @@ const metros = { "Ладожская", "Проспект Большевиков", "Улица Дыбенко" - ], - violet: [ + ]), + violet: new Set([ "Комендантский проспект", "Старая Деревня", "Крестовский остров", @@ -81,15 +79,23 @@ const metros = { "Проспект славы", "Дунайскай", "Шушары" - ], - gold: [ - "Юго западная", - "Каретная", - "Путиловская", - "Броневая", - "Заставская", - "Боровая" - ] + ]), } -export { metros } +const colors = { + red: "#D6083B", + blue: "#0078C9", + green: "#009A49", + orange: "#EA7125", + violet: "#702785", +} + +const lines = { + red: "Красная", + blue: "Синяя", + green: "Зелёная", + orange: "Оранжевая", + violet: "Фиолетовая", +} + +export { stations, colors, lines } diff --git a/front/src/components/AnnouncementDetails.jsx b/front/src/components/AnnouncementDetails.jsx index 7685e35..0439fa0 100644 --- a/front/src/components/AnnouncementDetails.jsx +++ b/front/src/components/AnnouncementDetails.jsx @@ -1,18 +1,19 @@ import { Modal, Button } from 'react-bootstrap' import { MapContainer, Marker, Popup, TileLayer } from 'react-leaflet' +import LineDot from './LineDot' import { categoryNames } from '../assets/category' import { useBook } from '../hooks/api' function AnnouncementDetails({ close, announcement: { id, name, category, bestBy, description, lat, lng, address, metro } }) { - const {handleBook, status: bookStatus} = useBook(id) + const { handleBook, status: bookStatus } = useBook(id) return (
- + Подробнее @@ -35,14 +36,18 @@ function AnnouncementDetails({ close, announcement: { id, name, category, bestBy /> - {address + "\n" + metro} + + {address} +
+ {metro} +
diff --git a/front/src/components/ClickHandler.jsx b/front/src/components/ClickHandler.jsx new file mode 100644 index 0000000..1404c20 --- /dev/null +++ b/front/src/components/ClickHandler.jsx @@ -0,0 +1,12 @@ +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 \ No newline at end of file diff --git a/front/src/components/Filters.jsx b/front/src/components/Filters.jsx index 9b63bd0..a8e156c 100644 --- a/front/src/components/Filters.jsx +++ b/front/src/components/Filters.jsx @@ -1,7 +1,7 @@ import { Button, Form, Modal } from "react-bootstrap" import { categoryNames } from "../assets/category" -import { metros } from '../assets/metro' +import { stations, lines } from '../assets/metro' function Filters({ filter, setFilter, filterShown, setFilterShown }) { @@ -55,11 +55,13 @@ function Filters({ filter, setFilter, filterShown, setFilterShown }) { - {Object.entries(metros).map( - ([branch, stations]) => - stations.map(metro => - - ) + {Object.entries(stations).map( + ([line, stations]) => + + {Array.from(stations).map(metro => + + )} + )} diff --git a/front/src/components/LineDot.jsx b/front/src/components/LineDot.jsx new file mode 100644 index 0000000..c9ee77c --- /dev/null +++ b/front/src/components/LineDot.jsx @@ -0,0 +1,12 @@ +import { colors, lines } from '../assets/metro' +import { lineByName } from '../utils/metro' + +function LineDot({ station }) { + const line = lineByName(station) + const lineTitle = lines[line] + const color = colors[line] + + return +} + +export default LineDot diff --git a/front/src/components/index.js b/front/src/components/index.js new file mode 100644 index 0000000..eeffa7d --- /dev/null +++ b/front/src/components/index.js @@ -0,0 +1,19 @@ +import AnnouncementDetails from "./AnnouncementDetails" +import BottomNavBar from "./BottomNavBar" +import Filters from "./Filters" +import LineDot from "./LineDot" +import LocationMarker from './LocationMarker' +import TrashboxMarkers from './TrashboxMarkers' +import WithToken from './WithToken' +import ClickHandler from './ClickHandler' + +export { + AnnouncementDetails, + BottomNavBar, + Filters, + LineDot, + LocationMarker, + TrashboxMarkers, + WithToken, + ClickHandler, +} diff --git a/front/src/hooks/index.js b/front/src/hooks/index.js new file mode 100644 index 0000000..7f558fd --- /dev/null +++ b/front/src/hooks/index.js @@ -0,0 +1,5 @@ +import useStoryDimensions from "./useStoryDimensions" + +export { + useStoryDimensions, +} diff --git a/front/src/pages/AddPage.jsx b/front/src/pages/AddPage.jsx index 90528ee..dd14b99 100644 --- a/front/src/pages/AddPage.jsx +++ b/front/src/pages/AddPage.jsx @@ -1,13 +1,13 @@ 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 { latLng } from "leaflet" -import { metros } from "../assets/metro" -import LocationMarker from "../components/LocationMarker" -import TrashboxMarkers from "../components/TrashboxMarkers" -import { useAddAnnouncement, useTrashboxes } from "../hooks/api" +import { stations, lines } from "../assets/metro" function AddPage() { const [addressPosition, setAddressPosition] = useState(latLng(59.972, 30.3227)) @@ -46,7 +46,7 @@ function AddPage() { })() }, [addressPosition]) - const {doAdd, status} = useAddAnnouncement() + const { doAdd, status } = useAddAnnouncement() const handleSubmit = (event) => { event.preventDefault() @@ -107,6 +107,9 @@ function AddPage() { position={addressPosition} setPosition={setAddressPosition} /> +

Адрес: {address}

@@ -134,11 +137,13 @@ function AddPage() { - {Object.entries(metros).map( - ([branch, stations]) => - stations.map(metro => - - ) + {Object.entries(stations).map( + ([line, stations]) => + + {Array.from(stations).map(metro => + + )} + )} diff --git a/front/src/pages/HomePage.jsx b/front/src/pages/HomePage.jsx index 63cfe93..0602629 100644 --- a/front/src/pages/HomePage.jsx +++ b/front/src/pages/HomePage.jsx @@ -1,11 +1,8 @@ import { useEffect, useState } from 'react' import Stories from 'react-insta-stories' -import BottomNavBar from '../components/BottomNavBar' -import useStoryDimensions from '../hooks/useStoryDimensions' -import AnnouncementDetails from '../components/AnnouncementDetails' -import Filters from '../components/Filters' - +import { BottomNavBar, AnnouncementDetails, Filters } from '../components' +import { useStoryDimensions } from '../hooks' import { useHomeAnnouncementList } from '../hooks/api' import puffSpinner from '../assets/puff.svg' @@ -29,21 +26,21 @@ function fallbackGenerateStories(announcementsFetch) { return fallbackStory() if (announcementsFetch.error) - return fallbackStory(announcementsFetch.error) + return fallbackStory(announcementsFetch.error, true) - if (stories.length == 0) + if (stories.length === 0) return fallbackStory("Здесь пока пусто") return stories } -const fallbackStory = (text) => [{ +const fallbackStory = (text, isError = false) => [{ content: ({ action }) => { // eslint-disable-next-line react-hooks/rules-of-hooks useEffect(() => { action('pause') }, [action]) return ( -
+
{text || }
) @@ -66,22 +63,14 @@ function HomePage() { return (<>
- {announcementsFetch.error ? - ( -
-

{announcementsFetch.error}

-
- ) : ( - - ) - } +
) diff --git a/front/src/pages/LoginPage.jsx b/front/src/pages/LoginPage.jsx index 3243ce8..cccf7a8 100644 --- a/front/src/pages/LoginPage.jsx +++ b/front/src/pages/LoginPage.jsx @@ -1,5 +1,6 @@ import { Form, Button, Card, Tabs, Tab } from "react-bootstrap" import { useNavigate } from "react-router-dom"; + import { useAuth } from "../hooks/api"; import { setToken } from "../utils/auth"; diff --git a/front/src/utils/metro.js b/front/src/utils/metro.js new file mode 100644 index 0000000..dce5a72 --- /dev/null +++ b/front/src/utils/metro.js @@ -0,0 +1,7 @@ +import { stations } from "../assets/metro" + +function lineByName(name) { + return Object.keys(stations).find(line => stations[line].has(name)) +} + +export { lineByName }