import React , { useEffect , useState , useRef } from "react" ; import styled from "styled-components" ; import ReactTooltip from "react-tooltip" ; import { getScrollbarWidth } from "src/utils/scroll-bar-width" ; import media from "src/utils/media" ; import copy from "src/copy" ; import { flavors , Flavor } from "src/flavor" ; import { toppings , Topping , isTopping } from "src/topping" ; import { useBobaContext } from "src/contexts/boba" ; import BobaDisplay from "./BobaDisplay" ; import OptionPicker from "./OptionPicker" ; type ToppingOrFlavor = Topping | Flavor ; const circleBgColors = { mango : "#F8E399" , milk : "#F2E1CF" , matcha : "#E3E8B7" , taro : "#E7C8D8" , strawberry : "#F6B7B7" } ; const filterShownOptions = ( selected ) : ToppingOrFlavor [ ] => { let resultArr = isTopping ( selected ) ? [ ... toppings ] : [ ... flavors ] ; const posInArr = resultArr . indexOf ( selected ) ; if ( posInArr === 0 ) { resultArr = resultArr . slice ( resultArr . length - 1 , resultArr . length ) . concat ( resultArr . slice ( 0 , 2 ) ) ; } else if ( posInArr === resultArr . length - 1 ) { resultArr = resultArr . slice ( resultArr . length - 2 , resultArr . length ) . concat ( resultArr . slice ( 0 , 1 ) ) ; } else { resultArr = resultArr . slice ( posInArr - 1 , posInArr + 2 ) ; } return resultArr ; } ; const shiftOptionBy = ( selected , shiftBy ) => { let newIndex = ( isTopping ( selected ) ? toppings . indexOf ( selected as Topping ) : flavors . indexOf ( selected as Flavor ) ) + shiftBy ; newIndex = ( ( newIndex % toppings . length ) + toppings . length ) % toppings . length ; return isTopping ( selected ) ? toppings [ newIndex ] : flavors [ newIndex ] ; } ; const Container = styled . div < { circleColor : string ; } > `
  width: 550px;
  height: 375px;
  position: relative;

  margin: auto;

  display: flex;
  justify-content: space-between;

  & div.circleBg {
    width: 300px;
    height: 300px;
    bottom: 10px;
    position: absolute;
    left: 50%;
    transform: translateX(-50%);

    transition: background-color 500ms ease-out;
    background-color: ${ props => props . circleColor };
    border-radius: 50%;
  }

  ${ media . phone `
    width: calc(100vw - ${ getScrollbarWidth ( ) }px);
    height: auto;

    & div.circleBg {
      width: 250px;
      height: 250px;
      bottom: 30px;
    }
  ` }
` ; const BobaCustomizer = ( ) => { const { flavor , topping , updateFlavor , updateTopping , updateShowBg } = useBobaContext ( ) ; const [ userInteracted , updateUserInteracted ] = useState ( false ) ; const [ boopChanged , updateBoopChanged ] = useState ( false ) ; const shownFlavors = filterShownOptions ( flavor ) as Flavor [ ] ; const shownToppings = filterShownOptions ( topping ) as Topping [ ] ; const switcherRef = useRef ( null ) ; const changeTopping = ( newTopping , fromParam ) => { if ( newTopping !== topping ) { updateUserInteracted ( true ) ; updateShowBg ( false ) ; setTimeout ( ( ) => updateShowBg ( true ) , 1000 ) ; } if ( fromParam ) { updateTopping ( newTopping , userInteracted ) ; } if ( switcherRef . current ) { ( switcherRef . current as any ) . slickGoTo ( toppings . indexOf ( newTopping ) ) ; } } ; const nextTopping = ( ) => changeTopping ( shiftOptionBy ( topping , 1 ) as Topping , false ) ; const prevTopping = ( ) => changeTopping ( shiftOptionBy ( topping , - 1 ) as Topping , false ) ; const changeFlavor = ( newFlavor ) => { if ( newFlavor !== flavor ) { updateUserInteracted ( true ) ; } updateFlavor ( newFlavor , userInteracted ) ; } ; const nextFlavor = ( ) => changeFlavor ( shiftOptionBy ( flavor , 1 ) as Flavor ) ; const prevFlavor = ( ) => changeFlavor ( shiftOptionBy ( flavor , - 1 ) as Flavor ) ; useEffect ( ( ) => { if ( ! userInteracted ) { const flavorChangerId = setInterval ( ( ) => updateFlavor ( shiftOptionBy ( flavor , 1 ) as Flavor , false ) , 3000 ) ; return ( ) => clearTimeout ( flavorChangerId ) ; } else { updateBoopChanged ( true ) ; } return ( ) => { } ; } , [ userInteracted , flavor ] ) ; useEffect ( ( ) => ReactTooltip . rebuild ( ) , [ flavor , topping ] ) ; return ( < Container className = "optionPicker" circleColor = { circleBgColors [ flavor ] } > < OptionPicker incrementOption = { nextFlavor } decrementOption = { prevFlavor } changeOption = { changeFlavor } shownOptions = { shownFlavors } selectedOption = { flavor } tooltipOptions = { copy . hero . flavors } / > < div className = "circleBg" / > < BobaDisplay switcherRef = { switcherRef } boopChanged = { boopChanged } animationEndCallback = { ( ) => updateBoopChanged ( false ) } selectedFlavor = { flavor } selectedTopping = { topping } updateTopping = { topping => updateTopping ( topping , userInteracted ) } prevTopping = { prevTopping } nextTopping = { nextTopping } nextFlavor = { nextFlavor } / > < OptionPicker incrementOption = { nextTopping } decrementOption = { prevTopping } changeOption = { ( topping ) => changeTopping ( topping , false ) } shownOptions = { shownToppings } selectedOption = { topping } tooltipOptions = { copy . hero . toppings } / > < /Container>); } ; export default BobaCustomizer ;