source: frontend/src/FrontPage.js@ 13f1472

Last change on this file since 13f1472 was 13f1472, checked in by Danilo <danilo.najkov@…>, 22 months ago

vip functionallity + menu fields + alergens filtering + google/fb login + email queueing

  • Property mode set to 100644
File size: 10.0 KB
Line 
1import React, {useState, useEffect} from 'react'
2import {Header} from "./Header";
3import {Link, useNavigate} from "react-router-dom";
4import {Button, Card, DatePicker, Form, Image, Input, Modal, notification, Rate, Spin, Upload} from "antd";
5import placeholderImage from '../src/Assets/placeholder.png'
6import AddNewReservation from "./Dashboard/AddNewReservation";
7import axios from "axios";
8import env from "./env";
9import Review from "./Dashboard/Review";
10import {PlusOutlined} from "@ant-design/icons";
11
12const FrontPage = ({user, logout}) => {
13 const [restaurant, setRestaurant] = useState({name:'Sample Restaurant name', address: 'Sample street 1', city:'Sample'});
14 const [newReservationModal, setNewReservationModal] = useState(false);
15 const [saveModalLoading, setSaveModalLoading] = useState(false);
16 const [newReviewModal, setNewReviewModal] = useState(false);
17 const [loading, setLoading] = useState(true);
18 const [refreshToggle, setRefreshToggle] = useState(false);
19 const history = useNavigate();
20 const [filteredMenuItems, setFilteredMenuItems] = useState([]);
21
22 useEffect(()=>{
23 setLoading(true);
24 axios.get(env.api + 'Restaurants').then(res=>{
25 setRestaurant(res.data);
26 console.log(user);
27 if(!user || !user.isVip){
28 setFilteredMenuItems(res.data.menu.filter(x => !x.isVipOnly));
29 }else{
30 setFilteredMenuItems(res.data.menu.sort((x,y) => x.isVipOnly ? -1 : 1));
31 }
32 setLoading(false);
33 });
34 },[user])
35
36 useEffect(()=>{
37 if(user && !user.isConfirmed) {
38 notification['warning']({
39 message: <p>Вашиот емаил не е потврден. <a href={'/confirm-email'}>Потврдете го тука</a></p>
40 });
41 }
42 },[user])
43
44 const updateSearchValue = (value) => {
45 const val = value.target.value.toLowerCase();
46 setFilteredMenuItems(items=>{
47 if(val.length==0){
48 return restaurant.menu;
49 }
50 const its = val.split(' ');
51 let allItems = []
52 if(!user || !user.isVip){
53 allItems = [...restaurant.menu.filter(x => !x.isVipOnly)]
54 }else{
55 allItems = [...restaurant.menu.sort(x => x.isVipOnly)]
56 }
57 for(let it of its){
58 if(it.length>0)
59 allItems = allItems.filter(x => !x.alergens.includes(it));
60 }
61 return allItems;
62 })
63 }
64
65 const saveNewReview = data =>{
66 setSaveModalLoading(true)
67 axios.post(env.api + 'Reviews',data,{ headers: {Authorization: localStorage.getItem('Auth')}}).then(res=>{
68 setNewReviewModal(false)
69 setSaveModalLoading(false)
70 notification['success']({
71 message: 'Успешно зачувано',
72 });
73 setRefreshToggle(ref => !ref);
74 }).catch(err=>{
75 setSaveModalLoading(false)
76 notification['error']({
77 message: 'Се случи проблем при зачувување',
78 });
79 });
80 }
81
82 return(
83 <div>
84 <Header onClickButton={!user?()=>history('/login'):logout} buttonText={!user?'Најави се':'Одјави се'} isVip={user && user.isVip}/>
85 {loading ? <Spin style={{margin: 20}}/> :
86 <div style={{
87 height: '400px',
88 width: '100%',
89 borderTop: '1px solid gray',
90 padding: '20px'
91 }}>
92 <div id={'businessFrontImage'}>
93 <Image
94 src={restaurant.base64Image}
95 id={'businessFrontInsideImage'}
96 placeholder={
97 <img
98 src={placeholderImage}
99 alt={'place'}
100 style={{width: '100%', height: '100%'}}
101 />
102 }
103 wrapperStyle={{overflow: 'hidden', width: '100%'}}
104 style={{width: '100%', height: '100%', margin: 'auto', objectFit: 'cover'}}>
105 </Image>
106 </div>
107 <div id={'businessFrontInfo'}>
108 <div style={{
109 width: '100%',
110 height: '100%',
111 display: 'flex',
112 flexDirection: 'column',
113 justifyContent: 'space-between'
114 }}>
115 <div style={{flexGrow: 1, fontSize: '20px', fontWeight: '500', textAlign: 'start'}}>
116 {restaurant.name}
117 <div style={{
118 color: 'gray',
119 fontSize: '10px'
120 }}>{restaurant.address}, {restaurant.phone}</div>
121 </div>
122 <Button onClick={() => setNewReservationModal(true)}
123 style={{width: '100%', marginTop: '5px'}} type={'primary'}>Резервирај</Button>
124 </div>
125
126 </div>
127 <div style={{textAlign: 'start', backgroundColor: '#F2F2F2'}}>
128 <div style={{
129 width: '100%',
130 height:'75px',
131 backgroundColor: 'white',
132 padding: '20px',
133 border: '1px solid lightgray'
134 }} >
135 <h2 style={{float: 'left'}}>Мени</h2>
136 <Input.Search onChange={updateSearchValue} placeholder={'Филтрирај алергени'} style={{float:'right', width:'200px'}}/>
137 </div>
138 {filteredMenuItems.map(el =>
139 <Card
140 key={el.id}
141 title={el.title}
142 extra={el.isVipOnly ? <span style={{color:'orange',fontWeight:'bold'}}>VIP </span>:''}
143 style={{ width: 280, display:'inline-block', margin:'10px',verticalAlign:'middle' }}
144 size="small"
145 cover={el.image != "data:image/png;base64," ? <img style={{cursor: 'pointer'}} src={el.image} alt="avatar"
146 height='100px' width={'270px'}/> : ''}
147 >
148 <p>{el.description}</p>
149 <p>Алергени: {el.alergens.length ==0 ? 'Нема' : el.alergens}</p>
150 <b>{el.price} ден.</b>
151 </Card>
152 )}
153 <Review user={user} front refresh={refreshToggle} setVisible={setNewReviewModal}/>
154 </div>
155 </div>
156 }
157 <Modal
158 style={{top: 20}}
159 width={'700px'}
160 title="Нова Резервација"
161 footer={[
162 <Button form="newResForm" key="submit" htmlType="submit" type={'primary'} loading={saveModalLoading}>
163 Прати
164 </Button>
165 ]}
166 onCancel={()=>setNewReservationModal(false)}
167 visible={newReservationModal}>
168 <AddNewReservation setModalSaveLoading={setSaveModalLoading} setModalVisible={setNewReservationModal} />
169 </Modal>
170 <Modal
171 style={{top: 20}}
172 width={'700px'}
173 title="Нова оценка"
174 footer={[
175 <Button form="newReviewForm" key="submit" htmlType="submit" type={'primary'} loading={saveModalLoading}>
176 Прати
177 </Button>
178 ]}
179 onCancel={()=>setNewReviewModal(false)}
180 visible={newReviewModal}>
181 <Form onFinish={saveNewReview}
182 id={'newReviewForm'}
183 onFinishFailed={()=>
184 notification['error']({
185 message: 'Ве молиме поправете ги сите грешки пред зачувување!',
186 })}>
187 <Form.Item
188 label="Наслов"
189 name="title"
190 rules={[
191 {
192 required: true,
193 message: 'Ве молиме внесете наслов!',
194 },
195 ]}
196 >
197 <Input/>
198 </Form.Item>
199 <Form.Item
200 label="Опис"
201 name="description"
202 rules={[
203 {
204 required: true,
205 message: 'Ве молиме внесете опис!',
206 },
207 ]}
208 >
209 <Input.TextArea rows={4}/>
210 </Form.Item>
211 <Form.Item
212 label="Оценка"
213 name="stars"
214 rules={[
215 {
216 required: true,
217 message: 'Ве молиме внесете оценка!',
218 },
219 ]}
220 >
221 <Rate/>
222 </Form.Item>
223 </Form>
224 </Modal>
225 </div>
226 )
227}
228export default FrontPage;
Note: See TracBrowser for help on using the repository browser.