From 37a88fc1a01daa81d2442792b9fa4419744d5270 Mon Sep 17 00:00:00 2001 From: Josip Date: Sat, 28 Jun 2025 07:33:12 +0200 Subject: [PATCH] Fix user profile updating --- .../payload/UserUpdateRequest.java | 7 +- .../socialnetwork/service/UserService.java | 94 ++++++---------- frontend/src/pages/EditProfilePage.jsx | 100 +++--------------- 3 files changed, 50 insertions(+), 151 deletions(-) diff --git a/backend/src/main/java/hr/algebra/socialnetwork/payload/UserUpdateRequest.java b/backend/src/main/java/hr/algebra/socialnetwork/payload/UserUpdateRequest.java index d91ee40..89f2f5d 100644 --- a/backend/src/main/java/hr/algebra/socialnetwork/payload/UserUpdateRequest.java +++ b/backend/src/main/java/hr/algebra/socialnetwork/payload/UserUpdateRequest.java @@ -1,14 +1,11 @@ package hr.algebra.socialnetwork.payload; -import hr.algebra.socialnetwork.model.Gender; import hr.algebra.socialnetwork.validation.AlgebraEmail; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; -import jakarta.validation.constraints.Size; public record UserUpdateRequest( + @NotNull(message = "User ID is required") Long userId, @NotBlank(message = "Email is required") @AlgebraEmail String email, - @Size(min = 6, message = "Password must be at least 6 characters") String password, @NotBlank(message = "First name is required") String firstName, - @NotBlank(message = "Last name is required") String lastName, - @NotNull(message = "Gender is required") Gender gender) {} + @NotBlank(message = "Last name is required") String lastName) {} diff --git a/backend/src/main/java/hr/algebra/socialnetwork/service/UserService.java b/backend/src/main/java/hr/algebra/socialnetwork/service/UserService.java index 22a7af0..83165c5 100644 --- a/backend/src/main/java/hr/algebra/socialnetwork/service/UserService.java +++ b/backend/src/main/java/hr/algebra/socialnetwork/service/UserService.java @@ -6,7 +6,6 @@ import hr.algebra.socialnetwork.exception.ResourceNotFoundException; import hr.algebra.socialnetwork.mapper.UserDTOMapper; import hr.algebra.socialnetwork.mapper.UserSummaryDTOMapper; -import hr.algebra.socialnetwork.model.Gender; import hr.algebra.socialnetwork.model.User; import hr.algebra.socialnetwork.payload.UserUpdateRequest; import hr.algebra.socialnetwork.repository.UserRepository; @@ -16,7 +15,6 @@ import lombok.AllArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; -import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; @@ -27,7 +25,6 @@ public class UserService { private final UserRepository userRepository; private final UserDTOMapper userDTOMapper; private final UserSummaryDTOMapper userSummaryDTOMapper; - private final PasswordEncoder passwordEncoder; private final S3Service s3Service; public Page getAllUsers(Pageable pageable) { @@ -54,54 +51,12 @@ public UserDTO updateUserByEmail(String email, UserUpdateRequest request) { return userDTOMapper.apply(user); } - private User findUserByEmail(String email) { - return userRepository - .findByEmail(email) - .orElseThrow( - () -> new ResourceNotFoundException("User with email [%s] not found".formatted(email))); - } - - public void uploadProfileImage(Long userId, MultipartFile file) { - User user = - userRepository - .findById(userId) - .orElseThrow(() -> new ResourceNotFoundException("User not found with id: " + userId)); - - String imageId = UUID.randomUUID().toString(); - String key = "profile-images/%s/%s.jpg".formatted(userId, imageId); - - try { - s3Service.putObject(key, file.getBytes()); - } catch (IOException e) { - throw new RuntimeException("Failed to upload profile image", e); - } - - user.setProfileImageId(imageId); - userRepository.save(user); - } - - public byte[] getProfileImage(Long userId) { - User user = - userRepository - .findById(userId) - .orElseThrow(() -> new ResourceNotFoundException("User not found with id: " + userId)); - - if (user.getProfileImageId() == null || user.getProfileImageId().isBlank()) { - throw new ResourceNotFoundException("Profile image not set for user " + userId); - } - - String key = "profile-images/%s/%s.jpg".formatted(userId, user.getProfileImageId()); - return s3Service.getObject(key); - } - private boolean applyUserUpdates(User user, UserUpdateRequest request) { boolean updated = false; updated |= updateFirstName(user, request.firstName()); updated |= updateLastName(user, request.lastName()); updated |= updateEmail(user, request.email()); - updated |= updateGender(user, request.gender()); - updated |= updatePassword(user, request.password()); return updated; } @@ -111,7 +66,6 @@ private boolean updateFirstName(User user, String newFirstName) { user.setFirstName(newFirstName); return true; } - return false; } @@ -120,7 +74,6 @@ private boolean updateLastName(User user, String newLastName) { user.setLastName(newLastName); return true; } - return false; } @@ -129,29 +82,50 @@ private boolean updateEmail(User user, String newEmail) { user.setEmail(newEmail); return true; } - return false; } - private boolean updateGender(User user, Gender newGender) { - if (newGender != null && !newGender.equals(user.getGender())) { - user.setGender(newGender); - return true; + private boolean isValidUpdate(String newValue, String oldValue) { + return newValue != null && !newValue.isBlank() && !newValue.equals(oldValue); + } + + public void uploadProfileImage(Long userId, MultipartFile file) { + User user = + userRepository + .findById(userId) + .orElseThrow(() -> new ResourceNotFoundException("User not found with id: " + userId)); + + String imageId = UUID.randomUUID().toString(); + String key = "profile-images/%s/%s.jpg".formatted(userId, imageId); + + try { + s3Service.putObject(key, file.getBytes()); + } catch (IOException e) { + throw new RuntimeException("Failed to upload profile image", e); } - return false; + user.setProfileImageId(imageId); + userRepository.save(user); } - private boolean updatePassword(User user, String newPassword) { - if (newPassword != null && !newPassword.isBlank()) { - user.setPassword(passwordEncoder.encode(newPassword)); - return true; + public byte[] getProfileImage(Long userId) { + User user = + userRepository + .findById(userId) + .orElseThrow(() -> new ResourceNotFoundException("User not found with id: " + userId)); + + if (user.getProfileImageId() == null || user.getProfileImageId().isBlank()) { + throw new ResourceNotFoundException("Profile image not set for user " + userId); } - return false; + String key = "profile-images/%s/%s.jpg".formatted(userId, user.getProfileImageId()); + return s3Service.getObject(key); } - private boolean isValidUpdate(String newValue, String oldValue) { - return newValue != null && !newValue.isBlank() && !newValue.equals(oldValue); + private User findUserByEmail(String email) { + return userRepository + .findByEmail(email) + .orElseThrow( + () -> new ResourceNotFoundException("User with email [%s] not found".formatted(email))); } } diff --git a/frontend/src/pages/EditProfilePage.jsx b/frontend/src/pages/EditProfilePage.jsx index b9871d7..858473d 100644 --- a/frontend/src/pages/EditProfilePage.jsx +++ b/frontend/src/pages/EditProfilePage.jsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from "react"; +import React, { useState } from "react"; import { Flex, Box, @@ -11,78 +11,56 @@ import { Heading, Card, Input, - Select, - Portal, InputGroup, } from "@chakra-ui/react"; import { useNavigate } from "react-router-dom"; import Navbar from "../components/layout/Navbar"; -import { PasswordInput } from "../components/common/PasswordInput"; import { getEmailPrefix, getFirstName, getFullName, - getGender, getLastName, getUID, } from "../utils/utils"; import { updateUser, uploadProfileImage } from "../services/usersService"; -import { createListCollection } from "@chakra-ui/react"; function EditProfile() { const navigate = useNavigate(); const [firstName, setFirstName] = useState(getFirstName()); const [lastName, setLastName] = useState(getLastName()); - const [gender, setGender] = useState(""); const [email, setEmail] = useState(getEmailPrefix()); - const [password, setPassword] = useState(""); - const [confirmPassword, setConfirmPassword] = useState(""); const [selectedProfileImage, setSelectedProfileImage] = useState(null); const fullName = getFullName(); const UID = getUID(); - const genderOptions = createListCollection({ - items: [ - { label: "FEMALE", value: "FEMALE" }, - { label: "MALE", value: "MALE" }, - { label: "OTHER", value: "OTHER" }, - ], - }); - - useEffect(() => { - const tempGenderFetch = getGender(); - setGender(tempGenderFetch); - }, []); - async function handleSubmit(e) { e.preventDefault(); - if (password !== confirmPassword) { - alert("Passwords do not match."); - return; + if (selectedProfileImage) { + const formData = new FormData(); + formData.append("file", selectedProfileImage); + + try { + await uploadProfileImage(UID, formData); + } catch (err) { + console.error("Image upload failed", err); + alert("Failed to upload profile image"); + return; + } } const userData = { - email, - password, + userId: UID, + email: email + "@algebra.hr", firstName, lastName, - gender, }; try { const response = await updateUser(UID, userData); - if (response?.status === 200) { - if (selectedProfileImage) { - const formData = new FormData(); - formData.append("file", selectedProfileImage); - await uploadProfileImage(UID, formData); - console.log("Profile image uploaded"); - } - alert("Profile updated successfully!"); } else { alert("Failed to update profile."); @@ -90,10 +68,6 @@ function EditProfile() { } catch (error) { console.error("Update failed:", error); } - - console.log( - `${firstName} | ${lastName} | ${gender} | ${email} | ${password} | ${confirmPassword}`, - ); } return ( @@ -164,36 +138,6 @@ function EditProfile() { /> - { - setGender(key.value[0]); - }} - > - - Gender - - - - - - - - - - - - {genderOptions.items.map((item) => ( - - {item.label} - - - ))} - - - - - Email @@ -205,22 +149,6 @@ function EditProfile() { - - Password - setPassword(e.target.value)} - /> - - - - Confirm password - setConfirmPassword(e.target.value)} - /> - - Profile Image