Skip to content

Commit

Permalink
Merge branch 'develop' into be/fix/#259
Browse files Browse the repository at this point in the history
  • Loading branch information
YunJuwon0825 committed Feb 23, 2025
2 parents 1c1cae8 + 85b17bb commit 3f3772c
Show file tree
Hide file tree
Showing 16 changed files with 208 additions and 142 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Sort;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
Expand Down Expand Up @@ -141,4 +142,13 @@ public CommonResponse<List<PageableResumeResponse>> searchResumesByTag(@RequestP

return CommonResponse.of(SuccessCode.OK, pageableResumeResponse);
}

@Operation(summary = "이력서 삭제")
@DeleteMapping("/resumes/{resume_id}")
public CommonResponse<?> deleteResume(@PathVariable("resume_id") Long resumeId) {
User user = userService.getLoginUser();

resumeService.softDeleteResume(user, resumeId);
return CommonResponse.of(SuccessCode.RESUME_SOFT_DELETED, null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
@Repository
public interface ResumeRepository extends JpaRepository<Resume, Long>, ResumeRepositoryQueryDsl {

Optional<Resume> findByUserAndId(User user, Long id);

@Query("SELECT r FROM Resume r WHERE r.user.username = :username")
List<Resume> findResumesByUsername(@Param("username") String username);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,10 @@ public Resume findLaterByUser(User user) {
public Slice<Resume> getResumesByUser(User user) {
return resumeRepository.findResumeByUser(user);
}

public void softDeleteResume(User user, Long resumeId) {
Resume resume = resumeRepository.findByUserAndId(user, resumeId)
.orElseThrow(ResumeNotFoundException::new);
resume.softDelete();
}
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,9 @@
package com.techeer.backend.api.user.converter;

import com.techeer.backend.api.user.domain.Role;
import com.techeer.backend.api.user.domain.SocialType;
import com.techeer.backend.api.user.domain.User;
import com.techeer.backend.api.user.dto.response.UserInfoResponse;

public class UserConverter {
public static User fromSignUp(String email, String username, String refreshToken, Role role,
SocialType socialType) {
return User.builder()
.email(email)
.username(username)
.refreshToken(refreshToken)
.role(role)
.socialType(socialType)
.build();
}

public static UserInfoResponse ofUserInfoResponse(User user) {
return UserInfoResponse.builder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public enum SuccessCode implements BaseStatus {
// Resume Success
RESUME_CREATED(HttpStatus.CREATED, "RESUME_201", "이력서가 성공적으로 저장되었습니다"),
RESUME_FETCH_OK(HttpStatus.OK, "RESUME_200", "이력서 조회 성공"),
RESUME_SOFT_DELETED(HttpStatus.NO_CONTENT, "RESUME_204", "이력서 소프트 삭제 성공"),

// User Success
USER_FETCH_OK(HttpStatus.OK, "USER_200", "유저 정보 조회 성공"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
import com.techeer.backend.api.resume.domain.Resume;
import com.techeer.backend.api.resume.exception.ResumeNotFoundException;
import com.techeer.backend.api.resume.repository.ResumeRepository;
import com.techeer.backend.api.user.domain.User;
import com.techeer.backend.util.domain.ResumeUtils;
import com.techeer.backend.util.domain.UserUtils;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
Expand All @@ -29,7 +32,7 @@ class ResumeServiceTest {

@Mock
private ResumeRepository resumeRepository;


@BeforeEach
void setUp() {
Expand Down Expand Up @@ -122,4 +125,23 @@ void searchResumesByUserName_ShouldReturnListOfResumes1() {

verify(resumeRepository, times(1)).findResumesByUsername(userName);
}

@Test
void deleteResume_WhenResumeExists_ShouldDeleteResume() {
// Given (테스트 준비)
User user = UserUtils.newInstance();
Resume resume = ResumeUtils.newInstance();
Long resumeId = 1L;

// Mocking: 특정 user와 resumeId로 조회하면 해당 resume 반환
when(resumeRepository.findByUserAndId(user, resumeId)).thenReturn(Optional.of(resume));

// When (테스트 실행)
resumeService.softDeleteResume(user, resumeId);

// Then (결과 검증)
assertNotNull(resume.getDeletedAt()); // deletedAt이 null이 아니면 softDelete()가 정상 동작한 것
verify(resumeRepository, times(1)).findByUserAndId(user, resumeId);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.techeer.backend.util.domain;

import com.techeer.backend.api.resume.domain.Resume;
import com.techeer.backend.api.tag.position.Position;

public class ResumeUtils {
public static Resume newInstance() {
return Resume.builder()
.user(UserUtils.newInstance()) // 연관된 User 객체 추가
.name("test_resume")
.career(3) // 경력 (예: 3년)
.position(Position.BACKEND) // 실제 Position Enum 값을 확인 후 넣어주세요
.resumePdf(null) // ResumePdf를 넣을 경우 적절한 객체를 생성해야 함
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.techeer.backend.util.domain;

import com.techeer.backend.api.user.domain.Role;
import com.techeer.backend.api.user.domain.SocialType;
import com.techeer.backend.api.user.domain.User;

public class UserUtils {
public static User newInstance() {
return User.builder()
.email("test_user@example.com")
.username("test_man")
.refreshToken("test_refresh_token")
.role(Role.REGULAR) // 실제 Role Enum 값을 확인 후 넣어주세요
.socialType(SocialType.GOOGLE) // 실제 SocialType Enum 값을 확인 후 넣어주세요
.build();
}
}
2 changes: 1 addition & 1 deletion frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ export default function App() {
<Route path="/" element={<MainPage />} />
<Route path="/login" element={<Login />} />
<Route path="/search" element={<SearchPage />} />
<Route path="/feedback/:id" element={<ResumeFeedbackPage />} />

<Route element={<ProtectedRoute />}>
<Route path="/feedback/:id" element={<ResumeFeedbackPage />} />
<Route path="/upload" element={<Upload />} />
<Route path="/myInfo" element={<MyInfoPage />} />
</Route>
Expand Down
5 changes: 1 addition & 4 deletions frontend/src/api/bookMarkApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,8 @@ import { jsonAxios } from "./axios.config.ts";
// 북마크 추가
export const postBookmark = async (resumeId: number) => {
try {
console.log("아이디", resumeId);
const response = await jsonAxios.post(`/bookmarks/${resumeId}`);
// 응답에서 bookmark_id를 받아옵니다
const bookmarkId = response.data.result.bookmark_id;
return bookmarkId;
return response.data.result;
} catch (error) {
console.error("북마크 추가 오류:", error);
throw error;
Expand Down
13 changes: 8 additions & 5 deletions frontend/src/components/MyInfoPage/BookmarkItem.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { useNavigate } from "react-router-dom";
import { Bookmark, Trash } from "lucide-react";
import Swal from "sweetalert2";
import { BookmarkType } from "../../dataType";
import { BookmarkListType } from "../../dataType";
import { deleteBookmarkById } from "../../api/bookMarkApi";
import { formatDate } from "../../utils/DateFormatter.ts";

type BookmarkItemProps = {
bookmark: BookmarkType;
bookmark: BookmarkListType;
onUpdate: () => void; // 북마크 변경 시 호출되는 콜백
};

Expand Down Expand Up @@ -49,14 +50,16 @@ function BookmarkItem({ bookmark, onUpdate }: BookmarkItemProps) {
<div className="flex items-center space-x-4">
<Bookmark className="w-5 h-5 text-gray-500 mx-2" />
<div>
<h4 className="font-medium">2024 테커 상반기 채용 이력서</h4>
<p className="text-sm text-gray-500">정유진</p>
<h4 className="font-medium">{bookmark.resume_title}</h4>
<p className="text-sm text-gray-500">{bookmark.resume_author}</p>
</div>
</div>
</div>

<div className="flex items-center space-x-4 ml-10">
<span className="text-sm text-gray-500">2025-01-11</span>
<span className="text-sm text-gray-500">
{formatDate(bookmark.created_at)}
</span>
</div>
<div
className="flex items-center justify-center w-20 h-10 hover:scale-125 cursor-pointer"
Expand Down
15 changes: 5 additions & 10 deletions frontend/src/components/MyInfoPage/BookmarkTap.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { useState, useEffect } from "react";
import BookmarkItem from "../../components/MyInfoPage/BookmarkItem.tsx";
import { useEffect } from "react";
import { getBookmarkById } from "../../api/bookMarkApi.ts";
import { BookmarkType } from "../../dataType.ts";
import { useBookmarkStore } from "../../store/BookmarkStore.ts";
import BookmarkItem from "../../components/MyInfoPage/BookmarkItem.tsx";

function BookmarkTap() {
const [bookmarks, setBookmarks] = useState<BookmarkType[]>([]);
const { bookmarks, setBookmarks } = useBookmarkStore();

const userId = 1; // 임시. 지금 userId 필요 없음

Expand All @@ -18,11 +18,6 @@ function BookmarkTap() {
}
};

// 북마크가 변경될 때 호출
const handleBookmarkUpdate = () => {
fetchBookmarks();
};

useEffect(() => {
fetchBookmarks();
}, []);
Expand All @@ -41,7 +36,7 @@ function BookmarkTap() {
<BookmarkItem
key={bookmark.bookmark_id}
bookmark={bookmark}
onUpdate={handleBookmarkUpdate}
onUpdate={fetchBookmarks}
/>
))
) : (
Expand Down
8 changes: 8 additions & 0 deletions frontend/src/dataType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,11 @@ export type BookmarkType = {
title: string;
date: string;
};

export type BookmarkListType = {
bookmark_id: number;
created_at: string;
resume_author: string;
resume_id: number;
resume_title: string;
};
Loading

0 comments on commit 3f3772c

Please sign in to comment.