Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: add cache modifiers to mutations #19

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions apps/web/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"tabWidth": 2,
"useTabs": false,
"semi": true
}
9 changes: 1 addition & 8 deletions apps/web/src/hooks/queries/useActivities/apiCalls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,7 @@ const basePath = "api/v1/courses";
export const useActivitiesRequests = (orgId: string) => {
const activitiesQuery = async (): Promise<Activity[]> => {
const res = await client.get(`${basePath}/${orgId}/activities/`);
return res.data.activities
.map((activity: Activity) => ({
...activity,
date: new Date(activity.date),
}))
.sort((a: Activity, b: Activity) => {
return b.date.getTime() - a.date.getTime();
});
return res.data.activities;
};

const createActivity = async (
Expand Down
26 changes: 26 additions & 0 deletions apps/web/src/hooks/queries/useActivities/cacheModifiers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { useQueryClient } from "@tanstack/react-query";
import { useQueryKey } from "./queryKey";
import type { Activity } from "@/types/interfaces";

export const useCacheModifiers = (queryKey: ReturnType<typeof useQueryKey>) => {
const queryClient = useQueryClient();

const addActivitiesToCache = (activities: Activity[]) => {
queryClient.setQueryData<Activity[]>(queryKey, (data) => {
if (!data) return [...activities];
return [...data, ...activities];
});
};

const removeMultipleActivitiesFromCache = (slugs: string[]) => {
const slugsSet = new Set(slugs);
queryClient.setQueryData<Activity[]>(queryKey, (data) => {
if (!data) return [];
return data.filter((activity) => !slugsSet.has(activity.slug));
});
};
return {
addActivitiesToCache,
removeMultipleActivitiesFromCache,
};
};
18 changes: 18 additions & 0 deletions apps/web/src/hooks/queries/useActivities/dataTransforms.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import type { Activity } from "@/types/interfaces";

export const useDataTransforms = () => {
const mapActivities = (activities: Activity[]) => {
return activities
.map((activity: Activity) => ({
...activity,
date: new Date(activity.date),
}))
.sort((a: Activity, b: Activity) => {
return b.date.getTime() - a.date.getTime();
});
};

return {
mapActivities,
};
};
22 changes: 15 additions & 7 deletions apps/web/src/hooks/queries/useActivities/index.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
import { useMutation, useQuery } from "@tanstack/react-query";
import { useQueryKey } from "./queryKey";
import { useActivitiesRequests } from "./apiCalls";
import { useQueryClient } from "@tanstack/react-query";
import { useDataTransforms } from "./dataTransforms";
import { useCacheModifiers } from "./cacheModifiers";

export const useActivitiesQuery = (orgId: string) => {
const queryKey = useQueryKey(orgId);
const { mapActivities } = useDataTransforms();
const { activitiesQuery } = useActivitiesRequests(orgId);
const query = useQuery({ queryKey, queryFn: activitiesQuery });
return { ...query };
const query = useQuery({
queryKey,
queryFn: () => activitiesQuery().then(mapActivities),
});
return query;
};

export const useActivitiesMutations = (orgId: string) => {
const queryClient = useQueryClient();
const queryKey = useQueryKey(orgId);
const { addActivitiesToCache, removeMultipleActivitiesFromCache } =
useCacheModifiers(queryKey);
const {
createActivity: createActivityRequest,
deleteActivity: deleteActivityRequest,
Expand All @@ -31,17 +37,19 @@ export const useActivitiesMutations = (orgId: string) => {
description: string;
date: string;
}) => createActivityRequest(name, slug, description, date),
onSuccess: () => queryClient.invalidateQueries({ queryKey }),
onSuccess: (activity) => addActivitiesToCache([activity]),
});

const deleteActivity = useMutation({
mutationFn: deleteActivityRequest,
onSuccess: () => queryClient.invalidateQueries({ queryKey }),
onSuccess: (_, slug) =>
removeMultipleActivitiesFromCache([slug]),
});

const deleteMultipleActivities = useMutation({
mutationFn: deleteMultipleActivitiesRequest,
onSuccess: () => queryClient.invalidateQueries({ queryKey }),
onSuccess: (_, slugs) =>
removeMultipleActivitiesFromCache(slugs),
});

return {
Expand Down
17 changes: 10 additions & 7 deletions apps/web/src/hooks/queries/useAssistants/apiCalls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,21 @@ export const useAssistantsRequests = (orgId: string) => {
const addAssistant = async (
email: string,
role: UserType = UserType.VIEWER
): Promise<Assistant | undefined> => {
const res = await client.post(`${basePath}/${orgId}/user_courses`, {
email,
role,
});
) => {
const res = await client.post<Assistant>(
`${basePath}/${orgId}/user_courses`,
{
email,
role,
}
);
return res.data;
};

const addMultipleAssistants = async (
emails: string[],
role: UserType | undefined
): Promise<Assistant[] | undefined> => {
): Promise<Assistant[]> => {
if (!role) {
throw new Error("Role is required");
}
Expand All @@ -56,7 +59,7 @@ export const useAssistantsRequests = (orgId: string) => {
const removeAssistant = async (
email: string,
role: UserType = UserType.VIEWER
): Promise<Assistant | undefined> => {
): Promise<Assistant> => {
return await client.delete(`/api/v1/courses/${orgId}/user_courses`, {
data: { email, role },
});
Expand Down
26 changes: 26 additions & 0 deletions apps/web/src/hooks/queries/useAssistants/cacheModifiers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { useQueryClient } from "@tanstack/react-query";
import { useQueryKey } from "./queryKey";
import type { Assistant } from "@/types/interfaces";

export const useCacheModifiers = (queryKey: ReturnType<typeof useQueryKey>) => {
const queryClient = useQueryClient();

const addAssistantsToCache = (assistants: Assistant[]) => {
queryClient.setQueryData<Assistant[]>(queryKey, (data) => {
if (!data) return [...assistants];
return [...data, ...assistants];
});
};

const removeMultipleAssistantsFromCache = (emails: string[]) => {
const emailsSet = new Set(emails);
queryClient.setQueryData<Assistant[]>(queryKey, (data) => {
if (!data) return [];
return data.filter((assistant) => !emailsSet.has(assistant.email));
});
};
return {
addAssistantsToCache,
removeMultipleAssistantsFromCache,
};
};
16 changes: 9 additions & 7 deletions apps/web/src/hooks/queries/useAssistants/index.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
import { useMutation, useQuery } from "@tanstack/react-query";
import { useQueryKey } from "./queryKey";
import { useAssistantsRequests } from "./apiCalls";
import { useQueryClient } from "@tanstack/react-query";
import { UserType } from "@/types/enums";
import { useCacheModifiers } from "./cacheModifiers";

export const useAssistantsQuery = (orgId: string) => {
const queryKey = useQueryKey(orgId);
const { assistantsQuery } = useAssistantsRequests(orgId);
const query = useQuery({ queryKey, queryFn: assistantsQuery });
return { ...query };
return query;
};

export const useAssistantsMutations = (orgId: string) => {
const queryClient = useQueryClient();
const queryKey = useQueryKey(orgId);
const { addAssistantsToCache, removeMultipleAssistantsFromCache } =
useCacheModifiers(queryKey);
const {
addAssistant: addAssistantRequest,
addMultipleAssistants: addMultipleAssistantsRequest,
Expand All @@ -29,7 +30,7 @@ export const useAssistantsMutations = (orgId: string) => {
email: string;
role: UserType | undefined;
}) => addAssistantRequest(email, role),
onSuccess: () => queryClient.invalidateQueries({ queryKey }),
onSuccess: (assistant) => addAssistantsToCache([assistant]),
});

const addMultipleAssistants = useMutation({
Expand All @@ -40,7 +41,7 @@ export const useAssistantsMutations = (orgId: string) => {
emails: string[];
role: UserType | undefined;
}) => addMultipleAssistantsRequest(emails, role),
onSuccess: () => queryClient.invalidateQueries({ queryKey }),
onSuccess: (assistants) => addAssistantsToCache(assistants),
});

const removeAssistant = useMutation({
Expand All @@ -51,12 +52,13 @@ export const useAssistantsMutations = (orgId: string) => {
email: string;
role: UserType | undefined;
}) => removeAssistantRequest(email, role),
onSuccess: () => queryClient.invalidateQueries({ queryKey }),
onSuccess: (_, { email }) => removeMultipleAssistantsFromCache([email]),
});

const removeMultipleAssistants = useMutation({
mutationFn: removeMultipleAssistantsRequest,
onSuccess: () => queryClient.invalidateQueries({ queryKey }),
onSuccess: (_, users) =>
removeMultipleAssistantsFromCache(users.map((user) => user.email)),
});

return {
Expand Down
4 changes: 2 additions & 2 deletions apps/web/src/hooks/queries/useOrg/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export const useOrgQuery = (orgId: string) => {
const queryKey = useQueryKey(orgId);
const { orgQuery } = useOrgRequests(orgId);
const query = useQuery({ queryKey, queryFn: orgQuery });
return { ...query };
return query;
};

export const useUserPermissionsOrgQuery = (orgId: string) => {
Expand All @@ -16,5 +16,5 @@ export const useUserPermissionsOrgQuery = (orgId: string) => {
queryKey,
queryFn: () => userPermissionsOrgQuery(),
});
return { ...query };
return query;
};
3 changes: 2 additions & 1 deletion apps/web/src/hooks/queries/useOrgs/apiCalls.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import client from "@/api/client";
import { UserType } from "@/types/enums";
import type { Org } from "@/types/interfaces";

const basePath = "api/v1/courses";

Expand All @@ -16,7 +17,7 @@ export const useOrgsRequests = () => {
};

const orgsQuery = async () => {
const res = await client.get(`${basePath}/`);
const res = await client.get<{ courses: Org[] }>(`${basePath}/`);
return res.data.courses;
};

Expand Down
26 changes: 26 additions & 0 deletions apps/web/src/hooks/queries/useOrgs/cacheModifiers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { useQueryClient } from "@tanstack/react-query";
import { useQueryKey } from "./queryKey";
import type { Org } from "@/types/interfaces";

export const useCacheModifiers = (queryKey: ReturnType<typeof useQueryKey>) => {
const queryClient = useQueryClient();

const addOrgToCache = (org: Org) => {
queryClient.setQueryData<Org[]>(queryKey, (data) => {
if (!data) return [org];
return [...data, org];
});
};

const removeOrgFromCache = (orgId: string) => {
queryClient.setQueryData<Org[]>(queryKey, (data) => {
if (!data) return [];
return data.filter((org) => org.id !== orgId);
});
};

return {
addOrgToCache,
removeOrgFromCache,
};
};
10 changes: 5 additions & 5 deletions apps/web/src/hooks/queries/useOrgs/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,29 @@ import type { CreateOrg } from "@/types/interfaces";
import { useMutation, useQuery } from "@tanstack/react-query";
import { useQueryKey } from "./queryKey";
import { useOrgsRequests } from "./apiCalls";
import { useQueryClient } from "@tanstack/react-query";
import { useCacheModifiers } from "./cacheModifiers";

export const useOrgsQuery = () => {
const queryKey = useQueryKey();
const { orgsQuery } = useOrgsRequests();
const query = useQuery({ queryKey, queryFn: orgsQuery });
return { ...query };
return query;
};

export const useOrgsMutations = () => {
const queryClient = useQueryClient();
const queryKey = useQueryKey();
const { addOrgToCache, removeOrgFromCache } = useCacheModifiers(queryKey);
const { createOrg: createOrgRequest, deleteOrg: deleteOrgRequest } =
useOrgsRequests();

const createOrg = useMutation({
mutationFn: (org: CreateOrg) => createOrgRequest(org.name, org.slug),
onSuccess: () => queryClient.invalidateQueries({ queryKey }),
onSuccess: (org) => addOrgToCache(org),
});

const deleteOrg = useMutation({
mutationFn: deleteOrgRequest,
onSuccess: () => queryClient.invalidateQueries({ queryKey }),
onSuccess: (_, orgId) => removeOrgFromCache(orgId),
});

return { createOrg, deleteOrg };
Expand Down
13 changes: 7 additions & 6 deletions apps/web/src/hooks/queries/useStudents/apiCalls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export const useStudentsRequests = (orgId: string) => {
const createStudent = async (
studentCodes: string[],
displayName: string | undefined
): Promise<Student> => {
) => {
const studentIds = await Promise.all(
studentCodes.map(
(studentCode: string): Promise<string> => clientHash(studentCode, orgId)
Expand All @@ -23,13 +23,14 @@ export const useStudentsRequests = (orgId: string) => {
if (displayName !== "") {
body = { ...body, display_name: displayName };
}
const res = await client.post(`${basePath}/${orgId}/students/`, body);
const res = await client.post<{ student: Student }>(
`${basePath}/${orgId}/students/`,
body
);
return res.data.student;
};

const createMultipleStudents = async (
students: CreateStudent[]
): Promise<Student[]> => {
const createMultipleStudents = async (students: CreateStudent[]) => {
const studentsWithHash = await Promise.all(
students.map(
async (student: CreateStudent): Promise<CreateStudent> => ({
Expand All @@ -43,7 +44,7 @@ export const useStudentsRequests = (orgId: string) => {
})
)
);
const res = await client.post(
const res = await client.post<{ students: Student[] }>(
`${basePath}/${orgId}/students/batch_create`,
{
students: studentsWithHash,
Expand Down
18 changes: 18 additions & 0 deletions apps/web/src/hooks/queries/useStudents/cacheModifiers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { useQueryClient } from "@tanstack/react-query";
import { useQueryKey } from "./queryKey";
import type { Student } from "@/types/interfaces";

export const useCacheModifiers = (queryKey: ReturnType<typeof useQueryKey>) => {
const queryClient = useQueryClient();

const addStudentsToCache = (students: Student[]) => {
queryClient.setQueryData<Student[]>(queryKey, (data) => {
if (!data) return [...students];
return [...data, ...students];
});
};

return {
addStudentsToCache,
};
};
Loading