Skip to content

Commit

Permalink
Merge pull request #124 from bcgov/BCAT-xxx-funding-year-search
Browse files Browse the repository at this point in the history
BCAT-533 | funding_year & status search
  • Loading branch information
jerry-ey authored May 13, 2024
2 parents 1850a32 + 4d33c2d commit 8a40c22
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 12 deletions.
12 changes: 10 additions & 2 deletions api/src/application/application.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,21 @@ export class ApplicationService {
});
}

if (query.fundingYear) {
queryBuilder.andWhere('app.fundingYear = :fundingYear', { fundingYear: query.fundingYear });
}

if (query.status) {
queryBuilder.andWhere('status.name = :status', { status: query.status });
}

if (query.orderBy) {
if (
['applicationType.name', 'assignedTo.displayName', 'status.name'].includes(query.orderBy)
) {
queryBuilder.orderBy({ [`${query.orderBy}`]: query.order });
queryBuilder.orderBy(query.orderBy, query.order, 'NULLS LAST');
} else {
queryBuilder.orderBy({ [`app.${query.orderBy}`]: query.order });
queryBuilder.orderBy(`app.${query.orderBy}`, query.order, 'NULLS LAST');
}
}

Expand Down
12 changes: 10 additions & 2 deletions api/src/common/dto/get-applications.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,22 @@ export class GetApplicationsDto extends PaginationDto {

@IsOptional()
@IsEnum(OrderByOptions)
order = OrderByOptions.ASC;
order = OrderByOptions.DESC;

@ApiPropertyOptional({ enum: ApplicationSortOptions })
@IsOptional()
@IsEnum(ApplicationSortOptions)
orderBy = ApplicationSortOptions.CONFIRMATION_ID;
orderBy = ApplicationSortOptions.FUNDING_YEAR;

@IsOptional()
@IsString()
totalCost: string;

@IsOptional()
@IsString()
fundingYear: string;

@IsOptional()
@IsString()
status: string;
}
72 changes: 64 additions & 8 deletions client/components/bcat-form-sections/application-dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { faTimes, faFilter } from '@fortawesome/free-solid-svg-icons';
import { useHttp } from '../../services/useHttp';
import { SetQueryParams } from '../../services/useQueryParams';
import { useRouter } from 'next/router';
import { API_ENDPOINT } from '../../constants';
import { API_ENDPOINT, ApplicationStatus } from '../../constants';
import { useDownloadXlsx } from 'services/useDownloadXlsx';

interface InputFilterProps {
Expand All @@ -15,6 +15,10 @@ interface InputFilterProps {
placeholder: string;
}

interface SelectFilterProps extends InputFilterProps {
options: { name: string; value: string }[];
}

const InputFilter: React.FC<InputFilterProps> = ({ searchType, onChange, placeholder }) => {
return (
<input
Expand All @@ -27,6 +31,30 @@ const InputFilter: React.FC<InputFilterProps> = ({ searchType, onChange, placeho
);
};

const SelectFilter: React.FC<SelectFilterProps> = ({
searchType,
onChange,
placeholder,
options,
}) => {
return (
<select
title={placeholder}
className='bg-white rounded border border-gray-300 text-gray-900 text-sm focus:ring-blue-500 focus:border-blue-500 block w-full pr-10 p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500'
placeholder={placeholder}
onChange={onChange}
value={searchType}
>
<option value=''>{placeholder}</option>
{options.map(({ name, value }) => (
<option key={value} value={value}>
{name}
</option>
))}
</select>
);
};

export const ApplicationDashboard: React.FC<any> = () => {
const { push, query } = useRouter();
const router = useRouter();
Expand All @@ -40,6 +68,8 @@ export const ApplicationDashboard: React.FC<any> = () => {
searchApplicationType: query?.applicationType ?? '',
searchAssignedTo: query?.assignedTo ?? '',
searchConfirmationID: query?.confirmationId ?? '',
searchFundingYear: query?.fundingYear ?? '',
searchStatus: query?.status ?? '',
searchTotalCost: '',
totalApplications: 0,
});
Expand All @@ -49,6 +79,8 @@ export const ApplicationDashboard: React.FC<any> = () => {
searchApplicationType,
searchAssignedTo,
searchConfirmationID,
searchFundingYear,
searchStatus,
searchTotalCost,
totalApplications,
data,
Expand Down Expand Up @@ -120,7 +152,9 @@ export const ApplicationDashboard: React.FC<any> = () => {
searchApplicationType.length === 0 &&
searchAssignedTo.length === 0 &&
searchConfirmationID.length == 0 &&
searchTotalCost.length === 0;
searchTotalCost.length === 0 &&
searchFundingYear == null &&
searchStatus == null;

return noValues;
};
Expand All @@ -137,6 +171,8 @@ export const ApplicationDashboard: React.FC<any> = () => {
assignedTo: searchAssignedTo,
confirmationId: searchConfirmationID,
totalCost: searchTotalCost,
fundingYear: searchFundingYear,
status: searchStatus,
};

SetQueryParams(push, query, params);
Expand All @@ -151,6 +187,8 @@ export const ApplicationDashboard: React.FC<any> = () => {
searchAssignedTo: '',
searchConfirmationID: '',
searchTotalCost: '',
searchFundingYear: '',
searchStatus: '',
}));
const params = {
...query,
Expand All @@ -159,6 +197,8 @@ export const ApplicationDashboard: React.FC<any> = () => {
assignedTo: '',
confirmationId: '',
totalCost: '',
fundingYear: '',
status: '',
limit: 20,
page: DEFAULT_QUERY.page,
};
Expand All @@ -185,6 +225,28 @@ export const ApplicationDashboard: React.FC<any> = () => {
<div className='w-full border py-4 px-8 mb-2'>
Filter By:
<div className='grid grid-cols-4 gap-1'>
<SelectFilter
placeholder='Funding Year'
searchType={searchFundingYear}
onChange={(e: any) => setState(p => ({ ...p, searchFundingYear: e.target.value }))}
options={[
{ name: '2024/25', value: '2024/25' },
{ name: '2025/26', value: '2025/26' },
{ name: '2026/27', value: '2026/27' },
]}
/>
<SelectFilter
placeholder='Status'
searchType={searchStatus}
onChange={(e: any) => setState(p => ({ ...p, searchStatus: e.target.value }))}
options={[
{ name: ApplicationStatus.RECEIVED, value: ApplicationStatus.RECEIVED },
{ name: ApplicationStatus.ASSIGNED, value: ApplicationStatus.ASSIGNED },
{ name: ApplicationStatus.APPROVED, value: ApplicationStatus.APPROVED },
{ name: ApplicationStatus.DENIED, value: ApplicationStatus.DENIED },
{ name: ApplicationStatus.WORKSHOP, value: ApplicationStatus.WORKSHOP },
]}
/>
<InputFilter
placeholder='Confirmation ID'
onChange={(e: any) =>
Expand All @@ -209,12 +271,6 @@ export const ApplicationDashboard: React.FC<any> = () => {
searchType={searchApplicationType}
/>

<InputFilter
placeholder='Estimated Cost'
onChange={(e: any) => setState(p => ({ ...p, searchTotalCost: e.target.value }))}
searchType={searchTotalCost}
/>

<InputFilter
placeholder='Assigned To'
onChange={(e: any) => setState(p => ({ ...p, searchAssignedTo: e.target.value }))}
Expand Down

0 comments on commit 8a40c22

Please sign in to comment.