diff --git a/app/_layout.jsx b/app/_layout.jsx
index 25f339e..1aeb44a 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,93 @@ const RootLayout = () => {
<>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
>
diff --git a/app/categoryView/categoryEditView.jsx b/app/categoryView/categoryEditView.jsx
index 5bb2b26..62c6a79 100644
--- a/app/categoryView/categoryEditView.jsx
+++ b/app/categoryView/categoryEditView.jsx
@@ -63,10 +63,10 @@ const CategoryEditView = () => {
const handleUpdateCategory = () => {
const updatedData = {
title: categoryName,
- color: colors[selectedColor],
+ color: 1,
category_id: params.id,
};
- updateCategory({ updatedData });
+ updateCategory(updatedData);
};
const renderColorItem = ({ item }) => (
diff --git a/app/categoryView/categoryListView.jsx b/app/categoryView/categoryListView.jsx
index f850c33..77ca997 100644
--- a/app/categoryView/categoryListView.jsx
+++ b/app/categoryView/categoryListView.jsx
@@ -1,3 +1,4 @@
+import CategoryBottomSheet from '@/components/categoryView/CategoryBottomSheet';
import CategoryListItem from '@/components/categoryView/CategoryListItem';
import { LoginContext } from '@/contexts/LoginContext';
import useCategoriesQuery from '@/hooks/api/useCategoriesQuery';
@@ -33,6 +34,7 @@ const CategoryListView = () => {
data={orderedCategories}
renderItem={({ item }) => renderItem({ item })}
/>
+
>
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}
>
= ({ 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..4c4bf84
--- /dev/null
+++ b/components/categoryView/CategoryBottomSheet.tsx
@@ -0,0 +1,167 @@
+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 } from 'react';
+import { useTranslation } from 'react-i18next';
+import { Pressable, StyleSheet, Text, TextInput, View } from 'react-native';
+
+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 handlePress = () => {
+ if (mode === CategoryModes.ADD) {
+ handleAddCategory();
+ } else {
+ handleEditCategory();
+ }
+ 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')}
+
+
+
+
+
+
+ );
+};
+
+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,
+ },
+ button: {
+ paddingHorizontal: widthPercentage(8),
+ paddingVertical: widthPercentage(16),
+ justifyContent: 'center',
+ alignItems: 'center',
+ backgroundColor: colors.Blue01,
+ borderRadius: widthPercentage(12),
+ },
+});
+
+export default CategoryBottomSheet;
diff --git a/components/categoryView/CategoryListItem.jsx b/components/categoryView/CategoryListItem.tsx
similarity index 53%
rename from components/categoryView/CategoryListItem.jsx
rename to components/categoryView/CategoryListItem.tsx
index d013e41..2b1c41a 100644
--- a/components/categoryView/CategoryListItem.jsx
+++ b/components/categoryView/CategoryListItem.tsx
@@ -1,22 +1,40 @@
-import { useRouter } from 'expo-router';
+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';
-const CategoryListItem = ({ item, isDraggedOn = false }) => {
- const router = useRouter();
+interface CategoryListItemProps {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ item: any;
+ isDraggedOn: boolean;
+}
- const handlePress = categoryItem => {
- router.push({
- pathname: 'categoryView/categoryEditView',
- params: {
- ...categoryItem,
- },
- });
+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(item)}>
+ handlePress()}>
{
+ const bottomSheetRef = useRef(null);
+ const [mode, setMode] = useState(ADD);
+ const [categoryName, setCategoryName] = useState('');
+ const [categoryId, setCategoryId] = useState(null);
+
+ const openBottomSheet = () => {
+ if (bottomSheetRef.current) {
+ bottomSheetRef.current.snapToIndex(0);
+ }
+ };
+
+ const closeBottomSheet = () => {
+ if (bottomSheetRef.current) {
+ bottomSheetRef.current.close();
+ }
+ };
+
+ return (
+
+ {children}
+
+ );
+};
+
+export default CategoryBottomSheetProvider;
diff --git a/hooks/api/useCategoryMutation.js b/hooks/api/useCategoryMutation.js
index 49e8ff3..c10cb43 100644
--- a/hooks/api/useCategoryMutation.js
+++ b/hooks/api/useCategoryMutation.js
@@ -18,9 +18,8 @@ export const useCategoryAddMutation = () => {
});
};
-const updateCategoryFetcher = async ({ updatedData }) => {
- const data = await Api.updateCategory({ updatedData });
-
+const updateCategoryFetcher = async updatedData => {
+ const data = await Api.updateCategory(updatedData);
return data;
};
diff --git a/locales/en.json b/locales/en.json
index 26a7df5..7efb2b9 100644
--- a/locales/en.json
+++ b/locales/en.json
@@ -43,7 +43,8 @@
"label": "category input",
"placeholder": "Write a category",
"color": "Color",
- "close": "Close"
+ "close": "Close",
+ "title": "Add Category"
},
"categoryEditView": {
"category": "category",
@@ -51,7 +52,8 @@
"color": "color",
"edit": "Edit",
"delete": "Delete",
- "close": "Close"
+ "close": "Close",
+ "title": "Edit Category"
}
},
"components": {
@@ -93,6 +95,12 @@
"createSubTodoWithAi": "Generate sub-todo",
"createSubTodo": "Add sub-todo",
"putInbox": "Put Inbox"
+ },
+ "categoryModal": {
+ "addCategory": "Add Category",
+ "editCategory": "Edit Category",
+ "categoryName": "Category Name",
+ "confirm": "Confirm"
}
},
"common": {
diff --git a/locales/ko.json b/locales/ko.json
index 20c5d9e..53872e3 100644
--- a/locales/ko.json
+++ b/locales/ko.json
@@ -44,7 +44,8 @@
"label": "카테고리 입력",
"placeholder": "카테고리를 입력해주세요",
"color": "색상",
- "close": "닫기"
+ "close": "닫기",
+ "title": "카테고리 생성"
},
"categoryEditView": {
"category": "카테고리",
@@ -52,7 +53,8 @@
"color": "색상",
"edit": "수정하기",
"delete": "삭제하기",
- "close": "닫기"
+ "close": "닫기",
+ "title": "카테고리 수정"
}
},
"components": {
@@ -94,6 +96,12 @@
"createSubTodoWithAi": "하위 투두 AI로 만들기",
"createSubTodo": "하위 투두 직접 만들기",
"putInbox": "인박스에 넣기"
+ },
+ "categoryModal": {
+ "addCategory": "카테고리 추가",
+ "editCategory": "카테고리 수정",
+ "categoryName": "카테고리 이름",
+ "confirm": "확인"
}
},
"common": {