From c6233c7e929a57b6735be8e4cddae9d7da2d8ecb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EA=B3=A0=EB=B3=91=EC=B0=AC?=
<70642609+byungchanKo99@users.noreply.github.com>
Date: Fri, 22 Nov 2024 15:33:56 +0900
Subject: [PATCH 01/12] =?UTF-8?q?[SZ-553]feat:=20=ED=88=AC=EB=8D=B0?=
=?UTF-8?q?=EC=9D=B4=EB=B7=B0=20=EB=93=9C=EB=9E=98=EA=B7=B8=EC=95=A4?=
=?UTF-8?q?=EB=93=9C=EB=A1=AD=20=EB=8F=99=EC=9E=91=ED=95=98=EA=B2=8C=20?=
=?UTF-8?q?=ED=95=A8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/(tabs)/index.jsx | 30 ++++++++++++-------
.../todayView/dailyTodos/DailyTodos.tsx | 20 ++++++++++---
.../dailyTodos/dailyTodo/DailyTodo.jsx | 19 +-----------
3 files changed, 36 insertions(+), 33 deletions(-)
diff --git a/app/(tabs)/index.jsx b/app/(tabs)/index.jsx
index 5784ead..58447a4 100644
--- a/app/(tabs)/index.jsx
+++ b/app/(tabs)/index.jsx
@@ -28,6 +28,8 @@ import { scale, verticalScale } from 'react-native-size-matters';
const TodayView = () => {
const { i18n } = useTranslation();
const { userId } = useContext(LoginContext);
+ const [isDragging, setIsDragging] = React.useState(false);
+
const getLoadingText = () => {
if (i18n.language === 'ko') {
return `투두`;
@@ -44,7 +46,12 @@ const TodayView = () => {
return (
-
+ setIsDragging(true)}
+ onDragEnd={() => setIsDragging(false)}
+ />
);
};
@@ -56,14 +63,14 @@ const TodayView = () => {
-
-
+
+
{
renderItem={renderCategoriesTodo}
keyExtractor={item => item.id}
contentContainerStyle={styles.flatList}
+ scrollEnabled={!isDragging}
/>
-
-
+
+
diff --git a/components/todayView/dailyTodos/DailyTodos.tsx b/components/todayView/dailyTodos/DailyTodos.tsx
index d33cf12..7fe9d59 100644
--- a/components/todayView/dailyTodos/DailyTodos.tsx
+++ b/components/todayView/dailyTodos/DailyTodos.tsx
@@ -19,12 +19,14 @@ import { Icon } from '@ui-kitten/components';
import React, { useContext } from 'react';
import { useTranslation } from 'react-i18next';
import { StyleSheet, TextInput, View } from 'react-native';
-import DraggableFlatList from 'react-native-draggable-flatlist';
+import DraggableFlatList, {
+ ScaleDecorator,
+} from 'react-native-draggable-flatlist';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
import DailyTodo from './dailyTodo/DailyTodo';
import { moderateScale, scale, verticalScale } from 'react-native-size-matters';
-const DailyTodos = ({ todosData, categoryId }) => {
+const DailyTodos = ({ todosData, categoryId, onDragStart, onDragEnd }) => {
const { userId } = useContext(LoginContext);
const { selectedDate } = useContext(DateContext);
const { t } = useTranslation();
@@ -36,6 +38,11 @@ const DailyTodos = ({ todosData, categoryId }) => {
selectedDate,
);
+ const handleDragEndWithCallback = ({ data, from, to }) => {
+ handleDragEnd({ data, from, to });
+ onDragEnd?.();
+ };
+
const { isTextInputOpen, activatedCategoryId, setTextInputOpen } =
useContext(TextInputContext);
@@ -51,7 +58,11 @@ const DailyTodos = ({ todosData, categoryId }) => {
};
const renderTodo = ({ item, drag, isActive }) => {
- return ;
+ return (
+
+
+
+ );
};
return (
@@ -60,7 +71,8 @@ const DailyTodos = ({ todosData, categoryId }) => {
onDragStart?.()}
keyExtractor={item => item.id.toString()}
onScroll={() => handleScroll(TODAYVIEW_SCROLL_EVENT, userId)}
scrollEventThrottle={DEFAULT_SCROLL_EVENT_THROTTLE}
diff --git a/components/todayView/dailyTodos/dailyTodo/DailyTodo.jsx b/components/todayView/dailyTodos/dailyTodo/DailyTodo.jsx
index 7418620..c7b3d39 100644
--- a/components/todayView/dailyTodos/dailyTodo/DailyTodo.jsx
+++ b/components/todayView/dailyTodos/dailyTodo/DailyTodo.jsx
@@ -1,10 +1,8 @@
-import SubTodoGenerateModal from '@/components/SubTodoGenerateModal';
import { TextInputContext } from '@/contexts/textInputContext';
import '@/locales/index';
import { useContext } from 'react';
import { View } from 'react-native';
import useModal from '../../../../hooks/common/useModal';
-import GeneratedSubTodoList from './generatedSubTodoList/GeneratedSubTodoList';
import SubTodoInfo from './subTodoInfo/SubTodoInfo';
import SubTodoList from './subTodoList/SubTodoList';
import TodoListItem from './todoListItem/TodoListItem';
@@ -18,15 +16,10 @@ const DailyTodo = ({ item, drag, isActive }) => {
setIsSubTodoToggleActivated,
subTodoInputActivated,
setSubTodoInputActivated,
- generatedSubTodos,
- setGeneratedSubTodos,
} = useDailyTodo();
const { setTextInputOpen } = useContext(TextInputContext);
- const {
- isVisible: isSubTodoGenerateModalVisible,
- setIsVisible: setIsSubTodoGenerateModalVisible,
- } = useModal();
+ const { setIsVisible: setIsSubTodoGenerateModalVisible } = useModal();
const { setIsVisible: setIsTodoModalVisible } = useModal();
@@ -62,16 +55,6 @@ const DailyTodo = ({ item, drag, isActive }) => {
setSubTodoInputActivated={setSubTodoInputActivated}
/>
) : null}
-
-
);
};
From e1518830c6d748509bf9cde06bcdeb00d21cc3ee Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EA=B3=A0=EB=B3=91=EC=B0=AC?=
<70642609+byungchanKo99@users.noreply.github.com>
Date: Fri, 22 Nov 2024 23:00:58 +0900
Subject: [PATCH 02/12] =?UTF-8?q?[SZ-553]feat:=20=EC=9D=BC=EB=B6=80=20?=
=?UTF-8?q?=EC=84=B1=EB=8A=A5=20=EC=B5=9C=EC=A0=81=ED=99=94?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 캘린더 컴포넌트 캐싱
- fetch 데이터 캐싱
---
components/WeeklyCalendar.jsx | 299 +++++++++++++++++---------------
hooks/api/useCategoriesQuery.js | 2 +
hooks/api/useInboxTodoQuery.js | 2 +
hooks/api/useTodoQuery.js | 2 +
4 files changed, 169 insertions(+), 136 deletions(-)
diff --git a/components/WeeklyCalendar.jsx b/components/WeeklyCalendar.jsx
index da98a56..8ec5f0d 100644
--- a/components/WeeklyCalendar.jsx
+++ b/components/WeeklyCalendar.jsx
@@ -13,79 +13,179 @@ import { Icon, Layout, Text, useTheme } from '@ui-kitten/components';
import { View } from 'react-native';
import moment from 'moment';
import 'moment/locale/ko';
-import React, { useContext, useEffect, useState } from 'react';
+import React, {
+ useContext,
+ useEffect,
+ useState,
+ useMemo,
+ useCallback,
+ memo,
+} from 'react';
import { useTranslation } from 'react-i18next';
import { TouchableOpacity } from 'react-native';
import fontStyles from '../theme/fontStyles';
import { moderateScale, scale, verticalScale } from 'react-native-size-matters';
import useTodosQuery from '@/hooks/api/useTodoQuery';
-const WeeklyCalendar = () => {
+// 날짜 변환 딕셔너리를 컴포넌트 외부로 이동
+const convertDictionary = {
+ 월: 'Mon',
+ 화: 'Tue',
+ 수: 'Wed',
+ 목: 'Thu',
+ 금: 'Fri',
+ 토: 'Sat',
+ 일: 'Sun',
+};
+
+// 날짜 아이템 컴포넌트 분리 및 메모이제이션
+const DayItem = memo(
+ ({ date, selectedDate, theme, todos, onDateSelect, userId, i18n }) => {
+ const convertWeekDates = useCallback(
+ convertedDate => {
+ if (i18n.language === 'ko') {
+ return convertedDate.format('ddd');
+ }
+ return convertDictionary[convertedDate.format('ddd')];
+ },
+ [i18n.language],
+ );
+
+ const todoCount = useMemo(
+ () =>
+ todos.filter(
+ todo =>
+ isTodoIncludedInTodayView(todo.date, date.format('YYYY-MM-DD')) &&
+ !todo.isCompleted,
+ ).length,
+ [todos, date],
+ );
+
+ const handlePress = useCallback(() => {
+ handleLogEvent(WEEKLYCALENDAR_DAYITEM_CLICK_EVENT, {
+ time: new Date().toISOString(),
+ userId,
+ day: date.format('YYYY-MM-DD'),
+ });
+ onDateSelect(date);
+ }, [date, userId, onDateSelect]);
+
+ return (
+
+
+ {convertWeekDates(date)}
+
+
+
+
+ {todoCount}
+
+
+
+ {date.format('D')}
+
+
+
+ );
+ },
+);
+
+const WeeklyCalendar = memo(() => {
const { selectedDate, setSelectedDate } = useContext(DateContext);
- const [currentDate, setcurrentDate] = useState(moment());
+ const [currentDate, setCurrentDate] = useState(moment());
const theme = useTheme();
const { userId } = useContext(LoginContext);
- const todos = useTodosQuery().data;
- // const [todos, setTodos] = useState(fedchedTodos.data);
- const getWeekDates = date => {
+ const { data: todos = [] } = useTodosQuery();
+ const { i18n } = useTranslation();
+
+ // 주간 날짜 계산 메모이제이션
+ const getWeekDates = useCallback(date => {
const start = date.clone().startOf('ISOWeek');
- const r = Array.from({ length: 7 }, (_, i) =>
+ return Array.from({ length: 7 }, (_, i) =>
moment(convertGmtToKst(new Date(start.clone().add(i, 'days')))),
);
- return r;
- };
- const [weekDates, setwWeekDates] = useState(getWeekDates(currentDate));
- const { i18n } = useTranslation();
+ }, []);
+
+ const weekDates = useMemo(
+ () => getWeekDates(currentDate),
+ [currentDate, getWeekDates],
+ );
- const navigateWeek = direction => {
- setcurrentDate(prevDate =>
+ const navigateWeek = useCallback(direction => {
+ setCurrentDate(prevDate =>
direction === 'next'
? prevDate.clone().add(7, 'd')
: prevDate.clone().subtract(7, 'd'),
);
- };
- useEffect(() => {
- setwWeekDates(getWeekDates(currentDate));
- }, [currentDate]);
- useEffect(() => {
- moment().isBetween(weekDates[0], weekDates[6])
- ? setSelectedDate(currentDate)
- : setSelectedDate(weekDates[0]);
- }, [weekDates, setSelectedDate, currentDate]);
+ }, []);
- const handleDateSelect = date => {
- setSelectedDate(date);
- };
+ const handleDateSelect = useCallback(
+ date => {
+ setSelectedDate(date);
+ },
+ [setSelectedDate],
+ );
- const convertMonthAndYear = date => {
+ const convertMonthAndYear = useCallback(date => {
return date.format('yyyy.MM');
- };
+ }, []);
- const convertDictionary = {
- 월: 'Mon',
- 화: 'Tue',
- 수: 'Wed',
- 목: 'Thu',
- 금: 'Fri',
- 토: 'Sat',
- 일: 'Sun',
- };
+ const convertCalendarType = useCallback(() => {
+ return i18n.language === 'ko' ? '주' : 'W';
+ }, [i18n.language]);
- const convertWeekDates = date => {
- if (i18n.language === 'ko') {
- return date.format('ddd');
- } else if (i18n.language === 'en') {
- return convertDictionary[date.format('ddd')];
- }
- };
+ // 주간 이동 버튼 핸들러
+ const handleNavigateWeek = useCallback(
+ direction => {
+ handleLogEvent(WEEKLYCALENDAR_NAVIGATEWEEK_CLICK_EVENT, {
+ time: new Date().toISOString(),
+ userId,
+ week: selectedDate.format('YYYY-MM-DD'),
+ direction,
+ });
+ navigateWeek(direction);
+ },
+ [navigateWeek, userId, selectedDate],
+ );
- const convertCalendarType = () => {
- if (i18n.language === 'ko') {
- return '주';
- } else if (i18n.language === 'en') {
- return 'W';
+ useEffect(() => {
+ if (moment().isBetween(weekDates[0], weekDates[6])) {
+ setSelectedDate(currentDate);
+ } else {
+ setSelectedDate(weekDates[0]);
}
- };
+ }, [weekDates, setSelectedDate, currentDate]);
return (
@@ -98,35 +198,14 @@ const WeeklyCalendar = () => {
- {
- handleLogEvent(WEEKLYCALENDAR_NAVIGATEWEEK_CLICK_EVENT, {
- time: new Date().toISOString(),
- userId: userId,
- week: selectedDate.format('YYYY-MM-DD'),
- direction: 'prev',
- });
- navigateWeek('prev');
- }}
- >
+ handleNavigateWeek('prev')}>
- {
- navigateWeek('next');
-
- handleLogEvent(WEEKLYCALENDAR_NAVIGATEWEEK_CLICK_EVENT, {
- time: new Date().toISOString(),
- userId: userId,
- week: selectedDate.format('YYYY-MM-DD'),
- direction: 'next',
- });
- }}
- >
+ handleNavigateWeek('next')}>
{
{weekDates.map((date, index) => (
-
-
- {convertWeekDates(date)}
-
- {
- handleLogEvent(WEEKLYCALENDAR_DAYITEM_CLICK_EVENT, {
- time: new Date().toISOString(),
- userId: userId,
- day: date.format('YYYY-MM-DD'),
- });
- handleDateSelect(date);
- }}
- style={{
- ...styles.touchBox,
- backgroundColor: date.isSame(selectedDate, 'day')
- ? theme.Blue01
- : 'transparent',
- }}
- >
-
-
- {
- todos.filter(
- todo =>
- isTodoIncludedInTodayView(
- todo.date,
- date.format('YYYY-MM-DD'),
- ) && !todo.isCompleted,
- ).length
- }
-
-
-
- {date.format('D')}
-
-
-
+
))}
);
-};
+});
+// 스타일은 동일하게 유지
const styles = StyleSheet.create({
background: {
display: 'flex',
diff --git a/hooks/api/useCategoriesQuery.js b/hooks/api/useCategoriesQuery.js
index 5f00f42..ae285eb 100644
--- a/hooks/api/useCategoriesQuery.js
+++ b/hooks/api/useCategoriesQuery.js
@@ -15,6 +15,8 @@ const useCategoriesQuery = userId => {
suspense: true,
refetchInterval: 60000,
refetchIntervalInBackground: true,
+ cacheTime: 180000,
+ staleTime: 30000,
});
};
diff --git a/hooks/api/useInboxTodoQuery.js b/hooks/api/useInboxTodoQuery.js
index faa94a6..a29a4d2 100644
--- a/hooks/api/useInboxTodoQuery.js
+++ b/hooks/api/useInboxTodoQuery.js
@@ -14,6 +14,8 @@ const useInboxTodoQuery = userId => {
queryKey: [INBOX_QUERY_KEY],
queryFn: () => fetcher(userId),
suspense: true,
+ cacheTime: 180000,
+ staleTime: 30000,
});
};
diff --git a/hooks/api/useTodoQuery.js b/hooks/api/useTodoQuery.js
index 63a760d..3e5f6f6 100644
--- a/hooks/api/useTodoQuery.js
+++ b/hooks/api/useTodoQuery.js
@@ -16,6 +16,8 @@ const useTodosQuery = userId => {
suspense: true,
refetchInterval: 60000,
refetchIntervalInBackground: true,
+ cacheTime: 180000,
+ staleTime: 30000,
});
};
From 6c3e085c6cbae9d1b823aeece03db04ce79b33fc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EA=B3=A0=EB=B3=91=EC=B0=AC?=
<70642609+byungchanKo99@users.noreply.github.com>
Date: Sat, 23 Nov 2024 00:18:56 +0900
Subject: [PATCH 03/12] =?UTF-8?q?[SZ-553]:feat:=20=EC=BA=98=EB=A6=B0?=
=?UTF-8?q?=EB=8D=94=EC=97=90=20=EB=82=A8=EC=9D=80=20=ED=88=AC=EB=91=90=20?=
=?UTF-8?q?=EA=B0=AF=EC=88=98=20=EB=B2=84=EA=B7=B8=20=EC=88=98=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
components/WeeklyCalendar.jsx | 48 ++++++++++++++++++++++++++---------
1 file changed, 36 insertions(+), 12 deletions(-)
diff --git a/components/WeeklyCalendar.jsx b/components/WeeklyCalendar.jsx
index 8ec5f0d..28671ea 100644
--- a/components/WeeklyCalendar.jsx
+++ b/components/WeeklyCalendar.jsx
@@ -26,6 +26,7 @@ import { TouchableOpacity } from 'react-native';
import fontStyles from '../theme/fontStyles';
import { moderateScale, scale, verticalScale } from 'react-native-size-matters';
import useTodosQuery from '@/hooks/api/useTodoQuery';
+import useCategoriesQuery from '@/hooks/api/useCategoriesQuery';
// 날짜 변환 딕셔너리를 컴포넌트 외부로 이동
const convertDictionary = {
@@ -40,7 +41,7 @@ const convertDictionary = {
// 날짜 아이템 컴포넌트 분리 및 메모이제이션
const DayItem = memo(
- ({ date, selectedDate, theme, todos, onDateSelect, userId, i18n }) => {
+ ({ date, selectedDate, theme, todoCount, onDateSelect, userId, i18n }) => {
const convertWeekDates = useCallback(
convertedDate => {
if (i18n.language === 'ko') {
@@ -51,16 +52,6 @@ const DayItem = memo(
[i18n.language],
);
- const todoCount = useMemo(
- () =>
- todos.filter(
- todo =>
- isTodoIncludedInTodayView(todo.date, date.format('YYYY-MM-DD')) &&
- !todo.isCompleted,
- ).length,
- [todos, date],
- );
-
const handlePress = useCallback(() => {
handleLogEvent(WEEKLYCALENDAR_DAYITEM_CLICK_EVENT, {
time: new Date().toISOString(),
@@ -127,6 +118,7 @@ const WeeklyCalendar = memo(() => {
const theme = useTheme();
const { userId } = useContext(LoginContext);
const { data: todos = [] } = useTodosQuery();
+ const { data: categories = [] } = useCategoriesQuery();
const { i18n } = useTranslation();
// 주간 날짜 계산 메모이제이션
@@ -187,6 +179,38 @@ const WeeklyCalendar = memo(() => {
}
}, [weekDates, setSelectedDate, currentDate]);
+ // 일주일치 할일 필터링을 위한 메모이제이션 추가
+ const filteredWeekTodos = useMemo(() => {
+ const startDate = weekDates[0].format('YYYY-MM-DD');
+ const endDate = weekDates[6].format('YYYY-MM-DD');
+
+ return todos.filter(todo => {
+ // 카테고리 체크
+ const isCategoryValid = categories.some(
+ category => category.id === todo.categoryId,
+ );
+ // 날짜가 해당 주에 포함되는지 체크
+ const isDateInRange = moment(todo.date).isBetween(
+ startDate,
+ endDate,
+ 'day',
+ '[]',
+ );
+ // 완료되지 않은 할일만 필터링
+ return !todo.isCompleted && isCategoryValid && isDateInRange;
+ });
+ }, [todos, categories, weekDates]);
+
+ // DayItem 컴포넌트에 전달할 할일 개수 계산 함수
+ const getTodoCountForDate = useCallback(
+ date => {
+ return filteredWeekTodos.filter(todo =>
+ isTodoIncludedInTodayView(todo.date, date.format('YYYY-MM-DD')),
+ ).length;
+ },
+ [filteredWeekTodos],
+ );
+
return (
@@ -234,7 +258,7 @@ const WeeklyCalendar = memo(() => {
date={date}
selectedDate={selectedDate}
theme={theme}
- todos={todos}
+ todoCount={getTodoCountForDate(date)}
onDateSelect={handleDateSelect}
userId={userId}
i18n={i18n}
From 6902b1bcefc69179e71c4e1dc383a59d999919b1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EA=B3=A0=EB=B3=91=EC=B0=AC?=
<70642609+byungchanKo99@users.noreply.github.com>
Date: Sat, 23 Nov 2024 03:23:46 +0900
Subject: [PATCH 04/12] =?UTF-8?q?[SZ-553]feat:=20optimistic=20ui=20?=
=?UTF-8?q?=EC=A0=81=EC=9A=A9=20=EC=A4=91?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../common/molecules/EditableTextField.tsx | 53 +++++---
.../todoMoreMenu/useTodoMoreMenu.tsx | 4 +-
.../dailyTodo/todoListItem/useTodoListItem.ts | 16 ++-
hooks/api/useTodoMutations.js | 55 --------
hooks/api/useTodoMutations.ts | 126 ++++++++++++++++++
hooks/api/useTodoQuery.js | 2 +-
6 files changed, 171 insertions(+), 85 deletions(-)
delete mode 100644 hooks/api/useTodoMutations.js
create mode 100644 hooks/api/useTodoMutations.ts
diff --git a/components/common/molecules/EditableTextField.tsx b/components/common/molecules/EditableTextField.tsx
index 3d6aa46..255fa4b 100644
--- a/components/common/molecules/EditableTextField.tsx
+++ b/components/common/molecules/EditableTextField.tsx
@@ -1,8 +1,9 @@
import { Text } from '@ui-kitten/components';
-import React, { useState } from 'react';
+import React, { useState, useCallback } from 'react';
import { StyleProp, StyleSheet, TextInput, TextStyle } from 'react-native';
import { Todo } from '../../../types/todo';
import { moderateScale, scale } from 'react-native-size-matters';
+import { memo } from 'react';
interface EditableListItemTitleProps {
isEditing: boolean;
@@ -12,26 +13,36 @@ interface EditableListItemTitleProps {
textStyles?: StyleProp | null;
}
-const EditableTextField = ({
- isEditing,
- handleSubmitEditing,
- item,
- inputStyles = styles.input,
- textStyles = styles.text,
-}: EditableListItemTitleProps) => {
- const [content, setContent] = useState(item.content);
- return isEditing ? (
- handleSubmitEditing(content)}
- autoFocus={true}
- style={inputStyles}
- />
- ) : (
- {item.content}
- );
-};
+const EditableTextField = memo(
+ ({
+ isEditing,
+ handleSubmitEditing,
+ item,
+ inputStyles = styles.input,
+ textStyles = styles.text,
+ }: EditableListItemTitleProps) => {
+ const [content, setContent] = useState(item.content);
+
+ const onSubmit = useCallback(() => {
+ handleSubmitEditing(content);
+ }, [content, handleSubmitEditing]);
+
+ const onChangeText = useCallback((text: string) => {
+ setContent(text);
+ }, []);
+ console.log(content);
+ return isEditing ? (
+
+ ) : (
+ {content}
+ );
+ },
+);
export default EditableTextField;
diff --git a/components/inboxView/inboxTodos/inboxTodo/todoListItem/todoMoreMenu/useTodoMoreMenu.tsx b/components/inboxView/inboxTodos/inboxTodo/todoListItem/todoMoreMenu/useTodoMoreMenu.tsx
index dea7a21..5178b46 100644
--- a/components/inboxView/inboxTodos/inboxTodo/todoListItem/todoMoreMenu/useTodoMoreMenu.tsx
+++ b/components/inboxView/inboxTodos/inboxTodo/todoListItem/todoMoreMenu/useTodoMoreMenu.tsx
@@ -38,8 +38,8 @@ const useTodoMoreMenu = ({
const updatedTodo = {
date: kstDate,
- todo_id: item.id,
- category_id: selectedCategory,
+ todoId: item.id,
+ categoryId: selectedCategory,
};
updateTodoDate(updatedTodo);
};
diff --git a/components/todayView/dailyTodos/dailyTodo/todoListItem/useTodoListItem.ts b/components/todayView/dailyTodos/dailyTodo/todoListItem/useTodoListItem.ts
index cb309ca..98383f0 100644
--- a/components/todayView/dailyTodos/dailyTodo/todoListItem/useTodoListItem.ts
+++ b/components/todayView/dailyTodos/dailyTodo/todoListItem/useTodoListItem.ts
@@ -1,6 +1,6 @@
import { TextInputContext } from '@/contexts/textInputContext';
import { useTheme } from '@ui-kitten/components';
-import { useContext } from 'react';
+import { useContext, useCallback } from 'react';
import { LoginContext } from '../../../../../contexts/LoginContext';
import { useTodoUpdateMutation } from '../../../../../hooks/api/useTodoMutations';
import {
@@ -48,6 +48,7 @@ const useTodoListItem = ({
});
};
+ // eslint-disable-next-line react-hooks/exhaustive-deps
const handleTodoContentUpdate = content => {
const updatedData = {
todoId: item.id,
@@ -56,11 +57,14 @@ const useTodoListItem = ({
updateTodo(updatedData);
};
- const handleTodoListItemSubmitEditing = content => {
- handleTodoContentUpdate(content);
- setIsEditing(false);
- setTodayTextInputOpen(false);
- };
+ const handleTodoListItemSubmitEditing = useCallback(
+ (content: string) => {
+ handleTodoContentUpdate(content);
+ setTodayTextInputOpen(false);
+ setIsEditing(false);
+ },
+ [handleTodoContentUpdate, setTodayTextInputOpen, setIsEditing],
+ );
const handleGenerateIconPress = () => {
setIsSubTodoGenerateModalVisible(true);
diff --git a/hooks/api/useTodoMutations.js b/hooks/api/useTodoMutations.js
deleted file mode 100644
index 3ef1b5a..0000000
--- a/hooks/api/useTodoMutations.js
+++ /dev/null
@@ -1,55 +0,0 @@
-import { api as Api } from '@/utils/api';
-import { useMutation, useQueryClient } from '@tanstack/react-query';
-import { INBOX_QUERY_KEY } from './useInboxTodoQuery';
-import { TODO_QUERY_KEY } from './useTodoQuery';
-
-// 생성 (Add Todo)
-const addTodoFetcher = async todoData => {
- const data = await Api.addTodo(todoData);
- return data;
-};
-
-export const useTodoAddMutation = () => {
- const queryClient = useQueryClient();
- return useMutation({
- mutationFn: addTodoFetcher,
- onSuccess: () => {
- queryClient.invalidateQueries({ queryKey: [TODO_QUERY_KEY] });
- queryClient.invalidateQueries({ queryKey: [INBOX_QUERY_KEY] });
- },
- });
-};
-
-// 수정 (Update Todo)
-const updateTodoFetcher = async updatedData => {
- const data = await Api.updateTodo(updatedData);
- return data;
-};
-
-export const useTodoUpdateMutation = () => {
- const queryClient = useQueryClient();
- return useMutation({
- mutationFn: updateTodoFetcher,
- onSuccess: () => {
- queryClient.invalidateQueries({ queryKey: [TODO_QUERY_KEY] });
- queryClient.invalidateQueries({ queryKey: [INBOX_QUERY_KEY] });
- },
- });
-};
-
-// 삭제 (Delete Todo)
-const deleteTodoFetcher = async todoId => {
- const data = await Api.deleteTodo(todoId.todoId);
- return data;
-};
-
-export const useTodoDeleteMutation = () => {
- const queryClient = useQueryClient();
- return useMutation({
- mutationFn: deleteTodoFetcher,
- onSuccess: () => {
- queryClient.invalidateQueries({ queryKey: [TODO_QUERY_KEY] });
- queryClient.invalidateQueries({ queryKey: [INBOX_QUERY_KEY] });
- },
- });
-};
diff --git a/hooks/api/useTodoMutations.ts b/hooks/api/useTodoMutations.ts
new file mode 100644
index 0000000..dac84f7
--- /dev/null
+++ b/hooks/api/useTodoMutations.ts
@@ -0,0 +1,126 @@
+import { api as Api } from '@/utils/api';
+import { useMutation, useQueryClient } from '@tanstack/react-query';
+import { INBOX_QUERY_KEY } from './useInboxTodoQuery';
+import { TODO_QUERY_KEY } from './useTodoQuery';
+import { Todo } from '@/types/todo';
+
+const addTodoFetcher = async (todoData: Omit) => {
+ const data = await Api.addTodo(todoData);
+ return data;
+};
+
+export const useTodoAddMutation = () => {
+ const queryClient = useQueryClient();
+ return useMutation({
+ mutationFn: addTodoFetcher,
+ onMutate: async newTodo => {
+ await queryClient.cancelQueries({ queryKey: [TODO_QUERY_KEY] });
+ await queryClient.cancelQueries({ queryKey: [INBOX_QUERY_KEY] });
+
+ const previousTodos = queryClient.getQueryData([TODO_QUERY_KEY]);
+ const previousInbox = queryClient.getQueryData([INBOX_QUERY_KEY]);
+
+ const optimisticTodo: Todo = {
+ ...newTodo,
+ id: Date.now(),
+ children: [],
+ };
+
+ queryClient.setQueryData([TODO_QUERY_KEY], old => [
+ ...(old || []),
+ optimisticTodo,
+ ]);
+ queryClient.setQueryData([INBOX_QUERY_KEY], old => [
+ ...(old || []),
+ optimisticTodo,
+ ]);
+
+ return { previousTodos, previousInbox };
+ },
+ onError: (_err, _newTodo, context) => {
+ queryClient.setQueryData([TODO_QUERY_KEY], context?.previousTodos);
+ queryClient.setQueryData([INBOX_QUERY_KEY], context?.previousInbox);
+ },
+ onSuccess: () => {
+ queryClient.invalidateQueries({ queryKey: [TODO_QUERY_KEY] });
+ queryClient.invalidateQueries({ queryKey: [INBOX_QUERY_KEY] });
+ },
+ });
+};
+
+const updateTodoFetcher = async (
+ updatedData: Partial & { todoId: number },
+) => {
+ const data = await Api.updateTodo(updatedData);
+ return data;
+};
+
+export const useTodoUpdateMutation = () => {
+ const queryClient = useQueryClient();
+ return useMutation({
+ mutationFn: updateTodoFetcher,
+ onMutate: async updatedTodo => {
+ await queryClient.cancelQueries({ queryKey: [TODO_QUERY_KEY] });
+ await queryClient.cancelQueries({ queryKey: [INBOX_QUERY_KEY] });
+
+ const previousTodos = queryClient.getQueryData([TODO_QUERY_KEY]);
+ const previousInbox = queryClient.getQueryData([INBOX_QUERY_KEY]);
+
+ const updateTodo = (old: Todo[] | undefined) =>
+ old?.map(todo => {
+ if (todo.id === updatedTodo.todoId) {
+ return { ...todo, ...updatedTodo };
+ }
+ return todo;
+ }) || [];
+
+ queryClient.setQueryData([TODO_QUERY_KEY], updateTodo);
+ queryClient.setQueryData([INBOX_QUERY_KEY], updateTodo);
+
+ return { previousTodos, previousInbox };
+ },
+ onError: (_err, _updatedTodo, context) => {
+ queryClient.setQueryData([TODO_QUERY_KEY], context?.previousTodos);
+ queryClient.setQueryData([INBOX_QUERY_KEY], context?.previousInbox);
+ },
+ onSuccess: () => {
+ queryClient.refetchQueries({ queryKey: [TODO_QUERY_KEY] });
+ queryClient.refetchQueries({ queryKey: [INBOX_QUERY_KEY] });
+ },
+ });
+};
+
+const deleteTodoFetcher = async ({ todoId }: { todoId: number }) => {
+ const data = await Api.deleteTodo(todoId);
+ return data;
+};
+
+export const useTodoDeleteMutation = () => {
+ const queryClient = useQueryClient();
+ return useMutation({
+ mutationFn: deleteTodoFetcher,
+ onMutate: async ({ todoId }) => {
+ await queryClient.cancelQueries({ queryKey: [TODO_QUERY_KEY] });
+ await queryClient.cancelQueries({ queryKey: [INBOX_QUERY_KEY] });
+
+ const previousTodos = queryClient.getQueryData([TODO_QUERY_KEY]);
+ const previousInbox = queryClient.getQueryData([INBOX_QUERY_KEY]);
+
+ const deleteTodo = (old: Todo[] | undefined) =>
+ old?.filter(todo => todo.id !== todoId) || [];
+
+ queryClient.setQueryData([TODO_QUERY_KEY], deleteTodo);
+ queryClient.setQueryData([INBOX_QUERY_KEY], deleteTodo);
+
+ return { previousTodos, previousInbox };
+ },
+ onError: (_err, _variables, context) => {
+ queryClient.setQueryData([TODO_QUERY_KEY], context?.previousTodos);
+ queryClient.setQueryData([INBOX_QUERY_KEY], context?.previousInbox);
+ },
+ onSuccess: () => {
+ queryClient.invalidateQueries({ queryKey: [TODO_QUERY_KEY] });
+ queryClient.invalidateQueries({ queryKey: [INBOX_QUERY_KEY] });
+ },
+ });
+};
diff --git a/hooks/api/useTodoQuery.js b/hooks/api/useTodoQuery.js
index 3e5f6f6..5081d57 100644
--- a/hooks/api/useTodoQuery.js
+++ b/hooks/api/useTodoQuery.js
@@ -1,4 +1,3 @@
-// useTodosQuery.js
import { api as Api } from '@/utils/api';
import { useQuery } from '@tanstack/react-query';
@@ -18,6 +17,7 @@ const useTodosQuery = userId => {
refetchIntervalInBackground: true,
cacheTime: 180000,
staleTime: 30000,
+ keepPreviousData: true,
});
};
From 8272c4627c5ae8deb82ff770cabbe71b0687aa9f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EA=B3=A0=EB=B3=91=EC=B0=AC?=
<70642609+byungchanKo99@users.noreply.github.com>
Date: Sat, 23 Nov 2024 04:27:26 +0900
Subject: [PATCH 05/12] =?UTF-8?q?[SZ-553]feat:=20=EC=B5=9C=EC=A0=81?=
=?UTF-8?q?=ED=99=94=20=EC=A4=91?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/(tabs)/_layout.jsx | 60 ++++----
components/categoryView/CategoryMainItem.jsx | 11 +-
.../common/molecules/EditableTextField.tsx | 1 +
.../inboxView/inboxTodos/InboxTodos.tsx | 8 +-
.../inboxTodos/inboxTodo/InboxTodo.jsx | 8 +-
.../inboxTodo/subTodoList/InboxSubTodo.jsx | 6 +-
.../inboxTodo/todoListItem/useTodoListItem.ts | 6 +-
.../todayView/dailyTodos/DailyTodos.tsx | 8 +-
.../dailyTodos/dailyTodo/DailyTodo.jsx | 24 +--
.../dailyTodo/subTodoInfo/SubTodoInfo.tsx | 1 +
.../dailyTodo/subTodoList/DailySubTodo.jsx | 6 +-
.../dailyTodo/todoListItem/TodoListItem.tsx | 139 +++++++++---------
.../todoMoreMenu/TodoMoreMenu.tsx | 6 +-
.../todoMoreMenu/useTodoMoreMenu.tsx | 12 +-
.../dailyTodo/todoListItem/useTodoListItem.ts | 21 +--
contexts/textInputContext.js | 31 ----
contexts/textInputStore.js | 17 +++
contexts/todoEditStore.ts | 18 +++
18 files changed, 178 insertions(+), 205 deletions(-)
delete mode 100644 contexts/textInputContext.js
create mode 100644 contexts/textInputStore.js
create mode 100644 contexts/todoEditStore.ts
diff --git a/app/(tabs)/_layout.jsx b/app/(tabs)/_layout.jsx
index bee5029..cd7d929 100644
--- a/app/(tabs)/_layout.jsx
+++ b/app/(tabs)/_layout.jsx
@@ -1,4 +1,3 @@
-import TextInputProvider from '@/contexts/textInputContext';
import '@/locales/index';
import { Tabs } from 'expo-router';
import React from 'react';
@@ -19,38 +18,35 @@ const inboxIcon = ({ color, size }) => (
const TabLayout = () => {
const { t } = useTranslation();
return (
-
-
+
-
-
-
-
+ />
+
+
);
};
diff --git a/components/categoryView/CategoryMainItem.jsx b/components/categoryView/CategoryMainItem.jsx
index e26fbba..30fab8a 100644
--- a/components/categoryView/CategoryMainItem.jsx
+++ b/components/categoryView/CategoryMainItem.jsx
@@ -1,7 +1,6 @@
-import { TextInputContext } from '@/contexts/textInputContext';
+import useTextInputStore from '@/contexts/textInputStore';
import colors from '@/theme/theme.json';
import { Icon } from '@ui-kitten/components';
-import { useContext } from 'react';
import { Pressable, StyleSheet, View } from 'react-native';
import { scale, verticalScale } from 'react-native-size-matters';
import CategoryButton from './CategoryButton';
@@ -12,7 +11,13 @@ const CategoryMainItem = ({ item, isToday = true }) => {
setTodayActivatedCategoryId,
setInboxTextInputOpen,
setInboxActivatedCategoryId,
- } = useContext(TextInputContext);
+ } = useTextInputStore(state => ({
+ setTodayTextInputOpen: state.setTodayTextInputOpen,
+ setTodayActivatedCategoryId: state.setTodayActivatedCategoryId,
+ setInboxTextInputOpen: state.setInboxTextInputOpen,
+ setInboxActivatedCategoryId: state.setInboxActivatedCategoryId,
+ }));
+
const handlePress = () => {
if (isToday) {
setTodayTextInputOpen(true);
diff --git a/components/common/molecules/EditableTextField.tsx b/components/common/molecules/EditableTextField.tsx
index 255fa4b..76e5754 100644
--- a/components/common/molecules/EditableTextField.tsx
+++ b/components/common/molecules/EditableTextField.tsx
@@ -37,6 +37,7 @@ const EditableTextField = memo(
onChangeText={onChangeText}
onSubmitEditing={onSubmit}
style={inputStyles}
+ autoFocus={true}
/>
) : (
{content}
diff --git a/components/inboxView/inboxTodos/InboxTodos.tsx b/components/inboxView/inboxTodos/InboxTodos.tsx
index 088076e..66d4160 100644
--- a/components/inboxView/inboxTodos/InboxTodos.tsx
+++ b/components/inboxView/inboxTodos/InboxTodos.tsx
@@ -1,5 +1,5 @@
import { LoginContext } from '@/contexts/LoginContext';
-import { TextInputContext } from '@/contexts/textInputContext';
+import useTextInputStore from '@/contexts/textInputStore';
import { useTodoUpdateMutation } from '@/hooks/api/useTodoMutations';
import useCreateInboxTodo from '@/hooks/todo/useCreateInboxTodo';
import useFilteredInboxTodos from '@/hooks/todo/useFilteredInboxTodo';
@@ -42,7 +42,11 @@ const InboxTodos = ({ todosData, categoryId }) => {
isInboxTextInputOpen,
inboxActivatedCategoryId,
setInboxTextInputOpen,
- } = useContext(TextInputContext);
+ } = useTextInputStore(state => ({
+ isInboxTextInputOpen: state.isInboxTextInputOpen,
+ inboxActivatedCategoryId: state.inboxActivatedCategoryId,
+ setInboxTextInputOpen: state.setInboxTextInputOpen,
+ }));
const { input, setInput, handleSubmit } = useCreateInboxTodo(
userId,
categoryId,
diff --git a/components/inboxView/inboxTodos/inboxTodo/InboxTodo.jsx b/components/inboxView/inboxTodos/inboxTodo/InboxTodo.jsx
index 4082d04..ba0e1c3 100644
--- a/components/inboxView/inboxTodos/inboxTodo/InboxTodo.jsx
+++ b/components/inboxView/inboxTodos/inboxTodo/InboxTodo.jsx
@@ -1,14 +1,14 @@
import SubTodoGenerateModal from '@/components/SubTodoGenerateModal';
import GeneratedSubTodoList from '@/components/todayView/dailyTodos/dailyTodo/generatedSubTodoList/GeneratedSubTodoList';
-import { TextInputContext } from '@/contexts/textInputContext';
import '@/locales/index';
-import React, { useContext } from 'react';
+import React from 'react';
import { View } from 'react-native';
import useModal from '../../../../hooks/common/useModal';
import SubTodoInfo from './subTodoInfo/SubTodoInfo';
import SubTodoList from './subTodoList/SubTodoList';
import TodoListItem from './todoListItem/TodoListItem';
import useInboxTodo from './useInboxTodo';
+import useTextInputStore from '@/contexts/textInputStore';
const InboxTodo = ({ item, drag, isActive }) => {
const {
@@ -22,7 +22,9 @@ const InboxTodo = ({ item, drag, isActive }) => {
setGeneratedSubTodos,
} = useInboxTodo();
- const { setInboxTextInputOpen } = useContext(TextInputContext);
+ const { setInboxTextInputOpen } = useTextInputStore(
+ state => state.setInboxTextInputOpen,
+ );
const {
isVisible: isSubTodoGenerateModalVisible,
diff --git a/components/inboxView/inboxTodos/inboxTodo/subTodoList/InboxSubTodo.jsx b/components/inboxView/inboxTodos/inboxTodo/subTodoList/InboxSubTodo.jsx
index 226b07c..236cfa3 100644
--- a/components/inboxView/inboxTodos/inboxTodo/subTodoList/InboxSubTodo.jsx
+++ b/components/inboxView/inboxTodos/inboxTodo/subTodoList/InboxSubTodo.jsx
@@ -1,5 +1,5 @@
import { LoginContext } from '@/contexts/LoginContext';
-import { TextInputContext } from '@/contexts/textInputContext';
+import useTextInputStore from '@/contexts/textInputStore';
import { useSubTodoUpdateMutation } from '@/hooks/api/useSubTodoMutations';
import {
handleLogEvent,
@@ -17,7 +17,9 @@ const InboxSubTodo = ({ item }) => {
const theme = useTheme();
const { mutate: updateSubTodo } = useSubTodoUpdateMutation();
const { userId } = useContext(LoginContext);
- const { setInboxTextInputOpen } = useContext(TextInputContext);
+ const { setInboxTextInputOpen } = useTextInputStore(
+ state => state.setInboxTextInputOpen,
+ );
const handleEdit = () => {
setIsEditing(true);
diff --git a/components/inboxView/inboxTodos/inboxTodo/todoListItem/useTodoListItem.ts b/components/inboxView/inboxTodos/inboxTodo/todoListItem/useTodoListItem.ts
index b454cc4..50f4044 100644
--- a/components/inboxView/inboxTodos/inboxTodo/todoListItem/useTodoListItem.ts
+++ b/components/inboxView/inboxTodos/inboxTodo/todoListItem/useTodoListItem.ts
@@ -1,4 +1,4 @@
-import { TextInputContext } from '@/contexts/textInputContext';
+import useTextInputStore from '@/contexts/textInputStore';
import { useTheme } from '@ui-kitten/components';
import { useContext } from 'react';
import { LoginContext } from '../../../../../contexts/LoginContext';
@@ -19,7 +19,9 @@ const useTodoListItem = ({
const { mutate: updateTodo } = useTodoUpdateMutation();
const { userId } = useContext(LoginContext);
const theme = useTheme();
- const { setInboxTextInputOpen } = useContext(TextInputContext);
+ const { setInboxTextInputOpen } = useTextInputStore(
+ state => state.setInboxTextInputOpen,
+ );
const checkIconlogPressEvent = () => {
handleLogEvent(DAILYTODO_TODOCOMPLETE_CLICK_EVENT, {
diff --git a/components/todayView/dailyTodos/DailyTodos.tsx b/components/todayView/dailyTodos/DailyTodos.tsx
index af5e588..ad0b4de 100644
--- a/components/todayView/dailyTodos/DailyTodos.tsx
+++ b/components/todayView/dailyTodos/DailyTodos.tsx
@@ -1,6 +1,6 @@
import { DateContext } from '@/contexts/DateContext';
import { LoginContext } from '@/contexts/LoginContext';
-import { TextInputContext } from '@/contexts/textInputContext';
+import useTextInputStore from '@/contexts/textInputStore';
import useCreateTodo from '@/hooks/todo/useCreateTodo';
import useFilteredTodos from '@/hooks/todo/useFilteredTodo';
import useHandleDrag from '@/hooks/todo/useHandleDrag';
@@ -47,7 +47,11 @@ const DailyTodos = ({ todosData, categoryId, onDragStart, onDragEnd }) => {
isTodayTextInputOpen,
todayActivatedCategoryId,
setTodayTextInputOpen,
- } = useContext(TextInputContext);
+ } = useTextInputStore(state => ({
+ isTodayTextInputOpen: state.isTodayTextInputOpen,
+ todayActivatedCategoryId: state.todayActivatedCategoryId,
+ setTodayTextInputOpen: state.setTodayTextInputOpen,
+ }));
const handleDragEnd = useHandleDrag();
diff --git a/components/todayView/dailyTodos/dailyTodo/DailyTodo.jsx b/components/todayView/dailyTodos/dailyTodo/DailyTodo.jsx
index 64501f8..d6c1a75 100644
--- a/components/todayView/dailyTodos/dailyTodo/DailyTodo.jsx
+++ b/components/todayView/dailyTodos/dailyTodo/DailyTodo.jsx
@@ -1,8 +1,5 @@
-import { TextInputContext } from '@/contexts/textInputContext';
import '@/locales/index';
-import { useContext } from 'react';
import { View } from 'react-native';
-import useModal from '../../../../hooks/common/useModal';
import SubTodoInfo from './subTodoInfo/SubTodoInfo';
import SubTodoList from './subTodoList/SubTodoList';
import TodoListItem from './todoListItem/TodoListItem';
@@ -10,37 +7,18 @@ import useDailyTodo from './useDailyTodo';
const DailyTodo = ({ item, drag, isActive, categoryId }) => {
const {
- isEditing,
- setIsEditing,
isSubtodoToggleActivated,
setIsSubTodoToggleActivated,
subTodoInputActivated,
setSubTodoInputActivated,
} = useDailyTodo();
- const { setIsVisible: setIsSubTodoGenerateModalVisible } = useModal();
- const { setTodayTextInputOpen } = useContext(TextInputContext);
-
- const { setIsVisible: setIsTodoModalVisible } = useModal();
-
- const handleEdit = () => {
- setIsEditing(true);
- setTodayTextInputOpen(false);
- setIsTodoModalVisible(false);
- };
-
return (
0}
- onEdit={handleEdit}
+ item={item}
setSubTodoInputActivated={setSubTodoInputActivated}
categoryId={categoryId}
/>
diff --git a/components/todayView/dailyTodos/dailyTodo/subTodoInfo/SubTodoInfo.tsx b/components/todayView/dailyTodos/dailyTodo/subTodoInfo/SubTodoInfo.tsx
index c3c3e62..d13629e 100644
--- a/components/todayView/dailyTodos/dailyTodo/subTodoInfo/SubTodoInfo.tsx
+++ b/components/todayView/dailyTodos/dailyTodo/subTodoInfo/SubTodoInfo.tsx
@@ -48,6 +48,7 @@ const SubTodoInfo: React.FC = ({
const styles = StyleSheet.create({
container: {
paddingTop: 0,
+ paddingRight: scale(2),
},
bottomContainer: {
flexDirection: 'row',
diff --git a/components/todayView/dailyTodos/dailyTodo/subTodoList/DailySubTodo.jsx b/components/todayView/dailyTodos/dailyTodo/subTodoList/DailySubTodo.jsx
index ddb437e..b5b5cb8 100644
--- a/components/todayView/dailyTodos/dailyTodo/subTodoList/DailySubTodo.jsx
+++ b/components/todayView/dailyTodos/dailyTodo/subTodoList/DailySubTodo.jsx
@@ -1,6 +1,6 @@
import EditableTextField from '@/components/common/molecules/EditableTextField';
import { LoginContext } from '@/contexts/LoginContext';
-import { TextInputContext } from '@/contexts/textInputContext';
+import useTextInputStore from '@/contexts/textInputStore';
import { useSubTodoUpdateMutation } from '@/hooks/api/useSubTodoMutations';
import getIconFillColor from '@/utils/getIconFillColor';
import {
@@ -18,7 +18,9 @@ const DailySubTodo = ({ item }) => {
const [isEditing, setIsEditing] = useState(false);
const { mutate: updateSubTodo } = useSubTodoUpdateMutation();
const { userId } = useContext(LoginContext);
- const { setTodayTextInputOpen } = useContext(TextInputContext);
+ const { setTodayTextInputOpen } = useTextInputStore(
+ state => state.setTodayTextInputOpen,
+ );
const handleEdit = () => {
setIsEditing(true);
diff --git a/components/todayView/dailyTodos/dailyTodo/todoListItem/TodoListItem.tsx b/components/todayView/dailyTodos/dailyTodo/todoListItem/TodoListItem.tsx
index a16e3ba..52decc0 100644
--- a/components/todayView/dailyTodos/dailyTodo/todoListItem/TodoListItem.tsx
+++ b/components/todayView/dailyTodos/dailyTodo/todoListItem/TodoListItem.tsx
@@ -1,6 +1,6 @@
import getIconFillColor from '@/utils/getIconFillColor';
import { Icon, ListItem, Text } from '@ui-kitten/components';
-import React from 'react';
+import React, { useCallback } from 'react';
import { Pressable, StyleSheet, View } from 'react-native';
import { RenderItemParams } from 'react-native-draggable-flatlist';
import { moderateScale, scale, verticalScale } from 'react-native-size-matters';
@@ -24,80 +24,73 @@ interface TodoListItemProps extends RenderItemParams {
categoryId: number;
}
-const TodoListItem: React.FC = ({
- item,
- drag,
+const TodoListItem: React.FC = React.memo(
+ ({ item, drag, isActive, setSubTodoInputActivated, categoryId }) => {
+ const {
+ isEditing,
+ setIsEditing,
+ theme,
+ handleCheckIconPress,
+ handleTodoListItemPress,
+ handleTodoListItemSubmitEditing,
+ } = useTodoListItem({
+ item,
+ });
- isActive,
- isEditing,
- setIsEditing,
- setIsSubTodoGenerateModalVisible,
- onEdit,
- setSubTodoInputActivated,
- categoryId,
-}) => {
- const {
- theme,
- handleCheckIconPress,
- handleTodoListItemPress,
- handleTodoListItemSubmitEditing,
- } = useTodoListItem({
- item,
- isEditing,
- setIsEditing,
- setIsSubTodoGenerateModalVisible,
- });
+ const accessoryLeft = useCallback(
+ (props?) => {
+ return (
+
+
+
+ );
+ },
+ [handleCheckIconPress, item.isCompleted],
+ );
- const accessoryLeft = (props?) => {
- return (
- handleCheckIconPress()}
- style={styles.touchableCheck}
- >
- {
+ return (
+
-
- );
- };
+ );
+ }, [item, setSubTodoInputActivated, categoryId, setIsEditing]);
- const accessoryRight = () => {
- return (
-
+ const title = useCallback(
+ () => (
+
+
+ {item.dueTime && (
+
+ {item.dueTime.split(':').slice(0, 2).join(':')}
+
+ )}
+
+ ),
+ [isEditing, handleTodoListItemSubmitEditing, item, theme],
);
- };
- const title = () => (
-
-
- {item.dueTime && (
-
- {item.dueTime.split(':').slice(0, 2).join(':')}
-
- )}
-
- );
-
- return (
- <>
+ return (
= ({
disabled={isActive}
title={title}
/>
- >
- );
-};
+ );
+ },
+);
const styles = StyleSheet.create({
checkIcon: {
@@ -132,4 +125,4 @@ const styles = StyleSheet.create({
},
});
-export default TodoListItem;
+export default React.memo(TodoListItem);
diff --git a/components/todayView/dailyTodos/dailyTodo/todoListItem/todoMoreMenu/TodoMoreMenu.tsx b/components/todayView/dailyTodos/dailyTodo/todoListItem/todoMoreMenu/TodoMoreMenu.tsx
index f5e308a..533712b 100644
--- a/components/todayView/dailyTodos/dailyTodo/todoListItem/todoMoreMenu/TodoMoreMenu.tsx
+++ b/components/todayView/dailyTodos/dailyTodo/todoListItem/todoMoreMenu/TodoMoreMenu.tsx
@@ -49,11 +49,10 @@ const MenuIconButton = onPress => (
);
const TodoMoreMenu = ({
- setIsSubTodoGenerateModalVisible,
- onEdit,
item,
setSubTodoInputActivated,
categoryId,
+ setIsEditing,
}) => {
const {
handleEditPress,
@@ -61,11 +60,10 @@ const TodoMoreMenu = ({
handleCreateSubTodoPress: handleAddSubTodoPress,
handlePutTodoToInboxPress,
} = useTodoMoreMenu({
- setIsSubTodoGenerateModalVisible,
- onEdit,
item,
setSubTodoInputActivated,
categoryId,
+ setIsEditing,
});
const [visible, setVisible] = useState(false);
const { t } = useTranslation();
diff --git a/components/todayView/dailyTodos/dailyTodo/todoListItem/todoMoreMenu/useTodoMoreMenu.tsx b/components/todayView/dailyTodos/dailyTodo/todoListItem/todoMoreMenu/useTodoMoreMenu.tsx
index 7578ca8..b720696 100644
--- a/components/todayView/dailyTodos/dailyTodo/todoListItem/todoMoreMenu/useTodoMoreMenu.tsx
+++ b/components/todayView/dailyTodos/dailyTodo/todoListItem/todoMoreMenu/useTodoMoreMenu.tsx
@@ -16,10 +16,9 @@ import { useContext } from 'react';
const useTodoMoreMenu = ({
item,
- onEdit = () => {},
- setIsSubTodoGenerateModalVisible,
setSubTodoInputActivated,
categoryId,
+ setIsEditing,
}) => {
const { userId } = useContext(LoginContext);
@@ -37,7 +36,7 @@ const useTodoMoreMenu = ({
const updatedTodo = {
date: kstDate,
- todo_id: item.id,
+ todoId: item.id,
category_id: categoryId,
};
updateTodoDate(updatedTodo);
@@ -49,7 +48,7 @@ const useTodoMoreMenu = ({
userId: userId,
todoId: item.id,
});
- onEdit();
+ setIsEditing(true);
};
const handleDeletePress = () => {
@@ -69,10 +68,6 @@ const useTodoMoreMenu = ({
});
};
- const handleGenerateSubTodoPress = () => {
- setIsSubTodoGenerateModalVisible(true);
- };
-
const handleCreateSubTodoPress = () => {
handleLogEvent(TODOMODAL_CREATESUBTODO_CLICK_EVENT, {
time: new Date().toISOString(),
@@ -95,7 +90,6 @@ const useTodoMoreMenu = ({
handleEditPress,
handleDeletePress,
handleChaneDatePress,
- handleGenerateSubTodoPress,
handleCreateSubTodoPress,
handlePutTodoToInboxPress,
};
diff --git a/components/todayView/dailyTodos/dailyTodo/todoListItem/useTodoListItem.ts b/components/todayView/dailyTodos/dailyTodo/todoListItem/useTodoListItem.ts
index 98383f0..eddcf38 100644
--- a/components/todayView/dailyTodos/dailyTodo/todoListItem/useTodoListItem.ts
+++ b/components/todayView/dailyTodos/dailyTodo/todoListItem/useTodoListItem.ts
@@ -1,6 +1,5 @@
-import { TextInputContext } from '@/contexts/textInputContext';
import { useTheme } from '@ui-kitten/components';
-import { useContext, useCallback } from 'react';
+import { useContext, useCallback, useState } from 'react';
import { LoginContext } from '../../../../../contexts/LoginContext';
import { useTodoUpdateMutation } from '../../../../../hooks/api/useTodoMutations';
import {
@@ -10,16 +9,11 @@ import {
handleLogEvent,
} from '../../../../../utils/logEvent';
-const useTodoListItem = ({
- item,
- isEditing,
- setIsEditing,
- setIsSubTodoGenerateModalVisible,
-}) => {
+const useTodoListItem = ({ item }) => {
const { mutate: updateTodo } = useTodoUpdateMutation();
const { userId } = useContext(LoginContext);
const theme = useTheme();
- const { setTodayTextInputOpen } = useContext(TextInputContext);
+ const [isEditing, setIsEditing] = useState(false);
const checkIconlogPressEvent = () => {
handleLogEvent(DAILYTODO_TODOCOMPLETE_CLICK_EVENT, {
@@ -60,16 +54,10 @@ const useTodoListItem = ({
const handleTodoListItemSubmitEditing = useCallback(
(content: string) => {
handleTodoContentUpdate(content);
- setTodayTextInputOpen(false);
setIsEditing(false);
},
- [handleTodoContentUpdate, setTodayTextInputOpen, setIsEditing],
+ [handleTodoContentUpdate, setIsEditing],
);
-
- const handleGenerateIconPress = () => {
- setIsSubTodoGenerateModalVisible(true);
- };
-
const handleSettingIconPress = () => {
handleLogEvent(DAILYTODO_MEATBALLMENU_CLICK_EVENT, {
time: new Date().toISOString(),
@@ -85,7 +73,6 @@ const useTodoListItem = ({
setIsEditing,
handleTodoListItemPress,
handleTodoListItemSubmitEditing,
- handleGenerateIconPress,
handleSettingIconPress,
};
};
diff --git a/contexts/textInputContext.js b/contexts/textInputContext.js
deleted file mode 100644
index bfc925c..0000000
--- a/contexts/textInputContext.js
+++ /dev/null
@@ -1,31 +0,0 @@
-import { createContext, useState } from 'react';
-
-export const TextInputContext = createContext();
-
-const TextInputProvider = ({ children }) => {
- const [isTodayTextInputOpen, setTodayTextInputOpen] = useState(false);
- const [todayActivatedCategoryId, setTodayActivatedCategoryId] =
- useState(null);
- const [isInboxTextInputOpen, setInboxTextInputOpen] = useState(false);
- const [inboxActivatedCategoryId, setInboxActivatedCategoryId] =
- useState(null);
-
- return (
-
- {children}
-
- );
-};
-
-export default TextInputProvider;
diff --git a/contexts/textInputStore.js b/contexts/textInputStore.js
new file mode 100644
index 0000000..8f6d0be
--- /dev/null
+++ b/contexts/textInputStore.js
@@ -0,0 +1,17 @@
+import { create } from 'zustand';
+
+const useTextInputStore = create(set => ({
+ isTodayTextInputOpen: false,
+ setTodayTextInputOpen: isOpen => set({ isTodayTextInputOpen: isOpen }),
+
+ todayActivatedCategoryId: null,
+ setTodayActivatedCategoryId: id => set({ todayActivatedCategoryId: id }),
+
+ isInboxTextInputOpen: false,
+ setInboxTextInputOpen: isOpen => set({ isInboxTextInputOpen: isOpen }),
+
+ inboxActivatedCategoryId: null,
+ setInboxActivatedCategoryId: id => set({ inboxActivatedCategoryId: id }),
+}));
+
+export default useTextInputStore;
diff --git a/contexts/todoEditStore.ts b/contexts/todoEditStore.ts
new file mode 100644
index 0000000..d36b15e
--- /dev/null
+++ b/contexts/todoEditStore.ts
@@ -0,0 +1,18 @@
+import { create } from 'zustand';
+
+interface TodoEditStore {
+ isEditing: boolean;
+ editingTodoId: number | null;
+ isSubTodoModalVisible: boolean;
+ setIsEditing: (isEditing: boolean) => void;
+ setEditingTodoId: (todoId: number | null) => void;
+}
+
+export const useTodoEditStore = create(set => ({
+ isEditing: false,
+ editingTodoId: null,
+ isSubTodoModalVisible: false,
+ isTodayTextInputOpen: false,
+ setIsEditing: isEditing => set({ isEditing }),
+ setEditingTodoId: todoId => set({ editingTodoId: todoId }),
+}));
From 0c145a0f1ab3a1aad09a50c3e756c7a7fe830403 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EA=B3=A0=EB=B3=91=EC=B0=AC?=
<70642609+byungchanKo99@users.noreply.github.com>
Date: Sat, 23 Nov 2024 04:46:53 +0900
Subject: [PATCH 06/12] =?UTF-8?q?[SZ-553]feat:=20=ED=88=AC=EB=91=90=20?=
=?UTF-8?q?=EC=88=98=EC=A0=95=20optimistic=20ui=20=EC=A0=81=EC=9A=A9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../common/molecules/EditableTextField.tsx | 33 +++++++++++++++----
.../dailyTodo/todoListItem/TodoListItem.tsx | 5 ++-
.../dailyTodo/todoListItem/useTodoListItem.ts | 19 +----------
3 files changed, 29 insertions(+), 28 deletions(-)
diff --git a/components/common/molecules/EditableTextField.tsx b/components/common/molecules/EditableTextField.tsx
index 76e5754..c44e7cd 100644
--- a/components/common/molecules/EditableTextField.tsx
+++ b/components/common/molecules/EditableTextField.tsx
@@ -4,38 +4,57 @@ import { StyleProp, StyleSheet, TextInput, TextStyle } from 'react-native';
import { Todo } from '../../../types/todo';
import { moderateScale, scale } from 'react-native-size-matters';
import { memo } from 'react';
+import { useTodoUpdateMutation } from '@/hooks/api/useTodoMutations';
+import {
+ NativeSyntheticEvent,
+ TextInputSubmitEditingEventData,
+} from 'react-native';
interface EditableListItemTitleProps {
isEditing: boolean;
- handleSubmitEditing: (content) => void;
+ setIsEditing: (isEditing: boolean) => void;
item: Todo;
inputStyles?: StyleProp | null;
textStyles?: StyleProp | null;
}
+const handleTodoContentUpdate = (content, item, updateTodo) => {
+ const updatedData = {
+ todoId: item.id,
+ content: content,
+ };
+ updateTodo(updatedData);
+};
+
const EditableTextField = memo(
({
isEditing,
- handleSubmitEditing,
+ setIsEditing,
item,
inputStyles = styles.input,
textStyles = styles.text,
}: EditableListItemTitleProps) => {
const [content, setContent] = useState(item.content);
+ const { mutate: updateTodo } = useTodoUpdateMutation();
- const onSubmit = useCallback(() => {
- handleSubmitEditing(content);
- }, [content, handleSubmitEditing]);
+ const handleTodoListItemSubmitEditing = useCallback(
+ async (e: NativeSyntheticEvent) => {
+ handleTodoContentUpdate(e.nativeEvent.text, item, updateTodo);
+ await new Promise(resolve => setTimeout(resolve, 100)); // 0.1초 대기
+ setIsEditing(false);
+ },
+ [item, setIsEditing, updateTodo],
+ );
const onChangeText = useCallback((text: string) => {
setContent(text);
}, []);
- console.log(content);
+ console.log(content, ' ', item.content);
return isEditing ? (
await handleTodoListItemSubmitEditing(e)}
style={inputStyles}
autoFocus={true}
/>
diff --git a/components/todayView/dailyTodos/dailyTodo/todoListItem/TodoListItem.tsx b/components/todayView/dailyTodos/dailyTodo/todoListItem/TodoListItem.tsx
index 52decc0..d4a9b03 100644
--- a/components/todayView/dailyTodos/dailyTodo/todoListItem/TodoListItem.tsx
+++ b/components/todayView/dailyTodos/dailyTodo/todoListItem/TodoListItem.tsx
@@ -32,7 +32,6 @@ const TodoListItem: React.FC = React.memo(
theme,
handleCheckIconPress,
handleTodoListItemPress,
- handleTodoListItemSubmitEditing,
} = useTodoListItem({
item,
});
@@ -72,7 +71,7 @@ const TodoListItem: React.FC = React.memo(
{item.dueTime && (
@@ -87,7 +86,7 @@ const TodoListItem: React.FC = React.memo(
)}
),
- [isEditing, handleTodoListItemSubmitEditing, item, theme],
+ [isEditing, item, setIsEditing, theme],
);
return (
diff --git a/components/todayView/dailyTodos/dailyTodo/todoListItem/useTodoListItem.ts b/components/todayView/dailyTodos/dailyTodo/todoListItem/useTodoListItem.ts
index eddcf38..fd794c0 100644
--- a/components/todayView/dailyTodos/dailyTodo/todoListItem/useTodoListItem.ts
+++ b/components/todayView/dailyTodos/dailyTodo/todoListItem/useTodoListItem.ts
@@ -1,5 +1,5 @@
import { useTheme } from '@ui-kitten/components';
-import { useContext, useCallback, useState } from 'react';
+import { useContext, useState } from 'react';
import { LoginContext } from '../../../../../contexts/LoginContext';
import { useTodoUpdateMutation } from '../../../../../hooks/api/useTodoMutations';
import {
@@ -42,22 +42,6 @@ const useTodoListItem = ({ item }) => {
});
};
- // eslint-disable-next-line react-hooks/exhaustive-deps
- const handleTodoContentUpdate = content => {
- const updatedData = {
- todoId: item.id,
- content: content,
- };
- updateTodo(updatedData);
- };
-
- const handleTodoListItemSubmitEditing = useCallback(
- (content: string) => {
- handleTodoContentUpdate(content);
- setIsEditing(false);
- },
- [handleTodoContentUpdate, setIsEditing],
- );
const handleSettingIconPress = () => {
handleLogEvent(DAILYTODO_MEATBALLMENU_CLICK_EVENT, {
time: new Date().toISOString(),
@@ -72,7 +56,6 @@ const useTodoListItem = ({ item }) => {
isEditing,
setIsEditing,
handleTodoListItemPress,
- handleTodoListItemSubmitEditing,
handleSettingIconPress,
};
};
From 68a5aafa3c440e4a19600f271327c3536c0fde9c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EA=B3=A0=EB=B3=91=EC=B0=AC?=
<70642609+byungchanKo99@users.noreply.github.com>
Date: Sat, 23 Nov 2024 05:22:21 +0900
Subject: [PATCH 07/12] =?UTF-8?q?[SZ-553]feat:=20=EB=93=9C=EB=9E=98?=
=?UTF-8?q?=EA=B7=B8=EC=95=A4=EB=93=9C=EB=A1=AD=20=EC=98=B5=ED=8B=B0?=
=?UTF-8?q?=EB=AF=B8=EC=8A=A4=ED=8B=B1=20=EC=A0=81=EC=9A=A9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
components/todayView/TextInput.tsx | 64 +++++++++
components/todayView/TodoList.tsx | 56 ++++++++
.../todayView/dailyTodos/DailyTodos.tsx | 130 +++++-------------
hooks/api/useTodoMutations.ts | 43 +++++-
hooks/todo/useFilteredTodo.js | 19 ++-
hooks/todo/useHandleDrag.js | 6 +-
6 files changed, 204 insertions(+), 114 deletions(-)
create mode 100644 components/todayView/TextInput.tsx
create mode 100644 components/todayView/TodoList.tsx
diff --git a/components/todayView/TextInput.tsx b/components/todayView/TextInput.tsx
new file mode 100644
index 0000000..3473971
--- /dev/null
+++ b/components/todayView/TextInput.tsx
@@ -0,0 +1,64 @@
+import React, { memo } from 'react';
+import { TextInput as RNTextInput, View, StyleSheet } from 'react-native';
+import { Icon } from '@ui-kitten/components';
+import { scale, verticalScale, moderateScale } from 'react-native-size-matters';
+import colors from '@/theme/theme.json';
+import { useTranslation } from 'react-i18next';
+
+interface TodoInputProps {
+ input: string;
+ setInput: (text: string) => void;
+ onSubmit: () => void;
+}
+
+const TodoInput = memo(({ input, setInput, onSubmit }: TodoInputProps) => {
+ const { t } = useTranslation();
+
+ return (
+
+
+
+
+
+
+ );
+});
+
+export default TodoInput;
+
+const styles = StyleSheet.create({
+ inputWrapper: {
+ width: '100%',
+ borderTopWidth: StyleSheet.hairlineWidth,
+ borderTopColor: colors.Gray02,
+ backgroundColor: 'white',
+ },
+ inputContainer: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ paddingHorizontal: scale(7),
+ paddingVertical: verticalScale(8),
+ },
+ checkIcon: {
+ width: scale(24),
+ height: verticalScale(24),
+ },
+ textInput: {
+ flex: 1,
+ backgroundColor: colors.Gray02,
+ borderRadius: moderateScale(4),
+ paddingVertical: verticalScale(8),
+ paddingHorizontal: scale(10),
+ },
+});
diff --git a/components/todayView/TodoList.tsx b/components/todayView/TodoList.tsx
new file mode 100644
index 0000000..d7a11a2
--- /dev/null
+++ b/components/todayView/TodoList.tsx
@@ -0,0 +1,56 @@
+import {
+ DEFAULT_SCROLL_EVENT_THROTTLE,
+ handleScroll,
+} from '@/utils/handleScroll';
+import { TODAYVIEW_SCROLL_EVENT } from '@/utils/logEvent';
+import React, { memo } from 'react';
+import { StyleSheet } from 'react-native';
+import DraggableFlatList from 'react-native-draggable-flatlist';
+import { Todo } from '@/types/todo';
+
+const TodoList = memo(
+ ({
+ todos,
+ renderItem,
+ onDragEnd,
+ onDragStart,
+ userId,
+ setTodos,
+ }: {
+ todos: Todo[];
+ renderItem: (info: {
+ item: Todo;
+ drag: () => void;
+ isActive: boolean;
+ }) => React.ReactNode;
+ onDragEnd: (params: { from: number; to: number; data: Todo[] }) => void;
+ onDragStart: () => void;
+ userId: string;
+ setTodos: (todos: Todo[]) => void;
+ }) => (
+ {
+ onDragEnd({ from, to, data });
+ setTodos(data);
+ }}
+ onDragBegin={onDragStart}
+ keyExtractor={item => item.id.toString()}
+ onScroll={() => handleScroll(TODAYVIEW_SCROLL_EVENT, userId)}
+ scrollEventThrottle={DEFAULT_SCROLL_EVENT_THROTTLE}
+ simultaneousHandlers={[]}
+ activationDistance={20}
+ containerStyle={styles.flatListContainer}
+ extraData={todos}
+ />
+ ),
+);
+
+export default TodoList;
+
+const styles = StyleSheet.create({
+ flatListContainer: {
+ flex: 1,
+ },
+});
diff --git a/components/todayView/dailyTodos/DailyTodos.tsx b/components/todayView/dailyTodos/DailyTodos.tsx
index ad0b4de..d7ba23c 100644
--- a/components/todayView/dailyTodos/DailyTodos.tsx
+++ b/components/todayView/dailyTodos/DailyTodos.tsx
@@ -5,67 +5,56 @@ import useCreateTodo from '@/hooks/todo/useCreateTodo';
import useFilteredTodos from '@/hooks/todo/useFilteredTodo';
import useHandleDrag from '@/hooks/todo/useHandleDrag';
import '@/locales/index';
-import colors from '@/theme/theme.json';
-import {
- DEFAULT_SCROLL_EVENT_THROTTLE,
- handleScroll,
-} from '@/utils/handleScroll';
import {
handleLogEvent,
- TODAYVIEW_SCROLL_EVENT,
TODAYVIEW_TEXTINPUT_SUBMIT_EVENT,
} from '@/utils/logEvent';
-import { Icon } from '@ui-kitten/components';
-import React, { useContext } from 'react';
-import { useTranslation } from 'react-i18next';
-import { StyleSheet, TextInput, View } from 'react-native';
-import DraggableFlatList, {
- ScaleDecorator,
-} from 'react-native-draggable-flatlist';
+import React, { useCallback, useContext, useEffect, useState } from 'react';
+import { StyleSheet, View } from 'react-native';
+import { ScaleDecorator } from 'react-native-draggable-flatlist';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
-import { moderateScale, scale, verticalScale } from 'react-native-size-matters';
import DailyTodo from './dailyTodo/DailyTodo';
+import TodoList from '../TodoList';
+import TodoInput from '../TextInput';
const DailyTodos = ({ todosData, categoryId, onDragStart, onDragEnd }) => {
const { userId } = useContext(LoginContext);
const { selectedDate } = useContext(DateContext);
- const { t } = useTranslation();
-
const currentTodos = useFilteredTodos(todosData, categoryId, selectedDate);
+ const [todos, setTodos] = useState(currentTodos);
const { input, setInput, handleSubmit } = useCreateTodo(
userId,
categoryId,
selectedDate,
);
- const handleDragEndWithCallback = ({ data, from, to }) => {
- handleDragEnd({ data, from, to });
- onDragEnd?.();
- };
-
const {
isTodayTextInputOpen,
todayActivatedCategoryId,
setTodayTextInputOpen,
- } = useTextInputStore(state => ({
- isTodayTextInputOpen: state.isTodayTextInputOpen,
- todayActivatedCategoryId: state.todayActivatedCategoryId,
- setTodayTextInputOpen: state.setTodayTextInputOpen,
- }));
+ } = useTextInputStore();
const handleDragEnd = useHandleDrag();
- const handleInputSubmit = () => {
+ const handleInputSubmit = useCallback(() => {
handleLogEvent(TODAYVIEW_TEXTINPUT_SUBMIT_EVENT, {
time: new Date().toISOString(),
- userId: userId,
+ userId,
});
handleSubmit();
setTodayTextInputOpen(false);
- };
+ }, [userId, handleSubmit, setTodayTextInputOpen]);
+
+ const handleDragEndWithCallback = useCallback(
+ ({ from, to, data }) => {
+ handleDragEnd({ from, to, data });
+ onDragEnd?.();
+ },
+ [handleDragEnd, onDragEnd],
+ );
- const renderTodo = ({ item, drag, isActive }) => {
- return (
+ const renderTodo = useCallback(
+ ({ item, drag, isActive }) => (
{
categoryId={categoryId}
/>
- );
- };
+ ),
+ [categoryId],
+ );
+
+ useEffect(() => {
+ setTodos(currentTodos);
+ }, [currentTodos]);
return (
- onDragStart?.()}
- keyExtractor={item => item.id.toString()}
- onScroll={() => handleScroll(TODAYVIEW_SCROLL_EVENT, userId)}
- scrollEventThrottle={DEFAULT_SCROLL_EVENT_THROTTLE}
- simultaneousHandlers={[]}
- activationDistance={20}
- containerStyle={styles.flatListContainer}
+ onDragStart={onDragStart}
+ userId={userId}
/>
{isTodayTextInputOpen && categoryId === todayActivatedCategoryId && (
-
-
-
-
-
-
+
)}
@@ -125,40 +103,6 @@ const styles = StyleSheet.create({
flex: 1,
backgroundColor: 'white',
},
- flatListContainer: {
- flex: 1,
- },
- keyboardAvoidingView: {
- width: '100%',
- position: 'absolute',
- bottom: 0,
- backgroundColor: 'white',
- },
- inputWrapper: {
- width: '100%',
- borderTopWidth: StyleSheet.hairlineWidth,
- borderTopColor: colors.Gray02,
- backgroundColor: 'white',
- },
- inputContainer: {
- flexDirection: 'row',
- alignItems: 'center',
- paddingHorizontal: scale(7),
- paddingVertical: verticalScale(8),
- },
- checkIcon: {
- width: scale(24),
- height: verticalScale(24),
- },
- textInput: {
- flex: 1,
- backgroundColor: colors.Gray02,
- borderRadius: moderateScale(4),
- marginLeft: scale(4),
- paddingHorizontal: scale(8),
- height: scale(24),
- fontSize: moderateScale(14),
- },
});
export default DailyTodos;
diff --git a/hooks/api/useTodoMutations.ts b/hooks/api/useTodoMutations.ts
index dac84f7..c7ccddb 100644
--- a/hooks/api/useTodoMutations.ts
+++ b/hooks/api/useTodoMutations.ts
@@ -49,7 +49,10 @@ export const useTodoAddMutation = () => {
};
const updateTodoFetcher = async (
- updatedData: Partial & { todoId: number },
+ updatedData: Partial & {
+ todoId: number;
+ patchRank?: { prevId: number | null };
+ },
) => {
const data = await Api.updateTodo(updatedData);
return data;
@@ -66,16 +69,44 @@ export const useTodoUpdateMutation = () => {
const previousTodos = queryClient.getQueryData([TODO_QUERY_KEY]);
const previousInbox = queryClient.getQueryData([INBOX_QUERY_KEY]);
- const updateTodo = (old: Todo[] | undefined) =>
- old?.map(todo => {
+ const updateTodoOrder = (old: Todo[] | undefined) => {
+ if (!old) return [];
+
+ if ('patchRank' in updatedTodo) {
+ const movedTodo = old.find(todo => todo.id === updatedTodo.todoId);
+ if (!movedTodo) return old;
+
+ const filteredTodos = old.filter(
+ todo => todo.id !== updatedTodo.todoId,
+ );
+
+ if (updatedTodo.patchRank.prevId === null) {
+ return [movedTodo, ...filteredTodos];
+ }
+
+ const targetIndex = filteredTodos.findIndex(
+ todo => todo.id === updatedTodo.patchRank!.prevId,
+ );
+
+ if (targetIndex === -1) return old;
+
+ return [
+ ...filteredTodos.slice(0, targetIndex + 1),
+ movedTodo,
+ ...filteredTodos.slice(targetIndex + 1),
+ ];
+ }
+
+ return old.map(todo => {
if (todo.id === updatedTodo.todoId) {
return { ...todo, ...updatedTodo };
}
return todo;
- }) || [];
+ });
+ };
- queryClient.setQueryData([TODO_QUERY_KEY], updateTodo);
- queryClient.setQueryData([INBOX_QUERY_KEY], updateTodo);
+ queryClient.setQueryData([TODO_QUERY_KEY], updateTodoOrder);
+ queryClient.setQueryData([INBOX_QUERY_KEY], updateTodoOrder);
return { previousTodos, previousInbox };
},
diff --git a/hooks/todo/useFilteredTodo.js b/hooks/todo/useFilteredTodo.js
index b6d9261..6d41cb3 100644
--- a/hooks/todo/useFilteredTodo.js
+++ b/hooks/todo/useFilteredTodo.js
@@ -1,17 +1,14 @@
-import { useEffect, useState } from 'react';
+import { useMemo } from 'react';
const useFilteredTodos = (todos, selectedCategory, selectedDate) => {
- const [filteredTodos, setFilteredTodos] = useState([]);
+ const filteredTodos = useMemo(() => {
+ if (!todos) return [];
- useEffect(() => {
- if (todos) {
- const filtered = todos.filter(
- todo =>
- todo.categoryId === selectedCategory &&
- todo.date === selectedDate.format('YYYY-MM-DD'),
- );
- setFilteredTodos(filtered);
- }
+ return todos.filter(
+ todo =>
+ todo.categoryId === selectedCategory &&
+ todo.date === selectedDate.format('YYYY-MM-DD'),
+ );
}, [todos, selectedCategory, selectedDate]);
return filteredTodos;
diff --git a/hooks/todo/useHandleDrag.js b/hooks/todo/useHandleDrag.js
index 8e28dec..d2bc410 100644
--- a/hooks/todo/useHandleDrag.js
+++ b/hooks/todo/useHandleDrag.js
@@ -5,9 +5,7 @@ const useHandleDrag = () => {
const handleDragEnd = ({ from, to, data: newData }) => {
if (!newData || newData.length === 0) return;
- if (from === to) {
- return;
- }
+ if (from === to) return;
let prevTodoId = null;
let nextTodoId = null;
@@ -22,7 +20,7 @@ const useHandleDrag = () => {
}
const updatedData = {
- todo_id: newData[to].id,
+ todoId: newData[to].id,
patchRank: {
prevId: prevTodoId,
nextId: nextTodoId,
From 67f0cffcaa84150c4abe6e256ee6fa945bd864e4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EA=B3=A0=EB=B3=91=EC=B0=AC?=
<70642609+byungchanKo99@users.noreply.github.com>
Date: Sat, 23 Nov 2024 07:24:14 +0900
Subject: [PATCH 08/12] =?UTF-8?q?[SZ-553]feat:=20=EC=88=98=EC=A0=95?=
=?UTF-8?q?=EC=8B=9C=20=EA=B2=80=EC=9D=80=ED=99=94=EB=A9=B4=20=EA=B9=9C?=
=?UTF-8?q?=EC=A7=9D=EC=9D=B4=EB=8A=94=20=EB=AC=B8=EC=A0=9C=20=ED=95=B4?=
=?UTF-8?q?=EA=B2=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/(tabs)/index.jsx | 4 +--
.../common/molecules/EditableTextField.tsx | 24 +++++++++++++++--
.../CalendarBottomSheet.tsx | 20 ++------------
.../SubTodoGenerateBottomSheet.tsx | 26 ++-----------------
4 files changed, 28 insertions(+), 46 deletions(-)
diff --git a/app/(tabs)/index.jsx b/app/(tabs)/index.jsx
index 58447a4..1cf6acf 100644
--- a/app/(tabs)/index.jsx
+++ b/app/(tabs)/index.jsx
@@ -87,9 +87,9 @@ const TodayView = () => {
scrollEnabled={!isDragging}
/>
-
-
+
+
diff --git a/components/common/molecules/EditableTextField.tsx b/components/common/molecules/EditableTextField.tsx
index c44e7cd..5b1bf29 100644
--- a/components/common/molecules/EditableTextField.tsx
+++ b/components/common/molecules/EditableTextField.tsx
@@ -1,5 +1,11 @@
import { Text } from '@ui-kitten/components';
-import React, { useState, useCallback } from 'react';
+import React, {
+ useState,
+ useCallback,
+ useContext,
+ useEffect,
+ useRef,
+} from 'react';
import { StyleProp, StyleSheet, TextInput, TextStyle } from 'react-native';
import { Todo } from '../../../types/todo';
import { moderateScale, scale } from 'react-native-size-matters';
@@ -9,6 +15,7 @@ import {
NativeSyntheticEvent,
TextInputSubmitEditingEventData,
} from 'react-native';
+import { AIBottomSheetContext } from '@/contexts/AIBottomSheetProvider';
interface EditableListItemTitleProps {
isEditing: boolean;
@@ -36,6 +43,18 @@ const EditableTextField = memo(
}: EditableListItemTitleProps) => {
const [content, setContent] = useState(item.content);
const { mutate: updateTodo } = useTodoUpdateMutation();
+ const { bottomSheetRef } = useContext(AIBottomSheetContext);
+ const inputRef = useRef(null);
+
+ useEffect(() => {
+ if (isEditing) {
+ bottomSheetRef.current?.close();
+ const timer = setTimeout(() => {
+ inputRef.current?.focus();
+ }, 100);
+ return () => clearTimeout(timer);
+ }
+ }, [isEditing, bottomSheetRef]);
const handleTodoListItemSubmitEditing = useCallback(
async (e: NativeSyntheticEvent) => {
@@ -49,14 +68,15 @@ const EditableTextField = memo(
const onChangeText = useCallback((text: string) => {
setContent(text);
}, []);
- console.log(content, ' ', item.content);
return isEditing ? (
await handleTodoListItemSubmitEditing(e)}
style={inputStyles}
autoFocus={true}
+ onFocus={() => bottomSheetRef.current?.close()}
/>
) : (
{content}
diff --git a/components/todayView/dailyTodos/calendarBottomSheet/CalendarBottomSheet.tsx b/components/todayView/dailyTodos/calendarBottomSheet/CalendarBottomSheet.tsx
index 7c1638a..262123f 100644
--- a/components/todayView/dailyTodos/calendarBottomSheet/CalendarBottomSheet.tsx
+++ b/components/todayView/dailyTodos/calendarBottomSheet/CalendarBottomSheet.tsx
@@ -1,9 +1,6 @@
import { View, Text, Pressable, StyleSheet } from 'react-native';
-import React, { useCallback, useContext, useMemo } from 'react';
-import BottomSheet, {
- BottomSheetBackdrop,
- BottomSheetView,
-} from '@gorhom/bottom-sheet';
+import React, { useContext, useMemo } from 'react';
+import BottomSheet, { BottomSheetView } from '@gorhom/bottom-sheet';
import { DateContext } from '@/contexts/DateContext';
import { CalendarBottomSheetContext } from '@/contexts/CalendarBottomSheetProvider';
import {
@@ -99,25 +96,12 @@ const CalendarBottomSheet = ({ isTodo, item }) => {
startDayOfWeek: 1,
});
- const renderBackdrop = useCallback(
- props => (
-
- ),
- [],
- );
-
return (
{
const { bottomSheetRef } = useContext(AIBottomSheetContext);
- const renderBackdrop = useCallback(
- props => (
-
- ),
- [],
- );
-
useEffect(() => {
if (generatedSubTodos.length > 0) {
setSelectedIndexes(generatedSubTodos.map((_, index) => index));
@@ -220,7 +199,6 @@ const SubTodoGenerateBottomSheet = ({ item }) => {
snapPoints={snapPoints}
index={-1}
enablePanDownToClose={true}
- backdropComponent={renderBackdrop}
>
{renderContent()}
From 541c89484d8f1a4623cf8e19ce75b2c85255cd18 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EA=B3=A0=EB=B3=91=EC=B0=AC?=
<70642609+byungchanKo99@users.noreply.github.com>
Date: Sat, 23 Nov 2024 07:38:12 +0900
Subject: [PATCH 09/12] =?UTF-8?q?[SZ-553]feat:=20=ED=88=AC=EB=91=90=20?=
=?UTF-8?q?=EC=83=9D=EC=84=B1=EC=8B=9C=20=EC=83=9D=EC=84=B1=ED=9B=84=20?=
=?UTF-8?q?=ED=8F=AC=EC=BB=A4=EC=8A=A4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/(tabs)/index.jsx | 9 +-
components/todayView/TodoList.tsx | 97 ++++++++++++-------
.../todayView/dailyTodos/DailyTodos.tsx | 4 +
3 files changed, 71 insertions(+), 39 deletions(-)
diff --git a/app/(tabs)/index.jsx b/app/(tabs)/index.jsx
index 1cf6acf..7facb97 100644
--- a/app/(tabs)/index.jsx
+++ b/app/(tabs)/index.jsx
@@ -42,9 +42,11 @@ const TodayView = () => {
userId: userId,
});
- const renderCategoriesTodo = ({ item }) => {
+ const renderCategoriesTodo = ({ item, index }) => {
+ const isLastItem = index === categoriesData.length - 1;
+
return (
-
+
void;
- isActive: boolean;
- }) => React.ReactNode;
- onDragEnd: (params: { from: number; to: number; data: Todo[] }) => void;
- onDragStart: () => void;
- userId: string;
- setTodos: (todos: Todo[]) => void;
- }) => (
- {
- onDragEnd({ from, to, data });
- setTodos(data);
- }}
- onDragBegin={onDragStart}
- keyExtractor={item => item.id.toString()}
- onScroll={() => handleScroll(TODAYVIEW_SCROLL_EVENT, userId)}
- scrollEventThrottle={DEFAULT_SCROLL_EVENT_THROTTLE}
- simultaneousHandlers={[]}
- activationDistance={20}
- containerStyle={styles.flatListContainer}
- extraData={todos}
- />
+ forwardRef<
+ FlatList,
+ {
+ todos: Todo[];
+ renderItem: (info: {
+ item: Todo;
+ drag: () => void;
+ isActive: boolean;
+ }) => React.ReactNode;
+ onDragEnd: (params: { from: number; to: number; data: Todo[] }) => void;
+ onDragStart: () => void;
+ userId: string;
+ setTodos: (todos: Todo[]) => void;
+ }
+ >(
+ (
+ {
+ todos,
+ renderItem,
+ onDragEnd,
+ onDragStart,
+ userId,
+ setTodos,
+ }: {
+ todos: Todo[];
+ renderItem: (info: {
+ item: Todo;
+ drag: () => void;
+ isActive: boolean;
+ }) => React.ReactNode;
+ onDragEnd: (params: { from: number; to: number; data: Todo[] }) => void;
+ onDragStart: () => void;
+ userId: string;
+ setTodos: (todos: Todo[]) => void;
+ },
+ ref,
+ ) => {
+ return (
+ {
+ onDragEnd({ from, to, data });
+ setTodos(data);
+ }}
+ onDragBegin={onDragStart}
+ keyExtractor={item => item.id.toString()}
+ onScroll={() => handleScroll(TODAYVIEW_SCROLL_EVENT, userId)}
+ scrollEventThrottle={DEFAULT_SCROLL_EVENT_THROTTLE}
+ simultaneousHandlers={[]}
+ activationDistance={20}
+ containerStyle={styles.flatListContainer}
+ extraData={todos}
+ />
+ );
+ },
),
);
diff --git a/components/todayView/dailyTodos/DailyTodos.tsx b/components/todayView/dailyTodos/DailyTodos.tsx
index d7ba23c..48a63d4 100644
--- a/components/todayView/dailyTodos/DailyTodos.tsx
+++ b/components/todayView/dailyTodos/DailyTodos.tsx
@@ -36,6 +36,8 @@ const DailyTodos = ({ todosData, categoryId, onDragStart, onDragEnd }) => {
const handleDragEnd = useHandleDrag();
+ const todoListRef = React.useRef(null);
+
const handleInputSubmit = useCallback(() => {
handleLogEvent(TODAYVIEW_TEXTINPUT_SUBMIT_EVENT, {
time: new Date().toISOString(),
@@ -43,6 +45,7 @@ const DailyTodos = ({ todosData, categoryId, onDragStart, onDragEnd }) => {
});
handleSubmit();
setTodayTextInputOpen(false);
+ todoListRef.current?.scrollToEnd();
}, [userId, handleSubmit, setTodayTextInputOpen]);
const handleDragEndWithCallback = useCallback(
@@ -75,6 +78,7 @@ const DailyTodos = ({ todosData, categoryId, onDragStart, onDragEnd }) => {
Date: Sat, 23 Nov 2024 09:04:20 +0900
Subject: [PATCH 10/12] =?UTF-8?q?[SZ-553]feat:=20=EC=B5=9C=EC=A2=85=20?=
=?UTF-8?q?=EB=A7=88=EB=AC=B4=EB=A6=AC?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/categoryView/categoryListView.jsx | 2 +
app/settingsView/settingsAccountView.tsx | 1 +
app/settingsView/settingsView.jsx | 6 +-
.../common/molecules/EditableTextField.tsx | 19 +++-
.../molecules/InboxEditableTextField.tsx | 49 ++++++++++
.../inboxView/inboxTodos/InboxTodos.tsx | 91 +++++--------------
.../inboxTodos/inboxTodo/InboxTodo.jsx | 26 +-----
.../inboxTodo/todoListItem/TodoListItem.tsx | 27 ++----
.../todoMoreMenu/TodoMoreMenu.tsx | 15 +--
.../todoMoreMenu/useTodoMoreMenu.tsx | 6 --
.../inboxTodo/todoListItem/useTodoListItem.ts | 14 +--
.../todayView/dailyTodos/DailyTodos.tsx | 6 ++
.../CalendarBottomSheet.tsx | 2 +-
.../dailyTodo/subTodoList/DailySubTodo.jsx | 14 +--
.../dailyTodo/subTodoList/SubTodoList.tsx | 10 +-
.../todoMoreMenu/TodoMoreMenu.tsx | 1 -
.../SubTodoGenerateBottomSheet.tsx | 18 +++-
contexts/LoginContext.js | 3 +
contexts/listRefStore.ts | 18 ++++
hooks/auth/useLogin.js | 4 +-
20 files changed, 176 insertions(+), 156 deletions(-)
create mode 100644 components/common/molecules/InboxEditableTextField.tsx
create mode 100644 contexts/listRefStore.ts
diff --git a/app/categoryView/categoryListView.jsx b/app/categoryView/categoryListView.jsx
index 9890adb..0bca343 100644
--- a/app/categoryView/categoryListView.jsx
+++ b/app/categoryView/categoryListView.jsx
@@ -49,6 +49,8 @@ const styles = StyleSheet.create({
},
list: {
backgroundColor: 'white',
+ paddingHorizontal: scale(20),
+
flex: 1,
},
});
diff --git a/app/settingsView/settingsAccountView.tsx b/app/settingsView/settingsAccountView.tsx
index 18dc24d..a77cd8f 100644
--- a/app/settingsView/settingsAccountView.tsx
+++ b/app/settingsView/settingsAccountView.tsx
@@ -1,5 +1,6 @@
import '@/locales/index';
import { IndexPath, Layout, Menu, MenuItem } from '@ui-kitten/components';
+import React from 'react';
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { SafeAreaView, StyleSheet } from 'react-native';
diff --git a/app/settingsView/settingsView.jsx b/app/settingsView/settingsView.jsx
index 89c2c59..54354fd 100644
--- a/app/settingsView/settingsView.jsx
+++ b/app/settingsView/settingsView.jsx
@@ -8,7 +8,7 @@ import {
useTheme,
} from '@ui-kitten/components';
import { useRouter } from 'expo-router';
-import React, { useState } from 'react';
+import React, { useContext, useState } from 'react';
import { useTranslation } from 'react-i18next';
import ConfirmModal from '@/components/common/molecules/ConfirmModal';
import { api as Api } from '@/utils/api';
@@ -25,6 +25,7 @@ import {
} from 'react-native';
import { heightPercentage, widthPercentage } from '@/utils/responsiveSize';
import fontStyles from '@/theme/fontStyles';
+import { LoginContext } from '@/contexts/LoginContext';
const privacyPolicyUrl =
'https://swm-onestep.github.io/posts/%EA%B0%9C%EC%9D%B8%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EB%B0%A9%EC%B9%A8-copy/';
const termsOfServiceUrl =
@@ -45,6 +46,7 @@ const renderCurrentStatus = currentStatus => () => (
);
const SettingsView = () => {
+ const { userName } = useContext(LoginContext);
const { t } = useTranslation();
const theme = useTheme();
const { clear: clearStorage } = useStorage();
@@ -175,7 +177,7 @@ const SettingsView = () => {
{t('views.settingsView.greeting')}
- user
+ {userName}
diff --git a/components/common/molecules/EditableTextField.tsx b/components/common/molecules/EditableTextField.tsx
index 5b1bf29..982b20f 100644
--- a/components/common/molecules/EditableTextField.tsx
+++ b/components/common/molecules/EditableTextField.tsx
@@ -16,6 +16,7 @@ import {
TextInputSubmitEditingEventData,
} from 'react-native';
import { AIBottomSheetContext } from '@/contexts/AIBottomSheetProvider';
+import { useSubTodoUpdateMutation } from '@/hooks/api/useSubTodoMutations';
interface EditableListItemTitleProps {
isEditing: boolean;
@@ -23,6 +24,10 @@ interface EditableListItemTitleProps {
item: Todo;
inputStyles?: StyleProp | null;
textStyles?: StyleProp | null;
+ isTodo?: boolean;
+ handleSubmitEditing?: (
+ e: NativeSyntheticEvent,
+ ) => void;
}
const handleTodoContentUpdate = (content, item, updateTodo) => {
@@ -40,9 +45,11 @@ const EditableTextField = memo(
item,
inputStyles = styles.input,
textStyles = styles.text,
+ isTodo = true,
}: EditableListItemTitleProps) => {
const [content, setContent] = useState(item.content);
const { mutate: updateTodo } = useTodoUpdateMutation();
+ const { mutate: updateSubTodo } = useSubTodoUpdateMutation();
const { bottomSheetRef } = useContext(AIBottomSheetContext);
const inputRef = useRef(null);
@@ -58,11 +65,19 @@ const EditableTextField = memo(
const handleTodoListItemSubmitEditing = useCallback(
async (e: NativeSyntheticEvent) => {
- handleTodoContentUpdate(e.nativeEvent.text, item, updateTodo);
+ if (isTodo) {
+ handleTodoContentUpdate(e.nativeEvent.text, item, updateTodo);
+ } else {
+ const updatedData = {
+ subtodoId: item.id,
+ content: e.nativeEvent.text,
+ };
+ updateSubTodo(updatedData);
+ }
await new Promise(resolve => setTimeout(resolve, 100)); // 0.1초 대기
setIsEditing(false);
},
- [item, setIsEditing, updateTodo],
+ [item, setIsEditing, updateTodo, updateSubTodo, isTodo],
);
const onChangeText = useCallback((text: string) => {
diff --git a/components/common/molecules/InboxEditableTextField.tsx b/components/common/molecules/InboxEditableTextField.tsx
new file mode 100644
index 0000000..3d6aa46
--- /dev/null
+++ b/components/common/molecules/InboxEditableTextField.tsx
@@ -0,0 +1,49 @@
+import { Text } from '@ui-kitten/components';
+import React, { useState } from 'react';
+import { StyleProp, StyleSheet, TextInput, TextStyle } from 'react-native';
+import { Todo } from '../../../types/todo';
+import { moderateScale, scale } from 'react-native-size-matters';
+
+interface EditableListItemTitleProps {
+ isEditing: boolean;
+ handleSubmitEditing: (content) => void;
+ item: Todo;
+ inputStyles?: StyleProp | null;
+ textStyles?: StyleProp | null;
+}
+
+const EditableTextField = ({
+ isEditing,
+ handleSubmitEditing,
+ item,
+ inputStyles = styles.input,
+ textStyles = styles.text,
+}: EditableListItemTitleProps) => {
+ const [content, setContent] = useState(item.content);
+ return isEditing ? (
+ handleSubmitEditing(content)}
+ autoFocus={true}
+ style={inputStyles}
+ />
+ ) : (
+ {item.content}
+ );
+};
+
+export default EditableTextField;
+
+const styles = StyleSheet.create({
+ text: {
+ paddingLeft: scale(8),
+ fontSize: moderateScale(14),
+ },
+ input: {
+ justifyContent: 'center',
+ alignItems: 'center',
+ paddingLeft: scale(8),
+ fontSize: moderateScale(14),
+ },
+});
diff --git a/components/inboxView/inboxTodos/InboxTodos.tsx b/components/inboxView/inboxTodos/InboxTodos.tsx
index 66d4160..8899780 100644
--- a/components/inboxView/inboxTodos/InboxTodos.tsx
+++ b/components/inboxView/inboxTodos/InboxTodos.tsx
@@ -1,6 +1,5 @@
import { LoginContext } from '@/contexts/LoginContext';
import useTextInputStore from '@/contexts/textInputStore';
-import { useTodoUpdateMutation } from '@/hooks/api/useTodoMutations';
import useCreateInboxTodo from '@/hooks/todo/useCreateInboxTodo';
import useFilteredInboxTodos from '@/hooks/todo/useFilteredInboxTodo';
import '@/locales/index';
@@ -14,30 +13,19 @@ import {
INBOXVIEW_SCROLL_EVENT,
TODAYVIEW_TEXTINPUT_SUBMIT_EVENT,
} from '@/utils/logEvent';
-import { Icon } from '@ui-kitten/components';
-import { LexoRank } from 'lexorank';
+
import React, { Fragment, useContext } from 'react';
-import { useTranslation } from 'react-i18next';
-import {
- KeyboardAvoidingView,
- StyleSheet,
- TextInput,
- View,
-} from 'react-native';
-import DraggableFlatList, {
- ScaleDecorator,
-} from 'react-native-draggable-flatlist';
-import { GestureHandlerRootView } from 'react-native-gesture-handler';
-import { KeyboardAccessoryView } from 'react-native-keyboard-accessory';
+import { KeyboardAvoidingView, StyleSheet } from 'react-native';
+
+import { FlatList, GestureHandlerRootView } from 'react-native-gesture-handler';
import { moderateScale, scale, verticalScale } from 'react-native-size-matters';
import InboxTodo from './inboxTodo/InboxTodo';
+import TodoInput from '@/components/todayView/TextInput';
const InboxTodos = ({ todosData, categoryId }) => {
- const { t } = useTranslation();
const { userId } = useContext(LoginContext);
const inboxCurrentTodos = useFilteredInboxTodos(todosData, categoryId);
- const { mutate: updateInboxTodo } = useTodoUpdateMutation();
const {
isInboxTextInputOpen,
inboxActivatedCategoryId,
@@ -52,24 +40,10 @@ const InboxTodos = ({ todosData, categoryId }) => {
categoryId,
);
- const renderTodo = ({ item, drag, isActive }) => {
- return (
-
-
-
- );
+ const renderTodo = ({ item }) => {
+ return ;
};
- const handleDragEnd = async ({ data }) => {
- const updatedData = data.map(item => {
- return {
- todoId: item.id,
- order: LexoRank.parse(item.order).toString(),
- };
- });
- updateInboxTodo(updatedData);
- };
- //TODO: order 순서 생각해보니까 이제 서버에서 하잖아? 일단 전체 투두에서 계속 마지막으로 붙이는 식으로 구현
const handleInputSubmit = async () => {
handleLogEvent(TODAYVIEW_TEXTINPUT_SUBMIT_EVENT, {
time: new Date().toISOString(),
@@ -81,42 +55,27 @@ const InboxTodos = ({ todosData, categoryId }) => {
};
return (
-
+
- renderTodo({ item })}
keyExtractor={item => item.id.toString()}
onScroll={() => handleScroll(INBOXVIEW_SCROLL_EVENT, userId)}
scrollEventThrottle={DEFAULT_SCROLL_EVENT_THROTTLE}
/>
{isInboxTextInputOpen && categoryId === inboxActivatedCategoryId ? (
-
-
-
-
-
-
+
) : null}
@@ -127,21 +86,19 @@ const styles = StyleSheet.create({
container: {
flex: 1,
},
- keyboardInputContainer: {
- backgroundColor: 'white',
- borderTopWidth: 0,
- },
- mainContainer: {
+ keyboardAvoidingView: {
flex: 1,
backgroundColor: 'white',
},
flatListContainer: {
flex: 1,
},
- keyboardAvoidingView: {
- width: '100%',
- position: 'absolute',
- bottom: 0,
+ keyboardInputContainer: {
+ backgroundColor: 'white',
+ borderTopWidth: 0,
+ },
+ mainContainer: {
+ flex: 1,
backgroundColor: 'white',
},
inputWrapper: {
diff --git a/components/inboxView/inboxTodos/inboxTodo/InboxTodo.jsx b/components/inboxView/inboxTodos/inboxTodo/InboxTodo.jsx
index ba0e1c3..031fa4d 100644
--- a/components/inboxView/inboxTodos/inboxTodo/InboxTodo.jsx
+++ b/components/inboxView/inboxTodos/inboxTodo/InboxTodo.jsx
@@ -1,5 +1,3 @@
-import SubTodoGenerateModal from '@/components/SubTodoGenerateModal';
-import GeneratedSubTodoList from '@/components/todayView/dailyTodos/dailyTodo/generatedSubTodoList/GeneratedSubTodoList';
import '@/locales/index';
import React from 'react';
import { View } from 'react-native';
@@ -10,7 +8,7 @@ import TodoListItem from './todoListItem/TodoListItem';
import useInboxTodo from './useInboxTodo';
import useTextInputStore from '@/contexts/textInputStore';
-const InboxTodo = ({ item, drag, isActive }) => {
+const InboxTodo = ({ item }) => {
const {
isEditing,
setIsEditing,
@@ -18,19 +16,12 @@ const InboxTodo = ({ item, drag, isActive }) => {
setIsSubTodoToggleActivated,
subTodoInputActivated,
setSubTodoInputActivated,
- generatedSubTodos,
- setGeneratedSubTodos,
} = useInboxTodo();
- const { setInboxTextInputOpen } = useTextInputStore(
+ const setInboxTextInputOpen = useTextInputStore(
state => state.setInboxTextInputOpen,
);
- const {
- isVisible: isSubTodoGenerateModalVisible,
- setIsVisible: setIsSubTodoGenerateModalVisible,
- } = useModal();
-
const { setIsVisible: setIsTodoModalVisible } = useModal();
const handleEdit = () => {
@@ -43,11 +34,8 @@ const InboxTodo = ({ item, drag, isActive }) => {
0}
onEdit={handleEdit}
@@ -65,16 +53,6 @@ const InboxTodo = ({ item, drag, isActive }) => {
setSubTodoInputActivated={setSubTodoInputActivated}
/>
) : null}
-
-
);
};
diff --git a/components/inboxView/inboxTodos/inboxTodo/todoListItem/TodoListItem.tsx b/components/inboxView/inboxTodos/inboxTodo/todoListItem/TodoListItem.tsx
index d325777..197439c 100644
--- a/components/inboxView/inboxTodos/inboxTodo/todoListItem/TodoListItem.tsx
+++ b/components/inboxView/inboxTodos/inboxTodo/todoListItem/TodoListItem.tsx
@@ -1,5 +1,4 @@
-import EditableTextField from '@/components/common/molecules/EditableTextField';
-import { heightPercentage, widthPercentage } from '@/utils/responsiveSize';
+import EditableTextField from '@/components/common/molecules/InboxEditableTextField';
import { Icon, ListItem } from '@ui-kitten/components';
import React from 'react';
import { Pressable, StyleSheet, Text } from 'react-native';
@@ -7,14 +6,11 @@ import { RenderItemParams } from 'react-native-draggable-flatlist';
import { Todo } from '../../../../../types/todo';
import TodoMoreMenu from './todoMoreMenu/TodoMoreMenu';
import useTodoListItem from './useTodoListItem';
+import { scale, verticalScale } from 'react-native-size-matters';
interface TodoListItemProps extends RenderItemParams {
isEditing: boolean;
setIsEditing: React.Dispatch>;
- setIsSubTodoGenerateModalVisible: React.Dispatch<
- React.SetStateAction
- >;
- setIsTodoModalVisible: React.Dispatch>;
onEdit: () => void;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
bottomSheetRef: React.MutableRefObject;
@@ -30,7 +26,6 @@ const TodoListItem: React.FC = ({
isActive,
isEditing,
setIsEditing,
- setIsSubTodoGenerateModalVisible,
onEdit,
setSubTodoInputActivated,
}) => {
@@ -44,7 +39,6 @@ const TodoListItem: React.FC = ({
item,
isEditing,
setIsEditing,
- setIsSubTodoGenerateModalVisible,
});
const accessoryLeft = (props?) => {
@@ -63,7 +57,6 @@ const TodoListItem: React.FC = ({
const accessoryRight = () => {
return (
= ({
onLongPress={drag}
disabled={isActive}
title={title}
+ style={{ paddingHorizontal: 0 }}
/>
>
);
@@ -107,8 +101,7 @@ const styles = StyleSheet.create({
container: {
flexDirection: 'row',
justifyContent: 'space-between',
- paddingBottom: heightPercentage(8),
- paddingTop: heightPercentage(8),
+ paddingVertical: verticalScale(10),
marginRight: 0,
paddingRight: 0,
},
@@ -119,13 +112,13 @@ const styles = StyleSheet.create({
flex: 1,
},
checkIcon: {
- width: widthPercentage(20),
- height: heightPercentage(20),
+ width: scale(20),
+ height: verticalScale(20),
},
settingIcon: {
- width: widthPercentage(20),
- height: heightPercentage(20),
- marginRight: widthPercentage(4),
+ width: scale(20),
+ height: verticalScale(20),
+ marginRight: scale(4),
},
touchableCheck: {
paddingTop: 0,
@@ -133,7 +126,7 @@ const styles = StyleSheet.create({
},
text: {
paddingTop: 0,
- paddingLeft: widthPercentage(4),
+ paddingLeft: scale(4),
},
input: {
paddingTop: 0,
diff --git a/components/inboxView/inboxTodos/inboxTodo/todoListItem/todoMoreMenu/TodoMoreMenu.tsx b/components/inboxView/inboxTodos/inboxTodo/todoListItem/todoMoreMenu/TodoMoreMenu.tsx
index 4246f11..7321beb 100644
--- a/components/inboxView/inboxTodos/inboxTodo/todoListItem/todoMoreMenu/TodoMoreMenu.tsx
+++ b/components/inboxView/inboxTodos/inboxTodo/todoListItem/todoMoreMenu/TodoMoreMenu.tsx
@@ -46,25 +46,19 @@ const MenuIconButton = onPress => (
);
-const TodoMoreMenu = ({
- setIsSubTodoGenerateModalVisible,
- onEdit,
- item,
- setSubTodoInputActivated,
-}) => {
+const TodoMoreMenu = ({ onEdit, item, setSubTodoInputActivated }) => {
const {
handleEditPress,
handleDeletePress,
- handleGenerateSubTodoPress,
handleCreateSubTodoPress: handleAddSubTodoPress,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
handlePutTodoToInboxPress,
} = useTodoMoreMenu({
- setIsSubTodoGenerateModalVisible,
onEdit,
item,
setSubTodoInputActivated,
});
+
const [visible, setVisible] = useState(false);
const { t } = useTranslation();
const { openBottomSheet } = useContext(CalendarBottomSheetContext);
@@ -119,12 +113,12 @@ const TodoMoreMenu = ({
disabled={item.children.length > 0}
accessoryLeft={GenerateSubtodoIcon}
title= 0}
+ disabled={true}
titleText={t('components.todoMoreMenu.createSubTodoWithAi')}
/>
onPress={() => {
setSelectedTodo(item);
- handleGenerateSubTodoPress();
+ setVisible(false);
}}
style={styles.middleMenuItem}
/>
@@ -136,6 +130,7 @@ const TodoMoreMenu = ({
/>
onPress={() => {
handleAddSubTodoPress();
+ setVisible(false);
}}
style={styles.middleMenuItem}
/>
diff --git a/components/inboxView/inboxTodos/inboxTodo/todoListItem/todoMoreMenu/useTodoMoreMenu.tsx b/components/inboxView/inboxTodos/inboxTodo/todoListItem/todoMoreMenu/useTodoMoreMenu.tsx
index 5178b46..614952b 100644
--- a/components/inboxView/inboxTodos/inboxTodo/todoListItem/todoMoreMenu/useTodoMoreMenu.tsx
+++ b/components/inboxView/inboxTodos/inboxTodo/todoListItem/todoMoreMenu/useTodoMoreMenu.tsx
@@ -18,7 +18,6 @@ import { useContext } from 'react';
const useTodoMoreMenu = ({
item,
onEdit = () => {},
- setIsSubTodoGenerateModalVisible,
setSubTodoInputActivated,
}) => {
const { selectedCategory } = useContext(CategoryContext);
@@ -70,10 +69,6 @@ const useTodoMoreMenu = ({
});
};
- const handleGenerateSubTodoPress = () => {
- setIsSubTodoGenerateModalVisible(true);
- };
-
const handleCreateSubTodoPress = () => {
handleLogEvent(TODOMODAL_CREATESUBTODO_CLICK_EVENT, {
time: new Date().toISOString(),
@@ -96,7 +91,6 @@ const useTodoMoreMenu = ({
handleEditPress,
handleDeletePress,
handleChaneDatePress,
- handleGenerateSubTodoPress,
handleCreateSubTodoPress,
handlePutTodoToInboxPress,
};
diff --git a/components/inboxView/inboxTodos/inboxTodo/todoListItem/useTodoListItem.ts b/components/inboxView/inboxTodos/inboxTodo/todoListItem/useTodoListItem.ts
index 50f4044..d831e8f 100644
--- a/components/inboxView/inboxTodos/inboxTodo/todoListItem/useTodoListItem.ts
+++ b/components/inboxView/inboxTodos/inboxTodo/todoListItem/useTodoListItem.ts
@@ -10,16 +10,11 @@ import {
handleLogEvent,
} from '../../../../../utils/logEvent';
-const useTodoListItem = ({
- item,
- isEditing,
- setIsEditing,
- setIsSubTodoGenerateModalVisible,
-}) => {
+const useTodoListItem = ({ item, isEditing, setIsEditing }) => {
const { mutate: updateTodo } = useTodoUpdateMutation();
const { userId } = useContext(LoginContext);
const theme = useTheme();
- const { setInboxTextInputOpen } = useTextInputStore(
+ const setInboxTextInputOpen = useTextInputStore(
state => state.setInboxTextInputOpen,
);
@@ -64,10 +59,6 @@ const useTodoListItem = ({
setInboxTextInputOpen(false);
};
- const handleGenerateIconPress = () => {
- setIsSubTodoGenerateModalVisible(true);
- };
-
const handleSettingIconPress = () => {
handleLogEvent(DAILYTODO_MEATBALLMENU_CLICK_EVENT, {
time: new Date().toISOString(),
@@ -83,7 +74,6 @@ const useTodoListItem = ({
setIsEditing,
handleTodoListItemPress,
handleTodoListItemSubmitEditing,
- handleGenerateIconPress,
handleSettingIconPress,
};
};
diff --git a/components/todayView/dailyTodos/DailyTodos.tsx b/components/todayView/dailyTodos/DailyTodos.tsx
index 48a63d4..8ee1069 100644
--- a/components/todayView/dailyTodos/DailyTodos.tsx
+++ b/components/todayView/dailyTodos/DailyTodos.tsx
@@ -16,6 +16,7 @@ import { GestureHandlerRootView } from 'react-native-gesture-handler';
import DailyTodo from './dailyTodo/DailyTodo';
import TodoList from '../TodoList';
import TodoInput from '../TextInput';
+import useListRefStore from '@/contexts/listRefStore';
const DailyTodos = ({ todosData, categoryId, onDragStart, onDragEnd }) => {
const { userId } = useContext(LoginContext);
@@ -36,8 +37,13 @@ const DailyTodos = ({ todosData, categoryId, onDragStart, onDragEnd }) => {
const handleDragEnd = useHandleDrag();
+ const { setTodoListRef } = useListRefStore();
const todoListRef = React.useRef(null);
+ useEffect(() => {
+ setTodoListRef(todoListRef);
+ }, [setTodoListRef]);
+
const handleInputSubmit = useCallback(() => {
handleLogEvent(TODAYVIEW_TEXTINPUT_SUBMIT_EVENT, {
time: new Date().toISOString(),
diff --git a/components/todayView/dailyTodos/calendarBottomSheet/CalendarBottomSheet.tsx b/components/todayView/dailyTodos/calendarBottomSheet/CalendarBottomSheet.tsx
index 262123f..8f8facd 100644
--- a/components/todayView/dailyTodos/calendarBottomSheet/CalendarBottomSheet.tsx
+++ b/components/todayView/dailyTodos/calendarBottomSheet/CalendarBottomSheet.tsx
@@ -26,7 +26,7 @@ const CalendarBottomSheet = ({ isTodo, item }) => {
);
const { mutate: updateTodoDate } = useTodoUpdateMutation();
const { mutate: updateSubTodoDate } = useSubTodoUpdateMutation();
- const snapPoints = useMemo(() => ['75%'], []);
+ const snapPoints = useMemo(() => ['90%'], []);
const { i18n } = useTranslation();
const handleDateUpdate = date => {
diff --git a/components/todayView/dailyTodos/dailyTodo/subTodoList/DailySubTodo.jsx b/components/todayView/dailyTodos/dailyTodo/subTodoList/DailySubTodo.jsx
index b5b5cb8..1c16016 100644
--- a/components/todayView/dailyTodos/dailyTodo/subTodoList/DailySubTodo.jsx
+++ b/components/todayView/dailyTodos/dailyTodo/subTodoList/DailySubTodo.jsx
@@ -18,7 +18,7 @@ const DailySubTodo = ({ item }) => {
const [isEditing, setIsEditing] = useState(false);
const { mutate: updateSubTodo } = useSubTodoUpdateMutation();
const { userId } = useContext(LoginContext);
- const { setTodayTextInputOpen } = useTextInputStore(
+ const setTodayTextInputOpen = useTextInputStore(
state => state.setTodayTextInputOpen,
);
@@ -36,15 +36,6 @@ const DailySubTodo = ({ item }) => {
updateSubTodo(updatedData);
};
- const handleSubTodoUpdate = content => {
- const updatedData = {
- subtodoId: item.id,
- content: content,
- };
- updateSubTodo(updatedData);
- setIsEditing(false);
- };
-
const handleCheckIconPress = () => {
handleLogEvent(DAILYTODO_SUBTODOCOMPLETE_CLICK_EVENT, {
time: new Date().toISOString(),
@@ -77,10 +68,11 @@ const DailySubTodo = ({ item }) => {
<>
>
);
diff --git a/components/todayView/dailyTodos/dailyTodo/subTodoList/SubTodoList.tsx b/components/todayView/dailyTodos/dailyTodo/subTodoList/SubTodoList.tsx
index 451ccae..2fe560f 100644
--- a/components/todayView/dailyTodos/dailyTodo/subTodoList/SubTodoList.tsx
+++ b/components/todayView/dailyTodos/dailyTodo/subTodoList/SubTodoList.tsx
@@ -1,6 +1,6 @@
import colors from '@/theme/theme.json';
import { Icon, List } from '@ui-kitten/components';
-import React from 'react';
+import React, { useEffect, useRef } from 'react';
import { useTranslation } from 'react-i18next';
import { StyleSheet, TextInput, View } from 'react-native';
import { Todo } from '../../../../../types/todo';
@@ -27,6 +27,13 @@ const SubTodoList: React.FC = ({
const { handleSubtodoSubmit, subTodoInput, setSubtodoInput } = useSubTodoList(
{ item, setSubTodoInputActivated },
);
+ const inputRef = useRef(null);
+
+ useEffect(() => {
+ if (subTodoInputActivated) {
+ inputRef.current?.focus();
+ }
+ }, [subTodoInputActivated]);
return (
= ({
fill={colors.Gray02}
/>
{
diff --git a/components/todayView/dailyTodos/dailyTodo/todoListItem/todoMoreMenu/TodoMoreMenu.tsx b/components/todayView/dailyTodos/dailyTodo/todoListItem/todoMoreMenu/TodoMoreMenu.tsx
index 533712b..c6ff9bc 100644
--- a/components/todayView/dailyTodos/dailyTodo/todoListItem/todoMoreMenu/TodoMoreMenu.tsx
+++ b/components/todayView/dailyTodos/dailyTodo/todoListItem/todoMoreMenu/TodoMoreMenu.tsx
@@ -71,7 +71,6 @@ const TodoMoreMenu = ({
const setSelectedTodo = useTodoStore(state => state.setSelectedTodo);
const { openBottomSheet: openAIBottomSheet } =
useContext(AIBottomSheetContext);
- useContext(AIBottomSheetContext);
const toggleMenu = useCallback(() => {
setVisible(true);
diff --git a/components/todayView/dailyTodos/subtodoGenerateBottomSheet/SubTodoGenerateBottomSheet.tsx b/components/todayView/dailyTodos/subtodoGenerateBottomSheet/SubTodoGenerateBottomSheet.tsx
index 685d9a3..44514e9 100644
--- a/components/todayView/dailyTodos/subtodoGenerateBottomSheet/SubTodoGenerateBottomSheet.tsx
+++ b/components/todayView/dailyTodos/subtodoGenerateBottomSheet/SubTodoGenerateBottomSheet.tsx
@@ -20,6 +20,7 @@ import axios from 'axios';
import { API_PATH } from '@/utils/config';
import * as Sentry from '@sentry/react-native';
import { AIBottomSheetContext } from '@/contexts/AIBottomSheetProvider';
+import useListRefStore from '@/contexts/listRefStore';
const SubTodoGenerateBottomSheet = ({ item }) => {
const { accessToken } = useContext(LoginContext);
@@ -29,6 +30,7 @@ const SubTodoGenerateBottomSheet = ({ item }) => {
const theme = useTheme();
const { t } = useTranslation();
const { mutate: addSubTodo } = useSubTodoAddMutation();
+ const { todoListRef } = useListRefStore();
const snapPoints = useMemo(() => ['75%'], []);
@@ -74,7 +76,21 @@ const SubTodoGenerateBottomSheet = ({ item }) => {
date: generatedSubTodos[index].date,
todoId: generatedSubTodos[index].todo,
}));
- addSubTodo({ todoData: newSubTodos });
+
+ addSubTodo(
+ { todoData: newSubTodos },
+ {
+ onSuccess: () => {
+ requestAnimationFrame(() => {
+ requestAnimationFrame(() => {
+ if (todoListRef?.current) {
+ todoListRef.current?.scrollToEnd({ animated: true });
+ }
+ });
+ });
+ },
+ },
+ );
handleClose();
};
diff --git a/contexts/LoginContext.js b/contexts/LoginContext.js
index b5929bd..31d5d82 100755
--- a/contexts/LoginContext.js
+++ b/contexts/LoginContext.js
@@ -10,6 +10,7 @@ const LoginProvider = ({ children }) => {
const [accessToken, setAccessToken] = useState();
const [refreshToken, setRefreshToken] = useState();
const [loginType, setLoginType] = useState();
+ const [userName, setUserName] = useState();
return (
{
setRefreshToken,
loginType,
setLoginType,
+ userName,
+ setUserName,
}}
>
{children}
diff --git a/contexts/listRefStore.ts b/contexts/listRefStore.ts
new file mode 100644
index 0000000..66d0e34
--- /dev/null
+++ b/contexts/listRefStore.ts
@@ -0,0 +1,18 @@
+/* eslint-disable @typescript-eslint/no-explicit-any */
+import { create } from 'zustand';
+
+type ListRefStore = {
+ categoryListRef: React.RefObject | null;
+ setCategoryListRef: (ref: React.RefObject) => void;
+ todoListRef: React.RefObject | null;
+ setTodoListRef: (ref: React.RefObject) => void;
+};
+
+const useListRefStore = create(set => ({
+ categoryListRef: null,
+ setCategoryListRef: ref => set({ categoryListRef: ref }),
+ todoListRef: null,
+ setTodoListRef: ref => set({ todoListRef: ref }),
+}));
+
+export default useListRefStore;
diff --git a/hooks/auth/useLogin.js b/hooks/auth/useLogin.js
index 18c817d..3f5de38 100644
--- a/hooks/auth/useLogin.js
+++ b/hooks/auth/useLogin.js
@@ -17,7 +17,8 @@ const useLogin = () => {
const storage = useStorage();
const { deviceToken } = useDeviceToken();
const router = useRouter();
- const { setIsLoggedIn, setUserId, setAccessToken } = useContext(LoginContext);
+ const { setIsLoggedIn, setUserId, setAccessToken, setUserName } =
+ useContext(LoginContext);
const { mutate: addCategory } = useCategoryAddMutation();
const { t } = useTranslation();
@@ -42,6 +43,7 @@ const useLogin = () => {
const user = await Api.getUserInfo();
await setAsyncStorageLoginInfo(jwtTokenData, user);
setUserId(jwtTokenData.userId);
+ setUserName(jwtTokenData.email);
setIsLoggedIn(true);
if (jwtTokenData.isNew) {
handleAddCategory({ categoryName: t('views.categoryAddView.init') });
From b895ba627c1252580435e9bc6b089e770dcffc19 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EA=B3=A0=EB=B3=91=EC=B0=AC?=
<70642609+byungchanKo99@users.noreply.github.com>
Date: Sat, 23 Nov 2024 09:21:35 +0900
Subject: [PATCH 11/12] =?UTF-8?q?[SZ-553]fix:=20=EC=95=8C=EB=A6=BC=20?=
=?UTF-8?q?=ED=97=88=EC=9A=A9=20=EC=9C=84=EC=B9=98=20=EC=88=98=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app.config.js | 4 ++--
app/categoryView/categoryListView.jsx | 1 -
hooks/auth/useGoogleAuth.js | 4 ----
3 files changed, 2 insertions(+), 7 deletions(-)
diff --git a/app.config.js b/app.config.js
index d9eca1a..0596a1f 100644
--- a/app.config.js
+++ b/app.config.js
@@ -76,7 +76,7 @@ const expoConfig = {
backgroundColor: '#ffffff',
},
package: 'com.safezone.onestep',
- versionCode: 7,
+ versionCode: 5,
softwareKeyboardLayoutMode: 'pan',
},
web: {
@@ -125,7 +125,7 @@ const expoConfig = {
],
'./plugins/withStaticFrameworks',
],
- runtimeVersion: '1.0.1',
+ runtimeVersion: '1.0.0',
updates: {
url: 'https://u.expo.dev/63f6bbd9-1594-44b3-b161-0e0051413ef0',
},
diff --git a/app/categoryView/categoryListView.jsx b/app/categoryView/categoryListView.jsx
index 0bca343..d610f79 100644
--- a/app/categoryView/categoryListView.jsx
+++ b/app/categoryView/categoryListView.jsx
@@ -44,7 +44,6 @@ const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
- paddingHorizontal: scale(20),
backgroundColor: 'white',
},
list: {
diff --git a/hooks/auth/useGoogleAuth.js b/hooks/auth/useGoogleAuth.js
index 0ccd86d..6ae5f4a 100644
--- a/hooks/auth/useGoogleAuth.js
+++ b/hooks/auth/useGoogleAuth.js
@@ -1,5 +1,4 @@
import { api as Api } from '@/utils/api';
-import messaging from '@react-native-firebase/messaging';
import * as Google from 'expo-auth-session/providers/google';
import { useEffect, useState } from 'react';
import { Platform } from 'react-native';
@@ -45,9 +44,6 @@ const useGoogleAuth = () => {
useEffect(() => {
getClientId();
handleLocalToken();
- (async () => {
- await messaging().requestPermission();
- })();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
From 575374e96d8489b79e58a2f4ab9584828ba82f27 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EA=B3=A0=EB=B3=91=EC=B0=AC?=
<70642609+byungchanKo99@users.noreply.github.com>
Date: Mon, 20 Jan 2025 04:09:04 +0900
Subject: [PATCH 12/12] =?UTF-8?q?[SZ-553]fix:=20=EC=82=AC=EC=9A=A9?=
=?UTF-8?q?=ED=95=98=EC=A7=80=20=EC=95=8A=EB=8A=94=20=ED=8C=8C=EC=9D=BC=20?=
=?UTF-8?q?=EC=82=AD=EC=A0=9C?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
중복 컴포넌트로 삭제.
---
components/InboxSubTodo.jsx | 93 -------------------------------------
1 file changed, 93 deletions(-)
delete mode 100644 components/InboxSubTodo.jsx
diff --git a/components/InboxSubTodo.jsx b/components/InboxSubTodo.jsx
deleted file mode 100644
index 2a1033d..0000000
--- a/components/InboxSubTodo.jsx
+++ /dev/null
@@ -1,93 +0,0 @@
-import { TextInputContext } from '@/contexts/textInputContext';
-import { useSubTodoUpdateMutation } from '@/hooks/api/useSubTodoMutations';
-import { Icon, Input, ListItem } from '@ui-kitten/components';
-import React, { useContext, useState } from 'react';
-import { Text, TouchableOpacity } from 'react-native';
-import { useTheme } from 'react-native-elements';
-import TodoModal from './TodoModal';
-
-const InboxSubTodo = ({ item }) => {
- const [isEditing, setIsEditing] = useState(false);
- const [content, setContent] = useState(item.content);
- const theme = useTheme();
- const [modalVisible, setModalVisible] = useState(false);
- const { mutate: updateInboxSubTodo } = useSubTodoUpdateMutation();
- const { setInboxTextInputOpen } = useContext(TextInputContext);
-
- const handleEdit = () => {
- setIsEditing(true);
- setInboxTextInputOpen(false);
- setModalVisible(false);
- };
-
- const handleInboxSubTodoUpdate = () => {
- const updatedData = {
- todoId: item.id,
- content: content,
- };
- updateInboxSubTodo(updatedData);
- };
-
- const outlineIcon = props => {
- return (
- setModalVisible(true)}>
-
-
- );
- };
-
- const settingIcon = props => {
- return (
- setModalVisible(true)}>
-
-
- );
- };
-
- return (
- <>
- setContent(value)}
- onSubmitEditing={() => {
- handleInboxSubTodoUpdate();
- setIsEditing(false);
- setInboxTextInputOpen(true);
- }}
- autoFocus={true}
- />
- ) : (
- {item.content}
- )
- }
- key={item.id}
- accessoryLeft={props => outlineIcon(props)}
- accessoryRight={props => settingIcon(props)}
- onPress={() => setModalVisible(true)}
- style={{ paddingLeft: 40 }}
- />
-
- >
- );
-};
-
-export default InboxSubTodo;