Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: extract page elements and use hooks for search #854

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 44 additions & 54 deletions src/features/Search/Filters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,47 +24,26 @@ interface IFilterProps {
loading: boolean;
}

class FilterComponent extends React.Component<IFilterProps, {}> {
constructor(props: IFilterProps) {
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
this.renderFormik = this.renderFormik.bind(this);
this.resetForm = this.resetForm.bind(this);
}
public render() {
return (
<Box>
<Formik
enableReinitialize={true}
initialValues={this.parseInitialValues(this.props.initFilters)}
onSubmit={this.handleSubmit}
render={this.renderFormik}
/>
</Box>
);
}
private parseInitialValues(initFilters: ISearchParameter[]) {
const FilterComponent: React.FC<IFilterProps> = (props) => {
const parseInitialValues = (initFilters: ISearchParameter[]) => {
const initVals = {
school: this.searchParam2List('application.general.school', initFilters),
gradYear: this.searchParam2List(
school: searchParam2List('application.general.school', initFilters),
gradYear: searchParam2List(
'application.general.graduationYear',
initFilters
),
degree: this.searchParam2List('application.general.degree', initFilters),
status: this.searchParam2List('status', initFilters),
skills: this.searchParam2List(
'application.shortAnswer.skills',
initFilters
),
jobInterest: this.searchParam2List(
degree: searchParam2List('application.general.degree', initFilters),
status: searchParam2List('status', initFilters),
skills: searchParam2List('application.shortAnswer.skills', initFilters),
jobInterest: searchParam2List(
'application.general.jobInterest',
initFilters
),
};
return initVals;
}
};

private renderFormik(fp: FormikProps<any>) {
const renderFormik = (fp: FormikProps<any>) => {
return (
<Form onSubmit={fp.handleSubmit}>
<FastField
Expand Down Expand Up @@ -130,15 +109,15 @@ class FilterComponent extends React.Component<IFilterProps, {}> {
<Box>
<Button
type="submit"
isLoading={this.props.loading}
disabled={this.props.loading}
isLoading={props.loading}
disabled={props.loading}
>
Submit
</Button>
</Box>
<Box>
<Button
onClick={this.resetForm(fp)}
onClick={resetForm(fp)}
type="button"
variant={ButtonVariant.Secondary}
>
Expand All @@ -148,36 +127,36 @@ class FilterComponent extends React.Component<IFilterProps, {}> {
</Flex>
</Form>
);
}
private resetForm(fp: FormikProps<any>): () => void {
};
const resetForm = (fp: FormikProps<any>): (() => void) => {
return () => {
fp.resetForm();
this.props.onResetForm();
props.onResetForm();
};
}
};
/**
* Converts the formik values into a search parameter list, and calls onChange hook.
* @param values Formik values
*/
private handleSubmit(values: FormikValues) {
const schoolSearchParam = this.list2SearchParam(
const handleSubmit = (values: FormikValues) => {
const schoolSearchParam = list2SearchParam(
'application.general.school',
values.school
);
const gradYearParam = this.list2SearchParam(
const gradYearParam = list2SearchParam(
'application.general.graduationYear',
values.gradYear
);
const degreeParam = this.list2SearchParam(
const degreeParam = list2SearchParam(
'application.general.degree',
values.degree
);
const statusParam = this.list2SearchParam('status', values.status);
const skillsParam = this.list2SearchParam(
const statusParam = list2SearchParam('status', values.status);
const skillsParam = list2SearchParam(
'application.shortAnswer.skills',
values.skills
);
const jobInterestParam = this.list2SearchParam(
const jobInterestParam = list2SearchParam(
'application.general.jobInterest',
values.jobInterest
);
Expand All @@ -190,18 +169,18 @@ class FilterComponent extends React.Component<IFilterProps, {}> {
skillsParam,
jobInterestParam
);
this.props.onChange(search);
}
props.onChange(search);
};

/**
* Converts formik value to SearchParameter list.
* @param param the location in the schema that these values must be in.
* @param values the formik values.
*/
private list2SearchParam(
const list2SearchParam = (
param: string,
values: string[]
): ISearchParameter[] {
): ISearchParameter[] => {
return values.length > 0
? [
{
Expand All @@ -211,11 +190,11 @@ class FilterComponent extends React.Component<IFilterProps, {}> {
},
]
: [];
}
private searchParam2List(
};
const searchParam2List = (
param: string,
searchParamList: ISearchParameter[]
): Array<string | number | boolean> {
): Array<string | number | boolean> => {
let searches: Array<string | number | boolean> = [];
searchParamList.forEach((searchParam) => {
if (searchParam.param === param) {
Expand All @@ -227,7 +206,18 @@ class FilterComponent extends React.Component<IFilterProps, {}> {
}
});
return searches;
}
}
};

return (
<Box>
<Formik
enableReinitialize={true}
initialValues={parseInitialValues(props.initFilters)}
onSubmit={handleSubmit}
render={renderFormik}
/>
</Box>
);
};

export { FilterComponent };
80 changes: 40 additions & 40 deletions src/features/Search/HackerSelect.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React, { useState, useContext } from 'react';
import { Sponsor } from '../../api';
import { Checkbox } from '../../shared/Form';
import NomineeContext from './Context';
Expand All @@ -7,55 +7,55 @@ interface IProps {
hackerId: string;
}

interface IState {
isChanging: boolean;
}

class HackerSelect extends React.Component<IProps, IState> {
public static contextType = NomineeContext;

constructor(props: IProps) {
super(props);
this.state = {
isChanging: false,
};
// push the selected hacker to the list of selected hacker for the search
const HackerSelect: React.FC<IProps> = (props) => {
// react state.context is assigned to the variable "contet"
const context = useContext(NomineeContext);

this.handleChange = this.handleChange.bind(this);
}
public render() {
const { hackerId } = this.props;
if (!this.context || !this.context.nominees) {
return <div />;
}
const isChecked = this.context.nominees.indexOf(hackerId) > -1;
return (
<div>
<Checkbox checked={isChecked} onChange={this.handleChange} />
</div>
);
}
// state to only change one hacker selection state at a time
const [isChanging, setIsChanging] = useState<boolean>(false);

private async handleChange(event: React.ChangeEvent<HTMLInputElement>) {
// function to push selected hacker to the search list
const handleChange = async (event: React.ChangeEvent<HTMLInputElement>) => {
const isChecked = event.target.checked;
const { isChanging } = this.state;
const { hackerId } = this.props;
const { hackerId } = props;

if (isChanging) {
return;
}

if (isChecked) {
this.context.nominees.push(hackerId);
} else {
this.context.nominees = this.context.nominees.filter(
(n: string) => n !== hackerId
);
if (context) {
// push them to the selected list
if (isChecked) {
context.nominees.push(hackerId);
} else {
// remove selected hacker from list
context.nominees = context.nominees.filter(
(n: string) => n !== hackerId
);
}
}

setIsChanging(true);
if (context) {
await Sponsor.update(context);
}
setIsChanging(false);
};

this.setState({ isChanging: true });
await Sponsor.update(this.context);
this.setState({ isChanging: false });
const { hackerId } = props;
if (!context || !context.nominees) {
return <div />;
}
}
let isChecked: boolean = false;
if (context) {
isChecked = context.nominees.indexOf(hackerId) > -1;
}
return (
<div>
<Checkbox checked={isChecked} onChange={handleChange} />
</div>
);
};

export default HackerSelect;
Loading