Skip to content
Merged
8 changes: 7 additions & 1 deletion src/app/recommend/page.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
'use client';

import ChatSection from '@/domains/recommend/components/ChatSection';
import Bg from '@/shared/assets/images/recommend_bg.webp';
import { useAuthStore } from '@/domains/shared/store/auth';
import ChatPreview from '@/domains/recommend/components/ChatPreview';

function Page() {
const { user } = useAuthStore();

return (
<div
className="relative bg-repeat bg-auto w-full flex flex-col"
style={{ backgroundImage: `url(${Bg.src})` }}
>
<h1 className="sr-only">취향추천하기</h1>
<ChatSection />
{user ? <ChatSection /> : <ChatPreview />}
</div>
);
}
Expand Down
2 changes: 1 addition & 1 deletion src/domains/login/components/LoginRedirectHandler.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import Spinner from '@/shared/components/spinner/Spinner';
import WelcomeModal from '@/domains/login/components/WelcomeModal';
import { useLoginRedirect } from '../hook/useAuthHooks';
import { useLoginRedirect } from '../hook/useLoginRedirect';

function LoginRedirectHandler() {
const { loading, welcomeModalOpen, handleCloseWelcomeModal, user } = useLoginRedirect();
Expand Down
2 changes: 1 addition & 1 deletion src/domains/login/components/LogoutConfirm.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import ConfirmModal from '@/shared/components/modal-pop/ConfirmModal';
import { useLogout } from '../hook/useAuthHooks';
import { useLogout } from '../hook/useLogout';

interface Props {
open: boolean;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,9 @@
import { useAuthStore } from '@/domains/shared/store/auth';
import { useCallback } from 'react';
import { useEffect, useState } from 'react';
import { usePathname, useRouter } from 'next/navigation';
import { getCookie, removeCookie } from '@/domains/shared/auth/utils/cookie';
import { useToast } from '@/shared/hook/useToast';

export const useLogout = () => {
const logout = useAuthStore((state) => state.logout);
const { toastSuccess, toastError } = useToast();

const handleLogout = useCallback(async () => {
try {
await logout();
toastSuccess('로그아웃 되었습니다.');
} catch (err) {
console.error('로그아웃 실패', err);
toastError('로그아웃 실패 ❌ 다시 시도해주세요.');
}
}, [logout, toastSuccess, toastError]);

return handleLogout;
};

export const useLoginRedirect = () => {
const router = useRouter();
const pathname = usePathname();
Expand Down
27 changes: 27 additions & 0 deletions src/domains/login/hook/useLogout.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { useAuthStore } from '@/domains/shared/store/auth';
import { useToast } from '@/shared/hook/useToast';
import { useCallback } from 'react';
import { useRouter } from 'next/navigation';

export const useLogout = () => {
const logout = useAuthStore((state) => state.logout);
const { toastSuccess, toastError } = useToast();
const router = useRouter();

const handleLogout = useCallback(async () => {
try {
await logout();
toastSuccess('로그아웃 되었습니다.');

// 마이페이지 일 시 메인페이지로 이동
if (window.location.pathname.startsWith('/mypage')) {
router.push('/');
}
} catch (err) {
console.error('로그아웃 실패', err);
toastError('로그아웃 실패 ❌ 다시 시도해주세요.');
}
}, [logout, toastSuccess, toastError, router]);

return handleLogout;
};
6 changes: 5 additions & 1 deletion src/domains/mypage/components/pages/my-bar/MyBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,11 @@ function MyBar() {
<div>
{myCocktail.length !== 0 ? (
<div
className="grid grid-cols-1 justify-items-center mt-10 gap-8 sm:[grid-template-columns:repeat(2,minmax(0,320px))] sm:justify-evenly md:[grid-template-columns:repeat(3,minmax(0,250px))]
className="
grid gap-8 md:justify-between justify-center
[grid-template-columns:repeat(1,minmax(0,250px))]
sm:[grid-template-columns:repeat(2,minmax(0,250px))]
md:[grid-template-columns:repeat(3,minmax(0,250px))]
"
>
{myCocktail.map(({ cocktailId, cocktailName, imageUrl }) => (
Expand Down
14 changes: 8 additions & 6 deletions src/domains/recipe/main/CocktailList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,23 @@ function CocktailList({ cocktails, RecipeFetch, hasNextPage, lastId, onItemClick

return (
<ul
className="place-content-between
grid gap-8 justify-items-center
grid-cols-1 sm:justify-items-stretch
sm:[grid-template-columns:repeat(2,minmax(0,320px))] sm:gap-8 md:[grid-template-columns:repeat(3,minmax(0,250px))]
lg:[grid-template-columns:repeat(4,minmax(0,250px))]
className="
grid gap-8 lg:justify-between justify-center
[grid-template-columns:repeat(1,minmax(0,250px))]
sm:[grid-template-columns:repeat(2,minmax(0,250px))]
md:[grid-template-columns:repeat(3,minmax(0,250px))]
lg:[grid-template-columns:repeat(4,minmax(0,250px))]
"
>
{cocktails.map(
({ cocktailImgUrl, cocktailId, cocktailName, cocktailNameKo, alcoholStrength }) => (
<li key={cocktailId} onClick={onItemClick}>
<li key={cocktailId} onClick={onItemClick} className="w-full">
<Link
href={`/recipe/${cocktailId}`}
onClick={() => {
sessionStorage.setItem('listScrollY', String(window.scrollY));
}}
className="block"
>
<CocktailCard
id={cocktailId}
Expand Down
78 changes: 78 additions & 0 deletions src/domains/recommend/components/ChatPreview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import Ssury from '@/shared/assets/ssury/ssury_shaker.webp';
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';

function ChatPreview() {
return (
<section className="relative flex-1 flex flex-col w-full">
<div className="page-layout max-w-1024 py-12">
<article aria-label="취향추천 챗봇 메시지" className="">
<header className="flex items-end">
<div className="relative w-15 md:w-20 h-15 md:h-20">
<Image
src={Ssury}
alt="쑤리아바타"
width={80}
height={80}
className="object-cover w-15 h-15 md:w-20 md:h-20"
/>
</div>
<p>쑤리</p>
</header>

{/* 메시지 그룹 */}
<div className="flex flex-col gap-3 mt-3 pl-3">
<div>
<div className="flex flex-col w-fit max-w-[80%] min-w-[120px] p-3 rounded-2xl rounded-tl-none bg-white text-black opacity-0 animate-fadeIn">
<div>
<p className="whitespace-pre-line">취향에 맞는 칵테일, 저와 함께 찾아볼까요?</p>
<Link
href="/login"
onNavigate={async () => {
await setPreLoginPath(window.location.pathname);
}}
className="block p-2 mt-3 flex-center font-semibold bg-gray-light rounded-3xl hover:bg-secondary hover:shadow-[inset_0_0_6px_rgba(255,196,1,1)] active:bg-secondary active:shadow-[inset_0_0_6px_rgba(255,196,1,1)]"
>
간편 로그인으로 빠르게 이용하기
</Link>
</div>
</div>
</div>
</div>
</article>

<div className="fixed left-0 bottom-0 w-full px-3 py-4 flex-center bg-primary">
<form onSubmit={(e) => e.preventDefault()} className="w-full max-w-[64rem]">
<div className="flex items-end gap-2">
<label htmlFor="chatInput" className="sr-only">
질문 입력창
</label>
<textarea
id="chatInput"
name="chatInput"
placeholder={'로그인 후 이용해주세요.'}
disabled
className={`
w-[calc(100%-3rem)] md:w-[calc(100%-3.75rem)] 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
`}
/>
<button
type="button"
aria-label="보내기"
className="flex-center w-10 md:w-13 h-10 md:h-13 rounded-xl border-1 border-white bg-secondary/20"
>
<Send className="text-secondary" />
</button>
</div>
</form>
</div>
</div>
</section>
);
}
export default ChatPreview;
2 changes: 1 addition & 1 deletion src/domains/recommend/components/ChatSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
import { useState } from 'react';
import MessageInput from './user/MessageInput';
import { fetchSendStepMessage, fetchSendTextMessage } from '../api/chat';
import { useAuthStore } from '@/domains/shared/store/auth';
import { ChatMessage, stepPayload } from '../types/recommend';
import ChatList from './ChatList';
import { useChatInit } from '../hook/useChatInit';
import { useSelectedOptions } from '../hook/useSelectedOptions';
import { useAuthStore } from '@/domains/shared/store/auth';

function ChatSection() {
const [messages, setMessages] = useState<ChatMessage[]>([]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ function CocktailCard({
<div className="flex flex-col gap-4">
<div
className={tw(
`${!className && 'w-80 h-75 md:w-62.5 '} rounded-xl overflow-hidden relative`,
`${!className && 'w-full max-w-[15.625rem] h-75'} rounded-xl overflow-hidden relative`,
className
)}
>
Expand Down
2 changes: 1 addition & 1 deletion src/shared/components/footer/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import Github from './Github';

function Footer() {
return (
<footer className="w-full bg-primary flex items-center justify-between p-[12px] font-serif font-light">
<footer className="w-full bg-primary flex items-center justify-between p-[12px] font-serif font-light shadow-footer">
<div className="flex flex-col gap-1">
<p className="text-sm md:text-base">Cocktail Discovery Service, SSOUL </p>
<div className="flex flex-col sm:flex-row gap-0.5 sm:gap-2 text-sm md:text-base">
Expand Down
43 changes: 30 additions & 13 deletions src/shared/components/header/DropdownMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { navItem } from '@/shared/utills/navigation';
import Image from 'next/image';
import Close from '@/shared/assets/icons/close_32.svg';
import User from '@/shared/assets/icons/user_24.svg';
import Bell from '@/shared/assets/icons/bell_24.svg';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
import { useEffect, useRef, useState } from 'react';
Expand All @@ -13,6 +14,7 @@ import { createPortal } from 'react-dom';
import { useAuthStore } from '@/domains/shared/store/auth';
import { setPreLoginPath } from '@/domains/shared/auth/utils/setPreLoginPath';
import LogoutConfirm from '@/domains/login/components/LogoutConfirm';
import { useRouter } from 'next/navigation';

interface Props {
isClicked: boolean;
Expand All @@ -28,8 +30,9 @@ function DropdownMenu({ isClicked, setIsClicked, visible, setVisible }: Props) {
const tlRef = useRef<GSAPTimeline | null>(null);
const [mounted, setMounted] = useState(false);

const { isLoggedIn, logout } = useAuthStore();
const { isLoggedIn } = useAuthStore();
const [logoutModalOpen, setLogoutModalOpen] = useState(false);
const router = useRouter();

useEffect(() => {
setMounted(true);
Expand Down Expand Up @@ -87,7 +90,7 @@ function DropdownMenu({ isClicked, setIsClicked, visible, setVisible }: Props) {
className="w-[62px] md:w-[82px] h-auto"
/>
</div>
<ul className="flex flex-col gap-[12px] text-black px-2 my-5">
<ul className="flex flex-col gap-[12px] text-black my-5">
{navItem
.filter((item) => {
// 비로그인 유저 마이페이지 숨기기
Expand Down Expand Up @@ -121,17 +124,31 @@ function DropdownMenu({ isClicked, setIsClicked, visible, setVisible }: Props) {

<div className="border border-t-[1px] border-t-gray flex items-center py-[32px] gap-2">
{isLoggedIn ? (
<button
type="button"
onClick={() => {
setLogoutModalOpen(true);
setIsClicked(false);
}}
className="flex items-center gap-2 text-black font-light text-xl hover:text-black/70"
>
<User color="var(--color-primary)" aria-hidden />
<span>로그아웃</span>
</button>
<div className="flex flex-col gap-3">
<button
type="button"
onClick={() => {
setIsClicked(false);
router.push('/mypage/my-alarm');
}}
className="flex items-center gap-2 text-black font-light text-xl hover:text-black/70"
>
<Bell color="var(--color-primary)" aria-hidden />
<span>알림</span>
</button>

<button
type="button"
onClick={() => {
setLogoutModalOpen(true);
setIsClicked(false);
}}
className="flex items-center gap-2 text-black font-light text-xl hover:text-black/70"
>
<User color="var(--color-primary)" aria-hidden />
<span>로그아웃</span>
</button>
</div>
) : (
<Link
href="/login"
Expand Down
5 changes: 4 additions & 1 deletion src/shared/components/header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ function Header() {
>
<HamburgerMenu />
<HeaderLogo />
<NavItem pathname={pathname} className="sm:block hidden" />
<NavItem
pathname={pathname}
className="hidden sm:block sm:absolute sm:left-1/2 sm:top-1/2 sm:-translate-x-1/2 sm:-translate-y-1/2"
/>
<HeaderBtn pathname={pathname} />
</header>
);
Expand Down
4 changes: 3 additions & 1 deletion src/shared/components/header/HeaderBtn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ function HeaderBtn({ pathname }: { pathname: string }) {
{
icon: Bell,
label: '알림',
onClick: () => setLogoutModalOpen(true),
className: pathname === '/mypage/my-alarm' ? 'text-tertiary' : 'text-current',
hiddenMobile: true,
onClick: () => router.push('/mypage/my-alarm'),
},
{
icon: User,
Expand Down
1 change: 1 addition & 0 deletions src/shared/styles/_theme.css
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@
--inset-shadow-black: inset 0 0px 6px rgba(0, 0, 0, 0.6);

--shadow-header: 0 6px 17px 0 rgba(255, 210, 187, 0.3);
--shadow-footer: 0 -1px 6px 0 rgba(255, 210, 187, 0.2);
}