From b471598d6cb7de92c4fe3009ed5cade560588291 Mon Sep 17 00:00:00 2001 From: pray4skylark Date: Tue, 2 Jun 2026 18:41:30 +0900 Subject: [PATCH] feat: add profile image to employee --- .../controller/EmployeeController.java | 11 +++++++ .../com/srsystem/dto/EmployeeSummary.java | 3 +- .../java/com/srsystem/entity/Employee.java | 3 ++ .../com/srsystem/service/EmployeeService.java | 4 ++- .../db/migration/V14__add_profile_image.sql | 1 + src/app/(main)/profile/page.tsx | 33 ++++++++++++++++--- src/services/employeeService.ts | 4 +++ src/types/index.ts | 1 + 8 files changed, 54 insertions(+), 6 deletions(-) create mode 100644 backend/src/main/resources/db/migration/V14__add_profile_image.sql diff --git a/backend/src/main/java/com/srsystem/controller/EmployeeController.java b/backend/src/main/java/com/srsystem/controller/EmployeeController.java index 1f62bc9..9237b4e 100644 --- a/backend/src/main/java/com/srsystem/controller/EmployeeController.java +++ b/backend/src/main/java/com/srsystem/controller/EmployeeController.java @@ -30,6 +30,7 @@ import org.springframework.web.bind.annotation.*; import jakarta.validation.Valid; import java.util.List; +import java.util.Map; @Tag(name = "Employee", description = "직원 관리 API") @RestController @@ -186,6 +187,16 @@ public class EmployeeController { return ResponseEntity.ok(ApiResponse.ok("비상연락망이 삭제되었습니다", null)); } + @Operation(summary = "프로필 이미지 설정", description = "직원의 프로필 이미지 URL을 저장합니다") + @PreAuthorize("hasAnyRole('EMPLOYEE', 'MANAGER', 'ADMIN')") + @PutMapping("/{empId}/profile-image") + public ResponseEntity> updateProfileImage( + @PathVariable Long empId, @RequestBody Map body) { + Employee emp = employeeService.findById(empId); + emp.setProfileImage(body.get("profileImage")); + return ResponseEntity.ok(ApiResponse.ok("프로필 이미지가 저장되었습니다", employeeService.update(empId, emp))); + } + @Operation(summary = "비밀번호 변경", description = "현재 사용자의 비밀번호를 변경합니다") @PreAuthorize("hasAnyRole('EMPLOYEE', 'MANAGER', 'ADMIN')") @PutMapping("/me/password") diff --git a/backend/src/main/java/com/srsystem/dto/EmployeeSummary.java b/backend/src/main/java/com/srsystem/dto/EmployeeSummary.java index 98f0f33..c34c07b 100644 --- a/backend/src/main/java/com/srsystem/dto/EmployeeSummary.java +++ b/backend/src/main/java/com/srsystem/dto/EmployeeSummary.java @@ -20,5 +20,6 @@ public record EmployeeSummary( String education, String major, LocalDate graduationDate, - String residence + String residence, + String profileImage ) {} diff --git a/backend/src/main/java/com/srsystem/entity/Employee.java b/backend/src/main/java/com/srsystem/entity/Employee.java index b5be363..69336d4 100644 --- a/backend/src/main/java/com/srsystem/entity/Employee.java +++ b/backend/src/main/java/com/srsystem/entity/Employee.java @@ -77,6 +77,9 @@ public class Employee extends BaseEntity { @Column(name = "residence", length = 255) private String residence; + @Column(name = "profile_image", length = 500) + private String profileImage; + @OneToMany(mappedBy = "employee", cascade = CascadeType.ALL, orphanRemoval = true) @OrderBy("sortOrder ASC") private List emergencyContacts; diff --git a/backend/src/main/java/com/srsystem/service/EmployeeService.java b/backend/src/main/java/com/srsystem/service/EmployeeService.java index cda1b30..7b87637 100644 --- a/backend/src/main/java/com/srsystem/service/EmployeeService.java +++ b/backend/src/main/java/com/srsystem/service/EmployeeService.java @@ -109,6 +109,7 @@ public class EmployeeService { employee.setMajor(updateRequest.getMajor()); employee.setGraduationDate(updateRequest.getGraduationDate()); employee.setResidence(updateRequest.getResidence()); + employee.setProfileImage(updateRequest.getProfileImage()); if (updateRequest.getPassword() != null && !updateRequest.getPassword().isBlank()) { employee.setPassword(passwordEncoder.encode(updateRequest.getPassword())); @@ -143,7 +144,8 @@ public class EmployeeService { employee.getEducation(), employee.getMajor(), employee.getGraduationDate(), - employee.getResidence() + employee.getResidence(), + employee.getProfileImage() ); } diff --git a/backend/src/main/resources/db/migration/V14__add_profile_image.sql b/backend/src/main/resources/db/migration/V14__add_profile_image.sql new file mode 100644 index 0000000..0aaf765 --- /dev/null +++ b/backend/src/main/resources/db/migration/V14__add_profile_image.sql @@ -0,0 +1 @@ +ALTER TABLE tb_employee ADD COLUMN IF NOT EXISTS profile_image VARCHAR(500); diff --git a/src/app/(main)/profile/page.tsx b/src/app/(main)/profile/page.tsx index d90acc6..be5f574 100644 --- a/src/app/(main)/profile/page.tsx +++ b/src/app/(main)/profile/page.tsx @@ -2,7 +2,7 @@ import React, { useState, useEffect } from 'react'; import { useRouter } from 'next/navigation'; -import { UserCircle, Mail, Briefcase, Calendar, Lock, Shield, CheckCircle, XCircle, AlertCircle, Phone, Plus, Pencil, Trash2, X, Save, GraduationCap, MapPin } from 'lucide-react'; +import { UserCircle, Mail, Briefcase, Calendar, Lock, Shield, CheckCircle, XCircle, AlertCircle, Phone, Plus, Pencil, Trash2, X, Save, GraduationCap, MapPin, Camera, Loader2 } from 'lucide-react'; import employeeService from '@/services/employeeService'; import type { ApiResponse, Employee, DispatchHistory, EmergencyContact } from '@/types'; @@ -266,9 +266,34 @@ export default function ProfilePage() { {/* Profile Card */}
- {/* Avatar */} -
- {formatInitial(employee.name)} + {/* Avatar with upload */} +
+ {employee.profileImage ? ( + {employee.name} + ) : ( +
+ {formatInitial(employee.name)} +
+ )} +
{/* Info Grid */} diff --git a/src/services/employeeService.ts b/src/services/employeeService.ts index 9b625ef..2f49620 100644 --- a/src/services/employeeService.ts +++ b/src/services/employeeService.ts @@ -83,6 +83,10 @@ const employeeService = { deleteEmergencyContact(empId: number, contactId: number) { return apiClient.delete>(`/employees/${empId}/emergency-contacts/${contactId}`); }, + + updateProfileImage(empId: number, profileImage: string) { + return apiClient.put>(`/employees/${empId}/profile-image`, { profileImage }); + }, }; export interface PortfolioEntry { diff --git a/src/types/index.ts b/src/types/index.ts index 63f063b..2d51f88 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -60,6 +60,7 @@ export interface Employee { major: string | null; graduationDate: string | null; residence: string | null; + profileImage: string | null; emergencyContacts?: EmergencyContact[]; }