diff --git a/frontend-temp/src/components/index.js b/frontend-temp/src/components/index.js index fb45a36..553d53f 100644 --- a/frontend-temp/src/components/index.js +++ b/frontend-temp/src/components/index.js @@ -1,6 +1,9 @@ // 공통 컴포넌트 (디바이스 무관) export * from './common'; +// 스케줄 컴포넌트 +export * from './schedule'; + // PC 컴포넌트 export * as PC from './pc'; diff --git a/frontend-temp/src/components/schedule/MobileScheduleCard.jsx b/frontend-temp/src/components/schedule/MobileScheduleCard.jsx new file mode 100644 index 0000000..754d725 --- /dev/null +++ b/frontend-temp/src/components/schedule/MobileScheduleCard.jsx @@ -0,0 +1,101 @@ +import { Clock, Tag, Link2 } from 'lucide-react'; + +/** + * Mobile 일정 카드 컴포넌트 + * 홈, 스케줄 페이지 등에서 공통으로 사용 + */ +function MobileScheduleCard({ schedule, onClick, className = '' }) { + const scheduleDate = new Date(schedule.date); + const today = new Date(); + const currentYear = today.getFullYear(); + const currentMonth = today.getMonth(); + + const scheduleYear = scheduleDate.getFullYear(); + const scheduleMonth = scheduleDate.getMonth(); + const isCurrentYear = scheduleYear === currentYear; + const isCurrentMonth = isCurrentYear && scheduleMonth === currentMonth; + + // 멤버 처리 + const memberList = schedule.member_names + ? schedule.member_names.split(',').map((n) => n.trim()).filter(Boolean) + : schedule.members?.map((m) => m.name) || []; + + // 5명 이상이면 '프로미스나인'으로 표시 + const displayMembers = memberList.length >= 5 ? ['프로미스나인'] : memberList; + + const categoryName = schedule.category_name || schedule.category?.name; + const sourceName = schedule.source?.name; + + return ( +
+ {/* 날짜 영역 */} +
+ {!isCurrentYear && ( + + {scheduleYear}.{scheduleMonth + 1} + + )} + {isCurrentYear && !isCurrentMonth && ( + + {scheduleMonth + 1}월 + + )} + + {scheduleDate.getDate()} + + + {['일', '월', '화', '수', '목', '금', '토'][scheduleDate.getDay()]} + +
+ + {/* 세로 구분선 */} +
+ + {/* 내용 영역 */} +
+

+ {schedule.title} +

+ {/* 시간 + 카테고리 + 소스 */} +
+ {schedule.time && ( + + + {schedule.time.slice(0, 5)} + + )} + {categoryName && ( + + + {categoryName} + + )} + {sourceName && ( + + + {sourceName} + + )} +
+ {/* 멤버 */} + {displayMembers.length > 0 && ( +
+ {displayMembers.map((name, i) => ( + + {name} + + ))} +
+ )} +
+
+ ); +} + +export default MobileScheduleCard; diff --git a/frontend-temp/src/components/schedule/ScheduleCard.jsx b/frontend-temp/src/components/schedule/ScheduleCard.jsx new file mode 100644 index 0000000..82e1b70 --- /dev/null +++ b/frontend-temp/src/components/schedule/ScheduleCard.jsx @@ -0,0 +1,98 @@ +import { Clock, Tag, Link2 } from 'lucide-react'; + +/** + * PC 일정 카드 컴포넌트 + * 홈, 스케줄 페이지 등에서 공통으로 사용 + */ +function ScheduleCard({ schedule, onClick, className = '' }) { + const scheduleDate = new Date(schedule.date); + const today = new Date(); + const currentYear = today.getFullYear(); + const currentMonth = today.getMonth(); + + const scheduleYear = scheduleDate.getFullYear(); + const scheduleMonth = scheduleDate.getMonth(); + const isCurrentYear = scheduleYear === currentYear; + const isCurrentMonth = isCurrentYear && scheduleMonth === currentMonth; + + const day = scheduleDate.getDate(); + const weekdays = ['일', '월', '화', '수', '목', '금', '토']; + const weekday = weekdays[scheduleDate.getDay()]; + + // 멤버 처리 + const memberList = schedule.member_names + ? schedule.member_names.split(',').map((n) => n.trim()).filter(Boolean) + : schedule.members?.map((m) => m.name) || []; + + // 5명 이상이면 '프로미스나인'으로 표시 + const displayMembers = memberList.length >= 5 ? ['프로미스나인'] : memberList; + + const categoryColor = schedule.category_color || '#6366f1'; + const categoryName = schedule.category_name || schedule.category?.name; + const sourceName = schedule.source?.name; + + return ( +
+ {/* 날짜 영역 */} +
+ {!isCurrentYear && ( + + {scheduleYear}.{scheduleMonth + 1} + + )} + {isCurrentYear && !isCurrentMonth && ( + + {scheduleMonth + 1}월 + + )} + {day} + {weekday} +
+ + {/* 내용 영역 */} +
+

{schedule.title}

+
+ {schedule.time && ( + + + {schedule.time.slice(0, 5)} + + )} + {categoryName && ( + + + {categoryName} + + )} + {sourceName && ( + + + {sourceName} + + )} +
+ {displayMembers.length > 0 && ( +
+ {displayMembers.map((name, i) => ( + + {name} + + ))} +
+ )} +
+
+ ); +} + +export default ScheduleCard; diff --git a/frontend-temp/src/components/schedule/index.js b/frontend-temp/src/components/schedule/index.js new file mode 100644 index 0000000..94dd3e2 --- /dev/null +++ b/frontend-temp/src/components/schedule/index.js @@ -0,0 +1,2 @@ +export { default as ScheduleCard } from './ScheduleCard'; +export { default as MobileScheduleCard } from './MobileScheduleCard'; diff --git a/frontend-temp/src/pages/home/mobile/Home.jsx b/frontend-temp/src/pages/home/mobile/Home.jsx index 9c1dd03..46f87e8 100644 --- a/frontend-temp/src/pages/home/mobile/Home.jsx +++ b/frontend-temp/src/pages/home/mobile/Home.jsx @@ -1,7 +1,8 @@ import { motion } from 'framer-motion'; -import { ChevronRight, Clock, Tag } from 'lucide-react'; +import { ChevronRight } from 'lucide-react'; import { useNavigate } from 'react-router-dom'; import { useMembers, useAlbums, useUpcomingSchedules } from '@/hooks'; +import { MobileScheduleCard } from '@/components'; /** * Mobile 홈 페이지 @@ -157,101 +158,20 @@ function MobileHome() {
{schedules.length > 0 ? (
- {schedules.map((schedule, index) => { - const scheduleDate = new Date(schedule.date); - const today = new Date(); - const currentYear = today.getFullYear(); - const currentMonth = today.getMonth(); - - const scheduleYear = scheduleDate.getFullYear(); - const scheduleMonth = scheduleDate.getMonth(); - const isCurrentYear = scheduleYear === currentYear; - const isCurrentMonth = - isCurrentYear && scheduleMonth === currentMonth; - - // 멤버 처리 - const memberList = schedule.member_names - ? schedule.member_names - .split(',') - .map((n) => n.trim()) - .filter(Boolean) - : schedule.members?.map((m) => m.name) || []; - - return ( - ( + + navigate('/schedule')} - > - {/* 날짜 영역 */} -
- {!isCurrentYear && ( - - {scheduleYear}.{scheduleMonth + 1} - - )} - {isCurrentYear && !isCurrentMonth && ( - - {scheduleMonth + 1}월 - - )} - - {scheduleDate.getDate()} - - - { - ['일', '월', '화', '수', '목', '금', '토'][ - scheduleDate.getDay() - ] - } - -
- - {/* 세로 구분선 */} -
- - {/* 내용 영역 */} -
-

- {schedule.title} -

- {/* 시간 + 카테고리 */} -
- {schedule.time && ( - - - {schedule.time.slice(0, 5)} - - )} - {schedule.category_name && ( - - - {schedule.category_name} - {schedule.source?.name && ` · ${schedule.source.name}`} - - )} -
- {/* 멤버 */} - {memberList.length > 0 && ( -
- {memberList.map((name, i) => ( - - {name.trim()} - - ))} -
- )} -
- - ); - })} + /> + + ))}
) : (
diff --git a/frontend-temp/src/pages/home/pc/Home.jsx b/frontend-temp/src/pages/home/pc/Home.jsx index d3624bc..527e1e7 100644 --- a/frontend-temp/src/pages/home/pc/Home.jsx +++ b/frontend-temp/src/pages/home/pc/Home.jsx @@ -1,7 +1,8 @@ import { motion } from 'framer-motion'; import { Link } from 'react-router-dom'; -import { Calendar, ArrowRight, Clock, Tag, Music } from 'lucide-react'; +import { Calendar, ArrowRight, Music } from 'lucide-react'; import { useMembers, useAlbums, useUpcomingSchedules } from '@/hooks'; +import { ScheduleCard } from '@/components'; /** * PC 홈 페이지 @@ -218,95 +219,21 @@ function Home() { visible: { opacity: 1, transition: { staggerChildren: 0.1 } }, }} > - {upcomingSchedules.map((schedule) => { - const scheduleDate = new Date(schedule.date); - const todayDate = new Date(); - const currentYear = todayDate.getFullYear(); - const currentMonth = todayDate.getMonth(); - - const scheduleYear = scheduleDate.getFullYear(); - const scheduleMonth = scheduleDate.getMonth(); - const isCurrentYear = scheduleYear === currentYear; - const isCurrentMonth = - isCurrentYear && scheduleMonth === currentMonth; - - const day = scheduleDate.getDate(); - const weekdays = ['일', '월', '화', '수', '목', '금', '토']; - const weekday = weekdays[scheduleDate.getDay()]; - - // 멤버 처리 - const memberList = schedule.member_names - ? schedule.member_names.split(',') - : schedule.members?.map((m) => m.name) || []; - - const categoryColor = schedule.category_color || '#6366f1'; - - return ( - - {/* 날짜 영역 */} -
- {!isCurrentYear && ( - - {scheduleYear}.{scheduleMonth + 1} - - )} - {isCurrentYear && !isCurrentMonth && ( - - {scheduleMonth + 1}월 - - )} - {day} - - {weekday} - -
- - {/* 내용 영역 */} -
-

{schedule.title}

-
- {schedule.time && ( - - - {schedule.time.slice(0, 5)} - - )} - - - {schedule.category_name} - {schedule.source?.name && ` · ${schedule.source.name}`} - -
- {memberList.length > 0 && ( -
- {memberList.map((name, i) => ( - - {name.trim()} - - ))} -
- )} -
-
- ); - })} + {upcomingSchedules.map((schedule) => ( + + + + ))} )}