Skip to content

Commit a6d7032

Browse files
authored
Goal improvements (#1007)
* Refactor BotSection and introduce BotSectionTabs for improved modularity This commit refactors the BotSection component to separate data handling and presentation logic, introducing the useBotSectionData hook for data fetching. Additionally, it creates the BotSectionTabs component to manage tabbed navigation for different bot dimensions, enhancing code organization and reusability. The BotCountries, BotDevices, BotMetadata, BotPages, and BotReferrers components are updated to utilize the new BotSectionTabs, streamlining their implementations and improving user experience. * goal improvements * Update GoalCard component styles and layout for improved responsiveness and visual consistency * Enhance StandardSectionDialog with error handling and update BucketSelection component for size prop This commit introduces error handling in the StandardSectionDialog by displaying an ErrorState component when data fetching fails. Additionally, the BucketSelection component is updated to accept a size prop, allowing for more flexible styling in different contexts. The GoalsPage is also modified to utilize the new size prop for the BucketSelection component. * Integrate GoalBarChartSkeleton into GoalCard and GoalsPage for improved loading states This commit introduces the GoalBarChartSkeleton component into both the GoalCard and GoalsPage components, enhancing the user experience during data loading. The layout is adjusted to accommodate the new skeleton, ensuring a consistent and visually appealing loading state across the application. * Refactor GoalCardSkeleton and GoalBarChartSkeleton for improved layout consistency This commit modifies the GoalCardSkeleton to enhance its layout by adjusting the flex properties for better alignment. Additionally, the GoalBarChartSkeleton is updated to be hidden on smaller screens, ensuring a responsive design that maintains visual integrity across different device sizes.
1 parent b7387d3 commit a6d7032

33 files changed

Lines changed: 1803 additions & 1227 deletions

client/src/api/analytics/endpoints/goals.ts

Lines changed: 46 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
import { authedFetch } from "../../utils";
2-
import { CommonApiParams, PaginationParams, SortParams, toQueryParams } from "./types";
2+
import {
3+
BucketedParams,
4+
CommonApiParams,
5+
PaginationParams,
6+
SortParams,
7+
toBucketedQueryParams,
8+
toQueryParams,
9+
} from "./types";
310
import type { GetSessionsResponse } from "./sessions";
411

512
// Goal type
@@ -39,12 +46,24 @@ export interface GoalsResponse {
3946
meta: PaginationMeta;
4047
}
4148

49+
export interface GoalTimeSeriesPoint {
50+
time: string;
51+
goal_id: number;
52+
conversions: number;
53+
total_sessions: number;
54+
conversion_rate: number;
55+
}
56+
4257
export interface GoalsParams extends CommonApiParams, PaginationParams, SortParams {
4358
pageSize?: number;
4459
sort?: "goalId" | "name" | "goalType" | "createdAt";
4560
order?: "asc" | "desc";
4661
}
4762

63+
export interface GoalTimeSeriesParams extends BucketedParams {
64+
goalIds: number[];
65+
}
66+
4867
export interface GoalSessionsParams extends CommonApiParams, PaginationParams {
4968
goalId: number;
5069
}
@@ -73,10 +92,7 @@ export interface UpdateGoalParams extends CreateGoalParams {
7392
* Fetch goals with pagination
7493
* GET /api/goals/:site
7594
*/
76-
export async function fetchGoals(
77-
site: string | number,
78-
params: GoalsParams
79-
): Promise<GoalsResponse> {
95+
export async function fetchGoals(site: string | number, params: GoalsParams): Promise<GoalsResponse> {
8096
const queryParams = {
8197
...toQueryParams(params),
8298
page: params.page,
@@ -89,6 +105,23 @@ export async function fetchGoals(
89105
return response;
90106
}
91107

108+
/**
109+
* Fetch bucketed conversion data for goals
110+
* GET /api/goals/bucketed/:site
111+
*/
112+
export async function fetchGoalTimeSeries(
113+
site: string | number,
114+
params: GoalTimeSeriesParams
115+
): Promise<GoalTimeSeriesPoint[]> {
116+
const queryParams = {
117+
...toBucketedQueryParams(params),
118+
goal_ids: params.goalIds,
119+
};
120+
121+
const response = await authedFetch<{ data: GoalTimeSeriesPoint[] }>(`/sites/${site}/goals/bucketed`, queryParams);
122+
return response.data;
123+
}
124+
92125
/**
93126
* Fetch sessions that completed a goal
94127
* GET /api/goals/:goalId/sessions/:site
@@ -118,14 +151,10 @@ export async function createGoal(
118151
site: string | number,
119152
params: CreateGoalParams
120153
): Promise<{ success: boolean; goalId: number }> {
121-
const response = await authedFetch<{ success: boolean; goalId: number }>(
122-
`/sites/${site}/goals`,
123-
undefined,
124-
{
125-
method: "POST",
126-
data: params,
127-
}
128-
);
154+
const response = await authedFetch<{ success: boolean; goalId: number }>(`/sites/${site}/goals`, undefined, {
155+
method: "POST",
156+
data: params,
157+
});
129158
return response;
130159
}
131160

@@ -152,16 +181,9 @@ export async function updateGoal(
152181
* Delete a goal
153182
* DELETE /api/goals/:goalId/:site
154183
*/
155-
export async function deleteGoal(
156-
site: string | number,
157-
goalId: number
158-
): Promise<{ success: boolean }> {
159-
const response = await authedFetch<{ success: boolean }>(
160-
`/sites/${site}/goals/${goalId}`,
161-
undefined,
162-
{
163-
method: "DELETE",
164-
}
165-
);
184+
export async function deleteGoal(site: string | number, goalId: number): Promise<{ success: boolean }> {
185+
const response = await authedFetch<{ success: boolean }>(`/sites/${site}/goals/${goalId}`, undefined, {
186+
method: "DELETE",
187+
});
166188
return response;
167189
}

client/src/api/analytics/endpoints/index.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ export type {
3434
SiteEventCountParams,
3535
} from "./events";
3636

37-
3837
// Errors endpoints
3938
export { fetchErrorNames, fetchErrorEvents, fetchErrorBucketed } from "./errors";
4039
export type {
@@ -51,12 +50,14 @@ export type {
5150
} from "./errors";
5251

5352
// Goals endpoints
54-
export { fetchGoals, fetchGoalSessions, createGoal, updateGoal, deleteGoal } from "./goals";
53+
export { fetchGoals, fetchGoalTimeSeries, fetchGoalSessions, createGoal, updateGoal, deleteGoal } from "./goals";
5554
export type {
5655
Goal,
56+
GoalTimeSeriesPoint,
5757
PaginationMeta,
5858
GoalsResponse,
5959
GoalsParams,
60+
GoalTimeSeriesParams,
6061
GoalSessionsParams,
6162
CreateGoalParams,
6263
UpdateGoalParams,

client/src/api/analytics/hooks/goals/useCreateGoal.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ export function useCreateGoal() {
3434
queryClient.invalidateQueries({
3535
queryKey: ["goals", variables.siteId.toString()],
3636
});
37+
queryClient.invalidateQueries({
38+
queryKey: ["goal-time-series", variables.siteId.toString()],
39+
});
3740
},
3841
});
3942
}

client/src/api/analytics/hooks/goals/useDeleteGoal.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ export function useDeleteGoal() {
1515
queryClient.invalidateQueries({
1616
queryKey: ["goals", site],
1717
});
18+
queryClient.invalidateQueries({
19+
queryKey: ["goal-time-series", site],
20+
});
1821
},
1922
});
2023
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { useQuery } from "@tanstack/react-query";
2+
import { TimeBucket } from "@rybbit/shared";
3+
import { GOALS_PAGE_FILTERS } from "../../../../lib/filterGroups";
4+
import { getFilteredFilters, useStore } from "../../../../lib/store";
5+
import { buildApiParams } from "../../../utils";
6+
import { fetchGoalTimeSeries } from "../../endpoints";
7+
8+
export function useGetGoalTimeSeries({ goalIds, bucket }: { goalIds: number[]; bucket?: TimeBucket }) {
9+
const { site, time, bucket: storeBucket, timezone } = useStore();
10+
const filteredFilters = getFilteredFilters(GOALS_PAGE_FILTERS);
11+
const bucketToUse = bucket || storeBucket;
12+
const params = buildApiParams(time, { filters: filteredFilters });
13+
14+
return useQuery({
15+
queryKey: ["goal-time-series", site, time, bucketToUse, filteredFilters, goalIds, timezone],
16+
queryFn: async () => {
17+
return fetchGoalTimeSeries(site, {
18+
...params,
19+
bucket: bucketToUse,
20+
goalIds,
21+
});
22+
},
23+
enabled: !!site && goalIds.length > 0,
24+
});
25+
}

client/src/api/analytics/hooks/goals/useUpdateGoal.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ export function useUpdateGoal() {
4343
queryClient.invalidateQueries({
4444
queryKey: ["goals", site],
4545
});
46+
queryClient.invalidateQueries({
47+
queryKey: ["goal-time-series", site],
48+
});
4649
},
4750
});
4851
}

client/src/api/analytics/hooks/useGetMetric.ts

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,16 +129,39 @@ export function useInfiniteMetric({
129129
parameter,
130130
limit = 25,
131131
useFilters = true,
132+
additionalFilters = [],
133+
customFilters = [],
134+
customTime,
132135
}: {
133136
parameter: FilterParameter;
134137
limit?: number;
135138
useFilters?: boolean;
139+
additionalFilters?: Filter[];
140+
customFilters?: Filter[];
141+
customTime?: Time;
136142
}): UseInfiniteQueryResult<InfiniteData<PaginatedResponse>> {
137143
const { time, site, filters, timezone } = useStore();
138-
const params = buildApiParams(time, { filters: useFilters ? filters : undefined });
144+
const timeToUse = customTime ?? time;
145+
const combinedFilters = useFilters
146+
? customFilters.length > 0
147+
? customFilters
148+
: [...filters, ...additionalFilters]
149+
: undefined;
150+
const params = buildApiParams(timeToUse, { filters: combinedFilters });
139151

140152
return useInfiniteQuery({
141-
queryKey: [parameter, time, site, filters, limit, "infinite-metric", timezone],
153+
queryKey: [
154+
parameter,
155+
customTime,
156+
time,
157+
site,
158+
filters,
159+
limit,
160+
additionalFilters,
161+
customFilters,
162+
"infinite-metric",
163+
timezone,
164+
],
142165
queryFn: async ({ pageParam = 1 }) => {
143166
return fetchMetric(site, {
144167
...params,

0 commit comments

Comments
 (0)