Changeset 77205be
- Timestamp:
- 12/26/23 18:50:43 (10 months ago)
- Branches:
- master
- Children:
- 1413ee2
- Parents:
- 950fa0d
- Files:
-
- 22 added
- 2 deleted
- 57 edited
- 4 moved
Legend:
- Unmodified
- Added
- Removed
-
mvnw.cmd
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
pom.xml
-
Property mode
changed from
100644
to100755
r950fa0d r77205be 6 6 <groupId>org.springframework.boot</groupId> 7 7 <artifactId>spring-boot-starter-parent</artifactId> 8 <version>2.7. 4</version>8 <version>2.7.6</version> 9 9 <relativePath/> <!-- lookup parent from repository --> 10 10 </parent> … … 17 17 <properties> 18 18 <java.version>17</java.version> 19 <org.modelmapper.version>3.2.0</org.modelmapper.version> 19 20 </properties> 20 21 <dependencies> … … 26 27 <groupId>org.springframework.boot</groupId> 27 28 <artifactId>spring-boot-starter-jdbc</artifactId> 29 </dependency> 30 <dependency> 31 <groupId>org.modelmapper</groupId> 32 <artifactId>modelmapper</artifactId> 33 <version>${org.modelmapper.version}</version> 28 34 </dependency> 29 35 <dependency> -
Property mode
changed from
-
src/main/java/edu/gjoko/schedlr/SchedlrApplication.java
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/main/java/edu/gjoko/schedlr/ServletInitializer.java
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/main/java/edu/gjoko/schedlr/config/AppAuthenticationEntryPoint.java
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/main/java/edu/gjoko/schedlr/config/AppAuthenticationFailureHandler.java
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/main/java/edu/gjoko/schedlr/config/AppConfig.java
-
Property mode
changed from
100644
to100755
r950fa0d r77205be 15 15 } 16 16 17 @Bean18 public AuthenticationSuccessHandler appAuthenticationSuccessHandler() {19 return new AppAuthenticationSuccessHandler();20 }21 17 22 18 @Bean -
Property mode
changed from
-
src/main/java/edu/gjoko/schedlr/config/AppFilter.java
-
Property mode
changed from
100644
to100755
r950fa0d r77205be 64 64 break; 65 65 case "CUSTOMER": 66 page = "/homepage"; 66 if ("/customer_admin".equals(httpServletRequest.getRequestURI())) { 67 page = "/customer_admin"; 68 } else { 69 page = "/homepage"; 70 } 67 71 break; 68 72 case "BUSINESS_OWNER": -
Property mode
changed from
-
src/main/java/edu/gjoko/schedlr/config/AppSecurityConfig.java
-
Property mode
changed from
100644
to100755
r950fa0d r77205be 32 32 private final BCryptPasswordEncoder passwordEncoder; 33 33 34 private final AuthenticationSuccessHandler authenticationSuccessHandler;35 36 34 private final AuthenticationFailureHandler authenticationFailureHandler; 37 35 … … 57 55 .loginPage("/login") 58 56 .loginProcessingUrl("/login") 59 .successHandler(authenticationSuccessHandler)60 57 .failureHandler(authenticationFailureHandler) 61 .defaultSuccessUrl("/ homepage")58 .defaultSuccessUrl("/login") 62 59 .and() 63 60 .logout(logout -> logout -
Property mode
changed from
-
src/main/java/edu/gjoko/schedlr/config/MvcConfig.java
-
Property mode
changed from
100644
to100755
r950fa0d r77205be 16 16 registry.addViewController("/admin").setViewName("admin"); 17 17 registry.addViewController("/business_admin").setViewName("business_admin"); 18 registry.addViewController("/customer_admin").setViewName("customer_admin"); 18 19 } 19 20 } -
Property mode
changed from
-
src/main/java/edu/gjoko/schedlr/controllers/AdministrationController.java
-
Property mode
changed from
100644
to100755
r950fa0d r77205be 8 8 9 9 import javax.servlet.http.HttpServletRequest; 10 import java.security.Principal;11 10 12 11 @Controller 13 public class Admin Controller {12 public class AdministrationController { 14 13 15 14 @GetMapping(path = "/admin") 16 public String getAdminPageTemplate(Model model , HttpServletRequest request) {15 public String getAdminPageTemplate(Model model) { 17 16 return "admin"; 18 17 } 19 18 20 19 @GetMapping(path = "/business_admin") 21 public String getBusinessAdminPageTemplate(Model model , HttpServletRequest request) {22 Authentication authentication = SecurityContextHolder.getContext().getAuthentication();23 String currentPrincipalName = authentication.getName();20 public String getBusinessAdminPageTemplate(Model model) { 21 return "business_admin"; 22 } 24 23 25 return "business_admin"; 24 @GetMapping(path = "/customer_admin") 25 public String getCustomerAdminPageTemplate(Model model) { 26 return "customer_admin"; 26 27 } 27 28 -
Property mode
changed from
-
src/main/java/edu/gjoko/schedlr/controllers/HomePageController.java
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/main/java/edu/gjoko/schedlr/controllers/LoginController.java
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/main/java/edu/gjoko/schedlr/controllers/RegisterController.java
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/main/java/edu/gjoko/schedlr/controllers/rest/BusinessApi.java
-
Property mode
changed from
100644
to100755
r950fa0d r77205be 2 2 3 3 import edu.gjoko.schedlr.entity.Business; 4 import edu.gjoko.schedlr.entity.BusinessType;5 4 import edu.gjoko.schedlr.services.BusinessService; 6 5 import lombok.AllArgsConstructor; … … 13 12 @RequestMapping("api/business") 14 13 @AllArgsConstructor 15 public class Business Controller{14 public class BusinessApi { 16 15 17 final BusinessService businessService;16 private final BusinessService businessService; 18 17 19 18 @PostMapping 20 public void getBusinessTypes(@RequestBody Business business) {19 public void saveBusiness(@RequestBody Business business) { 21 20 businessService.saveBusiness(business); 22 21 } … … 40 39 @GetMapping(path = "/{businessTypeId}") 41 40 public List<Business> getBusinessesByBusinessType(@PathVariable("businessTypeId") Long id) { 42 BusinessType businessType = new BusinessType(); 43 businessType.setId(id); 44 return businessService.findByBusinessTypeAndActiveStatus(businessType); 41 return businessService.findByBusinessTypeAndActiveStatus(id); 45 42 } 46 43 } -
Property mode
changed from
-
src/main/java/edu/gjoko/schedlr/controllers/rest/NomenclatureApi.java
-
Property mode
changed from
100644
to100755
r950fa0d r77205be 13 13 @RequestMapping("api/nomenclatures") 14 14 @AllArgsConstructor 15 public class Nomenclature Controller{15 public class NomenclatureApi { 16 16 17 17 private final NomenclaturesService nomenclaturesService; -
Property mode
changed from
-
src/main/java/edu/gjoko/schedlr/controllers/rest/UserApi.java
-
Property mode
changed from
100644
to100755
r950fa0d r77205be 1 1 package edu.gjoko.schedlr.controllers.rest; 2 2 3 import edu.gjoko.schedlr.entity.Business;4 3 import lombok.AllArgsConstructor; 5 4 import org.springframework.web.bind.annotation.GetMapping; … … 8 7 9 8 import javax.servlet.http.HttpServletRequest; 10 import java.util.List;11 9 12 10 @RestController 13 11 @RequestMapping("api/user") 14 12 @AllArgsConstructor 15 public class User Controller{13 public class UserApi { 16 14 17 15 @GetMapping(path = "/me") -
Property mode
changed from
-
src/main/java/edu/gjoko/schedlr/entity/Appointment.java
-
Property mode
changed from
100644
to100755
r950fa0d r77205be 1 1 package edu.gjoko.schedlr.entity; 2 2 3 import lombok.AllArgsConstructor; 4 import lombok.Getter; 5 import lombok.NoArgsConstructor; 6 import lombok.Setter; 3 import com.fasterxml.jackson.annotation.JsonBackReference; 4 import lombok.*; 7 5 import org.springframework.data.annotation.LastModifiedDate; 8 6 import org.springframework.data.jpa.domain.support.AuditingEntityListener; … … 14 12 @EntityListeners(AuditingEntityListener.class) 15 13 @Table(name = "appointment") 16 @Getter 17 @Setter 14 @Data 18 15 @NoArgsConstructor 19 16 @AllArgsConstructor … … 30 27 private LocalDateTime endTime; 31 28 32 @OneToOne 33 @JoinColumn(name = "customer_id", referencedColumnName = "id") 29 @ManyToOne 30 @JoinColumn(name = "stakeholder_id") 31 @JsonBackReference(value = "customerAppointments") 34 32 private Stakeholder customer; 35 33 36 34 @ManyToOne 37 @JoinColumn(name = "business_id") 38 private Business business; 35 @JoinColumn(name = "service_id") 36 @JsonBackReference(value = "serviceAppointments") 37 private Service service; 39 38 40 @ ManyToOne41 @ JoinColumn(name = "service_id")42 private Service service;39 @Column(name = "appointment_status", length = 32, columnDefinition = "varchar(32) default 'NEW'") 40 @Enumerated(EnumType.STRING) 41 private AppointmentStatus appointmentStatus = AppointmentStatus.NEW; 43 42 44 43 @Column(name = "created") … … 49 48 @LastModifiedDate 50 49 private LocalDateTime modified; 50 51 public String getTimePeriod() { 52 return startTime + " - " + endTime; 53 } 54 51 55 } -
Property mode
changed from
-
src/main/java/edu/gjoko/schedlr/entity/Business.java
-
Property mode
changed from
100644
to100755
r950fa0d r77205be 37 37 private BusinessType businessType; 38 38 39 @ ManyToOne()39 @OneToOne(cascade = CascadeType.PERSIST) 40 40 @JoinColumn(name = "owner_id", referencedColumnName = "id", nullable = false) 41 41 @JsonProperty("owner") … … 43 43 44 44 @OneToMany(mappedBy = "business", cascade = CascadeType.PERSIST) 45 @JsonManagedReference 45 @JsonManagedReference(value = "services") 46 46 private List<Service> services; 47 47 -
Property mode
changed from
-
src/main/java/edu/gjoko/schedlr/entity/BusinessStatus.java
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/main/java/edu/gjoko/schedlr/entity/BusinessType.java
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/main/java/edu/gjoko/schedlr/entity/Service.java
-
Property mode
changed from
100644
to100755
r950fa0d r77205be 3 3 import com.fasterxml.jackson.annotation.JsonBackReference; 4 4 import com.fasterxml.jackson.annotation.JsonIgnore; 5 import com.fasterxml.jackson.annotation.JsonManagedReference; 5 6 import lombok.AllArgsConstructor; 6 7 import lombok.Getter; … … 13 14 import javax.persistence.*; 14 15 import java.time.LocalDateTime; 16 import java.util.List; 15 17 16 18 @Entity … … 33 35 private Integer price; 34 36 35 @OneToOne(cascade = CascadeType.PERSIST) 37 @Column(name = "cumulated_rating") 38 private Float rating = 0.0f; 39 40 @Column(name = "reviews_count") 41 private Integer reviewsCount = 0; 42 43 @OneToOne(cascade = CascadeType.MERGE) 36 44 @JoinColumn(name = "service_type_id", referencedColumnName = "id") 37 45 private ServiceType serviceType; … … 39 47 @ManyToOne 40 48 @JoinColumn(name = "business_id") 41 @JsonBackReference 49 @JsonBackReference(value = "services") 42 50 private Business business; 51 52 @OneToMany(mappedBy="service") 53 @JsonManagedReference(value = "serviceAppointments") 54 private List<Appointment> appointments; 43 55 44 56 @Column(name = "created") -
Property mode
changed from
-
src/main/java/edu/gjoko/schedlr/entity/ServiceType.java
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/main/java/edu/gjoko/schedlr/entity/Stakeholder.java
-
Property mode
changed from
100644
to100755
r950fa0d r77205be 2 2 3 3 import com.fasterxml.jackson.annotation.JsonIgnore; 4 import com.fasterxml.jackson.annotation.JsonManagedReference; 4 5 import lombok.AllArgsConstructor; 5 6 import lombok.Getter; … … 12 13 import javax.persistence.*; 13 14 import java.time.LocalDateTime; 15 import java.util.List; 14 16 15 17 @Entity … … 39 41 private String email; 40 42 43 @Column(name = "phone_number") 44 private String phoneNumber; 45 41 46 @Column(name = "username") 42 47 private String username; … … 44 49 @Column(name = "password") 45 50 private String password; 51 52 @OneToMany(mappedBy = "customer") 53 @JsonManagedReference(value = "customerAppointments") 54 private List<Appointment> appointments; 46 55 47 56 @Column(name = "created") … … 54 63 @JsonIgnore 55 64 private LocalDateTime modified; 65 66 public String getFullName() { 67 return firstName + " " + lastName; 68 } 56 69 } -
Property mode
changed from
-
src/main/java/edu/gjoko/schedlr/entity/StakeholderType.java
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/main/java/edu/gjoko/schedlr/exceptions/BlockingTimeException.java
-
Property mode
changed from
100644
to100755
r950fa0d r77205be 3 3 public class BlockingTimeException extends RuntimeException { 4 4 5 public static final String MESSAGE = " The selected dates are overlapping with another appointment";5 public static final String MESSAGE = "Error! The selected dates are overlapping with another appointment."; 6 6 public BlockingTimeException() { 7 7 super(MESSAGE); -
Property mode
changed from
-
src/main/java/edu/gjoko/schedlr/repositories/AppointmentRepository.java
-
Property mode
changed from
100644
to100755
r950fa0d r77205be 2 2 3 3 import edu.gjoko.schedlr.entity.Appointment; 4 import edu.gjoko.schedlr.entity.Business;5 4 import edu.gjoko.schedlr.entity.Stakeholder; 6 5 import org.springframework.data.jpa.repository.JpaRepository; … … 10 9 import java.time.LocalDateTime; 11 10 import java.util.List; 11 import java.util.Optional; 12 12 13 13 @Repository 14 14 public interface AppointmentRepository extends JpaRepository<Appointment, Long> { 15 15 16 List<Appointment> getAppointmentsByBusiness(Business business); 16 @Query(value = "select ap from Appointment as ap " + 17 "where ap.service.business.id = :businessId " + 18 "and ap.appointmentStatus = 'NEW'") 19 List<Appointment> getActiveAppointmentsByBusiness(Long businessId); 17 20 18 List<Appointment> getAppointmentsByCustomer(Stakeholder customer); 21 @Query( value = "select ap from Appointment as ap " + 22 "where ap.service.business.id = :businessId " + 23 "and (" + 24 "(ap.startTime between :startDate and :endDate) " + 25 "or (ap.endTime between :startDate and :endDate) " + 26 "or (:startDate = ap.startTime and ap.startTime = :endDate)" + 27 "or (:startDate > ap.startTime and ap.endTime > :endDate)" + 28 ")") 29 List<Appointment> findBlockingAppointments(Long businessId, LocalDateTime startDate, LocalDateTime endDate); 19 30 20 List<Appointment> findAppointmentsByBusinessAndStartTimeBetweenOrEndTimeBetween(Business business, LocalDateTime startTime, LocalDateTime endTime, LocalDateTime startTime1, LocalDateTime endTime1); 31 @Query(value = "select ap from Appointment as ap " + 32 "where ap.service.business.owner.id = :businessOwnerId " + 33 "and ap.startTime > :now ") 34 List<Appointment> findFutureAppointmentsByBusinessOwnerId(Long businessOwnerId, LocalDateTime now); 21 35 22 @Query(value = "select a from Appointment a " + 23 "where business_id = :businessId " + 24 "and (" + 25 "(start_time between :startDate and :endDate) " + 26 "or (end_time between :startDate and :endDate) " + 27 "or (:startDate <= start_time and end_time >= :endDate)" + 28 ")", nativeQuery = true) 29 List<Appointment> findBlockingAppointments(Long businessId, LocalDateTime startDate, LocalDateTime endDate); 36 @Query(value = "select ap from Appointment as ap " + 37 "where ap.customer.id = :customerId " + 38 "and ap.startTime < :now") 39 List<Appointment> findPastAppointmentsByCustomerId(Long customerId, LocalDateTime now); 40 41 @Query(value = "select ap from Appointment as ap " + 42 "where ap.service.business.owner.id = :businessOwnerId " + 43 "and ap.startTime < :now ") 44 List<Appointment> findPastAppointmentsByBusinessOwnerId(Long businessOwnerId, LocalDateTime now); 45 46 @Query(value = "select ap from Appointment as ap " + 47 "where ap.customer.id = :customerId " + 48 "and ap.startTime > :now ") 49 List<Appointment> findFutureAppointmentsByCustomerId(Long customerId, LocalDateTime now); 50 51 Optional<Appointment> findAppointmentByIdAndCustomer_Id(Long id, Long customerId); 52 53 Optional<Appointment> findAppointmentByIdAndService_Business_Owner_Id(Long id, Long ownerId); 30 54 } -
Property mode
changed from
-
src/main/java/edu/gjoko/schedlr/repositories/BusinessRepository.java
-
Property mode
changed from
100644
to100755
r950fa0d r77205be 17 17 18 18 List<Business> findBusinessesByBusinessTypeAndBusinessStatus(BusinessType businessType, BusinessStatus businessStatus); 19 20 List<Business> findBusinessesByBusinessStatusAndBusinessType_Id(BusinessStatus businessStatus, Long id); 19 21 } -
Property mode
changed from
-
src/main/java/edu/gjoko/schedlr/repositories/BusinessTypeRepository.java
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/main/java/edu/gjoko/schedlr/repositories/ServiceRepository.java
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/main/java/edu/gjoko/schedlr/repositories/ServiceTypeRepository.java
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/main/java/edu/gjoko/schedlr/repositories/StakeholderRepository.java
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/main/java/edu/gjoko/schedlr/services/AppointmentsService.java
-
Property mode
changed from
100644
to100755
r950fa0d r77205be 1 1 package edu.gjoko.schedlr.services; 2 2 3 import edu.gjoko.schedlr.entity.Appointment; 4 import edu.gjoko.schedlr.entity.Business; 5 import edu.gjoko.schedlr.entity.Stakeholder; 3 import edu.gjoko.schedlr.dto.AppointmentInfoDto; 4 import edu.gjoko.schedlr.entity.*; 6 5 import edu.gjoko.schedlr.exceptions.BlockingTimeException; 6 import edu.gjoko.schedlr.mappers.AppointmentInfoDtoBusinessMapper; 7 import edu.gjoko.schedlr.mappers.AppointmentInfoDtoCustomerMapper; 7 8 import edu.gjoko.schedlr.repositories.AppointmentRepository; 8 9 import edu.gjoko.schedlr.repositories.ServiceRepository; 9 import edu.gjoko.schedlr.repositories.S erviceTypeRepository;10 import edu.gjoko.schedlr.repositories.StakeholderRepository; 10 11 import lombok.AllArgsConstructor; 11 12 import org.springframework.stereotype.Service; 12 13 14 import javax.persistence.EntityNotFoundException; 15 import javax.security.sasl.AuthenticationException; 16 import java.time.LocalDateTime; 17 import java.util.ArrayList; 13 18 import java.util.List; 19 import java.util.Optional; 14 20 15 21 @Service … … 18 24 19 25 private final AppointmentRepository appointmentRepository; 26 private final StakeholderRepository stakeholderRepository; 27 private final ServiceRepository serviceRepository; 28 private final AppointmentInfoDtoBusinessMapper appointmentInfoDtoBusinessMapper; 29 private final AppointmentInfoDtoCustomerMapper appointmentInfoDtoCustomerMapper; 20 30 21 private final ServiceRepository serviceRepository;22 31 23 32 public void saveAppointment(Appointment appointment) { 24 33 var service = serviceRepository.findById(appointment.getService().getId()).get(); 25 appointment.setEndTime(appointment.getStartTime().plusMinutes(service.getDuration())); 34 35 // remove 1 minute in order to prevent overlapping 36 appointment.setEndTime(appointment.getStartTime().plusMinutes(service.getDuration() - 1)); 26 37 List<Appointment> blockingAppointments = appointmentRepository. 27 38 findBlockingAppointments( 28 appointment.get Business().getId(), appointment.getStartTime(), appointment.getEndTime());39 appointment.getService().getBusiness().getId(), appointment.getStartTime(), appointment.getEndTime()); 29 40 30 41 // check to see if there are blocking exceptions … … 35 46 } 36 47 37 public List<Appointment> getAppointmentsByBusiness(Business business) { 38 return appointmentRepository.getAppointmentsByBusiness(business); 48 public List<AppointmentInfoDto> getFutureAppointmentInfoList(Long stakeholderId) { 49 StakeholderType type = stakeholderRepository.findById(stakeholderId).get().getStakeholderType(); 50 List<AppointmentInfoDto> appointmentInfoDtoList = new ArrayList<>(); 51 52 switch (type) { 53 case BUSINESS_OWNER -> appointmentInfoDtoList = appointmentRepository.findFutureAppointmentsByBusinessOwnerId(stakeholderId, LocalDateTime.now()) 54 .stream() 55 .map(appointmentInfoDtoBusinessMapper::appointmentToAppointmentInfoDto) 56 .toList(); 57 case CUSTOMER -> appointmentInfoDtoList = appointmentRepository.findFutureAppointmentsByCustomerId(stakeholderId, LocalDateTime.now()) 58 .stream() 59 .map(appointmentInfoDtoCustomerMapper::appointmentToAppointmentInfoDto) 60 .toList(); 61 } 62 63 return appointmentInfoDtoList; 39 64 } 40 65 41 private List<Appointment> getAppointmentsByCustomer(Stakeholder stakeholder) { 42 return appointmentRepository.getAppointmentsByCustomer(stakeholder); 66 public List<AppointmentInfoDto> getPastAppointmentInfoList(Long stakeholderId) { 67 StakeholderType type = stakeholderRepository.findById(stakeholderId).get().getStakeholderType(); 68 List<Appointment> appointmentInfoDtoList = new ArrayList<>(); 69 70 switch (type) { 71 case BUSINESS_OWNER -> appointmentInfoDtoList = appointmentRepository.findPastAppointmentsByBusinessOwnerId(stakeholderId, LocalDateTime.now()); 72 case CUSTOMER -> appointmentInfoDtoList = appointmentRepository.findPastAppointmentsByCustomerId(stakeholderId, LocalDateTime.now()); 73 } 74 75 return appointmentInfoDtoList 76 .stream() 77 .map(appointmentInfoDtoBusinessMapper::appointmentToAppointmentInfoDto) 78 .toList(); 79 80 } 81 82 public List<Appointment> getActiveAppointmentsByBusiness(Long businessId) { 83 return appointmentRepository.getActiveAppointmentsByBusiness(businessId); 84 } 85 86 public void deleteAppointment(Long appointmentId, Long stakeholderId) throws AuthenticationException { 87 Optional<Stakeholder> stakeholderOptional = stakeholderRepository.findById(stakeholderId); 88 if (stakeholderOptional.isPresent()) { 89 Optional<Appointment> optional = appointmentRepository.findAppointmentByIdAndCustomer_Id(appointmentId, stakeholderId); 90 if (optional.isEmpty()) { 91 optional = appointmentRepository.findAppointmentByIdAndService_Business_Owner_Id(appointmentId, stakeholderId); 92 if (optional.isEmpty()) { 93 throw new EntityNotFoundException("No appointment was found for the give stakeholder and appointment id."); 94 } else { 95 softDeleteAppointment(optional.get(), AppointmentStatus.CANCELLED_BY_BUSINESS_OWNER); 96 } 97 } else { 98 softDeleteAppointment(optional.get(), AppointmentStatus.CANCELLED_BY_CUSTOMER); 99 } 100 } else { 101 throw new AuthenticationException(); 102 } 103 } 104 105 public void softDeleteAppointment(Appointment appointment, AppointmentStatus appointmentStatus) { 106 appointment.setAppointmentStatus(appointmentStatus); 107 appointmentRepository.save(appointment); 43 108 } 44 109 } -
Property mode
changed from
-
src/main/java/edu/gjoko/schedlr/services/BusinessService.java
-
Property mode
changed from
100644
to100755
r950fa0d r77205be 2 2 3 3 import edu.gjoko.schedlr.entity.*; 4 import edu.gjoko.schedlr.repositories.BusinessRepository; 5 import edu.gjoko.schedlr.repositories.ServiceRepository; 6 import edu.gjoko.schedlr.repositories.ServiceTypeRepository; 7 import edu.gjoko.schedlr.repositories.StakeholderRepository; 4 import edu.gjoko.schedlr.repositories.*; 8 5 import lombok.AllArgsConstructor; 9 6 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 10 7 import org.springframework.stereotype.Service; 8 import org.springframework.util.CollectionUtils; 11 9 12 10 import java.util.List; … … 22 20 private final ServiceTypeRepository serviceTypeRepository; 23 21 private final ServiceRepository serviceRepository; 22 private final StakeholderService stakeholderService; 24 23 25 24 private final StakeholderRepository stakeholderRepository; … … 54 53 .stream() 55 54 .forEach(business -> { 56 stakeholder Repository.save(business.getOwner());57 s erviceRepository.saveAll(business.getServices());58 businessRepository.save(business);55 stakeholderService.saveOrUpdateStakeholder(business.getOwner()); 56 saveOrUpdateServices(business.getServices()); 57 saveOrUpdateBusiness(business); 59 58 }); 60 59 } … … 66 65 } 67 66 68 public List<Business> findByBusinessTypeAndActiveStatus(BusinessType businessType) { 69 return businessRepository.findBusinessesByBusinessTypeAndBusinessStatus(businessType, ACTIVE); 67 public List<Business> findByBusinessTypeAndActiveStatus(Long businessTypeId) { 68 return businessRepository.findBusinessesByBusinessStatusAndBusinessType_Id(ACTIVE, businessTypeId); 69 } 70 71 72 73 private void saveOrUpdateBusiness(Business business) { 74 if (business.getId() != null) { 75 var foundBusinessEntity = businessRepository.findById(business.getId()); 76 business.setCreated(foundBusinessEntity.get().getCreated()); 77 } 78 businessRepository.save(business); 79 } 80 81 private void saveOrUpdateServices(List<edu.gjoko.schedlr.entity.Service> serviceList) { 82 if (!CollectionUtils.isEmpty(serviceList)) { 83 serviceList.forEach( service -> { 84 if (service.getId() != null) { 85 var found = serviceRepository.findById(service.getId()); 86 service.setCreated(found.get().getCreated()); 87 } 88 }); 89 serviceRepository.saveAll(serviceList); 90 } 70 91 } 71 92 } -
Property mode
changed from
-
src/main/java/edu/gjoko/schedlr/services/NomenclaturesService.java
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/main/java/edu/gjoko/schedlr/services/PostgresUserDetailsService.java
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/main/java/edu/gjoko/schedlr/services/StakeholderService.java
-
Property mode
changed from
100644
to100755
r950fa0d r77205be 6 6 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 7 7 import org.springframework.stereotype.Service; 8 9 import java.util.Optional; 8 10 9 11 @Service … … 28 30 return stakeholderRepository.findById(id).get(); 29 31 } 32 33 public void saveOrUpdateStakeholder(Stakeholder stakeholder) { 34 if (stakeholder.getId() != null) { 35 var found = stakeholderRepository.findById(stakeholder.getId()).get(); 36 found.setFirstName(stakeholder.getFirstName()); 37 found.setLastName(stakeholder.getLastName()); 38 found.setPhoneNumber(stakeholder.getPhoneNumber()); 39 found.setEmail(stakeholder.getEmail()); 40 found.setUsername(stakeholder.getUsername()); 41 stakeholderRepository.save(found); 42 } 43 } 30 44 } -
Property mode
changed from
-
src/main/resources/application.properties
-
Property mode
changed from
100644
to100755
r950fa0d r77205be 1 spring.datasource.url=jdbc:postgresql://localhost:543 3/schedlr2 spring.datasource.username= postgres3 spring.datasource.password= silic0n1 spring.datasource.url=jdbc:postgresql://localhost:5432/schedlr 2 spring.datasource.username=gjoko 3 spring.datasource.password=gjoko 4 4 5 5 spring.sql.init.mode=never -
Property mode
changed from
-
src/main/resources/data.sql
-
Property mode
changed from
100644
to100755
r950fa0d r77205be 1 insert into stakeholder (id, created, email, first_name, last_name, modified, password, stakeholder_type, username)2 values (nextval('hibernate_sequence'), current_timestamp, 'admin@schedlr.com', 'admin', 'admin', current_timestamp, '$2a$10$DJyjt.Vj/U8MEuYX1PXL9ukQSMwXHVdhre3POlTqpYzNxHB5gu/MW','ADMIN', 'admin');3 4 insert into stakeholder (id, created, email, first_name, last_name, modified, password, stakeholder_type, username)5 values (nextval('hibernate_sequence'), current_timestamp, 'user1@schedlr.com', 'gjoko', 'kostadinov', current_timestamp, '$2a$10$Zc28AcCpAgxB.e67UMF/2.FgchjH9QWB7z8nP0TdkrFneV4IHPXji','CUSTOMER', 'user');6 7 1 insert into business_type (id, created, modified, name) 8 2 values (1, current_timestamp, current_timestamp, 'tailor'), … … 21 15 (nextval('hibernate_sequence'), current_timestamp, current_timestamp, 'dress shortening', 1), 22 16 (nextval('hibernate_sequence'), current_timestamp, current_timestamp, 'holes fixing', 1); 17 18 insert into stakeholder (id, created, phone_number, email, first_name, last_name, modified, password, stakeholder_type, username) 19 values (nextval('hibernate_sequence'), current_timestamp, '075658123', 'admin@schedlr.com', 'admin', 'admin', current_timestamp, '$2a$10$DJyjt.Vj/U8MEuYX1PXL9ukQSMwXHVdhre3POlTqpYzNxHB5gu/MW','ADMIN', 'admin'), 20 (nextval('hibernate_sequence'), current_timestamp, '071658125', 'user1@schedlr.com', 'gjoko', 'kostadinov', current_timestamp, '$2a$10$Zc28AcCpAgxB.e67UMF/2.FgchjH9QWB7z8nP0TdkrFneV4IHPXji','CUSTOMER', 'user'), 21 (11111, current_timestamp, '078658523', 'c@c.com', 'Kliment', 'Nedelkovski', current_timestamp, '$2a$10$OratLSMKNsqd7Re.Md3I4.jrRHtTQNaLz/wUKo.I98..GufnD48uG','CUSTOMER', 'kliment123'), 22 (10000, current_timestamp, '071218123', 'q@c.com', 'Stefan', 'Petrovski', current_timestamp, '$2a$10$x10O8eLp1r1wHwxDGvyo5.TBL216p8h797JJjQYEfFTbj/1bnCMki','BUSINESS_OWNER', 'stefan123'); 23 24 insert into business (id, business_status, company_name, created, modified, business_type_id, owner_id) 25 values (10001, 'ACTIVE', 'krojach stefan', current_timestamp, current_timestamp, 1, 10000); 26 27 insert into service (id, created, modified, duration, price, cumulated_rating, reviews_count, business_id, service_type_id) 28 values (10002, current_timestamp, current_timestamp, 60, 400, 0, 0, 10001, 6), 29 (10003, current_timestamp, current_timestamp, 30, 200, 0, 0, 10001, 7); 30 31 insert into appointment (id, created, modified, start_time, end_time, stakeholder_id, service_id) 32 values 33 (nextval('hibernate_sequence'), current_timestamp, current_timestamp, current_date + time '10:00:00', current_date + time '10:59:00', 11111, 10002), 34 (nextval('hibernate_sequence'), current_timestamp, current_timestamp, current_date + time '11:00:00', current_date + time '11:29:00', 11111, 10003), 35 (nextval('hibernate_sequence'), current_timestamp, current_timestamp, current_date + time '13:00:00', current_date + time '13:59:00', 11111, 10002), 36 (nextval('hibernate_sequence'), current_timestamp, current_timestamp, current_date + time '14:00:00', current_date + time '14:29:00', 11111, 10003), 37 (nextval('hibernate_sequence'), current_timestamp, current_timestamp, current_date + time '14:30:00', current_date + time '14:59:00', 11111, 10003), 38 (nextval('hibernate_sequence'), current_timestamp, current_timestamp, current_date + 1 + time '11:30:00', current_date + 1 + time '11:59:00', 11111, 10003), 39 (nextval('hibernate_sequence'), current_timestamp, current_timestamp, current_date + 1 + time '13:30:00', current_date + 1 + time '14:29:00', 11111, 10002), 40 (nextval('hibernate_sequence'), current_timestamp, current_timestamp, current_date + 1 + time '15:00:00', current_date + 1 + time '15:29:00', 11111, 10003), 41 (nextval('hibernate_sequence'), current_timestamp, current_timestamp, current_date + 1 + time '14:30:00', current_date + 1 + time '14:59:00', 11111, 10003), 42 (nextval('hibernate_sequence'), current_timestamp, current_timestamp, current_date - 1 + time '09:00:00', current_date - 1 + time '09:29:00', 11111, 10003), 43 (nextval('hibernate_sequence'), current_timestamp, current_timestamp, current_date - 1 + time '10:00:00', current_date - 1 + time '10:59:00', 11111, 10002), 44 (nextval('hibernate_sequence'), current_timestamp, current_timestamp, current_date - 1 + time '12:00:00', current_date - 1 + time '12:29:00', 11111, 10003), 45 (nextval('hibernate_sequence'), current_timestamp, current_timestamp, current_date - 1 + time '12:40:00', current_date - 1 + time '12:09:00', 11111, 10003), 46 (nextval('hibernate_sequence'), current_timestamp, current_timestamp, current_date - 2 + time '10:30:00', current_date - 2 + time '10:59:00', 11111, 10003), 47 (nextval('hibernate_sequence'), current_timestamp, current_timestamp, current_date - 2 + time '12:10:00', current_date - 2 + time '13:09:00', 11111, 10002), 48 (nextval('hibernate_sequence'), current_timestamp, current_timestamp, current_date - 2 + time '15:10:00', current_date - 2 + time '15:39:00', 11111, 10003), 49 (nextval('hibernate_sequence'), current_timestamp, current_timestamp, current_date - 2 + time '14:15:00', current_date - 2 + time '14:44:00', 11111, 10003), 50 (nextval('hibernate_sequence'), current_timestamp, current_timestamp, current_date - 3 + time '11:10:00', current_date - 3 + time '11:39:00', 11111, 10003), 51 (nextval('hibernate_sequence'), current_timestamp, current_timestamp, current_date - 3 + time '14:30:00', current_date - 3 + time '14:59:00', 11111, 10003), 52 (nextval('hibernate_sequence'), current_timestamp, current_timestamp, current_date - 3 + time '08:00:00', current_date - 3 + time '08:29:00', 11111, 10003), 53 (nextval('hibernate_sequence'), current_timestamp, current_timestamp, current_date + 2 + time '10:10:00', current_date + 2 + time '10:29:00', 11111, 10003), 54 (nextval('hibernate_sequence'), current_timestamp, current_timestamp, current_date + 2 + time '11:15:00', current_date + 2 + time '11:44:00', 11111, 10003), 55 (nextval('hibernate_sequence'), current_timestamp, current_timestamp, current_date + 2 + time '14:30:00', current_date + 2 + time '14:59:00', 11111, 10003), 56 (nextval('hibernate_sequence'), current_timestamp, current_timestamp, current_date + 3 + time '11:14:00', current_date + 3 + time '11:44:00', 11111, 10003), 57 (nextval('hibernate_sequence'), current_timestamp, current_timestamp, current_date + 3 + time '13:25:00', current_date + 3 + time '13:54:00', 11111, 10003), 58 (nextval('hibernate_sequence'), current_timestamp, current_timestamp, current_date + 3 + time '14:00:00', current_date + 3 + time '14:29:00', 11111, 10003); -
Property mode
changed from
-
src/main/resources/static/css/admin.css
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/main/resources/static/css/business_admin.css
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/main/resources/static/css/headers.css
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/main/resources/static/css/homepage.css
-
Property mode
changed from
100644
to100755
r950fa0d r77205be 74 74 .card { 75 75 padding: 10px; 76 77 76 } -
Property mode
changed from
-
src/main/resources/static/css/login.css
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/main/resources/static/css/register.css
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/main/resources/static/js/admin.js
-
Property mode
changed from
100644
to100755
r950fa0d r77205be 1 1 $(document).ready(function() { 2 var companies = {};2 let companies = []; 3 3 4 $.ajax({ 5 url: "http://localhost:8080/api/business" 6 }).then(function (data) { 4 getCompanies().then(function (data) { 7 5 companies = data; 8 var $el = $("#table_body");9 10 $.each(data, function (index, obj) {11 if(obj.businessStatus == "NEW" || obj.businessStatus == "DEACTIVATED") {12 $el.append("<tr>\n" +13 " <th scope=\"row\">" + obj.id + "</th>\n" +14 " <td>" + obj.companyName + "</td>\n" +15 " <td>" + obj.owner.firstName + " " + obj.owner.lastName + "</td>\n" +16 " <td><input class=\"form-check-input\" type=\"checkbox\" value=\"" + obj.id +"\"></td>\n" +17 " </tr>")18 }19 if (obj.businessStatus == "ACTIVE") {20 $el.append("<tr>\n" +21 " <th scope=\"row\">" + obj.id + "</th>\n" +22 " <td>" + obj.companyName + "</td>\n" +23 " <td>" + obj.owner.firstName + " " + obj.owner.lastName + "</td>\n" +24 " <td><input class=\"form-check-input\" type=\"checkbox\" checked value=\"" + obj.id +"\"></td>\n" +25 " </tr>")26 }27 });28 6 }); 29 7 30 8 $('#save_button').click(function () { 9 var companiesToSave = []; 31 10 $.each($('#table_body tr'), function(index, row) { 32 if(companies[index].businessStatus == "NEW" && $($($(row).children() [3]).children()[0]).is(':checked')) { 33 companies[index]['businessStatus'] = 'ACTIVE'; 11 if((companies[index].businessStatus === "NEW" || companies[index].businessStatus === "DEACTIVATED") && $($($(row).children() [3]).children()[0]).is(':checked')) { 12 let cloneCompany = { ...companies[index] } 13 cloneCompany['businessStatus'] = 'ACTIVE'; 14 companiesToSave.push(cloneCompany); 34 15 } 35 if(companies[index].businessStatus == "ACTIVE" && ! $($($(row).children() [3]).children()[0]).is(':checked')) { 36 companies[index]['businessStatus'] = 'DEACTIVATED'; 16 if(companies[index].businessStatus === "ACTIVE" && !$($($(row).children() [3]).children()[0]).is(':checked')) { 17 let cloneCompany = { ...companies[index] } 18 cloneCompany['businessStatus'] = 'DEACTIVATED'; 19 companiesToSave.push(cloneCompany); 37 20 } 38 21 }); 39 console.log(JSON.stringify(companies)); 22 console.log(JSON.stringify(companiesToSave)); 23 24 40 25 $.ajax({ 41 26 url: "http://localhost:8080/api/business", 42 27 type:"PATCH", 43 data: JSON.stringify(companies ),28 data: JSON.stringify(companiesToSave), 44 29 contentType:"application/json; charset=utf-8", 45 30 dataType: 'text', 46 31 success: function(succ){ 32 getCompanies().then(function (data) { 33 companies = data; 34 }); 47 35 alert( "Updates applied successfully" ); 48 36 }, … … 53 41 event.preventDefault(); 54 42 }); 43 44 function getCompanies() { 45 return $.ajax({ 46 url: "http://localhost:8080/api/business" 47 }).then(function (data) { 48 var $el = $("#table_body"); 49 $("#new_table tbody").html(""); 50 $.each(data, function (index, obj) { 51 if(obj.businessStatus == "NEW" || obj.businessStatus == "DEACTIVATED") { 52 $el.append("<tr>\n" + 53 " <th scope=\"row\">" + obj.id + "</th>\n" + 54 " <td>" + obj.companyName + "</td>\n" + 55 " <td>" + obj.owner.firstName + " " + obj.owner.lastName + "</td>\n" + 56 " <td><input class=\"form-check-input\" type=\"checkbox\" value=\"" + obj.id +"\"></td>\n" + 57 " </tr>") 58 } 59 if (obj.businessStatus == "ACTIVE") { 60 $el.append("<tr>\n" + 61 " <th scope=\"row\">" + obj.id + "</th>\n" + 62 " <td>" + obj.companyName + "</td>\n" + 63 " <td>" + obj.owner.firstName + " " + obj.owner.lastName + "</td>\n" + 64 " <td><input class=\"form-check-input\" type=\"checkbox\" checked value=\"" + obj.id +"\"></td>\n" + 65 " </tr>") 66 } 67 }); 68 return data; 69 }); 70 } 55 71 }); -
Property mode
changed from
-
src/main/resources/static/js/bootstrap.bundle.min.js
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/main/resources/static/js/bootstrap.bundle.min.js.map
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/main/resources/static/js/business_admin.js
-
Property mode
changed from
100644
to100755
r950fa0d r77205be 1 1 $(document).ready(function() { 2 3 2 var business = {}; 4 3 5 $.ajax({ 6 url: "http://localhost:8080/api/business/me" 7 }).then(function (data) { 8 business = data; 9 var $header = $("#header"); 10 11 // header 12 $header.text($header.text() + " " + business["owner"]['firstName'] + " " + business['owner']['lastName']); 13 14 // business info 15 if(business['businessStatus'] == 'NEW') { 16 $('#new_business_warning').removeAttr("hidden"); 17 } 18 $('#business_status').val(business['businessStatus']); 19 $('#business_type').val(business['businessType']['text']); 20 21 // owner info 22 $('#firstName').val(business['owner']['firstName']); 23 $('#lastName').val(business['owner']['lastName']); 24 $('#email').val(business['owner']['email']); 25 $('#username').val(business['owner']['username']); 26 27 // services info 28 var $el = $("#predefined_services_admin_panel"); 29 $el.empty(); 30 $.each(business['services'], function (index, obj) { 31 $el.append( 32 '<div class=\"form-outline mb-4\">' + 33 ' <div class="row">' + 34 ' <div class="col-md-6">\n' + 35 ' <input class="form-check-input" type="checkbox" checked value=\"' + obj.id + '\" id=\"' + obj.id + '\">\n' + 36 ' <label class="form-check-label" for=\"' + obj.id + '\">\n' + 37 obj['serviceType'].name + 38 ' </label>\n' + 39 ' </div>' + 40 ' <div class=\"form-outline col-md-2 d-grid\">' + 41 ' <input type=\"text\" id=\"' + obj.id + obj['serviceType'].name.replace(/\s/g, "") + "duration" + '\" class=\"form-control\" placeholder="time" value=\"' + obj.duration + '" />' + 42 ' </div>' + 43 ' <div class=\"form-outline col-md-2 d-grid\">' + 44 ' <input type=\"text\" id=\"' + obj.id + obj['serviceType'].name.replace(/\s/g, "") + "price" + '\" class=\"form-control\" placeholder="price" value=\"' + obj.price + '" />' + 45 ' </div>' + 46 ' </div>' + 47 '</div>'); 48 }); 49 }); 4 getBusinessInfo(business); 5 6 getAppointments(); 50 7 51 8 $("#add_service").click(function () { … … 122 79 $("#update_owner_button").click(function() { 123 80 businesses = []; 124 console.log("Gjoko");125 81 business['owner']['firstName'] = $('#firstName').val(); 126 82 business['owner']['lastName'] = $('#lastName').val(); 127 83 business['owner']['email'] = $('#email').val(); 84 business['owner']['phoneNumber'] = $('#phoneNumber').val(); 128 85 business['owner']['username'] = $('#username').val(); 129 86 … … 147 104 event.preventDefault(); 148 105 }); 106 107 function cancelAppointment(appointmentId) { 108 if (confirm("Are you sure you want to cancel the appointment?")) { 109 $.ajax({ 110 url: "http://localhost:8080/api/appointment/" + appointmentId, 111 type:"DELETE" 112 }).success(function (data) { 113 alert("Appointment successfully canceled.") 114 getAppointments(); 115 }).error(function (error) { 116 alert("Something went wrong."); 117 }); 118 } 119 } 120 121 function getAppointments() { 122 $.ajax({ 123 url: "http://localhost:8080/api/appointment/future/me" 124 }).then(function (data) { 125 console.log(data); 126 var $el = $("#bookings-table-body"); 127 $el.empty(); 128 $.each(data, function (index, obj) { 129 var element = 130 '<tr>' + 131 ' <th scope="row">' + (parseInt(index) + 1) + '</th>' + 132 ' <td>' + obj['fullName'] + '</td>' + 133 ' <td>' + obj['email'] + '</td>' + 134 ' <td>' + obj['phoneNumber'] + '</td>' + 135 ' <td>' + obj['timePeriod'] + '</td>' + 136 ' <td>' + obj['serviceName'] + '</td>'; 137 138 switch (obj['status']) { 139 case 'NEW': 140 element += ' <td><button type="button" class="btn btn-danger" onclick="cancelAppointment(' + obj['appointmentId'] + ')">Cancel appointment</button></td>'; 141 break; 142 case 'CANCELLED_BY_CUSTOMER': 143 element += ' <td><button type="button" class="btn btn-secondary" disabled>Cancelled by customer</button></td>'; 144 break; 145 case 'CANCELLED_BY_BUSINESS_OWNER': 146 element += ' <td><button type="button" class="btn btn-secondary" disabled>Cancelled by business owner</button></td>'; 147 break; 148 } 149 element+='</tr>'; 150 151 $el.append(element); 152 }); 153 }); 154 } 155 156 function getBusinessInfo(business) { 157 $.ajax({ 158 url: "http://localhost:8080/api/business/me" 159 }).then(function (data) { 160 business = data; 161 var $header = $("#header"); 162 163 // header 164 $header.text($header.text() + " " + business["owner"]['firstName'] + " " + business['owner']['lastName']); 165 166 // business info 167 if(business['businessStatus'] == 'NEW') { 168 $('#new_business_warning').removeAttr("hidden"); 169 } 170 $('#business_status').val(business['businessStatus']); 171 $('#business_type').val(business['businessType']['text']); 172 173 // owner info 174 $('#firstName').val(business['owner']['firstName']); 175 $('#lastName').val(business['owner']['lastName']); 176 $('#phoneNumber').val(business['owner']['phoneNumber']); 177 $('#email').val(business['owner']['email']); 178 $('#username').val(business['owner']['username']); 179 180 // services info 181 var $el = $("#predefined_services_admin_panel"); 182 $el.empty(); 183 $.each(business['services'], function (index, obj) { 184 $el.append( 185 '<div class=\"form-outline mb-4\">' + 186 ' <div class="row">' + 187 ' <div class="col-md-6">\n' + 188 ' <input class="form-check-input" type="checkbox" checked value=\"' + obj.id + '\" id=\"' + obj.id + '\">\n' + 189 ' <label class="form-check-label" for=\"' + obj.id + '\">\n' + obj['serviceType'].name + '</label>\n' + 190 ' </div>' + 191 ' <div class=\"form-outline col-md-2 d-grid\">' + 192 ' <input type=\"text\" id=\"' + obj.id + obj['serviceType'].name.replace(/\s/g, "") + "duration" + '\" class=\"form-control\" placeholder="time" value=\"' + obj.duration + '" />' + 193 ' </div>' + 194 ' <div class=\"form-outline col-md-2 d-grid\">' + 195 ' <input type=\"text\" id=\"' + obj.id + obj['serviceType'].name.replace(/\s/g, "") + "price" + '\" class=\"form-control\" placeholder="price" value=\"' + obj.price + '" />' + 196 ' </div>' + 197 ' </div>' + 198 '</div>'); 199 }); 200 }); 201 } -
Property mode
changed from
-
src/main/resources/static/js/fullcalendar.js
r950fa0d r77205be 332 332 /* View Rendering 333 333 -----------------------------------------------------------------------------*/ 334 335 336 334 function changeView(newViewName) { 337 335 if (!currentView || newViewName != currentView.name) { … … 480 478 // TODO: going forward, most of this stuff should be directly handled by the view 481 479 482 483 480 function refetchEvents() { // can be called as an API method 484 481 clearEvents(); … … 538 535 } 539 536 540 541 542 537 /* Header Updating 543 538 -----------------------------------------------------------------------------*/ 544 545 546 539 function updateTitle() { 547 540 header.updateTitle(currentView.title); -
src/main/resources/static/js/homepage.js
-
Property mode
changed from
100644
to100755
r950fa0d r77205be 3 3 var businesses = {}; 4 4 var date = new Date(); 5 var selectedServices = {}; 6 var events = []; 5 7 var d = date.getDate(); 6 8 var m = date.getMonth(); … … 69 71 70 72 $("#companyType").change(function () { 73 resetRatingCard(); 71 74 var selectedVal = $(this).find(':selected').val(); 72 75 var selectedObj = businessTypes[selectedVal - 1]; … … 75 78 }).then(function (data) { 76 79 businesses = data; 77 console.log(data);78 80 var $el = $("#company"); 79 81 var $servicesEl = $("#service"); … … 84 86 $el.append("<option value=" + obj.id + ">" + obj.companyName + "</option>"); 85 87 }); 88 89 if (data && data.length === 1) { 90 selectedServices = data[0]["services"]; 91 resetAndAppendServices(selectedServices); 92 } 86 93 }); 87 94 }); 88 95 89 96 $("#company").change(function () { 97 resetRatingCard(); 90 98 var selectedVal = $(this).find(':selected').val(); 91 99 $.ajax({ 92 100 url: "http://localhost:8080/api/appointment/business/" + selectedVal 93 101 }).then(function (data) { 94 console.log(data); 95 var $el = $("#service"); 96 emptyDropdown($el); 97 98 var services = businesses.find(item => item.id == selectedVal)['services']; 99 console.log(services); 100 101 $.each(services, function (index, obj) { 102 $el.append("<option value=" + obj.id + ">" + obj.serviceType.name + "</option>"); 103 }); 104 }); 105 }); 106 102 // get already stored service from in-memory 103 selectedServices = businesses.find(item => item.id == selectedVal)['services']; 104 resetAndAppendServices(selectedServices); 105 }); 106 $('#calendar').fullCalendar('refetchEvents'); 107 }); 108 109 $("#service").change(function () { 110 var selectedVal = $("#service").find(':selected').val(); 111 var service = selectedServices.find(item => item.id == selectedVal); 112 setRatingCard(service['serviceType']['name'], service['rating'], service['reviewsCount'], selectedVal); 113 }); 114 115 $("#startdatetime").change(function() { 116 var date = new Date(document.getElementById("startdatetime").valueAsDate); 117 var selectedVal = $("#service").find(':selected').val(); 118 var minutes = selectedServices.find(item => item.id == selectedVal)['duration']; 119 date.setMinutes(date.getMinutes() + minutes); 120 document.getElementById("enddatetime").value = date.toISOString().slice(0, 16); 121 }); 107 122 108 123 /* initialize the calendar 109 124 -----------------------------------------------------------------*/ 110 111 var calendar = $('#calendar').fullCalendar({ 125 loadCalendar(); 126 127 resetRatingCard(); 128 129 $("#createAppointment").click(function() { 130 var appointment = {}; 131 var business = {}; 132 business['id'] = parseInt($("#company").val()); 133 appointment['service'] = {'id': parseInt($("#service").val()), 'business':business}; 134 appointment['startTime'] = $("#startdatetime").val(); 135 136 $.ajax({ 137 url: "http://localhost:8080/api/appointment", 138 type:"POST", 139 data: JSON.stringify(appointment), 140 contentType:"application/json; charset=utf-8", 141 dataType: 'text', 142 success: function(succ){ 143 alert("Successful appointment!"); 144 var companyId = parseInt($("#company").find(':selected').val()); 145 getAppointmentsByBusiness(companyId, events); 146 destroyCalendar(); 147 loadCalendar(events); 148 }, 149 error: function(error) { 150 alert(error.responseText); 151 } 152 }); 153 }); 154 155 }); 156 157 document.getElementById("login").addEventListener("click", function(event){ 158 window.location = "/login"; 159 }); 160 161 function resetAndAppendServices(services) { 162 var $el = $("#service"); 163 emptyDropdown($el); 164 165 $.each(services, function (index, obj) { 166 $el.append("<option value=" + obj.id + ">" + obj.serviceType.name + "</option>"); 167 }); 168 } 169 170 function emptyDropdown(element) { 171 var defaultOption = element.children().get(0); 172 element.children().remove(); 173 element.append(defaultOption); 174 } 175 176 /*loadCalendar([{'title': 'Gjoko', 'start': '2023-09-01 01:00:00', 'end': '2023-09-01 01:30:00', 'allDay':false, 'color': 'blue'}])*/ 177 178 function getAppointmentsByBusiness(businessId, events) { 179 $.ajax({ 180 url: "http://localhost:8080/api/appointment/business/" + businessId, 181 type:"GET", 182 contentType:"application/json; charset=utf-8", 183 dataType: 'text', 184 success: function(data){ 185 // reset events 186 events = []; 187 console.log(data); 188 $.each(JSON.parse(data), function (index, object) { 189 var event = {} 190 event['title'] = object['title']; 191 event['start'] = object['startTime'].replace('T', ' '); 192 event['end'] = object['endTime'].replace('T', ' '); 193 event['allDay'] = false; 194 event['color'] = 'blue'; 195 events.push(event); 196 }); 197 198 }, 199 error: function(error) { 200 console.log(error.responseText); 201 } 202 }); 203 } 204 205 function loadCalendar(events) { 206 $('#calendar').fullCalendar({ 112 207 header: { 113 208 left: 'title', … … 178 273 179 274 }, 180 181 events: [ 182 { 183 title: 'All Day Event', 184 start: new Date(y, m, 1) 185 }, 186 { 187 id: 999, 188 title: 'Repeating Event', 189 start: new Date(y, m, d-3, 16, 0), 190 allDay: false, 191 className: 'info' 192 }, 193 { 194 id: 999, 195 title: 'Repeating Event', 196 start: new Date(y, m, d+4, 16, 0), 197 allDay: false, 198 className: 'info' 199 }, 200 { 201 title: 'Meeting', 202 start: new Date(y, m, d, 10, 30), 203 allDay: false, 204 className: 'info' 205 }, 206 { 207 title: 'Lunch', 208 start: new Date(y, m, d, 12, 0), 209 end: new Date(y, m, d, 14, 0), 210 allDay: false, 211 className: 'info' 212 }, 213 { 214 title: 'Birthday Party', 215 start: new Date(y, m, d+1, 19, 0), 216 end: new Date(y, m, d+1, 22, 30), 217 allDay: false, 218 }, 219 { 220 title: 'Click for Google', 221 start: new Date(y, m, 28), 222 end: new Date(y, m, 29), 223 url: 'http://google.com/', 224 className: 'success' 225 } 226 ], 227 }); 228 229 $("#createAppointment").click(function() { 230 var appointment = {}; 231 appointment['business'] = {'id': parseInt($("#company").val())}; 232 appointment['service'] = {'id': parseInt($("#service").val())}; 233 appointment['startTime'] = $("#startdatetime").val(); 234 235 $.ajax({ 236 url: "http://localhost:8080/api/appointment", 237 type:"POST", 238 data: JSON.stringify(appointment), 239 contentType:"application/json; charset=utf-8", 240 dataType: 'text', 241 success: function(succ){ 242 console.log('success'); 243 }, 244 error: function(err) { 245 console.log(JSON.stringify(err)); 246 } 247 }); 248 }) 249 250 }); 251 252 document.getElementById("login").addEventListener("click", function(event){ 253 window.location = "/login"; 254 }); 255 256 function emptyDropdown(element) { 257 var defaultOption = element.children().get(0); 258 element.children().remove().end().append(defaultOption); 259 } 275 events: function (start, end, callback) { 276 var selectedVal = $("#company").find(':selected').val(); 277 if(!isNaN(parseInt(selectedVal))) { 278 $.ajax({ 279 url: "http://localhost:8080/api/appointment/business/" + selectedVal, 280 type:"GET", 281 contentType:"application/json; charset=utf-8", 282 dataType: 'text', 283 success: function(data){ 284 // reset events 285 var events = []; 286 $.each(JSON.parse(data), function (index, object) { 287 var event = {} 288 event['title'] = object['title']; 289 event['start'] = object['startTime'].replace('T', ' '); 290 event['end'] = object['endTime'].replace('T', ' '); 291 event['allDay'] = false; 292 event['color'] = '#3b71ca'; 293 event['textColor'] = '#FFFFFF'; 294 events.push(event); 295 }); 296 // load events 297 callback(events); 298 }, 299 error: function(error) { 300 console.log(error.responseText); 301 } 302 }); 303 } 304 }, 305 }); 306 } 307 308 function goToProfile() { 309 window.location = "/customer_admin"; 310 } 311 312 function destroyCalendar() { 313 $('#calendar').fullCalendar('destroy'); 314 } 315 316 function resetRatingCard() { 317 $('#rating-service-name').empty(); 318 $('#rating-value').empty(); 319 $('#rating-count').empty(); 320 $('#reviews-li').remove(); 321 } 322 323 function setRatingCard(name, value, count, serviceId) { 324 $('#rating-service-name').text(name); 325 $('#rating-value').text(value); 326 $('#rating-count').text(count); 327 $('#reviews-li').remove(); 328 getReviewsForService(serviceId); 329 330 } 331 332 function getReviewsForService(serviceId){ 333 $.ajax({ 334 url: "http://localhost:8080/api/review/" + serviceId 335 }).then(function (data) { 336 var $el = $("#reviewsModalBody"); 337 $('#reviews-ul').append($('<td class="form-outline mb-4"><button type="button" id="reviews-li" class="btn btn-primary btn-block" data-bs-toggle="modal" data-bs-target="#showReviewsModal">Checkout reviews</button></td>')); 338 $el.empty(); 339 340 $.each(data, function (index, obj) { 341 var element = '<div class="card m-3" style="max-width: 300px; padding: 0;">'; 342 element += '<div class="card-header" style="' + generateHeaderStyle(obj['rating']) + '">' + generateStars(obj['rating']) + '</div>'; 343 element += '<ul class="list-group list-group-flush">'; 344 element += '<li class="list-group-item"><i><b>Business:</b></i> ' + obj['businessName'] + '</li>'; 345 element += '<li class="list-group-item"><i><b>Service:</b></i> ' + obj['serviceName'] + '</li>'; 346 element += '<li class="list-group-item"><i><b>Reviewer:</b></i> ' + obj['customerName'] + '</li>'; 347 element += '<li class="list-group-item"><i><b>Comment:</b></i> ' + obj['comment'] + '</li>'; 348 element += '<li class="list-group-item"><small class="text-body-secondary"><i>Created:</i> ' + obj['created'] + '</small></li>'; 349 element += '</ul>'; 350 element += '</div>'; 351 352 $el.append(element); 353 }); 354 }); 355 } 356 357 function generateStars(number) { 358 return '☆'.repeat(number); 359 } 360 361 function generateHeaderStyle(number) { 362 var style = ''; 363 switch (number) { 364 case 5: 365 style = 'background-color: RGBA(13,110,253,var(--bs-bg-opacity,1)) !important; '; 366 break; 367 case 4: 368 style = 'background-color: RGBA(25,135,84,var(--bs-bg-opacity,1)) !important; '; 369 break; 370 case 3: 371 style = 'background-color: RGBA(108,117,125,var(--bs-bg-opacity,1)) !important; '; 372 break; 373 case 2: 374 style = 'background-color: RGBA(255,193,7,var(--bs-bg-opacity,1)) !important; '; 375 break; 376 case 1: 377 style = 'background-color: RGBA(220,53,69,var(--bs-bg-opacity,1)) !important; '; 378 break; 379 } 380 381 style += ' color: #fff !important;' 382 return style; 383 } -
Property mode
changed from
-
src/main/resources/static/js/login.js
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/main/resources/static/js/logout.js
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/main/resources/static/js/register_business.js
-
Property mode
changed from
100644
to100755
r950fa0d r77205be 75 75 ownerObj['username'] = $('#username').val(); 76 76 ownerObj['password'] = $('#password').val(); 77 ownerObj['phoneNumber'] = $('#phoneNumber').val(); 77 78 businessObj['owner'] = ownerObj; 78 79 … … 102 103 }); 103 104 businessObj['services'] = servicesObj; 105 console.log(businessObj); 104 106 $.ajax({ 105 107 url: "http://localhost:8080/api/business", … … 108 110 contentType:"application/json; charset=utf-8", 109 111 dataType: 'text', 110 success: function(succ ){112 success: function(success){ 111 113 alert( "Well done! You have finished the registration process. " + 112 114 "Please check periodically to see if the company has been approved." ); -
Property mode
changed from
-
src/main/resources/templates/admin.html
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/main/resources/templates/business_admin.html
-
Property mode
changed from
100644
to100755
r950fa0d r77205be 15 15 <header class="p-3 mb-3 border-bottom"> 16 16 <div class="row"> 17 <div class="col-md-10 mb-10" 17 <div class="col-md-10 mb-10"> 18 18 <span id="header"> 19 19 Welcome back … … 30 30 <nav> 31 31 <div class="nav nav-tabs" id="nav-tab" role="tablist"> 32 <a class="nav-link active" id="nav-business-tab" data-bs-toggle="tab" href="#nav-business" role="tab" aria-controls="nav-business" aria-selected="true">Business Info</a> 33 <a class="nav-link" id="nav-owner-tab" data-bs-toggle="tab" href="#nav-owner" role="tab" aria-controls="nav-owner" aria-selected="false">Owner Info</a> 34 <a class="nav-link" id="nav-services-tab" data-bs-toggle="tab" href="#nav-services" role="tab" aria-controls="nav-services" aria-selected="false">Services Info</a> 32 <a class="nav-link active" id="nav-business-tab" data-bs-toggle="tab" href="#nav-business" role="tab" 33 aria-controls="nav-business" aria-selected="true">Business Info</a> 34 <a class="nav-link" id="nav-owner-tab" data-bs-toggle="tab" href="#nav-owner" role="tab" 35 aria-controls="nav-owner" aria-selected="false">Owner Info</a> 36 <a class="nav-link" id="nav-services-tab" data-bs-toggle="tab" href="#nav-services" role="tab" 37 aria-controls="nav-services" aria-selected="false">Services Info</a> 38 <a class="nav-link" id="nav-appointments-tab" data-bs-toggle="tab" href="#nav-appointments" role="tab" 39 aria-controls="nav-appointments" aria-selected="false">Appointments</a> 35 40 </div> 36 41 </nav> … … 41 46 <label for="business_status">Business status</label> 42 47 <input type="text" id="business_status" disabled class="form-control" aria-label="business_status"/> 43 <p id="new_business_warning" style="color:darkorange;" hidden>Please wait for the admin to approve your business.</p> 48 <p id="new_business_warning" style="color:darkorange;" hidden>Please wait for the admin to approve your 49 business.</p> 44 50 </div> 45 51 … … 70 76 </div> 71 77 </div> 78 <!-- Phone number input --> 79 <div class="form-outline mb-4"> 80 <label for="phoneNumber">Phone number</label> 81 <input type="number" id="phoneNumber" class="form-control" placeholder="Phone number" 82 aria-label="phoneNumber"/> 83 </div> 84 72 85 <!-- Email input --> 73 86 <div class="form-outline mb-4"> … … 76 89 aria-label="Email"/> 77 90 </div> 78 <!-- Emailinput -->91 <!-- Username input --> 79 92 <div class="form-outline mb-4"> 80 93 <label for="username">Username</label> … … 97 110 <input type="text" id="input_service" class="form-control" 98 111 placeholder="Services" 99 aria-label="services" 112 aria-label="services"/> 100 113 </div> 101 114 </div> … … 111 124 </div> 112 125 </div> 126 <div class="tab-pane fade" id="nav-appointments" role="tabpanel" aria-labelledby="nav-appointments-tab"> 127 <div class="form-outline col-lg-12 row"> 128 <div class="form-outline col-lg-12"> 129 <div class="table-responsive"> 130 <table class="table"> 131 <thead> 132 <tr> 133 <th scope="col">#</th> 134 <th scope="col">Full name</th> 135 <th scope="col">Email</th> 136 <th scope="col">Phone number</th> 137 <th scope="col">Time period</th> 138 <th scope="col">Service</th> 139 <th scope="col">Action</th> 140 </tr> 141 </thead> 142 <tbody id="bookings-table-body"> 143 </tbody> 144 </table> 145 </div> 146 </div> 147 </div> 148 </div> 113 149 </div> 114 150 <script src='js/jquery-1.10.2.js' type="text/javascript"></script> -
Property mode
changed from
-
src/main/resources/templates/homepage.html
-
Property mode
changed from
100644
to100755
r950fa0d r77205be 16 16 <link href='css/fullcalendar.print.css' rel='stylesheet' media='print'/> 17 17 <link href="css/homepage.css" rel="stylesheet"/> 18 <link href="css/headers.css" rel="stylesheet" >18 <link href="css/headers.css" rel="stylesheet" /> 19 19 </head> 20 20 <body> … … 27 27 </div> 28 28 <div class="col-md-2 mb-2"> 29 <button id="profile" class="btn btn-primary btn-block" >29 <button id="profile" class="btn btn-primary btn-block" onclick="goToProfile()"> 30 30 Profile 31 31 </button> … … 70 70 <div class="form-outline mb-4"> 71 71 <label for="startdatetime">Start:</label> 72 <input type="datetime-local" id="startdatetime" name="startdatetime"> 72 <input type="datetime-local" id="startdatetime" name="startdatetime" style="float:right;"> 73 </div> 74 <div class="form-outline mb-4"> 75 <label for="enddatetime">End:</label> 76 <input type="datetime-local" id="enddatetime" name="enddatetime" style="float:right;"> 73 77 </div> 74 78 <div class="form-outline mb-4"> … … 78 82 </div> 79 83 </div> 84 <div class="card form-outline mb-4" style="margin-top:30px;" > 85 <ul class="list-group list-group-flush" id="reviews-ul"> 86 <li class="list-group-item"><b>service name: </b><span id="rating-service-name"></span></li> 87 <li class="list-group-item"><b>rating </b><span id="rating-value"></span></li> 88 <li class="list-group-item" style="margin-bottom:10px;"><b>reviews count </b><span id="rating-count"></span></li> 89 <li class="list-group-item" id="reviews-li"><a href="#/reviews_page">Checkout reviews</a></li> 90 </ul> 91 </div> 80 92 93 </div> 94 <div class="modal fade" id="showReviewsModal" tabindex="-1" aria-labelledby="showReviewsModalLabel" aria-hidden="true"> 95 <div class="modal-dialog modal-xl modal-dialog-scrollable modal-dialog-centered" > 96 <div class="modal-content"> 97 <div class="modal-header"> 98 <h1>Reviews</h1> 99 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> 100 </div> 101 <div class="modal-body form-outline col-lg-12 row" id="reviewsModalBody" style="--mdb-gutter-x: 0 !important; background-color: #f0f0f0 !important;"> 102 <div class="card m-3" style="max-width: 300px; padding: 0;"> 103 <div class="card-header text-bg-success"> 104 ☆☆☆☆☆ 105 </div> 106 <ul class="list-group list-group-flush"> 107 <li class="list-group-item"><i>Business:</i> Businessname<</li> 108 <li class="list-group-item"><i>Service:</i> Customer Name</li> 109 <li class="list-group-item"><i>Reviewer:</i> Customer Name</li> 110 <li class="list-group-item"><i>Comment:</i> Lorem ipsum diem amet</li> 111 <li class="list-group-item"><small class="text-body-secondary">Created on 29-11-2023T11:32:23</small></li> 112 </ul> 113 </div> 114 </div> 115 <div class="modal-footer"> 116 <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button> 117 </div> 118 </div> 119 </div> 81 120 </div> 82 121 <script src='js/jquery-1.10.2.js' type="text/javascript"></script> -
Property mode
changed from
-
src/main/resources/templates/login.html
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
-
src/main/resources/templates/register_business.html
-
Property mode
changed from
100644
to100755
r950fa0d r77205be 44 44 </div> 45 45 </div> 46 </div> 47 48 <!-- Phone number input --> 49 <div class="form-outline mb-4"> 50 <input type="number" id="phoneNumber" class="form-control" placeholder="Phone number" 51 aria-label="phonenumber"/> 46 52 </div> 47 53 -
Property mode
changed from
-
src/main/resources/templates/register_customer.html
-
Property mode
changed from
100644
to100755
r950fa0d r77205be 67 67 </div> 68 68 69 <!-- Phone number input --> 70 <div class="form-outline mb-4"> 71 <input type="number" id="phoneNumber" class="form-control" required th:field="*{phoneNumber}" /> 72 <label class="form-label" for="phoneNumber">Phone Number</label> 73 </div> 74 69 75 <!-- Email input --> 70 76 <div class="form-outline mb-4"> -
Property mode
changed from
-
src/test/java/edu/gjoko/schedlr/SchedlrApplicationTests.java
-
Property mode
changed from
100644
to100755
-
Property mode
changed from
Note:
See TracChangeset
for help on using the changeset viewer.