@chakra-ui/react#Accordion TypeScript Examples
The following examples show how to use
@chakra-ui/react#Accordion.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: index.tsx From engine with MIT License | 6 votes |
EditElement: view = ({ showV2 = observe.showV2 }) => {
if (!showV2) {
return null;
}
return (
<Box padding="4" height="100%">
<Accordion allowMultiple={true}>
<Details />
<Header />
<Guards />
<Body />
<Cleanup />
</Accordion>
</Box>
);
}
Example #2
Source File: ElementDescription.tsx From engine with MIT License | 6 votes |
Operations = ({ value, path, id }) => {
return (
<Accordion allowMultiple allowToggle key={Math.random()}>
{Object.entries(value).map(([name, op]) => (
<AccordionItem key={Math.random()}>
<AccordionButton p="0">
<OperationPath
key={Math.random()}
name={name}
op={op}
selectedPath={path}
/>
<AccordionIcon />
</AccordionButton>
<AccordionPanel
bg="gray.400"
p="0"
border="1px solid"
borderColor="gray.300"
>
<Dependencies op={op} id={id} />
</AccordionPanel>
</AccordionItem>
))}
</Accordion>
);
}
Example #3
Source File: index.tsx From dope-monorepo with GNU General Public License v3.0 | 6 votes |
ItemEntitiesPanel = (props: {itemEntities: ItemEntity[]}) => {
return (
<div>
<div style={{
paddingLeft: '1rem',
}}>
<Text>
{props.itemEntities.length}
</Text>
</div>
<Accordion>
{
props.itemEntities.map((itemEntity, i) => {
return <AccordionItem key={i}>
<h2>
<AccordionButton>
<Box flex='1' textAlign='left'>
#{i}: {itemEntity.name}
</Box>
<AccordionIcon />
</AccordionButton>
</h2>
<AccordionPanel pb={4}>
<Position object={itemEntity}/>
</AccordionPanel>
</AccordionItem>
})
}
</Accordion>
</div>
)
}
Example #4
Source File: AccordionPreview.tsx From openchakra with MIT License | 6 votes |
AccordionPreview: React.FC<IPreviewProps> = ({ component }) => {
const { props, ref } = useInteractive(component, true)
const { drop, isOver } = useDropComponent(component.id, acceptedTypes)
let boxProps: any = {}
if (isOver) {
props.bg = 'teal.50'
}
return (
<Box ref={drop(ref)} {...boxProps}>
<Accordion {...props}>
{component.children.map((key: string) => (
<ComponentPreview key={key} componentName={key} />
))}
</Accordion>
</Box>
)
}
Example #5
Source File: ConnectionSettings.tsx From bluebubbles-server with Apache License 2.0 | 5 votes |
ConnectionSettings = (): JSX.Element => {
const proxyService: string = (useAppSelector(state => state.config.proxy_service) ?? '').toLowerCase().replace(' ', '-');
return (
<Stack direction='column' p={5}>
<Flex flexDirection='row' justifyContent='flex-start' alignItems='center'>
<Text fontSize='2xl'>Connection Settings</Text>
<Popover trigger='hover'>
<PopoverTrigger>
<Box ml={2} _hover={{ color: 'brand.primary', cursor: 'pointer' }}>
<AiOutlineInfoCircle />
</Box>
</PopoverTrigger>
<PopoverContent>
<PopoverArrow />
<PopoverCloseButton />
<PopoverHeader>Information</PopoverHeader>
<PopoverBody>
<Text>
These settings will determine how your clients will connect to the server
</Text>
</PopoverBody>
</PopoverContent>
</Popover>
</Flex>
<Divider orientation='horizontal' />
<Spacer />
<ProxyServiceField />
<Spacer />
{(proxyService === 'ngrok') ? (<NgrokRegionField />) : null}
<Spacer />
{(proxyService === 'ngrok') ? (<NgrokAuthTokenField />) : null}
<Spacer />
<Divider orientation='horizontal' />
<ServerPasswordField />
<LocalPortField />
<Spacer />
<Accordion allowMultiple>
<AccordionItem>
<AccordionButton>
<Box flex='1' textAlign='left' width="15em">
Advanced Connection Settings
</Box>
<AccordionIcon />
</AccordionButton>
<AccordionPanel pb={4}>
<EncryptCommunicationsField />
<Box m={15} />
{(proxyService === 'dynamic-dns') ? (<UseHttpsField />) : null}
</AccordionPanel>
</AccordionItem>
</Accordion>
</Stack>
);
}
Example #6
Source File: FeatureSettings.tsx From bluebubbles-server with Apache License 2.0 | 5 votes |
FeatureSettings = (): JSX.Element => {
const hideDockIcon = (useAppSelector(state => state.config.hide_dock_icon) ?? false);
const useTerminal = (useAppSelector(state => state.config.start_via_terminal) ?? false);
return (
<section>
<Stack direction='column' p={5}>
<Text fontSize='2xl'>Features</Text>
<Divider orientation='horizontal' />
<Spacer />
<PrivateApiField />
<Spacer />
<AutoCaffeinateField />
<Spacer />
<AutoStartField />
<Spacer />
<FormControl>
<Checkbox id='hide_dock_icon' isChecked={hideDockIcon} onChange={onCheckboxToggle}>Hide Dock Icon</Checkbox>
<FormHelperText>
Hiding the dock icon will not close the app. You can open the app again via the status bar icon.
</FormHelperText>
</FormControl>
<Spacer />
<Accordion allowMultiple>
<AccordionItem>
<AccordionButton>
<Box flex='1' textAlign='left' width="15em">
Advanced Feature Settings
</Box>
<AccordionIcon />
</AccordionButton>
<AccordionPanel pb={4}>
<FormControl>
<Checkbox id='start_via_terminal' isChecked={useTerminal} onChange={onCheckboxToggle}>Always Start via Terminal</Checkbox>
<FormHelperText>
When BlueBubbles starts up, it will auto-reload itself in terminal mode.
When in terminal, type "help" for command information.
</FormHelperText>
</FormControl>
</AccordionPanel>
</AccordionItem>
</Accordion>
</Stack>
</section>
);
}
Example #7
Source File: ContainerWidget.tsx From ke with MIT License | 5 votes |
ContainerWidget = (props: any): JSX.Element => {
const {
setInitialValue,
submitChange,
resourceName,
mainDetailObject,
provider,
setMainDetailObject,
refreshMainDetailObject,
notifier,
user,
analytics,
ViewType,
containerStore,
containerErrorsStore,
widgets,
name,
isCollapsible = false,
helpText = '',
style,
accordionProps,
accordionItemProps,
accordionPanelProps,
AccordionButton: UserAccordionButton,
setCurrentState,
} = props
const containerContent = mountComponents({
setInitialValue,
submitChange,
resourceName,
mainDetailObject,
elements: widgets,
provider,
setMainDetailObject,
refreshMainDetailObject,
notifier,
user,
analytics,
ViewType,
containerStore,
containerErrorsStore,
setCurrentState,
})
const context = (containerStore as Store<object>).getState()
const isContainerCollapsible = getAccessor(isCollapsible, mainDetailObject, context)
const { getDataTestId } = useCreateTestId()
return isContainerCollapsible ? (
<Accordion allowToggle pt={4} {...accordionProps} {...getDataTestId(props)}>
<AccordionItem {...accordionItemProps}>
{UserAccordionButton ? (
<UserAccordionButton>{helpText}</UserAccordionButton>
) : (
<h2>
<AccordionButton>
<Box flex="1" textAlign="left">
{helpText}
</Box>
<AccordionIcon />
</AccordionButton>
</h2>
)}
<AccordionPanel pb={4} {...accordionPanelProps}>
{containerContent}
</AccordionPanel>
</AccordionItem>
</Accordion>
) : (
<Box data-name={name} {...getDataTestId(props)} {...style}>
{containerContent}
</Box>
)
}
Example #8
Source File: Profile.tsx From dope-monorepo with GNU General Public License v3.0 | 5 votes |
Profile = () => {
const [section, setSection] = useQueryParam('section', SECTIONS[0]);
const [searchValue, setSearchValue] = useQueryParam('q', '');
const debouncedSearchValue = useDebounce<string>(searchValue, 250);
const handleSearchChange = (event: ChangeEvent<HTMLInputElement>) => {
const value = event.target.value;
setSearchValue(value);
};
return (
<>
<Stack
margin="0"
spacing="8px"
width="100%"
padding="16px"
background="white"
borderBottom="2px solid black"
direction={['column', 'column', 'row']}
>
<InputGroup>
<Input
className="search"
placeholder="Search…"
size="sm"
border="2px solid black"
borderRadius="4px"
onChange={handleSearchChange}
value={searchValue}
_focus={{ boxShadow: '0' }}
/>
{searchValue !== '' && (
<InputRightElement height="100%">
<Image
width="16px"
src="/images/icon/circle-clear-input.svg"
alt="Search"
onClick={() => setSearchValue('')}
cursor="pointer"
/>
</InputRightElement>
)}
</InputGroup>
</Stack>
<Accordion
allowToggle
defaultIndex={SECTIONS.findIndex(val => val === section)}
onChange={idx => {
if (idx == -1) return;
const sectionIdx = Array.isArray(idx) ? idx[0] : idx;
setSection(SECTIONS[sectionIdx]);
}}
>
<Section>
<Hustlers searchValue={debouncedSearchValue} />
</Section>
<Section>
<Gear searchValue={debouncedSearchValue} />
</Section>
<Section>
<Dopes searchValue={debouncedSearchValue} />
</Section>
</Accordion>
</>
);
}
Example #9
Source File: index.tsx From dope-monorepo with GNU General Public License v3.0 | 5 votes |
PlayerPanel = (props: {player: Player}) => {
const player = props.player;
return (
<Accordion>
<AccordionItem>
<h2>
<AccordionButton>
<Box flex='1' textAlign='left'>
Basic info
</Box>
<AccordionIcon />
</AccordionButton>
</h2>
<AccordionPanel pb={4}>
<InputGroup size="sm">
<InputLeftAddon children='Name' />
<Input onChange={(e) => player.name = e.target.value} placeholder={player.name} />
</InputGroup>
<div>
<Position object={player} />
</div>
</AccordionPanel>
</AccordionItem>
<AccordionItem>
<h2>
<AccordionButton>
<Box flex='1' textAlign='left'>
Quests
</Box>
<AccordionIcon />
</AccordionButton>
</h2>
<AccordionPanel pb={4}>
{player.questManager.quests.map((quest, i) => {
<Text>
{quest.name}: {quest.description}
</Text>
})}
</AccordionPanel>
</AccordionItem>
</Accordion>
)
}
Example #10
Source File: faq.tsx From coindrop with GNU General Public License v3.0 | 5 votes |
FAQ: FunctionComponent = () => {
const theme = useTheme();
const panelBgColor = useColorModeValue("gray.50", undefined);
return (
<Box>
<Box my={6}>
<Heading as="h1" textAlign="center">
FAQ
</Heading>
<Text textAlign="center">
Frequently Asked Questions
</Text>
</Box>
<Container maxW={theme.breakpoints.lg}>
<Accordion defaultIndex={-1} allowToggle>
{accordionText.map(({title, body}) => (
<AccordionItem key={title}>
<AccordionButton>
<Box flex="1" textAlign="left">
{title}
</Box>
<AccordionIcon />
</AccordionButton>
<AccordionPanel>
<Box
p={4}
bg={panelBgColor}
>
{body}
</Box>
</AccordionPanel>
</AccordionItem>
))}
</Accordion>
</Container>
<Text textAlign="center" mt={4} fontSize="sm">
{"Do you have a question that's not answered here? Send it to "}
<Link href={`mailto:${coindropEmail}`} isExternal>
{coindropEmail}
</Link>
</Text>
</Box>
);
}
Example #11
Source File: index.tsx From dope-monorepo with GNU General Public License v3.0 | 4 votes |
HustlersPanel = (props: { hustlers: Hustler[] }) => {
const hustlers = props.hustlers;
return (
<Accordion allowToggle>
{hustlers.map((hustler, i) =>
<AccordionItem key={i}>
<h2>
<AccordionButton>
<Box flex='1' textAlign='left'>
{hustler.name}: {hustler.hustlerId ?? 'No Hustler'}
<br/>
Citizen: {hustler instanceof Citizen ? '✅' : '❌'}
</Box>
<AccordionIcon />
</AccordionButton>
</h2>
<AccordionPanel pb={4}>
<InputGroup size="sm">
<InputLeftAddon children='Name' />
<Input onChange={(e) => hustler.name = e.target.value} placeholder={hustler.name} />
</InputGroup>
<div>
<Position object={hustler} />
</div>
<br />
<Accordion allowToggle>
{hustler instanceof Citizen ? <div>
<AccordionItem>
<h2>
<AccordionButton>
<Box flex='1' textAlign='left'>
Path
</Box>
<AccordionIcon />
</AccordionButton>
</h2>
<AccordionPanel pb={4}>
Repeat path:
<Checkbox defaultChecked={hustler.repeatPath} onChange={(e) => hustler.repeatPath = e.target.checked} />
<br />
Follow path:
<Checkbox defaultChecked={hustler.shouldFollowPath} onChange={(e) => hustler.shouldFollowPath = e.target.checked} />
<br />
<br />
{
hustler.path.map((p, i) =>
<div key={i}>
PathPoint #{i}
<Position object={p.position} />
<br />
</div>
)
}
</AccordionPanel>
</AccordionItem>
<AccordionItem>
<h2>
<AccordionButton>
<Box flex='1' textAlign='left'>
Conversations
</Box>
<AccordionIcon />
</AccordionButton>
</h2>
<AccordionPanel pb={4}>
{
hustler.conversations.map((c, i) =>
<div key={i}>
<Accordion>
{
c.texts.map((t, i) =>
<AccordionItem key={i}>
<h2>
<AccordionButton>
<Box flex='1' textAlign='left'>
{t.text}
</Box>
<AccordionIcon />
</AccordionButton>
</h2>
<AccordionPanel pb={4}>
<InputGroup size="sm">
<InputLeftAddon children='Text' />
<Input onChange={(e) => t.text = e.target.value} placeholder={t.text} />
</InputGroup>
<Text>
Choices
</Text>
{
t.choices ? t.choices.map((c, i) =>
<div key={i}>
<InputGroup size="sm">
<InputLeftAddon children='Text' />
<Input onChange={(e) => (t.choices!)[i] = e.target.value} placeholder={c} />
</InputGroup>
</div>
) : undefined
}
</AccordionPanel>
</AccordionItem>
)
}
</Accordion>
</div>
)
}
</AccordionPanel>
</AccordionItem>
</div> : undefined}
</Accordion>
</AccordionPanel>
</AccordionItem>
)}
</Accordion>
)
}
Example #12
Source File: index.tsx From dope-monorepo with GNU General Public License v3.0 | 4 votes |
LightsPanel = (props: { player: Player, lights: Phaser.GameObjects.LightsManager }) => {
const [, forceUpdate] = useReducer(x => x + 1, 0);
const player = props.player;
const lights = props.lights;
return (
<>
<div style={{
paddingLeft: '1rem',
}}>
Enabled: <Checkbox onChange={(e) => lights.active = e.target.checked} defaultChecked={lights.active}/>
<br/>
Number of lights: {lights.getLightCount()}
<br/>
Ambient color:
<input
type="color"
onChange={(e) => {
const value = e.target.value;
const color = value.substring(1);
const r = parseInt(color.substring(0, 2), 16) / 255;
const g = parseInt(color.substring(2, 4), 16) / 255;
const b = parseInt(color.substring(4, 6), 16) / 255;
lights.ambientColor.set(r, g, b);
}}
defaultValue={'#' +
(lights.ambientColor.r * 255).toString(16) +
(lights.ambientColor.g * 255).toString(16) +
(lights.ambientColor.b * 255).toString(16)}
/>
<br/>
<br />
<Button onClick={(e) => {
lights.addLight(player.x, player.y);
forceUpdate();
}}>
Add light
</Button>
<br />
<Button onClick={(e) => {
let layer: Phaser.GameObjects.Layer;
if (!(layer = (lights as any).pointLightLayer))
layer = (lights as any).pointLightLayer = player.scene.add.layer();
layer.add(lights.addPointLight(player.x, player.y));
forceUpdate();
}}>
Add pointlight
</Button>
</div>
<br/>
<Accordion defaultIndex={0}>
{
// getLights doesnt actually return an array of the lights... it returns an object with the dist and light
lights.getLights(player.scene.cameras.main).map((light, i) => {
const distance = (light as any).distance;
light = (light as any).light;
return <AccordionItem key={i}>
<h2>
<AccordionButton>
<Box flex='1' textAlign='left'>
Light: {light.x} {light.y}
<br />
PointLight: {light instanceof Phaser.GameObjects.PointLight ? '✅' : '❌'}
</Box>
<AccordionIcon />
</AccordionButton>
</h2>
<AccordionPanel pb={4}>
<Position object={light}/>
<InputGroup size="sm">
<InputLeftAddon children='Radius' />
<Input onChange={(e) => light.radius = Number.parseFloat(e.target.value) ?? 0} placeholder={light.radius.toString()} />
</InputGroup>
<InputGroup size="sm">
<InputLeftAddon children='Intensity' />
<Input onChange={(e) => light.intensity = Number.parseFloat(e.target.value) ?? 0} placeholder={light.intensity.toString()} />
</InputGroup>
<br/>
Visible: <Checkbox onChange={(e) => light.visible = e.target.checked} defaultChecked={light.visible}/>
<div>
Color:
<input
type="color"
onChange={(e) => {
const value = e.target.value;
const color = value.substring(1);
const r = parseInt(color.substring(0, 2), 16) / 255;
const g = parseInt(color.substring(2, 4), 16) / 255;
const b = parseInt(color.substring(4, 6), 16) / 255;
light.color.set(r, g, b);
}}
defaultValue={'#' +
((light.color as any).r * 255).toString(16).padStart(2, '0') +
((light.color as any).g * 255).toString(16).padStart(2, '0') +
((light.color as any).b * 255).toString(16).padStart(2, '0')}
/>
</div>
<br/>
<Button variant="cny" onClick={(e) => {
if (light instanceof Phaser.GameObjects.PointLight)
(light as any).layer.remove(light);
else
lights.removeLight(light);
forceUpdate();
}}>
Remove light
</Button>
</AccordionPanel>
</AccordionItem>
})
}
</Accordion>
</>
)
}
Example #13
Source File: index.tsx From dope-monorepo with GNU General Public License v3.0 | 4 votes |
WorldPanel = (props: {map: LDtkMapPack}) => {
const gameScene = props.map.displayLayers[0].scene as GameScene;
return (
<div>
<div style={{
paddingLeft: '1rem',
}}>
<Text>
Day color:
<input
type="color"
onChange={(e) => {
const value = e.target.value;
const color = value.substring(1);
const r = parseInt(color.substring(0, 2), 16);
const g = parseInt(color.substring(2, 4), 16);
const b = parseInt(color.substring(4, 6), 16);
gameScene.dayColor = [r, g, b];
}}
defaultValue={'#' +
gameScene.dayColor[0].toString(16) +
gameScene.dayColor[1].toString(16) +
gameScene.dayColor[2].toString(16)}
/>
<br/>
Night color:
<input
type="color"
onChange={(e) => {
const value = e.target.value;
const color = value.substring(1);
const r = parseInt(color.substring(0, 2), 16);
const g = parseInt(color.substring(2, 4), 16);
const b = parseInt(color.substring(4, 6), 16);
gameScene.nightColor = [r, g, b];
}}
defaultValue={'#' +
gameScene.nightColor[0].toString(16) +
gameScene.nightColor[1].toString(16) +
gameScene.nightColor[2].toString(16)}
/>
<br/>
<br/>
Display Layers: {props.map.displayLayers.length}
<br/>
IntGrid Layers: {props.map.intGridLayers.length}
<br/>
Entities: {props.map.entities.length}
</Text>
</div>
<Accordion>
<AccordionItem>
<h2>
<AccordionButton>
<Box flex='1' textAlign='left'>
Display Layers
</Box>
<AccordionIcon />
</AccordionButton>
</h2>
</AccordionItem>
<AccordionItem>
<h2>
<AccordionButton>
<Box flex='1' textAlign='left'>
Collide layer
</Box>
<AccordionIcon />
</AccordionButton>
</h2>
<AccordionPanel pb={4}>
</AccordionPanel>
</AccordionItem>
<AccordionItem>
<h2>
<AccordionButton>
<Box flex='1' textAlign='left'>
IntGrid Layers
</Box>
<AccordionIcon />
</AccordionButton>
</h2>
</AccordionItem>
<AccordionItem>
<h2>
<AccordionButton>
<Box flex='1' textAlign='left'>
Entities
</Box>
<AccordionIcon />
</AccordionButton>
</h2>
<AccordionPanel pb={4}>
<Accordion>
{
props.map.entities.map((entity, i) => {
return <AccordionItem key={i}>
<h2>
<AccordionButton>
<Box flex='1' textAlign='left'>
#{i}: {entity.name}
</Box>
<AccordionIcon />
</AccordionButton>
</h2>
<AccordionPanel pb={4}>
<Position object={entity}/>
</AccordionPanel>
</AccordionItem>
})
}
</Accordion>
</AccordionPanel>
</AccordionItem>
</Accordion>
</div>
)
}
Example #14
Source File: StylesPanel.tsx From openchakra with MIT License | 4 votes |
StylesPanel: React.FC<Props> = ({ isRoot, showChildren, parentIsRoot, }) => ( <Accordion defaultIndex={[0]} allowMultiple> {!isRoot && ( <AccordionContainer title="Custom props"> <CustomPropsPanel /> </AccordionContainer> )} {!isRoot && !parentIsRoot && ( <AccordionContainer title="Parent"> <ParentInspector /> </AccordionContainer> )} {showChildren && ( <AccordionContainer title="Children"> <ChildrenInspector /> </AccordionContainer> )} {!isRoot && ( <> <AccordionContainer title="Layout"> <DisplayPanel /> </AccordionContainer> <AccordionContainer title="Spacing"> <PaddingPanel type="margin" /> <PaddingPanel type="padding" /> </AccordionContainer> <AccordionContainer title="Size"> <DimensionPanel /> </AccordionContainer> <AccordionContainer title="Typography"> <TextPanel /> </AccordionContainer> </> )} <AccordionContainer title="Backgrounds"> <ColorsControl withFullColor label="Color" name="backgroundColor" enableHues /> {!isRoot && ( <GradientControl withFullColor label="Gradient" name="bgGradient" options={[ 'to top', 'to top right', 'to top left', 'to bottom right', 'to bottom', 'to bottom left', 'to right', 'to left', ]} enableHues /> )} </AccordionContainer> {!isRoot && ( <> <AccordionContainer title="Border"> <BorderPanel /> </AccordionContainer> <AccordionContainer title="Effect"> <EffectsPanel /> </AccordionContainer> </> )} </Accordion> )
Example #15
Source File: PaymentMethodsInput.tsx From coindrop with GNU General Public License v3.0 | 4 votes |
PaymentMethodsInput: FC<Props> = ({ fieldArrayName, fields, control, register, remove, append }) => {
const { colors } = useTheme();
const paymentMethodsDataWatch: PaymentMethod[] = useWatch({
control,
name: fieldArrayName,
});
const [openAccordionItemIndex, setOpenAccordionItemIndex] = useState(-1);
useEffect(() => {
if (
paymentMethodsDataWatch[paymentMethodsDataWatch.length - 1]?.paymentMethodId === "default-blank"
|| paymentMethodsDataWatch[paymentMethodsDataWatch.length - 1]?.address === ""
) {
setOpenAccordionItemIndex(paymentMethodsDataWatch.length - 1);
}
}, [paymentMethodsDataWatch]);
const containsInvalidAddress = paymentMethodsDataWatch.some(paymentMethod => !paymentMethod.address);
const { isAddressTouched, setIsAddressTouched } = useContext(AdditionalValidation);
// optgroup not compatible with Chakra dark mode: https://github.com/chakra-ui/chakra-ui/issues/2853
// const optionsGroup = (category: Category) => {
// const optgroupLabels: Record<Category, string> = {
// "digital-wallet": 'Digital Wallets',
// "digital-asset": "Digital Assets",
// "subscription-platform": "Subscription Platforms",
// };
// return (
// <optgroup label={optgroupLabels[category]}>
// {paymentMethods
// .filter(paymentMethod => paymentMethod.category === category)
// .sort((a, b) => (a.id < b.id ? -1 : 1))
// .map(({ id, displayName }) => (
// <option
// key={id}
// value={id}
// style={{display: paymentMethodsDataWatch.map(paymentMethodDataWatch => paymentMethodDataWatch.paymentMethodId).includes(id) ? "none" : undefined }}
// >
// {displayName}
// </option>
// ))}
// </optgroup>
// );
// };
return (
<>
{fields.length < 1
? 'No payment methods defined yet.'
: (
<Accordion
allowToggle
defaultIndex={-1}
index={openAccordionItemIndex}
>
{
fields
.map((item, index) => {
const watchedData = paymentMethodsDataWatch.find(watchedPaymentMethod => watchedPaymentMethod.id === item.id);
const PaymentMethodIcon = paymentMethodIcons[watchedData?.paymentMethodId];
return (
<AccordionItem
key={item.id}
>
<AccordionButton
onClick={() => {
setIsAddressTouched(true);
if (openAccordionItemIndex !== index && !paymentMethodsDataWatch.find(paymentMethod => paymentMethod.address === "")) {
setOpenAccordionItemIndex(index);
} else {
setOpenAccordionItemIndex(undefined);
}
}}
>
<Flex flex="1" textAlign="left" align="center">
<Flex mr={1} align="center">
{PaymentMethodIcon ? <PaymentMethodIcon mr={2} /> : <QuestionOutlineIcon mr={2} />}
{paymentMethodNames[watchedData?.paymentMethodId] ?? 'Add payment method'}
</Flex>
{watchedData?.isPreferred && (
<Flex>
<StarIcon
ml={2}
size="16px"
color={colors.yellow['400']}
/>
<Text
as="span"
fontSize="xs"
ml={1}
>
<i>Preferred</i>
</Text>
</Flex>
)}
</Flex>
<AccordionIcon />
</AccordionButton>
<AccordionPanel pb={4} id={`accordion-panel-${watchedData.paymentMethodId}`}>
<input
ref={register()}
name={`${fieldArrayName}[${index}].id`}
defaultValue={item.id}
style={{display: 'none'}}
/>
<Box
display={paymentMethodNames[watchedData?.paymentMethodId] ? "none" : "block"}
data-cy={`select-payment-method-container-${watchedData.paymentMethodId}`}
>
<Select
name={`${fieldArrayName}[${index}].paymentMethodId`}
ref={register()}
defaultValue={paymentMethodNames[item.paymentMethodId] ? item.paymentMethodId : 'default-blank'}
isInvalid={containsInvalidAddress && isAddressTouched}
onChange={() => setIsAddressTouched(false)}
>
<option hidden disabled value="default-blank">Select...</option>
{/* optgroup not compatible with Chakra dark mode: https://github.com/chakra-ui/chakra-ui/issues/2853 */}
{Object.entries(paymentMethodNames)
.sort((a, b) => {
const [aId] = a;
const [bId] = b;
return aId < bId ? -1 : 1;
})
.map(([paymentMethodId, paymentMethodDisplayName]) => (
<option
key={paymentMethodId}
value={paymentMethodId}
style={{display: paymentMethodsDataWatch.map(paymentMethod => paymentMethod.paymentMethodId).includes(paymentMethodId) ? "none" : undefined }}
>
{paymentMethodDisplayName}
</option>
))}
</Select>
</Box>
<Box
mx={3}
display={paymentMethodNames[watchedData?.paymentMethodId] ? "block" : "none"}
>
<FormControl isRequired>
<FormLabel htmlFor={`${fieldArrayName}[${index}].address`}>Address</FormLabel>
<Input
id={`address-input-${watchedData.paymentMethodId}`}
name={`${fieldArrayName}[${index}].address`}
ref={register()}
defaultValue={item.address}
isInvalid={containsInvalidAddress && isAddressTouched}
/>
<Box>
<Checkbox
name={`${fieldArrayName}[${index}].isPreferred`}
ref={register()}
defaultValue={item?.isPreferred ? 1 : 0}
defaultIsChecked={item?.isPreferred}
mt={1}
colorScheme="yellow"
>
Preferred
</Checkbox>
</Box>
</FormControl>
</Box>
<Flex
justify={watchedData?.paymentMethodId === 'default-blank' ? 'space-between' : 'flex-end'}
mt={3}
wrap="wrap"
align="center"
>
{watchedData?.paymentMethodId === 'default-blank' && (
<Text fontSize="xs" ml={1}>
<Link href="/blog/payment-method-request" isExternal>
Payment method not listed?
</Link>
</Text>
)}
<Button
onClick={() => {
remove(index);
setIsAddressTouched(false);
}}
leftIcon={<MinusIcon />}
size="sm"
>
{'Remove '}
{/* {paymentMethodNames[watchedData?.paymentMethodId]} */}
</Button>
</Flex>
</AccordionPanel>
</AccordionItem>
);
})
}
</Accordion>
)}
<Flex
justify="center"
mt={2}
>
<Button
id="add-payment-method-button"
onClick={() => {
append({});
setIsAddressTouched(false);
}}
leftIcon={<AddIcon />}
variant="ghost"
size="sm"
isDisabled={
(
fields.length > 0
&& !paymentMethodNames[paymentMethodsDataWatch[paymentMethodsDataWatch.length - 1]?.paymentMethodId]
)
|| containsInvalidAddress
}
>
Add payment method
</Button>
</Flex>
</>
);
}