Skip to content

Commit

Permalink
fix: insights UI/UX (#16610)
Browse files Browse the repository at this point in the history
* remove old code remnant

* -

* WIP

* type change

* --

* typefix

* fix type

* fix type

* change type name

* add basewhere to eventsByStatus

* add basewhere to the rest

* fix rendering null popular event list item

* URL params for start and endtime to have YYYY-MM-DD format

* remove console log

* resolve suggestion

---------

Co-authored-by: Udit Takkar <[email protected]>
  • Loading branch information
alishaz-polymath and Udit-takkar authored Sep 27, 2024
1 parent 2872b26 commit 38fa0fa
Show file tree
Hide file tree
Showing 10 changed files with 437 additions and 797 deletions.
4 changes: 4 additions & 0 deletions apps/web/public/static/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -2618,5 +2618,9 @@
"you_are_unauthorized_to_make_this_change_to_the_booking": "You are unauthorized to make this change to the booking",
"hide_calendar_event_details": "Hide calendar event details on shared calendars",
"description_hide_calendar_event_details": "When a calendar is shared, events are visible to readers but their details are hidden from those without write access.",
"last_number_of_days": "last {{count}} days",
"month_to_date": "month to date",
"year_to_date": "year to date",
"custom_range": "custom range",
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@ export const AverageEventDurationChart = () => {
const { filter } = useFilterContext();
const { dateRange, selectedMemberUserId, isAll, initialConfig } = filter;
const [startDate, endDate] = dateRange;
const { selectedTeamId: teamId, selectedUserId } = filter;
const { selectedTeamId: teamId, selectedUserId, selectedEventTypeId } = filter;
const initialConfigIsReady = !!(initialConfig?.teamId || initialConfig?.userId || initialConfig?.isAll);
const { data, isSuccess, isPending } = trpc.viewer.insights.averageEventDuration.useQuery(
{
startDate: startDate.toISOString(),
endDate: endDate.toISOString(),
teamId: teamId ?? undefined,
teamId,
eventTypeId: selectedEventTypeId ?? undefined,
memberUserId: selectedMemberUserId ?? undefined,
userId: selectedUserId ?? undefined,
isAll,
Expand Down
1 change: 1 addition & 0 deletions packages/features/insights/components/BookingKPICards.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { KPICard } from "./KPICard";
export const BookingKPICards = () => {
const { t } = useLocale();
const { filter } = useFilterContext();

const { dateRange, selectedEventTypeId, selectedUserId, selectedMemberUserId, isAll, initialConfig } =
filter;
const initialConfigIsReady = !!(initialConfig?.teamId || initialConfig?.userId || initialConfig?.isAll);
Expand Down
27 changes: 16 additions & 11 deletions packages/features/insights/components/PopularEventsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import { LoadingInsight } from "./LoadingInsights";
export const PopularEventsTable = () => {
const { t } = useLocale();
const { filter } = useFilterContext();
const { dateRange, selectedMemberUserId, selectedUserId, isAll, initialConfig } = filter;
const { dateRange, selectedMemberUserId, selectedUserId, isAll, initialConfig, selectedEventTypeId } =
filter;
const [startDate, endDate] = dateRange;
const { selectedTeamId: teamId } = filter;

Expand All @@ -20,6 +21,7 @@ export const PopularEventsTable = () => {
endDate: endDate.toISOString(),
teamId: teamId ?? undefined,
userId: selectedUserId ?? undefined,
eventTypeId: selectedEventTypeId ?? undefined,
memberUserId: selectedMemberUserId ?? undefined,
isAll,
},
Expand All @@ -41,16 +43,19 @@ export const PopularEventsTable = () => {
<Title className="text-emphasis">{t("popular_events")}</Title>
<Table className="mt-5">
<TableBody>
{data.map((item) => (
<TableRow key={item.eventTypeId}>
<TableCell className="text-default">{item.eventTypeName}</TableCell>
<TableCell>
<Text className="text-default text-right">
<strong>{item.count}</strong>
</Text>
</TableCell>
</TableRow>
))}
{data.map(
(item) =>
item.eventTypeId && (
<TableRow key={item.eventTypeId}>
<TableCell className="text-default">{item.eventTypeName}</TableCell>
<TableCell>
<Text className="text-default text-right">
<strong>{item.count}</strong>
</Text>
</TableCell>
</TableRow>
)
)}
</TableBody>
</Table>
{data.length === 0 && (
Expand Down
6 changes: 3 additions & 3 deletions packages/features/insights/context/FiltersProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export function FiltersProvider({ children }: { children: React.ReactNode }) {
dateRange: [
startTimeParsed ? dayjs(startTimeParsed) : dayjs().subtract(1, "week"),
endTimeParsed ? dayjs(endTimeParsed) : dayjs(),
"w",
!startTimeParsed && !endTimeParsed ? "w" : null,
],
selectedTimeView: "week",
selectedUserId: userIdParsed || null,
Expand Down Expand Up @@ -131,8 +131,8 @@ export function FiltersProvider({ children }: { children: React.ReactNode }) {
setParamsIfDefined("userId", selectedUserId || initialConfig?.userId);
setParamsIfDefined("eventTypeId", selectedEventTypeId);
setParamsIfDefined("isAll", isAll || initialConfig?.isAll);
setParamsIfDefined("startTime", startTime?.toISOString());
setParamsIfDefined("endTime", endTime?.toISOString());
setParamsIfDefined("startTime", startTime?.format("YYYY-MM-DD"));
setParamsIfDefined("endTime", endTime?.format("YYYY-MM-DD"));
setParamsIfDefined("filter", selectedFilter?.[0]);
router.push(`${pathname}?${newSearchParams.toString()}`);
},
Expand Down
126 changes: 80 additions & 46 deletions packages/features/insights/filters/DateSelect.tsx
Original file line number Diff line number Diff line change
@@ -1,68 +1,102 @@
import { DateRangePicker } from "@tremor/react";
import { useState } from "react";

import dayjs from "@calcom/dayjs";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { DateRangePicker } from "@calcom/ui";
import { Select } from "@calcom/ui";

import { useFilterContext } from "../context/provider";
import "./DateSelect.css";

type RangeType = "tdy" | "w" | "t" | "m" | "y" | undefined | null;

export const DateSelect = () => {
const { t } = useLocale();
const presetOptions = [
{ label: t("today"), value: "tdy" },
{ label: t("last_number_of_days", { count: 7 }), value: "w" },
{ label: t("last_number_of_days", { count: 30 }), value: "t" },
{ label: t("month_to_date"), value: "m" },
{ label: t("year_to_date"), value: "y" },
{ label: t("custom_range"), value: null },
];

const { filter, setConfigFilters } = useFilterContext();
const currentDate = dayjs();
const [startDate, endDate, range] = filter?.dateRange || [null, null, null];
const [initialStartDate, initialEndDate, range] = filter?.dateRange || [null, null, null];
const [startDate, setStartDate] = useState(initialStartDate);
const [endDate, setEndDate] = useState(initialEndDate);
const startValue = startDate?.toDate() || null;
const endValue = endDate?.toDate() || null;
return (
<div className="custom-date max-w-96 w-full sm:w-auto">
<DateRangePicker
value={[startValue, endValue, range]}
defaultValue={[startValue, endValue, range]}
onValueChange={(datesArray) => {
const [selected, ...rest] = datesArray;
const [start, end, range] = datesArray;
// If range has value and it's of type RangeType

if (
range &&
(range === "tdy" || range === "w" || range === "t" || range === "m" || range === "y")
) {
setConfigFilters({
dateRange: [dayjs(start).startOf("d"), dayjs(end).endOf("d"), range],
});
const [selectedPreset, setSelectedPreset] = useState(presetOptions.find((c) => c.value === range));

return;
} else if (start && !end) {
// If only start time has value that means selected date should push to dateRange with last value null
const currentDates = filter.dateRange;
if (currentDates && currentDates.length > 0) {
// remove last position of array
currentDates.pop();
// push new value to array
currentDates.push(dayjs(selected));
// if lenght > 2 then remove first value
if (currentDates.length > 2) {
currentDates.shift();
}
setConfigFilters({
dateRange: [currentDates[0], currentDates[1], null],
});
}
const updateDateRange = (val: string | null) => {
setSelectedPreset(presetOptions.find((c) => c.value === val));
let startDate = dayjs();
let endDate = dayjs();

return;
}
switch (val) {
case "tdy": // Today
startDate = dayjs().startOf("day");
endDate = dayjs().endOf("day");
break;
case "w": // Last 7 days
startDate = dayjs().subtract(7, "day").startOf("day");
endDate = dayjs().endOf("day");
break;
case "t": // Last 30 days
startDate = dayjs().subtract(30, "day").startOf("day");
endDate = dayjs().endOf("day");
break;
case "m": // Month to Date
startDate = dayjs().startOf("month");
endDate = dayjs().endOf("day");
break;
case "y": // Year to Date
startDate = dayjs().startOf("year");
endDate = dayjs().endOf("day");
break;
default:
break;
}
// Update the datepicker date selection
setStartDate(startDate);
setEndDate(endDate);
// Update the configuration filter
setConfigFilters({
dateRange: [dayjs(startDate), dayjs(endDate), val],
});
};

// If range has value and it's of type RangeType
return (
<div className="ml me-2 ms-2 inline-flex space-x-2 rtl:space-x-reverse">
<DateRangePicker
dates={{
startDate: startValue,
endDate: endValue,
}}
options={undefined}
enableDropdown={true}
placeholder={t("select_date_range")}
enableYearPagination={true}
minDate={currentDate.subtract(2, "year").toDate()}
maxDate={currentDate.toDate()}
color="gray"
disabled={false}
onDatesChange={({ startDate, endDate }) => {
setConfigFilters({
dateRange: [dayjs(startDate), dayjs(endDate), null],
});
setStartDate(dayjs(startDate));
setEndDate(dayjs(endDate));
setSelectedPreset(presetOptions.find((c) => c.value === null));
}}
/>
<Select
variant="default"
data-testid="insights-preset"
options={presetOptions}
value={selectedPreset}
className="w-40 capitalize text-black"
defaultValue={selectedPreset}
onChange={(e) => {
if (e) {
updateDateRange(e.value);
}
}}
/>
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion packages/features/insights/filters/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export const Filters = () => {
/>
</Tooltip>
</ButtonGroup> */}
<div className="flex flex-col-reverse gap-2 sm:flex-row sm:flex-nowrap sm:justify-between">
<div className="flex flex-col-reverse sm:flex-row sm:flex-nowrap sm:justify-between">
<Download />
<DateSelect />
</div>
Expand Down
Loading

0 comments on commit 38fa0fa

Please sign in to comment.