diff --git a/app/(menu)/game/[league]/schedule/page.tsx b/app/(menu)/game/[league]/schedule/page.tsx index 974c7c3..2ed3bec 100644 --- a/app/(menu)/game/[league]/schedule/page.tsx +++ b/app/(menu)/game/[league]/schedule/page.tsx @@ -1,3 +1,69 @@ -export default function page() { - return
page입니다
; +'use client' + +import ScheduleCalendar from "@/components/game/schedule/schedule-calendar"; +import ScheduleCarousel from "@/components/game/schedule/schedule-carousel"; +import { useEffect, useState } from "react"; + +export default function Schedule() { + const date = new Date() + const year = date.getFullYear() //년 + const month = date.getMonth() + 1 //월 + const today = date.getDate() //일 + + const [currentDate, setCurrentDate] = useState({ year: year, month: month, today: today }) // 현재 날짜 (년,월) + const [schedules, setSchedules] = useState([]) // 스케줄 API 데이터 + + const stringDate = `${currentDate.year}${String(currentDate.month).padStart(2, '0')}` // 현재 선택된 날짜 스트링(API Params) e.g. '202409' + + useEffect(() => { + getMonthSchedules(stringDate); + }, [stringDate]) + + const getMonthSchedules = async (params: string) => { + try { + const res = await fetch( + `${process.env.NEXT_PUBLIC_API_KEY}/game/monthschedule?yearMonth=${params}`, + { + next: { revalidate: 3600 }, // 1시간마다 캐싱 + } + ); + + if (!res.ok) { + throw new Error('Network response was not ok'); + } + + const data = await res.json(); + setSchedules(data.data.list); + + } catch (error) { + console.error('API 요청 에러:', error); + } + } + + const handleCurrentMonth = (month: string) => { + if (month === 'next') { + setCurrentDate(prev => { + if (prev.month === 12) { + return { year: prev.year + 1, month: 1 } + } + return { ...prev, month: prev.month + 1 } + }) + } + + if (month === 'prev') { + setCurrentDate(prev => { + if (prev.month === 1) { + return { year: prev.year - 1, month: 12 } + } + return { ...prev, month: prev.month - 1 } + }) + } + } + + return ( +
+ + +
+ ) } diff --git a/app/(menu)/layout.tsx b/app/(menu)/layout.tsx index 71f65d5..844e532 100644 --- a/app/(menu)/layout.tsx +++ b/app/(menu)/layout.tsx @@ -1,4 +1,5 @@ -import BreadCrumb from "@/components/common/breadcrumb/Breadcrumb"; +import BreadCrumb from "@/components/common/breadcrumb/breadcrumb" +import SubBannerMenu from "@/components/common/sub-menu-banner"; import CategoryMenu from "@/components/common/CategoryMenu"; import type { Metadata } from "next"; diff --git a/components/common/breadcrumb/BreadcrumbSegment.tsx b/components/common/breadcrumb/breadcrumb-segment.tsx similarity index 100% rename from components/common/breadcrumb/BreadcrumbSegment.tsx rename to components/common/breadcrumb/breadcrumb-segment.tsx diff --git a/components/common/breadcrumb/Breadcrumb.tsx b/components/common/breadcrumb/breadcrumb.tsx similarity index 95% rename from components/common/breadcrumb/Breadcrumb.tsx rename to components/common/breadcrumb/breadcrumb.tsx index d9c2cfe..519e1b6 100644 --- a/components/common/breadcrumb/Breadcrumb.tsx +++ b/components/common/breadcrumb/breadcrumb.tsx @@ -2,7 +2,7 @@ import { Breadcrumb, BreadcrumbList } from "@/components/ui"; import { usePathname } from "next/navigation"; -import BreadcrumbSegment from "./BreadcrumbSegment"; +import BreadcrumbSegment from "./breadcrumb-segment"; const BreadCrumb = () => { const pathName: string = usePathname(); diff --git a/components/common/sub-menu-banner.tsx b/components/common/sub-menu-banner.tsx new file mode 100644 index 0000000..84b7903 --- /dev/null +++ b/components/common/sub-menu-banner.tsx @@ -0,0 +1,84 @@ +"use client"; +import { usePathname, useRouter } from "next/navigation"; +import React, { useEffect, useState } from "react"; + +import submenuBg from "@/assets/images/submenu_bg.png"; +import Image from "next/image"; +import { SubMenuInfo } from "@/constants/header-menu"; + +interface SubMenu { + id: string; + title: string; + descript: string; +} + +const SubBannerMenu = () => { + const router = useRouter(); + const pathname: string = usePathname(); + const currentPath: string = pathname.split("/").pop() || ""; // 현재 메뉴 이름 + const [subMenuList, setSubMenuList] = useState([]); // 해당 메뉴의 하위 메뉴 리스트 + const [title, setTitle] = useState(""); + const [descript, setDescript] = useState(""); + + // 현재 진입한 메뉴와 하위메뉴 정보들을 상태로 관리 + useEffect(() => { + const findMenuInfo = () => { + for (const menu in SubMenuInfo) { + const subMenuAll = SubMenuInfo[ + menu as keyof typeof SubMenuInfo + ] as SubMenu[]; + const matchedMenu = subMenuAll.find((item) => item.id === currentPath); + + if (matchedMenu) { + setSubMenuList(subMenuAll); + setTitle(matchedMenu.title); + setDescript(matchedMenu.descript); + break; + } + } + }; + + findMenuInfo(); + }, [currentPath]); + + return ( +
+
+
+ Submenu background +
+

{title}

+

{descript}

+
+
+
+
+
+ {subMenuList.map((tab) => ( + + ))} +
+
+
+
+
+ ); +}; + +export default SubBannerMenu; diff --git a/components/game/schedule/schedule-calendar.tsx b/components/game/schedule/schedule-calendar.tsx new file mode 100644 index 0000000..83e8d44 --- /dev/null +++ b/components/game/schedule/schedule-calendar.tsx @@ -0,0 +1,101 @@ +'use client' + +import { ChevronLeft, ChevronRight } from 'lucide-react' +import Image from 'next/image'; + +const ScheduleCalendar = ({ date, schedules, monthHandler }: ScheduleCalendarProps) => { + const daysInMonth = new Date(date.year, date.month, 0).getDate() // 현재 선택된 月의 마지막 날짜 + const firstDayOfMonth = new Date(date.year, date.month - 1, 1).getDay() // 현재 선택된 月의 시작 요일 + + const days = Array.from({ length: daysInMonth }, (_, i) => i + 1) + const weekdays = ['일', '월', '화', '수', '목', '금', '토'] + + return ( +
+
+ +
+ {date.year}년 + {date.month}월 +
+ +
+ +
+ {weekdays.map((day) => ( +
+ {day} +
+ ))} + + {Array(firstDayOfMonth).fill(null).map((_, index) => ( +
+ ))} + + {days.map((day) => { + const keyDate = `${date.year}${String(date.month).padStart(2, '0')}` + String(day).padStart(2, '0'); + const todaySchedule = schedules.find((schedule) => schedule.displayDate === keyDate); + + return ( +
+
+ + {day} + + {todaySchedule?.outcome === '승' ? +
+ : todaySchedule?.outcome === '패' && +
+ } +
+
+ + { + todaySchedule && ( +
+
+ {todaySchedule.visit} + vs + {todaySchedule.home} +
+

{todaySchedule.gtime}

+ {todaySchedule.stadium === '수원' ? +

+ {todaySchedule.stadium} +

+ :

{todaySchedule.stadium}

+ } +
+ ) + } +
+ ) + })} +
+
+ ) +} + +export default ScheduleCalendar; \ No newline at end of file diff --git a/components/game/schedule/schedule-carousel.tsx b/components/game/schedule/schedule-carousel.tsx new file mode 100644 index 0000000..cf966eb --- /dev/null +++ b/components/game/schedule/schedule-carousel.tsx @@ -0,0 +1,67 @@ +'use client' + +import { useEffect, useState } from 'react' +import { Card, CardContent } from "@/components/ui/card" +import { + Carousel, + CarouselApi, + CarouselContent, + CarouselItem, + CarouselNext, + CarouselPrevious, +} from "@/components/ui/carousel" + +const ScheduleCarousel = ({ date }: { date: CalendarDate }) => { + const [api, setApi] = useState() + const [center, setCenter] = useState(0) + + useEffect(() => { + if (!api) { + return + } + setCenter(api.selectedScrollSnap() + 2) + + const onSelect = () => { + setCenter(api.selectedScrollSnap() + 2) + } + + // 이벤트 등록 + api.on("select", onSelect) + + // 언마운트 시 이벤트 제거 (cleanup) + return () => { + api.off("select", onSelect) + } + }, [api]) + + return ( +
+ + + {Array.from({ length: 10 }).map((_, index) => ( + +
+ + + {index + 1} + + +
+
+ ))} +
+ + +
+ +
+ ) +} + +export default ScheduleCarousel diff --git a/components/game/schedule/type.d.ts b/components/game/schedule/type.d.ts new file mode 100644 index 0000000..3e41c85 --- /dev/null +++ b/components/game/schedule/type.d.ts @@ -0,0 +1,33 @@ +type GameSchedule = { + broadcast: string + displayDate: string + gameDate: number + gmkey: string + gtime: string + home: string + homeKey: string + homeLogo: string + homeScore: number + matchTeamCode: string + matchTeamName: string + outcome: string + stadium: string + stadiumKey: string + status: string + visit: string + visitKey: string + visitLogo: string + visitScore: number +} + +type CalendarDate = { + year: number + month: number + today?: number +} + +type ScheduleCalendarProps = { + date: CalendarDate + schedules: GameSchedule[] + monthHandler: (increment: string) => void +} \ No newline at end of file diff --git a/components/ui/carousel.tsx b/components/ui/carousel.tsx new file mode 100644 index 0000000..ec505d0 --- /dev/null +++ b/components/ui/carousel.tsx @@ -0,0 +1,262 @@ +"use client" + +import * as React from "react" +import useEmblaCarousel, { + type UseEmblaCarouselType, +} from "embla-carousel-react" +import { ArrowLeft, ArrowRight } from "lucide-react" + +import { cn } from "@/lib/utils" +import { Button } from "@/components/ui/button" + +type CarouselApi = UseEmblaCarouselType[1] +type UseCarouselParameters = Parameters +type CarouselOptions = UseCarouselParameters[0] +type CarouselPlugin = UseCarouselParameters[1] + +type CarouselProps = { + opts?: CarouselOptions + plugins?: CarouselPlugin + orientation?: "horizontal" | "vertical" + setApi?: (api: CarouselApi) => void +} + +type CarouselContextProps = { + carouselRef: ReturnType[0] + api: ReturnType[1] + scrollPrev: () => void + scrollNext: () => void + canScrollPrev: boolean + canScrollNext: boolean +} & CarouselProps + +const CarouselContext = React.createContext(null) + +function useCarousel() { + const context = React.useContext(CarouselContext) + + if (!context) { + throw new Error("useCarousel must be used within a ") + } + + return context +} + +const Carousel = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes & CarouselProps +>( + ( + { + orientation = "horizontal", + opts, + setApi, + plugins, + className, + children, + ...props + }, + ref + ) => { + const [carouselRef, api] = useEmblaCarousel( + { + ...opts, + axis: orientation === "horizontal" ? "x" : "y", + }, + plugins + ) + const [canScrollPrev, setCanScrollPrev] = React.useState(false) + const [canScrollNext, setCanScrollNext] = React.useState(false) + + const onSelect = React.useCallback((api: CarouselApi) => { + if (!api) { + return + } + + setCanScrollPrev(api.canScrollPrev()) + setCanScrollNext(api.canScrollNext()) + }, []) + + const scrollPrev = React.useCallback(() => { + api?.scrollPrev() + }, [api]) + + const scrollNext = React.useCallback(() => { + api?.scrollNext() + }, [api]) + + const handleKeyDown = React.useCallback( + (event: React.KeyboardEvent) => { + if (event.key === "ArrowLeft") { + event.preventDefault() + scrollPrev() + } else if (event.key === "ArrowRight") { + event.preventDefault() + scrollNext() + } + }, + [scrollPrev, scrollNext] + ) + + React.useEffect(() => { + if (!api || !setApi) { + return + } + + setApi(api) + }, [api, setApi]) + + React.useEffect(() => { + if (!api) { + return + } + + onSelect(api) + api.on("reInit", onSelect) + api.on("select", onSelect) + + return () => { + api?.off("select", onSelect) + } + }, [api, onSelect]) + + return ( + +
+ {children} +
+
+ ) + } +) +Carousel.displayName = "Carousel" + +const CarouselContent = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => { + const { carouselRef, orientation } = useCarousel() + + return ( +
+
+
+ ) +}) +CarouselContent.displayName = "CarouselContent" + +const CarouselItem = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => { + const { orientation } = useCarousel() + + return ( +
+ ) +}) +CarouselItem.displayName = "CarouselItem" + +const CarouselPrevious = React.forwardRef< + HTMLButtonElement, + React.ComponentProps +>(({ className, variant = "outline", size = "icon", ...props }, ref) => { + const { orientation, scrollPrev, canScrollPrev } = useCarousel() + + return ( + + ) +}) +CarouselPrevious.displayName = "CarouselPrevious" + +const CarouselNext = React.forwardRef< + HTMLButtonElement, + React.ComponentProps +>(({ className, variant = "outline", size = "icon", ...props }, ref) => { + const { orientation, scrollNext, canScrollNext } = useCarousel() + + return ( + + ) +}) +CarouselNext.displayName = "CarouselNext" + +export { + type CarouselApi, + Carousel, + CarouselContent, + CarouselItem, + CarouselPrevious, + CarouselNext, +} diff --git a/next.config.mjs b/next.config.mjs index 4678774..5a7e504 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -1,4 +1,15 @@ /** @type {import('next').NextConfig} */ -const nextConfig = {}; +const nextConfig = { + images: { + remotePatterns: [ + { + protocol: 'http', + hostname: '54.180.228.165', + port: '', + pathname: '/api/static/**', + }, + ], + }, +}; -export default nextConfig; +export default nextConfig; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 5ddb6fd..d559238 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,9 +10,10 @@ "dependencies": { "@radix-ui/react-dialog": "^1.1.2", "@radix-ui/react-select": "^2.1.2", - "@radix-ui/react-slot": "^1.1.0", + "@radix-ui/react-slot": "^1.1.1", "@radix-ui/react-tabs": "^1.1.1", "@tanstack/react-query": "^5.62.2", + "axios": "^1.7.9", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "date-fns": "^3.6.0", @@ -3366,6 +3367,24 @@ } } }, + "node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", + "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-compose-refs": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz", @@ -3432,6 +3451,24 @@ } } }, + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", + "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-direction": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz", @@ -3650,6 +3687,24 @@ } } }, + "node_modules/@radix-ui/react-primitive/node_modules/@radix-ui/react-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", + "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-roving-focus": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.0.tgz", @@ -3739,7 +3794,7 @@ } } }, - "node_modules/@radix-ui/react-slot": { + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-slot": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", @@ -3757,6 +3812,39 @@ } } }, + "node_modules/@radix-ui/react-slot": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.1.tgz", + "integrity": "sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slot/node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz", + "integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-tabs": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.1.tgz", @@ -6142,6 +6230,12 @@ "dev": true, "license": "MIT" }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, "node_modules/available-typed-arrays": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", @@ -6168,6 +6262,17 @@ "node": ">=4" } }, + "node_modules/axios": { + "version": "1.7.9", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz", + "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/axobject-query": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", @@ -7035,6 +7140,18 @@ "dev": true, "license": "MIT" }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/commander": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", @@ -7620,6 +7737,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/dequal": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", @@ -8919,6 +9045,26 @@ "dev": true, "license": "ISC" }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -8993,6 +9139,20 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/form-data": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fs-extra": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", @@ -10657,7 +10817,6 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -10667,7 +10826,6 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, "license": "MIT", "dependencies": { "mime-db": "1.52.0" @@ -11898,6 +12056,12 @@ "react-is": "^16.13.1" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, "node_modules/public-encrypt": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", diff --git a/package.json b/package.json index f874c97..06d70ad 100644 --- a/package.json +++ b/package.json @@ -13,9 +13,10 @@ "dependencies": { "@radix-ui/react-dialog": "^1.1.2", "@radix-ui/react-select": "^2.1.2", - "@radix-ui/react-slot": "^1.1.0", + "@radix-ui/react-slot": "^1.1.1", "@radix-ui/react-tabs": "^1.1.1", "@tanstack/react-query": "^5.62.2", + "axios": "^1.7.9", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "date-fns": "^3.6.0",