fix apply the plan docs/alrahma_api_fix_plan_school_year_only_v7
Web Client CI/CD / Lint (ESLint + TypeScript) (push) Successful in 29s
Web Client CI/CD / Build (tsc + Vite) (push) Successful in 30s
Web Client CI/CD / Deploy to shared hosting (push) Successful in 33s

This commit is contained in:
root
2026-07-07 01:52:37 -04:00
parent b510f534fd
commit 4b78aafa65
18 changed files with 664 additions and 256 deletions
+30 -5
View File
@@ -1,22 +1,27 @@
import { type FormEvent, useEffect, useState } from 'react'
import { useNavigate } from 'react-router-dom'
import { createStaff, fetchStaffFormOptions, type RoleOption } from '../../api/staff'
import { ReadOnlyBanner, SchoolYearSelector } from '../../components/schoolYear'
import { useSchoolYear } from '../../context/SchoolYearContext'
export function StaffCreatePage() {
const navigate = useNavigate()
const { selectedSchoolYearName, isReadOnlyYear } = useSchoolYear()
const [roles, setRoles] = useState<RoleOption[]>([])
const [firstname, setFirstname] = useState('')
const [lastname, setLastname] = useState('')
const [email, setEmail] = useState('')
const [phone, setPhone] = useState('')
const [password, setPassword] = useState('')
const [roleId, setRoleId] = useState<number>(0)
const [status, setStatus] = useState('active')
const [error, setError] = useState<string | null>(null)
useEffect(() => {
let cancelled = false
;(async () => {
try {
const data = await fetchStaffFormOptions()
const data = await fetchStaffFormOptions({ school_year: selectedSchoolYearName ?? undefined })
if (cancelled) return
const list = data.roles ?? []
setRoles(list)
@@ -28,17 +33,21 @@ export function StaffCreatePage() {
return () => {
cancelled = true
}
}, [])
}, [selectedSchoolYearName])
async function onSubmit(e: FormEvent) {
e.preventDefault()
if (!selectedSchoolYearName) {
setError('Please select a school year.')
return
}
if (!roleId) {
setError('Please select a role.')
return
}
try {
await createStaff({ firstname, lastname, email, password, role_id: roleId })
navigate('/app/staff')
await createStaff({ firstname, lastname, email, phone, password, role_id: roleId, status, school_year: selectedSchoolYearName })
navigate(`/app/staff?school_year=${encodeURIComponent(selectedSchoolYearName)}`)
} catch (err) {
setError(err instanceof Error ? err.message : 'Unable to create staff.')
}
@@ -47,6 +56,11 @@ export function StaffCreatePage() {
return (
<div className="container mt-4">
<h2>Add Staff Member</h2>
<div className="d-flex justify-content-between align-items-center mb-3">
<div className="text-muted">School year: {selectedSchoolYearName ?? '—'}</div>
<SchoolYearSelector compact />
</div>
<ReadOnlyBanner />
{error ? <div className="alert alert-danger">{error}</div> : null}
<form onSubmit={(e) => void onSubmit(e)}>
<div className="mb-3">
@@ -89,6 +103,10 @@ export function StaffCreatePage() {
required
/>
</div>
<div className="mb-3">
<label className="form-label">Phone</label>
<input type="tel" className="form-control" value={phone} onChange={(e) => setPhone(e.target.value)} />
</div>
<div className="mb-3">
<label className="form-label">Role</label>
<select
@@ -104,7 +122,14 @@ export function StaffCreatePage() {
))}
</select>
</div>
<button type="submit" className="btn btn-success">
<div className="mb-3">
<label className="form-label">Status</label>
<select className="form-select" value={status} onChange={(e) => setStatus(e.target.value)}>
<option value="active">Active</option>
<option value="inactive">Inactive</option>
</select>
</div>
<button type="submit" className="btn btn-success" disabled={isReadOnlyYear || !selectedSchoolYearName}>
Create
</button>
</form>