UNPKG

@ministryofjustice/hmpps-digital-prison-reporting-frontend

Version:

The Digital Prison Reporting Frontend contains templates and code to help display data effectively in UI applications.

375 lines (348 loc) 13.2 kB
import dayjs from 'dayjs' import { Request } from 'express' import { components } from '../../../types/api' import { DateFilterValue, FilterValue, GranularDateRange } from '../../_filters/types' import StartEndDateUtils from '../start-end-date/utils' import { Granularity, QuickFilters } from './types' const hasPartialStartEnd = (granularity: Granularity, startDate: string, endDate: string) => { let partialStart let partialEnd switch (granularity) { case Granularity.DAILY: partialStart = false partialEnd = false break case Granularity.MONTHLY: { const startOfMonth = dayjs(startDate).startOf('month') const endOfMonth = dayjs(endDate).endOf('month') partialStart = !startOfMonth.isSame(startDate, 'day') partialEnd = !endOfMonth.isSame(endDate, 'day') } break case Granularity.ANNUALLY: { const startOfYear = dayjs(startDate).startOf('year') const endOfYear = dayjs(endDate).endOf('year') partialStart = !startOfYear.isSame(startDate, 'day') partialEnd = !endOfYear.isSame(endDate, 'day') } break default: partialStart = false partialEnd = false break } return { start: partialStart, end: partialEnd, } } const getQuickFilterOptions = () => { const options: { value: QuickFilters; text: string; disabled?: boolean }[] = [ { value: QuickFilters.NONE, text: 'None' }, { value: QuickFilters.TODAY, text: 'Today' }, { value: QuickFilters.PAST, text: 'Past:', disabled: true }, { value: QuickFilters.YESTERDAY, text: 'Yesterday' }, { value: QuickFilters.LAST_SEVEN_DAYS, text: 'Last 7 days' }, { value: QuickFilters.LAST_THIRTY_DAYS, text: 'Last 30 days' }, { value: QuickFilters.LAST_MONTH, text: 'Last month' }, { value: QuickFilters.LAST_FULL_MONTH, text: 'Last full month' }, { value: QuickFilters.LAST_NINETY_DAYS, text: 'Last 90 days' }, { value: QuickFilters.LAST_THREE_MONTHS, text: 'Last 3 months' }, { value: QuickFilters.LAST_FULL_THREE_MONTHS, text: 'Last full 3 months' }, { value: QuickFilters.LAST_SIX_MONTHS, text: 'Last 6 months' }, { value: QuickFilters.LAST_FULL_SIX_MONTHS, text: 'Last full 6 months' }, { value: QuickFilters.LAST_YEAR, text: 'Last year' }, { value: QuickFilters.LAST_FULL_YEAR, text: 'Last full year' }, { value: QuickFilters.FUTURE, text: 'Future:', disabled: true }, { value: QuickFilters.TOMORROW, text: 'Tomorrow' }, { value: QuickFilters.NEXT_SEVEN_DAYS, text: 'Next 7 days' }, { value: QuickFilters.NEXT_THIRTY_DAYS, text: 'Next 30 days' }, { value: QuickFilters.NEXT_MONTH, text: 'Next month' }, { value: QuickFilters.NEXT_FULL_MONTH, text: 'Next full month' }, { value: QuickFilters.NEXT_NINETY_DAYS, text: 'Next 90 days' }, { value: QuickFilters.NEXT_THREE_MONTHS, text: 'Next 3 months' }, { value: QuickFilters.NEXT_FULL_THREE_MONTHS, text: 'Next full 3 months' }, { value: QuickFilters.NEXT_SIX_MONTHS, text: 'Next 6 months' }, { value: QuickFilters.NEXT_FULL_SIX_MONTHS, text: 'Next full 6 months' }, { value: QuickFilters.NEXT_YEAR, text: 'Next year' }, { value: QuickFilters.NEXT_FULL_YEAR, text: 'Next full year' }, ] return options } const getGranularityOptions = () => { const options: { value: Granularity; text: string; disabled?: boolean }[] = [ { value: Granularity.HOURLY, text: 'Hourly' }, { value: Granularity.DAILY, text: 'Daily' }, // { value: Granularity.WEEKLY, text: 'Weekly' }, { value: Granularity.MONTHLY, text: 'Monthly' }, // { value: Granularity.QUARTERLY, text: 'Quarterly' }, { value: Granularity.ANNUALLY, text: 'Annually' }, ] return options } const setDateRangeFromQuickFilterValue = (value: string) => { let startDate let endDate let granularity switch (value) { case QuickFilters.TODAY: endDate = dayjs() startDate = dayjs() granularity = Granularity.DAILY break case QuickFilters.YESTERDAY: endDate = dayjs().subtract(1, 'day') startDate = dayjs().subtract(1, 'day') granularity = Granularity.DAILY break case QuickFilters.LAST_SEVEN_DAYS: endDate = dayjs() startDate = endDate.subtract(7, 'day').add(1, 'day') granularity = Granularity.DAILY break case QuickFilters.LAST_THIRTY_DAYS: endDate = dayjs() startDate = endDate.subtract(30, 'day').add(1, 'day') granularity = Granularity.DAILY break case QuickFilters.LAST_MONTH: endDate = dayjs() startDate = endDate.subtract(1, 'month').add(1, 'day') granularity = Granularity.MONTHLY break case QuickFilters.LAST_FULL_MONTH: endDate = dayjs().subtract(1, 'month').endOf('month') startDate = endDate.startOf('month') granularity = Granularity.MONTHLY break case QuickFilters.LAST_NINETY_DAYS: endDate = dayjs() startDate = endDate.subtract(90, 'day').add(1, 'day') granularity = Granularity.DAILY break case QuickFilters.LAST_THREE_MONTHS: endDate = dayjs() startDate = endDate.subtract(3, 'month').add(1, 'day') granularity = Granularity.MONTHLY break case QuickFilters.LAST_FULL_THREE_MONTHS: endDate = dayjs().subtract(1, 'month').endOf('month') startDate = endDate.subtract(2, 'month').startOf('month') granularity = Granularity.MONTHLY break case QuickFilters.LAST_SIX_MONTHS: endDate = dayjs() startDate = endDate.subtract(6, 'month').add(1, 'day') granularity = Granularity.MONTHLY break case QuickFilters.LAST_FULL_SIX_MONTHS: endDate = dayjs().subtract(1, 'month').endOf('month') startDate = endDate.subtract(6, 'month').startOf('month') granularity = Granularity.MONTHLY break case QuickFilters.LAST_YEAR: endDate = dayjs() startDate = endDate.subtract(1, 'year').add(1, 'day') granularity = Granularity.ANNUALLY break case QuickFilters.LAST_FULL_YEAR: endDate = dayjs().subtract(1, 'year').endOf('year') startDate = endDate.startOf('year') granularity = Granularity.ANNUALLY break case QuickFilters.TOMORROW: endDate = dayjs().add(1, 'day') startDate = dayjs().add(1, 'day') granularity = Granularity.DAILY break case QuickFilters.NEXT_SEVEN_DAYS: startDate = dayjs() endDate = dayjs().add(7, 'day').subtract(1, 'day') granularity = Granularity.DAILY break case QuickFilters.NEXT_THIRTY_DAYS: startDate = dayjs() endDate = dayjs().add(30, 'day').subtract(1, 'day') granularity = Granularity.DAILY break case QuickFilters.NEXT_MONTH: startDate = dayjs() endDate = dayjs().add(1, 'month').subtract(1, 'day') granularity = Granularity.MONTHLY break case QuickFilters.NEXT_FULL_MONTH: startDate = dayjs().add(1, 'month').startOf('month') endDate = startDate.endOf('month') granularity = Granularity.MONTHLY break case QuickFilters.NEXT_NINETY_DAYS: startDate = dayjs() endDate = dayjs().add(90, 'day').subtract(1, 'day') granularity = Granularity.DAILY break case QuickFilters.NEXT_THREE_MONTHS: startDate = dayjs() endDate = dayjs().add(3, 'month').subtract(1, 'day') granularity = Granularity.MONTHLY break case QuickFilters.NEXT_FULL_THREE_MONTHS: startDate = dayjs().add(1, 'month').startOf('month') endDate = startDate.add(2, 'month').endOf('month') granularity = Granularity.MONTHLY break case QuickFilters.NEXT_YEAR: startDate = dayjs() endDate = dayjs().add(1, 'year').subtract(1, 'day') granularity = Granularity.ANNUALLY break case QuickFilters.NEXT_FULL_YEAR: startDate = dayjs().add(1, 'year').startOf('year') endDate = startDate.endOf('year') granularity = Granularity.ANNUALLY break default: endDate = dayjs() startDate = dayjs() granularity = Granularity.DAILY break } return { start: startDate.format('YYYY-MM-DD').toString(), end: endDate.format('YYYY-MM-DD').toString(), granularity, } } const getOptionDisplayValue = (value: string, options: { text: string; value: string }[]) => { const item = options.find((opt) => { return opt.value === value }) return item.text || value } const setValueFromRequest = (filter: FilterValue, req: Request, prefix: string) => { const { preventDefault } = req.query const quickFilter = <string>req.query[`${prefix}${filter.name}.quick-filter`] let granularity: Granularity let start let end if (quickFilter && quickFilter !== QuickFilters.NONE) { ;({ granularity, start, end } = setDateRangeFromQuickFilterValue(quickFilter)) } else { granularity = (<string>req.query[`${prefix}${filter.name}.granularity`]) as Granularity start = <string>req.query[`${prefix}${filter.name}.start`] end = <string>req.query[`${prefix}${filter.name}.end`] } const defaultStart = preventDefault ? null : (<GranularDateRange>filter.value)?.start const defaultEnd = preventDefault ? null : (<GranularDateRange>filter.value)?.end const defaultGranularity = preventDefault ? Granularity.DAILY : (<GranularDateRange>filter.value)?.granularity.value const defaultQuickFilter = preventDefault ? 'none' : (<GranularDateRange>filter.value)?.quickFilter.value const granularityOptions = getGranularityOptions() const quickFilterOptions = getQuickFilterOptions() const startDate = start || defaultStart || (<DateFilterValue>filter).min const endDate = end || defaultEnd || (<DateFilterValue>filter).max const granularityValue = granularity || defaultGranularity const quickFilterValue = quickFilter || defaultQuickFilter const value = { start: startDate, end: endDate, granularity: { value: granularityValue, display: getOptionDisplayValue(granularityValue, granularityOptions), }, quickFilter: { value: quickFilterValue, display: getOptionDisplayValue(quickFilterValue, quickFilterOptions), }, partialDate: { ...hasPartialStartEnd(granularityValue, startDate, endDate), }, } return value as GranularDateRange } const getFilterFromDefinition = ( filter: components['schemas']['FilterDefinition'] & { defaultGranularity: Granularity defaultQuickFilterValue: QuickFilters }, filterData: FilterValue, ) => { let value const quickFilterValue = filter.defaultQuickFilterValue const granularityOptions = getGranularityOptions() const quickFilterOptions = getQuickFilterOptions() if (quickFilterValue) { const { start, end, granularity } = setDateRangeFromQuickFilterValue(quickFilterValue) value = { start, end, granularity: { value: granularity, display: getOptionDisplayValue(granularity, granularityOptions), }, quickFilter: { value: quickFilterValue, display: getOptionDisplayValue(quickFilterValue, quickFilterOptions), }, partialDate: { ...hasPartialStartEnd(granularity, start, end), }, } } else { value = <GranularDateRange>StartEndDateUtils.getStartAndEndValueFromDefinition(filter) const granularityValue: Granularity = value.granularity ? value.granularity.value : filter.defaultGranularity || Granularity.DAILY value = { ...value, granularity: { value: granularityValue, display: getOptionDisplayValue(granularityValue, granularityOptions), }, quickFilter: { value: QuickFilters.NONE, display: 'None', }, partialDate: { ...hasPartialStartEnd(granularityValue, value.start, value.end), }, } } return { ...filterData, min: filter.min, max: filter.max, value, quickFilterOptions: getQuickFilterOptions(), granularityOptions: getGranularityOptions(), } } const getQueryFromDefinition = ( filter: components['schemas']['FilterDefinition'] & { defaultGranularity: Granularity defaultQuickFilterValue: QuickFilters }, name: string, filterPrefix: string, startEndParams: string, ) => { const params = [] if (filter.defaultQuickFilterValue) { const { start, end, granularity } = setDateRangeFromQuickFilterValue(filter.defaultQuickFilterValue) params.push(`${filterPrefix}${name}.quick-filter=${filter.defaultQuickFilterValue}`) params.push(`${filterPrefix}${name}.granularity=${granularity}`) params.push(`${filterPrefix}${name}.start=${start}`) params.push(`${filterPrefix}${name}.end=${end}`) } else if (filter.defaultGranularity && startEndParams) { params.push(`${filterPrefix}${name}.granularity=${filter.defaultGranularity}`) params.push(`${startEndParams}`) } else if (filter.defaultGranularity) { params.push(`${filterPrefix}${name}.granularity=${filter.defaultGranularity}`) } return params.join('&') } export default { getFilterFromDefinition, setValueFromRequest, getQueryFromDefinition, }