import React, { ReactElement } from 'react'; import { useReducer, useEffect } from 'react'; import { Button } from './Button'; import { Variant, Size } from '../types/VariantTypes'; interface State { status: string; isTempStatus: boolean; tempStatusTime: number; isAddingToBag: boolean; timeoutId: number | null; } type AddToBagActions = | { type: 'SetStatus'; payload: { status: string } } | { type: 'SetTempStatus'; payload: { status: string; time: number } } | { type: 'SetIsAddingToBag'; payload: { isAddingToBag: boolean } }; const initialState: State = { status: 'ADD TO BAG', isTempStatus: false, tempStatusTime: 3000, isAddingToBag: false, timeoutId: null, }; const reducer = (state: State, action: AddToBagActions): State => { switch (action.type) { case 'SetStatus': return { ...state, status: action.payload.status, isTempStatus: false }; case 'SetTempStatus': return { ...state, status: action.payload.status, tempStatusTime: action.payload.time, isTempStatus: true, }; case 'SetIsAddingToBag': return { ...state, isAddingToBag: action.payload.isAddingToBag }; } }; interface Props { trunkshowId: number; productId: number; selectedSize: Size; selectedVariant: Variant; onAddToBag: Function; customizable: boolean; href?: string; } export const AddToBag = (props: Props): ReactElement => { const [state, dispatch] = useReducer(reducer, initialState); const selectedSizeSoldOut = props.selectedSize && !props.selectedSize.can_sell; const handleClick = (): void => { if (props.selectedSize) { dispatch({ type: 'SetIsAddingToBag', payload: { isAddingToBag: true } }); props.onAddToBag( props.trunkshowId, props.productId, props.selectedSize, props.selectedVariant, () => { dispatch({ type: 'SetIsAddingToBag', payload: { isAddingToBag: false }, }); dispatch({ type: 'SetTempStatus', payload: { status: 'SUCCESSFULLY ADDED TO BAG', time: 3000 }, }); }, () => { dispatch({ type: 'SetIsAddingToBag', payload: { isAddingToBag: false }, }); dispatch({ type: 'SetTempStatus', payload: { status: 'UNABLE TO ADD ITEM TO BAG', time: 3000 }, }); }, ); } else { dispatch({ type: 'SetTempStatus', payload: { status: 'PLEASE SELECT A SIZE', time: 3000 }, }); } }; useEffect(() => { if (state.isTempStatus) { state.timeoutId = window.setTimeout( () => dispatch({ type: 'SetStatus', payload: { status: 'ADD TO BAG' } }), state.tempStatusTime, ); } return (): void => state.timeoutId && clearTimeout(state.timeoutId); }, [state.isTempStatus, state.tempStatusTime, state.timeoutId]); if ( !props.selectedVariant.coming_soon && props.selectedVariant.can_sell && !selectedSizeSoldOut && props.customizable ) { return ( { window.location.href = props.selectedVariant.href; }} /> ); } else if ( !props.selectedVariant.coming_soon && props.selectedVariant.can_sell && !selectedSizeSoldOut && state.isAddingToBag ) { return ; } else if ( !props.selectedVariant.coming_soon && props.selectedVariant.can_sell && !selectedSizeSoldOut && !state.isAddingToBag ) { return ( ); } else if ( !props.selectedVariant.coming_soon && !props.selectedVariant.can_sell ) { return ( ); } else if (props.selectedVariant.coming_soon) { return ( ); } else if ( !props.selectedVariant.coming_soon && props.selectedVariant.can_sell && selectedSizeSoldOut ) { return ( ); } }; const AddToBagButton = (props: { children?: ReactElement | Array | string; theme: string; text?: string; disabled?: boolean; onClick?: () => void; loading?: boolean; }): ReactElement => { const children = props.children ? props.children : props.text; const { theme, disabled = false, loading = false, onClick } = props; return ( ); };