diff --git a/package.json b/package.json index 45e2f17..058eb5b 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,6 @@ ] }, "dependencies": { - "@toss/use-funnel": "^1.4.2", "axios": "^1.13.2", "next": "16.0.10", "react": "19.2.1", diff --git a/public/images/missionIcon/color.svg b/public/images/missionIcon/color.svg new file mode 100644 index 0000000..98fe240 --- /dev/null +++ b/public/images/missionIcon/color.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/images/missionIcon/food.svg b/public/images/missionIcon/food.svg new file mode 100644 index 0000000..a4c2552 --- /dev/null +++ b/public/images/missionIcon/food.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/images/missionIcon/plant.svg b/public/images/missionIcon/plant.svg new file mode 100644 index 0000000..f29c66d --- /dev/null +++ b/public/images/missionIcon/plant.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/images/missionIcon/time.svg b/public/images/missionIcon/time.svg new file mode 100644 index 0000000..4da007f --- /dev/null +++ b/public/images/missionIcon/time.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/images/missionIcon/tv.svg b/public/images/missionIcon/tv.svg new file mode 100644 index 0000000..55fb1b5 --- /dev/null +++ b/public/images/missionIcon/tv.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/app/day-log/page.tsx b/src/app/day-log/page.tsx index 422d7b2..eb11c03 100644 --- a/src/app/day-log/page.tsx +++ b/src/app/day-log/page.tsx @@ -7,7 +7,7 @@ import { SharedDiaryCard } from "@/components/dailyRecord/SharedDiaryCard"; import DailyRecordData from "@/mock/dailyRecord.json"; const DailyRecordPage = () => { - const MY_ID = 101; + const MY_ID = 111; const hasMyRecord = DailyRecordData.some(item => item.userId === MY_ID); return ( diff --git a/src/app/day-story/upload/page.tsx b/src/app/day-story/upload/page.tsx new file mode 100644 index 0000000..8854fa0 --- /dev/null +++ b/src/app/day-story/upload/page.tsx @@ -0,0 +1,23 @@ +"use client"; +import { useState } from "react"; + +import { BackHeader } from "@/components/common/BackHeader"; +import { DailyMissionCard } from "@/components/dailyPhoto/DailyMissionCard"; +import { DailyMissionProgress } from "@/components/dailyPhoto/DailyMissionProgress"; + +import { MISSION_STATUS } from "@/constants/missionCard"; + +const DayStoryUpload = () => { + const [status, setStatus] = + useState("NOT_STARTED"); + return ( +
+ + +
+ +
+
+ ); +}; +export default DayStoryUpload; diff --git a/src/app/shared-diary/[id]/comment/page.tsx b/src/app/shared-diary/[id]/comment/page.tsx new file mode 100644 index 0000000..b5cc797 --- /dev/null +++ b/src/app/shared-diary/[id]/comment/page.tsx @@ -0,0 +1,7 @@ +import { SharedDiaryComment } from "@/components/dailyRecord/SharedDiaryChat"; + +const SharedDiaryChatPage = () => { + return ; +}; + +export default SharedDiaryChatPage; diff --git a/src/app/shared-diary/upload/page.tsx b/src/app/shared-diary/upload/page.tsx new file mode 100644 index 0000000..2635d6a --- /dev/null +++ b/src/app/shared-diary/upload/page.tsx @@ -0,0 +1 @@ +//공유일기 글쓰기 페이지 diff --git a/src/assets/SendButton.tsx b/src/assets/SendButton.tsx index 2294d4c..c775409 100644 --- a/src/assets/SendButton.tsx +++ b/src/assets/SendButton.tsx @@ -2,12 +2,16 @@ import SendIcon from "@/assets/messenger.svg"; interface SendButtonProps { hasText: boolean; + onClick: React.MouseEventHandler; } -export const SendButton = ({ hasText = false }: SendButtonProps) => { +export const SendButton = ({ hasText = false, onClick }: SendButtonProps) => { return ( - ); diff --git a/src/assets/close.svg b/src/assets/close.svg index 4553bec..71e65f4 100644 --- a/src/assets/close.svg +++ b/src/assets/close.svg @@ -1,3 +1,4 @@ - - + + + diff --git a/src/assets/left-arrow.svg b/src/assets/left-arrow.svg index e099fe1..fc0a3f2 100644 --- a/src/assets/left-arrow.svg +++ b/src/assets/left-arrow.svg @@ -1,3 +1,3 @@ - + diff --git a/src/assets/questionMark.svg b/src/assets/questionMark.svg new file mode 100644 index 0000000..bbc61af --- /dev/null +++ b/src/assets/questionMark.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/common/BackHeader.tsx b/src/components/common/BackHeader.tsx index 1d9865d..dc69df6 100644 --- a/src/components/common/BackHeader.tsx +++ b/src/components/common/BackHeader.tsx @@ -9,9 +9,15 @@ interface HeaderProps { title: string; timeAgo?: string; // 하루한컷보기에서 사용 menuIcon?: boolean; // 채팅페이지에서 사용 + titleColor?: string; //하루한컷 업로드에서 사용 } -export const BackHeader = ({ title, timeAgo, menuIcon }: HeaderProps) => { +export const BackHeader = ({ + title, + timeAgo, + menuIcon, + titleColor = "black", +}: HeaderProps) => { const router = useRouter(); return ( @@ -21,9 +27,11 @@ export const BackHeader = ({ title, timeAgo, menuIcon }: HeaderProps) => { onClick={() => router.back()} className="absolute top-1/2 left-4 -translate-y-1/2 cursor-pointer" > - + -

+

{title}

{timeAgo && ( diff --git a/src/components/common/MessageInput.tsx b/src/components/common/MessageInput.tsx index d483d6b..71e8213 100644 --- a/src/components/common/MessageInput.tsx +++ b/src/components/common/MessageInput.tsx @@ -2,19 +2,40 @@ import { useState } from "react"; import { SendButton } from "@/assets/SendButton"; -export const MessageInput = () => { +interface MessageInputProps { + onFocus?: React.FocusEventHandler; + onSend?: (message: string) => void; +} + +export const MessageInput = ({ onFocus, onSend }: MessageInputProps) => { const [text, setText] = useState(""); + const [isComposing, setIsComposing] = useState(false); + const hasText = Boolean(text); + const sendMessage = () => { + if (!hasText) return; + onSend?.(text.trim()); + setText(""); + }; return (
setText(e.target.value)} + onFocus={onFocus} + onCompositionStart={() => setIsComposing(true)} + onCompositionEnd={() => setIsComposing(false)} + onKeyDown={e => { + if (e.key === "Enter" && !isComposing) { + e.preventDefault(); + sendMessage(); + } + }} /> - +
); }; diff --git a/src/components/dailyPhoto/DailyMissionCard.tsx b/src/components/dailyPhoto/DailyMissionCard.tsx new file mode 100644 index 0000000..75b5283 --- /dev/null +++ b/src/components/dailyPhoto/DailyMissionCard.tsx @@ -0,0 +1,109 @@ +"use client"; +import Image from "next/image"; +import { useRouter } from "next/navigation"; + +import { useState } from "react"; + +import { MISSION_SORT, MISSION_STATUS } from "@/constants/missionCard"; +import { WEEK_DAYS_KOR } from "@/constants/weekDays"; + +import { useImageUpload } from "@/hooks/useImageUpload"; + +import missionCardData from "@/mock/randomMission.json"; + +import { getTodayIndex } from "@/utils/getCurrentDay"; +import { getMissionSubtitle } from "@/utils/getMissionSubtitle"; + +interface DailyMissionCardProps { + status: keyof typeof MISSION_STATUS; + setStatus: React.Dispatch>; +} + +export const DailyMissionCard = ({ + status, + setStatus, +}: DailyMissionCardProps) => { + const [previewUrl, setPreviewUrl] = useState(null); + + const currentDayIndex = getTodayIndex(); + + const subtitle = getMissionSubtitle(status, currentDayIndex); + + const missionKind = missionCardData[0].kind; + + const missionIcon = MISSION_SORT.find( + item => item.sort === missionKind, + )?.icon; + + const onSelectImage = (previewUrl: string) => { + setPreviewUrl(previewUrl); + setStatus("IMAGE_UPLOADED"); + }; + + const { inputRef, openFilePicker, onChangeFile } = useImageUpload({ + onSelect: ({ previewUrl }) => { + onSelectImage(previewUrl); + }, + maxSizeMB: 10, + }); + + const router = useRouter(); + return ( +
+
+

+ {MISSION_STATUS[status].title} +

+

{subtitle}

+
+ {status === "NOT_STARTED" && missionIcon && ( +
+ 미션카드종류 이미지 +
+ )} + {status !== "NOT_STARTED" && previewUrl && ( +
+ 하루한컷이미지 +
+ )} + +
+
+ {status === "IMAGE_CONFIRMED" + ? "미션이 완료되었어요!" + : missionCardData[0].mission} +
+ +
+ +
+ ); +}; diff --git a/src/components/dailyPhoto/DailyMissionProgress.tsx b/src/components/dailyPhoto/DailyMissionProgress.tsx new file mode 100644 index 0000000..0cd1d67 --- /dev/null +++ b/src/components/dailyPhoto/DailyMissionProgress.tsx @@ -0,0 +1,83 @@ +"use client"; + +import CheckIcon from "@/assets/check.svg"; +import CrossIcon from "@/assets/close.svg"; +import QuestionIcon from "@/assets/questionMark.svg"; + +import { MISSION_STATUS } from "@/constants/missionCard"; +import { WEEK_DAYS_KOR, WEEK_DAY_KEYS } from "@/constants/weekDays"; + +import dailyRecordProgress from "@/mock/dailyRecordProgress.json"; + +import { getWeekDayStatus } from "@/utils/getCurrentDay"; + +type WeekDayKey = keyof typeof dailyRecordProgress; + +interface DailyMissionProgressProps { + status: keyof typeof MISSION_STATUS; +} + +export const DailyMissionProgress = ({ status }: DailyMissionProgressProps) => { + return ( +
    + {WEEK_DAYS_KOR.map((item, index) => { + const dayStatus = getWeekDayStatus(index); // past | today | future + const dayKey = WEEK_DAY_KEYS[index] as WeekDayKey; + + const isCompleted = + dayStatus === "today" && status === "IMAGE_CONFIRMED" + ? true + : dailyRecordProgress[dayKey]; + + const showCheck = + (dayStatus === "past" && isCompleted) || + (dayStatus === "today" && isCompleted); + + const showCross = dayStatus === "past" && !isCompleted; + + const showQuestion = + dayStatus === "future" || (dayStatus === "today" && !isCompleted); + + return ( +
  • +
    + {showCheck && ( +
    + +
    + )} + + {showCross && ( +
    + +
    + )} + + {showQuestion && ( +
    + +
    + )} + + + {item} + +
    +
  • + ); + })} +
+ ); +}; diff --git a/src/components/dailyRecord/CommentList.tsx b/src/components/dailyRecord/CommentList.tsx new file mode 100644 index 0000000..8e2d585 --- /dev/null +++ b/src/components/dailyRecord/CommentList.tsx @@ -0,0 +1,45 @@ +import Image from "next/image"; + +import { DiaryComment } from "@/types/diaryComment.type"; + +import { formatDate } from "@/utils/formatDate"; + +interface CommentListProps { + comments: DiaryComment[]; +} + +export const CommentList = ({ comments }: CommentListProps) => { + if (comments.length === 0) { + return ( +
+

아직 댓글이 없습니다

+

댓글을 남겨보세요!

+
+ ); + } + + return ( +
    + {comments.map(comment => ( +
  • + {comment.userName} +
    +
    +

    {comment.userName}

    +

    {comment.comment}

    +
    +

    + {formatDate(comment.createdAt)} +

    +
    +
  • + ))} +
+ ); +}; diff --git a/src/components/dailyRecord/Header.tsx b/src/components/dailyRecord/Header.tsx index 850644e..56158af 100644 --- a/src/components/dailyRecord/Header.tsx +++ b/src/components/dailyRecord/Header.tsx @@ -13,7 +13,7 @@ export const Header = () => { return (
-

하루기록

+

하루기록

{isAlarmNew ? ( -
-

- 댓글 -

-
-

아직 댓글이 없습니다

-

댓글을 남겨보세요!

-
+
{ + if (!isPage) router.back(); + }} + > +
e.stopPropagation()} + > +
+ +
+

+ 댓글 +

+
+
+
myProfileImage + { + if (!isPage && numericId !== null) { + router.push(`/shared-diary/${numericId}/comment`); + } + }} + onSend={message => { + setComments(prev => [ + ...prev, + { + id: Date.now(), + userName: MyProfile.userName, + profileImg: profileImg, + comment: message, + createdAt: new Date().toISOString(), + }, + ]); + }} /> -
diff --git a/src/constants/missionCard.ts b/src/constants/missionCard.ts new file mode 100644 index 0000000..408c256 --- /dev/null +++ b/src/constants/missionCard.ts @@ -0,0 +1,28 @@ +export const MISSION_STATUS = { + NOT_STARTED: { + title: "하루한컷 미션 도착!", + subtitle: (localday: string) => localday, + buttonText: "시작하기", + }, + IMAGE_UPLOADED: { + title: "하루한컷 미션을 공유할까요?", + subtitle: "확인을 누르면 미션이 완료돼요", + buttonText: "공유하기", + }, + IMAGE_CONFIRMED: { + title: "미션 업로드 성공", + subtitle: "소중한 오늘의 한컷을 기록했어요", + buttonText: "보러가기", + }, +} as const; + +export const MISSION_SORT = [ + { sort: "food", icon: "/images/missionIcon/food.svg" }, + { + sort: "plant", + icon: "/images/missionIcon/plant.svg", + }, + { sort: "color", icon: "/images/missionIcon/color.svg" }, + { sort: "time", icon: "/images/missionIcon/time.svg" }, + { sort: "tv", icon: "/images/missionIcon/tv.svg" }, +]; diff --git a/src/constants/navBarItems.ts b/src/constants/navBarItems.ts index fe8bc36..aa8a099 100644 --- a/src/constants/navBarItems.ts +++ b/src/constants/navBarItems.ts @@ -22,7 +22,7 @@ export const NAV_ITEMS = [ { key: "record", label: "하루기록", - href: "/record", + href: "/day-log", icons: { blank: RecordBlankIcon, fill: RecordFillIcon, diff --git a/src/constants/weekDays.ts b/src/constants/weekDays.ts new file mode 100644 index 0000000..8fb05b7 --- /dev/null +++ b/src/constants/weekDays.ts @@ -0,0 +1,19 @@ +export const WEEK_DAYS_KOR = [ + "월", + "화", + "수", + "목", + "금", + "토", + "일", +] as const; + +export const WEEK_DAY_KEYS = [ + "monday", + "tuesday", + "wednesday", + "thursday", + "friday", + "saturday", + "sunday", +] as const; diff --git a/src/hooks/useImageUpload.ts b/src/hooks/useImageUpload.ts new file mode 100644 index 0000000..54d56d1 --- /dev/null +++ b/src/hooks/useImageUpload.ts @@ -0,0 +1,42 @@ +import { useRef } from "react"; + +import { UploadImageResult, uploadImage } from "@/utils/uploadImage.util"; + +interface UseImageUploadProps { + onSelect: (result: UploadImageResult) => void; + maxSizeMB?: number; +} + +export const useImageUpload = ({ + onSelect, + maxSizeMB, +}: UseImageUploadProps) => { + const inputRef = useRef(null); + + const openFilePicker = () => { + inputRef.current?.click(); + }; + + const onChangeFile = (e: React.ChangeEvent) => { + const file = e.target.files?.[0]; + if (!file) return; + + try { + const result = uploadImage(file, { maxSizeMB }); + onSelect(result); + } catch (error) { + if (error instanceof Error) { + alert(error.message); + } + } + + // 같은 파일 재선택 가능하게 + e.target.value = ""; + }; + + return { + inputRef, + openFilePicker, + onChangeFile, + }; +}; diff --git a/src/mock/dailyRecordProgress.json b/src/mock/dailyRecordProgress.json new file mode 100644 index 0000000..26b76ba --- /dev/null +++ b/src/mock/dailyRecordProgress.json @@ -0,0 +1,9 @@ +{ + "monday": true, + "tuesday": false, + "wednesday": true, + "thursday": false, + "friday": false, + "saturday": true, + "sunday": false +} diff --git a/src/mock/diaryComment.json b/src/mock/diaryComment.json new file mode 100644 index 0000000..aa88400 --- /dev/null +++ b/src/mock/diaryComment.json @@ -0,0 +1,23 @@ +[ + { + "id": 1, + "userName": "박혜미", + "profileImg": "/images/1.jpg", + "comment": "코코넛 커피도 마셔주세요", + "createdAt": "2025-12-30T09:12:00" + }, + { + "id": 2, + "userName": "신수진", + "profileImg": "/images/2.jpg", + "comment": "코코넛 커피도 마셔주세요2", + "createdAt": "2026-01-01T09:12:00" + }, + { + "id": 3, + "userName": "박영신", + "profileImg": "/images/3.jpg", + "comment": "코코넛 커피도 마셔주세요3", + "createdAt": "2026-01-03T09:12:00" + } +] diff --git a/src/mock/randomMission.json b/src/mock/randomMission.json new file mode 100644 index 0000000..b5fa404 --- /dev/null +++ b/src/mock/randomMission.json @@ -0,0 +1,13 @@ +[ + { "kind": "food", "mission": "오늘의 점심식사를 공유해주세요" }, + { "kind": "plant", "mission": "오늘의 꽃을 공유해주세요" }, + { + "kind": "color", + "mission": "오늘의 빨간색을 공유해주세요" + }, + { + "kind": "time", + "mission": "오늘 행복한 순간을 공유해주세요" + }, + { "kind": "tv", "mission": "오늘의 드라마를 공유해주세요" } +] diff --git a/src/styles/globals.css b/src/styles/globals.css index c9b4367..962eed8 100644 --- a/src/styles/globals.css +++ b/src/styles/globals.css @@ -41,7 +41,7 @@ --color-neutral-11: #f9f9fb; --color-white: #fefefe; - --color-dim-02: #242628D4; + --color-dim-02: #242628d4; } @layer utilities { @@ -68,50 +68,27 @@ .bg-dim02-gradient { background: linear-gradient( - 0deg, - rgba(36, 38, 40, 0.83) 0%, - rgba(36, 38, 40, 0.83) 100% - ) + 0deg, + rgba(36, 38, 40, 0.83) 0%, + rgba(36, 38, 40, 0.83) 100% + ); } - .bg-onboarding-circle-mint { - border-radius: 146px; + .bg-onboarding-circle-mint { background: linear-gradient( 180deg, - rgba(79, 255, 144, 0.10) 0%, - rgba(255, 255, 255, 0.10) 100% + rgba(79, 255, 144, 0.1) 0%, + rgba(255, 255, 255, 0.1) 100% ); } .bg-onboarding-circle-gray { - border-radius: 146px; background: linear-gradient( 160deg, - rgba(255, 255, 255, 0.10) 42.99%, - rgba(103, 103, 103, 0.10) 80.56% + rgba(255, 255, 255, 0.1) 42.99%, + rgba(103, 103, 103, 0.1) 80.56% ); } -} - -@layer utilities { - .scrollbar-hide { - -ms-overflow-style: none; /* IE and Edge */ - scrollbar-width: none; /* Firefox */ - } - .scrollbar-hide::-webkit-scrollbar { - display: none; /* Chrome, Safari, Opera*/ - } - .bg-radial-yellowgreen-mintgreen { - background: - radial-gradient( - 39.1% 31.12% at 80.25% 2.51%, - rgba(246, 248, 173, 0.42) 57.26%, - rgba(255, 255, 255, 0.42) 100% - ), - radial-gradient( - 39.99% 49.21% at 23.64% 2.72%, - rgba(66, 240, 158, 0.66) 21.15%, - rgba(255, 255, 255, 0.87) 93.53% - ); + .bg-gradient-orange { + background: linear-gradient(180deg, #f9cb4c 0%, #fdbb05 100%); } } - diff --git a/src/types/diaryComment.type.ts b/src/types/diaryComment.type.ts new file mode 100644 index 0000000..e877568 --- /dev/null +++ b/src/types/diaryComment.type.ts @@ -0,0 +1,7 @@ +export type DiaryComment = { + id: number; + userName: string; + profileImg: string; + comment: string; + createdAt: string; +}; diff --git a/src/utils/formatDate.ts b/src/utils/formatDate.ts new file mode 100644 index 0000000..56c71dc --- /dev/null +++ b/src/utils/formatDate.ts @@ -0,0 +1,13 @@ +export const formatDate = (createdAt: string): string => { + const date = new Date(createdAt); + + if (isNaN(date.getTime())) { + throw new Error("Invalid date string"); + } + + const year = date.getFullYear().toString().slice(2); + const month = String(date.getMonth() + 1).padStart(2, "0"); + const day = String(date.getDate()).padStart(2, "0"); + + return `${year}년 ${month}월${day}일`; +}; diff --git a/src/utils/getCurrentDay.ts b/src/utils/getCurrentDay.ts new file mode 100644 index 0000000..f03fe2d --- /dev/null +++ b/src/utils/getCurrentDay.ts @@ -0,0 +1,18 @@ +// 월:0 ~ 일:6 +export const getMondayStartIndex = (day: number) => (day === 0 ? 6 : day - 1); + +// 오늘 요일 인덱스 +export const getTodayIndex = () => { + const today = new Date().getDay(); + return getMondayStartIndex(today); +}; + +type DayStatus = "past" | "today" | "future"; + +export const getWeekDayStatus = (targetIndex: number): DayStatus => { + const todayIndex = getTodayIndex(); + + if (targetIndex < todayIndex) return "past"; + if (targetIndex > todayIndex) return "future"; + return "today"; +}; diff --git a/src/utils/getMissionSubtitle.ts b/src/utils/getMissionSubtitle.ts new file mode 100644 index 0000000..011c84e --- /dev/null +++ b/src/utils/getMissionSubtitle.ts @@ -0,0 +1,15 @@ +import { MISSION_STATUS } from "@/constants/missionCard"; +import { WEEK_DAYS_KOR } from "@/constants/weekDays"; + +export const getMissionSubtitle = ( + status: keyof typeof MISSION_STATUS, + todayIndex: number, +) => { + const currentDay = WEEK_DAYS_KOR[todayIndex]; + const rawSubtitle = MISSION_STATUS[status].subtitle; + const text = + typeof rawSubtitle === "function" + ? `${rawSubtitle(currentDay)}요일` + : rawSubtitle; + return text; +}; diff --git a/src/utils/uploadImage.util.ts b/src/utils/uploadImage.util.ts new file mode 100644 index 0000000..705b486 --- /dev/null +++ b/src/utils/uploadImage.util.ts @@ -0,0 +1,35 @@ +export interface UploadImageOptions { + maxSizeMB?: number; + allowedTypes?: string[]; +} + +export interface UploadImageResult { + file: File; + previewUrl: string; +} + +export const uploadImage = ( + file: File, + options: UploadImageOptions = {}, +): UploadImageResult => { + const { + maxSizeMB = 5, + allowedTypes = ["image/jpeg", "image/png", "image/webp"], + } = options; + + // 타입 검사 + if (!allowedTypes.includes(file.type)) { + throw new Error("지원하지 않는 이미지 형식입니다."); + } + + // 용량 검사 + const maxSize = maxSizeMB * 1024 * 1024; + if (file.size > maxSize) { + throw new Error(`이미지 용량은 ${maxSizeMB}MB 이하만 가능합니다.`); + } + + return { + file, + previewUrl: URL.createObjectURL(file), + }; +}; diff --git a/yarn.lock b/yarn.lock index 4a6fba9..552b8aa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -847,7 +847,7 @@ "@babel/plugin-transform-modules-commonjs" "^7.27.1" "@babel/plugin-transform-typescript" "^7.28.5" -"@babel/runtime@^7.14.8", "@babel/runtime@^7.19.0", "@babel/runtime@^7.21.0", "@babel/runtime@^7.23.8", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2", "@babel/runtime@^7.7.2": +"@babel/runtime@^7.23.8", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2", "@babel/runtime@^7.7.2": version "7.28.4" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.28.4.tgz#a70226016fabe25c5783b2f22d3e1c9bc5ca3326" integrity sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ== @@ -1507,63 +1507,6 @@ postcss "^8.4.41" tailwindcss "4.1.18" -"@toss/assert@^1.2.2": - version "1.2.2" - resolved "https://registry.yarnpkg.com/@toss/assert/-/assert-1.2.2.tgz#78a96586e134edd38947553b20a18bc24a692c52" - integrity sha512-qK2G1LzI2ghY0aUOsz9mFiy2v/eNlMHG5qXdSogfGFLxHqFZ6KQWJQpnb9eN+dyHYIudBVWPZhbkljqnT8R3/g== - dependencies: - "@toss/utils" "^1.6.1" - -"@toss/react@^1.8.1": - version "1.8.1" - resolved "https://registry.yarnpkg.com/@toss/react/-/react-1.8.1.tgz#d69d9e5dfed21c8f9fa791473293239e31ac5dda" - integrity sha512-jH3oo/7yctexuutj/YgQrddaK1bU2s5659dkJIXOe23bEjkY+lbhvEz2FLEhRjSo6k6ktPagpxO4AcdhCi5k5A== - dependencies: - "@babel/runtime" "^7.14.8" - "@toss/storage" "^1.4.1" - "@toss/utils" "^1.6.1" - classnames "^2.3.1" - lodash.debounce "^4.0.8" - lodash.throttle "^4.1.1" - -"@toss/storage@^1.4.1": - version "1.4.1" - resolved "https://registry.yarnpkg.com/@toss/storage/-/storage-1.4.1.tgz#c7f03946244a35631dbd4f40a7c513c314750f86" - integrity sha512-jvnBXAQ/Fqqdt+gqYKeHYk7SzR2LX/FC50JIoVI0RldG1mDh1tebOqD7XkrZ89q77t/RwTuh60+8fjZDgend/g== - dependencies: - "@babel/runtime" "^7.19.0" - -"@toss/use-funnel@^1.4.2": - version "1.4.2" - resolved "https://registry.yarnpkg.com/@toss/use-funnel/-/use-funnel-1.4.2.tgz#08e7d681e4f200fb83159100c037fb195dd43e8e" - integrity sha512-qgfYhdoJh07D4+kyRgRE3Du5wEdecFOR9Ht3MjgFMYAJyGplNbD++hpD/FcXrGT5oa14KG0bB5bpp60KLmPkFw== - dependencies: - "@toss/assert" "^1.2.2" - "@toss/react" "^1.8.1" - "@toss/storage" "^1.4.1" - "@toss/use-query-param" "^1.3.1" - "@toss/utils" "^1.6.1" - fast-deep-equal "^3.1.3" - -"@toss/use-query-param@^1.3.1": - version "1.3.1" - resolved "https://registry.yarnpkg.com/@toss/use-query-param/-/use-query-param-1.3.1.tgz#a9bc67692972f300b8d011e00f0af17f6fa3d7d0" - integrity sha512-GRA+6st46/88KgmP9PGx8mV9sxxkewwLMzBl25TpXPjnqHz+tiZdybVZMQ5UHj0Kzf7bZnHGF3kd5oko492vxA== - -"@toss/utility-types@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@toss/utility-types/-/utility-types-1.2.1.tgz#3c67bea23b7aaffd4b4e7c2a518773ae22a496f6" - integrity sha512-1y8s1bvmuhuMX/d6qR9mmvcgFZIKYIQqJbAIshlGArXkjk/ec67gXc5uByEV1Y7in9ZhrGNRmjD8DTH0988vpQ== - -"@toss/utils@^1.6.1": - version "1.6.1" - resolved "https://registry.yarnpkg.com/@toss/utils/-/utils-1.6.1.tgz#e1226b1274b3d7e04b5b648ef11accdc013568c3" - integrity sha512-x6m8jLKWtAmCbxTLXbgTzJ5wZyRSUQPLpR/oLJP1ZK9ytXcRf03oA46W/+78kErUkEw/yQz2L+t2xFDHSeZ6IQ== - dependencies: - "@babel/runtime" "^7.14.8" - "@toss/utility-types" "^1.2.1" - date-fns "^2.25.0" - "@trivago/prettier-plugin-sort-imports@^6.0.0": version "6.0.1" resolved "https://registry.yarnpkg.com/@trivago/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-6.0.1.tgz#b71c020c4069c0b7a75953227ad6c803cea3f568" @@ -2345,11 +2288,6 @@ chrome-trace-event@^1.0.2: resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz#05bffd7ff928465093314708c93bdfa9bd1f0f5b" integrity sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ== -classnames@^2.3.1: - version "2.5.1" - resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.5.1.tgz#ba774c614be0f016da105c858e7159eae8e7687b" - integrity sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow== - cli-cursor@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-5.0.0.tgz#24a4831ecf5a6b01ddeb32fb71a4b2088b0dce38" @@ -2521,13 +2459,6 @@ data-view-byte-offset@^1.0.1: es-errors "^1.3.0" is-data-view "^1.0.1" -date-fns@^2.25.0: - version "2.30.0" - resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.30.0.tgz#f367e644839ff57894ec6ac480de40cae4b0f4d0" - integrity sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw== - dependencies: - "@babel/runtime" "^7.21.0" - debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" @@ -3875,11 +3806,6 @@ lodash.merge@^4.6.2: resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== -lodash.throttle@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" - integrity sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ== - log-update@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/log-update/-/log-update-6.1.0.tgz#1a04ff38166f94647ae1af562f4bd6a15b1b7cd4"