Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Week6/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
},
"dependencies": {
"@hookform/resolvers": "^5.0.1",
"@tanstack/react-query": "^5.72.1",
"@tanstack/react-query": "^5.76.1",
"@tanstack/react-query-devtools": "^5.75.2",
"axios": "^1.8.4",
"clsx": "^2.1.1",
Expand All @@ -21,6 +21,7 @@
"react-content-loader": "^7.0.2",
"react-dom": "^19.0.0",
"react-hook-form": "^7.55.0",
"react-icons": "^5.5.0",
"react-router-dom": "^7.4.1",
"zod": "^3.24.2"
},
Expand Down
Binary file added Week6/public/Lp.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Week6/public/closed-eyes.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Week6/public/eyes.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Week6/public/profile.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion Week6/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
import HomePage from './pages/Home/HomePage';
import Layout from './layout/Layout';
import SignupPage from './pages/SignUp/SignupPage';
import Mypage from './pages/Mypage';
import Mypage from './pages/Mypage/Mypage';
import LoginPage from './pages/Login/LoginPage';
import ProtectedLayout from './layout/ProtectedLayout';
import GoogleLoginRedirectPage from './pages/Login/GoogleLoginRedirectPage';
Expand Down
23 changes: 23 additions & 0 deletions Week6/src/apis/image.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { privateAxios, publicAxios } from './axiosInstance';
import { API_UPLOADS } from '../constants/api';
import { ResponseImageDto } from '../types/image';

export const postImagePrivate = async (
file: File,
): Promise<ResponseImageDto> => {
const formData = new FormData();
formData.append('file', file); // file타입

const { data } = await privateAxios.post(
API_UPLOADS.PRIVATE_UPLOAD,
formData,
);

return data;
};

export const postImagePublic = async () => {
const { data } = await publicAxios.post(API_UPLOADS.PUBLIC_UPLOAD);

return data;
};
105 changes: 103 additions & 2 deletions Week6/src/apis/lp.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import { API_COMMENTS, API_LPS } from '../constants/api';
import { API_COMMENTS, API_LIKES, API_LPS } from '../constants/api';
import { SortOrder } from '../constants/sort';
import {
ResponseLpDto,
ResponseLpDetailDto,
ResponseCommentDto,
CreateLpDto,
ResponsePostCommentDto,
ResponsePatchCommentDto,
patchLpDto,
} from '../types/lp';
import { privateAxios, publicAxios } from './axiosInstance';

Expand All @@ -25,6 +29,7 @@ export const getLpInfo = async ({
order,
},
});
console.log(data);
return data;
};

Expand All @@ -36,7 +41,7 @@ export const getLpDetail = async (
};

interface GetCommentsParms extends GetLpInfoParams {
lpId: number | string;
lpId: number;
}

export const getComments = async ({
Expand All @@ -51,3 +56,99 @@ export const getComments = async ({
);
return data;
};

export const postComment = async ({
lpId,
content,
}: {
lpId: number;
content: string;
}) => {
const { data } = await privateAxios.post<ResponsePostCommentDto>(
API_COMMENTS.CREATE(lpId),
{ content },
);
return data;
};

export const patchComment = async ({
lpId,
commentId,
content,
}: {
lpId: number;
commentId: number;
content: string;
}) => {
const { data } = await privateAxios.patch<ResponsePostCommentDto>(
API_COMMENTS.UPDATE(lpId, commentId),
{ content },
);
return data;
};

export const deleteComment = async ({
lpId,
commentId,
}: {
lpId: number;
commentId: number;
}) => {
const { data } = await privateAxios.delete<ResponsePatchCommentDto>(
API_COMMENTS.DELETE(lpId, commentId),
);

return data;
};

export const postLp = async ({
title,
content,
thumbnail,
tags,
published = true,
}: CreateLpDto) => {
const { data } = await privateAxios.post(API_LPS.CREATE, {
title,
content,
thumbnail,
tags,
published,
});

return data;
};

export const patchLp = async ({
lpId,
title,
content,
thumbnail,
tags,
published = true,
}: patchLpDto) => {
const { data } = await privateAxios.patch(API_LPS.UPDATE(lpId), {
title,
content,
thumbnail,
tags,
published,
});

return data;
};

export const deleteLp = async (lpId: number) => {
const { data } = await privateAxios.delete(API_LPS.DELETE(lpId));
return data;
};

export const postLike = async (lpId: number) => {
const { data } = await privateAxios.post(API_LIKES.LIKE(lpId));
return data;
};

export const deleteLike = async (lpId: number) => {
const { data } = await privateAxios.delete(API_LIKES.UNLIKE(lpId));
return data;
};
24 changes: 24 additions & 0 deletions Week6/src/apis/users.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { API_USERS } from '../constants/api';
import { privateAxios } from './axiosInstance';

interface patchUsersProps {
name: string;
bio: string;
avatar: string;
}

export const patchUsers = async ({ name, bio, avatar }: patchUsersProps) => {
const { data } = await privateAxios.patch(API_USERS.UPDATE_USER, {
name,
bio,
avatar,
});

return data;
};

export const deleteUser = async () => {
const { data } = await privateAxios.delete(API_USERS.DELETE_USER);

return data;
};
16 changes: 16 additions & 0 deletions Week6/src/components/LogoutButton/LogoutButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { useAuth } from '../../context/AuthContext';

function LogoutButton() {
const { logout } = useAuth();

return (
<button
onClick={logout}
className="px-4 py-2 text-white transition-colors duration-100 rounded-md bg-sky-600 hover:bg-sky-400"
>
로그아웃
</button>
);
}

export default LogoutButton;
63 changes: 63 additions & 0 deletions Week6/src/components/Modal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// src/components/common/Modal.tsx
import { PropsWithChildren } from 'react';
import { createPortal } from 'react-dom';

interface ModalProps extends PropsWithChildren {
/** 열림‧닫힘 여부 */
open: boolean;
/** 본문 메시지 */
message: string;
/** “예” 클릭 시 실행 */
onConfirm: () => void;
/** “아니오” 클릭 시 실행 */
onCancel: () => void;
/** 버튼 레이블(기본값: “예”) */
confirmText?: string;
/** 버튼 레이블(기본값: “아니오”) */
cancelText?: string;
}

export default function Modal({
open,
message,
onConfirm,
onCancel,
confirmText = '예',
cancelText = '아니오',
}: ModalProps) {
if (!open) return null;

return createPortal(
<div className="fixed inset-0 z-50 flex items-center justify-center">
{/* overlay */}
<div
className="absolute inset-0 bg-black opacity-60"
onClick={onCancel}
/>
{/* dialog */}
<div className="relative z-10 w-full max-w-sm p-8 bg-white rounded-lg shadow-lg">
{/* 메시지 */}
<p className="mb-6 text-center text-gray-900">{message}</p>

{/* 버튼 그룹 */}
<div className="flex justify-center gap-4">
<button
type="button"
onClick={onConfirm}
className="flex-1 py-2 text-gray-900 transition bg-gray-200 rounded-md hover:bg-gray-300"
>
{confirmText}
</button>
<button
type="button"
onClick={onCancel}
className="flex-1 py-2 text-white transition bg-pink-500 rounded-md hover:bg-pink-600"
>
{cancelText}
</button>
</div>
</div>
</div>,
document.body,
);
}
18 changes: 9 additions & 9 deletions Week6/src/constants/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,24 @@ export const API_LPS = {
CREATE: '/v1/lps',
LIST_BY_USER_ID: (userId: string) => `/v1/lps/user/${userId}`,
LIST_MY: '/v1/lps/user',
DETAIL: (lpId: string | number) => `/v1/lps/${lpId}`,
UPDATE: (lpId: string | number) => `/v1/lps/${lpId}`,
DELETE: (lpId: string) => `/v1/lps/${lpId}`,
DETAIL: (lpId: number) => `/v1/lps/${lpId}`,
UPDATE: (lpId: number) => `/v1/lps/${lpId}`,
DELETE: (lpId: number) => `/v1/lps/${lpId}`,
LIST_BY_TAG: (tagName: string) => `/v1/lps/tag/${tagName}`,
};

export const API_COMMENTS = {
LIST: (lpId: string | number) => `/v1/lps/${lpId}/comments`,
CREATE: (lpId: string) => `/v1/lps/${lpId}/comments`,
UPDATE: (lpId: string, commentId: string) =>
LIST: (lpId: number) => `/v1/lps/${lpId}/comments`,
CREATE: (lpId: number) => `/v1/lps/${lpId}/comments`,
UPDATE: (lpId: number, commentId: number) =>
`/v1/lps/${lpId}/comments/${commentId}`,
DELETE: (lpId: string, commentId: string) =>
DELETE: (lpId: number, commentId: number) =>
`/v1/lps/${lpId}/comments/${commentId}`,
};

export const API_LIKES = {
LIKE: (lpId: string) => `/v1/lps/${lpId}/likes`,
UNLIKE: (lpId: string) => `/v1/lps/${lpId}/likes`,
LIKE: (lpId: number) => `/v1/lps/${lpId}/likes`,
UNLIKE: (lpId: number) => `/v1/lps/${lpId}/likes`,
LIST_MY_LIKES: '/v1/lps/likes/me',
LIST_USER_LIKES: (userId: string) => `/v1/lps/likes/${userId}`,
};
Expand Down
6 changes: 5 additions & 1 deletion Week6/src/constants/images.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
export const IMAGE_PATH = {
GOOGLE_LOGO: '/google-logo.png',
PROFILE: '/my.png',
MY: '/my.png',
SEARCH_ICON: '/search.png',
LOGO: '/Logo.png',
EYE: '/eyes.png',
CLOSED_EYE: '/closed-eyes.png',
LP: '/Lp.png',
PROFILE: '/profile.png',
} as const;
5 changes: 5 additions & 0 deletions Week6/src/constants/key.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,8 @@ export const LOCAL_STORAGE_KEY = {
accessToken: 'accessToken',
refreshToken: 'refreshToken',
} as const;

export const QUERY_KEY = {
users: 'users',
lpDetail: 'lpDetail',
};
Loading