From 6df47ee610a6a74edaf900fa8f69407ac3b65090 Mon Sep 17 00:00:00 2001 From: = <=> Date: Sat, 27 May 2023 02:32:34 +0300 Subject: [PATCH] add search page --- public/icons/heart.svg | 3 + public/icons/likedHeart.svg | 3 + src/elements/GenerateCard/index.tsx | 4 +- src/elements/Header/index.tsx | 16 +- src/elements/RouteCard/index.tsx | 125 ++++++++++ src/elements/RouteCard/style.css | 160 ++++++++++++ src/index.tsx | 10 + src/pages/Main/index.tsx | 49 ++-- src/pages/Main/style.css | 1 + src/pages/SearchPage/index.tsx | 206 ++++++++++++++++ src/pages/SearchPage/struct.json | 365 ++++++++++++++++++++++++++++ src/pages/SearchPage/style.css | 120 +++++++++ src/router.tsx | 5 + 13 files changed, 1035 insertions(+), 32 deletions(-) create mode 100644 public/icons/heart.svg create mode 100644 public/icons/likedHeart.svg create mode 100644 src/elements/RouteCard/index.tsx create mode 100644 src/elements/RouteCard/style.css create mode 100644 src/pages/SearchPage/index.tsx create mode 100644 src/pages/SearchPage/struct.json create mode 100644 src/pages/SearchPage/style.css diff --git a/public/icons/heart.svg b/public/icons/heart.svg new file mode 100644 index 0000000..1567cfb --- /dev/null +++ b/public/icons/heart.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/likedHeart.svg b/public/icons/likedHeart.svg new file mode 100644 index 0000000..5cd8a6a --- /dev/null +++ b/public/icons/likedHeart.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/elements/GenerateCard/index.tsx b/src/elements/GenerateCard/index.tsx index 4350541..291fce7 100644 --- a/src/elements/GenerateCard/index.tsx +++ b/src/elements/GenerateCard/index.tsx @@ -15,11 +15,11 @@ export const GenerateCard:React.FC = (props) =>{
-
Сгенерируй свой фантастический Тур!
+
Выбери свой фантастический Тур!
- +
); diff --git a/src/elements/Header/index.tsx b/src/elements/Header/index.tsx index ffdec2e..074d325 100644 --- a/src/elements/Header/index.tsx +++ b/src/elements/Header/index.tsx @@ -6,17 +6,17 @@ export const RusPassHeader:React.FC = () =>{
- - - - + + + +
- - - - + + + +
diff --git a/src/elements/RouteCard/index.tsx b/src/elements/RouteCard/index.tsx new file mode 100644 index 0000000..4c61358 --- /dev/null +++ b/src/elements/RouteCard/index.tsx @@ -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 = (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:
+ {day.paths.map((value) => ) + } +
+ } + }) + + 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( +
+ + + setSelectedDay(e)} /> + +
+ } + open={showMap} + rootClassName='mainCardContent' + contentClassName="mainCardContent" + sidebarClassName="tourCardSidebar" + styles={{ sidebar: { background: "white"}}} + > + + +
+
+
ИМЯ ТУРА
+
+
{props.options.length} дней,
+
{cntPlaces} мест
+
+
+ +
+ setSelectedDay(e)} /> +
+
setShowMap(!showMap)}> +
От 5000 рублей
+
Просмотреть план тура
+
+
setLiked(!liked)}> + +
+
+
+ + + + ); +} \ No newline at end of file diff --git a/src/elements/RouteCard/style.css b/src/elements/RouteCard/style.css new file mode 100644 index 0000000..fd05a41 --- /dev/null +++ b/src/elements/RouteCard/style.css @@ -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; +} \ No newline at end of file diff --git a/src/index.tsx b/src/index.tsx index f933c1a..9a8eaf4 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -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( + + + ); diff --git a/src/pages/Main/index.tsx b/src/pages/Main/index.tsx index e1f7d95..2eb648e 100644 --- a/src/pages/Main/index.tsx +++ b/src/pages/Main/index.tsx @@ -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,10 +8,13 @@ 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){ @@ -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 (
@@ -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 = () => { setDates(e as any)} + disabledDate={disabledDate} + onChange={(e)=>setDates(e as any)} > - +
{ toolsOpened?
@@ -208,7 +213,7 @@ export const Main: react.FC = () => {
-

Добавьте в избранное

+

Избранное

diff --git a/src/pages/Main/style.css b/src/pages/Main/style.css index 35245d2..8b63555 100644 --- a/src/pages/Main/style.css +++ b/src/pages/Main/style.css @@ -117,6 +117,7 @@ } + .ant-select-selector, .ant-picker{ border: 0px !important; } diff --git a/src/pages/SearchPage/index.tsx b/src/pages/SearchPage/index.tsx new file mode 100644 index 0000000..bc13a45 --- /dev/null +++ b/src/pages/SearchPage/index.tsx @@ -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{ + 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( +
+ +

Посмотрите, что мы нашли по вашему запросу

+
+
+
setToolsOpened(!toolsOpened)}> + +
Фильтры
+
+ +