From 668dbe5bed155c68e0602a9f9dee384ef2ec38ef Mon Sep 17 00:00:00 2001 From: Antoine Bagnaud Date: Wed, 4 Sep 2024 17:33:29 +0200 Subject: [PATCH] feat: app fully functionnal Need some style fix --- src/components/BarcodeCameraView.js | 84 ++++--- src/navigation/courier/SelectRange.js | 33 ++- src/navigation/courier/barcode/Barcode.js | 133 ++++++++++- .../courier/barcode/BarcodeIncident.js | 212 ++++++++++++++++++ .../courier/barcode/BarcodeReport.js | 13 +- src/navigation/index.js | 2 + src/navigation/navigators/CourierNavigator.js | 4 + 7 files changed, 426 insertions(+), 55 deletions(-) create mode 100644 src/navigation/courier/barcode/BarcodeIncident.js diff --git a/src/components/BarcodeCameraView.js b/src/components/BarcodeCameraView.js index a6292ddf1..08fb8fb74 100644 --- a/src/components/BarcodeCameraView.js +++ b/src/components/BarcodeCameraView.js @@ -6,6 +6,7 @@ import _ from 'lodash'; import { Icon } from 'native-base'; import Ionicons from 'react-native-vector-icons/Ionicons'; import { TouchableOpacity } from 'react-native-gesture-handler'; +import FocusHandler from './FocusHandler'; function getBoxBoundaries(points) { const xs = points.map(point => point.x); @@ -39,6 +40,11 @@ export default function BarcodeCameraView(props) { const [barcode, setBarcode] = useState(null); const [flash, setFlash] = useState(false); + //The hide behavior is a hack to force the camera to re-render + //if another camera is opened on modal. If we don't do this, the + //camera will not render. + const [hide, setHide] = useState(false); + if (!hasPermission) { return ( @@ -73,41 +79,53 @@ export default function BarcodeCameraView(props) { }, 200); return ( - - + { + setHide(false); + }} + onBlur={() => { + setHide(true); }} /> - - setFlash(!flash)}> - + - - - + + setFlash(!flash)}> + + + + + )} + ); } diff --git a/src/navigation/courier/SelectRange.js b/src/navigation/courier/SelectRange.js index e3b4afaed..1a3e7b8f1 100644 --- a/src/navigation/courier/SelectRange.js +++ b/src/navigation/courier/SelectRange.js @@ -1,9 +1,11 @@ import React, { useState } from 'react'; -import { FormControl, Input, KeyboardAvoidingView, Button } from 'native-base'; +import { FormControl, Input, Button, ScrollView, View } from 'native-base'; import { withTranslation } from 'react-i18next'; import moment from 'moment'; import DateTimePicker from 'react-native-modal-datetime-picker'; +import KeyboardAdjustView from '../../components/KeyboardAdjustView'; + function SelectRange({ t, route, navigation }) { const { after, before, navigateTo } = route.params; const [afterDate, setAfterDate] = useState(moment(after)); @@ -12,23 +14,36 @@ function SelectRange({ t, route, navigation }) { const [showAfterDatePicker, setShowAfterDatePicker] = useState(false); const [showBeforeDatePicker, setShowBeforeDatePicker] = useState(false); + const isAfterInvalid = afterDate?.isBefore(moment()); + const isBeforeInvalid = beforeDate?.isBefore(afterDate); + return ( - - + + + {t('TASK_FORM_DONE_AFTER_LABEL')} setShowAfterDatePicker(true)} + onTouchStart={() => setShowAfterDatePicker(true)} value={afterDate.format('ll LT')} /> + + {t('TASK_FORM_DONE_BEFORE_LABEL')} setShowBeforeDatePicker(true)} + onTouchStart={() => setShowBeforeDatePicker(true)} value={beforeDate.format('ll LT')} /> - - + setAfterDate(moment(date))} onCancel={() => setShowAfterDatePicker(false)} /> @@ -52,10 +68,11 @@ function SelectRange({ t, route, navigation }) { mode="datetime" isVisible={showBeforeDatePicker} minimumDate={afterDate.toDate()} + minuteInterval={15} onConfirm={date => setBeforeDate(moment(date))} onCancel={() => setShowBeforeDatePicker(false)} /> - + ); } diff --git a/src/navigation/courier/barcode/Barcode.js b/src/navigation/courier/barcode/Barcode.js index 10252c95b..bfab6109b 100644 --- a/src/navigation/courier/barcode/Barcode.js +++ b/src/navigation/courier/barcode/Barcode.js @@ -1,13 +1,23 @@ -import React, { useState } from 'react'; +import React, { useEffect, useState } from 'react'; import { withTranslation } from 'react-i18next'; import { connect } from 'react-redux'; -import { ScrollView, StyleSheet, Text, View, Vibration } from 'react-native'; -import { Button, IconButton } from 'native-base'; +import { + ScrollView, + StyleSheet, + Text, + View, + Vibration, + Alert, +} from 'react-native'; +import { Button, IconButton, TextArea } from 'native-base'; import Ionicons from 'react-native-vector-icons/Ionicons'; import BarcodeCameraView from '../../../components/BarcodeCameraView'; import { CommonActions } from '@react-navigation/native'; import NavigationHolder from '../../../NavigationHolder'; +import { assignTask } from '../../../redux/Dispatch/actions'; +import { unassignTask } from '../../../redux/Dispatch/actions'; +import Modal from "react-native-modal" async function _fetchBarcode(httpClient, barcode) { if (barcode) { @@ -28,17 +38,108 @@ function TextSection({ title, value, variant = 'data' }) { ); } -function BarcodePage({ httpClient }) { +function BarcodePage({ httpClient, user, assignTask, unassignTask }) { const [barcode, setBarcode] = useState(null); const [entity, setEntity] = useState(null); + const [clientAction, setClientAction] = useState(null); + const [showNoteModal, setShowNoteModal] = useState(false); - return ( + const askUnassign = () => { + Alert.alert( + 'Task already assigned', + 'This task is already assigned to you', + [ + { + text: 'Unassign', + onPress: () => { + unassignTask(entity.id, user.username); + setClientAction(null); + }, + }, + { + text: 'Ok', + onPress: () => { + setClientAction(null); + }, + }, + ], + ); + }; + + const askAssign = () => { + Alert.alert( + 'Task already assigned', + 'This task is already assigned to another courier', + [ + { + text: 'Assign to me', + onPress: () => { + assignTask(entity.id, user.username); + setClientAction(null); + }, + }, + { + text: 'Ok', + onPress: () => { + setClientAction(null); + }, + }, + ], + ); + }; + + useEffect(() => { + return; + if (!clientAction) return; + switch (clientAction) { + case 'ask_unassign': + askUnassign(); + break; + case 'ask_assign': + askAssign(); + break; + default: + setClientAction(null); + } + }, [clientAction]); + + useEffect(() => { + if (!entity) return; + if (!entity?.barcodes?.packages) return; + const packages = entity?.barcodes?.packages.reduce( + (acc, p) => acc + p.barcodes.length, + 0, + ); + if (packages > 1) { + const details = entity?.barcodes?.packages + .map(p => `${p.barcodes.length}x ${p.name}`) + .join('\n'); + Alert.alert( + 'Multiple packages', + `${packages} packages:\n\n${details}\n\nNo need to scan the other packages`, + [{ text: 'Ok' }], + ); + } + }, [entity]); + + return <> + setShowNoteModal(false)}> + +