diff --git a/.eslintignore b/.eslintignore index 8061a94..e60c658 100755 --- a/.eslintignore +++ b/.eslintignore @@ -6,4 +6,5 @@ node_modules next-env.d.ts next.config.ts tailwind.config.ts -yarn.lock \ No newline at end of file +yarn.lock +next.config.mjs \ No newline at end of file diff --git a/next.config.mjs b/next.config.mjs index 558d35f..2f34ebc 100755 --- a/next.config.mjs +++ b/next.config.mjs @@ -13,7 +13,7 @@ const nextConfig = { return config; }, images: { - domains: ["images.unsplash.com", "plus.unsplash.com"], + domains: ["images.unsplash.com", "plus.unsplash.com", "www.50plus.or.kr"], }, }; diff --git a/package.json b/package.json index 9f18c4c..562b906 100755 --- a/package.json +++ b/package.json @@ -22,14 +22,18 @@ "@radix-ui/react-tooltip": "^1.1.2", "@tanstack/react-query": "^5.55.4", "axios": "^1.7.7", + "date-fns": "^4.1.0", "embla-carousel-react": "^8.3.0", "lucide-react": "^0.441.0", "moment": "^2.30.1", "moment-timezone": "^0.5.45", "next": "14.2.8", + "next-themes": "^0.3.0", "react": "^18", "react-dom": "^18", "react-icons": "^5.3.0", + "react-spinners": "^0.14.1", + "sonner": "^1.5.0", "tailwindcss-animate": "^1.0.7", "zustand": "^4.5.5" }, @@ -44,6 +48,7 @@ "@storybook/react": "^8.2.9", "@storybook/test": "^8.2.9", "@tanstack/react-query-devtools": "^5.55.4", + "@types/navermaps": "^3.7.6", "@types/node": "22.5.4", "@types/react": "18.3.5", "@types/react-dom": "^18", diff --git a/public/icons/calendar_filled.svg b/public/icons/calendar_filled.svg new file mode 100755 index 0000000..721990b --- /dev/null +++ b/public/icons/calendar_filled.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/icons/copy_link.svg b/public/icons/copy_link.svg new file mode 100644 index 0000000..89c01c0 --- /dev/null +++ b/public/icons/copy_link.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/public/icons/heart.svg b/public/icons/heart.svg new file mode 100755 index 0000000..11a9ed9 --- /dev/null +++ b/public/icons/heart.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/heart_default.svg b/public/icons/heart_default.svg new file mode 100755 index 0000000..12170ea --- /dev/null +++ b/public/icons/heart_default.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/home_alt.svg b/public/icons/home_alt.svg new file mode 100644 index 0000000..ee2aa38 --- /dev/null +++ b/public/icons/home_alt.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/icons/hosted_by.svg b/public/icons/hosted_by.svg new file mode 100755 index 0000000..3d307f1 --- /dev/null +++ b/public/icons/hosted_by.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/icons/kakao.svg b/public/icons/kakao.svg new file mode 100644 index 0000000..7beea94 --- /dev/null +++ b/public/icons/kakao.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/icons/kakao_logo.svg b/public/icons/kakao_logo.svg new file mode 100755 index 0000000..314ad7b --- /dev/null +++ b/public/icons/kakao_logo.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/public/icons/like.svg b/public/icons/like.svg new file mode 100755 index 0000000..12170ea --- /dev/null +++ b/public/icons/like.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/like_filled.svg b/public/icons/like_filled.svg new file mode 100755 index 0000000..b7c6d79 --- /dev/null +++ b/public/icons/like_filled.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/location.svg b/public/icons/location.svg new file mode 100755 index 0000000..cdede15 --- /dev/null +++ b/public/icons/location.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/map_pin.svg b/public/icons/map_pin.svg new file mode 100755 index 0000000..0525d82 --- /dev/null +++ b/public/icons/map_pin.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/person.svg b/public/icons/person.svg new file mode 100755 index 0000000..2a76606 --- /dev/null +++ b/public/icons/person.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/public/icons/price.svg b/public/icons/price.svg new file mode 100755 index 0000000..9466a70 --- /dev/null +++ b/public/icons/price.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/public/icons/share.svg b/public/icons/share.svg new file mode 100755 index 0000000..078e7b3 --- /dev/null +++ b/public/icons/share.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/public/icons/time.svg b/public/icons/time.svg new file mode 100755 index 0000000..149180d --- /dev/null +++ b/public/icons/time.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/user_circle.svg b/public/icons/user_circle.svg new file mode 100755 index 0000000..7d3a73c --- /dev/null +++ b/public/icons/user_circle.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/user_default.svg b/public/icons/user_default.svg new file mode 100755 index 0000000..fda8380 --- /dev/null +++ b/public/icons/user_default.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/images/class_1.png b/public/images/class_1.png new file mode 100755 index 0000000..47fe1bb Binary files /dev/null and b/public/images/class_1.png differ diff --git a/public/images/class_2.png b/public/images/class_2.png new file mode 100755 index 0000000..228b7b0 Binary files /dev/null and b/public/images/class_2.png differ diff --git a/public/images/class_3.png b/public/images/class_3.png new file mode 100755 index 0000000..28c9407 Binary files /dev/null and b/public/images/class_3.png differ diff --git a/public/images/current_position.png b/public/images/current_position.png new file mode 100755 index 0000000..b3c383c Binary files /dev/null and b/public/images/current_position.png differ diff --git a/public/images/free_ticket.png b/public/images/free_ticket.png deleted file mode 100755 index 7b033dd..0000000 Binary files a/public/images/free_ticket.png and /dev/null differ diff --git a/public/images/heart.png b/public/images/heart.png new file mode 100755 index 0000000..d72069d Binary files /dev/null and b/public/images/heart.png differ diff --git a/public/images/heart_filled.png b/public/images/heart_filled.png new file mode 100755 index 0000000..866dad0 Binary files /dev/null and b/public/images/heart_filled.png differ diff --git a/public/images/marker_icon.png b/public/images/marker_icon.png new file mode 100755 index 0000000..3fef606 Binary files /dev/null and b/public/images/marker_icon.png differ diff --git a/public/images/one_day.png b/public/images/one_day.png deleted file mode 100755 index 28f1b55..0000000 Binary files a/public/images/one_day.png and /dev/null differ diff --git a/public/images/senior.png b/public/images/senior.png new file mode 100755 index 0000000..2bd7f2e Binary files /dev/null and b/public/images/senior.png differ diff --git a/public/images/sijak_happy.png b/public/images/sijak_happy.png new file mode 100755 index 0000000..f0b8f58 Binary files /dev/null and b/public/images/sijak_happy.png differ diff --git a/public/images/sijak_logo.png b/public/images/sijak_logo.png new file mode 100755 index 0000000..a1b2a74 Binary files /dev/null and b/public/images/sijak_logo.png differ diff --git a/public/images/sijak_position.png b/public/images/sijak_position.png new file mode 100755 index 0000000..521b9a2 Binary files /dev/null and b/public/images/sijak_position.png differ diff --git a/public/images/sports_plan.png b/public/images/sports_plan.png deleted file mode 100755 index 92a313c..0000000 Binary files a/public/images/sports_plan.png and /dev/null differ diff --git a/src/app/class/[id]/page.tsx b/src/app/class/[id]/page.tsx index d7f66f5..b08cfe2 100755 --- a/src/app/class/[id]/page.tsx +++ b/src/app/class/[id]/page.tsx @@ -1,11 +1,5 @@ "use client"; -import { - ArrowLeftIcon, - HeartIcon, - PersonIcon, - Share1Icon, -} from "@radix-ui/react-icons"; import { Button, Dialog, @@ -14,15 +8,16 @@ import { DialogPortal, DialogTitle, DialogTrigger, + Divider, + Skeleton, } from "@/shared/ui"; -import { CiCalendar, CiFaceSmile } from "react-icons/ci"; import { useCallback, useEffect, useState } from "react"; import { Class } from "@/entities/class/model/class"; import { DialogDescription } from "@radix-ui/react-dialog"; import Image from "next/image"; -import Link from "next/link"; -import { MdOutlinePlace } from "react-icons/md"; +import MiniMap from "@/features/map/ui/MiniMap/MiniMap"; +import { toast } from "sonner"; import useClassInfo from "@/entities/class/api/useClassInfo"; import { useParams } from "next/navigation"; @@ -49,142 +44,443 @@ const ClassInfoPage = () => { } }, [handleClassDataList, isSuccess]); - if (isLoading) { - return
loading...
; - } + // TODO: 로직 유틸 함수로 옮기기 + const handleCopyClipBoard = async (text: string) => { + try { + await navigator.clipboard.writeText(text); + toast("링크를 복사했어요."); + } catch (err) { + console.log(err); + } + }; + + const shareLinkToKakao = () => { + // TODO: 카카오 링크 공유하기 + }; + const shareLinkToURL = () => { + if (data) { + handleCopyClipBoard(data.link); + } + }; return ( - classInfo && ( -
-
-
- -
- -
뒤로가기
-
- -
-
-
-
- -
공유
+
+
+
+ {classInfo && ( +
+ 문화
-
-
-
-
+ )} + {classInfo && ( +
+ 7일 남음 +
+ )} + {/* TODO: 몇 일 남았는지 계산하는 로직 필요 */} + {isLoading && } + {classInfo && ( {classInfo.name} + )} +
+
+ map_pin +
+ {/* TODO: 거리 계산 */} + {isLoading && } + {classInfo && ( +
+ 내 위치에서 1.1km ∙ 대중교통 약 10분 이내 +
+ )}
-
-
-
안내사항
-
-
+
+ {/* 정보 div */} + {/* TODO: 컴포넌트화 */} +
+
+
+ {isLoading && } + {classInfo && ( +
{classInfo.name}
-
- -
+ )} +
+ {/* TODO: 좋아요 API */} + + {/* TODO: 공유하기 */} + + +
+ share +
+
+ + + 링크 공유 + 링크 공유용 모달 + + +
+ {/* TODO: 컴포넌트 화 */} +
+ kakao logo +
+ 카카오톡 공유하기 +
+
+
+ copy_link +
+ 링크 복사하기 +
+
+
+
+
+
-
-
-
- +
+
+
+
+
+ person +
+ 인원 +
-
인원
+ {isLoading && } + {classInfo && ( +
+ 정원 {classInfo.capacity}명 +
+ )}
-
{classInfo.capacity}
-
-
-
-
- +
+
+ hosted_by +
+ 주최 +
-
주최
+ {isLoading && } + {classInfo && ( +
{classInfo.hosted_by}
+ )}
-
{classInfo.hosted_by}
-
-
-
-
- +
+ {/* TODO: type 수정 */} +
+ user_circle +
+ 구분 +
-
장소
+ {isLoading && } + {classInfo && ( +
+ {classInfo.target} +
+ )}
-
{classInfo.location}
-
-
-
-
- + {/* TODO: type 수정 */} +
+
+ calendar +
+ 기간 +
-
시간
+ {isLoading && } + {classInfo && ( +
{classInfo.time}
+ )}
- {/* FIXME */} -
{classInfo.time}
-
-
-
-
- +
+
+ time +
+ 시간 +
-
일정
+ {isLoading && } + {classInfo && ( +
+ {classInfo.day_of_week}요일 {classInfo.time} +
+ )}
- {/* FIXME */} -
매주 {classInfo.day_of_week}요일
-
-
-
지도
-
-
{classInfo.location_detail}
-
{classInfo.location}
- +
+
+ price +
+ 가격 +
+
+ {isLoading && } + {classInfo && ( +
+ {classInfo.price.toLocaleString("ko-KR")}원 +
+ )} +
+
+
+ location +
+ 장소 +
+
+ {isLoading && } + {classInfo && ( +
{classInfo.location_detail}
+ )}
+ {isLoading && } + {classInfo && ( +
+ +
+ )}
-
-
-
클래스 정보
-
{classInfo.description}
+
+ {/* TODO */} +
+
+
+ 클래스 내용
-
-
준비물
-
준비물 소개
+
+ {/* TODO: 컴포넌트화 */} +
+
+ 수강자격 +
+ {isLoading && } + {classInfo && ( +
{classInfo.target}
+ )} +
+ +
+
+ 교육내용 +
+ {isLoading && } + {classInfo && ( +
{classInfo.description}
+ )} +
+ +
+
+ 자격증 관련사항 +
+ {isLoading && } + {classInfo && ( +
{classInfo.description}
+ )} +
+ +
+
+ 교재명 +
+ {isLoading && } + {classInfo && ( +
{classInfo.description}
+ )} +
+ +
+
+ 교재비 +
+ {isLoading && } + {classInfo && ( +
+ {`${classInfo.price.toLocaleString("ko-KR")}원`} +
+ )} +
+ +
+
+ 재료비 +
+ {isLoading && } + {classInfo && ( +
+ {`${classInfo.price.toLocaleString("ko-KR")}원`} +
+ )} +
+ +
+
+ 준비물 +
+ {isLoading && } + {classInfo && ( +
{classInfo.description}
+ )} +
+
-
-
- -
+
+
+ 강사 이력
-
-
가격
-
{classInfo.price}원
+ {/* TODO: 강사 이력 정보 */} + {isLoading && } + {classInfo && ( +
+
양옥연
+
+ + • POP디자인기사, 아동예쁜글씨지도자, 초크POP지도자, + 북아트지도자 자격취득 + + + • 사)한국문화예술가협회 회장 글작(글씨작가그룹) 대표 + + • 도서출판 아름답게사는 우리가 꽃이다 대표 + • 인스타: @johaegrim / 유튜브: 조해그림글씨 +
+
+ )} +
+
+
교육 계획
+ {/* {isLoading && } */} + {classInfo &&
} +
+
+ {/* TODO: 컴포넌트 화, 하단 바 */} +
+
+ +
+ {isLoading && } + {classInfo && ( +
+ {classInfo.price.toLocaleString("ko-KR")}원
+ )} + {isLoading && ( + + )} + {classInfo && (
{classInfo.link && tempApplyStatus ? ( ) : ( -
- +
+
@@ -193,11 +489,24 @@ const ClassInfoPage = () => { 마이페이지 설명 -
-
-
- 신청 페이지를 불러오지 못했습니다. +
+
+
+ 신청 페이지를
+
+ 불러오지 못했습니다. +
+
+
+ {/* TODO: 문구 확인 */} + 데이터가 만료되거나 이용 완료되어 불러오지 못했습니다. +
+
+ {/* TODO: router.push(home) */} +
@@ -205,9 +514,9 @@ const ClassInfoPage = () => {
)}
-
+ )}
- ) +
); }; diff --git a/src/app/entire/page.tsx b/src/app/entire/page.tsx new file mode 100755 index 0000000..8f1b835 --- /dev/null +++ b/src/app/entire/page.tsx @@ -0,0 +1,58 @@ +"use client"; + +import { useCallback, useEffect, useState } from "react"; + +import { Class } from "@/entities/class/model/class"; +import { ClassList } from "@/entities/class/ui"; +import SkeletonCard from "@/entities/class/ui/Class/SkeletonCard/SkeletonCard"; +import useEntireClass from "@/entities/class/api/useEntireClass"; + +const EntirePage = () => { + const [classListData, setClassListData] = useState(); + + // TODO: 전체 클래스 가져오는 API로 수정 필요 + const { data, isLoading, isSuccess } = useEntireClass(); + + const handleEntireClassDataList = useCallback(() => { + if (data) { + const entireClassData = data.data.data; + // FIXME: 수정 + setClassListData(entireClassData); + } + }, [data]); + + useEffect(() => { + if (isSuccess) { + handleEntireClassDataList(); + } + }, [handleEntireClassDataList, isSuccess]); + + return ( +
+
+
+
전체 클래스
+
한번에 보기
+
+
+
+
+ {/* FIXME: 수정 필요 */} + {isLoading ? ( +
+ + + +
+ ) : classListData && isSuccess ? ( + + ) : ( +
클래스가 존재하지 않습니다
+ )} +
+
+
+ ); +}; + +export default EntirePage; diff --git a/src/app/favicon.ico b/src/app/favicon.ico index 718d6fe..e28cfe3 100755 Binary files a/src/app/favicon.ico and b/src/app/favicon.ico differ diff --git a/src/app/fonts/PretendardVariable.woff2 b/src/app/fonts/PretendardVariable.woff2 new file mode 100755 index 0000000..49c54b5 Binary files /dev/null and b/src/app/fonts/PretendardVariable.woff2 differ diff --git a/src/app/globals.css b/src/app/globals.css index 83c7efc..7d94e38 100755 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -40,6 +40,7 @@ html { body { margin: 0; line-height: inherit; + width: 100vw; height: 100vh; } hr { diff --git a/src/app/layout.tsx b/src/app/layout.tsx index a111278..74b7c27 100755 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,26 +1,22 @@ import "./globals.css"; -import { Footer, Header } from "@/shared/ui"; +import { Footer, Header, Toaster } from "@/shared/ui"; import Initializer from "@/mocks/Initializer"; import type { Metadata } from "next"; import Providers from "@/features/provider/Provider"; +import Script from "next/script"; import localFont from "next/font/local"; -const geistSans = localFont({ - src: "./fonts/GeistVF.woff", - variable: "--font-geist-sans", - weight: "100 900", -}); -const geistMono = localFont({ - src: "./fonts/GeistMonoVF.woff", - variable: "--font-geist-mono", +const pretendard = localFont({ + src: "./fonts/PretendardVariable.woff2", + variable: "--font-pretendard", weight: "100 900", }); export const metadata: Metadata = { - title: "Create Next App", - description: "Generated by create next app", + title: "시작", + description: "시니어를 위한 문화생활 플랫폼", }; export default function RootLayout({ @@ -30,11 +26,18 @@ export default function RootLayout({ }>) { return ( + +