@material-ui/lab#Autocomplete JavaScript Examples
The following examples show how to use
@material-ui/lab#Autocomplete.
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.js From flame-coach-web with MIT License | 6 votes |
SearchClient = ({
clients,
clientDefault,
searchSelectedHandler,
inputRef,
disabled,
...rest
}) => {
return (
<Autocomplete
id="search-client"
freeSolo
options={clients.map((option) => option)}
onChange={(event, client) => {
searchSelectedHandler(client);
}}
value={clients.find(client => client.identifier === clientDefault)}
disabled={disabled}
getOptionLabel={(option) => `${option.firstname} ${option.lastname}`}
renderInput={(params) => (
<TextField {...rest} {...params} label="Client" name="client"
variant="outlined" inputRef={inputRef}/>
)}
/>
);
}
Example #2
Source File: KbSearch.js From dataqa with GNU General Public License v3.0 | 6 votes |
render() {
const { classes } = this.props;
return (
<Autocomplete
classes={{ inputRoot: classes.inputRoot }}
options={this.state.options}
getOptionLabel={option => option.name}
onChange={this.addSuggestion}
renderInput={params => <TextField
{...params}
label={""}
required={false}
/>
}
onInputChange={this.onInputChange}
getOptionSelected={(value, option) => value.name == option.name}
autoSelect={true}
inputValue={this.state.inputValue}
disableClearable={true}
value={this.state.value}
/>
)
}
Example #3
Source File: expiries.jsx From GraphVega with MIT License | 6 votes |
render() {
return(
<Autocomplete
noOptionsText={"Select an underlying from the search first!"}
options={this.state.expirations}
getOptionLabel={(option) => option}
onChange={this.valueChange}
renderInput={(params) => <TextField {...params} label="Select expiration" margin="normal" />}
/>
)
}
Example #4
Source File: search.jsx From GraphVega with MIT License | 6 votes |
render() {
return (
<Autocomplete
loading={this.state.loading}
options={this.state.options}
renderOption={(option, { selected }) => (
<>
{option.description}
<div className="text-secondary">({option.symbol})</div>
</>
)}
getOptionLabel={(option) => option.description}
getOptionSelected={(option, value) =>
option.description === value.description
}
onChange={this.valueChange}
onInputChange={this.handleInputValueChange}
filterOptions={(x) => x}
renderInput={(params) => (
<TextField
{...params}
label="Search by Company Name or (Symbol)"
autoFocus={true}
InputProps={{
...params.InputProps,
endAdornment: (
<React.Fragment>
{this.state.loading ? (
<CircularProgress size="1.5rem" />
) : null}
{params.InputProps.endAdornment}
</React.Fragment>
),
}}
/>
)}
/>
);
}
Example #5
Source File: FolioHeader.jsx From archeage-tools with The Unlicense | 5 votes |
render() {
const { open, loading, searchType, options } = this.state;
const { items, mobile } = this.props;
return (
<AppBar position="static" className="section folio-header">
<Toolbar>
{!mobile &&
<Typography variant="h5" className="title-text">Folio</Typography>}
<Autocomplete
open={open}
onOpen={() => this.setOpen(true)}
onClose={() => this.setOpen(false)}
onChange={this.handleSearch}
loading={loading}
options={options}
getOptionLabel={option => option.name || option}
filterOptions={(options) => options}
classes={{
noOptions: 'folio-no-option',
}}
renderOption={option => (
<div className="item-result" key={option.id}>
<Item id={option.id} inline />
{items[option.id]
? <Typography variant="body2">{items[option.id].name}</Typography>
: <Skeleton variant="text" />}
</div>
)}
freeSolo
onInputChange={(e, value) => {
this._handleQuery(value);
}}
renderInput={params => (
<TextField
{...params}
label={`Search by ${searchTypes.find(type => type.value === searchType).label}`}
fullWidth
variant="standard"
size="small"
margin="none"
InputProps={{
...params.InputProps,
endAdornment: (
<>
{loading ? <CircularProgress color="inherit" size={20} /> : null}
{params.InputProps.endAdornment}
</>
),
}}
InputLabelProps={{
...params.InputLabelProps,
}}
/>
)}
/>
<RadioGroup name="search-type" value={searchType} onChange={this.handleTypeChange} row={!mobile}>
{searchTypes.map(searchType => (
<FormControlLabel
control={<Radio size="small" color="primary" />}
{...searchType}
key={searchType.value}
/>
))}
</RadioGroup>
</Toolbar>
</AppBar>
);
}
Example #6
Source File: AnnounceMessage.js From treetracker-admin-client with GNU Affero General Public License v3.0 | 4 votes |
AnnounceMessageForm = ({ setToggleAnnounceMessage }) => {
const { orgList } = useContext(AppContext);
const {
setErrorMessage,
user,
regions,
postBulkMessageSend,
setThreads,
} = useContext(MessagingContext);
const { form, sendButton } = useStyles();
const [organization, setOrganization] = useState({});
const [inputValueOrg, setInputValueOrg] = useState('');
const [region, setRegion] = useState({});
const [inputValueRegion, setInputValueRegion] = useState('');
const [errors, setErrors] = useState(null);
const [values, setValues] = useState({
title: '',
message: '',
videoLink: '',
});
const handleChange = (e) => {
setErrors(null);
const { name, value } = e.target;
setValues({
...values,
[name]: `${value}`,
});
};
const validateAnnouncement = (payload) => {
const errors = {};
if (!payload.subject) {
errors.subject = 'Please enter a subject for your announcement';
}
if (payload.body.length === 0 || !/\w/g.test(payload.body.trim())) {
errors.body = 'Please enter a message';
}
const videoUrl = /^((?:https?:)?\/\/)?.*/;
if (payload.video_link && !videoUrl.test(payload.video_link.trim())) {
errors.video_link = 'Please enter a valid video link';
}
if (
(!payload.region_id && !payload.organization_id) ||
(payload.region_id && payload.organization_id)
) {
errors.recipient = 'Please select an organization or region';
}
return errors;
};
const handleSubmit = async (e) => {
e.preventDefault();
const payload = {
author_handle: user.userName,
subject: values.title,
type: 'announce',
body: values.message,
};
if (values?.videoLink) {
payload['video_link'] = values.videoLink;
}
if (region?.id) {
payload['region_id'] = region.id;
}
if (organization?.id) {
payload['organization_id'] = organization.stakeholder_uuid;
}
const errs = validateAnnouncement(payload);
try {
const errorsFound = Object.keys(errs).length > 0;
if (errorsFound) {
setErrors(errs);
} else {
const res = await postBulkMessageSend(payload);
setErrorMessage('');
if (res.error) {
setErrorMessage(
`Sorry, something went wrong and we couldn't create the announcement: ${res.message}`
);
} else {
// close the drawer
setValues({
title: '',
message: '',
videoLink: '',
});
setOrganization('');
setRegion('');
setToggleAnnounceMessage(false);
const organization = orgList.find(
(org) => org.stakeholder_uuid === payload.organization_id
);
const region = regions.find(
(region) => region.id === payload.region_id
);
const newAnnouncement = {
id: null,
type: 'announce',
parent_message_id: null,
from: payload.author_handle,
to: null,
recipient_organization_id: payload.organization_id || null,
recipient_region_id: payload.region_id || null,
subject: payload.subject,
body: payload.body,
composed_at: new Date().toISOString(),
video_link: null,
survey_response: null,
survey: null,
bulk_message_recipients: [
{
organization: organization?.name,
region: region?.name,
},
],
};
log.debug('...update threads w/ new announcement');
// update the full set of threads
setThreads((prev) => [
{
username: `${newAnnouncement.id}`,
messages: [newAnnouncement],
avatar: '',
},
...prev,
]);
}
}
} catch (err) {
console.log(err);
}
};
return (
<form className={form} onSubmit={handleSubmit}>
{errors?.subject && (
<Typography
style={{ color: 'red', fontWeight: 'bold', margin: '20px 10px 0px' }}
>
{errors.subject}
</Typography>
)}
<GSInputLabel text="Announce: Title" />
<TextField
fullWidth
label="Title"
name="title"
value={values.title}
onChange={handleChange}
required
/>
{errors?.body && (
<Typography
style={{ color: 'red', fontWeight: 'bold', margin: '20px 10px 0px' }}
>
{errors.body}
</Typography>
)}
<GSInputLabel text={'Message'} />
<TextField
multiline
rows={5}
name="message"
value={values.message}
onChange={handleChange}
label="Write your message here ..."
required
/>
{errors?.video_link && (
<Typography
style={{ color: 'red', fontWeight: 'bold', margin: '20px 10px 0px' }}
>
{errors.video_link}
</Typography>
)}
<GSInputLabel text={'Add a Video Link'} />
<TextField
name="videoLink"
value={values.videoLink}
onChange={handleChange}
label="Add a video link, e.g., YouTube URL"
/>
{errors?.recipient && (
<Typography
style={{ color: 'red', fontWeight: 'bold', margin: '20px 10px 0px' }}
>
{errors.recipient}
</Typography>
)}
<GSInputLabel
id="select-label"
text={'Target Audience by Organization'}
/>
<Autocomplete
name="organization"
selectOnFocus
handleHomeEndKeys
options={orgList}
getOptionLabel={(option) => option.name || ''}
value={organization}
onChange={(e, val) => setOrganization(val)}
inputValue={inputValueOrg}
getOptionSelected={(option, value) => option.id === value.id}
onInputChange={(e, val) => {
setErrors(null);
setInputValueOrg(val);
}}
id="controllable-states-demo"
freeSolo
sx={{ width: 300 }}
renderInput={(params) => (
<TextField {...params} label="Select Organization" />
)}
/>
<GSInputLabel id="select-reg-label" text={'Target Audience by Region'} />
<Autocomplete
name="region"
selectOnFocus
handleHomeEndKeys
value={region}
onChange={(e, value) => setRegion(value)}
options={regions}
getOptionLabel={(option) => option.name || ''}
inputValue={inputValueRegion}
getOptionSelected={(option, value) => option.id === value.id}
onInputChange={(e, val) => {
setErrors(null);
setInputValueRegion(val);
}}
id="controllable-states-demo"
freeSolo
sx={{ width: 300 }}
renderInput={(params) => (
<TextField {...params} label="Select Region" />
)}
/>
<Button disabled={!!errors} className={sendButton} type="submit">
Send Message
</Button>
</form>
);
}
Example #7
Source File: NewMessage.js From treetracker-admin-client with GNU Affero General Public License v3.0 | 4 votes |
NewMessage = ({ openModal, handleClose, setMessageRecipient }) => {
const { box, formContent, header, button } = useStyles();
const {
setErrorMessage,
user,
authors,
setThreads,
postMessageSend,
} = useContext(MessagingContext);
const [messageContent, setMessageContent] = useState('');
const [recipient, setRecipient] = useState('');
const [inputValue, setInputValue] = useState('');
const [errors, setErrors] = useState(null);
useEffect(() => {
if (openModal === false) {
setMessageContent('');
setRecipient('');
}
}, [openModal]);
useEffect(() => {
// set an error message right away if there are no authors
if (authors.length === 0) {
setErrors('Sorry, no accounts were found.');
}
}, [authors]);
const handleChange = (e) => {
// don't remove the error if it's not a user mistake, like there aren't any authors
if (authors.length > 0) {
setErrors(null);
}
const { name, value } = e.target;
name === 'body'
? setMessageContent(value)
: setRecipient(e.target.textContent);
};
const validateMessage = (payload) => {
const errors = {};
if (payload.body.length === 0 || !/\w/g.test(payload.body.trim())) {
errors.body = 'Please enter a message';
}
if (!payload.recipient_handle) {
errors.recipient = 'Please select a recipient';
}
if (authors.length === 0) {
errors.accounts = 'Sorry, no accounts were found.';
}
return errors;
};
const handleSubmit = async (e) => {
e.preventDefault();
const messagePayload = {
author_handle: user.userName,
recipient_handle: recipient,
type: 'message',
body: messageContent,
};
const errs = validateMessage(messagePayload);
const errorsFound = Object.keys(errs).length > 0;
if (errorsFound) {
setErrors(errs);
} else {
const res = await postMessageSend(messagePayload);
if (res.error) {
setErrorMessage(res.message);
} else {
const newMessage = {
parent_message_id: null,
body: messageContent,
composed_at: new Date().toISOString(),
from: user.userName,
id: uuid(),
recipient_organization_id: null,
recipient_region_id: null,
survey: null,
to: recipient,
type: 'message',
video_link: null,
};
log.debug('...update threads after postMessageSend');
// update the full set of threads
setThreads((prev) =>
[...prev, { userName: recipient, messages: [newMessage] }].sort(
(a, b) =>
new Date(b?.messages?.at(-1).composed_at) -
new Date(a?.messages?.at(-1).composed_at)
)
);
}
setMessageRecipient(recipient);
handleClose();
}
};
return (
<Modal
open={openModal}
onClose={handleClose}
aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description"
>
<Box className={box}>
<form className={formContent} onSubmit={handleSubmit}>
<Box className={header} my={1}>
<Typography variant="h3">Send New Message</Typography>
</Box>
{errors?.accounts && (
<Typography
style={{
color: 'red',
fontWeight: 'bold',
margin: '20px 10px 0px',
}}
>
{errors.accounts}
</Typography>
)}
<FormControl>
{errors?.recipient && (
<Typography
style={{
color: 'red',
fontWeight: 'bold',
margin: '20px 10px 0px',
}}
>
{errors.recipient}
</Typography>
)}
<GSInputLabel text="Choose the Message Recipient" />
<Autocomplete
name="to"
selectOnFocus
clearOnBlur
handleHomeEndKeys
value={recipient}
onChange={handleChange}
options={
authors.length
? authors.map((author) => author.handle || '').sort()
: []
}
inputValue={inputValue}
getOptionSelected={(option, value) => option === value}
onInputChange={(e, val) => setInputValue(val)}
id="controllable-states-demo"
freeSolo
sx={{ width: 300 }}
renderInput={(params) => (
<TextField {...params} label="Message Recipient" />
)}
/>
</FormControl>
<FormControl>
{errors?.message && (
<Typography
style={{
color: 'red',
fontWeight: 'bold',
margin: '20px 10px 0px',
}}
>
{errors.message}
</Typography>
)}
<GSInputLabel text="Message" />
<TextField
multiline
placeholder="Write your message here ..."
name="body"
value={messageContent}
onChange={handleChange}
/>
</FormControl>
<Button
type="submit"
size="large"
className={button}
disabled={!!errors}
>
Send Message
</Button>
</form>
</Box>
</Modal>
);
}
Example #8
Source File: Survey.js From treetracker-admin-client with GNU Affero General Public License v3.0 | 4 votes |
SurveyForm = ({ setToggleSurvey }) => {
const { form, submitButton, input } = useStyles();
const {
setErrorMessage,
user,
regions,
postBulkMessageSend,
setThreads,
} = useContext(MessagingContext);
const { orgList } = useContext(AppContext);
const [title, setTitle] = useState('');
const [questionOne, setQuestionOne] = useState({
prompt: '',
choiceOne: '',
choiceTwo: '',
choiceThree: '',
});
const [questionTwo, setQuestionTwo] = useState({
prompt: '',
choiceOne: '',
choiceTwo: '',
choiceThree: '',
});
const [questionThree, setQuestionThree] = useState({
prompt: '',
choiceOne: '',
choiceTwo: '',
choiceThree: '',
});
const [errors, setErrors] = useState(null);
// * Both values needed for organization/region autocompletes
const [organization, setOrganization] = useState({});
const [inputValueOrg, setInputValueOrg] = useState('');
const [region, setRegion] = useState({});
const [inputValueRegion, setInputValueRegion] = useState('');
const handleChange = (e, question) => {
setErrors(null);
const { name, value } = e.target;
if (question === 'questionOne') {
setQuestionOne({
...questionOne,
[name]: value,
});
} else if (question === 'questionTwo') {
setQuestionTwo({
...questionTwo,
[name]: value,
});
} else if (question === 'questionThree') {
setQuestionThree({
...questionThree,
[name]: value,
});
} else if (name === 'title') {
setTitle(value);
}
};
const validateSurvey = (payload) => {
const errors = {};
if (!payload.subject && payload.survey.title.length <= 1) {
errors.title = 'Please enter a title for your survey';
}
if (payload.survey.questions.length === 0) {
errors.questions = 'Please enter at least one question';
} else {
payload.survey.questions.forEach((question) => {
if (!question.prompt) {
errors.questions = 'Please enter a prompt for each question';
}
if (
question.choices.length < 3 ||
question.choices.some((choice) => choice === '')
) {
errors.questions = 'Please enter 3 choices for each question';
}
});
}
if (
(!payload.region_id && !payload.organization_id) ||
(payload.region_id && payload.organization_id)
) {
errors.recipient = 'Please select an organization or region';
}
return errors;
};
const handleSubmit = async (e) => {
e.preventDefault();
const allQuestions = { questionOne, questionTwo, questionThree };
const payload = {
author_handle: user.userName,
subject: title,
type: 'survey',
body: 'Survey',
survey: {
title: title,
questions: [],
},
};
if (region?.id) {
payload['region_id'] = region.id;
}
if (organization?.id) {
payload['organization_id'] = organization.stakeholder_uuid;
}
Object.values(allQuestions).forEach((question) => {
const { prompt, choiceOne, choiceTwo, choiceThree } = question;
if (prompt.length > 1) {
payload.survey.questions.push({
prompt,
choices: [choiceOne, choiceTwo, choiceThree],
});
}
});
const errs = validateSurvey(payload);
try {
const errorsFound = Object.keys(errs).length > 0;
if (errorsFound) {
setErrors(errs);
} else {
const res = await postBulkMessageSend(payload);
setErrorMessage('');
if (res.error) {
setErrorMessage(
`Sorry, something went wrong and we couldn't create the survey: ${res.message}`
);
} else {
// reset and hide the survey drawer
setQuestionOne({
prompt: '',
choiceOne: '',
choiceTwo: '',
choiceThree: '',
});
setQuestionTwo({
prompt: '',
choiceOne: '',
choiceTwo: '',
choiceThree: '',
});
setQuestionThree({
prompt: '',
choiceOne: '',
choiceTwo: '',
choiceThree: '',
});
setOrganization('');
setRegion('');
setTitle('');
setToggleSurvey(false);
const newSurvey = {
id: uuid(),
type: 'survey',
parent_message_id: null,
from: payload.author_handle,
to: null,
recipient_organization_id: payload.organization_id || null,
recipient_region_id: payload.region_id || null,
subject: payload.subject,
body: null,
composed_at: new Date().toISOString(),
video_link: null,
survey_response: null,
survey: payload.survey,
};
log.debug('...update threads w/ new survey');
// update state with with the new survey
setThreads((prev) => [
{
username: `${newSurvey.id}`,
messages: [newSurvey],
avatar: '',
},
...prev,
]);
}
}
} catch (err) {
console.log(err);
}
};
return (
<form className={form} onSubmit={handleSubmit}>
<GSInputLabel text="Survey Title" />
<TextField
className={input}
fullWidth
label="Survey Title"
name="title"
value={title}
onChange={handleChange}
{...(errors?.title && { error: true })}
/>
{errors?.questions && (
<Typography
style={{
color: 'red',
fontWeight: 'bold',
margin: '20px 10px 0px',
}}
>
{errors.questions}
</Typography>
)}
{['One', 'Two', 'Three'].map((num) => (
<div key={num}>
<GSInputLabel text={`Survey Question ${num}`} />
<TextField
className={input}
fullWidth
label="Write your question: "
name="prompt"
value={`question${num}`['prompt']}
onChange={(e) => handleChange(e, `question${num}`)}
{...(errors?.questions && { error: true })}
/>
<GSInputLabel text={`Question ${num} Answer Options`} />
<TextField
className={input}
fullWidth
label="A: "
name="choiceOne"
value={`question${num}`['choiceOne']}
onChange={(e) => handleChange(e, `question${num}`)}
{...(errors?.questions && { error: true })}
/>
<TextField
className={input}
fullWidth
label="B: "
name="choiceTwo"
value={`question${num}`['choiceTwo']}
onChange={(e) => handleChange(e, `question${num}`)}
{...(errors?.questions && { error: true })}
/>
<TextField
className={input}
fullWidth
label="C: "
name="choiceThree"
value={`question${num}`['choiceThree']}
onChange={(e) => handleChange(e, `question${num}`)}
{...(errors?.questions && { error: true })}
/>
</div>
))}
<div>
{errors?.recipient && (
<Typography
style={{
color: 'red',
fontWeight: 'bold',
margin: '20px 10px 0px',
}}
>
{errors.recipient}
</Typography>
)}
<FormControl fullWidth {...(errors?.recipient && { error: true })}>
<GSInputLabel
id="select-label"
text={'Target Audience by Organization'}
/>
<Autocomplete
name="organization"
selectOnFocus
handleHomeEndKeys
options={orgList}
getOptionLabel={(option) => option.name || ''}
value={organization}
onChange={(e, val) => setOrganization(val)}
inputValue={inputValueOrg}
getOptionSelected={(option, value) => option.id === value.id}
onInputChange={(e, val) => {
setErrors(null);
setInputValueOrg(val);
}}
id="controllable-states-demo"
freeSolo
sx={{ width: 300 }}
renderInput={(params) => (
<TextField
{...params}
label="Select Organization"
{...(errors?.recipient && { error: true })}
/>
)}
/>
</FormControl>
<FormControl fullWidth {...(errors?.recipient && { error: true })}>
<GSInputLabel
id="select-reg-label"
text={'Target Audience by Region'}
/>
<Autocomplete
name="region"
selectOnFocus
handleHomeEndKeys
value={region}
onChange={(e, value) => setRegion(value)}
options={regions}
getOptionLabel={(option) => option.name || ''}
inputValue={inputValueRegion}
getOptionSelected={(option, value) => option.id === value.id}
onInputChange={(e, val) => {
setErrors(null);
setInputValueRegion(val);
}}
id="controllable-states-demo"
freeSolo
sx={{ width: 300 }}
renderInput={(params) => (
<TextField
{...params}
label="Select Region"
{...(errors?.recipient && { error: true })}
/>
)}
/>
</FormControl>
</div>
<Button
disabled={!!errors}
type="submit"
size="large"
className={submitButton}
>
Submit
</Button>
</form>
);
}
Example #9
Source File: Crops.jsx From archeage-tools with The Unlicense | 4 votes |
render() {
const { mobile, crops, removeCrop, items, climates } = this.props;
const { dd, hh, mm, ss, climate, crop, note, timer, seedbed, errors } = this.state;
const cropCustom = CROP_CUSTOM[crop.id];
setTitle('My Farm Timers');
return (
<div className={cn('tool-container', { mobile })}>
<Paper className="section">
<AppBar position="static">
<Toolbar>
<Typography variant="h5" className="title-text">My Farm Timers</Typography>
</Toolbar>
</AppBar>
<div className="crops-container">
<Autocomplete
className="crop-select"
autoHighlight
disableClearable
blurOnSelect
size="small"
loading={!items.length}
options={items}
onChange={this.handleSelectCrop}
value={crop}
getOptionLabel={option => option.name || ''}
renderOption={option => (
<div className="item-result" key={option.id}>
<Item id={option.id} inline />
<Typography variant="body2">{option.name}</Typography>
</div>
)}
groupBy={option => option.group}
renderInput={params => (
<FormControl error={hasProperty(errors, 'crop')}>
<TextField
{...params}
label={`Find a crop, tree, or livestock`}
variant="standard"
size="medium"
InputProps={{
...params.InputProps,
endAdornment: (
<>
{params.InputProps.endAdornment}
</>
),
}}
InputLabelProps={{
...params.InputLabelProps,
}}
/>
{errors.crop && <FormHelperText>{errors.crop}</FormHelperText>}
</FormControl>
)}
/>
<FormControl component="fieldset">
<FormLabel>Timer</FormLabel>
<RadioGroup
name="timer-type"
value={timer}
onChange={this.handleTimerChange}
>
<FormControlLabel
value={TIMER_TYPE.MATURES}
control={<Radio size="small" />}
label="Matures"
disabled={cropCustom && !cropCustom.types.includes(TIMER_TYPE.MATURES)}
/>
<FormControlLabel
value={TIMER_TYPE.HARVEST}
control={<Radio size="small" />}
label="Harvest"
disabled={(!crop.description || !crop.description.match(HARVEST_REGEX)) && !(cropCustom && cropCustom.types.includes(TIMER_TYPE.HARVEST))}
/>
</RadioGroup>
</FormControl>
<FormControl className="select-group" error={hasProperty(errors, 'climate')}>
<InputLabel className="group-label" shrink>Climate(s)</InputLabel>
<ButtonGroup color="secondary">
{Object.values(climates).map(c => (
<Tooltip title={c.name} key={`climate-${c.id}`}>
<Button
variant={climate.includes(c.name) && !seedbed ? 'contained' : 'outlined'}
className={cn({ selected: climate.includes(c.name) })}
onClick={(e) => this.handleSelectClimate(e, c.name)}
disabled={seedbed}
>
<span className={cn('climate-icon small', c.name)} />
</Button>
</Tooltip>
))}
</ButtonGroup>
{errors.climate && <FormHelperText>{errors.climate}</FormHelperText>}
<FormControlLabel
control={<Checkbox size="small" />}
label="Seedbed?"
disabled={crop.type !== 'Seed' || crop.name.includes('Bundle')}
checked={seedbed}
onChange={this.handleSeedbedChange}
/>
</FormControl>
<FormControl className="ts-select">
<InputLabel shrink>Time Remaining</InputLabel>
<div className="multi-input">
<Input
id="dd"
placeholder="0"
endAdornment="d"
inputProps={{
maxLength: 1,
ref: this.dd,
}}
value={dd}
onChange={this.handleTimeChange('dd')}
onKeyPress={this.checkEnter}
/>
<Input
id="hh"
placeholder="0"
endAdornment="h"
inputProps={{
maxLength: 2,
ref: this.hh,
}}
value={hh}
onChange={this.handleTimeChange('hh')}
onKeyPress={this.checkEnter}
/>
<Input
id="mm"
placeholder="0"
endAdornment="m"
inputProps={{
maxLength: 2,
ref: this.mm,
}}
value={mm}
onChange={this.handleTimeChange('mm')}
onKeyPress={this.checkEnter}
/>
<Input
id="ss"
placeholder="0"
endAdornment="s"
inputProps={{
maxLength: 2,
ref: this.ss,
}}
value={ss}
onChange={this.handleTimeChange('ss')}
onKeyPress={this.checkEnter}
/>
</div>
<Typography variant="overline" style={{ fontSize: 10 }}>Leave blank for default times.</Typography>
</FormControl>
<TextField
className="ts-select"
label="Note (optional)"
value={note}
onChange={this.changeNote}
onKeyPress={this.checkEnter}
/>
<FormControl className="ts-track-button">
<Button color="primary" variant="contained" onClick={this.addCrop}>Track</Button>
</FormControl>
</div>
</Paper>
<Paper className="section">
<AppBar position="static">
<Toolbar variant="dense">
<Typography variant="subtitle1" className="title-text">Timers</Typography>
</Toolbar>
</AppBar>
<Table size="small">
<TableBody>
{crops.map((crop, index) => (
<CropTimer
{...crop}
key={`crop-${index}`}
onDelete={() => removeCrop(index)}
onRestart={() => this.reharvestCrop(index, crop)}
onMark={this.setMark(index)}
/>
))}
</TableBody>
</Table>
</Paper>
<AdContainer type="horizontal" />
</div>
);
}
Example #10
Source File: Skills.jsx From archeage-tools with The Unlicense | 4 votes |
render() {
const { skillsets } = this.state;
const { mobile, findClassName, classes, skillsets: skillsetData } = this.props;
let className;
const selectedSkillsets = skillsets.map(sks => sks.id);
if (skillsets.every(sks => Boolean(sks.id))) {
className = findClassName(selectedSkillsets);
}
const spentPoints = this.getSpentPoints();
const remainingPoints = MAX_POINTS - spentPoints;
const skillsetPoints = this.getTreePoints();
if (className) {
setTitle(`${className} Build (${skillsetPoints.join('/')})`);
} else {
const skillsetNames = selectedSkillsets.filter(id => Boolean(id)).map(id => skillsetData[id].name);
if (skillsetNames.length > 0) {
setTitle(`${skillsetNames.join('/')} Build (${skillsetPoints.splice(0, skillsetNames.length).join('/')})`);
} else {
setTitle('Skill Calculator');
}
}
return (
<div className="skills-container">
<div className="skills-header">
<Paper className="section">
<AppBar position="static">
<Toolbar>
<Typography variant="h5">
Skill Builder:
</Typography>
<Autocomplete
className="title-text class-select color-white"
autoHighlight
disableClearable
blurOnSelect
size="small"
loading={!objectHasProperties(classes)}
options={classes}
onChange={this.handleSelectClass}
value={{ name: className, skillsetIds: selectedSkillsets }}
getOptionLabel={option => option.name || ''}
renderOption={option => (
<div className="class-result" key={`class-${option.name}`}>
<div className="skillset-icons">
{option.skillsetIds.sort((a, b) => a - b).map(id => (
<span className="skillset-icon" data-id={id} key={`${option.name}-${id}`} />
))}
</div>
<Typography variant="body2">{option.name}</Typography>
</div>
)}
renderInput={params => (
<TextField
{...params}
label={`Find a class`}
variant="standard"
size="medium"
margin="none"
InputProps={{
...params.InputProps,
endAdornment: (
<>
{params.InputProps.endAdornment}
</>
),
}}
InputLabelProps={{
...params.InputLabelProps,
}}
/>
)}
/>
<Typography variant="subtitle2">{spentPoints}/{MAX_POINTS}</Typography>
<Tooltip title="Reset All Trees">
<IconButton color="inherit" aria-label="Reset" onClick={this.resetAllTrees}>
<ReplayIcon />
</IconButton>
</Tooltip>
</Toolbar>
</AppBar>
</Paper>
</div>
<div className={cn('section', 'skill-trees', { mobile })}>
{[0, 1, 2].map(treeId =>
<SkillTree
treeId={treeId}
key={`tree-${treeId}`}
setSkillTree={this.setSkillTree}
setSkill={this.setSkill}
setAncestral={this.setAncestral}
resetSkillTree={this.resetSkillTree}
treeData={skillsets[treeId]}
remainingPoints={remainingPoints}
selectedSkillset={selectedSkillsets}
/>,
)}
</div>
<AdContainer type="horizontal" />
</div>
);
}
Example #11
Source File: Taxes.jsx From archeage-tools with The Unlicense | 4 votes |
// eslint-disable-next-line complexity
render() {
const { openDialog, calculateLabor, mobile, price, buildings, createBuilding, characters } = this.props;
const { hostile, options, building, character, editId, editOpen, selectedOnly } = this.state;
const characterList = characters.length > 0 ? characters : ['Character 1'];
setTitle('Tax Calculator');
const properties = buildings.map(({ itemId, hostile, character }, index) => ({
...createBuilding(itemId),
hostile,
index,
character,
}));
const characterProperties = properties.filter(filterByCharacter(character));
const heavyTaxProperties = characterList.map((_, i) => countAll(properties.filter(filterByCharacter(i)).map(p => p.exempt
? 0 : 1)));
const heavyTaxRate = characterList.map((_, i) => HEAVY_TAX_RATE[Math.min(heavyTaxProperties[i] || 0, 8)]);
const taxesPerWeek = characterList.map((_, i) => this.calculateTaxes(properties.filter(filterByCharacter(i)), heavyTaxRate[i]));
const laborCost = characterList.map((_, i) => Math.ceil(taxesPerWeek[i] / 5) * (calculateLabor(300, CONSTRUCTION)));
// pending property
const pendingProperty = building.itemId ? ({ ...createBuilding(building.itemId), hostile }) : null;
let placeCost = 0;
let placeIncrease = 0;
if (pendingProperty) {
const { baseTax, deposit, hostile, exempt } = pendingProperty;
const newHeavyProperties = heavyTaxProperties[character] + (exempt ? 0 : 1);
const newHeavyRate = HEAVY_TAX_RATE[Math.min(newHeavyProperties, 8)];
const heavyTaxFee = !exempt ? Math.round(newHeavyRate * baseTax) : 0;
const hostileFee = hostile ? baseTax * HOSTILE_FACTION_TAX : 0;
const taxRate = baseTax + heavyTaxFee + hostileFee;
const newTaxes = this.calculateTaxes([...characterProperties, pendingProperty], newHeavyRate);
placeIncrease = newTaxes - taxesPerWeek[character];
placeCost = taxRate + deposit;
}
const taxPrice = (
<>
<TableCell colSpan={mobile ? 2 : 1}>
<Item id={ITEM.TAX_CERTIFICATE} inline /> Price:
</TableCell>
<TableCell align="right" colSpan={mobile ? 2 : 1}>
<ItemPrice itemId={ITEM.TAX_CERTIFICATE} unitSize={1} />
</TableCell>
</>
);
const taxSilverPerLabor = (
<>
<TableCell colSpan={mobile ? 2 : 1}>
<Tooltip title="Silver per labor">
<span>
<span className="dropdown-icon silver" /> per Labor:
</span>
</Tooltip>
</TableCell>
<TableCell align="right" colSpan={mobile ? 2 : 1}>
<Currency
type={CURRENCY.COIN}
count={(price ? price - 0.0046 : 0) * 5 / calculateLabor(300, CONSTRUCTION) * 10000}
/>
</TableCell>
</>
);
return (
<div className={cn('tool-container', { mobile })}>
<Paper className="section">
<AppBar position="static">
<Toolbar>
<Typography variant="h5" className="title-text">Tax Calculator</Typography>
<Tooltip title="Configure Proficiency">
<IconButton onClick={() => openDialog(DIALOG_MY_GAME, PROFICIENCIES)} color="inherit">
<ListAltIcon />
</IconButton>
</Tooltip>
</Toolbar>
</AppBar>
<div className="calculator-box">
<div className="calculator-totals">
<Autocomplete
className="building-select"
autoHighlight
disableClearable
blurOnSelect
size="small"
loading={!options.length}
options={options}
onChange={this.handleSelectBuilding}
value={building}
getOptionLabel={option => option.name || ''}
renderOption={option => (
<div className="item-result" key={option.id}>
<Item id={option.itemId} inline />
<Typography variant="body2">{option.name}</Typography>
</div>
)}
groupBy={option => option.group}
renderInput={params => (
<FormControl>
<TextField
{...params}
label={`Find a building`}
variant="standard"
size="medium"
InputProps={{
...params.InputProps,
endAdornment: (
<>
{params.InputProps.endAdornment}
</>
),
}}
InputLabelProps={{
...params.InputLabelProps,
}}
/>
</FormControl>
)}
/>
<Table size="small" className="place-info">
<TableBody>
<TableRow>
<TableCell>
<Item id={ITEM.TAX_CERTIFICATE} inline /> to Place:
</TableCell>
<TableCell align="right">
{placeCost}
</TableCell>
</TableRow>
<TableRow>
<TableCell>
Additional <Item id={ITEM.TAX_CERTIFICATE} inline /> per Week:
</TableCell>
<TableCell align="right">
{placeIncrease}
</TableCell>
</TableRow>
</TableBody>
</Table>
<div className="form-options">
<Tooltip title={
<>
<Typography style={{ textDecoration: 'underline' }}>Hostile Zones</Typography>
<Typography variant="body2">
Hostile zones are zones that are controlled by an enemy faction.<br />
Conflict zones are not considered hostile, but Growlgate Isle is considered hostile if you're
not a pirate.<br />
Placing property in a hostile zone will incur a hostile faction tax of
+{HOSTILE_FACTION_TAX * 100}%.
</Typography>
</>
}
>
<FormControlLabel
control={<Checkbox onChange={this.toggleHostile} checked={hostile} color="primary" />}
label="In Hostile Zone"
/>
</Tooltip>
<Button
color="primary"
variant="contained"
disabled={!building.itemId}
onClick={this.addProperty}
>
Add Property
</Button>
</div>
<Table size="small" className="total-list" stickyHeader>
<TableHead>
<TableRow>
<TableCell colSpan={2}>
Tax Totals
</TableCell>
<TableCell colSpan={mobile ? 2 : 4} align="right">
[
<Link
onClick={this.handleSelectedOnly(false)}
style={{ textDecoration: !selectedOnly ? 'underline' : 'none', cursor: 'pointer' }}
color="inherit"
>
All Characters
</Link>
|
<Link
onClick={this.handleSelectedOnly(true)}
style={{ textDecoration: selectedOnly ? 'underline' : 'none', cursor: 'pointer' }}
color="inherit"
>
Selected Character
</Link>]
</TableCell>
</TableRow>
</TableHead>
<TableBody>
<TableRow>
<TableCell>Properties:</TableCell>
<TableCell align="right">
{selectedOnly ? characterProperties.length : properties.length}
{((selectedOnly && heavyTaxProperties[character] !== characterProperties.length) || (!selectedOnly && countAll(Object.values(heavyTaxProperties)) !== properties.length)) &&
<Tooltip title="Heavy Tax Properties">
<span> <span className="hint">
({selectedOnly ? (heavyTaxProperties[character] || 0)
: countAll(Object.values(heavyTaxProperties))})
</span></span>
</Tooltip>}
</TableCell>
<TableCell>
<Tooltip
title={
<Table size="small" stickyHeader>
<TableHead>
<TableRow>
<TableCell>
Properties
</TableCell>
<TableCell align="right">
Rate
</TableCell>
</TableRow>
</TableHead>
<TableBody>
{HEAVY_TAX_RATE.filter((_, i) => i > 0).map((rate, id) => (
<TableRow key={`rate-tip-${id}`}>
<TableCell>
{id + 1}{id + 2 === HEAVY_TAX_RATE.length && '+'}
</TableCell>
<TableCell align="right">
+{rate * 100}%
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
}
>
<span className="hint">Heavy Tax Rate:</span>
</Tooltip>
</TableCell>
<TableCell align="right">
<OptionalTooltip
title={!selectedOnly &&
<Table size="small" stickyHeader>
<TableHead>
<TableRow>
<TableCell>
Character
</TableCell>
<TableCell align="right">
Rate
</TableCell>
</TableRow>
</TableHead>
<TableBody>
{Object.entries(heavyTaxRate).map(([id, rate]) => (
<TableRow key={`rate-row-${id}`}>
<TableCell>
{characterList[id]}
</TableCell>
<TableCell align="right">
+{rate * 100}%
</TableCell>
</TableRow>
))}
</TableBody>
</Table>}
>
<span>+{(selectedOnly ? heavyTaxRate[character]
: Object.values(heavyTaxRate).reduce((max, v) => v > max ? v : max, 0)) * 100}%</span>
</OptionalTooltip>
</TableCell>
{!mobile && taxPrice}
</TableRow>
<TableRow>
<TableCell><Item id={ITEM.TAX_CERTIFICATE} inline /> per Week:</TableCell>
<TableCell align="right">{selectedOnly ? taxesPerWeek[character]
: countAll(Object.values(taxesPerWeek))}</TableCell>
<TableCell>Labor per Week:</TableCell>
<TableCell align="right">{selectedOnly ? laborCost[character]
: countAll(Object.values(laborCost))}</TableCell>
{!mobile && taxSilverPerLabor}
</TableRow>
{mobile &&
<>
<TableRow>
{taxPrice}
</TableRow>
<TableRow>
{taxSilverPerLabor}
</TableRow>
</>}
</TableBody>
</Table>
</div>
{!mobile &&
<AdContainer section={false} type="square" />}
</div>
</Paper>
{mobile && <AdContainer type="feed" />}
<Paper className="section">
<AppBar position="static">
<Toolbar variant="dense">
<Tabs
value={Math.min(character, characterList.length - 1)}
onChange={this.setCharacter}
variant="scrollable"
>
{characterList.map((name, id) => (
<Tab
key={`tax-character-${id}`}
value={id}
label={
<span>
{name}
<IconButton
color="inherit"
size="small"
onClick={(e) => {
e.stopPropagation();
this.handleEditCharacter(id);
}}
style={{ marginLeft: 12 }}
>
<EditIcon />
</IconButton>
</span>
}
/>
))}
</Tabs>
<Tooltip title="Add Character">
<span>
<IconButton
onClick={() => this.handleEditCharacter(null)}
color="inherit"
disabled={characters.length >= MAX_CHARACTERS}
>
<AddIcon />
</IconButton>
</span>
</Tooltip>
</Toolbar>
</AppBar>
{mobile
? <PropertyList
calculateTax={this.calculateTax}
properties={properties}
heavyTaxProperties={heavyTaxProperties[character]}
heavyTaxRate={heavyTaxRate[character]}
character={character}
/>
: <PropertyTable
calculateTax={this.calculateTax}
properties={properties}
heavyTaxProperties={heavyTaxProperties[character]}
heavyTaxRate={heavyTaxRate[character]}
character={character}
/>}
</Paper>
<AdContainer type="horizontal" />
<CharacterDialog
characterId={editId}
open={editOpen}
onClose={this.handleEditClose}
/>
</div>
);
}