Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev --turbopack",
"dev": "next dev",
"format": "prettier --write \"src/**/*.{ts,tsx,js,jsx}\"",
"format:check": "prettier --check \"src/**/*.{ts,tsx,js,jsx}\"",
"prepare": "husky",
Expand Down
38 changes: 21 additions & 17 deletions src/app/recipe/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import Input from '@/shared/components/Input-box/Input';
import Accordion from '../../domains/recipe/components/main/Accordion';
import CocktailList from '@/domains/recipe/CocktailList';
import PageHeader from '@/domains/shared/components/page-header/PageHeader';
import { Suspense } from 'react';
import SkeletonRecipe from '@/domains/recipe/skeleton/SkeletonRecipe';

export const metadata: Metadata = {
title: 'SSOUL | 칵테일레시피',
Expand All @@ -18,24 +20,26 @@ function Page() {
<PageHeader title="Cocktail Recipes" description="다양하고 재밌는 칵테일 레시피" />
</section>
<div className="page-layout max-w-1224 mt-6">
<section className="flex flex-col-reverse items-start gap-6 md:flex-row md:justify-between md:items-center ">
<Accordion />
<Input
placeholder="내용을 입력해 주세요."
id="search"
variant="search"
className="w-full md:max-w-80"
/>
</section>
<section>
<div className="h-10 flex justify-between items-center mt-3 border-b-1 border-gray-light">
<p>n개</p>
<SelectBox option={['', '댓글순', '인기순']} title="최신순" />
</div>
<section className="mt-5">
<CocktailList />
<Suspense fallback={<SkeletonRecipe />}>
<section className="flex flex-col-reverse items-start gap-6 md:flex-row md:justify-between md:items-center ">
<Accordion />
<Input
placeholder="내용을 입력해 주세요."
id="search"
variant="search"
className="w-full md:max-w-80"
/>
</section>
</section>
<section>
<div className="h-10 flex justify-between items-center mt-3 border-b-1 border-gray-light">
<p>n개</p>
<SelectBox option={['', '댓글순', '인기순']} title="최신순" />
</div>
<section className="mt-5">
<CocktailList />
</section>
</section>
</Suspense>
</div>
</div>
);
Expand Down
5 changes: 2 additions & 3 deletions src/domains/recipe/CocktailCard.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { StaticImageData } from 'next/image';
import Image from 'next/image';
import Img from '@/shared/assets/images/dummy/exampleCocktail.png';
import Keep from '../shared/keep/Keep';
import Label from '../shared/label/Label';

import Label from '../shared/components/label/Label';
import Keep from '../shared/components/keep/Keep';

interface Props {
src?: StaticImageData;
Expand Down
4 changes: 2 additions & 2 deletions src/domains/recipe/details/DetailList.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import DetailRecommendList from "./DetailRecommendList";
import DetailRecommendList from './DetailRecommendList';

function DetailList() {
return (
<ul className='flex justify-between gap-2'>
<ul className="flex justify-between gap-2">
<li>
<DetailRecommendList />
</li>
Expand Down
67 changes: 35 additions & 32 deletions src/domains/recipe/details/DetailMain.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,45 +7,48 @@ import SsuryShake from '@/shared/assets/ssury/ssury_make.webp';
import SsuryDrink from '@/shared/assets/ssury/ssury_drink.webp';
import Image from 'next/image';
import DetailList from './DetailList';

import { Suspense } from 'react';
import SkeletonDetail from '../skeleton/SkeletonDetail';

function DetailMain() {
return (
<div className="max-w-1024 page-layout py-12">
<DetailsHeader />

<article className="flex flex-col items-center mt-4 lg:mt-0">
<span className="md:bg-secondary w-1 h-100 -translate-y-19 absolute top-0 left-1/2 -translate-x-1/2 md: z-2"></span>
<span className="h-3 w-3 rounded-full absolute top-80 left-1/2 -translate-x-1/2 z-99 md:bg-secondary"></span>
<DetailItem />
</article>

<section className="mt-20 flex flex-col gap-5">
<div className="border-b-1 h-18 border-white">
<div className="flex items-center gap-3">
<Image src={SsuryShake} alt="" width="48" height="48" />
<h3 className="text-3xl font-bold">레시피</h3>
<Suspense fallback={<SkeletonDetail />}>
<div className="max-w-1024 page-layout py-12">
<DetailsHeader />

<article className="flex flex-col items-center mt-4 lg:mt-0">
<span className="md:bg-secondary w-1 h-100 -translate-y-19 absolute top-0 left-1/2 -translate-x-1/2 md: z-2"></span>
<span className="h-3 w-3 rounded-full absolute top-80 left-1/2 -translate-x-1/2 z-99 md:bg-secondary"></span>
<DetailItem />
</article>

<section className="mt-20 flex flex-col gap-5">
<div className="border-b-1 h-18 border-white">
<div className="flex items-center gap-3">
<Image src={SsuryShake} alt="" width="48" height="48" />
<h3 className="text-3xl font-bold">레시피</h3>
</div>
</div>
</div>
<DetailRecipe />
</section>

<section className="mt-20" aria-labelledby="옆으로 슬라이드되는 리스트">
<h2 className="sr-only">추천 칵테일 리스트</h2>
<div className="border-b-1 h-18 border-white">
<div className="flex items-center gap-3">
<Image src={SsuryDrink} alt="" width="48" height="48" />
<h3 className="text-3xl font-bold">추천리스트</h3>
<DetailRecipe />
</section>

<section className="mt-20" aria-labelledby="옆으로 슬라이드되는 리스트">
<h2 className="sr-only">추천 칵테일 리스트</h2>
<div className="border-b-1 h-18 border-white">
<div className="flex items-center gap-3">
<Image src={SsuryDrink} alt="" width="48" height="48" />
<h3 className="text-3xl font-bold">추천리스트</h3>
</div>
</div>
</div>

<div className="mt-5">
<DetailList />
</div>
</section>
<div className="mt-5">
<DetailList />
</div>
</section>

<section>{/* 여기에 댓글 컴포넌트 */}</section>
</div>
<section>{/* 여기에 댓글 컴포넌트 */}</section>
</div>
</Suspense>
);
}
export default DetailMain;
112 changes: 112 additions & 0 deletions src/domains/recipe/skeleton/SkeletonDetail.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// DetailSkeleton.tsx
// 한 페이지에 붙여넣기만 하면 되는 최소 스켈레톤 UI

export default function DetailSkeleton() {
return (
<div className="page-layout max-w-1024 py-12 animate-pulse">
{/* 헤더 */}
<div className="mt-4 flex items-center justify-between">
<div className="h-8 w-16 rounded bg-gray animate-pulse " />
<div className="flex items-center gap-3">
<div className="h-8 w-8 rounded bg-gray animate-pulse " />
<div className="h-8 w-8 rounded bg-gray animate-pulse " />
</div>
</div>

{/* 메인 아이템 */}
<article className="flex flex-col items-center mt-8 ">
{/* 타이틀/설명 */}
<div
className="flex flex-col items-center gap-3 relative md:flex-row md:justify-between
md:ml-15 md:w-150
lg:ml-30 lg:w-187.5 h-50"
>
<div className="flex flex-col md:ml-10 gap-3 items-center md:items-end">
<div className="h-6 w-14 rounded bg-gray animate-pulse" />
<div className="h-8 w-56 rounded bg-gray animate-pulse " />
<div className="h-7 w-40 rounded bg-gray animate-pulse " />
</div>
<div className="w-70 h-20 rounded mr-5 md:mr-0 md:self-end md:w-70 lg:w-100 bg-gray animate-pulse" />
</div>

{/* 이미지 */}
<div className="mt-8 h-[375px] w-[300px] aspect-[3/4] rounded-2xl bg-gray animate-pulse" />

{/* 도수/글래스 정보 */}
<dl className="flex flex-col mt-6 gap-3 w-72">
<div className="flex items-center gap-3">
<div className="h-5 w-22 rounded bg-gray animate-pulse" />

<div className="flex-1 h-3 rounded bg-gray animate-pulse" />
</div>
<div className="flex items-center gap-3">
<div className="h-5 w-24 rounded bg-gray animate-pulse" />
<div className="h-5 w-20 rounded bg-gray animate-pulse" />
</div>
</dl>
</article>

{/* 레시피 섹션 */}
<section className="mt-16 flex flex-col gap-5">
<div className="border-b-1 h-18 border-white flex items-center gap-3">
<div className="h-12 w-12 rounded bg-gray animate-pulse" />
<div className="h-8 w-36 rounded bg-gray animate-pulse" />
</div>

<div className="flex flex-col md:flex-row px-5 gap-5">
{/* 재료 */}
<article className="flex flex-col gap-3 md:w-1/2">
<div className="h-7 w-16 rounded bg-gray animate-pulse" />
<ul className="flex flex-col gap-2">
{Array.from({ length: 4 }).map((_, i) => (
<li key={i} className="h-5 w-56 rounded bg-gray animate-pulse" />
))}
</ul>
</article>

{/* 만드는 법 */}
<span className="border-t-1 pt-5 md:border-l-1 md:border-t-0 md:px-10 border-white">
<article className="flex flex-col gap-3">
<div className="h-7 w-24 rounded bg-gray animate-pulse" />
<ol className="flex flex-col gap-2">
{Array.from({ length: 4 }).map((_, i) => (
<li key={i} className="h-5 w-72 rounded bg-gray animate-pulse" />
))}
</ol>
</article>
</span>
</div>
</section>

{/* 추천 리스트 */}
<section className="mt-16">
<div className="border-b-1 h-18 border-white flex items-center gap-3">
<div className="h-12 w-12 rounded bg-gray animate-pulse" />
<div className="h-8 w-28 rounded bg-gray animate-pulse" />
</div>

<div className="mt-6">
<ul className="flex justify-between gap-4">
{Array.from({ length: 3 }).map((_, i) => (
<li key={i} className="w-full max-w-[250px]">
<div className="relative w-full aspect-[5/6] overflow-hidden rounded-lg">
<div className="absolute inset-0 bg-gray animate-pulse"></div>
</div>
<div className="mt-3 space-y-2">
<div className="h-5 w-3/5 rounded bg-gray animate-pulse"></div>
<div className="h-4 w-2/5 rounded bg-gray animate-pulse"></div>
</div>
</li>
))}
</ul>
</div>
</section>

{/* 댓글 자리 */}
<section className="mt-16">
<div className="h-8 w-24 rounded bg-gray animate-pulse" />
<div className="mt-4 h-24 w-full rounded bg-gray animate-pulse" />
</section>
</div>
);
}
33 changes: 33 additions & 0 deletions src/domains/recipe/skeleton/SkeletonRecipe.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// app/recipe/loading.tsx (예)
function SkeletonRecipe() {
return (
<div className="animate-pulse">
{/* Toolbar 자리 (Accordion + Input) */}
<div className="flex flex-col-reverse items-start gap-6 md:flex-row md:justify-between md:items-center">
<div className="h-10 w-40 bg-gray rounded-lg animate-pulse " />
<div className="h-10 w-full md:max-w-80 bg-gray rounded animate-pulse" />
</div>

{/* 상단 라인 */}
<div className="h-10 flex justify-between items-center mt-3 border-b-1 border-gray-light">
<div className="h-4 w-10 bg-gray rounded animate-pulse" />
<div className="h-8 w-28 bg-gray rounded animate-pulse" />
</div>

{/* 리스트 자리 */}
<div className="mt-5 grid gap-8 grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4">
{Array.from({ length: 8 }).map((_, i) => (
<div key={i} className="w-full min-w-0">
<div className="relative w-full aspect-[3/4] max-w-80 max-h-75 md:max-w-62.5 overflow-hidden rounded-xl bg-gray animate-pulse" />
<div className="mt-4.5 space-y-2">
<div className="h-5 w-2/3 bg-gray rounded animate-pulse" />
<div className="h-4 w-1/2 bg-gray rounded animate-pulse" />
</div>
</div>
))}
</div>
</div>
);
}

export default SkeletonRecipe;
1 change: 1 addition & 0 deletions src/domains/shared/components/page-header/PageHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
'use client';
import StarBg from '../star-bg/StarBg';

interface Props {
Expand Down
1 change: 1 addition & 0 deletions src/shared/components/Input-box/Input.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
'use client';
import tw from '@/shared/utills/tw';
import { cva } from 'class-variance-authority';
import { HTMLInputTypeAttribute, Ref } from 'react';
Expand Down