diff --git a/src/main/java/br/edu/utfpr/servicebook/controller/MyAccountController.java b/src/main/java/br/edu/utfpr/servicebook/controller/MyAccountController.java index 1daf723b..3fdeb3c2 100644 --- a/src/main/java/br/edu/utfpr/servicebook/controller/MyAccountController.java +++ b/src/main/java/br/edu/utfpr/servicebook/controller/MyAccountController.java @@ -1,21 +1,23 @@ package br.edu.utfpr.servicebook.controller; import br.edu.utfpr.servicebook.model.dto.*; -import br.edu.utfpr.servicebook.model.entity.City; -import br.edu.utfpr.servicebook.model.entity.Individual; -import br.edu.utfpr.servicebook.model.entity.User; -import br.edu.utfpr.servicebook.model.entity.UserCode; +import br.edu.utfpr.servicebook.model.entity.*; import br.edu.utfpr.servicebook.model.mapper.*; import br.edu.utfpr.servicebook.security.IAuthentication; import br.edu.utfpr.servicebook.security.RoleType; import br.edu.utfpr.servicebook.service.*; import br.edu.utfpr.servicebook.util.UserTemplateInfo; import br.edu.utfpr.servicebook.util.TemplateUtil; +import br.edu.utfpr.servicebook.util.UserWizardUtil; +import org.apache.coyote.Response; +import org.cloudinary.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException; import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; import org.springframework.validation.BindingResult; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -26,8 +28,11 @@ import javax.annotation.security.RolesAllowed; import javax.persistence.EntityNotFoundException; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; import java.io.IOException; +import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; @RequestMapping("/minha-conta") @Controller @@ -72,6 +77,16 @@ public class MyAccountController { @Autowired private TemplateUtil templateUtil; + @Autowired + private UserWizardUtil userWizardUtil; + + @Autowired + private AddressMapper addressMapper; + @Autowired + private StateService stateService; + @Autowired + private StateMapper stateMapper; + @GetMapping public String home(HttpServletRequest request) { return "redirect:/minha-conta/cliente"; @@ -186,8 +201,139 @@ public ModelAndView showMyEmail(@PathVariable Long id) throws IOException { return mv; } + //edita endereço + + /** + * Apresenta a tela de endereço do usuário. + * @param id + * @return + * @throws IOException + */ + @GetMapping("/meu-endereco/{id}") + @RolesAllowed({RoleType.USER, RoleType.COMPANY}) + public String showMyAddress(@PathVariable Long id, Model model) throws IOException { + + Optional oUser = this.userService.findById(id); + + if (!oUser.isPresent()) { + throw new EntityNotFoundException("Usuário não encontrado pelo id informado."); + } + + Optional oUserAuthenticated = this.userService.findByEmail(authentication.getEmail()); + if(!oUserAuthenticated.isPresent()){ + throw new AuthenticationCredentialsNotFoundException("Usuário não autenticado! Por favor, realize sua autenticação no sistema."); + } + + User userAuthenticated = oUserAuthenticated.get(); + + //verifica se o usuario autenticado é o mesmo que está tentando atualizar as informações + if (id != userAuthenticated.getId()) { + throw new AuthenticationCredentialsNotFoundException("Você não tem permissão para atualizar essas informações"); + } + + Address address = userAuthenticated.getAddress(); + City city = address.getCity(); + State state = city.getState(); + + UserDTO userDTO = userMapper.toDto(oUser.get()); + + List cities = this.cityService.findAll(); + List states = this.stateService.findAll(); + + model.addAttribute("professional", userDTO); + model.addAttribute("cities", cities); + model.addAttribute("states", states); + + return "professional/account/my-address"; + } + + + /** + * @param id + * @param redirectAttributes + * @return + * @throws IOException + */ + @PatchMapping("/meu-endereco/{id}") + @RolesAllowed({RoleType.USER, RoleType.COMPANY}) + public String saveAddress( + @PathVariable Long id, + @Validated AddressUpdateDTO dto, + BindingResult errors, + RedirectAttributes redirectAttributes) + throws IOException { + + Optional oUser = this.userService.findById(id); + + if (!oUser.isPresent()) { + throw new EntityNotFoundException("Usuário não encontrado pelo id informado."); + } + + Optional oUserAuthenticated = this.userService.findByEmail(authentication.getEmail()); + if(!oUserAuthenticated.isPresent()){ + throw new AuthenticationCredentialsNotFoundException("Usuário não autenticado! Por favor, realize sua autenticação no sistema."); + } + + User userAuthenticated = oUserAuthenticated.get(); + + //verifica se o usuario autenticado é o mesmo que está tentando atualizar as informações + if (id != userAuthenticated.getId()) { + throw new AuthenticationCredentialsNotFoundException("Você não tem permissão para atualizar essas informações"); + } + + //verifica se o estado está cadastrado + if(!stateService.findById(dto.getState()).isPresent()){ + errors.rejectValue("state", "error.dto", "Estado não cadastrado! Por favor, insira um estado cadastrado."); + redirectAttributes.addFlashAttribute("errors", errors.getAllErrors()); + return "redirect:/minha-conta/meu-endereco/{id}"; + } + + //verifica se a cidade existe para o estado informado + if(!cityService.findByIdAndState_Id(dto.getCity(), dto.getState()).isPresent()){ + errors.rejectValue("city", "error.dto", "Cidade não cadastrada para o estado informado! Por favor, insira uma cidade cadastrada."); + redirectAttributes.addFlashAttribute("errors", errors.getAllErrors()); + return "redirect:/minha-conta/meu-endereco/{id}"; + } + + try { + //atualiza o endereço do usuário + Address address = userAuthenticated.getAddress(); + address.setCity(cityService.findById(dto.getCity()).get()); + address.setStreet(dto.getStreet().trim()); + address.setNumber(dto.getNumber().trim()); + address.setPostalCode(dto.getPostalCode().trim()); + address.setNeighborhood(dto.getNeighborhood().trim()); + + userAuthenticated.setAddress(address); + + this.userService.save(userAuthenticated); + redirectAttributes.addFlashAttribute("msg", "Endereço editado com sucesso"); + } catch (Exception exception) { + errors.rejectValue(null, "not-found", "Erro ao editar endereço: " + exception.getMessage()); + redirectAttributes.addFlashAttribute("errors", errors.getAllErrors()); + return "redirect:/minha-conta/meu-endereco/{id}"; + } + + return "redirect:/minha-conta/meu-endereco/{id}"; + } + + @PostMapping("/meu-endereco/{id}") + @RolesAllowed({RoleType.USER, RoleType.ADMIN}) + @ResponseBody + public ResponseEntity getExpertiseData(@PathVariable("id") Long userId, @RequestBody String data,BindingResult errors, + RedirectAttributes redirectAttributes) { + Response response = new Response(); + Optional oUser = this.userService.findById(userId); + JSONObject jsonObject = new JSONObject(data); + if(!cityService.findByName(jsonObject.getString("localidade")).isPresent()){ + response.setMessage("Cidade não cadastrada! Por favor, insira uma cidade cadastrada."); + return ResponseEntity.status(401).body(response.getMessage()); + } + response.setMessage("Cidade cadastrada no sistema!!"); + return ResponseEntity.status(200).body(response.getMessage()); + } + /** - * FIXME Ao mudar o email, fazer logout para o usuário logar novamente, aí com o novo email * @param id * @param request * @param redirectAttributes diff --git a/src/main/java/br/edu/utfpr/servicebook/controller/UserRegisterController.java b/src/main/java/br/edu/utfpr/servicebook/controller/UserRegisterController.java index c806442b..9e3f2654 100644 --- a/src/main/java/br/edu/utfpr/servicebook/controller/UserRegisterController.java +++ b/src/main/java/br/edu/utfpr/servicebook/controller/UserRegisterController.java @@ -604,7 +604,7 @@ public String saveUserNameAndCNPJ( @PermitAll public String saveUserAddress( HttpSession httpSession, - @Validated(AddressDTO.RequestUserAddressInfoGroupValidation.class) AddressDTO dto, + @Validated AddressDTO dto, BindingResult errors, RedirectAttributes redirectAttributes, Model model @@ -686,8 +686,7 @@ public String saveUser( IndividualDTO.RequestUserEmailInfoGroupValidation.class, IndividualDTO.RequestUserPasswordInfoGroupValidation.class, IndividualDTO.RequestUserPhoneInfoGroupValidation.class, - IndividualDTO.RequestUserNameAndCNPJInfoGroupValidation.class, - AddressDTO.RequestUserAddressInfoGroupValidation.class + IndividualDTO.RequestUserNameAndCNPJInfoGroupValidation.class }); if (errors.hasErrors()) { @@ -705,8 +704,7 @@ public String saveUser( IndividualDTO.RequestUserEmailInfoGroupValidation.class, IndividualDTO.RequestUserPasswordInfoGroupValidation.class, IndividualDTO.RequestUserPhoneInfoGroupValidation.class, - IndividualDTO.RequestUserNameAndCPFInfoGroupValidation.class, - AddressDTO.RequestUserAddressInfoGroupValidation.class + IndividualDTO.RequestUserNameAndCPFInfoGroupValidation.class }); if (errors.hasErrors()) { diff --git a/src/main/java/br/edu/utfpr/servicebook/model/dto/AddressDTO.java b/src/main/java/br/edu/utfpr/servicebook/model/dto/AddressDTO.java index 6b2ec868..85a2aa07 100644 --- a/src/main/java/br/edu/utfpr/servicebook/model/dto/AddressDTO.java +++ b/src/main/java/br/edu/utfpr/servicebook/model/dto/AddressDTO.java @@ -12,26 +12,22 @@ @AllArgsConstructor public class AddressDTO implements Serializable { - @NotBlank(message = "Rua inválida! Por favor, insira a rua do endereço.", groups = AddressDTO.RequestUserAddressInfoGroupValidation.class) + @NotBlank(message = "Rua inválida! Por favor, insira a rua do endereço.") private String street; - @NotBlank(message = "Número inválido! Por favor, insira o número do endereço.", groups = AddressDTO.RequestUserAddressInfoGroupValidation.class) private String number; - @NotBlank(message = "CEP inválido! Por favor, insira o CEP do endereço.", groups = AddressDTO.RequestUserAddressInfoGroupValidation.class) + @NotBlank(message = "CEP inválido! Por favor, insira o CEP do endereço.") private String postalCode; - @NotBlank(message = "Bairro inválido! Por favor, insira o bairro do endereço.", groups = AddressDTO.RequestUserAddressInfoGroupValidation.class) + @NotBlank(message = "Bairro inválido! Por favor, insira o bairro do endereço.") private String neighborhood; - @NotBlank(message = "Cidade Inválida! Por favor, insira a cidade do endereço.", groups = AddressDTO.RequestUserAddressInfoGroupValidation.class) + @NotBlank(message = "Cidade Inválida! Por favor, insira a cidade do endereço.") private String city; - @NotBlank(message = "Estado inválido! Por favor, insira o estado do endereço.", groups = AddressDTO.RequestUserAddressInfoGroupValidation.class) + @NotBlank(message = "Estado inválido! Por favor, insira o estado do endereço.") private String state; - public interface RequestUserAddressInfoGroupValidation { - - } } diff --git a/src/main/java/br/edu/utfpr/servicebook/model/dto/AddressFullDTO.java b/src/main/java/br/edu/utfpr/servicebook/model/dto/AddressFullDTO.java index bb150d20..b2709221 100644 --- a/src/main/java/br/edu/utfpr/servicebook/model/dto/AddressFullDTO.java +++ b/src/main/java/br/edu/utfpr/servicebook/model/dto/AddressFullDTO.java @@ -4,17 +4,21 @@ import lombok.Data; import lombok.NoArgsConstructor; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; import java.io.Serializable; @Data @NoArgsConstructor @AllArgsConstructor public class AddressFullDTO implements Serializable { - + @NotBlank(message = "Por favor, insira o nome da rua.") private String street; private String number; + @NotBlank(message = "Por favor, insira o CEP.") private String postalCode; private String neighborhood; + @NotNull(message = "Por favor, selecione uma cidade.") private CityMidDTO city; } diff --git a/src/main/java/br/edu/utfpr/servicebook/model/dto/AddressUpdateDTO.java b/src/main/java/br/edu/utfpr/servicebook/model/dto/AddressUpdateDTO.java new file mode 100644 index 00000000..99a75ea0 --- /dev/null +++ b/src/main/java/br/edu/utfpr/servicebook/model/dto/AddressUpdateDTO.java @@ -0,0 +1,34 @@ +package br.edu.utfpr.servicebook.model.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.io.Serializable; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class AddressUpdateDTO implements Serializable { + + @NotBlank(message = "Rua inválida! Por favor, insira a rua do endereço.") + private String street; + + private String number; + + @NotBlank(message = "CEP inválido! Por favor, insira o CEP do endereço.") + private String postalCode; + + @NotBlank(message = "Bairro inválido! Por favor, insira o bairro do endereço.") + private String neighborhood; + + @NotNull(message = "Cidade Inválida! Por favor, insira a cidade do endereço.") + private Long city; + + @NotNull(message = "Estado inválido! Por favor, insira o estado do endereço.") + private Long state; + + +} diff --git a/src/main/java/br/edu/utfpr/servicebook/model/dto/StateMinDTO.java b/src/main/java/br/edu/utfpr/servicebook/model/dto/StateMinDTO.java index c64a889a..27eeab2c 100644 --- a/src/main/java/br/edu/utfpr/servicebook/model/dto/StateMinDTO.java +++ b/src/main/java/br/edu/utfpr/servicebook/model/dto/StateMinDTO.java @@ -11,6 +11,7 @@ @AllArgsConstructor public class StateMinDTO implements Serializable { + private Long id; private String uf; } diff --git a/src/main/java/br/edu/utfpr/servicebook/model/mapper/AddressMapper.java b/src/main/java/br/edu/utfpr/servicebook/model/mapper/AddressMapper.java new file mode 100644 index 00000000..5bc54ee9 --- /dev/null +++ b/src/main/java/br/edu/utfpr/servicebook/model/mapper/AddressMapper.java @@ -0,0 +1,35 @@ +package br.edu.utfpr.servicebook.model.mapper; + +import br.edu.utfpr.servicebook.model.dto.AddressDTO; +import br.edu.utfpr.servicebook.model.dto.UserDTO; +import br.edu.utfpr.servicebook.model.entity.Address; +import br.edu.utfpr.servicebook.model.entity.City; +import br.edu.utfpr.servicebook.model.entity.User; +import org.modelmapper.ModelMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class AddressMapper { + + @Autowired + private ModelMapper mapper; + + public AddressDTO toDto(Address entity) { + AddressDTO dto = mapper.map(entity, AddressDTO.class); + return dto; + } + + public Address toEntity(AddressDTO dto) { + Address entity = mapper.map(dto, Address.class); + return entity; + } + + public Address toUpdate(AddressDTO dto, Long id, City city) { + Address entity = mapper.map(dto, Address.class); + entity.setId(id); + entity.setCity(city); + return entity; + } + +} diff --git a/src/main/java/br/edu/utfpr/servicebook/model/repository/CityRepository.java b/src/main/java/br/edu/utfpr/servicebook/model/repository/CityRepository.java index 937bbfa2..c9ebab9c 100644 --- a/src/main/java/br/edu/utfpr/servicebook/model/repository/CityRepository.java +++ b/src/main/java/br/edu/utfpr/servicebook/model/repository/CityRepository.java @@ -14,4 +14,7 @@ public interface CityRepository extends JpaRepository { Optional findByName(String name); + Optional findByIdAndState(Long id, State state); + Optional findByIdAndState_Id(Long cityId, Long stateId); + } diff --git a/src/main/java/br/edu/utfpr/servicebook/service/CityService.java b/src/main/java/br/edu/utfpr/servicebook/service/CityService.java index 4a7103fc..6d6485fc 100644 --- a/src/main/java/br/edu/utfpr/servicebook/service/CityService.java +++ b/src/main/java/br/edu/utfpr/servicebook/service/CityService.java @@ -40,6 +40,14 @@ public Optional findByNameAndState(String name, State state){ return this.cityRepository.findByNameAndState(name, state); } + public Optional findByIdAndState(Long id, State state){ + return this.cityRepository.findByIdAndState(id, state); + } + + public Optional findByIdAndState_Id(Long cityId, Long stateId){ + return this.cityRepository.findByIdAndState_Id(cityId, stateId); + } + public Optional findByName(String name){ return this.cityRepository.findByName(name); } diff --git a/src/main/webapp/WEB-INF/view/professional/account/my-address.jsp b/src/main/webapp/WEB-INF/view/professional/account/my-address.jsp new file mode 100644 index 00000000..083b4ca0 --- /dev/null +++ b/src/main/webapp/WEB-INF/view/professional/account/my-address.jsp @@ -0,0 +1,162 @@ +<%@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" %> + + + + +
+
+ +
+
+
+ ${msg} +
+
+
+
+ + +
+
+
+ + ${e.getDefaultMessage()}
+
+
+
+
+
+ + + + + +
+
+

+ Qual o seu endereço? +

+
+ Será útil para filtrar serviços por região e de acordo com a distância + para o local de realização do serviço. +
+
+ + +
+
+
+ + + +
+
+
+
+ +
+
+ +
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+ +
+ + +
+
+
+
+ +
+ + +
+
+
+
+
+ + +
+
+
+
+
+
+ +
+
+ + + + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/view/professional/edit-account.jsp b/src/main/webapp/WEB-INF/view/professional/edit-account.jsp index 152a6ec5..52cf0e54 100644 --- a/src/main/webapp/WEB-INF/view/professional/edit-account.jsp +++ b/src/main/webapp/WEB-INF/view/professional/edit-account.jsp @@ -40,7 +40,7 @@
- +

location_on

Meu endereço

diff --git a/src/main/webapp/assets/resources/scripts/cep-user-registration.js b/src/main/webapp/assets/resources/scripts/cep-user-registration.js index 266cf770..e210a830 100644 --- a/src/main/webapp/assets/resources/scripts/cep-user-registration.js +++ b/src/main/webapp/assets/resources/scripts/cep-user-registration.js @@ -1,8 +1,8 @@ $(document).ready(function () { - $('#postalCode').focus(); + $('#postal-code').focus(); function clearFormAddress() { - $('#postalCode').val(''); + $('#postal-code').val(''); $('#neighborhood').val(''); $('#street').val(''); $('#number').val(''); @@ -11,7 +11,8 @@ $(document).ready(function () { } $('#btn-search-cep').click(function () { - let cep = $('#postalCode').val().replace(/\D/g, ''); + debugger + let cep = $('#postal-code').val().replace(/\D/g, ''); if (cep != '') { let cepRegex = /^[0-9]{8}$/; @@ -19,7 +20,7 @@ $(document).ready(function () { if (cepRegex.test(cep)) { $.getJSON('https://viacep.com.br/ws/' + cep + '/json/?callback=?', function (data) { if (!('erro' in data)) { - $('#postalCode').removeClass('invalid'); + $('#postal-code').removeClass('invalid'); $('#error-cep').html(''); $('#neighborhood').val(data.bairro).focus(); @@ -27,24 +28,53 @@ $(document).ready(function () { $('#city').val(data.localidade).focus(); $('#state').val(data.uf).focus(); $('#number').focus(); + validaCity(data); } else { - $('#postalCode').addClass('invalid'); + $('#postal-code').addClass('invalid'); $('#errorPostalCode').removeClass('hide'); $('#errorPostalCode').html('CEP não encontrado!'); clearFormAddress(); } + $('select').formSelect(); }); } else { - $('#postalCode').addClass('invalid'); + $('#postal-code').addClass('invalid'); $('#errorPostalCode').removeClass('hide'); $('#errorPostalCode').html('CEP inválido!'); clearFormAddress(); } } else { - $('#postalCode').addClass('invalid'); + $('#postal-code').addClass('invalid'); $('#errorPostalCode').removeClass('hide'); $('#errorPostalCode').html('CEP inválido!'); clearFormAddress(); } }); + + function validaCity(data) { + var inputElement = document.querySelector('input[name="id"]'); + var professionalId = inputElement.value; + const apiUrl = `minha-conta/meu-endereco/${professionalId}` + $.ajax({ + url: apiUrl, + type: 'POST', + dataType: 'json', + contentType: 'application/json', + data: JSON.stringify(data), + success: function(response) { + console.log(response); + }, + error: function(error) { + console.error('Ocorreu um erro:', error); + if (error.status != 200) { + $("#errorCity").text(error.responseText) + $("#containerError").css("display", "block"); + } else { + $("#sucessCity").text(error.responseText) + $("#containerSucess").css("display", "block"); + } + } + }); + + } });