From f4aa746dc9350ef87cfee4269810ffa51df96743 Mon Sep 17 00:00:00 2001 From: = <=> Date: Mon, 29 May 2023 10:48:15 +0300 Subject: [PATCH 1/3] fich --- .vscode/settings.json | 3 +++ package.json | 16 ++++------------ src/client/config.ts | 2 +- src/consts.tsx | 13 +++++++++++-- src/pages/Login/index.tsx | 7 ++++--- src/pages/Login/style.css | 3 +-- src/pages/Main/index.tsx | 6 +++--- src/pages/Register/index.tsx | 5 ++--- src/pages/Register/style.css | 3 +-- src/pages/SearchPage/index.tsx | 26 +++++++++++++++++++------- src/router.tsx | 6 +++--- 11 files changed, 52 insertions(+), 38 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..6f3a291 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "liveServer.settings.port": 5501 +} \ No newline at end of file diff --git a/package.json b/package.json index 39bd0c7..16c67af 100644 --- a/package.json +++ b/package.json @@ -48,16 +48,8 @@ "react-app/jest" ] }, - "browserslist": { - "production": [ - ">0.2%", - "not dead", - "not op_mini all" - ], - "development": [ - "last 1 chrome version", - "last 1 firefox version", - "last 1 safari version" - ] - } + "browserslist": [ + "defaults", + "not ie 11" + ] } diff --git a/src/client/config.ts b/src/client/config.ts index 7964b79..cf36c66 100644 --- a/src/client/config.ts +++ b/src/client/config.ts @@ -1 +1 @@ -export const origin = 'https://dev2.akarpov.ru/' \ No newline at end of file +export const origin = 'https://0e06-92-100-146-65.ngrok-free.app/' \ No newline at end of file diff --git a/src/consts.tsx b/src/consts.tsx index a6ca788..5fdea72 100644 --- a/src/consts.tsx +++ b/src/consts.tsx @@ -7,9 +7,18 @@ import axios from "axios"; // }); -export const backend = axios.create({ +export let backend = axios.create({ baseURL: 'https://0e06-92-100-146-65.ngrok-free.app/api/', timeout: 100000, headers: {'Authorization': 'Bearer ' + localStorage.getItem('token')} } -) \ No newline at end of file +) + +export const updateBackend = () =>{ + backend = axios.create({ + baseURL: 'https://0e06-92-100-146-65.ngrok-free.app/api/', + timeout: 100000, + headers: {'Authorization': 'Bearer ' + localStorage.getItem('token')} + } + ) +} \ No newline at end of file diff --git a/src/pages/Login/index.tsx b/src/pages/Login/index.tsx index e5d9a95..f125745 100644 --- a/src/pages/Login/index.tsx +++ b/src/pages/Login/index.tsx @@ -25,6 +25,7 @@ export const Login: react.FC = () => { - + + + } \ No newline at end of file diff --git a/src/pages/Login/style.css b/src/pages/Login/style.css index 2bf7a67..2cc26ad 100644 --- a/src/pages/Login/style.css +++ b/src/pages/Login/style.css @@ -20,8 +20,7 @@ width: 400px; } -.btn-y{ - width: 440px!important; +.login-btn-y{ background-color: #FFCF08; border-radius: 10px; padding: 15px 50px; diff --git a/src/pages/Main/index.tsx b/src/pages/Main/index.tsx index 17a2f01..2bd166a 100644 --- a/src/pages/Main/index.tsx +++ b/src/pages/Main/index.tsx @@ -1,7 +1,7 @@ import { AutoComplete, DatePicker, Input, Checkbox, Select, Radio, Space, Spin } from 'antd'; import react, { useEffect, useState } from 'react' import { useNavigate } from 'react-router-dom'; -import { backend } from '../../consts'; +import { backend, updateBackend } from '../../consts'; import { Button } from '../../elements/Button'; import { FavoriteCard, FavoriteCardIE } from '../../elements/FavoriteCard'; import { GenerateCard } from '../../elements/GenerateCard'; @@ -21,10 +21,10 @@ export const Main: react.FC = () => { let navigate = useNavigate() let token = localStorage.getItem('token') - let firstAuth = localStorage.getItem('firstAuth') - + console.log(token) useEffect(()=>{ + updateBackend() if (null == localStorage.getItem('token')){ navigate('/login') } diff --git a/src/pages/Register/index.tsx b/src/pages/Register/index.tsx index c91ac33..12835cc 100644 --- a/src/pages/Register/index.tsx +++ b/src/pages/Register/index.tsx @@ -38,9 +38,8 @@ export const Register: react.FC = () => { или
- {}}> - - + + } \ No newline at end of file diff --git a/src/pages/Register/style.css b/src/pages/Register/style.css index 2bf7a67..2cc26ad 100644 --- a/src/pages/Register/style.css +++ b/src/pages/Register/style.css @@ -20,8 +20,7 @@ width: 400px; } -.btn-y{ - width: 440px!important; +.login-btn-y{ background-color: #FFCF08; border-radius: 10px; padding: 15px 50px; diff --git a/src/pages/SearchPage/index.tsx b/src/pages/SearchPage/index.tsx index 4270216..78c449f 100644 --- a/src/pages/SearchPage/index.tsx +++ b/src/pages/SearchPage/index.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from "react"; +import React, { useEffect, useRef, useState } from "react"; import { useParams } from "react-router-dom"; import { backend } from "../../consts"; import { RouteCard, RouteCardIE } from "../../elements/RouteCard"; @@ -15,14 +15,26 @@ export const SearchPage:React.FC = () =>{ const [data, setData] = useState([]) const [events, setEvents] = useState([]) + const queried = useRef(false); useEffect(()=>{ - if (cities.length == 0){ - backend.get('/data/cities').then((response)=>setCities(response.data)) - backend.post('/route/build',JSON.parse(prefs as string)).then((r)=>setData(r.data as any)) - backend.post('/recommendations/build_events/',JSON.parse(prefs as string)).then((r)=>setEvents(r.data as any)) - } - }) + const dataLoad = async (prefs: string) => { + const cities = await backend.get('/data/cities') + const routes = await backend.post('/route/build',JSON.parse(prefs as string)) + const events = await backend.post('/recommendations/build_events/',JSON.parse(prefs as string)) + return { + cities, routes, events + } + } + if (!queried.current) { + queried.current = true; + dataLoad(prefs as string).then((data) => { + setCities(data.cities.data as any); + setData(data.routes.data as any); + setEvents(data.events.data as any); + }) + } + }, [prefs]) console.log(events) let newData; diff --git a/src/router.tsx b/src/router.tsx index 950efbf..73a5ff3 100644 --- a/src/router.tsx +++ b/src/router.tsx @@ -1,5 +1,5 @@ import { - createBrowserRouter + createBrowserRouter, createHashRouter } from 'react-router-dom' import App from './App' import { Register } from './pages/Register'; @@ -7,8 +7,8 @@ import { Login } from './pages/Login'; 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'; +import { Prefernces } from './elements/Prefernces'; const routes = [ @@ -47,4 +47,4 @@ const routes = [ ] -export const router = createBrowserRouter(routes); +export const router = createHashRouter(routes); From c6e547f4d6e8512ce19d713e114f3b93f39cce8e Mon Sep 17 00:00:00 2001 From: = <=> Date: Mon, 29 May 2023 10:57:38 +0300 Subject: [PATCH 2/3] add tinder --- src/client/index.ts | 161 ++++++++++++++++---------- src/pages/EventMatch/index.tsx | 202 ++++++++++++++++++--------------- src/pages/EventMatch/style.css | 54 +++++++-- 3 files changed, 258 insertions(+), 159 deletions(-) diff --git a/src/client/index.ts b/src/client/index.ts index 6a2581d..e316436 100644 --- a/src/client/index.ts +++ b/src/client/index.ts @@ -1,60 +1,103 @@ -import axios from 'axios'; -import { origin } from './config'; - - -export const register = async (username: string, password: string) => { - await axios.post( - origin + 'api/auth/register/', - { - 'username': username, - 'email': username, - 'password': password - } - ) -} - -export const signin = async (username: string, password: string) => { - const response = await axios.post( - origin + 'api/auth/token/', - { - 'username': username, - 'password': password - } - ); - return response.data; -} - - -export const startTinder = async () => { - const data = await axios.get( - origin + 'api/tinder/start', - { - headers: { - 'Authorization': 'Bearer ' + localStorage.getItem('token') - } - } - ); - return data.data; -} - -export const swipe = async (itemId: string, type: string) => { - var url = origin + 'api/tinder/' + itemId + '/proceed/'; - console.log(url, itemId) - try{ - const data = await axios.post( - url, - { - 'action': type, - }, - { - headers: { - 'Authorization': 'Bearer ' + localStorage.getItem('token') - } - } - ); - return data.data; - } catch { - return false - } - +import axios from 'axios'; +import { origin } from './config'; + + +export const register = async (username: string, password: string) => { + await axios.post( + origin + 'api/auth/register/', + { + 'username': username, + 'email': username, + 'password': password + } + ) +} + +export const signin = async (username: string, password: string) => { + const response = await axios.post( + origin + 'api/auth/token/', + { + 'username': username, + 'password': password + } + ); + return response.data; +} + + +export const startTinder = async () => { + const data = await axios.get( + origin + 'api/tinder/start', + { + headers: { + 'Authorization': 'Bearer ' + localStorage.getItem('token') + } + } + ); + return data.data; +} + +export const swipe = async (itemId: string, type: string) => { + var url = origin + 'api/tinder/' + itemId + '/proceed/'; + console.log(url, itemId) + try{ + const data = await axios.post( + url, + { + 'action': type, + }, + { + headers: { + 'Authorization': 'Bearer ' + localStorage.getItem('token') + } + } + ); + return data.data; + } catch { + return false + } + +} + +export const dailySelectionGenerate = async () => { + var data = await axios.get( + origin + 'api/recommendations/get_daily_selection/', + { + headers: { + 'Authorization': 'Bearer ' + localStorage.getItem('token') + } + } + ); + return data.data; +} + +export const dailySelectionBuild = async (buildData: any) => { + var data = await axios.post( + origin + 'api/recommendations/generate_daily_selection/', + {nodes: buildData}, + { + headers: { + 'Authorization': 'Bearer ' + localStorage.getItem('token') + } + } + ); + return data.data; +} + + +export const saveTinderPath = async (tinderData: any) => { + await axios.post( + origin + 'api/route/save', { + "points": [{ + date: '2000-01-01', + paths: tinderData + },] + }, + + { + headers: { + 'Authorization': 'Bearer ' + localStorage.getItem('token') + } + } + ) } \ No newline at end of file diff --git a/src/pages/EventMatch/index.tsx b/src/pages/EventMatch/index.tsx index b9ed8e8..f9c3f2c 100644 --- a/src/pages/EventMatch/index.tsx +++ b/src/pages/EventMatch/index.tsx @@ -1,93 +1,111 @@ -import react, { useRef } from 'react' -import TinderCard from 'react-tinder-card' -import './style.css' -import { Block } from '../../elements/Block' -import { Card, TinderCardContent } from '../../elements/Card' -import { Button } from '../../elements/Button' -import { startTinder, swipe, } from '../../client' -import {useNavigate} from 'react-router-dom'; - -interface IEventData{ - title: string; - description: string; - id: string; -} - - -export const EventMatch: react.FC = () => { - const ref = useRef(null); - const navigate = useNavigate(); - const started = useRef(false); - const swiping = useRef(false); - const [cardData, setCardData] = react.useState({title: "", description: "", id: ''} as IEventData); - const data = react.useRef({title: "", description: "", id: ''} as IEventData) - - - if (!started.current) { - started.current = true; - startTinder().then((e) => { - - data.current = { - title: e.title, - description: e.description.split(' ').slice(0, 10).join(' '), - id: e.oid - }; - setCardData({ - title: e.title, - description: e.description.split(' ').slice(0, 10).join(' '), - id: e.oid - }); - }) - } - - - return
- - { - console.log("swipe"); - if (swiping.current) return; - swiping.current = true; - swipe(data.current.id, type).then((e) => { - if (!e) { - navigate('/'); - return; - } - data.current = { - title: e.event.title, - description: e.event.description.split(' ').slice(0, 10).join(' '), - id: e.event.oid - }; - setCardData( - { - title: e.event.title, - description: e.event.description.split(' ').slice(0, 10).join(' '), - id: e.event.oid - } - ); - setTimeout(() => { - (ref.current as any).restoreCard(); - swiping.current = false; - }, 2000); - }) - - }}> - - - - - - - - - - - -
+import react, { useRef, useState } from 'react' +import TinderCard from 'react-tinder-card' +import './style.css' +import { Block } from '../../elements/Block' +import { Card, TinderCardContent } from '../../elements/Card' +import { Button } from '../../elements/Button' +import { dailySelectionBuild, dailySelectionGenerate, saveTinderPath, startTinder, swipe, } from '../../client' +import {useNavigate} from 'react-router-dom'; +import { MyMap } from '../../elements/map' + +interface IEventData{ + title: string; + description: string; + id: string; +} + + +export const EventMatch: react.FC = () => { + const ref = useRef(null); + const navigate = useNavigate(); + const started = useRef(false); + const [dailyData, setDailyData] = useState([]); + const [resData, setResData] = useState([]); + const queried = useRef(false); + const [answerData, setAnswerData] = useState([]); + + if (!started.current) { + started.current = true; + dailySelectionGenerate().then((e) => { + console.log(e) + setDailyData(e.events); + }) + } + + return
+ + { + dailyData.map((e) => { + return { + console.log(dailyData.indexOf(e)) + if (dailyData.indexOf(e) == 0) { + if (!resData.length) return; + if (!queried.current) { + dailySelectionBuild(resData).then((e) => { + setAnswerData(e.path); + }); + queried.current = true; + } + } + + if (type == 'right') { + setResData(resData.concat([ + { + 'action': 'right', + 'oid': (e as any).oid + } as any + ])) + } + + }} + > + + + + + + }) + } +
+ { + dailyData.length && !answerData.length ? + (!queried.current ? +
Вы не выбрали ни одного события, Мы не можем сгенерировать вам маршрут. Возвращяйтесь к нам завтра. { + navigate('/'); + }} + >Вернуться на главную
: Подождите немного, мы генерируем для вас ежедневный маршрут) : answerData.length ? e.type == 'point').map((e: any) => {return { + cords: [e.point.lat, e.point.lon], + title: e.point.title, + description: "" + }}) + + }> : <> + } + { + answerData.length ?
+ + +
: <> + } +
+ +
+
} \ No newline at end of file diff --git a/src/pages/EventMatch/style.css b/src/pages/EventMatch/style.css index e421adb..b92a5ec 100644 --- a/src/pages/EventMatch/style.css +++ b/src/pages/EventMatch/style.css @@ -1,9 +1,47 @@ -.tinder-block{ - width: 700px; - display: flex; - justify-content: center; -} - -.main-btn{ - background-color: #FFCF08; +.tinder-block{ + width: 700px; + display: flex; + justify-content: center; +} + +.main-btn{ + background-color: #FFCF08; +} + +.tinder-block{ + height: 600px; +} + +.card{ + position: absolute; +} +.span-er{ + width: 250px; + text-align: center; +} +a{ + color: black; +} +a:visited{ + color: black; +} + +.btns{ + display: flex; + flex-direction: column; + gap: 10px; + margin-top: 20px; +} + +.cont-span{ + display: flex; + justify-content: center; + flex-direction: column; + width: 500px; +} + +.span-cont{ + display: flex; + justify-content: center; + } \ No newline at end of file From ba33783464cd1ce5e5ee302d2be0a759fcfd1f5d Mon Sep 17 00:00:00 2001 From: = <=> Date: Thu, 8 Jun 2023 15:56:19 +0300 Subject: [PATCH 3/3] add adaptive and fix bugs --- public/bonus.svg | 13 +++--- public/favicon.ico | Bin 3870 -> 64562 bytes public/favorites.svg | 4 +- public/index.html | 4 +- public/profile.svg | 4 +- public/search.svg | 12 ++--- src/elements/Card/index.tsx | 2 +- src/elements/Card/style.css | 71 +++++++++++++++--------------- src/elements/ChoiceIcon/style.css | 13 ++++++ src/elements/Header/index.tsx | 9 ++-- src/elements/Header/style.css | 20 +++++++++ src/elements/HotelCard/index.tsx | 5 ++- src/elements/Prefernces/index.tsx | 12 +---- src/elements/Prefernces/style.css | 20 ++++++++- src/elements/RouteCard/style.css | 25 +++++++++++ src/elements/Search/index.tsx | 29 ++++++------ src/pages/EventMatch/index.tsx | 2 + src/pages/EventMatch/style.css | 12 +++++ src/pages/Main/index.tsx | 54 ++++++++++++++--------- src/pages/Main/style.css | 69 ++++++++++++++++++++++++++--- src/pages/Register/style.css | 12 +++++ src/pages/SearchPage/index.tsx | 19 ++------ src/pages/SearchPage/style.css | 43 +++++++++++++++++- 23 files changed, 325 insertions(+), 129 deletions(-) diff --git a/public/bonus.svg b/public/bonus.svg index 1aaec19..94acde9 100644 --- a/public/bonus.svg +++ b/public/bonus.svg @@ -1,13 +1,14 @@ - - + + - - - + + + + - + diff --git a/public/favicon.ico b/public/favicon.ico index a11777cc471a4344702741ab1c8a588998b1311a..92589a2ac19a2cd2124cda7a71c2d737d04aa4d4 100644 GIT binary patch literal 64562 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 baj7?x%VD!5Cxk2YbYLNVeiXvvpMCWYo=by@ diff --git a/public/favorites.svg b/public/favorites.svg index 0a6b8cd..f5535e3 100644 --- a/public/favorites.svg +++ b/public/favorites.svg @@ -1,8 +1,8 @@ - + - + diff --git a/public/index.html b/public/index.html index 369d5cd..bda80fa 100644 --- a/public/index.html +++ b/public/index.html @@ -25,10 +25,10 @@ work correctly both with client-side routing and a non-root public URL. Learn how to configure a non-root public URL by running `npm run build`. --> - React App + Russpass MAGNUM OPUS - +