diff --git a/public/language.svg b/public/language.svg index 2518fb9..f9f9367 100644 --- a/public/language.svg +++ b/public/language.svg @@ -1,16 +1,6 @@ - - - - - - - - - - - - - - - + + + + + diff --git a/public/menu.svg b/public/menu.svg index d17ca80..8e583ca 100644 --- a/public/menu.svg +++ b/public/menu.svg @@ -1,8 +1,8 @@ - + - + diff --git a/public/redpin.png b/public/redpin.png new file mode 100644 index 0000000..4140c98 Binary files /dev/null and b/public/redpin.png differ diff --git a/src/elements/Header/index.tsx b/src/elements/Header/index.tsx index de0ae13..88e5692 100644 --- a/src/elements/Header/index.tsx +++ b/src/elements/Header/index.tsx @@ -14,7 +14,7 @@ export const RusPassHeader:React.FC = () =>{ navigate('/')}>
- + navigate('/buyed')} src='/language.svg'> navigate('/favorites')}> navigate('/login')} >
diff --git a/src/elements/RouteCard/index.tsx b/src/elements/RouteCard/index.tsx index bdb7804..5715f49 100644 --- a/src/elements/RouteCard/index.tsx +++ b/src/elements/RouteCard/index.tsx @@ -7,6 +7,7 @@ import Sidebar from "react-sidebar"; import { PlaceCard } from "../TourCard"; import { Collapse, Tabs, TabsProps } from "antd"; import { backend } from "../../consts"; +import { useNavigate } from "react-router-dom"; export interface RouteCardIE{ rawProps:any, @@ -36,7 +37,7 @@ export const RouteCard:React.FC = (props) =>{ const [showMap, setShowMap] = useState(false) const [selectedDay, setSelectedDay] = useState('0') const [liked, setLiked] = useState(false) - + let navigate = useNavigate() let cntPlaces = 0 props.options.forEach((route)=>{ cntPlaces += route.paths.length @@ -92,9 +93,17 @@ export const RouteCard:React.FC = (props) =>{ // backend.get('route/list').then((e)=>console.log(e.data)) backend.post('route/save', { points: props.rawProps.path - }) + }).then((e)=>console.log(e.data)) setLiked(!liked) } + + const onBuy = () =>{ + backend.post('route/save', { + points: props.rawProps.path + }).then((e)=>backend.get('buy/' + e.data.id + '/add_to_buy/')) + + navigate('/buyed') + } return(
= (props) =>{
setSelectedDay(e)} /> +
} diff --git a/src/elements/RouteChangeCard/index.tsx b/src/elements/RouteChangeCard/index.tsx new file mode 100644 index 0000000..9d5b18e --- /dev/null +++ b/src/elements/RouteChangeCard/index.tsx @@ -0,0 +1,102 @@ +import React, { useState } from "react"; +import { Button } from '../Button' +import { Block } from '../Block' +import './style.css' +import { MyMap } from "../map"; +import Sidebar from "react-sidebar"; +import { PlaceCard } from "../TourCard"; +import { Collapse, Tabs, TabsProps } from "antd"; +import { backend } from "../../consts"; + +export interface RouteCardIE{ + rawProps:any, + city:string, + options: { + date:string, + paths:({ + type:string + distance:number, + point_type:string, + point:{ + lat:number, + lon:number, + title: string, + description:string, + oid:string + } + })[] + }[] +} + +const { Panel } = Collapse; + + +export const RouteChangeCard:React.FC = (props) =>{ + + const [selectedDay, setSelectedDay] = useState('0') + + let cntPlaces = 0 + props.options.forEach((route)=>{ + cntPlaces += route.paths.length + }) + + let points = props.options[Number(selectedDay)].paths.map((path)=>{ + return { + description:path.point.description, + title: path.point.title, + cords:[path.point.lon, path.point.lat] + } + }) + + let remappedPoints = props.options[Number(selectedDay)].paths.map((path)=>{ + if (path.point_type == 'remapped_point'){ + return { + description:path.point.description, + title: path.point.title, + cords:[path.point.lon, path.point.lat] + } + } + + }) + + for (let i = 0; i < remappedPoints.length; i++) { + if (remappedPoints[i] == undefined) { + remappedPoints.splice(i, 1); + i--; + } + } + console.log(remappedPoints) + + + + const colapseItems: TabsProps['items'] = props.options.map((day, index)=>{ + + return { + key:index.toString(), + label: (index+1).toString() + 'день', + children: + { + day.paths.map((value, index2) => + + +

{value.point.description}

+
+ ) + } +
+ + } + }) + + + return( +
+
{props.city}
+ + setSelectedDay(e)} /> +
+ + ); +} \ No newline at end of file diff --git a/src/elements/RouteChangeCard/style.css b/src/elements/RouteChangeCard/style.css new file mode 100644 index 0000000..3b98599 --- /dev/null +++ b/src/elements/RouteChangeCard/style.css @@ -0,0 +1,191 @@ +.tourcard-block{ + width: 400px; + height: 548px; + display: flex; + flex-direction: column; + gap:25px; + padding: 25px; + border: solid #F5DFB8 1px; + background-color: #fff; +} + +.cardDescr{ + display: flex; + flex-direction: row; + justify-content: space-between; +} + +.cardTitle{ + display: flex; + flex-direction: column; + gap:15px; +} + +.cardInfo{ + display: flex; + gap:15px; + color:rgba(29, 29, 29, 0.5) +} + +.cardAvatar{ + height: 100px; + transform: rotate(5deg); +} + +.titleText{ + font-size: 24px; + padding-right: 50px; +} + +.placesWrapper{ + display: flex; + flex-direction: column; + gap:20px; + margin-top: 30px; + height: 260px; + overflow-y: scroll; +} +.placesWrapper::-webkit-scrollbar { + width: 0; + } +.placeCard{ + width: 100%; + display: flex; + flex-direction: row; + justify-content: space-between; +} + +.placeImage{ + width: 40px; + height: 40px; + border-radius: 5px; +} + +.placeDescrWrapper{ + display: flex; + flex-direction: column; + gap:7px; + font-size: 16px; +} + +.placeType{ + color:rgba(29, 29, 29, 0.5); + font-size: 12px; +} + +.mainCardContent{ + position: relative !important; +} + +.tourCardSidebar{ + position: fixed !important; + left: 0px; + width: 30%; + top:0px; + border-radius: 0px 20px 20px 0px; + padding: 50px; +} + +.sidebarChangeContent{ + display: flex; + flex-direction: column; + gap:50px; + align-items: center; + justify-content: space-between; + width: 400px; + height: 100%; +} + + +.openBtn{ + display: flex; + flex-direction: row; + +} + +.yOpenBtn{ + width: 80%; + height:48px; + background: #FFCF08; + padding: 0px 16px; + border-radius: 20px 4px 4px 20px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + cursor: pointer; + transition: 0.3s; +} + +.yOpenBtn:hover{ + opacity: 0.5; +} + +.yOpenBtnTitle{ + font-weight: 500; + font-size: 16px; + line-height: 22px; + color: #1D1D1D; +} +.yOpenBtnDescr{ + font-weight: 500; + font-size: 14px; + line-height: 18px; + text-align: center; + color: rgba(29, 29, 29, 0.5); +} + +.btnWrapper{ + display: flex; + flex-direction: row; + width: 100%; + gap:5px; + align-items: center; + justify-content: center; +} + +.likeBtn{ + height:48px; + padding: 0px 13px 0px 11px; + background: rgba(245, 223, 184, 0.5); + border-radius: 4px 20px 20px 4px; + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + cursor: pointer; + transition: 0.3s; +} + +.likeBtn:hover{ + opacity: 0.5; +} + +@media screen and (max-device-width: 600px) { + .tourcard-block{ + width: 300px; + gap:15px; + padding: 15px; + } + .titleText{ + font-size: 18px; + line-height: 22px; + } + + .cardInfo{ + font-size: 14px; + } + .tourCardSidebar{ + width: calc(100% - 150px); + } +} + +@media screen and (max-device-width: 400px) { + .tourcard-block{ + width: 280px; + } +} + +.tabs{ + width: 100%; +} \ No newline at end of file diff --git a/src/elements/map/index.tsx b/src/elements/map/index.tsx index 883b8f3..00147ad 100644 --- a/src/elements/map/index.tsx +++ b/src/elements/map/index.tsx @@ -14,6 +14,12 @@ export interface MapIE{ description:string }[] + remapedPoints?:{ + cords:number[], + title:string, + description:string + }[] + } export const MyMap: React.FC = (props) =>{ @@ -26,13 +32,12 @@ export const MyMap: React.FC = (props) =>{ const [route, setRoute] = useState() - console.log(route) useEffect(()=>{ setTimeout(()=> axios.get('https://api.mapbox.com/directions/v5/mapbox/walking/'+pathString+'?alternatives=true&continue_straight=true&geometries=geojson&language=en&overview=simplified&steps=true&access_token=pk.eyJ1IjoiZmlyZXNpZWh0IiwiYSI6ImNrdW9kemYzbTB4ZGkycHAxbXN2YnIzaGMifQ.G0fl-qVbecucfOvn8OtU4Q').then( (data:any) => setRoute(data.data.routes[0].geometry) - ), 1000) + ).catch((err)=>console.log('ERRRRRRRR')), 1000) }) @@ -91,7 +96,6 @@ export const MyMap: React.FC = (props) =>{ } }; - console.log(props) return (
@@ -119,6 +123,13 @@ export const MyMap: React.FC = (props) =>{ }) } + { + props.remapedPoints != undefined? props.remapedPoints.map((point, index)=>{ + return + + + }) : null + }
diff --git a/src/pages/Buyed/index.tsx b/src/pages/Buyed/index.tsx new file mode 100644 index 0000000..3fbde18 --- /dev/null +++ b/src/pages/Buyed/index.tsx @@ -0,0 +1,88 @@ +import { Spin } from "antd"; +import React, { useEffect, useState } from "react"; +import { backend } from "../../consts"; +import { RusPassHeader } from "../../elements/Header"; +import { RouteCard } from "../../elements/RouteCard"; + +export const Buyed:React.FC = () =>{ + const [data, setData] = useState([]) + + useEffect(()=>{ + backend.get('/buy/').then((e)=>setData(e.data)) + }) + let newData; + + if (data.length != 0){ + newData = data.map((tour:any, index)=>{ + + let newPath = tour.points.map((path:any)=>{ + let newPaths = path.paths + for (let i = 0; i < newPaths.length; i++) { + if (newPaths[i].type == 'transition') { + newPaths.splice(i, 1); + i--; + } + } + + return { + date:path.date, + paths: newPaths + } + }) + + + return { + city: 'Тур №' + (index+1), + path: newPath + } + }) + } + + + + + + + + + + + return( +
+ + +

Ваши купленные туры

+ + { + data.length == 0 || newData == undefined? + + : +
+

Рекомендованные Туры

+ +
+ { + newData.map((tour:any, index:number)=> + + ) + } + +
+
+ } + + + Документация + +
+ + + + + +
+ +
© 2023 A project of the Government of Moscow
+
+ ); +} diff --git a/src/pages/Favorites/index.tsx b/src/pages/Favorites/index.tsx new file mode 100644 index 0000000..c21c589 --- /dev/null +++ b/src/pages/Favorites/index.tsx @@ -0,0 +1,77 @@ +import react, { useEffect, useRef, useState } from 'react' +import { useNavigate } from 'react-router-dom'; +import { backend, updateBackend } from '../../consts'; + +import { RusPassHeader } from '../../elements/Header'; +// import './style.css' + +import { EventCard } from '../../elements/EventCard'; +import { Spin } from 'antd'; + +export const Favorites: react.FC = () => { + const [favorites, setFavorites] = useState([]) + let navigate = useNavigate() + + + const queried = useRef(false); + + useEffect(()=>{ + updateBackend() + + const dataLoad = async () =>{ + const favorites = await backend.get('user/favorite') + return { + favorites + } + } + + if (!queried.current && localStorage.getItem('token') != null && localStorage.getItem('firstAuth') != 'true') { + queried.current = true; + dataLoad().then((data) => { + setFavorites(data.favorites.data as any); + }) + } + + if (null == localStorage.getItem('token')){ + navigate('/login') + } + }) + + return ( +
+ + +
+

Избранное

+
+ { + favorites.length == 0? + : + favorites.map((favorite:any, index)=>{ + return + + }) + } +
+
+ + Документация + +
+ + + + + +
+ +
© 2023 A project of the Government of Moscow
+
+ + ); +} \ No newline at end of file diff --git a/src/pages/Main/index.tsx b/src/pages/Main/index.tsx index 70d17c7..1cc8756 100644 --- a/src/pages/Main/index.tsx +++ b/src/pages/Main/index.tsx @@ -112,7 +112,7 @@ export const Main: react.FC = () => { }
- +
diff --git a/src/pages/Weather/index.tsx b/src/pages/Weather/index.tsx new file mode 100644 index 0000000..cb3a397 --- /dev/null +++ b/src/pages/Weather/index.tsx @@ -0,0 +1,104 @@ +import { Spin } from "antd"; +import React, { useEffect, useState } from "react"; +import { useParams } from "react-router-dom"; +import { backend } from "../../consts"; +import { Button } from "../../elements/Button"; +import { RusPassHeader } from "../../elements/Header"; +import { RouteCard } from "../../elements/RouteCard"; +import { RouteChangeCard } from "../../elements/RouteChangeCard"; +import './styles.css' +export const Weather:React.FC = () =>{ + let {routeChangeId} = useParams() + const [weather, setWeather] = useState() + + useEffect(()=>{ + if (weather == undefined){ + backend.get('weather/' + routeChangeId + '/').then((e)=>setWeather(e.data)) + } + }) + + let prev_route; + let predicted_route; + console.log(weather ) + if (weather != undefined){ + + let newPath = weather.prev_route.points.map((path:any)=>{ + let newPaths = path.paths + for (let i = 0; i < newPaths.length; i++) { + if (newPaths[i].type == 'transition') { + newPaths.splice(i, 1); + i--; + } + } + + return { + date:path.date, + paths: newPaths + } + }) + + + prev_route = { + city: 'Старый маршрут', + path: newPath + } + + let newPredictPath = weather.predicted_route.points.map((path:any)=>{ + let newPaths = path.paths + for (let i = 0; i < newPaths.length; i++) { + if (newPaths[i].type == 'transition') { + newPaths.splice(i, 1); + i--; + } + } + + return { + date:path.date, + paths: newPaths + } + }) + + predicted_route = { + city: 'Предлагаемый маршрут', + path: newPredictPath + } + + } + return
+ + + + { + prev_route == undefined || predicted_route == undefined? + + : +
+

Измените маршрут из-за погоды!

+ +
+ + +
+
+ + + +
+
+} + + + + Документация + +
+ + + + + +
+ +
© 2023 A project of the Government of Moscow
+
+} \ No newline at end of file diff --git a/src/pages/Weather/styles.css b/src/pages/Weather/styles.css new file mode 100644 index 0000000..7c68a5b --- /dev/null +++ b/src/pages/Weather/styles.css @@ -0,0 +1,21 @@ +.changeBtnWrapper{ + display: flex; + flex-direction: row; + gap:25px; + align-items:center ; + justify-content: center; +} + +.changeYBtn{ + width: 400px; + background: #FFCF08; +} +.changeBtn{ + width: 400px; +} + +@media screen and (max-device-width: 500px) { + .changeBtnWrapper{ + flex-wrap: wrap; + } +} \ No newline at end of file diff --git a/src/router.tsx b/src/router.tsx index 73a5ff3..5b17026 100644 --- a/src/router.tsx +++ b/src/router.tsx @@ -9,6 +9,9 @@ import { EventMatch } from './pages/EventMatch'; import { GenerateTour } from './pages/GenerateTour'; import { SearchPage } from './pages/SearchPage'; import { Prefernces } from './elements/Prefernces'; +import { Favorites } from './pages/Favorites'; +import { Weather } from './pages/Weather'; +import { Buyed } from './pages/Buyed'; const routes = [ @@ -43,6 +46,18 @@ const routes = [ { path: '/prefs', element: + }, + { + path:'/favorites', + element: + }, + { + path: '/route/:routeChangeId/change', + element: + }, + { + path: '/buyed', + element: } ]