@material-ui/core#Slider JavaScript Examples
The following examples show how to use
@material-ui/core#Slider.
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: VolumeController.js From qasong with ISC License | 6 votes |
function volumeBar({ volume, setVolume, condensed }) {
function handleChange(e, newValue) {
setVolume(newValue / 100);
}
const classes = useStyles();
return (
<Box className={classes.root} px={3}>
<Grid container justify="center" spacing={2}>
<Grid item>
<VolumeDown onClick={() => setVolume(0)} />
</Grid>
<Grid item xs align="center">
<Slider color="secondary" value={volume * 100} onChange={handleChange} />
</Grid>
{!condensed && (
<Grid item>
<VolumeUp onClick={() => setVolume(1)} />
</Grid>
)}
</Grid>
</Box>
);
}
Example #2
Source File: ProgressBar.js From qasong with ISC License | 6 votes |
//import { formatSeconds } from "../../../functions";
function ProgressBar({ songProgress, songDuration, changeTime }) {
function handleChange(e, newValue) {
changeTime(newValue);
}
return (
<Box px={3}>
<Grid container spacing={2}>
{/*<Grid item>
<Typography style={{ fontSize: 12 }} color="textSecondary">
{formatSeconds(songProgress)}
</Typography>
</Grid>*/}
<Grid item xs>
<Slider
color="secondary"
value={songProgress}
max={songDuration}
onChange={handleChange}
/>
</Grid>
{/* <Grid item>
<Typography style={{ fontSize: 12 }} color="textSecondary">
{formatSeconds(songDuration)}
</Typography>
</Grid> */}
</Grid>
</Box>
);
}
Example #3
Source File: SurveyPage4.jsx From Corona-tracker with MIT License | 5 votes |
WellnessSlider = withStyles({
markLabel: {
fontSize: '1.17rem',
},
})(Slider)
Example #4
Source File: analysis.jsx From GraphVega with MIT License | 5 votes |
render() {
return(
<>
<Positions
positions={this.props.positions}
quantity={this.props.quantity}
quote={this.props.quote}
/>
<br />
<Row>
<Col sm={{span:5, offset:1}}>
<Card>
<CardContent>
<h6>
Implied volatility: {this.state.iv}% (avg: {this.state.originalIV}%)
</h6>
<Slider
defaultValue={this.state.originalIV}
value={this.state.iv}
onChange={this.handleIVChange}
min={0}
max={150}
/>
</CardContent>
</Card>
</Col>
<Col sm={{span:5}}>
<Card>
<CardContent>
<h6>
Days till last option expiry: {this.state.maxDateNum - this.state.dateNum} ({this.state.date})
</h6>
<Slider
value={this.state.dateNum}
onChange={this.handleDateChange}
min={0}
max={this.state.maxDateNum}
/>
</CardContent>
</Card>
</Col>
</Row>
<br />
<Row>
<Col sm={{span:12}}>
<LineChart data={this.state.chartData}/>
</Col>
</Row>
</>
)
}
Example #5
Source File: VerticalSliderView.js From Nemesis with GNU General Public License v3.0 | 5 votes |
render() {
return (
<div className="vertical-slider-view">
<Typography
variant="caption"
className={this.props.labelClassName}
style={{ whiteSpace: "nowrap" }}
>
<FormattedMessage id={this.props.item.id} />
</Typography>
<Slider
className={this.props.sliderClassName}
value={this.parser(this.props.item.current)}
disabled={!!this.state.isDirty}
min={this.parser(this.props.item.min)}
max={this.parser(this.props.item.max)}
step={this.props.item.step}
//vertical={this.props.item.axis === "y"}
orientation="vertical"
reverse="true"
onChange={(event, inputVal) => {
this.setState({ inputVal: this.parser(inputVal) });
this.props.item.current = this.parser(inputVal);
this.props.onChange && this.props.onChange(event, inputVal);
}}
onDragEnd={() => {
this.updateValue(this.state.inputVal);
}}
/>
<TextField
name={this.props.item.id}
inputProps={this.props.textInputProps}
type="number"
disabled={this.props.inputDisabled}
value={this.parser(this.state.inputVal)}
onBlur={() => {
this.updateValue(this.state.inputVal);
}}
onChange={event => {
this.setState({ inputVal: this.parser(event.target.value) });
}}
/>
</div>
);
}
Example #6
Source File: SliderView.js From Nemesis with GNU General Public License v3.0 | 5 votes |
render() {
return (
<div className={`slider-control ${this.props.item.id}`}>
<div className="slider-control-inner">
<Typography className="slider-control-label">
<FormattedMessage id={this.props.item.id} />
</Typography>
<Slider
value={this.parser(this.props.item.current)}
disabled={!!this.state.isDirty}
min={this.parser(this.props.item.min)}
max={this.parser(this.props.item.max)}
step={this.props.item.step}
vertical={this.props.item.axis === "y"}
onChange={(event, inputVal) => {
this.setState({ inputVal: this.parser(inputVal) });
this.props.item.current = this.parser(inputVal);
this.props.onChange && this.props.onChange(event, inputVal);
}}
onDragEnd={() => {
this.updateValue(this.state.inputVal);
}}
/>
</div>
<TextField
className="slider-control-input"
classes={{ padding: 0 }}
inputProps={{
className: "slider-control-input"
}}
name={this.props.item.id}
type="number"
disabled={this.props.inputDisabled}
value={this.parser(this.state.inputVal)}
onBlur={() => {
this.updateValue(this.state.inputVal);
}}
onChange={event => {
this.setState({ inputVal: this.parser(event.target.value) });
}}
/>
</div>
);
}
Example #7
Source File: Volume.jsx From archeage-tools with The Unlicense | 5 votes |
render() {
const { volume: _volume, setVolume } = this.props;
const { menu, volume } = this.state;
return (
<>
<Tooltip title={`Volume: ${_volume}%`}>
<IconButton
size="small"
onClick={this.handleOpenMenu}
color="inherit"
ref={this.menuRef}
>
<div>
{_volume > 49 && <VolumeUpIcon />}
{_volume < 50 && _volume > 0 && <VolumeDownIcon />}
{_volume === 0 && <VolumeMuteIcon />}
</div>
</IconButton>
</Tooltip>
<Popover
anchorEl={menu}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'center',
}}
transformOrigin={{
vertical: 'top',
horizontal: 'center',
}}
getContentAnchorEl={null}
open={Boolean(menu)}
onClose={this.handleCloseMenu}
>
<div className="volume-column">
<VolumeUpIcon />
<Slider
defaultValue={volume}
onChange={setVolume}
min={0}
max={100}
step={1}
orientation="vertical"
className="vol-slider"
/>
<VolumeDownIcon />
<Typography variant="subtitle2">{_volume}%</Typography>
</div>
</Popover>
</>
);
}
Example #8
Source File: NNFFBuildPanelDetails.js From Otto with MIT License | 5 votes |
function LayerOption({ layer, layerIndex, nn_dispatch }) {
const classes = useStyles();
if (layer == null) {
return null;
}
return (
<Grid className={classes.layerInputItem} item>
{/* <Grid style={{ "margin-top": "28px" }} item>
<Divider />
</Grid> */}
<Grid item>
<Grid direction="row" className={classes.nodesItem} container>
<Grid item>
<Typography className={classes.nodesLabel} gutterBottom>
Nodes
</Typography>
</Grid>
<Grid className={classes.sliderWidth} item>
<Slider
value={layer.units}
valueLabelDisplay="on"
ValueLabelComponent={ValueLabelDisplay}
step={1}
marks
min={1}
max={10}
onChange={(event, units) =>
onNodesChanged(layerIndex, units, nn_dispatch)
}
/>
</Grid>
</Grid>
</Grid>
<Grid item className={classes.actionItem}>
<FormControl className={classes.actionWidth}>
<InputLabel>Activation Function</InputLabel>
<Select
value={layer.activation}
onChange={(event) =>
onLayerActivationChange(event, layerIndex, nn_dispatch)
}
>
{Object.keys(Activations).map((key) => (
<MenuItem value={Activations[key]}>{Activations[key]}</MenuItem>
))}
</Select>
</FormControl>
</Grid>
<Grid item className={classes.actionItem}>
<FormControl className={classes.actionWidth}>
<InputLabel>Weight Initializer</InputLabel>
<Select
value={layer.initializer}
onChange={(event) =>
onLayerInitializerChange(event, layerIndex, nn_dispatch)
}
>
{Object.keys(Initializers).map((key) => (
<MenuItem value={Initializers[key]}>{Initializers[key]}</MenuItem>
))}
</Select>
</FormControl>
</Grid>
</Grid>
);
}
Example #9
Source File: SurveyPage1.jsx From Corona-tracker with MIT License | 5 votes |
WellnessSlider = withStyles({
markLabel: {
fontSize: '1.17rem',
},
})(Slider)
Example #10
Source File: ModeItemView.js From Nemesis with GNU General Public License v3.0 | 4 votes |
render() {
return (
<Accordion
defaultExpanded={this.state.mappings && this.state.mappings.length > 0}
>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="panel1c-content"
id="panel1c-header"
>
<Grid container spacing={3}>
<Grid item xs={9}>
<Typography className="heading">
<FormattedMessage
id={`aux.title.${this.props.auxMode.label}`}
/>
{false && (
<Chip
size="small"
color="primary"
label="Active"
style={{ marginLeft: "10px" }}
/>
)}
</Typography>
</Grid>
<Grid item xs={1} />
<Grid item xs={12} style={{ marginTop: "-24px" }}>
<Typography className="secondaryHeading">
<FormattedMessage
id={`aux.explanation.${this.props.auxMode.label}`}
/>
<a
href="#secondary-heading-and-columns"
style={{ color: "#288FDA", marginLeft: "10px" }}
className="link"
>
Learn more
</a>
</Typography>
</Grid>
</Grid>
</AccordionSummary>
{this.state.mappings &&
this.state.mappings.map((mapping, i) => {
let sliderLeft = 0;
var active_mode = false;
//set telemetry min and max
if (mapping.channel > -1 && this.props.telemetry) {
sliderLeft =
((this.props.telemetry[mapping.channel] - this.props.min) *
100) /
(this.props.max - this.props.min);
if (
this.props.telemetry[mapping.channel] > mapping.range[0] &&
this.props.telemetry[mapping.channel] < mapping.range[1]
) {
active_mode = true;
} else {
active_mode = false;
}
}
return (
<AccordionDetails
className={active_mode ? "active-mode details" : "details"}
key={mapping.key}
>
<Grid container spacing={1}>
<Grid item xs>
<HelperSelect
id={this.props.id}
className={this.props.id}
label="Channel"
value={
this.props.channels.filter(
c => c.value === mapping.channel
)[0].value
}
items={this.props.channels}
onChange={(event, value) => {
this.channelChange(i, value.props.value); // the channel object has the channel number in its value
this.setState({ isDirty: true }); // also set info changed here
}}
/>
</Grid>
<Grid item xs>
<Typography
style={{ margin: "20px", fontFamily: "inherit" }}
>
{this.props.min}
</Typography>
</Grid>
<Grid item xs={6}>
<ExpandMoreIcon //should not be grid item
style={{
position: "relative",
left: `${sliderLeft}%`
}}
color="secondary"
fontSize="large"
/>
<Slider
aria-labelledby="range-slider"
value={[mapping.range[0], mapping.range[1]]}
min={this.props.min}
max={this.props.max}
marks
step={this.props.step}
valueLabelDisplay="on"
onChange={(event, value) => this.sliderChange(i, value)}
onChangeCommitted={(event, value) =>
this.sliderChangeCommitted(i, value)
} // onChangeCommitted == mouseUp
/>
</Grid>
<Grid item xs>
<Typography style={{ margin: "20px" }}>
{this.props.max}
</Typography>
</Grid>
<Grid item xs>
<Tooltip title="Delete range">
<IconButton
aria-label="delete"
size="small"
style={{ marginTop: "20px" }}
onClick={() => this.deleteRange(i)}
>
<DeleteIcon style={{ fontSize: 18 }} />
</IconButton>
</Tooltip>
{i === this.state.mappings.length - 1 && (
<Tooltip title="Add another range">
<IconButton
aria-label="add"
size="small"
style={{ marginTop: "20px" }}
name="add_range"
onClick={() => this.addRange()}
color="primary"
variant="contained"
>
<AddCircleOutlineIcon />
</IconButton>
</Tooltip>
)}
</Grid>
</Grid>
</AccordionDetails>
);
})}
<Divider />
<AccordionActions>
{this.state.mappings &&
this.state.mappings.length === 0 && (
<Tooltip title="Add a range to start using this mode.">
<IconButton
aria-label="add"
name="add_range"
onClick={() => this.addRange()}
color="primary"
variant="contained"
>
<AddCircleOutlineIcon />
</IconButton>
</Tooltip>
)}
<Tooltip title="Bring mode back to saved state">
<Button size="small">Reset</Button>
</Tooltip>
</AccordionActions>
</Accordion>
);
}
Example #11
Source File: KNNToolbox.js From Otto with MIT License | 4 votes |
export default function KNNToolbox() {
const classes = useStyles();
const { state } = useState();
const { model_state, model_dispatch } = useModelState();
const [kVal, setKVal] = React.useState(model_state.knn_k);
const [col1, setCol1] = React.useState(model_state.knn_column1_index);
const [col2, setCol2] = React.useState(model_state.knn_column2_index);
function onUpdatePlot() {
model_dispatch({
type: ModelActions.SET_KNN_COLS,
indices: [col1, col2],
});
if (kVal !== model_state.knn_k) {
model_dispatch({
type: ModelActions.SET_KNN_K,
k: kVal,
});
invokeKNN(kVal, state.sample_dataset, model_dispatch);
}
}
return (
<Grid direction="column" container style={{ marginTop: "20px" }}>
{/* K Value */}
<Grid item>
<Grid direction="row" className={classes.nodesItem} container>
<Grid item>
<Typography className={classes.nodesLabel} gutterBottom>
K
</Typography>
</Grid>
<Grid className={classes.sliderWidth} item>
<Slider
value={kVal}
valueLabelDisplay="on"
ValueLabelComponent={ValueLabelDisplay}
step={1}
marks
min={1}
max={20}
onChange={(event, val) => setKVal(val)}
/>
</Grid>
</Grid>
</Grid>
{/* Column 1 */}
<Grid item className={classes.actionItem}>
<FormControl className={classes.actionWidth}>
<InputLabel id="demo-simple-select-label">X-Axis</InputLabel>
<Select
value={model_state.knn_columns.length > 0 ? col1 : ""}
onChange={(event) => setCol1(event.target.value)}
>
{model_state.knn_columns.map((column, index) => (
<MenuItem key={index} value={index}>
{model_state.knn_columns_map[column]}
</MenuItem>
))}
</Select>
</FormControl>
</Grid>
{/* Column 2 */}
<Grid item className={classes.actionItem}>
<FormControl className={classes.actionWidth}>
<InputLabel id="demo-simple-select-label">Y-Axis</InputLabel>
<Select
value={model_state.knn_columns.length > 0 ? col2 : ""}
onChange={(event) => setCol2(event.target.value)}
>
{model_state.knn_columns.map((column, index) => (
<MenuItem key={index} value={index}>
{model_state.knn_columns_map[column]}
</MenuItem>
))}
</Select>
</FormControl>
</Grid>
<Grid item>
<Button
color="primary"
className={classes.button}
variant="outlined"
onClick={onUpdatePlot}
>
{model_state.knn_k !== kVal ? "Re-Train Model" : "Update Plot"}
</Button>
</Grid>
</Grid>
);
}
Example #12
Source File: updateQuizDetails.js From Quizzie with MIT License | 4 votes |
function UpdateQuizDetails(props) {
const [quizId, setQuizId] = useState(props.match.params.id);
const [quizName, setQuizName] = useState("");
const [quizDate, setQuizDate] = useState(new Date());
const [duration, setDuration] = useState(5);
const [type, setType] = useState("private");
const [loading, setLoading] = useState(true);
const [redirect, setRedirect] = useState(false);
const { executeRecaptcha } = useGoogleReCaptcha();
const onQuizNameChange = (event) => {
setQuizName(event.target.value);
};
const handleDateChange = (date) => {
setQuizDate(date);
};
const handleTimeChange = (e, val) => {
setDuration(val);
};
const onTypeChange = (event) => {
setType(event.target.value);
};
const handleSubmit = async () => {
setLoading(true);
let token = localStorage.getItem("authToken");
let url = `https://quizzie-api.herokuapp.com/quiz/updateDetails/${quizId}`;
let captcha = await executeRecaptcha("update_quiz_details");
let updateOps = [
{ propName: "quizName", value: quizName },
{ propName: "scheduledFor", value: quizDate.getTime() },
{ propName: "quizDuration", value: duration },
];
let data = {
updateOps,
captcha,
};
try {
await axios
.patch(url, data, {
headers: {
"auth-token": token,
},
})
.then((res) => {
setLoading(false);
setRedirect(true);
});
} catch (error) {
console.log(error);
setLoading(false);
}
};
const getQuizDetails = async () => {
setLoading(true);
let token = localStorage.getItem("authToken");
let url = `https://quizzie-api.herokuapp.com/quiz/${quizId}`;
try {
await axios
.get(url, {
headers: {
"auth-token": token,
},
})
.then((res) => {
let details = res.data.result;
setQuizName(details.quizName);
setQuizDate(new Date(Number(details.scheduledFor)));
setDuration(details.quizDuration);
setType(details.quizType);
setLoading(false);
});
} catch (error) {
console.log(error);
setLoading(false);
}
};
useEffect(() => {
getQuizDetails();
}, []);
useEffect(() => {
let token = localStorage.getItem("authToken");
if (token === null) {
setLoading(false);
setRedirect(true);
return;
}
}, []);
if (loading) {
return <Loading />;
} else if (redirect) {
return <Redirect to={`/editQuiz/${quizId}`} />;
} else {
return (
<Container className="create-quiz-page">
<div className="create-form">
<Typography variant="h4" className="create-head">
Quiz Details
</Typography>
<div className="create-form-inputs">
<TextInput
variant="outlined"
label="Quiz Name"
value={quizName}
onChange={onQuizNameChange}
name="Quiz Name"
className="form-input"
/>
<MuiPickersUtilsProvider utils={DateFnsUtils}>
<Grid
className="date-time-select"
container
spacing={3}
>
<Grid item xs={12} sm={6}>
<KeyboardDatePicker
disableToolbar
variant="inline"
format="MM/dd/yyyy"
margin="normal"
label="Select Quiz Date"
value={quizDate}
onChange={handleDateChange}
/>
</Grid>
<Grid item xs={12} sm={6}>
<KeyboardTimePicker
margin="normal"
label="Select Quiz Start Time"
value={quizDate}
onChange={handleDateChange}
/>
</Grid>
</Grid>
</MuiPickersUtilsProvider>
<p style={{ marginTop: "5%", marginBottom: "5%" }}>
Quiz Time (in minutes):
</p>
<Slider
defaultValue={5}
aria-labelledby="quiz time slider"
step={5}
min={5}
max={60}
valueLabelDisplay="on"
marks
className="time-slider"
value={duration}
onChange={handleTimeChange}
/>
<p style={{ color: "#777" }}>Select quiz type: </p>
<Tooltip title="Cannot change quiz type">
<Select
disabled
value={type}
onChange={onTypeChange}
className="type-select"
>
<MenuItem value="public">Public</MenuItem>
<MenuItem value="private">Private</MenuItem>
</Select>
</Tooltip>
<Button
className="login-btn create-btn"
onClick={handleSubmit}
>
Update Quiz
</Button>
</div>
</div>
</Container>
);
}
}
Example #13
Source File: Volume.js From budgie-stream with MIT License | 4 votes |
VolumeSlider = () => {
const classes = useStyles();
const { playback } = useContext(ClientContext);
const [state, setState] = playback;
const devices = state.devices.filter((device) => device.selected === true);
// Only control the volume if any devices are selected
const disabled = !state.playing;
const [masterValue, setMasterValue] = useState(30);
const prevMasterValue = usePreviousValue(masterValue);
const [anchorEl, setAnchorEl] = useState(null);
const ref = createRef();
const open = Boolean(anchorEl);
const handleClose = () => {
setAnchorEl(null);
};
const handleMasterVol = (newMasterValue) => {
// Toggle multiple devices control
if (devices.length > 1) {
setAnchorEl(ref.current);
}
setMasterValue(newMasterValue);
if (devices.length === 1) {
handleVolChange(devices[0].name, newMasterValue, null);
} else {
const masterChange = newMasterValue - prevMasterValue;
handleVolChange(null, null, masterChange);
}
};
const handleVolChange = (deviceName, newValue, master = false) => {
let newState = [...state.devices];
if (!master) {
const deviceIndex = state.devices.findIndex(
(device) => device.name === deviceName
);
newState[deviceIndex] = { ...newState[deviceIndex], vol: newValue };
const avgVol =
devices.reduce(
(totalCalories, device) => totalCalories + device.vol,
0
) / devices.length;
setMasterValue(avgVol);
} else {
newState.map((x) => (x.selected ? (x.vol = x.vol + master) : x));
}
setState((prevState) => ({
...prevState,
devices: newState,
}));
setVolume(devices);
};
return (
<>
<div className={classes.root}>
<Grid container className={classes.container} spacing={1}>
<Grid item id="volume-icon">
<VolumeUp />
</Grid>
<Grid item ref={ref} xs>
<Slider
className={classes.slider}
value={masterValue}
disabled={disabled}
onChange={(event, value) => handleMasterVol(value)}
aria-labelledby="volume-slider"
/>
</Grid>
</Grid>
</div>
<Popover
className={classes.popover}
open={open}
anchorEl={anchorEl}
onClose={handleClose}
anchorOrigin={{
vertical: "top",
horizontal: "center",
}}
transformOrigin={{
vertical: "bottom",
horizontal: "center",
}}
>
<DevicesVolume devices={devices} handleChange={handleVolChange} />
</Popover>
</>
);
}
Example #14
Source File: FontConverter.js From handReacting with Apache License 2.0 | 4 votes |
function FontConverter() {
const [text, setText] = useState("A hero can be anyone. Even a man doing something as simple and reassuring as putting a coat around a young boy's shoulders to let him know that the world hadn't ended. This is a sample text. Enter your text here to convert to handwritten font.")
const [fontFamily, setFontFamily] = useState("'Beth Ellen', cursive")
const [fontSize, setFontSize] = useState(17)
const [color, setColor] = useState('blue')
const [pageColor, setPageColor] = useState('white')
const [letterSpacing, setLetterSpacing] = useState(1)
const [wordSpacing, setWordSpacing] = useState(1)
const [lineHeight, setLineHeight] = useState(30)
const [fontWeight, setFontWeight] = useState(300)
const [line, setLine] = useState(false)
const [shadow, setShadow] = useState(false)
const [margin, setMargin] = useState(false)
const [marginTop, setMarginTop] = useState(false)
const [showColorPicker1, setShowColorPicker1] = useState(false)
const [showColorPicker2, setShowColorPicker2] = useState(false)
const colorList = ['#ffffff', '#f2f2f2', '#e6e6e6', '#d9d9d9', '#cccccc', '#bfbfbf', '#ffffe6', ' #ffffcc', '#ffffb3', '#ffff99', '#e6ffff', '#e6ffe6']
const handleLineHeight = (event, newValue) => {
setLineHeight(newValue);
};
const handleFontWeight = (event, newValue) => {
setFontWeight(newValue);
};
const handlePageLines = (event) => {
setLine(!line);
};
const handleShadow = (event) => {
setShadow(!shadow);
};
const handleMargin = (event) => {
setMargin(!margin);
};
const handleMarginTop = (event) => {
setMarginTop(!marginTop);
};
const generateJpeg = () => {
domtoimage.toJpeg(document.getElementById('page'), { quality: 1 })
.then(function (dataUrl) {
var link = document.createElement('a');
link.download = 'download.jpeg';
link.href = dataUrl;
link.click();
});
}
return (
<div className="fontConverter">
<div className="fontStyler">
<div className="input_container">
<Paper elevation={15} className="paper_input" >
<textarea onChange={e => setText(e.target.value)}
className="inputTextField" cols='36' rows='19'>
{text}
</textarea>
</Paper>
<div className="usageButton">
<Usage />
</div>
</div>
<div className="font_selector">
{/* <h2>Select Styles</h2> */}
<div className="gridOne">
<div className="fontFamily" style={{marginBottom: "1.5rem"}}>
<FormControl style={{minWidth: 150}}>
<InputLabel id="font-label">Fonts</InputLabel>
<Select
labelId="font-label"
onChange={e => setFontFamily(e.target.value)}
>
<MenuItem style={{fontFamily: "'Architects Daughter', cursive"}} value={"'Architects Daughter', cursive"}>Architects Daughter</MenuItem>
<MenuItem style={{fontFamily: "'Bad Script', cursive"}} value={"'Bad Script', cursive"}>Bad Script</MenuItem>
<MenuItem style={{fontFamily: "'Beth Ellen', cursive"}} value={"'Beth Ellen', cursive"}>Beth Ellen</MenuItem>
<MenuItem style={{fontFamily: "'Bilbo', cursive"}} value={"'Bilbo', cursive"}>Bilbo</MenuItem>
<MenuItem style={{fontFamily: "'Calligraffitti', cursive"}} value={"'Calligraffitti', cursive"}>Calligraffitti</MenuItem>
<MenuItem style={{fontFamily: "'Caveat', cursive"}} value={"'Caveat', cursive"}>Caveat</MenuItem>
<MenuItem style={{fontFamily: "'Charmonman', cursive"}} value={"'Charmonman', cursive"}>Charmonman</MenuItem>
<MenuItem style={{fontFamily: "'Dancing Script', cursive"}} value={"'Dancing Script', cursive"}>Dancing Script</MenuItem>
<MenuItem style={{fontFamily: "'Dawning of a New Day', cursive"}} value={"'Dawning of a New Day', cursive"}>Dawning of a New Day</MenuItem>
<MenuItem style={{fontFamily: "'Euphoria Script', cursive"}} value={"'Euphoria Script', cursive"}>Euphoria Script</MenuItem>
<MenuItem style={{fontFamily: "'Homemade Apple', cursive"}} value={"'Homemade Apple', cursive"}>Homemade Apple</MenuItem>
<MenuItem style={{fontFamily: "'Indie Flower', cursive"}} value={"'Indie Flower', cursive"}>Indie Flower</MenuItem>
<MenuItem style={{fontFamily: "'Just Me Again Down Here', cursive"}} value={"'Just Me Again Down Here', cursive"}>Just Me Again Down Here</MenuItem>
<MenuItem style={{fontFamily: "'Kristi', cursive"}} value={"'Kristi', cursive"}>Kristi</MenuItem>
<MenuItem style={{fontFamily: "'Liu Jian Mao Cao', cursive"}} value={"'Liu Jian Mao Cao', cursive"}>Liu Jian Mao Cao</MenuItem>
<MenuItem style={{fontFamily: "'Loved by the King', cursive"}} value={"'Loved by the King', cursive"}>Loved by the King</MenuItem>
<MenuItem style={{fontFamily: "'Lovers Quarrel', cursive"}} value={"'Lovers Quarrel', cursive"}>Lovers Quarrel</MenuItem>
<MenuItem style={{fontFamily: "'Marck Script', cursive"}} value={"'Marck Script', cursive"}>Marck Script</MenuItem>
<MenuItem style={{fontFamily: "'Mr Dafoe', cursive"}} value={"'Mr Dafoe', cursive"}>Mr Dafoe</MenuItem>
<MenuItem style={{fontFamily: "'Mr De Haviland', cursive"}} value={"'Mr De Haviland', cursive"}>Mr De Haviland</MenuItem>
<MenuItem style={{fontFamily: "'Mrs Saint Delafield', cursive"}} value={"'Mrs Saint Delafield', cursive"}>Mrs Saint Delafield</MenuItem>
<MenuItem style={{fontFamily: "'Nanum Brush Script', cursive"}} value={"'Nanum Brush Script', cursive"}>Nanum Brush Script</MenuItem>
<MenuItem style={{fontFamily: "'Over the Rainbow', cursive"}} value={"'Over the Rainbow', cursive"}>Over the Rainbow</MenuItem>
<MenuItem style={{fontFamily: "'Parisienne', cursive"}} value={"'Parisienne', cursive"}>Parisienne</MenuItem>
<MenuItem style={{fontFamily: "'Qwigley', cursive"}} value={"'Qwigley', cursive"}>Qwigley</MenuItem>
<MenuItem style={{fontFamily: "'Rancho', cursive"}} value={"'Rancho', cursive"}>Rancho</MenuItem>
<MenuItem style={{fontFamily: "'ArchiReenie Beanietects', cursive"}} value={"'ArchiReenie Beanietects', cursive"}>Reenie Beanie</MenuItem>
<MenuItem style={{fontFamily: "'Ruthie', cursive"}} value={"'Ruthie', cursive"}>Ruthie</MenuItem>
<MenuItem style={{fontFamily: "'Sacramento', cursive"}} value={"'Sacramento', cursive"}>Sacramento</MenuItem>
<MenuItem style={{fontFamily: "'Shadows Into Light', cursive"}} value={"'Shadows Into Light', cursive"}>Shadows Into Light</MenuItem>
<MenuItem style={{fontFamily: "'Shadows Into Light Two', cursive"}} value={"'Shadows Into Light Two', cursive"}>Shadows Into Light Two</MenuItem>
<MenuItem style={{fontFamily: "'Vibur', cursive"}} value={"'Vibur', cursive"}>Vibur</MenuItem>
<MenuItem style={{fontFamily: "'Waiting for the Sunrise', cursive"}} value={"'Waiting for the Sunrise', cursive"}>Waiting for the Sunrise</MenuItem>
<MenuItem style={{fontFamily: "'Yellowtail', cursive"}} value={"'Yellowtail', cursive"}>Yellowtail</MenuItem>
</Select>
</FormControl>
</div>
<div className="fontSize" style={{marginBottom: "1.5rem"}}>
<FormControl style={{minWidth: 150}}>
<InputLabel id="fontSize-label" >Font Size</InputLabel>
<Select
value={fontSize}
labelId="fontSize-label"
onChange={e => setFontSize(e.target.value)}
>
<MenuItem value={14}>14</MenuItem>
<MenuItem value={15}>15</MenuItem>
<MenuItem value={16}>16</MenuItem>
<MenuItem value={17}>17</MenuItem>
<MenuItem value={18}>18</MenuItem>
<MenuItem value={19}>19</MenuItem>
<MenuItem value={20}>20</MenuItem>
<MenuItem value={21}>21</MenuItem>
<MenuItem value={22}>22</MenuItem>
<MenuItem value={23}>23</MenuItem>
<MenuItem value={24}>24</MenuItem>
</Select>
</FormControl>
</div>
<div className="fontWeight" style={{marginBottom: "1.5rem"}}>
<InputLabel id="fontWeight">Font Weight</InputLabel>
<Slider style={{width: 150}}
defaultValue={200}
value={fontWeight}
aria-labelledby="discrete-slider"
valueLabelDisplay="auto"
onChange={handleFontWeight}
step={100}
min={100}
max={900}
/>
</div>
<div className="letterSpacing" style={{marginBottom: "1.5rem"}}>
<FormControl style={{minWidth: 150}}>
<InputLabel id="letterSpacing-label">Letter Spacing</InputLabel>
<Select
value={letterSpacing}
labelId="letterSpacing-label"
onChange={e => setLetterSpacing(e.target.value)}
>
<MenuItem value={-2}>-2</MenuItem>
<MenuItem value={-1.5}>-1.5</MenuItem>
<MenuItem value={-1}>-1</MenuItem>
<MenuItem value={-0.5}>-0.5</MenuItem>
<MenuItem value={0}>0</MenuItem>
<MenuItem value={0.5}>0.5</MenuItem>
<MenuItem value={1}>1</MenuItem>
<MenuItem value={1.5}>1.5</MenuItem>
<MenuItem value={2}>2</MenuItem>
<MenuItem value={3}>3</MenuItem>
<MenuItem value={4}>4</MenuItem>
</Select>
</FormControl>
</div>
<div className="wordSpacing" style={{marginBottom: "1.5rem"}}>
<FormControl style={{minWidth: 150}}>
<InputLabel id="wordSpacing-label">Word Spacing</InputLabel>
<Select
value={wordSpacing}
labelId="wordSpacing-label"
onChange={e => setWordSpacing(e.target.value)}
>
<MenuItem value={-4}>-4</MenuItem>
<MenuItem value={-3}>-3</MenuItem>
<MenuItem value={-2}>-2</MenuItem>
<MenuItem value={-1}>-1</MenuItem>
<MenuItem value={0}>0</MenuItem>
<MenuItem value={0.5}>0.5</MenuItem>
<MenuItem value={1}>1</MenuItem>
<MenuItem value={2}>2</MenuItem>
<MenuItem value={3}>3</MenuItem>
<MenuItem value={4}>4</MenuItem>
<MenuItem value={5}>6</MenuItem>
<MenuItem value={6}>8</MenuItem>
</Select>
</FormControl>
</div>
</div>
<div className="gridTwo">
<div className="colorButton">
<Button style={{backgroundColor: `${color}`}} onClick={() => setShowColorPicker1(showColorPicker => !showColorPicker)} variant="contained" color="primary">
{showColorPicker1 ? 'Close ' : 'Font Color'}
</Button>
</div>
<div className="colorPicker">
{
showColorPicker1 && (
<SketchPicker
color={color}
onChange={targetColor => setColor(targetColor.hex)}
/>
)
}
</div>
<div className="colorButton">
<Button style={{backgroundColor: `${pageColor}`, color: 'black'}} onClick={() => setShowColorPicker2(showColorPicker => !showColorPicker)} variant="contained" color="primary">
{showColorPicker2 ? 'Close ' : 'Page Color'}
</Button>
</div>
<div className="colorPicker">
{
showColorPicker2 && (
<CirclePicker
colors={colorList}
color={pageColor}
onChange={targetColor => setPageColor(targetColor.hex)}
/>
)
}
</div>
</div>
<div className="gridThree">
<div className="lineHeight" style={{marginBottom: "1.5rem"}}>
<InputLabel id="lineHeight">Line Height</InputLabel>
<Slider style={{width: 150}}
defaultValue={30}
value={lineHeight}
aria-labelledby="discrete-slider"
valueLabelDisplay="auto"
onChange={handleLineHeight}
step={1}
min={10}
max={70}
color="primary"
/>
</div>
<div className="linesCheckbox">
<Tooltip title="Add Page Lines" placement="right" TransitionComponent={Fade} arrow>
<FormControlLabel
control={<Switch checked={line} onChange={handlePageLines} name="lines" color="primary"/>}
label="Page Lines"
/>
</Tooltip>
</div>
<div className="shadowCheckbox">
<Tooltip title="Add Shadow To Paper" placement="left" TransitionComponent={Fade} arrow>
<FormControlLabel
control={<Switch checked={shadow} onChange={handleShadow} name="shadow" color="primary"/>}
label="Scan Effect"
/>
</Tooltip>
</div>
<div className="marginCheckbox">
<Tooltip title="Insert Margin" placement="right" TransitionComponent={Fade} arrow>
<FormControlLabel
control={<Switch checked={margin} onChange={handleMargin} name="shadow" color="primary"/>}
label="Page Margin"
/>
</Tooltip>
</div>
<div className="marginTopCheckbox">
<Tooltip title="Give Top Margin" placement="right" TransitionComponent={Fade} arrow>
<FormControlLabel
control={<Switch checked={marginTop} onChange={handleMarginTop} name="shadow" color="primary"/>}
label="Top Space"
/>
</Tooltip>
</div>
</div>
</div>
<div className="output_container">
<Paper elevation={3} square={true} className="paper" id="page" style={{backgroundImage:
line? 'repeating-linear-gradient(transparent 0px, transparent 24px, #333333 25px)' : 'none', backgroundColor: `${pageColor}`,
WebkitBoxShadow: shadow ? 'inset 18px 0px 50px -7px rgba(106,110,101,1)' : 'none', MozBoxShadow: shadow ? 'inset 18px 0px 50px -7px rgba(106,110,101,1)' : 'none',
boxShadow: shadow ? 'inset 18px 0px 50px -7px rgba(106,110,101,1)' : 'none'}}>
<p className="output_text"
style={{fontFamily: `${fontFamily}`, fontSize: `${fontSize}px`, color: `${color}`,
letterSpacing: `${letterSpacing}px`, wordSpacing: `${wordSpacing}px`, lineHeight: `${lineHeight}px`, paddingTop: marginTop? '2rem' : '0',
fontWeight: `${fontWeight}`, left: margin? '2rem' : '0', borderLeft: margin? '2px solid #666666' : 'none', paddingLeft: margin? '0.5rem' : '0'}}>
{text}
</p>
</Paper>
<div className="download_button">
<Button onClick={generateJpeg} variant="contained" style={{color: 'white', backgroundColor: '#ec4c4c'}}>Download Image </Button>
</div>
</div>
</div>
</div>
)
}
Example #15
Source File: Player.js From Octave with MIT License | 4 votes |
// The Entire Bottom part where all the song controls are available
function Player({ show }) {
// playing 0 -> paused | 1 -> playing | -1 -> loading
const [playing, setPlaying] = useState(0);
const [continuousTime, setContinuousTime] = useState(0);
const [displayCurrentTime, setDisplayCurrentTime] = useState("0:00");
const [displayDurationTime, setDisplayDurationTime] = useState("0:00");
const [currentSong, setCurrentSong] = useState(null);
const audioRef = useRef(null);
const { newSong, songIndex } = useSelector((state) => state.currentSession);
const dispatch = useDispatch();
const isPlayingRef = useRef(false);
const onTabCloseRef = useRef((e) => {
if (isPlayingRef.current) {
e.preventDefault();
e.returnValue = "You have unfinished changes!";
}
});
useEffect(() => {
const fn = onTabCloseRef.current;
window.addEventListener("beforeunload", fn);
return () => {
window.removeEventListener("beforeunload", fn);
};
}, []);
useEffect(() => {
if (currentSong) {
document.title = `${currentSong.name} (${currentSong.artist}) | Octave`;
dispatch(setPlayingSong(currentSong));
setRecentSongsLocalStorage(currentSong);
}
}, [currentSong, dispatch]);
useEffect(() => {
if (newSong) {
dispatch(setSongIndex(0));
setCurrentSong(newSong);
setPlaying(-1);
dispatch(setNewSong(null));
}
}, [dispatch, newSong, songIndex]);
// playing 0 -> paused | 1 -> playing | -1 -> loading
const playPauseSong = () => {
if (!currentSong) {
playNextSong();
return;
}
if (playing === 1) {
audioRef.current.pause();
setPlaying(0);
isPlayingRef.current = false;
document.title = `Octave`;
} else {
audioRef.current.play();
setPlaying(1);
isPlayingRef.current = true;
document.title = `${currentSong?.name} (${currentSong?.artist}) | Octave`;
}
};
const playNextSong = useCallback(() => {
const nextSong = getNextSong(songIndex);
if (nextSong) {
setCurrentSong(nextSong);
setPlaying(-1);
dispatch(incSongIndex());
}
}, [songIndex, dispatch]);
const playPreviousSong = useCallback(() => {
const prevSong = getPreviousSong(songIndex);
if (prevSong) {
setCurrentSong(prevSong);
dispatch(decSongIndex());
}
}, [songIndex, dispatch]);
const playSongByMediaSession = useCallback(async () => {
await audioRef.current.play();
navigator.mediaSession.playbackState = "playing";
setPlaying(1);
isPlayingRef.current = true;
document.title = `${currentSong?.name} (${currentSong?.artist}) | Octave`;
}, [currentSong]);
const pauseSongByMediaSession = async () => {
await audioRef.current.pause();
navigator.mediaSession.playbackState = "paused";
setPlaying(0);
isPlayingRef.current = false;
document.title = `Octave`;
};
// MediaSession docs -> https://developer.mozilla.org/en-US/docs/Web/API/MediaSession
const setupMediaSession = useCallback(() => {
if ("mediaSession" in navigator) {
navigator.mediaSession.metadata = new window.MediaMetadata({
title: currentSong.name,
artist: currentSong.artist,
});
navigator.mediaSession.setActionHandler("play", () => {
playSongByMediaSession();
});
navigator.mediaSession.setActionHandler("pause", () => {
pauseSongByMediaSession();
});
navigator.mediaSession.setActionHandler("previoustrack", () => {
playPreviousSong();
});
navigator.mediaSession.setActionHandler("nexttrack", () => {
playNextSong();
});
}
}, [currentSong, playNextSong, playPreviousSong, playSongByMediaSession]);
// When the audio element is rendered on the screen, this function gets executed
const audioElementCallbackRef = useCallback(
(node) => {
if (!node) return;
audioRef.current = node;
audioRef.current.ontimeupdate = (event) => {
const { duration, currentTime } = event.srcElement;
let progressPercent = (currentTime / duration) * 100;
// calculate current time of a song
const currentRunningTime = calculateCurrentTime(currentTime);
setContinuousTime(progressPercent);
setDisplayCurrentTime(currentRunningTime);
};
audioRef.current.onended = () => {
setPlaying(0);
isPlayingRef.current = false;
document.title = `Octave`;
playNextSong();
};
// can also use oncanplay
audioRef.current.onloadeddata = async () => {
await audioRef.current.play();
setPlaying(1);
isPlayingRef.current = true;
setupMediaSession();
const durationTime = calculateDurationTime(audioRef.current.duration);
setDisplayDurationTime(durationTime);
};
},
[audioRef, playNextSong, setupMediaSession]
);
const songProgressChanged = useCallback(
(event, value) => {
if (!currentSong) return;
const newProgressSeconds = (value / 100) * audioRef.current.duration;
audioRef.current.currentTime = newProgressSeconds;
setContinuousTime(newProgressSeconds);
},
[audioRef, currentSong]
);
if (!show) return null;
return (
<div className="player">
<div className="player__progress">
<Slider
color="secondary"
value={continuousTime}
onChangeCommitted={songProgressChanged}
/>
</div>
<div className="player__main">
<div className="player__song">
{currentSong?.imageUrl && (
<img
src={currentSong.imageUrl}
alt=""
className="song__infoImage"
/>
)}
<div className="song__info">
<p className="song__infoTrack">{currentSong?.name}</p>
<p className="song__infoArtist">{currentSong?.artist}</p>
</div>
</div>
<PlayerControls
playPauseSong={playPauseSong}
playing={playing}
playNextSong={playNextSong}
playPreviousSong={playPreviousSong}
/>
<div className="player__left">
<PlayerSongListButton />
<div className="player__duration">
<span className="duration__current">{displayCurrentTime}</span>
<span>/</span>
<span className="duration__total">{displayDurationTime}</span>
</div>
</div>
</div>
<audio ref={audioElementCallbackRef} src={currentSong?.url}></audio>
</div>
);
}
Example #16
Source File: CreateQuiz.js From Quizzie with MIT License | 4 votes |
function CreateQuiz() {
const [quizName, setQuizName] = useState("");
const [quizDate, setQuizDate] = useState(new Date());
const [duration, setDuration] = useState(5);
const [type, setType] = useState("private");
const [loading, setLoading] = useState(false);
const [redirect, setRedirect] = useState(false);
const [redirectEdit, setRedirectEdit] = useState(false);
const [quizId, setQuizId] = useState("");
const [error, setError] = useState(false);
const { executeRecaptcha } = useGoogleReCaptcha();
const onQuizNameChange = (event) => {
setQuizName(event.target.value);
};
const handleDateChange = (date) => {
setQuizDate(date);
};
const handleTimeChange = (e, val) => {
setDuration(val);
};
const onTypeChange = (event) => {
setType(event.target.value);
};
const handleSubmit = async () => {
setLoading(true);
let token = localStorage.getItem("authToken");
let url = "https://quizzie-api.herokuapp.com/quiz/createQuiz";
let captcha = await executeRecaptcha("create_quiz");
let data = {
quizName: quizName,
scheduledFor: quizDate.getTime(),
quizDuration: duration,
quizType: type,
captcha: captcha,
};
try {
await axios
.post(url, data, {
headers: {
"auth-token": token,
},
})
.then((res) => {
setQuizId(res.data.result._id);
setLoading(false);
setRedirectEdit(true);
});
} catch (error) {
console.log(error);
setLoading(false);
}
};
useEffect(() => {
let token = localStorage.getItem("authToken");
if (token === null) {
setLoading(false);
setRedirect(true);
return;
}
}, []);
if (loading) {
return <Loading />;
} else if (redirect) {
return <Redirect to="/dashboard" />;
} else if (redirectEdit) {
return <Redirect to={`/editQuiz/${quizId}`} />;
} else {
return (
<Container className="create-quiz-page">
<div className="create-form">
<Typography variant="h4" className="create-head">
Quiz Details
</Typography>
<div className="create-form-inputs">
<TextInput
variant="outlined"
label="Quiz Name"
value={quizName}
onChange={onQuizNameChange}
name="Quiz Name"
className="form-input"
/>
<MuiPickersUtilsProvider utils={DateFnsUtils}>
<Grid
className="date-time-select"
container
spacing={3}
>
<Grid item xs={12} sm={6}>
<KeyboardDatePicker
disableToolbar
variant="inline"
format="MM/dd/yyyy"
margin="normal"
label="Select Quiz Date"
value={quizDate}
onChange={handleDateChange}
/>
</Grid>
<Grid item xs={12} sm={6}>
<KeyboardTimePicker
ampm={true}
format="hh:mm:ss aa"
views={["hours", "minutes", "seconds"]}
margin="normal"
label="Select Quiz Start Time"
value={quizDate}
onChange={handleDateChange}
keyboardIcon={<AccessAlarm />}
/>
</Grid>
</Grid>
</MuiPickersUtilsProvider>
<p style={{ marginTop: "5%", marginBottom: "5%" }}>
Quiz Time (in minutes):
</p>
<Slider
defaultValue={5}
aria-labelledby="quiz time slider"
step={5}
min={5}
max={60}
valueLabelDisplay="on"
marks
className="time-slider"
value={duration}
onChange={handleTimeChange}
/>
<p>Select quiz type: </p>
<Select
value={type}
onChange={onTypeChange}
className="type-select"
>
<MenuItem value="public">Public</MenuItem>
<MenuItem value="private">Private</MenuItem>
</Select>
<Button
className="login-btn create-btn"
onClick={handleSubmit}
>
Create Quiz
</Button>
<Typography
variant="subtitle1"
className="create-subtitle"
>
NOTE: After creating the quiz, you can add questions
by editing the quiz in YOUR QUIZZES section of the
dashboard.
</Typography>
</div>
</div>
<Snackbar
open={error}
autoHideDuration={5000}
onClose={() => setError(false)}
>
<Alert
variant="filled"
severity="error"
onClose={() => setError(false)}
>
There was a problem. Please try again!
</Alert>
</Snackbar>
</Container>
);
}
}
Example #17
Source File: SearchPage.js From app with MIT License | 4 votes |
function SearchPage() {
const classes = useStyles();
const { showError } = useNotifications();
// State
const [showAddressPicker, setShowAddressPicker] = useState(false);
const [nearbyRequests, setNearbyRequests] = useState(null);
const [currentLatLong, setCurrentLatLong] = useState({
latitude: DEFAULT_LATITUDE,
longitude: DEFAULT_LONGITUDE,
});
const [currentPlaceLabel, setCurrentPlaceLabel] = React.useState(
`Using default location: ${DEFAULT_LOCATION_NAME}`,
);
const [distance, setDistance] = useState(defaultDistance);
const [searching, setSearching] = useState(false);
const [onSearch$] = useState(() => new Subject());
// Data
const user = useUser();
const firestore = useFirestore();
const analytics = useAnalytics();
const { GeoPoint } = useFirestore;
async function searchForNearbyRequests({ searchLocation, searchDistance }) {
if (!searchLocation) return;
// Use lat/long set to state (either from profile or default)
const { latitude, longitude } = searchLocation;
setSearching(true);
analytics.logEvent('search', {
search_term: `latitude=${latitude}&longitude=${longitude}`,
});
try {
// Query for nearby requests
const geofirestore = new GeoFirestore(firestore);
const nearbyRequestsSnap = await geofirestore
.collection(REQUESTS_PUBLIC_COLLECTION)
.near({
center: new GeoPoint(latitude, longitude),
radius: KM_TO_MILES * searchDistance,
})
.where('status', '==', 1)
.limit(30)
.get();
const sortedByDistance = nearbyRequestsSnap.docs.sort(
(a, b) => a.distance - b.distance,
);
setNearbyRequests(
sortedByDistance.map((docSnap) => ({
...docSnap.data(),
id: docSnap.id,
distance: kmToMiles(docSnap.distance).toFixed(2),
})),
);
setSearching(false);
} catch (err) {
showError('Error searching for nearby requests');
// eslint-disable-next-line no-console
console.log(err);
setSearching(false);
}
}
// Setup an observable for debouncing the search requests.
useEffect(() => {
const subscription = onSearch$
.pipe(debounceTime(500))
.subscribe(searchForNearbyRequests);
return () => subscription.unsubscribe();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
// This pushes new empty values to the observable when the distance or location changes.
useEffect(() => {
onSearch$.next({
searchLocation: currentLatLong,
searchDistance: distance,
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [currentLatLong, distance]);
useEffect(() => {
async function loadLatLongFromProfile() {
// TODO: Search is triggered twice when the user is logged in. Once with the first render,
// and then again when the user is assigned. Need to fix this behavior.
// Set lat/long from profile or fallback to defaults
if (user && user.uid) {
const profileRef = firestore.doc(`${USERS_COLLECTION}/${user.uid}`);
const profileSnap = await profileRef.get();
const geopoint = profileSnap.get('preciseLocation');
if (geopoint) {
const userLocation = {
latitude: geopoint.latitude,
longitude: geopoint.longitude,
};
setCurrentLatLong(userLocation);
setCurrentPlaceLabel(
`Near ${profileSnap.get('generalLocationName')}`,
);
onSearch$.next({
searchLocation: userLocation,
searchDistance: defaultDistance,
});
} else {
onSearch$.next({
searchLocation: currentLatLong,
searchDistance: defaultDistance,
});
}
} else {
onSearch$.next({
searchLocation: currentLatLong,
searchDistance: defaultDistance,
});
}
}
// NOTE: useEffect is used to load data so it can be done conditionally based
// on whether current user is logged in
loadLatLongFromProfile();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [user]);
function handleCopyNeedLink(id) {
const el = document.createElement('textarea');
document.body.appendChild(el);
el.value = `${window.location.origin}${generatePath(REQUEST_PATH, {
requestId: id,
})}`;
el.select();
document.execCommand('copy');
document.body.removeChild(el);
}
// Gets the lat/lng for the selected address.
function handlePlaceSelect(_event, selection) {
if (!selection) return;
geocodeByAddress(selection.description)
.then((results) => getLatLng(results[0]))
.then((latLng) => {
setCurrentLatLong({ latitude: latLng.lat, longitude: latLng.lng });
})
.catch((error) => {
showError('Failed to get the location from address.');
// eslint-disable-next-line no-console
console.error('Error', error);
});
}
function handlePlaceChange(address) {
setCurrentPlaceLabel(address);
}
return (
<Container maxWidth="md">
<Helmet>
<title>Find Opportunities</title>
</Helmet>
<Typography variant="h6">Search Criteria</Typography>
<Paper className={classes.filterPaper}>
{!showAddressPicker && (
<div className={classes.searchLocation}>
<Typography id="continuous-slider">{currentPlaceLabel}</Typography>
<Button
data-test="new-location-button"
onClick={() => setShowAddressPicker(true)}
className={classes.enterAddressButton}>
Select new location
</Button>
</div>
)}
{showAddressPicker && (
<>
<LoadScript
id="script-loader"
libraries={USED_GOOGLE_MAPS_LIBRARIES}
googleMapsApiKey={process.env.REACT_APP_FIREBASE_API_KEY}>
<PlacesAutocomplete
value={currentPlaceLabel}
onChange={handlePlaceChange}>
{({ getInputProps, suggestions, loading }) => (
<>
{/* {console.log(suggestions)} */}
<Autocomplete
data-test="places-autocomplete"
onChange={handlePlaceSelect}
options={suggestions}
loading={loading}
getOptionLabel={(sug) => sug.description}
noOptionsText="No matches"
renderInput={(params) => (
<TextField
margin="none"
data-test="address-entry"
{...getInputProps({
...params,
label: 'Address',
className: classes.searchInput,
})}
InputProps={{
...params.InputProps,
endAdornment: (
<>
{loading && (
<CircularProgress color="inherit" size={20} />
)}
</>
),
}}
/>
)}
/>
</>
)}
</PlacesAutocomplete>
</LoadScript>
<Typography align="right" variant="caption" display="block">
Powered by Google Maps
</Typography>
</>
)}
<Divider className={classes.divider} />
<Typography id="continuous-slider" gutterBottom>
Distance (in miles)
</Typography>
<div className={classes.distance}>
<Slider
defaultValue={defaultDistance}
valueLabelDisplay="on"
// valueLabelFormat={x => `${x} mi`}
marks={markValues}
onChange={(_event, value) => setDistance(value)}
min={1}
max={markValues[markValues.length - 1].value}
/>
</div>
</Paper>
{searching && (
<Paper className={classes.simplePaper}>
<LinearProgress />
</Paper>
)}
{nearbyRequests && nearbyRequests.length === 0 && (
<Paper className={classes.simplePaper}>
<Typography data-test="no-requests-found">
No requests found with {distance} miles. You can try expanding the
search area or try entering a new location.
</Typography>
</Paper>
)}
{nearbyRequests &&
nearbyRequests.map((result) => (
<Paper className={classes.resultPaper} key={result.id}>
<Grid container>
<Hidden xsDown>
<Grid item className={classes.distanceContainer} sm={2}>
{result.distance}
<br />
miles
</Grid>
</Hidden>
<Grid item className={classes.requestSummary} xs={12} sm={10}>
{parseInt(result.immediacy, 10) > 5 && (
<img
align="right"
src="/taskIcon.png"
width="50px"
height="50px"
alt="Urgent"
title="Urgent"
/>
)}
<Typography variant="h6">
{result.name ? result.name : result.firstName} –{' '}
{result.generalLocationName}
</Typography>
<Typography variant="caption" gutterBottom>
Requested {format(result.createdAt.toDate(), 'p - PPPP')}
</Typography>
<Typography variant="h5" className={classes.needs} gutterBottom>
{result.needs.map((item) => (
<React.Fragment key={item}>
{allCategoryMap[item] ? (
<Chip
size="small"
variant="outlined"
icon={
item === 'grocery-pickup' ? <GroceryIcon /> : null
}
label={allCategoryMap[item].shortDescription}
/>
) : (
<Alert severity="error">
Could not find '{item}' in all category map.
</Alert>
)}
</React.Fragment>
))}
{result.needFinancialAssistance && (
<Chip
variant="outlined"
size="small"
icon={<FinancialAssitanceIcon />}
label="Need financial assistance"
/>
)}
</Typography>
<Hidden smUp>
<Typography
align="right"
variant="h5"
className={classes.TaskTitle}>
{result.distance} miles
</Typography>
</Hidden>
<Grid container justify="flex-end">
<Grid item>
{navigator.share ? (
<Button
size="small"
onClick={() => {
navigator.share({
title: 'CV19 Assist Need Link',
text: 'CV19 Assist Need Link',
url: `${window.location.origin}${generatePath(
REQUEST_PATH,
{
requestId: result.id,
},
)}`,
});
}}>
SHARE
</Button>
) : (
<Button
size="small"
onClick={() => handleCopyNeedLink(result.id)}>
COPY LINK FOR SHARING
</Button>
)}{' '}
<Button
component={Link}
to={generatePath(REQUEST_PATH, {
requestId: result.id,
})}
size="small"
color="primary"
disableElevation>
DETAILS...
</Button>
</Grid>
</Grid>
</Grid>
</Grid>
</Paper>
))}
</Container>
);
}
Example #18
Source File: DepositStepper.js From lrc-staking-dapp with MIT License | 4 votes |
DepositStepper = React.memo(({
classes, messages, maxAmount, onApprove, onStake, allowance, stake, approve, onDone,
}) => {
const [step, setStep] = useState(0);
const [amount, setAmount] = useState('0');
const [isStaking, setIsStaking] = useState(false);
const [isDone, setIsDone] = useState(false);
const { width, height } = useWindowSize();
useEffect(() => {
checkEnoughAllowanceRedirectToStakeStep(amount, allowance, step, setStep);
}, [amount, allowance, step, setStep]);
useEffect(() => {
checkAsyncStakeIsDone(step, isStaking, stake, setIsStaking, setIsDone, setStep);
}, [step, isStaking, stake, setIsStaking, setIsDone, setStep]);
useEffect(() => {
timeoutConfetti(isDone, onDone);
}, [isDone, onDone]);
return (
<div className={classes.root}>
<Stepper activeStep={step} orientation="vertical">
<Step>
<StepLabel>{messages['Are you sure?']}</StepLabel>
<StepContent>
<Typography>{messages['Your tokens will be locked until your stake age is older than 90 day. If you add new tokens into your stake, your age will be weighted by the amount of tokens.']}</Typography>
<div className={classes.actionsContainer}>
<div>
<Button
disabled
className={classes.button}
>
{messages.Back}
</Button>
<Button
variant="contained"
color="primary"
onClick={() => setStep(STEP.AMOUNT)}
className={classes.button}
>
{messages['I understand']}
</Button>
</div>
</div>
</StepContent>
</Step>
<Step>
<StepLabel>{messages['Select amount']}</StepLabel>
<StepContent>
<Typography>{messages['Please fill in the amount of LRC you want to stake.']}</Typography>
<TextField
value={amount}
variant="outlined"
label="Amount"
fullWidth
type="number"
placeholder={safeAmountToPrint(maxAmount)}
className={classes.inputLRC}
onChange={(e) => setAmount(safeAmount(e.target.value || 0)
.isLessThanOrEqualTo(maxAmount)
? e.target.value : safeAmountToPrint(maxAmount))}
/>
<Slider
value={safeAmount(maxAmount).isZero()
? 0 : safeAmount(amount).div(maxAmount).multipliedBy(100).toFixed(0) * 1}
defaultValue={0}
valueLabelFormat={(value) => `${value}%`}
getAriaValueText={() => '%'}
aria-labelledby="discrete-slider-restrict"
step={null}
valueLabelDisplay="auto"
marks={[{ label: '0%', value: 0 }, { label: '25%', value: 25 }, { label: '50%', value: 50 }, { label: '75%', value: 75 }, { label: '100%', value: 100 }]}
className={classes.sliderAmount}
onChange={(_, value) => setAmount(safeAmountToPrint(safeAmount(maxAmount)
.multipliedBy(value / 100)))}
/>
<div className={classes.actionsContainer}>
<div>
<Button
onClick={() => setStep(STEP.DISCLAIMER)}
className={classes.button}
>
{messages.Back}
</Button>
<Button
disabled={safeAmount(amount).isLessThanOrEqualTo(0)}
variant="contained"
color="primary"
onClick={() => setStep(STEP.APPROVAL)}
className={classes.button}
>
{messages.Next}
</Button>
</div>
</div>
</StepContent>
</Step>
<Step>
<StepLabel>{messages.Approve}</StepLabel>
<StepContent>
<Typography>
{messages['You need to allow the staking pool to take $LRC_AMOUNT from your wallet.'].split('$LRC_AMOUNT')[0]}
<span className={`font-weight-bold ${classes.spanAmount}`}>
{numeral(amount).format('(0.00a)')}
{' '}
LRC
</span>
{messages['You need to allow the staking pool to take $LRC_AMOUNT from your wallet.'].split('$LRC_AMOUNT')[1]}
</Typography>
<div className={classes.actionsContainer}>
<div className={classes.divBackAndConfirm}>
<Button
onClick={() => setStep(STEP.AMOUNT)}
className={classes.button}
>
{messages.Back}
</Button>
<div className={classes.wrapper}>
<Button
disabled={approve.isLoading}
variant="contained"
color="primary"
onClick={() => onApprove(safeAmountFixed(amount))}
className={classes.button}
>
{ approve.isLoading && messages.Approving }
{ !approve.isLoading && messages.Approve }
</Button>
{ approve.isLoading
&& (<CircularProgress size={24} className={classes.buttonProgress} />)}
</div>
</div>
</div>
</StepContent>
</Step>
<Step>
<StepLabel>{messages.Stake}</StepLabel>
<StepContent>
<Typography>{messages['You can now deposit your LRC to the staking pool.']}</Typography>
<div className={classes.actionsContainer}>
<div className={classes.divBackAndConfirm}>
<Button
onClick={() => setStep(STEP.AMOUNT)}
className={classes.button}
>
{messages.Back}
</Button>
<div className={classes.wrapper}>
<Button
disabled={stake.isLoading}
variant="contained"
color="primary"
onClick={() => onStake(safeAmountFixed(amount))}
className={classes.button}
>
{ stake.isLoading && messages.Staking }
{ !stake.isLoading && messages.Stake }
</Button>
{ stake.isLoading
&& (<CircularProgress size={24} className={classes.buttonProgress} />)}
</div>
</div>
</div>
</StepContent>
</Step>
<Step>
<StepLabel>{messages.Done}</StepLabel>
<StepContent>
<Typography color="primary" className="animated infinite heartBeat delay-1s">
{messages['Your Loopring token are now staked and you will start collecting fees on all trades !']}
</Typography>
<div className={classes.divConfetti}>
<Confetti
width={width}
height={height}
/>
</div>
</StepContent>
</Step>
</Stepper>
</div>
);
})
Example #19
Source File: WithdrawStepper.js From lrc-staking-dapp with MIT License | 4 votes |
WithdrawStepper = React.memo(({
classes, messages, maxAmount, onWithdraw, withdraw, onDone,
}) => {
const [step, setStep] = useState(0);
const [amount, setAmount] = useState('0');
const [isWithdrawing, setIsWithdrawing] = useState(false);
const [isDone, setIsDone] = useState(false);
useEffect(() => {
checkAsyncWithdrawIsDone(step, isWithdrawing, withdraw, setIsWithdrawing, setIsDone, setStep);
}, [step, isWithdrawing, withdraw, setIsWithdrawing, setIsDone, setStep]);
useEffect(() => {
timeoutRedirect(isDone, onDone);
}, [isDone, onDone]);
return (
<div className={classes.root}>
<Stepper activeStep={step} orientation="vertical">
<Step>
<StepLabel>{messages['Are you sure?']}</StepLabel>
<StepContent>
<Typography>{messages['When you make a withdrawal, the pending rewards will automatically be added to your stake which will result in resetting the age of your stake to today (this does not impact the age to make a withdrawal).']}</Typography>
<div className={classes.actionsContainer}>
<div>
<Button
disabled
className={classes.button}
>
{messages.Back}
</Button>
<Button
variant="contained"
color="primary"
onClick={() => setStep(STEP.AMOUNT)}
className={classes.button}
>
{messages['I understand']}
</Button>
</div>
</div>
</StepContent>
</Step>
<Step>
<StepLabel>{messages['Select amount']}</StepLabel>
<StepContent>
<Typography>{messages['Please fill in the amount of LRC you want to withdraw.']}</Typography>
<TextField
value={amount}
variant="outlined"
label="Amount"
fullWidth
type="number"
placeholder={safeAmountToPrint(maxAmount)}
className={classes.inputLRC}
onChange={(e) => setAmount(safeAmount(e.target.value || 0)
.isLessThanOrEqualTo(maxAmount)
? e.target.value : safeAmountToPrint(maxAmount))}
/>
<Slider
value={safeAmount(maxAmount).isZero()
? 0 : safeAmount(amount).div(maxAmount).multipliedBy(100).toFixed(0) * 1}
defaultValue={0}
valueLabelFormat={(value) => `${value}%`}
getAriaValueText={() => '%'}
aria-labelledby="discrete-slider-restrict"
step={null}
valueLabelDisplay="auto"
marks={[{ label: '0%', value: 0 }, { label: '25%', value: 25 }, { label: '50%', value: 50 }, { label: '75%', value: 75 }, { label: '100%', value: 100 }]}
className={classes.sliderAmount}
onChange={(_, value) => setAmount(safeAmountToPrint(safeAmount(maxAmount)
.multipliedBy(value / 100)))}
/>
<div className={classes.actionsContainer}>
<div>
<Button
onClick={() => setStep(STEP.DISCLAIMER)}
className={classes.button}
>
{messages.Back}
</Button>
<Button
disabled={safeAmount(amount).isLessThanOrEqualTo(0)}
variant="contained"
color="primary"
onClick={() => setStep(STEP.WITHDRAW)}
className={classes.button}
>
{messages.Next}
</Button>
</div>
</div>
</StepContent>
</Step>
<Step>
<StepLabel>{messages.Withdraw}</StepLabel>
<StepContent>
<Typography>
<span className={`font-weight-bold ${classes.spanAmount}`}>
{numeral(amount).format('(0.00a)')}
{' '}
LRC
</span>
{messages['$LRC_AMOUNT will be transferred from your stake to your wallet.'].split('$LRC_AMOUNT')[1]}
</Typography>
<div className={classes.actionsContainer}>
<div className={classes.divBackAndConfirm}>
<Button
onClick={() => setStep(STEP.AMOUNT)}
className={classes.button}
>
{messages.Back}
</Button>
<div className={classes.wrapper}>
<Button
disabled={withdraw.isLoading}
variant="contained"
color="primary"
onClick={() => onWithdraw(safeAmountFixed(amount))}
className={classes.button}
>
{ withdraw.isLoading && messages.Withdrawing }
{ !withdraw.isLoading && messages.Withdraw }
</Button>
{ withdraw.isLoading
&& (<CircularProgress size={24} className={classes.buttonProgress} />)}
</div>
</div>
</div>
</StepContent>
</Step>
<Step>
<StepLabel>{messages.Done}</StepLabel>
<StepContent>
<Typography color="primary">
{messages['Your withdrawal has been processed, we hope to see you soon :(']}
</Typography>
</StepContent>
</Step>
</Stepper>
</div>
);
})