From 3152bf13e6ed768a03d92277312f326aa0a2e9bf Mon Sep 17 00:00:00 2001 From: Christopher Seven Phiri Date: Tue, 16 Jul 2024 15:16:40 +0200 Subject: [PATCH] add date range --- src/app/(dashboard)/stats/actions.ts | 29 +++++++++++++-- src/app/(dashboard)/stats/content.tsx | 12 +++++-- src/app/(dashboard)/stats/filters.ts | 50 ++++++++++++++++++++------ src/app/(dashboard)/stats/model.ts | 17 +++------ src/components/filters/filter-card.tsx | 9 ++++- src/lib/models/types.ts | 2 +- src/lib/utils.ts | 38 +++++++++++++++++--- src/model/filters.ts | 2 +- 8 files changed, 123 insertions(+), 36 deletions(-) diff --git a/src/app/(dashboard)/stats/actions.ts b/src/app/(dashboard)/stats/actions.ts index a94501b..edc322f 100644 --- a/src/app/(dashboard)/stats/actions.ts +++ b/src/app/(dashboard)/stats/actions.ts @@ -9,6 +9,7 @@ import { createPatientFilters, createQuestionnaireResponseFilters, } from "./filters"; +import { eachDayOfInterval } from "@/lib/utils"; export async function fetchRequiredData() { const locationQuery = paramGenerator("/Location", { @@ -30,10 +31,10 @@ export async function fetchData(formData: FormData) { ) as FilterFormData; console.log(JSON.stringify(data)); - let rawDate: string | null = null; + let rawDate: string | string[] | null = null; const baseFilter = data.filters.map((filter) => { const temp: Record = {}; - + if (filter.template == "_tag_location") { console.log(filter); const template = `http://smartregister.org/fhir/location-tag|${ @@ -47,6 +48,29 @@ export async function fetchData(formData: FormData) { rawDate = filter.params.find((e) => e.name == "date")?.value?.split("T")[0] ?? null; + } else if (filter.template == "dateRange") { + const value = filter.params[0].value; + if (value) { + const { from, to } = value as any; + console.log(from, to); + + if (from && to) { + const start = new Date(from.split("T")[0]); + const end = new Date(to.split("T")[0]); + console.log({ start, end }); + + rawDate = eachDayOfInterval({ + start, + end, + }).map((e) => { + console.log(e); + + return e.toISOString().split("T")[0]; + }); + } else if (from) { + rawDate = [from.split("T")[0]]; + } + } } return temp; }); @@ -54,7 +78,6 @@ export async function fetchData(formData: FormData) { if (rawDate) { rawDate = fixDate(rawDate); } - const bundle = await fetchBundle([ createQuestionnaireResponseFilters( diff --git a/src/app/(dashboard)/stats/content.tsx b/src/app/(dashboard)/stats/content.tsx index f1cbee5..fb00be4 100644 --- a/src/app/(dashboard)/stats/content.tsx +++ b/src/app/(dashboard)/stats/content.tsx @@ -10,10 +10,10 @@ type Props = {}; const Content = (props: Props) => { const { data } = useGenericContext(); const { summaries, date } = data as SummaryResponse; - + return (
- {date &&

Results for: {date.split("T")[0]}

} + {date &&

Results for: {formatDate(date)}

} {summaries.map((summary) => (
@@ -28,4 +28,12 @@ const Content = (props: Props) => { ); }; +const formatDate = (date: string | string[]) => { + if (typeof date === "string") { + return date.split("T")[0]; + } else { + return date.map((d) => format(d, "dd/MM/yyyy")).join(", "); + } +}; + export default Content; diff --git a/src/app/(dashboard)/stats/filters.ts b/src/app/(dashboard)/stats/filters.ts index c8e96a3..5c6e652 100644 --- a/src/app/(dashboard)/stats/filters.ts +++ b/src/app/(dashboard)/stats/filters.ts @@ -8,7 +8,7 @@ type PatientType = export const createQuestionnaireResponseFilters = ( questionnaire: string, - date: string | null, + date: string | string[] | null, baseFilter: Record[], hasCount = true ) => { @@ -22,19 +22,33 @@ export const createQuestionnaireResponseFilters = ( query.fromArray(baseFilter); query.remove("date"); + query.remove("dateRange"); + if (date) { - query.add( - "_tag", - `https://d-tree.org/fhir/created-on-tag|${format(date, "dd/MM/yyyy")}` - ); + if (typeof date === "string") { + date = [date]; + } else { + query.add( + "_tag", + date + .map( + (d) => + `https://d-tree.org/fhir/created-on-tag|${format( + d, + "dd/MM/yyyy" + )}` + ) + .join(",") + ); + date.forEach((d) => {}); + } } return query.toUrl("/QuestionnaireResponse"); }; - export const createPatientFilters = ( types: PatientType[] | undefined = undefined, - date: string | null, + date: string | string[] | null, baseFilter: Record[] ) => { const query = new QueryParam({ @@ -43,11 +57,25 @@ export const createPatientFilters = ( query.fromArray(baseFilter); query.remove("date"); + query.remove("dateRange"); if (date) { - query.add( - "_tag", - `https://d-tree.org/fhir/created-on-tag|${format(date, "dd/MM/yyyy")}` - ); + if (typeof date === "string") { + date = [date]; + } else { + query.add( + "_tag", + date + .map( + (d) => + `https://d-tree.org/fhir/created-on-tag|${format( + d, + "dd/MM/yyyy" + )}` + ) + .join(",") + ); + date.forEach((d) => {}); + } } if (types) { query.add( diff --git a/src/app/(dashboard)/stats/model.ts b/src/app/(dashboard)/stats/model.ts index eada71d..9ceba28 100644 --- a/src/app/(dashboard)/stats/model.ts +++ b/src/app/(dashboard)/stats/model.ts @@ -1,10 +1,7 @@ -import { randomInt } from "crypto"; -import { addDays } from "date-fns"; - -export const fixDate = (date: string) => { +export const fixDate = (date: string | string[]) => { return date; // return addDays(date, 1).toISOString(); -} +}; export class QueryParam { queries: Map = new Map(); @@ -13,8 +10,6 @@ export class QueryParam { } add(key: string, value: any) { - console.log(key,this.queries.has(key) ); - if (this.queries.has(key)) { this.queries.set(`${key}[${Math.random()}]`, value); } else { @@ -48,13 +43,9 @@ export class QueryParam { for (const key in values) { this.from(values[key]); } - console.log(values); - console.log(this.queries); - } - toUrl( resources: string,) { - console.log(this.queries); + toUrl(resources: string) { const query = Array.from(this.queries) .map(([key, value]) => { if (key.includes("[")) { @@ -63,6 +54,6 @@ export class QueryParam { return `${key}=${value}`; }) .join("&"); - return `${resources}?${query}`; + return `${resources}?${query}`; } } diff --git a/src/components/filters/filter-card.tsx b/src/components/filters/filter-card.tsx index 996b333..fa57ae5 100644 --- a/src/components/filters/filter-card.tsx +++ b/src/components/filters/filter-card.tsx @@ -158,7 +158,14 @@ const GetInput = ({ mode="range" selected={field.value} onSelect={(date) => { - field.onChange(date); + if (date) { + field.onChange({ + from: date.from ? formatISO(date.from) : undefined, + to: date.to ? formatISO(date.to) : undefined, + }); + } else { + field.onChange(null); + } }} // disabled={(date) => // date > new Date() || date < new Date("1900-01-01") diff --git a/src/lib/models/types.ts b/src/lib/models/types.ts index b1b4249..2f83890 100644 --- a/src/lib/models/types.ts +++ b/src/lib/models/types.ts @@ -29,7 +29,7 @@ export type LocationData = { export type SummaryResponse = { summaries: SummaryItem[], - date: string | null + date: string | string[] | null } export type SummaryItem = { diff --git a/src/lib/utils.ts b/src/lib/utils.ts index ec79801..4701e0e 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -1,6 +1,36 @@ -import { type ClassValue, clsx } from "clsx" -import { twMerge } from "tailwind-merge" - +import { type ClassValue, clsx } from "clsx"; +import { twMerge } from "tailwind-merge"; +import { addDays, subMinutes, startOfDay } from "date-fns"; + export function cn(...inputs: ClassValue[]) { - return twMerge(clsx(inputs)) + return twMerge(clsx(inputs)); +} + +export function eachDayOfInterval({ + start, + end = new Date(Date.now()), +}: { + start: Date; + end?: Date; +}) { + const offset = { + start: start.getTimezoneOffset(), + end: end.getTimezoneOffset(), + }; + + // Adjust start and end dates for timezone offset to use start of UTC date + const adjusted = { + start: subMinutes(startOfDay(start.getTime()), offset.start), + end: subMinutes(startOfDay(end.getTime()), offset.end), + }; + + let accumulator = adjusted.start; + const days: Date[] = []; + + while (end >= accumulator) { + days.push(accumulator); + accumulator = addDays(accumulator, 1); + } + + return days; } diff --git a/src/model/filters.ts b/src/model/filters.ts index 7c7a8ab..662a1c9 100644 --- a/src/model/filters.ts +++ b/src/model/filters.ts @@ -109,7 +109,7 @@ export const statsFilters: Filter[] = [ { id: "filter-by-date-rage", name: "Search by date range", - template: "date", + template: "dateRange", isObject: true, params: [ {