generated from HackYourFuture-CPH/boilerplate-for-fp
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #28 from HackYourFuture-CPH/checkinresponses-backe…
…nd/eva Checkin responses backend/eva
- Loading branch information
Showing
9 changed files
with
461 additions
and
0 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
42 changes: 42 additions & 0 deletions
42
packages/client/src/containers/Dashboard/CheckinQuestionsPage/AddCheckinQuestionModal.jsx
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 |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
|
||
const AddCheckinQuestionModal = ({ | ||
showAddModal, | ||
setShowAddModal, | ||
newQuestionText, | ||
setNewQuestionText, | ||
handleAdd, | ||
}) => { | ||
if (!showAddModal) { | ||
return null; | ||
} | ||
|
||
return ( | ||
<div> | ||
<h2>Add Checkin Question</h2> | ||
<textarea | ||
value={newQuestionText} | ||
onChange={(e) => setNewQuestionText(e.target.value)} | ||
placeholder="Enter the new question..." | ||
rows={4} | ||
></textarea> | ||
<button type="button" onClick={handleAdd}> | ||
Add Question | ||
</button> | ||
<button type="button" onClick={() => setShowAddModal(false)}> | ||
Cancel | ||
</button> | ||
</div> | ||
); | ||
}; | ||
|
||
AddCheckinQuestionModal.propTypes = { | ||
showAddModal: PropTypes.bool.isRequired, | ||
setShowAddModal: PropTypes.func.isRequired, | ||
newQuestionText: PropTypes.string.isRequired, | ||
setNewQuestionText: PropTypes.func.isRequired, | ||
handleAdd: PropTypes.func.isRequired, | ||
}; | ||
|
||
export { AddCheckinQuestionModal }; |
165 changes: 165 additions & 0 deletions
165
packages/client/src/containers/Dashboard/CheckinQuestionsPage/CheckinQuestions.jsx
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 |
---|---|---|
@@ -0,0 +1,165 @@ | ||
import React, { useEffect, useState } from 'react'; | ||
import { apiURL } from '../../../apiURL'; | ||
import { AddCheckinQuestionModal } from './AddCheckinQuestionModal'; | ||
import { EditCheckinQuestionModal } from './EditCheckinQuestionModal'; | ||
import { Button, Typography } from '@mui/material'; | ||
|
||
const CheckinQuestions = () => { | ||
const [checkinQuestions, setCheckinQuestions] = useState(null); | ||
const [editQuestionId, setEditQuestionId] = useState(null); | ||
const [showAddModal, setShowAddModal] = useState(false); | ||
const [newQuestionText, setNewQuestionText] = useState(''); | ||
const [updatedQuestionText, setUpdatedQuestionText] = useState(''); | ||
|
||
useEffect(() => { | ||
fetchCheckinQuestions(); | ||
}, []); | ||
|
||
const fetchCheckinQuestions = async () => { | ||
try { | ||
const response = await fetch(`${apiURL()}/checkinQuestions`); | ||
if (!response.ok) { | ||
throw new Error('Failed to fetch checkin questions'); | ||
} | ||
const data = await response.json(); | ||
setCheckinQuestions(data); | ||
} catch (error) { | ||
console.error('Error fetching checkin questions:', error.message); | ||
setCheckinQuestions([]); | ||
} | ||
}; | ||
|
||
const handleEditQuestion = (questionId, questionText) => { | ||
setEditQuestionId(questionId); | ||
setUpdatedQuestionText(questionText); | ||
}; | ||
|
||
const handleAddQuestion = () => { | ||
setShowAddModal(true); | ||
setEditQuestionId(null); | ||
}; | ||
|
||
const handleSaveEdit = async (questionId) => { | ||
try { | ||
const response = await fetch( | ||
`${apiURL()}/checkinQuestions/${questionId}`, | ||
{ | ||
method: 'PATCH', | ||
headers: { | ||
'Content-Type': 'application/json', | ||
}, | ||
body: JSON.stringify({ question_text: updatedQuestionText }), | ||
}, | ||
); | ||
if (!response.ok) { | ||
throw new Error('Failed to edit checkin question'); | ||
} | ||
fetchCheckinQuestions(); | ||
setEditQuestionId(null); | ||
} catch (error) { | ||
console.error('Error editing checkin question:', error.message); | ||
} | ||
}; | ||
|
||
const handleAdd = async () => { | ||
try { | ||
const response = await fetch(`${apiURL()}/checkinQuestions`, { | ||
method: 'POST', | ||
headers: { | ||
'Content-Type': 'application/json', | ||
}, | ||
body: JSON.stringify({ question_text: newQuestionText }), | ||
}); | ||
if (!response.ok) { | ||
throw new Error('Failed to add question'); | ||
} | ||
fetchCheckinQuestions(); | ||
setShowAddModal(false); | ||
} catch (error) { | ||
console.error('Error adding question:', error.message); | ||
} | ||
}; | ||
|
||
const handleDeleteQuestion = async (questionId) => { | ||
const confirmDelete = window.confirm( | ||
'Are you sure you want to delete this question?', | ||
); | ||
if (confirmDelete) { | ||
try { | ||
const response = await fetch( | ||
`${apiURL()}/checkinQuestions/${questionId}`, | ||
{ method: 'DELETE' }, | ||
); | ||
if (!response.ok) { | ||
throw new Error('Failed to delete checkin question'); | ||
} | ||
fetchCheckinQuestions(); | ||
} catch (error) { | ||
console.error('Error deleting checkin question:', error.message); | ||
} | ||
} | ||
}; | ||
|
||
if (checkinQuestions === null) { | ||
return <Typography>Loading Questions...</Typography>; | ||
} | ||
|
||
return ( | ||
<div> | ||
<Typography variant="h4" component="h1"> | ||
Checkin Questions | ||
</Typography> | ||
<ul> | ||
{checkinQuestions.map((question) => ( | ||
<li key={question.question_id}> | ||
<Typography>{question.question_text}</Typography> | ||
{editQuestionId !== question.question_id && ( | ||
<> | ||
<Button | ||
onClick={() => | ||
handleEditQuestion( | ||
question.question_id, | ||
question.question_text, | ||
) | ||
} | ||
color="primary" | ||
> | ||
Edit | ||
</Button> | ||
<Button | ||
onClick={() => handleDeleteQuestion(question.question_id)} | ||
color="secondary" | ||
> | ||
Delete | ||
</Button> | ||
</> | ||
)} | ||
</li> | ||
))} | ||
</ul> | ||
<Button onClick={handleAddQuestion} variant="contained" color="primary"> | ||
Add Question | ||
</Button> | ||
{showAddModal && ( | ||
<AddCheckinQuestionModal | ||
showAddModal={showAddModal} | ||
setShowAddModal={setShowAddModal} | ||
newQuestionText={newQuestionText} | ||
setNewQuestionText={setNewQuestionText} | ||
handleAdd={handleAdd} | ||
/> | ||
)} | ||
{editQuestionId && ( | ||
<EditCheckinQuestionModal | ||
showEditModal={editQuestionId} | ||
questionId={editQuestionId} | ||
questionText={updatedQuestionText} | ||
setQuestionText={setUpdatedQuestionText} | ||
handleSaveEdit={handleSaveEdit} | ||
/> | ||
)} | ||
</div> | ||
); | ||
}; | ||
|
||
export { CheckinQuestions }; |
40 changes: 40 additions & 0 deletions
40
packages/client/src/containers/Dashboard/CheckinQuestionsPage/EditCheckinQuestionModal.jsx
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 |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
|
||
export const EditCheckinQuestionModal = ({ | ||
showEditModal, | ||
questionId, | ||
questionText, | ||
setQuestionText, | ||
handleSaveEdit, | ||
}) => { | ||
if (!showEditModal) { | ||
return null; | ||
} | ||
|
||
return ( | ||
<div> | ||
<h2>Edit Checkin Question</h2> | ||
<textarea | ||
value={questionText} | ||
onChange={(e) => setQuestionText(e.target.value)} | ||
placeholder="Enter the updated question..." | ||
rows={4} | ||
></textarea> | ||
<button | ||
type="button" | ||
onClick={() => handleSaveEdit(questionId, questionText)} | ||
> | ||
Save | ||
</button> | ||
</div> | ||
); | ||
}; | ||
|
||
EditCheckinQuestionModal.propTypes = { | ||
showEditModal: PropTypes.bool.isRequired, | ||
questionId: PropTypes.number.isRequired, | ||
questionText: PropTypes.string.isRequired, | ||
setQuestionText: PropTypes.func.isRequired, | ||
handleSaveEdit: PropTypes.func.isRequired, | ||
}; |
106 changes: 106 additions & 0 deletions
106
packages/client/src/containers/ReportPage/ReportPage.jsx
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 |
---|---|---|
@@ -0,0 +1,106 @@ | ||
import React, { useState, useEffect } from 'react'; | ||
import { apiURL } from '../../apiURL'; | ||
import { useTeamIdContext } from '../../hooks/contextHook'; | ||
|
||
const ReportPage = () => { | ||
const [questions, setQuestions] = useState([]); | ||
const [responses, setResponses] = useState({}); | ||
const [loading, setLoading] = useState(true); | ||
const { teamId } = useTeamIdContext(); | ||
|
||
useEffect(() => { | ||
const loadQuestions = async () => { | ||
try { | ||
setLoading(true); | ||
const questionsRes = await fetch(`${apiURL()}/checkinQuestions`, { | ||
headers: { 'X-Team-ID': teamId }, | ||
}); | ||
const questionsData = await questionsRes.json(); | ||
setQuestions(questionsData); | ||
|
||
// Initialize responses state | ||
const initialResponses = {}; | ||
questionsData.forEach((question) => { | ||
initialResponses[question.question_id] = ''; | ||
}); | ||
setResponses(initialResponses); | ||
} catch (error) { | ||
console.error('Error fetching data:', error); | ||
} finally { | ||
setLoading(false); | ||
} | ||
}; | ||
|
||
loadQuestions(); | ||
}, [teamId]); // Added teamId dependency | ||
|
||
const handleResponseChange = (questionId, text) => { | ||
setResponses((prevResponses) => ({ | ||
...prevResponses, | ||
[questionId]: text, | ||
})); | ||
}; | ||
|
||
const handleSubmit = async () => { | ||
try { | ||
setLoading(true); | ||
const payload = { | ||
responses, | ||
}; | ||
|
||
const response = await fetch(`${apiURL()}/checkinResponses`, { | ||
method: 'POST', | ||
headers: { | ||
'Content-Type': 'application/json', | ||
'X-Team-ID': teamId, // Add this if your API requires it | ||
}, | ||
body: JSON.stringify(payload), | ||
}); | ||
|
||
if (!response.ok) { | ||
throw new Error('Failed to submit check-in data'); | ||
} | ||
|
||
alert('Submitted successfully!'); | ||
setResponses({}); | ||
} catch (error) { | ||
console.error('Error submitting check-in:', error); | ||
alert('Error submitting data: ' + error.message); | ||
} finally { | ||
setLoading(false); | ||
} | ||
}; | ||
|
||
if (loading) { | ||
return <div>Loading...</div>; | ||
} | ||
|
||
const isSubmitDisabled = questions.some( | ||
(q) => !responses[q.question_id] || responses[q.question_id].trim() === '', | ||
); | ||
|
||
return ( | ||
<div> | ||
<h2>Check-in Questions</h2> | ||
{questions.map((question) => ( | ||
<div key={question.question_id}> | ||
<p>{question.question_text}</p> | ||
<textarea | ||
placeholder="Your response" | ||
value={responses[question.question_id]} | ||
onChange={(e) => | ||
handleResponseChange(question.question_id, e.target.value) | ||
} | ||
rows="2" | ||
style={{ width: '100%', marginBottom: '10px' }} | ||
/> | ||
</div> | ||
))} | ||
<button onClick={handleSubmit} disabled={loading || isSubmitDisabled}> | ||
{loading ? 'Submitting...' : 'Submit'} | ||
</button> | ||
</div> | ||
); | ||
}; | ||
|
||
export { ReportPage }; |
Oops, something went wrong.