import React, { useCallback, useEffect, useState } from 'react' import apiFetch from '@wordpress/api-fetch' import bringLogo from '../../assets/img/Bring_logo.svg' import collectPackagesImg from '../../assets/img/collect-packages.png' import { Button, ButtonGroup, Snackbar, Spinner, Notice, } from '@wordpress/components' import { BookingRequest, MybringCustomerAndServices, Order, ServiceDetails, ValidationError, } from './model/models' import CustomerSelector from './components/CustomerSelector' import { useI18n } from '@wordpress/react-i18n' import { arrowRight, pages, undo } from '@wordpress/icons' import BookedOrders from './components/BookedOrders' import Orders from './components/Orders' const OrderList = () => { const [orders, setOrders] = useState>([]) const [customers, setCustomers] = useState>( [] ) const [failedFromBooking, setFailedFromBooking] = useState>([]) const [customerNumber, setCustomerNumber] = useState() const [bookingStatus, setBookingStatus] = useState>({}) const [bookingTriggered, setBookingTriggered] = useState(false) const [bookingFinished, setBookingFinished] = useState(false) const [inProgress, setInProgress] = useState(false) const [currentlyDriving, setCurrentlyDriving] = useState(new Set()) const [labelFailure, setLabelFailure] = useState(false) const [waybillsFailure, setWaybillsFailure] = useState(false) const [labelsInProgress, setLabelsInProgress] = useState(false) const [waybillsInProgress, setWaybillsInProgress] = useState(false) const [returnLabelsInProgress, setReturnLabelsInProgress] = useState(false) const [bookingComplete, setBookingComplete] = useState>([]) const [availableServices, setAvailableServices] = useState< Array >([]) const { __ } = useI18n() const fetchCustomers = useCallback(async () => { const response: MybringCustomerAndServices[] = await apiFetch({ path: '/posten-bring-checkout/customers', }) if (response) setCustomers(response) if (!customerNumber && response !== null && response.length > 0) { const defaultCustomer = response.find(it => it.defaultCustomer) setCustomerNumber( defaultCustomer?.customerNumber || response[0].customerNumber ) } }, []) const fetchOrders = async (params: string) => { const response: Order[] = await apiFetch({ path: '/posten-bring-checkout/bookings' + (params ? '?' + params : ''), }) if (response) setOrders(response) } const fetchAvailableServices = async () => { const response: ServiceDetails[] = await apiFetch({ path: '/posten-bring-checkout/services', }) if (response) setAvailableServices(response) } const updateOrders = useCallback(() => { const orderIdsString = sessionStorage.getItem('posten_order_ids') if (orderIdsString) { const orderIdsArray = orderIdsString.split(',') const queryParamsArray = orderIdsArray.map(id => `orderIds[]=${id}`) const params = queryParamsArray.join('&') fetchOrders(params) } }, []) useEffect(() => { fetchCustomers() updateOrders() fetchAvailableServices() const handleSessionStorageChange = () => { setOrders([]) updateOrders() } window.addEventListener( 'posten-order-ids-changed', handleSessionStorageChange ) return () => { window.removeEventListener( 'posten-order-ids-changed', handleSessionStorageChange ) } }, [fetchCustomers, updateOrders]) const handleBooking = async () => { if (!orders.length) { return } setBookingTriggered(true) setInProgress(true) const newBookingStatus = { ...bookingStatus } const requests = orders .filter(order => (order.mybring_bookings?.length || 0) === 0) .map(async order => { const data = { orderId: order.order_id, testIndicator: false, selectedShippingOption: order.order_shipping_option, customerNumber, orderRef: order.order_id, packages: [ { weightInKg: order.total_weight / 1000, }, ], } as BookingRequest if ( !order.order_validation_errors.some(value => value.bookingDisabled) && order.order_shipping_option ) { try { await apiFetch({ path: '/posten-bring-checkout/bookings?orderId=' + order.order_id, method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(data), }) newBookingStatus[order.order_id] = 'success' } catch (error) { const bookingErrorMessage = error.message || __('Unknown error', 'posten-bring-checkout') const updatedOrder = { ...order, order_validation_errors: [ ...order.order_validation_errors, { bookingDisabled: true, message: bookingErrorMessage }, ], } setFailedFromBooking(prevFailed => [...prevFailed, updatedOrder]) newBookingStatus[order.order_id] = 'error' } const newStatus = { ...newBookingStatus } setBookingStatus(newStatus) setBookingComplete(Object.keys(newStatus)) } }) await Promise.all(requests) setTimeout(() => { setBookingFinished(true) setInProgress(false) }, 400) } useEffect(() => { const done = new Set(bookingComplete) setTimeout(() => { setCurrentlyDriving(done) }, 50) }, [bookingComplete, bookingComplete.length]) const mapServiceId = (orderShippingOption: string | undefined) => { if (!orderShippingOption) { return ( {__('No shipping option selected', 'posten-bring-checkout')} ) } return ( availableServices && availableServices.find( service => service.service_id === orderShippingOption )?.name ) } const onSave = (orderId: string, editedOrder?: Order) => { setOrders( orders.map(order => order.order_id === orderId ? editedOrder || order : order ) ) } const validationErrorsList = orders.filter( order => order.order_validation_errors.length > 0 ) const bookableOrders = orders.filter( order => (order.mybring_bookings?.length || 0) === 0 ) const bookedOrders = orders.filter( order => (order.mybring_bookings?.length || 0) > 0 && order.order_shipping_option && order.order_shipping_option !== '' ) const returnLabelsExist = !!orders.filter( order => (order.mybring_bookings?.length || 0) > 0 && order.mybring_bookings.filter(booking => booking.returnLabelUrl).length > 0 ) const waybillsExist = !!orders.filter( order => (order.mybring_bookings?.length || 0) > 0 && order.mybring_bookings.filter(booking => booking.waybillUrl).length > 0 ) const getLabels = async (labelType: string) => { setLabelFailure(false) const newTab = window.open('', '_blank') const orderIds = orders .filter( order => bookingStatus[order.order_id] === 'success' || (order.mybring_bookings?.length || 0) > 0 ) .map(order => order.order_id) .join(',') const response = await apiFetch({ path: `/posten-bring-checkout/labels?orderIds=${orderIds}&labelType=${labelType}`, method: 'GET', headers: { Accept: 'application/pdf', }, parse: false, }).catch(() => { setLabelFailure(true) }) setLabelsInProgress(false) setReturnLabelsInProgress(false) if (response?.ok) { const blob = await response.blob() const url = window.URL.createObjectURL( new Blob([blob], { type: 'application/pdf' }) ) if (newTab) { newTab.location.href = url } } } const getWaybills = async () => { setWaybillsFailure(false) const newTab = window.open('', '_blank') const orderIds = orders .filter( order => bookingStatus[order.order_id] === 'success' || (order.mybring_bookings?.length || 0) > 0 ) .map(order => order.order_id) .join(',') const response = await apiFetch({ path: `/posten-bring-checkout/waybills?orderIds=${orderIds}`, method: 'GET', headers: { Accept: 'application/pdf', }, parse: false, }).catch(() => { setWaybillsFailure(true) }) setWaybillsInProgress(false) if (response?.ok) { const blob = await response.blob() const url = window.URL.createObjectURL( new Blob([blob], { type: 'application/pdf' }) ) if (newTab) { newTab.location.href = url } } } return (

{__('Book shipping for multiple orders', 'posten-bring-checkout')}

{''}
{(bookableOrders.length === 0 && bookedOrders.length > 0) || (bookingFinished && bookedOrders.length > 0) || (bookingFinished && bookableOrders.length > 0 && Object.values(bookingStatus).includes('success')) ? (
{waybillsExist && ( )} {returnLabelsExist && ( )} {labelFailure && ( { setLabelFailure(false) }} > {__( 'An error occurred while generating labels. Please try again', 'posten-bring-checkout' )} )} {waybillsFailure && ( { setWaybillsFailure(false) }} > {__( 'An error occurred while generating waybills. Please try again', 'posten-bring-checkout' )} )}
) : null}
{orders && orders.length > 0 ? ( {(bookingTriggered || (bookableOrders.length === 0 && bookedOrders.length > 0)) && ( )}
{__('Order id', 'posten-bring-checkout')} {__('Shipping with', 'posten-bring-checkout')} {__('Weight', 'posten-bring-checkout')}{__('Status', 'posten-bring-checkout')}
) : (
)}
{validationErrorsList.length > 0 || Object.values(bookingStatus).includes('error') ? (

{' '} {__( 'There are problems with some of the orders:', 'posten-bring-checkout' )}
    {failedFromBooking.map(order => (
  • #{order.order_id} :{' '} {order.order_validation_errors .map(error => error.message) .join(', ')}
  • ))} {validationErrorsList.map(order => order.order_validation_errors.map( (error: ValidationError) => (
  • #{order.order_id} :{' '} {error.message}
  • ) ) )}
) : ( '' )}
{''}
setCustomerNumber(selectedCustomerNumber) } />
{/* eslint-disable-next-line @wordpress/i18n-no-flanking-whitespace */} {__('By ordering, you accept our ', 'posten-bring-checkout')} {__('terms and conditions.', 'posten-bring-checkout')}
) } export default OrderList