Created
July 24, 2023 08:27
-
-
Save andyxmas/a048ac8afe6f7c62020894c2c9ab351e to your computer and use it in GitHub Desktop.
availability select
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { useState, useEffect } from "react"; | |
import { | |
Select, | |
useAppMetafields, | |
BlockStack, | |
useApplyAttributeChange, | |
useTranslate, | |
TextField, | |
useExtensionCapability, | |
useBuyerJourneyIntercept, | |
} from "@shopify/checkout-ui-extensions-react"; | |
const AvailabilitySelect = () => { | |
/** | |
* Variables | |
*/ | |
const INPUT_COMPARATOR = "enter-manually"; | |
const translate = useTranslate(); | |
const applyAttributesChange = useApplyAttributeChange(); | |
// Fetch the metafield at the shop level | |
const availabilityOptionsArray = useAppMetafields({ | |
namespace: "checkout", | |
key: "recipient-availability-options", | |
}); | |
let availabilityOptions = []; | |
if ( | |
availabilityOptionsArray.length && | |
availabilityOptionsArray[0].metafield?.value | |
) { | |
availabilityOptions = JSON.parse( | |
availabilityOptionsArray[0].metafield.value | |
); | |
} | |
/** | |
* State | |
*/ | |
const [selection, setSelection] = useState(""); | |
const [showTextField, setShowTextField] = useState(false); | |
const [textFieldInput, setTextFieldInput] = useState(""); | |
const [textFieldPositionInput, setTextFieldPositionInput] = useState(""); | |
const [validationError, setValidationError] = useState(false); | |
const [selectValidationError, setSelectValidationError] = useState(false); | |
const canBlockProgress = useExtensionCapability("block_progress"); | |
// If textFieldInput is not valid, show validation errors | |
useEffect(() => { | |
if (canBlockProgress && !isTextFieldSet()) { | |
showValidationErrors(); | |
return; | |
} | |
clearValidationErrors(); | |
}, [textFieldInput]); | |
// Block progress if no selection is made | |
useEffect(() => { | |
if (canBlockProgress && !isSelectionSet()) { | |
showValidationErrors(); | |
return; | |
} | |
clearValidationErrors(); | |
}, [selection]); | |
/** | |
* Block progress | |
*/ | |
useBuyerJourneyIntercept(() => { | |
let response = { | |
behavior: "allow", | |
perform: (result) => { | |
// Ensure any errors are hidden | |
clearValidationErrors(); | |
}, | |
}; | |
if (showTextField && textFieldInput.trim().length === 0) { | |
response = { | |
behavior: "block", | |
reason: translate("availability.error.reason"), | |
perform: (result) => { | |
// If we were able to block progress, set a validation error | |
if (result.behavior === "block") | |
setValidationError(translate("availability.error.label")); | |
}, | |
}; | |
} | |
if (selection.trim().length === 0) { | |
response = { | |
behavior: "block", | |
reason: translate("availability.error.reason"), | |
perform: (result) => { | |
// If we were able to block progress, set a validation error | |
if (result.behavior === "block") | |
setSelectValidationError( | |
translate("availability.duration.error.reason") | |
); | |
}, | |
}; | |
} | |
return response; | |
}, [textFieldInput, showTextField, selection]); | |
/** | |
* Methods | |
*/ | |
const isTextFieldSet = () => { | |
return textFieldInput !== ""; | |
}; | |
const isSelectionSet = () => { | |
return selection !== ""; | |
}; | |
const showValidationErrors = () => { | |
setValidationError(true); | |
}; | |
const clearValidationErrors = () => { | |
setValidationError(false); | |
setSelectValidationError(false); | |
}; | |
/** | |
* Setter to determine if the text field should be rendered | |
* @param {*} value input select value | |
* @returns {void} | |
*/ | |
const canRenderTextField = (value) => { | |
if (!value) { | |
setShowTextField(false); | |
return; | |
} | |
if (value.toLowerCase().replace(/ /g, "-") !== INPUT_COMPARATOR) { | |
setShowTextField(false); | |
return; | |
} | |
setShowTextField(true); | |
}; | |
return ( | |
<BlockStack> | |
<TextField | |
label={translate("recipient.label")} | |
type="text" | |
value={textFieldPositionInput} | |
onChange={(value) => { | |
setTextFieldPositionInput(value); | |
applyAttributesChange({ | |
type: "updateAttribute", | |
key: "Recipient Position", | |
value: `${value}`, | |
}); | |
}} | |
/> | |
<Select | |
label={translate("availability.label")} | |
value={selection} | |
error={selectValidationError} | |
onChange={(value) => { | |
setSelection(value); | |
applyAttributesChange({ | |
type: "updateAttribute", | |
key: "Availability", | |
value: `${value}`, | |
}); | |
canRenderTextField(value); | |
}} | |
options={[ | |
{ | |
label: translate("availability.option.label"), | |
value: "select option", | |
disabled: true, | |
}, | |
].concat( | |
availabilityOptions.map((option) => { | |
return { | |
value: option, | |
label: option, | |
}; | |
}) | |
)} | |
/> | |
{showTextField && ( | |
<TextField | |
label={translate("availability.duration.label")} | |
type="text" | |
value={textFieldInput} | |
error={validationError} | |
required={canBlockProgress} | |
onChange={(value) => { | |
setTextFieldInput(value); | |
applyAttributesChange({ | |
type: "updateAttribute", | |
key: "Vessel Duration", | |
value: `${value}`, | |
}); | |
}} | |
/> | |
)} | |
</BlockStack> | |
); | |
}; | |
export { AvailabilitySelect }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment