2022-05-11 18:50:27 +09:00

199 lines
7.0 KiB
TypeScript

import React, { Component } from "react";
import { useNavigate } from "react-router-dom";
import { useAppDispatch } from "../../app/hooks";
import DataUtils, { SearchResults } from "../data/DataUtils";
import { setTitle } from "../page-title/pageTitleSlice";
import { setResults } from "../search-results/searchResultsSlice";
import styles from "./SearchForm.module.css";
interface FCProps {}
interface Props extends FCProps {
navigate: any;
dispatch: any;
}
interface State {
pdStart: string;
pdEnd: string;
widthMin: string;
widthMax: string;
depthMin: string;
depthMax: string;
cellType: string;
area: string;
geneType: string;
keyword: string;
}
class SearchForm extends Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
pdStart: "44",
pdEnd: "100",
widthMin: "317",
widthMax: "512",
depthMin: "90",
depthMax: "230",
cellType: "any",
area: "all",
geneType: "all",
keyword: "",
};
this.handleInputChange = this.handleInputChange.bind(this);
this.handleSelectChange = this.handleSelectChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
componentDidMount() {
this.props.dispatch(setTitle("Database Search"));
}
doSearch(): SearchResults {
const toNumber = (v: string): number => parseInt(v.trim(), 10);
const params = {
pdStart: toNumber(this.state.pdStart),
pdEnd: toNumber(this.state.pdEnd),
widthMin: toNumber(this.state.widthMin),
widthMax: toNumber(this.state.widthMax),
depthMin: toNumber(this.state.depthMin),
depthMax: toNumber(this.state.depthMax),
cellType: this.state.cellType.trim(),
area: this.state.area.trim(),
geneType: this.state.geneType.trim(),
keyword: this.state.keyword.trim(),
};
return DataUtils.search(params);
}
handleInputChange: React.ChangeEventHandler<HTMLInputElement> = (event: React.ChangeEvent<HTMLInputElement>) => {
const target = event.target;
const value = target.value;
const name = target.name;
switch (name) {
case "pdStart":
this.setState({ pdStart: value });
break;
case "pdEnd":
this.setState({ pdStart: value });
break;
case "widthMin":
this.setState({ widthMin: value });
break;
case "widthMax":
this.setState({ widthMax: value });
break;
case "depthMin":
this.setState({ depthMin: value });
break;
case "depthMax":
this.setState({ depthMax: value });
break;
case "cellType":
this.setState({ cellType: value });
break;
case "keyword":
this.setState({ keyword: value });
break;
}
};
handleSelectChange: React.ChangeEventHandler<HTMLSelectElement> = (event: React.ChangeEvent<HTMLSelectElement>) => {
const target = event.target;
const value = target.value;
const name = target.name;
switch (name) {
case "area":
this.setState({ area: value });
break;
case "geneType":
this.setState({ geneType: value });
break;
}
};
handleSubmit: React.FormEventHandler<HTMLFormElement> = (event: React.FormEvent) => {
event.preventDefault();
const results = this.doSearch();
this.props.dispatch(setResults(results));
this.props.navigate("/search/results");
};
render() {
return (
<form onSubmit={this.handleSubmit}>
<div className={styles.formGroup}>
<label htmlFor="pdStart">Postnatal Days</label>
<div className={styles.value}>
<input type="number" name="pdStart" className={styles.txtParam} value={this.state.pdStart} onChange={this.handleInputChange} />
<span className={styles.range}>-</span>
<input type="number" name="pdEnd" className={styles.txtParam} value={this.state.pdEnd} onChange={this.handleInputChange} />
</div>
</div>
<div className={styles.formGroup}>
<label htmlFor="widthMin">Recording volume width (height)</label>
<div className={styles.value}>
<input type="number" name="widthMin" className={styles.txtParam} value={this.state.widthMin} onChange={this.handleInputChange} />
<span className={styles.range}>-</span>
<input type="number" name="widthMax" className={styles.txtParam} value={this.state.widthMax} onChange={this.handleInputChange} />
</div>
</div>
<div className={styles.formGroup}>
<label htmlFor="depthMin">Recording volume depth</label>
<div className={styles.value}>
<input type="number" name="depthMin" className={styles.txtParam} value={this.state.depthMin} onChange={this.handleInputChange} />
<span className={styles.range}>-</span>
<input type="number" name="depthMax" className={styles.txtParam} value={this.state.depthMax} onChange={this.handleInputChange} />
</div>
</div>
<div className={styles.formGroup}>
<label htmlFor="cellType">Cell type (E, I, G, P, S, or "any")</label>
<div className={styles.value}>
<input type="text" name="cellType" className={styles.txtParamStr} value={this.state.cellType} onChange={this.handleInputChange} />
</div>
</div>
<div className={styles.formGroup}>
<label htmlFor="area">Target area</label>
<div className={styles.value}>
<select name="area" className={styles.selParam} value={this.state.area} onChange={this.handleSelectChange}>
<option value="all">All</option>
<option value="L2/3, V1">L2/3 in the visual cortex</option>
</select>
</div>
</div>
<div className={styles.formGroup}>
<label htmlFor="geneType">Mouse line</label>
<div className={styles.value}>
<select name="geneType" className={styles.selParam} value={this.state.geneType} onChange={this.handleSelectChange}>
<option value="all">All</option>
<option value="VGAT-Venus">VGAT-Venus</option>
<option value="PV/myrGFP-LDLRct">PV/myrGFP-LDLRct</option>
<option value="Dlx5/6-GCaMP3">Dlx5/6-GCaMP3</option>
</select>
</div>
</div>
<div className={styles.formGroup}>
<label htmlFor="keyword">Keyword Search</label>
<div className={styles.value}>
<input type="text" name="keyword" className={styles.txtKeyword} value={this.state.keyword} onChange={this.handleInputChange} />
</div>
</div>
<div className={styles.formGroup}>
<div className={styles.submit}>
<input type="submit" value="Search" />
</div>
</div>
</form>
);
}
}
const SearchFormFC: React.FC<FCProps> = (props: FCProps) => {
const navigate = useNavigate();
const dispatch = useAppDispatch();
return <SearchForm navigate={navigate} dispatch={dispatch} />;
};
export default SearchFormFC;