diff --git a/src/Modules/Certificates/FeeStructureCertificate.jsx b/src/Modules/Certificates/FeeStructureCertificate.jsx
index 541876e8e..2d94d89c0 100644
--- a/src/Modules/Certificates/FeeStructureCertificate.jsx
+++ b/src/Modules/Certificates/FeeStructureCertificate.jsx
@@ -10,6 +10,7 @@ import {
Group,
Loader,
Paper,
+ Select,
Stack,
Text,
TextInput,
@@ -63,6 +64,17 @@ const filenameFrom = (header, fallback) => {
return match?.[1] || fallback;
};
+function ordinalWithSuperscript(value) {
+ const match = /^(\d+)(st|nd|rd|th)$/.exec((value ?? "").trim());
+ if (!match) return value;
+ return (
+ <>
+ {match[1]}
+ {match[2]}
+ >
+ );
+}
+
const indianCurrency = (value) => {
const [whole, fraction] = Number(value).toFixed(2).split(".");
const head = whole.slice(0, -3);
@@ -80,6 +92,8 @@ export default function FeeStructureCertificate() {
const [rollNumber, setRollNumber] = useState("");
const [selectedStudent, setSelectedStudent] = useState(null);
const [structure, setStructure] = useState(null);
+ const [financialYears, setFinancialYears] = useState([]);
+ const [selectedSemester, setSelectedSemester] = useState(null);
const [certificateMeta, setCertificateMeta] = useState(null);
const [preview, setPreview] = useState(null);
const [fetchingStudent, setFetchingStudent] = useState(false);
@@ -89,25 +103,31 @@ export default function FeeStructureCertificate() {
const clearStudent = () => {
setSelectedStudent(null);
setStructure(null);
+ setFinancialYears([]);
+ setSelectedSemester(null);
setCertificateMeta(null);
setPreview(null);
};
- const fetchStudent = async () => {
- const normalizedRollNumber = rollNumber.trim().toUpperCase();
- if (!normalizedRollNumber || fetchingStudent) return;
-
- clearStudent();
- setRollNumber(normalizedRollNumber);
+ const fetchStudent = async (roll, semester) => {
+ if (!roll || fetchingStudent) return;
setFetchingStudent(true);
try {
const { data } = await axios.get(feeStructureCertificateStudentRoute, {
...authConfig(),
- params: { roll_number: normalizedRollNumber },
+ params: { roll_number: roll, semester: semester || undefined },
});
setSelectedStudent(data.student || null);
setStructure(data.structure || null);
+ setFinancialYears(
+ (data.financial_years || []).map((item) => ({
+ value: String(item.value),
+ label: item.label,
+ })),
+ );
+ setSelectedSemester(data.selected_semester ?? null);
setCertificateMeta(data.certificate || null);
+ setPreview(null);
} catch (error) {
notifications.show({
color: "red",
@@ -119,6 +139,21 @@ export default function FeeStructureCertificate() {
}
};
+ const searchStudent = () => {
+ const normalizedRollNumber = rollNumber.trim().toUpperCase();
+ if (!normalizedRollNumber) return;
+ clearStudent();
+ setRollNumber(normalizedRollNumber);
+ fetchStudent(normalizedRollNumber);
+ };
+
+ const changeFinancialYear = (value) => {
+ const semester = Number(value);
+ setSelectedSemester(semester);
+ setPreview(null);
+ fetchStudent(rollNumber, semester);
+ };
+
const showPreview = () => {
if (!selectedStudent || !structure?.rows?.length || !certificateMeta)
return;
@@ -135,7 +170,7 @@ export default function FeeStructureCertificate() {
try {
const response = await axios.post(
feeStructureCertificatePdfRoute,
- { student_id: selectedStudent.student_id },
+ { student_id: selectedStudent.student_id, semester: selectedSemester },
{ ...authConfig(), responseType: "blob" },
);
const filename = filenameFrom(
@@ -159,7 +194,9 @@ export default function FeeStructureCertificate() {
}
};
- const ready = Boolean(selectedStudent?.is_ready && structure?.rows?.length);
+ const ready = Boolean(
+ selectedStudent?.is_ready && structure?.rows?.length && selectedSemester,
+ );
return (
<>
@@ -185,7 +222,7 @@ export default function FeeStructureCertificate() {
onKeyDown={(event) => {
if (event.key === "Enter") {
event.preventDefault();
- fetchStudent();
+ searchStudent();
}
}}
rightSection={
@@ -195,7 +232,7 @@ export default function FeeStructureCertificate() {
}
- onClick={fetchStudent}
+ onClick={searchStudent}
disabled={!rollNumber.trim()}
loading={fetchingStudent}
fullWidth
@@ -215,8 +252,9 @@ export default function FeeStructureCertificate() {
{selectedStudent.programme} in {selectedStudent.discipline}
- {selectedStudent.year_ordinal} Year,{" "}
- {selectedStudent.semester_ordinal} Semester
+ {ordinalWithSuperscript(selectedStudent.year_ordinal)} Year,{" "}
+ {ordinalWithSuperscript(selectedStudent.semester_ordinal)}{" "}
+ Semester
{structure?.academic_year_label && (
@@ -236,6 +274,21 @@ export default function FeeStructureCertificate() {
)}
+ {financialYears.length > 0 && (
+
+ )}
+