Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
0ca6858
[feat]칵테일 댓글 ui
mtm-git1018 Oct 9, 2025
da66e02
[chore] merge전 커밋
mtm-git1018 Oct 10, 2025
c6e283f
Merge remote-tracking branch 'origin/dev' into feat/commentRecipe#97
mtm-git1018 Oct 10, 2025
44b38a4
[chore] 확인용 커밋
mtm-git1018 Oct 10, 2025
14f2ea8
댓글에러
EunbinJung Oct 10, 2025
749c0f7
포맷
EunbinJung Oct 10, 2025
b987ff2
커뮤니티 댓글 수정
EunbinJung Oct 10, 2025
e81d109
[chore]풀 전용 커밋
mtm-git1018 Oct 10, 2025
436c68d
Merge branch 'feat/commentRecipe#97' of https://github.com/prgrms-web…
mtm-git1018 Oct 10, 2025
7ac9c4d
[feat] 칵테일 댓글등록
mtm-git1018 Oct 10, 2025
943550c
[feat]로그인 유저 킵 버튼
mtm-git1018 Oct 10, 2025
116298d
[feat] 나만의 바 라벨링
mtm-git1018 Oct 10, 2025
cf9b181
[feat]로그인 한 유저 킵버튼
mtm-git1018 Oct 11, 2025
e1c70c2
Merge remote-tracking branch 'origin/dev' into feat/commentRecipe#97
mtm-git1018 Oct 11, 2025
7e3f638
[feaet] 상세페이지 킵
mtm-git1018 Oct 11, 2025
0a4742e
[feat]레시피페이지정렬
mtm-git1018 Oct 11, 2025
0572d20
[feat] 댓글 클릭시 해당 글로 보내주는 기능
mtm-git1018 Oct 11, 2025
fd29597
[feat]댓글 작성 토스트
mtm-git1018 Oct 11, 2025
8b0a72e
[feat]댓글 validation
mtm-git1018 Oct 11, 2025
9acd060
[feat]댓글 validation
mtm-git1018 Oct 11, 2025
733ce4f
[fix] 댓글, 킵 아이템 비로그인 경고
mtm-git1018 Oct 11, 2025
3ae278d
[fix] mypage 401에러 대응
mtm-git1018 Oct 11, 2025
d025835
[feat] 마이페이지 프로필 수정 동기화
mtm-git1018 Oct 11, 2025
a3ef49b
[chore]포매팅
mtm-git1018 Oct 11, 2025
509e2f6
Merge remote-tracking branch 'origin/dev' into feat/commentRecipe#97
mtm-git1018 Oct 12, 2025
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
27 changes: 27 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
]
},
"dependencies": {
"@tanstack/react-query": "^5.90.2",
"@tanstack/react-virtual": "^3.13.12",
"class-variance-authority": "^0.7.1",
"gsap": "^3.13.0",
Expand Down
35 changes: 19 additions & 16 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import FooterWrapper from '@/shared/components/footer/FooterWrapper';
import ScrollTopBtnWrapper from '@/shared/components/scroll-top/ScrollTopBtnWrapper';
import KaKaoScript from './api/kakao/KaKaoScript';
import IdleHandler from '@/domains/login/components/IdleHandler';
import Provider from '@/shared/api/Provider';

export const metadata: Metadata = {
title: { default: 'SSOUL', template: 'SSOUL | %s' },
Expand All @@ -21,24 +22,26 @@ export default function RootLayout({
return (
<html lang="ko-KR">
<body className="relative flex flex-col min-h-screen">
<Header />
<IdleHandler />
<main className="flex flex-1 pt-[2.75rem] md:pt-[3.75rem]">{children}</main>
<FooterWrapper />
<Provider>
<Header />
<IdleHandler />
<main className="flex flex-1 pt-[2.75rem] md:pt-[3.75rem]">{children}</main>
<FooterWrapper />

<div id="modal-root"></div>
<Toaster
position="top-center"
toastOptions={{
duration: 2000,
style: {
minWidth: '340px',
background: 'transparent',
},
}}
/>
<div id="modal-root"></div>
<Toaster
position="top-center"
toastOptions={{
duration: 2000,
style: {
minWidth: '340px',
background: 'transparent',
},
}}
/>

<ScrollTopBtnWrapper />
<ScrollTopBtnWrapper />
</Provider>
</body>
<KaKaoScript />
</html>
Expand Down
2 changes: 1 addition & 1 deletion src/app/mypage/my-setting/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import MySetting from '@/domains/mypage/main/MySetting';

import { Metadata } from 'next';
export const metadata: Metadata = {
title: 'SSOUL | 마이페이지',
title: '마이페이지',
description: 'SSOUL 서비스에서 나의 활동을 관리할 수 있는 페이지입니다',
};

Expand Down
50 changes: 30 additions & 20 deletions src/domains/mypage/api/fetchProfile.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,46 @@
'use client';
import { getApi } from '@/app/api/config/appConfig';
import { useEffect, useState } from 'react';

interface Profile {
abvDegree: number;
abvLabel: string;
abvLevel: number;
email?: string;
id: number;
myCommentCount: number;
myKeepCount: number;
myLikedPostCount: number;
myPostCount: number;
nickname: string;
}
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { Profile } from '../types/type';

function useFetchProfile() {
const [profile, setProfile] = useState<Profile | null>(null);
const queryClient = useQueryClient();

const fetchProfile = async () => {
const res = await fetch(`${getApi}/me/profile`, {
method: 'GET',
credentials: 'include',
});
const json = await res.json();
setProfile(json.data);

return json.data;
};

useEffect(() => {
fetchProfile();
}, []);
const patchNickName = useMutation({
mutationFn: async (nickname: string) => {
const res = await fetch(`${getApi}/me/profile`, {
method: 'PATCH',
credentials: 'include',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ nickname }),
});
if (!res.ok) throw new Error('닉네임 수정 실패');
const json = await res.json();
return json.data;
},

onMutate: async (nickname) => {
// 같은 키로 요청중인 fetch 중단
await queryClient.cancelQueries({ queryKey: ['myProfile'] });
// 캐시에 저장된 데이터를 즉시 가져오는 역할 실패시 prev로 롤백
const prev = queryClient.getQueryData(['myProfile']);
// 캐시 내용을 수정
queryClient.setQueryData(['myProfile'], (old: Profile) => ({ ...old, nickname }));
return { prev };
},
});
const profile = useQuery({ queryKey: ['myProfile'], queryFn: fetchProfile });

return { profile, fetchProfile };
return { fetchProfile, profile, patchNickName };
}
export default useFetchProfile;
16 changes: 5 additions & 11 deletions src/domains/mypage/components/EditNickName.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Input from '@/shared/components/Input-box/Input';
import ModalLayout from '@/shared/components/modal-pop/ModalLayout';
import { useToast } from '@/shared/hook/useToast';
import { Dispatch, SetStateAction, useEffect, useState } from 'react';
import useFetchProfile from '../api/fetchProfile';

interface Props {
open: boolean;
Expand All @@ -27,6 +28,7 @@ function EditNickName({
}: Props) {
const [defaultNickname, setDefaultNickname] = useState(nickname);
const { toastSuccess, toastError } = useToast();
const { patchNickName } = useFetchProfile();

useEffect(() => {
setEditNickName(nickname);
Expand All @@ -35,22 +37,14 @@ function EditNickName({

const handlesave = async () => {
if (editNickName.length <= 1 || editNickName.length >= 8) {
toastError('닉네임은 2글자 이상 입력해야합니다');
toastError('닉네임은 2글자 이상 8글자 이내로 입력해야합니다');
return;
}

await setNickName(editNickName);
// CRUD중 CUD를 관리하는 메서드
await patchNickName.mutateAsync(editNickName);

await fetch(`${getApi}/me/profile`, {
method: 'PATCH',
credentials: 'include',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
nickname: editNickName,
}),
});
await setIsOpen(false);
toastSuccess('닉네임이 저장되었습니다.');
};
Expand Down
14 changes: 6 additions & 8 deletions src/domains/mypage/main/MyProfile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,13 @@ import AbvGraph from '@/domains/shared/components/abv-graph/AbvGraph';
import MyAbv from './MyAbv';
import SsuryImage from './SsuryImage';
import useFetchProfile from '../api/fetchProfile';
import { useEffect } from 'react';
import { useQuery } from '@tanstack/react-query';

function MyProfile() {
const { profile, fetchProfile } = useFetchProfile();
useEffect(() => {
fetchProfile();
}, [profile?.nickname]);
const { fetchProfile } = useFetchProfile();
const { data } = useQuery({ queryKey: ['myProfile'], queryFn: fetchProfile });

if (!profile) return;
if (!data) return;
const {
nickname,
abvLevel,
Expand All @@ -21,12 +19,12 @@ function MyProfile() {
myCommentCount,
myKeepCount,
abvDegree,
} = profile;
} = data;

return (
<section className="h-auto p-6 bg-white rounded-2xl">
<header className="flex flex-col gap-8 md:gap-3 md:flex-row md:justify-between ">
{profile && (
{data && (
<>
<div className="flex flex-col pb-4 md:pb-0 md:flex-col gap-6">
<div className="rounded-full w-17.5 h-17.5 flex items-center gap-2">
Expand Down
4 changes: 3 additions & 1 deletion src/domains/mypage/main/MySetting.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ import WithdrawModal from '@/domains/mypage/components/WithdrawModal';
import TextButton from '@/shared/components/button/TextButton';
import { useEffect, useState } from 'react';
import useFetchProfile from '../api/fetchProfile';
import { useQuery } from '@tanstack/react-query';

function MySetting() {
const { profile } = useFetchProfile();
const { fetchProfile } = useFetchProfile();
const { data: profile } = useQuery({ queryKey: ['myProfile'], queryFn: fetchProfile });
const [isOpen, setIsOpen] = useState(false);
const [isQuit, setIsQuit] = useState(false);
const [nickname, setNickName] = useState(profile?.nickname);
Expand Down
12 changes: 12 additions & 0 deletions src/domains/mypage/types/type.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export interface Profile {
abvDegree: number;
abvLabel: string;
abvLevel: number;
email: string | null;
id: number;
myCommentCount: number;
myKeepCount: number;
myLikedPostCount: number;
myPostCount: number;
nickname: string;
}
1 change: 1 addition & 0 deletions src/domains/recipe/components/main/Cocktails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import CocktailSearchBar from './CocktailSearchBar';
import useSearchControl from '../../hook/useSearchControl';
import CocktailSearch from '../../api/CocktailSearch';


function Cocktails() {
const [data, setData] = useState<Cocktail[]>([]);
const [lastId, setLastId] = useState<number | null>(null);
Expand Down
8 changes: 8 additions & 0 deletions src/shared/api/Provider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
'use client';
import { useState } from 'react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';

export default function Providers({ children }: { children: React.ReactNode }) {
const [client] = useState(() => new QueryClient());
return <QueryClientProvider client={client}>{children}</QueryClientProvider>;
}