Skip to content

Commit

Permalink
Merge pull request #1913 from coopcycle/delivery-form-pickup
Browse files Browse the repository at this point in the history
Delivery form pickup
  • Loading branch information
vladimir-8 authored Dec 12, 2024
2 parents 2de82d1 + 98d4bac commit 6e78f30
Show file tree
Hide file tree
Showing 9 changed files with 551 additions and 70 deletions.
8 changes: 8 additions & 0 deletions src/i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,14 @@
"CART_COLLECTION_TIME_DIFF": "Collection in {{diff}} minutes",
"TIME_DIFF_SHORT": "{{min}} - {{max}} minutes",
"TASK_ADD_PROOF_OF_DELIVERY": "Add a proof of delivery",
"STORE_NEW_DELIVERY_PICKUP_TITLE": "Pickup address",
"STORE_NEW_DELIVERY_PICKUP_DESCRIPTION": "Fill in the information about the pickup address or keep the default one",
"STORE_NEW_DELIVERY_PICKUP_DEFAULT_ADDRESS": "Default pickup address",
"STORE_NEW_DELIVERY_PICKUP_USE_CUSTOM_ADDRESS": "Use a custom address",
"STORE_NEW_DELIVERY_DROPOFF_TITLE": "Dropoff address",
"STORE_NEW_DELIVERY_DROPOFF_DESCRIPTION": "Fill in the information about the dropoff address and the contact details",
"STORE_NEW_DELIVERY_PACKAGES_TITLE": "Time slot and packages",
"STORE_NEW_DELIVERY_PACKAGES_DESCRIPTION": "Select a time slot, the weight of the package if necessary and the packages to deliver",
"STORE_NEW_DELIVERY": "New delivery",
"STORE_NEW_DELIVERY_ADDRESS": "Address",
"STORE_NEW_DELIVERY_SEARCH_CLIENT": "Search for a client",
Expand Down
8 changes: 8 additions & 0 deletions src/i18n/locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,14 @@
"TASK_IMAGE_UPLOAD_CONFIRM_LONG": "L'image a été uploadée avec succès",
"AN_ERROR_OCCURRED": "Une erreur s'est produite",
"TASK_ADD_PROOF_OF_DELIVERY": "Ajouter une preuve de livraison",
"STORE_NEW_DELIVERY_PICKUP_TITLE": "Adresse de récupération",
"STORE_NEW_DELIVERY_PICKUP_DESCRIPTION": "Indiquez une adresse de récupération ou garder l'address de livraison par défaut pour récupérer la commande",
"STORE_NEW_DELIVERY_PICKUP_DEFAULT_ADDRESS": "Adresse de livraison par défaut",
"STORE_NEW_DELIVERY_PICKUP_USE_CUSTOM_ADDRESS": "Utiliser une adresse personnalisée",
"STORE_NEW_DELIVERY_DROPOFF_TITLE": "Adresse de dépôt",
"STORE_NEW_DELIVERY_DROPOFF_DESCRIPTION": "Remplissez les informations de livraison ainsi que la personne à contacter",
"STORE_NEW_DELIVERY_PACKAGES_TITLE": "Tranche horaire et paquets",
"STORE_NEW_DELIVERY_PACKAGES_DESCRIPTION": "Sélectionnez une tranche horaire a respecter, le poids du colis si nécessaire et les paquets à livrer",
"STORE_NEW_DELIVERY": "Nouvelle livraison",
"STORE_NEW_DELIVERY_ADDRESS": "Adresse",
"STORE_NEW_DELIVERY_SEARCH_CLIENT": "Rechercher un client",
Expand Down
2 changes: 2 additions & 0 deletions src/navigation/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import StoreDashboard from './store/Dashboard';
import StoreDelivery from './store/Delivery';
import StoreNewDeliveryAddress from './store/NewDeliveryAddress';
import StoreNewDeliveryForm from './store/NewDeliveryForm';
import StoreNewDeliveryPickup from './store/NewDeliveryPickup';
import StoreNewDeliveryPrice from './store/NewDeliveryPrice';

import CheckoutPaymentMethodCard from './checkout/PaymentMethodCard';
Expand Down Expand Up @@ -131,6 +132,7 @@ export default {
TaskSignature,
StoreDashboard,
StoreDelivery,
StoreNewDeliveryPickup,
StoreNewDeliveryAddress,
StoreNewDeliveryForm,
StoreNewDeliveryPrice,
Expand Down
21 changes: 15 additions & 6 deletions src/navigation/navigators/StoreNavigator.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import { createStackNavigator } from '@react-navigation/stack';
import React from 'react';

import screens, { headerLeft } from '..';
import NavigationHolder from '../../NavigationHolder';
import HeaderButton from '../../components/HeaderButton';
import i18n from '../../i18n';
import NavigationHolder from '../../NavigationHolder';
import HeaderBackButton from '../store/components/HeaderBackButton';
import { stackNavigatorScreenOptions } from '../styles';

Expand Down Expand Up @@ -36,14 +36,16 @@ const MainNavigator = () => (
name="StoreDelivery"
component={screens.StoreDelivery}
options={({ route }) => {
let id
let id;
if (route.params.delivery) {
id = route.params.delivery.orderNumber ? route.params.delivery.orderNumber : route.params.delivery.id
id = route.params.delivery.orderNumber
? route.params.delivery.orderNumber
: route.params.delivery.id;
}
return {
title: i18n.t('STORE_DELIVERY', { id: id })
}}
}
title: i18n.t('STORE_DELIVERY', { id: id }),
};
}}
/>
</MainStack.Navigator>
);
Expand All @@ -52,6 +54,13 @@ const NewDeliveryStack = createStackNavigator();

const NewDeliveryNavigator = () => (
<NewDeliveryStack.Navigator screenOptions={stackNavigatorScreenOptions}>
<NewDeliveryStack.Screen
name="StoreNewDeliveryPickup"
component={screens.StoreNewDeliveryPickup}
options={{
headerShown: false,
}}
/>
<NewDeliveryStack.Screen
name="StoreNewDeliveryAddress"
component={screens.StoreNewDeliveryAddress}
Expand Down
47 changes: 35 additions & 12 deletions src/navigation/store/NewDeliveryAddress.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { IconCircleArrowDownFilled } from '@tabler/icons-react-native';
import { Formik } from 'formik';
import { AsYouType, parsePhoneNumberFromString } from 'libphonenumber-js';
import _ from 'lodash';
Expand All @@ -14,9 +15,9 @@ import {
useBackgroundHighlightColor,
usePrimaryColor,
} from '../../styles/theme';
import ModalFormWrapper from './ModalFormWrapper';
import ClientListInput from './components/ClientListInput';
import FormInput from './components/FormInput';
import ModalFormWrapper from './ModalFormWrapper';

function NewDeliveryAddress(props) {
const [validAddress, setValidAddress] = useState(false);
Expand All @@ -31,6 +32,7 @@ function NewDeliveryAddress(props) {
addresses,
assertDelivery,
t,
route,
navigation,
country,
} = props;
Expand All @@ -43,7 +45,7 @@ function NewDeliveryAddress(props) {
function setAddressData(data, setFieldValue) {
const contactName = data.contactName || '';
const telephone = data.telephone || '';
const businessName = data.businessName || '';
const businessName = data.name || '';
const description = data.description || '';

setFieldValue('contactName', contactName);
Expand Down Expand Up @@ -97,7 +99,7 @@ function NewDeliveryAddress(props) {
}

function validate(values) {
let errors = {};
const errors = {};

if (_.isEmpty(values.telephone)) {
errors.telephone = t('STORE_NEW_DELIVERY_ERROR.EMPTY_PHONE_NUMBER');
Expand All @@ -122,7 +124,7 @@ function NewDeliveryAddress(props) {
return errors;
}

let initialValues = {
const initialValues = {
telephone: '',
contactName: '',
businessName: '',
Expand All @@ -136,7 +138,7 @@ function NewDeliveryAddress(props) {
}

function submit(values) {
const delivery = {
const dropoff = {
telephone: parsePhoneNumberFromString(values.telephone, country).format(
'E.164',
),
Expand All @@ -146,7 +148,10 @@ function NewDeliveryAddress(props) {
address,
};

navigation.navigate('StoreNewDeliveryForm', { delivery });
navigation.navigate('StoreNewDeliveryForm', {
pickup: route.params?.pickup || undefined,
dropoff: dropoff,
});
}

return (
Expand All @@ -167,6 +172,20 @@ function NewDeliveryAddress(props) {
setFieldTouched,
}) => (
<ModalFormWrapper handleSubmit={handleSubmit} t={t}>
<View style={[styles.formGroup, { zIndex: 2 }]}>
<View style={[styles.header, styles.label]}>
<IconCircleArrowDownFilled
size={24}
fill={primaryColor}
color={backgroundColor}
stroke={10}
/>
<Text>{t('STORE_NEW_DELIVERY_DROPOFF_TITLE')}</Text>
</View>
<Text style={styles.optional}>
{t('STORE_NEW_DELIVERY_DROPOFF_DESCRIPTION')}
</Text>
</View>
<View style={[styles.formGroup, { zIndex: 2 }]}>
<Text style={styles.label}>
{t('STORE_NEW_DELIVERY_SEARCH_CLIENT')}{' '}
Expand Down Expand Up @@ -199,12 +218,10 @@ function NewDeliveryAddress(props) {
onBlur={handleBlur('address')}
value={address}
onSelectAddress={e => onSelectAddress(e, setFieldValue)}
containerStyle={[
{
flex: 1,
justifyContent: 'center',
},
]}
containerStyle={{
flex: 1,
justifyContent: 'center',
}}
style={{
borderRadius: 0,
padding: 10,
Expand Down Expand Up @@ -340,6 +357,12 @@ const styles = StyleSheet.create({
errorInput: {
borderColor: '#FF4136',
},
header: {
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
gap: 5,
},
formGroup: {
marginBottom: 10,
},
Expand Down
82 changes: 49 additions & 33 deletions src/navigation/store/NewDeliveryForm.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Formik } from 'formik';
import { parsePhoneNumberFromString } from 'libphonenumber-js';
import moment from 'moment';
import { Box, Button, HStack, Text, VStack } from 'native-base';
import React, { useEffect, useState } from 'react';
Expand All @@ -15,14 +14,18 @@ import KeyboardManager from 'react-native-keyboard-manager';
import DateTimePickerModal from 'react-native-modal-datetime-picker';
import { connect, useDispatch } from 'react-redux';

import { IconPackage } from '@tabler/icons-react-native';
import {
loadPackages,
loadTimeSlot,
loadTimeSlotChoices,
loadTimeSlots,
} from '../../redux/Store/actions';
import { selectStore, selectTimeSlots } from '../../redux/Store/selectors';
import { useBackgroundContainerColor } from '../../styles/theme';
import {
useBackgroundContainerColor,
usePrimaryColor,
} from '../../styles/theme';
import Range from '../checkout/ProductDetails/Range';
import ModalFormWrapper from './ModalFormWrapper';
import FormInput from './components/FormInput';
Expand All @@ -32,6 +35,7 @@ function DeliveryForm(props) {
const [isDateTimePickerVisible, setIsDateTimePickerVisible] = useState(false);
const [selectedTimeSlot, setSelectedTimeSlot] = useState('');
const backgroundColor = useBackgroundContainerColor();
const primaryColor = usePrimaryColor();
const [selectedChoice, setSelectedChoice] = React.useState(null);
const [packagesCount, setPackagesCount] = useState([]);
const dispatch = useDispatch();
Expand Down Expand Up @@ -139,6 +143,7 @@ function DeliveryForm(props) {
function submit(values) {
const delivery = {
store: store['@id'],
pickup: route.params?.pickup || undefined,
dropoff: {
address: {
...values.address,
Expand All @@ -160,7 +165,7 @@ function DeliveryForm(props) {
}

function validate(values) {
let errors = {};
const errors = {};

if (hasTimeSlot && !selectedChoice) {
errors.timeSlot = t('STORE_NEW_DELIVERY_ERROR.EMPTY_TIME_SLOT');
Expand Down Expand Up @@ -210,48 +215,40 @@ function DeliveryForm(props) {
}

function handleChangeWeight(value, setFieldValue, setFieldTouched) {
value = value.replace(',', '.').replace(/[^0-9.]/g, '');
let newValue = value.replace(',', '.').replace(/[^0-9.]/g, '');

const firstDecimalIndex = value.indexOf('.');
const firstDecimalIndex = newValue.indexOf('.');
if (firstDecimalIndex === 0) {
value = '0' + value;
newValue = `0${newValue}`;
} else if (firstDecimalIndex !== -1) {
value =
value.substring(0, firstDecimalIndex + 1) +
value.substring(firstDecimalIndex + 1).replace(/\./g, '');
newValue =
newValue.substring(0, firstDecimalIndex + 1) +
newValue.substring(firstDecimalIndex + 1).replace(/\./g, '');
}

if (value.includes('.')) {
const decimalIndex = value.indexOf('.');
value =
value.substring(0, decimalIndex + 1) +
value.substring(decimalIndex + 1, decimalIndex + 4);
if (newValue.includes('.')) {
const decimalIndex = newValue.indexOf('.');
newValue =
newValue.substring(0, decimalIndex + 1) +
newValue.substring(decimalIndex + 1, decimalIndex + 4);
}

setFieldValue('weight', value);
setFieldValue('weight', newValue);
setFieldTouched('weight');
}

const delivery = route.params?.delivery;

let telephone = '';
if (delivery.telephone) {
const phoneNumber = parsePhoneNumberFromString(delivery.telephone, country);
if (phoneNumber && phoneNumber.isValid()) {
telephone = phoneNumber.formatNational();
}
}
const dropoff = route.params?.dropoff;

let initialValues = {
address: delivery.address,
address: dropoff.address,
// set from the first step newDeliveryAddress
description: delivery.description || '',
contactName: delivery.contactName || '',
businessName: delivery.businessName || '',
telephone,
description: dropoff.description || '',
contactName: dropoff.contactName || '',
businessName: dropoff.businessName || '',
telephone: dropoff.telephone || '',
// ----------------
weight: null,
comments: delivery.comments || '',
comments: dropoff.comments || '',
};

if (hasTimeSlot) {
Expand Down Expand Up @@ -284,6 +281,19 @@ function DeliveryForm(props) {
setFieldTouched,
}) => (
<ModalFormWrapper handleSubmit={handleSubmit} t={t}>
<View style={[styles.formGroup, { zIndex: 2 }]}>
<View style={[styles.header, styles.label]}>
<IconPackage
size={24}
stroke={primaryColor}
color={backgroundColor}
/>
<Text>{t('STORE_NEW_DELIVERY_PACKAGES_TITLE')}</Text>
</View>
<Text style={styles.optional}>
{t('STORE_NEW_DELIVERY_PACKAGES_DESCRIPTION')}
</Text>
</View>
{hasTimeSlot ? (
<TimeSlotSelector
selectValue={selectedChoice}
Expand Down Expand Up @@ -345,8 +355,8 @@ function DeliveryForm(props) {
gap: 16,
marginTop: 4,
}}>
{packages && packages.length ? (
packagesCount.map((item, index) => {
{packages?.length ? (
packagesCount.map(item => {
return (
<View
style={[
Expand All @@ -358,7 +368,7 @@ function DeliveryForm(props) {
backgroundColor,
},
]}
key={index}>
key={item.type}>
<Range
onPress={() => {}}
onPressIncrement={() =>
Expand Down Expand Up @@ -414,6 +424,12 @@ function DeliveryForm(props) {
}

const styles = StyleSheet.create({
header: {
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
gap: 5,
},
label: {
marginBottom: 8,
fontWeight: '500',
Expand Down
Loading

0 comments on commit 6e78f30

Please sign in to comment.