Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 메인 캘린더 헤더 수정/#68 #75

Merged
merged 20 commits into from
Jul 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading