diff --git a/adminfront/src/features/tenants/routes/TenantFineGrainedPermissionsPage.tsx b/adminfront/src/features/tenants/routes/TenantFineGrainedPermissionsPage.tsx index dc47f741..7542716f 100644 --- a/adminfront/src/features/tenants/routes/TenantFineGrainedPermissionsPage.tsx +++ b/adminfront/src/features/tenants/routes/TenantFineGrainedPermissionsPage.tsx @@ -75,24 +75,74 @@ export function TenantFineGrainedPermissionsPage() { const addSystemRelationMutation = useMutation({ mutationFn: (payload: { userId: string; relation: string }) => addSystemRelation(payload.userId, payload.relation), + onMutate: async (newRelation) => { + await queryClient.cancelQueries({ queryKey: ["system-relations"] }); + const previousRelations = queryClient.getQueryData(["system-relations"]); + + queryClient.setQueryData(["system-relations"], (old) => { + if (!old) return []; + return old.map((user) => { + if (user.userId === newRelation.userId) { + return { + ...user, + relations: user.relations.includes(newRelation.relation) + ? user.relations + : [...user.relations, newRelation.relation], + }; + } + return user; + }); + }); + + return { previousRelations }; + }, + onError: (err: AxiosError<{ error?: string }>, _, context) => { + if (context?.previousRelations) { + queryClient.setQueryData(["system-relations"], context.previousRelations); + } + toast.error(err.response?.data?.error || t("msg.common.error", "오류가 발생했습니다.")); + }, onSuccess: () => { - queryClient.invalidateQueries({ queryKey: ["system-relations"] }); toast.success(t("msg.admin.system.relations.add_success", "시스템 메뉴 권한이 추가되었습니다.")); }, - onError: (err: AxiosError<{ error?: string }>) => { - toast.error(err.response?.data?.error || t("msg.common.error", "오류가 발생했습니다.")); + onSettled: () => { + queryClient.invalidateQueries({ queryKey: ["system-relations"] }); }, }); const removeSystemRelationMutation = useMutation({ mutationFn: (payload: { userId: string; relation: string }) => removeSystemRelation(payload.userId, payload.relation), + onMutate: async (targetRelation) => { + await queryClient.cancelQueries({ queryKey: ["system-relations"] }); + const previousRelations = queryClient.getQueryData(["system-relations"]); + + queryClient.setQueryData(["system-relations"], (old) => { + if (!old) return []; + return old.map((user) => { + if (user.userId === targetRelation.userId) { + return { + ...user, + relations: user.relations.filter((r) => r !== targetRelation.relation), + }; + } + return user; + }); + }); + + return { previousRelations }; + }, + onError: (err: AxiosError<{ error?: string }>, _, context) => { + if (context?.previousRelations) { + queryClient.setQueryData(["system-relations"], context.previousRelations); + } + toast.error(err.response?.data?.error || t("msg.common.error", "오류가 발생했습니다.")); + }, onSuccess: () => { - queryClient.invalidateQueries({ queryKey: ["system-relations"] }); toast.success(t("msg.admin.system.relations.remove_success", "시스템 메뉴 권한이 회수되었습니다.")); }, - onError: (err: AxiosError<{ error?: string }>) => { - toast.error(err.response?.data?.error || t("msg.common.error", "오류가 발생했습니다.")); + onSettled: () => { + queryClient.invalidateQueries({ queryKey: ["system-relations"] }); }, }); diff --git a/adminfront/src/features/tenants/routes/TenantFineGrainedPermissionsTab.tsx b/adminfront/src/features/tenants/routes/TenantFineGrainedPermissionsTab.tsx index 9f801e8a..7c4eac3d 100644 --- a/adminfront/src/features/tenants/routes/TenantFineGrainedPermissionsTab.tsx +++ b/adminfront/src/features/tenants/routes/TenantFineGrainedPermissionsTab.tsx @@ -68,24 +68,74 @@ export function TenantFineGrainedPermissionsTab({ tenantIdProp }: TenantFineGrai const addRelationMutation = useMutation({ mutationFn: (payload: { userId: string; relation: string }) => addTenantRelation(tenantId, payload.userId, payload.relation), + onMutate: async (newRelation) => { + await queryClient.cancelQueries({ queryKey: ["tenant-relations", tenantId] }); + const previousRelations = queryClient.getQueryData(["tenant-relations", tenantId]); + + queryClient.setQueryData(["tenant-relations", tenantId], (old) => { + if (!old) return []; + return old.map((user) => { + if (user.userId === newRelation.userId) { + return { + ...user, + relations: user.relations.includes(newRelation.relation) + ? user.relations + : [...user.relations, newRelation.relation], + }; + } + return user; + }); + }); + + return { previousRelations }; + }, + onError: (err: AxiosError<{ error?: string }>, _, context) => { + if (context?.previousRelations) { + queryClient.setQueryData(["tenant-relations", tenantId], context.previousRelations); + } + toast.error(err.response?.data?.error || t("msg.common.error", "오류가 발생했습니다.")); + }, onSuccess: () => { - queryClient.invalidateQueries({ queryKey: ["tenant-relations", tenantId] }); toast.success(t("msg.admin.tenants.relations.add_success", "세부 권한이 추가되었습니다.")); }, - onError: (err: AxiosError<{ error?: string }>) => { - toast.error(err.response?.data?.error || t("msg.common.error", "오류가 발생했습니다.")); + onSettled: () => { + queryClient.invalidateQueries({ queryKey: ["tenant-relations", tenantId] }); }, }); const removeRelationMutation = useMutation({ mutationFn: (payload: { userId: string; relation: string }) => removeTenantRelation(tenantId, payload.userId, payload.relation), + onMutate: async (targetRelation) => { + await queryClient.cancelQueries({ queryKey: ["tenant-relations", tenantId] }); + const previousRelations = queryClient.getQueryData(["tenant-relations", tenantId]); + + queryClient.setQueryData(["tenant-relations", tenantId], (old) => { + if (!old) return []; + return old.map((user) => { + if (user.userId === targetRelation.userId) { + return { + ...user, + relations: user.relations.filter((r) => r !== targetRelation.relation), + }; + } + return user; + }); + }); + + return { previousRelations }; + }, + onError: (err: AxiosError<{ error?: string }>, _, context) => { + if (context?.previousRelations) { + queryClient.setQueryData(["tenant-relations", tenantId], context.previousRelations); + } + toast.error(err.response?.data?.error || t("msg.common.error", "오류가 발생했습니다.")); + }, onSuccess: () => { - queryClient.invalidateQueries({ queryKey: ["tenant-relations", tenantId] }); toast.success(t("msg.admin.tenants.relations.remove_success", "세부 권한이 회수되었습니다.")); }, - onError: (err: AxiosError<{ error?: string }>) => { - toast.error(err.response?.data?.error || t("msg.common.error", "오류가 발생했습니다.")); + onSettled: () => { + queryClient.invalidateQueries({ queryKey: ["tenant-relations", tenantId] }); }, });