Skip to content

Commit

Permalink
Добавил:
Browse files Browse the repository at this point in the history
- Карточку с персональным предложением
- Возможность зумить и рассматривать фотографии
- Модальное окно
Изменил:
- Карусель с фотографиями
Подключил:
- react-zoom-pan-pinch (для просмотра фотографий)
  • Loading branch information
FotuneGame committed Jan 5, 2024
1 parent 652d725 commit 9ad7dd7
Show file tree
Hide file tree
Showing 10 changed files with 165 additions and 16 deletions.
14 changes: 14 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"react-icons": "^4.12.0",
"react-router-dom": "^6.21.1",
"react-scripts": "5.0.1",
"react-zoom-pan-pinch": "^3.3.0",
"web-vitals": "^2.1.4"
},
"scripts": {
Expand Down
9 changes: 9 additions & 0 deletions src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,12 @@
.content {
min-height: calc(100vh - 80px);
}

@media only screen and (max-width: 371px){
h1{
font-size: 14px;
}
p{
font-size: 12px;
}
}
47 changes: 47 additions & 0 deletions src/component/PersonalityOrder/PersonalityOrder.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import React, {useState} from 'react';
import {FaArrowCircleRight} from 'react-icons/fa';

const PersonalityOrder = (props) => {

const [message,setMessage] = useState({name:"",phone:"",date:"",time:"",text:""});

const sendMessage = (e)=>{
e.preventDefault();
if(message.name.length>128 || message.text.length > 1024){
alert("Слишком много символов в имене (>128) или в сообщении (>1024)");
return;
}
console.log(message); //Место вызова к серверу
setMessage({name:"",phone:"",date:"",time:"",text:""});
alert("Сообщение отправлено");
}

return (
<div className="container shadow d-grid align-content-center p-3 mt-3">
<h1 className="row mx-1 mb-2">{props?.title}</h1>
<div className="row">
<form method="POST" className="d-grid ">
<div className="row">
<div className="col-12 col-lg-6 mt-2">
<input className="form-control mt-1" value={message.name} type="text" maxLength="128" placeholder="Имя" onChange={(e)=>setMessage({...message,name:e.target.value})}/>
<input className="form-control mt-1" value={message.phone} type="phone" placeholder="Телефон" onChange={(e)=>setMessage({...message,phone:e.target.value})}/>
<div className="d-flex justify-content-between">
<input className="form-control mt-2 me-2" value={message.date} type="date" placeholder="дд.мм.гггг" onChange={(e)=>setMessage({...message,date:e.target.value})}/>
<input className="form-control mt-2" value={message.time} type="time" placeholder="чч.мм" onChange={(e)=>setMessage({...message,time:e.target.value})}/>
</div>
</div>
<div className="col-12 col-lg-6 mt-2 align-content-around">
<textarea cols="60" rows="5" className="form-control" value={message.text} maxLength="1024" placeholder="Сообщение" onChange={(e)=>setMessage({...message,text:e.target.value})}/>
<button className="btn btn-success my-2 float-end w-50 text-start" onClick={(e)=>sendMessage(e)}>
Отправить
<FaArrowCircleRight className="float-end" size="1.5rem" color="white"/>
</button>
</div>
</div>
</form>
</div>
</div>
);
};

export default PersonalityOrder;
28 changes: 18 additions & 10 deletions src/component/carousel/Carousel.jsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
import React from 'react';
import React, {useState} from 'react';
import {Carousel as CarouselB} from "react-bootstrap"
import ModuleImg from '../modal/Modal';
import Wrapper from "./wrapper/Wrapper";

const Carousel = ({imgs}) => {
const [modalVisible,setModalVisible]=useState(false);

const Carousel = (props) => {
return (
<CarouselB>
{props.imgs
? props.imgs.map((path,index) =>
<CarouselB.Item key={path+index} >
<img className="img-fluid rounded" src={path}/>
</CarouselB.Item>)
:null}
</CarouselB>
<ModuleImg visible={modalVisible} setVisible={setModalVisible}>
<CarouselB interval={null}>
{imgs
? imgs.map((path,index) =>
<CarouselB.Item key={path+index}>
{modalVisible ? <Wrapper setModalVisible={setModalVisible}><img className="img-fluid rounded" src={path}/></Wrapper>
: <img className="img-fluid rounded" src={path}
onClick={() => setModalVisible(true)}/>
}
</CarouselB.Item>)
:null}
</CarouselB>
</ModuleImg>
);
};

Expand Down
35 changes: 35 additions & 0 deletions src/component/carousel/wrapper/Wrapper.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React from 'react';
import {TransformWrapper, TransformComponent, useControls} from "react-zoom-pan-pinch";
import {FaSearchMinus, FaSearchPlus, FaTimes,FaHistory} from "react-icons/fa";

const Wrapper = ({children,setModalVisible}) => {

const Controls = () => {
const { zoomIn, zoomOut,resetTransform} = useControls();
return (
<div className="position-absolute top-0 end-0 z-3">
<div className=" d-flex justify-content-center">
<div className="col-4 m-0 p-0" onClick={()=>setModalVisible(false)}></div>
<button className="btn bg-transparent px-2 mx-0" onClick={() => zoomIn()}><FaSearchPlus size="1.5rem" color="white"/></button>
<button className="btn bg-transparent px-2 mx-0" onClick={() => zoomOut()}><FaSearchMinus size="1.5rem" color="white"/></button>
<button className="btn bg-transparent px-2 mx-0" onClick={() => resetTransform()}><FaHistory size="1.5rem" color="white"/></button>
<button className="btn bg-transparent px-2 mx-0" onClick={()=>setModalVisible(false)}>
<FaTimes size="2rem" color="white"/>
</button>
<div className="col-4 m-0 p-0" onClick={()=>setModalVisible(false)}></div>
</div>
</div>
);
};

return (
<TransformWrapper>
<Controls/>
<TransformComponent>
{children}
</TransformComponent>
</TransformWrapper>
);
};

export default Wrapper;
16 changes: 16 additions & 0 deletions src/component/modal/Modal.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from 'react';
import style from './Modal.module.css';

const Modal = ({children,visible,setVisible}) => {

const modalClass = [];
if(visible)modalClass.push(style.active);

return (
<div className={modalClass.join(' ')} onClick={()=>setVisible(false)}>
<div className={style.content} onClick={(e)=>e.stopPropagation()}>{children}</div>
</div>
);
};

export default Modal;
17 changes: 17 additions & 0 deletions src/component/modal/Modal.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.active{
position: fixed;
top:0px;
left: 0px;
right: 0px;
bottom: 0px;
background: rgba(0,0,0,0.75);
z-index: 3;
display: flex;
justify-content: center;
align-items: center;
padding: 3rem;
}

.content{
display: grid;
}
4 changes: 3 additions & 1 deletion src/page/About.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import React from 'react';
import {FaPhoneAlt,FaEnvelope} from "react-icons/fa";
import PersonalityOrder from "../component/PersonalityOrder/PersonalityOrder";

const About = () => {
return (
<div className="content pt-5">
<div className="content mt-2 pt-5">
<div className="container shadow d-grid align-content-center p-3">
<div className="row">
<div className="col-12 py-3 col-lg-6 py-lg-0 align-self-center">
Expand All @@ -30,6 +31,7 @@ const About = () => {
</div>
</div>
</div>
<PersonalityOrder title="ПОЛУЧИТЬ ПЕРСОНАЛЬНОЕ ПРЕДЛОЖЕНИЕ"/>
</div>
);
};
Expand Down
10 changes: 5 additions & 5 deletions src/page/Buffet.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,24 @@ import {FaFilePdf} from "react-icons/fa";
const Buffet = () => {
return (
<div className="content mt-2 pt-5">
<div className="container shadow d-grid align-content-center p-3">
<div className="container shadow d-grid align-content-center p-lg-3">
<div className="row">
<div className="col-12 py-3 col-lg-6 py-lg-0 align-self-center">
<Carousel imgs={["./img/page/main.jpg","./img/page/main.jpg"]}/>
</div>
<div className="col-12 py-3 col-lg-6 py-lg-0">
<h1>МОБИЛЬНЫЙ ФУРШЕТ</h1>
<p>В долгой водной прогулке незаменим мобильный фуршет, заказанный и приготовленный специально для Вас. Кейтеринг предоставляет разнообразное меню: от антипасти до сета круассанов, от канапе из морских продуктов до ассорти из твёрдого сыра с виноградом, орехами и мёдом. Все блюда готовятся непосредственно перед доставкой на борт и доставляются за 10-15 минут до начала рейса в специальных рефрижераторных автомобилях, что гарантирует их свежесть и высокие вкусовые качества.</p>
<div className="d-flex py-3 py-lg-0 justify-content-around">
<div className="mx-1 row ">
<div className="d-grid d-lg-flex py-3 py-lg-0 justify-content-around">
<div className="mx-1 row py-2">
<FaFilePdf size="2rem" color="black" />
<a className="text-black text-center" href="#" >Мобильный фуршет</a>
</div>
<div className="mx-1 row">
<div className="mx-1 row py-2">
<FaFilePdf size="2rem" color="black" />
<a className="text-black text-center" href="#">Фуршетное меню</a>
</div>
<div className="mx-1 row">
<div className="mx-1 row py-2">
<FaFilePdf size="2rem" color="black" />
<a className="text-black text-center" href="#">Банкетное меню</a>
</div>
Expand Down

0 comments on commit 9ad7dd7

Please sign in to comment.