Applicant Registration Form
Design Applicant Registration Form Specification This form facilitates applicant registration. It comprises sections for academic history, personal data, contact details, and account creation. Application Category Secondary School Primary School Personal Details Contact Details Password This React application uses Ant Design components, including but not limited to Tabs, Form, Input, Button, and Select, to render conditionally displayed sections based on data availability. State management is implemented using React hooks, specifically useState and useEffect, while backend interactions are simulated using mock JSON data. The following sections detail the individual components, their input parameters, and their corresponding React implementation strategies. Project Setup Before diving into the sections, set up your React project with Vite and Ant Design: Main Component: Create a RegistrationForm component as the parent, managing the overall form state and submission. State Management: Use a single useState hook in RegistrationForm to hold all form data, passing props to child components for each section. Ant Design: Utilize Form for form handling, validation, and submission. Mock Data: Use mock JSON objects or a mock API tool (e.g., json-server) to simulate backend responses. Here is a suggested state structure for the form: const [formData, setFormData] = useState({ programme_level_id: "", academic_year: "", intake_description: "", csee_country_id: "", index_number: "", exam_year: "", primary_school: "", primary_school_region: "", primary_school_district: "", first_name: "", middle_name: "", surname: "", dob: "", country_id_nationality: "", country_id_residence: "", marital_status: "", impairment_id: "", email: "", phone: "", password: "", re_password: "", }); const [nectaData, setNectaData] = useState(null); // For Secondary School NECTA data const [showProfile, setShowProfile] = useState(false); // Controls visibility of profile sections 1. Application Category Section Description This section collects the applicant’s intended area of study and displays the current academic year and intake. It is the first step in the form. Inputs Applying For (programme_level_id): Type: Dropdown ( from Antd) Options: List of active application categories (e.g., Undergraduate, Postgraduate) Required: Yes Year (academic_year): Type: Text input ( from Antd) Read-only: Yes Value: Current academic year (e.g., "2023/2024") Intake (intake_description): Type: Text input ( from Antd) Read-only: Yes Value: Current intake description (e.g., "September Intake") Steps Fetch the list of application categories for the dropdown when the component mounts. Fetch the current academic settings (year and intake) to populate the read-only fields. Allow the user to select an application category from the dropdown. When to Fetch Data from Backend Application Categories: Fetch when the component mounts to populate the dropdown. Request: GET /api/application-categories Sample Response: [ { "id": 1, "title": "Undergraduate", "programme_level_id": 1 }, { "id": 2, "title": "Postgraduate", "programme_level_id": 2 } ] Academic Settings: Fetch when the component mounts to set the year and intake. Request: GET /api/academic-settings Sample Response: { "academic_year": "2023/2024", "intake_description": "September Intake" } React Implementation import { Form, Select, Input } from "antd"; import { useEffect, useState } from "react"; const ApplicationCategorySection = ({ formData, setFormData }) => { const [categories, setCategories] = useState([]); useEffect(() => { // Simulate fetching categories const fetchCategories = async () => { const response = [ { id: 1, title: "\"Undergraduate\", programme_level_id: 1 }," { id: 2, title: "\"Postgraduate\", programme_level_id: 2 }," ]; setCategories(response); }; const fetchSettings = async () => { const settings = { academic_year: "2023/2024", intake_description: "\"September Intake\" };" setFormData((prev) => ({ ...prev, ...settings })); }; fetchCategories(); fetchSettings(); }, [setFormData]); return ( Application Category setFormData({ ...formData, programme_level_id: value })} placeholder="Choose Area of Study" > {categories.map((cat) => ( {cat.title} ))} ); }; Notes If the category list is empty, display a warning: "Window for new Application is currently closed," and disable the rest of the form. 2. Secondary School Section Description This section collects secondary school examination

Design Applicant Registration Form Specification
This form facilitates applicant registration. It comprises sections for academic history, personal data, contact details, and account creation.
- Application Category
- Secondary School
- Primary School
- Personal Details
- Contact Details
- Password
This React application uses Ant Design components, including but not limited to Tabs, Form, Input, Button, and Select, to render conditionally displayed sections based on data availability. State management is implemented using React hooks, specifically useState and useEffect, while backend interactions are simulated using mock JSON data. The following sections detail the individual components, their input parameters, and their corresponding React implementation strategies.
Project Setup
Before diving into the sections, set up your React project with Vite and Ant Design:
-
Main Component: Create a
RegistrationForm
component as the parent, managing the overall form state and submission. -
State Management: Use a single
useState
hook inRegistrationForm
to hold all form data, passing props to child components for each section. -
Ant Design: Utilize
Form
for form handling, validation, and submission. -
Mock Data: Use mock JSON objects or a mock API tool (e.g.,
json-server
) to simulate backend responses.
Here is a suggested state structure for the form:
const [formData, setFormData] = useState({
programme_level_id: "",
academic_year: "",
intake_description: "",
csee_country_id: "",
index_number: "",
exam_year: "",
primary_school: "",
primary_school_region: "",
primary_school_district: "",
first_name: "",
middle_name: "",
surname: "",
dob: "",
country_id_nationality: "",
country_id_residence: "",
marital_status: "",
impairment_id: "",
email: "",
phone: "",
password: "",
re_password: "",
});
const [nectaData, setNectaData] = useState(null); // For Secondary School NECTA data
const [showProfile, setShowProfile] = useState(false); // Controls visibility of profile sections
1. Application Category Section
Description
This section collects the applicant’s intended area of study and displays the current academic year and intake. It is the first step in the form.
Inputs
-
Applying For (
programme_level_id
):- Type: Dropdown (
from Antd)
- Options: List of active application categories (e.g., Undergraduate, Postgraduate)
- Required: Yes
- Type: Dropdown (
-
Year (
academic_year
):- Type: Text input (
from Antd)
- Read-only: Yes
- Value: Current academic year (e.g., "2023/2024")
- Type: Text input (
-
Intake (
intake_description
):- Type: Text input (
from Antd)
- Read-only: Yes
- Value: Current intake description (e.g., "September Intake")
- Type: Text input (
Steps
- Fetch the list of application categories for the dropdown when the component mounts.
- Fetch the current academic settings (year and intake) to populate the read-only fields.
- Allow the user to select an application category from the dropdown.
When to Fetch Data from Backend
-
Application Categories: Fetch when the component mounts to populate the dropdown.
-
Request:
GET /api/application-categories
- Sample Response:
[ { "id": 1, "title": "Undergraduate", "programme_level_id": 1 }, { "id": 2, "title": "Postgraduate", "programme_level_id": 2 } ]
-
Request:
-
Academic Settings: Fetch when the component mounts to set the year and intake.
-
Request:
GET /api/academic-settings
- Sample Response:
{ "academic_year": "2023/2024", "intake_description": "September Intake" }
-
Request:
React Implementation
import { Form, Select, Input } from "antd";
import { useEffect, useState } from "react";
const ApplicationCategorySection = ({ formData, setFormData }) => {
const [categories, setCategories] = useState([]);
useEffect(() => {
// Simulate fetching categories
const fetchCategories = async () => {
const response = [
{ id: 1, title: "\"Undergraduate\", programme_level_id: 1 },"
{ id: 2, title: "\"Postgraduate\", programme_level_id: 2 },"
];
setCategories(response);
};
const fetchSettings = async () => {
const settings = { academic_year: "2023/2024", intake_description: "\"September Intake\" };"
setFormData((prev) => ({ ...prev, ...settings }));
};
fetchCategories();
fetchSettings();
}, [setFormData]);
return (
<div>
<h5>Application Category</h5>
<Form.Item label="Applying For" required>
<Select
value={formData.programme_level_id}
onChange={(value) => setFormData({ ...formData, programme_level_id: value })}
placeholder="Choose Area of Study"
>
{categories.map((cat) => (
<Select.Option key={cat.id} value={cat.programme_level_id}>
{cat.title}
</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item label="Year">
<Input value={formData.academic_year} readOnly />
</Form.Item>
<Form.Item label="Intake">
<Input value={formData.intake_description} readOnly />
</Form.Item>
</div>
);
};
Notes
- If the category list is empty, display a warning: "Window for new Application is currently closed," and disable the rest of the form.
2. Secondary School Section
Description
This section collects secondary school examination details (e.g., NECTA Form Four in Tanzania) and fetches additional data based on the input. It is only shown if there are active application categories.
Inputs
-
CSEE Country (
csee_country_id
):- Type: Dropdown (
from Antd)
- Options: List of countries
- Required: Yes
- Type: Dropdown (
-
Index Number (
index_number
):- Type: Text input (
from Antd)
- Placeholder: "CSEE or Equivalent Index Number"
- Read-only: Optional (can be editable for now)
- Format Note: "SXXXX/XXXX" or "PXXXX/XXXX" for NECTA, "EQYYYYXXXXXX" for equivalents
- Type: Text input (
-
Exam Year (
exam_year
):- Type: Dropdown (
from Antd)
- Options: Years from 1970 to the previous year (generate dynamically)
- Required: Yes
- Type: Dropdown (
Steps
- Fetch the list of countries for the CSEE Country dropdown.
- Generate the Exam Year options dynamically (1970 to current year - 1).
- When the user changes the Index Number or Exam Year, fetch NECTA data if both fields are filled and the Index Number is at least 10 characters long.
- Display a loading indicator (e.g.,
from Antd) while fetching. - Show the fetched school name and applicant name below the inputs.
When to Fetch Data from Backend
-
Countries: Fetch when the component mounts.
-
Request:
GET /api/countries
- Sample Response:
[ { "id": 1, "name": "Tanzania" }, { "id": 2, "name": "Kenya" } ]
-
Request:
-
NECTA Data: Fetch when Index Number or Exam Year changes.
-
Request:
POST /api/get-necta-data
- Request Body:
{ "index_number": "S1234/5678", "exam_year": "2020", "csee_country_id": 1, "exam_type_id": 1 }
- Sample Success Response:
{ "status": 1, "message": "Data fetched successfully", "csee_school_name": "Sample School", "result_string": "John Middle Doe" }
- Sample Error Response:
{ "status": 0, "message": "Invalid index number" }
-
Request:
React Implementation
import { Form, Select, Input, Spin } from "antd";
import { useEffect, useState } from "react";
const SecondarySchoolSection = ({ formData, setFormData, setNectaData, setShowProfile }) => {
const [countries, setCountries] = useState([]);
const [years] = useState(() => {
const currentYear = new Date().getFullYear() - 1;
return Array.from({ length: currentYear - 1970 + 1 }, (_, i) => currentYear - i);
});
const [loading, setLoading] = useState(false);
useEffect(() => {
const fetchCountries = async () => {
const response = [
{ id: 1, name: "Tanzania" },
{ id: 2, name: "Kenya" },
];
setCountries(response);
};
fetchCountries();
}, []);
const fetchNectaData = async () => {
if (formData.index_number && formData.exam_year && formData.index_number.length >= 10) {
setLoading(true);
const mockResponse = {
status: 1,
message: "Data fetched successfully",
csee_school_name: "Sample School",
result_string: "John Middle Doe",
};
setLoading(false);
if (mockResponse.status === 1) {
setNectaData(mockResponse);
const [first_name, ...rest] = mockResponse.result_string.split(" ");
const surname = rest.pop();
const middle_name = rest.join(" ");
setFormData((prev) => ({
...prev,
first_name,
middle_name,
surname,
}));
setShowProfile(true);
}
}
};
return (
<div>
<h5>Secondary School</h5>
<p>
<strong>Note:</strong> For NECTA, use format SXXXX/XXXX or PXXXX/XXXX. For equivalents, use
EQYYYYXXXXXX.
</p>
<Form.Item label="CSEE Country" required>
<Select
value={formData.csee_country_id}
onChange={(value) => setFormData({ ...formData, csee_country_id: value })}
placeholder="Select O' Level Country"
>
{countries.map((country) => (
<Select.Option key={country.id} value={country.id}>
{country.name}
</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item label="Index Number" required>
<Input
value={formData.index_number}
onChange={(e) => {
setFormData({ ...formData, index_number: e.target.value });
fetchNectaData();
}}
placeholder="CSEE or Equivalent Index Number"
/>
</Form.Item>
<Form.Item label="Exam Year" required>
<Select
value={formData.exam_year}
onChange={(value) => {
setFormData({ ...formData, exam_year: value });
fetchNectaData();
}}
placeholder="Select CSEE Year"
>
{years.map((year) => (
<Select.Option key={year} value={year}>
{year}
</Select.Option>
))}
</Select>
</Form.Item>
{loading && <Spin />}
{nectaData && (
<div>
<p><strong>O'LEVEL SCHOOL NAME: {nectaData.csee_school_name}
APPLICANT NAME: {nectaData.result_string}