feat(roles): implement roles core architecture

- Add comprehensive role and permission models
- Add all CRUD API request functions
- Add custom hooks with React Query integration
- Support role permissions management
- Follow established development pattern
This commit is contained in:
hosseintaromi 2025-07-18 14:02:53 +03:30
parent 50f596c999
commit efb92ac136
3 changed files with 273 additions and 0 deletions

View File

@ -0,0 +1,147 @@
import { QUERY_KEYS } from "@/utils/query-key";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import {
getRoles,
getRole,
createRole,
updateRole,
deleteRole,
getRolePermissions,
assignPermissionToRole,
removePermissionFromRole,
getAllPermissions,
} from "./_requests";
import { CreateRoleRequest, UpdateRoleRequest } from "./_models";
import { Role } from "@/types/auth";
import toast from "react-hot-toast";
export const useRoles = () => {
return useQuery({
queryKey: [QUERY_KEYS.GET_ROLES],
queryFn: () => getRoles(),
});
};
export const useRole = (id: string) => {
return useQuery({
queryKey: [QUERY_KEYS.GET_ROLE, id],
queryFn: () => getRole(id),
enabled: !!id,
});
};
export const useCreateRole = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (roleData: CreateRoleRequest) => createRole(roleData),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: [QUERY_KEYS.GET_ROLES] });
toast.success("نقش با موفقیت ایجاد شد");
},
onError: (error: any) => {
toast.error(error?.message || "خطا در ایجاد نقش");
},
});
};
export const useUpdateRole = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (data: UpdateRoleRequest) =>
updateRole(data.id.toString(), data),
onSuccess: (data: Role) => {
queryClient.invalidateQueries({ queryKey: [QUERY_KEYS.GET_ROLES] });
queryClient.invalidateQueries({
queryKey: [QUERY_KEYS.GET_ROLE, data.id.toString()],
});
toast.success("نقش با موفقیت به‌روزرسانی شد");
},
onError: (error: any) => {
toast.error(error?.message || "خطا در به‌روزرسانی نقش");
},
});
};
export const useDeleteRole = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (id: string) => deleteRole(id),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: [QUERY_KEYS.GET_ROLES] });
toast.success("نقش با موفقیت حذف شد");
},
onError: (error: any) => {
toast.error(error?.message || "خطا در حذف نقش");
},
});
};
export const useRolePermissions = (id: string) => {
return useQuery({
queryKey: [QUERY_KEYS.GET_ROLE_PERMISSIONS, id],
queryFn: () => getRolePermissions(id),
enabled: !!id,
});
};
export const useAssignPermission = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: ({
roleId,
permissionId,
}: {
roleId: string;
permissionId: string;
}) => assignPermissionToRole(roleId, permissionId),
onSuccess: (_, variables) => {
queryClient.invalidateQueries({
queryKey: [QUERY_KEYS.GET_ROLE_PERMISSIONS, variables.roleId],
});
queryClient.invalidateQueries({
queryKey: [QUERY_KEYS.GET_ROLE, variables.roleId],
});
toast.success("دسترسی با موفقیت اختصاص داده شد");
},
onError: (error: any) => {
toast.error(error?.message || "خطا در اختصاص دسترسی");
},
});
};
export const useRemovePermission = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: ({
roleId,
permissionId,
}: {
roleId: string;
permissionId: string;
}) => removePermissionFromRole(roleId, permissionId),
onSuccess: (_, variables) => {
queryClient.invalidateQueries({
queryKey: [QUERY_KEYS.GET_ROLE_PERMISSIONS, variables.roleId],
});
queryClient.invalidateQueries({
queryKey: [QUERY_KEYS.GET_ROLE, variables.roleId],
});
toast.success("دسترسی با موفقیت حذف شد");
},
onError: (error: any) => {
toast.error(error?.message || "خطا در حذف دسترسی");
},
});
};
export const usePermissions = () => {
return useQuery({
queryKey: [QUERY_KEYS.GET_PERMISSIONS],
queryFn: () => getAllPermissions(),
});
};

View File

@ -0,0 +1,39 @@
import { Role, Permission } from "@/types/auth";
export interface CreateRoleRequest {
title: string;
description: string;
}
export interface UpdateRoleRequest {
id: number;
title: string;
description: string;
}
export interface RoleWithPermissions extends Role {
permissions: Permission[];
}
export interface RolePermissionsResponse {
permissions: Permission[];
}
export interface AssignPermissionResponse {
message: string;
}
export interface DeleteRoleResponse {
message: string;
}
export interface RoleFormData {
title: string;
description: string;
}
export type Response<T> = {
data: T;
message?: string;
success?: boolean;
};

View File

@ -0,0 +1,87 @@
import {
APIUrlGenerator,
httpGetRequest,
httpPostRequest,
httpPutRequest,
httpDeleteRequest,
} from "@/utils/baseHttpService";
import { API_ROUTES } from "@/constant/routes";
import { Role, Permission } from "@/types/auth";
import {
CreateRoleRequest,
UpdateRoleRequest,
DeleteRoleResponse,
AssignPermissionResponse,
} from "./_models";
export const getRoles = async () => {
const response = await httpGetRequest<Role[]>(
APIUrlGenerator(API_ROUTES.GET_ROLES)
);
return response.data;
};
export const getRole = async (id: string) => {
const response = await httpGetRequest<Role>(
APIUrlGenerator(API_ROUTES.GET_ROLE(id))
);
return response.data;
};
export const createRole = async (roleData: CreateRoleRequest) => {
const response = await httpPostRequest<Role>(
APIUrlGenerator(API_ROUTES.CREATE_ROLE),
roleData
);
return response.data;
};
export const updateRole = async (id: string, roleData: UpdateRoleRequest) => {
const response = await httpPutRequest<Role>(
APIUrlGenerator(API_ROUTES.UPDATE_ROLE(id)),
roleData
);
return response.data;
};
export const deleteRole = async (id: string) => {
const response = await httpDeleteRequest<DeleteRoleResponse>(
APIUrlGenerator(API_ROUTES.DELETE_ROLE(id))
);
return response.data;
};
export const getRolePermissions = async (id: string) => {
const response = await httpGetRequest<Permission[]>(
APIUrlGenerator(API_ROUTES.GET_ROLE_PERMISSIONS(id))
);
return response.data;
};
export const assignPermissionToRole = async (
roleId: string,
permissionId: string
) => {
const response = await httpPostRequest<AssignPermissionResponse>(
APIUrlGenerator(API_ROUTES.ASSIGN_ROLE_PERMISSION(roleId, permissionId)),
{}
);
return response.data;
};
export const removePermissionFromRole = async (
roleId: string,
permissionId: string
) => {
const response = await httpDeleteRequest<AssignPermissionResponse>(
APIUrlGenerator(API_ROUTES.REMOVE_ROLE_PERMISSION(roleId, permissionId))
);
return response.data;
};
export const getAllPermissions = async () => {
const response = await httpGetRequest<Permission[]>(
APIUrlGenerator(API_ROUTES.GET_PERMISSIONS)
);
return response.data;
};