المطلوب
في صفحة الصفوف:
الصف الأول
الصف الثاني
الصف الثالثJSXكل صف يحتوي زر:
عرض الأقسامJSX🚀 الخطوة 1: إضافة الزر داخل جدول الصفوف
داخل:
classrooms.map(...)JSXأضف:
<Link
to={`/classrooms/${classroom.documentId}/sections`}
className="btn btn-info btn-sm"
>
الأقسام
</Link>JSX🚀 الخطوة 2: إنشاء Route
داخل App.jsx
<Route
path="/classrooms/:id/sections"
element={<ClassroomSections />}
/>JSX🚀 الخطوة 3: إنشاء صفحة جديدة
pages/classrooms/ClassroomSections.jsxJSX🎯 ما الذي ستفعله الصفحة؟
1- جلب بيانات الصف
الصف الأولJSX2- جلب الأقسام التابعة له
A
B
CJSX🚀 الخطوة 4: إنشاء fetchSingleClassroom
داخل ClassroomsSlice
AsyncThunk
export const fetchSingleClassroom =
createAsyncThunk(
"classrooms/fetchSingleClassroom",
async (id, thunkAPI) => {
try {
const response =
await axiosInstance.get(
`/classrooms/${id}?populate=grade`
);
return response.data.data;
} catch (error) {
return thunkAPI.rejectWithValue(
error.response?.data || error.message
);
}
}
);JSXinitialState
أضف:
singleClassroom: null,JSXaddCase
.addCase(
fetchSingleClassroom.fulfilled,
(state, action) => {
state.singleClassroom =
action.payload;
}
)JSX🚀 الخطوة 5: إنشاء fetchSectionsByClassroom
داخل SectionsSlice
AsyncThunk
export const fetchSectionsByClassroom =
createAsyncThunk(
"sections/fetchSectionsByClassroom",
async (classroomId, thunkAPI) => {
try {
const response =
await axiosInstance.get(
`/sections?filters[classroom][documentId][$eq]=${classroomId}&populate=classroom.grade`
);
return response.data.data;
} catch (error) {
return thunkAPI.rejectWithValue(
error.response?.data || error.message
);
}
}
);JSXaddCase
.addCase(
fetchSectionsByClassroom.fulfilled,
(state, action) => {
state.sections =
action.payload;
}
)JSX🚀 الخطوة 6: صفحة ClassroomSections
البداية
import { useEffect } from "react";
import { useDispatch, useSelector }
from "react-redux";
import { useParams, Link }
from "react-router-dom";
import {
fetchSingleClassroom
}
from "../../features/classrooms/ClassroomsSlice";
import {
fetchSectionsByClassroom
}
from "../../features/sections/SectionsSlice";JSXHooks
const { id } = useParams();
const dispatch = useDispatch();JSXRedux
const {
singleClassroom
} = useSelector(
(state) => state.classrooms
);
const {
sections
} = useSelector(
(state) => state.sections
);JSXFetch
useEffect(() => {
dispatch(
fetchSingleClassroom(id)
);
dispatch(
fetchSectionsByClassroom(id)
);
}, [dispatch, id]);JSX🚀 عرض معلومات الصف
<div className="card mb-3">
<div className="card-body">
<h3>
{singleClassroom?.name}
</h3>
<p>
المرحلة:
{singleClassroom?.grade?.name}
</p>
</div>
</div>JSX🚀 عرض الأقسام
<table className="table table-bordered">
<thead>
<tr>
<th>#</th>
<th>اسم القسم</th>
<th>الإجراءات</th>
</tr>
</thead>
<tbody>
{
sections.map(
(section, index) => (
<tr
key={
section.documentId
}
>
<td>
{index + 1}
</td>
<td>
{section.name}
</td>
<td>
<Link
to={`/sections/${section.documentId}/students`}
className="btn btn-primary btn-sm"
>
الطلاب
</Link>
</td>
</tr>
)
)
}
</tbody>
</table>JSX🎯 النتيجة النهائية
سيصبح لديك تسلسل احترافي جدًا:
صفوف
↓
صف واحد
↓
الأقسام التابعة
↓
طلاب القسم
↓
تفاصيل الطالبJSX💡 اقتراح معماري مهم
بما أنك بدأت تضيف صفحات متسلسلة، أنصحك باعتماد هذا النمط:
/grades/:id/classrooms
/classrooms/:id/sections
/sections/:id/students
/students/:idJSXبهذا تصبح الروابط منطقية وقابلة للمشاركة، وحتى عند تحديث الصفحة (F5) يمكن جلب البيانات من الـ API مباشرة لكل مستوى من مستويات النظام. 🚀