add admin pages
This commit is contained in:
+818
-2
@@ -1,11 +1,25 @@
|
||||
import { apiUrl } from '../lib/apiOrigin'
|
||||
import { apiFetch, getStoredToken } from './http'
|
||||
import type {
|
||||
AdministratorAbsenceFormResponse,
|
||||
AdministratorAbsenceSubmitResponse,
|
||||
AdministratorAdminAttendanceResponse,
|
||||
AdministratorDailyAttendanceResponse,
|
||||
AdministratorDashboardMetricsResponse,
|
||||
AdministratorDashboardSearchResponse,
|
||||
ApiEnvelope,
|
||||
BroadcastEmailOptionsResponse,
|
||||
BroadcastEmailSendResponse,
|
||||
ClassSectionShowResponse,
|
||||
ClassSectionsResponse,
|
||||
DashboardPayload,
|
||||
FamilyAdminIndexResponse,
|
||||
GradingOverviewResponse,
|
||||
IpBansResponse,
|
||||
LoginFailure,
|
||||
LoginResponse,
|
||||
LoginSuccess,
|
||||
LateSlipLogsResponse,
|
||||
NavBuilderDataResponse,
|
||||
NavBuilderDeleteResponse,
|
||||
NavBuilderSaveResponse,
|
||||
@@ -19,16 +33,41 @@ import type {
|
||||
ParentRegistrationOverviewResponse,
|
||||
ParentEmergencyContactsResponse,
|
||||
ParentAttendanceReportsListResponse,
|
||||
SchoolCalendarListResponse,
|
||||
SchoolCalendarOptionsResponse,
|
||||
SchoolCalendarShowResponse,
|
||||
ParentAuthorizedUsersApiResponse,
|
||||
ParentMessagesResponse,
|
||||
NotificationAlertsResponse,
|
||||
PaypalTransactionsResponse,
|
||||
PrintNotificationRecipientsResponse,
|
||||
SchoolCalendarEventsResponse,
|
||||
StudentAssignmentsResponse,
|
||||
StudentScoresResponse,
|
||||
ReportCardAcknowledgementResponse,
|
||||
ReportCardMetaResponse,
|
||||
RemovedStudentsResponse,
|
||||
ClassProgressGroupsResponse,
|
||||
ClassProgressMetaResponse,
|
||||
ClassProgressShowResponse,
|
||||
ParentProfileRecord,
|
||||
ContactSubmitResponse,
|
||||
CompetitionScoresEditResponse,
|
||||
CompetitionScoresIndexResponse,
|
||||
ExamDraftAdminResponse,
|
||||
PublicCompetitionIndexResponse,
|
||||
PublicCompetitionShowResponse,
|
||||
StudentDirectoryResponse,
|
||||
StudentScoreCardResponse,
|
||||
StudentEmergencyContactResponse,
|
||||
StudentParentResponse,
|
||||
StudentPromotionTotalsResponse,
|
||||
SubjectCurriculumResponse,
|
||||
TeacherClassAssignmentsResponse,
|
||||
TeacherSubmissionsResponse,
|
||||
EmergencyContactGroupsResponse,
|
||||
EmergencyContactShowResponse,
|
||||
UsersResponse,
|
||||
} from './types'
|
||||
|
||||
export async function loginRequest(
|
||||
@@ -57,6 +96,702 @@ export async function fetchDashboardRoute(): Promise<ApiEnvelope<DashboardPayloa
|
||||
return apiFetch<ApiEnvelope<DashboardPayload>>('/api/v1/dashboard/route')
|
||||
}
|
||||
|
||||
export async function fetchAdministratorDashboardMetrics(): Promise<AdministratorDashboardMetricsResponse> {
|
||||
return apiFetch<AdministratorDashboardMetricsResponse>('/api/v1/administrator/dashboard/metrics')
|
||||
}
|
||||
|
||||
export async function searchAdministratorDashboard(query: string): Promise<AdministratorDashboardSearchResponse> {
|
||||
const q = query.trim()
|
||||
const qs = q ? `?query=${encodeURIComponent(q)}` : ''
|
||||
return apiFetch<AdministratorDashboardSearchResponse>(`/api/v1/administrator/dashboard/user-search${qs}`)
|
||||
}
|
||||
|
||||
export async function fetchAdministratorAbsenceForm(): Promise<AdministratorAbsenceFormResponse> {
|
||||
return apiFetch<AdministratorAbsenceFormResponse>('/api/v1/administrator/absence')
|
||||
}
|
||||
|
||||
export async function submitAdministratorAbsence(payload: {
|
||||
dates: string[]
|
||||
reason_type?: string
|
||||
reason: string
|
||||
}): Promise<AdministratorAbsenceSubmitResponse> {
|
||||
return apiFetch<AdministratorAbsenceSubmitResponse>('/api/v1/administrator/absence', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export async function fetchAdministratorDailyAttendance(
|
||||
params?: { semester?: string | null; schoolYear?: string | null },
|
||||
): Promise<AdministratorDailyAttendanceResponse> {
|
||||
const query = new URLSearchParams()
|
||||
if (params?.semester) query.set('semester', params.semester)
|
||||
if (params?.schoolYear) query.set('school_year', params.schoolYear)
|
||||
const qs = query.size > 0 ? `?${query.toString()}` : ''
|
||||
return apiFetch<AdministratorDailyAttendanceResponse>(`/api/v1/attendance/admin/daily${qs}`)
|
||||
}
|
||||
|
||||
export async function addAdministratorAttendanceEntry(payload: {
|
||||
class_section_id: number
|
||||
student_id: number
|
||||
school_id?: string | null
|
||||
status: 'present' | 'absent' | 'late'
|
||||
date?: string | null
|
||||
reason?: string | null
|
||||
class_id?: number | null
|
||||
is_reported?: 'yes' | 'no' | null
|
||||
}): Promise<{ message?: string }> {
|
||||
return apiFetch<{ message?: string }>('/api/v1/attendance/admin/add-entry', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export async function updateAdministratorAttendance(payload: {
|
||||
class_section_id: number
|
||||
student_id: number
|
||||
school_id?: string | null
|
||||
status: 'present' | 'absent' | 'late'
|
||||
date: string
|
||||
reason?: string | null
|
||||
class_id?: number | null
|
||||
semester?: string | null
|
||||
school_year?: string | null
|
||||
is_reported?: string | null
|
||||
}): Promise<{ message?: string }> {
|
||||
return apiFetch<{ message?: string }>('/api/v1/attendance/admin/update', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export async function fetchAdministratorAdminAttendance(
|
||||
params?: { date?: string | null; semester?: string | null; schoolYear?: string | null },
|
||||
): Promise<AdministratorAdminAttendanceResponse> {
|
||||
const query = new URLSearchParams()
|
||||
if (params?.date) query.set('date', params.date)
|
||||
if (params?.semester) query.set('semester', params.semester)
|
||||
if (params?.schoolYear) query.set('school_year', params.schoolYear)
|
||||
const qs = query.size > 0 ? `?${query.toString()}` : ''
|
||||
return apiFetch<AdministratorAdminAttendanceResponse>(`/api/v1/attendance/staff/admins${qs}`)
|
||||
}
|
||||
|
||||
export async function saveAdministratorAdminAttendance(payload: {
|
||||
date: string
|
||||
semester: string
|
||||
school_year: string
|
||||
admins: Record<
|
||||
string,
|
||||
{
|
||||
status?: string | null
|
||||
reason?: string | null
|
||||
role_name?: string | null
|
||||
role_slug?: string | null
|
||||
}
|
||||
>
|
||||
}): Promise<{ message?: string }> {
|
||||
return apiFetch<{ message?: string }>('/api/v1/attendance/staff/admins/save', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export async function fetchBroadcastEmailOptions(): Promise<BroadcastEmailOptionsResponse> {
|
||||
return apiFetch<BroadcastEmailOptionsResponse>('/api/v1/broadcast-email/options')
|
||||
}
|
||||
|
||||
export async function sendBroadcastEmail(payload: {
|
||||
from_key: string
|
||||
mode: 'personalized' | 'standard'
|
||||
subject: string
|
||||
body_html: string
|
||||
wrap_layout?: boolean
|
||||
preheader?: string
|
||||
cta_text?: string
|
||||
cta_url?: string
|
||||
test_email?: string
|
||||
send_test_only?: boolean
|
||||
parent_ids?: number[]
|
||||
}): Promise<BroadcastEmailSendResponse> {
|
||||
return apiFetch<BroadcastEmailSendResponse>('/api/v1/broadcast-email/send', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export async function fetchSchoolCalendarOptions(): Promise<SchoolCalendarOptionsResponse> {
|
||||
return apiFetch<SchoolCalendarOptionsResponse>('/api/v1/settings/school-calendar/options')
|
||||
}
|
||||
|
||||
export async function fetchAdministratorCalendarEvents(params?: {
|
||||
schoolYear?: string | null
|
||||
semester?: string | null
|
||||
audience?: 'admin' | 'teacher' | 'parent' | null
|
||||
}): Promise<SchoolCalendarListResponse> {
|
||||
const query = new URLSearchParams()
|
||||
if (params?.schoolYear) query.set('school_year', params.schoolYear)
|
||||
if (params?.semester) query.set('semester', params.semester)
|
||||
if (params?.audience) query.set('audience', params.audience)
|
||||
const qs = query.size > 0 ? `?${query.toString()}` : ''
|
||||
return apiFetch<SchoolCalendarListResponse>(`/api/v1/settings/school-calendar/events${qs}`)
|
||||
}
|
||||
|
||||
export async function fetchAdministratorCalendarEvent(eventId: number): Promise<SchoolCalendarShowResponse> {
|
||||
return apiFetch<SchoolCalendarShowResponse>(`/api/v1/settings/school-calendar/events/${eventId}`)
|
||||
}
|
||||
|
||||
export async function createAdministratorCalendarEvent(payload: {
|
||||
title: string
|
||||
description?: string
|
||||
event_type?: string
|
||||
date: string
|
||||
notify_parent?: boolean
|
||||
notify_teacher?: boolean
|
||||
notify_admin?: boolean
|
||||
no_school?: boolean
|
||||
school_year?: string
|
||||
semester?: string
|
||||
send_email_parent?: boolean
|
||||
send_email_teacher?: boolean
|
||||
send_email_admin?: boolean
|
||||
}): Promise<SchoolCalendarShowResponse> {
|
||||
return apiFetch<SchoolCalendarShowResponse>('/api/v1/settings/school-calendar/events', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export async function updateAdministratorCalendarEvent(
|
||||
eventId: number,
|
||||
payload: Record<string, unknown>,
|
||||
): Promise<SchoolCalendarShowResponse> {
|
||||
return apiFetch<SchoolCalendarShowResponse>(`/api/v1/settings/school-calendar/events/${eventId}`, {
|
||||
method: 'PATCH',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export async function deleteAdministratorCalendarEvent(eventId: number): Promise<ApiEnvelope<null>> {
|
||||
return apiFetch<ApiEnvelope<null>>(`/api/v1/settings/school-calendar/events/${eventId}`, {
|
||||
method: 'DELETE',
|
||||
})
|
||||
}
|
||||
|
||||
export async function fetchStudentAssignments(
|
||||
schoolYear?: string | null,
|
||||
): Promise<StudentAssignmentsResponse> {
|
||||
const query = schoolYear ? `?school_year=${encodeURIComponent(schoolYear)}` : ''
|
||||
return apiFetch<StudentAssignmentsResponse>(`/api/v1/students/assignments${query}`)
|
||||
}
|
||||
|
||||
export async function assignStudentClass(payload: {
|
||||
student_id: number
|
||||
class_section_ids?: number[]
|
||||
class_section_id?: number[]
|
||||
is_event_only?: boolean
|
||||
}): Promise<{ ok: boolean; message?: string }> {
|
||||
return apiFetch<{ ok: boolean; message?: string }>('/api/v1/students/assign-class', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
student_id: payload.student_id,
|
||||
class_section_id: payload.class_section_id ?? payload.class_section_ids ?? [],
|
||||
is_event_only: payload.is_event_only ?? false,
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
export async function removeStudentClass(payload: {
|
||||
student_id: number
|
||||
class_section_id: number
|
||||
}): Promise<{ ok: boolean; message?: string }> {
|
||||
return apiFetch<{ ok: boolean; message?: string }>('/api/v1/students/remove-class', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export async function fetchRemovedStudents(
|
||||
schoolYear?: string | null,
|
||||
): Promise<RemovedStudentsResponse> {
|
||||
const query = schoolYear ? `?school_year=${encodeURIComponent(schoolYear)}` : ''
|
||||
return apiFetch<RemovedStudentsResponse>(`/api/v1/students/removed${query}`)
|
||||
}
|
||||
|
||||
export async function setStudentActive(payload: {
|
||||
student_id: number
|
||||
is_active: boolean
|
||||
}): Promise<{ ok: boolean; message?: string }> {
|
||||
return apiFetch<{ ok: boolean; message?: string }>('/api/v1/students/set-active', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export async function autoDistributeStudents(payload: {
|
||||
class_id?: number
|
||||
class_section_id?: number
|
||||
students_per_section: number
|
||||
school_year?: string | null
|
||||
}): Promise<ApiEnvelope<{ sections?: Array<Record<string, unknown>>; message?: string }>> {
|
||||
return apiFetch<ApiEnvelope<{ sections?: Array<Record<string, unknown>>; message?: string }>>(
|
||||
'/api/v1/students/auto-distribute',
|
||||
{
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(payload),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
export async function fetchStudentPromotionTotals(
|
||||
schoolYear?: string | null,
|
||||
): Promise<StudentPromotionTotalsResponse> {
|
||||
const query = schoolYear ? `?school_year=${encodeURIComponent(schoolYear)}` : ''
|
||||
return apiFetch<StudentPromotionTotalsResponse>(`/api/v1/students/promotion-totals${query}`)
|
||||
}
|
||||
|
||||
export async function fetchStudentDirectory(
|
||||
schoolYear?: string | null,
|
||||
): Promise<StudentDirectoryResponse> {
|
||||
const query = schoolYear ? `?school_year=${encodeURIComponent(schoolYear)}` : ''
|
||||
return apiFetch<StudentDirectoryResponse>(`/api/v1/students${query}`)
|
||||
}
|
||||
|
||||
export async function updateStudentProfile(
|
||||
studentId: number,
|
||||
payload: Record<string, unknown>,
|
||||
): Promise<{ ok: boolean; message?: string }> {
|
||||
return apiFetch<{ ok: boolean; message?: string }>(`/api/v1/students/${studentId}`, {
|
||||
method: 'PATCH',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export async function fetchStudentParent(studentId: number): Promise<StudentParentResponse> {
|
||||
return apiFetch<StudentParentResponse>(`/api/v1/students/${studentId}/parents`)
|
||||
}
|
||||
|
||||
export async function fetchStudentEmergencyContacts(
|
||||
studentId: number,
|
||||
): Promise<StudentEmergencyContactResponse> {
|
||||
return apiFetch<StudentEmergencyContactResponse>(`/api/v1/students/${studentId}/emergency-contacts`)
|
||||
}
|
||||
|
||||
export async function fetchTeacherClassAssignments(
|
||||
schoolYear?: string | null,
|
||||
): Promise<TeacherClassAssignmentsResponse> {
|
||||
const query = schoolYear ? `?school_year=${encodeURIComponent(schoolYear)}` : ''
|
||||
return apiFetch<TeacherClassAssignmentsResponse>(
|
||||
`/api/v1/administrator/teacher-class/assignments${query}`,
|
||||
)
|
||||
}
|
||||
|
||||
export async function assignTeacherClass(payload: {
|
||||
teacher_id: number
|
||||
class_section_id: number
|
||||
teacher_role?: string
|
||||
school_year?: string
|
||||
}): Promise<{ ok: boolean; message?: string; position?: string | null }> {
|
||||
return apiFetch<{ ok: boolean; message?: string; position?: string | null }>(
|
||||
'/api/v1/administrator/teacher-class/assign',
|
||||
{
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(payload),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
export async function deleteTeacherClassAssignment(payload: {
|
||||
teacher_id: number
|
||||
class_section_id: number
|
||||
position: 'main' | 'ta'
|
||||
school_year?: string
|
||||
}): Promise<{ ok: boolean; message?: string }> {
|
||||
return apiFetch<{ ok: boolean; message?: string }>(
|
||||
'/api/v1/administrator/teacher-class/delete',
|
||||
{
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(payload),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
export async function fetchTeacherSubmissions(): Promise<TeacherSubmissionsResponse> {
|
||||
return apiFetch<TeacherSubmissionsResponse>('/api/v1/administrator/teacher-submissions')
|
||||
}
|
||||
|
||||
export async function fetchPublishedCompetitions(): Promise<PublicCompetitionIndexResponse> {
|
||||
return apiFetch<PublicCompetitionIndexResponse>('/api/winners/competitions', {}, { attachAuth: false })
|
||||
}
|
||||
|
||||
export async function fetchPublishedCompetition(id: number): Promise<PublicCompetitionShowResponse> {
|
||||
return apiFetch<PublicCompetitionShowResponse>(`/api/winners/competitions/${id}`, {}, { attachAuth: false })
|
||||
}
|
||||
|
||||
export async function fetchCompetitionScoresIndex(
|
||||
classSectionId?: number | null,
|
||||
): Promise<CompetitionScoresIndexResponse> {
|
||||
const query = classSectionId ? `?class_section_id=${encodeURIComponent(String(classSectionId))}` : ''
|
||||
return apiFetch<CompetitionScoresIndexResponse>(`/api/v1/competition-scores${query}`)
|
||||
}
|
||||
|
||||
export async function fetchCompetitionScoresDetail(
|
||||
id: number,
|
||||
classSectionId?: number | null,
|
||||
): Promise<CompetitionScoresEditResponse> {
|
||||
const query = classSectionId ? `?class_section_id=${encodeURIComponent(String(classSectionId))}` : ''
|
||||
return apiFetch<CompetitionScoresEditResponse>(`/api/v1/competition-scores/${id}${query}`)
|
||||
}
|
||||
|
||||
export async function saveCompetitionScores(
|
||||
id: number,
|
||||
payload: { class_section_id?: number | null; scores: Record<string, number | string> },
|
||||
): Promise<{ ok: boolean; message?: string; savedCount?: number; invalidScores?: string[] }> {
|
||||
return apiFetch<{ ok: boolean; message?: string; savedCount?: number; invalidScores?: string[] }>(
|
||||
`/api/v1/competition-scores/${id}`,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(payload),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
export async function notifyTeacherSubmissions(payload: {
|
||||
notify: number[]
|
||||
missing_items?: Record<string, string[]>
|
||||
}): Promise<{ message?: string; sent?: number; failed?: number }> {
|
||||
return apiFetch<{ message?: string; sent?: number; failed?: number }>(
|
||||
'/api/v1/administrator/teacher-submissions/notify',
|
||||
{
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(payload),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
export async function fetchSubjectCurriculum(): Promise<SubjectCurriculumResponse> {
|
||||
return apiFetch<SubjectCurriculumResponse>('/api/v1/subjects/curriculum')
|
||||
}
|
||||
|
||||
export async function createSubjectCurriculum(payload: {
|
||||
class_id: number
|
||||
subject: string
|
||||
unit_number?: number | null
|
||||
unit_title?: string | null
|
||||
chapter_name: string
|
||||
}): Promise<ApiEnvelope<{ entry?: unknown }>> {
|
||||
return apiFetch<ApiEnvelope<{ entry?: unknown }>>('/api/v1/subjects/curriculum', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export async function updateSubjectCurriculum(
|
||||
id: number,
|
||||
payload: Record<string, unknown>,
|
||||
): Promise<ApiEnvelope<{ entry?: unknown }>> {
|
||||
return apiFetch<ApiEnvelope<{ entry?: unknown }>>(`/api/v1/subjects/curriculum/${id}`, {
|
||||
method: 'PATCH',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export async function deleteSubjectCurriculum(id: number): Promise<ApiEnvelope<null>> {
|
||||
return apiFetch<ApiEnvelope<null>>(`/api/v1/subjects/curriculum/${id}`, {
|
||||
method: 'DELETE',
|
||||
})
|
||||
}
|
||||
|
||||
export async function fetchClassSections(params?: {
|
||||
search?: string
|
||||
schoolYear?: string | null
|
||||
semester?: string | null
|
||||
page?: number
|
||||
perPage?: number
|
||||
}): Promise<ClassSectionsResponse> {
|
||||
const query = new URLSearchParams()
|
||||
if (params?.search) query.set('search', params.search)
|
||||
if (params?.schoolYear) query.set('school_year', params.schoolYear)
|
||||
if (params?.semester) query.set('semester', params.semester)
|
||||
if (params?.page) query.set('page', String(params.page))
|
||||
if (params?.perPage) query.set('per_page', String(params.perPage))
|
||||
const qs = query.size > 0 ? `?${query.toString()}` : ''
|
||||
return apiFetch<ClassSectionsResponse>(`/api/v1/class-sections${qs}`)
|
||||
}
|
||||
|
||||
export async function fetchClassSection(sectionId: number): Promise<ClassSectionShowResponse> {
|
||||
return apiFetch<ClassSectionShowResponse>(`/api/v1/class-sections/${sectionId}`)
|
||||
}
|
||||
|
||||
export async function createClassSection(payload: {
|
||||
class_id: number
|
||||
class_section_id: number
|
||||
class_section_name: string
|
||||
semester: string
|
||||
school_year: string
|
||||
}): Promise<ClassSectionShowResponse> {
|
||||
return apiFetch<ClassSectionShowResponse>('/api/v1/class-sections', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export async function updateClassSection(
|
||||
sectionId: number,
|
||||
payload: Partial<{
|
||||
class_id: number
|
||||
class_section_id: number
|
||||
class_section_name: string
|
||||
semester: string
|
||||
school_year: string
|
||||
}>,
|
||||
): Promise<ClassSectionShowResponse> {
|
||||
return apiFetch<ClassSectionShowResponse>(`/api/v1/class-sections/${sectionId}`, {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export async function deleteClassSection(sectionId: number): Promise<ApiEnvelope<null>> {
|
||||
return apiFetch<ApiEnvelope<null>>(`/api/v1/class-sections/${sectionId}`, {
|
||||
method: 'DELETE',
|
||||
})
|
||||
}
|
||||
|
||||
export async function fetchExamDraftAdminData(): Promise<ExamDraftAdminResponse> {
|
||||
return apiFetch<ExamDraftAdminResponse>('/api/v1/exams/drafts/admin')
|
||||
}
|
||||
|
||||
async function fetchMultipartJson<T>(path: string, formData: FormData): Promise<T> {
|
||||
const headers = new Headers({ Accept: 'application/json' })
|
||||
const token = getStoredToken()
|
||||
if (token) headers.set('Authorization', `Bearer ${token}`)
|
||||
const res = await fetch(apiUrl(path), {
|
||||
method: 'POST',
|
||||
headers,
|
||||
body: formData,
|
||||
})
|
||||
const body: unknown = await res.json().catch(() => null)
|
||||
if (!res.ok) {
|
||||
const msg =
|
||||
typeof body === 'object' && body !== null && 'message' in body
|
||||
? String((body as { message?: unknown }).message ?? '')
|
||||
: ''
|
||||
throw new Error(msg || `HTTP ${res.status}`)
|
||||
}
|
||||
return body as T
|
||||
}
|
||||
|
||||
export async function uploadLegacyExamDraft(payload: {
|
||||
class_section_id: number
|
||||
school_year: string
|
||||
semester: string
|
||||
exam_type?: string
|
||||
old_exam_file: File
|
||||
}): Promise<{ ok: boolean; message?: string }> {
|
||||
const formData = new FormData()
|
||||
formData.set('class_section_id', String(payload.class_section_id))
|
||||
formData.set('school_year', payload.school_year)
|
||||
formData.set('semester', payload.semester)
|
||||
if (payload.exam_type) formData.set('exam_type', payload.exam_type)
|
||||
formData.set('old_exam_file', payload.old_exam_file)
|
||||
return fetchMultipartJson('/api/v1/exams/drafts/admin/legacy', formData)
|
||||
}
|
||||
|
||||
export async function reviewExamDraft(payload: {
|
||||
draft_id: number
|
||||
review_status?: string
|
||||
admin_comments?: string
|
||||
final_file?: File | null
|
||||
}): Promise<{ ok: boolean; message?: string }> {
|
||||
const formData = new FormData()
|
||||
formData.set('draft_id', String(payload.draft_id))
|
||||
if (payload.review_status) formData.set('review_status', payload.review_status)
|
||||
if (payload.admin_comments) formData.set('admin_comments', payload.admin_comments)
|
||||
if (payload.final_file) formData.set('final_file', payload.final_file)
|
||||
return fetchMultipartJson('/api/v1/exams/drafts/admin/review', formData)
|
||||
}
|
||||
|
||||
export async function fetchGradingOverview(params?: {
|
||||
classId?: number | null
|
||||
semester?: string | null
|
||||
schoolYear?: string | null
|
||||
}): Promise<GradingOverviewResponse> {
|
||||
const query = new URLSearchParams()
|
||||
if (params?.classId) query.set('class_id', String(params.classId))
|
||||
if (params?.semester) query.set('semester', params.semester)
|
||||
if (params?.schoolYear) query.set('school_year', params.schoolYear)
|
||||
const qs = query.size > 0 ? `?${query.toString()}` : ''
|
||||
return apiFetch<GradingOverviewResponse>(`/api/v1/grading/overview${qs}`)
|
||||
}
|
||||
|
||||
export async function fetchIpBans(params?: {
|
||||
status?: 'all' | 'active'
|
||||
page?: number
|
||||
perPage?: number
|
||||
}): Promise<IpBansResponse> {
|
||||
const query = new URLSearchParams()
|
||||
if (params?.status) query.set('status', params.status)
|
||||
if (params?.page) query.set('page', String(params.page))
|
||||
if (params?.perPage) query.set('per_page', String(params.perPage))
|
||||
const qs = query.size > 0 ? `?${query.toString()}` : ''
|
||||
return apiFetch<IpBansResponse>(`/api/v1/ip-bans${qs}`)
|
||||
}
|
||||
|
||||
export async function banIp(payload: {
|
||||
id?: number
|
||||
ip?: string
|
||||
hours?: number
|
||||
}): Promise<ApiEnvelope<{ ban?: unknown }>> {
|
||||
return apiFetch<ApiEnvelope<{ ban?: unknown }>>('/api/v1/ip-bans/ban', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export async function unbanIp(payload: {
|
||||
id?: number
|
||||
ip?: string
|
||||
all?: boolean
|
||||
}): Promise<ApiEnvelope<{ ban?: unknown; count?: number }>> {
|
||||
return apiFetch<ApiEnvelope<{ ban?: unknown; count?: number }>>('/api/v1/ip-bans/unban', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export async function fetchLateSlipLogs(params?: {
|
||||
schoolYear?: string | null
|
||||
semester?: string | null
|
||||
q?: string
|
||||
dateFrom?: string
|
||||
dateTo?: string
|
||||
page?: number
|
||||
perPage?: number
|
||||
}): Promise<LateSlipLogsResponse> {
|
||||
const query = new URLSearchParams()
|
||||
if (params?.schoolYear) query.set('school_year', params.schoolYear)
|
||||
if (params?.semester) query.set('semester', params.semester)
|
||||
if (params?.q) query.set('q', params.q)
|
||||
if (params?.dateFrom) query.set('date_from', params.dateFrom)
|
||||
if (params?.dateTo) query.set('date_to', params.dateTo)
|
||||
if (params?.page) query.set('page', String(params.page))
|
||||
if (params?.perPage) query.set('per_page', String(params.perPage))
|
||||
const qs = query.size > 0 ? `?${query.toString()}` : ''
|
||||
return apiFetch<LateSlipLogsResponse>(`/api/v1/attendance/late-slip-logs${qs}`)
|
||||
}
|
||||
|
||||
export async function deleteLateSlipLog(id: number): Promise<ApiEnvelope<null>> {
|
||||
return apiFetch<ApiEnvelope<null>>(`/api/v1/attendance/late-slip-logs/${id}`, {
|
||||
method: 'DELETE',
|
||||
})
|
||||
}
|
||||
|
||||
export async function fetchUsers(params?: {
|
||||
sort?: string
|
||||
order?: 'asc' | 'desc'
|
||||
}): Promise<UsersResponse> {
|
||||
const query = new URLSearchParams()
|
||||
if (params?.sort) query.set('sort', params.sort)
|
||||
if (params?.order) query.set('order', params.order)
|
||||
const qs = query.size > 0 ? `?${query.toString()}` : ''
|
||||
return apiFetch<UsersResponse>(`/api/v1/users${qs}`)
|
||||
}
|
||||
|
||||
export async function deleteUser(userId: number): Promise<{ ok: boolean; message?: string }> {
|
||||
return apiFetch<{ ok: boolean; message?: string }>(`/api/v1/users/${userId}`, {
|
||||
method: 'DELETE',
|
||||
})
|
||||
}
|
||||
|
||||
export async function fetchNotificationAlerts(): Promise<NotificationAlertsResponse> {
|
||||
return apiFetch<NotificationAlertsResponse>('/api/v1/administrator/notifications/alerts')
|
||||
}
|
||||
|
||||
export async function saveNotificationAlerts(
|
||||
subjects: Record<string, string[]>,
|
||||
): Promise<{ message?: string }> {
|
||||
return apiFetch<{ message?: string }>('/api/v1/administrator/notifications/alerts', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ subjects }),
|
||||
})
|
||||
}
|
||||
|
||||
export async function fetchPrintNotificationRecipients(): Promise<PrintNotificationRecipientsResponse> {
|
||||
return apiFetch<PrintNotificationRecipientsResponse>(
|
||||
'/api/v1/administrator/notifications/print-recipients',
|
||||
)
|
||||
}
|
||||
|
||||
export async function savePrintNotificationRecipients(
|
||||
notify: Record<string, number | boolean>,
|
||||
): Promise<{ message?: string }> {
|
||||
return apiFetch<{ message?: string }>(
|
||||
'/api/v1/administrator/notifications/print-recipients',
|
||||
{
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ notify }),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
export async function fetchFamilyAdminIndex(params?: {
|
||||
studentId?: number | null
|
||||
guardianId?: number | null
|
||||
}): Promise<FamilyAdminIndexResponse> {
|
||||
const query = new URLSearchParams()
|
||||
if (params?.studentId) query.set('student_id', String(params.studentId))
|
||||
if (params?.guardianId) query.set('guardian_id', String(params.guardianId))
|
||||
const qs = query.size > 0 ? `?${query.toString()}` : ''
|
||||
return apiFetch<FamilyAdminIndexResponse>(`/api/v1/family-admin${qs}`)
|
||||
}
|
||||
|
||||
export async function fetchPaypalTransactions(params?: {
|
||||
q?: string
|
||||
perPage?: number
|
||||
}): Promise<PaypalTransactionsResponse> {
|
||||
const query = new URLSearchParams()
|
||||
if (params?.q) query.set('q', params.q)
|
||||
if (params?.perPage) query.set('per_page', String(params.perPage))
|
||||
const qs = query.size > 0 ? `?${query.toString()}` : ''
|
||||
return apiFetch<PaypalTransactionsResponse>(`/api/v1/paypal-transactions${qs}`)
|
||||
}
|
||||
|
||||
export async function fetchPaypalTransactionsCsv(params?: { q?: string }): Promise<Blob> {
|
||||
const headers = new Headers({ Accept: 'text/csv' })
|
||||
const token = getStoredToken()
|
||||
if (token) headers.set('Authorization', `Bearer ${token}`)
|
||||
const query = new URLSearchParams()
|
||||
if (params?.q) query.set('q', params.q)
|
||||
const suffix = query.size > 0 ? `?${query.toString()}` : ''
|
||||
const res = await fetch(apiUrl(`/api/v1/paypal-transactions/csv${suffix}`), { headers })
|
||||
if (!res.ok) throw new Error(`HTTP ${res.status}`)
|
||||
return res.blob()
|
||||
}
|
||||
|
||||
export async function fetchNavMenu(): Promise<NavMenuResponse> {
|
||||
return apiFetch<NavMenuResponse>('/api/v1/nav-builder/menu')
|
||||
}
|
||||
@@ -208,14 +943,95 @@ export async function fetchReportCardAcknowledgement(
|
||||
)
|
||||
}
|
||||
|
||||
export async function fetchClassProgressGroups(): Promise<ClassProgressGroupsResponse> {
|
||||
return apiFetch<ClassProgressGroupsResponse>('/api/v1/class-progress?group_by_week=1')
|
||||
export async function fetchClassProgressGroups(params?: {
|
||||
classSectionId?: number | null
|
||||
status?: string | null
|
||||
weekStart?: string | null
|
||||
weekEnd?: string | null
|
||||
subject?: string | null
|
||||
page?: number
|
||||
perPage?: number
|
||||
}): Promise<ClassProgressGroupsResponse> {
|
||||
const query = new URLSearchParams()
|
||||
query.set('group_by_week', '1')
|
||||
if (params?.classSectionId) query.set('class_section_id', String(params.classSectionId))
|
||||
if (params?.status) query.set('status', params.status)
|
||||
if (params?.weekStart) query.set('week_start', params.weekStart)
|
||||
if (params?.weekEnd) query.set('week_end', params.weekEnd)
|
||||
if (params?.subject) query.set('subject', params.subject)
|
||||
if (params?.page) query.set('page', String(params.page))
|
||||
if (params?.perPage) query.set('per_page', String(params.perPage))
|
||||
return apiFetch<ClassProgressGroupsResponse>(`/api/v1/class-progress?${query.toString()}`)
|
||||
}
|
||||
|
||||
export async function fetchClassProgressDetail(id: number): Promise<ClassProgressShowResponse> {
|
||||
return apiFetch<ClassProgressShowResponse>(`/api/v1/class-progress/${id}`)
|
||||
}
|
||||
|
||||
export async function fetchClassProgressMeta(params?: {
|
||||
classId?: number | null
|
||||
sundayCount?: number | null
|
||||
}): Promise<ClassProgressMetaResponse> {
|
||||
const query = new URLSearchParams()
|
||||
if (params?.classId) query.set('class_id', String(params.classId))
|
||||
if (params?.sundayCount) query.set('sunday_count', String(params.sundayCount))
|
||||
const qs = query.size > 0 ? `?${query.toString()}` : ''
|
||||
return apiFetch<ClassProgressMetaResponse>(`/api/v1/class-progress/meta${qs}`)
|
||||
}
|
||||
|
||||
export async function fetchStudentScoreCard(studentId: number): Promise<StudentScoreCardResponse> {
|
||||
return apiFetch<StudentScoreCardResponse>(`/api/v1/students/${studentId}/score-card`)
|
||||
}
|
||||
|
||||
export async function fetchAdministratorEmergencyContacts(params?: {
|
||||
parentId?: number | null
|
||||
parentIds?: number[]
|
||||
}): Promise<EmergencyContactGroupsResponse> {
|
||||
const query = new URLSearchParams()
|
||||
if (params?.parentId) query.set('parent_id', String(params.parentId))
|
||||
for (const id of params?.parentIds ?? []) {
|
||||
query.append('parent_ids[]', String(id))
|
||||
}
|
||||
const qs = query.size > 0 ? `?${query.toString()}` : ''
|
||||
return apiFetch<EmergencyContactGroupsResponse>(`/api/v1/administrator/emergency-contacts${qs}`)
|
||||
}
|
||||
|
||||
export async function fetchAdministratorEmergencyContact(
|
||||
contactId: number,
|
||||
parentId: number,
|
||||
): Promise<EmergencyContactShowResponse> {
|
||||
return apiFetch<EmergencyContactShowResponse>(
|
||||
`/api/v1/administrator/emergency-contacts/${contactId}?parent_id=${encodeURIComponent(String(parentId))}`,
|
||||
)
|
||||
}
|
||||
|
||||
export async function updateAdministratorEmergencyContact(
|
||||
contactId: number,
|
||||
payload: {
|
||||
parent_id: number
|
||||
name: string
|
||||
cellphone: string
|
||||
email?: string | null
|
||||
relation?: string | null
|
||||
},
|
||||
): Promise<EmergencyContactShowResponse> {
|
||||
return apiFetch<EmergencyContactShowResponse>(`/api/v1/administrator/emergency-contacts/${contactId}`, {
|
||||
method: 'PATCH',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
}
|
||||
|
||||
export async function deleteAdministratorEmergencyContact(
|
||||
contactId: number,
|
||||
parentId: number,
|
||||
): Promise<{ ok: true }> {
|
||||
return apiFetch<{ ok: true }>(
|
||||
`/api/v1/administrator/emergency-contacts/${contactId}?parent_id=${encodeURIComponent(String(parentId))}`,
|
||||
{ method: 'DELETE' },
|
||||
)
|
||||
}
|
||||
|
||||
export async function updateParentProfile(
|
||||
payload: Required<
|
||||
Pick<
|
||||
|
||||
+838
-2
@@ -87,6 +87,120 @@ export type NavBuilderDataResponse = ApiEnvelope<{ data: NavBuilderData }>
|
||||
export type NavBuilderSaveResponse = ApiEnvelope<{ id: number }>
|
||||
export type NavBuilderDeleteResponse = ApiEnvelope<null>
|
||||
|
||||
export type AdministratorDashboardMetricsResponse = {
|
||||
counts?: {
|
||||
students?: number
|
||||
teachers?: number
|
||||
teacherAssistants?: number
|
||||
admins?: number
|
||||
parents?: number
|
||||
}
|
||||
recentActivities?: Array<{
|
||||
login_time?: string | null
|
||||
email?: string | null
|
||||
}>
|
||||
meta?: {
|
||||
schoolYear?: string | null
|
||||
semester?: string | null
|
||||
}
|
||||
}
|
||||
|
||||
export type AdministratorDashboardSearchResponse = {
|
||||
query: string
|
||||
results: {
|
||||
users?: Record<string, unknown>[]
|
||||
students?: Record<string, unknown>[]
|
||||
parents?: Record<string, unknown>[]
|
||||
staff?: Record<string, unknown>[]
|
||||
emergency_contacts?: Record<string, unknown>[]
|
||||
}
|
||||
scope_used?: string
|
||||
scope_label?: string
|
||||
total_found?: number
|
||||
}
|
||||
|
||||
export type AdministratorAbsenceRow = {
|
||||
date?: string | null
|
||||
status?: string | null
|
||||
reason?: string | null
|
||||
}
|
||||
|
||||
export type AdministratorAbsenceFormResponse = {
|
||||
admin_name?: string | null
|
||||
semester?: string | null
|
||||
schoolYear?: string | null
|
||||
existing?: AdministratorAbsenceRow[]
|
||||
availableDates?: string[]
|
||||
}
|
||||
|
||||
export type AdministratorAbsenceSubmitResponse = {
|
||||
message?: string
|
||||
saved?: number
|
||||
dates?: string[]
|
||||
}
|
||||
|
||||
export type AdministratorDailyAttendanceEntry = {
|
||||
date?: string | null
|
||||
status?: string | null
|
||||
reason?: string | null
|
||||
is_reported?: string | null
|
||||
modified_by?: string | number | null
|
||||
}
|
||||
|
||||
export type AdministratorDailyAttendanceSummary = {
|
||||
total_presence?: number
|
||||
total_late?: number
|
||||
total_absence?: number
|
||||
total_attendance?: number
|
||||
}
|
||||
|
||||
export type AdministratorDailyAttendanceStudent = {
|
||||
id: number
|
||||
firstname?: string | null
|
||||
lastname?: string | null
|
||||
school_id?: string | null
|
||||
}
|
||||
|
||||
export type AdministratorDailyAttendanceSection = {
|
||||
id?: number
|
||||
class_id?: number
|
||||
class_section_id?: number | string
|
||||
class_section_name?: string | null
|
||||
}
|
||||
|
||||
export type AdministratorDailyAttendanceResponse = {
|
||||
attendance_data?: Record<string, Record<string, AdministratorDailyAttendanceEntry[]>>
|
||||
attendance_record?: Record<string, Record<string, AdministratorDailyAttendanceSummary>>
|
||||
students_by_section?: Record<string, AdministratorDailyAttendanceStudent[]>
|
||||
grades?: Record<string, AdministratorDailyAttendanceSection[]>
|
||||
dates_by_section?: Record<string, string[]>
|
||||
date_list?: string[]
|
||||
no_school_days?: Record<string, boolean>
|
||||
total_passed_days?: number
|
||||
semester?: string | null
|
||||
school_year?: string | null
|
||||
current_admin_name?: string | null
|
||||
}
|
||||
|
||||
export type AdministratorAdminAttendanceRow = {
|
||||
user_id?: number
|
||||
firstname?: string | null
|
||||
lastname?: string | null
|
||||
email?: string | null
|
||||
role_name?: string | null
|
||||
role_slug?: string | null
|
||||
status?: string | null
|
||||
reason?: string | null
|
||||
date?: string | null
|
||||
}
|
||||
|
||||
export type AdministratorAdminAttendanceResponse = {
|
||||
semester?: string | null
|
||||
school_year?: string | null
|
||||
date?: string | null
|
||||
admins_grid?: AdministratorAdminAttendanceRow[]
|
||||
}
|
||||
|
||||
export type ParentAttendanceRow = {
|
||||
firstname: string
|
||||
lastname: string
|
||||
@@ -158,6 +272,646 @@ export type ContactSubmitResponse = {
|
||||
message?: string
|
||||
}
|
||||
|
||||
export type BroadcastEmailParentOption = {
|
||||
id: number
|
||||
firstname?: string | null
|
||||
lastname?: string | null
|
||||
email?: string | null
|
||||
school_id?: string | null
|
||||
}
|
||||
|
||||
export type BroadcastEmailSenderOption = {
|
||||
key: string
|
||||
label: string
|
||||
}
|
||||
|
||||
export type BroadcastEmailOptionsResponse = {
|
||||
ok: true
|
||||
parents: BroadcastEmailParentOption[]
|
||||
fromOptions: BroadcastEmailSenderOption[]
|
||||
}
|
||||
|
||||
export type BroadcastEmailSendResponse = {
|
||||
ok: boolean
|
||||
message?: string
|
||||
stats?: {
|
||||
mode?: string
|
||||
sent?: number
|
||||
attempted?: number
|
||||
failed?: number
|
||||
}
|
||||
}
|
||||
|
||||
export type SchoolCalendarDetailRow = {
|
||||
id: number
|
||||
title: string
|
||||
description?: string
|
||||
event_type?: string | null
|
||||
date: string
|
||||
notify_parent?: number
|
||||
notify_teacher?: number
|
||||
notify_admin?: number
|
||||
no_school?: number
|
||||
semester?: string
|
||||
school_year?: string
|
||||
created_at?: string | null
|
||||
updated_at?: string | null
|
||||
}
|
||||
|
||||
export type SchoolCalendarOptionsResponse = ApiEnvelope<{
|
||||
event_types: string[]
|
||||
defaults: {
|
||||
school_year?: string | null
|
||||
semester?: string | null
|
||||
}
|
||||
}>
|
||||
|
||||
export type SchoolCalendarListResponse = ApiEnvelope<{
|
||||
events: SchoolCalendarEventRow[]
|
||||
}>
|
||||
|
||||
export type SchoolCalendarShowResponse = ApiEnvelope<{
|
||||
event: SchoolCalendarDetailRow
|
||||
}>
|
||||
|
||||
export type ClassSectionRow = {
|
||||
id: number
|
||||
class_id?: number | null
|
||||
class_section_id?: number | null
|
||||
class_section_name?: string | null
|
||||
class_name?: string | null
|
||||
semester?: string | null
|
||||
school_year?: string | null
|
||||
created_at?: string | null
|
||||
updated_at?: string | null
|
||||
}
|
||||
|
||||
export type ClassSectionsResponse = ApiEnvelope<{
|
||||
sections: ClassSectionRow[]
|
||||
meta?: {
|
||||
current_page?: number
|
||||
per_page?: number
|
||||
total?: number
|
||||
last_page?: number
|
||||
}
|
||||
}>
|
||||
|
||||
export type ClassSectionShowResponse = ApiEnvelope<{
|
||||
section: ClassSectionRow
|
||||
}>
|
||||
|
||||
export type StudentAssignmentRow = {
|
||||
student_id: number
|
||||
name: string
|
||||
age?: number | string | null
|
||||
email?: string | null
|
||||
phone?: string | null
|
||||
registration_grade?: string | null
|
||||
class_section_name?: string | null
|
||||
class_section_names?: string[]
|
||||
class_section_ids?: number[]
|
||||
new_student?: string | null
|
||||
registration_date?: string | null
|
||||
school_year?: string | null
|
||||
semester?: string | null
|
||||
}
|
||||
|
||||
export type StudentAssignmentOption = {
|
||||
id: number
|
||||
class_section_id: number
|
||||
class_section_name: string
|
||||
school_year?: string | null
|
||||
}
|
||||
|
||||
export type StudentAssignmentsResponse = {
|
||||
ok: true
|
||||
students: StudentAssignmentRow[]
|
||||
classes: StudentAssignmentOption[]
|
||||
schoolYears: string[]
|
||||
selectedYear?: string | null
|
||||
currentYear?: string | null
|
||||
isCurrentYear?: boolean
|
||||
}
|
||||
|
||||
export type ExamDraftRow = {
|
||||
id: number
|
||||
teacher_id: number
|
||||
class_section_id: number
|
||||
class_section_name?: string | null
|
||||
semester?: string | null
|
||||
school_year?: string | null
|
||||
exam_type?: string | null
|
||||
draft_title?: string | null
|
||||
description?: string | null
|
||||
teacher_file?: string | null
|
||||
teacher_filename?: string | null
|
||||
status?: string | null
|
||||
admin_id?: number | null
|
||||
admin_comments?: string | null
|
||||
reviewed_at?: string | null
|
||||
final_file?: string | null
|
||||
final_filename?: string | null
|
||||
final_pdf_file?: string | null
|
||||
version?: number | null
|
||||
previous_draft_id?: number | null
|
||||
is_legacy?: boolean | number | null
|
||||
teacher_first?: string | null
|
||||
teacher_last?: string | null
|
||||
admin_first?: string | null
|
||||
admin_last?: string | null
|
||||
}
|
||||
|
||||
export type ExamDraftAdminResponse = {
|
||||
ok: true
|
||||
drafts: ExamDraftRow[]
|
||||
class_sections: Array<{ class_section_id: number; class_section_name: string }>
|
||||
legacy_by_class: Record<
|
||||
string,
|
||||
{
|
||||
class_section_id: number
|
||||
class_section_name: string
|
||||
items: ExamDraftRow[]
|
||||
}
|
||||
>
|
||||
exam_types: string[]
|
||||
status_options: string[]
|
||||
school_year?: string | null
|
||||
semester?: string | null
|
||||
allowed_extensions?: string[]
|
||||
max_upload_bytes?: number
|
||||
}
|
||||
|
||||
export type GradingOverviewStudentRow = {
|
||||
id: number
|
||||
school_id?: string | null
|
||||
firstname?: string | null
|
||||
lastname?: string | null
|
||||
class_id?: number
|
||||
ptap?: number | string | null
|
||||
semester_score?: number | string | null
|
||||
attendance?: number | string | null
|
||||
homework_avg?: number | string | null
|
||||
project_avg?: number | string | null
|
||||
quiz_avg?: number | string | null
|
||||
participation?: number | string | null
|
||||
midterm_exam?: number | string | null
|
||||
final_exam?: number | string | null
|
||||
matched_biz_csid?: number | null
|
||||
matched_pk_csid?: number | null
|
||||
placement_level?: string | null
|
||||
}
|
||||
|
||||
export type GradingOverviewResponse = {
|
||||
ok: true
|
||||
grades: Record<string, Array<{ class_section_id: number; class_section_name: string }>>
|
||||
students_by_section: Record<string, GradingOverviewStudentRow[]>
|
||||
semester?: string | null
|
||||
school_year?: string | null
|
||||
requested_class_id?: number | null
|
||||
semester_options?: string[]
|
||||
scores_released?: boolean
|
||||
scores_released_fall?: boolean
|
||||
scores_released_spring?: boolean
|
||||
score_locks?: Record<string, boolean>
|
||||
}
|
||||
|
||||
export type IpBanRow = {
|
||||
id: number
|
||||
ip_address?: string | null
|
||||
attempts?: number
|
||||
last_attempt_at?: string | null
|
||||
blocked_until?: string | null
|
||||
is_active?: boolean
|
||||
created_at?: string | null
|
||||
updated_at?: string | null
|
||||
}
|
||||
|
||||
export type IpBansResponse = ApiEnvelope<{
|
||||
bans: IpBanRow[]
|
||||
meta?: {
|
||||
current_page?: number
|
||||
per_page?: number
|
||||
total?: number
|
||||
last_page?: number
|
||||
}
|
||||
}>
|
||||
|
||||
export type LateSlipLogRow = {
|
||||
id: number
|
||||
school_year?: string | null
|
||||
semester?: string | null
|
||||
student_name?: string | null
|
||||
slip_date?: string | null
|
||||
time_in?: string | null
|
||||
grade?: string | null
|
||||
reason?: string | null
|
||||
admin_name?: string | null
|
||||
printed_by?: string | null
|
||||
printed_at?: string | null
|
||||
created_at?: string | null
|
||||
updated_at?: string | null
|
||||
}
|
||||
|
||||
export type LateSlipLogsResponse = ApiEnvelope<{
|
||||
logs: LateSlipLogRow[]
|
||||
meta?: {
|
||||
current_page?: number
|
||||
per_page?: number
|
||||
total?: number
|
||||
last_page?: number
|
||||
}
|
||||
}>
|
||||
|
||||
export type UserListRow = {
|
||||
user?: {
|
||||
id?: number
|
||||
firstname?: string | null
|
||||
lastname?: string | null
|
||||
email?: string | null
|
||||
status?: string | null
|
||||
cellphone?: string | null
|
||||
gender?: string | null
|
||||
address_street?: string | null
|
||||
city?: string | null
|
||||
state?: string | null
|
||||
zip?: string | null
|
||||
school_year?: string | null
|
||||
semester?: string | null
|
||||
[key: string]: unknown
|
||||
} | null
|
||||
roles?: Array<{ id?: number; name?: string | null; slug?: string | null }>
|
||||
role_ids?: number[]
|
||||
parent_type?: string
|
||||
second_from_parents?: string
|
||||
}
|
||||
|
||||
export type UsersResponse = {
|
||||
ok: true
|
||||
users: UserListRow[]
|
||||
}
|
||||
|
||||
export type NotificationAdminRow = {
|
||||
id: number
|
||||
firstname?: string | null
|
||||
lastname?: string | null
|
||||
email?: string | null
|
||||
}
|
||||
|
||||
export type NotificationAlertsResponse = {
|
||||
admins: NotificationAdminRow[]
|
||||
subjects: Record<string, string>
|
||||
assignedSubjects: Record<string, Record<string, boolean>>
|
||||
tableReady: boolean
|
||||
}
|
||||
|
||||
export type PrintNotificationRecipientsResponse = {
|
||||
admins: NotificationAdminRow[]
|
||||
assigned: Record<string, boolean>
|
||||
tableReady: boolean
|
||||
}
|
||||
|
||||
export type FamilyGuardianRow = {
|
||||
user_id?: number
|
||||
firstname?: string | null
|
||||
lastname?: string | null
|
||||
email?: string | null
|
||||
cellphone?: string | null
|
||||
relation?: string | null
|
||||
is_primary?: boolean
|
||||
receive_emails?: boolean
|
||||
receive_sms?: boolean
|
||||
}
|
||||
|
||||
export type FamilyStudentRow = {
|
||||
id?: number
|
||||
firstname?: string | null
|
||||
lastname?: string | null
|
||||
school_id?: string | null
|
||||
class_section_name?: string | null
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type FamilyRow = {
|
||||
id: number
|
||||
family_code?: string
|
||||
household_name?: string
|
||||
address_line1?: string
|
||||
address_line2?: string
|
||||
city?: string
|
||||
state?: string
|
||||
postal_code?: string
|
||||
country?: string
|
||||
primary_phone?: string
|
||||
preferred_lang?: string
|
||||
preferred_contact_method?: string
|
||||
is_active?: boolean
|
||||
is_primary_home?: boolean
|
||||
guardians?: FamilyGuardianRow[]
|
||||
students?: FamilyStudentRow[]
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type FamilyAdminIndexResponse = ApiEnvelope<{
|
||||
student?: { id?: number; firstname?: string | null; lastname?: string | null } | null
|
||||
families: FamilyRow[]
|
||||
guardians: Record<string, unknown>[]
|
||||
students: Record<string, unknown>[]
|
||||
searchStudents: Record<string, unknown>[]
|
||||
searchGuardians: NotificationAdminRow[]
|
||||
resolved_student_id?: number | null
|
||||
}>
|
||||
|
||||
export type PaypalTransactionRow = {
|
||||
id: number
|
||||
transaction_id?: string | null
|
||||
order_id?: string | null
|
||||
parent_school_id?: string | null
|
||||
payer_email?: string | null
|
||||
amount?: number
|
||||
net_amount?: number
|
||||
currency?: string | null
|
||||
status?: string | null
|
||||
event_type?: string | null
|
||||
created_at?: string | null
|
||||
}
|
||||
|
||||
export type PaypalTransactionsResponse = {
|
||||
ok: true
|
||||
transactions: PaypalTransactionRow[]
|
||||
pagination?: {
|
||||
current_page?: number
|
||||
per_page?: number
|
||||
total?: number
|
||||
last_page?: number
|
||||
}
|
||||
}
|
||||
|
||||
export type RemovedStudentRow = {
|
||||
id: number
|
||||
school_id?: string | null
|
||||
firstname?: string | null
|
||||
lastname?: string | null
|
||||
gender?: string | null
|
||||
age?: number | string | null
|
||||
class_sections?: string[]
|
||||
class_section_name?: string | null
|
||||
}
|
||||
|
||||
export type RemovedStudentsResponse = {
|
||||
ok: true
|
||||
active_students: RemovedStudentRow[]
|
||||
removed_students: RemovedStudentRow[]
|
||||
school_year?: string | null
|
||||
}
|
||||
|
||||
export type StudentPromotionTotalsRow = {
|
||||
class_id?: number | null
|
||||
class_section_id?: number | null
|
||||
class_section_name?: string | null
|
||||
total?: number
|
||||
}
|
||||
|
||||
export type StudentPromotionTotalsResponse = {
|
||||
ok: true
|
||||
year?: string | null
|
||||
rows: StudentPromotionTotalsRow[]
|
||||
}
|
||||
|
||||
export type StudentDirectoryRow = {
|
||||
id: number
|
||||
school_id?: string | null
|
||||
firstname?: string | null
|
||||
lastname?: string | null
|
||||
dob?: string | null
|
||||
age?: number | null
|
||||
gender?: string | null
|
||||
is_active?: boolean | number | null
|
||||
registration_grade?: string | null
|
||||
is_new?: boolean | number | null
|
||||
photo_consent?: boolean | number | null
|
||||
parent_id?: number | null
|
||||
registration_date?: string | null
|
||||
tuition_paid?: boolean | number | null
|
||||
semester?: string | null
|
||||
year_of_registration?: string | number | null
|
||||
school_year?: string | null
|
||||
medical_conditions?: string | null
|
||||
allergies?: string | null
|
||||
}
|
||||
|
||||
export type StudentDirectoryResponse = {
|
||||
ok: true
|
||||
students: StudentDirectoryRow[]
|
||||
school_year?: string | null
|
||||
current_year?: string | null
|
||||
}
|
||||
|
||||
export type StudentParentResponse = {
|
||||
ok: true
|
||||
student_id: number
|
||||
parent?: {
|
||||
id?: number
|
||||
firstname?: string | null
|
||||
lastname?: string | null
|
||||
email?: string | null
|
||||
cellphone?: string | null
|
||||
} | null
|
||||
}
|
||||
|
||||
export type StudentEmergencyContactResponse = {
|
||||
ok: true
|
||||
student_id: number
|
||||
rows: Array<Record<string, unknown>>
|
||||
}
|
||||
|
||||
export type TeacherClassAssignmentRow = {
|
||||
teacher_id: number
|
||||
firstname?: string | null
|
||||
lastname?: string | null
|
||||
name?: string | null
|
||||
email?: string | null
|
||||
cellphone?: string | null
|
||||
role?: string | null
|
||||
school_year?: string | null
|
||||
main_assignments?: Array<{
|
||||
section_id?: number
|
||||
class_section_name?: string | null
|
||||
role?: string | null
|
||||
semester?: string | null
|
||||
school_year?: string | null
|
||||
}>
|
||||
ta_assignments?: Array<{
|
||||
section_id?: number
|
||||
class_section_name?: string | null
|
||||
role?: string | null
|
||||
semester?: string | null
|
||||
school_year?: string | null
|
||||
}>
|
||||
}
|
||||
|
||||
export type TeacherClassOption = {
|
||||
class_section_id: number
|
||||
class_section_name: string
|
||||
class_id?: number | null
|
||||
class_name?: string | null
|
||||
teacher_role?: string | null
|
||||
school_year?: string | null
|
||||
semester?: string | null
|
||||
}
|
||||
|
||||
export type TeacherClassAssignmentsResponse = {
|
||||
ok: true
|
||||
school_year?: string | null
|
||||
teachers: TeacherClassAssignmentRow[]
|
||||
classes: TeacherClassOption[]
|
||||
}
|
||||
|
||||
export type TeacherSubmissionTeacherRow = {
|
||||
id: number
|
||||
label: string
|
||||
role_key?: string | null
|
||||
}
|
||||
|
||||
export type TeacherSubmissionReportRow = {
|
||||
class_section?: string | null
|
||||
class_section_id?: number
|
||||
teachers?: TeacherSubmissionTeacherRow[]
|
||||
midterm_score_status?: string | null
|
||||
midterm_comment_status?: string | null
|
||||
participation_status?: string | null
|
||||
ptap_comment_status?: string | null
|
||||
attendance_status?: string | null
|
||||
missing_items?: string[]
|
||||
student_count?: number
|
||||
}
|
||||
|
||||
export type TeacherSubmissionsResponse = {
|
||||
rows: TeacherSubmissionReportRow[]
|
||||
semester?: string | null
|
||||
schoolYear?: string | null
|
||||
notificationHistory?: Record<string, unknown>
|
||||
summary?: {
|
||||
total_items?: number
|
||||
missing_items?: number
|
||||
submitted_items?: number
|
||||
submission_percentage?: number
|
||||
}
|
||||
}
|
||||
|
||||
export type SubjectCurriculumClassRow = {
|
||||
id: number
|
||||
class_name: string
|
||||
school_year?: string | null
|
||||
}
|
||||
|
||||
export type SubjectCurriculumEntryRow = {
|
||||
id: number
|
||||
class_id: number
|
||||
class_name?: string | null
|
||||
subject: string
|
||||
unit_number?: number | string | null
|
||||
unit_title?: string | null
|
||||
chapter_name: string
|
||||
}
|
||||
|
||||
export type SubjectCurriculumResponse = {
|
||||
ok: true
|
||||
classes: SubjectCurriculumClassRow[]
|
||||
entries: SubjectCurriculumEntryRow[]
|
||||
subject_labels: Record<string, string>
|
||||
}
|
||||
|
||||
export type PublicCompetitionRow = {
|
||||
id: number
|
||||
title?: string | null
|
||||
class_section_id?: number | null
|
||||
semester?: string | null
|
||||
school_year?: string | null
|
||||
is_published?: boolean | number | null
|
||||
is_locked?: boolean | number | null
|
||||
published_at?: string | null
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type PublicCompetitionIndexResponse = {
|
||||
status: boolean
|
||||
data?: {
|
||||
competitions: PublicCompetitionRow[]
|
||||
}
|
||||
message?: string
|
||||
}
|
||||
|
||||
export type PublicCompetitionWinnerRow = {
|
||||
student_id?: number
|
||||
class_section_id?: number
|
||||
rank?: number
|
||||
score?: number | string | null
|
||||
prize_amount?: number | string | null
|
||||
firstname?: string | null
|
||||
lastname?: string | null
|
||||
class_section_name?: string | null
|
||||
name?: string | null
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type PublicCompetitionShowResponse = {
|
||||
status: boolean
|
||||
data?: {
|
||||
competition: PublicCompetitionRow
|
||||
winners_by_class: Record<string, PublicCompetitionWinnerRow[]>
|
||||
section_map: Record<string, string>
|
||||
question_counts: Record<string, number>
|
||||
}
|
||||
message?: string
|
||||
}
|
||||
|
||||
export type CompetitionScoresIndexCompetitionRow = {
|
||||
id: number
|
||||
title?: string | null
|
||||
class_section_id?: number | null
|
||||
is_locked?: boolean | number | null
|
||||
is_published?: boolean | number | null
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export type CompetitionScoresIndexResponse = {
|
||||
ok: true
|
||||
competitions: CompetitionScoresIndexCompetitionRow[]
|
||||
activeClassId?: number
|
||||
activeClassName?: string | null
|
||||
questionCounts?: Record<string, number>
|
||||
scoreCounts?: Record<string, number>
|
||||
studentTotal?: number
|
||||
sectionMap?: Record<string, string>
|
||||
schoolYear?: string | null
|
||||
semester?: string | null
|
||||
hasClasses?: boolean
|
||||
}
|
||||
|
||||
export type CompetitionScoreStudentRow = {
|
||||
id?: number
|
||||
student_id?: number
|
||||
school_id?: string | null
|
||||
firstname?: string | null
|
||||
lastname?: string | null
|
||||
}
|
||||
|
||||
export type CompetitionScoresEditResponse = {
|
||||
ok: boolean
|
||||
competition?: PublicCompetitionRow
|
||||
students?: CompetitionScoreStudentRow[]
|
||||
scoreMap?: Record<string, number | string>
|
||||
classSectionId?: number
|
||||
classSectionName?: string | null
|
||||
classStudentCount?: number
|
||||
questionCount?: number | null
|
||||
classSelectionLocked?: boolean
|
||||
isLocked?: boolean
|
||||
schoolYear?: string | null
|
||||
semester?: string | null
|
||||
message?: string
|
||||
}
|
||||
|
||||
/** Loose JSON payloads for complex parent dashboards (events, registration, attendance report form). */
|
||||
export type ParentEventsResponse = Record<string, unknown>
|
||||
export type ParentRegistrationResponse = Record<string, unknown>
|
||||
@@ -259,6 +1013,36 @@ export type StudentScoresResponse = {
|
||||
rows: StudentScoreRow[]
|
||||
}
|
||||
|
||||
export type StudentScoreCardStudent = {
|
||||
id: number
|
||||
firstname?: string | null
|
||||
lastname?: string | null
|
||||
school_id?: string | null
|
||||
}
|
||||
|
||||
export type StudentScoreCardRow = {
|
||||
school_year?: string | null
|
||||
semester?: string | null
|
||||
homework_avg?: number | string | null
|
||||
project_avg?: number | string | null
|
||||
participation_score?: number | string | null
|
||||
quiz_avg?: number | string | null
|
||||
test_avg?: number | string | null
|
||||
attendance_score?: number | string | null
|
||||
ptap_score?: number | string | null
|
||||
midterm_exam_score?: number | string | null
|
||||
semester_score?: number | string | null
|
||||
class_section_name?: string | null
|
||||
comments?: Record<string, string>
|
||||
year_score?: number | string | null
|
||||
}
|
||||
|
||||
export type StudentScoreCardResponse = {
|
||||
ok: true
|
||||
student: StudentScoreCardStudent
|
||||
rows: StudentScoreCardRow[]
|
||||
}
|
||||
|
||||
export type ReportCardStudentMetaRow = {
|
||||
id: number
|
||||
firstname: string
|
||||
@@ -289,6 +1073,7 @@ export type ClassProgressReportRow = {
|
||||
id: number
|
||||
teacher_name?: string | null
|
||||
class_section_name?: string | null
|
||||
class_section_id?: number | null
|
||||
subject?: string | null
|
||||
unit_title?: string | null
|
||||
status?: string | null
|
||||
@@ -296,9 +1081,12 @@ export type ClassProgressReportRow = {
|
||||
covered?: string | null
|
||||
homework?: string | null
|
||||
support_needed?: string | null
|
||||
flags?: string[]
|
||||
week_start?: string | null
|
||||
week_end?: string | null
|
||||
attachments?: { id?: number; original_name?: string | null; url?: string | null }[]
|
||||
created_at?: string | null
|
||||
updated_at?: string | null
|
||||
attachments?: { id?: number; name?: string | null; file_path?: string | null; download_url?: string | null }[]
|
||||
}
|
||||
|
||||
export type ClassProgressGroupRow = {
|
||||
@@ -316,10 +1104,58 @@ export type ClassProgressGroupsResponse = ApiEnvelope<{
|
||||
|
||||
export type ClassProgressShowResponse = ApiEnvelope<{
|
||||
report?: ClassProgressReportRow
|
||||
weekly_reports?: Record<string, ClassProgressReportRow>
|
||||
weekly_reports?: ClassProgressReportRow[]
|
||||
status_options?: Record<string, string>
|
||||
}>
|
||||
|
||||
export type ClassProgressMetaResponse = ApiEnvelope<{
|
||||
subject_sections?: Record<string, { label?: string; db_subject?: string }>
|
||||
status_options?: Record<string, string>
|
||||
sunday_options?: string[]
|
||||
curriculum?: Record<string, Array<Record<string, unknown>>>
|
||||
}>
|
||||
|
||||
export type EmergencyContactGroupRow = {
|
||||
parent_id: number
|
||||
parent_name?: string | null
|
||||
parent_phones?: string[]
|
||||
students?: Array<{
|
||||
id?: number
|
||||
student_id?: number
|
||||
firstname?: string | null
|
||||
lastname?: string | null
|
||||
}>
|
||||
contacts?: Array<{
|
||||
id: number
|
||||
parent_id?: number
|
||||
name?: string | null
|
||||
cellphone?: string | null
|
||||
email?: string | null
|
||||
relation?: string | null
|
||||
semester?: string | null
|
||||
school_year?: string | null
|
||||
}>
|
||||
}
|
||||
|
||||
export type EmergencyContactGroupsResponse = {
|
||||
ok: true
|
||||
groups: EmergencyContactGroupRow[]
|
||||
}
|
||||
|
||||
export type EmergencyContactShowResponse = {
|
||||
ok: true
|
||||
contact: {
|
||||
id: number
|
||||
parent_id: number
|
||||
name?: string | null
|
||||
cellphone?: string | null
|
||||
email?: string | null
|
||||
relation?: string | null
|
||||
semester?: string | null
|
||||
school_year?: string | null
|
||||
}
|
||||
}
|
||||
|
||||
export type ParentRegistrationOverviewResponse = {
|
||||
ok: true
|
||||
parent: ParentProfileRecord | null
|
||||
|
||||
Reference in New Issue
Block a user