diff --git a/.env.example b/.env.example deleted file mode 100644 index f9a270e0..00000000 --- a/.env.example +++ /dev/null @@ -1,15 +0,0 @@ -TWILIO_ACCOUNT_SID=valor-twilio -TWILIO_AUTH_TOKEN=valor-twilio -TWILIO_VERIFY_SERVICE_SID=valor-twilio - -#Constantes para api de NSFW -X_RAPIDAPI_KEY=chave -X_RAPIDAPI_HOST=nsfw-image-classification1.p.rapidapi.com - -CLOUDINARY_CLOUD_NAME=valor-cloudinary -CLOUDINARY_API_KEY=valor-cloudinary -CLOUDINARY_API_SECRET=valor-cloudinary - -PERSPECTIVE_API_KEY=valor-perspective - -RECAPTCHA_SITE_KEY=valor-recaptcha diff --git a/src/main/java/br/edu/utfpr/servicebook/controller/ClientController.java b/src/main/java/br/edu/utfpr/servicebook/controller/ClientController.java index e4966ad3..f203517c 100644 --- a/src/main/java/br/edu/utfpr/servicebook/controller/ClientController.java +++ b/src/main/java/br/edu/utfpr/servicebook/controller/ClientController.java @@ -16,6 +16,7 @@ import br.edu.utfpr.servicebook.util.pagination.PaginationUtil; import br.edu.utfpr.servicebook.util.UserTemplateInfo; import br.edu.utfpr.servicebook.util.TemplateUtil; +import com.cloudinary.utils.ObjectUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -24,18 +25,29 @@ import org.springframework.data.domain.Sort; import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException; import org.springframework.stereotype.Controller; +import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.support.RedirectAttributes; import javax.annotation.security.RolesAllowed; import javax.persistence.EntityNotFoundException; import javax.servlet.http.HttpServletRequest; +import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.text.ParseException; import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.Arrays; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; +import br.edu.utfpr.servicebook.util.DateUtil; +import com.cloudinary.Cloudinary; +import com.cloudinary.utils.ObjectUtils; @RequestMapping("/minha-conta/cliente") @Controller @@ -104,7 +116,23 @@ public class ClientController { @Autowired private ProfessionalMapper professionalMapper; + @Autowired + private ServiceService serviceService; + + @Autowired + private CategoryService categoryService; + + @Autowired + private AssessmentProfessionalService assessmentProfessionalService; + + @Autowired + private AssessmentProfessionalFileService assessmentProfessionalFileService; + @Autowired + private Cloudinary cloudinary; + + @Autowired + private AssessmentProfessionalFileMapper assessmentProfessionalFileMapper; /** * Método que apresenta a tela inicial do cliente * @return @@ -258,12 +286,25 @@ public ModelAndView showDetailsRequestCandidate(@PathVariable Optional job JobCandidateDTO jobCandidateDTO = jobCandidateMapper.toDto(jobCandidate.get()); UserDTO clientDTO = userMapper.toDto(oClient.get()); + List assessmentProfessional = assessmentProfessionalService.findAllByProfessional(oCandidate.get()); + Double starsQuality = assessmentProfessionalService.getFindByProfessional(oCandidate.get()); + Double starsPunctuality = assessmentProfessionalService.getFindByProfessionalPunctuality(oCandidate.get()); + + Double starsProfessional = assessmentProfessionalService.calculateAveragePunctualityAndQualitySumByProfessional(oCandidate.get()); + + // if (assessmentProfessional.isPresent()) { +// mv.addObject("assessmentProfessional", assessmentProfessional.get()); +// } List follows = followsService.findFollowProfessionalClient(oCandidate.get(), oClient.get()); boolean isFollow = !follows.isEmpty(); System.out.println(jobCandidateDTO.getId()); mv.addObject("jobCandidate", jobCandidateDTO); mv.addObject("isFollow", isFollow); mv.addObject("client", clientDTO); + mv.addObject("assessmentProfessional", assessmentProfessional); + mv.addObject("starsQuality", starsQuality); + mv.addObject("starsPunctuality", starsPunctuality); + mv.addObject("starsProfessional", starsProfessional); return mv; } @@ -739,7 +780,7 @@ public String markAsClose( * Altera o estado de um serviço para TO_HIRED, ou seja, o cliente contratou um serviço mas * fica no estado de espera da confirmação do profissional. * @param jobId - * @param individualId + * @param userId * @param redirectAttributes * @return * @throws IOException @@ -776,4 +817,198 @@ public String markAsHided(@PathVariable Long jobId, @PathVariable Long userId, R return "redirect:/minha-conta/cliente/meus-pedidos/"+jobId; } + + /** + * O cliente escolhe um profissional para realizar o orçamento ou cancela a escolha do profissional para orçamento. + * * + * @param servicoId + * @param candidateId + * @param redirectAttributes + * @return + * @throws IOException + */ + @PatchMapping("/orcamento-ao/{candidateId}/para/servico/{servicoId}") + @RolesAllowed({RoleType.USER, RoleType.COMPANY}) + public String markAsBudgetAndCreateJobRequest(@PathVariable Long candidateId, @PathVariable Long servicoId, RedirectAttributes redirectAttributes) throws IOException { + Optional oClientAuthenticated = (userService.findByEmail(authentication.getEmail())); + + if(!oClientAuthenticated.isPresent()){ + return "redirect:/login"; + } + Optional oService = serviceService.findById(servicoId); + + if (!oService.isPresent()) { + throw new EntityNotFoundException("Serviço não encontrado"); + } + + Optional oIndividual = individualService.findById(candidateId); + if (!oIndividual.isPresent()) { + throw new EntityNotFoundException("Usuário não encontrado"); + } + + JobRequest jobRequest = new JobRequest(); + jobRequest.setExpertise(oService.get().getExpertise()); + jobRequest.setUser(oClientAuthenticated.get()); + jobRequest.setStatus(JobRequest.Status.BUDGET); + jobRequest.setQuantityCandidatorsMax(1); + jobRequest.setDateCreated(DateUtil.getToday()); + jobRequest.setDateTarget(DateUtil.getNextMonth()); + + jobRequest.setClientConfirmation(true); + jobRequest.setProfessionalConfirmation(true); + jobRequestService.save(jobRequest); + + JobCandidate jobCandidate = new JobCandidate(jobRequest, oIndividual.get()); + jobCandidate.setChosenByBudget(true); + jobCandidateService.save(jobCandidate); + + return "redirect:/minha-conta/cliente#paraOrcamento"; + } + + /** + * Altera o estado de um serviço para TO_HIRED, ou seja, o cliente contratou um serviço mas + * fica no estado de espera da confirmação do profissional. + * @param jobId + * @param userId + * @param redirectAttributes + * @return + * @throws IOException + */ + @PatchMapping("/contrata/{userId}/para/servico/{jobId}") + @RolesAllowed({RoleType.USER, RoleType.COMPANY}) + public String markAsHideAndCreateJobRequest(@PathVariable Long jobId, @PathVariable Long userId, RedirectAttributes redirectAttributes) throws IOException { + Optional oClientAuthenticated = (userService.findByEmail(authentication.getEmail())); + + if(!oClientAuthenticated.isPresent()){ + return "redirect:/login"; + } + Optional oService = serviceService.findById(jobId); + + if (!oService.isPresent()) { + throw new EntityNotFoundException("Serviço não encontrado"); + } + + Optional oIndividual = individualService.findById(userId); + if (!oIndividual.isPresent()) { + throw new EntityNotFoundException("Usuário não encontrado"); + } + + JobRequest jobRequest = new JobRequest(); + jobRequest.setExpertise(oService.get().getExpertise()); + jobRequest.setUser(oClientAuthenticated.get()); + jobRequest.setStatus(JobRequest.Status.TO_DO); + jobRequest.setQuantityCandidatorsMax(1); + jobRequest.setDateCreated(DateUtil.getToday()); + jobRequest.setDateTarget(DateUtil.getNextMonth()); + + jobRequest.setClientConfirmation(true); + jobRequest.setProfessionalConfirmation(true); + jobRequestService.save(jobRequest); + + JobCandidate jobCandidate = new JobCandidate(jobRequest, oIndividual.get()); + jobCandidate.setChosenByBudget(true); + jobCandidateService.save(jobCandidate); + + JobContracted jobContracted = new JobContracted(); + jobContracted.setJobRequest(jobRequest); + jobContracted.setUser(oIndividual.get()); + jobContracted.setHiredDate(DateUtil.getToday()); + jobContracted.setTodoDate(DateUtil.getToday().plusDays(10)); + jobContractedService.save(jobContracted); + + return "redirect:/minha-conta/cliente#paraFazer"; + } + + /** + * Avalia o serviço depois de finalizado + * @param jobId + * @param redirectAttributes + * @return + * @throws IOException + */ + @GetMapping("/avaliar/servico/{jobId}/profissional/{profissionalId}") + @RolesAllowed({RoleType.USER, RoleType.COMPANY}) + public ModelAndView evaluateService(@PathVariable Long jobId, @PathVariable Long profissionalId, RedirectAttributes redirectAttributes) throws IOException { + Optional oClientAuthenticated = (userService.findByEmail(authentication.getEmail())); + ModelAndView mv = new ModelAndView("client/evaluate-jobs"); + + if(!oClientAuthenticated.isPresent()){ + return mv.addObject("visitor/login"); + } + + Optional oJobRequest = jobRequestService.findById(jobId); + + Optional oIndividual = userService.findById(profissionalId); + Optional oJobContracted = jobContractedService.findByJobRequest(oJobRequest.get()); + + if (!oJobRequest.isPresent()) { + throw new EntityNotFoundException("Job não encontrado"); + } + mv.addObject("job", oJobRequest.get()); + mv.addObject("professional", oIndividual.get()); + mv.addObject("jobContracted", oJobContracted.get()); + + return mv; + } + + /** + * @param jobId + * @param profissionalId + * @param dto + * @param redirectAttributes + * @return + * @throws IOException + * @throws ParseException + */ + @PostMapping("/avaliar/servico/{jobId}/profissional/{profissionalId}") + @RolesAllowed({RoleType.USER}) + public String saveAssessmentProfessional( + @PathVariable Long profissionalId, + @PathVariable Long jobId, + AssessmentProfessionalDTO dto, + AssessmentProfessionalFileDTO dtoFiles, + RedirectAttributes redirectAttributes, + BindingResult errors + ) throws IOException, ParseException { + String currentUserEmail = authentication.getEmail(); + + Optional oindividual = individualService.findById(profissionalId); + Optional oClliente = individualService.findByEmail(currentUserEmail); + + if(!oindividual.isPresent()){ + throw new EntityNotFoundException("O usuário não foi encontrado!"); + } + + Optional oJobRequest = jobRequestService.findById(jobId); + + AssessmentProfessional assessmentProfessional = new AssessmentProfessional(); + assessmentProfessional.setComment(dto.getComment()); + assessmentProfessional.setProfessional(oindividual.get()); + assessmentProfessional.setQuality(dto.getQuality()); + assessmentProfessional.setPunctuality(dto.getPunctuality()); + assessmentProfessional.setDate(dto.getDate()); + assessmentProfessional.setClient(oClliente.get()); + assessmentProfessional.setJobRequest(oJobRequest.get()); + assessmentProfessionalService.save(assessmentProfessional); + + AssessmentProfessionalFiles assessmentProfessionalFiles = assessmentProfessionalFileMapper.toEntity(dtoFiles); + assessmentProfessionalFiles.setAssessmentProfessional(assessmentProfessional); + assessmentProfessionalFileService.save(assessmentProfessionalFiles); + + redirectAttributes.addFlashAttribute("msg", "Avaliação realizada com sucesso!"); + + return "redirect:/minha-conta/cliente#executados"; + } + + public boolean isValidateImage(MultipartFile image){ + List contentTypes = Arrays.asList("image/png", "image/jpg", "image/jpeg"); + + for(int i = 0; i < contentTypes.size(); i++){ + if(image.getContentType().toLowerCase().startsWith(contentTypes.get(i))){ + return true; + } + } + + return false; + } } \ No newline at end of file diff --git a/src/main/java/br/edu/utfpr/servicebook/controller/IndexController.java b/src/main/java/br/edu/utfpr/servicebook/controller/IndexController.java index e1c2b3bd..922385d1 100644 --- a/src/main/java/br/edu/utfpr/servicebook/controller/IndexController.java +++ b/src/main/java/br/edu/utfpr/servicebook/controller/IndexController.java @@ -1,7 +1,13 @@ package br.edu.utfpr.servicebook.controller; +import br.edu.utfpr.servicebook.model.dto.CategoryDTO; +import br.edu.utfpr.servicebook.model.dto.ExpertiseDTO; import br.edu.utfpr.servicebook.model.dto.JobRequestFullDTO; +import br.edu.utfpr.servicebook.model.dto.ServiceDTO; import br.edu.utfpr.servicebook.model.entity.*; +import br.edu.utfpr.servicebook.model.mapper.CategoryMapper; +import br.edu.utfpr.servicebook.model.mapper.ExpertiseMapper; +import br.edu.utfpr.servicebook.model.mapper.ServiceMapper; import br.edu.utfpr.servicebook.security.IAuthentication; import br.edu.utfpr.servicebook.security.RoleType; import br.edu.utfpr.servicebook.service.*; @@ -15,20 +21,20 @@ import org.springframework.data.domain.Page; import org.springframework.security.authentication.AnonymousAuthenticationToken; import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.support.RedirectAttributes; import javax.annotation.security.PermitAll; import javax.annotation.security.RolesAllowed; +import javax.persistence.EntityNotFoundException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; @RequestMapping("/") @Controller @@ -61,6 +67,20 @@ public class IndexController { @Autowired private HttpSession httpSession; + @Autowired + private CategoryService categoryService; + + @Autowired + private CategoryMapper categoryMapper; + + @Autowired + private ExpertiseMapper expertiseMapper; + + @Autowired + private ServiceService serviceService; + + @Autowired + private ServiceMapper serviceMapper; @GetMapping @PermitAll public ModelAndView showIndexPage(HttpServletResponse response) { @@ -81,6 +101,11 @@ public ModelAndView showIndexPage(HttpServletResponse response) { return new ModelAndView("redirect:/minha-conta/empresa/disponiveis"); } } + //lista de categorias + List categories = categoryService.findAll(); + List categoryDTOs = categories.stream() + .map(s -> categoryMapper.toDto(s)) + .collect(Collectors.toList()); List cities = cityService.findAll(); mv.addObject("cities", cities); @@ -90,6 +115,7 @@ public ModelAndView showIndexPage(HttpServletResponse response) { mv.addObject("totalJobContracted", jobContractedService.countAll()); mv.addObject("totalProfessionals", userService.countProfessionals()); mv.addObject("totalClients", userService.countUsersWithoutExpertise()); + mv.addObject("categories", categoryDTOs); return mv; } @@ -101,8 +127,6 @@ public String showClientPage(HttpSession httpSession, RedirectAttributes redirec return "redirect:/"; } - - @GetMapping("/bem-vindo") @PermitAll public ModelAndView showWelcomePage() { @@ -122,4 +146,36 @@ public String notAuthorized() { return "error/not-authorized"; } + @GetMapping("/especialidades/categoria/{categoryId}") + @PermitAll + @ResponseBody + public List showExpertisesByCategory(@PathVariable Long categoryId) throws Exception { + Optional oCategory = categoryService.findById(categoryId); + + Category category = categoryService.findById(categoryId).orElseThrow(() -> new EntityNotFoundException("Categoria não encontrada")); + + List expertises = expertiseService.findByCategoryId(categoryId); + + List expertiseDTOS = expertises.stream() + .map(s -> expertiseMapper.toDto(s)) + .collect(Collectors.toList()); + + return expertiseDTOS; + } + + @GetMapping("/servicos/especialidade/{expertiseId}") + @PermitAll + @ResponseBody + public List showServicesByExpertise(@PathVariable Long expertiseId) throws Exception { + + Expertise expertise = expertiseService.findById(expertiseId).orElseThrow(() -> new EntityNotFoundException("Especialidade não encontrada")); + + List services = serviceService.findByExpertise(expertise); + + List servicesDTO = services.stream() + .map(s -> serviceMapper.toDto(s)) + .collect(Collectors.toList()); + + return servicesDTO; + } } \ No newline at end of file diff --git a/src/main/java/br/edu/utfpr/servicebook/controller/ProfessionalController.java b/src/main/java/br/edu/utfpr/servicebook/controller/ProfessionalController.java index e64b516c..b2a6f425 100644 --- a/src/main/java/br/edu/utfpr/servicebook/controller/ProfessionalController.java +++ b/src/main/java/br/edu/utfpr/servicebook/controller/ProfessionalController.java @@ -2,10 +2,7 @@ import br.edu.utfpr.servicebook.model.dto.*; import br.edu.utfpr.servicebook.model.entity.*; -import br.edu.utfpr.servicebook.model.mapper.IndividualMapper; -import br.edu.utfpr.servicebook.model.mapper.JobContractedMapper; -import br.edu.utfpr.servicebook.model.mapper.ProfessionalServiceOfferingMapper; -import br.edu.utfpr.servicebook.model.mapper.UserMapper; +import br.edu.utfpr.servicebook.model.mapper.*; import br.edu.utfpr.servicebook.security.IAuthentication; import br.edu.utfpr.servicebook.service.*; @@ -15,8 +12,10 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.data.domain.Page; import org.springframework.stereotype.Controller; +import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; import javax.annotation.security.PermitAll; import javax.persistence.EntityNotFoundException; @@ -73,6 +72,22 @@ public class ProfessionalController { @Autowired private PaginationUtil paginationUtil; + @Autowired + private ServiceService serviceService; + + @Autowired + private ExpertiseService expertiseService; + + @Autowired + private CategoryService categoryService; + + @Autowired + private CategoryMapper categoryMapper; + + + @Autowired + private ExpertiseMapper expertiseMapper; + @GetMapping @PermitAll protected ModelAndView showAll() throws Exception { @@ -106,7 +121,7 @@ protected ModelAndView showAll() throws Exception { * Retorna a lista de profissionais de acordo com o termo de busca. * Se estiver logado, o usuário poderá ter acesso a todos os profissionais de acordo com a sua busca. * Caso seja um visitante, terá acesso a apenas 4 profissionais. - * @param searchTerm + * @param searchService * @param page * @return * @throws Exception @@ -114,8 +129,12 @@ protected ModelAndView showAll() throws Exception { @GetMapping(value = "/busca") @PermitAll protected ModelAndView showSearchResults( - @RequestParam(value = "termo-da-busca") String searchTerm, - @RequestParam(value = "pag", defaultValue = "1") int page +// @RequestParam(value = "termo-da-busca") String searchTerm, + @RequestParam(defaultValue = "0", value = "serviceId") Long searchService, + @RequestParam(defaultValue = "", value = "expertiseId") Long searchExpertise, + @RequestParam(defaultValue = "", value = "categoryId") Long searchCategory, + @RequestParam(value = "pag", defaultValue = "1") int page, + RedirectAttributes redirectAttributes ) throws Exception { ModelAndView mv = new ModelAndView("visitor/search-results"); @@ -132,17 +151,45 @@ protected ModelAndView showSearchResults( page = 1; size = this.paginationSizeVisitor; } + if(searchService == 0){ + redirectAttributes.addFlashAttribute("msg", "A atualização foi salva com sucesso!"); + } else { - Page professionals = individualService.findDistinctByTermIgnoreCaseWithPagination(searchTerm, page, size); - List professionalSearchItemDTOS = professionals.stream() - .map(s -> individualMapper.toSearchItemDto(s, individualService.getExpertises(s))) - .collect(Collectors.toList()); + Optional service = serviceService.findById(searchService); + Optional expertise = expertiseService.findById(searchExpertise); + Optional category = categoryService.findById(searchCategory); + + Page professionals = individualService.findAllIndividualsByService(service.get(), page, size); + Page professionalServiceOfferings = professionalServiceOfferingService.findAllIndividualsByService(service.get(), page, size); + + List professionalSearchItemDTOS = professionals.stream() + .map(s -> individualMapper.toSearchItemDto(s, individualService.getExpertises(s))) + .collect(Collectors.toList()); + + List professionalServiceOfferingDTOS = professionalServiceOfferings.stream() + .map(s -> professionalServiceOfferingMapper.toDTO(s)).collect(Collectors.toList()); + + //lista de categorias + List categories = categoryService.findAll(); + List categoryDTOs = categories.stream() + .map(s -> categoryMapper.toDto(s)) + .collect(Collectors.toList()); - PaginationDTO paginationDTO = paginationUtil.getPaginationDTO(professionals, "/profissionais/busca?termo-da-busca="+ searchTerm); - mv.addObject("professionals", professionalSearchItemDTOS); - mv.addObject("pagination", paginationDTO); - mv.addObject("isParam", true); - mv.addObject("searchTerm", searchTerm); + PaginationDTO paginationDTO = paginationUtil.getPaginationDTO(professionals, "/profissionais/busca?categoryId=" + searchCategory + "&expertiseId=" + searchExpertise + "&serviceId=" + searchService); + + mv.addObject("professionals", professionalSearchItemDTOS); + mv.addObject("categoryDTOs", categoryDTOs); + mv.addObject("pagination", paginationDTO); + mv.addObject("isParam", true); + mv.addObject("service", service.get().getName()); + mv.addObject("searchTerm", searchService); + mv.addObject("dto_expertise", expertise.get()); + mv.addObject("dto", category.get()); + mv.addObject("dto_service", service.get()); + + mv.addObject("professionalServiceOfferingDTOS", professionalServiceOfferingDTOS); + + } return mv; } @@ -208,4 +255,49 @@ protected ModelAndView showProfessionalDetailsToVisitors(@PathVariable("id") Lon } return mv; } + + @GetMapping("busca/todos") + @PermitAll + protected ModelAndView showProfessionalsServices( + @RequestParam(defaultValue = "0", value = "serviceId") Long searchService, + @RequestParam(defaultValue = "", value = "expertiseId") Long searchExpertise, + @RequestParam(defaultValue = "", value = "categoryId") Long searchCategory) throws Exception { + + //cliente autenticado, caso esteja logado + Optional oClientAuthenticated = (userService.findByEmail(authentication.getEmail())); + + ModelAndView mv = new ModelAndView("visitor/professionals-services"); + mv.addObject("logged", oClientAuthenticated.isPresent()); + if(!oClientAuthenticated.isPresent()){ + return new ModelAndView("visitor/login"); + } + + Optional expertise = expertiseService.findById(searchExpertise); + + //se o cliente está logado, mostra se ele segue o profissional + if(oClientAuthenticated.isPresent()){ + UserDTO clientDTO = userMapper.toDto(oClientAuthenticated.get()); + mv.addObject("client", clientDTO); + } + Optional service = serviceService.findById(searchService); + + List professionals = individualService.findAllIndividualsByService(service.get()); + + List professionalServiceOfferings = professionalServiceOfferingService.findAllIndividualsByService(service.get()); + + List professionalSearchItemDTOS = professionals.stream() + .map(s -> individualMapper.toSearchItemDto(s, individualService.getExpertises(s))) + .collect(Collectors.toList()); + + List professionalServiceOfferingDTOS = professionalServiceOfferings.stream() + .map(s -> professionalServiceOfferingMapper.toDTO(s)).collect(Collectors.toList()); + + Optional countProfessionals = professionalServiceOfferingService.countAllByService(service.get()); + + mv.addObject("expertise", expertise.get()); + mv.addObject("professionalServiceOfferingDTOS", professionalServiceOfferingDTOS); + mv.addObject("countProfessionals", countProfessionals.get()); + + return mv; + } } diff --git a/src/main/java/br/edu/utfpr/servicebook/model/dto/AssessmentProfessionalDTO.java b/src/main/java/br/edu/utfpr/servicebook/model/dto/AssessmentProfessionalDTO.java new file mode 100644 index 00000000..38bd7820 --- /dev/null +++ b/src/main/java/br/edu/utfpr/servicebook/model/dto/AssessmentProfessionalDTO.java @@ -0,0 +1,40 @@ +package br.edu.utfpr.servicebook.model.dto; + +import br.edu.utfpr.servicebook.model.entity.JobRequest; +import br.edu.utfpr.servicebook.model.entity.User; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; + +import java.io.Serializable; +import java.time.LocalDate; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@ToString +public class AssessmentProfessionalDTO implements Serializable { + private Long id; + + private float punctuality; + + private float quality; + + private String comment; + + private LocalDate date; + + private Long professionalId; + + private User professional; + + private Long clientId; + + private User client; + + private Long jobRequestId; + + private JobRequest jobRequest; + +} diff --git a/src/main/java/br/edu/utfpr/servicebook/model/dto/AssessmentProfessionalFileDTO.java b/src/main/java/br/edu/utfpr/servicebook/model/dto/AssessmentProfessionalFileDTO.java new file mode 100644 index 00000000..200bd23f --- /dev/null +++ b/src/main/java/br/edu/utfpr/servicebook/model/dto/AssessmentProfessionalFileDTO.java @@ -0,0 +1,32 @@ +package br.edu.utfpr.servicebook.model.dto; + +import br.edu.utfpr.servicebook.model.entity.AssessmentProfessional; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import org.springframework.web.multipart.MultipartFile; + +import java.io.Serializable; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@ToString +public class AssessmentProfessionalFileDTO implements Serializable { + private Long id; + +// private String path; + +// private String video; + private String pathIcon; + private String pathVideos; + + private MultipartFile pathImage; + + private MultipartFile pathVideo; + + private Long assessmentProfessionalId; + + private AssessmentProfessional assessmentProfessional; +} diff --git a/src/main/java/br/edu/utfpr/servicebook/model/dto/ExpertiseMinDTO.java b/src/main/java/br/edu/utfpr/servicebook/model/dto/ExpertiseMinDTO.java index b831a082..b789a186 100644 --- a/src/main/java/br/edu/utfpr/servicebook/model/dto/ExpertiseMinDTO.java +++ b/src/main/java/br/edu/utfpr/servicebook/model/dto/ExpertiseMinDTO.java @@ -12,5 +12,6 @@ public class ExpertiseMinDTO implements Serializable { private String name; + private Long categoryId; } diff --git a/src/main/java/br/edu/utfpr/servicebook/model/dto/JobCandidateDTO.java b/src/main/java/br/edu/utfpr/servicebook/model/dto/JobCandidateDTO.java index 8c068b70..7ba06478 100644 --- a/src/main/java/br/edu/utfpr/servicebook/model/dto/JobCandidateDTO.java +++ b/src/main/java/br/edu/utfpr/servicebook/model/dto/JobCandidateDTO.java @@ -18,5 +18,7 @@ public class JobCandidateDTO implements Serializable { private UserDTO user; + private String individual; + private boolean chosenByBudget; } diff --git a/src/main/java/br/edu/utfpr/servicebook/model/dto/ProfessionalServiceOfferingDTO.java b/src/main/java/br/edu/utfpr/servicebook/model/dto/ProfessionalServiceOfferingDTO.java index 01c3d995..e13439c7 100644 --- a/src/main/java/br/edu/utfpr/servicebook/model/dto/ProfessionalServiceOfferingDTO.java +++ b/src/main/java/br/edu/utfpr/servicebook/model/dto/ProfessionalServiceOfferingDTO.java @@ -43,7 +43,10 @@ public class ProfessionalServiceOfferingDTO { private ServiceDTO service; private Long serviceId; - + /** + * Preço do serviço individual. + */ + private Long price; /** * Profissional que oferece o serviço. */ diff --git a/src/main/java/br/edu/utfpr/servicebook/model/entity/AssessmentProfessional.java b/src/main/java/br/edu/utfpr/servicebook/model/entity/AssessmentProfessional.java new file mode 100644 index 00000000..dcacb6eb --- /dev/null +++ b/src/main/java/br/edu/utfpr/servicebook/model/entity/AssessmentProfessional.java @@ -0,0 +1,46 @@ +package br.edu.utfpr.servicebook.model.entity; + +import lombok.Data; +import lombok.NoArgsConstructor; +import br.edu.utfpr.servicebook.model.entity.JobRequest; +import br.edu.utfpr.servicebook.model.entity.User; +import javax.persistence.*; +import java.io.Serializable; +import java.time.LocalDate; + +@Data +@NoArgsConstructor +@Table(name = "assessment_professionals") +@Entity +public class AssessmentProfessional { + private static final long serialVersionUID = 1L; + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private float punctuality; + + private float quality; + + private String comment; + + private LocalDate date; + + @PrePersist + public void onPersist() { + this.date = LocalDate.now(); + } + + @ManyToOne + @JoinColumn(name = "professional_id") + private User professional; + + @ManyToOne + @JoinColumn(name = "client_id") + private User client; + + @ManyToOne + @JoinColumn(name = "jobRequest_id") + private JobRequest jobRequest; + +} diff --git a/src/main/java/br/edu/utfpr/servicebook/model/entity/AssessmentProfessionalFiles.java b/src/main/java/br/edu/utfpr/servicebook/model/entity/AssessmentProfessionalFiles.java new file mode 100644 index 00000000..ad018acb --- /dev/null +++ b/src/main/java/br/edu/utfpr/servicebook/model/entity/AssessmentProfessionalFiles.java @@ -0,0 +1,29 @@ +package br.edu.utfpr.servicebook.model.entity; + +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; + +import javax.persistence.*; + +@Data +@NoArgsConstructor +@Table(name = "assessment_professionals_files") +@Entity +public class AssessmentProfessionalFiles { + private static final long serialVersionUID = 1L; + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne + @JoinColumn(name = "assessment_professional_id") + private AssessmentProfessional assessmentProfessional; + + @Column(nullable = true) + private String pathImage; + + @Column(nullable = true) + private String pathVideo; +} diff --git a/src/main/java/br/edu/utfpr/servicebook/model/entity/JobRequest.java b/src/main/java/br/edu/utfpr/servicebook/model/entity/JobRequest.java index 11a73c12..d471206e 100644 --- a/src/main/java/br/edu/utfpr/servicebook/model/entity/JobRequest.java +++ b/src/main/java/br/edu/utfpr/servicebook/model/entity/JobRequest.java @@ -79,7 +79,7 @@ public enum Status { @PrePersist public void onPersist(){ this.dateCreated = LocalDate.now(); - this.status = Status.AVAILABLE; +// this.status = Status.AVAILABLE; } @PreUpdate diff --git a/src/main/java/br/edu/utfpr/servicebook/model/mapper/AssessmentProfessionalFileMapper.java b/src/main/java/br/edu/utfpr/servicebook/model/mapper/AssessmentProfessionalFileMapper.java new file mode 100644 index 00000000..f97b1fdc --- /dev/null +++ b/src/main/java/br/edu/utfpr/servicebook/model/mapper/AssessmentProfessionalFileMapper.java @@ -0,0 +1,28 @@ +package br.edu.utfpr.servicebook.model.mapper; + +import br.edu.utfpr.servicebook.model.dto.AssessmentProfessionalFileDTO; +import br.edu.utfpr.servicebook.model.dto.ServiceDTO; +import br.edu.utfpr.servicebook.model.entity.AssessmentProfessionalFiles; +import br.edu.utfpr.servicebook.model.entity.Service; +import org.modelmapper.ModelMapper; +import org.modelmapper.convention.MatchingStrategies; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class AssessmentProfessionalFileMapper { + @Autowired + private ModelMapper mapper; + + public AssessmentProfessionalFileDTO toDto(AssessmentProfessionalFiles entity){ + AssessmentProfessionalFileDTO dto = mapper.map(entity, AssessmentProfessionalFileDTO.class); + return dto; + } + + public AssessmentProfessionalFiles toEntity(AssessmentProfessionalFileDTO dto){ + mapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT); + AssessmentProfessionalFiles entity = mapper.map(dto, AssessmentProfessionalFiles.class); + return entity; + } + +} diff --git a/src/main/java/br/edu/utfpr/servicebook/model/mapper/AssessmentProfessionalMapper.java b/src/main/java/br/edu/utfpr/servicebook/model/mapper/AssessmentProfessionalMapper.java new file mode 100644 index 00000000..25342810 --- /dev/null +++ b/src/main/java/br/edu/utfpr/servicebook/model/mapper/AssessmentProfessionalMapper.java @@ -0,0 +1,31 @@ +package br.edu.utfpr.servicebook.model.mapper; + +import br.edu.utfpr.servicebook.model.dto.*; +import br.edu.utfpr.servicebook.model.entity.AssessmentProfessional; +import br.edu.utfpr.servicebook.model.entity.Expertise; +import br.edu.utfpr.servicebook.model.entity.ProfessionalExpertise; +import org.modelmapper.ModelMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component +public class AssessmentProfessionalMapper { + @Autowired + private ModelMapper mapper; + + public AssessmentProfessionalDTO toDTO(AssessmentProfessional entity) { + return mapper.map(entity, AssessmentProfessionalDTO.class); + } + + public AssessmentProfessionalDTO toResponseDTO(AssessmentProfessional entity) { + AssessmentProfessionalDTO dto = mapper.map(entity, AssessmentProfessionalDTO.class); + dto.setId(entity.getId()); + return dto; + } + + public AssessmentProfessional toEntity(AssessmentProfessionalDTO dto) { + return mapper.map(dto, AssessmentProfessional.class); + } +} diff --git a/src/main/java/br/edu/utfpr/servicebook/model/mapper/ProfessionalServiceOfferingMapper.java b/src/main/java/br/edu/utfpr/servicebook/model/mapper/ProfessionalServiceOfferingMapper.java index 80956a23..60a6f007 100644 --- a/src/main/java/br/edu/utfpr/servicebook/model/mapper/ProfessionalServiceOfferingMapper.java +++ b/src/main/java/br/edu/utfpr/servicebook/model/mapper/ProfessionalServiceOfferingMapper.java @@ -1,9 +1,6 @@ package br.edu.utfpr.servicebook.model.mapper; -import br.edu.utfpr.servicebook.model.dto.AddressDTO; -import br.edu.utfpr.servicebook.model.dto.ProfessionalServiceOfferingDTO; -import br.edu.utfpr.servicebook.model.entity.Address; -import br.edu.utfpr.servicebook.model.entity.City; +import br.edu.utfpr.servicebook.model.dto.*; import br.edu.utfpr.servicebook.model.entity.ProfessionalServiceOffering; import org.modelmapper.ModelMapper; import org.springframework.beans.factory.annotation.Autowired; @@ -25,4 +22,8 @@ public ProfessionalServiceOffering toEntity(ProfessionalServiceOfferingDTO dto){ return entity; } + public ProfessionalServiceOfferingDTO toSearchItemDto(ProfessionalServiceOffering entity){ + ProfessionalServiceOfferingDTO dto = mapper.map(entity, ProfessionalServiceOfferingDTO.class); + return dto; + } } diff --git a/src/main/java/br/edu/utfpr/servicebook/model/repository/AssessmentProfessionalFileRepository.java b/src/main/java/br/edu/utfpr/servicebook/model/repository/AssessmentProfessionalFileRepository.java new file mode 100644 index 00000000..17d67e14 --- /dev/null +++ b/src/main/java/br/edu/utfpr/servicebook/model/repository/AssessmentProfessionalFileRepository.java @@ -0,0 +1,13 @@ +package br.edu.utfpr.servicebook.model.repository; + +import br.edu.utfpr.servicebook.model.entity.AssessmentProfessional; +import br.edu.utfpr.servicebook.model.entity.AssessmentProfessionalFiles; +import br.edu.utfpr.servicebook.model.entity.JobCandidate; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +@Repository +public interface AssessmentProfessionalFileRepository extends JpaRepository { +} diff --git a/src/main/java/br/edu/utfpr/servicebook/model/repository/AssessmentProfessionalRepository.java b/src/main/java/br/edu/utfpr/servicebook/model/repository/AssessmentProfessionalRepository.java new file mode 100644 index 00000000..922cb559 --- /dev/null +++ b/src/main/java/br/edu/utfpr/servicebook/model/repository/AssessmentProfessionalRepository.java @@ -0,0 +1,31 @@ +package br.edu.utfpr.servicebook.model.repository; + +import br.edu.utfpr.servicebook.model.entity.*; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.Optional; + +@Repository +public interface AssessmentProfessionalRepository extends JpaRepository { + + List findAssessmentProfessionalById(User user); + + Optional findAssessmentProfessionalByProfessional(Long professionalId); + + Optional findAssessmentProfessionalByProfessional(User user); + + List findAllByProfessional(User user); + + @Query("SELECT AVG(pe.quality) AS soma_quality FROM AssessmentProfessional pe WHERE pe.professional = :user") + Double calculateTotalQualityByProfessional(User user); + + @Query("SELECT AVG(pe.punctuality) AS soma_punctuality FROM AssessmentProfessional pe WHERE pe.professional = :user") + Double calculateTotalPunctualityByProfessional(User user); + + @Query("SELECT (AVG(pe.punctuality) + AVG(pe.quality)) / count(pe.id) FROM AssessmentProfessional pe WHERE pe.professional = :user") + Double calculateAveragePunctualityAndQualitySumByProfessional(User user); + +} diff --git a/src/main/java/br/edu/utfpr/servicebook/model/repository/IndividualRepository.java b/src/main/java/br/edu/utfpr/servicebook/model/repository/IndividualRepository.java index 93828008..3a1beb63 100644 --- a/src/main/java/br/edu/utfpr/servicebook/model/repository/IndividualRepository.java +++ b/src/main/java/br/edu/utfpr/servicebook/model/repository/IndividualRepository.java @@ -1,6 +1,7 @@ package br.edu.utfpr.servicebook.model.repository; import br.edu.utfpr.servicebook.model.entity.Individual; +import br.edu.utfpr.servicebook.model.entity.Service; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; @@ -53,4 +54,16 @@ Page findDistinctByTermIgnoreCaseWithPagination( "or lower(p.description) like lower(concat('%', :term, '%')) " + "or lower(pe.expertise.name) like lower(concat('%', :term, '%'))") List findDistinctByTermIgnoreCase(String term); + + @Query("select p from Individual p left join ProfessionalServiceOffering pe on p.id = pe.user.id where " + + "pe.service = :term") + Page findAllIndividualsByService( + Service term, + Pageable pageable); + + @Query("select p from Individual p left join ProfessionalServiceOffering pe on p.id = pe.user.id where " + + "pe.service = :term") + List findAllIndividualsByService( + Service term); + } \ No newline at end of file diff --git a/src/main/java/br/edu/utfpr/servicebook/model/repository/ProfessionalServiceOfferingRepository.java b/src/main/java/br/edu/utfpr/servicebook/model/repository/ProfessionalServiceOfferingRepository.java index b792a723..fd482414 100644 --- a/src/main/java/br/edu/utfpr/servicebook/model/repository/ProfessionalServiceOfferingRepository.java +++ b/src/main/java/br/edu/utfpr/servicebook/model/repository/ProfessionalServiceOfferingRepository.java @@ -1,6 +1,8 @@ package br.edu.utfpr.servicebook.model.repository; import br.edu.utfpr.servicebook.model.entity.*; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; @@ -63,6 +65,35 @@ public interface ProfessionalServiceOfferingRepository extends JpaRepository findProfessionalServiceOfferingByName(String name); + @Query("select distinct p from ProfessionalServiceOffering p left join Service pe on p.service = pe where " + + "lower(p.name) like lower(concat('%', :term, '%'))" + + "or lower(p.description) like lower(concat('%', :term, '%')) " + + "or lower(pe.expertise.name) like lower(concat('%', :term, '%'))") + Page findDistinctByTermIgnoreCaseWithPagination( + String term, + Pageable pageable); + /** + * Busca o serviço atraves dos anuncios gravados. + * @param term + * @param pageable + * @return + */ + @Query("select pe from Individual p left join ProfessionalServiceOffering pe on p = pe.user where " + + "pe.service = :term") + Page findAllIndividualsByService( + Service term, + Pageable pageable); + + /** + * Busca o serviço atraves dos anuncios gravados. + * @param term + * @return + */ + @Query("select pe from Individual p left join ProfessionalServiceOffering pe on p = pe.user where " + + "pe.service = :term") + List findAllIndividualsByService( + Service term); + Optional countAllByService(Service service); } diff --git a/src/main/java/br/edu/utfpr/servicebook/service/AssessmentProfessionalFileService.java b/src/main/java/br/edu/utfpr/servicebook/service/AssessmentProfessionalFileService.java new file mode 100644 index 00000000..55efacd2 --- /dev/null +++ b/src/main/java/br/edu/utfpr/servicebook/service/AssessmentProfessionalFileService.java @@ -0,0 +1,29 @@ +package br.edu.utfpr.servicebook.service; + +import br.edu.utfpr.servicebook.model.entity.AssessmentProfessionalFiles; +import br.edu.utfpr.servicebook.model.repository.AssessmentProfessionalFileRepository; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Slf4j +@Service +public class AssessmentProfessionalFileService { + + @Autowired + private AssessmentProfessionalFileRepository repository; + + public AssessmentProfessionalFiles save(AssessmentProfessionalFiles entity){ + return repository.save(entity); + } + + public void delete(Long id){ + repository.deleteById(id); + } + + public List findAll(){ + return this.repository.findAll(); + } +} diff --git a/src/main/java/br/edu/utfpr/servicebook/service/AssessmentProfessionalService.java b/src/main/java/br/edu/utfpr/servicebook/service/AssessmentProfessionalService.java new file mode 100644 index 00000000..642073d6 --- /dev/null +++ b/src/main/java/br/edu/utfpr/servicebook/service/AssessmentProfessionalService.java @@ -0,0 +1,47 @@ +package br.edu.utfpr.servicebook.service; + +import br.edu.utfpr.servicebook.model.entity.AssessmentProfessional; +import br.edu.utfpr.servicebook.model.entity.ProfessionalExpertise; +import br.edu.utfpr.servicebook.model.entity.ProfessionalExpertisePK; +import br.edu.utfpr.servicebook.model.entity.User; +import br.edu.utfpr.servicebook.model.repository.AssessmentProfessionalRepository; +import br.edu.utfpr.servicebook.model.repository.ProfessionalExpertiseRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Optional; + +@Service +public class AssessmentProfessionalService { + + @Autowired + private AssessmentProfessionalRepository assessmentProfessionalRepository; + + public AssessmentProfessional save(AssessmentProfessional assessmentProfessional) { + return this.assessmentProfessionalRepository.save(assessmentProfessional); + } + + public Optional findById(Long assessmentProfessional){ + return this.assessmentProfessionalRepository.findById(assessmentProfessional); + } + + public Double getFindByProfessional(User user) { + return this.assessmentProfessionalRepository.calculateTotalQualityByProfessional(user); + } + + public Double getFindByProfessionalPunctuality(User user) { + return this.assessmentProfessionalRepository.calculateTotalPunctualityByProfessional(user); + } + public Optional findByProfessional (Long professionalId){ + return this.assessmentProfessionalRepository.findAssessmentProfessionalByProfessional(professionalId); + } + + public List findAllByProfessional (User professionalId){ + return this.assessmentProfessionalRepository.findAllByProfessional(professionalId); + } + + public Double calculateAveragePunctualityAndQualitySumByProfessional(User user) { + return this.assessmentProfessionalRepository.calculateAveragePunctualityAndQualitySumByProfessional(user); + } +} diff --git a/src/main/java/br/edu/utfpr/servicebook/service/IndividualService.java b/src/main/java/br/edu/utfpr/servicebook/service/IndividualService.java index 59d2fa0f..f1d474b4 100644 --- a/src/main/java/br/edu/utfpr/servicebook/service/IndividualService.java +++ b/src/main/java/br/edu/utfpr/servicebook/service/IndividualService.java @@ -129,7 +129,14 @@ public User getAuthenticated(){ return null; } + public Page findAllIndividualsByService(br.edu.utfpr.servicebook.model.entity.Service searchTerm, Integer page, Integer size){ + PageRequest pageRequest = PageRequest.of(page - 1, size); + return this.individualRepository.findAllIndividualsByService(searchTerm, pageRequest); + } + public List findAllIndividualsByService(br.edu.utfpr.servicebook.model.entity.Service service_id){ + return this.individualRepository.findAllIndividualsByService(service_id); + } @Transactional public void saveExpertisesCompany(Company company, ProfessionalExpertise professionalExpertise) { diff --git a/src/main/java/br/edu/utfpr/servicebook/service/ProfessionalServiceOfferingService.java b/src/main/java/br/edu/utfpr/servicebook/service/ProfessionalServiceOfferingService.java index 59ca9a31..e39e7a23 100644 --- a/src/main/java/br/edu/utfpr/servicebook/service/ProfessionalServiceOfferingService.java +++ b/src/main/java/br/edu/utfpr/servicebook/service/ProfessionalServiceOfferingService.java @@ -1,12 +1,11 @@ package br.edu.utfpr.servicebook.service; -import br.edu.utfpr.servicebook.model.entity.Expertise; -import br.edu.utfpr.servicebook.model.entity.ProfessionalServiceOffering; -import br.edu.utfpr.servicebook.model.entity.Service; -import br.edu.utfpr.servicebook.model.entity.User; +import br.edu.utfpr.servicebook.model.entity.*; import br.edu.utfpr.servicebook.model.repository.CategoryRepository; import br.edu.utfpr.servicebook.model.repository.ProfessionalServiceOfferingRepository; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; import org.springframework.data.jpa.repository.Query; import java.util.List; import java.util.Optional; @@ -68,6 +67,11 @@ public List findProfessionalServiceOfferingByServic return professionalServiceOfferingRepository.findProfessionalServiceOfferingByService(service); } + public Page findDistinctByTermIgnoreCaseWithPagination(String searchTerm, Integer page, Integer size){ + PageRequest pageRequest = PageRequest.of(page - 1, size); + return this.professionalServiceOfferingRepository.findDistinctByTermIgnoreCaseWithPagination(searchTerm, pageRequest); + } + /** * Busca todas os serviços de um profissional por serviço cadastrado pelo administrador. */ @@ -97,4 +101,17 @@ public List findProfessionalServiceOfferingByUserAn public Optional findProfessionalServiceOfferingByName(String name){ return professionalServiceOfferingRepository.findProfessionalServiceOfferingByName(name); } + + public Page findAllIndividualsByService(Service searchTerm, Integer page, Integer size){ + PageRequest pageRequest = PageRequest.of(page - 1, size); + return this.professionalServiceOfferingRepository.findAllIndividualsByService(searchTerm, pageRequest); + } + + public List findAllIndividualsByService(Service service){ + return this.professionalServiceOfferingRepository.findAllIndividualsByService(service); + } + + public Optional countAllByService(Service service) { + return this.professionalServiceOfferingRepository.countAllByService(service); + } } diff --git a/src/main/java/br/edu/utfpr/servicebook/service/ServiceService.java b/src/main/java/br/edu/utfpr/servicebook/service/ServiceService.java index 09450fe8..ba373f91 100644 --- a/src/main/java/br/edu/utfpr/servicebook/service/ServiceService.java +++ b/src/main/java/br/edu/utfpr/servicebook/service/ServiceService.java @@ -6,6 +6,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; diff --git a/src/main/java/br/edu/utfpr/servicebook/service/UserService.java b/src/main/java/br/edu/utfpr/servicebook/service/UserService.java index 8bd03cc1..a6bc61ed 100644 --- a/src/main/java/br/edu/utfpr/servicebook/service/UserService.java +++ b/src/main/java/br/edu/utfpr/servicebook/service/UserService.java @@ -1,6 +1,7 @@ package br.edu.utfpr.servicebook.service; import br.edu.utfpr.servicebook.model.dto.ExpertiseDTO; +import br.edu.utfpr.servicebook.model.dto.UserDTO; import br.edu.utfpr.servicebook.model.entity.Expertise; import br.edu.utfpr.servicebook.model.entity.Individual; import br.edu.utfpr.servicebook.model.entity.ProfessionalExpertise; diff --git a/src/main/resources/data.sql b/src/main/resources/data.sql index 82ffd9c3..3abfaf12 100644 --- a/src/main/resources/data.sql +++ b/src/main/resources/data.sql @@ -88,9 +88,10 @@ INSERT INTO services (name, description, allow_scheduling, path_icon, expertise_ VALUES ('Balanceamento', 'Balanceamento das rodas', false, 'https://res.cloudinary.com/dgueb0wir/image/upload/v1689176876/servicebook/expertises/mecanico_quczum.svg', 4), ('Troca de óleo', 'Troca do óleo do motor', false, 'https://res.cloudinary.com/dgueb0wir/image/upload/v1689176876/servicebook/expertises/mecanico_quczum.svg', 4); -INSERT INTO professional_service_offerings (name, description, service_id, user_id) -VALUES ('Balanceamento com máquina importada', 'O balanceamento com 100% de garantia', 1, 2), - (null, null, 2, 2); +INSERT INTO professional_service_offerings (name, description, price, service_id, user_id) +VALUES ('Balanceamento com máquina importada', 'O balanceamento com 100% de garantia', 19000, 1, 2), + ('Troca de óleo', 'Troca de óleo', 25000, 2, 2), + ('Balanceamento', 'Balanceamento', null, 1, 2); INSERT INTO companies (cnpj, id) VALUES ('98.988.640/0001-91', 7); @@ -150,10 +151,13 @@ VALUES ('1', '2', 'false'), ('1', '6', 'false'), ('2', '2', 'false'), ('3', '2', 'true'), + ('14', '2', 'true'), ('17', '2', 'false'); INSERT INTO follows (client_id, professional_id) -VALUES (4, 2) - +VALUES (4, 2); +INSERT INTO assessment_professionals (comment, date, punctuality, quality, client_id, job_request_id, professional_id) +VALUES ('òtimo profissional', '2024-01-02', 2.5, 2, 4, 17,2), + ('Profissional pontual', '2024-01-02', 5, 1.5, 4, 17,2); diff --git a/src/main/webapp/WEB-INF/tags/search-bar.tag b/src/main/webapp/WEB-INF/tags/search-bar.tag index dde28e28..e8ee50ca 100644 --- a/src/main/webapp/WEB-INF/tags/search-bar.tag +++ b/src/main/webapp/WEB-INF/tags/search-bar.tag @@ -1,33 +1,73 @@ <%@tag description="Servicebook - Search bar template" pageEncoding="UTF-8" %> +<%@attribute name="items" type="java.util.ArrayList" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + +
-
-
-
-

O QUE VOCÊ PRECISA?

-
+
+
+
+

O QUE VOCÊ PRECISA?

+
Nos informe de qual serviço você precisa e escolha o melhor profissional!
+
+
+ +
+
+
+ ${msg} +
+
+
-
-
-
- -
-
-
-
- -
-
-
-
-
\ No newline at end of file +
+
+
+ + +
+
+ + + +
+ +
+ + + + +
+ +
+
+ +
+
+
+
+
+
diff --git a/src/main/webapp/WEB-INF/tags/template.tag b/src/main/webapp/WEB-INF/tags/template.tag index dd89cfcb..5798d36f 100644 --- a/src/main/webapp/WEB-INF/tags/template.tag +++ b/src/main/webapp/WEB-INF/tags/template.tag @@ -12,13 +12,28 @@ + + + + + + + + + + + + ${title} + + - + + + @@ -131,12 +146,15 @@ src="https://code.jquery.com/jquery-3.7.0.min.js" integrity="sha256-2Pmvv0kuTBOenSvLm6bvfBSSHrUJ+3A7x6P5Ebd07/g=" crossorigin="anonymous"> + + + - diff --git a/src/main/webapp/WEB-INF/view/client/details-request-candidate.jsp b/src/main/webapp/WEB-INF/view/client/details-request-candidate.jsp index f3df826c..1ea14322 100644 --- a/src/main/webapp/WEB-INF/view/client/details-request-candidate.jsp +++ b/src/main/webapp/WEB-INF/view/client/details-request-candidate.jsp @@ -27,11 +27,12 @@
+<%-- ${jobCandidate.user}--%> - + star - + star_border @@ -95,6 +96,52 @@ solicitar um orçamento.

+ + + +
+
+ Qualidade: + + + star + + + star_border + + +
+ +
+ Pontualidade: + + + star + + + star_border + + +
+
+ +
+
    +
  • +
    insert_commentComentários
    + + +
    + + ${c.comment} + +
    +
    +
  • +
+
+
+

Entre em contato com o profissional.

@@ -146,37 +193,37 @@
- -
-
Avaliação:
+<%-- --%> +<%--
--%> +<%--
Avaliação:
--%> - - +<%-- --%> +<%-- --%> - - +<%-- --%> +<%-- --%> - - +<%-- --%> +<%-- --%> - - +<%-- --%> +<%-- --%> - - +<%-- --%> +<%-- --%> -
-
- - -
+<%--
--%> +<%--
--%> +<%-- --%> +<%-- --%> +<%--
--%> -
- -
-
-
- +<%--
--%> +<%-- --%> +<%--
--%> +<%--
--%> +<%--
--%> +<%--
--%>
diff --git a/src/main/webapp/WEB-INF/view/client/details-request.jsp b/src/main/webapp/WEB-INF/view/client/details-request.jsp index 9bd4c152..bf9cae56 100644 --- a/src/main/webapp/WEB-INF/view/client/details-request.jsp +++ b/src/main/webapp/WEB-INF/view/client/details-request.jsp @@ -18,6 +18,12 @@
+ +
@@ -147,11 +153,15 @@
-
@@ -234,5 +244,4 @@ } }); }); - - + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/view/client/evaluate-jobs.jsp b/src/main/webapp/WEB-INF/view/client/evaluate-jobs.jsp new file mode 100644 index 00000000..3caaf433 --- /dev/null +++ b/src/main/webapp/WEB-INF/view/client/evaluate-jobs.jsp @@ -0,0 +1,121 @@ +<%@page contentType="text/html" pageEncoding="UTF-8" %> +<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %> +<%@ taglib prefix="t" tagdir="/WEB-INF/tags" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> + + + + + + + + + + + + +
+ + + +
+

+ Avalie o Serviço!

+

Agora que o serviço foi concluído pelo profissional, você poderá avalia-lo.

+
+ +
+

Profissional: ${professional.name}

+

Descrição: ${job.description}

+

Data e Horário: ${jobContracted.hiredDate}

+

Concluído: ${jobContracted.finishDate}

+ +
+ +
+
+
PONTUALIDADE
+
+ + + + + + + + + + +
+
+ +
+
QUALIDADE DO SERVIÇO
+ +
+ + + + + + + + + + +
+
+ +
+
DEIXE SEU COMENTÁRIO
+ +
+ +
+
ADICIONAR IMAGEM DO SERVIÇO
+ +
+
+ File + +
+
+ +
+
+
+ +
+
ADICIONAR VIDEO DO SERVIÇO
+ +
+
+ File + +
+
+ +
+
+
+ +
+ +
+
+ +
+ + +
+
diff --git a/src/main/webapp/WEB-INF/view/client/job-request/tabs/available-jobs-report.jsp b/src/main/webapp/WEB-INF/view/client/job-request/tabs/available-jobs-report.jsp index abc48ad9..ff11a859 100644 --- a/src/main/webapp/WEB-INF/view/client/job-request/tabs/available-jobs-report.jsp +++ b/src/main/webapp/WEB-INF/view/client/job-request/tabs/available-jobs-report.jsp @@ -50,21 +50,11 @@ tagdir="/WEB-INF/tags" %>
- - diff --git a/src/main/webapp/WEB-INF/view/client/job-request/tabs/disputed-jobs-report.jsp b/src/main/webapp/WEB-INF/view/client/job-request/tabs/disputed-jobs-report.jsp index 60bfac53..0a3e495b 100644 --- a/src/main/webapp/WEB-INF/view/client/job-request/tabs/disputed-jobs-report.jsp +++ b/src/main/webapp/WEB-INF/view/client/job-request/tabs/disputed-jobs-report.jsp @@ -55,7 +55,7 @@ tagdir="/WEB-INF/tags" %> href="#modal-delete" data-url="${pageContext.request.contextPath}/minha-conta/cliente/meus-pedidos/${job.jobRequest.id}" data-name="${job.jobRequest.description}" - class="waves-effect waves-light btn modal-trigger" + class="waves-effect waves-light btn modal-trigger red" >Excluir
diff --git a/src/main/webapp/WEB-INF/view/client/job-request/tabs/doing-jobs-report.jsp b/src/main/webapp/WEB-INF/view/client/job-request/tabs/doing-jobs-report.jsp index 7c722d68..6b570ccf 100644 --- a/src/main/webapp/WEB-INF/view/client/job-request/tabs/doing-jobs-report.jsp +++ b/src/main/webapp/WEB-INF/view/client/job-request/tabs/doing-jobs-report.jsp @@ -44,7 +44,7 @@
diff --git a/src/main/webapp/WEB-INF/view/client/job-request/tabs/executed-jobs-report.jsp b/src/main/webapp/WEB-INF/view/client/job-request/tabs/executed-jobs-report.jsp index fd8ddf2b..7c8dc766 100644 --- a/src/main/webapp/WEB-INF/view/client/job-request/tabs/executed-jobs-report.jsp +++ b/src/main/webapp/WEB-INF/view/client/job-request/tabs/executed-jobs-report.jsp @@ -45,7 +45,7 @@
diff --git a/src/main/webapp/WEB-INF/view/client/job-request/tabs/todo-jobs-report.jsp b/src/main/webapp/WEB-INF/view/client/job-request/tabs/todo-jobs-report.jsp index 46c39889..5fc2c6d0 100644 --- a/src/main/webapp/WEB-INF/view/client/job-request/tabs/todo-jobs-report.jsp +++ b/src/main/webapp/WEB-INF/view/client/job-request/tabs/todo-jobs-report.jsp @@ -44,7 +44,7 @@
diff --git a/src/main/webapp/WEB-INF/view/client/my-requests.jsp b/src/main/webapp/WEB-INF/view/client/my-requests.jsp index 3196ea00..f4b12990 100644 --- a/src/main/webapp/WEB-INF/view/client/my-requests.jsp +++ b/src/main/webapp/WEB-INF/view/client/my-requests.jsp @@ -13,6 +13,10 @@ +

Minhas Solicitações

    diff --git a/src/main/webapp/WEB-INF/view/visitor/index.jsp b/src/main/webapp/WEB-INF/view/visitor/index.jsp index 3ee4fcb6..ef5c70cc 100644 --- a/src/main/webapp/WEB-INF/view/visitor/index.jsp +++ b/src/main/webapp/WEB-INF/view/visitor/index.jsp @@ -5,14 +5,13 @@ -
    - +
    @@ -74,3 +73,10 @@
    + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/view/visitor/professionals-services.jsp b/src/main/webapp/WEB-INF/view/visitor/professionals-services.jsp new file mode 100644 index 00000000..6375b18b --- /dev/null +++ b/src/main/webapp/WEB-INF/view/visitor/professionals-services.jsp @@ -0,0 +1,147 @@ +<%@page contentType="text/html" pageEncoding="UTF-8" %> +<%@taglib prefix="t" tagdir="/WEB-INF/tags" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> + + + + + + + + +
    +
    +
    + + + +
    +

    Foto de especialidade + ${expertise.name} +

    + +

    ${service}

    +
    +
    + +
    + ${countProfessionals} RESULTADOS ENCONTRADOS +
    +
    + +
    + Classificar por + + + + + + + + + +
    +
    + +
    + + +
    +
    +
    + ${professional.user.address.neighborhood} - ${professional.user.address.city.state.uf} +
    +
    +
    + + + Foto de perfil + + + Sem foto de perfil + + +
    +
    ${professional.user.name}
    + + ${professional.description} +
    + +
    +
    +
    + + + + + +

    +
    +
    +
    +
    + +
    +
    + +
    +
    +
    +
    + sentiment_dissatisfied +

    + Nenhum profissional encontrado! +

    +
    +
    +
    +
    +
    +
    +
    + +
    +

    Entre ou cadastre-se para ter acesso ao demais profissionais

    +
    +
    + +
    + +
    +
    +
    +
    +
    + +
    +
    + diff --git a/src/main/webapp/WEB-INF/view/visitor/search-results.jsp b/src/main/webapp/WEB-INF/view/visitor/search-results.jsp index d90d7530..9ba16df2 100644 --- a/src/main/webapp/WEB-INF/view/visitor/search-results.jsp +++ b/src/main/webapp/WEB-INF/view/visitor/search-results.jsp @@ -1,6 +1,7 @@ <%@page contentType="text/html" pageEncoding="UTF-8" %> <%@taglib prefix="t" tagdir="/WEB-INF/tags" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> @@ -10,48 +11,94 @@ - - - +
    + + +
    +

    Foto de especialidade + ${dto_expertise.name} +

    + +

    ${service}

    +
    +
    +
    + + PROFISSIONAIS + ver mais navigate_next +
    +
    - - -
    -
    -
    + + +
    +
    +
    + ${professional.user.address.neighborhood} - ${professional.user.address.city.state.uf} +
    +
    - - Foto de perfil + + Foto de perfil - Sem foto de perfil + Sem foto de perfil -
    -
    -
    ${professional.name}
    -
    -
    -
    - -
    ${expertise.name}
    -
    +
    +
    ${professional.user.name}
    + + ${professional.description} +
    +
    -
    - Ver perfil +
    + +
    + + +
    +
    + + +<%--

    +<%-- value="${professional.price/100}" type="currency"/>

    --%> + +
    + + +
    + +
    + - +
    @@ -81,9 +128,17 @@
    + diff --git a/src/main/webapp/assets/libraries/select2/css/select2.min.css b/src/main/webapp/assets/libraries/select2/css/select2.min.css new file mode 100644 index 00000000..f00f1547 --- /dev/null +++ b/src/main/webapp/assets/libraries/select2/css/select2.min.css @@ -0,0 +1 @@ +.select2-container{box-sizing:border-box;display:inline-block;margin:0;position:relative;vertical-align:middle}.select2-container .select2-selection--single{box-sizing:border-box;cursor:pointer;display:block;height:28px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--single .select2-selection__rendered{display:block;padding-left:8px;padding-right:20px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-selection--single .select2-selection__clear{background-color:transparent;border:none;font-size:1em}.select2-container[dir="rtl"] .select2-selection--single .select2-selection__rendered{padding-right:8px;padding-left:20px}.select2-container .select2-selection--multiple{box-sizing:border-box;cursor:pointer;display:block;min-height:32px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--multiple .select2-selection__rendered{display:inline;list-style:none;padding:0}.select2-container .select2-selection--multiple .select2-selection__clear{background-color:transparent;border:none;font-size:1em}.select2-container .select2-search--inline .select2-search__field{box-sizing:border-box;border:none;font-size:100%;margin-top:5px;margin-left:5px;padding:0;max-width:100%;resize:none;height:18px;vertical-align:bottom;font-family:sans-serif;overflow:hidden;word-break:keep-all}.select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-dropdown{background-color:white;border:1px solid #aaa;border-radius:4px;box-sizing:border-box;display:block;position:absolute;left:-100000px;width:100%;z-index:1051}.select2-results{display:block}.select2-results__options{list-style:none;margin:0;padding:0}.select2-results__option{padding:6px;user-select:none;-webkit-user-select:none}.select2-results__option--selectable{cursor:pointer}.select2-container--open .select2-dropdown{left:0}.select2-container--open .select2-dropdown--above{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--open .select2-dropdown--below{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-search--dropdown{display:block;padding:4px}.select2-search--dropdown .select2-search__field{padding:4px;width:100%;box-sizing:border-box}.select2-search--dropdown .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-search--dropdown.select2-search--hide{display:none}.select2-close-mask{border:0;margin:0;padding:0;display:block;position:fixed;left:0;top:0;min-height:100%;min-width:100%;height:auto;width:auto;opacity:0;z-index:99;background-color:#fff;filter:alpha(opacity=0)}.select2-hidden-accessible{border:0 !important;clip:rect(0 0 0 0) !important;-webkit-clip-path:inset(50%) !important;clip-path:inset(50%) !important;height:1px !important;overflow:hidden !important;padding:0 !important;position:absolute !important;width:1px !important;white-space:nowrap !important}.select2-container--default .select2-selection--single{background-color:#fff;border:1px solid #aaa;border-radius:4px}.select2-container--default .select2-selection--single .select2-selection__rendered{color:#444;line-height:28px}.select2-container--default .select2-selection--single .select2-selection__clear{cursor:pointer;float:right;font-weight:bold;height:26px;margin-right:20px;padding-right:0px}.select2-container--default .select2-selection--single .select2-selection__placeholder{color:#999}.select2-container--default .select2-selection--single .select2-selection__arrow{height:26px;position:absolute;top:1px;right:1px;width:20px}.select2-container--default .select2-selection--single .select2-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__clear{float:left}.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__arrow{left:1px;right:auto}.select2-container--default.select2-container--disabled .select2-selection--single{background-color:#eee;cursor:default}.select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear{display:none}.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select2-container--default .select2-selection--multiple{background-color:white;border:1px solid #aaa;border-radius:4px;cursor:text;padding-bottom:5px;padding-right:5px;position:relative}.select2-container--default .select2-selection--multiple.select2-selection--clearable{padding-right:25px}.select2-container--default .select2-selection--multiple .select2-selection__clear{cursor:pointer;font-weight:bold;height:20px;margin-right:10px;margin-top:5px;position:absolute;right:0;padding:1px}.select2-container--default .select2-selection--multiple .select2-selection__choice{background-color:#e4e4e4;border:1px solid #aaa;border-radius:4px;box-sizing:border-box;display:inline-block;margin-left:5px;margin-top:5px;padding:0;padding-left:20px;position:relative;max-width:100%;overflow:hidden;text-overflow:ellipsis;vertical-align:bottom;white-space:nowrap}.select2-container--default .select2-selection--multiple .select2-selection__choice__display{cursor:default;padding-left:2px;padding-right:5px}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove{background-color:transparent;border:none;border-right:1px solid #aaa;border-top-left-radius:4px;border-bottom-left-radius:4px;color:#999;cursor:pointer;font-size:1em;font-weight:bold;padding:0 4px;position:absolute;left:0;top:0}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover,.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:focus{background-color:#f1f1f1;color:#333;outline:none}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice{margin-left:5px;margin-right:auto}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice__display{padding-left:5px;padding-right:2px}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove{border-left:1px solid #aaa;border-right:none;border-top-left-radius:0;border-bottom-left-radius:0;border-top-right-radius:4px;border-bottom-right-radius:4px}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__clear{float:left;margin-left:10px;margin-right:auto}.select2-container--default.select2-container--focus .select2-selection--multiple{border:solid black 1px;outline:0}.select2-container--default.select2-container--disabled .select2-selection--multiple{background-color:#eee;cursor:default}.select2-container--default.select2-container--disabled .select2-selection__choice__remove{display:none}.select2-container--default.select2-container--open.select2-container--above .select2-selection--single,.select2-container--default.select2-container--open.select2-container--above .select2-selection--multiple{border-top-left-radius:0;border-top-right-radius:0}.select2-container--default.select2-container--open.select2-container--below .select2-selection--single,.select2-container--default.select2-container--open.select2-container--below .select2-selection--multiple{border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--default .select2-search--dropdown .select2-search__field{border:1px solid #aaa}.select2-container--default .select2-search--inline .select2-search__field{background:transparent;border:none;outline:0;box-shadow:none;-webkit-appearance:textfield}.select2-container--default .select2-results>.select2-results__options{max-height:200px;overflow-y:auto}.select2-container--default .select2-results__option .select2-results__option{padding-left:1em}.select2-container--default .select2-results__option .select2-results__option .select2-results__group{padding-left:0}.select2-container--default .select2-results__option .select2-results__option .select2-results__option{margin-left:-1em;padding-left:2em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-2em;padding-left:3em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-3em;padding-left:4em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-4em;padding-left:5em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-5em;padding-left:6em}.select2-container--default .select2-results__option--group{padding:0}.select2-container--default .select2-results__option--disabled{color:#999}.select2-container--default .select2-results__option--selected{background-color:#ddd}.select2-container--default .select2-results__option--highlighted.select2-results__option--selectable{background-color:#5897fb;color:white}.select2-container--default .select2-results__group{cursor:default;display:block;padding:6px}.select2-container--classic .select2-selection--single{background-color:#f7f7f7;border:1px solid #aaa;border-radius:4px;outline:0;background-image:-webkit-linear-gradient(top, #fff 50%, #eee 100%);background-image:-o-linear-gradient(top, #fff 50%, #eee 100%);background-image:linear-gradient(to bottom, #fff 50%, #eee 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0)}.select2-container--classic .select2-selection--single:focus{border:1px solid #5897fb}.select2-container--classic .select2-selection--single .select2-selection__rendered{color:#444;line-height:28px}.select2-container--classic .select2-selection--single .select2-selection__clear{cursor:pointer;float:right;font-weight:bold;height:26px;margin-right:20px}.select2-container--classic .select2-selection--single .select2-selection__placeholder{color:#999}.select2-container--classic .select2-selection--single .select2-selection__arrow{background-color:#ddd;border:none;border-left:1px solid #aaa;border-top-right-radius:4px;border-bottom-right-radius:4px;height:26px;position:absolute;top:1px;right:1px;width:20px;background-image:-webkit-linear-gradient(top, #eee 50%, #ccc 100%);background-image:-o-linear-gradient(top, #eee 50%, #ccc 100%);background-image:linear-gradient(to bottom, #eee 50%, #ccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFCCCCCC', GradientType=0)}.select2-container--classic .select2-selection--single .select2-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__clear{float:left}.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__arrow{border:none;border-right:1px solid #aaa;border-radius:0;border-top-left-radius:4px;border-bottom-left-radius:4px;left:1px;right:auto}.select2-container--classic.select2-container--open .select2-selection--single{border:1px solid #5897fb}.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow{background:transparent;border:none}.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select2-container--classic.select2-container--open.select2-container--above .select2-selection--single{border-top:none;border-top-left-radius:0;border-top-right-radius:0;background-image:-webkit-linear-gradient(top, #fff 0%, #eee 50%);background-image:-o-linear-gradient(top, #fff 0%, #eee 50%);background-image:linear-gradient(to bottom, #fff 0%, #eee 50%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0)}.select2-container--classic.select2-container--open.select2-container--below .select2-selection--single{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0;background-image:-webkit-linear-gradient(top, #eee 50%, #fff 100%);background-image:-o-linear-gradient(top, #eee 50%, #fff 100%);background-image:linear-gradient(to bottom, #eee 50%, #fff 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFFFFFFF', GradientType=0)}.select2-container--classic .select2-selection--multiple{background-color:white;border:1px solid #aaa;border-radius:4px;cursor:text;outline:0;padding-bottom:5px;padding-right:5px}.select2-container--classic .select2-selection--multiple:focus{border:1px solid #5897fb}.select2-container--classic .select2-selection--multiple .select2-selection__clear{display:none}.select2-container--classic .select2-selection--multiple .select2-selection__choice{background-color:#e4e4e4;border:1px solid #aaa;border-radius:4px;display:inline-block;margin-left:5px;margin-top:5px;padding:0}.select2-container--classic .select2-selection--multiple .select2-selection__choice__display{cursor:default;padding-left:2px;padding-right:5px}.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove{background-color:transparent;border:none;border-top-left-radius:4px;border-bottom-left-radius:4px;color:#888;cursor:pointer;font-size:1em;font-weight:bold;padding:0 4px}.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove:hover{color:#555;outline:none}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice{margin-left:5px;margin-right:auto}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice__display{padding-left:5px;padding-right:2px}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove{border-top-left-radius:0;border-bottom-left-radius:0;border-top-right-radius:4px;border-bottom-right-radius:4px}.select2-container--classic.select2-container--open .select2-selection--multiple{border:1px solid #5897fb}.select2-container--classic.select2-container--open.select2-container--above .select2-selection--multiple{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-container--classic.select2-container--open.select2-container--below .select2-selection--multiple{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--classic .select2-search--dropdown .select2-search__field{border:1px solid #aaa;outline:0}.select2-container--classic .select2-search--inline .select2-search__field{outline:0;box-shadow:none}.select2-container--classic .select2-dropdown{background-color:#fff;border:1px solid transparent}.select2-container--classic .select2-dropdown--above{border-bottom:none}.select2-container--classic .select2-dropdown--below{border-top:none}.select2-container--classic .select2-results>.select2-results__options{max-height:200px;overflow-y:auto}.select2-container--classic .select2-results__option--group{padding:0}.select2-container--classic .select2-results__option--disabled{color:grey}.select2-container--classic .select2-results__option--highlighted.select2-results__option--selectable{background-color:#3875d7;color:#fff}.select2-container--classic .select2-results__group{cursor:default;display:block;padding:6px}.select2-container--classic.select2-container--open .select2-dropdown{border-color:#5897fb} \ No newline at end of file diff --git a/src/main/webapp/assets/libraries/select2/js/select2.min.js b/src/main/webapp/assets/libraries/select2/js/select2.min.js new file mode 100644 index 00000000..cc9a83f1 --- /dev/null +++ b/src/main/webapp/assets/libraries/select2/js/select2.min.js @@ -0,0 +1,2 @@ +/*! Select2 4.1.0-rc.0 | https://github.com/select2/select2/blob/master/LICENSE.md */ +!function(n){"function"==typeof define&&define.amd?define(["jquery"],n):"object"==typeof module&&module.exports?module.exports=function(e,t){return void 0===t&&(t="undefined"!=typeof window?require("jquery"):require("jquery")(e)),n(t),t}:n(jQuery)}(function(t){var e,n,s,p,r,o,h,f,g,m,y,v,i,a,_,s=((u=t&&t.fn&&t.fn.select2&&t.fn.select2.amd?t.fn.select2.amd:u)&&u.requirejs||(u?n=u:u={},g={},m={},y={},v={},i=Object.prototype.hasOwnProperty,a=[].slice,_=/\.js$/,h=function(e,t){var n,s,i=c(e),r=i[0],t=t[1];return e=i[1],r&&(n=x(r=l(r,t))),r?e=n&&n.normalize?n.normalize(e,(s=t,function(e){return l(e,s)})):l(e,t):(r=(i=c(e=l(e,t)))[0],e=i[1],r&&(n=x(r))),{f:r?r+"!"+e:e,n:e,pr:r,p:n}},f={require:function(e){return w(e)},exports:function(e){var t=g[e];return void 0!==t?t:g[e]={}},module:function(e){return{id:e,uri:"",exports:g[e],config:(t=e,function(){return y&&y.config&&y.config[t]||{}})};var t}},r=function(e,t,n,s){var i,r,o,a,l,c=[],u=typeof n,d=A(s=s||e);if("undefined"==u||"function"==u){for(t=!t.length&&n.length?["require","exports","module"]:t,a=0;a":">",'"':""","'":"'","/":"/"};return"string"!=typeof e?e:String(e).replace(/[&<>"'\/\\]/g,function(e){return t[e]})},s.__cache={};var n=0;return s.GetUniqueElementId=function(e){var t=e.getAttribute("data-select2-id");return null!=t||(t=e.id?"select2-data-"+e.id:"select2-data-"+(++n).toString()+"-"+s.generateChars(4),e.setAttribute("data-select2-id",t)),t},s.StoreData=function(e,t,n){e=s.GetUniqueElementId(e);s.__cache[e]||(s.__cache[e]={}),s.__cache[e][t]=n},s.GetData=function(e,t){var n=s.GetUniqueElementId(e);return t?s.__cache[n]&&null!=s.__cache[n][t]?s.__cache[n][t]:r(e).data(t):s.__cache[n]},s.RemoveData=function(e){var t=s.GetUniqueElementId(e);null!=s.__cache[t]&&delete s.__cache[t],e.removeAttribute("data-select2-id")},s.copyNonInternalCssClasses=function(e,t){var n=(n=e.getAttribute("class").trim().split(/\s+/)).filter(function(e){return 0===e.indexOf("select2-")}),t=(t=t.getAttribute("class").trim().split(/\s+/)).filter(function(e){return 0!==e.indexOf("select2-")}),t=n.concat(t);e.setAttribute("class",t.join(" "))},s}),u.define("select2/results",["jquery","./utils"],function(d,p){function s(e,t,n){this.$element=e,this.data=n,this.options=t,s.__super__.constructor.call(this)}return p.Extend(s,p.Observable),s.prototype.render=function(){var e=d('
      ');return this.options.get("multiple")&&e.attr("aria-multiselectable","true"),this.$results=e},s.prototype.clear=function(){this.$results.empty()},s.prototype.displayMessage=function(e){var t=this.options.get("escapeMarkup");this.clear(),this.hideLoading();var n=d(''),s=this.options.get("translations").get(e.message);n.append(t(s(e.args))),n[0].className+=" select2-results__message",this.$results.append(n)},s.prototype.hideMessages=function(){this.$results.find(".select2-results__message").remove()},s.prototype.append=function(e){this.hideLoading();var t=[];if(null!=e.results&&0!==e.results.length){e.results=this.sort(e.results);for(var n=0;n
    ",{class:"select2-results__options select2-results__options--nested",role:"none"});i.append(l),o.append(a),o.append(i)}else this.template(e,t);return p.StoreData(t,"data",e),t},s.prototype.bind=function(t,e){var i=this,n=t.id+"-results";this.$results.attr("id",n),t.on("results:all",function(e){i.clear(),i.append(e.data),t.isOpen()&&(i.setClasses(),i.highlightFirstItem())}),t.on("results:append",function(e){i.append(e.data),t.isOpen()&&i.setClasses()}),t.on("query",function(e){i.hideMessages(),i.showLoading(e)}),t.on("select",function(){t.isOpen()&&(i.setClasses(),i.options.get("scrollAfterSelect")&&i.highlightFirstItem())}),t.on("unselect",function(){t.isOpen()&&(i.setClasses(),i.options.get("scrollAfterSelect")&&i.highlightFirstItem())}),t.on("open",function(){i.$results.attr("aria-expanded","true"),i.$results.attr("aria-hidden","false"),i.setClasses(),i.ensureHighlightVisible()}),t.on("close",function(){i.$results.attr("aria-expanded","false"),i.$results.attr("aria-hidden","true"),i.$results.removeAttr("aria-activedescendant")}),t.on("results:toggle",function(){var e=i.getHighlightedResults();0!==e.length&&e.trigger("mouseup")}),t.on("results:select",function(){var e,t=i.getHighlightedResults();0!==t.length&&(e=p.GetData(t[0],"data"),t.hasClass("select2-results__option--selected")?i.trigger("close",{}):i.trigger("select",{data:e}))}),t.on("results:previous",function(){var e,t=i.getHighlightedResults(),n=i.$results.find(".select2-results__option--selectable"),s=n.index(t);s<=0||(e=s-1,0===t.length&&(e=0),(s=n.eq(e)).trigger("mouseenter"),t=i.$results.offset().top,n=s.offset().top,s=i.$results.scrollTop()+(n-t),0===e?i.$results.scrollTop(0):n-t<0&&i.$results.scrollTop(s))}),t.on("results:next",function(){var e,t=i.getHighlightedResults(),n=i.$results.find(".select2-results__option--selectable"),s=n.index(t)+1;s>=n.length||((e=n.eq(s)).trigger("mouseenter"),t=i.$results.offset().top+i.$results.outerHeight(!1),n=e.offset().top+e.outerHeight(!1),e=i.$results.scrollTop()+n-t,0===s?i.$results.scrollTop(0):tthis.$results.outerHeight()||s<0)&&this.$results.scrollTop(n))},s.prototype.template=function(e,t){var n=this.options.get("templateResult"),s=this.options.get("escapeMarkup"),e=n(e,t);null==e?t.style.display="none":"string"==typeof e?t.innerHTML=s(e):d(t).append(e)},s}),u.define("select2/keys",[],function(){return{BACKSPACE:8,TAB:9,ENTER:13,SHIFT:16,CTRL:17,ALT:18,ESC:27,SPACE:32,PAGE_UP:33,PAGE_DOWN:34,END:35,HOME:36,LEFT:37,UP:38,RIGHT:39,DOWN:40,DELETE:46}}),u.define("select2/selection/base",["jquery","../utils","../keys"],function(n,s,i){function r(e,t){this.$element=e,this.options=t,r.__super__.constructor.call(this)}return s.Extend(r,s.Observable),r.prototype.render=function(){var e=n('');return this._tabindex=0,null!=s.GetData(this.$element[0],"old-tabindex")?this._tabindex=s.GetData(this.$element[0],"old-tabindex"):null!=this.$element.attr("tabindex")&&(this._tabindex=this.$element.attr("tabindex")),e.attr("title",this.$element.attr("title")),e.attr("tabindex",this._tabindex),e.attr("aria-disabled","false"),this.$selection=e},r.prototype.bind=function(e,t){var n=this,s=e.id+"-results";this.container=e,this.$selection.on("focus",function(e){n.trigger("focus",e)}),this.$selection.on("blur",function(e){n._handleBlur(e)}),this.$selection.on("keydown",function(e){n.trigger("keypress",e),e.which===i.SPACE&&e.preventDefault()}),e.on("results:focus",function(e){n.$selection.attr("aria-activedescendant",e.data._resultId)}),e.on("selection:update",function(e){n.update(e.data)}),e.on("open",function(){n.$selection.attr("aria-expanded","true"),n.$selection.attr("aria-owns",s),n._attachCloseHandler(e)}),e.on("close",function(){n.$selection.attr("aria-expanded","false"),n.$selection.removeAttr("aria-activedescendant"),n.$selection.removeAttr("aria-owns"),n.$selection.trigger("focus"),n._detachCloseHandler(e)}),e.on("enable",function(){n.$selection.attr("tabindex",n._tabindex),n.$selection.attr("aria-disabled","false")}),e.on("disable",function(){n.$selection.attr("tabindex","-1"),n.$selection.attr("aria-disabled","true")})},r.prototype._handleBlur=function(e){var t=this;window.setTimeout(function(){document.activeElement==t.$selection[0]||n.contains(t.$selection[0],document.activeElement)||t.trigger("blur",e)},1)},r.prototype._attachCloseHandler=function(e){n(document.body).on("mousedown.select2."+e.id,function(e){var t=n(e.target).closest(".select2");n(".select2.select2-container--open").each(function(){this!=t[0]&&s.GetData(this,"element").select2("close")})})},r.prototype._detachCloseHandler=function(e){n(document.body).off("mousedown.select2."+e.id)},r.prototype.position=function(e,t){t.find(".selection").append(e)},r.prototype.destroy=function(){this._detachCloseHandler(this.container)},r.prototype.update=function(e){throw new Error("The `update` method must be defined in child classes.")},r.prototype.isEnabled=function(){return!this.isDisabled()},r.prototype.isDisabled=function(){return this.options.get("disabled")},r}),u.define("select2/selection/single",["jquery","./base","../utils","../keys"],function(e,t,n,s){function i(){i.__super__.constructor.apply(this,arguments)}return n.Extend(i,t),i.prototype.render=function(){var e=i.__super__.render.call(this);return e[0].classList.add("select2-selection--single"),e.html(''),e},i.prototype.bind=function(t,e){var n=this;i.__super__.bind.apply(this,arguments);var s=t.id+"-container";this.$selection.find(".select2-selection__rendered").attr("id",s).attr("role","textbox").attr("aria-readonly","true"),this.$selection.attr("aria-labelledby",s),this.$selection.attr("aria-controls",s),this.$selection.on("mousedown",function(e){1===e.which&&n.trigger("toggle",{originalEvent:e})}),this.$selection.on("focus",function(e){}),this.$selection.on("blur",function(e){}),t.on("focus",function(e){t.isOpen()||n.$selection.trigger("focus")})},i.prototype.clear=function(){var e=this.$selection.find(".select2-selection__rendered");e.empty(),e.removeAttr("title")},i.prototype.display=function(e,t){var n=this.options.get("templateSelection");return this.options.get("escapeMarkup")(n(e,t))},i.prototype.selectionContainer=function(){return e("")},i.prototype.update=function(e){var t,n;0!==e.length?(n=e[0],t=this.$selection.find(".select2-selection__rendered"),e=this.display(n,t),t.empty().append(e),(n=n.title||n.text)?t.attr("title",n):t.removeAttr("title")):this.clear()},i}),u.define("select2/selection/multiple",["jquery","./base","../utils"],function(i,e,c){function r(e,t){r.__super__.constructor.apply(this,arguments)}return c.Extend(r,e),r.prototype.render=function(){var e=r.__super__.render.call(this);return e[0].classList.add("select2-selection--multiple"),e.html('
      '),e},r.prototype.bind=function(e,t){var n=this;r.__super__.bind.apply(this,arguments);var s=e.id+"-container";this.$selection.find(".select2-selection__rendered").attr("id",s),this.$selection.on("click",function(e){n.trigger("toggle",{originalEvent:e})}),this.$selection.on("click",".select2-selection__choice__remove",function(e){var t;n.isDisabled()||(t=i(this).parent(),t=c.GetData(t[0],"data"),n.trigger("unselect",{originalEvent:e,data:t}))}),this.$selection.on("keydown",".select2-selection__choice__remove",function(e){n.isDisabled()||e.stopPropagation()})},r.prototype.clear=function(){var e=this.$selection.find(".select2-selection__rendered");e.empty(),e.removeAttr("title")},r.prototype.display=function(e,t){var n=this.options.get("templateSelection");return this.options.get("escapeMarkup")(n(e,t))},r.prototype.selectionContainer=function(){return i('
    • ')},r.prototype.update=function(e){if(this.clear(),0!==e.length){for(var t=[],n=this.$selection.find(".select2-selection__rendered").attr("id")+"-choice-",s=0;s')).attr("title",s()),e.attr("aria-label",s()),e.attr("aria-describedby",n),a.StoreData(e[0],"data",t),this.$selection.prepend(e),this.$selection[0].classList.add("select2-selection--clearable"))},e}),u.define("select2/selection/search",["jquery","../utils","../keys"],function(s,a,l){function e(e,t,n){e.call(this,t,n)}return e.prototype.render=function(e){var t=this.options.get("translations").get("search"),n=s('');this.$searchContainer=n,this.$search=n.find("textarea"),this.$search.prop("autocomplete",this.options.get("autocomplete")),this.$search.attr("aria-label",t());e=e.call(this);return this._transferTabIndex(),e.append(this.$searchContainer),e},e.prototype.bind=function(e,t,n){var s=this,i=t.id+"-results",r=t.id+"-container";e.call(this,t,n),s.$search.attr("aria-describedby",r),t.on("open",function(){s.$search.attr("aria-controls",i),s.$search.trigger("focus")}),t.on("close",function(){s.$search.val(""),s.resizeSearch(),s.$search.removeAttr("aria-controls"),s.$search.removeAttr("aria-activedescendant"),s.$search.trigger("focus")}),t.on("enable",function(){s.$search.prop("disabled",!1),s._transferTabIndex()}),t.on("disable",function(){s.$search.prop("disabled",!0)}),t.on("focus",function(e){s.$search.trigger("focus")}),t.on("results:focus",function(e){e.data._resultId?s.$search.attr("aria-activedescendant",e.data._resultId):s.$search.removeAttr("aria-activedescendant")}),this.$selection.on("focusin",".select2-search--inline",function(e){s.trigger("focus",e)}),this.$selection.on("focusout",".select2-search--inline",function(e){s._handleBlur(e)}),this.$selection.on("keydown",".select2-search--inline",function(e){var t;e.stopPropagation(),s.trigger("keypress",e),s._keyUpPrevented=e.isDefaultPrevented(),e.which!==l.BACKSPACE||""!==s.$search.val()||0<(t=s.$selection.find(".select2-selection__choice").last()).length&&(t=a.GetData(t[0],"data"),s.searchRemoveChoice(t),e.preventDefault())}),this.$selection.on("click",".select2-search--inline",function(e){s.$search.val()&&e.stopPropagation()});var t=document.documentMode,o=t&&t<=11;this.$selection.on("input.searchcheck",".select2-search--inline",function(e){o?s.$selection.off("input.search input.searchcheck"):s.$selection.off("keyup.search")}),this.$selection.on("keyup.search input.search",".select2-search--inline",function(e){var t;o&&"input"===e.type?s.$selection.off("input.search input.searchcheck"):(t=e.which)!=l.SHIFT&&t!=l.CTRL&&t!=l.ALT&&t!=l.TAB&&s.handleSearch(e)})},e.prototype._transferTabIndex=function(e){this.$search.attr("tabindex",this.$selection.attr("tabindex")),this.$selection.attr("tabindex","-1")},e.prototype.createPlaceholder=function(e,t){this.$search.attr("placeholder",t.text)},e.prototype.update=function(e,t){var n=this.$search[0]==document.activeElement;this.$search.attr("placeholder",""),e.call(this,t),this.resizeSearch(),n&&this.$search.trigger("focus")},e.prototype.handleSearch=function(){var e;this.resizeSearch(),this._keyUpPrevented||(e=this.$search.val(),this.trigger("query",{term:e})),this._keyUpPrevented=!1},e.prototype.searchRemoveChoice=function(e,t){this.trigger("unselect",{data:t}),this.$search.val(t.text),this.handleSearch()},e.prototype.resizeSearch=function(){this.$search.css("width","25px");var e="100%";""===this.$search.attr("placeholder")&&(e=.75*(this.$search.val().length+1)+"em"),this.$search.css("width",e)},e}),u.define("select2/selection/selectionCss",["../utils"],function(n){function e(){}return e.prototype.render=function(e){var t=e.call(this),e=this.options.get("selectionCssClass")||"";return-1!==e.indexOf(":all:")&&(e=e.replace(":all:",""),n.copyNonInternalCssClasses(t[0],this.$element[0])),t.addClass(e),t},e}),u.define("select2/selection/eventRelay",["jquery"],function(o){function e(){}return e.prototype.bind=function(e,t,n){var s=this,i=["open","opening","close","closing","select","selecting","unselect","unselecting","clear","clearing"],r=["opening","closing","selecting","unselecting","clearing"];e.call(this,t,n),t.on("*",function(e,t){var n;-1!==i.indexOf(e)&&(t=t||{},n=o.Event("select2:"+e,{params:t}),s.$element.trigger(n),-1!==r.indexOf(e)&&(t.prevented=n.isDefaultPrevented()))})},e}),u.define("select2/translation",["jquery","require"],function(t,n){function s(e){this.dict=e||{}}return s.prototype.all=function(){return this.dict},s.prototype.get=function(e){return this.dict[e]},s.prototype.extend=function(e){this.dict=t.extend({},e.all(),this.dict)},s._cache={},s.loadPath=function(e){var t;return e in s._cache||(t=n(e),s._cache[e]=t),new s(s._cache[e])},s}),u.define("select2/diacritics",[],function(){return{"Ⓐ":"A","A":"A","À":"A","Á":"A","Â":"A","Ầ":"A","Ấ":"A","Ẫ":"A","Ẩ":"A","Ã":"A","Ā":"A","Ă":"A","Ằ":"A","Ắ":"A","Ẵ":"A","Ẳ":"A","Ȧ":"A","Ǡ":"A","Ä":"A","Ǟ":"A","Ả":"A","Å":"A","Ǻ":"A","Ǎ":"A","Ȁ":"A","Ȃ":"A","Ạ":"A","Ậ":"A","Ặ":"A","Ḁ":"A","Ą":"A","Ⱥ":"A","Ɐ":"A","Ꜳ":"AA","Æ":"AE","Ǽ":"AE","Ǣ":"AE","Ꜵ":"AO","Ꜷ":"AU","Ꜹ":"AV","Ꜻ":"AV","Ꜽ":"AY","Ⓑ":"B","B":"B","Ḃ":"B","Ḅ":"B","Ḇ":"B","Ƀ":"B","Ƃ":"B","Ɓ":"B","Ⓒ":"C","C":"C","Ć":"C","Ĉ":"C","Ċ":"C","Č":"C","Ç":"C","Ḉ":"C","Ƈ":"C","Ȼ":"C","Ꜿ":"C","Ⓓ":"D","D":"D","Ḋ":"D","Ď":"D","Ḍ":"D","Ḑ":"D","Ḓ":"D","Ḏ":"D","Đ":"D","Ƌ":"D","Ɗ":"D","Ɖ":"D","Ꝺ":"D","DZ":"DZ","DŽ":"DZ","Dz":"Dz","Dž":"Dz","Ⓔ":"E","E":"E","È":"E","É":"E","Ê":"E","Ề":"E","Ế":"E","Ễ":"E","Ể":"E","Ẽ":"E","Ē":"E","Ḕ":"E","Ḗ":"E","Ĕ":"E","Ė":"E","Ë":"E","Ẻ":"E","Ě":"E","Ȅ":"E","Ȇ":"E","Ẹ":"E","Ệ":"E","Ȩ":"E","Ḝ":"E","Ę":"E","Ḙ":"E","Ḛ":"E","Ɛ":"E","Ǝ":"E","Ⓕ":"F","F":"F","Ḟ":"F","Ƒ":"F","Ꝼ":"F","Ⓖ":"G","G":"G","Ǵ":"G","Ĝ":"G","Ḡ":"G","Ğ":"G","Ġ":"G","Ǧ":"G","Ģ":"G","Ǥ":"G","Ɠ":"G","Ꞡ":"G","Ᵹ":"G","Ꝿ":"G","Ⓗ":"H","H":"H","Ĥ":"H","Ḣ":"H","Ḧ":"H","Ȟ":"H","Ḥ":"H","Ḩ":"H","Ḫ":"H","Ħ":"H","Ⱨ":"H","Ⱶ":"H","Ɥ":"H","Ⓘ":"I","I":"I","Ì":"I","Í":"I","Î":"I","Ĩ":"I","Ī":"I","Ĭ":"I","İ":"I","Ï":"I","Ḯ":"I","Ỉ":"I","Ǐ":"I","Ȉ":"I","Ȋ":"I","Ị":"I","Į":"I","Ḭ":"I","Ɨ":"I","Ⓙ":"J","J":"J","Ĵ":"J","Ɉ":"J","Ⓚ":"K","K":"K","Ḱ":"K","Ǩ":"K","Ḳ":"K","Ķ":"K","Ḵ":"K","Ƙ":"K","Ⱪ":"K","Ꝁ":"K","Ꝃ":"K","Ꝅ":"K","Ꞣ":"K","Ⓛ":"L","L":"L","Ŀ":"L","Ĺ":"L","Ľ":"L","Ḷ":"L","Ḹ":"L","Ļ":"L","Ḽ":"L","Ḻ":"L","Ł":"L","Ƚ":"L","Ɫ":"L","Ⱡ":"L","Ꝉ":"L","Ꝇ":"L","Ꞁ":"L","LJ":"LJ","Lj":"Lj","Ⓜ":"M","M":"M","Ḿ":"M","Ṁ":"M","Ṃ":"M","Ɱ":"M","Ɯ":"M","Ⓝ":"N","N":"N","Ǹ":"N","Ń":"N","Ñ":"N","Ṅ":"N","Ň":"N","Ṇ":"N","Ņ":"N","Ṋ":"N","Ṉ":"N","Ƞ":"N","Ɲ":"N","Ꞑ":"N","Ꞥ":"N","NJ":"NJ","Nj":"Nj","Ⓞ":"O","O":"O","Ò":"O","Ó":"O","Ô":"O","Ồ":"O","Ố":"O","Ỗ":"O","Ổ":"O","Õ":"O","Ṍ":"O","Ȭ":"O","Ṏ":"O","Ō":"O","Ṑ":"O","Ṓ":"O","Ŏ":"O","Ȯ":"O","Ȱ":"O","Ö":"O","Ȫ":"O","Ỏ":"O","Ő":"O","Ǒ":"O","Ȍ":"O","Ȏ":"O","Ơ":"O","Ờ":"O","Ớ":"O","Ỡ":"O","Ở":"O","Ợ":"O","Ọ":"O","Ộ":"O","Ǫ":"O","Ǭ":"O","Ø":"O","Ǿ":"O","Ɔ":"O","Ɵ":"O","Ꝋ":"O","Ꝍ":"O","Œ":"OE","Ƣ":"OI","Ꝏ":"OO","Ȣ":"OU","Ⓟ":"P","P":"P","Ṕ":"P","Ṗ":"P","Ƥ":"P","Ᵽ":"P","Ꝑ":"P","Ꝓ":"P","Ꝕ":"P","Ⓠ":"Q","Q":"Q","Ꝗ":"Q","Ꝙ":"Q","Ɋ":"Q","Ⓡ":"R","R":"R","Ŕ":"R","Ṙ":"R","Ř":"R","Ȑ":"R","Ȓ":"R","Ṛ":"R","Ṝ":"R","Ŗ":"R","Ṟ":"R","Ɍ":"R","Ɽ":"R","Ꝛ":"R","Ꞧ":"R","Ꞃ":"R","Ⓢ":"S","S":"S","ẞ":"S","Ś":"S","Ṥ":"S","Ŝ":"S","Ṡ":"S","Š":"S","Ṧ":"S","Ṣ":"S","Ṩ":"S","Ș":"S","Ş":"S","Ȿ":"S","Ꞩ":"S","Ꞅ":"S","Ⓣ":"T","T":"T","Ṫ":"T","Ť":"T","Ṭ":"T","Ț":"T","Ţ":"T","Ṱ":"T","Ṯ":"T","Ŧ":"T","Ƭ":"T","Ʈ":"T","Ⱦ":"T","Ꞇ":"T","Ꜩ":"TZ","Ⓤ":"U","U":"U","Ù":"U","Ú":"U","Û":"U","Ũ":"U","Ṹ":"U","Ū":"U","Ṻ":"U","Ŭ":"U","Ü":"U","Ǜ":"U","Ǘ":"U","Ǖ":"U","Ǚ":"U","Ủ":"U","Ů":"U","Ű":"U","Ǔ":"U","Ȕ":"U","Ȗ":"U","Ư":"U","Ừ":"U","Ứ":"U","Ữ":"U","Ử":"U","Ự":"U","Ụ":"U","Ṳ":"U","Ų":"U","Ṷ":"U","Ṵ":"U","Ʉ":"U","Ⓥ":"V","V":"V","Ṽ":"V","Ṿ":"V","Ʋ":"V","Ꝟ":"V","Ʌ":"V","Ꝡ":"VY","Ⓦ":"W","W":"W","Ẁ":"W","Ẃ":"W","Ŵ":"W","Ẇ":"W","Ẅ":"W","Ẉ":"W","Ⱳ":"W","Ⓧ":"X","X":"X","Ẋ":"X","Ẍ":"X","Ⓨ":"Y","Y":"Y","Ỳ":"Y","Ý":"Y","Ŷ":"Y","Ỹ":"Y","Ȳ":"Y","Ẏ":"Y","Ÿ":"Y","Ỷ":"Y","Ỵ":"Y","Ƴ":"Y","Ɏ":"Y","Ỿ":"Y","Ⓩ":"Z","Z":"Z","Ź":"Z","Ẑ":"Z","Ż":"Z","Ž":"Z","Ẓ":"Z","Ẕ":"Z","Ƶ":"Z","Ȥ":"Z","Ɀ":"Z","Ⱬ":"Z","Ꝣ":"Z","ⓐ":"a","a":"a","ẚ":"a","à":"a","á":"a","â":"a","ầ":"a","ấ":"a","ẫ":"a","ẩ":"a","ã":"a","ā":"a","ă":"a","ằ":"a","ắ":"a","ẵ":"a","ẳ":"a","ȧ":"a","ǡ":"a","ä":"a","ǟ":"a","ả":"a","å":"a","ǻ":"a","ǎ":"a","ȁ":"a","ȃ":"a","ạ":"a","ậ":"a","ặ":"a","ḁ":"a","ą":"a","ⱥ":"a","ɐ":"a","ꜳ":"aa","æ":"ae","ǽ":"ae","ǣ":"ae","ꜵ":"ao","ꜷ":"au","ꜹ":"av","ꜻ":"av","ꜽ":"ay","ⓑ":"b","b":"b","ḃ":"b","ḅ":"b","ḇ":"b","ƀ":"b","ƃ":"b","ɓ":"b","ⓒ":"c","c":"c","ć":"c","ĉ":"c","ċ":"c","č":"c","ç":"c","ḉ":"c","ƈ":"c","ȼ":"c","ꜿ":"c","ↄ":"c","ⓓ":"d","d":"d","ḋ":"d","ď":"d","ḍ":"d","ḑ":"d","ḓ":"d","ḏ":"d","đ":"d","ƌ":"d","ɖ":"d","ɗ":"d","ꝺ":"d","dz":"dz","dž":"dz","ⓔ":"e","e":"e","è":"e","é":"e","ê":"e","ề":"e","ế":"e","ễ":"e","ể":"e","ẽ":"e","ē":"e","ḕ":"e","ḗ":"e","ĕ":"e","ė":"e","ë":"e","ẻ":"e","ě":"e","ȅ":"e","ȇ":"e","ẹ":"e","ệ":"e","ȩ":"e","ḝ":"e","ę":"e","ḙ":"e","ḛ":"e","ɇ":"e","ɛ":"e","ǝ":"e","ⓕ":"f","f":"f","ḟ":"f","ƒ":"f","ꝼ":"f","ⓖ":"g","g":"g","ǵ":"g","ĝ":"g","ḡ":"g","ğ":"g","ġ":"g","ǧ":"g","ģ":"g","ǥ":"g","ɠ":"g","ꞡ":"g","ᵹ":"g","ꝿ":"g","ⓗ":"h","h":"h","ĥ":"h","ḣ":"h","ḧ":"h","ȟ":"h","ḥ":"h","ḩ":"h","ḫ":"h","ẖ":"h","ħ":"h","ⱨ":"h","ⱶ":"h","ɥ":"h","ƕ":"hv","ⓘ":"i","i":"i","ì":"i","í":"i","î":"i","ĩ":"i","ī":"i","ĭ":"i","ï":"i","ḯ":"i","ỉ":"i","ǐ":"i","ȉ":"i","ȋ":"i","ị":"i","į":"i","ḭ":"i","ɨ":"i","ı":"i","ⓙ":"j","j":"j","ĵ":"j","ǰ":"j","ɉ":"j","ⓚ":"k","k":"k","ḱ":"k","ǩ":"k","ḳ":"k","ķ":"k","ḵ":"k","ƙ":"k","ⱪ":"k","ꝁ":"k","ꝃ":"k","ꝅ":"k","ꞣ":"k","ⓛ":"l","l":"l","ŀ":"l","ĺ":"l","ľ":"l","ḷ":"l","ḹ":"l","ļ":"l","ḽ":"l","ḻ":"l","ſ":"l","ł":"l","ƚ":"l","ɫ":"l","ⱡ":"l","ꝉ":"l","ꞁ":"l","ꝇ":"l","lj":"lj","ⓜ":"m","m":"m","ḿ":"m","ṁ":"m","ṃ":"m","ɱ":"m","ɯ":"m","ⓝ":"n","n":"n","ǹ":"n","ń":"n","ñ":"n","ṅ":"n","ň":"n","ṇ":"n","ņ":"n","ṋ":"n","ṉ":"n","ƞ":"n","ɲ":"n","ʼn":"n","ꞑ":"n","ꞥ":"n","nj":"nj","ⓞ":"o","o":"o","ò":"o","ó":"o","ô":"o","ồ":"o","ố":"o","ỗ":"o","ổ":"o","õ":"o","ṍ":"o","ȭ":"o","ṏ":"o","ō":"o","ṑ":"o","ṓ":"o","ŏ":"o","ȯ":"o","ȱ":"o","ö":"o","ȫ":"o","ỏ":"o","ő":"o","ǒ":"o","ȍ":"o","ȏ":"o","ơ":"o","ờ":"o","ớ":"o","ỡ":"o","ở":"o","ợ":"o","ọ":"o","ộ":"o","ǫ":"o","ǭ":"o","ø":"o","ǿ":"o","ɔ":"o","ꝋ":"o","ꝍ":"o","ɵ":"o","œ":"oe","ƣ":"oi","ȣ":"ou","ꝏ":"oo","ⓟ":"p","p":"p","ṕ":"p","ṗ":"p","ƥ":"p","ᵽ":"p","ꝑ":"p","ꝓ":"p","ꝕ":"p","ⓠ":"q","q":"q","ɋ":"q","ꝗ":"q","ꝙ":"q","ⓡ":"r","r":"r","ŕ":"r","ṙ":"r","ř":"r","ȑ":"r","ȓ":"r","ṛ":"r","ṝ":"r","ŗ":"r","ṟ":"r","ɍ":"r","ɽ":"r","ꝛ":"r","ꞧ":"r","ꞃ":"r","ⓢ":"s","s":"s","ß":"s","ś":"s","ṥ":"s","ŝ":"s","ṡ":"s","š":"s","ṧ":"s","ṣ":"s","ṩ":"s","ș":"s","ş":"s","ȿ":"s","ꞩ":"s","ꞅ":"s","ẛ":"s","ⓣ":"t","t":"t","ṫ":"t","ẗ":"t","ť":"t","ṭ":"t","ț":"t","ţ":"t","ṱ":"t","ṯ":"t","ŧ":"t","ƭ":"t","ʈ":"t","ⱦ":"t","ꞇ":"t","ꜩ":"tz","ⓤ":"u","u":"u","ù":"u","ú":"u","û":"u","ũ":"u","ṹ":"u","ū":"u","ṻ":"u","ŭ":"u","ü":"u","ǜ":"u","ǘ":"u","ǖ":"u","ǚ":"u","ủ":"u","ů":"u","ű":"u","ǔ":"u","ȕ":"u","ȗ":"u","ư":"u","ừ":"u","ứ":"u","ữ":"u","ử":"u","ự":"u","ụ":"u","ṳ":"u","ų":"u","ṷ":"u","ṵ":"u","ʉ":"u","ⓥ":"v","v":"v","ṽ":"v","ṿ":"v","ʋ":"v","ꝟ":"v","ʌ":"v","ꝡ":"vy","ⓦ":"w","w":"w","ẁ":"w","ẃ":"w","ŵ":"w","ẇ":"w","ẅ":"w","ẘ":"w","ẉ":"w","ⱳ":"w","ⓧ":"x","x":"x","ẋ":"x","ẍ":"x","ⓨ":"y","y":"y","ỳ":"y","ý":"y","ŷ":"y","ỹ":"y","ȳ":"y","ẏ":"y","ÿ":"y","ỷ":"y","ẙ":"y","ỵ":"y","ƴ":"y","ɏ":"y","ỿ":"y","ⓩ":"z","z":"z","ź":"z","ẑ":"z","ż":"z","ž":"z","ẓ":"z","ẕ":"z","ƶ":"z","ȥ":"z","ɀ":"z","ⱬ":"z","ꝣ":"z","Ά":"Α","Έ":"Ε","Ή":"Η","Ί":"Ι","Ϊ":"Ι","Ό":"Ο","Ύ":"Υ","Ϋ":"Υ","Ώ":"Ω","ά":"α","έ":"ε","ή":"η","ί":"ι","ϊ":"ι","ΐ":"ι","ό":"ο","ύ":"υ","ϋ":"υ","ΰ":"υ","ώ":"ω","ς":"σ","’":"'"}}),u.define("select2/data/base",["../utils"],function(n){function s(e,t){s.__super__.constructor.call(this)}return n.Extend(s,n.Observable),s.prototype.current=function(e){throw new Error("The `current` method must be defined in child classes.")},s.prototype.query=function(e,t){throw new Error("The `query` method must be defined in child classes.")},s.prototype.bind=function(e,t){},s.prototype.destroy=function(){},s.prototype.generateResultId=function(e,t){e=e.id+"-result-";return e+=n.generateChars(4),null!=t.id?e+="-"+t.id.toString():e+="-"+n.generateChars(4),e},s}),u.define("select2/data/select",["./base","../utils","jquery"],function(e,a,l){function n(e,t){this.$element=e,this.options=t,n.__super__.constructor.call(this)}return a.Extend(n,e),n.prototype.current=function(e){var t=this;e(Array.prototype.map.call(this.$element[0].querySelectorAll(":checked"),function(e){return t.item(l(e))}))},n.prototype.select=function(i){var e,r=this;if(i.selected=!0,null!=i.element&&"option"===i.element.tagName.toLowerCase())return i.element.selected=!0,void this.$element.trigger("input").trigger("change");this.$element.prop("multiple")?this.current(function(e){var t=[];(i=[i]).push.apply(i,e);for(var n=0;nthis.maximumInputLength?this.trigger("results:message",{message:"inputTooLong",args:{maximum:this.maximumInputLength,input:t.term,params:t}}):e.call(this,t,n)},e}),u.define("select2/data/maximumSelectionLength",[],function(){function e(e,t,n){this.maximumSelectionLength=n.get("maximumSelectionLength"),e.call(this,t,n)}return e.prototype.bind=function(e,t,n){var s=this;e.call(this,t,n),t.on("select",function(){s._checkIfMaximumSelected()})},e.prototype.query=function(e,t,n){var s=this;this._checkIfMaximumSelected(function(){e.call(s,t,n)})},e.prototype._checkIfMaximumSelected=function(e,t){var n=this;this.current(function(e){e=null!=e?e.length:0;0=n.maximumSelectionLength?n.trigger("results:message",{message:"maximumSelected",args:{maximum:n.maximumSelectionLength}}):t&&t()})},e}),u.define("select2/dropdown",["jquery","./utils"],function(t,e){function n(e,t){this.$element=e,this.options=t,n.__super__.constructor.call(this)}return e.Extend(n,e.Observable),n.prototype.render=function(){var e=t('');return e.attr("dir",this.options.get("dir")),this.$dropdown=e},n.prototype.bind=function(){},n.prototype.position=function(e,t){},n.prototype.destroy=function(){this.$dropdown.remove()},n}),u.define("select2/dropdown/search",["jquery"],function(r){function e(){}return e.prototype.render=function(e){var t=e.call(this),n=this.options.get("translations").get("search"),e=r('');return this.$searchContainer=e,this.$search=e.find("input"),this.$search.prop("autocomplete",this.options.get("autocomplete")),this.$search.attr("aria-label",n()),t.prepend(e),t},e.prototype.bind=function(e,t,n){var s=this,i=t.id+"-results";e.call(this,t,n),this.$search.on("keydown",function(e){s.trigger("keypress",e),s._keyUpPrevented=e.isDefaultPrevented()}),this.$search.on("input",function(e){r(this).off("keyup")}),this.$search.on("keyup input",function(e){s.handleSearch(e)}),t.on("open",function(){s.$search.attr("tabindex",0),s.$search.attr("aria-controls",i),s.$search.trigger("focus"),window.setTimeout(function(){s.$search.trigger("focus")},0)}),t.on("close",function(){s.$search.attr("tabindex",-1),s.$search.removeAttr("aria-controls"),s.$search.removeAttr("aria-activedescendant"),s.$search.val(""),s.$search.trigger("blur")}),t.on("focus",function(){t.isOpen()||s.$search.trigger("focus")}),t.on("results:all",function(e){null!=e.query.term&&""!==e.query.term||(s.showSearch(e)?s.$searchContainer[0].classList.remove("select2-search--hide"):s.$searchContainer[0].classList.add("select2-search--hide"))}),t.on("results:focus",function(e){e.data._resultId?s.$search.attr("aria-activedescendant",e.data._resultId):s.$search.removeAttr("aria-activedescendant")})},e.prototype.handleSearch=function(e){var t;this._keyUpPrevented||(t=this.$search.val(),this.trigger("query",{term:t})),this._keyUpPrevented=!1},e.prototype.showSearch=function(e,t){return!0},e}),u.define("select2/dropdown/hidePlaceholder",[],function(){function e(e,t,n,s){this.placeholder=this.normalizePlaceholder(n.get("placeholder")),e.call(this,t,n,s)}return e.prototype.append=function(e,t){t.results=this.removePlaceholder(t.results),e.call(this,t)},e.prototype.normalizePlaceholder=function(e,t){return t="string"==typeof t?{id:"",text:t}:t},e.prototype.removePlaceholder=function(e,t){for(var n=t.slice(0),s=t.length-1;0<=s;s--){var i=t[s];this.placeholder.id===i.id&&n.splice(s,1)}return n},e}),u.define("select2/dropdown/infiniteScroll",["jquery"],function(n){function e(e,t,n,s){this.lastParams={},e.call(this,t,n,s),this.$loadingMore=this.createLoadingMore(),this.loading=!1}return e.prototype.append=function(e,t){this.$loadingMore.remove(),this.loading=!1,e.call(this,t),this.showLoadingMore(t)&&(this.$results.append(this.$loadingMore),this.loadMoreIfNeeded())},e.prototype.bind=function(e,t,n){var s=this;e.call(this,t,n),t.on("query",function(e){s.lastParams=e,s.loading=!0}),t.on("query:append",function(e){s.lastParams=e,s.loading=!0}),this.$results.on("scroll",this.loadMoreIfNeeded.bind(this))},e.prototype.loadMoreIfNeeded=function(){var e=n.contains(document.documentElement,this.$loadingMore[0]);!this.loading&&e&&(e=this.$results.offset().top+this.$results.outerHeight(!1),this.$loadingMore.offset().top+this.$loadingMore.outerHeight(!1)<=e+50&&this.loadMore())},e.prototype.loadMore=function(){this.loading=!0;var e=n.extend({},{page:1},this.lastParams);e.page++,this.trigger("query:append",e)},e.prototype.showLoadingMore=function(e,t){return t.pagination&&t.pagination.more},e.prototype.createLoadingMore=function(){var e=n('
    • '),t=this.options.get("translations").get("loadingMore");return e.html(t(this.lastParams)),e},e}),u.define("select2/dropdown/attachBody",["jquery","../utils"],function(u,o){function e(e,t,n){this.$dropdownParent=u(n.get("dropdownParent")||document.body),e.call(this,t,n)}return e.prototype.bind=function(e,t,n){var s=this;e.call(this,t,n),t.on("open",function(){s._showDropdown(),s._attachPositioningHandler(t),s._bindContainerResultHandlers(t)}),t.on("close",function(){s._hideDropdown(),s._detachPositioningHandler(t)}),this.$dropdownContainer.on("mousedown",function(e){e.stopPropagation()})},e.prototype.destroy=function(e){e.call(this),this.$dropdownContainer.remove()},e.prototype.position=function(e,t,n){t.attr("class",n.attr("class")),t[0].classList.remove("select2"),t[0].classList.add("select2-container--open"),t.css({position:"absolute",top:-999999}),this.$container=n},e.prototype.render=function(e){var t=u(""),e=e.call(this);return t.append(e),this.$dropdownContainer=t},e.prototype._hideDropdown=function(e){this.$dropdownContainer.detach()},e.prototype._bindContainerResultHandlers=function(e,t){var n;this._containerResultsHandlersBound||(n=this,t.on("results:all",function(){n._positionDropdown(),n._resizeDropdown()}),t.on("results:append",function(){n._positionDropdown(),n._resizeDropdown()}),t.on("results:message",function(){n._positionDropdown(),n._resizeDropdown()}),t.on("select",function(){n._positionDropdown(),n._resizeDropdown()}),t.on("unselect",function(){n._positionDropdown(),n._resizeDropdown()}),this._containerResultsHandlersBound=!0)},e.prototype._attachPositioningHandler=function(e,t){var n=this,s="scroll.select2."+t.id,i="resize.select2."+t.id,r="orientationchange.select2."+t.id,t=this.$container.parents().filter(o.hasScroll);t.each(function(){o.StoreData(this,"select2-scroll-position",{x:u(this).scrollLeft(),y:u(this).scrollTop()})}),t.on(s,function(e){var t=o.GetData(this,"select2-scroll-position");u(this).scrollTop(t.y)}),u(window).on(s+" "+i+" "+r,function(e){n._positionDropdown(),n._resizeDropdown()})},e.prototype._detachPositioningHandler=function(e,t){var n="scroll.select2."+t.id,s="resize.select2."+t.id,t="orientationchange.select2."+t.id;this.$container.parents().filter(o.hasScroll).off(n),u(window).off(n+" "+s+" "+t)},e.prototype._positionDropdown=function(){var e=u(window),t=this.$dropdown[0].classList.contains("select2-dropdown--above"),n=this.$dropdown[0].classList.contains("select2-dropdown--below"),s=null,i=this.$container.offset();i.bottom=i.top+this.$container.outerHeight(!1);var r={height:this.$container.outerHeight(!1)};r.top=i.top,r.bottom=i.top+r.height;var o=this.$dropdown.outerHeight(!1),a=e.scrollTop(),l=e.scrollTop()+e.height(),c=ai.bottom+o,a={left:i.left,top:r.bottom},l=this.$dropdownParent;"static"===l.css("position")&&(l=l.offsetParent());i={top:0,left:0};(u.contains(document.body,l[0])||l[0].isConnected)&&(i=l.offset()),a.top-=i.top,a.left-=i.left,t||n||(s="below"),e||!c||t?!c&&e&&t&&(s="below"):s="above",("above"==s||t&&"below"!==s)&&(a.top=r.top-i.top-o),null!=s&&(this.$dropdown[0].classList.remove("select2-dropdown--below"),this.$dropdown[0].classList.remove("select2-dropdown--above"),this.$dropdown[0].classList.add("select2-dropdown--"+s),this.$container[0].classList.remove("select2-container--below"),this.$container[0].classList.remove("select2-container--above"),this.$container[0].classList.add("select2-container--"+s)),this.$dropdownContainer.css(a)},e.prototype._resizeDropdown=function(){var e={width:this.$container.outerWidth(!1)+"px"};this.options.get("dropdownAutoWidth")&&(e.minWidth=e.width,e.position="relative",e.width="auto"),this.$dropdown.css(e)},e.prototype._showDropdown=function(e){this.$dropdownContainer.appendTo(this.$dropdownParent),this._positionDropdown(),this._resizeDropdown()},e}),u.define("select2/dropdown/minimumResultsForSearch",[],function(){function e(e,t,n,s){this.minimumResultsForSearch=n.get("minimumResultsForSearch"),this.minimumResultsForSearch<0&&(this.minimumResultsForSearch=1/0),e.call(this,t,n,s)}return e.prototype.showSearch=function(e,t){return!(function e(t){for(var n=0,s=0;s');return e.attr("dir",this.options.get("dir")),this.$container=e,this.$container[0].classList.add("select2-container--"+this.options.get("theme")),r.StoreData(e[0],"element",this.$element),e},o}),u.define("jquery-mousewheel",["jquery"],function(e){return e}),u.define("jquery.select2",["jquery","jquery-mousewheel","./select2/core","./select2/defaults","./select2/utils"],function(i,e,r,t,o){var a;return null==i.fn.select2&&(a=["open","close","destroy"],i.fn.select2=function(t){if("object"==typeof(t=t||{}))return this.each(function(){var e=i.extend(!0,{},t);new r(i(this),e)}),this;if("string"!=typeof t)throw new Error("Invalid arguments for Select2: "+t);var n,s=Array.prototype.slice.call(arguments,1);return this.each(function(){var e=o.GetData(this,"select2");null==e&&window.console&&console.error&&console.error("The select2('"+t+"') method was called on an element that is not using Select2."),n=e[t].apply(e,s)}),-1Não há especialidades"); + } else + $('#expertise-select').removeAttr("disabled"); + $("#expertise-select").append(""); + + $.each(expertises, function (index, expertise) { + + if(expertise.id == element){ + $("#expertise-select").append(""); + }else { + $("#expertise-select").append(""); + } + + }); + $("#expertise-select").formSelect(); + } + }); + } + if ($("#expertise-select").val() != '') { + selectExpertise(element) + } + + var element_service = $("#dto_service").val(); + function selectExpertise(expertiseId) { + $.ajax({ + url: "servicos/especialidade/"+ expertiseId, + type: "GET", + success: function (services) { + + $("#service-select").empty(); + + //se o array for vazio, coloca o option que não há especialidades + if (services.length === 0) { + $('#service-select').prop("disabled", true); + $("#service-select").append(""); + } else + $('#service-select').removeAttr("disabled"); + $("#service-select").append(""); + + $.each(services, function (index, service) { + $("#service-select").append(""); + + if(service.id == element_service){ + $("#service-select").append(""); + }else { + $("#service-select").append(""); + } + + }); + $("#service-select").formSelect(); + } + }); + } + + // LISTA DE ESPECIALIDADE DE ACORDO COM A CATEGORIA + $("#category-select").change(function () { + let categoryId = $(this).val(); + $.ajax({ + url: "especialidades/categoria/"+ categoryId, + type: "GET", + success: function (expertises) { + console.log(expertises) + + $("#expertise-select").empty(); + + //se o array for vazio, coloca o option que não há especialidades + if (expertises.length === 0) + $("#expertise-select").append(""); + else + $("#expertise-select").append(""); + + $.each(expertises, function (index, expertise) { + $("#expertise-select").append(""); + }); + $("#expertise-select").formSelect(); + } + }); + }); + + // LISTA DE SERVIÇOS DE ACORDO COM A ESPECIALIDADE + $("#expertise-select").change(function () { + let expertiseId = $(this).val(); + $.ajax({ + url: "servicos/especialidade/"+ expertiseId, + type: "GET", + success: function (services) { + + $("#service-select").empty(); + + //se o array for vazio, coloca o option que não há especialidades + if (services.length === 0) + $("#service-select").append(""); + else + $("#service-select").append(""); + + $.each(services, function (index, service) { + $("#service-select").append(""); + + }); + $("#service-select").formSelect(); + } + }); + }); +}) \ No newline at end of file diff --git a/src/main/webapp/assets/resources/scripts/main.js b/src/main/webapp/assets/resources/scripts/main.js index 78b37b27..0049c59a 100644 --- a/src/main/webapp/assets/resources/scripts/main.js +++ b/src/main/webapp/assets/resources/scripts/main.js @@ -1,24 +1,24 @@ -$(document).ready(function (){ +$(document).ready(function () { - $('#select-city').change(function(i){ + $('#select-city').change(function (i) { let selectedCountry = $(this).children("option:selected").val(); $('#img-city').attr("src", selectedCountry); }); - $('#quantityCandidatorsMax').on('input', function() { + $('#quantityCandidatorsMax').on('input', function () { $('#value-input-range').html($(this).val()); }); //Tempo de exibição de mensagens $(".msg-view").fadeTo(5000, 0.0); - setTimeout(function() { + setTimeout(function () { $(".msg-view").addClass('hide'); }, 5001); - $("#show-area-perfil").click(function(i){ + $("#show-area-perfil").click(function (i) { $("#area-perfil").toggleClass('hide-on-med-and-down'); }); - + $('.modal').modal({ onOpenEnd: function (modal, trigger) { var url = $(trigger).data('url'); @@ -30,4 +30,4 @@ $(document).ready(function (){ modal.find('#strong-name').text(name); } }); -}); \ No newline at end of file +}) \ No newline at end of file diff --git a/src/main/webapp/assets/resources/styles/client/client.css b/src/main/webapp/assets/resources/styles/client/client.css index e69de29b..0504a4ca 100644 --- a/src/main/webapp/assets/resources/styles/client/client.css +++ b/src/main/webapp/assets/resources/styles/client/client.css @@ -0,0 +1,41 @@ +.professional-data{ + border: 1px solid black; +} + +fieldset, label { margin: 0; padding: 0; } +/****** Style Star Rating Widget *****/ + +.rating { + border: none; + float: left; +} + +.rating > input { display: none; } +.rating > label:before { + margin: 5px; + font-size: 1.25em; + font-family: FontAwesome; + display: inline-block; + content: "\f005"; +} + +.rating > .half:before { + content: "\f089"; + position: absolute; +} + +.rating > label { + color: #ddd; + float: right; +} + +/***** CSS Magic to Highlight Stars on Hover *****/ + +.rating > input:checked ~ label, /* show gold star when clicked */ +.rating:not(:checked) > label:hover, /* hover current star */ +.rating:not(:checked) > label:hover ~ label { color: #FFD700; } /* hover previous stars in list */ + +.rating > input:checked + label:hover, /* hover current star when changing rating */ +.rating > input:checked ~ label:hover, +.rating > label:hover ~ input:checked ~ label, /* lighten current selection */ +.rating > input:checked ~ label:hover ~ label { color: #FFED85; } \ No newline at end of file diff --git a/src/main/webapp/assets/resources/styles/visitor/visitor.css b/src/main/webapp/assets/resources/styles/visitor/visitor.css index 5c4a4ad2..51cb9ca0 100644 --- a/src/main/webapp/assets/resources/styles/visitor/visitor.css +++ b/src/main/webapp/assets/resources/styles/visitor/visitor.css @@ -56,6 +56,181 @@ font-weight: 400; } +/*cards da pesquisa*/ +.card .card-content{ + padding: 13px !important; +} +.label_price{ + /*background-color: #333333;*/ + background-color: #53b1ed; + font-weight: bold; + font-size: 1rem; + text-align: center; + padding: 5px; +} +.label_duration{ + /*background-color: #333333;*/ + background-color: #53b1ed; + font-weight: bold; + font-size: 1rem; + text-align: center; + padding: 5px; +} +.div_cards_services{ + margin: 10px 0 30px; +} + +.btn_view{ + /*float: right;*/ + float: right; + color: #1194e5 !important; + font-weight: bold; +} +.button-profile{ + font-size: .8rem !important; + margin-top: 30px; +} + +.card-name-service{ + padding: 0; + margin-top: 0 !important; + margin: 0 10px 20px; +} + +.card-name-expertise{ + background-color: #53b1ed; + margin: 0; +} +.avatar-expertise{ + width: 60px; + margin: 0 10px; +} +.span-name{ + position: absolute; + top: 10%; +} + +.btn_combined{ + width: 100%; + background-color: #53b1ed; + border: none; +} + +.btn_combined:hover{ + background-color: #53b1ed; +} + +/*.form-input {*/ +/* -webkit-appearance: none;*/ +/* appearance: none;*/ +/*}*/ + +/*.form-input::before {*/ +/* content: '';*/ +/* cursor: pointer;*/ +/* height: 100%;*/ +/* left: 0;*/ +/* position: absolute;*/ +/* top: 0;*/ +/* width: 100%;*/ +/*}*/ + + +/*.form-input::after {*/ +/* content: '';*/ +/* cursor: pointer;*/ +/* height: 15px;*/ +/* border-radius: 50px;*/ +/* border: 4px solid #21209c;*/ +/* left: 10%;*/ +/* position: absolute;*/ +/* top: 50%;*/ +/* transform: translate(0, -50%);*/ +/* width: 15px;*/ +/*}*/ + +/*.form-input:checked::after {*/ +/* border: 4px solid #ffffff;*/ +/*}*/ + +/*.form-label {*/ +/* color: #21209c;*/ +/* font-size: 1.1rem;*/ +/* margin-left: 10px;*/ +/* z-index: 1;*/ +/* !*position: absolute; This is an alternative option *!*/ +/*}*/ + +/*.form-input:checked ~ .form-label {*/ +/* color: red;*/ +/*}*/ + +/*.flex-center {*/ +/* align-items: center;*/ +/* display: flex;*/ +/* justify-content: center;*/ +/*}*/ +/*.form-row {*/ +/* background: #ffffff;*/ +/* border-radius: 50px;*/ +/* height: 40px;*/ +/* margin: 10px;*/ +/* overflow: hidden;*/ +/* position: relative;*/ +/* width: 150px;*/ +/*}*/ + + +/*TODOS OS PROFISSIONAIS DA BUSCA COM O SERVIÇO PESQUISADO*/ +.div_filter { + background-color: #D9D9D9; + padding: 20px 10px !important; +} +.labels_filter{ + /*margin: 5px 10px;*/ +} + +/* Oculta o radio button visualmente */ +.labels_filter input[type="radio"] { + position: absolute !important; + opacity: 0; +} + +/* Estiliza a label para parecer um botão clicável */ +.labels_filter { + padding: 5px; + cursor: pointer; + border: 1px solid #ccc; + margin: 0 10px; + width: 250px !important; +} + +/* Estiliza o span dentro da label */ +.labels_filter span { + padding-left: 10px; + padding-right: 10px; +} + +/* Adiciona estilo quando o radio button está marcado */ +.labels_filter input[type="radio"]:checked + span { + font-weight: bold; + color: white !important; + background-color: #549CED; + width: 200px !important; + text-align: center; + padding-left: 0 !important; +} + +.labels_filter input[type="radio"]:not(:checked)+span { + font-weight: bold; + text-align: center; + padding-left: 0 !important; + width: 200px !important; +} +.labels_filter input[type="radio"]+span:before, input[type="radio"]+span:after{ + content: none !important; + padding-left: 0 !important; +} \ No newline at end of file