diff --git a/app/_layout.jsx b/app/_layout.jsx index 25f339e..69d7cea 100755 --- a/app/_layout.jsx +++ b/app/_layout.jsx @@ -3,6 +3,8 @@ import CategoryAddIcon from '@/components/CategoryAddIcon'; import HeaderIcon from '@/components/HeaderIcon'; import HeaderMenu from '@/components/HeaderMenu'; import { env, getSentryConfig, getStoryBookConfig } from '@/constants/env'; +import CategoryBottomSheetProvider from '@/contexts/CategoryBottomSheetProvider'; +import FunnelProvider from '@/contexts/FunnelContext'; import LoginProvider from '@/contexts/LoginContext'; import '@/locales/index'; import { default as theme } from '@/theme/theme.json'; @@ -16,7 +18,6 @@ import React from 'react'; import { useTranslation } from 'react-i18next'; import { GestureHandlerRootView } from 'react-native-gesture-handler'; import { default as mapping } from '../theme/mapping.json'; -import FunnelProvider from '@/contexts/FunnelContext'; const SENTRY_MODE = env.SENTRY_MODE; Sentry.init({ @@ -48,88 +49,79 @@ const RootLayout = () => { <> - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + diff --git a/app/categoryView/categoryAddView.jsx b/app/categoryView/categoryAddView.jsx deleted file mode 100644 index 1321165..0000000 --- a/app/categoryView/categoryAddView.jsx +++ /dev/null @@ -1,135 +0,0 @@ -import { useCategoryAddMutation } from '@/hooks/api/useCategoryMutation'; -import '@/locales/index'; -import BottomSheet, { BottomSheetView } from '@gorhom/bottom-sheet'; -import { Button, Input, Layout, Text } from '@ui-kitten/components'; -import { useRouter } from 'expo-router'; -import React, { useEffect, useRef, useState } from 'react'; -import { useTranslation } from 'react-i18next'; -import { FlatList, SafeAreaView, TouchableOpacity, View } from 'react-native'; - -const colors = { - '#FF3D71': 0, - '#FF7E29': 1, - '#FFC233': 2, - '#4CAF50': 3, - '#00BCD4': 4, -}; - -const CategoryAddView = () => { - const router = useRouter(); - const [categoryName, setCategoryName] = useState(''); - const [selectedColor, setSelectedColor] = useState(Object.keys(colors)[0]); - const bottomSheetRef = useRef(null); - - const { t } = useTranslation(); - - const { mutate: addCategory, isSuccess } = useCategoryAddMutation(); - - useEffect(() => { - if (isSuccess) { - setCategoryName(''); - router.back(); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [isSuccess]); - - const openBottomSheet = () => { - bottomSheetRef.current.snapToIndex(0); - }; - - const handleAddCategory = () => { - const addCategoryData = { - title: categoryName, - color: colors[selectedColor], - }; - addCategory({ addCategoryData }); - }; - - const renderColorItem = ({ item }) => ( - { - setSelectedColor(item); - bottomSheetRef.current.close(); // Close the bottom sheet - }} - /> - ); - - return ( - - - - openBottomSheet()} - > - - {t('views.categoryAddView.color')} - - - - - - - - - {t('views.categoryAddView.color')} - - index.toString()} - numColumns={5} - /> - - - - - - - ); -}; - -export default CategoryAddView; diff --git a/app/categoryView/categoryEditView.jsx b/app/categoryView/categoryEditView.jsx deleted file mode 100644 index 5bb2b26..0000000 --- a/app/categoryView/categoryEditView.jsx +++ /dev/null @@ -1,255 +0,0 @@ -import ConfirmDeleteModal from '@/components/ConfirmDeleteModal'; -import { useCategoryUpdateMutation } from '@/hooks/api/useCategoryMutation'; -import '@/locales/index'; -import BottomSheet, { BottomSheetView } from '@gorhom/bottom-sheet'; -import { Button, Divider, Layout, Text, useTheme } from '@ui-kitten/components'; -import { useLocalSearchParams, useRouter } from 'expo-router'; -import React, { useEffect, useRef, useState } from 'react'; -import { useTranslation } from 'react-i18next'; -import { - FlatList, - Keyboard, - SafeAreaView, - StyleSheet, - TextInput, - TouchableOpacity, - TouchableWithoutFeedback, - View, -} from 'react-native'; - -const colors = { - '#FF3D71': 0, - '#FF7E29': 1, - '#FFC233': 2, - '#4CAF50': 3, - '#00BCD4': 4, -}; - -const getColor = index => Object.keys(colors)[index]; - -const CategoryEditView = () => { - const params = useLocalSearchParams(); - if (params.title) { - typeof params.title === 'string' - ? params.title - : (params.title = params.title.join('')); - } - const router = useRouter(); - const [categoryName, setCategoryName] = useState(params.title || ''); - const [selectedColor, setSelectedColor] = useState( - getColor(params.color) || Object.keys(colors)[0], - ); - const [isEditing, setIsEditing] = useState(false); - const bottomSheetRef = useRef(null); - const [modalVisible, setModalVisible] = useState(false); - const theme = useTheme(); - const { t } = useTranslation(); - - const { mutate: updateCategory, isSuccess: isUpdateSuccess } = - useCategoryUpdateMutation(); - - useEffect(() => { - if (isUpdateSuccess) { - setCategoryName(''); - router.back(); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [isUpdateSuccess]); - - const openBottomSheet = () => { - bottomSheetRef.current.snapToIndex(0); - }; - - const handleUpdateCategory = () => { - const updatedData = { - title: categoryName, - color: colors[selectedColor], - category_id: params.id, - }; - updateCategory({ updatedData }); - }; - - const renderColorItem = ({ item }) => ( - { - setSelectedColor(item); - bottomSheetRef.current.close(); // Close the bottom sheet - }} - /> - ); - - return ( - { - Keyboard.dismiss(); - setIsEditing(false); - }} - > - - - - {t('views.categoryEditView.category')} - - {isEditing ? ( - - ) : ( - setIsEditing(prev => !prev)}> - {categoryName} - - )} - - openBottomSheet()} - > - - {t('views.categoryEditView.color')} - - - - - - - - - - - - {t('views.categoryEditView.color')} - - index.toString()} - numColumns={5} - /> - - - - - - - - - ); -}; - -const styles = StyleSheet.create({ - container: { - flex: 1, - backgroundColor: 'red', - }, - layout: { - flex: 1, - padding: 20, - }, - headerText: { - fontSize: 20, - fontWeight: 'bold', - marginBottom: 10, - }, - categoryName: { - fontSize: 16, - marginLeft: 10, - padding: 8, - marginTop: 3, - margin: 3.2, - }, - divider: { - marginBottom: 20, - }, - inputContainer: { - marginBottom: 20, - }, - labelText: { - fontSize: 16, - marginBottom: 10, - color: '#8F9BB3', - }, - input: { fontSize: 16, marginLeft: 10, padding: 8 }, - colorSelector: { - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'space-between', - marginBottom: 20, - }, - colorPreview: { - width: 24, - height: 24, - borderRadius: 12, - borderWidth: 1, - borderColor: '#E4E9F2', - }, - button: { - marginTop: 20, - }, -}); - -export default CategoryEditView; diff --git a/app/categoryView/categoryListView.jsx b/app/categoryView/categoryListView.jsx index f850c33..9890adb 100644 --- a/app/categoryView/categoryListView.jsx +++ b/app/categoryView/categoryListView.jsx @@ -1,9 +1,11 @@ +import CategoryBottomSheet from '@/components/categoryView/CategoryBottomSheet'; import CategoryListItem from '@/components/categoryView/CategoryListItem'; import { LoginContext } from '@/contexts/LoginContext'; import useCategoriesQuery from '@/hooks/api/useCategoriesQuery'; -import { Layout, List, Text } from '@ui-kitten/components'; +import { List, Text } from '@ui-kitten/components'; import React, { useContext, useEffect, useState } from 'react'; import { SafeAreaView, StyleSheet } from 'react-native'; +import { scale } from 'react-native-size-matters'; const renderItem = ({ item }) => { return ; @@ -27,13 +29,12 @@ const CategoryListView = () => { return ( <> - - renderItem({ item })} - /> - + renderItem({ item })} + /> + ); @@ -42,14 +43,13 @@ const CategoryListView = () => { const styles = StyleSheet.create({ container: { flex: 1, - }, - layout: { - flex: 1, justifyContent: 'center', - paddingHorizontal: 20, + paddingHorizontal: scale(20), + backgroundColor: 'white', }, list: { backgroundColor: 'white', + flex: 1, }, }); diff --git a/components/CategoryAddIcon.jsx b/components/CategoryAddIcon.jsx index 5bd3600..fa34dac 100644 --- a/components/CategoryAddIcon.jsx +++ b/components/CategoryAddIcon.jsx @@ -1,14 +1,25 @@ -import { TouchableOpacity, StyleSheet } from 'react-native'; +import { + ADD, + CategoryBottomSheetContext, +} from '@/contexts/CategoryBottomSheetProvider'; import { Icon, useTheme } from '@ui-kitten/components'; -import React from 'react'; -import { router } from 'expo-router'; +import React, { useContext } from 'react'; +import { StyleSheet, TouchableOpacity } from 'react-native'; const CategoryAddIcon = () => { const theme = useTheme(); + const { setMode, setCategoryId, openBottomSheet, setCategoryName } = + useContext(CategoryBottomSheetContext); + const handlePress = () => { + setMode(ADD); + setCategoryId(null); + setCategoryName(''); + openBottomSheet(); + }; return ( router.push('categoryView/categoryAddView')} + onPress={() => handlePress()} style={styles.iconContainer} > { - const router = useRouter(); + const { closeBottomSheet } = useContext(CategoryBottomSheetContext); const { mutate: deleteCategory, isSuccess: isDeleteSuccess } = useCategoryDeleteMutation(); @@ -20,7 +20,7 @@ const ConfirmDeleteModal = ({ modalVisible, setModalVisible, categoryId }) => { useEffect(() => { if (isDeleteSuccess) { setModalVisible(false); - router.back(); + closeBottomSheet(); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [isDeleteSuccess]); diff --git a/components/categoryView/Category.tsx b/components/categoryView/Category.tsx deleted file mode 100644 index a66dad6..0000000 --- a/components/categoryView/Category.tsx +++ /dev/null @@ -1,44 +0,0 @@ -// import colors from '@/theme/theme.json'; -// import { heightPercentage, widthPercentage } from '@/utils/responsiveSize'; -// import { Icon } from '@ui-kitten/components'; -// import React from 'react'; -// import { Pressable, StyleSheet, View } from 'react-native'; -// import DailyTodos from '../todayView/dailyTodos/DailyTodos'; -// import CategoryButton from './CategoryButton'; - -// interface CategoryProps { -// categoryId: number; -// categoryName: string; -// } - -// const Category: React.FC = ({ categoryId, categoryName }) => { -// return ( -// -// -// -// -// -// -// -// -// -// ); -// }; - -// const styles = StyleSheet.create({ -// headerContainer: { -// flexDirection: 'row', -// justifyContent: 'space-between', -// }, -// icon: { -// width: widthPercentage(16), -// height: heightPercentage(16), -// }, -// plusIconContainer: { -// backgroundColor: colors.Gray02, -// padding: widthPercentage(8), -// borderRadius: widthPercentage(4), -// }, -// }); - -// export default Category; diff --git a/components/categoryView/CategoryBottomSheet.tsx b/components/categoryView/CategoryBottomSheet.tsx new file mode 100644 index 0000000..f46512b --- /dev/null +++ b/components/categoryView/CategoryBottomSheet.tsx @@ -0,0 +1,194 @@ +import { CategoryBottomSheetContext } from '@/contexts/CategoryBottomSheetProvider'; +import { + useCategoryAddMutation, + useCategoryUpdateMutation, +} from '@/hooks/api/useCategoryMutation'; +import fontStyles from '@/theme/fontStyles'; +import colors from '@/theme/theme.json'; +import { heightPercentage, widthPercentage } from '@/utils/responsiveSize'; +import BottomSheet, { + BottomSheetBackdrop, + BottomSheetView, +} from '@gorhom/bottom-sheet'; +import { Icon } from '@ui-kitten/components'; +import React, { useCallback, useContext, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { Pressable, StyleSheet, Text, TextInput, View } from 'react-native'; +import ConfirmDeleteModal from '../ConfirmDeleteModal'; + +enum CategoryModes { + ADD = 1, + EDIT = 2, +} + +const CategoryBottomSheet = () => { + const { mode, categoryId, categoryName, setCategoryName, closeBottomSheet } = + useContext(CategoryBottomSheetContext); + const { t } = useTranslation(); + const categoryAddText = t('components.categoryModal.addCategory'); + const categoryEditText = t('components.categoryModal.editCategory'); + const titleText = + mode === CategoryModes.ADD ? categoryAddText : categoryEditText; + const { bottomSheetRef } = useContext(CategoryBottomSheetContext); + const { mutate: addCategory } = useCategoryAddMutation(); + const { mutate: updateCategory } = useCategoryUpdateMutation(); + const [modalVisible, setModalVisible] = useState(false); + + const handlePress = () => { + if (mode === CategoryModes.ADD) { + handleAddCategory(); + } else { + handleEditCategory(); + } + setModalVisible(false); + closeBottomSheet(); + }; + + const handleAddCategory = () => { + const addCategoryData = { + title: categoryName, + color: 1, + }; + addCategory({ addCategoryData }); + }; + + const handleEditCategory = () => { + const updatedData = { + title: categoryName, + color: 1, + category_id: categoryId, + }; + updateCategory(updatedData); + }; + + const renderBackdrop = useCallback( + props => ( + + ), + [], + ); + + return ( + + + + {titleText} + + + + + + + + {t('components.categoryModal.categoryName')} + + + + + + + {t('components.categoryModal.confirm')} + + + {mode === CategoryModes.EDIT ? ( + setModalVisible(true)} + > + + {t('components.categoryModal.delete')} + + + ) : null} + + + + + + ); +}; + +const styles = StyleSheet.create({ + bottomSheetView: { + flex: 1, + padding: widthPercentage(18), + backgroundColor: 'white', + }, + topContainer: { + backgroundColor: 'white', + flexDirection: 'row', + justifyContent: 'space-between', + marginTop: heightPercentage(20), + height: heightPercentage(60), + }, + middleContainer: { + justifyContent: 'space-between', + flex: 1, + }, + bottomContainer: { + marginBottom: heightPercentage(20), + }, + icon: { + width: heightPercentage(20), + height: heightPercentage(20), + }, + titleText: { + fontSize: fontStyles.Subtitle.S1.B_130.fontSize, + fontFamily: fontStyles.Subtitle.S1.B_130.fontFamily, + }, + nameText: { + fontSize: fontStyles.Paragraph.P1.M_100.fontSize, + fontFamily: fontStyles.Paragraph.P1.M_100.fontFamily, + marginBottom: widthPercentage(12), + }, + textInput: { + borderWidth: 1, + borderColor: '#E6E8EB', + borderRadius: widthPercentage(12), + height: heightPercentage(42), + paddingHorizontal: widthPercentage(16), + }, + buttonText: { + color: 'white', + fontSize: fontStyles.Subtitle.S1.M_100.fontSize, + fontFamily: fontStyles.Subtitle.S1.M_100.fontFamily, + }, + confirmButton: { + paddingHorizontal: widthPercentage(8), + paddingVertical: widthPercentage(16), + justifyContent: 'center', + alignItems: 'center', + backgroundColor: colors.Blue01, + borderRadius: widthPercentage(12), + }, + deleteButton: { + marginTop: heightPercentage(10), + paddingHorizontal: widthPercentage(8), + paddingVertical: widthPercentage(16), + justifyContent: 'center', + alignItems: 'center', + backgroundColor: colors.Red01, + borderRadius: widthPercentage(12), + }, +}); + +export default CategoryBottomSheet; diff --git a/components/categoryView/CategoryListItem.jsx b/components/categoryView/CategoryListItem.jsx deleted file mode 100644 index d013e41..0000000 --- a/components/categoryView/CategoryListItem.jsx +++ /dev/null @@ -1,55 +0,0 @@ -import { useRouter } from 'expo-router'; -import { Pressable, StyleSheet, View } from 'react-native'; -import DragAndDropIcon from '../icons/DragAndDropIcon'; -import CategoryButton from './CategoryButton'; - -const CategoryListItem = ({ item, isDraggedOn = false }) => { - const router = useRouter(); - - const handlePress = categoryItem => { - router.push({ - pathname: 'categoryView/categoryEditView', - params: { - ...categoryItem, - }, - }); - }; - - return ( - handlePress(item)}> - - - - - - ); -}; - -const styles = StyleSheet.create({ - draggedOnContainer: { - paddingTop: 10, - paddingLeft: 8, - paddingRight: 8, - paddingBottom: 10, - borderRadius: 8, - flexDirection: 'row', - justifyContent: 'space-between', - backgroundColor: '#E0E0E0', - }, - notDraggedOnContainer: { - paddingTop: 10, - paddingLeft: 8, - paddingRight: 8, - paddingBottom: 10, - borderRadius: 8, - flexDirection: 'row', - justifyContent: 'space-between', - backgroundColor: 'white', - }, -}); - -export default CategoryListItem; diff --git a/components/categoryView/CategoryListItem.tsx b/components/categoryView/CategoryListItem.tsx new file mode 100644 index 0000000..f477c3a --- /dev/null +++ b/components/categoryView/CategoryListItem.tsx @@ -0,0 +1,69 @@ +import { + CategoryBottomSheetContext, + EDIT, +} from '@/contexts/CategoryBottomSheetProvider'; +import React, { useContext } from 'react'; +import { Pressable, StyleSheet, View } from 'react-native'; +import DragAndDropIcon from '../icons/DragAndDropIcon'; +import CategoryButton from './CategoryButton'; +import { verticalScale } from 'react-native-size-matters'; + +interface CategoryListItemProps { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + item: any; + isDraggedOn: boolean; +} + +const CategoryListItem: React.FC = ({ + item, + isDraggedOn = false, +}) => { + const { openBottomSheet, setMode, setCategoryId, setCategoryName } = + useContext(CategoryBottomSheetContext); + + const handlePress = () => { + // router.push({ + // pathname: 'categoryView/categoryEditView', + // params: { + // ...categoryItem, + // }, + // }); + setMode(EDIT); + setCategoryId(item.id); + setCategoryName(item.title); + openBottomSheet(); + }; + + return ( + handlePress()}> + + + + + + ); +}; + +const styles = StyleSheet.create({ + draggedOnContainer: { + paddingTop: 10, + paddingLeft: 8, + paddingRight: 8, + paddingBottom: 10, + borderRadius: 8, + flexDirection: 'row', + justifyContent: 'space-between', + backgroundColor: '#E0E0E0', + }, + notDraggedOnContainer: { + paddingVertical: verticalScale(10), + flexDirection: 'row', + justifyContent: 'space-between', + }, +}); + +export default CategoryListItem; diff --git a/components/common/molecules/ConfirmModal.tsx b/components/common/molecules/ConfirmModal.tsx index aebb0a6..29f7d18 100644 --- a/components/common/molecules/ConfirmModal.tsx +++ b/components/common/molecules/ConfirmModal.tsx @@ -1,7 +1,8 @@ +import colors from '@/theme/theme.json'; +import { Button, Layout, Modal, Text, useTheme } from '@ui-kitten/components'; import React from 'react'; -import { Modal, Layout, Text, Button, useTheme } from '@ui-kitten/components'; -import { StyleSheet, View } from 'react-native'; import { useTranslation } from 'react-i18next'; +import { StyleSheet, View } from 'react-native'; import { scale, verticalScale } from 'react-native-size-matters'; import fontStyles from '../../../theme/fontStyles'; @@ -73,7 +74,7 @@ const ConfirmModal: React.FC = ({ {t(cancelTextKey)} -