diff --git a/apps/mobile/app/i18n/ar.ts b/apps/mobile/app/i18n/ar.ts index 349116f8c..d058274ec 100644 --- a/apps/mobile/app/i18n/ar.ts +++ b/apps/mobile/app/i18n/ar.ts @@ -226,6 +226,17 @@ const ar: Translations = { korean: "Korean", hebrew: "Hebrew", }, + versionScreen: { + mainTitle: "نسخ المهمة", + listOfVersions: "قائمة النسخ", + noActiveVersions: "لا توجد نسخ نشطة", + createNewVersionButton: "إنشاء نسخة جديدة", + createNewVersionText: "إنشاء نسخة جديدة", + versionNamePlaceholder: "اسم النسخة", + cancelButtonText: "إلغاء", + createButtonText: "إنشاء", + updateButtonText: "تحديث", + }, statusScreen: { mainTitle: "Task Statuses", statuses: "Statuses", diff --git a/apps/mobile/app/i18n/bg.ts b/apps/mobile/app/i18n/bg.ts index bfe2769f3..0be9773c9 100644 --- a/apps/mobile/app/i18n/bg.ts +++ b/apps/mobile/app/i18n/bg.ts @@ -222,6 +222,17 @@ const bg = { korean: "Korean", hebrew: "Hebrew", }, + versionScreen: { + mainTitle: "Task Versions", + listOfVersions: "List of Versions", + noActiveVersions: "There are no active versions", + createNewVersionButton: "Create new version", + createNewVersionText: "Create New Version", + versionNamePlaceholder: "Version Name", + cancelButtonText: "Cancel", + createButtonText: "Create", + updateButtonText: "Update", + }, statusScreen: { mainTitle: "Task Statuses", listStatuses: "List of Statuses", diff --git a/apps/mobile/app/i18n/en.ts b/apps/mobile/app/i18n/en.ts index 9d2c478d4..c08fc8416 100644 --- a/apps/mobile/app/i18n/en.ts +++ b/apps/mobile/app/i18n/en.ts @@ -223,6 +223,17 @@ const en = { korean: "Korean", hebrew: "Hebrew", }, + versionScreen: { + mainTitle: "Task Versions", + listOfVersions: "List of Versions", + noActiveVersions: "There are no active versions", + createNewVersionButton: "Create new version", + createNewVersionText: "Create New Version", + versionNamePlaceholder: "Version Name", + cancelButtonText: "Cancel", + createButtonText: "Create", + updateButtonText: "Update", + }, statusScreen: { mainTitle: "Task Statuses", statuses: "Statuses", diff --git a/apps/mobile/app/i18n/es.ts b/apps/mobile/app/i18n/es.ts index f81304015..5536beee2 100644 --- a/apps/mobile/app/i18n/es.ts +++ b/apps/mobile/app/i18n/es.ts @@ -222,6 +222,17 @@ const es = { korean: "Korean", hebrew: "Hebrew", }, + versionScreen: { + mainTitle: "Task Versions", + listOfVersions: "List of Versions", + noActiveVersions: "There are no active versions", + createNewVersionButton: "Create new version", + createNewVersionText: "Create New Version", + versionNamePlaceholder: "Version Name", + cancelButtonText: "Cancel", + createButtonText: "Create", + updateButtonText: "Update", + }, statusScreen: { mainTitle: "Task Statuses", listStatuses: "List of Statuses", diff --git a/apps/mobile/app/i18n/fr.ts b/apps/mobile/app/i18n/fr.ts index efe8e2de5..383870aba 100644 --- a/apps/mobile/app/i18n/fr.ts +++ b/apps/mobile/app/i18n/fr.ts @@ -223,6 +223,17 @@ const fr = { korean: "Coréen", hebrew: "Hébreu", }, + versionScreen: { + mainTitle: "Versions de la tâche", + listOfVersions: "Liste des versions", + noActiveVersions: "Aucune version active", + createNewVersionButton: "Créer une nouvelle version", + createNewVersionText: "Créer une nouvelle version", + versionNamePlaceholder: "Nom de la version", + cancelButtonText: "Annuler", + createButtonText: "Créer", + updateButtonText: "Mettre à jour", + }, statusScreen: { mainTitle: "Task Statuses", listStatuses: "List of Statuses", diff --git a/apps/mobile/app/i18n/he.ts b/apps/mobile/app/i18n/he.ts index dc25874d3..295aa4cd4 100644 --- a/apps/mobile/app/i18n/he.ts +++ b/apps/mobile/app/i18n/he.ts @@ -222,6 +222,17 @@ const he = { korean: "Korean", hebrew: "Hebrew", }, + versionScreen: { + mainTitle: "Task Versions", + listOfVersions: "List of Versions", + noActiveVersions: "There are no active versions", + createNewVersionButton: "Create new version", + createNewVersionText: "Create New Version", + versionNamePlaceholder: "Version Name", + cancelButtonText: "Cancel", + createButtonText: "Create", + updateButtonText: "Update", + }, statusScreen: { mainTitle: "Task Statuses", listStatuses: "List of Statuses", diff --git a/apps/mobile/app/i18n/ko.ts b/apps/mobile/app/i18n/ko.ts index 25bc988ce..6270bc276 100644 --- a/apps/mobile/app/i18n/ko.ts +++ b/apps/mobile/app/i18n/ko.ts @@ -225,6 +225,17 @@ const ko: Translations = { korean: "Korean", hebrew: "Hebrew", }, + versionScreen: { + mainTitle: "작업 버전", + listOfVersions: "버전 목록", + noActiveVersions: "활성 버전이 없습니다", + createNewVersionButton: "새 버전 생성", + createNewVersionText: "새 버전 생성", + versionNamePlaceholder: "버전 이름", + cancelButtonText: "취소", + createButtonText: "생성", + updateButtonText: "업데이트", + }, statusScreen: { mainTitle: "Task Statuses", statuses: "Statuses", diff --git a/apps/mobile/app/i18n/ru.ts b/apps/mobile/app/i18n/ru.ts index d5653e98d..985a4cc0b 100644 --- a/apps/mobile/app/i18n/ru.ts +++ b/apps/mobile/app/i18n/ru.ts @@ -222,6 +222,17 @@ const ru = { korean: "Korean", hebrew: "Hebrew", }, + versionScreen: { + mainTitle: "Task Versions", + listOfVersions: "List of Versions", + noActiveVersions: "There are no active versions", + createNewVersionButton: "Create new version", + createNewVersionText: "Create New Version", + versionNamePlaceholder: "Version Name", + cancelButtonText: "Cancel", + createButtonText: "Create", + updateButtonText: "Update", + }, statusScreen: { mainTitle: "Task Statuses", listStatuses: "List of Statuses", diff --git a/apps/mobile/app/navigators/AuthenticatedNavigator.tsx b/apps/mobile/app/navigators/AuthenticatedNavigator.tsx index 6143ced2d..1525078c1 100644 --- a/apps/mobile/app/navigators/AuthenticatedNavigator.tsx +++ b/apps/mobile/app/navigators/AuthenticatedNavigator.tsx @@ -24,6 +24,7 @@ import { TaskPriorityScreen, MembersSettingsScreen, AuthenticatedTaskScreen, + TaskVersionScreen, } from "../screens" // HELPERS @@ -60,6 +61,7 @@ export type AuthenticatedDrawerParamList = { TaskSizeScreen: undefined TaskStatus: undefined TaskPriority: undefined + TaskVersion: undefined MembersSettingsScreen: undefined TaskScreen: { taskId: string } } @@ -252,6 +254,7 @@ export const AuthenticatedNavigator = observer(function AuthenticatedNavigator() + diff --git a/apps/mobile/app/screens/Authenticated/SettingScreen/Team/index.tsx b/apps/mobile/app/screens/Authenticated/SettingScreen/Team/index.tsx index 8d357d355..362e937e5 100644 --- a/apps/mobile/app/screens/Authenticated/SettingScreen/Team/index.tsx +++ b/apps/mobile/app/screens/Authenticated/SettingScreen/Team/index.tsx @@ -16,6 +16,7 @@ import { useTaskStatus } from "../../../../services/hooks/features/useTaskStatus import { useTaskPriority } from "../../../../services/hooks/features/useTaskPriority" import { useTaskSizes } from "../../../../services/hooks/features/useTaskSizes" import { useTaskLabels } from "../../../../services/hooks/features/useTaskLabels" +import { useTaskVersion } from "../../../../services/hooks/features/useTaskVersion" interface ITeamSettingProps { props: any @@ -35,6 +36,7 @@ const TeamSettings: FC = observer(({ props, onOpenBottomSheet const { priorities } = useTaskPriority() const { sizes } = useTaskSizes() const { labels } = useTaskLabels() + const { versions } = useTaskVersion() return ( @@ -54,6 +56,13 @@ const TeamSettings: FC = observer(({ props, onOpenBottomSheet onPress={() => onOpenBottomSheet("Team Name", 4)} /> {isTeamManager ? : null} + navigation.navigate("TaskVersion")} + /> = observer(({ props, onOpenBottomSheet /> navigation.navigate("TaskLabelScreen")} diff --git a/apps/mobile/app/screens/Authenticated/TaskVersionScreen/components/TaskVersionForm.tsx b/apps/mobile/app/screens/Authenticated/TaskVersionScreen/components/TaskVersionForm.tsx new file mode 100644 index 000000000..b3fa3cf6c --- /dev/null +++ b/apps/mobile/app/screens/Authenticated/TaskVersionScreen/components/TaskVersionForm.tsx @@ -0,0 +1,163 @@ +/* eslint-disable react-native/no-color-literals */ +/* eslint-disable react-native/no-inline-styles */ +import React, { useEffect, useState } from "react" +import { View, Text, TouchableOpacity, TextInput, StyleSheet, Keyboard } from "react-native" +import { translate } from "../../../../i18n" +import { typography, useAppTheme } from "../../../../theme" + +import { + ITaskVersionCreate, + ITaskVersionItemList, +} from "../../../../services/interfaces/ITaskVersion" + +const TaskVersionForm = ({ + isEdit, + onDismiss, + item, + onCreateVersion, + onUpdateVersion, +}: { + isEdit: boolean + onDismiss: () => unknown + item?: ITaskVersionItemList + onUpdateVersion: (id: string, data: ITaskVersionCreate) => unknown + onCreateVersion: (data: ITaskVersionCreate) => unknown +}) => { + const { colors, dark } = useAppTheme() + const [versionName, setVersionName] = useState(null) + + useEffect(() => { + if (isEdit) { + setVersionName(item.name) + } else { + setVersionName(null) + } + }, [item, isEdit]) + + const handleSubmit = async () => { + if (versionName.trim().length <= 0) { + return + } + + if (isEdit) { + await onUpdateVersion(item?.id, { + name: versionName, + }) + } else { + await onCreateVersion({ + name: versionName, + color: "#FFFFFF", + }) + } + + setVersionName(null) + onDismiss() + } + + return ( + + + {translate("settingScreen.versionScreen.createNewVersionText")} + + setVersionName(text)} + /> + + + { + onDismiss() + Keyboard.dismiss() + }} + > + + {translate("settingScreen.versionScreen.cancelButtonText")} + + + { + if (versionName) { + handleSubmit().finally(() => Keyboard.dismiss()) + } + }} + > + + {isEdit + ? translate("settingScreen.versionScreen.updateButtonText") + : translate("settingScreen.versionScreen.createButtonText")} + + + + + ) +} + +export default TaskVersionForm + +const styles = StyleSheet.create({ + cancelBtn: { + alignItems: "center", + backgroundColor: "#E6E6E9", + borderRadius: 12, + height: 57, + justifyContent: "center", + width: "48%", + }, + cancelTxt: { + color: "#1A1C1E", + fontFamily: typography.primary.semiBold, + fontSize: 18, + }, + createBtn: { + alignItems: "center", + backgroundColor: "#3826A6", + borderRadius: 12, + height: 57, + justifyContent: "center", + width: "48%", + }, + createTxt: { + color: "#FFF", + fontFamily: typography.primary.semiBold, + fontSize: 18, + }, + formTitle: { + color: "#1A1C1E", + fontFamily: typography.primary.semiBold, + fontSize: 24, + }, + versionNameInput: { + alignItems: "center", + borderColor: "#DCE4E8", + borderRadius: 12, + borderWidth: 1, + height: 57, + marginTop: 16, + paddingHorizontal: 18, + width: "100%", + }, + wrapButtons: { + flexDirection: "row", + justifyContent: "space-between", + marginTop: 40, + width: "100%", + }, +}) diff --git a/apps/mobile/app/screens/Authenticated/TaskVersionScreen/components/VersionItem.tsx b/apps/mobile/app/screens/Authenticated/TaskVersionScreen/components/VersionItem.tsx new file mode 100644 index 000000000..cbca71e1d --- /dev/null +++ b/apps/mobile/app/screens/Authenticated/TaskVersionScreen/components/VersionItem.tsx @@ -0,0 +1,89 @@ +/* eslint-disable react-native/no-color-literals */ +/* eslint-disable react-native/no-inline-styles */ +import React, { FC } from "react" +import { View, Text, StyleSheet } from "react-native" +import { AntDesign, Ionicons } from "@expo/vector-icons" +import { typography, useAppTheme } from "../../../../theme" +import { formatName } from "../../../../helpers/name-format" +import { ITaskVersionItemList } from "../../../../services/interfaces/ITaskVersion" + +interface IVersionItem { + version: ITaskVersionItemList + onDeleteTask: () => unknown + openForEdit: () => unknown +} + +const VersionItem: FC = ({ version, onDeleteTask, openForEdit }) => { + const { colors, dark } = useAppTheme() + + return ( + + + + {formatName(version?.name)} + + + + openForEdit()} + /> + onDeleteTask()} + /> + + + ) +} + +export default VersionItem + +const styles = StyleSheet.create({ + container: { + alignItems: "center", + borderRadius: 10, + borderWidth: 1, + flexDirection: "row", + justifyContent: "space-between", + marginTop: 16, + padding: 6, + paddingRight: 16, + width: "100%", + }, + rightSection: { + flexDirection: "row", + justifyContent: "space-between", + width: "16%", + }, + text: { + fontFamily: typography.primary.medium, + fontSize: 14, + marginLeft: 13.5, + }, + versionContainer: { + alignItems: "center", + backgroundColor: "#D4EFDF", + borderRadius: 10, + flexDirection: "row", + height: "100%", + paddingHorizontal: 16, + paddingVertical: 12, + width: "60%", + }, +}) diff --git a/apps/mobile/app/screens/Authenticated/TaskVersionScreen/index.tsx b/apps/mobile/app/screens/Authenticated/TaskVersionScreen/index.tsx new file mode 100644 index 000000000..c72f909b6 --- /dev/null +++ b/apps/mobile/app/screens/Authenticated/TaskVersionScreen/index.tsx @@ -0,0 +1,216 @@ +/* eslint-disable react-native/no-color-literals */ +/* eslint-disable react-native/no-inline-styles */ +import React, { FC, useRef, useState } from "react" +import { + View, + Text, + ViewStyle, + TouchableOpacity, + StyleSheet, + ActivityIndicator, + FlatList, +} from "react-native" +import { AntDesign, Ionicons } from "@expo/vector-icons" +import { Screen } from "../../../components" +import { AuthenticatedDrawerScreenProps } from "../../../navigators/AuthenticatedNavigator" +import { translate } from "../../../i18n" +import { typography, useAppTheme } from "../../../theme" +import BottomSheet from "reanimated-bottom-sheet" +import Animated from "react-native-reanimated" +import { useTaskVersion } from "../../../services/hooks/features/useTaskVersion" +import { ITaskVersionItemList } from "../../../services/interfaces/ITaskVersion" +import { BlurView } from "expo-blur" +import VersionItem from "./components/VersionItem" +import TaskVersionForm from "./components/TaskVersionForm" + +export const TaskVersionScreen: FC> = + function AuthenticatedDrawerScreen(_props) { + const { colors, dark } = useAppTheme() + const { navigation } = _props + + const { isLoading, versions, deleteTaskVersion, updateTaskVersion, createTaskVersion } = + useTaskVersion() + + const [editMode, setEditMode] = useState(false) + const [itemToEdit, setItemToEdit] = useState(null) + const [isSheetOpen, setIsSheetOpen] = useState(false) + + const sheetRef = useRef(null) + + const fall = new Animated.Value(1) + const openForEdit = (item: ITaskVersionItemList) => { + setEditMode(true) + setIsSheetOpen(true) + setItemToEdit(item) + sheetRef.current.snapTo(0) + } + + return ( + + + + + navigation.navigate("Setting")}> + + + + {translate("settingScreen.versionScreen.mainTitle")} + + + + + + + + {translate("settingScreen.versionScreen.listOfVersions")} + + + + {isLoading ? ( + + ) : null} + {!isLoading && versions?.total === 0 ? ( + + {translate("settingScreen.versionScreen.noActiveVersions")} + + ) : null} + + ( + openForEdit(item)} + onDeleteTask={() => deleteTaskVersion(item.id)} + version={item} + /> + )} + keyExtractor={(_, index) => index.toString()} + ListFooterComponent={() => } + /> + + + { + setEditMode(false) + setIsSheetOpen(true) + sheetRef.current.snapTo(0) + }} + > + + + {translate("settingScreen.versionScreen.createNewVersionButton")} + + + + {isSheetOpen && ( + + )} + ( + { + setEditMode(false) + setIsSheetOpen(false) + sheetRef.current.snapTo(1) + }} + onUpdateVersion={updateTaskVersion} + onCreateVersion={createTaskVersion} + isEdit={editMode} + /> + )} + /> + + ) + } + +const $container: ViewStyle = { + flex: 1, +} +const $headerContainer: ViewStyle = { + padding: 20, + paddingVertical: 16, + shadowColor: "rgba(0, 0, 0, 0.6)", + shadowOffset: { + width: 0, + height: 2, + }, + shadowOpacity: 0.07, + shadowRadius: 1.0, + elevation: 1, + zIndex: 10, +} + +const styles = StyleSheet.create({ + btnText: { + color: "#3826A6", + fontFamily: typography.primary.semiBold, + fontSize: 18, + fontStyle: "normal", + }, + container: { + alignItems: "center", + flexDirection: "row", + width: "100%", + }, + createButton: { + alignItems: "center", + alignSelf: "center", + borderColor: "#3826A6", + borderRadius: 12, + borderWidth: 2, + flexDirection: "row", + justifyContent: "center", + marginTop: 24, + padding: 16, + width: "90%", + }, + noVersionTxt: { + color: "#7E7991", + fontFamily: typography.primary.semiBold, + fontSize: 16, + }, + title: { + alignSelf: "center", + fontFamily: typography.primary.semiBold, + fontSize: 16, + textAlign: "center", + width: "80%", + }, + title2: { + color: "#7E7991", + fontFamily: typography.primary.semiBold, + fontSize: 16, + marginBottom: 8, + }, +}) diff --git a/apps/mobile/app/screens/index.ts b/apps/mobile/app/screens/index.ts index 523cf83c5..ec32fc0c4 100644 --- a/apps/mobile/app/screens/index.ts +++ b/apps/mobile/app/screens/index.ts @@ -17,3 +17,4 @@ export * from "./Authenticated/TaskLabelScreen" export * from "./Authenticated/TaskSizeScreen" export * from "./Authenticated/MembersSettingsScreen" export * from "./Authenticated/TaskScreen" +export * from "./Authenticated/TaskVersionScreen" diff --git a/apps/mobile/app/services/client/requests/task-version.ts b/apps/mobile/app/services/client/requests/task-version.ts index 4c300c850..6a5fe12f2 100644 --- a/apps/mobile/app/services/client/requests/task-version.ts +++ b/apps/mobile/app/services/client/requests/task-version.ts @@ -1,4 +1,5 @@ /* eslint-disable camelcase */ +import { PaginationResponse } from "../../interfaces/IDataResponse" import { ITaskVersionCreate, ITaskVersionItemList } from "../../interfaces/ITaskVersion" import { serverFetch } from "../fetch" @@ -65,7 +66,7 @@ export function getTaskVersionListRequest( }, bearer_token: string, ) { - return serverFetch({ + return serverFetch>({ path: `/task-versions?tenantId=${tenantId}&organizationId=${organizationId}&organizationTeamId=${activeTeamId}`, method: "GET", bearer_token, diff --git a/apps/mobile/app/services/hooks/features/useTaskVersion.ts b/apps/mobile/app/services/hooks/features/useTaskVersion.ts index 95e82a49d..d3a53eb6d 100644 --- a/apps/mobile/app/services/hooks/features/useTaskVersion.ts +++ b/apps/mobile/app/services/hooks/features/useTaskVersion.ts @@ -27,7 +27,11 @@ export function useTaskVersion() { const createTaskVersion = useCallback( async (data: ITaskVersionCreate) => { - await createVersionRequest(data, authToken, tenantId) + await createVersionRequest( + { ...data, organizationId, organizationTeamId: activeTeamId }, + authToken, + tenantId, + ) queryClient.invalidateQueries("versions") }, [authToken, tenantId, queryClient], @@ -43,8 +47,13 @@ export function useTaskVersion() { ) const updateTaskVersion = useCallback( - async ({ id, data }) => { - await editTaskVersionRequest({ id, datas: data, bearer_token: authToken, tenantId }) + async (id: string, data: ITaskVersionCreate) => { + await editTaskVersionRequest({ + id, + datas: { ...data, organizationId, organizationTeamId: activeTeamId }, + bearer_token: authToken, + tenantId, + }) queryClient.invalidateQueries("versions") }, [authToken, tenantId, queryClient],