Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
a47fb14
[fix] 챗봇 추천 페이지 수정 및 기능추가 (#130)
ahk0413 Oct 13, 2025
61bd59c
Design/main#11 (#131)
EunbinJung Oct 13, 2025
f071906
Style/main page 2#122 (#132)
mtm-git1018 Oct 13, 2025
bd767b0
Style/메인페이지 슬라이드영역 (#135)
mtm-git1018 Oct 14, 2025
1dbeb90
[fix] 로그아웃 시 auth/me api 자동호출로 401 에러 (#136)
ahk0413 Oct 14, 2025
993820d
Design/main#11 (#138)
EunbinJung Oct 15, 2025
d6035f4
[fix] 레이아웃 분리 (#139)
ahk0413 Oct 15, 2025
0a71cd0
Refactor/recipe fetch (#140)
mtm-git1018 Oct 15, 2025
8ee022c
Merge remote-tracking branch 'origin/main' into dev
mtm-git1018 Oct 15, 2025
95248c2
[fix] 경로 오류 수정
mtm-git1018 Oct 15, 2025
a160b2a
경로 수정
mtm-git1018 Oct 15, 2025
9c64186
[fix] 경로수정
mtm-git1018 Oct 15, 2025
52e82c3
Feat/write#19 (#142)
EunbinJung Oct 15, 2025
3f0e6f3
[fix] MainSlide 수정 (#143)
ahk0413 Oct 15, 2025
1d0e476
Refactor/칵테일 정렬 기능 수정 (#144)
mtm-git1018 Oct 15, 2025
0d6c6be
Merge remote-tracking branch 'origin/main' into dev
mtm-git1018 Oct 15, 2025
c3c3644
[fix]충돌에러수정
mtm-git1018 Oct 15, 2025
d28a1f4
[style] 폰트 추가
mtm-git1018 Oct 15, 2025
94a65e0
[fix]파일 내 코드중복 수정
mtm-git1018 Oct 15, 2025
9e976a5
[chore]포매팅
mtm-git1018 Oct 15, 2025
06e809c
[fix]타입중복 수정
mtm-git1018 Oct 15, 2025
fcef37f
[chore]포매팅
mtm-git1018 Oct 15, 2025
ca5539a
docs/ 폰트 추가 및 삭제 (#146)
mtm-git1018 Oct 15, 2025
1c30893
[fix] scroll 위치이동
ahk0413 Oct 15, 2025
b517217
Merge remote-tracking branch 'origin/dev' into dev
ahk0413 Oct 15, 2025
ad53efa
Feat/write#19 (#147)
EunbinJung Oct 15, 2025
13fd5e1
Merge remote-tracking branch 'origin/dev' into dev
ahk0413 Oct 15, 2025
b75f7e8
[style] 폰트 추가
mtm-git1018 Oct 15, 2025
0efeda3
Merge branch 'dev' of https://github.com/prgrms-web-devcourse-final-p…
mtm-git1018 Oct 15, 2025
82254e5
[feat] 스크롤 버튼 추가
ahk0413 Oct 15, 2025
d02add2
Merge remote-tracking branch 'origin/dev' into dev
ahk0413 Oct 15, 2025
3723a9b
[fix] 시작 애니메이션 원복
ahk0413 Oct 15, 2025
c99fd87
[docs]README
mtm-git1018 Oct 15, 2025
49a5fbd
Feat/write#19 (#148)
EunbinJung Oct 15, 2025
85690d2
Merge branch 'main' into dev
EunbinJung Oct 15, 2025
c4b7b8b
[fix] 로그인 시 여러번 뜨는 toast 알림 이슈 수정
ahk0413 Oct 15, 2025
b3ceb95
Merge branch 'dev' of https://github.com/prgrms-web-devcourse-final-p…
ahk0413 Oct 15, 2025
dfe596e
fix/메인페이지 아코디언박스 오류 수정 (#151)
mtm-git1018 Oct 15, 2025
93c9bef
Merge remote-tracking branch 'origin/main' into dev
mtm-git1018 Oct 15, 2025
1353b45
[fix] 수정
EunbinJung Oct 16, 2025
ff1a17a
[fix] 다시 수정
EunbinJung Oct 16, 2025
c7f4eb3
수정
EunbinJung Oct 16, 2025
42e2438
수정
EunbinJung Oct 16, 2025
2591b69
Merge branch 'dev' of https://github.com/prgrms-web-devcourse-final-p…
EunbinJung Oct 16, 2025
0498846
메인 칵테일로고 반응형
EunbinJung Oct 16, 2025
da60f41
수정
EunbinJung Oct 16, 2025
b1394e7
Merge branch 'main' into dev
EunbinJung Oct 16, 2025
dc27ff7
next.js 수정
EunbinJung Oct 16, 2025
e154d53
Merge branch 'main' into dev
EunbinJung Oct 16, 2025
5636a66
Merge branch 'dev' of https://github.com/prgrms-web-devcourse-final-p…
EunbinJung Oct 16, 2025
05038f0
모바일글쓰기 수정
EunbinJung Oct 16, 2025
41adece
Merge branch 'dev' of https://github.com/prgrms-web-devcourse-final-p…
EunbinJung Oct 16, 2025
28b5eb0
인풋옵션수정
EunbinJung Oct 16, 2025
eb20d6c
401에러 로그인추가
EunbinJung Oct 17, 2025
65f161a
401수정
EunbinJung Oct 17, 2025
aa56dc0
수정
EunbinJung Oct 17, 2025
0584401
[docs] readme 수정
ahk0413 Oct 20, 2025
4a77b33
[docs] readme 수정
ahk0413 Oct 20, 2025
afde45d
[docs] readme 수정
ahk0413 Oct 20, 2025
049fd7b
Update README.md
EunbinJung Oct 20, 2025
c2ed553
Refactor/LCP문제 개선 (#159)
mtm-git1018 Nov 7, 2025
175d7d3
Merge remote-tracking branch 'origin/main' into dev
mtm-git1018 Nov 7, 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
5 changes: 4 additions & 1 deletion next.config.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import type { NextConfig } from 'next';

const nextConfig: NextConfig = {
reactStrictMode: false,
experimental: {
scrollRestoration: false,
},
images: {
// 외부 이미지 최적화 완전 비활성화 (Vercel 유료 기능 회피)
unoptimized: true,
// unoptimized: true,
domains: [
'team2-app-s3-bucket.s3.ap-northeast-2.amazonaws.com',
'team2-app-s3-bucket.s3.amazonaws.com',
Expand All @@ -15,12 +16,14 @@ const nextConfig: NextConfig = {
{
protocol: 'https',
hostname: 'www.thecocktaildb.com',
pathname: '/images/**',
},
],
},
env: {
NPUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL,
},

// webpack 설정
webpack: (config) => {
// @ts-expect-error 타입 에러 무시
Expand Down
4 changes: 2 additions & 2 deletions src/app/(with-layout)/mypage/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import MyNav from '@/domains/mypage/main/MyNav';
import MyProfile from '@/domains/mypage/main/MyProfile';
import MyNav from '@/domains/mypage/components/main/MyNav';
import MyProfile from '@/domains/mypage/components/main/MyProfile';
import SkeletonLayout from '@/domains/mypage/skeleton/main/SkeletonLayout';
import { Suspense } from 'react';

Expand Down
3 changes: 1 addition & 2 deletions src/app/(with-layout)/mypage/my-setting/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import MySetting from '@/domains/mypage/main/MySetting';

import MySetting from '@/domains/mypage/components/main/MySetting';
import { Metadata } from 'next';
export const metadata: Metadata = {
title: '마이페이지',
Expand Down
3 changes: 2 additions & 1 deletion src/domains/community/hook/useItemVirtualizer.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { useVirtualizer } from '@tanstack/react-virtual';
import { CommentType, Post } from '../types/post';
import { Cocktail } from '@/domains/recipe/types/types';

export function useItemVirtualizer(
items: CommentType[] | Post[] | null,
items: CommentType[] | Post[] | Cocktail[] | null,
parentRef: React.RefObject<HTMLElement | null>
) {
return useVirtualizer({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use client';
import Help from '@/shared/assets/icons/help_24.svg';
import ToolTip from '@/shared/components/tool-tip/ToolTip';
import useMedia from '../hook/useMedia';
import useMedia from '../../hook/useMedia';

function MyAbv({ abv }: { abv: number }) {
const isMd = useMedia('(min-width:768px)');
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
'use client';
import TabMenu from '@/domains/mypage/main/TabMenu';

import Link from 'next/link';
import { usePathname } from 'next/navigation';
import TabMenu from './TabMenu';

const MAIN_TABMENU = [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
import AbvGraph from '@/domains/shared/components/abv-graph/AbvGraph';
import MyAbv from './MyAbv';
import SsuryImage from './SsuryImage';
import useFetchProfile from '../api/fetchProfile';

import { useQuery } from '@tanstack/react-query';
import useFetchProfile from '../../api/fetchProfile';

function MyProfile() {
const { fetchProfile } = useFetchProfile();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import ToggleBtn from '@/domains/mypage/components/ToggleBtn';
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';
import useFetchProfile from '../../api/fetchProfile';

function MySetting() {
const { fetchProfile } = useFetchProfile();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import useProfileSsury from '../hook/useProfileSsury';
import Image from 'next/image';
import useProfileSsury from '../../hook/useProfileSsury';

function SsuryImage({ abvLevel }: { abvLevel: number }) {
const profileImage = useProfileSsury(abvLevel);
Expand Down
3 changes: 2 additions & 1 deletion src/domains/mypage/components/pages/my-active/MyComment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ function MyComment() {
credentials: 'include',
});
const json = await res.json();

setMyComment(json.data.items);
};

Expand All @@ -31,7 +32,7 @@ function MyComment() {

return (
<section>
{CommentList.length !== 0 ? (
{myComment.length !== 0 ? (
<CommentList
comments={myComment}
isLoading={isLoading}
Expand Down
34 changes: 28 additions & 6 deletions src/domains/recipe/api/fetchRecipe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ interface PageParam {
lastValue: number | string;
}

// 로그인 한 유저의 킵 칵테일을 Get으로 불러옴
const fetchKeep = async (): Promise<Set<number>> => {
const res = await fetch(`${getApi}/me/bar`, {
method: 'GET',
Expand All @@ -41,6 +42,7 @@ const fetchKeep = async (): Promise<Set<number>> => {
return new Set(myKeep.map((v: { cocktailId: number }) => v.cocktailId));
};

// 비 로그인 유저도 볼 수 있는 칵테일 API fetch 각 종 정렬 파라미터를 문자열로 받아서 정렬함
const fetchRecipe = async (
pageParam: PageParam | null,
size: number,
Expand Down Expand Up @@ -68,6 +70,7 @@ const fetchRecipe = async (
return json.data ?? [];
};

// 검색전용 API 여기서 필터링 토글도 받음
const searchCocktails = async (filters: SearchFilters): Promise<Cocktail[]> => {
const body = {
keyword: filters.keyword?.trim() ?? '',
Expand All @@ -90,6 +93,7 @@ const searchCocktails = async (filters: SearchFilters): Promise<Cocktail[]> => {
return json.data ?? [];
};

// 적용된 필터
const hasActiveFilters = (filters: SearchFilters): boolean => {
return !!(
filters.keyword?.trim() ||
Expand All @@ -99,10 +103,24 @@ const hasActiveFilters = (filters: SearchFilters): boolean => {
);
};

export const useKeepQuery = () => {
const user = useAuthStore((state) => state.user);

return useQuery({
queryKey: ['keeps', user?.id],
queryFn: fetchKeep,
enabled: !!user,
staleTime: 5 * 60 * 1000,
gcTime: 10 * 60 * 1000,
});
};

// 무한스크롤 fetch
export const useCocktailsInfiniteQuery = (size: number = 20, sortBy?: Sort) => {
const user = useAuthStore((state) => state.user);
const queryClient = useQueryClient();
const prevSortBy = useRef(sortBy);
const { data: keepIds } = useKeepQuery();

useEffect(() => {
if (prevSortBy.current !== undefined && prevSortBy.current !== sortBy) {
Expand All @@ -118,11 +136,10 @@ export const useCocktailsInfiniteQuery = (size: number = 20, sortBy?: Sort) => {
queryFn: async ({ pageParam }) => {
const cocktails = await fetchRecipe(pageParam, size, sortBy);

if (user) {
const keepId = await fetchKeep();
if (user && keepIds) {
return cocktails.map((item) => ({
...item,
isKeep: keepId.has(item.cocktailId),
isKeep: keepIds.has(item.cocktailId),
}));
}

Expand Down Expand Up @@ -159,31 +176,36 @@ export const useCocktailsInfiniteQuery = (size: number = 20, sortBy?: Sort) => {
initialPageParam: null as PageParam | null,
refetchOnMount: false,
refetchOnWindowFocus: false,
staleTime: 2 * 60 * 1000,
});
};

// 검색용 fetch
export const useCocktailsSearchQuery = (filters: SearchFilters) => {
const user = useAuthStore((state) => state.user);
const isActive = hasActiveFilters(filters);
const { data: keepIds } = useKeepQuery();

return useQuery({
queryKey: ['cocktails', 'search', filters, user?.id],
queryFn: async () => {
const cocktails = await searchCocktails(filters);
if (user && cocktails.length > 0) {
const keepId = await fetchKeep();
if (user && cocktails.length > 0 && keepIds) {
return cocktails.map((item) => ({
...item,
isKeep: keepId.has(item.cocktailId),
isKeep: keepIds.has(item.cocktailId),
}));
}
return cocktails;
},
enabled: isActive,
refetchOnMount: false,
refetchOnWindowFocus: false,
staleTime: 5 * 60 * 1000,
});
};

// 검색모드를 전환하여 어떤 fetch를 하는지 결정
export const useCocktails = (
filters: CocktailFilter,
infiniteScrollSize: number = 20,
Expand Down
20 changes: 18 additions & 2 deletions src/domains/recipe/components/main/CocktailFilter.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import SelectBox from '@/shared/components/select-box/SelectBox';
import { useRouter } from 'next/navigation';
import { useRouter, useSearchParams } from 'next/navigation';

interface Props {
cocktailsEA: number;
Expand All @@ -12,18 +12,34 @@ function CocktailFilter({ cocktailsEA }: Props) {
댓글순: 'comments',
};

const searchParams = useSearchParams();
const router = useRouter();

const getCurrentSort = () => {
const sortBy = searchParams.get('sortBy') || 'recent';

const entry = Object.entries(sortMap).find(([_, value]) => value === sortBy);
return entry ? entry[0] : '최신순';
};

const handleChange = (selectTitle: string) => {
const sortValue = sortMap[selectTitle as keyof typeof sortMap];

const params = new URLSearchParams(searchParams.toString());
params.set('sortBy', sortValue);

router.push(`?sortBy=${sortValue}`);
};

return (
<div className="h-10 flex justify-between items-center mt-3 border-b-1 border-gray-light">
<p>{cocktailsEA}개+</p>
<SelectBox option={['최신순', '댓글순', '인기순']} title="최신순" onChange={handleChange} />
<SelectBox
option={['최신순', '댓글순', '인기순']}
title="최신순"
onChange={handleChange}
value={getCurrentSort()}
/>
</div>
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
'use client';

import SelectBox from '@/shared/components/select-box/SelectBox';
import { Dispatch, SetStateAction, useEffect } from 'react';
import { useSearchParams, usePathname, useRouter } from 'next/navigation';
import { usePathname, useRouter, useSearchParams } from 'next/navigation';
import { Dispatch, SetStateAction } from 'react';

interface Props {
setAlcoholBaseTypes: Dispatch<SetStateAction<string[]>>;
Expand Down Expand Up @@ -64,26 +64,21 @@ const SELECT_OPTIONS = [
},
];

function Accordion({ setAlcoholBaseTypes, setCocktailTypes, setAlcoholStrengths }: Props) {
function CocktailFilterRadios({
setAlcoholBaseTypes,
setAlcoholStrengths,
setCocktailTypes,
}: Props) {
const router = useRouter();
const pathname = usePathname();
const searchParams = useSearchParams();

// url 파라미터에서 값을 가져와 POST를 도와줌
useEffect(() => {
const abv = searchParams.get('abv');
const base = searchParams.get('base');
const glass = searchParams.get('glass');

setAlcoholStrengths(abv ? [abv] : []);
setAlcoholBaseTypes(base ? [base] : []);
setCocktailTypes(glass ? [glass] : []);
}, [searchParams, setAlcoholStrengths, setAlcoholBaseTypes, setCocktailTypes]);

// 파라미터 값을 한글로 역 변환해주는 함수
const getDisplayValue = (id: string, code: string | null): string => {
// 파라미터에서 가져오는 값 없다면 전체로 표시 이 값을 전체가 아닌 타이틀이 나와야함
if (!code) return '전체';

// 파라미터에서 가져오는 아이디가 선택한 아이디와 일치하는지
const optionGroup = SELECT_OPTIONS.find((opt) => opt.id === id);
if (!optionGroup) return '전체';

Expand Down Expand Up @@ -147,9 +142,8 @@ function Accordion({ setAlcoholBaseTypes, setCocktailTypes, setAlcoholStrengths
<SelectBox
option={option}
title={title}
id={id}
groupKey="filter"
value={currentValue}
align="left"
onChange={(value) => handleSelect(id, value)}
/>
</li>
Expand All @@ -159,4 +153,4 @@ function Accordion({ setAlcoholBaseTypes, setCocktailTypes, setAlcoholStrengths
);
}

export default Accordion;
export default CocktailFilterRadios;
Loading
Loading