-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
QCMPLUS-40 : update display AnswersList and delete unused import
Signed-off-by: teklit_tewolde <teklit_tewolde@connect-tech.sncf>
- Loading branch information
teklit_tewolde
committed
Aug 20, 2024
1 parent
4699774
commit 700e94d
Showing
7 changed files
with
167 additions
and
114 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,104 +1,173 @@ | ||
import React, { useEffect, useState } from "react"; | ||
import { Col, Form, Row, Table, Button } from "react-bootstrap"; | ||
import { getAnswersByQuestionId, deleteAnswer } from '../../services/AnswerService'; // Assurez-vous que l'import de l'API est correct | ||
import React, {useCallback, useEffect, useState} from "react"; | ||
import {Alert, Button, Col, Form, Row, Spinner, Table} from "react-bootstrap"; | ||
import {createAnswer, deleteAnswer, getAllAnswers, updateAnswer} from '../../services/AnswerService'; | ||
|
||
const AnswersList = ({ title, questionId }) => { | ||
const [answers, setAnswers] = useState([]); // État pour stocker les réponses | ||
const [searchTerm, setSearchTerm] = useState(''); // État pour la barre de recherche | ||
const [answers, setAnswers] = useState([]); | ||
const [searchTerm, setSearchTerm] = useState(''); | ||
const [newAnswerText, setNewAnswerText] = useState(''); | ||
const [loading, setLoading] = useState(false); | ||
const [error, setError] = useState(null); | ||
|
||
// Fonction pour récupérer les réponses depuis l'API | ||
const fetchAnswers = async () => { | ||
const fetchAnswers = useCallback(async () => { | ||
setLoading(true); | ||
setError(null); | ||
try { | ||
const response = await getAnswersByQuestionId(questionId); // Utilisation de l'API | ||
console.log("Data fetched from API:", response.data); // Vérification des données reçues | ||
setAnswers(response.data); // Mise à jour du state avec les réponses | ||
const response = await getAllAnswers(); | ||
setAnswers(response.data); | ||
} catch (error) { | ||
setError("Error fetching answers."); | ||
console.error("Error fetching answers:", error); | ||
} finally { | ||
setLoading(false); | ||
} | ||
}; | ||
}, []); | ||
|
||
useEffect(() => { | ||
fetchAnswers(); | ||
}, [questionId]); // Appel à l'API lorsque le component se monte ou quand questionId change | ||
}, [fetchAnswers]); | ||
|
||
// Fonction pour supprimer une réponse | ||
const handleDelete = async (id) => { | ||
setLoading(true); | ||
setError(null); | ||
try { | ||
await deleteAnswer(id); | ||
fetchAnswers(); // Récupérer à nouveau les réponses après suppression | ||
fetchAnswers(); | ||
} catch (error) { | ||
setError("Error deleting answer."); | ||
console.error("Error deleting answer:", error); | ||
setLoading(false); | ||
} | ||
}; | ||
|
||
// Filtrage des réponses en fonction du terme de recherche | ||
const filteredAnswers = answers.filter((answer) => | ||
answer.answers_text.toLowerCase().includes(searchTerm.toLowerCase()) | ||
); | ||
const handleCreate = async () => { | ||
if (newAnswerText.trim() === '') return; | ||
setLoading(true); | ||
setError(null); | ||
try { | ||
await createAnswer({answer_text: newAnswerText, questionId: questionId, isCorrect: false}); | ||
setNewAnswerText(''); | ||
fetchAnswers(); | ||
} catch (error) { | ||
setError("Error creating answer."); | ||
console.error("Error creating answer:", error); | ||
setLoading(false); | ||
} | ||
}; | ||
|
||
const handleUpdate = async (id, updatedText) => { | ||
if (updatedText.trim() === '') return; | ||
setLoading(true); | ||
setError(null); | ||
try { | ||
const answerToUpdate = answers.find(answer => answer.id === id); | ||
if (answerToUpdate) { | ||
await updateAnswer(id, {...answerToUpdate, answer_text: updatedText}); | ||
fetchAnswers(); | ||
} | ||
} catch (error) { | ||
setError("Error updating answer."); | ||
console.error("Error updating answer:", error); | ||
setLoading(false); | ||
} | ||
}; | ||
|
||
const handleView = (answer) => { | ||
alert("show Answer : Travail en cours"); | ||
}; | ||
|
||
const filteredAnswers = searchTerm | ||
? answers.filter((answer) => | ||
answer.answer_text && answer.answer_text.toLowerCase().includes(searchTerm.toLowerCase()) | ||
) | ||
: answers; | ||
|
||
return ( | ||
<> | ||
<Row className="mb-3"> | ||
<Col> | ||
<h4 className="text-start mb-3">{title}</h4> | ||
<h4 className="text-start mb-3 text-dark">{title}</h4> | ||
</Col> | ||
<Col> | ||
<Form.Control | ||
type="text" | ||
placeholder="Search for answer text" | ||
value={searchTerm} | ||
onChange={(e) => setSearchTerm(e.target.value)} | ||
className="text-dark" | ||
/> | ||
</Col> | ||
</Row> | ||
<Row className="mb-3"> | ||
<Col> | ||
<Form.Control | ||
type="text" | ||
placeholder="Enter new answer" | ||
value={newAnswerText} | ||
onChange={(e) => setNewAnswerText(e.target.value)} | ||
className="text-dark" | ||
/> | ||
</Col> | ||
<Col> | ||
<div className="search-bar"> | ||
<Form.Control | ||
type="text" | ||
placeholder="Search for answer text" | ||
value={searchTerm} | ||
onChange={(e) => setSearchTerm(e.target.value)} // Gestion de la recherche | ||
/> | ||
</div> | ||
<Button variant="primary" onClick={handleCreate} disabled={loading}> | ||
{loading ? <Spinner animation="border" size="sm"/> : "Add Answer"} | ||
</Button> | ||
</Col> | ||
</Row> | ||
<Table striped bordered hover className="small-font"> | ||
<thead> | ||
<tr> | ||
<th>Answer ID</th> | ||
<th>Question ID</th> | ||
<th>Answer Text</th> | ||
<th>Actions</th> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
{answers.length === 0 ? ( | ||
{error && <Alert variant="danger">{error}</Alert>} | ||
<div style={{maxHeight: '500px', overflowY: 'scroll'}}> | ||
<Table striped bordered hover className="small-font text-dark"> | ||
<thead> | ||
<tr> | ||
<td colSpan="4" className="text-center"> | ||
No answers available for this question | ||
</td> | ||
<th className="text-dark">N°</th> | ||
<th className="text-dark">Question ID</th> | ||
<th className="text-dark">Answer ID</th> | ||
<th className="text-dark">Answer Text</th> | ||
<th className="text-dark">Actions</th> | ||
</tr> | ||
) : ( | ||
filteredAnswers.length > 0 ? ( | ||
filteredAnswers.map((answer) => ( | ||
<tr key={answer.id}> | ||
<td>{answer.id}</td> | ||
<td>{answer.questionId}</td> | ||
<td>{answer.answers_text}</td> | ||
<td> | ||
</thead> | ||
<tbody> | ||
{loading ? ( | ||
<tr> | ||
<td colSpan="4" className="text-center text-dark"> | ||
<Spinner animation="border"/> | ||
</td> | ||
</tr> | ||
) : filteredAnswers.length === 0 ? ( | ||
<tr> | ||
<td colSpan="4" className="text-center text-dark"> | ||
No answers available | ||
</td> | ||
</tr> | ||
) : ( | ||
filteredAnswers.map((answer, index) => ( | ||
<tr key={answer.answerId} className="text-dark"> | ||
<td className="text-dark">{index + 1}</td> | ||
<td className="text-dark">{answer.question.questionId}</td> | ||
<td className="text-dark">{answer.answerId}</td> | ||
<td className="text-dark">{answer.answerText}</td> | ||
<td className="text-dark"> | ||
<Button variant="success" size="sm" onClick={() => handleView(answer)}>View</Button> | ||
<Button variant="warning" size="sm" | ||
onClick={() => handleUpdate(answer.id, answer.answer_text)} | ||
className="ms-2">Update</Button> | ||
<Button | ||
variant="danger" | ||
onClick={() => handleDelete(answer.id)} | ||
disabled={loading} | ||
className="ms-2" | ||
> | ||
Delete | ||
{loading ? <Spinner animation="border" size="sm"/> : "Delete"} | ||
</Button> | ||
</td> | ||
</tr> | ||
)) | ||
) : ( | ||
<tr> | ||
<td colSpan="4" className="text-center"> | ||
No answers match your search | ||
</td> | ||
</tr> | ||
) | ||
)} | ||
</tbody> | ||
</Table> | ||
)} | ||
</tbody> | ||
</Table> | ||
</div> | ||
</> | ||
); | ||
}; | ||
|
||
export default AnswersList; | ||
|
||
export default AnswersList; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,24 +1,12 @@ | ||
import axios from 'axios'; | ||
import {API_BASE_URL} from "./AxiosInstance"; | ||
import axiosInstance, {API_BASE_URL} from "./AxiosInstance"; | ||
|
||
const ANSWER_REST_API_URL = API_BASE_URL+"/api/answers"; | ||
const ANSWER_REST_API_URL = API_BASE_URL + "/api/answers"; | ||
|
||
export const getAnswersByQuestionId = async (questionId) => { | ||
return axios.get(`${ANSWER_REST_API_URL}/question/${questionId}`); | ||
}; | ||
|
||
export const getAnswerById = async (id) => { | ||
return axios.get(`${ANSWER_REST_API_URL}/${id}`); | ||
}; | ||
export const getAllAnswers = () => axiosInstance.get(ANSWER_REST_API_URL); | ||
|
||
export const createAnswer = async (answer) => { | ||
return axios.post(ANSWER_REST_API_URL, answer); | ||
}; | ||
|
||
export const updateAnswer = async (id, answer) => { | ||
return axios.put(`${ANSWER_REST_API_URL}/${id}`, answer); | ||
}; | ||
|
||
export const deleteAnswer = async (id) => { | ||
return axios.delete(`${ANSWER_REST_API_URL}/${id}`); | ||
}; | ||
export const getAnswersByQuestionId = (questionId) => axiosInstance.get(`${ANSWER_REST_API_URL}/question/${questionId}`); | ||
export const getAnswerById = (id) => axiosInstance.get(`${ANSWER_REST_API_URL}/${id}`); | ||
export const createAnswer = (answer) => axiosInstance.post(ANSWER_REST_API_URL, answer); | ||
export const updateAnswer = (id, answer) => axiosInstance.put(`${ANSWER_REST_API_URL}/${id}`, answer); | ||
export const deleteAnswer = (id) => axiosInstance.delete(`${ANSWER_REST_API_URL}/${id}`); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,8 @@ | ||
import axios from 'axios'; | ||
import {API_BASE_URL} from "./AxiosInstance"; | ||
import axiosInstance, {API_BASE_URL} from "./AxiosInstance"; | ||
|
||
const EXAM_REST_API_URL = API_BASE_URL+"/api"; | ||
const EXAM_REST_API_URL = API_BASE_URL + "/api"; | ||
|
||
export const getQuizzes = async () => { | ||
return axios.get(`${EXAM_REST_API_URL}/quizzes`); | ||
}; | ||
|
||
export const getQuestions = async (quizId) => { | ||
return axios.get(`${EXAM_REST_API_URL}/quizzes/${quizId}/questions`); | ||
}; | ||
|
||
export const getAnswers = async (questionId) => { | ||
return axios.get(`${EXAM_REST_API_URL}/questions/${questionId}/answers`); | ||
}; | ||
|
||
export const submitExamSession = async (sessionData) => { | ||
return axios.post(`${EXAM_REST_API_URL}/exam_sessions`, sessionData); | ||
}; | ||
export const getQuizzes = () => axiosInstance.get(`${EXAM_REST_API_URL}/quizzes`); | ||
export const getQuestions = (quizId) => axiosInstance.get(`${EXAM_REST_API_URL}/quizzes/${quizId}/questions`); | ||
export const getAnswers = (questionId) => axiosInstance.get(`${EXAM_REST_API_URL}/questions/${questionId}/answers`); | ||
export const submitExamSession = (sessionData) => axiosInstance.post(`${EXAM_REST_API_URL}/exam_sessions`, sessionData); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters