add search page

This commit is contained in:
= 2023-05-27 02:32:34 +03:00
parent a53737bcf4
commit 6df47ee610
13 changed files with 1035 additions and 32 deletions

3
public/icons/heart.svg Normal file
View File

@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.3508 5.45537C8.65965 3.72582 5.87681 3.72581 4.1857 5.45537C2.54748 7.13082 2.54748 9.80799 4.18569 11.4834L11.7996 19.2704C11.9026 19.3757 12.072 19.3757 12.1749 19.2704L19.7888 11.4834C21.427 9.80799 21.427 7.13082 19.7888 5.45537C18.0977 3.72581 15.3149 3.72582 13.6237 5.45537L12.5235 6.5806C12.3824 6.72492 12.1891 6.80627 11.9873 6.80627C11.7854 6.80627 11.5921 6.72492 11.451 6.5806L10.3508 5.45537ZM20.8613 4.40669C23.0695 6.66508 23.0695 10.2737 20.8613 12.5321L13.2474 20.3191C12.5561 21.0261 11.4184 21.0261 10.7271 20.3191L3.11319 12.5321C0.904979 10.2737 0.90498 6.66508 3.11319 4.40669C5.3927 2.07537 9.14377 2.07537 11.4233 4.40669L11.9873 4.98349L12.5512 4.40669C14.8307 2.07538 18.5818 2.07537 20.8613 4.40669Z" fill="#1D1D1D"/>
</svg>

After

Width:  |  Height:  |  Size: 902 B

View File

@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M20.87 12.5366C23.0775 10.279 23.0775 6.67156 20.87 4.41392C18.5913 2.08338 14.8415 2.08338 12.5627 4.41392L11.9992 4.99029L11.4356 4.41392C9.15684 2.08338 5.40701 2.08338 3.12826 4.41392C0.920789 6.67156 0.920788 10.279 3.12826 12.5366L10.7393 20.3206C11.4304 21.0275 12.5679 21.0275 13.2591 20.3206L20.87 12.5366Z" fill="#E23108"/>
</svg>

After

Width:  |  Height:  |  Size: 486 B

View File

@ -15,11 +15,11 @@ export const GenerateCard:React.FC = (props) =>{
<Block className='generatecard-block'>
<div className="generateCardDescr">
<div className="generateCardTitle">
<div className="generateTitleText">Сгенерируй свой фантастический Тур!</div>
<div className="generateTitleText">Выбери свой фантастический Тур!</div>
</div>
</div>
<img src='generateTour.png'></img>
<Button className='generate-y'>Cгенерирвоать тур <img className="wand" src='magicWand.svg'></img></Button>
<Button className='generate-y'>Выбрать <img className="wand" src='magicWand.svg'></img></Button>
</Block>
);

View File

@ -6,17 +6,17 @@ export const RusPassHeader:React.FC = () =>{
<div className="padding">
<div className="headerWrapper">
<div className="iconWrapper">
<img className="headerIcon" src='logo.svg'></img>
<img className="headerIcon" src='menu.svg'></img>
<img className="headerIcon" src='bonus.svg'></img>
<img className="headerIcon" src='search.svg'></img>
<img className="headerIcon" src='/logo.svg'></img>
<img className="headerIcon" src='/menu.svg'></img>
<img className="headerIcon" src='/bonus.svg'></img>
<img className="headerIcon" src='/search.svg'></img>
</div>
<div className="iconWrapper">
<img className="headerIcon" src='language.svg'></img>
<img className="headerIcon" src='support.svg'></img>
<img className="headerIcon" src='favorites.svg'></img>
<img className="headerIcon" src='profile.svg'></img>
<img className="headerIcon" src='/language.svg'></img>
<img className="headerIcon" src='/support.svg'></img>
<img className="headerIcon" src='/favorites.svg'></img>
<img className="headerIcon" src='/profile.svg'></img>
</div>
</div>
</div>

View File

@ -0,0 +1,125 @@
import React, { useState } from "react";
import { Button } from '../../elements/Button'
import { Block } from '../../elements/Block'
import './style.css'
import { MyMap } from "../map";
import Sidebar from "react-sidebar";
import { PlaceCard } from "../TourCard";
import { Collapse, Tabs, TabsProps } from "antd";
export interface RouteCardIE{
options: {
date:string,
paths:({
type:string
point:{
lat:number,
lon:number,
title: string,
description:string,
oid:string
}
})[]
}[]
}
const { Panel } = Collapse;
export const RouteCard:React.FC<RouteCardIE> = (props) =>{
const [showMap, setShowMap] = useState(false)
const [selectedDay, setSelectedDay] = useState('0')
const [liked, setLiked] = useState(false)
let cntPlaces = 0
props.options.forEach((route)=>{
cntPlaces += route.paths.length
})
let points = props.options[Number(selectedDay)].paths.map((path)=>{
return [path.point.lon, path.point.lat]
})
const items: TabsProps['items'] = props.options.map((day, index)=>{
return {
key:index.toString(),
label: (index+1).toString() + 'день',
children: <div className="placesWrapper">
{day.paths.map((value) => <PlaceCard
title={value.point.title}
description={value.point.description}
icon='/icons/not_found.jpeg'
location={[value.point.lon, value.point.lat]}
></PlaceCard>)
}
</div>
}
})
const colapseItems: TabsProps['items'] = props.options.map((day, index)=>{
return {
key:index.toString(),
label: (index+1).toString() + 'день',
children: <Collapse
bordered={false}
>
{
day.paths.map((value, index2) =>
<Panel header={value.point.title} key={'collapse'+index.toString()+index2.toString()}>
<img style={{width:'200px'}} src='/icons/not_found.jpeg'></img>
<p>{value.point.description}</p>
</Panel>
)
}
</Collapse>
}
})
return(
<div>
<Sidebar
sidebar={
<div className='sidebarContent'>
<MyMap points={points}></MyMap>
<Tabs defaultActiveKey="0" items={colapseItems} onChange={(e:string)=>setSelectedDay(e)} />
<Button className='btn-y' onClick={()=>setShowMap(!showMap)}>Закрыть</Button>
</div>
}
open={showMap}
rootClassName='mainCardContent'
contentClassName="mainCardContent"
sidebarClassName="tourCardSidebar"
styles={{ sidebar: { background: "white"}}}
>
<Block className='tourcard-block'>
<div className="cardDescr">
<div className="cardTitle">
<div className="titleText">ИМЯ ТУРА</div>
<div className="cardInfo">
<div>{props.options.length} дней,</div>
<div>{cntPlaces} мест</div>
</div>
</div>
<img className="cardAvatar" src='/icons/not_found.jpeg'></img>
</div>
<Tabs defaultActiveKey="1" items={items} onChange={(e:string)=>setSelectedDay(e)} />
<div className="btnWrapper">
<div className="yOpenBtn" onClick={()=>setShowMap(!showMap)}>
<div className="yOpenBtnTitle">От 5000 рублей</div>
<div className="yOpenBtnDescr">Просмотреть план тура</div>
</div>
<div className="likeBtn" onClick={()=>setLiked(!liked)}>
<img src={liked? '/icons/likedHeart.svg':'/icons/heart.svg'}></img>
</div>
</div>
</Block>
</Sidebar>
</div>
);
}

View File

@ -0,0 +1,160 @@
.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;
}
.sidebarContent{
display: flex;
flex-direction: column;
gap:50px;
align-items: center;
justify-content: space-between;
}
.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;
}

View File

@ -4,6 +4,7 @@ import './index.css';
import App from './App';
import {router} from './router';
import {RouterProvider} from 'react-router-dom'
import {ConfigProvider } from 'antd';
const root = ReactDOM.createRoot(
@ -11,6 +12,15 @@ const root = ReactDOM.createRoot(
);
root.render(
<React.StrictMode>
<ConfigProvider
theme={{
token: {
colorPrimary: '#FFCF08',
},
}}
>
<RouterProvider router={router} />
</ConfigProvider>
</React.StrictMode>
);

View File

@ -1,5 +1,6 @@
import { AutoComplete, DatePicker, Input, Checkbox, Select } from 'antd';
import react, { useEffect, useState } from 'react'
import { useNavigate } from 'react-router-dom';
import { backend } from '../../consts';
import { Button } from '../../elements/Button';
import { FavoriteCard, FavoriteCardIE } from '../../elements/FavoriteCard';
@ -7,11 +8,14 @@ import { GenerateCard } from '../../elements/GenerateCard';
import { RusPassHeader } from '../../elements/Header';
import { TourCard, TourCardIE } from '../../elements/TourCard';
import './style.css'
import dayjs from 'dayjs';
import type { RangePickerProps } from 'antd/es/date-picker';
export const Main: react.FC = () => {
const { RangePicker } = DatePicker;
const [cities, setCities] = useState([])
useEffect(()=>{
if (cities.length == 0){
backend.get('/data/cities').then((response)=>setCities(response.data))
@ -54,26 +58,27 @@ export const Main: react.FC = () => {
location:'Казань'
} as FavoriteCardIE
const [dates, setDates] = useState()
const options = [
{
label: 'Подсказка 1',
options: 'Подсказка 1',
},
{
label: 'Подсказка 2',
options: 'Подсказка 2',
},
{
label: 'Подсказка 3',
options: 'Подсказка 3',
},
];
const [toolsOpened, setToolsOpened] = useState(false)
const [city, setCity] = useState('')
const [dates, setDates] = useState([])
let searchParams = {}
if (dates.length == 2){
searchParams = {
date_from: new Date((dates as any)[0]).toISOString().split('T')[0],
date_to: new Date((dates as any)[1]).toISOString().split('T')[0],
city: city
}
}
const disabledDate: RangePickerProps['disabledDate'] = (current:any) => {
// Can not select days before today and today
return current && current < dayjs().endOf('day');
};
let navigate = useNavigate()
return (
<div className='mainWrapper'>
<RusPassHeader></RusPassHeader>
@ -91,8 +96,7 @@ export const Main: react.FC = () => {
showSearch
placeholder="Выберите направление"
optionFilterProp="children"
// onChange={onChange}
// onSearch={onSearch}
onChange={(e)=>setCity(e)}
filterOption={(input, option) =>
(option?.label ?? '').toLowerCase().includes(input.toLowerCase())
}
@ -107,10 +111,11 @@ export const Main: react.FC = () => {
<img src='react.svg'></img>
<RangePicker
disabledDate={disabledDate}
onChange={(e)=>setDates(e as any)}
></RangePicker>
<img src='react.svg'></img>
<Button className='btn-y'>Сгенерировать</Button>
<Button className='btn-y' onClick={()=>navigate('search/' + JSON.stringify(searchParams))}>Сгенерировать</Button>
</div>
{
toolsOpened? <div className='searchOpened'>
@ -208,7 +213,7 @@ export const Main: react.FC = () => {
</div>
</div>
<div className='mainCard'>
<h2>Добавьте в избранное</h2>
<h2>Избранное</h2>
<div className='fav-wrapper'>
<FavoriteCard {...favoriteCardProps}></FavoriteCard>
<FavoriteCard {...favoriteCardProps}></FavoriteCard>

View File

@ -117,6 +117,7 @@
}
.ant-select-selector, .ant-picker{
border: 0px !important;
}

View File

@ -0,0 +1,206 @@
import React, { useEffect, useState } from "react";
import { useNavigate, useParams } from "react-router-dom";
import { backend } from "../../consts";
import data from './struct.json';
import { RouteCard } from "../../elements/RouteCard";
import { RusPassHeader } from "../../elements/Header";
import { AutoComplete, DatePicker, Input, Checkbox, Select } from 'antd';
import { RangePickerProps } from "antd/es/date-picker";
import dayjs from 'dayjs';
import { Button } from "../../elements/Button";
import './style.css'
const { RangePicker } = DatePicker;
export const SearchPage:React.FC = () =>{
let { prefs } = useParams();
const [cities, setCities] = useState([])
let props = data.map((day)=>{
let paths = day.paths
for (let i=0; i<paths.length; i++){
if (paths[i].type != 'point'){
paths.splice(i,1)
i--
}
}
return {
date:day.date,
paths: paths
}
})
useEffect(()=>{
if (cities.length == 0){
backend.get('/data/cities').then((response)=>setCities(response.data))
}
// backend.post('/route/build', props).then((response)=>console.log(response.data))
})
const [city, setCity] = useState('')
const [dates, setDates] = useState([])
let searchParams = {}
if (dates.length == 2){
searchParams = {
date_from: new Date((dates as any)[0]).toISOString().split('T')[0],
date_to: new Date((dates as any)[1]).toISOString().split('T')[0],
city: city
}
}
const disabledDate: RangePickerProps['disabledDate'] = (current:any) => {
// Can not select days before today and today
return current && current < dayjs().endOf('day');
};
let navigate = useNavigate()
const [toolsOpened, setToolsOpened] = useState(false)
return(
<div className="mainWrapper">
<RusPassHeader></RusPassHeader>
<h1>Посмотрите, что мы нашли по вашему запросу</h1>
<div>
<div style={{borderRadius: toolsOpened? '20px 20px 0px 0px':'20px'}} className='toolsMainWrapper'>
<div className='rowWrapper' onClick={()=>setToolsOpened(!toolsOpened)}>
<img src='/filter.svg'></img>
<div>Фильтры</div>
</div>
<img src='/react.svg'></img>
<Select
className='antdBorder'
showSearch
placeholder="Выберите направление"
optionFilterProp="children"
onChange={(e)=>setCity(e)}
filterOption={(input, option) =>
(option?.label ?? '').toLowerCase().includes(input.toLowerCase())
}
options={cities.map((city:any)=>{
return {
value:city.oid,
label: city.title
}
}
)}
/>
<img src='/react.svg'></img>
<RangePicker
disabledDate={disabledDate}
onChange={(e)=>setDates(e as any)}
></RangePicker>
<img src='/react.svg'></img>
<Button className='btn-y' onClick={()=>navigate('search/' + JSON.stringify(searchParams))}>Сгенерировать</Button>
</div>
{
toolsOpened? <div className='searchOpened'>
<div className='questionWrapper'>
<h2>Как добраться</h2>
<div className='checkboxWrapper'>
<Checkbox>Самолет</Checkbox>
<Checkbox>ЖД</Checkbox>
<Checkbox>Автобус</Checkbox>
<Checkbox>Смешанный</Checkbox>
</div>
</div>
<div className='questionWrapper'>
<h2>Где остановимся</h2>
<div className='checkboxWrapper'>
<Checkbox>Отель</Checkbox>
<Checkbox>Хостел</Checkbox>
<Checkbox>Апартаменты</Checkbox>
</div>
</div>
<div className='questionWrapper'>
<h2>Как перемещаться на месте</h2>
<div className='checkboxWrapper'>
<Checkbox>Машина</Checkbox>
<Checkbox>Общественный транспорт</Checkbox>
<Checkbox>Пешком</Checkbox>
</div>
</div>
<div className='questionWrapper'>
<h2>Что посмотреть</h2>
<div className='checkboxWrapper'>
<Checkbox>Музеи и выставки</Checkbox>
<Checkbox>Мероприятия и места</Checkbox>
<Checkbox>Обзорные экскурсии</Checkbox>
<Checkbox>Культурное наследие</Checkbox>
<Checkbox>Парки и прогулки</Checkbox>
</div>
</div>
<div className='questionWrapper'>
<h2>Где питаться</h2>
<div className='checkboxWrapper'>
<Checkbox>Рестораны</Checkbox>
<Checkbox>Кафе</Checkbox>
<Checkbox>Бары</Checkbox>
</div>
</div>
<div className='questionWrapper'>
<h2>Дополнительно</h2>
<div className='checkboxWrapper'>
<Checkbox>С детьми</Checkbox>
<Checkbox>С животными</Checkbox>
</div>
</div>
<div className='questionWrapper'>
<h2>Рейтинг</h2>
<div className='checkboxWrapper'>
<Checkbox>5*</Checkbox>
<Checkbox>4*</Checkbox>
<Checkbox>3*</Checkbox>
<Checkbox>2*</Checkbox>
<Checkbox>1*</Checkbox>
</div>
</div>
<div className='questionWrapper'>
<h2>Рейтинг</h2>
<div className='checkboxWrapper'>
<Checkbox>5*</Checkbox>
<Checkbox>4*</Checkbox>
<Checkbox>3*</Checkbox>
<Checkbox>2*</Checkbox>
<Checkbox>1*</Checkbox>
</div>
</div>
</div>:null
}
</div>
<div className='mainCard'>
<div className='cardWrapper'>
<RouteCard options={props as any}></RouteCard>
<RouteCard options={props as any}></RouteCard>
<RouteCard options={props as any}></RouteCard>
<RouteCard options={props as any}></RouteCard>
<RouteCard options={props as any}></RouteCard>
<RouteCard options={props as any}></RouteCard>
<RouteCard options={props as any}></RouteCard>
</div>
</div>
<a href='/'>Документация</a>
<div className='mainIconWrapper'>
<img className='mainIcon' src='/icons/yt.svg'></img>
<img className='mainIcon' src='/icons/vk.svg'></img>
<img className='mainIcon' src='/icons/dz.svg'></img>
<img className='mainIcon' src='/icons/tg.svg'></img>
<img className='mainIcon' src='/icons/ok.svg'></img>
</div>
<div className='grey'>© 2023 A project of the Government of Moscow</div>
</div>
);
}

View File

@ -0,0 +1,365 @@
[
{
"date": "2023-05-25T00:00:00",
"paths": [
{
"type": "point",
"point": {
"lat": 59.930238,
"lon": 30.365905,
"title": "Отель «Невский Берег 93»",
"description": "",
"oid": "6315c8cea46e26e568f592eb"
},
"point_type": "hotel"
},
{
"type": "transition",
"distance": 1.782898459212654,
"time": 2139
},
{
"type": "point",
"point": {
"lat": 59.9275966,
"lon": 30.3344591,
"title": "Department 57",
"description": "",
"oid": "5d3248e12a670c0017f16bdb"
},
"point_type": "restaurant",
"time": 5400
},
{
"type": "transition",
"distance": 1.5728674597934658,
"time": 1887
},
{
"type": "point",
"point": {
"lat": 59.92956160000001,
"lon": 30.3623123,
"title": "Московский вокзал",
"description": "Станция, с которой началось железнодорожное движение между Санкт-Петербургом и Москвой. В 1851 году на царском поезде Николай I с семьей совершил путешествие в Белокаменную. До нее состав добирался 19 часов. А через несколько месяцев отправиться в поездку смогли и все желающие. Здание вокзала построили по проекту Константина Тона, автора храма Христа Спасителя. С 1930-х между двумя столицами курсирует «Красная стрела», а любители быстрых путешествий прибывают сюда на «Ласточках» и «Сапсанах». \t ",
"oid": "60e3e9d447a72f00189ec01c"
},
"point_type": "point",
"time": 5400
},
{
"type": "transition",
"distance": 0.06652633017394935,
"time": 79
},
{
"type": "point",
"point": {
"lat": 59.930146,
"lon": 30.362068,
"title": "Большая обзорная экскурсия с посещением крейсера «Аврора»",
"description": "Автобусная обзорная экскурсия по городу познакомит вас с богатой историей Санкт-Петербурга, его уникальными памятниками, а также с современным обликом Северной столицы. Небольшое путешествие в комфортабельном автобусе — удобный и доступный способ увидеть все главные достопримечательности города, не завися от погодных условий.\n\nОдним из символов революционных перемен стал крейсер «Аврора».\n\nВ ходе экскурсии вы увидите Невский проспект, Стрелку Васильевского острова, Спас-на-Крови, Кунсткамеру, Адмиралтейство, Марсово поле, домик Петра I, Петропавловскую крепость, крейсер «Аврора».\n\nВ стоимость включено обслуживание лицензированного гида на русском языке и автобус туристического класса. При посадке в автобус осуществляется свободная рассадка.\n\n* Право на льготные билеты имеют студенты и пенсионеры РФ и республики Беларусь (при наличии соответствующих документов. Не паспорта).\n\n** Право на школьные билеты имеют школьники РФ и республики Беларусь (при наличии соответствующих документов. Не паспорта).\n\n*** Право на иностранный льготный билет имеют школьники и студенты, не являющиеся гражданами РФ и республики Беларусь (при наличии международного удостоверения студента или паспорта (для школьников).\n\nОтправление и окончание: Московский вокзал, Невский просп., 85\nСбор группы: рядом с офисом, который находится прямо в здании Московского вокзала (Центральный вход в вокзал со стороны пл. Восстания, первая стеклянная дверь направо, вывеска «Экскурсии Visit SPb») за 15 минут.\nПродолжительность: 3 часа.",
"oid": "64312e653145a2c4ce7ecaa8"
},
"point_type": "point",
"time": 10200
},
{
"type": "transition",
"distance": 0.0,
"time": 0
},
{
"type": "point",
"point": {
"lat": 59.930146,
"lon": 30.362068,
"title": "Большая обзорная экскурсия с посещением крейсера «Аврора»",
"description": "Автобусная обзорная экскурсия по городу познакомит вас с богатой историей Санкт-Петербурга, его уникальными памятниками, а также с современным обликом Северной столицы. Небольшое путешествие в комфортабельном автобусе — удобный и доступный способ увидеть все главные достопримечательности города, не завися от погодных условий.\n\nОдним из символов революционных перемен стал крейсер «Аврора».\n\nВ ходе экскурсии вы увидите Невский проспект, Стрелку Васильевского острова, Спас-на-Крови, Кунсткамеру, Адмиралтейство, Марсово поле, домик Петра I, Петропавловскую крепость, крейсер «Аврора».\n\nВ стоимость включено обслуживание лицензированного гида на русском языке и автобус туристического класса. При посадке в автобус осуществляется свободная рассадка.\n\n* Право на льготные билеты имеют студенты и пенсионеры РФ и республики Беларусь (при наличии соответствующих документов. Не паспорта).\n\n** Право на школьные билеты имеют школьники РФ и республики Беларусь (при наличии соответствующих документов. Не паспорта).\n\n*** Право на иностранный льготный билет имеют школьники и студенты, не являющиеся гражданами РФ и республики Беларусь (при наличии международного удостоверения студента или паспорта (для школьников).\n\nОтправление и окончание: Московский вокзал, Невский просп., 85\nСбор группы: рядом с офисом, который находится прямо в здании Московского вокзала (Центральный вход в вокзал со стороны пл. Восстания, первая стеклянная дверь направо, вывеска «Экскурсии Visit SPb») за 15 минут.\nПродолжительность: 3 часа.",
"oid": "64312e653145a2c4ce7ecaa8"
},
"point_type": "point",
"time": 7200
},
{
"type": "point",
"point": {
"lat": 59.94384,
"lon": 30.353379,
"title": "Ресторан Schengen ",
"description": "Небольшой городской ресторан европейской кухни со стильным интерьером. Пространство состоит из двух залов. Первый — светлый и просторный, с панорамными окнами на Кирочную улицу. Здесь много стекла, огромное зеркало во всю стену, круглый стол на шесть человек и детская комната. Второй зал — с барной стойкой, он идеально подходит для вечернего времяпрепровождения и душевных бесед в компании друзей.\n",
"oid": "5e7c2f929134ed0019dde670"
},
"point_type": "restaurant",
"time": 10200
},
{
"type": "transition",
"distance": 0.29901207167741317,
"time": 358
},
{
"type": "point",
"point": {
"lat": 59.943629,
"lon": 30.348046,
"title": "StandUp Asia",
"description": "Самое колоритное стендап-шоу Петербурга! Настоящая изюминка Comedy Place!\n\nАзия — это не только мопеды, панды, сашими и кунг-фу.\n\nАзия — это ещё и особый юмор, способный рассмешить человека любой национальности, профессии, вкусов и предпочтений.\n\nСпециально для любимых зрителей организаторы Comedy Place нашли самых смешных азиатов Петербурга и пригласили их продемонстрировать свои таланты под одной крышей.\n\nВозможно, вы давно хотели побывать в Корее или посетить концерт Babymetal в Японии? Но коронавирус и прочие неприятные ограничения всё время разрушают ваши мечты?\n\nТогда StandUp Asia — это то, что вам нужно! Это шоу собрано по национальному признаку, оно живое, аутентичное, незабываемое, но совсем не ограничивается шутками про азиатские стереотипы.\n\nБудет весело и по-азиатски остро!\n\nСбор гостей за 30 минут до начала мероприятия.",
"oid": "64287c1a58b0515ee3990a74"
},
"point_type": "point",
"time": 8400
}
]
},
{
"date": "2023-05-26T00:00:00",
"paths": [
{
"type": "point",
"point": {
"lat": 59.930238,
"lon": 30.365905,
"title": "Отель «Невский Берег 93»",
"description": "",
"oid": "6315c8cea46e26e568f592eb"
},
"point_type": "hotel"
},
{
"type": "transition",
"distance": 1.8090974456320528,
"time": 2170
},
{
"type": "point",
"point": {
"lat": 59.9406377,
"lon": 30.3410541,
"title": "Tawny",
"description": "",
"oid": "5d362ccf2a670c0017f17082"
},
"point_type": "restaurant",
"time": 5400
},
{
"type": "transition",
"distance": 1.5891503046746898,
"time": 1906
},
{
"type": "point",
"point": {
"lat": 59.9309247,
"lon": 30.36187,
"title": "Обелиск «Городу-герою Ленинграду»",
"description": "На пересечении Невского и Лиговского проспектов, рядом с Московским вокзалом, возвышается обелиск, посвященный героическому подвигу города в годы войны. На его вершине золотая звезда: городом-героем Петербург стали называть еще в 1945 году. А внизу скульптурные композиции, которые рассказывают о его обороне. Отсюда начинаются шествия «Бессмертного полка».",
"oid": "60f7b60747a72f00189f7a27"
},
"point_type": "point",
"time": 7800
},
{
"type": "transition",
"distance": 0.0874594365753838,
"time": 104
},
{
"type": "point",
"point": {
"lat": 59.930146,
"lon": 30.362068,
"title": "Большая обзорная экскурсия с посещением крейсера «Аврора»",
"description": "Автобусная обзорная экскурсия по городу познакомит вас с богатой историей Санкт-Петербурга, его уникальными памятниками, а также с современным обликом Северной столицы. Небольшое путешествие в комфортабельном автобусе — удобный и доступный способ увидеть все главные достопримечательности города, не завися от погодных условий.\n\nОдним из символов революционных перемен стал крейсер «Аврора».\n\nВ ходе экскурсии вы увидите Невский проспект, Стрелку Васильевского острова, Спас-на-Крови, Кунсткамеру, Адмиралтейство, Марсово поле, домик Петра I, Петропавловскую крепость, крейсер «Аврора».\n\nВ стоимость включено обслуживание лицензированного гида на русском языке и автобус туристического класса. При посадке в автобус осуществляется свободная рассадка.\n\n* Право на льготные билеты имеют студенты и пенсионеры РФ и республики Беларусь (при наличии соответствующих документов. Не паспорта).\n\n** Право на школьные билеты имеют школьники РФ и республики Беларусь (при наличии соответствующих документов. Не паспорта).\n\n*** Право на иностранный льготный билет имеют школьники и студенты, не являющиеся гражданами РФ и республики Беларусь (при наличии международного удостоверения студента или паспорта (для школьников).\n\nОтправление и окончание: Московский вокзал, Невский просп., 85\nСбор группы: рядом с офисом, который находится прямо в здании Московского вокзала (Центральный вход в вокзал со стороны пл. Восстания, первая стеклянная дверь направо, вывеска «Экскурсии Visit SPb») за 15 минут.\nПродолжительность: 3 часа.",
"oid": "64312e653145a2c4ce7ecaa8"
},
"point_type": "point",
"time": 7200
},
{
"type": "transition",
"distance": 0.0,
"time": 0
},
{
"type": "point",
"point": {
"lat": 59.930146,
"lon": 30.362068,
"title": "Большая обзорная экскурсия с посещением крейсера «Аврора»",
"description": "Автобусная обзорная экскурсия по городу познакомит вас с богатой историей Санкт-Петербурга, его уникальными памятниками, а также с современным обликом Северной столицы. Небольшое путешествие в комфортабельном автобусе — удобный и доступный способ увидеть все главные достопримечательности города, не завися от погодных условий.\n\nОдним из символов революционных перемен стал крейсер «Аврора».\n\nВ ходе экскурсии вы увидите Невский проспект, Стрелку Васильевского острова, Спас-на-Крови, Кунсткамеру, Адмиралтейство, Марсово поле, домик Петра I, Петропавловскую крепость, крейсер «Аврора».\n\nВ стоимость включено обслуживание лицензированного гида на русском языке и автобус туристического класса. При посадке в автобус осуществляется свободная рассадка.\n\n* Право на льготные билеты имеют студенты и пенсионеры РФ и республики Беларусь (при наличии соответствующих документов. Не паспорта).\n\n** Право на школьные билеты имеют школьники РФ и республики Беларусь (при наличии соответствующих документов. Не паспорта).\n\n*** Право на иностранный льготный билет имеют школьники и студенты, не являющиеся гражданами РФ и республики Беларусь (при наличии международного удостоверения студента или паспорта (для школьников).\n\nОтправление и окончание: Московский вокзал, Невский просп., 85\nСбор группы: рядом с офисом, который находится прямо в здании Московского вокзала (Центральный вход в вокзал со стороны пл. Восстания, первая стеклянная дверь направо, вывеска «Экскурсии Visit SPb») за 15 минут.\nПродолжительность: 3 часа.",
"oid": "64312e653145a2c4ce7ecaa8"
},
"point_type": "point",
"time": 8400
},
{
"type": "point",
"point": {
"lat": 59.943365,
"lon": 30.350657,
"title": "Ресторан Mr. Bo",
"description": "Ресторан паназиатской кухни у Спасо-Преображенского собора, авторский проект двух шеф-поваров ― Дмитрия Богачева и Эльдара Мурадова. Они решили отойти от канонических традиционных рецептов, поэтому каждое блюдо в Mr. Bo ― результат поиска нового, экстраординарного, неожиданного. Устрицы со страчателлой или маракуйей, пельмени с креветкой и свининой, лист бегонии с мороженым из яблока и икрой алоэ ― меню ресторана читается как захватывающий кулинарный роман. А яркость, огромная палитра сильных и насыщенных вкусов, которыми можно бесконечно жонглировать, открывая новые оттенки, ― это лишь некоторые из его сюжетных линий.\n",
"oid": "5e7ca3aa3a44190019893b6a"
},
"point_type": "restaurant",
"time": 7800
},
{
"type": "transition",
"distance": 0.14887651851478786,
"time": 178
},
{
"type": "point",
"point": {
"lat": 59.943629,
"lon": 30.348046,
"title": "StandUp Asia",
"description": "Самое колоритное стендап-шоу Петербурга! Настоящая изюминка Comedy Place!\n\nАзия — это не только мопеды, панды, сашими и кунг-фу.\n\nАзия — это ещё и особый юмор, способный рассмешить человека любой национальности, профессии, вкусов и предпочтений.\n\nСпециально для любимых зрителей организаторы Comedy Place нашли самых смешных азиатов Петербурга и пригласили их продемонстрировать свои таланты под одной крышей.\n\nВозможно, вы давно хотели побывать в Корее или посетить концерт Babymetal в Японии? Но коронавирус и прочие неприятные ограничения всё время разрушают ваши мечты?\n\nТогда StandUp Asia — это то, что вам нужно! Это шоу собрано по национальному признаку, оно живое, аутентичное, незабываемое, но совсем не ограничивается шутками про азиатские стереотипы.\n\nБудет весело и по-азиатски остро!\n\nСбор гостей за 30 минут до начала мероприятия.",
"oid": "64287c1a58b0515ee3990a74"
},
"point_type": "point",
"time": 9000
},
{
"type": "point",
"point": {
"lat": 59.933773,
"lon": 30.3225289,
"title": "Ресторан «Рибай»",
"description": "В ресторане царит культ всего натурального и настоящего: от честных порций стейков всех видов и степеней прожарки до добротного интерьера заведения, в котором сочетаются уютные кожаные диваны и футуристичные бюсты быков. Изюминка ресторана ― ежедневное шоу: официанты поют популярные песни, танцуют и даже показывают фокусы.",
"oid": "5e7c315d9134ed0019dde886"
},
"point_type": "restaurant",
"time": 5400
}
]
},
{
"date": "2023-05-27T00:00:00",
"paths": [
{
"type": "point",
"point": {
"lat": 59.930238,
"lon": 30.365905,
"title": "Отель «Невский Берег 93»",
"description": "",
"oid": "6315c8cea46e26e568f592eb"
},
"point_type": "hotel"
},
{
"type": "transition",
"distance": 1.078849384303934,
"time": 1294
},
{
"type": "point",
"point": {
"lat": 59.9325189,
"lon": 30.3471536,
"title": "Chateau Vintage",
"description": "",
"oid": "5d438518ddae360019a1bf04"
},
"point_type": "restaurant",
"time": 6600
},
{
"type": "transition",
"distance": 0.7711890730184835,
"time": 925
},
{
"type": "point",
"point": {
"lat": 59.93,
"lon": 30.36,
"title": "Музей-квартира актеров Самойловых",
"description": "Мемориальный музей-квартира Самойловых был открыт в Петербурге 28 января 1994 года. Этот музей посвящен собирательному образу артиста-профессионала, для которого жизнь частная неразрывна с жизнью сценической. В течение 18 лет (1869-1887) во втором этаже дома № 8 на Стремянной улице проживал знаменитый актер императорского Александринского театра Василий Васильевич Самойлов (1813-1887) - талантливейший представитель актерской династии Самойловых. Ко времени создания музея бывшая квартира Самойловых, ставшая старой коммунальной квартирой, оказалась входящей в состав пятизвездочного отеля \"Невский Палас\". В результате кропотливых реставрационных и строительных работ, тщательной научной работы по созданию экспозиции, возник музей с неповторимым изысканным обликом и интереснейшей экспозицией. Два зала полностью посвящены истории актерской семьи Самойловых. Здесь собраны портреты представителей трех поколений династии, личные вещи, предметы обстановки, живописные полотна, мастерски выполненные В.В. Самойловым. Большой портретный зал рассказывает об артистическом окружении Самойловых, истории императорских театров Санкт-Петербурга XIX - начала XX столетий. Кроме портретов, здесь представлены разнообразные предметы театрального быта прошлого века, личные вещи блистательных актеров Александринки. Небольшой концертный зал возрождает музыкальные традиции дома Самойловых, где постоянно устраивались музыкальные вечера. Здесь бывали А. Даргомыжский, А. Рубинштейн, Л. Ауэр. В зале проводятся концерты камерной классической музыки, театральные вечера. В 2001 г. в стенах музея также разместилась экспозиция, посвященная людям и событиям русского балетного театра от истоков до наших дней. Одно из множества звучных имен, которым наградила Петербург история, - \"столица русского балета\". Именно наш город подарил миру величайших танцовщиков ХХ века - А. Павлову, В. Нижинского, Г. Уланову, М. Барышникова, Р. Нуреева. Экспозиция дает уникальную возможность поближе познакомиться с этими выдающимися мастерами. Здесь можно увидеть подлинные эскизы Льва Бакста и Александра Бенуа, редчайшие фотографии и афиши, хранящие память о легендарных спектаклях Мариуса Петипа, о жемчужинах Дягилевских сезонов и знаменитых премьерах советского периода",
"oid": "kQTUniJawCTMBhQSuxvPxVnW"
},
"point_type": "point",
"time": 9600
},
{
"type": "transition",
"distance": 0.11677625100231924,
"time": 140
},
{
"type": "point",
"point": {
"lat": 59.930146,
"lon": 30.362068,
"title": "Большая обзорная экскурсия с посещением крейсера «Аврора»",
"description": "Автобусная обзорная экскурсия по городу познакомит вас с богатой историей Санкт-Петербурга, его уникальными памятниками, а также с современным обликом Северной столицы. Небольшое путешествие в комфортабельном автобусе — удобный и доступный способ увидеть все главные достопримечательности города, не завися от погодных условий.\n\nОдним из символов революционных перемен стал крейсер «Аврора».\n\nВ ходе экскурсии вы увидите Невский проспект, Стрелку Васильевского острова, Спас-на-Крови, Кунсткамеру, Адмиралтейство, Марсово поле, домик Петра I, Петропавловскую крепость, крейсер «Аврора».\n\nВ стоимость включено обслуживание лицензированного гида на русском языке и автобус туристического класса. При посадке в автобус осуществляется свободная рассадка.\n\n* Право на льготные билеты имеют студенты и пенсионеры РФ и республики Беларусь (при наличии соответствующих документов. Не паспорта).\n\n** Право на школьные билеты имеют школьники РФ и республики Беларусь (при наличии соответствующих документов. Не паспорта).\n\n*** Право на иностранный льготный билет имеют школьники и студенты, не являющиеся гражданами РФ и республики Беларусь (при наличии международного удостоверения студента или паспорта (для школьников).\n\nОтправление и окончание: Московский вокзал, Невский просп., 85\nСбор группы: рядом с офисом, который находится прямо в здании Московского вокзала (Центральный вход в вокзал со стороны пл. Восстания, первая стеклянная дверь направо, вывеска «Экскурсии Visit SPb») за 15 минут.\nПродолжительность: 3 часа.",
"oid": "64312e653145a2c4ce7ecaa8"
},
"point_type": "point",
"time": 7200
},
{
"type": "transition",
"distance": 0.0,
"time": 0
},
{
"type": "point",
"point": {
"lat": 59.930146,
"lon": 30.362068,
"title": "Большая обзорная экскурсия с посещением крейсера «Аврора»",
"description": "Автобусная обзорная экскурсия по городу познакомит вас с богатой историей Санкт-Петербурга, его уникальными памятниками, а также с современным обликом Северной столицы. Небольшое путешествие в комфортабельном автобусе — удобный и доступный способ увидеть все главные достопримечательности города, не завися от погодных условий.\n\nОдним из символов революционных перемен стал крейсер «Аврора».\n\nВ ходе экскурсии вы увидите Невский проспект, Стрелку Васильевского острова, Спас-на-Крови, Кунсткамеру, Адмиралтейство, Марсово поле, домик Петра I, Петропавловскую крепость, крейсер «Аврора».\n\nВ стоимость включено обслуживание лицензированного гида на русском языке и автобус туристического класса. При посадке в автобус осуществляется свободная рассадка.\n\n* Право на льготные билеты имеют студенты и пенсионеры РФ и республики Беларусь (при наличии соответствующих документов. Не паспорта).\n\n** Право на школьные билеты имеют школьники РФ и республики Беларусь (при наличии соответствующих документов. Не паспорта).\n\n*** Право на иностранный льготный билет имеют школьники и студенты, не являющиеся гражданами РФ и республики Беларусь (при наличии международного удостоверения студента или паспорта (для школьников).\n\nОтправление и окончание: Московский вокзал, Невский просп., 85\nСбор группы: рядом с офисом, который находится прямо в здании Московского вокзала (Центральный вход в вокзал со стороны пл. Восстания, первая стеклянная дверь направо, вывеска «Экскурсии Visit SPb») за 15 минут.\nПродолжительность: 3 часа.",
"oid": "64312e653145a2c4ce7ecaa8"
},
"point_type": "point",
"time": 8400
},
{
"type": "point",
"point": {
"lat": 59.94050576,
"lon": 30.3781665,
"title": "Ресторан La Marée ",
"description": "Гастрономический ресторан рядом с Таврическим дворцом, в котором подаются блюда из свежайшей рыбы и морепродуктов. Деликатесы в La Marée доставляют из разных уголков планеты. Ассортимент удивит даже самых искушенных гурманов — в аквариумах ресторана живут камчатские и колючие крабы, королевские лангусты и лангустины, морские ежи и сверчки, разнообразные моллюски и улитки, устрицы, сахалинские гребешки, тюрбо. На ледяных прилавках можно увидеть редчайшего морского ерша, лакедру и ламбуку. Обширная карта вин дает возможность подобрать достойную пару к любому блюду.\n",
"oid": "5e7c32439134ed0019dde99e"
},
"point_type": "restaurant",
"time": 7800
},
{
"type": "transition",
"distance": 1.3463603731003255,
"time": 1615
},
{
"type": "point",
"point": {
"lat": 59.9489622,
"lon": 30.3953743,
"title": "Смольный собор",
"description": "Действующий православный храм и выдающийся архитектурный памятник XVIII века. Был заложен в 1748 году по указу императрицы Елизаветы Петровны, а освящен лишь спустя 87 лет. Проект собора выполнил зодчий Бартоломео Франческо Растрелли, интерьер храма в начале ХIХ века создал архитектор Василий Стасов. Смотровая площадка Смольного — одна из самых высоких в Петербурге. Расположена на звоннице собора на высоте 50-ти метров, к ней ведут 278 ступеней. С помощью обзорной аудиоэкскурсии и бинокля можно самостоятельно изучить панораму исторического центра города. Богослужения в храме совершаются ежедневно.",
"oid": "60a4d5046e219d0018fe9151"
},
"point_type": "point",
"time": 4800
},
{
"type": "point",
"point": {
"lat": 59.93986419999999,
"lon": 30.377725,
"title": "Ресторан Francesco",
"description": "Один из самых «итальянских» ресторанов Петербурга напоминает фамильный особняк с антикварной мебелью и духом прошлого в каждой мелочи. В меню Francesco блюда, приготовленные по оригинальным домашним рецептам. Здесь гости найдут широкий выбор пасты, блюда из свежайшей рыбы и морепродуктов, несколько сортов оригинальных сыров и блюда от шефа, которые можно попробовать только во Francesco.\n",
"oid": "5e7c31ee9134ed0019dde937"
},
"point_type": "restaurant",
"time": 9600
}
]
}
]

View File

@ -0,0 +1,120 @@
.mainCard{
background-color: #FFFBF3;
width: сalc(100%-100px);
margin: 0px 50px;
display: flex;
flex-direction: column;
gap:25px;
border-radius: 48px;
padding: 50px;
width: calc(100% - 200px);
}
.cardWrapper{
display: inline-flex;
flex-direction: row;
flex-wrap: wrap;
gap:25px;
justify-content: center;
}
.fav-wrapper{
display: flex;
justify-content: space-between;
gap: 25px;
flex-wrap: wrap;
}
.grey{
font-size: 12px;
color:#1D1D1D
}
.mainIcon{
cursor: pointer;
transition: 0.3s;
}
.mainIcon:hover{
transform: scale(1.1);
}
.mainIconWrapper{
display: flex;
flex-direction: row;
gap:25px
}
.mainWrapper{
display: flex;
flex-direction: column;
gap:50px;
justify-content: center;
align-items: center;
padding-bottom: 100px;
}
.toolsMainWrapper{
display: flex;
align-items: center;
justify-content: space-between;
gap:15px;
background-color: white;
border-radius: 20px;
padding: 10px 50px;
margin-top: -50px;
}
.headMainWrapper{
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
}
.backgroundIMG{
width: calc(100% - 100px);
}
.rowWrapper{
display: flex;
flex-direction: row;
gap:10px;
cursor: pointer;
align-items: center;
justify-content: center;
}
.searchOpened{
transition: 0.3s;
margin-top: 0px;
background-color: white;
position: relative;
border-radius: 0px 0px 20px 20px;
padding: 10px 50px;
gap:25px;
display: flex;
flex-direction: row;
flex-wrap: wrap;
gap:50px;
padding-bottom: 50px;
}
.checkboxWrapper{
display: flex;
flex-direction: column;
gap:10px
}
.ant-select-selector, .ant-picker{
border: 0px !important;
}

View File

@ -8,6 +8,7 @@ import { Main } from './pages/Main';
import { EventMatch } from './pages/EventMatch';
import { GenerateTour } from './pages/GenerateTour';
import { Prefernces } from './elements/Prefernces';
import { SearchPage } from './pages/SearchPage';
const routes = [
@ -27,6 +28,10 @@ const routes = [
path: '/',
element: <Main></Main>
},
{
path: '/search/:prefs',
element: <SearchPage></SearchPage>
},
{
path: '/event-match',
element: <EventMatch></EventMatch>