refactor: remove dropdown component and use combobox instead (#242)

This commit is contained in:
Camila Sosa Morales 2023-04-27 10:51:25 -03:00 committed by GitHub
parent fd4b7c953c
commit 9f48213e28
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 133 additions and 295 deletions

View File

@ -35,7 +35,7 @@
"uuid": "^9.0.0",
"@types/node": "^18.15.11",
"ts-node": "^10.9.1",
"typescript": "^5.0.4"
"typescript": "^5.0.4",
"web3": "^1.9.0"
}
}

View File

@ -5,14 +5,16 @@ const querystring = require('querystring');
import { v4 } from 'uuid';
import { nfaContract } from '@libs/nfa-contract';
export const submitBuildInfo = async (event: APIGatewayEvent): Promise<APIGatewayProxyResult> => {
export const submitBuildInfo = async (
event: APIGatewayEvent
): Promise<APIGatewayProxyResult> => {
try {
const eventData = querystring.parse(event.body);
const id = v4();
const buildInfo = {
buildId: id,
createdAt: new Date().toISOString(),
submittedData: eventData
submittedData: eventData,
};
// place holder call

View File

@ -1,45 +1,44 @@
import {
APIGatewayProxyResult,
APIGatewayEvent,
///APIGatewayEventRequestContext,
} from 'aws-lambda';
import { formatJSONResponse } from '@libs/api-gateway';
import { v4 } from 'uuid';
export const submitMintInfo = async (
event: APIGatewayEvent,
///context: APIGatewayEventRequestContext
): Promise<APIGatewayProxyResult> => {
try {
const id = v4();
/**if (!verifyAlchemySig(event.headers.xalchemywork)) {
APIGatewayProxyResult,
APIGatewayEvent,
///APIGatewayEventRequestContext,
} from 'aws-lambda';
import { formatJSONResponse } from '@libs/api-gateway';
import { v4 } from 'uuid';
export const submitMintInfo = async (
event: APIGatewayEvent
///context: APIGatewayEventRequestContext
): Promise<APIGatewayProxyResult> => {
try {
const id = v4();
/**if (!verifyAlchemySig(event.headers.xalchemywork)) {
throw new Error('Invalid sig');
}**/
if (event.body == undefined) {
throw new Error('Undefined data');
}
const mintInfo = {
buildId: id,
createdAt: new Date().toISOString(),
body: JSON.parse(event.body),
};
// check if we have it in mongo
// if so, trigger verification call
// if not, add to mongo
return formatJSONResponse({
mintInfo,
});
} catch (e) {
return formatJSONResponse({
status: 500,
message: e,
});
if (event.body == undefined) {
throw new Error('Undefined data');
}
};
const mintInfo = {
buildId: id,
createdAt: new Date().toISOString(),
body: JSON.parse(event.body),
};
// check if we have it in mongo
// if so, trigger verification call
// if not, add to mongo
return formatJSONResponse({
mintInfo,
});
} catch (e) {
return formatJSONResponse({
status: 500,
message: e,
});
}
};

View File

@ -10,4 +10,4 @@ export const newMint = {
},
},
],
};
};

View File

@ -1,8 +1,16 @@
var Web3 = require('web3');
var web3 = new Web3(Web3.givenProvider || "ws://localhost:17895");
var web3 = new Web3(Web3.givenProvider || 'ws://localhost:17895');
export const logDecoder = (eventFieldsABI: { indexed: boolean; internalType: string; name: string; type: string; }[], data: string, topics: string[]) => {
return web3.eth.abi.decodeLog(eventFieldsABI, data, topics);
export const logDecoder = (
eventFieldsABI: {
indexed: boolean;
internalType: string;
name: string;
type: string;
}[],
data: string,
topics: string[]
) => {
return web3.eth.abi.decodeLog(eventFieldsABI, data, topics);
};

View File

@ -1,186 +0,0 @@
import { Listbox, Transition } from '@headlessui/react';
import { Fragment } from 'react';
import { Flex } from '@/components';
import { Icon } from '@/components/core/icon';
type DropdownOptionProps = {
option: DropdownItem;
};
const DropdownOption: React.FC<DropdownOptionProps> = ({
option,
}: DropdownOptionProps) => (
<Listbox.Option
className={({ active }) =>
`relative cursor-default select-none py-2 px-3.5 text-slate11 rounded-xl mb-2 text-sm max-w-full ${
active ? 'bg-slate5 text-slate12' : 'bg-transparent'
}`
}
value={option}
>
{({ selected, active }) => (
<Flex css={{ justifyContent: 'space-between' }}>
<span
className={`${
active ? 'text-slate12' : 'text-slate11'
} max-w-full break-words pr-5`}
>
{option.label}
</span>
{selected && (
<Icon
name="check"
color="white"
css={{
position: 'absolute',
top: '$0',
bottom: '$0',
right: '$0',
display: 'flex',
alignItems: 'center',
pr: '$4',
}}
/>
)}
</Flex>
)}
</Listbox.Option>
);
type DropdownButtonProps = {
/**
* The selected value of the dropdown.
*/
selectedValue: DropdownItem | undefined;
/**
* If it's true, the list of options will be displayed
*/
open: boolean;
/**
* Background color of the dropdown. Should be on tailwind palette.
*/
backgroundColor?: string;
/**
* Text color of the dropdown. Should be on tailwind palette.
*/
textColor?: string;
};
const DropdownButton: React.FC<DropdownButtonProps> = ({
selectedValue,
backgroundColor,
textColor,
}: DropdownButtonProps) => {
const textColorCss = textColor ? `text-${textColor}` : 'text-slate12';
const borderColor = backgroundColor
? `border-${backgroundColor}`
: 'border-slate7';
const backgroundColorClass = backgroundColor
? `bg-${backgroundColor}`
: 'bg-transparent';
return (
<Listbox.Button
className={`relative w-full cursor-default ${borderColor} border-solid border rounded-xl py-3 pl-3.5 pr-10 h-11 text-left focus:outline-none sm:text-sm
${backgroundColorClass}
`}
>
<span
className={`block truncate ${
selectedValue && selectedValue.label
? `${textColorCss}`
: 'text-slate11'
} break-words`}
>
{selectedValue && selectedValue.label ? selectedValue.label : 'Select'}
</span>
<span
className={`pointer-events-none absolute top-1 bottom-0 right-0 flex items-center pr-4 ${textColorCss}`}
>
<Icon name="chevron-down" />
</span>
</Listbox.Button>
);
};
export type DropdownItem = {
/**
* The key of the item.
*/
value: string;
/**
* The label to display of the item.
*/
label: string;
};
export type DropdownProps = {
/**
* List of items to be displayed in the dropdown.
*/
items: DropdownItem[];
/**
* The selected value of the dropdown.
*/
selectedValue: DropdownItem | undefined;
/**
* Callback when the selected value changes.
*/
onChange(option: DropdownItem): void;
/**
* Background color of the dropdown. Should be on tailwind palette. https://tailwindcss.com/docs/background-color
*/
backgroundColor?: string;
/**
* Text color of the dropdown. Should be on tailwind palette. https://tailwindcss.com/docs/text-color
*/
textColor?: string;
/**
* Width of the options list. Should be on tailwind width. https://tailwindcss.com/docs/width
*/
optionsWidth?: string;
};
export const Dropdown: React.FC<DropdownProps> = ({
items,
selectedValue,
onChange,
backgroundColor,
textColor,
optionsWidth,
}: DropdownProps) => {
const handleDropdownChange = (option: DropdownItem): void => {
onChange(option);
};
const width = optionsWidth ? `w-${optionsWidth}` : 'w-full';
return (
<Listbox value={selectedValue} by="value" onChange={handleDropdownChange}>
{({ open }) => (
<div className="relative max-w-full">
<DropdownButton
selectedValue={selectedValue}
open={open}
backgroundColor={backgroundColor}
textColor={textColor}
/>
<Transition
as={Fragment}
leave="transition ease-in duration-100"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<Listbox.Options
className={`absolute mt-1 max-h-36 ${width} right-0 z-10 overflow-auto rounded-xl bg-black px-3 pt-2 border-solid border-slate6 border text-base focus:outline-none sm:text-sm`}
>
{items.map((option: DropdownItem) => (
<DropdownOption key={option.value} option={option} />
))}
</Listbox.Options>
</Transition>
</div>
)}
</Listbox>
);
};

View File

@ -1,2 +1 @@
export * from './dropdown';
export * from './combobox';

View File

@ -4,14 +4,23 @@ import { Combobox, Flex, Icon, IconName } from '@/components';
type Item = { id: number; label: string; icon: IconName };
type ItemDropdown = { id: number; label: string };
const Items: Item[] = [
{ id: 1, label: 'Option 1', icon: 'branch' },
{ id: 2, label: 'Option 2', icon: 'ethereum' },
{ id: 3, label: 'Option 3', icon: 'metamask' },
];
const ItemsDropdown: ItemDropdown[] = [
{ id: 1, label: 'Option 1' },
{ id: 2, label: 'Option 2' },
{ id: 3, label: 'Option 3' },
];
export const ComboboxTest: React.FC = () => {
const selected = useState<Item>();
const selectedDropdown = useState<ItemDropdown>(ItemsDropdown[0]);
return (
<Flex
@ -24,25 +33,19 @@ export const ComboboxTest: React.FC = () => {
alignSelf: 'center',
}}
>
<Combobox unattached items={Items} selected={selected} queryKey="label">
<Combobox
unattached
items={ItemsDropdown}
selected={selectedDropdown}
queryKey="label"
>
{({ Field, Options }) => (
<>
<Field>
{(selected) => (
<>
<Icon name={selected?.icon || 'search'} />
{selected?.label || 'Select an option'}
</>
)}
<Field css={{ backgroundColor: '$slate4', borderColor: '$slate4' }}>
{(selected) => <>{selected?.label || 'Select an option'}</>}
</Field>
<Options>
{(item) => (
<>
<Icon name={item.icon} /> {item.label}
</>
)}
</Options>
<Options disableSearch>{(item) => <>{item.label}</>}</Options>
</>
)}
</Combobox>

View File

@ -1,17 +1,18 @@
import { useState } from 'react';
import {
Dropdown,
DropdownItem,
InputGroup,
InputGroupText,
} from '@/components';
import { Combobox, InputGroup, InputGroupText } from '@/components';
import { useDebounce } from '@/hooks';
import { AppLog } from '@/utils';
import { Explore } from '../explore.context';
import { NFASearchFragmentStyles as S } from './nfa-search.styles';
const orderResults: DropdownItem[] = [
type SortItem = {
value: string;
label: string;
};
const orderResults: SortItem[] = [
{ value: 'newest', label: 'Newest' },
{ value: 'oldest', label: 'Oldest' },
{ value: 'a-z', label: 'Sort A-Z' },
@ -26,34 +27,36 @@ export const NFASearchFragment: React.FC = () => {
setSearch,
setPageNumber,
} = Explore.useContext();
const [selectedValue, setSelectedValue] = useState<DropdownItem>(
orderResults[0]
);
const [selectedValue, setSelectedValue] = useState<SortItem>(orderResults[0]);
const handleSortChange = (item: DropdownItem): void => {
setSelectedValue(item);
setPageNumber(0);
setEndReached(false);
const handleSortChange = (item: SortItem | undefined): void => {
if (item) {
setSelectedValue(item);
setPageNumber(0);
setEndReached(false);
switch (item.value) {
case 'newest':
setOrderBy('tokenId');
setOrderDirection('desc');
break;
case 'oldest':
setOrderBy('tokenId');
setOrderDirection('asc');
break;
case 'a-z':
setOrderBy('name');
setOrderDirection('asc');
break;
case 'z-a':
setOrderBy('name');
setOrderDirection('desc');
break;
default:
break;
switch (item.value) {
case 'newest':
setOrderBy('tokenId');
setOrderDirection('desc');
break;
case 'oldest':
setOrderBy('tokenId');
setOrderDirection('asc');
break;
case 'a-z':
setOrderBy('name');
setOrderDirection('asc');
break;
case 'z-a':
setOrderBy('name');
setOrderDirection('desc');
break;
default:
break;
}
} else {
AppLog.errorToast('Error selecting sort option. Try again');
}
};
@ -78,15 +81,29 @@ export const NFASearchFragment: React.FC = () => {
<S.Input.Icon name="search" />
<InputGroupText placeholder="Search" onChange={handleSearchChange} />
</InputGroup>
<Dropdown
<Combobox
items={orderResults}
selectedValue={selectedValue}
onChange={handleSortChange}
backgroundColor="slate4"
textColor="slate11"
optionsWidth="40"
/>
selected={[selectedValue, handleSortChange]}
css={{ minWidth: '$28' }}
queryKey="label"
>
{({ Field, Options }) => (
<>
<Field
css={{
backgroundColor: '$slate4',
borderColor: '$slate4',
color: '$slate11',
}}
>
{(selected) => selected?.label || 'Select'}
</Field>
<Options disableSearch css={{ minWidth: '$44', left: 'unset' }}>
{(item) => item.label}
</Options>
</>
)}
</Combobox>
</S.Input.Wrapper>
</S.Container>
);

View File

@ -31,10 +31,6 @@ export const NFASearchFragmentStyles = {
width: '100%',
maxWidth: '30rem',
justifySelf: 'center',
button: {
minWidth: '$28',
},
}),
Icon: styled(Icon, {
fontSize: '$lg',