Skip to content

Commit

Permalink
Merge pull request #75 from DearMyPeace/dev/68-feat-메인-캘린더-헤더-수정/#68
Browse files Browse the repository at this point in the history
feat: 메인 캘린더 헤더 수정/#68
  • Loading branch information
hyobb109 authored Jul 7, 2024
2 parents ddea00a + f6ac1f6 commit b32b190
Show file tree
Hide file tree
Showing 17 changed files with 326 additions and 108 deletions.
13 changes: 4 additions & 9 deletions src/api/diary/get.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,26 @@
import React from 'react';
import instance from '@api/axios';
import { DateStatus, IDate, IDiaryCount, IDiaryListResponse, NEW_DIARY } from '@type/Diary';
import { IDate, IDiaryCount, IDiaryListResponse, newDiary } from '@type/Diary';
import { useQuery, UseQueryResult } from '@tanstack/react-query';

export const fetchDiaryList = async (targetDate: string): Promise<IDiaryListResponse> => {
const response = await instance.get(`/diary/${targetDate}`);
return response.data;
};

export const useDiaryList = (targetDate: string, dateStatus: DateStatus) => {
export const useDiaryList = (targetDate: string, isMarked: boolean) => {
return useQuery({
queryKey: ['diary', 'list', targetDate],
queryFn: () => fetchDiaryList(targetDate),
enabled: !!targetDate,
enabled: !!targetDate && isMarked,
staleTime: Infinity,
select: (data) => {
const diaryList = data.diaries.map((item) => ({
id: item.diaryId,
content: item.content,
createdTime: item.createdDate,
}));
diaryList.length < 3 &&
diaryList.push({
id: NEW_DIARY,
content: '이 날의 심심기록을 남겨보세요',
createdTime: '',
});
diaryList.length < 3 && diaryList.push(newDiary);
return { sendStatus: data.sendStatus, diaryList };
},
});
Expand Down
139 changes: 139 additions & 0 deletions src/components/diary/calendar/CalendarSelectModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import MyText from '@components/common/MyText';
import { appColor3 } from '@utils/colors';
import { kMonth } from '@utils/localeConfig';
import { fontLarge } from '@utils/Sizing';
import React from 'react';
import {
View,
Modal,
FlatList,
Pressable,
TouchableWithoutFeedback,
StyleSheet,
ListRenderItem,
} from 'react-native';

interface IMonthItem {
month: string;
index: number;
}

interface ICalendarSelectModalProps {
isModalVisible: boolean;
handleModalDismiss: () => void;
selectedMonth: number;
selectedYear: number;
setSelectedMonth: (month: number) => void;
setSelectedYear: (year: number) => void;
}

const CalendarSelectModal = ({
isModalVisible,
handleModalDismiss,
selectedMonth,
selectedYear,
setSelectedMonth,
setSelectedYear,
}: ICalendarSelectModalProps) => {
const renderMonthItem: ListRenderItem<IMonthItem> = ({ item }) => (
<Pressable style={styles.modalItem} onPress={() => setSelectedMonth(item.index + 1)}>
<View style={selectedMonth === item.index + 1 && styles.selectedStyle}>
<MyText style={selectedMonth === item.index + 1 ? styles.selectedText : styles.modalText}>
{item.month}
</MyText>
</View>
</Pressable>
);

const renderYearItem: ListRenderItem<number> = ({ item }) => (
<Pressable style={styles.modalItem} onPress={() => setSelectedYear(item)}>
<View style={selectedYear === item && styles.selectedStyle}>
<MyText style={selectedYear === item ? styles.selectedText : styles.modalText}>
{item}
</MyText>
</View>
</Pressable>
);
return (
<Modal visible={isModalVisible} transparent={true} animationType="fade">
<TouchableWithoutFeedback onPress={handleModalDismiss}>
<View style={styles.modalOverlay}>
<View style={styles.modalContent}>
<View style={styles.modalListContainer}>
<View style={styles.modalMonth}>
<FlatList
data={kMonth.map((month, index) => ({ month, index }))}
renderItem={renderMonthItem}
keyExtractor={(item) => item.index.toString()}
initialScrollIndex={Math.max(0, selectedMonth - 1)}
getItemLayout={(data, index) => ({ length: 50, offset: 50 * index, index })}
showsVerticalScrollIndicator={false}
/>
</View>
<View style={styles.modalYear}>
<FlatList
data={Array.from({ length: 50 }, (_, i) => 2000 + i)}
renderItem={renderYearItem}
keyExtractor={(item) => item.toString()}
initialScrollIndex={Math.max(0, selectedYear - 2000)}
getItemLayout={(data, index) => ({ length: 50, offset: 50 * index, index })}
showsVerticalScrollIndicator={false}
/>
</View>
</View>
</View>
</View>
</TouchableWithoutFeedback>
</Modal>
);
};

export default CalendarSelectModal;

const styles = StyleSheet.create({
modalOverlay: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'rgba(0, 0, 0, 0.5)',
},
modalContent: {
width: 300,
maxHeight: 300,
backgroundColor: '#ffffff',
borderRadius: 10,
padding: 10,
flexDirection: 'row',
},
modalListContainer: {
flexDirection: 'row',
justifyContent: 'space-between',
width: '100%',
},
modalMonth: {
width: '50%',
},
modalYear: {
width: '50%',
},
modalItem: {
paddingVertical: 10,
paddingHorizontal: 20,
},
modalText: {
fontSize: fontLarge,
textAlign: 'center',
},
selectedText: {
fontSize: fontLarge,
textAlign: 'center',
color: appColor3,
},
selectedStyle: {
borderColor: appColor3,
borderWidth: 1,
borderRadius: 15,
paddingVertical: 10,
paddingHorizontal: 19,
},
});
79 changes: 65 additions & 14 deletions src/components/diary/calendar/MyCalendar.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,31 @@
import React from 'react';
import React, { useEffect, useState } from 'react';
import CalendarArrow, { Direction } from '@components/diary/calendar/CalendarArrow';
import { StyleSheet, View, Platform } from 'react-native';
import { Calendar, DateData } from 'react-native-calendars';
import setLocaleConfig from '@utils/localeConfig';
import { IDiaryCount, IMarkedDates } from '@type/Diary';
import { StyleSheet, View } from 'react-native';
import { Calendar } from 'react-native-calendars';
import setLocaleConfig, { kMonth } from '@utils/localeConfig';
import { IDate, IMarkedDates } from '@type/Diary';
import { dotColors } from '@utils/colors';
import { fontLarge } from '@utils/Sizing';
import { getToday } from '@utils/dateUtils';
import MyText from '@components/common/MyText';
import TextButton from '@components/common/TextButton';
import CalendarSelectModal from './CalendarSelectModal';
import useCalendarHook from '@hooks/diary/calendarHook';

setLocaleConfig();
interface IMyCalendarProps {
selectedDate: string;
markedDates: IDiaryCount[];
onDayPress: (date: DateData) => void;
onMonthChange: (date: DateData) => void;
}

const MyCalendar = ({ selectedDate, markedDates, onDayPress, onMonthChange }: IMyCalendarProps) => {
const MyCalendar = () => {
const {
onDayPress,
onMonthChange,
markedDates,
selectedDate,
setSelectedDate,
saveDateStatus,
setTargetMonth,
} = useCalendarHook();
const [isModalVisible, setModalVisible] = useState(false);
const [selectedMonth, setSelectedMonth] = useState(parseInt(selectedDate.slice(5, 7), 10));
const [selectedYear, setSelectedYear] = useState(parseInt(selectedDate.slice(0, 4), 10));
const markedDatesList: IMarkedDates = markedDates.reduce((acc, date) => {
acc[date.markedDate] = {
selected: date.markedDate === selectedDate,
Expand All @@ -26,10 +35,36 @@ const MyCalendar = ({ selectedDate, markedDates, onDayPress, onMonthChange }: IM
return acc;
}, {} as IMarkedDates);

useEffect(() => {
setSelectedMonth(parseInt(selectedDate.slice(5, 7), 10));
setSelectedYear(parseInt(selectedDate.slice(0, 4), 10));
setTargetMonth({
year: selectedYear.toString(),
month: selectedMonth.toString().padStart(2, '0') as IDate['month'],
});
saveDateStatus(selectedDate);
}, [selectedDate]);

const handleModalDismiss = () => {
setSelectedDate(`${selectedYear}-${selectedMonth.toString().padStart(2, '0')}-01`);
setModalVisible(false);
};

const onHeaderPress = () => {
setModalVisible(true);
};

const getDisplayDate = (date: Date) => {
const year = date.getFullYear();
const month = date.getMonth();
return `${kMonth[month]} ${year}`;
};

return (
<View style={styles.container}>
<Calendar
maxDate={getToday()}
key={selectedDate}
current={selectedDate}
style={styles.calendar}
theme={{
textDayFontFamily: 'GowunBatang-Regular',
Expand Down Expand Up @@ -58,6 +93,7 @@ const MyCalendar = ({ selectedDate, markedDates, onDayPress, onMonthChange }: IM
},
},
}}
webAriaLevel={1}
hideExtraDays
enableSwipeMonths
firstDay={1}
Expand All @@ -68,6 +104,21 @@ const MyCalendar = ({ selectedDate, markedDates, onDayPress, onMonthChange }: IM
...markedDatesList,
}}
renderArrow={(direction: Direction) => <CalendarArrow direction={direction} />}
renderHeader={(date: string) => (
<>
<TextButton onPress={onHeaderPress}>
<MyText size={fontLarge}>{getDisplayDate(new Date(date))}</MyText>
</TextButton>
<CalendarSelectModal
isModalVisible={isModalVisible}
handleModalDismiss={handleModalDismiss}
selectedMonth={selectedMonth}
selectedYear={selectedYear}
setSelectedMonth={setSelectedMonth}
setSelectedYear={setSelectedYear}
/>
</>
)}
/>
</View>
);
Expand Down
22 changes: 14 additions & 8 deletions src/components/diary/carousel/DiaryCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ const DiaryCard = ({
useEffect(() => {
setDiaryInput(id === NEW_DIARY ? '' : content);
setIsEditing(false);
setTimeStartWriting('');
}, [id, content]);

const addNewDiary = useMutation({
Expand All @@ -46,7 +47,7 @@ const DiaryCard = ({
setSnackbar('저장이 완료되었습니다.');
setTimeStartWriting('');
},
onError: (error) => {
onError: (error: any) => {
setSnackbar(error.response.data.message || '오류가 발생했습니다.');
},
onSettled: () => {
Expand All @@ -59,7 +60,7 @@ const DiaryCard = ({
queryClient.invalidateQueries({ queryKey: ['diary'] });
setSnackbar('삭제가 완료되었습니다.');
},
onError: (error) => {
onError: (error: any) => {
setSnackbar(error.response.data.message || '오류가 발생했습니다.');
},
onSettled: () => {
Expand All @@ -75,7 +76,7 @@ const DiaryCard = ({
queryClient.invalidateQueries({ queryKey: ['diary', 'list'] });
setSnackbar('수정이 완료되었습니다.');
},
onError: (error) => {
onError: (error: any) => {
setSnackbar(error.response.data.message || '오류가 발생했습니다.');
},
onSettled: () => {
Expand All @@ -86,13 +87,12 @@ const DiaryCard = ({
const sendDiary = useMutation({
mutationFn: (data: IAiLetterRequest) => postAiLetters(data),
onSuccess: (data) => {
console.log(data);
queryClient.invalidateQueries({ queryKey: ['diary', 'list'] });
queryClient.invalidateQueries({ queryKey: ['userInfo'] });
queryClient.invalidateQueries({ queryKey: ['fetchAiLettersMonthSummary'] });
// setSnackbar('편지가 도착했습니다');
},
onError: (error) => {
onError: (error: any) => {
setSnackbar(error.response.data.message || '오류가 발생했습니다.');
},
});
Expand Down Expand Up @@ -127,8 +127,7 @@ const DiaryCard = ({
};

const sendDiaryData = () => {
const formattedTime = `${targetDate}T${timeStartWriting.split('T')[1]}`;
const cretatedDate = id === NEW_DIARY ? formattedTime : createdTime;
const cretatedDate = id === NEW_DIARY ? timeStartWriting : createdTime;
const data = {
content: diaryInput,
createdDate: cretatedDate,
Expand Down Expand Up @@ -163,6 +162,12 @@ const DiaryCard = ({
sendDiaryData();
};

const onCancelSaveEdit = () => {
setInformModalVisible(false);
setIsEditing(false);
setDiaryInput(content);
};

const onKeyboardDismiss = () => {
setIsEditing(false);
Keyboard.dismiss();
Expand Down Expand Up @@ -216,13 +221,14 @@ const DiaryCard = ({
visible={isSendModalVisible}
setIsVisible={setSendModalVisible}
onConfirm={onConfirmSend}
content="기록을 보내시겠습니까?"
content={`이 날의 기록을 모두 보내시겠습니까?\n편지는 하루에 한 번만 받을 수 있어요.`}
confirmText="보내기"
/>
<BasicConfirmModal
visible={isInformModalVisible}
setIsVisible={setInformModalVisible}
onConfirm={onConfirmSaveEdit}
onCancel={onCancelSaveEdit}
content={`기록을 수정해도\n편지의 내용은 바뀌지 않아요.`}
confirmText="저장"
/>
Expand Down
Loading

0 comments on commit b32b190

Please sign in to comment.