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
18 changes: 18 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions src/assets/icon/ai/warning.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
52 changes: 52 additions & 0 deletions src/components/common/ComingSoonPlaceholder.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import type { ReactNode } from "react";
import { memo } from "react";
import { twMerge } from "tailwind-merge";

import WarningIcon from "@/assets/icon/ai/warning.svg?react";

export interface IComingSoonPlaceholderProps {
title: ReactNode;
description: ReactNode;
footer: ReactNode;
className?: string;
}

const ComingSoonPlaceholder = memo(function ComingSoonPlaceholder({
title,
description,
footer,
className,
}: IComingSoonPlaceholderProps) {
return (
<div
className={twMerge(
"flex h-full min-h-[70vh] w-full flex-1 flex-col items-center justify-center p-4",
className,
)}
>
<div
className="coming-soon-stagger flex w-full max-w-[420px] flex-col items-center rounded-[32px] bg-white px-8 py-12 text-center shadow-card transition-smooth hover:shadow-card-hover tablet:px-6"
role="status"
aria-live="polite"
>
Comment thread
Seojegyeong marked this conversation as resolved.
<div className="mb-6 flex items-center justify-center">
<WarningIcon className="h-30 w-auto shrink-0" aria-hidden />
</div>

<h1 className="mb-4 text-balance font-heading1 font-bold leading-snug tracking-tight text-text-main">
{title}
</h1>

<p className="break-keep font-body1 leading-relaxed text-text-auth-sub">
{description}
</p>

<div className="mt-8 flex w-full items-center justify-center rounded-component-md bg-chart-inactive px-6 py-4">
<p className="font-body1 font-medium text-text-main">{footer}</p>
</div>
</div>
</div>
);
});

export default ComingSoonPlaceholder;
17 changes: 16 additions & 1 deletion src/components/sidebar/Sidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { Dispatch, FocusEvent, SetStateAction } from "react";
import { useCallback } from "react";
import { AnimatePresence, motion } from "framer-motion";
import { twMerge } from "tailwind-merge";

Expand All @@ -7,6 +8,7 @@ import { footerNav, mainNav } from "@/constants/sidebarNav";
import { mainNavSidebar } from "@/utils/navigation/mainNavSidebar";
import { isPathMatch } from "@/utils/navigation/pathMatch";

import { useComingSoon } from "@/hooks/common/useComingSoon";
import { useSidebar } from "@/hooks/sidebar/useSidebar";

import { SidebarItem } from "./SidebarItem";
Expand Down Expand Up @@ -64,6 +66,19 @@ export default function Sidebar() {
toggleOpenId,
} = useSidebar();

const { showComingSoon } = useComingSoon();

const handleFooterItemClick = useCallback(
(id: string, hasChildren: boolean) => {
if (id === "notifications") {
showComingSoon("알림 기능은 준비 중이에요. 나중에 다시 확인해 주세요.");
return;
}
handleItemClick(id, hasChildren);
},
[handleItemClick, showComingSoon],
);

return (
<motion.div
className={twMerge(
Expand Down Expand Up @@ -159,7 +174,7 @@ export default function Sidebar() {
item={item}
isCollapsed={isCollapsed}
className="w-full h-full"
onClick={handleItemClick}
onClick={handleFooterItemClick}
/>
</div>
);
Expand Down
16 changes: 16 additions & 0 deletions src/hooks/common/useComingSoon.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { useCallback } from "react";
import { toast } from "sonner";

const DEFAULT_MESSAGE =
"해당 기능은 아직 준비 중이에요. 곧 이용하실 수 있어요!";

export function useComingSoon() {
const showComingSoon = useCallback((message: string = DEFAULT_MESSAGE) => {
toast.info(message, {
id: "coming-soon",
duration: 4000,
});
}, []);

return { showComingSoon };
}
23 changes: 23 additions & 0 deletions src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,23 @@ button {
animation-delay: 100ms;
}

/* 준비 중 플레이스홀더 — 자식 순차 진입 (인라인 delay 제거) */
.coming-soon-stagger > * {
animation: slide-fade-up 350ms var(--ease-out) both;
}
.coming-soon-stagger > :nth-child(1) {
animation-delay: 0ms;
}
.coming-soon-stagger > :nth-child(2) {
animation-delay: 50ms;
}
.coming-soon-stagger > :nth-child(3) {
animation-delay: 100ms;
}
.coming-soon-stagger > :nth-child(4) {
animation-delay: 150ms;
}

/* 그래프 상승 애니메이션 */
@keyframes graph-up {
from {
Expand Down Expand Up @@ -481,6 +498,12 @@ button {
transform: none;
}

.coming-soon-stagger > * {
animation: none;
opacity: 1;
transform: none;
}

/* 인트로 캐러셀 — 위치 이동 중단 */
.animate-scroll {
animation: none;
Expand Down
20 changes: 19 additions & 1 deletion src/pages/dashboard/timeline/Timeline.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
import ComingSoonPlaceholder from "@/components/common/ComingSoonPlaceholder";

export default function Timeline() {
return <div>Timeline</div>;
return (
<ComingSoonPlaceholder
title={
<>
<span className="block">성과 타임라인을</span>
<span className="block">준비하고 있어요</span>
</>
}
description={
<>
<span className="block">캠페인 흐름을 한눈에 파악할 수 있도록,</span>
<span className="block">더 유용한 기능으로 찾아올게요.</span>
</>
}
footer="조금만 기다려 주시면 감사하겠습니다"
/>
);
}
22 changes: 21 additions & 1 deletion src/pages/workspace/Billing.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,23 @@
import ComingSoonPlaceholder from "@/components/common/ComingSoonPlaceholder";

export default function Billing() {
return <div>Billing</div>;
return (
<ComingSoonPlaceholder
title={
<>
<span className="block">플랜 및 결제 기능을</span>
<span className="block">준비하고 있어요</span>
</>
}
description={
<>
<span className="block">
플랜 선택과 결제 정보를 편하게 관리할 수 있는
</span>
<span className="block">기능을 열심히 만들고 있습니다.</span>
</>
}
footer="정식 오픈 후 이용하실 수 있습니다"
/>
);
}
Loading