mirror of https://github.com/certusone/oyster.git
feat: add creators
This commit is contained in:
parent
00de45009f
commit
1e35a14628
|
@ -0,0 +1,91 @@
|
|||
import { Select, Spin } from 'antd';
|
||||
import { SelectProps } from 'antd/es/select';
|
||||
import debounce from 'lodash/debounce';
|
||||
import React, { useMemo, useRef, useState } from 'react';
|
||||
import './styles.less';
|
||||
|
||||
export interface DebounceSelectProps<ValueType = any>
|
||||
extends Omit<SelectProps<ValueType>, 'options' | 'children'> {
|
||||
fetchOptions: (search: string) => Promise<ValueType[]>;
|
||||
debounceTimeout?: number;
|
||||
}
|
||||
|
||||
function DebounceSelect<
|
||||
ValueType extends { key?: string; label: React.ReactNode; value: string | number } = any
|
||||
>({ fetchOptions, debounceTimeout = 800, ...props }: DebounceSelectProps) {
|
||||
const [fetching, setFetching] = useState(false);
|
||||
const [options, setOptions] = useState<ValueType[]>([]);
|
||||
const fetchRef = useRef(0);
|
||||
|
||||
const debounceFetcher = useMemo(() => {
|
||||
const loadOptions = (value: string) => {
|
||||
fetchRef.current += 1;
|
||||
const fetchId = fetchRef.current;
|
||||
setOptions([]);
|
||||
setFetching(true);
|
||||
|
||||
fetchOptions(value).then(newOptions => {
|
||||
if (fetchId !== fetchRef.current) {
|
||||
// for fetch callback order
|
||||
return;
|
||||
}
|
||||
|
||||
setOptions(newOptions);
|
||||
setFetching(false);
|
||||
});
|
||||
};
|
||||
|
||||
return debounce(loadOptions, debounceTimeout);
|
||||
}, [fetchOptions, debounceTimeout]);
|
||||
|
||||
return (
|
||||
<Select<ValueType>
|
||||
labelInValue
|
||||
filterOption={false}
|
||||
onSearch={debounceFetcher}
|
||||
notFoundContent={fetching ? <Spin size="small" /> : null}
|
||||
{...props}
|
||||
options={options}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// Usage of DebounceSelect
|
||||
interface UserValue {
|
||||
label: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
async function fetchUserList(username: string): Promise<UserValue[]> {
|
||||
console.log('fetching user', username);
|
||||
|
||||
return fetch('https://randomuser.me/api/?results=5')
|
||||
.then(response => response.json())
|
||||
.then(body =>
|
||||
body.results.map(
|
||||
(user: { name: { first: string; last: string }; login: { username: string } }) => ({
|
||||
label: `${user.name.first} ${user.name.last}`,
|
||||
value: user.login.username,
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
export const UserSearch = () => {
|
||||
const [value, setValue] = React.useState<UserValue[]>([]);
|
||||
|
||||
return (
|
||||
<DebounceSelect
|
||||
className="user-selector"
|
||||
mode="multiple"
|
||||
size="large"
|
||||
value={value}
|
||||
placeholder="Select creator"
|
||||
fetchOptions={fetchUserList}
|
||||
onChange={newValue => {
|
||||
setValue(newValue);
|
||||
}}
|
||||
style={{ width: '100%' }}
|
||||
/>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,11 @@
|
|||
.user-selector {
|
||||
background: #282828;
|
||||
border-radius: 8px;
|
||||
padding: 3px 0px;
|
||||
overflow: hidden;
|
||||
|
||||
.ant-select-selector {
|
||||
border-width: 0px !important;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
|
@ -11,8 +11,10 @@ import {
|
|||
Progress,
|
||||
Spin,
|
||||
InputNumber,
|
||||
Select,
|
||||
} from 'antd';
|
||||
import { ArtCard } from './../../components/ArtCard';
|
||||
import { UserSearch } from './../../components/UserSearch';
|
||||
import './styles.less';
|
||||
import { mintNFT } from '../../models';
|
||||
import {
|
||||
|
@ -33,6 +35,7 @@ import { MintLayout } from '@solana/spl-token';
|
|||
import { useHistory, useParams } from 'react-router-dom';
|
||||
|
||||
const { Step } = Steps;
|
||||
const { Option } = Select;
|
||||
const { Dragger } = Upload;
|
||||
|
||||
export const ArtCreateView = () => {
|
||||
|
@ -158,11 +161,9 @@ const CategoryStep = (props: { confirm: (category: MetadataCategory) => void })
|
|||
return (
|
||||
<>
|
||||
<Row className="call-to-action">
|
||||
<h2>Create your NFT artwork on Meta</h2>
|
||||
<h2>Create a new item</h2>
|
||||
<p>
|
||||
Creating NFT on Solana is not only low cost for artists but supports
|
||||
environment with 20% of the fees form the platform donated to
|
||||
charities.
|
||||
First time creating on Metaplex? <a>Read our creators’ guide.</a>
|
||||
</p>
|
||||
</Row>
|
||||
<Row>
|
||||
|
@ -374,6 +375,12 @@ const InfoStep = (props: {
|
|||
}
|
||||
/>
|
||||
</label>
|
||||
<label className="action-field">
|
||||
<span className="field-title">Creators</span>
|
||||
<UserSearch
|
||||
|
||||
/>
|
||||
</label>
|
||||
<label className="action-field">
|
||||
<span className="field-title">Description</span>
|
||||
<Input.TextArea
|
||||
|
|
|
@ -22,6 +22,9 @@
|
|||
|
||||
p {
|
||||
color: #6d6d6d;
|
||||
font-family: Inter;
|
||||
font-style: normal;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
margin-bottom: 50px;
|
||||
|
|
Loading…
Reference in New Issue