From 64bd0f34ef41ea68d444d0af293a30a2c4941489 Mon Sep 17 00:00:00 2001 From: ahk0413 Date: Sun, 12 Oct 2025 20:08:42 +0900 Subject: [PATCH 1/7] =?UTF-8?q?[fix]=20=EB=85=BC=EC=95=8C=EC=BD=9C?= =?UTF-8?q?=EC=9D=BC=20=EC=8B=9C=20payload=20=EA=B0=92=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/domains/recommend/components/ChatPreview.tsx | 2 +- src/domains/recommend/hook/useSelectedOptions.ts | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/domains/recommend/components/ChatPreview.tsx b/src/domains/recommend/components/ChatPreview.tsx index 3029d176..ed21f50f 100644 --- a/src/domains/recommend/components/ChatPreview.tsx +++ b/src/domains/recommend/components/ChatPreview.tsx @@ -27,7 +27,7 @@ function ChatPreview() {
-

취향에 맞는 칵테일, 저와 함께 찾아볼까요?

+

취향에 맞는 칵테일🤩 저와 함께 찾아볼까요?

{ diff --git a/src/domains/recommend/hook/useSelectedOptions.ts b/src/domains/recommend/hook/useSelectedOptions.ts index 584eda65..08a1a45c 100644 --- a/src/domains/recommend/hook/useSelectedOptions.ts +++ b/src/domains/recommend/hook/useSelectedOptions.ts @@ -16,8 +16,13 @@ export function useSelectedOptions() { const setStepOption = (step: number, value: string) => { if (step === 2) selectedOptions.current.selectedAlcoholStrength = value; - if (step === 3) selectedOptions.current.selectedAlcoholBaseType = value; - // if (step === 4) selectedOptions.current.selectedCocktailType = value; + if (step === 3) { + if (selectedOptions.current.selectedAlcoholStrength === 'NON_ALCOHOLIC') { + selectedOptions.current.selectedCocktailType = value; + } else { + selectedOptions.current.selectedAlcoholBaseType = value; + } + } }; const reset = () => { From e1eee13d7b223e81391e50ecf8b509fde5ad1fb4 Mon Sep 17 00:00:00 2001 From: ahk0413 Date: Mon, 13 Oct 2025 00:12:54 +0900 Subject: [PATCH 2/7] =?UTF-8?q?[fix]=20options=20=EA=B8=B0=EB=B3=B8?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../recommend/components/bot/BotMessage.tsx | 18 ++++++++++-------- .../recommend/components/bot/BotOptions.tsx | 18 +++++++++++++----- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/src/domains/recommend/components/bot/BotMessage.tsx b/src/domains/recommend/components/bot/BotMessage.tsx index 21552590..b2d44402 100644 --- a/src/domains/recommend/components/bot/BotMessage.tsx +++ b/src/domains/recommend/components/bot/BotMessage.tsx @@ -33,7 +33,12 @@ function BotMessage({ onSelectedOption, isTyping, }: BotMessages) { - const [selected, setSelected] = useState(''); + const [selectedOptions, setSelectedOptions] = useState>({}); + + const handleOptionChange = (step: number, value: string) => { + setSelectedOptions((prev) => ({ ...prev, [step]: value })); + onSelectedOption?.(value); // 부모로 단일 값 전달 + }; return (
@@ -69,13 +74,10 @@ function BotMessage({ {msg.type === 'RADIO_OPTIONS' && msg.options?.length && ( { - setSelected(val); - onSelectedOption?.(val); - }} + step={stepData?.currentStep ?? 0} // step id용 + value={selectedOptions[stepData?.currentStep ?? 0] ?? ''} // step별 선택값 + onChange={(val) => handleOptionChange(stepData?.currentStep ?? 0, val)} + disabled={currentStep ? currentStep > (stepData?.currentStep ?? 0) : false} // disabled 처리 /> )} {/* {children} */} diff --git a/src/domains/recommend/components/bot/BotOptions.tsx b/src/domains/recommend/components/bot/BotOptions.tsx index 7e6040ce..2af487a2 100644 --- a/src/domains/recommend/components/bot/BotOptions.tsx +++ b/src/domains/recommend/components/bot/BotOptions.tsx @@ -8,10 +8,18 @@ interface BotOptionsProps { value: string; onChange: (value: string) => void; step: number; - currentStep: number; + currentStep?: number; + disabled?: boolean; } -function BotOptions({ options, value, onChange, step, currentStep }: BotOptionsProps) { +function BotOptions({ + options, + value, + onChange, + step, + currentStep, + disabled = false, +}: BotOptionsProps) { return (
{options.map((opt) => ( @@ -27,7 +35,7 @@ function BotOptions({ options, value, onChange, step, currentStep }: BotOptionsP value={opt.value} checked={value === opt.value} onChange={() => onChange(opt.value)} - disabled={currentStep > step && value !== opt.value} + disabled={disabled} className="sr-only" /> step && value !== opt.value ? 'cursor-not-allowed bg-gray-light' : 'hover:bg-secondary'}`} + ${disabled ? 'cursor-not-allowed bg-gray-light' : 'hover:bg-secondary'}`} > - {opt.label} + {opt.label} ))} From ccba6dbc09d2515338b51fd5971d739b9cb40d97 Mon Sep 17 00:00:00 2001 From: ahk0413 Date: Mon, 13 Oct 2025 11:18:49 +0900 Subject: [PATCH 3/7] =?UTF-8?q?[feat]=20=EB=8B=A4=EC=8B=9C=20=EC=8B=9C?= =?UTF-8?q?=EC=9E=91=ED=95=98=EA=B8=B0=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/domains/recommend/components/ChatList.tsx | 13 +--- .../recommend/components/ChatSection.tsx | 21 ++++++- .../recommend/components/bot/BotMessage.tsx | 63 +++++++++++-------- src/domains/recommend/hook/useChatInit.ts | 2 +- 4 files changed, 60 insertions(+), 39 deletions(-) diff --git a/src/domains/recommend/components/ChatList.tsx b/src/domains/recommend/components/ChatList.tsx index 4687b795..ebaeae9c 100644 --- a/src/domains/recommend/components/ChatList.tsx +++ b/src/domains/recommend/components/ChatList.tsx @@ -8,14 +8,6 @@ function ChatList({ messages, userCurrentStep, onSelectedOption }: ChatListProps const { chatListRef, chatEndRef, showNewMessageAlert, handleCheckBottom, handleScrollToBottom } = useChatScroll(messages[messages.length - 1]?.id); - const getRecommendations = ( - type: string | undefined, - stepData?: StepRecommendation | null - ): RecommendationItem[] => { - if (type !== 'CARD_LIST' || !stepData?.recommendations) return []; - return stepData.recommendations; - }; - return (
void; isTyping?: boolean; @@ -28,7 +26,6 @@ interface BotMessages { function BotMessage({ messages, showProfile, - stepData, currentStep, onSelectedOption, isTyping, @@ -71,31 +68,47 @@ function BotMessage({
{/* radio */} - {msg.type === 'RADIO_OPTIONS' && msg.options?.length && ( + {msg.type === 'RADIO_OPTIONS' && msg.stepData?.options?.length ? ( handleOptionChange(stepData?.currentStep ?? 0, val)} - disabled={currentStep ? currentStep > (stepData?.currentStep ?? 0) : false} // disabled 처리 + options={msg.stepData.options} // stepData와 options가 존재하는 게 보장됨 + step={msg.stepData.currentStep ?? 0} + value={selectedOptions[msg.stepData.currentStep ?? 0] ?? ''} + onChange={(val) => handleOptionChange(msg.stepData?.currentStep ?? 0, val)} + disabled={currentStep ? currentStep > (msg.stepData.currentStep ?? 0) : false} /> - )} - {/* {children} */} + ) : null}
- {msg.type === 'CARD_LIST' && msg.recommendations?.length ? ( -
    - {msg.recommendations.map((rec) => ( -
  • - + {/* 카드 목록 */} +
      + {msg.stepData.recommendations.map((rec) => ( +
    • + +
    • + ))} +
    + + {/* 카드 목록 마지막 restart */} + {msg.stepData?.options && msg.stepData.options?.length > 0 && ( +
    +

    다시 추천받기를 원하시나요?

    + handleOptionChange(msg.stepData?.currentStep ?? 0, val)} + disabled={currentStep ? currentStep > (msg.stepData.currentStep ?? 0) : false} /> -
  • - ))} -
+
+ )} + ) : ( '' )} diff --git a/src/domains/recommend/hook/useChatInit.ts b/src/domains/recommend/hook/useChatInit.ts index 341ae672..2539a9a4 100644 --- a/src/domains/recommend/hook/useChatInit.ts +++ b/src/domains/recommend/hook/useChatInit.ts @@ -11,7 +11,7 @@ export function useChatInit(setMessages: React.Dispatch Date: Mon, 13 Oct 2025 12:35:28 +0900 Subject: [PATCH 4/7] =?UTF-8?q?[feat]=20=EC=B1=84=ED=8C=85=20=EC=BA=A1?= =?UTF-8?q?=EC=B2=98=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 7 ++++ package.json | 5 +-- src/domains/recommend/components/ChatList.tsx | 10 ++++-- .../recommend/components/ChatPreview.tsx | 10 +++++- .../recommend/components/ChatSection.tsx | 8 +++-- .../components/bot/BotCocktailCard.tsx | 1 + .../components/user/MessageInput.tsx | 25 +++++++++++---- src/domains/recommend/hook/useChatCapture.ts | 32 +++++++++++++++++++ src/domains/recommend/types/recommend.ts | 3 ++ src/shared/assets/icons/crop_32.svg | 3 ++ 10 files changed, 90 insertions(+), 14 deletions(-) create mode 100644 src/domains/recommend/hook/useChatCapture.ts create mode 100644 src/shared/assets/icons/crop_32.svg diff --git a/package-lock.json b/package-lock.json index ff6b65a9..f43daaad 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "@tanstack/react-virtual": "^3.13.12", "class-variance-authority": "^0.7.1", "gsap": "^3.13.0", + "html-to-image": "^1.11.13", "lottie-react": "^2.4.1", "next": "15.5.3", "react": "19.1.0", @@ -6329,6 +6330,12 @@ "node": ">= 0.4" } }, + "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/husky": { "version": "9.1.7", "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", diff --git a/package.json b/package.json index 4eaef365..3c01ca92 100644 --- a/package.json +++ b/package.json @@ -22,14 +22,15 @@ "@tanstack/react-virtual": "^3.13.12", "class-variance-authority": "^0.7.1", "gsap": "^3.13.0", + "html-to-image": "^1.11.13", "lottie-react": "^2.4.1", "next": "15.5.3", "react": "19.1.0", "react-dom": "19.1.0", "react-hot-toast": "^2.6.0", + "react-intersection-observer": "^9.16.0", "react-use": "^17.6.0", - "swiper": "^12.0.2", - "react-intersection-observer": "^9.16.0" + "swiper": "^12.0.2" }, "devDependencies": { "@eslint/eslintrc": "^3", diff --git a/src/domains/recommend/components/ChatList.tsx b/src/domains/recommend/components/ChatList.tsx index ebaeae9c..658f6470 100644 --- a/src/domains/recommend/components/ChatList.tsx +++ b/src/domains/recommend/components/ChatList.tsx @@ -4,13 +4,18 @@ import BotMessage from './bot/BotMessage'; import NewMessageAlert from './bot/NewMessageAlert'; import UserMessage from './user/UserMessage'; -function ChatList({ messages, userCurrentStep, onSelectedOption }: ChatListProps) { +function ChatList({ messages, userCurrentStep, onSelectedOption, chatRef }: ChatListProps) { const { chatListRef, chatEndRef, showNewMessageAlert, handleCheckBottom, handleScrollToBottom } = useChatScroll(messages[messages.length - 1]?.id); + const combinedRef = (el: HTMLDivElement) => { + chatListRef.current = el; + if (chatRef) chatRef.current = el; + }; + return (
@@ -39,7 +44,6 @@ function ChatList({ messages, userCurrentStep, onSelectedOption }: ChatListProps }, ]} showProfile={showProfile} - stepData={msg.stepData} currentStep={userCurrentStep} onSelectedOption={onSelectedOption} isTyping={isTyping} diff --git a/src/domains/recommend/components/ChatPreview.tsx b/src/domains/recommend/components/ChatPreview.tsx index ed21f50f..fc988baa 100644 --- a/src/domains/recommend/components/ChatPreview.tsx +++ b/src/domains/recommend/components/ChatPreview.tsx @@ -3,6 +3,7 @@ import Image from 'next/image'; import Send from '@/shared/assets/icons/send_36.svg'; import Link from 'next/link'; import { setPreLoginPath } from '@/domains/shared/auth/utils/setPreLoginPath'; +import Crop from '@/shared/assets/icons/crop_32.svg'; function ChatPreview() { return ( @@ -45,7 +46,14 @@ function ChatPreview() {
e.preventDefault()} className="w-full max-w-[64rem]"> -
+
+ diff --git a/src/domains/recommend/components/ChatSection.tsx b/src/domains/recommend/components/ChatSection.tsx index 4443f44a..c1faf253 100644 --- a/src/domains/recommend/components/ChatSection.tsx +++ b/src/domains/recommend/components/ChatSection.tsx @@ -1,6 +1,6 @@ 'use client'; -import { useState } from 'react'; +import { useRef, useState } from 'react'; import MessageInput from './user/MessageInput'; import { fetchGreeting, fetchSendStepMessage, fetchSendTextMessage } from '../api/chat'; import { ChatMessage, stepPayload } from '../types/recommend'; @@ -9,11 +9,14 @@ import { useSelectedOptions } from '../hook/useSelectedOptions'; import { useAuthStore } from '@/domains/shared/store/auth'; import { useChatInit } from '../hook/useChatInit'; import { useChatWarning } from '../hook/useChatWarning'; +import { useChatCapture } from '../hook/useChatCapture'; function ChatSection() { const [messages, setMessages] = useState([]); const [userCurrentStep, setUserCurrentStep] = useState(0); const { selectedOptions, setOption, setStepOption } = useSelectedOptions(); + const chatRef = useRef(null); + const { capture } = useChatCapture(chatRef); const isInputDisabled = selectedOptions.current.selectedSearchType !== 'QA' && userCurrentStep < 3; @@ -150,11 +153,12 @@ function ChatSection() { ⚠️ 페이지를 벗어나면 채팅내용이 사라집니다.
- + ); } diff --git a/src/domains/recommend/components/bot/BotCocktailCard.tsx b/src/domains/recommend/components/bot/BotCocktailCard.tsx index 78d5c659..62ab45e8 100644 --- a/src/domains/recommend/components/bot/BotCocktailCard.tsx +++ b/src/domains/recommend/components/bot/BotCocktailCard.tsx @@ -19,6 +19,7 @@ function BotCocktailCard({ cocktailId, cocktailNameKo, cocktailImgUrl }: Recomme className="object-cover" alt={cocktailNameKo} sizes="200px" + crossOrigin="anonymous" priority />
diff --git a/src/domains/recommend/components/user/MessageInput.tsx b/src/domains/recommend/components/user/MessageInput.tsx index b8fe686b..0200a770 100644 --- a/src/domains/recommend/components/user/MessageInput.tsx +++ b/src/domains/recommend/components/user/MessageInput.tsx @@ -1,16 +1,18 @@ 'use client'; import Send from '@/shared/assets/icons/send_36.svg'; +import Crop from '@/shared/assets/icons/crop_32.svg'; import { handleTextareaSubmit } from '@/shared/utills/handleTextareaSubmit'; import { resizeTextarea } from '@/shared/utills/textareaResize'; import { useRef, useState } from 'react'; interface Props { onSubmit: (message: string) => void; + onCapture: () => void; disabled: boolean; } -function MessageInput({ onSubmit, disabled }: Props) { +function MessageInput({ onSubmit, disabled, onCapture }: Props) { const [value, setValue] = useState(''); const textareaRef = useRef(null); @@ -22,9 +24,20 @@ function MessageInput({ onSubmit, disabled }: Props) { }; return ( -
- e.preventDefault()} className="w-full max-w-[64rem]"> -
+
+ e.preventDefault()} + className="flex items-center w-full max-w-[64rem] gap-2 justify-between" + > + +
@@ -39,7 +52,7 @@ function MessageInput({ onSubmit, disabled }: Props) { placeholder={disabled ? '옵션 선택' : '칵테일 추천 질문 입력'} disabled={disabled} className={` - w-[calc(100%-3rem)] md:w-[calc(100%-3.75rem)] px-4 py-2 md:py-3.5 + flex-1 px-4 py-2 md:py-3.5 rounded-lg h-[40px] md:h-[52px] max-h-[160px] md:max-h-[280px] bg-white text-primary placeholder:text-gray-dark resize-none outline-none disabled:bg-gray disabled:text-gray-dark disabled:cursor-not-allowed @@ -49,7 +62,7 @@ function MessageInput({ onSubmit, disabled }: Props) { type="button" onClick={() => handleTextareaSubmit(null, textareaRef.current, handleSubmit)} aria-label="보내기" - className="flex-center w-10 md:w-13 h-10 md:h-13 rounded-xl border-1 border-white bg-secondary/20" + className="flex-center w-10 md:w-13 h-10 md:h-13 rounded-xl border-1 border-white bg-secondary/20 hover:bg-white/10 active:bg-white/10" > diff --git a/src/domains/recommend/hook/useChatCapture.ts b/src/domains/recommend/hook/useChatCapture.ts new file mode 100644 index 00000000..22c2cb08 --- /dev/null +++ b/src/domains/recommend/hook/useChatCapture.ts @@ -0,0 +1,32 @@ +import { RefObject } from 'react'; +import * as htmlToImage from 'html-to-image'; + +export function useChatCapture(chatRef: RefObject) { + const capture = async () => { + if (!chatRef.current) return; + + const chatEl = chatRef.current; + const originalHeight = chatEl.style.height; + + chatEl.style.height = chatEl.scrollHeight + 'px'; + + try { + const dataUrl = await htmlToImage.toPng(chatEl, { + backgroundColor: '#1A1A1A', + cacheBust: true, + includeQueryParams: true, + }); + + const link = document.createElement('a'); + link.href = dataUrl; + link.download = 'chat.png'; + link.click(); + } catch (err) { + console.error('채팅 캡처 실패:', err); + } finally { + chatEl.style.height = originalHeight; + } + }; + + return { capture }; +} diff --git a/src/domains/recommend/types/recommend.ts b/src/domains/recommend/types/recommend.ts index 837e0b14..b03588ef 100644 --- a/src/domains/recommend/types/recommend.ts +++ b/src/domains/recommend/types/recommend.ts @@ -1,3 +1,5 @@ +import { RefObject } from 'react'; + export interface StepOption { value: string; label: string; @@ -57,4 +59,5 @@ export interface ChatListProps { userCurrentStep: number; onSelectedOption: (value: string) => void; isBotTyping?: boolean; + chatRef?: RefObject; } diff --git a/src/shared/assets/icons/crop_32.svg b/src/shared/assets/icons/crop_32.svg new file mode 100644 index 00000000..0cb3570b --- /dev/null +++ b/src/shared/assets/icons/crop_32.svg @@ -0,0 +1,3 @@ + + + From 469f28429fd253dd93bf162a05990067b3819177 Mon Sep 17 00:00:00 2001 From: ahk0413 Date: Mon, 13 Oct 2025 12:50:32 +0900 Subject: [PATCH 5/7] =?UTF-8?q?[fix]=20currentStep=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/domains/recommend/components/bot/BotOptions.tsx | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/domains/recommend/components/bot/BotOptions.tsx b/src/domains/recommend/components/bot/BotOptions.tsx index 2af487a2..49dbb357 100644 --- a/src/domains/recommend/components/bot/BotOptions.tsx +++ b/src/domains/recommend/components/bot/BotOptions.tsx @@ -12,14 +12,7 @@ interface BotOptionsProps { disabled?: boolean; } -function BotOptions({ - options, - value, - onChange, - step, - currentStep, - disabled = false, -}: BotOptionsProps) { +function BotOptions({ options, value, onChange, step, disabled = false }: BotOptionsProps) { return (
{options.map((opt) => ( From 3b2c40cea062817e78b3ed6bdd81a2cb2e45f145 Mon Sep 17 00:00:00 2001 From: ahk0413 Date: Mon, 13 Oct 2025 16:48:46 +0900 Subject: [PATCH 6/7] =?UTF-8?q?[fix]=20=ED=8C=8C=EB=B9=84=EC=BD=98=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=ED=97=A4=EB=8D=94=20=EB=A9=94?= =?UTF-8?q?=EB=89=B4=20=EB=84=A4=EC=9D=B4=EB=B0=8D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/favicon.ico | Bin 0 -> 15406 bytes src/app/layout.tsx | 1 + .../recommend/components/bot/BotMessage.tsx | 6 +++--- src/shared/utills/navigation.ts | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) create mode 100644 public/favicon.ico diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..b12f6ffd22a6fbc751e463170b9cd5b81207f7af GIT binary patch literal 15406 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 literal 0 HcmV?d00001 diff --git a/src/app/layout.tsx b/src/app/layout.tsx index f35edec6..03583974 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -15,6 +15,7 @@ export const metadata: Metadata = { title: { default: 'SSOUL', template: 'SSOUL | %s' }, metadataBase: new URL('http://www.ssoul.life'), description: '칵테일을 좋아하는 사람들을 위한 서비스', + icons: '/favicon.ico', }; export default function RootLayout({ diff --git a/src/domains/recommend/components/bot/BotMessage.tsx b/src/domains/recommend/components/bot/BotMessage.tsx index 07ca54e1..c3c183ae 100644 --- a/src/domains/recommend/components/bot/BotMessage.tsx +++ b/src/domains/recommend/components/bot/BotMessage.tsx @@ -34,7 +34,7 @@ function BotMessage({ const handleOptionChange = (step: number, value: string) => { setSelectedOptions((prev) => ({ ...prev, [step]: value })); - onSelectedOption?.(value); // 부모로 단일 값 전달 + onSelectedOption?.(value); }; return ( @@ -70,11 +70,11 @@ function BotMessage({ {/* radio */} {msg.type === 'RADIO_OPTIONS' && msg.stepData?.options?.length ? ( handleOptionChange(msg.stepData?.currentStep ?? 0, val)} - disabled={currentStep ? currentStep > (msg.stepData.currentStep ?? 0) : false} + disabled={currentStep !== undefined && currentStep > msg.stepData.currentStep!} /> ) : null}
diff --git a/src/shared/utills/navigation.ts b/src/shared/utills/navigation.ts index d3338c8a..5c31933d 100644 --- a/src/shared/utills/navigation.ts +++ b/src/shared/utills/navigation.ts @@ -1,5 +1,5 @@ export const navItem = [ - { href: '/recipe', label: '칵테일 찾기' }, + { href: '/recipe', label: '칵테일 레시피' }, { href: '/recommend', label: '취향추천받기' }, { href: '/community', label: '커뮤니티' }, { From 5d160a7dabedd9afb55db93fbd6ae986d6281bee Mon Sep 17 00:00:00 2001 From: ahk0413 Date: Mon, 13 Oct 2025 16:56:26 +0900 Subject: [PATCH 7/7] =?UTF-8?q?[style]=20layout=20=EB=AA=A8=EB=B0=94?= =?UTF-8?q?=EC=9D=BC=20=EB=8C=80=EC=9D=91=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/layout.tsx | 2 +- src/shared/styles/_utilities.css | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 03583974..b72838c1 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -25,7 +25,7 @@ export default function RootLayout({ }>) { return ( - +
diff --git a/src/shared/styles/_utilities.css b/src/shared/styles/_utilities.css index 02fbc28b..362cb7c3 100644 --- a/src/shared/styles/_utilities.css +++ b/src/shared/styles/_utilities.css @@ -127,4 +127,14 @@ .swiper-pagination-bullet-active { background: var(--color-secondary) !important; } + + .min-h-full-screen { + min-height: 100vh; + min-height: 100svh; + } + + .h-full-screen { + height: 100vh; + height: 100svh; + } }