fix teacher, parent and admin pages
This commit is contained in:
@@ -0,0 +1,261 @@
|
||||
/**
|
||||
* Roles & permissions admin (legacy CI rolepermission/*).
|
||||
* Expected under `/api/v1/role-permission`.
|
||||
*/
|
||||
import { apiFetch } from './http'
|
||||
|
||||
const BASE = '/api/v1/role-permission'
|
||||
|
||||
function unwrapData<T>(body: T): T {
|
||||
if (!body || typeof body !== 'object') return body
|
||||
const maybeEnvelope = body as { data?: unknown }
|
||||
return (maybeEnvelope.data as T | undefined) ?? body
|
||||
}
|
||||
|
||||
export type RoleRow = {
|
||||
id?: number | string
|
||||
name?: string
|
||||
slug?: string
|
||||
description?: string
|
||||
dashboard_route?: string
|
||||
priority?: number
|
||||
is_active?: number | string | boolean
|
||||
user_count?: number
|
||||
}
|
||||
|
||||
export type PermissionRow = {
|
||||
id?: number | string
|
||||
name?: string
|
||||
description?: string
|
||||
created_at?: string
|
||||
updated_at?: string
|
||||
}
|
||||
|
||||
export async function fetchRolesList(): Promise<{ roles?: RoleRow[] }> {
|
||||
const body = await apiFetch<{ roles?: RoleRow[] } | { data?: { roles?: RoleRow[] } }>(`${BASE}/roles`)
|
||||
return unwrapData(body)
|
||||
}
|
||||
|
||||
export async function fetchPermissionsList(): Promise<{ permissions?: PermissionRow[] }> {
|
||||
const body = await apiFetch<
|
||||
{ permissions?: PermissionRow[] } | { data?: { permissions?: PermissionRow[] } }
|
||||
>(`${BASE}/permissions`)
|
||||
return unwrapData(body)
|
||||
}
|
||||
|
||||
export type AssignUserRow = {
|
||||
id?: number | string
|
||||
account_id?: string
|
||||
firstname?: string
|
||||
lastname?: string
|
||||
email?: string
|
||||
roles?: string[]
|
||||
}
|
||||
|
||||
export async function fetchUsersForAssign(params?: {
|
||||
school_year?: string
|
||||
semester?: string
|
||||
page?: number
|
||||
per_page?: number
|
||||
}): Promise<{ users?: AssignUserRow[]; meta?: { current_page?: number; last_page?: number; total?: number; per_page?: number } }> {
|
||||
const qs = new URLSearchParams()
|
||||
if (params?.school_year) qs.set('school_year', params.school_year)
|
||||
if (params?.semester) qs.set('semester', params.semester)
|
||||
qs.set('per_page', String(params?.per_page ?? 200))
|
||||
if (params?.page) qs.set('page', String(params.page))
|
||||
qs.set('sort_by', 'lastname')
|
||||
qs.set('sort_dir', 'asc')
|
||||
const suffix = qs.toString() ? `?${qs}` : ''
|
||||
const body = await apiFetch<
|
||||
| {
|
||||
users?: AssignUserRow[]
|
||||
meta?: { current_page?: number; last_page?: number; total?: number; per_page?: number }
|
||||
}
|
||||
| {
|
||||
data?: {
|
||||
users?: AssignUserRow[]
|
||||
meta?: { current_page?: number; last_page?: number; total?: number; per_page?: number }
|
||||
}
|
||||
}
|
||||
>(
|
||||
`${BASE}/users${suffix}`,
|
||||
)
|
||||
return unwrapData(body)
|
||||
}
|
||||
|
||||
export async function fetchAllUsersForAssign(params?: {
|
||||
school_year?: string
|
||||
semester?: string
|
||||
}): Promise<{ users: AssignUserRow[] }> {
|
||||
const usersById = new Map<string, AssignUserRow>()
|
||||
let page = 1
|
||||
let lastPage = 1
|
||||
|
||||
do {
|
||||
const response = await fetchUsersForAssign({
|
||||
school_year: params?.school_year,
|
||||
semester: params?.semester,
|
||||
page,
|
||||
per_page: 200,
|
||||
})
|
||||
for (const user of response.users ?? []) {
|
||||
const key = String(user.id ?? '').trim()
|
||||
if (key === '') {
|
||||
continue
|
||||
}
|
||||
if (!usersById.has(key)) {
|
||||
usersById.set(key, user)
|
||||
}
|
||||
}
|
||||
lastPage = Number(response.meta?.last_page ?? page)
|
||||
page += 1
|
||||
} while (page <= lastPage)
|
||||
|
||||
return { users: [...usersById.values()] }
|
||||
}
|
||||
|
||||
export async function saveUserRoles(payload: {
|
||||
user_id: number | string
|
||||
role_ids: (number | string)[]
|
||||
}): Promise<{ ok?: boolean; message?: string }> {
|
||||
const userId = encodeURIComponent(String(payload.user_id))
|
||||
const body = await apiFetch<{ ok?: boolean; message?: string } | { data?: { ok?: boolean; message?: string } }>(
|
||||
`${BASE}/users/${userId}/roles`,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ role_ids: payload.role_ids }),
|
||||
},
|
||||
)
|
||||
return unwrapData(body)
|
||||
}
|
||||
|
||||
export async function createRole(payload: Record<string, unknown>): Promise<{ ok?: boolean; message?: string }> {
|
||||
const body = await apiFetch<{ ok?: boolean; message?: string } | { data?: { ok?: boolean; message?: string } }>(
|
||||
`${BASE}/roles`,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(payload),
|
||||
},
|
||||
)
|
||||
return unwrapData(body)
|
||||
}
|
||||
|
||||
export async function updateRole(
|
||||
roleId: number | string,
|
||||
payload: Record<string, unknown>,
|
||||
): Promise<{ ok?: boolean; message?: string }> {
|
||||
const body = await apiFetch<{ ok?: boolean; message?: string } | { data?: { ok?: boolean; message?: string } }>(
|
||||
`${BASE}/roles/${encodeURIComponent(String(roleId))}`,
|
||||
{
|
||||
method: 'PATCH',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(payload),
|
||||
},
|
||||
)
|
||||
return unwrapData(body)
|
||||
}
|
||||
|
||||
export async function deleteRole(roleId: number | string): Promise<{ ok?: boolean }> {
|
||||
const body = await apiFetch<{ ok?: boolean } | { data?: { ok?: boolean } }>(
|
||||
`${BASE}/roles/${encodeURIComponent(String(roleId))}`,
|
||||
{ method: 'DELETE' },
|
||||
)
|
||||
return unwrapData(body)
|
||||
}
|
||||
|
||||
export async function fetchRole(roleId: number | string): Promise<{ role?: RoleRow }> {
|
||||
const body = await apiFetch<{ role?: RoleRow } | { data?: { role?: RoleRow } }>(
|
||||
`${BASE}/roles/${encodeURIComponent(String(roleId))}`,
|
||||
)
|
||||
return unwrapData(body)
|
||||
}
|
||||
|
||||
export async function createPermission(payload: {
|
||||
name: string
|
||||
description?: string
|
||||
}): Promise<{ ok?: boolean; message?: string }> {
|
||||
const body = await apiFetch<{ ok?: boolean; message?: string } | { data?: { ok?: boolean; message?: string } }>(
|
||||
`${BASE}/permissions`,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(payload),
|
||||
},
|
||||
)
|
||||
return unwrapData(body)
|
||||
}
|
||||
|
||||
export async function fetchPermission(
|
||||
permissionId: number | string,
|
||||
): Promise<{ permission?: PermissionRow }> {
|
||||
const body = await apiFetch<{ permission?: PermissionRow } | { data?: { permission?: PermissionRow } }>(
|
||||
`${BASE}/permissions/${encodeURIComponent(String(permissionId))}`,
|
||||
)
|
||||
return unwrapData(body)
|
||||
}
|
||||
|
||||
export async function updatePermission(
|
||||
permissionId: number | string,
|
||||
payload: { name: string; description?: string },
|
||||
): Promise<{ ok?: boolean; message?: string }> {
|
||||
const body = await apiFetch<{ ok?: boolean; message?: string } | { data?: { ok?: boolean; message?: string } }>(
|
||||
`${BASE}/permissions/${encodeURIComponent(String(permissionId))}`,
|
||||
{
|
||||
method: 'PATCH',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(payload),
|
||||
},
|
||||
)
|
||||
return unwrapData(body)
|
||||
}
|
||||
|
||||
export type PermissionMatrixRow = {
|
||||
id?: number | string
|
||||
name?: string
|
||||
}
|
||||
|
||||
export type ExistingPermissionFlags = {
|
||||
can_create?: boolean
|
||||
can_read?: boolean
|
||||
can_update?: boolean
|
||||
can_delete?: boolean
|
||||
}
|
||||
|
||||
export async function fetchRolePermissionMatrix(roleId: number | string): Promise<{
|
||||
roleId?: number | string
|
||||
permissions?: PermissionMatrixRow[]
|
||||
existing?: Record<string, ExistingPermissionFlags>
|
||||
}> {
|
||||
const body = await apiFetch<
|
||||
| {
|
||||
roleId?: number | string
|
||||
permissions?: PermissionMatrixRow[]
|
||||
existing?: Record<string, ExistingPermissionFlags>
|
||||
}
|
||||
| {
|
||||
data?: {
|
||||
roleId?: number | string
|
||||
permissions?: PermissionMatrixRow[]
|
||||
existing?: Record<string, ExistingPermissionFlags>
|
||||
}
|
||||
}
|
||||
>(`${BASE}/roles/${encodeURIComponent(String(roleId))}/permissions`)
|
||||
return unwrapData(body)
|
||||
}
|
||||
|
||||
export async function saveRolePermissionMatrix(
|
||||
roleId: number | string,
|
||||
payload: Record<string, { create?: boolean; read?: boolean; update?: boolean; delete?: boolean }>,
|
||||
): Promise<{ ok?: boolean; message?: string }> {
|
||||
const body = await apiFetch<{ ok?: boolean; message?: string } | { data?: { ok?: boolean; message?: string } }>(
|
||||
`${BASE}/roles/${encodeURIComponent(String(roleId))}/permissions`,
|
||||
{
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ permissions: payload }),
|
||||
},
|
||||
)
|
||||
return unwrapData(body)
|
||||
}
|
||||
Reference in New Issue
Block a user