|
1 | | -import { useEffect } from "react"; |
| 1 | +import React, { useCallback } from "react"; |
2 | 2 |
|
3 | | -import axios, { AxiosError } from "axios"; |
| 3 | +import dayjs from "dayjs"; |
| 4 | +import isSameOrAfter from "dayjs/plugin/isSameOrAfter"; |
| 5 | +import isSameOrBefore from "dayjs/plugin/isSameOrBefore"; |
| 6 | +import timezone from "dayjs/plugin/timezone"; |
4 | 7 | import { router } from "expo-router"; |
5 | | -import { SafeAreaView, View, Text } from "react-native"; |
| 8 | +import { FlatList, RefreshControl, View, Text } from "react-native"; |
| 9 | +import { CalendarProvider, ExpandableCalendar } from "react-native-calendars"; |
| 10 | +import { SafeAreaView } from "react-native-safe-area-context"; |
6 | 11 |
|
| 12 | +import CommonCalendar from "@/components/ui/CommonCalendar"; |
7 | 13 | import CustomHeader from "@/components/ui/CustomHeader"; |
8 | | -import { UsersScheduleUrl } from "@/constants/ApiUrls"; |
| 14 | +import PostBlock from "@/components/ui/PostBlock"; |
| 15 | +// import { primaryColor } from "@/constants/CalendarTheme"; |
| 16 | +import useLikeRefresh from "@/hooks/useLikeRefresh"; |
| 17 | +import { usePlan } from "@/hooks/usePlan"; |
| 18 | + |
| 19 | +// dayjs 플러그인 설정 |
| 20 | +dayjs.extend(timezone); |
| 21 | +dayjs.extend(isSameOrBefore); |
| 22 | +dayjs.extend(isSameOrAfter); |
9 | 23 |
|
10 | 24 | export default function Plan() { |
11 | | - useEffect(() => { |
12 | | - const getSchedule = async () => { |
13 | | - try { |
14 | | - const response = await axios(`${UsersScheduleUrl}/check`, { |
15 | | - params: { |
16 | | - month: "2025-06", // TODO: 실제 날짜로 변경 |
17 | | - }, |
18 | | - }); |
19 | | - console.log(response); |
20 | | - } catch (e) { |
21 | | - const axiosError = e as AxiosError; |
22 | | - console.error(axiosError); |
23 | | - } |
24 | | - }; |
25 | | - getSchedule(); |
26 | | - // test |
27 | | - }, []); |
| 25 | + const { refresh, onRefresh } = useLikeRefresh(); |
| 26 | + const { |
| 27 | + schedules, |
| 28 | + scheduleDates, |
| 29 | + loading, |
| 30 | + hasMore, |
| 31 | + selectedDate, |
| 32 | + loadMore, |
| 33 | + handleDateChange, |
| 34 | + handleMonthChange, |
| 35 | + } = usePlan(); |
| 36 | + |
| 37 | + const getSelectedDateSchedules = useCallback(() => { |
| 38 | + const selectedDayjs = dayjs(selectedDate); |
| 39 | + |
| 40 | + return schedules.filter((item) => { |
| 41 | + const startDate = dayjs(item.startDate); |
| 42 | + const endDate = dayjs(item.endDate); |
| 43 | + |
| 44 | + return ( |
| 45 | + selectedDayjs.isSameOrAfter(startDate, "day") && |
| 46 | + selectedDayjs.isSameOrBefore(endDate, "day") |
| 47 | + ); |
| 48 | + }); |
| 49 | + }, [schedules, selectedDate]); |
| 50 | + |
| 51 | + // 월별 일정 데이터를 생성 (scheduleDates 기반) |
| 52 | + const getMonthlySchedules = useCallback(() => { |
| 53 | + return scheduleDates.map((dateString, index) => ({ |
| 54 | + id: index + 1, |
| 55 | + startDate: dateString, |
| 56 | + endDate: dateString, |
| 57 | + title: "일정", |
| 58 | + })); |
| 59 | + }, [scheduleDates]); |
28 | 60 |
|
29 | 61 | return ( |
30 | | - <> |
31 | | - <SafeAreaView className="w-full flex-1 bg-white"> |
32 | | - <CustomHeader |
33 | | - title="나의 일정" |
34 | | - isCommit={false} |
35 | | - cancel={() => router.replace("/my")} |
| 62 | + <SafeAreaView className="flex-1 bg-white"> |
| 63 | + <CustomHeader |
| 64 | + title="나의 일정" |
| 65 | + isCommit={false} |
| 66 | + cancel={() => { |
| 67 | + router.replace("/my"); |
| 68 | + }} |
| 69 | + /> |
| 70 | + |
| 71 | + <CalendarProvider |
| 72 | + date={selectedDate} |
| 73 | + disableAutoDaySelection={[ |
| 74 | + ExpandableCalendar.navigationTypes.MONTH_ARROWS, |
| 75 | + ExpandableCalendar.navigationTypes.WEEK_ARROWS, |
| 76 | + ExpandableCalendar.navigationTypes.MONTH_SCROLL, |
| 77 | + ExpandableCalendar.navigationTypes.WEEK_SCROLL, |
| 78 | + ]} |
| 79 | + > |
| 80 | + <CommonCalendar |
| 81 | + selectedDate={selectedDate} |
| 82 | + schedules={getMonthlySchedules()} |
| 83 | + onDateChange={handleDateChange} |
| 84 | + onMonthChange={(month) => { |
| 85 | + console.log("Month changed to:", month); |
| 86 | + handleMonthChange(month.dateString.slice(0, 7)); |
| 87 | + }} |
| 88 | + monthRangeLimit={2} |
| 89 | + showStatusBar={false} |
| 90 | + closeOnDayPress={false} |
| 91 | + disablePan={true} |
| 92 | + animateScroll={true} |
| 93 | + hideKnob={true} |
36 | 94 | /> |
37 | | - <View> |
38 | | - <Text>해당 위치에 달력 컴포넌트를 활용</Text> |
39 | | - <Text>컨텐츠 일정과 동일한 구성, 데이터만 달리</Text> |
40 | | - </View> |
41 | | - </SafeAreaView> |
42 | | - </> |
| 95 | + |
| 96 | + {getSelectedDateSchedules().length === 0 && !loading ? ( |
| 97 | + <View className="mt-8 flex-1 items-center justify-center"> |
| 98 | + <Text className="text-base text-gray-500"> |
| 99 | + 선택한 날짜에 일정이 없습니다. |
| 100 | + </Text> |
| 101 | + </View> |
| 102 | + ) : ( |
| 103 | + <FlatList |
| 104 | + className="mt-4 px-6" |
| 105 | + data={getSelectedDateSchedules()} |
| 106 | + renderItem={({ item }) => ( |
| 107 | + <PostBlock |
| 108 | + info={{ |
| 109 | + img_url: item.image || "", |
| 110 | + title: item.title, |
| 111 | + address: item.address, |
| 112 | + start_date: item.startDate, |
| 113 | + end_date: item.endDate, |
| 114 | + }} |
| 115 | + /> |
| 116 | + )} |
| 117 | + keyExtractor={(item) => item.contentId.toString()} |
| 118 | + onEndReached={loadMore} |
| 119 | + onEndReachedThreshold={0.8} |
| 120 | + refreshControl={ |
| 121 | + <RefreshControl refreshing={refresh} onRefresh={onRefresh} /> |
| 122 | + } |
| 123 | + removeClippedSubviews={true} |
| 124 | + initialNumToRender={10} |
| 125 | + /> |
| 126 | + )} |
| 127 | + </CalendarProvider> |
| 128 | + </SafeAreaView> |
43 | 129 | ); |
44 | 130 | } |
0 commit comments