Skip to content

Commit d7ea3ff

Browse files
committed
[DOP-29615] Add filter by Job.type
1 parent 0282bea commit d7ea3ff

File tree

18 files changed

+213
-111
lines changed

18 files changed

+213
-111
lines changed

src/components/job/JobIcon.tsx

Lines changed: 0 additions & 9 deletions
This file was deleted.

src/components/job/JobIconWithType.tsx

Lines changed: 0 additions & 21 deletions
This file was deleted.

src/components/job/JobRaList.tsx

Lines changed: 7 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,21 @@
11
import { ReactElement } from "react";
2-
import {
3-
List,
4-
TextField,
5-
SearchInput,
6-
minLength,
7-
DatagridConfigurable,
8-
useTranslate,
9-
} from "react-admin";
2+
import { List, TextField, DatagridConfigurable } from "react-admin";
103
import { ListActions } from "@/components/base";
114
import {
125
LocationRaNameWithLinkField,
136
LocationRaTypeWithIconField,
147
} from "@/components/location";
158
import JobRaTypeField from "./JobRaTypeField";
9+
import JobRaListFilters from "./JobRaListFilters";
1610

1711
const JobRaList = (): ReactElement => {
18-
const translate = useTranslate();
19-
20-
const jobFilters = [
21-
<SearchInput
22-
key="search_query"
23-
source="search_query"
24-
alwaysOn
25-
validate={minLength(3)}
26-
placeholder={translate(
27-
"resources.jobs.filters.search_query.placeholder",
28-
)}
29-
/>,
30-
];
31-
3212
return (
3313
<List
34-
actions={<ListActions />}
35-
filters={jobFilters}
14+
actions={
15+
<ListActions>
16+
<JobRaListFilters />
17+
</ListActions>
18+
}
3619
resource="jobs"
3720
storeKey={false}
3821
>
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { minLength, useTranslate } from "react-admin";
2+
3+
import { useForm, FormProvider } from "react-hook-form";
4+
import { Box, Button, InputAdornment } from "@mui/material";
5+
import SearchIcon from "@mui/icons-material/Search";
6+
import { TextInput, useListContext } from "react-admin";
7+
import { useEffect } from "react";
8+
import JobTypeRaFilter from "./JobRaTypeFilter";
9+
10+
type JobRaListFilterValues = {
11+
job_type?: string[];
12+
search_query?: string;
13+
};
14+
15+
const JobRaListFilters = () => {
16+
const translate = useTranslate();
17+
const { filterValues, setFilters } = useListContext();
18+
const form = useForm({ defaultValues: filterValues });
19+
20+
const submit = form.handleSubmit((formValues: JobRaListFilterValues) => {
21+
if (Object.keys(formValues).length > 0) {
22+
setFilters(formValues);
23+
}
24+
});
25+
26+
// fill up filters just after opening the page
27+
useEffect(() => {
28+
submit();
29+
}, []);
30+
31+
return (
32+
<FormProvider {...form}>
33+
<form onSubmit={submit}>
34+
<Box display="flex" alignItems="flex-end">
35+
<Box component="span" mr={2}>
36+
<JobTypeRaFilter />
37+
</Box>
38+
39+
<Box component="span" mr={2} sx={{ flex: 0.3 }}>
40+
{/* Not using SearchInput here because it doesn't match styles with other filters */}
41+
<TextInput
42+
source="search_query"
43+
InputProps={{
44+
endAdornment: (
45+
<InputAdornment position="end">
46+
<SearchIcon color="disabled" />
47+
</InputAdornment>
48+
),
49+
}}
50+
validate={minLength(3)}
51+
label="resources.jobs.filters.search_query.label"
52+
helperText="resources.jobs.filters.search_query.helperText"
53+
/>
54+
</Box>
55+
56+
<Box component="span" mb={4}>
57+
<Button
58+
variant="outlined"
59+
color="primary"
60+
type="submit"
61+
>
62+
{translate("resources.jobs.filters.apply_button")}
63+
</Button>
64+
</Box>
65+
</Box>
66+
</form>
67+
</FormProvider>
68+
);
69+
};
70+
71+
export default JobRaListFilters;

src/components/job/JobRaListForLocation.tsx

Lines changed: 7 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,24 @@
11
import { ReactElement } from "react";
22

33
import { ListActions } from "@/components/base";
4-
import {
5-
List,
6-
TextField,
7-
DatagridConfigurable,
8-
SearchInput,
9-
minLength,
10-
useTranslate,
11-
} from "react-admin";
4+
import { List, TextField, DatagridConfigurable } from "react-admin";
125
import JobRaTypeField from "./JobRaTypeField";
6+
import JobRaListFilters from "./JobRaListFilters";
137

148
const JobRaListForLocation = ({
159
locationId,
1610
}: {
1711
locationId: number;
1812
}): ReactElement => {
19-
const translate = useTranslate();
20-
21-
const jobFilters = [
22-
<SearchInput
23-
key="search_query"
24-
source="search_query"
25-
alwaysOn
26-
validate={minLength(3)}
27-
placeholder={translate(
28-
"resources.jobs.filters.search_query.placeholder",
29-
)}
30-
/>,
31-
];
32-
3313
return (
3414
<List
3515
resource="jobs"
16+
actions={
17+
<ListActions>
18+
<JobRaListFilters />
19+
</ListActions>
20+
}
3621
filter={{ location_id: locationId }}
37-
filters={jobFilters}
38-
actions={<ListActions />}
3922
title={false}
4023
storeKey={false}
4124
>

src/components/job/JobRaRepr.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { ReactElement } from "react";
22
import { Stack } from "@mui/material";
33
import { useRecordContext } from "react-admin";
4-
import JobIcon from "./JobIcon";
4+
import JobTypeIcon from "./JobTypeIcon";
55
import { JobDetailedResponseV1 } from "@/dataProvider/types";
66

77
const JobRaRepr = (): ReactElement | null => {
@@ -19,7 +19,7 @@ const JobRaRepr = (): ReactElement | null => {
1919
textDecoration: "underline",
2020
}}
2121
>
22-
<JobIcon job={job.data} />
22+
<JobTypeIcon jobType={job.data.type} />
2323
<span>{job.data.name}</span>
2424
</Stack>
2525
);
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { ReactElement } from "react";
22
import { FieldProps, useRecordContext } from "react-admin";
3-
import JobIconWithType from "./JobIconWithType";
3+
import JobTypeRepr from "./JobTypeRepr";
44
import { JobDetailedResponseV1 } from "@/dataProvider/types";
55

66
/* eslint-disable @typescript-eslint/no-unused-vars */
@@ -9,7 +9,7 @@ const JobRaTypeField = (props: FieldProps): ReactElement | null => {
99
if (!record) {
1010
return null;
1111
}
12-
return <JobIconWithType job={record.data} />;
12+
return <JobTypeRepr jobType={record.data.type} />;
1313
};
1414

1515
export default JobRaTypeField;
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { JobTypesResponseV1 } from "@/dataProvider/types";
2+
import { ReactElement, useEffect, useState } from "react";
3+
import { SelectArrayInput, useDataProvider, useTranslate } from "react-admin";
4+
import { getDefaultJobType } from "./JobType";
5+
6+
const JobRaTypeFilter = (): ReactElement => {
7+
const dataProvider = useDataProvider();
8+
const translate = useTranslate();
9+
10+
const [jobTypes, setJobTypes] = useState<string[]>([]);
11+
12+
useEffect(() => {
13+
dataProvider.getJobTypes({}).then((response: JobTypesResponseV1) => {
14+
setJobTypes(response.job_types);
15+
});
16+
}, [dataProvider]);
17+
18+
const jobTypesRepr = jobTypes.map((jobType) => {
19+
return {
20+
id: jobType,
21+
name: translate(
22+
`resources.jobs.types.${jobType.toLocaleLowerCase()}`,
23+
{ _: getDefaultJobType(jobType) },
24+
),
25+
};
26+
});
27+
28+
return (
29+
<SelectArrayInput
30+
source="job_type"
31+
choices={jobTypesRepr}
32+
label="resources.jobs.filters.job_type.label"
33+
helperText="resources.jobs.filters.job_type.helperText"
34+
/>
35+
);
36+
};
37+
38+
export default JobRaTypeFilter;

src/components/job/JobType.tsx

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
11
import { useTranslate } from "react-admin";
2-
import { JobResponseV1 } from "@/dataProvider/types";
32

4-
const JobType = ({ job }: { job: JobResponseV1 }): string => {
3+
export const getDefaultJobType = (jobType: string): string => {
4+
return jobType
5+
.split("_")
6+
.map(
7+
(s) =>
8+
s.charAt(0).toLocaleUpperCase() +
9+
s.substring(1).toLocaleLowerCase(),
10+
)
11+
.join(" ");
12+
};
13+
14+
const JobType = ({ jobType }: { jobType: string }): string => {
515
const translate = useTranslate();
616

7-
return translate(`resources.jobs.types.${job.type.toLocaleLowerCase()}`, {
8-
_: job.type
9-
.split("_")
10-
.map(
11-
(s) =>
12-
s.charAt(0).toLocaleUpperCase() +
13-
s.substring(1).toLocaleLowerCase(),
14-
)
15-
.join(" "),
17+
return translate(`resources.jobs.types.${jobType.toLocaleLowerCase()}`, {
18+
_: getDefaultJobType(jobType),
1619
});
1720
};
1821

src/components/job/JobTypeIcon.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { ReactElement } from "react";
2+
import { IconByName } from "@/components/icons";
3+
4+
const JobTypeIcon = ({ jobType }: { jobType: string }): ReactElement => {
5+
return <IconByName name={jobType} />;
6+
};
7+
8+
export default JobTypeIcon;

0 commit comments

Comments
 (0)