ui update and axios
@@ -19,6 +19,7 @@
|
||||
"@types/react-redux": "^7.1.24",
|
||||
"@types/react-router": "^5.1.20",
|
||||
"@types/socket.io": "^3.0.2",
|
||||
"axios": "^1.3.4",
|
||||
"framer-motion": "^7.4.0",
|
||||
"i18next": "^22.4.6",
|
||||
"i18next-browser-languagedetector": "^7.0.1",
|
||||
@@ -4938,6 +4939,29 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "1.3.4",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz",
|
||||
"integrity": "sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.15.0",
|
||||
"form-data": "^4.0.0",
|
||||
"proxy-from-env": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/axios/node_modules/form-data": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
|
||||
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"mime-types": "^2.1.12"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/axobject-query": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz",
|
||||
@@ -14146,6 +14170,11 @@
|
||||
"node": ">= 0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/proxy-from-env": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
|
||||
},
|
||||
"node_modules/psl": {
|
||||
"version": "1.9.0",
|
||||
"resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
|
||||
@@ -20942,6 +20971,28 @@
|
||||
"resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.4.3.tgz",
|
||||
"integrity": "sha512-32+ub6kkdhhWick/UjvEwRchgoetXqTK14INLqbGm5U2TzBkBNF3nQtLYm8ovxSkQWArjEQvftCKryjZaATu3w=="
|
||||
},
|
||||
"axios": {
|
||||
"version": "1.3.4",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz",
|
||||
"integrity": "sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==",
|
||||
"requires": {
|
||||
"follow-redirects": "^1.15.0",
|
||||
"form-data": "^4.0.0",
|
||||
"proxy-from-env": "^1.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"form-data": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
|
||||
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
|
||||
"requires": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"mime-types": "^2.1.12"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"axobject-query": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz",
|
||||
@@ -27447,6 +27498,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"proxy-from-env": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
|
||||
},
|
||||
"psl": {
|
||||
"version": "1.9.0",
|
||||
"resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
"@types/react-redux": "^7.1.24",
|
||||
"@types/react-router": "^5.1.20",
|
||||
"@types/socket.io": "^3.0.2",
|
||||
"axios": "^1.3.4",
|
||||
"framer-motion": "^7.4.0",
|
||||
"i18next": "^22.4.6",
|
||||
"i18next-browser-languagedetector": "^7.0.1",
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
"popup-control-link": "Link for connection",
|
||||
"popup-control-btn": "Copy",
|
||||
"popup-control-btn-active": "Link Copied",
|
||||
"language-control-btn": "Language",
|
||||
"language-control-btn": "English",
|
||||
"exit-control-btn": "Exit",
|
||||
"popup-control-exit-title": "Are you sure you want to end the demo?",
|
||||
"popup-control-yes": "Finish",
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
"popup-control-link": "Ссылка для подключения",
|
||||
"popup-control-btn": "Скопировать",
|
||||
"popup-control-btn-active": "Ссылка скопирована",
|
||||
"language-control-btn": "Язык",
|
||||
"language-control-btn": "Русский язык",
|
||||
"exit-control-btn": "Выйти",
|
||||
"popup-control-exit-title": "Вы уверены, что хотите закончить демонстрацию??",
|
||||
"popup-control-yes": "Закончить",
|
||||
|
||||
@@ -11,13 +11,9 @@
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
border-width: 0px 2px;
|
||||
border-style: solid;
|
||||
border-color: #23242a;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.popup {
|
||||
@@ -51,6 +47,11 @@
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
.popup-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@media screen and (max-width: 1440px) {
|
||||
@@ -73,6 +74,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1024px) {
|
||||
.card-container {
|
||||
gap: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 920px) {
|
||||
.card-title {
|
||||
margin: 36px 0 32px 0;
|
||||
|
||||
@@ -25,12 +25,17 @@ const App: React.FC = () => {
|
||||
const { handleCurrentCard } = cardSlice.actions;
|
||||
const { handleChangeLanguage } = languageSlice.actions;
|
||||
const { cards, currentCard } = useAppSelector((state) => state.cardReducer);
|
||||
const { currentLang } = useAppSelector((state) => state.languageReducer);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(fetchCards());
|
||||
dispatch(handleChangeLanguage(cookies.get("i18next")));
|
||||
dispatch(fetchCards(cookies.get("i18next")));
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(fetchCards(cookies.get("i18next")));
|
||||
}, [currentLang])
|
||||
|
||||
const handleCards = (card: ICards) => {
|
||||
dispatch(handleCurrentCard(card));
|
||||
history.push("/connect-page");
|
||||
@@ -59,8 +64,10 @@ const App: React.FC = () => {
|
||||
{currentCard ? (
|
||||
<div className="background">
|
||||
<Header></Header>
|
||||
<div className="content__container">
|
||||
<PopupComponent></PopupComponent>
|
||||
<div className="popup-container">
|
||||
<div className="content__container">
|
||||
<PopupComponent></PopupComponent>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
@@ -72,7 +79,9 @@ const App: React.FC = () => {
|
||||
</Route>
|
||||
<Route path="/plan">
|
||||
<Header></Header>
|
||||
<PlanComponent></PlanComponent>
|
||||
<div className="popup-container">
|
||||
<PlanComponent></PlanComponent>
|
||||
</div>
|
||||
</Route>
|
||||
</Switch>
|
||||
);
|
||||
|
||||
@@ -5,9 +5,8 @@ import { useTranslation } from "react-i18next";
|
||||
import { useAppDispatch, useAppSelector } from "hooks/redux";
|
||||
|
||||
|
||||
export const LoadingPopup: React.FC<any> = ({ }) => {
|
||||
export const LoadingPopup: React.FC<any> = ({ logo }) => {
|
||||
|
||||
const { currentCard } = useAppSelector((state) => state.cardReducer);
|
||||
|
||||
const history = useHistory();
|
||||
const { t } = useTranslation();
|
||||
@@ -16,7 +15,7 @@ export const LoadingPopup: React.FC<any> = ({ }) => {
|
||||
<div className="popup popup-type-loader">
|
||||
<div className="loading-logo-container">
|
||||
<div className="popup-img-container">
|
||||
<img className="popup-logo" src={currentCard.image.logo} alt="лого" />
|
||||
<img className="popup-logo" src={logo} alt="лого" />
|
||||
</div>
|
||||
<span className="loading-caption">Пожалуйста подождите</span>
|
||||
</div>
|
||||
|
||||
@@ -52,7 +52,7 @@ export const PopupComponent: React.FC = () => {
|
||||
>
|
||||
<PopupConnect
|
||||
isLoading={true}
|
||||
logo={currentCard.image.logo}
|
||||
logo={currentCard.logo}
|
||||
onConnect={() => dispatch(createSession(currentCard.title))}
|
||||
></PopupConnect>
|
||||
</motion.div>
|
||||
@@ -65,7 +65,7 @@ export const PopupComponent: React.FC = () => {
|
||||
animate={"show"}
|
||||
exit={"hidden"}
|
||||
>
|
||||
<LoadingPopup logo={currentCard.image.logo}></LoadingPopup>
|
||||
<LoadingPopup logo={currentCard.logo}></LoadingPopup>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
|
||||
@@ -9,23 +9,21 @@ export const Card: React.FC<any> = ({ item, onClick }) => {
|
||||
console.log(currentLang);
|
||||
return (
|
||||
<div onClick={() => onClick()} className="card">
|
||||
<img className="card-image" src={item.image.preview} alt='building' />
|
||||
<img className="card-image" src={item.preview} alt='building' />
|
||||
<div className="card-body">
|
||||
<div className="card-header">
|
||||
<img src={iconButton} className="card-icon" alt="лого" />
|
||||
<img src={item.icon} className="card-icon" alt="лого" />
|
||||
<div className="card-name">
|
||||
<h2 className="caption-name">{currentLang === "ru" ? item.title_full.ru : item.title_full.en}</h2>
|
||||
<h2 className="card-location">{currentLang === "ru" ? item.location.ru : item.location.en}</h2>
|
||||
<h2 className="caption-name">{item.app_title}</h2>
|
||||
<h2 className="card-location">{item.location}</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div className="card-description-block">
|
||||
<p className="card-description"> {currentLang === "ru"
|
||||
? item.description.ru
|
||||
: item.description.en}
|
||||
<p className="card-description">
|
||||
{item.description}
|
||||
</p>
|
||||
{item.description_second ? <p className="card-description-second">{currentLang === "ru"
|
||||
? item.description_second.ru
|
||||
: item.description_second.en}
|
||||
{item.feature_description ? <p className="card-description-second">
|
||||
{item.feature_description}
|
||||
</p> : <p className="card-description-empty"></p>}
|
||||
|
||||
</div>
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
}
|
||||
|
||||
.calendar {
|
||||
height: 320px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.calendar-header {
|
||||
@@ -42,6 +42,12 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.calendar-cell_active {
|
||||
cursor: pointer;
|
||||
background: rgba(86, 126, 206, 0.2);
|
||||
|
||||
}
|
||||
|
||||
.calendar-nav:hover {
|
||||
background: rgba(86, 126, 206, 0.2);
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ export const CalendarComponent: React.FC<any> = ({ time, pickedTime }) => {
|
||||
|
||||
return (
|
||||
<div className="calendar-container">
|
||||
<h3 className="title-planning calendar-title">Выберите <br></br> дату.</h3>
|
||||
<h3 className="plan-title">Выберите дату.</h3>
|
||||
<div className="calendar">
|
||||
<div className="calendar-header">
|
||||
<img
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
.form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.form-input-container {
|
||||
@@ -11,6 +11,7 @@
|
||||
}
|
||||
|
||||
.form-input {
|
||||
width: 100%;
|
||||
background: #23242a;
|
||||
box-sizing: border-box;
|
||||
outline: none;
|
||||
@@ -26,6 +27,9 @@
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
.form-input-caption {
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
@@ -34,9 +38,78 @@
|
||||
}
|
||||
|
||||
.form-input:focus {
|
||||
border-image-source: linear-gradient(180deg, #bc75ff 0%, #798fff 100%);
|
||||
border: linear-gradient(180deg, #bc75ff 0%, #798fff 100%);
|
||||
}
|
||||
|
||||
.form-input:invalid {
|
||||
border: 1px solid #E94444;
|
||||
.form-border {
|
||||
cursor: text;
|
||||
position: relative;
|
||||
border: 1px solid transparent;
|
||||
|
||||
}
|
||||
|
||||
.form-border::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
border-radius: 4px;
|
||||
padding: 1px;
|
||||
background: transparent;
|
||||
-webkit-mask:
|
||||
linear-gradient(#fff 0 0) content-box,
|
||||
linear-gradient(#fff 0 0);
|
||||
-webkit-mask-composite: xor;
|
||||
mask-composite: exclude;
|
||||
}
|
||||
|
||||
.form-border-error {
|
||||
cursor: text;
|
||||
position: relative;
|
||||
border: 1px solid transparent;
|
||||
|
||||
}
|
||||
|
||||
.form-border-error::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
border-radius: 4px;
|
||||
padding: 1px;
|
||||
background: transparent;
|
||||
-webkit-mask:
|
||||
linear-gradient(#fff 0 0) content-box,
|
||||
linear-gradient(#fff 0 0);
|
||||
-webkit-mask-composite: xor;
|
||||
mask-composite: exclude;
|
||||
}
|
||||
|
||||
.form-border-error:focus-within::after {
|
||||
background: linear-gradient(180deg, #E94444 100%, #E94444 100%);
|
||||
}
|
||||
|
||||
.form-border:focus-within::after {
|
||||
background: linear-gradient(180deg, #798fff -41.07%, #d375ff 100%);
|
||||
}
|
||||
|
||||
|
||||
|
||||
input:-webkit-autofill,
|
||||
input:-webkit-autofill:focus {
|
||||
transition: background-color 600000s 0s, color 600000s 0s;
|
||||
}
|
||||
|
||||
.error-caption {
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-size: 10px;
|
||||
line-height: 130%;
|
||||
/* identical to box height, or 13px */
|
||||
height: 26px;
|
||||
display: none;
|
||||
/* Error */
|
||||
color: #E94444;
|
||||
}
|
||||
|
||||
.error-caption-active {
|
||||
display: inline-block;
|
||||
}
|
||||
@@ -2,24 +2,32 @@ import chevron from "images/icons/ChevronLeft.svg";
|
||||
import "./Form.css";
|
||||
|
||||
import { planSlice } from "store/reducers/planSlice";
|
||||
import useFormWithValidation from "hooks/useFormWithValidation";
|
||||
import { useAppDispatch, useAppSelector } from "hooks/redux";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
export const Form: React.FC<any> = ({ time }) => {
|
||||
const [error, showError] = useState(false)
|
||||
const { values, handleChangeState, resetForm, errors, isValid } =
|
||||
useFormWithValidation();
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
const { handleNavigation, handleTimeValue } = planSlice.actions;
|
||||
|
||||
const handleValue = (day: moment.Moment) => {
|
||||
dispatch(
|
||||
handleNavigation({
|
||||
isDone: false,
|
||||
isCalendar: false,
|
||||
isTimepicker: true,
|
||||
isForm: false,
|
||||
})
|
||||
);
|
||||
|
||||
dispatch(handleTimeValue(day));
|
||||
};
|
||||
useEffect(() => {
|
||||
resetForm();
|
||||
}, [resetForm]);
|
||||
|
||||
|
||||
|
||||
function handleSubmit(e: React.SyntheticEvent) {
|
||||
e.preventDefault();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
const handleReturn = () => {
|
||||
dispatch(
|
||||
@@ -34,8 +42,8 @@ export const Form: React.FC<any> = ({ time }) => {
|
||||
|
||||
return (
|
||||
<div className="calendar-container">
|
||||
<h3 className="plan-title plan-title-plan">
|
||||
Расскажите <br></br> о себе.
|
||||
<h3 className="plan-title">
|
||||
Расскажите о себе.
|
||||
</h3>
|
||||
<button
|
||||
onClick={() => handleReturn()}
|
||||
@@ -49,17 +57,27 @@ export const Form: React.FC<any> = ({ time }) => {
|
||||
<div className="calendar-header">
|
||||
<span className="calendar-date">{time.format("DD MMM, LT")}</span>
|
||||
</div>
|
||||
<form className="form">
|
||||
<form noValidate onSubmit={handleSubmit} className="form">
|
||||
<div className="form-input-container">
|
||||
<span className="form-input-caption">Имя</span>
|
||||
<input min={2} max={30} className="form-input" type="text"></input>
|
||||
<label className="form-input-caption">Имя</label>
|
||||
<div className={errors.name ? "form-border-error" : 'form-border'}>
|
||||
<input required onChange={handleChangeState} name='name' value={values.name} minLength={2} maxLength={30} className="form-input" type="text"></input>
|
||||
</div>
|
||||
<span className={errors.name ? "error-caption error-caption-active" : "error-caption"}>{errors.name}</span>
|
||||
</div>
|
||||
<div className="form-input-container">
|
||||
<span className="form-input-caption">E-mail</span>
|
||||
<input className="form-input" type="e-mail"></input>
|
||||
<label className="form-input-caption">E-mail</label>
|
||||
<div className={errors.email ? "form-border-error" : 'form-border'}>
|
||||
<input required onChange={handleChangeState} name='email' value={values.email} className="form-input" type="email"></input>
|
||||
</div>
|
||||
<span className={errors.email ? "error-caption error-caption-active" : "error-caption"}>{errors.email}</span>
|
||||
|
||||
|
||||
</div>
|
||||
<button
|
||||
style={{ marginTop: "32px" }}
|
||||
type="submit"
|
||||
disabled={!isValid}
|
||||
style={{ marginTop: "24px" }}
|
||||
className="button button-primary"
|
||||
>
|
||||
Запланировать
|
||||
|
||||
@@ -3,14 +3,15 @@
|
||||
width: 428px;
|
||||
justify-content: center;
|
||||
padding: 24px 56px;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
box-sizing: border-box;
|
||||
border-width: 0px 2px;
|
||||
border-style: solid;
|
||||
border-color: #23242a;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.button-plan {
|
||||
margin-top: 24px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.calendar-position {
|
||||
@@ -33,6 +34,7 @@
|
||||
font-size: 38px;
|
||||
line-height: 100%;
|
||||
color: #f2f2f2;
|
||||
width: 60%;
|
||||
}
|
||||
|
||||
.calendar-date {
|
||||
@@ -103,23 +105,44 @@
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 920px) {
|
||||
.calendar-position {
|
||||
top: 50%;
|
||||
}
|
||||
.plan-logo-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 430px) {
|
||||
|
||||
|
||||
|
||||
@media screen and (max-width: 640px) {
|
||||
|
||||
.plan-title {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.plan-logo-container {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.content-container-plan {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
padding: 10px;
|
||||
gap: 45px;
|
||||
padding: 0 10px;
|
||||
border: none;
|
||||
height: auto;
|
||||
|
||||
}
|
||||
|
||||
.calendar-position {
|
||||
position: static;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
.calendar {
|
||||
width: 100%;
|
||||
}
|
||||
@@ -129,7 +152,8 @@
|
||||
}
|
||||
|
||||
.plan-title {
|
||||
margin-top: 32px;
|
||||
margin-top: 24px;
|
||||
margin-bottom: 24px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-size: 24px;
|
||||
@@ -137,9 +161,3 @@
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 380px) {
|
||||
.calendar-position {
|
||||
top: 60%;
|
||||
}
|
||||
}
|
||||
@@ -16,12 +16,15 @@ import { useAppSelector } from "hooks/redux";
|
||||
import { popupAnimation } from "utils/animationProps";
|
||||
|
||||
export const PlanComponent: React.FC<any> = () => {
|
||||
const { isDone, isCalendar, isTimepicker, isForm, time } = useAppSelector(
|
||||
const { isDone, isCalendar, isTimepicker, isForm, time, currTime } = useAppSelector(
|
||||
(state) => state.planReducer
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="content-container-plan">
|
||||
<div className="plan-logo-container">
|
||||
<img style={{ width: "158px" }} src={logo}></img>
|
||||
</div>
|
||||
<div className="calendar-position">
|
||||
<AnimatePresence mode="wait">
|
||||
{isCalendar && (
|
||||
@@ -43,7 +46,7 @@ export const PlanComponent: React.FC<any> = () => {
|
||||
animate={"show"}
|
||||
exit={"hidden"}
|
||||
>
|
||||
<TimepickerComponent time={time}></TimepickerComponent>
|
||||
<TimepickerComponent time={currTime}></TimepickerComponent>
|
||||
</motion.div>
|
||||
)}
|
||||
{isForm && (
|
||||
@@ -54,7 +57,7 @@ export const PlanComponent: React.FC<any> = () => {
|
||||
animate={"show"}
|
||||
exit={"hidden"}
|
||||
>
|
||||
<Form time={time}></Form>
|
||||
<Form time={currTime}></Form>
|
||||
</motion.div>
|
||||
)}
|
||||
{isDone && (
|
||||
@@ -72,7 +75,7 @@ export const PlanComponent: React.FC<any> = () => {
|
||||
{!isDone && (
|
||||
<>
|
||||
<div className="line line-calendar"></div>
|
||||
<button style={{height: '32px'}} className="button button-type-small">
|
||||
<button style={{ height: '32px' }} className="button button-type-small">
|
||||
На сайт жилого комплекса
|
||||
</button>
|
||||
</>
|
||||
|
||||
@@ -1,11 +1,4 @@
|
||||
.button-plan {
|
||||
margin-top: 16px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.plan-title-plan {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.timepicker-cell {
|
||||
padding: 9px 18px;
|
||||
|
||||
@@ -51,7 +51,7 @@ export const TimepickerComponent: React.FC<any> = ({ time }) => {
|
||||
};
|
||||
return (
|
||||
<div className="calendar-container">
|
||||
<h3 style={{margin:"0"}} className="title-planning">Выберите <br></br> время.</h3>
|
||||
<h3 className="plan-title">Выберите время.</h3>
|
||||
<button
|
||||
onClick={() => handleReturn()}
|
||||
style={{ width: "120px", padding: "4px 16px 4px 4px", height: "32px" }}
|
||||
|
||||
@@ -7,7 +7,7 @@ import { useTranslation } from "react-i18next";
|
||||
import { Button } from "components/shared/Button/Button";
|
||||
|
||||
export const FullscreenButton: React.FC<any> = ({ isSidebarWide }) => {
|
||||
|
||||
|
||||
const [active, setActive] = useState(Boolean(document.fullscreenElement));
|
||||
const [button, setButton] = useState({
|
||||
icon: fullscreen,
|
||||
@@ -46,7 +46,8 @@ export const FullscreenButton: React.FC<any> = ({ isSidebarWide }) => {
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div tabIndex={-1} onClick={handleClick} className="toolbar-button-area">
|
||||
<div onFocus={(e) => e.target.blur()}
|
||||
tabIndex={-1} onClick={handleClick} className="toolbar-button-area">
|
||||
<Button
|
||||
isSidebarWide={isSidebarWide}
|
||||
button={button}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M3 19C2.44772 19 2 18.5523 2 18V7C2 6.44772 2.44772 6 3 6H8.82201C9.28827 6 9.66624 6.37798 9.66624 6.84424C9.66624 7.3105 9.28827 7.68848 8.82201 7.68848H4.34491C4.06877 7.68848 3.84491 7.91233 3.84491 8.18848V11.1494C3.84491 11.4256 4.06877 11.6494 4.34491 11.6494H8.42515C8.88966 11.6494 9.26621 12.026 9.26621 12.4905C9.26621 12.955 8.88966 13.3315 8.42515 13.3315H4.34491C4.06877 13.3315 3.84491 13.5554 3.84491 13.8315V16.8115C3.84491 17.0877 4.06877 17.3115 4.34491 17.3115H8.89365C9.35991 17.3115 9.73789 17.6895 9.73789 18.1558C9.73789 18.622 9.35991 19 8.89365 19H3Z" fill="#C5C7CE"/>
|
||||
<path d="M21.0865 6C21.591 6 22 6.40899 22 6.9135V18C22 18.5523 21.5523 19 21 19H20.8462C20.5082 19 20.193 18.8293 20.0085 18.5461L14.1107 9.49922C14.0972 9.47838 14.074 9.46582 14.0491 9.46582C14.0085 9.46582 13.9755 9.49876 13.9755 9.5394V18.0775C13.9755 18.587 13.5625 19 13.0531 19C12.5436 19 12.1306 18.587 12.1306 18.0775V7C12.1306 6.44772 12.5783 6 13.1306 6H13.2963C13.6343 6 13.9495 6.1708 14.1341 6.45403L20.0378 15.5135C20.0514 15.5343 20.0746 15.5469 20.0994 15.5469C20.1401 15.5469 20.173 15.5139 20.173 15.4733V6.9135C20.173 6.40899 20.582 6 21.0865 6Z" fill="#C5C7CE"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -1,8 +1,13 @@
|
||||
import microOn from "images/icons/MicroOn.svg";
|
||||
import en from "./EN.svg";
|
||||
import ru from "./RU.svg";
|
||||
|
||||
import { useState } from "react";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { AnimatePresence, motion } from "framer-motion";
|
||||
|
||||
import { useAppDispatch, useAppSelector } from "hooks/redux";
|
||||
import { languageSlice } from "store/reducers/languageSlice";
|
||||
|
||||
import { Button } from "components/shared/Button/Button";
|
||||
|
||||
const container = {
|
||||
@@ -21,24 +26,41 @@ const container = {
|
||||
};
|
||||
|
||||
export const LanguageButton: React.FC<any> = ({ hover, setHover, isSidebarWide }) => {
|
||||
const [active, setActive] = useState(false);
|
||||
const [open, setOpen] = useState(false);
|
||||
const { handleChangeLanguage } = languageSlice.actions;
|
||||
const { currentLang } = useAppSelector((state) => state.languageReducer);
|
||||
const dispatch = useAppDispatch()
|
||||
|
||||
const button = {
|
||||
icon: microOn,
|
||||
const [open, setOpen] = useState(false);
|
||||
const [button, setButton] = useState({
|
||||
icon: currentLang === 'en' ? en : ru,
|
||||
active: "language-control-btn",
|
||||
inactive: "language-control-btn",
|
||||
type: "language",
|
||||
};
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
setButton({
|
||||
icon: currentLang === 'en' ? en : ru,
|
||||
active: "language-control-btn",
|
||||
inactive: "language-control-btn",
|
||||
type: "language",
|
||||
})
|
||||
}, [currentLang])
|
||||
|
||||
|
||||
const handleClick = () => {
|
||||
if (currentLang === 'en') {
|
||||
dispatch(handleChangeLanguage('ru'))
|
||||
} else {
|
||||
dispatch(handleChangeLanguage('en'))
|
||||
}
|
||||
|
||||
function handleClick() {
|
||||
setOpen(true);
|
||||
setActive((prev) => !prev);
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<div className="toolbar-button-area">
|
||||
<Button isSidebarWide={isSidebarWide} button={button} onClick={handleClick}></Button>
|
||||
<div onClick={handleClick} className="toolbar-button-area">
|
||||
<Button isSidebarWide={isSidebarWide} button={button}></Button>
|
||||
<AnimatePresence>
|
||||
{open && (
|
||||
<motion.div
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M2.89773 18.7877C2.40193 18.7877 2 18.3858 2 17.89V7C2 6.44771 2.44772 6 3 6H6.24172C7.16366 6 7.92872 6.17067 8.5369 6.51201C9.14894 6.85335 9.60604 7.32581 9.90819 7.9294C10.2103 8.52882 10.3614 9.2219 10.3614 10.0086C10.3614 10.7912 10.2084 11.4801 9.90238 12.0754C9.60023 12.6665 9.14313 13.1265 8.53109 13.4553C7.92291 13.7842 7.15785 13.9486 6.23591 13.9486H3.85311C3.39447 13.9486 3.02266 13.5768 3.02266 13.1182V13.1182C3.02266 12.6595 3.39447 12.2877 3.85311 12.2877H6.07321C6.65427 12.2877 7.12686 12.1982 7.49099 12.0192C7.859 11.8402 8.12822 11.5801 8.29866 11.2387C8.46911 10.8974 8.55433 10.4874 8.55433 10.0086C8.55433 9.52578 8.46717 9.10743 8.29285 8.7536C8.12241 8.39978 7.85319 8.1292 7.48518 7.94188C7.12105 7.7504 6.64265 7.65466 6.04997 7.65466H4.29547C4.01933 7.65466 3.79547 7.87852 3.79547 8.15466V17.89C3.79547 18.3858 3.39354 18.7877 2.89773 18.7877V18.7877ZM7.32848 13.0183C7.66354 13.0183 7.97028 13.2062 8.12241 13.5047L10.1411 17.4661C10.4493 18.0708 10.01 18.7877 9.3313 18.7877V18.7877C8.9869 18.7877 8.67209 18.5931 8.51818 18.285L6.53132 14.3075C6.23536 13.7151 6.66621 13.0183 7.32848 13.0183V13.0183Z" fill="#C5C7CE"/>
|
||||
<path d="M20.1987 6.90064C20.1987 6.40323 20.602 6 21.0994 6V6C21.5968 6 22 6.40323 22 6.90064V14.4107C22 15.3056 21.8044 16.0986 21.4131 16.7896C21.0219 17.4765 20.4718 18.0176 19.7629 18.4131C19.054 18.8044 18.2231 19 17.2702 19C16.3211 19 15.4922 18.8044 14.7833 18.4131C14.0744 18.0176 13.5243 17.4765 13.1331 16.7896C12.7418 16.0986 12.5462 15.3056 12.5462 14.4107V6.89773C12.5462 6.40193 12.9481 6 13.4439 6V6C13.9397 6 14.3417 6.40193 14.3417 6.89773V14.2546C14.3417 14.8332 14.4598 15.3473 14.6961 15.7968C14.9363 16.2464 15.2752 16.6002 15.713 16.8583C16.1507 17.1122 16.6698 17.2392 17.2702 17.2392C17.8745 17.2392 18.3955 17.1122 18.8332 16.8583C19.2748 16.6002 19.6119 16.2464 19.8443 15.7968C20.0806 15.3473 20.1987 14.8332 20.1987 14.2546V6.90064Z" fill="#C5C7CE"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
@@ -1,5 +1,5 @@
|
||||
import "./PlayerStyles.css";
|
||||
import React, { useEffect } from "react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useHistory, useParams } from "react-router-dom";
|
||||
|
||||
import { Sidebar } from "components/pages/Stream/Sidebar/Sidebar";
|
||||
@@ -14,6 +14,7 @@ type link = {
|
||||
|
||||
export const PlayerComponent: React.FC<any> = ({ closeStream }) => {
|
||||
const { id } = useParams<link>();
|
||||
const [click, setClick] = useState(false)
|
||||
const dispatch = useAppDispatch();
|
||||
const { cleanErrors } = sessionSlice.actions;
|
||||
const history = useHistory();
|
||||
@@ -31,18 +32,23 @@ export const PlayerComponent: React.FC<any> = ({ closeStream }) => {
|
||||
|
||||
const { url } = useAppSelector((state) => state.sessionReducer);
|
||||
|
||||
const exitPopup = () => {
|
||||
setClick(prev => !prev)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<iframe
|
||||
onLoad={(e: any) => e.target.focus()}
|
||||
id="player"
|
||||
onFocus={() => console.log('focus')}
|
||||
onBlur={(e) => e.target.focus()} /// element loosing focus and keyboard input doesn't work
|
||||
src={url}
|
||||
className={"player playerOn"}
|
||||
security={""}
|
||||
allowFullScreen={true}
|
||||
></iframe>
|
||||
<Sidebar closeStream={closeStream}></Sidebar>
|
||||
|
||||
<Sidebar exitPopup={click} closeStream={closeStream}></Sidebar>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import "../PopupShare/sharePopup.css";
|
||||
import "./PopupExit.css";
|
||||
import close from 'images/icons/close.svg'
|
||||
|
||||
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
@@ -10,15 +12,12 @@ export const PopupExit: React.FC<TSidebarPopup> = ({ setClose, onExit }) => {
|
||||
|
||||
return (
|
||||
<div className="popup exit-popup-container popup">
|
||||
<div className="popup-position-container">
|
||||
<div className="mobile-users-part-header">
|
||||
<h2 className="mobile-users-part-header-title exit-popup-button-title">
|
||||
{t("popup-control-exit-title")}
|
||||
</h2>
|
||||
<button
|
||||
onClick={() => setClose()}
|
||||
className="mobile-users-part-header-close-button"
|
||||
></button>
|
||||
<div className="popup-container-position">
|
||||
<h2 className="mobile-users-part-header-title">
|
||||
{t("popup-control-exit-title")}
|
||||
</h2>
|
||||
<div onClick={() => setClose()} className="icon-close-container">
|
||||
<img src={close}></img>
|
||||
</div>
|
||||
<div className="exit-popup-button-container">
|
||||
<button onClick={() => setClose()} className="button button-primary">
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import "./sharePopup.css";
|
||||
import close from 'images/icons/close.svg'
|
||||
|
||||
import { useState, useEffect } from "react";
|
||||
|
||||
@@ -23,39 +24,41 @@ export const PopupShare: React.FC<any> = ({ setClose }) => {
|
||||
|
||||
return (
|
||||
<div className="share-popup-container popup">
|
||||
<div className="mobile-users-part-header share-header-popup">
|
||||
<h2 className="mobile-users-part-header-title">
|
||||
{t("popup-control-invite-title")}
|
||||
</h2>
|
||||
<button
|
||||
onClick={closePopup}
|
||||
className="mobile-users-part-header-close-button"
|
||||
></button>
|
||||
</div>
|
||||
<div className="share-popup-data-container">
|
||||
<h3 className="share-popup-data-title">
|
||||
{t("popup-control-link")}
|
||||
</h3>
|
||||
<input
|
||||
className="share-popup-data-input href"
|
||||
value={window.location.href}
|
||||
readOnly
|
||||
></input>
|
||||
</div>
|
||||
<div className="share-popup-data-container">
|
||||
{!copy ? (
|
||||
<button onClick={copyLink} className="button button-primary ">
|
||||
<span className="share-popup-copy-button-icon"></span>
|
||||
<span className="">
|
||||
{copy ? t("popup-control-btn-active") : t("popup-control-btn")}
|
||||
</span>
|
||||
</button>
|
||||
) : (
|
||||
<button onClick={copyLink} className="button button-teritary">
|
||||
<span className="share-popup-copied-button-icon"></span>
|
||||
<span className="">{t("popup-control-btn-active")}</span>
|
||||
</button>
|
||||
)}
|
||||
|
||||
<div className="popup-container-position">
|
||||
<div onClick={closePopup} className="icon-close-container">
|
||||
<img src={close}></img>
|
||||
</div>
|
||||
<div className="mobile-users-part-header share-header-popup">
|
||||
<h2 className="mobile-users-part-header-title">
|
||||
{t("popup-control-invite-title")}
|
||||
</h2>
|
||||
</div>
|
||||
<div className="share-popup-data-container">
|
||||
<h3 className="share-popup-data-title">
|
||||
{t("popup-control-link")}
|
||||
</h3>
|
||||
<input
|
||||
className="share-popup-data-input href"
|
||||
value={window.location.href}
|
||||
readOnly
|
||||
></input>
|
||||
</div>
|
||||
<div className="share-popup-data-container">
|
||||
{!copy ? (
|
||||
<button onClick={copyLink} className="button button-primary ">
|
||||
<span className="share-popup-copy-button-icon"></span>
|
||||
<span className="">
|
||||
{copy ? t("popup-control-btn-active") : t("popup-control-btn")}
|
||||
</span>
|
||||
</button>
|
||||
) : (
|
||||
<button onClick={copyLink} className="button button-teritary">
|
||||
<span className="share-popup-copied-button-icon"></span>
|
||||
<span className="">{t("popup-control-btn-active")}</span>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
.share-popup-container {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
background: #151619;
|
||||
@@ -10,7 +8,26 @@
|
||||
width: 400px;
|
||||
color: #ffffff;
|
||||
padding: 40px;
|
||||
}
|
||||
|
||||
.icon-close-container {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
padding: 8px;
|
||||
height: 40px;
|
||||
width: 40px;
|
||||
box-sizing: border-box;
|
||||
top: -40px;
|
||||
right: -40px;
|
||||
|
||||
}
|
||||
|
||||
.popup-container-position {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 32px;
|
||||
|
||||
}
|
||||
|
||||
.share-header-popup {
|
||||
|
||||
@@ -110,8 +110,8 @@
|
||||
position: relative;
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
padding: 8px;
|
||||
background-color: transparent;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.toolbar-button-area.hidden {
|
||||
@@ -152,8 +152,8 @@
|
||||
.toolbar-button {
|
||||
background: transparent;
|
||||
position: relative;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
color: #ffffff;
|
||||
@@ -161,7 +161,8 @@
|
||||
font-size: 14px;
|
||||
justify-content: center;
|
||||
line-height: 17px;
|
||||
padding: 0px;
|
||||
box-sizing: border-box;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.toolbar-button-active {
|
||||
@@ -575,8 +576,7 @@
|
||||
}
|
||||
|
||||
@media screen and (max-height: 700px) {
|
||||
.toolbar-field {
|
||||
}
|
||||
.toolbar-field {}
|
||||
|
||||
|
||||
.toolbar-button:hover {
|
||||
@@ -643,4 +643,4 @@
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,13 +16,18 @@ import {
|
||||
wideSidebarAdminVariants,
|
||||
} from "utils/animationProps";
|
||||
|
||||
export const Sidebar: React.FC<any> = ({ closeStream }) => {
|
||||
export const Sidebar: React.FC<any> = ({ closeStream, exitPopup }) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
const [popup, setPopup] = useState({
|
||||
popup1: false,
|
||||
popup2: false,
|
||||
});
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
console.log('test')
|
||||
}, [exitPopup])
|
||||
|
||||
const isAdmin = true;
|
||||
|
||||
const [selected, setSelected] = useState(false);
|
||||
@@ -63,6 +68,7 @@ export const Sidebar: React.FC<any> = ({ closeStream }) => {
|
||||
|
||||
useEffect(() => () => unmountComponent(), []);
|
||||
|
||||
|
||||
function unmountComponent() {
|
||||
setOpen(false);
|
||||
setPopup({
|
||||
@@ -81,6 +87,7 @@ export const Sidebar: React.FC<any> = ({ closeStream }) => {
|
||||
return (
|
||||
<>
|
||||
<motion.div
|
||||
/// onHoverEnd={() => /// closeSideBar()}
|
||||
initial={false}
|
||||
animate={open ? "open" : "closed"}
|
||||
variants={wideSidebar ? setAnimation() : sidebarVariants}
|
||||
@@ -162,3 +169,7 @@ export const Sidebar: React.FC<any> = ({ closeStream }) => {
|
||||
</>
|
||||
);
|
||||
};
|
||||
function getElementById(arg0: string) {
|
||||
throw new Error("Function not implemented.");
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import { animationButton } from "utils/animationProps";
|
||||
import { useAppSelector } from "hooks/redux";
|
||||
|
||||
export const Button: React.FC<any> = ({ button, active, isSidebarWide }) => {
|
||||
|
||||
|
||||
const [hover, setHover] = useState(false);
|
||||
const { currentLang } = useAppSelector((state) => state.languageReducer);
|
||||
|
||||
@@ -27,11 +27,7 @@ export const Button: React.FC<any> = ({ button, active, isSidebarWide }) => {
|
||||
: "toolbar-button"
|
||||
}
|
||||
>
|
||||
{button.type === "language" ? (
|
||||
<span className="language-caption">{currentLang.toUpperCase()}</span>
|
||||
) : (
|
||||
<img alt="icon" className="toolbar-icon" src={button.icon} />
|
||||
)}
|
||||
<img alt="icon" className="toolbar-icon" src={button.icon} />
|
||||
</motion.div>
|
||||
<motion.span
|
||||
initial={false}
|
||||
|
||||
@@ -1,11 +1,48 @@
|
||||
|
||||
.header-container {
|
||||
.header {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
padding: 30px 40px;
|
||||
color: #ffffff;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.header-popup {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.header-button-container {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
|
||||
}
|
||||
|
||||
|
||||
.button-lang {
|
||||
background: transparent;
|
||||
border: none;
|
||||
outline: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
box-sizing: border-box;
|
||||
border-radius: 4px;
|
||||
padding: 10px 14px;
|
||||
}
|
||||
|
||||
|
||||
.button-lang:hover {
|
||||
background: #23242A;
|
||||
}
|
||||
|
||||
.button-lang-active {
|
||||
cursor: pointer;
|
||||
pointer-events: none;
|
||||
background: #2E3038;
|
||||
|
||||
}
|
||||
|
||||
.header__buttons_wrapper {
|
||||
@@ -19,29 +56,15 @@
|
||||
}
|
||||
|
||||
.header-logo {
|
||||
width: 31px;
|
||||
height: 50px;
|
||||
|
||||
width: 104px;
|
||||
height: 40px;
|
||||
|
||||
}
|
||||
|
||||
.header-buttons {
|
||||
margin-right: 96px;
|
||||
}
|
||||
|
||||
.header-button {
|
||||
font-family: "GilroyWebRegular";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-size: 16px;
|
||||
line-height: 125%;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
color: #ffffff;
|
||||
cursor: pointer;
|
||||
padding: 0px;
|
||||
appearance: none;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.header-lang-button-text:hover {
|
||||
background: rgba(235, 235, 235, 0.2);
|
||||
@@ -159,15 +182,10 @@
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1600px) {
|
||||
.header-container {
|
||||
.header {
|
||||
padding: 35px 48px;
|
||||
}
|
||||
|
||||
.header-logo {
|
||||
width: 46px;
|
||||
height: 74px;
|
||||
}
|
||||
|
||||
.header-button {
|
||||
font-size: 20px;
|
||||
|
||||
@@ -177,7 +195,7 @@
|
||||
height: auto;
|
||||
|
||||
}
|
||||
|
||||
|
||||
.header-buttons {
|
||||
gap: 48px;
|
||||
}
|
||||
@@ -186,25 +204,25 @@
|
||||
width: 70px;
|
||||
padding: 7px 15px;
|
||||
top: 57px;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@media screen and (max-width: 1279px) {
|
||||
.header-container {
|
||||
.header {
|
||||
padding: 30px 12px;
|
||||
}
|
||||
|
||||
.header-lang-button {
|
||||
top: 40px;
|
||||
right: 12px;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1024px) {
|
||||
.header-container {
|
||||
.header {
|
||||
padding: 15px 12px;
|
||||
}
|
||||
|
||||
@@ -216,11 +234,18 @@
|
||||
|
||||
|
||||
@media screen and (max-width: 639px) {
|
||||
.header {
|
||||
background: #262626;
|
||||
|
||||
.header-logo {
|
||||
width: 94px;
|
||||
height: 36px;
|
||||
|
||||
}
|
||||
|
||||
.header-popup {
|
||||
position: static;
|
||||
}
|
||||
.header-container {
|
||||
|
||||
.header {
|
||||
padding: 8px 10px;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,9 @@ import "./Header.css";
|
||||
import "styles/styles.css";
|
||||
|
||||
import logo from "./logoIcon.svg";
|
||||
import chevron from "./chevronIcon.svg";
|
||||
import ru from 'images/icons/RU.svg'
|
||||
import en from 'images/icons/EN.svg'
|
||||
|
||||
|
||||
import React, { CSSProperties, useState } from "react";
|
||||
import { useLocation } from "react-router-dom";
|
||||
@@ -16,110 +18,24 @@ export type THeader = {
|
||||
};
|
||||
|
||||
export const Header: React.FC = ({ }) => {
|
||||
const [open, setOpen] = useState<boolean>(false);
|
||||
const [menuOpen, setMenuOpen] = useState(false);
|
||||
const [opacity, setOpacity] = useState(false);
|
||||
const buttons = [{
|
||||
icon: ru, value: "ru"
|
||||
}, { icon: en, value: "en" }]
|
||||
const location = useLocation();
|
||||
|
||||
const { handleChangeLanguage } = languageSlice.actions;
|
||||
const { currentLang } = useAppSelector((state) => state.languageReducer);
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
function handleUpdateLanguage(value: string) {
|
||||
dispatch(handleChangeLanguage(value));
|
||||
setOpen((prev) => !prev);
|
||||
}
|
||||
|
||||
function handleOpen() {
|
||||
setOpen((prev) => !prev);
|
||||
}
|
||||
|
||||
function handleOpacity() {
|
||||
setOpacity(true);
|
||||
}
|
||||
|
||||
const style = {
|
||||
background: "rgba(235, 235, 235, 0.2",
|
||||
};
|
||||
|
||||
const iconTransform = {
|
||||
transform: "rotate(-90deg)",
|
||||
} as CSSProperties;
|
||||
|
||||
const setBackground = opacity && (!open as boolean);
|
||||
|
||||
function setOpacityAndMenu() {
|
||||
setMenuOpen(true);
|
||||
const targetElement = document.querySelector("body") as HTMLElement;
|
||||
targetElement.style.overflow = "hidden";
|
||||
}
|
||||
|
||||
function openMenu() {
|
||||
setMenuOpen(false);
|
||||
const targetElement = document.querySelector("body") as HTMLElement;
|
||||
targetElement.style.overflow = "visible";
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={
|
||||
location.pathname === "connect-page" ? "header" : "header-main"
|
||||
}
|
||||
>
|
||||
<div className="header-container">
|
||||
<a target='_blank' href="https://estate.graff.tech/" style={{cursor: "pointer"}}><img className="header-logo" alt="company-logo" src={logo} />
|
||||
</a>
|
||||
<div className="header-buttons">
|
||||
<div
|
||||
className={
|
||||
open
|
||||
? "header-lang-button header-lang-button_active"
|
||||
: "header-lang-button header-lang-button_disabled"
|
||||
}
|
||||
style={setBackground ? style : { background: "transparent" }}
|
||||
>
|
||||
<img
|
||||
alt="img"
|
||||
src={chevron}
|
||||
className="header-select__icon"
|
||||
style={
|
||||
open
|
||||
? iconTransform
|
||||
: {
|
||||
transform: "rotate(0deg)",
|
||||
}
|
||||
}
|
||||
></img>
|
||||
<div className="wrapper__button">
|
||||
<div
|
||||
onMouseEnter={handleOpacity}
|
||||
onMouseLeave={() => setOpacity(false)}
|
||||
onClick={handleOpen}
|
||||
className=" header-lang-button-picked"
|
||||
>
|
||||
{currentLang.toLocaleUpperCase()}
|
||||
</div>
|
||||
</div>
|
||||
{currentLang === "ru" ? (
|
||||
<button
|
||||
value={"en"}
|
||||
onClick={(e: any) => handleUpdateLanguage(e.target.value)}
|
||||
className="header-lang-button-text"
|
||||
>
|
||||
EN
|
||||
</button>
|
||||
) : (
|
||||
<button
|
||||
onClick={(e: any) => handleUpdateLanguage(e.target.value)}
|
||||
value={"ru"}
|
||||
className="header-lang-button-text"
|
||||
>
|
||||
RU
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<header className={location.pathname === '/' ? 'header' : 'header header-popup'}>
|
||||
<a className="header-logo" target='_blank' href="https://estate.graff.tech/" style={{ cursor: "pointer" }}><img alt="company-logo" src={logo} />
|
||||
</a>
|
||||
<div className="header-button-container">
|
||||
{buttons.map((item, index) => (<button key={index} onClick={() => dispatch(handleChangeLanguage(item.value))} value={item.value} className={currentLang === item.value ? 'button-lang button-lang-active' : "button-lang"}><img src={item.icon}></img></button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
};
|
||||
|
||||
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
@@ -0,0 +1,38 @@
|
||||
import { useState, useCallback } from 'react';
|
||||
|
||||
interface IForm {
|
||||
name: string;
|
||||
email: string
|
||||
}
|
||||
|
||||
export default function useFormWithValidation() {
|
||||
const [values, setValues] = useState<IForm>({
|
||||
name: "",
|
||||
email: ""
|
||||
});
|
||||
const [errors, setErrors] = useState<IForm>({
|
||||
name: "",
|
||||
email: ""
|
||||
});
|
||||
const [isValid, setIsValid] = useState<boolean>(false);
|
||||
|
||||
const handleChangeState = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const target = event.target;
|
||||
const name = target.name;
|
||||
const value = target.value;
|
||||
setValues({ ...values, [name]: value });
|
||||
setErrors({ ...errors, [name]: target.validationMessage });
|
||||
setIsValid(target.closest("form").checkValidity());
|
||||
};
|
||||
|
||||
const resetForm = useCallback(
|
||||
(newValues = { name: "", email: "" }, newIsValid = false) => {
|
||||
setValues(newValues);
|
||||
setErrors(newValues);
|
||||
setIsValid(newIsValid);
|
||||
},
|
||||
[setValues, setErrors, setIsValid]
|
||||
);
|
||||
|
||||
return { values, handleChangeState, errors, isValid, resetForm };
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
<svg width="20" height="13" viewBox="0 0 20 13" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1 13C0.447716 13 0 12.5523 0 12V1C0 0.447715 0.447715 0 1 0H6.82201C7.28827 0 7.66624 0.377978 7.66624 0.844238V0.844238C7.66624 1.3105 7.28827 1.68848 6.82201 1.68848H2.34491C2.06877 1.68848 1.84491 1.91233 1.84491 2.18848V5.14941C1.84491 5.42556 2.06877 5.64941 2.34491 5.64941H6.42515C6.88966 5.64941 7.26621 6.02597 7.26621 6.49048V6.49048C7.26621 6.95499 6.88966 7.33154 6.42515 7.33154H2.34491C2.06877 7.33154 1.84491 7.5554 1.84491 7.83154V10.8115C1.84491 11.0877 2.06877 11.3115 2.34491 11.3115H6.89365C7.35991 11.3115 7.73789 11.6895 7.73789 12.1558V12.1558C7.73789 12.622 7.35991 13 6.89365 13H1Z" fill="#F2F2F2"/>
|
||||
<path d="M19.0865 0C19.591 0 20 0.408988 20 0.913501V12C20 12.5523 19.5523 13 19 13H18.8462C18.5082 13 18.193 12.8293 18.0085 12.5461L12.1107 3.49922C12.0972 3.47838 12.074 3.46582 12.0491 3.46582V3.46582C12.0085 3.46582 11.9755 3.49876 11.9755 3.5394V12.0775C11.9755 12.587 11.5625 13 11.0531 13V13C10.5436 13 10.1306 12.587 10.1306 12.0775V1C10.1306 0.447715 10.5783 0 11.1306 0H11.2963C11.6343 0 11.9495 0.170802 12.1341 0.454032L18.0378 9.51347C18.0514 9.53431 18.0746 9.54687 18.0994 9.54687V9.54687C18.1401 9.54687 18.173 9.51394 18.173 9.4733V0.913501C18.173 0.408988 18.582 0 19.0865 0V0Z" fill="#F2F2F2"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1,4 @@
|
||||
<svg width="20" height="13" viewBox="0 0 20 13" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0.897734 12.7877C0.401929 12.7877 0 12.3858 0 11.89V0.999999C0 0.447714 0.447715 0 1 0H4.24172C5.16366 0 5.92872 0.170669 6.5369 0.512008C7.14894 0.853346 7.60604 1.32581 7.90819 1.92939C8.21034 2.52882 8.36142 3.2219 8.36142 4.00865C8.36142 4.79123 8.20841 5.48015 7.90238 6.07541C7.60023 6.66651 7.14313 7.12648 6.53109 7.45533C5.92291 7.78418 5.15785 7.94861 4.23591 7.94861H1.85311C1.39447 7.94861 1.02266 7.5768 1.02266 7.11816C1.02266 6.65951 1.39447 6.2877 1.85311 6.2877H4.07321C4.65427 6.2877 5.12686 6.19821 5.49099 6.01921C5.859 5.84022 6.12822 5.58005 6.29866 5.23871C6.46911 4.89737 6.55433 4.48735 6.55433 4.00865C6.55433 3.52578 6.46717 3.10743 6.29285 2.7536C6.12241 2.39978 5.85319 2.1292 5.48518 1.94188C5.12105 1.7504 4.64265 1.65466 4.04997 1.65466H2.29547C2.01933 1.65466 1.79547 1.87852 1.79547 2.15466V11.89C1.79547 12.3858 1.39354 12.7877 0.897734 12.7877ZM5.32848 7.01825C5.66354 7.01825 5.97028 7.20621 6.12241 7.50474L8.14113 11.4661C8.44931 12.0708 8.01003 12.7877 7.3313 12.7877C6.9869 12.7877 6.67209 12.5931 6.51818 12.285L4.53132 8.30754C4.23536 7.71508 4.66621 7.01825 5.32848 7.01825Z" fill="#F2F2F2"/>
|
||||
<path d="M18.1987 0.900639C18.1987 0.403229 18.602 0 19.0994 0C19.5968 0 20 0.40323 20 0.900639V8.41066C20 9.30564 19.8044 10.0986 19.4131 10.7896C19.0219 11.4765 18.4718 12.0176 17.7629 12.4131C17.054 12.8044 16.2231 13 15.2702 13C14.3211 13 13.4922 12.8044 12.7833 12.4131C12.0744 12.0176 11.5243 11.4765 11.1331 10.7896C10.7418 10.0986 10.5462 9.30564 10.5462 8.41066V0.897733C10.5462 0.401929 10.9481 0 11.4439 0C11.9397 0 12.3417 0.401929 12.3417 0.897734V8.25456C12.3417 8.83317 12.4598 9.34726 12.6961 9.79683C12.9363 10.2464 13.2752 10.6002 13.713 10.8583C14.1507 11.1122 14.6698 11.2392 15.2702 11.2392C15.8745 11.2392 16.3955 11.1122 16.8332 10.8583C17.2748 10.6002 17.6119 10.2464 17.8443 9.79683C18.0806 9.34726 18.1987 8.83317 18.1987 8.25456V0.900639Z" fill="#F2F2F2"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
@@ -1,3 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M7.99984 7.99995L14.666 14.6666M7.99984 7.99995L14.6665 1.33331M7.99984 7.99995L1.33317 14.6666M7.99984 7.99995L1.3332 1.33331" stroke="white" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12 12L16.9996 17M12 12L17 7M12 12L7 17M12 12L7.00002 7" stroke="#C5C7CE" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 304 B After Width: | Height: | Size: 252 B |
@@ -48,16 +48,16 @@ button {
|
||||
@media screen and (max-width: 1024px) {
|
||||
.main {
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
gap: 0;
|
||||
margin: 0 12px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 920px) {
|
||||
.main {
|
||||
width: 100%;
|
||||
gap: 0;
|
||||
padding: 0 20px;
|
||||
margin: 0 auto;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,25 +1,11 @@
|
||||
export interface ICards {
|
||||
_id: string;
|
||||
description: {
|
||||
en: string;
|
||||
ru: string;
|
||||
};
|
||||
description_second?: {
|
||||
en: string;
|
||||
ru: string;
|
||||
};
|
||||
image: {
|
||||
logo: string;
|
||||
perview: string;
|
||||
};
|
||||
location: {
|
||||
en: string;
|
||||
ru: string;
|
||||
};
|
||||
app_title: string;
|
||||
title: string;
|
||||
|
||||
title_full: {
|
||||
en: string;
|
||||
ru: string;
|
||||
};
|
||||
language: string;
|
||||
location: string;
|
||||
feature_description: string;
|
||||
icon: string;
|
||||
logo: string;
|
||||
preview: string;
|
||||
_id: string;
|
||||
}
|
||||
|
||||
@@ -1,29 +1,38 @@
|
||||
import { createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import MainApi from "../../utils/api";
|
||||
const api = new MainApi("https://a1.coord.graff.tech");
|
||||
import axios from 'axios';
|
||||
|
||||
const instance = axios.create({
|
||||
baseURL: 'https://a1.test.coord.graff.tech',
|
||||
});
|
||||
|
||||
instance.defaults.headers.post['Content-Type'] = 'application/json';
|
||||
|
||||
|
||||
|
||||
export const fetchCards = createAsyncThunk(
|
||||
"cards/FetchAll",
|
||||
async (_, thunkAPI) => {
|
||||
async (language: string, thunkAPI) => {
|
||||
try {
|
||||
const response = await api.getRC();
|
||||
return response;
|
||||
} catch (e) {
|
||||
return thunkAPI.rejectWithValue("Нет доступных демонстраций");
|
||||
const { data } = await instance.get('/title/get_for_language/', { params: { start: 0, count: 100, language: language } });
|
||||
return data;
|
||||
} catch (e: any) {
|
||||
const { response } = e
|
||||
return thunkAPI.rejectWithValue(response.data.message);
|
||||
}
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
export const createSession = createAsyncThunk(
|
||||
"session/Create",
|
||||
async (title: string, thunkApi) => {
|
||||
try {
|
||||
const response = await api.createSession(title);
|
||||
return response;
|
||||
const { data } = await instance.post('/session/create', { title });
|
||||
return data;
|
||||
} catch (e: any) {
|
||||
console.log(e)
|
||||
return thunkApi.rejectWithValue(e);
|
||||
const { response } = e
|
||||
return thunkApi.rejectWithValue(response.data.message);
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -32,10 +41,11 @@ export const connectSession = createAsyncThunk(
|
||||
"session/Connect",
|
||||
async (code: string, thunkApi) => {
|
||||
try {
|
||||
const response = await api.connectSession(code);
|
||||
return response;
|
||||
} catch (e) {
|
||||
return thunkApi.rejectWithValue('Error');
|
||||
const { data } = await instance.get('/session/connect', { params: { session_id: code } });
|
||||
return data;
|
||||
} catch (e: any) {
|
||||
const { response } = e
|
||||
return thunkApi.rejectWithValue(response.data.message);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
|
||||
import i18next from "i18next";
|
||||
import cookies from "js-cookie";
|
||||
|
||||
|
||||
interface LanguageState {
|
||||
currentLang: string;
|
||||
}
|
||||
|
||||
const initialState: LanguageState = {
|
||||
currentLang: '',
|
||||
currentLang: cookies.get("i18next"),
|
||||
};
|
||||
|
||||
export const languageSlice = createSlice({
|
||||
|
||||
@@ -10,6 +10,11 @@ interface IState {
|
||||
isDone: boolean;
|
||||
}
|
||||
|
||||
interface IForm {
|
||||
name: string,
|
||||
value: string | number
|
||||
}
|
||||
|
||||
export interface planState {
|
||||
time: Moment;
|
||||
isCalendar: boolean;
|
||||
@@ -18,10 +23,12 @@ export interface planState {
|
||||
isDone: boolean;
|
||||
email: string;
|
||||
name: string;
|
||||
currTime: Moment | null
|
||||
}
|
||||
|
||||
const initialState: planState = {
|
||||
time: moment.default(),
|
||||
currTime: null,
|
||||
isCalendar: true,
|
||||
isTimepicker: false,
|
||||
isForm: false,
|
||||
@@ -42,8 +49,9 @@ export const planSlice = createSlice({
|
||||
},
|
||||
|
||||
handleTimeValue(state, action: PayloadAction<Moment>) {
|
||||
state.time = action.payload;
|
||||
state.currTime = action.payload;
|
||||
},
|
||||
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -130,4 +130,10 @@ h3 {
|
||||
font-size: 38px;
|
||||
line-height: 100%;
|
||||
color: #F2F2F2;
|
||||
}
|
||||
|
||||
.button-primary:disabled {
|
||||
cursor: default;
|
||||
pointer-events: none;
|
||||
opacity: 0.5;
|
||||
}
|
||||