Changeset 899b19d
- Timestamp:
- 07/10/22 10:27:45 (2 years ago)
- Branches:
- master
- Children:
- a26f6a1
- Parents:
- cc4db18
- Files:
-
- 8 added
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
frontend/src/App.js
rcc4db18 r899b19d 1 1 import './App.css'; 2 import {Route, BrowserRouter as Router, Navigate, Routes } from "react-router-dom";2 import {Route, BrowserRouter as Router, Navigate, Routes, useNavigate} from "react-router-dom"; 3 3 import axios from 'axios' 4 4 import env from './env' … … 12 12 import Restaurant from "./Dashboard/Restaurant"; 13 13 import Menu from "./Dashboard/Menu"; 14 import Review from "./Dashboard/Review"; 14 15 15 16 16 17 function App() { 17 const [user, setUser] = useState( false)18 const [user, setUser] = useState(undefined) 18 19 const [loading, setLoading] = useState(false) 19 20 useEffect(()=>{ … … 29 30 }) 30 31 } 32 const logout = () => { 33 setUser(undefined); 34 sessionStorage.removeItem('Auth'); 35 window.location.replace('/') 36 } 31 37 return ( 32 38 <div style={{textAlign:'center'}}> 33 39 <Router> 34 40 <Routes> 35 <Route path="/dashboard" element={loading ? <Spin /> : user ? <Dashboard setUser={setUser}/>: <Navigate to="/login" replace={true} />}>41 <Route path="/dashboard" element={loading ? <Spin /> : user ? (user.isAdmin ? <Dashboard setUser={setUser}/> : <Navigate to="/" replace={true} />) : <Navigate to="/login" replace={true} />}> 36 42 <Route path="/dashboard" element={<Restaurant/>}/> 37 43 <Route path="/dashboard/menu" element={<Menu/>}/> 38 44 <Route path="/dashboard/reservations" element={<Reservations/>}/> 39 <Route path="/dashboard/reviews" element={ 'reviews'}/>45 <Route path="/dashboard/reviews" element={<Review/>}/> 40 46 <Route path="/dashboard/todo" element={'todo'}/> 41 47 </Route> 42 48 <Route path="/login" element={loading ? <Spin /> : !user ? <Login setUser={setUser}/> : <Navigate to="/dashboard" replace={true} />}/> 43 49 <Route path="/register" element={loading ? <Spin /> : !user ? <Register setUser={setUser}/> : <Navigate to="/dashboard" replace={true} />}/> 44 <Route path="/" element={<FrontPage />}/>50 <Route path="/" element={<FrontPage user={user} logout={logout}/>}/> 45 51 </Routes> 46 52 </Router> -
frontend/src/FrontPage.js
rcc4db18 r899b19d 2 2 import {Header} from "./Header"; 3 3 import {useNavigate} from "react-router-dom"; 4 import {Button, Card, Image, Modal, Spin} from "antd";4 import {Button, Card, DatePicker, Form, Image, Input, Modal, notification, Rate, Spin} from "antd"; 5 5 import placeholderImage from '../src/Assets/placeholder.png' 6 6 import AddNewReservation from "./Dashboard/AddNewReservation"; 7 7 import axios from "axios"; 8 8 import env from "./env"; 9 import Review from "./Dashboard/Review"; 9 10 10 const FrontPage = ({ }) => {11 const FrontPage = ({user, logout}) => { 11 12 const [restaurant, setRestaurant] = useState({name:'Sample Restaurant name', address: 'Sample street 1', city:'Sample'}); 12 13 const [newReservationModal, setNewReservationModal] = useState(false); 13 14 const [saveModalLoading, setSaveModalLoading] = useState(false); 15 const [newReviewModal, setNewReviewModal] = useState(false); 14 16 const [loading, setLoading] = useState(true); 17 const [refreshToggle, setRefreshToggle] = useState(false); 15 18 const history = useNavigate(); 16 19 … … 23 26 },[]) 24 27 28 const saveNewReview = data =>{ 29 setSaveModalLoading(true) 30 axios.post(env.api + 'Reviews',data,{ headers: {Authorization: sessionStorage.getItem('Auth')}}).then(res=>{ 31 setNewReviewModal(false) 32 setSaveModalLoading(false) 33 notification['success']({ 34 message: 'Успешно зачувано', 35 }); 36 setRefreshToggle(ref => !ref); 37 }).catch(err=>{ 38 setSaveModalLoading(false) 39 notification['error']({ 40 message: 'Се случи проблем при зачувување', 41 }); 42 }); 43 } 44 25 45 return( 26 46 <div> 27 <Header onClickButton={ ()=>history('/login')} buttonText={'Логирајсе'}/>47 <Header onClickButton={!user?()=>history('/login'):logout} buttonText={!user?'Најави се':'Одјави се'}/> 28 48 {loading ? <Spin style={{margin: 20}}/> : 29 49 <div style={{ … … 69 89 </div> 70 90 <div style={{textAlign: 'start', backgroundColor: '#F2F2F2'}}> 71 <h2 style={{textAlign:'center',paddingTop:'20px'}}>Мени</h2> 91 <div style={{ 92 width: '100%', 93 height:'75px', 94 backgroundColor: 'white', 95 padding: '20px', 96 border: '1px solid lightgray' 97 }} > 98 <h2 style={{float: 'left'}}>Мени</h2> 99 </div> 72 100 {restaurant.menu.map(el => 73 <Card title={el.title} style={{ width: 280, display:'inline-block', margin:'10px' }} size="small">101 <Card key={el.id} title={el.title} style={{ width: 280, display:'inline-block', margin:'10px' }} size="small"> 74 102 <p>{el.description}</p> 75 103 <b>{el.price} ден.</b> 76 104 </Card> 77 105 )} 106 <Review user={user} front refresh={refreshToggle} setVisible={setNewReviewModal}/> 78 107 </div> 79 108 </div> … … 92 121 <AddNewReservation setModalSaveLoading={setSaveModalLoading} setModalVisible={setNewReservationModal} /> 93 122 </Modal> 123 <Modal 124 style={{top: 20}} 125 width={'700px'} 126 title="Нова оценка" 127 footer={[ 128 <Button form="newReviewForm" key="submit" htmlType="submit" type={'primary'} loading={saveModalLoading}> 129 Прати 130 </Button> 131 ]} 132 onCancel={()=>setNewReviewModal(false)} 133 visible={newReviewModal}> 134 <Form onFinish={saveNewReview} 135 id={'newReviewForm'} 136 onFinishFailed={()=> 137 notification['error']({ 138 message: 'Ве молиме поправете ги сите грешки пред зачувување!', 139 })}> 140 <Form.Item 141 label="Наслов" 142 name="title" 143 rules={[ 144 { 145 required: true, 146 message: 'Ве молиме внесете наслов!', 147 }, 148 ]} 149 > 150 <Input/> 151 </Form.Item> 152 <Form.Item 153 label="Опис" 154 name="description" 155 rules={[ 156 { 157 required: true, 158 message: 'Ве молиме внесете опис!', 159 }, 160 ]} 161 > 162 <Input.TextArea rows={4}/> 163 </Form.Item> 164 <Form.Item 165 label="Оценка" 166 name="stars" 167 rules={[ 168 { 169 required: true, 170 message: 'Ве молиме внесете оценка!', 171 }, 172 ]} 173 > 174 <Rate/> 175 </Form.Item> 176 </Form> 177 </Modal> 94 178 </div> 95 96 179 ) 97 180 } 98 99 181 export default FrontPage; -
frontend/src/auth.js
rcc4db18 r899b19d 21 21 setAuthCookie(res.data.token) 22 22 console.log(res.data.token) 23 setUser( true)23 setUser(res.data) 24 24 setLoading(false) 25 history( '/dashboard')25 history(res.data.isAdmin ? '/dashboard' : '/') 26 26 }).catch(el => { 27 27 Modal.error({ … … 101 101 axios.post(env.api+'Users/register',{email: attr.email, password: attr.password}).then(res => { 102 102 setAuthCookie(res.data.token) 103 setUser( true)103 setUser(res.data) 104 104 setLoading(false) 105 history( '/dashboard')105 history(res.data.isAdmin ? '/dashboard' : '/') 106 106 }) 107 107 } -
resTools_backend/backend/Controllers/RestaurantsController.cs
rcc4db18 r899b19d 20 20 } 21 21 22 /* 22 23 [Authorize] 23 24 [HttpPost()] … … 30 31 return Ok(); 31 32 } 33 */ 32 34 33 35 [HttpGet()] -
resTools_backend/backend/Controllers/UsersController.cs
rcc4db18 r899b19d 13 13 { 14 14 private readonly IUserService _userService = null; 15 private readonly IRestaurantService _restaurantService = null; 15 16 16 public UsersController(IUserService userService )17 public UsersController(IUserService userService, IRestaurantService restaurantService) 17 18 { 18 19 _userService = userService; 20 _restaurantService = restaurantService; 19 21 } 20 22 … … 45 47 public async Task<AuthenticateResponse> Register(CreateUserRequest req) 46 48 { 47 var response = await _userService.Register(req); 49 bool isFirst = await _restaurantService.GetRestaurant() == null; 50 var response = await _userService.Register(req, isFirst); 51 if (isFirst) 52 { 53 await _restaurantService.CreateRestaurant("", response.Id); 54 } 48 55 return response; 49 56 } -
resTools_backend/backend/DTOs/AuthenticateResponse.cs
rcc4db18 r899b19d 13 13 [JsonProperty] 14 14 public string Token { get; set; } 15 [JsonProperty] 16 public bool IsAdmin { get; set; } 15 17 } -
resTools_backend/backend/DTOs/RestaurantResponse.cs
rcc4db18 r899b19d 14 14 public List<MenuItemResponse> Menu { get; set; } 15 15 [JsonProperty] 16 public List<ReviewResponse> Reviews { get; set; } 17 [JsonProperty] 18 public double AverageReview { get; set; } 19 [JsonProperty] 16 20 public string Base64Image { get; set; } 17 21 } -
resTools_backend/backend/Data/DataContext.cs
rcc4db18 r899b19d 66 66 } 67 67 68 private DbSet<Review> reviews; 69 public DbSet<Review> Reviews 70 { 71 get 72 { 73 if (reviews == null) 74 { 75 reviews = Set<Review>(); 76 } 77 78 return reviews; 79 } 80 } 81 68 82 69 83 protected override void OnModelCreating(ModelBuilder modelBuilder) … … 89 103 .WithOne(b => b.Restaurant); 90 104 modelBuilder.Entity<Restaurant>() 91 .HasMany(p => p. Menu)105 .HasMany(p => p.Reviews) 92 106 .WithOne(b => b.Restaurant); 93 94 107 95 108 // … … 108 121 .HasOne(p => p.Restaurant) 109 122 .WithMany(b => b.Menu); 123 124 // 125 // Review 126 // 127 modelBuilder.Entity<Review>().Property(x => x.Id).IsRequired().ValueGeneratedOnAdd(); 128 modelBuilder.Entity<Review>() 129 .HasOne(p => p.Restaurant) 130 .WithMany(b => b.Reviews); 131 modelBuilder.Entity<Review>() 132 .HasOne(p => p.User); 110 133 } 111 134 } -
resTools_backend/backend/Entities/Restaurant.cs
rcc4db18 r899b19d 10 10 public virtual ICollection<Reservation> Reservations { get; set; } 11 11 public virtual ICollection<MenuItem> Menu { get; set; } 12 public virtual ICollection<Review> Reviews { get; set; } 12 13 public string Name { get; set; } 13 14 public string Address { get; set; } -
resTools_backend/backend/Entities/User.cs
rcc4db18 r899b19d 8 8 public string Email { get; set; } 9 9 public string Password { get; set; } 10 [JsonIgnore]10 public bool IsAdmin { get; set; } 11 11 public virtual Restaurant Restaurant { get; set; } 12 12 } -
resTools_backend/backend/Migrations/DataContextModelSnapshot.cs
rcc4db18 r899b19d 131 131 }); 132 132 133 modelBuilder.Entity("backend.Entities.Review", b => 134 { 135 b.Property<int>("Id") 136 .ValueGeneratedOnAdd() 137 .HasColumnType("integer"); 138 139 NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); 140 141 b.Property<DateTime>("CreatedAt") 142 .HasColumnType("timestamp with time zone"); 143 144 b.Property<string>("Description") 145 .IsRequired() 146 .HasColumnType("text"); 147 148 b.Property<int>("RestaurantId") 149 .HasColumnType("integer"); 150 151 b.Property<int>("Stars") 152 .HasColumnType("integer"); 153 154 b.Property<string>("Title") 155 .IsRequired() 156 .HasColumnType("text"); 157 158 b.Property<int>("UserId") 159 .HasColumnType("integer"); 160 161 b.HasKey("Id"); 162 163 b.HasIndex("RestaurantId"); 164 165 b.HasIndex("UserId"); 166 167 b.ToTable("Reviews"); 168 }); 169 133 170 modelBuilder.Entity("backend.Entities.User", b => 134 171 { … … 142 179 .IsRequired() 143 180 .HasColumnType("text"); 181 182 b.Property<bool>("IsAdmin") 183 .HasColumnType("boolean"); 144 184 145 185 b.Property<string>("Password") … … 183 223 }); 184 224 225 modelBuilder.Entity("backend.Entities.Review", b => 226 { 227 b.HasOne("backend.Entities.Restaurant", "Restaurant") 228 .WithMany("Reviews") 229 .HasForeignKey("RestaurantId") 230 .OnDelete(DeleteBehavior.Cascade) 231 .IsRequired(); 232 233 b.HasOne("backend.Entities.User", "User") 234 .WithMany() 235 .HasForeignKey("UserId") 236 .OnDelete(DeleteBehavior.Cascade) 237 .IsRequired(); 238 239 b.Navigation("Restaurant"); 240 241 b.Navigation("User"); 242 }); 243 185 244 modelBuilder.Entity("backend.Entities.Restaurant", b => 186 245 { … … 188 247 189 248 b.Navigation("Reservations"); 249 250 b.Navigation("Reviews"); 190 251 }); 191 252 -
resTools_backend/backend/Program.cs
rcc4db18 r899b19d 47 47 builder.Services.AddScoped<IReservationService, ReservationService>(); 48 48 builder.Services.AddScoped<IMenuService, MenuService>(); 49 builder.Services.AddScoped<IReviewService, ReviewService>(); 49 50 builder.Services.AddScoped<ISmsService, SmsService>(); 50 51 -
resTools_backend/backend/Services/RestaurantService.cs
rcc4db18 r899b19d 32 32 { 33 33 RestaurantResponse res = await _context.Restoraunts 34 .Include(x => x.Menu) 35 .Include(x => x.Reviews).ThenInclude(x => x.User) 34 36 .Select(x => new RestaurantResponse() 35 37 { … … 44 46 Description = x.Description, 45 47 Price = x.Price 46 }).ToList() 48 }).ToList(), 49 Reviews = x.Reviews.OrderByDescending(x => x.CreatedAt).Select(x => new ReviewResponse() 50 { 51 Id = x.Id, 52 Title = x.Title, 53 Description = x.Description, 54 Stars = x.Stars, 55 CreatedAt = x.CreatedAt, 56 Username = x.User == null ? "Anonymous" : x.User.Email 57 }).ToList(), 58 AverageReview = x.Reviews.Count>0 ? x.Reviews.Select(x => x.Stars).Average() : 0 47 59 }) 48 60 .FirstOrDefaultAsync(); -
resTools_backend/backend/Services/UserService.cs
rcc4db18 r899b19d 15 15 { 16 16 Task<AuthenticateResponse> Authenticate(AuthenticateRequest model); 17 Task<AuthenticateResponse> Register(CreateUserRequest req );17 Task<AuthenticateResponse> Register(CreateUserRequest req, bool isFirst); 18 18 Task<User> GetById(int id); 19 19 } … … 40 40 var token = generateJwtToken(user); 41 41 42 return new AuthenticateResponse { Email = user.Email, Id = user.Id, Token = token };42 return new AuthenticateResponse { Email = user.Email, Id = user.Id, Token = token, IsAdmin = user.IsAdmin}; 43 43 } 44 44 … … 48 48 } 49 49 50 public async Task<AuthenticateResponse> Register(CreateUserRequest req )50 public async Task<AuthenticateResponse> Register(CreateUserRequest req, bool isFirst) 51 51 { 52 User user = new User() { Email = req.Email, Password = req.Password };52 User user = new User() { Email = req.Email, Password = req.Password, IsAdmin = isFirst }; 53 53 await _context.Users.AddAsync(user); 54 54 await _context.SaveChangesAsync(); 55 55 var token = generateJwtToken(user); 56 return new AuthenticateResponse { Email = user.Email, Id = user.Id, Token = token };56 return new AuthenticateResponse { Email = user.Email, Id = user.Id, Token = token, IsAdmin = user.IsAdmin }; 57 57 } 58 58
Note:
See TracChangeset
for help on using the changeset viewer.