145 lines
3.6 KiB
TypeScript
145 lines
3.6 KiB
TypeScript
import { apiFetch } from './http'
|
|
|
|
type TrophyApiEnvelope<T> = {
|
|
ok?: boolean
|
|
data?: T
|
|
}
|
|
|
|
export type TrophyStudent = {
|
|
student_id?: number
|
|
class_section_id?: number
|
|
name?: string
|
|
firstname?: string | null
|
|
lastname?: string | null
|
|
school_id?: string | null
|
|
gender?: string | null
|
|
fall_score?: number | null
|
|
spring_score?: number | null
|
|
year_score?: number | null
|
|
projected_trophy?: boolean
|
|
predicted?: boolean
|
|
actual?: boolean
|
|
status?: string
|
|
}
|
|
|
|
export type TrophyProjectionClassResult = {
|
|
section_id: number
|
|
section_name: string
|
|
students: TrophyStudent[]
|
|
threshold: number | null
|
|
trophy_count: number
|
|
student_count: number
|
|
scored_count: number
|
|
method: string
|
|
boys: number
|
|
girls: number
|
|
trophy_boys: number
|
|
trophy_girls: number
|
|
pct_boys: number
|
|
pct_girls: number
|
|
pct_trophy_boys: number
|
|
pct_trophy_girls: number
|
|
pct_trophy_total: number
|
|
}
|
|
|
|
export type TrophyProjectionPayload = {
|
|
selected_year: string
|
|
selected_percentile: number
|
|
years: string[]
|
|
class_results: TrophyProjectionClassResult[]
|
|
summary: Record<string, number>
|
|
}
|
|
|
|
export type TrophyWinnersClassResult = {
|
|
section_id: number
|
|
section_name: string
|
|
threshold: number | null
|
|
winners: TrophyStudent[]
|
|
student_count: number
|
|
boys: number
|
|
girls: number
|
|
trophy_boys: number
|
|
trophy_girls: number
|
|
pct_boys: number
|
|
pct_girls: number
|
|
pct_trophy_boys: number
|
|
pct_trophy_girls: number
|
|
pct_trophy_total: number
|
|
}
|
|
|
|
export type TrophyWinnersPayload = {
|
|
selected_year: string
|
|
selected_percentile: number
|
|
years: string[]
|
|
class_results: TrophyWinnersClassResult[]
|
|
summary: Record<string, number>
|
|
}
|
|
|
|
export type TrophyFinalClassResult = {
|
|
section_id: number
|
|
section_name: string
|
|
students: TrophyStudent[]
|
|
student_count: number
|
|
fall_threshold: number | null
|
|
year_threshold: number | null
|
|
predicted_count: number
|
|
actual_count: number
|
|
confirmed: number
|
|
surprises: number
|
|
missed: number
|
|
accuracy: number
|
|
}
|
|
|
|
export type TrophyGenderSummary = {
|
|
total: number
|
|
boys: number
|
|
girls: number
|
|
other: number
|
|
pct_boys: number
|
|
pct_girls: number
|
|
pct_other: number
|
|
}
|
|
|
|
export type TrophyFinalPayload = {
|
|
selected_year: string
|
|
selected_percentile: number
|
|
years: string[]
|
|
class_results: TrophyFinalClassResult[]
|
|
summary: Record<string, number>
|
|
winner_gender_summary: TrophyGenderSummary
|
|
all_gender_summary: TrophyGenderSummary
|
|
pass_gender_summary: TrophyGenderSummary
|
|
winner_stickers: Array<{ name: string; section: string }>
|
|
}
|
|
|
|
type TrophyFilters = {
|
|
school_year?: string
|
|
percentile?: string | number
|
|
}
|
|
|
|
function withQuery(path: string, params?: TrophyFilters) {
|
|
const qs = new URLSearchParams()
|
|
if (params?.school_year) qs.set('school_year', String(params.school_year))
|
|
if (params?.percentile !== undefined && String(params.percentile).trim() !== '') {
|
|
qs.set('percentile', String(params.percentile))
|
|
}
|
|
return qs.size > 0 ? `${path}?${qs.toString()}` : path
|
|
}
|
|
|
|
async function fetchTrophyPayload<T>(path: string, params?: TrophyFilters): Promise<T> {
|
|
const res = await apiFetch<TrophyApiEnvelope<T>>(withQuery(path, params))
|
|
return (res.data ?? {}) as T
|
|
}
|
|
|
|
export function fetchTrophyProjection(params?: TrophyFilters) {
|
|
return fetchTrophyPayload<TrophyProjectionPayload>('/api/v1/administrator/trophy', params)
|
|
}
|
|
|
|
export function fetchTrophyWinners(params?: TrophyFilters) {
|
|
return fetchTrophyPayload<TrophyWinnersPayload>('/api/v1/administrator/trophy/winners', params)
|
|
}
|
|
|
|
export function fetchTrophyFinal(params?: TrophyFilters) {
|
|
return fetchTrophyPayload<TrophyFinalPayload>('/api/v1/administrator/trophy/final', params)
|
|
}
|