\n
\n
\n \n \n
\n
\n
\n
\n
\n
\n
\n
\n
\n\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
{I18n.t(\"cart_summary.credit_cards.supported_card_types\")}
\n
{I18n.t(\"cart_summary.credit_cards.secure_payment_notice\")}
\n
\n
\n \n \n
\n \n \n \n );\n }\n}\n","// Some functions take a variable number of arguments, or a few expected\n// arguments at the beginning and then a variable number of values to operate\n// on. This helper accumulates all remaining arguments past the function’s\n// argument length (or an explicit `startIndex`), into an array that becomes\n// the last argument. Similar to ES6’s \"rest parameter\".\nexport default function restArguments(func, startIndex) {\n startIndex = startIndex == null ? func.length - 1 : +startIndex;\n return function () {\n var length = Math.max(arguments.length - startIndex, 0),\n rest = Array(length),\n index = 0;\n\n for (; index < length; index++) {\n rest[index] = arguments[index + startIndex];\n }\n\n switch (startIndex) {\n case 0:\n return func.call(this, rest);\n\n case 1:\n return func.call(this, arguments[0], rest);\n\n case 2:\n return func.call(this, arguments[0], arguments[1], rest);\n }\n\n var args = Array(startIndex + 1);\n\n for (index = 0; index < startIndex; index++) {\n args[index] = arguments[index];\n }\n\n args[startIndex] = rest;\n return func.apply(this, args);\n };\n}","import tagTester from './_tagTester.js';\nimport has from './_has.js';\nvar isArguments = tagTester('Arguments'); // Define a fallback version of the method in browsers (ahem, IE < 9), where\n// there isn't any inspectable \"Arguments\" type.\n\n(function () {\n if (!isArguments(arguments)) {\n isArguments = function isArguments(obj) {\n return has(obj, 'callee');\n };\n }\n})();\n\nexport default isArguments;","import getLength from './_getLength.js';\nimport isArrayLike from './_isArrayLike.js';\nimport isArray from './isArray.js';\nimport isArguments from './isArguments.js'; // Internal implementation of a recursive `flatten` function.\n\nexport default function flatten(input, depth, strict, output) {\n output = output || [];\n\n if (!depth && depth !== 0) {\n depth = Infinity;\n } else if (depth <= 0) {\n return output.concat(input);\n }\n\n var idx = output.length;\n\n for (var i = 0, length = getLength(input); i < length; i++) {\n var value = input[i];\n\n if (isArrayLike(value) && (isArray(value) || isArguments(value))) {\n // Flatten current level of array or arguments object.\n if (depth > 1) {\n flatten(value, depth - 1, strict, output);\n idx = output.length;\n } else {\n var j = 0,\n len = value.length;\n\n while (j < len) {\n output[idx++] = value[j++];\n }\n }\n } else if (!strict) {\n output[idx++] = value;\n }\n }\n\n return output;\n}","import restArguments from './restArguments.js';\nimport flatten from './_flatten.js';\nimport filter from './filter.js';\nimport contains from './contains.js'; // Take the difference between one array and a number of other arrays.\n// Only the elements present in just the first array will remain.\n\nexport default restArguments(function (array, rest) {\n rest = flatten(rest, true, true);\n return filter(array, function (value) {\n return !contains(rest, value);\n });\n});","import restArguments from './restArguments.js';\nimport difference from './difference.js'; // Return a version of the array that does not contain the specified value(s).\n\nexport default restArguments(function (array, otherArrays) {\n return difference(array, otherArrays);\n});","import cb from './_cb.js';\nimport keys from './keys.js'; // Returns the first key on an object that passes a truth test.\n\nexport default function findKey(obj, predicate, context) {\n predicate = cb(predicate, context);\n\n var _keys = keys(obj),\n key;\n\n for (var i = 0, length = _keys.length; i < length; i++) {\n key = _keys[i];\n if (predicate(obj[key], key, obj)) return key;\n }\n}","import find from './find.js';\nimport matcher from './matcher.js'; // Convenience version of a common use case of `_.find`: getting the first\n// object containing specific `key:value` pairs.\n\nexport default function findWhere(obj, attrs) {\n return find(obj, matcher(attrs));\n}","import isArrayLike from './_isArrayLike.js';\nimport findIndex from './findIndex.js';\nimport findKey from './findKey.js'; // Return the first value which passes a truth test.\n\nexport default function find(obj, predicate, context) {\n var keyFinder = isArrayLike(obj) ? findIndex : findKey;\n var key = keyFinder(obj, predicate, context);\n if (key !== void 0 && key !== -1) return obj[key];\n}","var V3_URL = 'https://js.stripe.com/v3';\nvar V3_URL_REGEX = /^https:\\/\\/js\\.stripe\\.com\\/v3\\/?(\\?.*)?$/;\nvar EXISTING_SCRIPT_MESSAGE = 'loadStripe.setLoadParameters was called but an existing Stripe.js script already exists in the document; existing script parameters will be used';\n\nvar findScript = function findScript() {\n var scripts = document.querySelectorAll(\"script[src^=\\\"\".concat(V3_URL, \"\\\"]\"));\n\n for (var i = 0; i < scripts.length; i++) {\n var script = scripts[i];\n\n if (!V3_URL_REGEX.test(script.src)) {\n continue;\n }\n\n return script;\n }\n\n return null;\n};\n\nvar injectScript = function injectScript(params) {\n var queryString = params && !params.advancedFraudSignals ? '?advancedFraudSignals=false' : '';\n var script = document.createElement('script');\n script.src = \"\".concat(V3_URL).concat(queryString);\n var headOrBody = document.head || document.body;\n\n if (!headOrBody) {\n throw new Error('Expected document.body not to be null. Stripe.js requires a element.');\n }\n\n headOrBody.appendChild(script);\n return script;\n};\n\nvar registerWrapper = function registerWrapper(stripe, startTime) {\n if (!stripe || !stripe._registerWrapper) {\n return;\n }\n\n stripe._registerWrapper({\n name: 'stripe-js',\n version: \"1.13.1\",\n startTime: startTime\n });\n};\n\nvar stripePromise = null;\n\nvar loadScript = function loadScript(params) {\n // Ensure that we only attempt to load Stripe.js at most once\n if (stripePromise !== null) {\n return stripePromise;\n }\n\n stripePromise = new Promise(function (resolve, reject) {\n if (typeof window === 'undefined') {\n // Resolve to null when imported server side. This makes the module\n // safe to import in an isomorphic code base.\n resolve(null);\n return;\n }\n\n if (window.Stripe && params) {\n console.warn(EXISTING_SCRIPT_MESSAGE);\n }\n\n if (window.Stripe) {\n resolve(window.Stripe);\n return;\n }\n\n try {\n var script = findScript();\n\n if (script && params) {\n console.warn(EXISTING_SCRIPT_MESSAGE);\n } else if (!script) {\n script = injectScript(params);\n }\n\n script.addEventListener('load', function () {\n if (window.Stripe) {\n resolve(window.Stripe);\n } else {\n reject(new Error('Stripe.js not available'));\n }\n });\n script.addEventListener('error', function () {\n reject(new Error('Failed to load Stripe.js'));\n });\n } catch (error) {\n reject(error);\n return;\n }\n });\n return stripePromise;\n};\n\nvar initStripe = function initStripe(maybeStripe, args, startTime) {\n if (maybeStripe === null) {\n return null;\n }\n\n var stripe = maybeStripe.apply(undefined, args);\n registerWrapper(stripe, startTime);\n return stripe;\n}; // own script injection.\n\n\nvar stripePromise$1 = Promise.resolve().then(function () {\n return loadScript(null);\n});\nvar loadCalled = false;\nstripePromise$1[\"catch\"](function (err) {\n if (!loadCalled) {\n console.warn(err);\n }\n});\n\nvar loadStripe = function loadStripe() {\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n loadCalled = true;\n var startTime = Date.now();\n return stripePromise$1.then(function (maybeStripe) {\n return initStripe(maybeStripe, args, startTime);\n });\n};\n\nexport { loadStripe };","import React from 'react';\nimport PropTypes from 'prop-types';\n\nimport Spinner from '../../../../../ui-components/Spinner'\nimport StripePaymentMethodsList from './StripePaymentMethodsList';\nimport AddStripeCreditCardModal from './modals/AddStripeCreditCardModal';\nimport AlertModal from \"../../../../../ui-components/AlertModal\";\nimport CreditCardsAPI from '../../../../../apis/CreditCardsAPI';\nimport {intercomTrackEvent} from \"../../../../../utils/Intercom/intercomHelper\";\nimport without from \"underscore/modules/without\";\nimport findWhere from \"underscore/modules/findWhere\";\nimport { CHANGE_PAYMENT_METHOD } from '../../../../../stores/CartStateStore';\n\n// used in AddStripeCreditCardModal\nimport { loadStripe } from \"@stripe/stripe-js\";\nconst stripePromise = loadStripe(process.env.STRIPE_PUBLISHABLE_API_KEY);\n\nfunction arrayWithout(array, id) {\n return without(array, findWhere(array, {\n id: id\n }));\n}\n\n\nexport default class StripeCheckout extends React.Component {\n\n static contextTypes = {\n userAuthToken: PropTypes.string\n };\n\n constructor(props) {\n super(props);\n\n this.state = {\n methods: [],\n loading: false,\n loaded: false,\n showNewCreditCardModal: false,\n selectedMethod: null,\n errorModalText: null\n };\n\n CreditCardsAPI.SetUserAuthToken(props.userAuthToken);\n }\n\n componentWillReceiveProps(props) {\n if (!this.state.loaded && props.shown && this.props.venueAcceptsStripe) {\n // Transition from shown: false to shown: true\n // Reload the payment methods\n this.reloadPaymentMethods();\n\n intercomTrackEvent('credit-cards-tab-selected', {});\n } else {\n if (props.shown && !this.props.shown) {\n // Transition from shown: false to shown: true\n // updates cart payment method.\n // TODO: refactor this bad practice.\n if (!!this.state.selectedMethod) {\n this.props.dispatchCartState({type: CHANGE_PAYMENT_METHOD, payload: {type: 'stripe', options: {method: this.state.selectedMethod}}})\n }\n }\n }\n }\n\n componentDidCatch(error, info) {\n }\n\n reloadPaymentMethods() {\n this.setState({loading: true});\n\n CreditCardsAPI.GetCreditCards().then((response) => {\n let cards = response.cards || [];\n let defaultMethod = response.default_source;\n\n //Check for American Express cards\n for (let card of cards) {\n if (card.brand === \"American Express\") {\n this.deletePaymentMethod(card);\n return;\n }\n }\n\n this.setState({methods: cards, loaded: true, loading: false, selectedMethod: defaultMethod});\n\n if (defaultMethod) {\n // Set as current method the first card\n this.props.dispatchCartState({type: CHANGE_PAYMENT_METHOD, payload: {type: 'stripe', options: {method: defaultMethod}}})\n } else {\n this.props.dispatchCartState({type: CHANGE_PAYMENT_METHOD, payload: {type: 'stripe', options: {}}})\n }\n }).catch((err) => {\n const res = err.response;\n\n const error_message = (res && res.body && res.body.error) ? (I18n.t(\"cart_summary.credit_cards.errors.cannot_get_cards\") + \": \" + res.body.error) : I18n.t(\"cart_summary.credit_cards.errors.cannot_get_cards\");\n this.setState({ errorModalText: error_message, methods: [], selectedMethod: null, loaded: true, loading: false});\n });\n }\n\n createPaymentMethod(method) {\n CreditCardsAPI.CreateCreditCard(method); // async, don't wait the result\n this.setState({loading: false, methods: this.state.methods.concat(method)});\n\n this.changeSelectedPaymentMethod(method);\n\n //const res = err.response;\n //const error_message = (res && res.body && res.body.error) ? (I18n.t(\"cart_summary.credit_cards.errors.cannot_add\") + \": \" + res.body.error) : I18n.t(\"cart_summary.credit_cards.errors.cannot_add\");\n //this.setState({errorModalText: error_message, loading: false});\n }\n\n changeSelectedPaymentMethod = (paymentMethod) => {\n this.setState({selectedMethod: paymentMethod.id});\n this.props.dispatchCartState({type: CHANGE_PAYMENT_METHOD, payload: {type: 'stripe', options: {method: paymentMethod.id}}})\n };\n\n deletePaymentMethod = (method) => {\n CreditCardsAPI.DeleteCreditCard(method);\n\n this.setState({methods: arrayWithout(this.state.methods, method.id)});\n\n /*CreditCardsAPI.DeleteCreditCard(method).then((response) => {\n this.setState({loading: false});\n this.reloadPaymentMethods();\n }).catch((err) => {\n const res = err.response;\n\n const error_message = (res && res.body && res.body.error) ? (I18n.t(\"cart_summary.credit_cards.errors.cannot_remove\") + \": \" + res.body.error) : I18n.t(\"cart_summary.credit_cards.errors.cannot_remove\");\n this.setState({errorModalText: error_message, loading: false});\n this.reloadPaymentMethods();\n });*/\n };\n\n showNewCardForm = (event) => {\n event.preventDefault();\n\n this.setState({showNewCreditCardModal: true});\n };\n\n hideNewCardForm = () => {\n this.setState({showNewCreditCardModal: false});\n };\n\n handleNewCreditCard = (method) => {\n this.hideNewCardForm();\n this.createPaymentMethod(method);\n };\n\n renderPaymentMethods(showAlertMessage) {\n return (this.state.methods.length > 0) ?\n
\n
{I18n.t(\"cart_summary.credit_cards.pre_auth_instructions\")}
\n {showAlertMessage &&
\n {I18n.t(\"cart_summary.credit_cards.delivery_price_instructions\")}\n
}\n
: null\n }\n\n renderSpinner() {\n return
;\n }\n\n renderNoStripe() {\n return (
{I18n.t(\"cart_summary.venue_no_credit_cards\")}
);\n }\n\n renderStripeForm() {\n return (
\n
this.setState({errorModalText: null})}/>\n\n \n
\n {(this.state.methods.length === 0) ?\n
{I18n.t(\"cart_summary.credit_cards.no_credit_cards_present\")}
:\n
\n }\n\n \n \n
this.setState({errorModalText: message}) }\n onHide={this.hideNewCardForm}\n show={this.state.showNewCreditCardModal}/>\n )\n }\n\n render() {\n if (this.state.loading) {\n return this.renderSpinner();\n } else {\n if (this.props.venueAcceptsStripe) {\n return this.renderStripeForm();\n } else {\n return this.renderNoStripe()\n }\n }\n }\n}\n","import React from 'react'\n\nimport { CHANGE_PAYMENT_METHOD } from '../../../../stores/CartStateStore';\nimport { ORDER_MAX_CHANGE_THRESHOLD } from '../../../../utils/config';\n\nexport default class CashForm extends React.Component {\n\n handleChange = (event) => {\n let value = event.target.value;\n value = value.replace(',', '.'); // Replace the commas with dots to support the decimal numbers\n value = value.replace(/[^0-9\\.]+/g, ''); // Replace non digits\n\n if (isNaN(parseFloat(value))) {\n value = '';\n }\n\n this.props.setCashAmount(value)\n\n this.props.dispatchCartState({type: CHANGE_PAYMENT_METHOD, payload: {type: 'cash', options: {cash_amount: value}}})\n };\n\n render() {\n const { enabled, errors, requiresCashValue} = this.props;\n\n if (!enabled) {\n return (\n {I18n.t('cart_summary.venue_no_cash')}
\n )\n }\n\n return (\n \n
{I18n.t('cart_summary.payment_in_cash_at_delivery')}
\n\n {requiresCashValue &&
\n
\n
\n €\n \n
\n
}\n\n {errors.payment_details && errors.payment_details.map(function (error) {\n return
{error}
\n })}\n\n {this.props.showAlertMessage &&
{I18n.t('cart_summary.cash_money_at_delivery', {value: ORDER_MAX_CHANGE_THRESHOLD})}
}\n\n
\n );\n }\n}\n","import React from \"react\"\n\nexport default function SatispayForm() {\n // -------------------------------------\n // Props destructuring\n // -------------------------------------\n\n // -------------------------------------\n // Hooks (e.g. useState, useMemo ...)\n // -------------------------------------\n\n // -------------------------------------\n // Effects\n // -------------------------------------\n\n // -------------------------------------\n // Component functions\n // -------------------------------------\n\n // -------------------------------------\n // Component local variables\n // -------------------------------------\n\n // -------------------------------------\n\n return (\n \n
\n {I18n.t(\"cart_summary.satispay.description\")}\n
\n
\n )\n}\n","import React from \"react\"\nimport Tabs from \"react-bootstrap/lib/Tabs\"\nimport Tab from \"react-bootstrap/lib/Tab\"\n\nimport { logCashAlertOverThreshold } from \"../../../../apis/Analytics/gtmActions\"\n\nimport AlertModal from \"../../../../ui-components/AlertModal\"\nimport StripeCheckout from \"./stripe/StripeCheckout\"\nimport CashForm from \"./CashForm\"\nimport { ORDER_MAX_CASH_THRESHOLD } from \"../../../../utils/config\"\nimport SatispayForm from \"./Satispay/SatispayForm\"\nimport { CHANGE_PAYMENT_METHOD } from \"../../../../stores/CartStateStore\"\nimport { useState } from \"react\"\n\nconst PAYMENTS_TABS = {\n CASH: 1,\n CREDIT_CARD: 2,\n SATISPAY: 3,\n}\n\nexport default function PaymentTypeSelector(props) {\n // -------------------------------------\n // Props destructuring\n // -------------------------------------\n\n const {\n userAuthToken,\n showAlertMessage,\n showStripeMethod,\n isTakeAway,\n venueAcceptsCash,\n venueAcceptsStripe,\n amount,\n deliveryPrice,\n cartState,\n dispatchCartState,\n errors,\n stripe_key\n } = props\n\n // -------------------------------------\n // Hooks (e.g. useState, useMemo ...)\n // -------------------------------------\n\n const [tab, setTab] = useState(getDefaultTabIndex())\n const [error, setError] = useState(null)\n const [cashAmount, setCashAmount] = useState(\"\")\n\n // -------------------------------------\n // Effects\n // -------------------------------------\n\n // -------------------------------------\n // Component functions\n // -------------------------------------\n\n function isCashDisabledByAmount() {\n return amount / 100.0 > ORDER_MAX_CASH_THRESHOLD && venueAcceptsStripe\n }\n\n function getDefaultTabIndex() {\n if (!venueAcceptsCash) {\n return PAYMENTS_TABS.CREDIT_CARD\n }\n\n if (isCashDisabledByAmount()) {\n return PAYMENTS_TABS.CREDIT_CARD\n }\n\n return PAYMENTS_TABS.CASH\n }\n\n function handleTabSelect(value) {\n switch (value) {\n case PAYMENTS_TABS.CASH:\n if (!venueAcceptsCash) {\n setError(I18n.t(\"cart_summary.venue_no_cash\"))\n return\n }\n\n if (isCashDisabledByAmount()) {\n setError(\n I18n.t(\"cart_summary.cash_value_too_high_alert\", {\n value: ORDER_MAX_CASH_THRESHOLD,\n })\n )\n logCashAlertOverThreshold()\n return\n }\n\n // also dispatched into CashForm\n // TODO: refactor\n dispatchCartState({\n type: CHANGE_PAYMENT_METHOD,\n payload: { type: \"cash\", options: { cash_amount: cashAmount } },\n })\n break\n case PAYMENTS_TABS.CREDIT_CARD:\n // actually dispatched into StripeCheckout\n // TODO: refactor StripeCheckout state management bad practice and dispatch here\n // dispatchCartState({type: CHANGE_PAYMENT_METHOD, payload: {type: 'satispay'}})\n break\n case PAYMENTS_TABS.SATISPAY:\n dispatchCartState({\n type: CHANGE_PAYMENT_METHOD,\n payload: { type: \"satispay\" },\n })\n break\n }\n\n setTab(value)\n }\n\n function renderCashForm() {\n return (\n \n )\n }\n\n function renderStripeForm() {\n return (\n \n )\n }\n\n function renderSatispayForm() {\n return \n }\n\n // -------------------------------------\n // Component local variables\n // -------------------------------------\n\n // -------------------------------------\n\n // GUARD\n if (!showStripeMethod) {\n return renderCashForm()\n }\n\n return (\n \n
setError(null)}\n show={!!error}\n title={I18n.t(\"cart_summary.warning\")}\n text={error}\n />\n\n \n \n {\" \"}\n {I18n.t(\"cart_summary.pay_with_cash\")}\n \n }\n >\n {\" \"}\n {renderCashForm()}\n \n \n {\" \"}\n {I18n.t(\"cart_summary.pay_with_card\")}\n \n }\n >\n {\" \"}\n {renderStripeForm()}\n \n
\n {\" \"}\n {I18n.t(\"cart_summary.pay_with_satispay\")}\n \n }\n >\n {\" \"}\n {renderSatispayForm()}\n \n \n
\n )\n}\n","import React from \"react\"\n\nimport CouponForm from \"./CouponForm\"\nimport PaymentTypeSelector from \"./PaymentTypeSelector\"\n\nexport default function PaymentDetailsForm(props) {\n return (\n
\n
{I18n.t(\"payment\")}
\n\n
\n\n
\n
\n )\n}\n","import React from \"react\"\n\nexport default function BillingDetailsForm(props) {\n // -------------------------------------\n // Props destructuring\n // -------------------------------------\n\n const { state, setState, errors } = props\n\n // -------------------------------------\n // Hooks (e.g. useState, useMemo ...)\n // -------------------------------------\n\n // -------------------------------------\n // Effects\n // -------------------------------------\n\n // -------------------------------------\n // Component functions\n // -------------------------------------\n\n function handleBusinessNameChange(event) {\n setState({ ...state, business_name: event.target.value })\n }\n\n function handleBusinessAddressChange(event) {\n setState({ ...state, business_address: event.target.value })\n }\n\n function handleVatCodeChange(event) {\n setState({ ...state, vat_code: event.target.value })\n }\n\n function handleBusinessInvoiceCode(event) {\n setState({ ...state, business_invoice_code: event.target.value })\n }\n\n function handleTaxCodeChange(event) {\n setState({ ...state, tax_code: event.target.value })\n }\n\n function handleToggle(event) {\n setState({ ...state, request_invoice: !state.request_invoice })\n }\n\n function renderForm() {\n return (\n
\n
\n
\n )\n }\n\n // -------------------------------------\n // Component local variables\n // -------------------------------------\n\n // -------------------------------------\n\n return (\n
\n
{I18n.t(\"cart_summary.billing_details\")}
\n
\n
\n
\n {state.request_invoice ? renderForm() : \"\"}\n
\n )\n}\n","// Country Data for Country Code Phone\nimport React from 'react';\n\nconst rawAllCountries = [\n [\n 'Afghanistan',\n ['asia'],\n 'af',\n '93'\n ],\n [\n 'Albania',\n ['europe'],\n 'al',\n '355'\n ],\n [\n 'Algeria',\n ['africa', 'north-africa'],\n 'dz',\n '213'\n ],\n [\n 'American Samoa',\n ['oceania'],\n 'as',\n '1684'\n ],\n [\n 'Andorra',\n ['europe'],\n 'ad',\n '376'\n ],\n [\n 'Angola',\n ['africa'],\n 'ao',\n '244'\n ],\n [\n 'Anguilla',\n ['america', 'carribean'],\n 'ai',\n '1264'\n ],\n [\n 'Antigua and Barbuda',\n ['america', 'carribean'],\n 'ag',\n '1268'\n ],\n [\n 'Argentina',\n ['america', 'south-america'],\n 'ar',\n '54',\n '+.. (..) ........'\n ],\n [\n 'Armenia',\n ['asia', 'ex-ussr'],\n 'am',\n '374'\n ],\n [\n 'Aruba',\n ['america', 'carribean'],\n 'aw',\n '297'\n ],\n [\n 'Australia',\n ['oceania'],\n 'au',\n '61',\n '+.. ... ... ...'\n ],\n [\n 'Austria',\n ['europe', 'european-union'],\n 'at',\n '43'\n ],\n [\n 'Azerbaijan',\n ['asia', 'ex-ussr'],\n 'az',\n '994'\n ],\n [\n 'Bahamas',\n ['america', 'carribean'],\n 'bs',\n '1242'\n ],\n [\n 'Bahrain',\n ['middle-east'],\n 'bh',\n '973'\n ],\n [\n 'Bangladesh',\n ['asia'],\n 'bd',\n '880'\n ],\n [\n 'Barbados',\n ['america', 'carribean'],\n 'bb',\n '1246'\n ],\n [\n 'Belarus',\n ['europe', 'ex-ussr'],\n 'by',\n '375',\n '+... (..) ... .. ..'\n ],\n [\n 'Belgium',\n ['europe', 'european-union'],\n 'be',\n '32',\n '+.. ... .. .. ..'\n ],\n [\n 'Belize',\n ['america', 'central-america'],\n 'bz',\n '501'\n ],\n [\n 'Benin',\n ['africa'],\n 'bj',\n '229'\n ],\n [\n 'Bermuda',\n ['america', 'north-america'],\n 'bm',\n '1441'\n ],\n [\n 'Bhutan',\n ['asia'],\n 'bt',\n '975'\n ],\n [\n 'Bolivia',\n ['america', 'south-america'],\n 'bo',\n '591'\n ],\n [\n 'Bosnia and Herzegovina',\n ['europe'],\n 'ba',\n '387'\n ],\n [\n 'Botswana',\n ['africa'],\n 'bw',\n '267'\n ],\n [\n 'Brazil',\n ['america', 'south-america'],\n 'br',\n '55',\n '+.. (..) .........',\n ],\n [\n 'British Indian Ocean Territory',\n ['asia'],\n 'io',\n '246'\n ],\n [\n 'British Virgin Islands',\n ['america', 'carribean'],\n 'vg',\n '1284'\n ],\n [\n 'Brunei',\n ['asia'],\n 'bn',\n '673'\n ],\n [\n 'Bulgaria',\n ['europe', 'european-union'],\n 'bg',\n '359'\n ],\n [\n 'Burkina Faso',\n ['africa'],\n 'bf',\n '226'\n ],\n [\n 'Burundi',\n ['africa'],\n 'bi',\n '257'\n ],\n [\n 'Cambodia',\n ['asia'],\n 'kh',\n '855'\n ],\n [\n 'Cameroon',\n ['africa'],\n 'cm',\n '237'\n ],\n [\n 'Cape Verde',\n ['africa'],\n 'cv',\n '238'\n ],\n [\n 'Caribbean Netherlands',\n ['america', 'carribean'],\n 'bq',\n '599',\n '',\n 1\n ],\n [\n 'Cayman Islands',\n ['america', 'carribean'],\n 'ky',\n '1345'\n ],\n [\n 'Central African Republic',\n ['africa'],\n 'cf',\n '236'\n ],\n [\n 'Chad',\n ['africa'],\n 'td',\n '235'\n ],\n [\n 'Chile',\n ['america', 'south-america'],\n 'cl',\n '56'\n ],\n [\n 'China',\n ['asia'],\n 'cn',\n '86',\n '+.. ..-.........'\n ],\n [\n 'Colombia',\n ['america', 'south-america'],\n 'co',\n '57'\n ],\n [\n 'Comoros',\n ['africa'],\n 'km',\n '269'\n ],\n [\n 'Congo',\n ['africa'],\n 'cd',\n '243'\n ],\n [\n 'Congo',\n ['africa'],\n 'cg',\n '242'\n ],\n [\n 'Cook Islands',\n ['oceania'],\n 'ck',\n '682'\n ],\n [\n 'Costa Rica',\n ['america', 'central-america'],\n 'cr',\n '506',\n '+... ....-....'\n ],\n [\n 'Côte d’Ivoire',\n ['africa'],\n 'ci',\n '225'\n ],\n [\n 'Croatia',\n ['europe', 'european-union'],\n 'hr',\n '385'\n ],\n [\n 'Cuba',\n ['america', 'carribean'],\n 'cu',\n '53'\n ],\n [\n 'Curaçao',\n ['america', 'carribean'],\n 'cw',\n '599',\n '',\n 0\n ],\n [\n 'Cyprus',\n ['europe', 'european-union'],\n 'cy',\n '357',\n '+... .. ......'\n ],\n [\n 'Czech Republic',\n ['europe', 'european-union'],\n 'cz',\n '420'\n ],\n [\n 'Denmark',\n ['europe', 'european-union'],\n 'dk',\n '45',\n '+.. .. .. .. ..'\n ],\n [\n 'Djibouti',\n ['africa'],\n 'dj',\n '253'\n ],\n [\n 'Dominica',\n ['america', 'carribean'],\n 'dm',\n '1767'\n ],\n [\n 'Ecuador',\n ['america', 'south-america'],\n 'ec',\n '593'\n ],\n [\n 'Egypt',\n ['africa', 'north-africa'],\n 'eg',\n '20'\n ],\n [\n 'El Salvador',\n ['america', 'central-america'],\n 'sv',\n '503',\n '+... ....-....'\n ],\n [\n 'Equatorial Guinea',\n ['africa'],\n 'gq',\n '240'\n ],\n [\n 'Eritrea',\n ['africa'],\n 'er',\n '291'\n ],\n [\n 'Estonia',\n ['europe', 'european-union', 'ex-ussr'],\n 'ee',\n '372',\n '+... .... ......'\n ],\n [\n 'Ethiopia',\n ['africa'],\n 'et',\n '251'\n ],\n [\n 'Falkland Islands',\n ['america', 'south-america'],\n 'fk',\n '500'\n ],\n [\n 'Faroe Islands',\n ['europe'],\n 'fo',\n '298'\n ],\n [\n 'Fiji',\n ['oceania'],\n 'fj',\n '679'\n ],\n [\n 'Finland',\n ['europe', 'european-union'],\n 'fi',\n '358',\n '+... .. ... .. ..'\n ],\n [\n 'France',\n ['europe', 'european-union'],\n 'fr',\n '33',\n '+.. . .. .. .. ..'\n ],\n [\n 'French Guiana',\n ['america', 'south-america'],\n 'gf',\n '594'\n ],\n [\n 'French Polynesia',\n ['oceania'],\n 'pf',\n '689'\n ],\n [\n 'Gabon',\n ['africa'],\n 'ga',\n '241'\n ],\n [\n 'Gambia',\n ['africa'],\n 'gm',\n '220'\n ],\n [\n 'Georgia',\n ['asia', 'ex-ussr'],\n 'ge',\n '995'\n ],\n [\n 'Germany',\n ['europe', 'european-union'],\n 'de',\n '49',\n '+.. .... ........'\n ],\n [\n 'Ghana',\n ['africa'],\n 'gh',\n '233'\n ],\n [\n 'Gibraltar',\n ['europe'],\n 'gi',\n '350'\n ],\n [\n 'Greece',\n ['europe', 'european-union'],\n 'gr',\n '30'\n ],\n [\n 'Greenland',\n ['america'],\n 'gl',\n '299'\n ],\n [\n 'Grenada',\n ['america', 'carribean'],\n 'gd',\n '1473'\n ],\n [\n 'Guadeloupe',\n ['america', 'carribean'],\n 'gp',\n '590',\n '',\n 0\n ],\n [\n 'Guam',\n ['oceania'],\n 'gu',\n '1671'\n ],\n [\n 'Guatemala',\n ['america', 'central-america'],\n 'gt',\n '502',\n '+... ....-....'\n ],\n [\n 'Guinea',\n ['africa'],\n 'gn',\n '224'\n ],\n [\n 'Guinea-Bissau',\n ['africa'],\n 'gw',\n '245'\n ],\n [\n 'Guyana',\n ['america', 'south-america'],\n 'gy',\n '592'\n ],\n [\n 'Haiti',\n ['america', 'carribean'],\n 'ht',\n '509',\n '+... ....-....'\n ],\n [\n 'Honduras',\n ['america', 'central-america'],\n 'hn',\n '504'\n ],\n [\n 'Hong Kong',\n ['asia'],\n 'hk',\n '852',\n '+... .... ....'\n ],\n [\n 'Hungary',\n ['europe', 'european-union'],\n 'hu',\n '36'\n ],\n [\n 'Iceland',\n ['europe'],\n 'is',\n '354',\n '+... ... ....'\n ],\n [\n 'India',\n ['asia'],\n 'in',\n '91',\n '+.. .....-.....'\n ],\n [\n 'Indonesia',\n ['asia'],\n 'id',\n '62'\n ],\n [\n 'Iran',\n ['middle-east'],\n 'ir',\n '98'\n ],\n [\n 'Iraq',\n ['middle-east'],\n 'iq',\n '964'\n ],\n [\n 'Ireland',\n ['europe', 'european-union'],\n 'ie',\n '353',\n '+... .. .......'\n ],\n [\n 'Israel',\n ['middle-east'],\n 'il',\n '972',\n '+... ... ... ....'\n ],\n [\n 'Italia',\n ['europe', 'european-union'],\n 'it',\n '39',\n '+.. ... .......',\n 0\n ],\n [\n 'Jamaica',\n ['america', 'carribean'],\n 'jm',\n '1876'\n ],\n [\n 'Japan',\n ['asia'],\n 'jp',\n '81',\n '+.. .. .... ....'\n ],\n [\n 'Jordan',\n ['middle-east'],\n 'jo',\n '962'\n ],\n [\n 'Kenya',\n ['africa'],\n 'ke',\n '254'\n ],\n [\n 'Kiribati',\n ['oceania'],\n 'ki',\n '686'\n ],\n [\n 'Kuwait',\n ['middle-east'],\n 'kw',\n '965'\n ],\n [\n 'Kyrgyzstan',\n ['asia', 'ex-ussr'],\n 'kg',\n '996'\n ],\n [\n 'Laos',\n ['asia'],\n 'la',\n '856'\n ],\n [\n 'Latvia',\n ['europe', 'european-union', 'ex-ussr'],\n 'lv',\n '371'\n ],\n [\n 'Lebanon',\n ['middle-east'],\n 'lb',\n '961'\n ],\n [\n 'Lesotho',\n ['africa'],\n 'ls',\n '266'\n ],\n [\n 'Liberia',\n ['africa'],\n 'lr',\n '231'\n ],\n [\n 'Libya',\n ['africa', 'north-africa'],\n 'ly',\n '218'\n ],\n [\n 'Liechtenstein',\n ['europe'],\n 'li',\n '423'\n ],\n [\n 'Lithuania',\n ['europe', 'european-union', 'ex-ussr'],\n 'lt',\n '370'\n ],\n [\n 'Luxembourg',\n ['europe', 'european-union'],\n 'lu',\n '352'\n ],\n [\n 'Macau',\n ['asia'],\n 'mo',\n '853'\n ],\n [\n 'Macedonia',\n ['europe'],\n 'mk',\n '389'\n ],\n [\n 'Madagascar',\n ['africa'],\n 'mg',\n '261'\n ],\n [\n 'Malawi',\n ['africa'],\n 'mw',\n '265'\n ],\n [\n 'Malaysia',\n ['asia'],\n 'my',\n '60',\n '+.. ..-....-....'\n ],\n [\n 'Maldives',\n ['asia'],\n 'mv',\n '960'\n ],\n [\n 'Mali',\n ['africa'],\n 'ml',\n '223'\n ],\n [\n 'Malta',\n ['europe', 'european-union'],\n 'mt',\n '356'\n ],\n [\n 'Marshall Islands',\n ['oceania'],\n 'mh',\n '692'\n ],\n [\n 'Martinique',\n ['america', 'carribean'],\n 'mq',\n '596'\n ],\n [\n 'Mauritania',\n ['africa'],\n 'mr',\n '222'\n ],\n [\n 'Mauritius',\n ['africa'],\n 'mu',\n '230'\n ],\n [\n 'Mexico',\n ['america', 'central-america'],\n 'mx',\n '52'\n ],\n [\n 'Micronesia',\n ['oceania'],\n 'fm',\n '691'\n ],\n [\n 'Moldova',\n ['europe'],\n 'md',\n '373',\n '+... (..) ..-..-..'\n ],\n [\n 'Monaco',\n ['europe'],\n 'mc',\n '377'\n ],\n [\n 'Mongolia',\n ['asia'],\n 'mn',\n '976'\n ],\n [\n 'Montenegro',\n ['europe'],\n 'me',\n '382'\n ],\n [\n 'Montserrat',\n ['america', 'carribean'],\n 'ms',\n '1664'\n ],\n [\n 'Morocco',\n ['africa', 'north-africa'],\n 'ma',\n '212'\n ],\n [\n 'Mozambique',\n ['africa'],\n 'mz',\n '258'\n ],\n [\n 'Myanmar',\n ['asia'],\n 'mm',\n '95'\n ],\n [\n 'Namibia',\n ['africa'],\n 'na',\n '264'\n ],\n [\n 'Nauru',\n ['africa'],\n 'nr',\n '674'\n ],\n [\n 'Nepal',\n ['asia'],\n 'np',\n '977'\n ],\n [\n 'Netherlands',\n ['europe', 'european-union'],\n 'nl',\n '31',\n '+.. .. ........'\n ],\n [\n 'New Caledonia',\n ['oceania'],\n 'nc',\n '687'\n ],\n [\n 'New Zealand',\n ['oceania'],\n 'nz',\n '64',\n '+.. ...-...-....'\n ],\n [\n 'Nicaragua',\n ['america', 'central-america'],\n 'ni',\n '505'\n ],\n [\n 'Niger',\n ['africa'],\n 'ne',\n '227'\n ],\n [\n 'Nigeria',\n ['africa'],\n 'ng',\n '234'\n ],\n [\n 'Niue',\n ['asia'],\n 'nu',\n '683'\n ],\n [\n 'Norfolk Island',\n ['oceania'],\n 'nf',\n '672'\n ],\n [\n 'North Korea',\n ['asia'],\n 'kp',\n '850'\n ],\n [\n 'Northern Mariana Islands',\n ['oceania'],\n 'mp',\n '1670'\n ],\n [\n 'Norway',\n ['europe'],\n 'no',\n '47',\n '+.. ... .. ...'\n ],\n [\n 'Oman',\n ['middle-east'],\n 'om',\n '968'\n ],\n [\n 'Pakistan',\n ['asia'],\n 'pk',\n '92',\n '+.. ...-.......'\n ],\n [\n 'Palau',\n ['oceania'],\n 'pw',\n '680'\n ],\n [\n 'Palestine',\n ['middle-east'],\n 'ps',\n '970'\n ],\n [\n 'Panama',\n ['america', 'central-america'],\n 'pa',\n '507'\n ],\n [\n 'Papua New Guinea',\n ['oceania'],\n 'pg',\n '675'\n ],\n [\n 'Paraguay',\n ['america', 'south-america'],\n 'py',\n '595'\n ],\n [\n 'Peru',\n ['america', 'south-america'],\n 'pe',\n '51'\n ],\n [\n 'Philippines',\n ['asia'],\n 'ph',\n '63',\n '+.. .... .......'\n ],\n [\n 'Poland',\n ['europe', 'european-union'],\n 'pl',\n '48',\n '+.. ...-...-...'\n ],\n [\n 'Portugal',\n ['europe', 'european-union'],\n 'pt',\n '351'\n ],\n [\n 'Qatar',\n ['middle-east'],\n 'qa',\n '974'\n ],\n [\n 'Réunion',\n ['africa'],\n 're',\n '262'\n ],\n [\n 'Romania',\n ['europe', 'european-union'],\n 'ro',\n '40'\n ],\n [\n 'Russia/Kazakhstan',\n ['europe', 'asia', 'ex-ussr'],\n 'ru',\n '7',\n '+. (...) ...-..-..',\n 0\n ],\n [\n 'Rwanda',\n ['africa'],\n 'rw',\n '250'\n ],\n [\n 'Saint Barthélemy',\n ['america', 'carribean'],\n 'bl',\n '590',\n '',\n 1\n ],\n [\n 'Saint Helena',\n ['africa'],\n 'sh',\n '290'\n ],\n [\n 'Saint Kitts and Nevis',\n ['america', 'carribean'],\n 'kn',\n '1869'\n ],\n [\n 'Saint Lucia',\n ['america', 'carribean'],\n 'lc',\n '1758'\n ],\n [\n 'Saint Martin',\n ['america', 'carribean'],\n 'mf',\n '590',\n '',\n 2\n ],\n [\n 'Saint Pierre and Miquelon',\n ['america', 'north-america'],\n 'pm',\n '508'\n ],\n [\n 'Saint Vincent and the Grenadines',\n ['america', 'carribean'],\n 'vc',\n '1784'\n ],\n [\n 'Samoa',\n ['oceania'],\n 'ws',\n '685'\n ],\n [\n 'San Marino',\n ['europe'],\n 'sm',\n '378'\n ],\n [\n 'São Tomé and Príncipe',\n ['africa'],\n 'st',\n '239'\n ],\n [\n 'Saudi Arabia',\n ['middle-east'],\n 'sa',\n '966'\n ],\n [\n 'Senegal',\n ['africa'],\n 'sn',\n '221'\n ],\n [\n 'Serbia',\n ['europe'],\n 'rs',\n '381'\n ],\n [\n 'Seychelles',\n ['africa'],\n 'sc',\n '248'\n ],\n [\n 'Sierra Leone',\n ['africa'],\n 'sl',\n '232'\n ],\n [\n 'Singapore',\n ['asia'],\n 'sg',\n '65',\n '+.. ....-....'\n ],\n [\n 'Sint Maarten',\n ['america', 'carribean'],\n 'sx',\n '1721'\n ],\n [\n 'Slovakia',\n ['europe', 'european-union'],\n 'sk',\n '421'\n ],\n [\n 'Slovenia',\n ['europe', 'european-union'],\n 'si',\n '386'\n ],\n [\n 'Solomon Islands',\n ['oceania'],\n 'sb',\n '677'\n ],\n [\n 'Somalia',\n ['africa'],\n 'so',\n '252'\n ],\n [\n 'South Africa',\n ['africa'],\n 'za',\n '27'\n ],\n [\n 'South Korea',\n ['asia'],\n 'kr',\n '82',\n '+.. ... .... ....'\n ],\n [\n 'South Sudan',\n ['africa', 'north-africa'],\n 'ss',\n '211'\n ],\n [\n 'Spain',\n ['europe', 'european-union'],\n 'es',\n '34',\n '+.. ... ... ...'\n ],\n [\n 'Sri Lanka',\n ['asia'],\n 'lk',\n '94'\n ],\n [\n 'Sudan',\n ['africa'],\n 'sd',\n '249'\n ],\n [\n 'Suriname',\n ['america', 'south-america'],\n 'sr',\n '597'\n ],\n [\n 'Swaziland',\n ['africa'],\n 'sz',\n '268'\n ],\n [\n 'Sweden',\n ['europe', 'european-union'],\n 'se',\n '46',\n '+.. (...) ...-...'\n ],\n [\n 'Switzerland',\n ['europe'],\n 'ch',\n '41',\n '+.. .. ... .. ..'\n ],\n [\n 'Syria',\n ['middle-east'],\n 'sy',\n '963'\n ],\n [\n 'Taiwan',\n ['asia'],\n 'tw',\n '886'\n ],\n [\n 'Tajikistan',\n ['asia', 'ex-ussr'],\n 'tj',\n '992'\n ],\n [\n 'Tanzania',\n ['africa'],\n 'tz',\n '255'\n ],\n [\n 'Thailand',\n ['asia'],\n 'th',\n '66'\n ],\n [\n 'Timor-Leste',\n ['asia'],\n 'tl',\n '670'\n ],\n [\n 'Togo',\n ['africa'],\n 'tg',\n '228'\n ],\n [\n 'Tokelau',\n ['oceania'],\n 'tk',\n '690'\n ],\n [\n 'Tonga',\n ['oceania'],\n 'to',\n '676'\n ],\n [\n 'Trinidad and Tobago',\n ['america', 'carribean'],\n 'tt',\n '1868'\n ],\n [\n 'Tunisia',\n ['africa', 'north-africa'],\n 'tn',\n '216'\n ],\n [\n 'Turkey',\n ['europe'],\n 'tr',\n '90',\n '+.. ... ... .. ..'\n ],\n [\n 'Turkmenistan',\n ['asia', 'ex-ussr'],\n 'tm',\n '993'\n ],\n [\n 'Turks and Caicos Islands',\n ['america', 'carribean'],\n 'tc',\n '1649'\n ],\n [\n 'Tuvalu',\n ['asia'],\n 'tv',\n '688'\n ],\n [\n 'U.S. Virgin Islands',\n ['america', 'carribean'],\n 'vi',\n '1340'\n ],\n [\n 'Uganda',\n ['africa'],\n 'ug',\n '256'\n ],\n [\n 'Ukraine',\n ['europe', 'ex-ussr'],\n 'ua',\n '380',\n '+... (..) ... .. ..'\n ],\n [\n 'United Arab Emirates',\n ['middle-east'],\n 'ae',\n '971'\n ],\n [\n 'United Kingdom',\n ['europe', 'european-union'],\n 'gb',\n '44',\n '+.. .... ......'\n ],\n [\n 'USA/Canada/Puerto Rico',\n ['america', 'north-america'],\n 'us/ca',\n '1',\n '+. (...) ...-....'\n ],\n [\n 'Uruguay',\n ['america', 'south-america'],\n 'uy',\n '598'\n ],\n [\n 'Uzbekistan',\n ['asia', 'ex-ussr'],\n 'uz',\n '998'\n ],\n [\n 'Vanuatu',\n ['oceania'],\n 'vu',\n '678'\n ],\n [\n 'Vatican City',\n ['europe'],\n 'va',\n '39',\n '+.. .. .... ....',\n 1\n ],\n [\n 'Venezuela',\n ['america', 'south-america'],\n 've',\n '58'\n ],\n [\n 'Vietnam',\n ['asia'],\n 'vn',\n '84'\n ],\n [\n 'Wallis and Futuna',\n ['oceania'],\n 'wf',\n '681'\n ],\n [\n 'Yemen',\n ['middle-east'],\n 'ye',\n '967'\n ],\n [\n 'Zambia',\n ['africa'],\n 'zm',\n '260'\n ],\n [\n 'Zimbabwe',\n ['africa'],\n 'zw',\n '263'\n ]\n];\n\nlet allCountryCodes = {};\n\nfunction addCountryCode(iso2, dialCode, priority) {\n if (!(dialCode in allCountryCodes)) {\n allCountryCodes[dialCode] = [];\n }\n const index = priority || 0;\n allCountryCodes[dialCode][index] = iso2;\n};\n\nconst allCountries = [].concat(...rawAllCountries.map((country) => {\n const countryItem = {\n name: country[0],\n regions: country[1],\n iso2: country[2],\n dialCode: country[3],\n format: country[4] || undefined,\n priority: country[5] || 0,\n hasAreaCodes: country[6] ? true : false,\n };\n\n const areaItems = [];\n\n country[6] && country[6].map((areaCode) => {\n const areaItem = {...countryItem};\n areaItem.regions = country[1];\n areaItem.dialCode = country[3] + areaCode;\n areaItem.isAreaCode = true;\n\n areaItems.push(areaItem);\n\n addCountryCode(country[2], areaItem.dialCode);\n });\n\n addCountryCode(\n countryItem.iso2,\n countryItem.dialCode,\n countryItem.hasAreaCodes\n );\n\n return (areaItems.length > 0) ? [countryItem, ...areaItems] : [countryItem];\n}));\n\nfunction renderCountryOptions (allCountries) {\n let countries = allCountries;\n const options = countries.map((country) => {\n const dialCode = `+${country.dialCode}`;\n return (\n
\n )\n });\n return options;\n}\n\nexport const countryOptionsForSelect = renderCountryOptions(allCountries);\n","import superagent from \"superagent\"\nimport { API_V2_URL } from \"../../base\"\nimport md5 from \"js-md5\"\n\nexport async function requestSMSCode(phoneNumber, userToken, languageCode) {\n const URL = `${API_V2_URL}phone_verifications/requests`\n const tokenAuth = `Token token=${userToken}`\n\n const res = await superagent\n .post(URL)\n .set(\"Authorization\", tokenAuth)\n .send({\n phone_number: phoneNumber,\n unique_identifier: md5(userToken),\n language: languageCode,\n })\n return res.body\n}\n\nexport async function verifySMSCode(phoneNumber, code, userToken) {\n const URL = `${API_V2_URL}phone_verifications/verifications`\n const tokenAuth = `Token token=${userToken}`\n\n const res = await superagent.post(URL).set(\"Authorization\", tokenAuth).send({\n phone_number: phoneNumber,\n code: code,\n })\n return res.body\n}\n","import React, { useState, useEffect } from \"react\"\nimport { countryOptionsForSelect } from \"../../../constants/CountryPhoneData\"\nimport { getUserDetails, updatePhone } from \"../../../apis/UserSessionAPI\"\nimport * as PhoneNumberVerificationAPI from \"../../../apis/External/PhoneNumberVerification\"\n\nconst recaptchaContainerId = \"recaptcha-container\"\n\nfunction formatError(ok = false, type = \"\", message = \"\") {\n return {\n ok: ok,\n type: type,\n message: message,\n }\n}\n\nexport default function PhoneDetailsForm(props) {\n // -------------------------------------\n // Props destructuring\n // -------------------------------------\n\n const { state, setState, userToken } = props\n\n // -------------------------------------\n // Hooks (e.g. useState, useMemo ...)\n // -------------------------------------\n\n const [waitingForConfirmation, setWaitingForConfirmation] = useState(false)\n\n // -------------------------------------\n // Effects\n // -------------------------------------\n\n useEffect(() => {\n async function doGetUserDetails() {\n if (userToken) {\n const user = await getUserDetails(userToken)\n if (\"phone\" in user) {\n const { phone } = user\n setState({\n ...state,\n isVerificationCompOpen: false,\n isNumberLoaded: true,\n number: phone.number,\n countryCode: phone.country_code,\n countryPrefix: phone.country_prefix,\n isVerified: phone.verified,\n renderPhoneConfirmationHelp: false,\n })\n } else {\n setState({\n ...state,\n isVerificationCompOpen: true,\n isNumberLoaded: true,\n })\n }\n }\n }\n doGetUserDetails()\n }, [])\n\n useEffect(() => {\n if (waitingForConfirmation) {\n let timer = setTimeout(() => {\n setState({ ...state, renderPhoneConfirmationHelp: true })\n }, 8000)\n return () => {\n clearTimeout(timer)\n }\n }\n }, [waitingForConfirmation])\n\n // -------------------------------------\n // Component functions\n // -------------------------------------\n\n function handleInputChange(event) {\n setState({\n ...state,\n [event.target.name]: event.target.value,\n })\n }\n\n function getPhoneInfo(isVerified) {\n return {\n country_code: state.countryCode,\n country_prefix: state.countryPrefix,\n number: state.newNumber,\n verified: isVerified,\n }\n }\n\n async function handleVerification(event) {\n event.preventDefault()\n\n if (!state.newNumber || !state.countryCode) {\n setState({\n ...state,\n error: formatError(\n false,\n \"sendingSMS\",\n I18n.t(\"cart_summary.phone_verification_check_number\")\n ),\n })\n\n return\n }\n\n setState({ ...state, isSendingSms: true })\n const completePhoneNumber = state.countryPrefix + state.newNumber\n\n try {\n await updatePhone(getPhoneInfo(false), userToken)\n\n await PhoneNumberVerificationAPI.requestSMSCode(\n completePhoneNumber,\n userToken,\n state.countryCode\n )\n\n setState({ ...state, isSendingSms: false })\n setWaitingForConfirmation(true)\n } catch (error) {\n let errorMessage\n if (error === \"taken\") {\n errorMessage = formatError(\n false,\n \"sendingSMS\",\n I18n.t(\"cart_summary.phone_exists_error\")\n )\n } else {\n errorMessage = formatError(\n false,\n \"sendingSMS\",\n I18n.t(\"cart_summary.phone_error\")\n )\n }\n setState({\n ...state,\n isSendingSms: false,\n error: errorMessage,\n })\n }\n }\n\n async function handleConfirmation(e) {\n e.preventDefault()\n if (!state.code) {\n setState({\n ...state,\n error: formatError(\n false,\n \"codeConfirmation\",\n I18n.t(\"cart_summary.missing_phone_code\")\n ),\n })\n return\n }\n\n const completePhoneNumber = state.countryPrefix + state.newNumber\n\n setState({ ...state, isConfirmingCode: true })\n\n // Verify sms code input\n try {\n await PhoneNumberVerificationAPI.verifySMSCode(\n completePhoneNumber,\n state.code,\n userToken\n )\n // SUCCESS: phone verified, update on backend\n const updateRes = await updatePhone(getPhoneInfo(true), userToken)\n\n setState({\n ...state,\n isConfirmingCode: false,\n error: formatError(true, \"\", \"\"),\n needVerification: false,\n number: updateRes.number,\n countryPrefix: updateRes.country_prefix,\n isVerified: updateRes.verified,\n })\n setWaitingForConfirmation(false)\n } catch (error) {\n setState({\n ...state,\n error: formatError(\n false,\n \"codeConfirmation\",\n I18n.t(\"cart_summary.phone_confirmation_code_alert\")\n ),\n isConfirmingCode: false,\n })\n }\n }\n\n function toggleVerification() {\n setState({\n ...state,\n needVerification: !state.needVerification,\n needToModify: true,\n })\n }\n\n function backToVerification() {\n setState({\n ...state,\n needVerification: true,\n error: formatError(true, \"\", \"\"),\n })\n setWaitingForConfirmation(false)\n }\n\n function renderPhoneVerification() {\n return (\n
\n
{I18n.t(\"cart_summary.phone_title\")}
\n
\n {I18n.t(\"cart_summary.phone_verification_info\")}{\" \"}\n {state.needToModify && (\n \n {I18n.t(\"cart_summary.back_from_modify\")}\n \n )}\n
\n
\n
\n )\n }\n\n function renderPhoneConfirmation() {\n return (\n
\n
{I18n.t(\"cart_summary.phone_title\")}
\n
\n {I18n.t(\"cart_summary.phone_code_info\")}{\" \"}\n {`${state.countryPrefix} ${state.newNumber}`}.\n
\n
\n {!state.error.ok && state.error.type === \"codeConfirmation\" && (\n
\n
\n
{state.error.message}
\n
\n
\n )}\n {state.renderPhoneConfirmationHelp && (\n
\n {I18n.t(\"cart_summary.phone_code_issues\")}.{\" \"}\n \n {I18n.t(\"cart_summary.phone_code_issues_send_again\")}\n \n
\n )}\n
\n )\n }\n\n // -------------------------------------\n // Component local variables\n // -------------------------------------\n\n const {\n isNumberLoaded,\n countryPrefix,\n number,\n isVerified,\n needVerification,\n needToModify,\n } = state\n if (!isNumberLoaded) {\n return (\n
\n
{I18n.t(\"cart_summary.phone_title\")}
\n
{I18n.t(\"cart_summary.phone_loading\")}
\n
\n )\n }\n\n // -------------------------------------\n\n return (\n
\n {isNumberLoaded && number && !needVerification ? (\n
\n
{I18n.t(\"cart_summary.phone_title\")}
\n
\n {isVerified\n ? I18n.t(\"cart_summary.phone_verified_info\")\n : I18n.t(\"cart_summary.phone_not_verified_info\")}{\" \"}\n \n {I18n.t(\"cart_summary.modify_phone\")}\n \n
\n {!isVerified && (\n
\n
\n
\n {I18n.t(\"cart_summary.phone_not_verified_alert\")}\n
\n
\n
\n )}\n
\n {`${countryPrefix} ${number}`}{\" \"}\n \n {isVerified ? \"verificato\" : \"non verificato\"}\n \n
\n {!isVerified && (\n
\n )}\n
\n ) : !waitingForConfirmation ? (\n renderPhoneVerification()\n ) : (\n renderPhoneConfirmation()\n )}\n
\n
\n )\n}\n","import React from \"react\"\n\nexport default function OrderPreferencesForm(props) {\n // -------------------------------------\n // Props destructuring\n // -------------------------------------\n\n const { state, setState } = props\n\n // -------------------------------------\n // Hooks (e.g. useState, useMemo ...)\n // -------------------------------------\n\n // -------------------------------------\n // Effects\n // -------------------------------------\n\n // -------------------------------------\n // Component functions\n // -------------------------------------\n\n function handleInputChange(event) {\n const target = event.target\n const value = target.type === \"checkbox\" ? target.checked : target.value\n const name = target.name\n\n setState({\n ...state,\n [name]: value,\n })\n }\n\n // -------------------------------------\n // Component local variables\n // -------------------------------------\n\n // -------------------------------------\n\n return (\n
\n
{I18n.t(\"requests\")}
\n
\n
\n )\n}\n","import superagent from \"superagent\";\nimport { API_V2_URL } from \"./base\";\n\nexport function getTakeAwaySlots(venueId, latitude, longitude) {\n const URL = `${API_V2_URL}venues/${venueId}/available_take_away_slots`;\n const time = new Date();\n\n return new Promise((resolve, reject) => {\n superagent\n .get(URL)\n .query({latitude: latitude, longitude: longitude, time: time})\n .set(\"Accept\", \"application/json\")\n .end((error, res) => {\n error ? reject(error) : resolve(res.body.result);\n });\n });\n}\n","import React, { Fragment, useState, useEffect, useRef } from \"react\"\n\nimport UserSessionForm from \"../UserSessionForm/UserSessionForm\"\nimport PlaceOrderButton from \"./components/forms/PlaceOrderButton\"\nimport DeliveryAddressForm from \"./components/forms/DeliveryAddressForm\"\nimport DeliveryTimeSlotForm from \"./components/forms/DeliveryTimeSlotForm\"\nimport TakeAwayTimeSlotForm from \"./components/forms/TakeAwayTimeSlotForm\"\nimport PaymentDetailsForm from \"./components/forms/payment/PaymentDetailsForm\"\nimport BillingDetailsForm from \"./components/forms/BillingDetailsForm\"\nimport PhoneDetailsForm from \"./components/forms/PhoneDetailsForm\"\nimport OrderPreferencesForm from \"./components/forms/OrderPreferencesForm\"\nimport CurrentUserStore from \"../stores/CurrentUserStore\"\nimport FluxAuthenticationActions from \"../actions/FluxAuthenticationActions\"\nimport AlertModal from \"../ui-components/AlertModal\"\nimport ServicesCart from \"../CartContainer/components/ServicesCart\"\n\nimport CartStateStore, {\n CHANGE_STORE,\n getCart,\n PLACE_ORDER,\n RESET_PAYMENT_INFO,\n UPDATE_DELIVERY_DETAILS,\n UPDATE_PAYMENT_INFO,\n useCartStateStore,\n} from \"../stores/CartStateStore\"\nimport getTarget from \"../utils/getTarget\"\nimport BrowserLocationHelper from \"../utils/browser_location_helper\"\nimport { getFromLocalStorage } from \"../utils/localStorage\"\nimport { getTakeAwaySlots } from \"../apis/TakeAwaySlots\"\nimport { ORDER_MAX_CHANGE_THRESHOLD } from \"../utils/config\"\n\nimport { CreateOrder } from \"../apis/OrdersAPI\"\n\nimport style from \"./style.module\"\n\nfunction _CheckoutApp(props) {\n // -------------------------------------\n // Props destructuring\n // -------------------------------------\n\n const {\n user_session_token,\n current_user,\n venue,\n delivery_address,\n deliverySlots,\n createOrderAPIURL,\n stripe_key,\n available_coupons,\n venue_accepts_stripe,\n venue_accepts_cash,\n show_stripe_method,\n billing_details,\n } = props\n\n // -------------------------------------\n // Hooks (e.g. useState, useMemo ...)\n // -------------------------------------\n\n const [state, setState] = useState({\n current_user: current_user,\n disabled: false,\n errors: {},\n errorModalText: null,\n timeSlotIndex: null,\n user_session_token: user_session_token,\n stripe_payment_intent_id: null,\n isTakeAway: false,\n takeAwayTimeSlots: null,\n selectedPickingTime: null,\n takeAwayTimeSlot: \"\",\n verifiedCountryPrefix: \"\",\n verifiedPhoneNumber: \"\",\n })\n const disableTimer = useRef(null)\n const [cartState, dispatchCartState] = useCartStateStore()\n\n const [deliveryAddressState, setDeliveryAddressState] = useState({\n street_name: delivery_address.street_name || \"\",\n street_number: delivery_address.street_number || \"\",\n city: delivery_address.city || \"\",\n postal_code: delivery_address.postal_code || \"\",\n latitude: delivery_address.latitude || \"\",\n longitude: delivery_address.longitude,\n phone: delivery_address.phone || \"\",\n phone_confirmation: delivery_address.phone_confirmation || \"\",\n country_prefix: delivery_address.country_prefix || \"+39\",\n country_code: delivery_address.country_code || \"it\",\n delivery_notes: delivery_address.delivery_notes || \"\",\n restricted_traffic_area: delivery_address.restricted_traffic_area === true,\n }) // TODO: refactor default state\n\n const [phoneDetailsState, setPhoneDetailsState] = useState({\n isNumberLoaded: false,\n needVerification: false,\n needToModify: false,\n number: \"\",\n newNumber: \"\",\n code: \"\",\n countryCode: \"IT\",\n countryPrefix: \"+39\",\n isVerified: false,\n recaptchaVerifying: false,\n error: {\n ok: true,\n type: \"\",\n message: \"\",\n },\n isSendingSms: false,\n isConfirmingCode: false,\n }) // TODO: refactor default state\n\n const [billingDetailsState, setBillingDetailsState] = useState({\n business_name: billing_details.business_name,\n business_address: billing_details.business_address,\n business_invoice_code: billing_details.business_invoice_code,\n vat_code: billing_details.vat_code,\n tax_code: billing_details.tax_code,\n request_invoice: billing_details.request_invoice,\n }) // TODO: refactor default state\n\n const [OrderPreferencesState, setOrderPreferencesState] = useState({\n baby_sleeping: false,\n order_modifications: \"\",\n })\n\n // -------------------------------------\n // Effects\n // -------------------------------------\n\n useEffect(() => {\n CurrentUserStore.addChangeListener(handleCurrentUserStoreChange)\n\n initializeTakeAwaySlots()\n\n dispatchCartState({ type: CHANGE_STORE, payload: venue })\n\n return () => {\n CurrentUserStore.removeChangeListener(handleCurrentUserStoreChange)\n\n clearInterval(disableTimer.current)\n }\n }, [])\n\n // -------------------------------------\n // Component functions\n // -------------------------------------\n\n function handleCurrentUserStoreChange() {\n const user = CurrentUserStore.getUser()\n\n // @todo: remove this hack. If a user is not logged in we should redirect to the sign_in page instead of the checkout app\n // and when the user signs in so we should redirect to the CheckoutApp\n // this could simplify the logic in Checkout app\n // this workaround is here to let the navbar refresh and display the state correctly once the user is logged in\n BrowserLocationHelper.ReloadPage()\n\n setState({\n ...state,\n current_user: user,\n user_session_token:\n user && user.user_session ? user.user_session.token : null,\n })\n }\n\n async function initializeTakeAwaySlots() {\n // If is a takeaway order get takeaway slots and add them to the state\n if (JSON.parse(getFromLocalStorage(\"take_away\")) === true) {\n const { latitude, longitude } = delivery_address\n const venueId = venue && venue.id\n const time = new Date()\n const takeAwaySlots = await getTakeAwaySlots(\n venueId,\n latitude,\n longitude,\n time\n )\n setState({ ...state, isTakeAway: true, takeAwayTimeSlots: takeAwaySlots })\n }\n }\n\n function handleInputChange(event) {\n setState({ ...state, [event.target.name]: event.target.value })\n }\n\n function handleTimeSlotIndexChanged(index) {\n if (!index) return\n\n const slots = deliverySlots\n\n const slot = slots[index]\n\n dispatchCartState({\n type: UPDATE_DELIVERY_DETAILS,\n payload: { price: slot?.price_cents || 0, errors: [] },\n })\n setState({ ...state, timeSlotIndex: index })\n }\n\n function handleTakeAwayTimeSlotChange(e) {\n const target = getTarget(e)\n setState({\n ...state,\n selectedPickingTime: target.value,\n takeAwayTimeSlot: target.options[target.selectedIndex].dataset.timeSlot,\n })\n }\n\n function getSelectedStartTime() {\n const deliverySlot = getSelectedTimeSlot()\n\n return deliverySlot ? deliverySlot.start_time : null\n }\n\n function getSelectedTimeSlot() {\n const index = state.timeSlotIndex\n const slots = deliverySlots\n\n return index && slots[index]\n }\n\n function getUserSessionToken() {\n return state.user_session_token\n }\n\n function getOrderHash() {\n const isTakeAway = state.isTakeAway\n const delivery_address = deliveryAddressState\n const billing_details = billingDetailsState\n const phoneDetailsForm = phoneDetailsState\n const deliverySlot = getSelectedTimeSlot()\n const payment_details = cartState.paymentMethod\n const order_preferences = OrderPreferencesState\n const coupon_code = Object.keys(getCart(cartState).coupons || {})[0]\n const timeSlot = deliverySlot\n ? `${deliverySlot.start_time}-${deliverySlot.end_time}`\n : isTakeAway\n ? state.takeAwayTimeSlot\n : null\n const proposed_picking_time = isTakeAway ? state.selectedPickingTime : null\n const vehicleType = deliverySlot ? deliverySlot.vehicle_type : null\n const orderType =\n deliverySlot && deliverySlot.vehicle_type === \"venue\"\n ? \"venue\"\n : isTakeAway\n ? \"take_away\"\n : null\n\n let order = {\n phone_attributes: {\n country_code: phoneDetailsForm.countryCode,\n country_prefix: phoneDetailsForm.countryPrefix,\n number: phoneDetailsForm.number,\n verified: phoneDetailsForm.isVerified,\n },\n latitude: delivery_address.latitude,\n longitude: delivery_address.longitude,\n street_name: delivery_address.street_name,\n street_number: delivery_address.street_number,\n postal_code: delivery_address.postal_code,\n city: delivery_address.city,\n delivery_notes: delivery_address.delivery_notes,\n restricted_traffic_area: delivery_address.restricted_traffic_area,\n baby_sleeping: order_preferences && order_preferences.baby_sleeping,\n order_modifications:\n order_preferences && order_preferences.order_modifications,\n line_items: getCart(cartState).products,\n venue_id: venue.id,\n time_slot: timeSlot,\n proposed_picking_time: proposed_picking_time,\n vehicle_type: vehicleType,\n coupon_code: coupon_code,\n payment_method: payment_details.type,\n request_invoice: billing_details.request_invoice,\n locale: I18n.locale,\n metadata: { source: \"website\" },\n }\n\n if (billing_details.request_invoice) {\n order.business_name = billing_details.business_name\n order.business_address = billing_details.business_address\n order.business_invoice_code = billing_details.business_invoice_code\n order.vat_code = billing_details.vat_code\n order.tax_code = billing_details.tax_code\n }\n\n switch (payment_details.type) {\n case \"cash\":\n order.cash_amount =\n parseFloat(payment_details.options.cash_amount).toFixed(2) || 0\n break\n case \"stripe\":\n order.payment_attributes = {\n payment_method: payment_details.options.method,\n flow_mode: \"async\",\n }\n break\n case \"satispay\":\n order.payment_attributes = {\n flow_mode: \"async\",\n }\n break\n }\n\n return { order: order, order_type: orderType }\n }\n\n function isOrderFormValid() {\n const phoneDetails = phoneDetailsState\n\n const payment_details = cartState.paymentMethod\n\n if (!phoneDetails || !phoneDetails.isVerified) {\n setState({\n ...state,\n errorModalText: I18n.t(\"cart_summary.phone_required_verified\"),\n })\n return false\n }\n\n if (!deliveryAddressState.street_number && !state.isTakeAway) {\n setState({\n ...state,\n errorModalText: I18n.t(\"cart_summary.street_number_alert\"),\n })\n return false\n }\n\n // ADD TakeAwaySlot validation\n\n // TODO: Move validations away from here\n switch (payment_details.type) {\n case \"cash\":\n const cash_amount = payment_details.options.cash_amount\n\n if (state.isTakeAway === true) {\n break\n }\n\n if (!cash_amount || cash_amount === \"\") {\n setState({\n ...state,\n errorModalText: I18n.t(\"cart_summary.cash_value_alert\"),\n })\n return false\n } else {\n // check amount > cartTotal\n const amount = parseFloat(cash_amount).toFixed(2) * 100 || 0\n let discountedTotal = getCart(cartState).total\n if (amount < discountedTotal) {\n setState({\n ...state,\n errorModalText: I18n.t(\"cart_summary.cash_value_too_low_alert\"),\n })\n return false\n }\n // check amount - cart total < threshold\n let deliveryPrice = cartState.deliveryDetails?.price || 0\n let order_max_change = ORDER_MAX_CHANGE_THRESHOLD * 100\n if (amount - discountedTotal - deliveryPrice > order_max_change) {\n let maxAmount = discountedTotal + deliveryPrice + order_max_change\n setState({\n ...state,\n errorModalText: I18n.t(\"cart_summary.change_too_high_alert\", {\n max_value: (maxAmount / 100.0).toFixed(2),\n change_value: ORDER_MAX_CHANGE_THRESHOLD,\n }),\n })\n return false\n }\n }\n\n break\n\n case \"stripe\":\n if (!payment_details.options.method) {\n setState({\n ...state,\n errorModalText: \"Devi aggiungere o scegliere una carta di credito.\",\n })\n return false\n }\n break\n case \"satispay\":\n // No validation needed\n break\n\n default:\n setState({ ...state, errorModalText: \"Metodo di pagamento non valido\" })\n return false\n }\n return true\n }\n\n async function placeOrder(e) {\n e.preventDefault && e.preventDefault()\n\n if (!isOrderFormValid()) {\n return\n }\n\n try {\n dispatchCartState({\n type: UPDATE_PAYMENT_INFO,\n payload: { createdAt: new Date().toISOString() },\n })\n setState({ ...state, disabled: true })\n\n const order = await CreateOrder(getOrderHash(), getUserSessionToken())\n\n // order is created, async payment is now processing\n handleOrderCreated(order)\n } catch (error) {\n // remove the payment in progress. The user is aware that something went wrong\n handleOrderCreationError(error)\n }\n }\n\n function handleOrderCreated(order) {\n if (order?.payment?.method_name === \"cash\") {\n // 'cash' has no more steps, the order is fine -> cleanup\n dispatchCartState({\n type: PLACE_ORDER,\n payload: { venue_id: order.venue.id, order: order },\n })\n }\n\n // Wait 2 seconds to be sure the call to external analytics services\n setTimeout(function () {\n BrowserLocationHelper.ChangeURL(\"/\" + I18n.locale + \"/orders/\" + order.id)\n }, 2000)\n }\n\n function handleOrderCreationError(error) {\n dispatchCartState({\n type: RESET_PAYMENT_INFO,\n payload: {},\n })\n\n setState({ ...state, disabled: false })\n\n if (error.status === 401) {\n FluxAuthenticationActions.unauthorized()\n return\n }\n\n const {\n response: { body },\n } = error\n\n if (body) {\n const { full_error_messages, detailed_errors } = body\n let message = I18n.t(\"cart_summary.missing_fields_alert\")\n\n if (full_error_messages && full_error_messages.length > 0) {\n message = full_error_messages.join(\", \")\n }\n\n setState({\n ...state,\n errorModalText: message,\n errors: detailed_errors,\n disabled: false,\n })\n } else {\n this.setState({\n ...state,\n errorModalText: \"Errore\",\n errors: \"Errore generico\",\n disabled: false,\n })\n }\n }\n\n function isCurrentUserLogged() {\n return state.current_user !== null\n }\n\n function renderCheckoutForm() {\n return (\n
\n )\n }\n\n function renderUserSessionForm() {\n return (\n
\n \n
\n )\n }\n\n // -------------------------------------\n // Component local variables\n // -------------------------------------\n\n // -------------------------------------\n\n return (\n
\n \n
{I18n.t(\"pages.orders.new.title\")}
\n
\n
\n
setState({ ...state, errorModalText: null })}\n />\n\n {isCurrentUserLogged()\n ? renderCheckoutForm()\n : renderUserSessionForm()}\n \n
\n
\n \n
{I18n.t(\"pages.orders.new.title_summary\")}
\n
\n \n
\n
\n \n )\n}\n\nexport default function CheckoutApp(props) {\n return (\n
\n <_CheckoutApp {...props}>\n \n )\n}\n","export default function getTarget(evt) {\n let targ;\n\n if (!evt) {\n evt = window.event;\n }\n\n if (evt.target) {\n targ = evt.target;\n } else if (evt.srcElement) {\n targ = evt.srcElement;\n }\n\n if (targ.nodeType == 3) {\n targ = targ.parentNode;\n }\n\n return targ;\n}\n","import React from \"react\"\n\nimport style from \"./index.module.sass\"\n\n// ----------------------------------------------------------------------------\n\nconst COLORS = {BLUE: \"blue\", RED: \"red\", YELLOW: \"yellow\", GREY: \"grey\"}\n\nfunction BubbleCard(props) {\n // -------------------------------------\n // Props destructuring\n // -------------------------------------\n\n const { children, color = COLORS.BLUE } = props\n\n // -------------------------------------\n // Hooks (e.g. useState, useMemo ...)\n // -------------------------------------\n\n // -------------------------------------\n // Effects\n // -------------------------------------\n\n // -------------------------------------\n // Component functions\n // -------------------------------------\n\n // -------------------------------------\n // Component local variables\n // -------------------------------------\n\n let mode = style.blue\n switch (color) {\n case COLORS.RED:\n mode = style.red\n break\n case COLORS.YELLOW:\n mode = style.yellow\n break\n case COLORS.GREY:\n mode = style.grey\n break\n }\n\n // -------------------------------------\n\n return (\n
\n )\n}\n\n// ----------------------------------------------------------------------------\n\nexport default BubbleCard\n","import React, { Fragment } from \"react\"\n\nimport { PAYMENT_STATUS, CASH_METHOD, MODE_TAKE_AWAY } from \"../\"\nimport ItemPrice from \"../../ui-components/ItemPrice\"\n\nimport style from \"./index.module.sass\"\n\n// ----------------------------------------------------------------------------\n\nfunction RecapSection(props) {\n // -------------------------------------\n // Props destructuring\n // -------------------------------------\n\n const { order } = props\n\n // -------------------------------------\n // Hooks (e.g. useState, useMemo ...)\n // -------------------------------------\n\n // -------------------------------------\n // Effects\n // -------------------------------------\n\n // -------------------------------------\n // Component functions\n // -------------------------------------\n\n function localizePaymentDesc() {\n if (order.payment.method_name === CASH_METHOD) {\n return I18n.t(CASH_METHOD)\n }\n\n switch (order.payment?.status) {\n case PAYMENT_STATUS.PREAUTHORIZED:\n return I18n.t(\"pages.orders.show.stripe.preauthorized_payment\")\n case PAYMENT_STATUS.PAID:\n return I18n.t(\"pages.orders.show.payment_desc\", {\n method: I18n.t(order?.payment?.method_name || \"empty\"),\n price: (order?.payment?.paid_amount_cents / 100).toFixed(2),\n defaultValue: \"\",\n })\n case PAYMENT_STATUS.REQUIRES_AUTH:\n return I18n.t(\"pages.orders.show.pending_payment_desc\")\n case PAYMENT_STATUS.EXPIRED:\n case PAYMENT_STATUS.FAILED:\n return I18n.t(\"pages.orders.show.payment_failed_recap\")\n default:\n return \"\"\n }\n }\n\n function renderLineItem(item) {\n return (\n
\n
{item.quantity}\n
\n {item.name}\n {item?.additional_parts?.map((add) => {\n return (\n \n {add.name}\n \n )\n })}\n
\n
\n
\n )\n }\n\n function renderLineItems() {\n if (Array.isArray(order.line_items)) {\n order.line_items.map((el) => {\n return renderLineItem(el)\n })\n } else {\n return Object.keys(order.line_items).map((key) => {\n return renderLineItem(order.line_items[key])\n })\n }\n }\n\n function renderTotalItem(\n title,\n amount,\n originalAmount = null,\n emphasize = false\n ) {\n return (\n
\n {title}\n \n
\n )\n }\n\n function renderInfo(title, text) {\n return (\n
\n )\n }\n\n // -------------------------------------\n // Component local variables\n // -------------------------------------\n\n // -------------------------------------\n\n return (\n
\n {order.takeaway_order && (\n
\n {I18n.t(\"pickup_time\")}
\n {order.proposed_picking_time}
\n \n )}\n\n {!order.takeaway_order && (\n
\n \n {order.mode === MODE_TAKE_AWAY\n ? I18n.t(\"pickup_time\")\n : I18n.t(\"delivery_time\")}\n
\n \n {order.mode === MODE_TAKE_AWAY\n ? order.start_time\n : `${order.start_time}/${order.end_time}`}\n
\n \n )}\n\n {order?.line_items && renderLineItems()}\n
\n {renderTotalItem(I18n.t(\"subtotal\"), order.goods_price_cents)}\n {order.mode !== MODE_TAKE_AWAY &&\n renderTotalItem(\n order.mode === \"venue\"\n ? I18n.t(\"delivery_marketplace\")\n : I18n.t(\"delivery_racer\"),\n order.delivery_price_cents\n )}\n {!!order.goods_discount_price_cents &&\n renderTotalItem(\n I18n.t(\"discount_coupon\"),\n -order.goods_discount_price_cents\n )}\n {renderTotalItem(\n I18n.t(\"total\"),\n (order.discounted_price_cents || order.total_price_cents),\n null,\n true\n )}\n\n
\n {order?.venue?.name &&\n renderInfo(I18n.t(\"restaurant\"), order.venue?.name)}\n {order?.complete_address &&\n renderInfo(I18n.t(\"address\"), order.complete_address)}\n {order?.phone && renderInfo(I18n.t(\"phone\"), order.phone)}\n {order?.delivery_notes &&\n renderInfo(\n I18n.t(\"pages.orders.show.additional_notes\"),\n order.delivery_notes\n )}\n\n {order?.request_invoice && order?.billing_address && (\n
\n \n {renderInfo(\n I18n.t(\"cart_summary.business_name\"),\n order?.billing_address?.business_name\n )}\n {renderInfo(\n I18n.t(\"cart_summary.business_address\"),\n order?.billing_address?.business_address\n )}\n {renderInfo(\n I18n.t(\"cart_summary.invoice_code\"),\n order?.billing_address?.business_invoice_code\n )}\n {renderInfo(\n I18n.t(\"cart_summary.vat_code\"),\n order?.billing_address?.vat_code\n )}\n {renderInfo(\n I18n.t(\"cart_summary.tax_code\"),\n order?.billing_address?.tax_code\n )}\n \n )}\n\n {order?.payment?.method_name && (\n
\n \n {renderInfo(\n I18n.t(\"pages.orders.show.payment\"),\n localizePaymentDesc()\n )}\n \n )}\n\n {order?.delivery_receipt && (\n
\n {I18n.t(\"pages.orders.show.download_receipt\")}\n \n )}\n\n
\n
\n )\n}\n\n// ----------------------------------------------------------------------------\n\nexport default RecapSection\n","import React from \"react\"\nimport Button from \"react-bootstrap/lib/Button\"\n\nimport BubbleCard from \"../../ui-components/BubbleCard\"\n\nimport style from \"../index.module.sass\"\n\n// ----------------------------------------------------------------------------\n\nfunction CancelledCard(props) {\n // -------------------------------------\n // Props destructuring\n // -------------------------------------\n\n // -------------------------------------\n // Hooks (e.g. useState, useMemo ...)\n // -------------------------------------\n\n // -------------------------------------\n // Effects\n // -------------------------------------\n\n // -------------------------------------\n // Component functions\n // -------------------------------------\n\n // -------------------------------------\n // Component local variables\n // -------------------------------------\n\n // -------------------------------------\n\n return (\n
\n
\n \n
\n {I18n.t(\"pages.orders.show.order_refused_card_title\")}\n
\n
\n {I18n.t(\"pages.orders.show.order_refused_card_desc\")}\n
\n
\n
\n \n
\n )\n}\n\n// ----------------------------------------------------------------------------\n\nexport default CancelledCard\n","import React, { useState, useEffect, useRef } from \"react\"\nimport Button from \"react-bootstrap/lib/Button\"\n\nimport BubbleCard from \"../../ui-components/BubbleCard\"\nimport BrowserLocationHelper from \"../../utils/browser_location_helper\"\n\nimport style from \"../index.module.sass\"\n\n// ----------------------------------------------------------------------------\n\nconst MAX_EXPIRES_TIME = 300000\n\nfunction PendingPaymentCard(props) {\n // -------------------------------------\n // Props destructuring\n // -------------------------------------\n\n const { expiresAt } = props\n\n // -------------------------------------\n // Hooks (e.g. useState, useMemo ...)\n // -------------------------------------\n\n const [deadline, setDeadline] = useState(null)\n const timer = useRef(null)\n\n // -------------------------------------\n // Effects\n // -------------------------------------\n\n useEffect(() => {\n if (!expiresAt) {\n return\n }\n timer.current = setInterval(() => {\n setDeadline(computeMinutes())\n }, 1000)\n return () => {\n clearInterval(timer)\n }\n })\n\n // -------------------------------------\n // Component functions\n // -------------------------------------\n\n function computeMinutes() {\n const now = new Date()\n const deadline = new Date(expiresAt)\n const diff = deadline - now\n\n if (diff <= 0 || diff > MAX_EXPIRES_TIME) {\n clearInterval(timer.current)\n return null\n }\n\n const minutes = Math.floor(diff / 1000 / 60)\n const seconds = Math.floor(diff / 1000 % 60)\n const time = `${minutes}:${seconds}`\n\n return time\n }\n\n function handleComplete() {\n const path = `${window.location}/payment`\n BrowserLocationHelper.ChangeURL(path)\n }\n\n // -------------------------------------\n // Component local variables\n // -------------------------------------\n\n // -------------------------------------\n\n return (\n
\n
\n \n
\n {I18n.t(\"pages.orders.show.pending_payment_warn_1\")}\n
\n {deadline && (\n
\n {I18n.t(\"pages.orders.show.pending_payment_warn_2\", {\n minutes: deadline,\n })}\n
\n )}\n
\n
\n \n
\n )\n}\n\n// ----------------------------------------------------------------------------\n\nexport default PendingPaymentCard\n","import React from \"react\"\nimport Button from \"react-bootstrap/lib/Button\"\n\nimport BubbleCard from \"../../ui-components/BubbleCard\"\n\nimport style from \"../index.module.sass\"\n\n// ----------------------------------------------------------------------------\n\nfunction CancelledCard(props) {\n // -------------------------------------\n // Props destructuring\n // -------------------------------------\n\n // -------------------------------------\n // Hooks (e.g. useState, useMemo ...)\n // -------------------------------------\n\n // -------------------------------------\n // Effects\n // -------------------------------------\n\n // -------------------------------------\n // Component functions\n // -------------------------------------\n\n // -------------------------------------\n // Component local variables\n // -------------------------------------\n\n // -------------------------------------\n\n return (\n
\n
\n \n
\n {I18n.t(\"pages.orders.show.payment_failed_warn\")}\n
\n
\n {I18n.t(\"pages.orders.show.order_refused_card_desc\")}\n
\n
\n
\n \n
\n )\n}\n\n// ----------------------------------------------------------------------------\n\nexport default CancelledCard\n","import React, { useState } from \"react\"\n\nimport style from \"./index.module.sass\"\n\n// ----------------------------------------------------------------------------\n\nfunction Stars(props) {\n // -------------------------------------\n // Props destructuring\n // -------------------------------------\n\n const { readOnly = false, currentVote, setCurrentVote = () => {} } = props\n\n // -------------------------------------\n // Hooks (e.g. useState, useMemo ...)\n // -------------------------------------\n\n // -------------------------------------\n // Effects\n // -------------------------------------\n\n // -------------------------------------\n // Component functions\n // -------------------------------------\n\n function handleStarClick(index) {\n return (e) => {\n if (!readOnly) {\n setCurrentVote(index + 1)\n }\n e.preventDefault()\n }\n }\n\n function renderStars(starsFloat) {\n let stars = Math.round(starsFloat)\n let filled = Array(stars).fill(true)\n let empty = Array(5 - stars).fill(false)\n\n return filled.concat(empty).map((el, index) => {\n return (\n
\n )\n })\n }\n\n // -------------------------------------\n // Component local variables\n // -------------------------------------\n\n // -------------------------------------\n\n return (\n
\n {renderStars(currentVote || 0)}\n
\n )\n}\n\n// ----------------------------------------------------------------------------\n\nexport default Stars\n","import React from \"react\"\nimport Modal from \"react-bootstrap/lib/Modal\"\n\nimport style from \"./index.module.sass\"\n\n// ----------------------------------------------------------------------------\n\nfunction BubbleModal(props) {\n // -------------------------------------\n // Props destructuring\n // -------------------------------------\n\n const { children, color = \"blue\" } = props\n\n // -------------------------------------\n // Hooks (e.g. useState, useMemo ...)\n // -------------------------------------\n\n // -------------------------------------\n // Effects\n // -------------------------------------\n\n // -------------------------------------\n // Component functions\n // -------------------------------------\n\n // -------------------------------------\n // Component local variables\n // -------------------------------------\n\n const mode = color === \"red\" ? \"modal--bubble-red\" : \"modal--bubble-blue\"\n\n // -------------------------------------\n\n return (\n
\n \n\n \n {children}\n \n )\n}\n\n// ----------------------------------------------------------------------------\n\nexport default BubbleModal\n","import superagent from \"superagent\"\nimport { API_V2_URL } from \"../../base\"\n\nexport async function orderRating(orderId, ratings, userToken) {\n const URL = `${API_V2_URL}orders/${orderId}/rating`\n const tokenAuth = `Token token=${userToken}`\n\n const res = await superagent\n .post(URL)\n .set(\"Accept\", \"application/json\")\n .set(\"Authorization\", tokenAuth)\n .send({\n notes: ratings.other,\n racer_punctuality: ratings.punctuality,\n food_temperature: null, // TODO: remove, kept for compatibility\n racer_courtesy: ratings.politeness,\n food_integrity: ratings.product_integrity,\n })\n return res.body\n}\n","import React, { useState, Fragment } from \"react\"\nimport Button from \"react-bootstrap/lib/Button\"\nimport BubbleModal from \"../../../ui-components/BubbleModal\"\n\nimport Stars from \"../Stars\"\nimport * as api from \"../../../apis/Authenticated/Orders/index.js\"\n\nimport style from \"./index.module.sass\"\n\n// ----------------------------------------------------------------------------\n\nconst RATING_KEYS = [\"punctuality\", \"politeness\", \"product_integrity\", \"other\"]\n\nconst ICONS = [\"fa-clock\", \"fa-laugh-wink\", \"fa-bags-shopping\", \"fa-comments\"]\n\nconst initialRatings = {\n [RATING_KEYS[0]]: undefined,\n [RATING_KEYS[1]]: undefined,\n [RATING_KEYS[2]]: undefined,\n [RATING_KEYS[3]]: undefined,\n}\n\nfunction RatingModal(props) {\n // -------------------------------------\n // Props destructuring\n // -------------------------------------\n\n const { order, onHide = () => {}, userToken, ...otherProps } = props\n\n // -------------------------------------\n // Hooks (e.g. useState, useMemo ...)\n // -------------------------------------\n\n const [loading, setLoading] = useState(false)\n const [step, setStep] = useState(0)\n const [ratings, setRatings] = useState(initialRatings)\n\n // -------------------------------------\n // Effects\n // -------------------------------------\n\n // -------------------------------------\n // Component functions\n // -------------------------------------\n\n function handleVote(vote) {\n setRatings({ ...ratings, [RATING_KEYS[step]]: vote })\n }\n\n function handleTextChange(e) {\n setRatings({ ...ratings, [RATING_KEYS[step]]: e.target.value })\n }\n\n async function handleNext() {\n // if there is no vote, do not proceed\n if (!!ratings[RATING_KEYS[step]] || step >= RATING_KEYS.length - 1) {\n if (step >= RATING_KEYS.length - 1) {\n setLoading(true)\n try {\n let res = await api.orderRating(order.id, ratings, userToken)\n if (res) {\n onHide(\"refresh\")\n } else {\n setLoading(false)\n }\n } catch (err) {\n setLoading(false)\n }\n } else {\n setStep(step + 1)\n }\n }\n }\n\n function handleHide() {\n // TODO: improve state\n setStep(0)\n setRatings(initialRatings)\n onHide()\n }\n\n // -------------------------------------\n // Component local variables\n // -------------------------------------\n\n // -------------------------------------\n\n return (\n
\n \n
\n {I18n.t(`pages.order_ratings.new.leave_feedback`)}\n
\n {loading &&
}\n {!loading && (\n
\n \n \n {step + 1}/{RATING_KEYS.length}\n
\n \n {I18n.t(\n `pages.order_ratings.new.steps.${RATING_KEYS[step]}.title`\n )}\n
\n \n {I18n.t(\n `pages.order_ratings.new.steps.${RATING_KEYS[step]}.description`\n )}\n
\n {step < RATING_KEYS.length - 1 && (\n \n )}\n {step >= RATING_KEYS.length - 1 && (\n \n )}\n\n {step < RATING_KEYS.length - 1 && (\n \n )}\n {step >= RATING_KEYS.length - 1 && (\n \n )}\n \n )}\n
\n \n )\n}\n\n// ----------------------------------------------------------------------------\n\nexport default RatingModal\n","import React, { useState, Fragment } from \"react\"\nimport Button from \"react-bootstrap/lib/Button\"\n\nimport BubbleCard from \"../../ui-components/BubbleCard\"\nimport Stars from \"./Stars\"\nimport RatingModal from \"./RatingModal\"\n\nimport style from \"../index.module.sass\"\n\n// ----------------------------------------------------------------------------\n\nfunction RatingCard(props) {\n // -------------------------------------\n // Props destructuring\n // -------------------------------------\n\n const {\n order = {},\n userToken,\n alreadyRated = true,\n canBeRated = false,\n } = props\n\n // -------------------------------------\n // Hooks (e.g. useState, useMemo ...)\n // -------------------------------------\n\n const [showRatingModal, setShowRatingModal] = useState(false)\n\n // -------------------------------------\n // Effects\n // -------------------------------------\n\n // -------------------------------------\n // Component functions\n // -------------------------------------\n\n function handleHide(action) {\n if (action === \"refresh\") {\n window.location.reload()\n } else {\n setShowRatingModal(false)\n }\n }\n\n // -------------------------------------\n // Component local variables\n // -------------------------------------\n\n // -------------------------------------\n\n return (\n
\n
\n \n {alreadyRated && (\n
\n \n {I18n.t(\"pages.orders.show.thanks_for_evaluation\")}\n
\n \n {I18n.t(\"pages.orders.show.average_evaluation\")}\n
\n \n \n )}\n\n {!alreadyRated && canBeRated && (\n
\n \n {I18n.t(\"pages.order_ratings.new.steps.intro.title\", {\n racer_fullname:\n (order && order.racer && order.racer.first_name) || \"\",\n })}\n
\n \n \n )}\n
\n\n \n \n
\n )\n}\n\n// ----------------------------------------------------------------------------\n\nexport default RatingCard\n","import React, { useState } from \"react\"\n\nimport BubbleCard from \"../ui-components/BubbleCard\"\nimport AlertModalWithBody from \"../ui-components/AlertModalWithBody\"\nimport RecapSection from \"./RecapSection\"\nimport CancelledCard from \"./CancelledCard\"\nimport PendingPaymentCard from \"./PendingPaymentCard\"\nimport FailedPaymentCard from \"./FailedPaymentCard\"\nimport RatingCard from \"./RatingCard\"\n\nimport style from \"./index.module.sass\"\n\n// ----------------------------------------------------------------------------\n\n// TODO: move to a const file\nexport const CASH_METHOD = \"cash\"\n\nexport const ORDER_STATUS = {\n PENDING_APPROVAL: \"pending_approval\",\n BRAND_NEW: \"brand_new\",\n PROCESSING: \"processing\",\n ACCEPTED: \"accepted\",\n COMPLETED: \"completed\",\n REJECTED: \"rejected\",\n PICKED_UP: \"picked_up\",\n CREATING: \"creating\",\n PENDING_PAYMENT: \"pending_payment\",\n PAYMENT_FAILED: \"payment_failed\",\n}\n\nexport const PAYMENT_STATUS = {\n PENDING: \"pending\",\n PREAUTHORIZED: \"preauthorized\",\n PAID: \"paid\",\n FAILED: \"failed\",\n REFUNDED: \"refunded\",\n CANCELED: \"canceled\",\n UNKNOWN: \"unknown\",\n REQUIRES_AUTH: \"requires_auth\",\n EXPIRED: \"expired\",\n}\n\nexport const MODE_TAKE_AWAY = \"take_away\"\nconst MODE_VENUE = \"venue\"\n\nfunction OrderRecap(props) {\n // -------------------------------------\n // Props destructuring\n // -------------------------------------\n\n const { order = {}, userToken } = props\n\n // -------------------------------------\n // Hooks (e.g. useState, useMemo ...)\n // -------------------------------------\n\n const [showCovidModal, setShowCovidModal] = useState()\n\n // -------------------------------------\n // Effects\n // -------------------------------------\n\n // -------------------------------------\n // Component functions\n // -------------------------------------\n\n function renderHeader(title, desc, isHTMLDesc = false) {\n return (\n
\n
{title}
\n {isHTMLDesc ? (\n
\n ) : (\n
{desc}
\n )}\n
\n )\n }\n\n function renderWarningCard(body, color) {\n return (\n
\n )\n }\n\n function renderCovidAlert() {\n return (\n
\n
setShowCovidModal(true)}\n >\n \n {` ${I18n.t(\"pages.orders.show.covid.link\")}`}\n
\n
setShowCovidModal(false)}\n onConfirm={() => setShowCovidModal(false)}\n title={I18n.t(\"pages.orders.show.covid.title\")}\n closeLabel={I18n.t(\"close\")}\n isTiny={false}\n >\n \n \n
\n )\n }\n\n // -------------------------------------\n // Component local variables\n // -------------------------------------\n\n let alreadyRated = order.rating && order.rating.average\n let canBeRated = order.accepts_rating == true && !(order.mode === \"take_away\")\n\n // -------------------------------------\n\n switch (order.status) {\n case ORDER_STATUS.PENDING_APPROVAL:\n return (\n
\n {renderHeader(\n I18n.t(\"pages.orders.show.order_pending_approval\"),\n I18n.t(\"pages.orders.show.order_request_received_warning\")\n )}\n \n
\n )\n case ORDER_STATUS.PICKED_UP:\n let description =\n order.mode === MODE_VENUE\n ? I18n.t(\"pages.orders.show.order_picked_up_venue_delivery_html\")\n : I18n.t(\"pages.orders.show.order_picked_up_html\", {\n name: order.racer?.first_name,\n phone: order.racer?.phone_number,\n })\n return (\n
\n {renderHeader(\n I18n.t(\"pages.orders.show.order_picked_up\"),\n description,\n true\n )}\n \n
\n )\n case ORDER_STATUS.COMPLETED:\n return (\n
\n {renderHeader(\n I18n.t(\"pages.orders.show.order_delivered\"),\n I18n.t(\"pages.orders.show.thanks\")\n )}\n {(alreadyRated || (!alreadyRated && canBeRated)) && userToken && (\n \n )}\n \n
\n )\n case ORDER_STATUS.REJECTED:\n if (\n order.payment?.status === PAYMENT_STATUS.EXPIRED ||\n order.payment?.status === PAYMENT_STATUS.FAILED\n ) {\n return (\n
\n {order?.payment?.status === PAYMENT_STATUS.EXPIRED\n ? renderHeader(\n I18n.t(\"pages.orders.show.payment_expired\"),\n I18n.t(\"pages.orders.show.payment_expired_desc\")\n )\n : renderHeader(\n I18n.t(\"pages.orders.show.payment_failed\"),\n I18n.t(\"pages.orders.show.payment_failed_desc\")\n )}\n \n \n
\n )\n } else {\n return (\n
\n {renderHeader(\n I18n.t(\"pages.orders.show.order_refused\"),\n I18n.t(\"pages.orders.show.order_refused_description\")\n )}\n \n \n
\n )\n }\n case ORDER_STATUS.PENDING_PAYMENT:\n return (\n
\n {renderHeader(\n I18n.t(\"pages.orders.show.pending_payment\"),\n I18n.t(\"pages.orders.show.pending_payment_desc\")\n )}\n
\n
\n
\n )\n case ORDER_STATUS.PAYMENT_FAILED:\n return (\n
\n {renderHeader(\n I18n.t(\"pages.orders.show.payment_failed\"),\n I18n.t(\"pages.orders.show.payment_failed_desc\")\n )}\n \n \n
\n )\n case ORDER_STATUS.ACCEPTED:\n return (\n
\n {order.mode === MODE_TAKE_AWAY\n ? renderHeader(\n I18n.t(\"pages.orders.show.order_accepted\"),\n I18n.t(\n \"pages.orders.show.order_accepted_venue_takeaway_description_html\",\n {\n time: order.start_time,\n venue_name: order.venue?.name,\n venue_address: `${order.venue?.address.street_name} ${order.venue?.address.street_number}`,\n }\n ),\n true\n )\n : renderHeader(\n I18n.t(\"pages.orders.show.order_accepted\"),\n I18n.t(\"pages.orders.show.order_accepted_description_html\", {\n name: order.racer?.first_name,\n phone: order.racer?.phone_number || \"--\",\n }),\n true\n )}\n \n
\n )\n case ORDER_STATUS.PROCESSING:\n return (\n
\n {renderHeader(\n I18n.t(\"pages.orders.show.order_request_received\"),\n I18n.t(\"pages.orders.show.order_accepted_description_html\", {\n name: order.racer?.first_name,\n phone: order.racer?.phone_number || \"--\",\n }),\n true\n )}\n {order.mode !== MODE_TAKE_AWAY && renderCovidAlert()}\n {order.needs_phone_verification &&\n renderWarningCard(\n I18n.t(\"pages.orders.show.keep_your_phone_close\"),\n \"yellow\"\n )}\n {order.credit_card &&\n order.payment.status === PAYMENT_STATUS.PREAUTHORIZED &&\n renderWarningCard(\n I18n.t(\"pages.orders.show.stripe.preauthorized_payment\"),\n \"blue\"\n )}\n {order.credit_card &&\n order.payment.status === PAYMENT_STATUS.PAID &&\n renderWarningCard(\n I18n.t(\"pages.orders.show.stripe.paid_payment\", {\n price: order.payment.stripe_paid_amount,\n }),\n \"blue\"\n )}\n \n
\n )\n default:\n // BRAND_NEW\n return (\n
\n {order.mode === MODE_TAKE_AWAY\n ? renderHeader(\n I18n.t(\"pages.orders.show.order_request_takeaway\"),\n I18n.t(\"pages.orders.show.order_request_takeaway_warning\")\n )\n : renderHeader(\n I18n.t(\"pages.orders.show.order_request_received\"),\n I18n.t(\"pages.orders.show.order_request_received_warning\")\n )}\n {order.mode !== MODE_TAKE_AWAY && renderCovidAlert()}\n {order.needs_phone_verification &&\n renderWarningCard(\n I18n.t(\"pages.orders.show.keep_your_phone_close\"),\n \"yellow\"\n )}\n {order.credit_card &&\n order.payment.status === PAYMENT_STATUS.PREAUTHORIZED &&\n renderWarningCard(\n I18n.t(\"pages.orders.show.stripe.preauthorized_payment\"),\n \"blue\"\n )}\n {order.credit_card &&\n order.payment.status === PAYMENT_STATUS.PAID &&\n renderWarningCard(\n I18n.t(\"pages.orders.show.stripe.paid_payment\", {\n price: order.payment.stripe_paid_amount,\n }),\n \"blue\"\n )}\n \n
\n )\n }\n}\n\n// ----------------------------------------------------------------------------\n\nexport default OrderRecap\n","import React from 'react'\n\nfunction OpenShareDialog(url, title, description, picture_url, successCallback) {\n FB.ui(\n {\n method: 'feed',\n name: title,\n caption: '',\n description: description,\n link: url,\n picture: picture_url\n },\n function (response) {\n if (!(response && response.post_id)) {\n // Cannot publish the post\n } else {\n // Post published\n if (typeof successCallback === 'function') {\n successCallback();\n }\n }\n }\n );\n}\n\nexport default class FacebookWallShareButton extends React.Component {\n\n constructor(props) {\n super(props);\n this.state = {};\n this.handleClick = this.handleClick.bind(this);\n }\n\n handleClick(event) {\n event.preventDefault();\n\n OpenShareDialog(this.props.url,this.props.title, this.props.description, this.props.pictureUrl, this.props.onShareSuccess);\n }\n\n render() {\n return (\n
\n );\n }\n}","import React from 'react'\nimport PropTypes from 'prop-types'\n\nimport FacebookWallShareButton from './FacebookWallShareButton';\nimport request from 'superagent';\n\n\nexport default class ShareOrderFacebookButton extends React.Component {\n static propTypes = {\n onShareApiUrl: PropTypes.string.isRequired\n };\n\n constructor(props) {\n super(props);\n this.state = {\n isShared: this.props.initialIsShared\n };\n\n this.handleOnShareSuccess = this.handleOnShareSuccess.bind(this);\n }\n\n handleOnShareSuccess() {\n if (window.ga) {\n ga('send', 'event', 'FBOrderShared', 'fb-order-shared');\n }\n\n request.post(this.props.onShareApiUrl)\n .set('Accept', 'application/json')\n .end((error, res) => {\n this.setState({\n isShared: true\n });\n });\n }\n\n renderAlreadyShared() {\n return (\n
\n Grazie per aver condiviso il tuo ordine con i tuoi amici!
Ti abbiamo regalato 1 Punto FR!\n
\n );\n }\n\n render() {\n return (\n this.state.isShared ? this.renderAlreadyShared() :
\n )\n }\n}\n","import React from 'react'\n\nexport default class AutoCompleteAddressInput extends React.Component {\n clearButtonStyle() {\n return Object.assign({}, styles.clearButton, {visibility: ((this.props.value.length > 0) ? 'visible' : 'hidden')});\n }\n\n render() {\n return (\n \n this.props.onChange(event.target.value)}\n />\n {/* this.props.onChange('')}/> */}\n
\n )\n }\n}\n\nconst styles = {\n clearButton: {\n position: 'absolute',\n right: '10px',\n paddingTop: '10px',\n color: 'gray',\n fontSize: '20px',\n cursor: 'pointer'\n },\n\n searchInput: {\n width: '100%',\n height: '44px',\n padding: '10px',\n fontSize: '16px'\n }\n};","export function getAddressComponent(types, components) {\n for (let component of components) {\n for (let _type of component.types) {\n if (types.indexOf(_type) !== -1) {\n return component.long_name;\n }\n }\n }\n}\n\nexport default class PlaceService {\n\n constructor(elemId) {\n const element = document.getElementById(elemId);\n\n this.placeService = new google.maps.places.PlacesService(element);\n }\n\n getPlace(token, placeId, callback) {\n let request = {\n placeId: placeId,\n fields: ['geometry', 'address_component'],\n sessionToken: token\n };\n\n this.placeService.getDetails(request, (placeResult, status) => {\n\n if (status === google.maps.places.PlacesServiceStatus.OK) {\n callback(placeResult);\n } else {\n // console.log(status);\n }\n });\n }\n}\n","import React from 'react'\n\nimport PlaceService from '../services/PlaceService';\n\nexport default class AutoCompleteAddressResults extends React.Component {\n\n constructor(props) {\n super(props);\n this.handleResultClick = this.handleResultClick.bind(this);\n }\n\n getPlaceService() {\n if (!this.placeService) {\n this.placeService = new PlaceService(\"maps-attributions\")\n }\n return this.placeService;\n }\n\n handleResultClick(placeId) {\n this.getPlaceService().getPlace(this.props.token, placeId, (placeResult) => {\n this.props.onAddressClicked(placeResult);\n });\n }\n\n renderResults() {\n return \n {\n this.props.addresses.map((address, index) => {\n return
this.handleResultClick(address.placeId)}>{address.description}
\n })\n }\n
\n }\n\n render() {\n return (\n \n
{this.renderResults()}
\n
Powered by Google
\n
\n )\n }\n}\n\nconst styles = {\n address: {\n margin: '10px',\n padding: '10px 0',\n borderBottom: '1px solid lightgray',\n cursor: 'pointer',\n fontSize: '16px'\n },\n poweredByGoogle: {\n textAlign: 'center',\n fontWeight: '400',\n margin: '20px'\n }\n};","import React from 'react'\n\nexport default class ConfirmAddressButton extends React.Component {\n\n handleClick = (event) => {\n event.preventDefault();\n\n if (this.props.disabled) { return; }\n\n this.props.onClick();\n };\n\n render() {\n const { text, disabled } = this.props;\n return (\n { text }\n )\n }\n}","import React from 'react'\nimport PropTypes from 'prop-types'\n\nfunction getOffsetPoint(latlng, offsetx, offsety, map) {\n\n const scale = Math.pow(2, map.getZoom());\n const projection = map.getProjection();\n const worldCoordinateCenter = projection.fromLatLngToPoint(latlng);\n const pixelOffset = new google.maps.Point((offsetx / scale) || 0, (offsety / scale) || 0);\n const worldCoordinateNewCenter = new google.maps.Point(\n worldCoordinateCenter.x - pixelOffset.x,\n worldCoordinateCenter.y + pixelOffset.y\n );\n\n return map.getProjection().fromPointToLatLng(worldCoordinateNewCenter);\n}\n\nexport default class UserLocationCircle extends React.Component {\n constructor(props) {\n super(props);\n this.positionCircle = null;\n this.accuracyCircle = null;\n }\n\n componentDidMount() {\n this.drawCircles();\n }\n\n componentDidUpdate(prevProps, prevState) {\n if (((this.props.lat != prevProps.lat) || (this.props.lng != prevProps.lng) || (this.props.accuracy != prevProps.accuracy) )) {\n this.drawCircles();\n }\n }\n\n drawCircles() {\n const localizationLatLng = new google.maps.LatLng(this.props.lat, this.props.lng);\n const map = this.props.map;\n\n // Accuracy Circle\n if (!this.accuracyCircle) {\n this.accuracyCircle = new google.maps.Circle({\n strokeColor: '#00A7E5',\n strokeOpacity: 0,\n strokeWeight: 0,\n fillColor: '#BCD4D6',\n fillOpacity: 0.5,\n map: map\n });\n }\n\n this.accuracyCircle.setRadius(this.props.accuracy);\n this.accuracyCircle.setCenter(localizationLatLng);\n\n const isMapReady = map.getProjection() != null;\n if (!isMapReady) { return; } \n\n // User position circle\n if (!this.positionCircle) {\n this.positionCircle = new google.maps.Marker({\n icon: '/assets/map-circle.png',\n map: this.props.map,\n position: getOffsetPoint(localizationLatLng, 0, 10, map)\n });\n }\n this.positionCircle.setPosition(getOffsetPoint(localizationLatLng, 0, 10, map));\n }\n\n render() {\n return false;\n }\n}\n\nUserLocationCircle.propTypes = {\n map: PropTypes.object.isRequired,\n lat: PropTypes.number.isRequired,\n lng: PropTypes.number.isRequired,\n accuracy: PropTypes.number.isRequired\n};","import React from 'react'\n\nimport UserLocationCircle from './UserLocationCircle';\nimport { GOOGLE_MAPS_JS_API_KEY } from \"../config.js\";\n\nexport default class MapViewer extends React.Component {\n\n constructor(props) {\n super(props);\n\n this.state = {};\n\n this.createDynamicGoogleMap = this.createDynamicGoogleMap.bind(this);\n this.handleMapDragEnd = this.handleMapDragEnd.bind(this);\n this.handleMapZoomChanged = this.handleMapZoomChanged.bind(this);\n }\n\n componentDidMount() {\n //this.createDynamicGoogleMap();\n this.createStaticGoogleMap();\n }\n\n componentDidUpdate(prevProps, prevState) {\n\n // Update the center of the map if changed\n if ((this.props.initialCenterLat !== prevProps.initialCenterLat) || (this.props.initialCenterLng !== prevProps.initialCenterLng)) {\n if (this.state.map) {\n const latLng = new google.maps.LatLng(this.props.initialCenterLat, this.props.initialCenterLng);\n this.state.map.setCenter(latLng);\n } else {\n this.createStaticGoogleMap();\n }\n }\n\n // Update the zoom level if changed\n if (this.state.map && (this.props.zoom !== this.state.map.getZoom())) {\n this.state.map.setZoom(this.props.zoom);\n }\n }\n\n handleMapDragEnd() {\n setTimeout(() => {\n const point = this.getCenter();\n\n this.props.onCenterChange(point.lat, point.lng);\n }, 400);\n }\n\n handleMapZoomChanged() {\n this.props.onZoomChange(this.state.map.getZoom());\n }\n\n handleStaticMapClicked = (event) => {\n this.setState({ staticMapSrc: null}, () => this.createDynamicGoogleMap())\n };\n\n createStaticGoogleMap() {\n\n let mapElem = document.getElementById(\"map-container\");\n const width = mapElem.offsetWidth;\n const height = mapElem.offsetHeight;\n const zoom = this.props.zoom;\n const lat = this.props.initialCenterLat;\n const lng = this.props.initialCenterLng;\n const scale = 2;\n\n let mapImageSrc = `https://maps.googleapis.com/maps/api/staticmap?center=${lat},${lng}&zoom=${zoom}&size=${width}x${height}&scale=${scale}&maptype=roadmap&key=${GOOGLE_MAPS_JS_API_KEY}`;\n this.setState({ staticMapSrc: mapImageSrc, staticMapWidth: width, staticMapHeight: height });\n }\n\n createDynamicGoogleMap() {\n const styleOptions = {\n name: \"FR Style\"\n };\n\n const MAP_STYLE = [\n {\n featureType: \"road\",\n elementType: \"all\",\n stylers: [\n {visibility: \"on\"}\n ]\n }\n ];\n\n let mapType = new google.maps.StyledMapType(MAP_STYLE, styleOptions);\n\n let map = new google.maps.Map(document.getElementById('map-element'), {\n center: {\n lat: this.props.initialCenterLat,\n lng: this.props.initialCenterLng\n },\n zoom: this.props.zoom,\n mapTypeId: google.maps.MapTypeId.ROADMAP,\n disableDefaultUI: true,\n clickableIcons: false,\n zoomControl: false\n });\n\n map.mapTypes.set(\"FR Style\", mapType);\n map.setMapTypeId(\"FR Style\");\n map.addListener('dragend', this.handleMapDragEnd);\n map.addListener('zoom_changed', this.handleMapZoomChanged);\n\n this.setState({\n map: map\n })\n }\n\n getCenter() {\n const center = this.state.map.getCenter();\n return {\n lat: center.lat(),\n lng: center.lng()\n }\n }\n\n render() {\n return (\n \n
\n {\n this.state.staticMapSrc &&\n
\n

\n
\n }\n\n
\n\n {this.props.children}\n\n { (this.props.localization.enabled && this.state.map) ?\n
: ''}\n \n )\n }\n}\n\nconst styles = {\n container: {\n position: 'relative',\n height: '100%',\n width: '100%'\n },\n\n map: {\n height: '100%',\n width: '100%'\n }\n};\n","const GOOGLE_MAPS_JS_API_KEY = 'AIzaSyC4Tl7IMVdoOkGL79Q_xf8WCK9ofKUa2lg';\n\nexport { GOOGLE_MAPS_JS_API_KEY };","import React from 'react'\n\nexport default function MapMarker(props) {\n return \n}\n\nconst styles = {\n marker: {\n position: 'absolute',\n top: '50%',\n left: '50%',\n width: '20px',\n height: '40px',\n display: 'block',\n content: ' ',\n margin: '-40px 0 0 -11px',\n background: \"url('https://maps.gstatic.com/mapfiles/api-3/images/spotlight-poi_hdpi.png')\",\n backgroundSize: '20px 40px', /* Since I used the HiDPI marker version this compensates for the 2x size */\n pointerEevents: 'none', /* This disables clicks on the marker. Not fully supported by all major browsers, though */\n backgroundRepeat: 'no-repeat'\n }\n};","import React from 'react'\n\nexport default function LocalizeButton({onClick}) {\n return (\n \n \n
\n\n )\n}\n\nconst styles = {\n button: {\n width: '50px',\n height: '50px',\n backgroundColor: 'white',\n borderRadius: '100%',\n position: 'absolute',\n bottom: '20px',\n right: '10px',\n color: '#ff420d',\n padding: '2px',\n textAlign: 'center',\n fontSize: '30px',\n boxShadow: '0px 1px 5px grey'\n }\n};","export default class SearchAddress {\n constructor() {\n this.autocompleteService = new google.maps.places.AutocompleteService();\n }\n\n search(token, term, onResult) {\n\n if (!term) {\n return;\n }\n\n const params = {\n componentRestrictions: {\n country: 'it'\n },\n input: term,\n types: ['address'],\n sessionToken: token\n };\n\n this.autocompleteService.getPlacePredictions(params, (predictions, status) => {\n if (typeof onResult === 'function') {\n if (status === 'OK') {\n let results = predictions.map((prediction) => {\n return {\n description: prediction.description,\n placeId: prediction.place_id\n }\n });\n\n onResult(results);\n } else {\n onResult([]);\n }\n }\n })\n\n }\n}","export default class Geolocalizer {\n constructor() {\n this.maximumAge = 5000;\n this.timeout = 5000;\n this.enableHighAccuracy = true;\n }\n\n localize(onSuccessCallback, onErrorCallback) {\n navigator.geolocation.getCurrentPosition(\n function onSuccess(position) {\n if (typeof(onSuccessCallback) === 'function') { onSuccessCallback(position); }\n },\n\n function onError(error) {\n if (typeof(onErrorCallback) === 'function') { onErrorCallback(error); }\n\n console.log('Position error, code: ' + error.code + '\\n' +\n 'message: ' + error.message + '\\n');\n }, { maximumAge: this.maximumAge, timeout: this.timeout, enableHighAccuracy: this.enableHighAccuracy });\n }\n\n static isSupported() {\n return typeof(navigator.geolocation) === 'object';\n }\n}","export default class Geocoder {\n\n static geocodePoint(lat, lng, callback) {\n let geocoder = new google.maps.Geocoder;\n\n geocoder.geocode({'location': {lat: lat, lng: lng}}, (results, status) => {\n if (status === google.maps.GeocoderStatus.OK) {\n const result = results[0];\n\n if (result) {\n let address = result.formatted_address;\n callback(result)\n } else {\n console(\"error\");\n }\n } else {\n console.log('Geocoder failed due to: ' + status);\n }\n });\n }\n}","import React from 'react'\n\nimport AutoCompleteAddressInput from './AutoCompleteAddressInput';\nimport AutoCompleteAddressResults from './AutoCompleteAddressResults';\nimport ConfirmAddressButton from './ConfirmAddressButton';\nimport MapViewer from './MapViewer';\nimport MapMarker from './MapMarker';\nimport LocalizeButton from './LocalizeButton';\nimport SearchAddressService from '../services/SearchAddressService';\nimport Geolocalizer from '../services/Geolocalizer';\nimport Geocoder from '../services/Geocoder';\nimport {getAddressComponent} from \"../services/PlaceService\";\n\nconst DEFAULT_LAT = 45.663825;\nconst DEFAULT_LNG = 12.250616;\n\nfunction getFullAddress(address_components) {\n const street_name = getAddressComponent([\"route\"], address_components);\n const street_number = getAddressComponent([\"street_number\"], address_components);\n const city = getAddressComponent([\"locality\",\"administrative_area_level_3\"], address_components);\n\n return `${street_name} ${street_number || ''}, ${city}`;\n}\n\nfunction getErrorMessage(error) {\n let message;\n\n switch (error.code) {\n case error.PERMISSION_DENIED:\n message = I18n.t(\"mobileapp.pages.locations.search.localization.not_enabled\");\n break;\n case error.POSITION_UNAVAILABLE:\n message = I18n.t(\"mobileapp.pages.locations.search.localization.cannot_retrieve\"); //\"Location information is unavailable.\";\n break;\n case error.TIMEOUT:\n message = I18n.t(\"mobileapp.pages.locations.search.localization.timeout\"); //\"The request to get user location timed out.\";\n break;\n default:\n message = I18n.t(\"mobileapp.pages.locations.search.localization.cannot_retrieve\");\n break;\n }\n\n return message;\n}\n\nexport default class MapAddressPickerContainer extends React.Component {\n\n constructor(props) {\n super(props);\n\n this.state = {\n addresses: [],\n value: props.initialFullAddress || '',\n operationInProgress: false,\n showMap: true,\n mapZoom: 17,\n chosenAddress: {\n description: props.initialFullAddress,\n lat: parseFloat(props.initialLat) || DEFAULT_LAT,\n lng: parseFloat(props.initialLng) || DEFAULT_LNG,\n components: []\n },\n localization: {\n enabled: false,\n accuracy: null,\n lat: null,\n lng: null\n }\n };\n\n\n this.searchAddressService = new SearchAddressService();\n this.geolocalizer = new Geolocalizer();\n this.geolocalizeUserTimeout = null;\n }\n\n componentWillUnmount() {\n this.clearGeolocalizerUserTimeout();\n }\n\n componentDidMount() {\n if (this.props.autoGeolocalizeUser) {\n this.geolocalizeUser(true);\n }\n }\n\n geolocalizeUser = (autoCenterMap = false) => {\n this.geolocalizer.localize(\n (position) => {\n const lat = position.coords.latitude;\n const lng = position.coords.longitude;\n const gpsAccuracy = position.coords.accuracy;\n\n let newState = {\n localization: {\n enabled: true,\n accuracy: gpsAccuracy,\n lat: lat,\n lng: lng\n }\n };\n\n if (autoCenterMap === true) {\n newState.mapZoom = 18;\n\n this.setState(newState);\n this.handleOnMapCenterChange(lat, lng);\n } else {\n this.setState(newState);\n }\n\n this.geolocalizeUserTimeout = setTimeout(this.geolocalizeUser, 3000); // refresh for better position\n\n //localizationStatusLabel.setText(I18n.t(\"mobileapp.pages.locations.search.localization.accuracy_label\", {meters: parseInt(gpsAccuracy) }));\n }, (error) => {\n\n this.clearGeolocalizerUserTimeout();\n alert(getErrorMessage(error));\n });\n };\n\n handleOnMapZoomChange = (zoom) => {\n this.setState({\n mapZoom: zoom\n });\n };\n\n handleOnLocalizeClick = () => {\n this.clearGeolocalizerUserTimeout();\n this.geolocalizeUser(true);\n };\n\n handleOnInputChange = (term) => {\n if (term.length === 0) {\n this.setState({\n addresses: [],\n showMap: true,\n value: '',\n });\n } else {\n let token = this.state.token;\n\n if (!token) {\n token = new google.maps.places.AutocompleteSessionToken();\n this.setState({token: token})\n }\n\n this.setState({\n value: term,\n });\n\n this.searchAddressService.search(token, term, (results) => {\n this.setState({\n addresses: results,\n showMap: false\n })\n });\n }\n };\n\n // @placeResult of type: google.maps.places.PlaceResult\n handleAddressClicked = (placeResult) => {\n const location = placeResult.geometry.location;\n const address_components = placeResult.address_components;\n const description = getFullAddress(address_components);\n\n this.setState({\n value: description,\n showMap: true,\n token: null,\n chosenAddress: {\n lat: location.lat(),\n lng: location.lng(),\n description: description,\n components: address_components\n }\n });\n };\n\n handleOnMapCenterChange = (lat, lng) => {\n this.setState({\n operationInProgress: true\n });\n\n Geocoder.geocodePoint(lat, lng, (result) => {\n const address_components = result.address_components;\n\n if ((typeof this.props.onConfirm === 'function') && address_components) {\n\n const description = getFullAddress(address_components);\n\n this.setState({\n operationInProgress: false,\n value: description,\n chosenAddress: {\n lat: lat,\n lng: lng,\n description: description,\n components: result.address_components\n }\n });\n }\n });\n };\n\n handleConfirmButtonClicked = () => {\n this.props.onConfirm(this.state.chosenAddress.lat, this.state.chosenAddress.lng, this.state.chosenAddress.components);\n };\n\n clearGeolocalizerUserTimeout = () => {\n if (this.geolocalizeUserTimeout) {\n clearTimeout(this.geolocalizeUserTimeout);\n }\n };\n\n isAddressFilled() {\n const { lat, lng, description } = this.state.chosenAddress;\n\n return lat && lng && description;\n }\n\n renderMap() {\n return (\n \n \n \n \n );\n }\n\n renderAutoCompleteResults() {\n return ;\n }\n\n render() {\n const { operationInProgress, value, showMap } = this.state;\n const buttonText = operationInProgress ? 'Attendi...' : ' Conferma indirizzo';\n const confirmButtonDisabled = !this.isAddressFilled();\n\n return (\n \n
\n\n
\n { showMap ? this.renderMap() : this.renderAutoCompleteResults() }\n
\n\n
\n \n
\n
\n )\n }\n}\n","import React from 'react'\n\nimport Modal from 'react-bootstrap/lib/Modal';\nimport MapAddressPickerContainer from './MapAddressPickerContainer';\n\nconst MapAddressPickerModal = (props) => {\n\n const {onModalHide, show} = props;\n\n return (\n \n \n {I18n.t('pages.locations.search.insert_address_title')}\n \n \n \n \n \n );\n};\n\nexport default MapAddressPickerModal;\n","import React from 'react'\n\nimport BrowserLocationHelper from '../utils/browser_location_helper';\nimport MapAddressPickerModal from './components/MapAddressPickerModal';\nimport {getAddressComponent} from './services/PlaceService'\n\nexport default class SelectAddressPage extends React.Component {\n constructor(props) {\n super(props);\n\n this.state = {\n address: props.initialAddress || {},\n showModal: false\n };\n\n this.handleChangeAddressInputClicked = this.handleChangeAddressInputClicked.bind(this);\n this.handleConfirmAddressButtonClicked = this.handleConfirmAddressButtonClicked.bind(this);\n this.handleOnModalHide = this.handleOnModalHide.bind(this);\n this.handleOnModalConfirm = this.handleOnModalConfirm.bind(this);\n this.gotoResultsPage = this.gotoResultsPage.bind(this);\n }\n\n getFullAddress() {\n const street_name = this.state.address.street_name;\n const street_number = this.state.address.street_number;\n const city = this.state.address.city;\n\n if (street_name && city) {\n return `${street_name} ${street_number || ''}, ${city}`;\n } else {\n return '';\n }\n }\n\n gotoResultsPage() {\n let url = this.props.searchURL;\n const address = this.state.address;\n \n url += \"?latitude=\" + address.latitude;\n url += \"&longitude=\" + address.longitude;\n url += \"&street_name=\" + address.street_name;\n url += \"&street_number=\" + address.street_number;\n url += \"&city=\" + address.city;\n url += \"&postal_code=\" + address.postal_code;\n\n BrowserLocationHelper.ChangeURL(url);\n }\n\n handleConfirmAddressButtonClicked(event) {\n if (event) { event.preventDefault(); }\n\n if (!this.state.address.latitude || !this.state.address.longitude) { return; }\n\n this.gotoResultsPage();\n }\n\n handleChangeAddressInputClicked(event) {\n event.preventDefault();\n\n if (window.google && window.google.maps) {\n this.setState({showModal: true});\n } else {\n try {\n const errorMessage = \"SelectAddressPage tried to open the modal but google is not loaded\";\n console.log(errorMessage);\n Raygun.send(new Error(errorMessage));\n } catch(err) {}\n }\n }\n\n handleOnModalHide() {\n this.setState({showModal: false});\n }\n\n handleOnModalConfirm(lat, lng, address_components = []) {\n //TODO: Change the way the state is managed by this component and MapAddressPickerContainer\n\n let street_name, street_number, city, postal_code;\n\n if (address_components && address_components.length === 0)\n {\n street_name = this.state.address.street_name;\n street_number = this.state.address.street_number;\n city = this.state.address.city;\n postal_code = this.state.address.postal_code;\n } else {\n street_name = getAddressComponent([\"route\"], address_components) || '';\n street_number = getAddressComponent([\"street_number\"], address_components) || '';\n city = getAddressComponent([\"locality\",\"administrative_area_level_3\"], address_components) || '';\n postal_code = getAddressComponent([\"postal_code\"], address_components) || '';\n }\n\n this.setState({\n address: {\n latitude: lat,\n longitude: lng,\n street_name,\n street_number,\n city,\n postal_code\n }\n });\n\n setTimeout(this.gotoResultsPage, 500 );\n }\n\n render() {\n return (\n \n )\n }\n}\n\nconst styles = {\n mainLabel: {\n fontSize: '40px',\n lineHeight: '30px',\n fontWeight: '300',\n marginBottom: '50px'\n },\n mainContainer: {\n width: '100%',\n position: 'absolute',\n top: '20%'\n },\n inputContainer: {\n height: '44px'\n },\n input: {\n width: '80%',\n color: 'black',\n height: '100%',\n padding: '5px',\n border: 'none'\n },\n a: {\n height: '100%',\n fontSize: '21px',\n verticalAlign: 'top'\n }\n};","export function diff_in_days(dateString) {\n const date = new Date(dateString);\n const today = new Date();\n\n const duration = date.getTime() - today.getTime();\n return duration / (1000 * 3600 * 24);\n}\n","import React from \"react\"\n\nimport style from \"./EmptyVenuesAlert.module\"\n\nexport default function EmptyVenuesAlert() {\n return (\n \n
\n
\n
😔
\n \n {I18n.t(\"react.venues.no_result.empty_venues\")}\n
\n \n
\n
\n )\n}\n","import React, { useState, useEffect } from \"react\"\nimport FormGroup from \"react-bootstrap/lib/FormGroup\"\nimport InputGroup from \"react-bootstrap/lib/InputGroup\"\nimport FormControl from \"react-bootstrap/lib/FormControl\"\nimport Button from \"react-bootstrap/lib/Button\"\n\nimport style from \"./index.module.sass\"\n// ----------------------------------------------------------------------------\n\nconst placeholder = I18n.t(\"pages.locations.venues.search.placeholder\")\n\nfunction VenueChooserSearchBar(props) {\n // -------------------------------------\n // Props destructuring\n // -------------------------------------\n\n const {\n onChange = () => {},\n defaultText = \"\",\n onSearch = () => {},\n isLoading = false,\n } = props\n\n // -------------------------------------\n // Hooks (e.g. useState, useMemo ...)\n // -------------------------------------\n\n const [currentText, setCurrentText] = useState(defaultText)\n\n // -------------------------------------\n // Effects\n // -------------------------------------\n\n useEffect(() => {\n onChange(currentText)\n }, [currentText])\n\n // -------------------------------------\n // Component functions\n // -------------------------------------\n\n function handleEnterPressed(event) {\n if (event.keyCode === 13) {\n onSearch(currentText)\n event.preventDefault()\n }\n }\n\n function handleSearch() {\n onSearch(currentText)\n }\n\n // -------------------------------------\n // Component local variables\n // -------------------------------------\n\n // -------------------------------------\n\n return (\n \n
\n {I18n.t(\"pages.locations.venues.search.title\")}\n
\n
\n
\n )\n}\n\n// ----------------------------------------------------------------------------\n\nexport default VenueChooserSearchBar\n","import React from \"react\"\n\nimport style from \"./RoundedCheckBox.module\"\n\nexport default function RoundedCheckBox({ checked, onChange, readOnly }) {\n return (\n \n )\n}\n","import React from \"react\"\nimport PropTypes from \"prop-types\"\nimport RoundedCheckBox from \"../../../../ui-components/RoundedCheckBox\"\n\nimport style from \"./index.module.sass\"\n\nexport default function FilterRow(props) {\n // -------------------------------------\n // Props destructuring\n // -------------------------------------\n\n const { name, label, selected, onSelect } = props\n\n // -------------------------------------\n // Hooks (e.g. useState, useMemo ...)\n // -------------------------------------\n\n // -------------------------------------\n // Effects\n // -------------------------------------\n\n // -------------------------------------\n // Component functions\n // -------------------------------------\n\n // -------------------------------------\n // Component local variables\n // -------------------------------------\n\n // -------------------------------------\n\n return (\n \n )\n}\n\nFilterRow.propTypes = {\n label: PropTypes.oneOfType([PropTypes.string, PropTypes.node]).isRequired,\n name: PropTypes.string.isRequired,\n selected: PropTypes.bool.isRequired,\n onSelect: PropTypes.func.isRequired,\n}\n","import React from \"react\"\nimport PropTypes from \"prop-types\"\n\nimport FilterRow from \"./FilterRow/index.jsx\"\n\nexport default function VenueCategoriesChooser(props) {\n // -------------------------------------\n // Props destructuring\n // -------------------------------------\n\n const { categories, onSelect, onAllCategoriesSelected } = props\n\n // -------------------------------------\n // Hooks (e.g. useState, useMemo ...)\n // -------------------------------------\n\n // -------------------------------------\n // Effects\n // -------------------------------------\n\n // -------------------------------------\n // Component functions\n // -------------------------------------\n\n // -------------------------------------\n // Component local variables\n // -------------------------------------\n\n const allCategoriesSelected = !categories.some((element) => element.selected)\n\n // -------------------------------------\n\n return (\n \n onAllCategoriesSelected()}\n />\n\n
\n {categories.map((category, index) => {\n return (\n onSelect(category.id)}\n />\n )\n })}\n
\n )\n}\n\nVenueCategoriesChooser.propTypes = {\n categories: PropTypes.array.isRequired,\n onSelect: PropTypes.func.isRequired,\n onAllCategoriesSelected: PropTypes.func.isRequired,\n}\n","import React from \"react\"\nimport PropTypes from \"prop-types\"\n\nimport FilterRow from \"./FilterRow/index.jsx\"\n\nexport default function VenueFeaturesChooser(props) {\n // -------------------------------------\n // Props destructuring\n // -------------------------------------\n\n const { selectedFeatures = {}, onFeatureSelected } = props\n\n // -------------------------------------\n // Hooks (e.g. useState, useMemo ...)\n // -------------------------------------\n\n // -------------------------------------\n // Effects\n // -------------------------------------\n\n // -------------------------------------\n // Component functions\n // -------------------------------------\n\n // -------------------------------------\n // Component local variables\n // -------------------------------------\n\n // -------------------------------------\n\n return (\n \n {Object.entries(selectedFeatures).map(([name, selected]) => {\n return (\n \n )\n })}\n
\n )\n}\n\nVenueFeaturesChooser.propTypes = {\n selectedFeatures: PropTypes.object.isRequired,\n onFeatureSelected: PropTypes.func.isRequired,\n}\n","import React from \"react\"\nimport Modal from \"react-bootstrap/lib/Modal\"\nimport Button from \"react-bootstrap/lib/Button\"\n\nimport VenueCategoriesChooser from \"../VenueCategoriesChooser\"\nimport VenueFeaturesChooser from \"../VenueFeaturesChooser\"\n\nimport style from \"./index.module.sass\"\n\nexport default function VenuesFilterModal(props) {\n // -------------------------------------\n // Props destructuring\n // -------------------------------------\n\n const {\n show,\n onClose,\n categories,\n onCategorySelected,\n onAllCategoriesSelected,\n selectedFeatures,\n onFeatureSelected,\n resultsCount,\n onClearFilterClicked,\n } = props\n\n // -------------------------------------\n // Hooks (e.g. useState, useMemo ...)\n // -------------------------------------\n\n // -------------------------------------\n // Effects\n // -------------------------------------\n\n // -------------------------------------\n // Component functions\n // -------------------------------------\n\n // -------------------------------------\n // Component local variables\n // -------------------------------------\n\n // -------------------------------------\n\n return (\n \n \n \n {I18n.t(\"pages.locations.venues.filters\")}\n \n \n \n \n {I18n.t(\"pages.locations.venues.features.title\")}\n
\n \n\n \n {I18n.t(\"pages.locations.venues.cuisines.title\")}\n
\n\n \n \n\n \n \n \n {I18n.t(\"pages.locations.venues.features.remove_filters\")}\n
\n \n \n \n )\n}\n","import React from \"react\";\n\nconst LoadingVenues = () => {\n return (\n \n
\n
{\"🛒 🛍\"}
{I18n.t(\"pages.locations.venues.loading\")}\n
\n
\n );\n}\n\nexport default LoadingVenues;\n","import React from \"react\";\n\nconst ErrorMessage = ({message}) => {\n return (\n \n );\n}\n\nexport default ErrorMessage;\n","import React from \"react\"\nimport { diff_in_days } from \"../../utils/dates/diff_in_days\"\n\nconst MAX_DAYS_FOR_COMING_AT_FUTURE = 90\n\nfunction ComingSoon(props) {\n // -------------------------------------\n // Props destructuring\n // -------------------------------------\n\n const { sDate } = props\n\n // -------------------------------------\n // Hooks (e.g. useState, useMemo ...)\n // -------------------------------------\n\n // -------------------------------------\n // Effects\n // -------------------------------------\n\n // -------------------------------------\n // Component functions\n // -------------------------------------\n\n // -------------------------------------\n // Component local variables\n // -------------------------------------\n\n const days = diff_in_days(sDate)\n const date = new Date(sDate)\n const formattedDate = `${date.getDate()}/${date.getMonth() + 1}`\n\n // -------------------------------------\n\n return (\n \n {days > MAX_DAYS_FOR_COMING_AT_FUTURE\n ? I18n.t(\"pages.locations.venues.venue_box.coming_at_future\")\n : I18n.t(\"pages.locations.venues.venue_box.coming_at\", {\n date: formattedDate,\n })}\n \n )\n}\n\nexport default ComingSoon\n","const mode = {\n DELIVERY: \"delivery\",\n PICKUP: \"pickup\"\n}\n\nexport const ORDER_MODE = Object.freeze(mode);\n","import React from \"react\"\nimport { ORDER_MODE } from \"../OrderMode\"\n\nimport style from \"./index.module.sass\"\n\nfunction FirstSlot(props) {\n // -------------------------------------\n // Props destructuring\n // -------------------------------------\n\n const { slot, orderMode } = props\n\n // -------------------------------------\n // Hooks (e.g. useState, useMemo ...)\n // -------------------------------------\n\n // -------------------------------------\n // Effects\n // -------------------------------------\n\n // -------------------------------------\n // Component functions\n // -------------------------------------\n\n function renderDeliverySlot(timeSlot) {\n if (timeSlot) {\n const { start_time } = timeSlot\n\n return (\n \n
{start_time}
\n
\n {I18n.t(\"pages.locations.venues.venue_box.delivery_from\")}\n
\n
\n )\n } else {\n return I18n.t(\"pages.locations.venues.venue_box.ended_deliveries\")\n }\n }\n\n function renderPickupSlot(timeSlot) {\n if (timeSlot) {\n const { picking_times = [] } = timeSlot\n\n return (\n \n
{picking_times[0]}
\n
\n {I18n.t(\"pages.locations.venues.venue_box.takeaway_from\")}\n
\n
\n )\n } else {\n return I18n.t(\"pages.locations.venues.venue_box.ended_takeaway_slots\")\n }\n }\n\n // -------------------------------------\n // Component local variables\n // -------------------------------------\n\n // -------------------------------------\n\n switch (orderMode) {\n case ORDER_MODE.DELIVERY:\n return renderDeliverySlot(slot)\n case ORDER_MODE.PICKUP:\n return renderPickupSlot(slot)\n default:\n return \"\"\n }\n}\n\nexport default FirstSlot\n","import React from \"react\"\nimport ServiceRow from \"../../../VenueServicesList/ServiceRow\"\nimport ComingSoon from \"../../DeliveryInfo/ComingSoon\"\nimport FirstSlot from \"../../DeliveryInfo/FirstSlot\"\n\nimport style from \"./index.module.sass\"\n\n// ----------------------------------------------------------------------------\n\nfunction ServiceBox(props) {\n // -------------------------------------\n // Props destructuring\n // -------------------------------------\n\n const { service, venue, onClick, orderMode } = props\n\n // -------------------------------------\n // Hooks (e.g. useState, useMemo ...)\n // -------------------------------------\n\n // -------------------------------------\n // Effects\n // -------------------------------------\n\n // -------------------------------------\n // Component functions\n // -------------------------------------\n\n function noVenue() {\n return \n }\n\n // -------------------------------------\n // Component local variables\n // -------------------------------------\n\n // GUARD\n if (!venue) {\n return noVenue()\n }\n\n let venueInfo = [venue.subtitle || \"\"]\n if (venue.accepts_cash && venue.accepts_stripe) {\n venueInfo.push(\n I18n.t(\"pages.locations.venues.venue_box.payments.card_and_cash\")\n )\n } else if (venue.accepts_stripe) {\n venueInfo.push(I18n.t(\"pages.locations.venues.venue_box.payments.cash\"))\n } else if (venue.accepts_stripe) {\n venueInfo.push(\n I18n.t(\"pages.locations.venues.venue_box.payments.credit_card\")\n )\n }\n\n if (!venue.accepts_discount_codes) {\n venueInfo.push(\n I18n.t(\"pages.locations.venues.venue_box.payments.no_coupon\")\n )\n }\n\n const venueDesc = venueInfo.join(\" • \")\n\n // -------------------------------------\n\n return (\n \n
{\n onClick(venue, service)\n }}\n >\n
\n
\n\n
\n
\n
{venue.name}
\n
{venueDesc}
\n
\n

\n
\n {venue.coming_soon_at && (\n \n )}\n {!venue.coming_soon_at && (\n \n )}\n
\n
\n
\n
\n
\n )\n}\n\n// ----------------------------------------------------------------------------\n\nexport default ServiceBox\n","import React from \"react\"\n\nimport ServiceBox from \"./ServiceBox\"\nimport style from \"./index.module.sass\"\nimport Spinner from \"../../ui-components/Spinner\"\n\n// ----------------------------------------------------------------------------\n\nfunction ServicesList(props) {\n // -------------------------------------\n // Props destructuring\n // -------------------------------------\n const { isLoading = false, venues = [], services, orderMode, onClick } = props\n // -------------------------------------\n // Hooks (e.g. useState, useMemo ...)\n // -------------------------------------\n\n // -------------------------------------\n // Effects\n // -------------------------------------\n\n // -------------------------------------\n // Component functions\n // -------------------------------------\n\n // -------------------------------------\n // Component local variables\n // -------------------------------------\n\n // -------------------------------------\n\n if (isLoading) {\n return (\n \n )\n }\n\n return (\n \n {services.map((s) => {\n return (\n
v.id === s.venue.id)[0]}\n orderMode={orderMode}\n onClick={onClick}\n />\n )\n })}\n {/* Prevent last line elements to grow without control */}\n {/* Actually the only working work-around to this flex lack */}\n \n \n \n \n )\n}\n\n// ----------------------------------------------------------------------------\n\nexport default ServicesList\n","import React from \"react\"\nimport { diff_in_days } from \"../../../../utils/dates/diff_in_days\"\n\nimport style from \"./index.module.sass\"\n\nconst MAX_DAYS_TO_BE_NEW = 30\n\nfunction VenueBadges(props) {\n // -------------------------------------\n // Props destructuring\n // -------------------------------------\n\n const { venue } = props\n const { first_published_at, promotion, priority } = venue\n\n // -------------------------------------\n // Hooks (e.g. useState, useMemo ...)\n // -------------------------------------\n\n // -------------------------------------\n // Effects\n // -------------------------------------\n\n // -------------------------------------\n // Component functions\n // -------------------------------------\n\n // -------------------------------------\n // Component local variables\n // -------------------------------------\n\n const isNew = -diff_in_days(first_published_at) < MAX_DAYS_TO_BE_NEW\n\n // -------------------------------------\n\n if (!isNew && !promotion && !(priority > 0)) {\n return \n }\n\n return (\n \n {isNew && (\n \n {I18n.t(\"pages.locations.venues.venue_box.new\")}\n \n )}\n {promotion && (\n \n {I18n.t(\"pages.locations.venues.venue_box.promotion\")}\n \n )}\n {priority > 0 && (\n \n {I18n.t(\"pages.locations.venues.venue_box.sponsored\")}\n \n )}\n
\n )\n}\n\nexport default VenueBadges\n","import React from \"react\"\nimport PropTypes from \"prop-types\"\n\nimport Col from \"react-bootstrap/lib/Col\"\nimport Row from \"react-bootstrap/lib/Row\"\n\nimport VenueBadges from \"./VenueBadges\"\nimport FirstSlot from \"../../DeliveryInfo/FirstSlot\"\nimport ComingSoon from \"../../DeliveryInfo/ComingSoon\"\n\nimport style from \"./index.module.sass\"\n\nexport default function VenueBox(props) {\n // -------------------------------------\n // Props destructuring\n // -------------------------------------\n\n const { venue, onClick, orderMode, isVisible = true } = props\n\n const {\n name,\n subtitle,\n coming_soon_at,\n first_time_slot,\n logo,\n cover_image,\n distance,\n promotion,\n accepts_cash,\n accepts_stripe,\n accepts_discount_codes,\n } = venue\n\n // -------------------------------------\n // Hooks (e.g. useState, useMemo ...)\n // -------------------------------------\n\n // -------------------------------------\n // Effects\n // -------------------------------------\n\n // -------------------------------------\n // Component functions\n // -------------------------------------\n\n function humanDistance(distance) {\n const roundedDistance = parseFloat(distance.toFixed(1))\n\n if (roundedDistance < 1) {\n return ` ${roundedDistance * 1000.0} m`\n } else {\n return ` ${roundedDistance} km`\n }\n }\n\n function renderVenueFeatures() {\n let features = []\n if (accepts_cash) {\n features.push(I18n.t(\"pages.locations.venues.venue_box.payments.cash\"))\n }\n if (accepts_stripe) {\n features.push(\n I18n.t(\"pages.locations.venues.venue_box.payments.credit_card\")\n )\n }\n if (!accepts_discount_codes) {\n features.push(\n I18n.t(\"pages.locations.venues.venue_box.payments.no_coupon\")\n )\n }\n\n return {features.join(\" • \")}
\n }\n\n // -------------------------------------\n // Component local variables\n // -------------------------------------\n\n // -------------------------------------\n\n return (\n {\n onClick && onClick(e, venue)\n }}\n >\n
\n\n
\n {isVisible &&

}\n
\n\n
\n
\n {coming_soon_at && }\n {!coming_soon_at && (\n \n )}\n
\n
\n\n
\n
\n\n
\n {name}\n {distance && {humanDistance(distance)}}\n
\n
{subtitle}
\n
\n {renderVenueFeatures()}\n
\n\n {promotion && (\n
\n \n {promotion.title}
\n \n
\n )}\n
\n
\n )\n}\n\nVenueBox.propTypes = {\n venue: PropTypes.object.isRequired,\n onClick: PropTypes.func.isRequired,\n}\n","import React from \"react\"\nimport PropTypes from \"prop-types\"\n\nimport VisibilitySensor from \"react-visibility-sensor/visibility-sensor\"\nimport VenueBox from \"./VenueBox\"\n\nimport style from \"./index.module.sass\"\n\nexport default function VenuesList({ orderMode, venues, onClick }) {\n // -------------------------------------\n // Props destructuring\n // -------------------------------------\n\n // -------------------------------------\n // Hooks (e.g. useState, useMemo ...)\n // -------------------------------------\n\n // -------------------------------------\n // Effects\n // -------------------------------------\n\n // -------------------------------------\n // Component functions\n // -------------------------------------\n\n function VisibleVenue({ index, venue, orderMode, onClick }) {\n return (\n \n {({ isVisible }) => {\n return (\n \n )\n }}\n \n )\n }\n\n // -------------------------------------\n // Component local variables\n // -------------------------------------\n\n // -------------------------------------\n return (\n // \n
\n {venues.map((venue, index) => {\n return (\n
\n )\n })}\n {/* Prevent last line elements to grow without control */}\n {/* Actually the only working work-around to this flex lack */}\n
\n
\n
\n
\n )\n}\n\nVenuesList.propTypes = {\n venues: PropTypes.array.isRequired,\n onClick: PropTypes.func.isRequired,\n}\n","import superagent from 'superagent';\nimport {API_V2_URL} from \"./base\";\n\nexport default class LocationAPI {\n\n static SendLocationSubscription(location) {\n const URL = `${API_V2_URL}locations/location_subscriptions`;\n\n return new Promise((resolve, reject) => {\n\n superagent.post(URL)\n .query({location_subscription: {\n email: location.email,\n latitude: location.latitude,\n longitude: location.longitude,\n street_name: location.street_name,\n street_number: location.street_number,\n city: location.city,\n postal_code: location.postal_code,\n venue_types: \"shop\"\n }\n })\n .end((error, res) => {\n error ? reject(error) : resolve(res.body);\n });\n });\n }\n}\n","import React, { useState, useEffect } from \"react\"\nimport Button from \"react-bootstrap/lib/Button\"\n\nimport Spinner from \"../../ui-components/Spinner\"\nimport SingleFieldFormWithValidation from \"../../ui-components/SingleFieldFormWithValidation\"\nimport LocationAPI from \"../../apis/LocationAPI\"\n\nimport style from \"./index.module.sass\"\nimport {\n intercomSendData,\n intercomTrackEvent,\n} from \"../../utils/Intercom/intercomHelper\"\n\n// ----------------------------------------------------------------------------\n\nconst steps = { leaveMail: 1, loading: 2, success: 3, error: 4 }\nconst success_message = I18n.t(\"react.venues.no_result.success_message\")\nconst error_message = I18n.t(\"react.venues.no_result.error_message\")\n\nfunction sendUncoveredAddressToIntercom(city) {\n if (!window.Intercom || typeof window.Intercom !== \"function\") {\n return\n }\n\n try {\n intercomTrackEvent(\"searched-uncovered-zone\", {\n \"Created at\": new Date(),\n \"Not covered zone\": city,\n })\n\n intercomSendData({\n \"Last not covered zone\": city,\n })\n } catch (error) {\n console.log(error)\n }\n}\n\nexport default function ZoneNotCovered(props) {\n // -------------------------------------\n // Props destructuring\n // -------------------------------------\n\n const { location } = props\n\n // -------------------------------------\n // Hooks (e.g. useState, useMemo ...)\n // -------------------------------------\n\n const [step, setStep] = useState(steps.leaveMail)\n const [email, setEmail] = useState(\"\")\n\n // -------------------------------------\n // Effects\n // -------------------------------------\n\n useEffect(() => {\n sendUncoveredAddressToIntercom(location.city)\n }, [])\n\n // -------------------------------------\n // Component functions\n // -------------------------------------\n\n function onSend() {\n setStep(steps.loading)\n\n let apiData = { ...location, email: email }\n LocationAPI.SendLocationSubscription(apiData)\n .then((res) => {\n setStep(steps.success)\n })\n .catch((err) => {\n setStep(steps.error)\n })\n }\n\n function onRetry() {\n setStep(steps.leaveMail)\n }\n\n // -------------------------------------\n // Component local variables\n // -------------------------------------\n\n // -------------------------------------\n\n return (\n
\n
\n
\n {step === steps.leaveMail && (\n
\n
\n
\n
😔
\n
\n {I18n.t(\"react.venues.no_result.page_title\")}\n
\n
\n {I18n.t(\"react.venues.no_result.page_subtitle\")}\n
\n
\n {I18n.t(\"react.venues.no_result.page_description\")}\n
\n
\n
\n
\n
\n )}\n {step === steps.loading &&
}\n {(step === steps.success || step === steps.error) && (\n
\n
\n
\n {step === steps.success ? success_message : error_message}\n
\n {step === steps.error && (\n \n )}\n \n
\n )}\n
\n
\n
\n )\n}\n\n// ----------------------------------------------------------------------------\n","import React, { Fragment } from \"react\"\nimport Switch from \"react-switch\"\nimport Col from \"react-bootstrap/lib/Col\"\nimport debounce from \"lodash/debounce\"\nimport StickyBox from \"react-sticky-box\"\n\nimport * as VenuesAPI from \"../apis/VenuesAPI\"\nimport { diff_in_days } from \"../utils/dates/diff_in_days\"\nimport { setToLocalStorage, getFromLocalStorage } from \"../utils/localStorage\"\nimport BrowserLocationHelper from \"../utils/browser_location_helper\"\nimport sendAddressToIntercom from \"../utils/Intercom/sendAddressToIntercom\"\nimport EmptyVenuesAlert from \"./components/EmptyVenuesAlert/EmptyVenuesAlert\"\nimport CampaignsBannerHorizontalList from \"./components/CampaignsBanner/CampaignsBannerHorizontalList\"\nimport VenueChooserSearchBar from \"./components/filters/VenueChooserSearchBar\"\nimport VenueCategoriesChooser from \"./components/filters/VenueCategoriesChooser\"\nimport VenueFeaturesChooser from \"./components/filters/VenueFeaturesChooser\"\nimport VenuesFilterModal from \"./components/filters/VenuesFilterModal/index.jsx\"\nimport LoadingVenues from \"./components/LoadingVenues\"\nimport ErrorMessage from \"./components/ErrorMessage\"\nimport ServicesList from \"./ServicesList\"\nimport VenuesList from \"./VenuesList\"\nimport ZoneNotCovered from \"./ZoneNotCovered/\"\nimport { ORDER_MODE } from \"./OrderMode\"\n\nimport {\n gtmSetUserProperties,\n logVenueClicked,\n logServiceClicked,\n} from \"../apis/Analytics/gtmActions\"\nimport { GetSearchedServices } from \"../apis/VenuesAPI\"\n\nconst storejs = require(\"store\")\n\nimport style from \"./style.module.sass\"\n\nconst FILTERING_EXPIRATION = \"filtering_expiration\"\nconst FILTERING_CATEGORIES = \"filtering_categories\"\nconst FILTERING_FEATURES = \"filtering_features\"\n\nfunction getVenueURL(url, citySlug, venueSlug) {\n return url.replace(\":city\", citySlug).replace(\":restaurant\", venueSlug)\n}\n\nfunction getInitialSelectedFeatures() {\n return {\n creditCard: false,\n discount: false,\n cash: false,\n new: false,\n promotion: false,\n }\n}\n\nfunction getInitialCategories(categories) {\n return categories\n .map((category) => {\n return {\n id: category.id,\n name: category.name,\n is_root: category.is_root,\n selected: false,\n }\n })\n .filter((category) => !category.is_root)\n}\n\nexport default class VenueChooserApp extends React.Component {\n constructor(props) {\n super(props)\n\n // check and reset stored filtering\n let now = new Date()\n let expiration = storejs.get(FILTERING_EXPIRATION)\n if (now > expiration) {\n storejs.set(FILTERING_CATEGORIES, null)\n storejs.set(FILTERING_FEATURES, null)\n }\n storejs.set(FILTERING_EXPIRATION, now.setMinutes(now.getMinutes() + 30))\n\n this.state = {\n errorMessage: null,\n categories: [],\n showFilterModal: false,\n resultsCount: 0,\n venues: [],\n isSearching: false,\n isLoading: false,\n searchFilteredVenues: [],\n searchFilteredServices: [],\n loaded: false,\n takeAwaySelected: false,\n selectedFeatures: {},\n }\n }\n\n componentDidMount() {\n this.loadVenues()\n }\n\n loadVenues = () => {\n let queryParam = {}\n\n if (JSON.parse(getFromLocalStorage(\"take_away\")) === true) {\n this.setState({\n takeAwaySelected: true,\n })\n queryParam = { take_away: true }\n }\n\n VenuesAPI.getVenues(this.props.location, queryParam)\n .then((data) => {\n if (data.delivery_zone) {\n gtmSetUserProperties({ delivery_zone: data.delivery_zone.name })\n\n sendAddressToIntercom(this.props.location, data.delivery_zone.name)\n }\n\n let categories = getInitialCategories(data.venue_categories)\n let storedCategories = storejs.get(FILTERING_CATEGORIES) || []\n categories.forEach((category) => {\n if (\n storedCategories.some((stored) => {\n return category.id === stored.id && stored.selected\n })\n ) {\n category.selected = true\n }\n })\n storejs.set(FILTERING_CATEGORIES, categories)\n\n let features = getInitialSelectedFeatures()\n let storedFeatures = storejs.get(FILTERING_FEATURES) || {}\n for (let key in features) {\n features[key] = features[key] || storedFeatures[key]\n }\n storejs.set(FILTERING_FEATURES, features)\n\n this.setState({\n loaded: true,\n zoneNotCovered: !data.delivery_zone && data.venues.length === 0,\n venues: data.venues,\n categories: categories,\n selectedFeatures: features,\n })\n })\n .catch((err) => {\n // TODO: missing handling errors\n this.setState({\n errorMessage: I18n.t(\"pages.locations.venues.generic_loading_error\"),\n })\n })\n }\n\n toggleTakeAwayModeWithLocalStorage = (takeawayMode) => {\n this.setState({\n takeAwaySelected: takeawayMode,\n })\n setToLocalStorage(\"take_away\", takeawayMode)\n }\n\n handleOnAllCategoriesSelected = () => {\n let newCategories = getInitialCategories(this.state.categories)\n storejs.set(FILTERING_CATEGORIES, newCategories)\n this.setState({\n categories: newCategories,\n })\n }\n\n handleOnCategorySelected = (id) => {\n let categories = this.state.categories\n\n for (let category of categories) {\n if (category.id === id) {\n category.selected = !category.selected\n break\n }\n }\n\n storejs.set(FILTERING_CATEGORIES, categories)\n this.setState({\n categories: categories,\n })\n }\n\n handleVenueClick = (event, venue) => {\n event.stopPropagation()\n\n const { slug, name, street_name, city, delivery_zone } = venue\n const { showVenueURL } = this.props\n const citySlug = delivery_zone ? delivery_zone.slug : city\n\n const url = getVenueURL(showVenueURL, citySlug, slug)\n\n logVenueClicked(`${name} - ${street_name}, ${city}`)\n\n if (event.shiftKey || event.ctrlKey || event.metaKey) {\n window.open(url, \"_blank\")\n } else {\n BrowserLocationHelper.ChangeURL(url)\n }\n }\n\n handleServiceClick = (venue, service) => {\n const { slug, name, street_name, city, delivery_zone } = venue\n const { showVenueURL } = this.props\n const citySlug = delivery_zone ? delivery_zone.slug : city\n\n const url = getVenueURL(showVenueURL, citySlug, slug)\n\n logServiceClicked(\n `${service?.name || \"no_name\"} - ${name} - ${street_name}, ${city}`\n )\n\n BrowserLocationHelper.ChangeURL(\n url +\n `?service_id=${service.id}&service_section_id=${\n service.section?.id || \"\"\n }`\n )\n }\n\n handleShowFilterModal = () => {\n this.setState({ showFilterModal: true })\n }\n\n handleOnCloseFilterModal = () => {\n this.setState({ showFilterModal: false })\n }\n\n handleOnClearFilterClicked = () => {\n storejs.set(FILTERING_CATEGORIES, null)\n storejs.set(FILTERING_FEATURES, null)\n\n this.setState({\n showFilterModal: false,\n selectedFeatures: getInitialSelectedFeatures(),\n categories: getInitialCategories(this.state.categories),\n })\n }\n\n handleTakeawayChange = () => {\n this.setState({ takeAwayChangeLoading: true }, () => {\n const queryParam = !this.state.takeAwaySelected ? { take_away: true } : {}\n\n VenuesAPI.getVenues(this.props.location, queryParam)\n .then((data) => {\n this.setState({\n takeAwayChangeLoading: false,\n loaded: true,\n zoneNotCovered: false,\n venues: data.venues,\n categories: getInitialCategories(data.venue_categories),\n })\n this.toggleTakeAwayModeWithLocalStorage(!this.state.takeAwaySelected)\n })\n .catch((err) => {\n // TODO: handle all error cases (i.e. err is undefined)\n if (err && err.indexOf && err.indexOf(\"zone-not-covered\") !== -1) {\n this.setState({\n takeAwayChangeLoading: false,\n loaded: true,\n venues: [],\n categories: [],\n zoneNotCovered: true,\n })\n } else {\n this.setState({ takeAwayChangeLoading: false })\n }\n })\n })\n }\n\n handleOnFeatureSelected = (name) => {\n const selectedFeatures = this.state.selectedFeatures\n selectedFeatures[name] = !selectedFeatures[name]\n\n storejs.set(FILTERING_FEATURES, selectedFeatures)\n this.setState({ selectedFeatures })\n }\n\n getVenueCategories() {\n return this.state.categories\n }\n\n getVisibleVenues() {\n const selectedCategoriesIds = this.getSelectedVenueCategories().map(\n (category) => category.id\n )\n\n let venues = this.state.isSearching\n ? this.state.searchFilteredVenues\n : this.state.venues\n\n // Filter venues that does not accept discount codes\n if (this.state.selectedFeatures[\"discount\"]) {\n venues = venues.filter((venue) => venue.accepts_discount_codes === true)\n }\n\n // Filter venues that does not accept credit cards\n if (this.state.selectedFeatures[\"creditCard\"]) {\n venues = venues.filter((venue) => venue.accepts_stripe === true)\n }\n\n // Filter venues that does not accept cash\n if (this.state.selectedFeatures[\"cash\"]) {\n venues = venues.filter((venue) => venue.accepts_cash === true)\n }\n\n // Filter venues that are new\n if (this.state.selectedFeatures[\"new\"]) {\n venues = venues.filter(\n (venue) => -diff_in_days(venue.first_published_at) < 30\n )\n }\n\n // Filter venues that have promotions\n if (this.state.selectedFeatures[\"promotion\"]) {\n venues = venues.filter((venue) => !!venue.promotion)\n }\n\n // Filter by selected categories\n if (selectedCategoriesIds.length === 0) {\n return venues\n } else {\n return venues.filter((venue) => {\n return venue.venue_category_ids.some(\n (category_id) => selectedCategoriesIds.indexOf(category_id) !== -1\n )\n })\n }\n }\n\n handleSearchOnVenues = (text) => {\n // filter venues and venues' services based on searchbar text\n if (!!text.trim()) {\n let filtered = this.state.venues.filter((el) => {\n return (el?.name || \"\").toLowerCase().includes(text.toLowerCase())\n })\n this.setState({ isSearching: true, searchFilteredVenues: filtered })\n this.handleSearchOnServices(text)\n } else {\n this.setState({\n isLoading: false,\n isSearching: false,\n searchFilteredServices: [],\n })\n }\n }\n\n handleSearchOnServices = (text) => {\n let venueIds = this.state.venues.map((v) => v.id)\n this.setState({ isLoading: true })\n GetSearchedServices(text, venueIds)\n .then((res) => {\n this.setState({\n isLoading: false,\n searchFilteredServices: res?.dishes || [],\n })\n })\n .catch((err) => {\n this.setState({ isLoading: false })\n })\n }\n\n getSelectedVenueCategories() {\n return this.getVenueCategories().filter(\n (category) => category.selected === true\n )\n }\n\n getAppliedFiltersCount() {\n let count = this.getSelectedVenueCategories().length\n\n count += Object.values(this.state.selectedFeatures).filter(\n (value) => value === true\n ).length\n\n return count\n }\n\n getOrderMode() {\n return this.state.takeAwaySelected ? ORDER_MODE.PICKUP : ORDER_MODE.DELIVERY\n }\n\n renderSearchBar() {\n const handler = debounce(this.handleSearchOnVenues, 1000)\n\n return (\n
\n \n \n )\n }\n\n render() {\n if (this.state.errorMessage) {\n return
\n }\n\n if (!this.state.loaded) {\n return
\n }\n\n const venues = this.getVisibleVenues()\n const { zoneNotCovered } = this.state\n const { location } = this.props\n const appliedFiltersCount = this.getAppliedFiltersCount()\n const venuesCount = venues.length\n\n return (\n
\n
{this.renderSearchBar()}
\n
\n
\n \n {this.renderSearchBar()}\n
\n
\n {I18n.t(\"pages.locations.venues.features.title\")}\n
\n
\n
\n
\n {I18n.t(\"pages.locations.venues.cuisines.title\")}\n
\n
\n
\n
\n \n\n
\n {/* TODO: handle TLT specific campaign banners */}\n {/*
\n \n
*/}\n\n
\n {venuesCount > 0 && (\n
\n {venuesCount}{\" \"}\n {venuesCount > 1\n ? I18n.t(\"pages.locations.venues.plural\")\n : I18n.t(\"pages.locations.venues.singular\")}\n
\n )}\n\n {appliedFiltersCount > 0 && (\n
\n \n {I18n.t(\"pages.locations.venues.features.remove_filters\") +\n \" \"}\n ({appliedFiltersCount})\n
\n )}\n
\n\n {zoneNotCovered &&
}\n {!zoneNotCovered &&\n venuesCount === 0 &&\n !this.state.isLoading &&\n this.state.searchFilteredServices.length === 0 ? (\n
\n ) : (\n
\n \n \n
\n )}\n
\n
\n\n
\n
\n \n {appliedFiltersCount}\n
\n
\n
\n
\n )\n }\n}\n","import { intercomSendData, intercomTrackEvent } from './intercomHelper'\n\nexport default function sendAddressToIntercom(location, deliveryZoneName) {\n // Update user or visitor search data on Intercom\n const searchedZone = {\n 'TLT - Last searched city': location.city,\n 'TLT - Last searched address': location.street_name,\n 'TLT - Last searched delivery zone': deliveryZoneName\n };\n\n intercomSendData(searchedZone);\n intercomTrackEvent('covered_address_search', searchedZone);\n}\n","import React, { useState } from \"react\"\nimport SearchPlacesForm from \"../SearchPlacesForm/SearchPlacesForm\"\n\nimport style from \"./ChangeAddressForm.module\"\n\n// ----------------------------------------------------------------------------\n\nfunction ChangeAddressForm(props) {\n // -------------------------------------\n // Props destructuring\n // -------------------------------------\n\n const { deliveryAddress = undefined, apiKey, path } = props\n\n // -------------------------------------\n // Hooks (e.g. useState, useMemo ...)\n // -------------------------------------\n\n const [isAddressChangeRequested, setIsAddressChangeRequested] = useState(\n false\n )\n\n // -------------------------------------\n // Effects\n // -------------------------------------\n\n // -------------------------------------\n // Component functions\n // -------------------------------------\n\n function handleChangeAddress() {\n setIsAddressChangeRequested(true)\n }\n\n function isFilled() {\n return (\n !!deliveryAddress.latitude &&\n !!deliveryAddress.longitude &&\n !!deliveryAddress.street_name &&\n !!deliveryAddress.city\n )\n }\n\n function formatAddress(deliveryAddress) {\n return isFilled(deliveryAddress)\n ? `${deliveryAddress?.street_name || \"\"}${\n deliveryAddress?.street_number\n ? \" \" + deliveryAddress?.street_number\n : \"\"\n }, ${deliveryAddress?.city}`\n : \"\"\n }\n\n function getAddress() {\n return formatAddress(deliveryAddress)\n }\n\n function renderChangeAddress() {\n if (isFilled() && !isAddressChangeRequested) {\n return (\n
\n \n {I18n.t(\"pages.venues.show.change_address_form.delivery_in\", {\n address: getAddress(),\n })}\n \n {` - ${I18n.t(\n \"pages.venues.show.change_address_form.change_address\"\n )}`}\n
\n )\n } else {\n return (\n
\n )\n }\n }\n\n // -------------------------------------\n // Component local variables\n // -------------------------------------\n\n // -------------------------------------\n\n return
{renderChangeAddress()}
\n}\n\n// ----------------------------------------------------------------------------\n\nexport default ChangeAddressForm\n","import React from 'react';\n\nconst PromotionBox = ({ description }) => {\n return (\n
\n
\n \n
\n
\n
\n {I18n.t(\"pages.venues.show.venue_details.promotion\")}\n
\n
\n {description}\n
\n
\n
\n )\n}\n\nexport default PromotionBox;\n","import React from \"react\"\nimport NavbarCartItem from \"../NavbarCartItem/NavbarCartItem\"\n\nimport style from \"./BottomCartItem.module\"\nimport throttle from \"lodash/throttle\";\n\nconst SM = 992\n\nexport default class BottomCartItem extends React.Component {\n constructor(props) {\n super(props)\n this.state = {\n visible: false,\n }\n\n this.ref = React.createRef()\n }\n\n componentDidMount() {\n document.addEventListener(\"scroll\", this.onScroll)\n\n if (window.innerWidth < SM) {\n this.setState({ visible: true })\n }\n }\n\n componentWillUnmount() {\n document.removeEventListener(\"scroll\", this.onScroll)\n }\n\n onScroll = throttle(() => {\n if (!this.ref) {\n return\n }\n\n if (window.pageYOffset > 180) {\n this.setState({ visible: true })\n } else {\n this.setState({ visible: false })\n }\n }, 300)\n\n render() {\n const { storeUrl, isStorePage } = this.props\n const { visible } = this.state\n\n return (\n
\n \n
\n )\n }\n}\n","import React from \"react\"\nimport ShowMoreText from \"react-show-more-text\"\n\nimport style from \"./index.module.sass\"\n\n// ----------------------------------------------------------------------------\n\nfunction VenueDescriptionWithShowMore(props) {\n // -------------------------------------\n // Props destructuring\n // -------------------------------------\n\n const { venue } = props\n\n // -------------------------------------\n // Hooks (e.g. useState, useMemo ...)\n // -------------------------------------\n\n // -------------------------------------\n // Effects\n // -------------------------------------\n\n // -------------------------------------\n // Component functions\n // -------------------------------------\n\n // -------------------------------------\n // Component local variables\n // -------------------------------------\n\n // -------------------------------------\n\n // if no description use standard copy\n if (!venue.description || venue.description.length === 0) {\n let categories = venue.venue_categories.map((el, index) => {\n return (index === 0 ? \"\" : \" \") + el.name\n })\n return (\n
\n {I18n.t(\"pages.venues.show.venue_details.default_description\", {\n venue_name: venue.name,\n venue_categories: categories,\n })}\n
\n )\n } else {\n return (\n
\n {venue.description}\n \n )\n }\n}\n\n// ----------------------------------------------------------------------------\n\nexport default VenueDescriptionWithShowMore\n","/* eslint no-console:0 */\n// This file is automatically compiled by Webpack, along with any other files\n// present in this directory. You're encouraged to place your actual application logic in\n// a relevant structure within app/javascript and only use these pack files to reference\n// that code so it'll be compiled.\n//\n// To reference this file, add <%= javascript_pack_tag 'application' %> to the appropriate\n// layout file, like app/views/layouts/application.html.erb\n\nimport 'core-js/stable'\nimport 'regenerator-runtime/runtime'\n\nimport ReactOnRails from \"react-on-rails\"\n\n// From old Sprockets files\nimport \"../utils/console_log\"\nimport \"../utils/page-ready\"\nimport \"../utils/affix\"\nimport \"../utils/alert-bar\"\nimport \"../utils/polyfills\"\n// import \"../utils/mobile-app-banner\" //@todo: Re add this\nimport \"../utils/topbar_web\" //@todo: Remove this\n// end sprockets files\n\nimport RequestUserPasswordToken from \"../bundles/RequestUserPasswordToken\";\nimport SignInUserLink from \"../bundles/SignInUserLink/SignInUserLink\";\nimport NavbarCartItem from \"../bundles/NavbarCartItem/NavbarCartItem\";\nimport CartContainer from \"../bundles/CartContainer/CartContainer\";\nimport DeliveryModeBox from \"../bundles/VenueServicesList/components/DeliveryModeBox\";\nimport VenueServicesList from \"../bundles/VenueServicesList/VenueServicesList\";\nimport CartSummaryModal from \"../bundles/CartSummaryModal\";\nimport UserSessionForm from \"../bundles/UserSessionForm/UserSessionForm\";\nimport CheckoutApp from \"../bundles/CheckoutApp/CheckoutApp\";\nimport SearchPlacesForm from \"../bundles/SearchPlacesForm/SearchPlacesForm\"\nimport OrderRecap from \"../bundles/OrderRecap/index.jsx\"\nimport ShareOrderFacebookButton from \"../bundles/SharingButtons/ShareOrderFacebookButton\";\nimport FacebookWallShareButton from \"../bundles/SharingButtons/FacebookWallShareButton\";\nimport ShareUrlBox from \"../bundles/SharingButtons/ShareUrlBox\";\nimport ChangeUserPasswordApp from \"../bundles/ChangeUserPasswordApp\";\nimport SelectAddressPage from \"../bundles/SelectAddressPage/SelectAddressPage\";\nimport VenueChooserApp from \"../bundles/VenueChooserApp/VenueChooserApp\";\nimport VenueBadges from \"../bundles/VenueChooserApp/VenuesList/VenueBox/VenueBadges/index.jsx\";\nimport ChangeAddressForm from \"../bundles/ChangeAddressForm\"\nimport PromotionBox from \"../bundles/VenueServicesList/components/Details/PromotionBox\";\nimport BottomCartItem from \"../bundles/BottomCartItem\";\nimport VenueDescriptionWithShowMore from \"../bundles/VenueServicesList/VenueDescriptionWithShowMore\"\nimport PaymentInProgressBanner from \"../bundles/PaymentApp/PaymentInProgressBanner\"\n\n// This is how react_on_rails can see the HelloWorld in the browser.\nReactOnRails.register({\n RequestUserPasswordToken,\n ChangeUserPasswordApp,\n SignInUserLink,\n NavbarCartItem,\n BottomCartItem,\n CartContainer,\n DeliveryModeBox,\n VenueServicesList,\n CartSummaryModal,\n UserSessionForm,\n CheckoutApp,\n SearchPlacesForm,\n OrderRecap,\n ChangeAddressForm,\n ShareOrderFacebookButton,\n ShareUrlBox,\n FacebookWallShareButton,\n SelectAddressPage,\n VenueChooserApp,\n VenueBadges,\n PromotionBox,\n VenueDescriptionWithShowMore,\n PaymentInProgressBanner\n});\n","import React, { useState } from \"react\"\n\nimport EmailInput from \"../ui-components/EmailInput\"\nimport SubmitButton from \"../ui-components/SubmitButton\"\nimport Row from \"../ui-components/Row\"\nimport Col from \"../ui-components/Col\"\nimport { RequestPasswordToken } from \"../apis/UserSessionAPI\"\n\nimport style from \"./RequestUserPasswordToken.module\"\n\nexport default function RequestUserPasswordToken() {\n // -------------------------------------\n // Props destructuring\n // -------------------------------------\n\n // -------------------------------------\n // Hooks (e.g. useState, useMemo ...)\n // -------------------------------------\n\n const [state, setState] = useState({\n email: \"\",\n error: false,\n tokenSent: false,\n submitDisabled: false,\n })\n\n // -------------------------------------\n // Effects\n // -------------------------------------\n\n // -------------------------------------\n // Component functions\n // -------------------------------------\n\n function handleEmailChanged(event) {\n setState({ ...state, email: event.target.value })\n }\n\n function handleSubmit(event) {\n event.preventDefault()\n\n setState({ ...state, tokenSent: false, error: false, submitDisabled: true })\n\n RequestPasswordToken(state.email)\n .then((res) => {\n setState({ ...state, tokenSent: true, submitDisabled: false })\n })\n .catch((error) => {\n setState({ ...state, error: true, submitDisabled: false })\n })\n }\n\n // -------------------------------------\n // Component local variables\n // -------------------------------------\n\n // -------------------------------------\n\n return (\n
\n
\n {I18n.t(\"pages.user_session.passwords.forgot_password\")}\n
\n\n
\n {I18n.t(\"pages.user_session.passwords.forgot_password_details\")}\n
\n\n
\n
\n )\n}\n","import React, { useState } from \"react\"\n\nimport { ChangePassword } from \"../apis/UserSessionAPI\"\nimport Row from \"../ui-components/Row\"\nimport Col from \"../ui-components/Col\"\nimport PasswordInput from \"../ui-components/PasswordInput\"\nimport SubmitButton from \"../ui-components/SubmitButton\"\nimport BrowserLocationHelper from \"../utils/browser_location_helper\"\n\nimport style from \"./ChangeUserPasswordApp.module\"\n\nexport default function ChangeUserPasswordApp(props) {\n // -------------------------------------\n // Props destructuring\n // -------------------------------------\n\n const { token } = props\n\n // -------------------------------------\n // Hooks (e.g. useState, useMemo ...)\n // -------------------------------------\n\n const [state, setState] = useState({\n password: \"\",\n error: false,\n submitDisabled: false,\n })\n\n // -------------------------------------\n // Effects\n // -------------------------------------\n\n // -------------------------------------\n // Component functions\n // -------------------------------------\n\n function handlePasswordChanged(event) {\n setState({ ...state, password: event.target.value })\n }\n\n function handleSubmit(event) {\n event.preventDefault()\n\n setState({ ...state, error: false, submitDisabled: true })\n\n ChangePassword(state.password, token)\n .then((res) => {\n BrowserLocationHelper.ChangeURL(\"/\")\n })\n .catch((error) => {\n setState({ ...state, error: true, submitDisabled: false })\n })\n }\n\n // -------------------------------------\n // Component local variables\n // -------------------------------------\n\n // -------------------------------------\n\n return (\n
\n
\n {I18n.t(\"pages.user_session.passwords.change_password\")}\n
\n\n
\n {I18n.t(\"pages.user_session.passwords.change_password_desc\")}\n
\n\n
\n
\n )\n}\n"],"sourceRoot":""}