Skip to content

Commit

Permalink
Merge pull request #28 from HackYourFuture-CPH/checkinresponses-backe…
Browse files Browse the repository at this point in the history
…nd/eva

Checkin responses backend/eva
  • Loading branch information
yagmureva authored Apr 21, 2024
2 parents cb35943 + 2d07966 commit eb984d5
Show file tree
Hide file tree
Showing 9 changed files with 461 additions and 0 deletions.
3 changes: 3 additions & 0 deletions packages/client/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Dashboard from './containers/Dashboard/Dashboard';
import { LandingPageContainer } from './containers/LandingPage/LandingPage';
import { CheckinQuestions } from './containers/QuestionPage/CheckinQuestions';
import { TeamIdContextProvider } from './hooks/contextHook';
import { ReportPage } from './containers/ReportPage/ReportPage';

function App() {
return (
Expand All @@ -15,6 +16,8 @@ function App() {
<Route path="/" element={<LandingPageContainer />} />
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/questions" element={<CheckinQuestions />} />
<Route path="/reportpage" element={<ReportPage />} />
<Route path="*" element={<PageNotFound />} />
</Routes>
</Router>
</TeamIdContextProvider>
Expand Down
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 };
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 };
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 packages/client/src/containers/ReportPage/ReportPage.jsx
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 };
Loading

0 comments on commit eb984d5

Please sign in to comment.