From 7f2560e1e3578edb95166c645bf4b6f264e97b23 Mon Sep 17 00:00:00 2001 From: Nafees Nazik <84864519+G3root@users.noreply.github.com> Date: Wed, 19 Oct 2022 01:04:01 +0530 Subject: [PATCH] feat: add optimistic updates for deleting and changing hidden status of event types. (#4721) * fix: remove loading state * feat: use optimistic update for deleting * feat: use optimistic update for hiding * Moved PR changes Co-authored-by: Peer Richelsen Co-authored-by: zomars --- apps/web/pages/event-types/index.tsx | 60 +++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 9 deletions(-) diff --git a/apps/web/pages/event-types/index.tsx b/apps/web/pages/event-types/index.tsx index 332bfc3297..beb6b3695f 100644 --- a/apps/web/pages/event-types/index.tsx +++ b/apps/web/pages/event-types/index.tsx @@ -98,13 +98,34 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL }); const setHiddenMutation = trpc.useMutation("viewer.eventTypes.update", { - onError: async (err) => { - console.error(err.message); + onMutate: async ({ id }) => { await utils.cancelQuery(["viewer.eventTypes"]); - await utils.invalidateQueries(["viewer.eventTypes"]); + const previousValue = utils.getQueryData(["viewer.eventTypes"]); + if (previousValue) { + const newList = [...types]; + const itemIndex = newList.findIndex((item) => item.id === id); + if (itemIndex !== -1 && newList[itemIndex]) { + newList[itemIndex].hidden = !newList[itemIndex].hidden; + } + utils.setQueryData(["viewer.eventTypes"], { + ...previousValue, + eventTypeGroups: [ + ...previousValue.eventTypeGroups.slice(0, groupIndex), + { ...group, eventTypes: newList }, + ...previousValue.eventTypeGroups.slice(groupIndex + 1), + ], + }); + } + return { previousValue }; }, - onSettled: async () => { - await utils.invalidateQueries(["viewer.eventTypes"]); + onError: async (err, _, context) => { + if (context?.previousValue) { + utils.setQueryData(["viewer.eventTypes"], context.previousValue); + } + console.error(err.message); + }, + onSettled: () => { + utils.invalidateQueries(["viewer.eventTypes"]); }, }); @@ -169,12 +190,31 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL }; const deleteMutation = trpc.useMutation("viewer.eventTypes.delete", { - onSuccess: async () => { - await utils.invalidateQueries(["viewer.eventTypes"]); + onSuccess: () => { showToast(t("event_type_deleted_successfully"), "success"); setDeleteDialogOpen(false); }, - onError: (err) => { + onMutate: async ({ id }) => { + await utils.cancelQuery(["viewer.eventTypes"]); + const previousValue = utils.getQueryData(["viewer.eventTypes"]); + if (previousValue) { + const newList = types.filter((item) => item.id !== id); + + utils.setQueryData(["viewer.eventTypes"], { + ...previousValue, + eventTypeGroups: [ + ...previousValue.eventTypeGroups.slice(0, groupIndex), + { ...group, eventTypes: newList }, + ...previousValue.eventTypeGroups.slice(groupIndex + 1), + ], + }); + } + return { previousValue }; + }, + onError: (err, _, context) => { + if (context?.previousValue) { + utils.setQueryData(["viewer.eventTypes"], context.previousValue); + } if (err instanceof HttpError) { const message = `${err.statusCode}: ${err.message}`; showToast(message, "error"); @@ -183,6 +223,9 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL showToast(err.message, "error"); } }, + onSettled: () => { + utils.invalidateQueries(["viewer.eventTypes"]); + }, }); const [isNativeShare, setNativeShare] = useState(true); @@ -439,7 +482,6 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL