diff --git a/src/app/(pages)/(albaform)/apply/[formId]/page.tsx b/src/app/(pages)/(albaform)/apply/[formId]/page.tsx
index 4b0a1d99..ffa9dc0e 100644
--- a/src/app/(pages)/(albaform)/apply/[formId]/page.tsx
+++ b/src/app/(pages)/(albaform)/apply/[formId]/page.tsx
@@ -8,7 +8,7 @@ import { cn } from "@/lib/tailwindUtil";
import axios from "axios";
import toast from "react-hot-toast";
import { useParams, useRouter } from "next/navigation";
-import { useMutation } from "@tanstack/react-query";
+import { useMutation, useQueryClient } from "@tanstack/react-query";
import Label from "../../component/Label";
import uploadResume from "@/utils/uploadResume";
import tempSave from "@/utils/tempSave";
@@ -47,44 +47,55 @@ export default function Apply() {
const formId = useParams().formId;
const router = useRouter();
- const currentValues = getValues();
- const { resume, ...submitData } = currentValues;
+ const queryClient = useQueryClient();
+
+ const onTempSave = async () => {
+ try {
+ const values = getValues();
+ const uploadedResume = await uploadResume(values.resume);
+ setValue("resumeId", uploadedResume.resumeId);
+ setValue("resumeName", uploadedResume.resumeName);
+ } catch (error) {
+ console.error("Error uploading resume:", error);
+ toast.error("이력서 업로드에 실패했습니다.");
+ }
+ };
// 폼 제출 리액트쿼리
const mutation = useMutation({
mutationFn: async () => {
- console.log("apply 제출 submitData 출력", submitData);
+ // 이력서 업로드 및 임시저장 먼저 수행
+ await onTempSave();
+
+ // 최신 값을 가져오기
+ const values = getValues();
+ const { resume, ...submitData } = values;
+
const response = await axios.post(`/api/forms/${formId}/applications`, submitData);
- console.log("apply 제출 response.data 출력", response.data);
+ return response.data;
},
onSuccess: () => {
+ // 로컬 스토리지 데이터 삭제
if (typeof window !== "undefined") {
window.localStorage.removeItem("tempAddFormData");
}
- toast.success("알바폼을 등록했습니다.");
- router.push(`/alba/${formId}`);
+
+ // 내 지원서 목록 캐시 무효화
+ queryClient.invalidateQueries({ queryKey: ["myApplications"] });
+
+ toast.success("지원이 완료되었습니다.");
+ router.push("/myalbaform");
},
onError: (error) => {
- console.error("에러가 발생했습니다.", error);
- toast.error("에러가 발생했습니다.");
+ console.error("지원하기에 실패했습니다.", error);
+ toast.error("지원하기에 실패했습니다.");
+ // 에러 발생 시 자동으로 임시저장
onTempSave();
},
});
- const onTempSave = async () => {
- try {
- const uploadedResume = await uploadResume(currentValues.resume);
- setValue("resumeId", uploadedResume.resumeId);
- setValue("resumeName", uploadedResume.resumeName);
- tempSave("applyData", currentValues);
- } catch (error) {
- console.error("Error uploading resume:", error);
- toast.error("이력서 업로드에 실패했습니다.");
- }
- };
-
const errorTextStyle =
"absolute -bottom-[26px] right-1 text-[13px] text-sm font-medium leading-[22px] text-state-error lg:text-base lg:leading-[26px]";
diff --git a/src/app/(pages)/albaTalk/[albatalkId]/sections/PostDetailSection.tsx b/src/app/(pages)/albaTalk/[albatalkId]/sections/PostDetailSection.tsx
index 3b8c411d..5fd2debc 100644
--- a/src/app/(pages)/albaTalk/[albatalkId]/sections/PostDetailSection.tsx
+++ b/src/app/(pages)/albaTalk/[albatalkId]/sections/PostDetailSection.tsx
@@ -45,6 +45,7 @@ export function PostDetailSection({ postId }: { postId: string }) {
onConfirm: () => {},
onCancel: () => {},
});
+ router.push("/albatalk");
},
});
},
@@ -82,12 +83,48 @@ export function PostDetailSection({ postId }: { postId: string }) {
{/* Author Info */}
-
-
+
-
{post?.writer.nickname}
-
|
-
{formatLocalDate(post?.createdAt || new Date())}
+
+
+ {post?.writer.nickname}
+ |
+ {formatLocalDate(post?.createdAt || new Date())}
+
+
+
+
+
+ {post?.commentCount}
+
+
+
+ {post?.likeCount}
+
@@ -111,36 +148,6 @@ export function PostDetailSection({ postId }: { postId: string }) {
) : null}
-
- {/* Footer */}
-
-
-
- {post?.commentCount}
-
-
-
- {post?.likeCount}
-
-
);
}
diff --git a/src/app/api/posts/[postId]/like/route.ts b/src/app/api/posts/[postId]/like/route.ts
index b2419865..a269cab1 100644
--- a/src/app/api/posts/[postId]/like/route.ts
+++ b/src/app/api/posts/[postId]/like/route.ts
@@ -6,7 +6,6 @@ import apiClient from "@/lib/apiClient";
// 게시글 좋아요 API
export async function POST(request: Request, { params }: { params: { postId: string } }) {
try {
- // 쿠키에서 액세스 토큰 가져오기
const accessToken = cookies().get("accessToken")?.value;
if (!accessToken) {
@@ -15,12 +14,16 @@ export async function POST(request: Request, { params }: { params: { postId: str
const postId = params.postId;
- // 게시글 좋아요 요청
- const response = await apiClient.post(`/posts/${postId}/like`, null, {
- headers: {
- Authorization: `Bearer ${accessToken}`,
- },
- });
+ // body를 빈 객체로 전송
+ const response = await apiClient.post(
+ `/posts/${postId}/like`,
+ {},
+ {
+ headers: {
+ Authorization: `Bearer ${accessToken}`,
+ },
+ }
+ );
return NextResponse.json(response.data);
} catch (error: unknown) {
@@ -37,7 +40,6 @@ export async function POST(request: Request, { params }: { params: { postId: str
// 게시글 좋아요 취소 API
export async function DELETE(request: Request, { params }: { params: { postId: string } }) {
try {
- // 쿠키에서 액세스 토큰 가져오기
const accessToken = cookies().get("accessToken")?.value;
if (!accessToken) {
@@ -46,7 +48,6 @@ export async function DELETE(request: Request, { params }: { params: { postId: s
const postId = params.postId;
- // 게시글 좋아요 취소 요청
const response = await apiClient.delete(`/posts/${postId}/like`, {
headers: {
Authorization: `Bearer ${accessToken}`,
diff --git a/src/app/api/posts/[postId]/route.ts b/src/app/api/posts/[postId]/route.ts
index ec76f32e..8f423708 100644
--- a/src/app/api/posts/[postId]/route.ts
+++ b/src/app/api/posts/[postId]/route.ts
@@ -7,10 +7,20 @@ import apiClient from "@/lib/apiClient";
export async function GET(request: Request, { params }: { params: { postId: string } }) {
try {
const postId = params.postId;
+ const accessToken = cookies().get("accessToken")?.value;
- // 게시글 상세 조회 요청
- const response = await apiClient.get(`/posts/${postId}`);
+ // 로그인한 유저의 경우 토큰과 함께 요청
+ if (accessToken) {
+ const response = await apiClient.get(`/posts/${postId}`, {
+ headers: {
+ Authorization: `Bearer ${accessToken}`,
+ },
+ });
+ return NextResponse.json(response.data);
+ }
+ // 로그인하지 않은 유저의 경우 토큰 없이 요청
+ const response = await apiClient.get(`/posts/${postId}`);
return NextResponse.json(response.data);
} catch (error: unknown) {
if (error instanceof AxiosError) {
diff --git a/src/app/components/card/cardList/MyApplicationListItem.tsx b/src/app/components/card/cardList/MyApplicationListItem.tsx
index f95cb507..c400767a 100644
--- a/src/app/components/card/cardList/MyApplicationListItem.tsx
+++ b/src/app/components/card/cardList/MyApplicationListItem.tsx
@@ -79,13 +79,15 @@ const MyApplicationListItem = ({ id, createdAt, status, resumeId, resumeName, fo
|
{formatLocalDate(createdAt, true)}
-
+ {resumeId > 0 && (
+
+ )}
{/* 중앙 컨텐츠 영역: 가게 정보, 제목, 설명 */}
diff --git a/src/app/components/input/file/ImageInput/ImageInputPlaceHolder.tsx b/src/app/components/input/file/ImageInput/ImageInputPlaceHolder.tsx
index 4ec6202e..e2b4a3f7 100644
--- a/src/app/components/input/file/ImageInput/ImageInputPlaceHolder.tsx
+++ b/src/app/components/input/file/ImageInput/ImageInputPlaceHolder.tsx
@@ -28,7 +28,9 @@ const ImageInputPlaceHolder: React.FC = ({
const fileInputRef = useRef(null);
useEffect(() => {
- setImageList(initialImages);
+ if (JSON.stringify(imageList) !== JSON.stringify(initialImages)) {
+ setImageList(initialImages);
+ }
}, [initialImages]);
const handleFileChange = async (event: React.ChangeEvent) => {
diff --git a/src/app/components/pagination/Pagination.tsx b/src/app/components/pagination/Pagination.tsx
index 4abea41d..bae1f139 100644
--- a/src/app/components/pagination/Pagination.tsx
+++ b/src/app/components/pagination/Pagination.tsx
@@ -61,41 +61,55 @@ const Pagination = ({ totalPage, currentPage, onPageChange }: PaginationProps):
return (
);
};
diff --git a/src/app/components/pagination/paginationComponent/PaginationBtn.tsx b/src/app/components/pagination/paginationComponent/PaginationBtn.tsx
index 51249823..46b56650 100644
--- a/src/app/components/pagination/paginationComponent/PaginationBtn.tsx
+++ b/src/app/components/pagination/paginationComponent/PaginationBtn.tsx
@@ -1,21 +1,30 @@
import { cn } from "@/lib/tailwindUtil";
-const PaginationBtn = ({
- children,
- extraStyle,
- disabled,
-}: {
+interface PaginationBtnProps {
children: React.ReactNode;
- extraStyle?: string;
+ onClick?: () => void;
disabled?: boolean;
-}) => {
- const wrapperStyle =
- "size-[34px] lg:radius-lg flex items-center justify-center rounded-md lg:size-[48px] bg-background-200";
- const textStyle = "leading-[24px] lg:text-lg text-sm lg:leading-[26px]";
- const defaultStyle = "text-grayscale-200 font-medium lg:font-normal";
+ extraStyle?: string;
+ "aria-label"?: string;
+ "aria-current"?: boolean;
+}
+const PaginationBtn = ({
+ children,
+ onClick,
+ disabled,
+ extraStyle,
+ "aria-label": ariaLabel,
+ "aria-current": ariaCurrent,
+}: PaginationBtnProps) => {
return (
-