[cc4db18] | 1 | import React, {useState, useEffect} from 'react'
|
---|
[d76b7ee] | 2 | import {Header} from "./Header";
|
---|
[a26f6a1] | 3 | import {Link, useNavigate} from "react-router-dom";
|
---|
[13f1472] | 4 | import {Button, Card, DatePicker, Form, Image, Input, Modal, notification, Rate, Spin, Upload} from "antd";
|
---|
[d76b7ee] | 5 | import placeholderImage from '../src/Assets/placeholder.png'
|
---|
| 6 | import AddNewReservation from "./Dashboard/AddNewReservation";
|
---|
[cc4db18] | 7 | import axios from "axios";
|
---|
| 8 | import env from "./env";
|
---|
[899b19d] | 9 | import Review from "./Dashboard/Review";
|
---|
[13f1472] | 10 | import {PlusOutlined} from "@ant-design/icons";
|
---|
[d76b7ee] | 11 |
|
---|
[899b19d] | 12 | const FrontPage = ({user, logout}) => {
|
---|
[d76b7ee] | 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);
|
---|
[899b19d] | 16 | const [newReviewModal, setNewReviewModal] = useState(false);
|
---|
[cc4db18] | 17 | const [loading, setLoading] = useState(true);
|
---|
[899b19d] | 18 | const [refreshToggle, setRefreshToggle] = useState(false);
|
---|
[d76b7ee] | 19 | const history = useNavigate();
|
---|
[13f1472] | 20 | const [filteredMenuItems, setFilteredMenuItems] = useState([]);
|
---|
[cc4db18] | 21 |
|
---|
| 22 | useEffect(()=>{
|
---|
| 23 | setLoading(true);
|
---|
| 24 | axios.get(env.api + 'Restaurants').then(res=>{
|
---|
| 25 | setRestaurant(res.data);
|
---|
[13f1472] | 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 | }
|
---|
[cc4db18] | 32 | setLoading(false);
|
---|
| 33 | });
|
---|
[13f1472] | 34 | },[user])
|
---|
[cc4db18] | 35 |
|
---|
[a26f6a1] | 36 | useEffect(()=>{
|
---|
| 37 | if(user && !user.isConfirmed) {
|
---|
| 38 | notification['warning']({
|
---|
| 39 | message: <p>Вашиот емаил не е потврден. <a href={'/confirm-email'}>Потврдете го тука</a></p>
|
---|
| 40 | });
|
---|
| 41 | }
|
---|
| 42 | },[user])
|
---|
| 43 |
|
---|
[13f1472] | 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 |
|
---|
[899b19d] | 65 | const saveNewReview = data =>{
|
---|
| 66 | setSaveModalLoading(true)
|
---|
[a26f6a1] | 67 | axios.post(env.api + 'Reviews',data,{ headers: {Authorization: localStorage.getItem('Auth')}}).then(res=>{
|
---|
[899b19d] | 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 |
|
---|
[d76b7ee] | 82 | return(
|
---|
| 83 | <div>
|
---|
[13f1472] | 84 | <Header onClickButton={!user?()=>history('/login'):logout} buttonText={!user?'Најави се':'Одјави се'} isVip={user && user.isVip}/>
|
---|
[cc4db18] | 85 | {loading ? <Spin style={{margin: 20}}/> :
|
---|
[d76b7ee] | 86 | <div style={{
|
---|
| 87 | height: '400px',
|
---|
| 88 | width: '100%',
|
---|
| 89 | borderTop: '1px solid gray',
|
---|
| 90 | padding: '20px'
|
---|
| 91 | }}>
|
---|
[cc4db18] | 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>
|
---|
[d76b7ee] | 106 | </div>
|
---|
[cc4db18] | 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>
|
---|
[d76b7ee] | 125 |
|
---|
[cc4db18] | 126 | </div>
|
---|
| 127 | <div style={{textAlign: 'start', backgroundColor: '#F2F2F2'}}>
|
---|
[899b19d] | 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>
|
---|
[13f1472] | 136 | <Input.Search onChange={updateSearchValue} placeholder={'Филтрирај алергени'} style={{float:'right', width:'200px'}}/>
|
---|
[899b19d] | 137 | </div>
|
---|
[13f1472] | 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 | >
|
---|
[cc4db18] | 148 | <p>{el.description}</p>
|
---|
[13f1472] | 149 | <p>Алергени: {el.alergens.length ==0 ? 'Нема' : el.alergens}</p>
|
---|
[cc4db18] | 150 | <b>{el.price} ден.</b>
|
---|
| 151 | </Card>
|
---|
| 152 | )}
|
---|
[899b19d] | 153 | <Review user={user} front refresh={refreshToggle} setVisible={setNewReviewModal}/>
|
---|
[cc4db18] | 154 | </div>
|
---|
[d76b7ee] | 155 | </div>
|
---|
[cc4db18] | 156 | }
|
---|
[d76b7ee] | 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>
|
---|
[899b19d] | 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>
|
---|
[d76b7ee] | 225 | </div>
|
---|
| 226 | )
|
---|
| 227 | }
|
---|
| 228 | export default FrontPage; |
---|