Skip to content

Commit

Permalink
Merge pull request #74 from DearMyPeace/dev/feat-기록-날짜-선택-편지에서-적용/#73
Browse files Browse the repository at this point in the history
feat: 기록 날짜 선택 편지에서 적용/#73
  • Loading branch information
hyobb109 authored Jul 7, 2024
2 parents 21adb83 + f6f6a94 commit ddea00a
Show file tree
Hide file tree
Showing 9 changed files with 188 additions and 223 deletions.
1 change: 1 addition & 0 deletions src/api/ai/get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ interface IAiLettersMonthSummary {
id: number;
date: string;
summary: string;
replyStatus: string;
}

export const fetchAiLettersMonthSummary = async ({
Expand Down
84 changes: 43 additions & 41 deletions src/hooks/ai/ailetterHook.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { useState, useRef, useCallback, useEffect } from 'react';
import React, { useState, useRef, useCallback, useEffect } from 'react';
import { FlatList } from 'react-native';
import { useQuery, useQueryClient } from '@tanstack/react-query';
import { IAiLetterEntry, IID } from '@type/IAiLetterEntry';
import { fetchAiLettersMonthSummary, fetchAiLettersViaID } from '@api/ai/get';
import { fillDatesWithData, generateDateRange } from '@utils/dateUtils';
import { isEmpty } from 'lodash';
import { generateDateRangeEntry } from '@utils/dateUtils';
import { useFocusEffect } from '@react-navigation/native';

export const useAiLetterData = (initialDateStr: string) => {
const [activeSections, setActiveSections] = useState<number[]>([]);
Expand All @@ -15,6 +15,11 @@ export const useAiLetterData = (initialDateStr: string) => {

const queryClient = useQueryClient();

useEffect(() => {
setCurrentDateStr(initialDateStr);
console.log('initialDateStr');
}, [initialDateStr]);

const fetchMonthSummary = async (dateStr: string): Promise<IAiLetterEntry[]> => {
const [year, month] = dateStr.split('-');
return fetchAiLettersMonthSummary({ year: parseInt(year), month: parseInt(month) });
Expand Down Expand Up @@ -75,25 +80,19 @@ export const useAiLetterData = (initialDateStr: string) => {
}
});

if (flatListRef.current) {
if (
flatListRef.current &&
aiLetterEntries.length > 0 &&
index >= 0 &&
index < aiLetterEntries.length
) {
flatListRef.current.scrollToIndex({ index, animated: true });
}
}
},
[aiLetterEntries, fetchContentForID],
[aiLetterEntries, fetchContentForID, flatListRef],
);

const onScrollToIndexFailed = (info) => {
if (info.index < 0 || info.index >= aiLetterEntries.length) {
console.warn(`Invalid index: ${info.index}`);
return;
}
const wait = new Promise((resolve) => setTimeout(resolve, 500));
wait.then(() => {
flatListRef.current?.scrollToIndex({ index: info.index, animated: true });
});
};

const {
data: monthSummaryData,
error: monthSummaryError,
Expand All @@ -105,33 +104,37 @@ export const useAiLetterData = (initialDateStr: string) => {
enabled: !!currentDateStr,
});

useEffect(() => {
if (monthSummaryData && monthSummaryData.length > 0) {
const dateRange = generateDateRange(
monthSummaryData[0].date,
monthSummaryData[monthSummaryData.length - 1].date,
);
const filledData = fillDatesWithData(dateRange, monthSummaryData);
setAiLetterEntries(filledData);

const todayStr = new Date().toISOString().slice(0, 10);
const todayIndex = filledData.findIndex((entry) => entry.date === todayStr);
if (todayIndex !== -1) {
const section = filledData[todayIndex];
if (!section.content) {
fetchContentForID(section.id);
}
setActiveSections([todayIndex]);
useFocusEffect(
useCallback(() => {
if (monthSummaryData && monthSummaryData.length > 0) {
const filledData = generateDateRangeEntry(monthSummaryData);
setAiLetterEntries(filledData);

if (flatListRef.current && filledData.length > 0 && todayIndex > 0) {
flatListRef.current.scrollToIndex({ index: todayIndex, animated: true });
const todayStr = new Date().toISOString().slice(0, 10);
const todayIndex = filledData.findIndex((entry) => entry.date === todayStr);
const currentDayIndex = filledData.findIndex((entry) => entry.date === currentDateStr);

if (currentDayIndex !== -1) {
const section = filledData[currentDayIndex];
if (!section.content) {
fetchContentForID(section.id);
}
setActiveSections([currentDayIndex]);
} else if (todayIndex !== -1) {
const section = filledData[todayIndex];
if (!section.content) {
fetchContentForID(section.id);
}
setActiveSections([todayIndex]);
} else {
setActiveSections([]);
}
} else {
setAiLetterEntries([]);
setActiveSections([]);
}
} else {
setAiLetterEntries([]);
setActiveSections([]);
}
}, [monthSummaryData, fetchContentForID]);
}, [monthSummaryData, fetchContentForID, currentDateStr]),
);

const refetchMonthData = useCallback(
async (newDateStr?: string) => {
Expand Down Expand Up @@ -159,7 +162,6 @@ export const useAiLetterData = (initialDateStr: string) => {
setActiveSections,
flatListRef,
handleAccordionChange,
onScrollToIndexFailed,
isLoading: monthSummaryLoading,
error: monthSummaryError,
refetchMonthSummary: refetchMonthData,
Expand Down
15 changes: 15 additions & 0 deletions src/hooks/common/useSelectedDate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { useRecoilValue } from 'recoil';
import { selectedDateStatus } from '@stores/tense';
import { IDate } from '@type/Diary';
import { format } from 'date-fns';

export const useSelectedDate = () => {
const tense = useRecoilValue(selectedDateStatus);
return {
tense,
getToday: () => tense,
getYear: () => format(new Date(tense), 'yyyy'),
getMonth: () => format(new Date(tense), 'MM') as IDate['month'],
getDay: () => format(new Date(tense), 'yyyy'),
};
};
11 changes: 6 additions & 5 deletions src/screens/ai/AiLetter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,31 @@ import AiLetterCalendar from '@screens/ai/AiLetterCalendar';
import AiLetterFlatList from '@screens/ai/AiLetterFlatList';
import AiLetterLoadingView from '@screens/ai/AiLetterLoadingView';
import AiLetterErrorView from '@screens/ai/AiLetterErrorView';
import { useSelectedDate } from '@hooks/common/useSelectedDate';

const AiLetter: React.FC = () => {
const todayDateStr = new Date().toISOString().slice(0, 10);
const { tense } = useSelectedDate();
const targetDateStr = new Date(tense).toISOString().slice(0, 10);
console.log('target Date Str', targetDateStr);

const {
aiLetterEntries,
activeSections,
flatListRef,
handleAccordionChange,
onScrollToIndexFailed,
isLoading,
error,
refetchMonthSummary,
refreshing,
} = useAiLetterData(todayDateStr);
} = useAiLetterData(targetDateStr);

const handleMonthChange = (newDateStr: string) => {
refetchMonthSummary(newDateStr);
};

return (
<View style={styles.container}>
<AiLetterCalendar onMonthChange={handleMonthChange}>
<AiLetterCalendar targetDateStr={targetDateStr} onMonthChange={handleMonthChange}>
{isLoading ? (
<AiLetterLoadingView />
) : error ? (
Expand All @@ -38,7 +40,6 @@ const AiLetter: React.FC = () => {
activeSections={activeSections}
flatListRef={flatListRef}
handleAccordionChange={handleAccordionChange}
onScrollToIndexFailed={onScrollToIndexFailed}
onRefresh={() => refetchMonthSummary()}
refreshing={refreshing}
/>
Expand Down
46 changes: 22 additions & 24 deletions src/screens/ai/AiLetterCalendar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,39 +7,37 @@ import { appColor3 } from '@utils/colors';
import AiLetterCalendarHeader from '@screens/ai/AiLetterCalendarHeader';
import MyText from '@components/common/MyText';

const getYear = () => format(new Date(), 'yyyy');
const getMonth = () => format(new Date(), 'MM') as IDate['month'];
const getDay = () => format(new Date(), 'dd');
const parseDateStr = (dateStr: string): IDay => {
const [year, month, day] = dateStr.split('-');
return {
year,
month: month.padStart(2, '0') as IDate['month'],
day: day.padStart(2, '0'),
};
};

const AiLetterCalendar = ({ children, onMonthChange }) => {
const AiLetterCalendar = ({ children, targetDateStr, onMonthChange }) => {
const [isToday, setIsToday] = useState(true);
const [, setIsDragging] = useState(false);
const timerRef = useRef<NodeJS.Timeout | null>(null);
const DRAG_THRESHOLD = 10;

const [selectedDate, setSelectedDate] = useState<IDay>({
year: getYear(),
month: getMonth(),
day: getDay(),
});
const initialDate = parseDateStr(targetDateStr);
const [selectedDate, setSelectedDate] = useState<IDay>(initialDate);

const position = useRef(new RNAnimated.ValueXY({ x: 0, y: 0 })).current;
const startPosition = useRef({ x: 0, y: 0 }).current;

useEffect(() => {
setSelectedDate({ year: getYear(), month: getMonth(), day: getDay() });
}, []);
setSelectedDate(parseDateStr(targetDateStr));
console.log('Initial render or targetDateStr changed');
}, [targetDateStr]);

useEffect(() => {
const checkIfToday = () => {
const todayYear = getYear();
const todayMonth = getMonth();
const todayDay = getDay();
setIsToday(
selectedDate.year === todayYear &&
selectedDate.month === todayMonth &&
selectedDate.day === todayDay,
);
const todayYear = format(new Date(), 'yyyy');
const todayMonth = format(new Date(), 'MM') as IDate['month'];
setIsToday(selectedDate.year === todayYear && selectedDate.month === todayMonth);
};

checkIfToday();
Expand All @@ -49,7 +47,7 @@ const AiLetterCalendar = ({ children, onMonthChange }) => {
(date) => {
const year = date.year.toString();
const month = date.month.toString().padStart(2, '0') as IDate['month'];
const day = getDay();
const day = format(new Date(), 'dd');
setSelectedDate({ year, month, day });
onMonthChange(`${year}-${month}`);
},
Expand All @@ -70,7 +68,7 @@ const AiLetterCalendar = ({ children, onMonthChange }) => {
const newDate = new Date(Number(selectedDate.year), Number(selectedDate.month) - 1 + increment);
const year = format(newDate, 'yyyy');
const month = format(newDate, 'MM') as IDate['month'];
const day = getDay();
const day = format(new Date(), 'dd');
setSelectedDate({ year, month, day });
onMonthChange(`${year}-${month}`);
};
Expand All @@ -84,9 +82,9 @@ const AiLetterCalendar = ({ children, onMonthChange }) => {
};

const handleTodayPress = () => {
const year = getYear();
const month = getMonth();
const day = getDay();
const year = format(new Date(), 'yyyy');
const month = format(new Date(), 'MM') as IDate['month'];
const day = format(new Date(), 'dd');
setSelectedDate({ year, month, day });
onMonthChange(`${year}-${month}`);
};
Expand Down
46 changes: 13 additions & 33 deletions src/screens/ai/AiLetterFlatList.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,5 @@
import React, { useState, useEffect, useRef } from 'react';
import {
View,
ScrollView,
FlatList,
StyleSheet,
ListRenderItem,
RefreshControl,
Platform,
} from 'react-native';
import { View, FlatList, StyleSheet, ListRenderItem, RefreshControl, Platform } from 'react-native';
import Accordion from 'react-native-collapsible/Accordion';
import { IAiLetterEntry } from '@type/IAiLetterEntry';
import NotUsingDay from '@components/ai/NotUsingDay';
Expand All @@ -21,7 +13,6 @@ interface AiLetterFlatListProps {
activeSections: number[];
flatListRef: React.RefObject<FlatList>;
handleAccordionChange: (section: IAiLetterEntry) => void;
onScrollToIndexFailed: (info: any) => void;
onRefresh: () => void;
refreshing: boolean;
}
Expand All @@ -31,17 +22,21 @@ const AiLetterFlatList: React.FC<AiLetterFlatListProps> = ({
activeSections,
flatListRef,
handleAccordionChange,
onScrollToIndexFailed,
onRefresh,
refreshing,
}) => {
const [isEmpty, setIsEmpty] = useState<boolean>(false);
const scrollViewRef = useRef<ScrollView>(null);

useEffect(() => {
setIsEmpty(aiLetterEntries.length === 0);
}, [aiLetterEntries]);

useEffect(() => {
if (flatListRef.current && activeSections.length > 0) {
flatListRef.current.scrollToIndex({ index: activeSections[0], animated: true });
}
}, [activeSections, flatListRef]);

const renderItem: ListRenderItem<IAiLetterEntry> = ({ item, index }) => {
let consecutiveNotUsingDayCount = 0;

Expand Down Expand Up @@ -71,7 +66,7 @@ const AiLetterFlatList: React.FC<AiLetterFlatListProps> = ({
<AiLetterEntryHeader
section={section}
isActive={isActive}
handleAccordionChange={handleAccordionChange}
handleAccordionChange={() => handleAccordionChange(section)}
/>
)}
renderContent={(section) => <AiLetterEntryContent section={section} />}
Expand All @@ -87,45 +82,30 @@ const AiLetterFlatList: React.FC<AiLetterFlatListProps> = ({
}

const getItemLayout = (_, index) => ({
length: 70,
offset: 70 * index,
length: 40,
offset: 40 * index,
index,
});

return (
<ScrollView
ref={scrollViewRef}
refreshControl={
<RefreshControl
style={styles.hideComponent}
refreshing={refreshing}
onRefresh={onRefresh}
tintColor="transparent"
colors={['transparent']}
/>
}
>
{Platform.OS !== 'web' && <CustomRefreshControlWrapper />}
<View style={{ flex: 1 }}>
<FlatList
ref={flatListRef}
data={aiLetterEntries}
renderItem={renderItem}
keyExtractor={(item, index) => (item.id ? item.id.toString() : `${item.date}-${index}`)}
onScrollToIndexFailed={onScrollToIndexFailed}
showsVerticalScrollIndicator={false}
getItemLayout={getItemLayout}
/>
</ScrollView>
{/* <CustomRefreshControlWrapper /> */}
</View>
);
};

const styles = StyleSheet.create({
notusingItem: {
alignItems: 'center',
},
hideComponent: {
display: 'none',
},
});

export default AiLetterFlatList;
Loading

0 comments on commit ddea00a

Please sign in to comment.