main
Some checks failed
UI Deploy (Next-Auth Support) 🎨 / build-and-deploy (push) Failing after 2m42s

This commit is contained in:
2026-01-27 23:24:17 +03:00
commit dc7ed1c48c
165 changed files with 23798 additions and 0 deletions

View File

@@ -0,0 +1,30 @@
import { apiRequest } from "@/lib/api/api-service";
import { ApiResponse } from "@/types/api-response";
import { PermissionResponseDto, CreatePermissionDto } from "./types";
/**
* Admin Permissions Service - Example Implementation
* Matches Backend: /api/admin/permissions/*
*/
const getAll = () => {
return apiRequest<ApiResponse<PermissionResponseDto[]>>({
url: "/admin/permissions",
client: "admin",
method: "get",
});
};
const create = (data: CreatePermissionDto) => {
return apiRequest<ApiResponse<PermissionResponseDto>>({
url: "/admin/permissions",
client: "admin",
method: "post",
data,
});
};
export const adminPermissionsService = {
getAll,
create,
};

View File

@@ -0,0 +1,18 @@
// Permission DTOs - Matches Backend
export interface PermissionResponseDto {
id: string;
name: string;
description?: string;
resource: string;
action: string;
createdAt: string;
updatedAt: string;
}
// Create Permission
export interface CreatePermissionDto {
name: string;
description?: string;
resource: string;
action: string;
}

View File

@@ -0,0 +1,40 @@
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { ApiResponse } from "@/types/api-response";
import { adminPermissionsService } from "./service";
import { PermissionResponseDto, CreatePermissionDto } from "./types";
export const AdminPermissionsQueryKeys = {
all: ["admin-permissions"] as const,
list: () => [...AdminPermissionsQueryKeys.all, "list"] as const,
};
export function useGetAllPermissions() {
const queryKey = AdminPermissionsQueryKeys.list();
const { data, ...rest } = useQuery<ApiResponse<PermissionResponseDto[]>>({
queryKey: queryKey,
queryFn: adminPermissionsService.getAll,
});
return { data: data?.data, ...rest };
}
export function useCreatePermission() {
const queryClient = useQueryClient();
const { data, ...rest } = useMutation<
ApiResponse<PermissionResponseDto>,
Error,
CreatePermissionDto
>({
mutationFn: (permissionData) =>
adminPermissionsService.create(permissionData),
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: AdminPermissionsQueryKeys.all,
});
},
});
return { data: data?.data, ...rest };
}

View File

@@ -0,0 +1,72 @@
import { apiRequest } from "@/lib/api/api-service";
import { ApiResponse } from "@/types/api-response";
import {
RoleResponseDto,
CreateRoleDto,
UpdateRoleDto,
RolePermissionResponseDto,
} from "./types";
/**
* Admin Roles Service - Example Implementation
* Matches Backend: /api/admin/roles/*
*/
const getAll = () => {
return apiRequest<ApiResponse<RoleResponseDto[]>>({
url: "/admin/roles",
client: "admin",
method: "get",
});
};
const create = (data: CreateRoleDto) => {
return apiRequest<ApiResponse<RoleResponseDto>>({
url: "/admin/roles",
client: "admin",
method: "post",
data,
});
};
const update = (roleId: string, data: UpdateRoleDto) => {
return apiRequest<ApiResponse<RoleResponseDto>>({
url: `/admin/roles/${roleId}`,
client: "admin",
method: "put",
data,
});
};
const remove = (roleId: string) => {
return apiRequest<ApiResponse<null>>({
url: `/admin/roles/${roleId}`,
client: "admin",
method: "delete",
});
};
const assignPermission = (roleId: string, permissionId: string) => {
return apiRequest<ApiResponse<RolePermissionResponseDto>>({
url: `/admin/roles/${roleId}/permissions/${permissionId}`,
client: "admin",
method: "post",
});
};
const removePermission = (roleId: string, permissionId: string) => {
return apiRequest<ApiResponse<null>>({
url: `/admin/roles/${roleId}/permissions/${permissionId}`,
client: "admin",
method: "delete",
});
};
export const adminRolesService = {
getAll,
create,
update,
remove,
assignPermission,
removePermission,
};

View File

@@ -0,0 +1,38 @@
// Role DTOs - Matches Backend
export interface RoleResponseDto {
id: string;
name: string;
description?: string;
permissions: PermissionInfo[];
_count?: {
users: number;
};
createdAt: string;
updatedAt: string;
}
export interface PermissionInfo {
id: string;
name: string;
resource: string;
action: string;
}
// Create/Update Role
export interface CreateRoleDto {
name: string;
description?: string;
}
export interface UpdateRoleDto {
name?: string;
description?: string;
}
// Role Permission Assignment
export interface RolePermissionResponseDto {
id: string;
roleId: string;
permissionId: string;
createdAt: string;
}

View File

@@ -0,0 +1,112 @@
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { ApiResponse } from "@/types/api-response";
import { adminRolesService } from "./service";
import {
RoleResponseDto,
CreateRoleDto,
UpdateRoleDto,
RolePermissionResponseDto,
} from "./types";
export const AdminRolesQueryKeys = {
all: ["admin-roles"] as const,
list: () => [...AdminRolesQueryKeys.all, "list"] as const,
};
export function useGetAllRoles() {
const queryKey = AdminRolesQueryKeys.list();
const { data, ...rest } = useQuery<ApiResponse<RoleResponseDto[]>>({
queryKey: queryKey,
queryFn: adminRolesService.getAll,
});
return { data: data?.data, ...rest };
}
export function useCreateRole() {
const queryClient = useQueryClient();
const { data, ...rest } = useMutation<
ApiResponse<RoleResponseDto>,
Error,
CreateRoleDto
>({
mutationFn: (roleData) => adminRolesService.create(roleData),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: AdminRolesQueryKeys.all });
},
});
return { data: data?.data, ...rest };
}
export function useUpdateRole() {
const queryClient = useQueryClient();
const { data, ...rest } = useMutation<
ApiResponse<RoleResponseDto>,
Error,
{ roleId: string; data: UpdateRoleDto }
>({
mutationFn: ({ roleId, data }) => adminRolesService.update(roleId, data),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: AdminRolesQueryKeys.all });
},
});
return { data: data?.data, ...rest };
}
export function useDeleteRole() {
const queryClient = useQueryClient();
const { data, ...rest } = useMutation<
ApiResponse<null>,
Error,
{ roleId: string }
>({
mutationFn: ({ roleId }) => adminRolesService.remove(roleId),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: AdminRolesQueryKeys.all });
},
});
return { data: data?.data, ...rest };
}
export function useAssignPermission() {
const queryClient = useQueryClient();
const { data, ...rest } = useMutation<
ApiResponse<RolePermissionResponseDto>,
Error,
{ roleId: string; permissionId: string }
>({
mutationFn: ({ roleId, permissionId }) =>
adminRolesService.assignPermission(roleId, permissionId),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: AdminRolesQueryKeys.all });
},
});
return { data: data?.data, ...rest };
}
export function useRemovePermission() {
const queryClient = useQueryClient();
const { data, ...rest } = useMutation<
ApiResponse<null>,
Error,
{ roleId: string; permissionId: string }
>({
mutationFn: ({ roleId, permissionId }) =>
adminRolesService.removePermission(roleId, permissionId),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: AdminRolesQueryKeys.all });
},
});
return { data: data?.data, ...rest };
}

View File

@@ -0,0 +1,53 @@
import { apiRequest } from "@/lib/api/api-service";
import { ApiResponse } from "@/types/api-response";
import { UserResponseDto } from "@/types/user";
import {
UsersQueryParams,
PaginatedUsersResponse,
UserRoleResponseDto,
} from "./types";
/**
* Admin Users Service - Example Implementation
* Matches Backend: /api/admin/users/*
*/
const getAll = (params?: UsersQueryParams) => {
return apiRequest<ApiResponse<PaginatedUsersResponse>>({
url: "/admin/users",
client: "admin",
method: "get",
params,
});
};
const toggleActive = (userId: string) => {
return apiRequest<ApiResponse<UserResponseDto>>({
url: `/admin/users/${userId}/toggle-active`,
client: "admin",
method: "put",
});
};
const assignRole = (userId: string, roleId: string) => {
return apiRequest<ApiResponse<UserRoleResponseDto>>({
url: `/admin/users/${userId}/roles/${roleId}`,
client: "admin",
method: "post",
});
};
const removeRole = (userId: string, roleId: string) => {
return apiRequest<ApiResponse<null>>({
url: `/admin/users/${userId}/roles/${roleId}`,
client: "admin",
method: "delete",
});
};
export const adminUsersService = {
getAll,
toggleActive,
assignRole,
removeRole,
};

View File

@@ -0,0 +1,18 @@
import { PaginatedData, PaginationDto } from "@/types/api-response";
import { UserResponseDto } from "../../users/types";
export type { UserResponseDto };
export type { PaginationDto };
// User Role Assignment
export interface UserRoleResponseDto {
id: string;
userId: string;
roleId: string;
createdAt: string;
}
// Pagination params
export type UsersQueryParams = PaginationDto;
// Response type for paginated users
export type PaginatedUsersResponse = PaginatedData<UserResponseDto>;

View File

@@ -0,0 +1,79 @@
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { ApiResponse } from "@/types/api-response";
import { adminUsersService } from "./service";
import {
UserRoleResponseDto,
UsersQueryParams,
PaginatedUsersResponse,
} from "./types";
import { UserResponseDto } from "@/types/user";
export const AdminUsersQueryKeys = {
all: ["admin-users"] as const,
list: (params?: UsersQueryParams) =>
[...AdminUsersQueryKeys.all, "list", params] as const,
};
export function useGetAllUsers(params?: UsersQueryParams) {
const queryKey = AdminUsersQueryKeys.list(params);
const { data, ...rest } = useQuery<ApiResponse<PaginatedUsersResponse>>({
queryKey: queryKey,
queryFn: () => adminUsersService.getAll(params),
});
return { data: data?.data, ...rest };
}
export function useToggleUserActive() {
const queryClient = useQueryClient();
const { data, ...rest } = useMutation<
ApiResponse<UserResponseDto>,
Error,
{ userId: string }
>({
mutationFn: ({ userId }) => adminUsersService.toggleActive(userId),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: AdminUsersQueryKeys.all });
},
});
return { data: data?.data, ...rest };
}
export function useAssignRole() {
const queryClient = useQueryClient();
const { data, ...rest } = useMutation<
ApiResponse<UserRoleResponseDto>,
Error,
{ userId: string; roleId: string }
>({
mutationFn: ({ userId, roleId }) =>
adminUsersService.assignRole(userId, roleId),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: AdminUsersQueryKeys.all });
},
});
return { data: data?.data, ...rest };
}
export function useRemoveRole() {
const queryClient = useQueryClient();
const { data, ...rest } = useMutation<
ApiResponse<null>,
Error,
{ userId: string; roleId: string }
>({
mutationFn: ({ userId, roleId }) =>
adminUsersService.removeRole(userId, roleId),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: AdminUsersQueryKeys.all });
},
});
return { data: data?.data, ...rest };
}

View File

@@ -0,0 +1,50 @@
import { apiRequest } from "@/lib/api/api-service";
import { ApiResponse } from "@/types/api-response";
import { LoginDto, RegisterDto, RefreshTokenDto, AuthResponse } from "./types";
/**
* Auth Service - Example Implementation
* Matches Backend: /api/auth/*
*/
const login = (data: LoginDto) => {
return apiRequest<ApiResponse<AuthResponse>>({
url: "/auth/login",
client: "auth",
method: "post",
data,
});
};
const register = (data: RegisterDto) => {
return apiRequest<ApiResponse<AuthResponse>>({
url: "/auth/register",
client: "auth",
method: "post",
data,
});
};
const refreshToken = (data: RefreshTokenDto) => {
return apiRequest<ApiResponse<AuthResponse>>({
url: "/auth/refresh",
client: "auth",
method: "post",
data,
});
};
const logout = () => {
return apiRequest<ApiResponse<null>>({
url: "/auth/logout",
client: "auth",
method: "post",
});
};
export const authService = {
login,
register,
refreshToken,
logout,
};

View File

@@ -0,0 +1,32 @@
// Auth Request DTOs
export interface LoginDto {
email: string;
password: string;
}
export interface RegisterDto {
email: string;
password: string;
firstName: string;
lastName: string;
username?: string;
}
export interface RefreshTokenDto {
refreshToken: string;
}
// Auth Response DTOs
export interface AuthResponse {
accessToken: string;
refreshToken: string;
expiresIn: number;
user: {
id: string;
email: string;
firstName: string;
lastName: string;
isActive?: boolean;
roles: string[];
};
}

View File

@@ -0,0 +1,64 @@
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { ApiResponse } from "@/types/api-response";
import { authService } from "./service";
import { LoginDto, RegisterDto, RefreshTokenDto, AuthResponse } from "./types";
export const AuthQueryKeys = {
all: ["auth"] as const,
session: () => [...AuthQueryKeys.all, "session"] as const,
};
export function useLogin() {
const queryClient = useQueryClient();
const { data, ...rest } = useMutation<
ApiResponse<AuthResponse>,
Error,
LoginDto
>({
mutationFn: (credentials: LoginDto) => authService.login(credentials),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: AuthQueryKeys.session() });
},
});
return { data: data?.data, ...rest };
}
export function useRegister() {
const { data, ...rest } = useMutation<
ApiResponse<AuthResponse>,
Error,
RegisterDto
>({
mutationFn: (userData: RegisterDto) => authService.register(userData),
});
return { data: data?.data, ...rest };
}
export function useRefreshToken() {
const { data, ...rest } = useMutation<
ApiResponse<AuthResponse>,
Error,
RefreshTokenDto
>({
mutationFn: (tokenData: RefreshTokenDto) =>
authService.refreshToken(tokenData),
});
return { data: data?.data, ...rest };
}
export function useLogout() {
const queryClient = useQueryClient();
const { data, ...rest } = useMutation<ApiResponse<null>, Error, void>({
mutationFn: () => authService.logout(),
onSuccess: () => {
queryClient.clear();
},
});
return { data: data?.data, ...rest };
}

View File

@@ -0,0 +1,86 @@
/**
* Example API Services - Barrel Export
* Import all services and hooks from this single file
*
* Usage:
* import { authService, useLogin, adminRolesService, useGetAllRoles } from '@/lib/api/Example';
*/
// Services
export { authService } from "./auth/service";
export { usersService } from "./users/service";
export { adminUsersService } from "./admin/users/service";
export { adminRolesService } from "./admin/roles/service";
export { adminPermissionsService } from "./admin/permissions/service";
// Hooks - Auth
export {
useLogin,
useRegister,
useRefreshToken,
useLogout,
AuthQueryKeys,
} from "./auth/use-hooks";
// Hooks - Users
export { useGetMe, UsersQueryKeys } from "./users/use-hooks";
// Hooks - Admin Users
export {
useGetAllUsers,
useToggleUserActive,
useAssignRole,
useRemoveRole,
AdminUsersQueryKeys,
} from "./admin/users/use-hooks";
// Hooks - Admin Roles
export {
useGetAllRoles,
useCreateRole,
useUpdateRole,
useDeleteRole,
useAssignPermission,
useRemovePermission,
AdminRolesQueryKeys,
} from "./admin/roles/use-hooks";
// Hooks - Admin Permissions
export {
useGetAllPermissions,
useCreatePermission,
AdminPermissionsQueryKeys,
} from "./admin/permissions/use-hooks";
// Types - Auth
export type {
LoginDto,
RegisterDto,
RefreshTokenDto,
AuthResponse,
} from "./auth/types";
// Types - Users (Common)
export type { UserResponseDto, RoleInfo } from "./users/types";
// Types - Admin Users (Specific)
export type {
UserRoleResponseDto,
UsersQueryParams,
PaginatedUsersResponse,
} from "./admin/users/types";
// Types - Admin Roles
export type {
RoleResponseDto,
CreateRoleDto,
UpdateRoleDto,
RolePermissionResponseDto,
PermissionInfo,
} from "./admin/roles/types";
// Types - Admin Permissions
export type {
PermissionResponseDto,
CreatePermissionDto,
} from "./admin/permissions/types";

View File

@@ -0,0 +1,20 @@
import { apiRequest } from "@/lib/api/api-service";
import { ApiResponse } from "@/types/api-response";
import { UserResponseDto } from "./types";
/**
* Users Service - Example Implementation
* Matches Backend: /api/users/*
*/
const getMe = () => {
return apiRequest<ApiResponse<UserResponseDto>>({
url: "/users/me",
client: "core",
method: "get",
});
};
export const usersService = {
getMe,
};

View File

@@ -0,0 +1,18 @@
// User Response DTO - Matches Backend UserResponseDto
export interface UserResponseDto {
id: string;
email: string;
firstName: string;
lastName: string;
username?: string;
isActive: boolean;
avatar?: string | null;
roles: RoleInfo[];
createdAt: string;
updatedAt: string;
}
export interface RoleInfo {
id: string;
name: string;
}

View File

@@ -0,0 +1,20 @@
import { useQuery } from "@tanstack/react-query";
import { ApiResponse } from "@/types/api-response";
import { usersService } from "./service";
import { UserResponseDto } from "./types";
export const UsersQueryKeys = {
all: ["users"] as const,
me: () => [...UsersQueryKeys.all, "me"] as const,
};
export function useGetMe() {
const queryKey = UsersQueryKeys.me();
const { data, ...rest } = useQuery<ApiResponse<UserResponseDto>>({
queryKey: queryKey,
queryFn: usersService.getMe,
});
return { data: data?.data, ...rest };
}