Skip to content

Commit

Permalink
Working tag and status filters
Browse files Browse the repository at this point in the history
  • Loading branch information
nicoleamber committed Sep 14, 2023
1 parent 926dafd commit 96ef3e5
Show file tree
Hide file tree
Showing 14 changed files with 198 additions and 88 deletions.
3 changes: 2 additions & 1 deletion web/src/app/job/context.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { JobTable } from '@/utils/types/job';
import { JobQuery, JobTable } from '@/utils/types/job';
import { createContext } from 'react';

export const JobListContext = createContext<JobTable | undefined>(undefined);
export const JobQueryContext = createContext<JobQuery | undefined>(undefined);
57 changes: 49 additions & 8 deletions web/src/app/job/hooks.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { axiosInstance } from '@/utils/services/axios';
import { JobSchema, JobTable, JobTableRow } from '@/utils/types/job';
import { JobQuery, JobSchema, JobTable, JobTableRow } from '@/utils/types/job';
import { ScheduleSchema } from '@/utils/types/schedule';
import { Moment } from 'moment';
import { useContext, useEffect, useState } from 'react';
import { JobListContext } from './context';
import { JobListContext, JobQueryContext } from './context';

export const useJobListContext = (): JobTable => {
const jobs = useContext(JobListContext);
Expand All @@ -14,6 +15,16 @@ export const useJobListContext = (): JobTable => {
return jobs;
};

export const useJobQueryContext = (): JobQuery => {
const query = useContext(JobQueryContext);

if (query === undefined) {
throw new Error('Missing JobQueryContext');
}

return query;
};

export const useHooks = () => {
const [page, setPage] = useState(1);
const [perPage] = useState(12);
Expand All @@ -23,13 +34,35 @@ export const useHooks = () => {
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState<string | undefined>();

const [tag, setTag] = useState('');
const [status, setStatus] = useState('');
const [startDate, setStartDate] = useState<Moment | null>(null);
const [endDate, setEndDate] = useState<Moment | null>(null);

const params: { page: number, perPage: number, tag?: string, status?: string, startDate?: string,
endDate?: string } = {
page, perPage,
};

if (tag) {
params.tag = tag;
}

if (status) {
params.status = status;
}

// if (startDate && endDate) {
// params.startDate = startDate.format("MM-DD-YYYY");
// params.endDate = endDate.format("MM-DD-YYYY");
// }

// TODO: validate dates

useEffect(() => {
axiosInstance
.get('/jobs', {
params: {
page,
perPage
}
params
})
.then((response) => {
setCount(response?.data.count);
Expand All @@ -42,7 +75,7 @@ export const useHooks = () => {
setIsLoading(false);
setError('Something went wrong.');
});
}, [page, perPage]);
}, [page, perPage, tag, status, startDate, endDate]);

return {
jobs,
Expand All @@ -52,6 +85,14 @@ export const useHooks = () => {
isLoading,
error,
setPage,
tag,
setTag,
status,
setStatus,
startDate,
setStartDate,
endDate,
setEndDate
};
};

Expand Down Expand Up @@ -81,7 +122,7 @@ const formatSchedules = (schedules: ScheduleSchema[]): string[] => {
return scheduleData;
};

const formatEnum = (value: string): string => {
export const formatEnum = (value: string): string => {
let words = value.split('_');
words = words.map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase());
return words.join(' ');
Expand Down
117 changes: 72 additions & 45 deletions web/src/app/job/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,61 +7,88 @@ import SearchFilterHeader from '@/components/organisms/SearchFilterHeader';
import { JobColumns } from '@/utils/constants/jobTableData';
import { Grid, Typography } from '@mui/material';
import { Fragment } from 'react';
import { JobListContext } from './context';
import { JobListContext, JobQueryContext } from './context';
import { useHooks } from './hooks';

const JobList = (): JSX.Element => {
const { page, jobs, count, pageCount, setPage, isLoading, error } =
useHooks();
const {
page,
jobs,
count,
pageCount,
setPage,
isLoading,
error,
tag,
setTag,
status,
setStatus,
startDate,
setStartDate,
endDate,
setEndDate
} = useHooks();

return (
<main>
<JobListContext.Provider
value={{ columns: JobColumns, data: jobs }}>
{isLoading ? (
<StatusDisplay isLoading={isLoading} />
) : error ? (
<StatusDisplay error={error} />
) : (
<Grid
container
sx={{
padding: 3,
gap: 3,
flexDirection: 'column'
}}>
<Grid item>
<SearchFilterHeader />
</Grid>
{!count ? (
<Grid
item
sx={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
height: '60vh'
}}>
<Typography variant='label1r'>
No jobs found
</Typography>
<JobQueryContext.Provider
value={{
tag,
setTag,
status,
setStatus,
startDate,
setStartDate,
endDate,
setEndDate
}}>
{isLoading ? (
<StatusDisplay isLoading={isLoading} />
) : error ? (
<StatusDisplay error={error} />
) : (
<Grid
container
sx={{
padding: 3,
gap: 3,
flexDirection: 'column'
}}>
<Grid item>
<SearchFilterHeader />
</Grid>
) : (
<Fragment>
<Grid item>
<JobListTable />
</Grid>
<Grid item sx={{ alignSelf: 'center' }}>
<Pagination
count={pageCount}
page={page}
onChange={setPage}
/>
{!count ? (
<Grid
item
sx={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
height: '60vh'
}}>
<Typography variant='label1r'>
No jobs found
</Typography>
</Grid>
</Fragment>
)}
</Grid>
)}
) : (
<Fragment>
<Grid item>
<JobListTable />
</Grid>
<Grid item sx={{ alignSelf: 'center' }}>
<Pagination
count={pageCount}
page={page}
onChange={setPage}
/>
</Grid>
</Fragment>
)}
</Grid>
)}
</JobQueryContext.Provider>
</JobListContext.Provider>
</main>
);
Expand Down
14 changes: 11 additions & 3 deletions web/src/components/molecules/CreatedDateRangeFilter/hooks.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import moment, { type Moment } from 'moment';
import { useJobQueryContext } from '@/app/job/hooks';
import { type Moment } from 'moment';
import { useEffect, useState } from 'react';

export const useHooks = () => {
const [startDate, setStartDate] = useState<Moment | null>(moment().startOf('month'));
const [endDate, setEndDate] = useState<Moment | null>(moment());
const { startDate, setStartDate, endDate, setEndDate } = useJobQueryContext();
const [isInvalidDate, setIsInvalidDate] = useState(false);
const [error, setError] = useState('');

const handleStartDateChange = (date: Moment | null): void => {
setStartDate(date);
Expand All @@ -15,12 +16,19 @@ export const useHooks = () => {
};

useEffect(() => {
if (startDate && !endDate || endDate && !startDate) {
setIsInvalidDate(true);
setError('Both startDate and endDate must be set');
}

if (startDate && endDate) {
setIsInvalidDate(endDate <= startDate);
setError('Please set a vaild date');
}
}, [startDate, endDate]);

return {
error,
startDate,
handleStartDateChange,
endDate,
Expand Down
9 changes: 3 additions & 6 deletions web/src/components/molecules/CreatedDateRangeFilter/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { useHooks } from './hooks';

const CreateDateRangeFilter = () => {
const {
error,
startDate,
handleStartDateChange,
endDate,
Expand Down Expand Up @@ -38,9 +39,7 @@ const CreateDateRangeFilter = () => {
id: 'created-start',
name: 'created-start',
error: isInvalidDate,
helperText: isInvalidDate
? 'Please set a valid date'
: ''
helperText: isInvalidDate ? error : ''
}
}}
/>
Expand All @@ -65,9 +64,7 @@ const CreateDateRangeFilter = () => {
id: 'created-end',
name: 'created-end',
error: isInvalidDate,
helperText: isInvalidDate
? 'Please set a valid date.'
: ''
helperText: isInvalidDate ? error : ''
}
}}
/>
Expand Down
13 changes: 11 additions & 2 deletions web/src/components/molecules/EstimationStatusFilter/hooks.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,24 @@
import { formatEnum, useJobQueryContext } from '@/app/job/hooks';
import { EstimationStatusEnum } from '@/utils/constants/estimationStatusEnum';
import { SelectChangeEvent } from '@mui/material';
import { useState } from 'react';

export const useHooks = () => {
const [status, setStatus] = useState('');
const { status, setStatus } = useJobQueryContext();

const handleChange = (e: SelectChangeEvent) => {
setStatus(e.target.value);
};

const statusOptions = Object.keys(EstimationStatusEnum).map((key) => {
return {
value: EstimationStatusEnum[key as keyof typeof EstimationStatusEnum],
name: formatEnum(key)
}
});

return {
status,
statusOptions,
handleChange
};
};
12 changes: 7 additions & 5 deletions web/src/components/molecules/EstimationStatusFilter/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import styles from '@/styles/Filter.module.css';
import { EstimationStatus } from '@/utils/constants/estimationStatus';
import { FormControl, InputLabel, MenuItem, Select } from '@mui/material';
import { useHooks } from './hooks';

const EstimationStatusFilter = () => {
const { status, handleChange } = useHooks();
const { status, statusOptions, handleChange } = useHooks();

return (
<FormControl sx={{ width: 180 }}>
Expand All @@ -20,9 +19,12 @@ const EstimationStatusFilter = () => {
color='secondary'
onChange={handleChange}
className={styles.input}>
{EstimationStatus.map((status) => (
<MenuItem key={status.id} value={status.status}>
{status.status}
<MenuItem key={'clear'} value={''}>
<em>None</em>
</MenuItem>
{statusOptions.map((status, key) => (
<MenuItem key={key} value={status.value}>
{status.name}
</MenuItem>
))}
</Select>
Expand Down
14 changes: 12 additions & 2 deletions web/src/components/molecules/TagFilter/hooks.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
import { formatEnum, useJobQueryContext } from '@/app/job/hooks';
import { TagsEnum } from '@/utils/constants/tagsEnum';

import { SelectChangeEvent } from '@mui/material';
import { useState } from 'react';

export const useHooks = () => {
const [tag, setTag] = useState('');
const { tag, setTag } = useJobQueryContext();

const handleChange = (e: SelectChangeEvent) => {
setTag(e.target.value);
};

const tagOptions = Object.keys(TagsEnum).map((key) => {
return {
value: TagsEnum[key as keyof typeof TagsEnum],
name: formatEnum(key)
}
});

return {
tag,
tagOptions,
handleChange
};
};
Loading

0 comments on commit 96ef3e5

Please sign in to comment.