diff --git a/apps/mobile/app/components/Task/DetailsBlock/blocks/TaskMainInfo.tsx b/apps/mobile/app/components/Task/DetailsBlock/blocks/TaskMainInfo.tsx index 107dafe59..849dfd31d 100644 --- a/apps/mobile/app/components/Task/DetailsBlock/blocks/TaskMainInfo.tsx +++ b/apps/mobile/app/components/Task/DetailsBlock/blocks/TaskMainInfo.tsx @@ -148,6 +148,7 @@ const TaskMainInfo = observer(() => { > { > { > { > unknown + task?: ITeamTask; + containerStyle?: ViewStyle; + priority?: string; + setPriority?: (priority: string) => unknown; + canCreatePriority?: boolean; } const TaskPriority: FC = observer( - ({ task, containerStyle, priority, setPriority }) => { - const { colors } = useAppTheme() - const { updateTask } = useTeamTasks() - const [openModal, setOpenModal] = useState(false) + ({ task, containerStyle, priority, setPriority, canCreatePriority }) => { + const { colors } = useAppTheme(); + const { updateTask } = useTeamTasks(); + const [openModal, setOpenModal] = useState(false); - const allTaskPriorities = useTaskPriorityValue() + const allTaskPriorities = useTaskPriorityValue(); const sizeValue = ( - task?.priority?.split("-").join(" ") || - (priority && priority.split("-").join(" ")) - )?.toLowerCase() + task?.priority?.split('-').join(' ') || + (priority && priority.split('-').join(' ')) + )?.toLowerCase(); const currentPriority = - allTaskPriorities && - Object.values(allTaskPriorities).find((item) => item.name.toLowerCase() === sizeValue) + allTaskPriorities && Object.values(allTaskPriorities).find((item) => item.name.toLowerCase() === sizeValue); const onChangePriority = async (text: string) => { if (task) { const taskEdit = { ...task, - priority: task?.priority === text ? null : text, - } + priority: task?.priority === text ? null : text + }; - await updateTask(taskEdit, task.id) + await updateTask(taskEdit, task.id); } else { - setPriority(text) + setPriority(text); } - } + }; return ( <> @@ -56,6 +56,7 @@ const TaskPriority: FC = observer( visible={openModal} setSelectedPriority={(e) => onChangePriority(e.value)} onDismiss={() => setOpenModal(false)} + canCreatePriority={canCreatePriority} /> setOpenModal(true)}> = observer( ...styles.container, ...containerStyle, borderColor: colors.border, - backgroundColor: currentPriority?.bgColor, + backgroundColor: currentPriority?.bgColor }} > {(task?.priority || priority) && currentPriority ? ( @@ -72,53 +73,51 @@ const TaskPriority: FC = observer( {limitTextCharaters({ text: currentPriority.name, - numChars: 15, + numChars: 15 })} ) : ( - - {translate("settingScreen.priorityScreen.priorities")} + + {translate('settingScreen.priorityScreen.priorities')} )} - ) - }, -) + ); + } +); const styles = StyleSheet.create({ container: { - alignItems: "center", - borderColor: "rgba(0,0,0,0.16)", + alignItems: 'center', + borderColor: 'rgba(0,0,0,0.16)', borderRadius: 10, borderWidth: 1, - flexDirection: "row", - justifyContent: "space-between", + flexDirection: 'row', + justifyContent: 'space-between', minHeight: 30, minWidth: 100, - paddingHorizontal: 8, + paddingHorizontal: 8 }, text: { fontFamily: typography.fonts.PlusJakartaSans.semiBold, - fontSize: 10, + fontSize: 10 }, wrapStatus: { - alignItems: "center", - flexDirection: "row", - width: "70%", - }, -}) + alignItems: 'center', + flexDirection: 'row', + width: '70%' + } +}); -export default TaskPriority +export default TaskPriority; diff --git a/apps/mobile/app/components/TaskPriorityPopup.tsx b/apps/mobile/app/components/TaskPriorityPopup.tsx index 900fe1dc8..d492db6fd 100644 --- a/apps/mobile/app/components/TaskPriorityPopup.tsx +++ b/apps/mobile/app/components/TaskPriorityPopup.tsx @@ -1,6 +1,6 @@ /* eslint-disable react-native/no-inline-styles */ /* eslint-disable react-native/no-color-literals */ -import React, { FC } from 'react'; +import React, { FC, useState } from 'react'; import { View, ViewStyle, @@ -12,19 +12,21 @@ import { TouchableOpacity, TouchableWithoutFeedback } from 'react-native'; -import { Feather, AntDesign } from '@expo/vector-icons'; -import { spacing, useAppTheme } from '../theme'; +import { Feather, AntDesign, Ionicons } from '@expo/vector-icons'; +import { spacing, useAppTheme, typography } from '../theme'; import { BadgedTaskPriority } from './PriorityIcon'; import { useTaskPriority } from '../services/hooks/features/useTaskPriority'; import { ITaskPriorityItem } from '../services/interfaces/ITaskPriority'; import { translate } from '../i18n'; import { BlurView } from 'expo-blur'; +import TaskPriorityForm from '../screens/Authenticated/TaskPrioritiesScreen/components/TaskPriorityForm'; export interface Props { visible: boolean; onDismiss: () => unknown; priorityName: string; setSelectedPriority: (status: ITaskPriorityItem) => unknown; + canCreatePriority?: boolean; } const ModalPopUp = ({ visible, children, onDismiss }) => { @@ -74,10 +76,15 @@ const TaskPriorityPopup: FC = function TaskPriorityPopup({ visible, onDismiss, setSelectedPriority, - priorityName + priorityName, + canCreatePriority }) { const { allTaskPriorities } = useTaskPriority(); - const { colors } = useAppTheme(); + const { colors, dark } = useAppTheme(); + const { createPriority, updatePriority } = useTaskPriority(); + + const [createPriorityMode, setCreatePriorityMode] = useState(false); + const onPrioritySelected = (size: ITaskPriorityItem) => { setSelectedPriority(size); onDismiss(); @@ -85,20 +92,61 @@ const TaskPriorityPopup: FC = function TaskPriorityPopup({ return ( - - - {translate('settingScreen.priorityScreen.priorities')} - - ( - - )} - legacyImplementation={true} - showsVerticalScrollIndicator={true} - keyExtractor={(_, index) => index.toString()} - /> + + {!createPriorityMode ? ( + <> + + {translate('settingScreen.priorityScreen.priorities')} + + ( + + )} + legacyImplementation={true} + showsVerticalScrollIndicator={true} + keyExtractor={(_, index) => index.toString()} + /> + {canCreatePriority && ( + setCreatePriorityMode(true)} + > + + + {translate('settingScreen.priorityScreen.createNewPriorityText')} + + + )} + + ) : ( + setCreatePriorityMode(false)} + onCreatePriority={createPriority} + onUpdatePriority={updatePriority} + isEdit={false} + /> + )} ); @@ -138,6 +186,12 @@ const $modalBackGround: ViewStyle = { }; const styles = StyleSheet.create({ + btnText: { + color: '#3826A6', + fontFamily: typography.primary.semiBold, + fontSize: 16, + fontStyle: 'normal' + }, colorFrame: { borderRadius: 10, height: 44, @@ -154,6 +208,18 @@ const styles = StyleSheet.create({ paddingVertical: 16, width: '90%' }, + createButton: { + alignItems: 'center', + alignSelf: 'center', + borderColor: '#3826A6', + borderRadius: 12, + borderWidth: 2, + flexDirection: 'row', + justifyContent: 'center', + marginTop: 10, + padding: 12, + width: '80%' + }, title: { fontSize: spacing.medium - 2, marginBottom: 16, diff --git a/apps/mobile/app/components/TaskSize.tsx b/apps/mobile/app/components/TaskSize.tsx index 4d5587902..0aad6c20e 100644 --- a/apps/mobile/app/components/TaskSize.tsx +++ b/apps/mobile/app/components/TaskSize.tsx @@ -1,60 +1,57 @@ /* eslint-disable react-native/no-color-literals */ /* eslint-disable react-native/no-inline-styles */ -import React, { FC, useState } from "react" -import { TouchableOpacity, View, Text, StyleSheet, ViewStyle, TextStyle } from "react-native" -import { AntDesign, Entypo } from "@expo/vector-icons" -import { observer } from "mobx-react-lite" -import { ITeamTask } from "../services/interfaces/ITask" -import { useTeamTasks } from "../services/hooks/features/useTeamTasks" -import { showMessage } from "react-native-flash-message" -import { typography, useAppTheme } from "../theme" -import TaskSizePopup from "./TaskSizePopup" -import { translate } from "../i18n" -import { limitTextCharaters } from "../helpers/sub-text" -import { useTaskSizeValue } from "./StatusType" +import React, { FC, useState } from 'react'; +import { TouchableOpacity, View, Text, StyleSheet, ViewStyle, TextStyle } from 'react-native'; +import { AntDesign, Entypo } from '@expo/vector-icons'; +import { observer } from 'mobx-react-lite'; +import { ITeamTask } from '../services/interfaces/ITask'; +import { useTeamTasks } from '../services/hooks/features/useTeamTasks'; +import { showMessage } from 'react-native-flash-message'; +import { typography, useAppTheme } from '../theme'; +import TaskSizePopup from './TaskSizePopup'; +import { translate } from '../i18n'; +import { limitTextCharaters } from '../helpers/sub-text'; +import { useTaskSizeValue } from './StatusType'; interface TaskSizeProps { - task?: ITeamTask - containerStyle?: ViewStyle - statusTextSyle?: TextStyle - size?: string - setSize?: (size: string) => unknown + task?: ITeamTask; + containerStyle?: ViewStyle; + statusTextSyle?: TextStyle; + size?: string; + setSize?: (size: string) => unknown; + canCreateSize?: boolean; } -const TaskSize: FC = observer(({ task, containerStyle, setSize, size }) => { - const { colors } = useAppTheme() - const { updateTask } = useTeamTasks() - const [openModal, setOpenModal] = useState(false) +const TaskSize: FC = observer(({ task, containerStyle, setSize, size, canCreateSize }) => { + const { colors } = useAppTheme(); + const { updateTask } = useTeamTasks(); + const [openModal, setOpenModal] = useState(false); - const allTaskSizes = useTaskSizeValue() + const allTaskSizes = useTaskSizeValue(); - const sizeValue = ( - task?.size?.split("-").join(" ") || - (size && size.split("-").join(" ")) - )?.toLowerCase() + const sizeValue = (task?.size?.split('-').join(' ') || (size && size.split('-').join(' ')))?.toLowerCase(); const currentSize = - allTaskSizes && - Object.values(allTaskSizes).find((item) => item.name.toLowerCase() === sizeValue) + allTaskSizes && Object.values(allTaskSizes).find((item) => item.name.toLowerCase() === sizeValue); const onChangeSize = async (text: string) => { if (task) { const taskEdit = { ...task, - size: task?.size === text ? null : text, - } + size: task?.size === text ? null : text + }; - const { response } = await updateTask(taskEdit, task.id) + const { response } = await updateTask(taskEdit, task.id); if (response.status !== 202) { showMessage({ - message: "Something went wrong", - type: "danger", - }) + message: 'Something went wrong', + type: 'danger' + }); } } else { - setSize(text) + setSize(text); } - } + }; return ( <> @@ -63,6 +60,7 @@ const TaskSize: FC = observer(({ task, containerStyle, setSize, s visible={openModal} setSelectedSize={(e) => onChangeSize(e.value)} onDismiss={() => setOpenModal(false)} + canCreateSize={canCreateSize} /> setOpenModal(true)}> = observer(({ task, containerStyle, setSize, s ...styles.container, ...containerStyle, borderColor: colors.border, - backgroundColor: currentSize?.bgColor, + backgroundColor: currentSize?.bgColor }} > {(task?.size || size) && currentSize ? ( @@ -84,42 +82,38 @@ const TaskSize: FC = observer(({ task, containerStyle, setSize, s - {translate("settingScreen.sizeScreen.sizes")} + {translate('settingScreen.sizeScreen.sizes')} )} - + - ) -}) + ); +}); const styles = StyleSheet.create({ container: { - alignItems: "center", - borderColor: "rgba(0,0,0,0.16)", + alignItems: 'center', + borderColor: 'rgba(0,0,0,0.16)', borderRadius: 10, borderWidth: 1, - flexDirection: "row", - justifyContent: "space-between", + flexDirection: 'row', + justifyContent: 'space-between', minHeight: 30, minWidth: 100, - paddingHorizontal: 8, + paddingHorizontal: 8 }, text: { fontFamily: typography.fonts.PlusJakartaSans.semiBold, - fontSize: 10, + fontSize: 10 }, wrapStatus: { - alignItems: "center", - flexDirection: "row", - width: "70%", - }, -}) + alignItems: 'center', + flexDirection: 'row', + width: '70%' + } +}); -export default TaskSize +export default TaskSize; diff --git a/apps/mobile/app/components/TaskSizePopup.tsx b/apps/mobile/app/components/TaskSizePopup.tsx index 9e5c83896..557256607 100644 --- a/apps/mobile/app/components/TaskSizePopup.tsx +++ b/apps/mobile/app/components/TaskSizePopup.tsx @@ -1,6 +1,6 @@ /* eslint-disable react-native/no-inline-styles */ /* eslint-disable react-native/no-color-literals */ -import React, { FC } from 'react'; +import React, { FC, useState } from 'react'; import { View, ViewStyle, @@ -12,19 +12,21 @@ import { TouchableOpacity, TouchableWithoutFeedback } from 'react-native'; -import { Feather, AntDesign } from '@expo/vector-icons'; -import { spacing, useAppTheme } from '../theme'; +import { Feather, AntDesign, Ionicons } from '@expo/vector-icons'; +import { spacing, useAppTheme, typography } from '../theme'; import { useTaskSizes } from '../services/hooks/features/useTaskSizes'; import { ITaskSizeItem } from '../services/interfaces/ITaskSize'; import { BadgedTaskSize } from './SizeIcon'; import { translate } from '../i18n'; import { BlurView } from 'expo-blur'; +import TaskSizeForm from '../screens/Authenticated/TaskSizeScreen/components/TaskSizeForm'; export interface Props { visible: boolean; onDismiss: () => unknown; sizeName: string; setSelectedSize: (status: ITaskSizeItem) => unknown; + canCreateSize?: boolean; } const ModalPopUp = ({ visible, children, onDismiss }) => { @@ -70,9 +72,19 @@ const ModalPopUp = ({ visible, children, onDismiss }) => { ); }; -const TaskStatusPopup: FC = function FilterPopup({ visible, onDismiss, setSelectedSize, sizeName }) { +const TaskStatusPopup: FC = function FilterPopup({ + visible, + onDismiss, + setSelectedSize, + sizeName, + canCreateSize +}) { const { allTaskSizes } = useTaskSizes(); - const { colors } = useAppTheme(); + const { colors, dark } = useAppTheme(); + const { createSize, updateSize } = useTaskSizes(); + + const [createSizeMode, setCreateSizeMode] = useState(false); + const onStatusSelected = (size: ITaskSizeItem) => { setSelectedSize(size); onDismiss(); @@ -80,20 +92,57 @@ const TaskStatusPopup: FC = function FilterPopup({ visible, onDismiss, se return ( - - - {translate('settingScreen.sizeScreen.sizes')} - - ( - - )} - legacyImplementation={true} - showsVerticalScrollIndicator={true} - keyExtractor={(_, index) => index.toString()} - /> + + {!createSizeMode ? ( + <> + + {translate('settingScreen.sizeScreen.sizes')} + + ( + + )} + legacyImplementation={true} + showsVerticalScrollIndicator={true} + keyExtractor={(_, index) => index.toString()} + /> + {canCreateSize && ( + setCreateSizeMode(true)} + > + + + {translate('settingScreen.sizeScreen.createNewSizeText')} + + + )} + + ) : ( + setCreateSizeMode(false)} + onCreateSize={createSize} + onUpdateSize={updateSize} + isEdit={false} + /> + )} ); @@ -133,6 +182,12 @@ const $modalBackGround: ViewStyle = { }; const styles = StyleSheet.create({ + btnText: { + color: '#3826A6', + fontFamily: typography.primary.semiBold, + fontSize: 16, + fontStyle: 'normal' + }, colorFrame: { borderRadius: 10, height: 44, @@ -149,6 +204,18 @@ const styles = StyleSheet.create({ paddingVertical: 16, width: '90%' }, + createButton: { + alignItems: 'center', + alignSelf: 'center', + borderColor: '#3826A6', + borderRadius: 12, + borderWidth: 2, + flexDirection: 'row', + justifyContent: 'center', + marginTop: 10, + padding: 12, + width: '80%' + }, title: { fontSize: spacing.medium - 2, marginBottom: 16, diff --git a/apps/mobile/app/components/TaskStatus.tsx b/apps/mobile/app/components/TaskStatus.tsx index e2d54a7aa..e42821c89 100644 --- a/apps/mobile/app/components/TaskStatus.tsx +++ b/apps/mobile/app/components/TaskStatus.tsx @@ -1,55 +1,55 @@ /* eslint-disable react-native/no-color-literals */ /* eslint-disable react-native/no-inline-styles */ -import React, { FC, useState } from "react" -import { TouchableOpacity, View, Text, StyleSheet, ViewStyle, TextStyle } from "react-native" -import { AntDesign, Feather } from "@expo/vector-icons" -import { ITeamTask } from "../services/interfaces/ITask" -import { observer } from "mobx-react-lite" -import { useTeamTasks } from "../services/hooks/features/useTeamTasks" -import TaskStatusPopup from "./TaskStatusPopup" -import { typography, useAppTheme } from "../theme" -import { translate } from "../i18n" -import { useTaskStatusValue } from "./StatusType" -import { limitTextCharaters } from "../helpers/sub-text" +import React, { FC, useState } from 'react'; +import { TouchableOpacity, View, Text, StyleSheet, ViewStyle, TextStyle } from 'react-native'; +import { AntDesign, Feather } from '@expo/vector-icons'; +import { ITeamTask } from '../services/interfaces/ITask'; +import { observer } from 'mobx-react-lite'; +import { useTeamTasks } from '../services/hooks/features/useTeamTasks'; +import TaskStatusPopup from './TaskStatusPopup'; +import { typography, useAppTheme } from '../theme'; +import { translate } from '../i18n'; +import { useTaskStatusValue } from './StatusType'; +import { limitTextCharaters } from '../helpers/sub-text'; interface TaskStatusProps { - task?: ITeamTask - containerStyle?: ViewStyle - statusTextSyle?: TextStyle - iconsOnly?: boolean - labelOnly?: boolean - status?: string - setStatus?: (status: string) => unknown + task?: ITeamTask; + containerStyle?: ViewStyle; + statusTextSyle?: TextStyle; + iconsOnly?: boolean; + labelOnly?: boolean; + status?: string; + setStatus?: (status: string) => unknown; + canCreateStatus?: boolean; } const TaskStatus: FC = observer( - ({ task, containerStyle, status, setStatus, iconsOnly, labelOnly }) => { - const { colors, dark } = useAppTheme() - const { updateTask } = useTeamTasks() - const [openModal, setOpenModal] = useState(false) + ({ task, containerStyle, status, setStatus, iconsOnly, labelOnly, canCreateStatus }) => { + const { colors, dark } = useAppTheme(); + const { updateTask } = useTeamTasks(); + const [openModal, setOpenModal] = useState(false); - const allStatuses = useTaskStatusValue() + const allStatuses = useTaskStatusValue(); const statusValue = ( - task?.status?.split("-").join(" ") || - (status && status.split("-").join(" ")) - )?.toLowerCase() + task?.status?.split('-').join(' ') || + (status && status.split('-').join(' ')) + )?.toLowerCase(); const statusItem = - allStatuses && - Object.values(allStatuses).find((item) => item?.name.toLowerCase() === statusValue) + allStatuses && Object.values(allStatuses).find((item) => item?.name.toLowerCase() === statusValue); const onChangeStatus = async (text: string) => { if (task) { const taskEdit = { ...task, - status: task?.status === text ? null : text, - } + status: task?.status === text ? null : text + }; - await updateTask(taskEdit, task.id) + await updateTask(taskEdit, task.id); } else { - setStatus(text) + setStatus(text); } - } + }; return ( <> @@ -58,6 +58,7 @@ const TaskStatus: FC = observer( visible={openModal} setSelectedStatus={(e) => onChangeStatus(e)} onDismiss={() => setOpenModal(false)} + canCreateStatus={canCreateStatus} /> setOpenModal(true)}> = observer( ...styles.container, borderWidth: iconsOnly ? 0 : 1, ...containerStyle, - backgroundColor: !dark ? "#F2F2F2" : colors.background, - borderColor: colors.border, + backgroundColor: !dark ? '#F2F2F2' : colors.background, + borderColor: colors.border }, - statusItem ? { backgroundColor: statusItem?.bgColor } : null, + statusItem ? { backgroundColor: statusItem?.bgColor } : null ]} > {statusItem ? ( - + {!labelOnly && statusItem.icon} {iconsOnly ? null : ( = observer( style={{ ...styles.text, marginLeft: labelOnly ? 0 : 11, - fontSize: labelOnly ? 8 : 10, + fontSize: labelOnly ? 8 : 10 }} > {limitTextCharaters({ text: statusItem?.name, - numChars: 11, + numChars: 11 })} )} @@ -96,40 +97,40 @@ const TaskStatus: FC = observer( {iconsOnly ? ( ) : ( - translate("settingScreen.statusScreen.statuses") + translate('settingScreen.statusScreen.statuses') )} )} - ) - }, -) + ); + } +); const styles = StyleSheet.create({ container: { - alignItems: "center", + alignItems: 'center', borderRadius: 10, - flexDirection: "row", - justifyContent: "space-between", + flexDirection: 'row', + justifyContent: 'space-between', minHeight: 30, - paddingHorizontal: 8, + paddingHorizontal: 8 }, text: { fontFamily: typography.fonts.PlusJakartaSans.semiBold, fontSize: 10, - textTransform: "capitalize", + textTransform: 'capitalize' }, wrapStatus: { - alignItems: "center", - flexDirection: "row", - }, -}) + alignItems: 'center', + flexDirection: 'row' + } +}); -export default TaskStatus +export default TaskStatus; diff --git a/apps/mobile/app/components/TaskStatusPopup.tsx b/apps/mobile/app/components/TaskStatusPopup.tsx index 236277269..2caa183b9 100644 --- a/apps/mobile/app/components/TaskStatusPopup.tsx +++ b/apps/mobile/app/components/TaskStatusPopup.tsx @@ -1,6 +1,6 @@ /* eslint-disable react-native/no-inline-styles */ /* eslint-disable react-native/no-color-literals */ -import React, { FC } from 'react'; +import React, { FC, useState } from 'react'; import { View, ViewStyle, @@ -12,19 +12,21 @@ import { TouchableOpacity, TouchableWithoutFeedback } from 'react-native'; -import { Feather, AntDesign } from '@expo/vector-icons'; +import { Feather, AntDesign, Ionicons } from '@expo/vector-icons'; import { useTaskStatus } from '../services/hooks/features/useTaskStatus'; import { ITaskStatusItem } from '../services/interfaces/ITaskStatus'; import { spacing, typography, useAppTheme } from '../theme'; import { translate } from '../i18n'; import { useTaskStatusValue } from './StatusType'; import { BlurView } from 'expo-blur'; +import TaskStatusForm from '../screens/Authenticated/TaskStatusScreen/components/TaskStatusForm'; export interface Props { visible: boolean; onDismiss: () => unknown; statusName: string; setSelectedStatus?: (status: string) => unknown; + canCreateStatus?: boolean; } const ModalPopUp = ({ visible, children, onDismiss }) => { @@ -70,9 +72,20 @@ const ModalPopUp = ({ visible, children, onDismiss }) => { ); }; -const TaskStatusPopup: FC = function FilterPopup({ visible, onDismiss, setSelectedStatus, statusName }) { +const TaskStatusPopup: FC = function FilterPopup({ + visible, + onDismiss, + setSelectedStatus, + statusName, + canCreateStatus +}) { const { allStatuses } = useTaskStatus(); - const { colors } = useAppTheme(); + const { colors, dark } = useAppTheme(); + + const [createStatusMode, setCreateStatusMode] = useState(false); + + const { createStatus, updateStatus } = useTaskStatus(); + const onStatusSelected = (status: string) => { setSelectedStatus(status); onDismiss(); @@ -80,20 +93,61 @@ const TaskStatusPopup: FC = function FilterPopup({ visible, onDismiss, se return ( - - - {translate('settingScreen.statusScreen.statuses')} - - ( - - )} - legacyImplementation={true} - showsVerticalScrollIndicator={true} - keyExtractor={(_, index) => index.toString()} - /> + + {!createStatusMode ? ( + <> + + {translate('settingScreen.statusScreen.statuses')} + + ( + + )} + legacyImplementation={true} + showsVerticalScrollIndicator={true} + keyExtractor={(_, index) => index.toString()} + /> + {canCreateStatus && ( + setCreateStatusMode(true)} + > + + + {translate('settingScreen.statusScreen.createNewStatusText')} + + + )} + + ) : ( + setCreateStatusMode(false)} + onCreateStatus={createStatus} + onUpdateStatus={updateStatus} + isEdit={false} + /> + )} ); @@ -139,6 +193,12 @@ const $modalBackGround: ViewStyle = { }; const styles = StyleSheet.create({ + btnText: { + color: '#3826A6', + fontFamily: typography.primary.semiBold, + fontSize: 16, + fontStyle: 'normal' + }, colorFrame: { alignItems: 'center', backgroundColor: '#D4EFDF', @@ -158,6 +218,18 @@ const styles = StyleSheet.create({ paddingVertical: 16, width: '90%' }, + createButton: { + alignItems: 'center', + alignSelf: 'center', + borderColor: '#3826A6', + borderRadius: 12, + borderWidth: 2, + flexDirection: 'row', + justifyContent: 'center', + marginTop: 10, + padding: 12, + width: '80%' + }, text: { fontFamily: typography.primary.medium, fontSize: 14, diff --git a/apps/mobile/app/components/TaskVersion.tsx b/apps/mobile/app/components/TaskVersion.tsx index 1499727a0..dc1425534 100644 --- a/apps/mobile/app/components/TaskVersion.tsx +++ b/apps/mobile/app/components/TaskVersion.tsx @@ -1,50 +1,50 @@ /* eslint-disable react-native/no-color-literals */ /* eslint-disable react-native/no-inline-styles */ -import React, { FC, useState } from "react" -import { TouchableOpacity, View, Text, StyleSheet, ViewStyle } from "react-native" -import { AntDesign, Entypo } from "@expo/vector-icons" -import { observer } from "mobx-react-lite" -import { ITeamTask } from "../services/interfaces/ITask" -import { useTeamTasks } from "../services/hooks/features/useTeamTasks" -import { typography, useAppTheme } from "../theme" -import { translate } from "../i18n" -import { useTaskVersionValue } from "./StatusType" -import { limitTextCharaters } from "../helpers/sub-text" -import TaskVersionPopup from "./TaskVersionPopup" +import React, { FC, useState } from 'react'; +import { TouchableOpacity, View, Text, StyleSheet, ViewStyle } from 'react-native'; +import { AntDesign, Entypo } from '@expo/vector-icons'; +import { observer } from 'mobx-react-lite'; +import { ITeamTask } from '../services/interfaces/ITask'; +import { useTeamTasks } from '../services/hooks/features/useTeamTasks'; +import { typography, useAppTheme } from '../theme'; +import { translate } from '../i18n'; +import { useTaskVersionValue } from './StatusType'; +import { limitTextCharaters } from '../helpers/sub-text'; +import TaskVersionPopup from './TaskVersionPopup'; interface TaskVersionProps { - task?: ITeamTask - containerStyle?: ViewStyle - version?: string - setVersion?: (priority: string) => unknown + task?: ITeamTask; + containerStyle?: ViewStyle; + version?: string; + setVersion?: (priority: string) => unknown; + canCreateVersion?: boolean; } const TaskVersion: FC = observer( - ({ task, containerStyle, version, setVersion }) => { - const { colors } = useAppTheme() - const { updateTask } = useTeamTasks() - const [openModal, setOpenModal] = useState(false) + ({ task, containerStyle, version, setVersion, canCreateVersion }) => { + const { colors } = useAppTheme(); + const { updateTask } = useTeamTasks(); + const [openModal, setOpenModal] = useState(false); - const allTaskVersions = useTaskVersionValue() + const allTaskVersions = useTaskVersionValue(); - const versionValue = (task?.version || (version && version))?.toLowerCase() + const versionValue = (task?.version || (version && version))?.toLowerCase(); const currentVersion = - allTaskVersions && - Object.values(allTaskVersions).find((item) => item.value.toLowerCase() === versionValue) + allTaskVersions && Object.values(allTaskVersions).find((item) => item.value.toLowerCase() === versionValue); const onChangeVersion = async (text: string) => { if (task) { const taskEdit = { ...task, - version: task?.version === text ? null : text, - } + version: task?.version === text ? null : text + }; - await updateTask(taskEdit, task.id) + await updateTask(taskEdit, task.id); } else { - setVersion(text) + setVersion(text); } - } + }; return ( <> @@ -53,6 +53,7 @@ const TaskVersion: FC = observer( visible={openModal} setSelectedVersion={(e) => onChangeVersion(e.value)} onDismiss={() => setOpenModal(false)} + canCreateVersion={canCreateVersion} /> setOpenModal(true)}> = observer( ...styles.container, ...containerStyle, borderColor: colors.border, - backgroundColor: colors.background, + backgroundColor: colors.background }} > {(task?.version || version) && currentVersion ? ( @@ -70,22 +71,20 @@ const TaskVersion: FC = observer( style={{ ...styles.text, marginLeft: 10, - color: colors.primary, + color: colors.primary }} > {limitTextCharaters({ text: currentVersion.name, - numChars: 15, + numChars: 15 })} ) : ( - - {translate("taskDetailsScreen.version")} + + {translate('taskDetailsScreen.version')} )} @@ -93,32 +92,32 @@ const TaskVersion: FC = observer( - ) - }, -) + ); + } +); const styles = StyleSheet.create({ container: { - alignItems: "center", - borderColor: "rgba(0,0,0,0.16)", + alignItems: 'center', + borderColor: 'rgba(0,0,0,0.16)', borderRadius: 10, borderWidth: 1, - flexDirection: "row", - justifyContent: "space-between", + flexDirection: 'row', + justifyContent: 'space-between', minHeight: 30, minWidth: 100, - paddingHorizontal: 8, + paddingHorizontal: 8 }, text: { fontFamily: typography.fonts.PlusJakartaSans.semiBold, fontSize: 10, - textTransform: "capitalize", + textTransform: 'capitalize' }, wrapStatus: { - alignItems: "center", - flexDirection: "row", - width: "70%", - }, -}) + alignItems: 'center', + flexDirection: 'row', + width: '70%' + } +}); -export default TaskVersion +export default TaskVersion; diff --git a/apps/mobile/app/components/TaskVersionPopup.tsx b/apps/mobile/app/components/TaskVersionPopup.tsx index 3de99d19d..3c9798e26 100644 --- a/apps/mobile/app/components/TaskVersionPopup.tsx +++ b/apps/mobile/app/components/TaskVersionPopup.tsx @@ -1,6 +1,6 @@ /* eslint-disable react-native/no-inline-styles */ /* eslint-disable react-native/no-color-literals */ -import React, { FC } from "react" +import React, { FC, useState } from 'react'; import { View, ViewStyle, @@ -10,22 +10,25 @@ import { Text, FlatList, TouchableOpacity, - TouchableWithoutFeedback, -} from "react-native" -import { Feather, AntDesign } from "@expo/vector-icons" -import { spacing, useAppTheme } from "../theme" -import { ITaskPriorityItem } from "../services/interfaces/ITaskPriority" + TouchableWithoutFeedback +} from 'react-native'; +import { Feather, AntDesign, Ionicons } from '@expo/vector-icons'; +import { spacing, useAppTheme, typography } from '../theme'; +import { ITaskPriorityItem } from '../services/interfaces/ITaskPriority'; // import { translate } from "../i18n" -import { BlurView } from "expo-blur" -import { useTaskVersion } from "../services/hooks/features/useTaskVersion" -import { BadgedTaskVersion } from "./VersionIcon" -import { ITaskVersionItemList } from "../services/interfaces/ITaskVersion" +import { BlurView } from 'expo-blur'; +import { useTaskVersion } from '../services/hooks/features/useTaskVersion'; +import { BadgedTaskVersion } from './VersionIcon'; +import { ITaskVersionItemList } from '../services/interfaces/ITaskVersion'; +import { translate } from '../i18n'; +import TaskVersionForm from '../screens/Authenticated/TaskVersionScreen/components/TaskVersionForm'; export interface Props { - visible: boolean - onDismiss: () => unknown - versionName: string - setSelectedVersion: (status: ITaskVersionItemList) => unknown + visible: boolean; + onDismiss: () => unknown; + versionName: string; + setSelectedVersion: (status: ITaskVersionItemList) => unknown; + canCreateVersion?: boolean; } const TaskVersionPopup: FC = function TaskPriorityPopup({ @@ -33,52 +36,96 @@ const TaskVersionPopup: FC = function TaskPriorityPopup({ onDismiss, setSelectedVersion, versionName, + canCreateVersion }) { - const { taskVersionList } = useTaskVersion() - const { colors } = useAppTheme() + const { taskVersionList } = useTaskVersion(); + const { colors, dark } = useAppTheme(); + const { createTaskVersion, updateTaskVersion } = useTaskVersion(); + + const [createVersionMode, setCreateVersionMode] = useState(false); + const onVersionSelected = (size: ITaskPriorityItem) => { - setSelectedVersion(size) - onDismiss() - } + setSelectedVersion(size); + onDismiss(); + setCreateVersionMode(false); + }; return ( - - Versions - ( - + {!createVersionMode ? ( + <> + Versions + ( + + )} + legacyImplementation={true} + showsVerticalScrollIndicator={true} + keyExtractor={(_, index) => index.toString()} /> - )} - legacyImplementation={true} - showsVerticalScrollIndicator={true} - keyExtractor={(_, index) => index.toString()} - /> + {canCreateVersion && ( + setCreateVersionMode(true)} + > + + + {translate('settingScreen.versionScreen.createNewVersionText')} + + + )} + + ) : ( + setCreateVersionMode(false)} + onCreateVersion={createTaskVersion} + onUpdateVersion={updateTaskVersion} + isEdit={false} + createVersionModal={true} + /> + )} - ) -} + ); +}; -export default TaskVersionPopup +export default TaskVersionPopup; interface ItemProps { - currentVersionName: string - version: ITaskPriorityItem - onVersionSelected: (size: ITaskPriorityItem) => unknown + currentVersionName: string; + version: ITaskPriorityItem; + onVersionSelected: (size: ITaskPriorityItem) => unknown; } const Item: FC = ({ currentVersionName, version, onVersionSelected }) => { - const { colors } = useAppTheme() - const selected = version.value === currentVersionName + const { colors } = useAppTheme(); + const selected = version.value === currentVersionName; return ( onVersionSelected(version)}> - + @@ -90,91 +137,107 @@ const Item: FC = ({ currentVersionName, version, onVersionSelected }) - ) -} + ); +}; const ModalPopUp = ({ visible, children, onDismiss }) => { - const [showModal, setShowModal] = React.useState(visible) - const scaleValue = React.useRef(new Animated.Value(0)).current + const [showModal, setShowModal] = React.useState(visible); + const scaleValue = React.useRef(new Animated.Value(0)).current; React.useEffect(() => { - toggleModal() - }, [visible]) + toggleModal(); + }, [visible]); const toggleModal = () => { if (visible) { - setShowModal(true) + setShowModal(true); Animated.spring(scaleValue, { toValue: 1, - useNativeDriver: true, - }).start() + useNativeDriver: true + }).start(); } else { - setTimeout(() => setShowModal(false), 200) + setTimeout(() => setShowModal(false), 200); Animated.timing(scaleValue, { toValue: 0, duration: 300, - useNativeDriver: true, - }).start() + useNativeDriver: true + }).start(); } - } + }; return ( onDismiss()}> - - {children} - + {children} - ) -} + ); +}; const $modalBackGround: ViewStyle = { flex: 1, - justifyContent: "center", -} + justifyContent: 'center' +}; const styles = StyleSheet.create({ + btnText: { + color: '#3826A6', + fontFamily: typography.primary.semiBold, + fontSize: 16, + fontStyle: 'normal' + }, colorFrame: { borderRadius: 10, height: 44, - justifyContent: "center", + justifyContent: 'center', paddingLeft: 16, - width: 180, + width: 180 }, container: { - alignSelf: "center", - backgroundColor: "#fff", + alignSelf: 'center', + backgroundColor: '#fff', borderRadius: 20, maxHeight: 396, paddingHorizontal: 6, paddingVertical: 16, - width: "90%", + width: '90%' + }, + createButton: { + alignItems: 'center', + alignSelf: 'center', + borderColor: '#3826A6', + borderRadius: 12, + borderWidth: 2, + flexDirection: 'row', + justifyContent: 'center', + marginTop: 10, + padding: 12, + width: '80%' }, title: { fontSize: spacing.medium - 2, marginBottom: 16, - marginHorizontal: 10, + marginHorizontal: 10 }, wrapperItem: { - alignItems: "center", - borderColor: "rgba(0,0,0,0.13)", + alignItems: 'center', + borderColor: 'rgba(0,0,0,0.13)', borderRadius: 10, borderWidth: 1, - flexDirection: "row", - justifyContent: "space-between", + flexDirection: 'row', + justifyContent: 'space-between', marginBottom: 10, padding: 6, paddingRight: 18, - width: "100%", - }, -}) + width: '100%' + } +}); diff --git a/apps/mobile/app/screens/Authenticated/TaskVersionScreen/components/TaskVersionForm.tsx b/apps/mobile/app/screens/Authenticated/TaskVersionScreen/components/TaskVersionForm.tsx index b3fa3cf6c..591b4080f 100644 --- a/apps/mobile/app/screens/Authenticated/TaskVersionScreen/components/TaskVersionForm.tsx +++ b/apps/mobile/app/screens/Authenticated/TaskVersionScreen/components/TaskVersionForm.tsx @@ -1,14 +1,11 @@ /* 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 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" +import { ITaskVersionCreate, ITaskVersionItemList } from '../../../../services/interfaces/ITaskVersion'; const TaskVersionForm = ({ isEdit, @@ -16,43 +13,45 @@ const TaskVersionForm = ({ item, onCreateVersion, onUpdateVersion, + createVersionModal }: { - isEdit: boolean - onDismiss: () => unknown - item?: ITaskVersionItemList - onUpdateVersion: (id: string, data: ITaskVersionCreate) => unknown - onCreateVersion: (data: ITaskVersionCreate) => unknown + isEdit: boolean; + onDismiss: () => unknown; + item?: ITaskVersionItemList; + onUpdateVersion: (id: string, data: ITaskVersionCreate) => unknown; + onCreateVersion: (data: ITaskVersionCreate) => unknown; + createVersionModal?: boolean; }) => { - const { colors, dark } = useAppTheme() - const [versionName, setVersionName] = useState(null) + const { colors, dark } = useAppTheme(); + const [versionName, setVersionName] = useState(null); useEffect(() => { if (isEdit) { - setVersionName(item.name) + setVersionName(item.name); } else { - setVersionName(null) + setVersionName(null); } - }, [item, isEdit]) + }, [item, isEdit]); const handleSubmit = async () => { if (versionName.trim().length <= 0) { - return + return; } if (isEdit) { await onUpdateVersion(item?.id, { - name: versionName, - }) + name: versionName + }); } else { await onCreateVersion({ name: versionName, - color: "#FFFFFF", - }) + color: '#FFFFFF' + }); } - setVersionName(null) - onDismiss() - } + setVersionName(null); + onDismiss(); + }; return ( - {translate("settingScreen.versionScreen.createNewVersionText")} + {translate('settingScreen.versionScreen.createNewVersionText')} setVersionName(text)} /> - + { - onDismiss() - Keyboard.dismiss() + onDismiss(); + Keyboard.dismiss(); }} > - - {translate("settingScreen.versionScreen.cancelButtonText")} - + {translate('settingScreen.versionScreen.cancelButtonText')} { if (versionName) { - handleSubmit().finally(() => Keyboard.dismiss()) + handleSubmit().finally(() => Keyboard.dismiss()); } }} > {isEdit - ? translate("settingScreen.versionScreen.updateButtonText") - : translate("settingScreen.versionScreen.createButtonText")} + ? translate('settingScreen.versionScreen.updateButtonText') + : translate('settingScreen.versionScreen.createButtonText')} - ) -} + ); +}; -export default TaskVersionForm +export default TaskVersionForm; const styles = StyleSheet.create({ cancelBtn: { - alignItems: "center", - backgroundColor: "#E6E6E9", + alignItems: 'center', + backgroundColor: '#E6E6E9', borderRadius: 12, height: 57, - justifyContent: "center", - width: "48%", + justifyContent: 'center', + width: '48%' }, cancelTxt: { - color: "#1A1C1E", + color: '#1A1C1E', fontFamily: typography.primary.semiBold, - fontSize: 18, + fontSize: 18 }, createBtn: { - alignItems: "center", - backgroundColor: "#3826A6", + alignItems: 'center', + backgroundColor: '#3826A6', borderRadius: 12, height: 57, - justifyContent: "center", - width: "48%", + justifyContent: 'center', + width: '48%' }, createTxt: { - color: "#FFF", + color: '#FFF', fontFamily: typography.primary.semiBold, - fontSize: 18, + fontSize: 18 }, formTitle: { - color: "#1A1C1E", + color: '#1A1C1E', fontFamily: typography.primary.semiBold, - fontSize: 24, + fontSize: 24 }, versionNameInput: { - alignItems: "center", - borderColor: "#DCE4E8", + alignItems: 'center', + borderColor: '#DCE4E8', borderRadius: 12, borderWidth: 1, height: 57, marginTop: 16, paddingHorizontal: 18, - width: "100%", + width: '100%' }, wrapButtons: { - flexDirection: "row", - justifyContent: "space-between", - marginTop: 40, - width: "100%", - }, -}) + flexDirection: 'row', + justifyContent: 'space-between', + width: '100%' + } +});