update admin popup error

This commit is contained in:
Dimas Atmodjo 2024-12-16 00:42:37 +07:00
parent df69cd3467
commit 1cb0f9cb8e
17 changed files with 238 additions and 155 deletions

View File

@ -91,15 +91,19 @@ const useClasses = () => {
try { try {
const createdClass = await classService.createData(newClass); const createdClass = await classService.createData(newClass);
setClasses((prevClasses) => [...prevClasses, createdClass.payload]); setClasses((prevClasses) => [...prevClasses, createdClass.payload]);
} catch (err) {
setError(err);
}finally{
resetForm();
setLoaderState(prev => ({ setLoaderState(prev => ({
...prev, ...prev,
loading: false, loading: false,
successMessage: 'Your new entry has been successfully created and saved.' successMessage: 'Your new entry has been successfully created and saved.'
})); }));
resetForm();
} catch (err) {
setLoaderState(prev => ({
...prev,
title: "ERROR",
loading: false,
successMessage: err.response.data.message
}));
} }
}; };
@ -117,14 +121,18 @@ const useClasses = () => {
setClasses((prevClasses) => setClasses((prevClasses) =>
prevClasses.map((s) => (s.ID_CLASS === id ? classData.payload : s)) prevClasses.map((s) => (s.ID_CLASS === id ? classData.payload : s))
); );
} catch (err) {
setError(err);
}finally{
setLoaderState(prev => ({ setLoaderState(prev => ({
...prev, ...prev,
loading: false, loading: false,
successMessage: 'Your data has been successfully updated.' successMessage: 'Your data has been successfully updated.'
})); }));
} catch (err) {
setLoaderState(prev => ({
...prev,
title: "ERROR",
loading: false,
successMessage: err.response.data.message
}));
} }
}; };

View File

@ -39,6 +39,9 @@ const useUpdateExercises = (levelId) => {
trueFalse: "", trueFalse: "",
matchingPairs: {}, matchingPairs: {},
}); });
const [imageContainer, setImageContainer] = useState("");
const [audioContainer, setAudioContainer] = useState("");
const [selectedQuestion, setSelectedQuestion] = useState(false); const [selectedQuestion, setSelectedQuestion] = useState(false);
@ -55,9 +58,9 @@ const useUpdateExercises = (levelId) => {
QUESTION:"", QUESTION:"",
QUESTION_TYPE:"", QUESTION_TYPE:"",
SCORE_WEIGHT:"", SCORE_WEIGHT:"",
AUDIO:"", AUDIO:'',
IMAGE:"", IMAGE:'',
VIDEO:"", VIDEO:'',
multipleChoices:"", multipleChoices:"",
trueFalse:"", trueFalse:"",
matchingPairs:{}, matchingPairs:{},
@ -82,6 +85,8 @@ const useUpdateExercises = (levelId) => {
const [selectedQuestionNumber, setSelectedQuestionNumber] = useState(null); const [selectedQuestionNumber, setSelectedQuestionNumber] = useState(null);
const handleShow = (data) => { const handleShow = (data) => {
setImageContainer("");
setAudioContainer("");
setSelectedQuestion(true); setSelectedQuestion(true);
setSelectedQuestionNumber(data+1); setSelectedQuestionNumber(data+1);
setFormData({ setFormData({
@ -91,13 +96,19 @@ const useUpdateExercises = (levelId) => {
QUESTION: exerciseData[data].QUESTION || "", QUESTION: exerciseData[data].QUESTION || "",
QUESTION_TYPE: exerciseData[data].QUESTION_TYPE || "", QUESTION_TYPE: exerciseData[data].QUESTION_TYPE || "",
SCORE_WEIGHT: exerciseData[data].SCORE_WEIGHT || "", SCORE_WEIGHT: exerciseData[data].SCORE_WEIGHT || "",
AUDIO: exerciseData[data].AUDIO || "", AUDIO: exerciseData[data].AUDIO || '',
IMAGE: exerciseData[data].IMAGE || "", IMAGE: exerciseData[data].IMAGE || '',
VIDEO: exerciseData[data].VIDEO || "", VIDEO: exerciseData[data].VIDEO || '',
multipleChoices: exerciseData[data].multipleChoices || "", multipleChoices: exerciseData[data].multipleChoices || "",
trueFalse: exerciseData[data].trueFalse || "", trueFalse: exerciseData[data].trueFalse || "",
matchingPairs: exerciseData[data].matchingPairs || {}, matchingPairs: exerciseData[data].matchingPairs || {},
}); });
if(exerciseData[data].IMAGE){
setImageContainer(exerciseData[data].IMAGE);
}
if(exerciseData[data].AUDIO){
setAudioContainer(exerciseData[data].AUDIO);
}
setShow(true); setShow(true);
}; };
const handleClose = () => { const handleClose = () => {
@ -105,6 +116,9 @@ const useUpdateExercises = (levelId) => {
resetForm(); resetForm();
setSelectedQuestion(null); setSelectedQuestion(null);
setMediaPreview(null); setMediaPreview(null);
setImageContainer("");
setAudioContainer("");
}; };
const handleShowNewData = () => { const handleShowNewData = () => {
@ -225,8 +239,13 @@ const useUpdateExercises = (levelId) => {
} }
}; };
const [deleteMedia, setDeleteMedia] = useState(false);
const [deleteMediaType, setDeleteMediaType] = useState(null);
const updateQuestion = async () => { const updateQuestion = async () => {
setDeleteMedia(false);
setDeleteMediaType(null)
const id = formData.ID_ADMIN_EXERCISE; const id = formData.ID_ADMIN_EXERCISE;
const updateData = new FormData(); const updateData = new FormData();
updateData.append('ID_LEVEL', levelId); updateData.append('ID_LEVEL', levelId);
updateData.append('QUESTION', formData.QUESTION); updateData.append('QUESTION', formData.QUESTION);
@ -239,15 +258,27 @@ const useUpdateExercises = (levelId) => {
updateData.append('AUDIO', formData.AUDIO); updateData.append('AUDIO', formData.AUDIO);
} }
if (formData.VIDEO === "") { if (formData.VIDEO === '') {
updateData.append('VIDEO', ""); updateData.append('VIDEO', "");
} }
if (formData.IMAGE === "") { if (formData.IMAGE === '') {
updateData.append('IMAGE', ""); updateData.append('IMAGE', "");
} }
if (formData.AUDIO === "") { if (formData.AUDIO === '') {
updateData.append('AUDIO', ""); updateData.append('AUDIO', "");
} }
//media checker delete
console.log('continer',imageContainer);
console.log('form',formData.IMAGE);
if (imageContainer !== '' && imageContainer !== formData.IMAGE) {
setDeleteMedia(true);
setDeleteMediaType('image')
}
if (audioContainer !== '' && audioContainer !== formData.AUDIO) {
setDeleteMedia(true);
setDeleteMediaType('audio')
}
if (formData.QUESTION_TYPE === "TFQ") { if (formData.QUESTION_TYPE === "TFQ") {
if (typeof formData.trueFalse === 'object') { if (typeof formData.trueFalse === 'object') {
@ -271,8 +302,15 @@ const useUpdateExercises = (levelId) => {
}); });
} }
const deleteMediaTypeData ={
'fileType' : deleteMediaType
}
handleShowLoader('Updated', '', true); handleShowLoader('Updated', '', true);
try { try {
if (deleteMedia) {
console.log(deleteMediaTypeData);
await exerciseService.deleteMedia(id, deleteMediaTypeData);
}
const update = await exerciseService.updateData(id, updateData); const update = await exerciseService.updateData(id, updateData);
setExerciseData((prevQuestion) => setExerciseData((prevQuestion) =>
prevQuestion.map((s) => (s.ID_ADMIN_EXERCISE === id ? update.payload : s)) prevQuestion.map((s) => (s.ID_ADMIN_EXERCISE === id ? update.payload : s))

View File

@ -103,6 +103,16 @@ const deleteData = async (id) => {
} }
}; };
const deleteMedia = async (id, data) => {
try {
const response = await axiosInstance.delete(`/exercise/file/${id}`, data);
return response.data;
} catch (error) {
console.error(`Error deleting question with ID ${id}:`, error);
throw error;
}
};
export default{ export default{
fetchData, fetchData,
getExerciseByLevelId, getExerciseByLevelId,
@ -111,4 +121,5 @@ export default{
updateData, updateData,
sortingData, sortingData,
deleteData, deleteData,
deleteMedia
}; };

View File

@ -82,43 +82,6 @@ const UpdateExercises = () => {
</Row> </Row>
<Row className='mb-45'> <Row className='mb-45'>
<Col className='h-fit'> <Col className='h-fit'>
{/* <div className="cards">
<div className="cards-title d-flex justify-content-between">
<div className="d-flex align-items-center">
<span style={{ cursor: 'grab' }}><i className="bi bi-list me-3" /></span>
<h4>1</h4>
<h4>.Multiple Choice</h4>
</div>
<div className="d-flex">
<Button size='sm' variant='outline-warning' className='me-2 border'><i className="bi bi-pencil me-1"></i>edit</Button>
<Button size='sm' variant='outline-danger' className='border'><i className="bi bi-trash3"></i></Button>
</div>
</div>
<div className="cards-body">
<Row className='mb-2'>
<Col className='d-flex align-items-center'>
<img src="https://picsum.photos/300/200" alt="" className='me-2 bg-light' style={{aspectRatio:"1/1",width:"5vw",objectPosition:"center",objectFit:"contain"}}/>
<p className='m-0 fs-14p'>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolorum assumenda tenetur nostrum, consequatur mollitia ea dignissimos adipisci rerum nesciunt laboriosam laborum ut atque beatae facilis nam illum impedit quia eius.</p>
</Col>
</Row>
<span className='fs-12p'>Question Choices</span>
<Row>
<Col md={6} className='d-flex align-items-center'>
<i className="bi bi-check text-success fs-5 me-1"></i><span className='fs-14p'>gatau</span>
</Col>
<Col md={6} className='d-flex align-items-center'>
<i className="bi bi-x text-red fs-5 me-1"></i><span className='fs-14p'>ya ini</span>
</Col>
<Col md={6} className='d-flex align-items-center'>
<i className="bi bi-x text-red fs-5 me-1"></i><span className='fs-14p'>ya itu</span>
</Col>
<Col md={6} className='d-flex align-items-center'>
<i className="bi bi-x text-red fs-5 me-1"></i><span className='fs-14p'>gatau ini</span>
</Col>
</Row>
</div>
</div> */}
{loading?( {loading?(
<div className='w-100 d-flex justify-content-center align-items-center' style={{height:"20vh"}}> <div className='w-100 d-flex justify-content-center align-items-center' style={{height:"20vh"}}>
@ -750,11 +713,6 @@ const UpdateExercises = () => {
) )
) )
)} )}
{/* <div className="py-4 bg-white d-flex justify-content-end">
<Button variant="blue" type="submit" className='ms-2 py-2 px-5 rounded-35'>
Update
</Button>
</div> */}
</Form> </Form>
</Modal.Body> </Modal.Body>
</Modal> </Modal>

View File

@ -92,7 +92,7 @@ const useProgress = () => {
const getClassTopic = async (id) => { const getClassTopic = async (id) => {
setLoadingModal(true); setLoadingModal(true);
try { try {
const classes = await progressService.getTopicByClass(id, '', '', '', 1000); const classes = await progressService.getTopicByClass(id);
setSelected(classes.payload.data); setSelected(classes.payload.data);
} catch (err) { } catch (err) {
console.log(err); console.log(err);

View File

@ -78,12 +78,30 @@ const useProgressClass = (progressId) => {
.replace(/\./g, ':') + ' WIB'; .replace(/\./g, ':') + ' WIB';
} }
const handleDownloadCSV = async () => {
try {
const response = await progressService.getCsvProgress();
const blob = new Blob([response], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
const downloadUrl = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = downloadUrl;
link.download = `progress ${name}-${topic}.csv`;
link.click();
URL.revokeObjectURL(downloadUrl);
} catch (error) {
console.error('Error downloading file:', error);
alert('Gagal mengunduh file');
}
}
return { return {
progress, progress,
section, section,
topic, topic,
name, name,
nisn,
loading, loading,
error, error,
@ -94,7 +112,8 @@ const useProgressClass = (progressId) => {
handlePageChange, handlePageChange,
handleLimitsChange, handleLimitsChange,
handleSearchChange, handleSearchChange,
formatLocalDate formatLocalDate,
handleDownloadCSV
}; };
}; };

View File

@ -30,9 +30,9 @@ const getStudentById = async (id) => {
} }
}; };
const getTopicByClass = async (id, search, sort, page, limit) => { const getTopicByClass = async (id) => {
try { try {
const response = await axiosInstance.get(`/monitoring/class/${id}?search=${search}&sort=${sort}&page=${page}&limit=${limit}`); const response = await axiosInstance.get(`/monitoring/class/${id}`);
return response.data; return response.data;
} catch (error) { } catch (error) {
console.error('Error fetching progress:', error); console.error('Error fetching progress:', error);
@ -52,7 +52,7 @@ const fetchDataStudentProgress = async (id, search, sort, page, limit) => {
const fetchDataClassProgress = async (dataId, search, sort, page, limit) => { const fetchDataClassProgress = async (dataId, search, sort, page, limit) => {
try { try {
const response = await axiosInstance.get(`/monitoring/class?search=${search}&sort=${sort}&page=${page}&limit=${limit}`, dataId); const response = await axiosInstance.post(`/monitoring/class?search=${search}&sort=${sort}&page=${page}&limit=${limit}`, dataId);
return response.data; return response.data;
} catch (error) { } catch (error) {
console.error('Error fetching progress:', error); console.error('Error fetching progress:', error);
@ -60,11 +60,28 @@ const fetchDataClassProgress = async (dataId, search, sort, page, limit) => {
} }
}; };
const getCsvProgress = async () => {
const configs = {
headers: {
Authorization: localStorage.getItem('token')
},
responseType: 'blob',
};
try {
const response = await axiosInstance.get(`/monitoring/class/csv`, configs);
return response.data;
} catch (error) {
console.error(`Error get file:`, error);
throw error;
}
};
export default{ export default{
fetchDataStudent, fetchDataStudent,
fetchDataClass, fetchDataClass,
getStudentById, getStudentById,
getTopicByClass, getTopicByClass,
fetchDataStudentProgress, fetchDataStudentProgress,
fetchDataClassProgress fetchDataClassProgress,
getCsvProgress
}; };

View File

@ -8,12 +8,10 @@ const ClassProgress = () => {
const { progressId } = useParams(); const { progressId } = useParams();
const { const {
progress, progress,
name,
section, section,
topic, topic,
name,
nisn,
loading, loading,
error,
totalPages, totalPages,
totalData, totalData,
@ -22,7 +20,8 @@ const ClassProgress = () => {
handlePageChange, handlePageChange,
handleLimitsChange, handleLimitsChange,
handleSearchChange, handleSearchChange,
formatLocalDate formatLocalDate,
handleDownloadCSV
} = useProgressClass(progressId); } = useProgressClass(progressId);
return ( return (
<div className='admin-teachers'> <div className='admin-teachers'>
@ -33,12 +32,12 @@ const ClassProgress = () => {
</Button> </Button>
<Breadcrumb className='custom-breadcrumb'> <Breadcrumb className='custom-breadcrumb'>
<Breadcrumb.Item href="/admin/learning-progress">Monitoring Progress</Breadcrumb.Item> <Breadcrumb.Item href="/admin/learning-progress">Monitoring Progress</Breadcrumb.Item>
<Breadcrumb.Item active>Progress Details</Breadcrumb.Item> <Breadcrumb.Item active>Class Progress Details</Breadcrumb.Item>
</Breadcrumb> </Breadcrumb>
</Col> </Col>
<Col sm={6} className="d-flex align-items-center justify-content-end"> <Col sm={6} className="d-flex align-items-center justify-content-end">
<Button variant="outline-blue" type="button" className='py-2 bg-white'> <Button variant="outline-blue" type="button" className='py-2 bg-white' onClick={(e) => { e.preventDefault(); handleDownloadCSV(); }}>
<i className="bi bi-download me-2"></i>Download PDF <i className="bi bi-download me-2"></i>Download CSV
</Button> </Button>
</Col> </Col>
</Row> </Row>
@ -46,7 +45,7 @@ const ClassProgress = () => {
<Col> <Col>
<div className="cards"> <div className="cards">
<div className="cards-title"> <div className="cards-title">
<h4 className='mb-2'>{nisn} - {name}</h4> <h4 className='mb-2'>{name}</h4>
<span className='text-grey'>{section} / {topic}</span> <span className='text-grey'>{section} / {topic}</span>
</div> </div>
<div className="cards-body"> <div className="cards-body">
@ -63,11 +62,11 @@ const ClassProgress = () => {
<Table hover> <Table hover>
<thead> <thead>
<tr> <tr>
<th>No</th> <th className='text-start'>NISN</th>
<th>NISN</th>
<th>Full Name</th> <th>Full Name</th>
<th>Level</th> <th>Level</th>
<th>Score</th> <th>Score</th>
<th>Feedback</th>
<th>Start Exercise</th> <th>Start Exercise</th>
<th>Finish Exercise</th> <th>Finish Exercise</th>
</tr> </tr>
@ -75,7 +74,7 @@ const ClassProgress = () => {
<tbody> <tbody>
{loading?( {loading?(
<tr> <tr>
<td colSpan={6} style={{height:"20vh"}}> <td colSpan={7} style={{height:"20vh"}}>
<Spinner animation="grow" variant="primary" /> <Spinner animation="grow" variant="primary" />
<Spinner animation="grow" variant="secondary" /> <Spinner animation="grow" variant="secondary" />
<Spinner animation="grow" variant="success" /> <Spinner animation="grow" variant="success" />
@ -88,18 +87,18 @@ const ClassProgress = () => {
progress.length > 0?( progress.length > 0?(
progress.map((data, index) => ( progress.map((data, index) => (
<tr key={index}> <tr key={index}>
<td>{index + 1}</td> <td className='text-start'>{data.NISN}</td>
<td>{data.NISN}</td>
<td>{data.NAME_USERS}</td> <td>{data.NAME_USERS}</td>
<td>{data.NAME_LEVEL}</td> <td>{data.NAME_LEVEL}</td>
<td>{data.SCORE}</td> <td>{data.SCORE}</td>
<td>{data.FEEDBACK_STUDENT ?? '-'}</td>
<td>{formatLocalDate(data.STUDENT_START)}</td> <td>{formatLocalDate(data.STUDENT_START)}</td>
<td>{formatLocalDate(data.STUDENT_FINISH)}</td> <td>{formatLocalDate(data.STUDENT_FINISH)}</td>
</tr> </tr>
)) ))
):( ):(
<tr> <tr>
<td colSpan={6} style={{height:'20vh'}}> <td colSpan={7} style={{height:'20vh'}}>
<h3>Empty Data</h3> <h3>Empty Data</h3>
</td> </td>
</tr> </tr>

View File

@ -206,26 +206,13 @@ const ManageProgress = () => {
</Row> </Row>
</Tab.Container> </Tab.Container>
<Modal show={show} onHide={handleClose} className='modal-admin' size='lg' centered> <Modal show={show} onHide={handleClose} className='modal-admin' size='xl' centered>
<Modal.Header closeButton> <Modal.Header closeButton>
<Modal.Title>Select Topic</Modal.Title> <Modal.Title>Select Topic</Modal.Title>
</Modal.Header> </Modal.Header>
<Modal.Body> <Modal.Body>
<Row>
<Col xs={6} lg={4} className='mb-3'>
<Card className='h-100'>
<Card.Body>
<Card.Title as='h3'>Vocabulary</Card.Title>
<Card.Text className='mb-4 fs-14p'>
The legend of naresh
</Card.Text>
<Button as={Link} to={`c/${selectedId}&21a9c23e-9737-49f5-bbd5-5b0ecac3f73d`} variant="warning" className='py-2 w-100 rounded-35'>See Details</Button>
</Card.Body>
</Card>
</Col>
</Row>
{loadingModal?( {loadingModal?(
<div className='d-flex justify-content-center align-items-center' style={{height:"20vh"}}> <div className='d-flex justify-content-center align-items-center' style={{height:"179px"}}>
<Spinner animation="grow" variant="primary" /> <Spinner animation="grow" variant="primary" />
<Spinner animation="grow" variant="secondary" /> <Spinner animation="grow" variant="secondary" />
<Spinner animation="grow" variant="success" /> <Spinner animation="grow" variant="success" />
@ -251,7 +238,9 @@ const ManageProgress = () => {
))} ))}
</Row> </Row>
):( ):(
<h2 className='my-3 text-center'>No Progress from this class</h2> <div className='d-flex justify-content-center align-items-center' style={{height:"179px"}}>
<h2 className='m-0 text-center'>No Progress from this class</h2>
</div>
) )
)} )}
</Modal.Body> </Modal.Body>

View File

@ -102,14 +102,18 @@ const useSections = () => {
setSections((prevSections) => setSections((prevSections) =>
prevSections.map((s) => (s.ID_SECTION === id ? section.payload : s)) prevSections.map((s) => (s.ID_SECTION === id ? section.payload : s))
); );
} catch (err) {
setError(err);
}finally{
setLoaderState(prev => ({ setLoaderState(prev => ({
...prev, ...prev,
loading: false, loading: false,
successMessage: 'Your data has been successfully updated.' successMessage: 'Your data has been successfully updated.'
})); }));
} catch (err) {
setLoaderState(prev => ({
...prev,
title: "ERROR",
loading: false,
successMessage: err.response.data.message
}));
} }
}; };
@ -121,15 +125,19 @@ const useSections = () => {
handleShowLoader('Deleted', '', true) handleShowLoader('Deleted', '', true)
try { try {
await sectionService.deleteData(id); await sectionService.deleteData(id);
} catch (err) {
setError(err);
}finally{
setSections((prevSections) => prevSections.filter((s) => s.ID_SECTION !== id)); setSections((prevSections) => prevSections.filter((s) => s.ID_SECTION !== id));
setLoaderState(prev => ({ setLoaderState(prev => ({
...prev, ...prev,
loading: false, loading: false,
successMessage: 'Your data has been successfully deleted.' successMessage: 'Your data has been successfully deleted.'
})); }));
} catch (err) {
setLoaderState(prev => ({
...prev,
title: "ERROR",
loading: false,
successMessage: err.response.data.message
}));
} }
} }
setLoaderState(prev => ({ ...prev, handleConfirm: confirmDelete })); setLoaderState(prev => ({ ...prev, handleConfirm: confirmDelete }));

View File

@ -225,7 +225,7 @@ const ManageSections = () => {
<Modal show={show} onHide={handleClose} className='modal-admin' size='lg' centered> <Modal show={show} onHide={handleClose} className='modal-admin' size='lg' centered>
<Modal.Header closeButton> <Modal.Header closeButton>
<Modal.Title>Update Teacher Data</Modal.Title> <Modal.Title>Update Section Data</Modal.Title>
</Modal.Header> </Modal.Header>
<Modal.Body> <Modal.Body>
<Form onSubmit={(e) => { e.preventDefault(); editSection(); }}> <Form onSubmit={(e) => { e.preventDefault(); editSection(); }}>

View File

@ -22,6 +22,7 @@ const useStudents = () => {
const [loaderState, setLoaderState] = useState({ loading: false, successMessage: '', title: '', description: '', confirmAction: false }); const [loaderState, setLoaderState] = useState({ loading: false, successMessage: '', title: '', description: '', confirmAction: false });
const resetForm = () =>{ const resetForm = () =>{
setFileImport(null);
setFormData({ setFormData({
fullName: '', fullName: '',
nisn: '', nisn: '',
@ -41,15 +42,19 @@ const useStudents = () => {
}; };
const createdStudent = await studentService.createData(newStudent); const createdStudent = await studentService.createData(newStudent);
setStudents((prevStudents) => [...prevStudents, createdStudent.payload]); setStudents((prevStudents) => [...prevStudents, createdStudent.payload]);
} catch (err) {
setError(err);
}finally{
resetForm(); resetForm();
setLoaderState(prev => ({ setLoaderState(prev => ({
...prev, ...prev,
loading: false, loading: false,
successMessage: 'Your new entry has been successfully created and saved.' successMessage: 'Your new entry has been successfully created and saved.'
})); }));
} catch (err) {
setLoaderState(prev => ({
...prev,
title: "ERROR",
loading: false,
successMessage: err.response.data.message
}));
} }
}; };
@ -60,16 +65,19 @@ const useStudents = () => {
console.log(file); console.log(file);
try { try {
const response = await studentService.registerImport(fileData); const response = await studentService.registerImport(fileData);
console.log(response.data);
} catch (err) {
setError(err);
}finally{
resetForm();
setLoaderState(prev => ({ setLoaderState(prev => ({
...prev, ...prev,
loading: false, loading: false,
successMessage: 'Your new entry has been successfully created and saved.' successMessage: 'Your new entry has been successfully created and saved.'
})); }));
resetForm();
} catch (err) {
setLoaderState(prev => ({
...prev,
title: "ERROR",
loading: false,
successMessage: err.response.data.message
}));
} }
} }
@ -83,14 +91,18 @@ const useStudents = () => {
setStudents((prevStudents) => setStudents((prevStudents) =>
prevStudents.map((s) => (s.ID === id ? student.payload : s)) prevStudents.map((s) => (s.ID === id ? student.payload : s))
); );
} catch (err) {
setError(err);
}finally{
setLoaderState(prev => ({ setLoaderState(prev => ({
...prev, ...prev,
loading: false, loading: false,
successMessage: 'Your data has been successfully updated.' successMessage: 'Your data has been successfully updated.'
})); }));
} catch (err) {
setLoaderState(prev => ({
...prev,
title: "ERROR",
loading: false,
successMessage: err.response.data.message
}));
} }
}; };
@ -98,15 +110,19 @@ const useStudents = () => {
handleShowLoader('Deleted', '', true) handleShowLoader('Deleted', '', true)
try { try {
await studentService.deleteData(id); await studentService.deleteData(id);
} catch (err) {
setError(err);
}finally{
setStudents((prevStudents) => prevStudents.filter((s) => s.ID !== id)); setStudents((prevStudents) => prevStudents.filter((s) => s.ID !== id));
setLoaderState(prev => ({ setLoaderState(prev => ({
...prev, ...prev,
loading: false, loading: false,
successMessage: 'Your data has been successfully deleted.' successMessage: 'Your data has been successfully deleted.'
})); }));
} catch (err) {
setLoaderState(prev => ({
...prev,
title: "ERROR",
loading: false,
successMessage: err.response.data.message
}));
} }
}; };
@ -175,22 +191,23 @@ const useStudents = () => {
}, [page, limit]); }, [page, limit]);
const handleDownloadTemplate = async () => {try { const handleDownloadTemplate = async () => {
const response = await studentService.getTemplate(); try {
const response = await studentService.getTemplate();
const blob = new Blob([response], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
const downloadUrl = URL.createObjectURL(blob); const blob = new Blob([response], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
const downloadUrl = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = downloadUrl; const link = document.createElement('a');
link.download = 'template.xls'; link.href = downloadUrl;
link.click(); link.download = 'template.xlsx';
link.click();
URL.revokeObjectURL(downloadUrl);
} catch (error) { URL.revokeObjectURL(downloadUrl);
console.error('Error downloading file:', error); } catch (error) {
alert('Gagal mengunduh file'); console.error('Error downloading file:', error);
} alert('Gagal mengunduh file');
}
} }
return { return {

View File

@ -377,7 +377,7 @@ const ManageStudents = () => {
onDragLeave={handleDragLeave} onDragLeave={handleDragLeave}
> >
<h5 className={`m-0 ${fileImport ? `text-green fs-3` : `text-grey`}`}>{fileImport ? fileImport.name : "Upload Excel file here"}</h5> <h5 className={`m-0 ${fileImport ? `text-green fs-3` : `text-grey`}`}>{fileImport ? fileImport.name : "Upload Excel file here"}</h5>
<span className={`fs-14p ${fileImport ? `text-green` : `text-grey`}`}>{fileImport ? "Your file is ready to import" : "Please make sure your Excel file follows the template."}</span> <span className={`fs-14p ${fileImport ? `text-green` : `text-grey`}`}>{fileImport ? "Your file is ready to import" : "Please make sure your Excel file follows the template.(*.xlsx)"}</span>
</label> </label>
</Row> </Row>
<div className="d-flex justify-content-end"> <div className="d-flex justify-content-end">

View File

@ -40,15 +40,18 @@ const useTeachers = () => {
CONFIRM_PASSWORD: data.confirm_pass, CONFIRM_PASSWORD: data.confirm_pass,
}; };
const createdTeacher = await teacherService.createData(newTeacher); const createdTeacher = await teacherService.createData(newTeacher);
setTeachers((prevTeachers) => [...prevTeachers, createdTeacher.payload]);
} catch (err) {
setError(err);
}finally{
resetForm();
setLoaderState(prev => ({ setLoaderState(prev => ({
...prev, ...prev,
loading: false, loading: false,
successMessage: 'Your new entry has been successfully created and saved.' successMessage: 'New teacher has been successfully created. waiting to verify the email.'
}));
resetForm();
} catch (err) {
setLoaderState(prev => ({
...prev,
title: "ERROR",
loading: false,
successMessage: err.response.data.message
})); }));
} }
}; };
@ -63,14 +66,18 @@ const useTeachers = () => {
setTeachers((prevTeachers) => setTeachers((prevTeachers) =>
prevTeachers.map((s) => (s.ID === id ? Teacher.payload : s)) prevTeachers.map((s) => (s.ID === id ? Teacher.payload : s))
); );
} catch (err) {
setError(err);
}finally{
setLoaderState(prev => ({ setLoaderState(prev => ({
...prev, ...prev,
loading: false, loading: false,
successMessage: 'Your data has been successfully updated.' successMessage: 'Your data has been successfully updated.'
})); }));
} catch (err) {
setLoaderState(prev => ({
...prev,
title: "ERROR",
loading: false,
successMessage: err.response.data.message
}));
} }
}; };
@ -78,15 +85,19 @@ const useTeachers = () => {
handleShowLoader('Deleted', '', true) handleShowLoader('Deleted', '', true)
try { try {
await teacherService.deleteData(id); await teacherService.deleteData(id);
} catch (err) {
setError(err);
}finally{
setTeachers((prevTeachers) => prevTeachers.filter((s) => s.ID !== id)); setTeachers((prevTeachers) => prevTeachers.filter((s) => s.ID !== id));
setLoaderState(prev => ({ setLoaderState(prev => ({
...prev, ...prev,
loading: false, loading: false,
successMessage: 'Your data has been successfully deleted.' successMessage: 'Your data has been successfully deleted.'
})); }));
} catch (err) {
setLoaderState(prev => ({
...prev,
title: "ERROR",
loading: false,
successMessage: err.response.data.message
}));
} }
}; };

View File

@ -106,14 +106,18 @@ const useTopics = () => {
setTopics((prevTopics) => setTopics((prevTopics) =>
prevTopics.map((s) => (s.ID_TOPIC === id ? topic.payload : s)) prevTopics.map((s) => (s.ID_TOPIC === id ? topic.payload : s))
); );
} catch (err) {
setError(err);
}finally{
setLoaderState(prev => ({ setLoaderState(prev => ({
...prev, ...prev,
loading: false, loading: false,
successMessage: 'Your data has been successfully updated.' successMessage: 'Your data has been successfully updated.'
})); }));
} catch (err) {
setLoaderState(prev => ({
...prev,
title: "ERROR",
loading: false,
successMessage: err.response.data.message
}));
} }
}; };
@ -125,15 +129,19 @@ const useTopics = () => {
handleShowLoader('Deleted', '', true) handleShowLoader('Deleted', '', true)
try { try {
await topicService.deleteData(id); await topicService.deleteData(id);
} catch (err) {
setError(err);
}finally{
setTopics((prevTopics) => prevTopics.filter((s) => s.ID_TOPIC !== id)); setTopics((prevTopics) => prevTopics.filter((s) => s.ID_TOPIC !== id));
setLoaderState(prev => ({ setLoaderState(prev => ({
...prev, ...prev,
loading: false, loading: false,
successMessage: 'Your data has been successfully deleted.' successMessage: 'Your data has been successfully deleted.'
})); }));
} catch (err) {
setLoaderState(prev => ({
...prev,
title: "ERROR",
loading: false,
successMessage: err.response.data.message
}));
} }
} }
setLoaderState(prev => ({ ...prev, handleConfirm: confirmDelete })); setLoaderState(prev => ({ ...prev, handleConfirm: confirmDelete }));

View File

@ -108,7 +108,7 @@ const ManageTopics = () => {
<td>{topic.NAME_TOPIC}</td> <td>{topic.NAME_TOPIC}</td>
<td>{topic.DESCRIPTION_TOPIC}</td> <td>{topic.DESCRIPTION_TOPIC}</td>
<td className='text-center action-col'> <td className='text-center action-col'>
<div class="d-flex"> <div className="d-flex">
<Button size='sm' className='btn-edit' onClick={() => handleShow(topic)}> <Button size='sm' className='btn-edit' onClick={() => handleShow(topic)}>
<i className="bi bi-pencil-square"></i> <i className="bi bi-pencil-square"></i>
</Button> </Button>

View File

@ -1,5 +1,5 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { Table, Row, Col, Nav, Tab, Button, Form, InputGroup, Dropdown, DropdownButton, Modal } from 'react-bootstrap'; import { Table, Row, Col, Nav, Tab, Button, Form, Spinner, Modal } from 'react-bootstrap';
import avatar from '../../../../assets/images/default-avatar.jpg'; import avatar from '../../../../assets/images/default-avatar.jpg';
import ilustration from '../../../../assets/images/illustration/changePass.png'; import ilustration from '../../../../assets/images/illustration/changePass.png';
import successModal from '../../../../assets/images/illustration/successModal.png'; import successModal from '../../../../assets/images/illustration/successModal.png';
@ -49,8 +49,8 @@ const Setting = () => {
return ( return (
<div className='admin-students'> <div className='admin-students'>
<h2 className='page-title strip'>Students</h2> <h2 className='page-title strip'>Admin Profile</h2>
<p className='page-desc'>Description of students.</p> <p className='page-desc'>Manage your account.</p>
<Tab.Container id="left-tabs-example" defaultActiveKey="profile"> <Tab.Container id="left-tabs-example" defaultActiveKey="profile">
<Row className='mb-45'> <Row className='mb-45'>
<Col xs={12}> <Col xs={12}>