diff --git a/package-lock.json b/package-lock.json index 3f40263f..dd5b2823 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7525,6 +7525,12 @@ "node": ">=10" } }, + "node_modules/html-to-image": { + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/html-to-image/-/html-to-image-1.11.13.tgz", + "integrity": "sha512-cuOPoI7WApyhBElTTb9oqsawRvZ0rHhaHwghRLlTuffoD1B2aDemlCruLeZrUIIdvG7gs9xeELEPm6PhuASqrg==", + "license": "MIT" + }, "node_modules/http-proxy-agent": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", diff --git a/src/domains/community/api/fetchComment.ts b/src/domains/community/api/fetchComment.ts index c4d1ffef..78258912 100644 --- a/src/domains/community/api/fetchComment.ts +++ b/src/domains/community/api/fetchComment.ts @@ -32,7 +32,6 @@ export const postComments = async (postId: number | ParamValue, content: string) credentials: 'include', body: JSON.stringify({ content }), }); - const text = await res.text(); if (!res.ok) { diff --git a/src/domains/main/components/mainSlide/components/MainSlide.tsx b/src/domains/main/components/mainSlide/components/MainSlide.tsx index 67f73fb6..88085e74 100644 --- a/src/domains/main/components/mainSlide/components/MainSlide.tsx +++ b/src/domains/main/components/mainSlide/components/MainSlide.tsx @@ -8,6 +8,7 @@ import MobileSlide from './mobile/MobileSlide'; import MainSlideIntro from './MainSlideIntro'; import MainSlideTest from './MainSlideTest'; import MainSlideCommunity from './MainSlideCommunity'; +import StarBg from '@/domains/shared/components/star-bg/StarBg'; gsap.registerPlugin(ScrollTrigger); @@ -18,7 +19,6 @@ function MainSlide() { const cleanupFnRef = useRef<(() => void) | null>(null); const resizeTimeoutRef = useRef(null); - // 초기 마운트 useEffect(() => { setIsMobile(window.innerWidth < 1024); setMounted(true); @@ -42,6 +42,9 @@ function MainSlide() { // 상태 업데이트 setIsMobile(newIsMobile); + } else if (!newIsMobile) { + // 데스크탑 내에서의 리사이즈 - ScrollTrigger refresh + ScrollTrigger.refresh(true); } }, 200); }; @@ -68,13 +71,12 @@ function MainSlide() { const stage = el.querySelector('.stage') as HTMLElement; if (!stage) return; - // 약간의 지연을 줘서 DOM이 안정화되도록 const timer = setTimeout(() => { if (!root.current) return; const ctx = gsap.context(() => { const panels = Array.from(el.querySelectorAll('.panel')); - const tl = gsap.timeline({ paused: true, defaults: { ease: 'none' } }); + const tl = gsap.timeline({ paused: true, defaults: { ease: 'power3.inOut' } }); panels.forEach((panel, i) => { const c = panel.querySelector('.slide-content'); @@ -82,13 +84,16 @@ function MainSlide() { const stageW = () => stage.clientWidth; const contentW = () => c.getBoundingClientRect().width; - gsap.set(c, { x: stageW() }); + gsap.set(c, { + x: () => stageW(), + immediateRender: false, + }); tl.to( c, { x: () => stageW() - contentW(), - duration: 1, + duration: 2, immediateRender: false, onStart: () => c.classList.remove('invisible'), }, @@ -109,9 +114,7 @@ function MainSlide() { ScrollTrigger.refresh(); }, root); - // cleanup 함수를 ref에 저장 cleanupFnRef.current = () => { - // ScrollTrigger를 먼저 완전히 제거 const allTriggers = ScrollTrigger.getAll(); allTriggers.forEach((st) => { if (st.trigger === el || el.contains(st.trigger as Node)) { @@ -119,26 +122,18 @@ function MainSlide() { } }); - // GSAP context revert try { ctx.revert(); - } catch (e) { - // 무시 - } + } catch {} - // 혹시 남아있는 pin-spacer 수동 제거 const pinSpacers = document.querySelectorAll('.pin-spacer'); pinSpacers.forEach((spacer) => { if (spacer.contains(el) || el.contains(spacer)) { - try { - const child = spacer.querySelector('section'); - if (child && spacer.parentElement) { - spacer.parentElement.appendChild(child); - } - spacer.remove(); - } catch (e) { - // 무시 + const child = spacer.querySelector('section'); + if (child && spacer.parentElement) { + spacer.parentElement.appendChild(child); } + spacer.remove(); } }); }; @@ -152,7 +147,6 @@ function MainSlide() { } }; }, [isMobile, mounted]); - // SSR 방지 if (!mounted) { return null; @@ -161,24 +155,28 @@ function MainSlide() { return ( <> {isMobile ? ( - + + + ) : ( -
-
-
- -
-
- -
-
- -
-
- + +
+
+
+ +
+
+ +
+
+ +
+
+ +
-
-
+ + )} ); diff --git a/src/domains/main/components/mainSlide/components/MainSlideAbv.tsx b/src/domains/main/components/mainSlide/components/MainSlideAbv.tsx index 494a1a85..31113543 100644 --- a/src/domains/main/components/mainSlide/components/MainSlideAbv.tsx +++ b/src/domains/main/components/mainSlide/components/MainSlideAbv.tsx @@ -41,7 +41,7 @@ function MainSlideAbv() { ]; return ( -
+
3
@@ -66,7 +66,7 @@ function MainSlideAbv() {
- + ); } export default MainSlideAbv; diff --git a/src/domains/main/components/mainSlide/components/MainSlideCommunity.tsx b/src/domains/main/components/mainSlide/components/MainSlideCommunity.tsx index 5489143d..fc1b4c3b 100644 --- a/src/domains/main/components/mainSlide/components/MainSlideCommunity.tsx +++ b/src/domains/main/components/mainSlide/components/MainSlideCommunity.tsx @@ -1,24 +1,23 @@ function MainSlideCommunity() { return ( -
+
2 -
+

술술 즐기는, 커뮤니티

-

+

칵테일에 대해 물어볼 곳이 없어 목이 마른 당신!
초보자부터 애호가까지, Ssoul에서는 누구나 칵테일 이야기를 나눌 수 있어요.
회원들과 소통하면 내 칵테일 솜씨를 뽐내보세요.

-
+
-
-
+ ); } export default MainSlideCommunity; diff --git a/src/domains/main/components/mainSlide/components/MainSlideDummyCard.tsx b/src/domains/main/components/mainSlide/components/MainSlideDummyCard.tsx index 18a5286e..799db773 100644 --- a/src/domains/main/components/mainSlide/components/MainSlideDummyCard.tsx +++ b/src/domains/main/components/mainSlide/components/MainSlideDummyCard.tsx @@ -9,7 +9,7 @@ interface Props { function MainSlideDummyCard({ src, cocktailName }: Props) { return ( -
+
diff --git a/src/domains/main/components/mainSlide/components/MainSlideIntro.tsx b/src/domains/main/components/mainSlide/components/MainSlideIntro.tsx index 69ec2f03..3733a450 100644 --- a/src/domains/main/components/mainSlide/components/MainSlideIntro.tsx +++ b/src/domains/main/components/mainSlide/components/MainSlideIntro.tsx @@ -1,19 +1,19 @@ -import background from '@/shared/assets/images/main_slide.webp'; +import background from '@/shared/assets/images/cocktailBg.webp'; import Image from 'next/image'; function MainSlideIntro() { return ( -
- -
+
+ +

칵테일
누구나 쉽게 즐길 수 있어요

SSOUL의 재밌고 다양한 기능들로 더 친근하게 접해보세요

-
-
+ + ); } export default MainSlideIntro; diff --git a/src/domains/main/components/mainSlide/components/MainSlideTest.tsx b/src/domains/main/components/mainSlide/components/MainSlideTest.tsx index c1b050a6..482e2c1e 100644 --- a/src/domains/main/components/mainSlide/components/MainSlideTest.tsx +++ b/src/domains/main/components/mainSlide/components/MainSlideTest.tsx @@ -15,11 +15,11 @@ const DUMMY_TEST = [ function MainSlideTest() { return ( -
+
1
-
+

AI기반 취향테스트

@@ -27,25 +27,29 @@ function MainSlideTest() { 복잡한 이름과 긴 설명 때문에 내 취향 칵테일 찾기 어려우셨나요?
AI쑤리가 당신에게 딱 맞는 칵테일을 추천해 드려요!

-
+
    - - 안녕하세요! 🍹바텐더 쑤리에요. -
    - 취향에 맞는 칵테일을 추천해드릴게요.
    - 어떤 유형으로 찾아드릴까요? - - } - option={DUMMY_TEST} - type="option" - /> - +
  • + + 안녕하세요! 🍹바텐더 쑤리에요. +
    + 취향에 맞는 칵테일을 추천해드릴게요.
    + 어떤 유형으로 찾아드릴까요? + + } + option={DUMMY_TEST} + type="option" + /> +
  • +
  • + +
-
+ ); } export default MainSlideTest; diff --git a/src/domains/main/components/mainSlide/components/MainSsuryDrunk.tsx b/src/domains/main/components/mainSlide/components/MainSsuryDrunk.tsx index 1d979cf4..a0e0093a 100644 --- a/src/domains/main/components/mainSlide/components/MainSsuryDrunk.tsx +++ b/src/domains/main/components/mainSlide/components/MainSsuryDrunk.tsx @@ -31,7 +31,7 @@ function MainSsuryDrunk({ src, abv }: Props) { %~ )}

- +
); } diff --git a/src/domains/main/components/mainSlide/components/MainTestDummy.tsx b/src/domains/main/components/mainSlide/components/MainTestDummy.tsx index 503acfa9..f7460351 100644 --- a/src/domains/main/components/mainSlide/components/MainTestDummy.tsx +++ b/src/domains/main/components/mainSlide/components/MainTestDummy.tsx @@ -34,7 +34,7 @@ const DUMMY_CARD = [ function MainTestDummy({ message, option, type }: Props) { return ( -
  • +
    쑤리

    {message && ( -
    +

    {message}

    @@ -66,7 +66,7 @@ function MainTestDummy({ message, option, type }: Props) { ))}
    -
    +
    )} {type == 'text' && (
    @@ -75,7 +75,7 @@ function MainTestDummy({ message, option, type }: Props) { ))}
    )} -
  • + ); } export default MainTestDummy; diff --git a/src/domains/main/components/mainSlide/components/mobile/MobileAbv.tsx b/src/domains/main/components/mainSlide/components/mobile/MobileAbv.tsx index 43b3b16a..5e3538e7 100644 --- a/src/domains/main/components/mainSlide/components/mobile/MobileAbv.tsx +++ b/src/domains/main/components/mainSlide/components/mobile/MobileAbv.tsx @@ -5,8 +5,12 @@ import Ssury4 from '@/shared/assets/ssury/ssury_level4.webp'; import Ssury5 from '@/shared/assets/ssury/ssury_level5.webp'; import Ssury6 from '@/shared/assets/ssury/ssury_level6.webp'; import MainSsuryDrunk from '../MainSsuryDrunk'; +import Add from '@/shared/assets/icons/add_24.svg'; +import clsx from 'clsx'; +import { useState } from 'react'; function MobileAbv() { + const [isClick, setIsClick] = useState(false); const SSURY_DRUNK = [ { id: 1, @@ -41,31 +45,49 @@ function MobileAbv() { ]; return ( -
    -
    - 3 +
    +
    + 3
    -

    - 내 알콜도수 UP -

    -

    - 5도 부터 시작하는 내 알콜도수
    글 작성,댓글,좋아요 / 킵으로 알콜도수 UP!
    - 알콜도수에 따라 변하는 쑤리(SSURY)를 보는 재미도 있어요. -

    -
    -
    -
      - {SSURY_DRUNK.map(({ id, src, abv }) => ( -
    • - -
    • - ))} -
    -
    - +
    +

    + 내 알콜도수 UP +

    + +
    +
    -
    +
    ); } diff --git a/src/domains/main/components/mainSlide/components/mobile/MobileSlide.tsx b/src/domains/main/components/mainSlide/components/mobile/MobileSlide.tsx index c0154be0..11e4c8e3 100644 --- a/src/domains/main/components/mainSlide/components/mobile/MobileSlide.tsx +++ b/src/domains/main/components/mainSlide/components/mobile/MobileSlide.tsx @@ -1,17 +1,24 @@ -import Image from 'next/image'; -import background from '@/shared/assets/images/main_slide.webp'; +import background from '@/shared/assets/images/cocktailBg.webp'; import MobileSlideTest from './MobileSlideTest'; import MobileSlideCommunity from './MobileSlideCommunity'; import MobileAbv from './MobileAbv'; function MobileSlide() { return ( -
    - -

    +
    +

    칵테일
    누구나 쉽게 즐길 수 있어요

    -

    +

    SSOUL의 재밌고 다양한 기능들로 더 친근하게 접해보세요

    diff --git a/src/domains/main/components/mainSlide/components/mobile/MobileSlideCommunity.tsx b/src/domains/main/components/mainSlide/components/mobile/MobileSlideCommunity.tsx index 393240d5..84e64ece 100644 --- a/src/domains/main/components/mainSlide/components/mobile/MobileSlideCommunity.tsx +++ b/src/domains/main/components/mainSlide/components/mobile/MobileSlideCommunity.tsx @@ -1,20 +1,41 @@ +import Add from '@/shared/assets/icons/add_24.svg'; +import clsx from 'clsx'; +import { useState } from 'react'; + function MobileSlideCommunity() { + const [isClick, setIsClick] = useState(false); return ( -
    -
    - 2 -
    -

    - 술술 즐기는, 커뮤니티 -

    -

    +

    +
    + 2 +
    +
    +

    + 술술 즐기는, 커뮤니티 +

    + +
    + -
    -
    + +
    ); } diff --git a/src/domains/main/components/mainSlide/components/mobile/MobileSlideTest.tsx b/src/domains/main/components/mainSlide/components/mobile/MobileSlideTest.tsx index fe04895f..22e07e80 100644 --- a/src/domains/main/components/mainSlide/components/mobile/MobileSlideTest.tsx +++ b/src/domains/main/components/mainSlide/components/mobile/MobileSlideTest.tsx @@ -1,5 +1,7 @@ +import { useState } from 'react'; import MainTestDummy from '../MainTestDummy'; - +import Add from '@/shared/assets/icons/add_24.svg'; +import clsx from 'clsx'; const DUMMY_TEST = [ { id: 1, @@ -14,34 +16,55 @@ const DUMMY_TEST = [ ]; function MobileSlideTest() { + const [isClick, setIsClick] = useState(false); return ( -
    - 1 -
    -
    -

    - AI기반 취향테스트 -

    -

    - 복잡한 이름과 긴 설명 때문에 내 취향 칵테일 찾기 어려우셨나요?
    - AI쑤리가 당신에게 딱 맞는 칵테일을 추천해 드려요! -

    -
    -
      - - 안녕하세요! 🍹바텐더 쑤리에요. -
      - 취향에 맞는 칵테일을 추천해드릴게요.
      - 어떤 유형으로 찾아드릴까요? - - } - option={DUMMY_TEST} - type="option" - /> - -
    +
    + 1 +
    +
    +
    +

    + AI기반 취향테스트 +

    + +
    + +
    ); diff --git a/src/domains/recipe/components/details/DetailsHeader.tsx b/src/domains/recipe/components/details/DetailsHeader.tsx index 31f4bb07..d15c0533 100644 --- a/src/domains/recipe/components/details/DetailsHeader.tsx +++ b/src/domains/recipe/components/details/DetailsHeader.tsx @@ -20,7 +20,6 @@ function DetailsHeader({ id, favor }: { id: number; favor: boolean | null }) { const url = async () => { const res = await fetch(`${getApi}/cocktails/${id}/share`); const json = await res.json(); - console.log(json.data); setMeta(json.data); }; diff --git a/src/domains/recipe/components/details/RecipeComment.tsx b/src/domains/recipe/components/details/RecipeComment.tsx index 581a0608..901a43c4 100644 --- a/src/domains/recipe/components/details/RecipeComment.tsx +++ b/src/domains/recipe/components/details/RecipeComment.tsx @@ -26,26 +26,26 @@ function RecipeComment({ cocktailId }: Props) { toastInfo('로그인 후 이용 가능합니다'); return; } + const body = { + cocktailId, + content: content, + }; - try { - const res = await fetch(`${getApi}/cocktails/${cocktailId}/comments`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - credentials: 'include', - body: JSON.stringify({ content }), - }); - const text = await res.text(); + const res = await fetch(`${getApi}/cocktails/${cocktailId}/comments`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + credentials: 'include', + body: JSON.stringify(body), + }); - if (!res.ok) { - toastInfo('댓글은 한 개만 작성가능합니다'); - return; - } - - const data = JSON.parse(text); - return data; - } catch (err) { - console.error(err); + const text = await res.text(); + if (!res.ok) { + toastInfo('댓글은 한 개만 작성가능합니다'); + return; } + + const data = JSON.parse(text); + return data; }; const { diff --git a/src/shared/assets/images/cocktailBg.webp b/src/shared/assets/images/cocktailBg.webp new file mode 100644 index 00000000..414f2546 Binary files /dev/null and b/src/shared/assets/images/cocktailBg.webp differ diff --git a/src/shared/assets/images/exampleCocktail.png b/src/shared/assets/images/exampleCocktail.png deleted file mode 100644 index a8cb859b..00000000 Binary files a/src/shared/assets/images/exampleCocktail.png and /dev/null differ