Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Interactive Discussion Forum with Responsive Design ✨ #432

Merged
merged 3 commits into from
Nov 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion client/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions client/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import "aos/dist/aos.css";
import Collab from "./component/Collab";
import CreateBlog from "./component/CreateBlog";
import UploadProject from "./component/UploadProject";
import DiscussionForum from "./component/DiscussionForum";

const Layout = ({ children, mode, setProgress, toggleMode, showAlert }) => {
return (
Expand Down Expand Up @@ -146,6 +147,7 @@ function App() {
<Route exact path='/uploadProject' element={<UploadProject mode={mode} setProgress={setProgress} showAlert={showAlert} />} />
<Route exact path='/createBlogPost' element={<CreateBlog />} />
<Route exact path='/read-more-blog/:id' element={<ReadMoreBlog mode={mode} setProgress={setProgress} showAlert={showAlert} />} />
<Route exact path='/discussionForum' element={<DiscussionForum mode={mode} setProgress={setProgress} showAlert={showAlert} />} />
<Route exact path='/*' element={<NotFound />} />
</Routes>
</Layout>
Expand Down
156 changes: 156 additions & 0 deletions client/src/component/DiscussionForum.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
import { useState, useEffect } from 'react';

const DiscussionForum = (props) => {
const [questions, setQuestions] = useState([]);

// Fetch questions from localStorage
useEffect(() => {
const storedQuestions = localStorage.getItem('questions');
if (storedQuestions) {
setQuestions(JSON.parse(storedQuestions));
}
}, []);

// Save questions to localStorage
const saveQuestions = (updatedQuestions) => {
setQuestions(updatedQuestions);
localStorage.setItem('questions', JSON.stringify(updatedQuestions));
};

// Helper function to save a new question
const addQuestion = (content) => {
const newQuestion = {
id: Date.now().toString(),
content,
answered: false,
answer: '',
};

const updatedQuestions = [...questions, newQuestion];
saveQuestions(updatedQuestions);
};

// Helper function to add an answer to a question
const addAnswer = (questionId, answerContent) => {
const updatedQuestions = questions.map((question) =>
question.id === questionId
? { ...question, answered: true, answer: answerContent }
: question
);
saveQuestions(updatedQuestions);
};

// Function to render the Question Card
const renderQuestionCard = (question) => {
return (
<div
className={`${props.mode === 'dark' ? 'bg-gray-800 text-gray-200' : 'bg-white text-gray-800'
} p-6 rounded-lg shadow-lg mb-6 w-full md:w-[48%] lg:w-[30%] transition-transform transform hover:scale-105`}
key={question.id}
>
<p className="text-xl font-semibold">{question.content}</p>
{question.answered ? (
<div className={`mt-4 ${props.mode === 'dark' ? 'bg-gray-700' : 'bg-white'} p-4 rounded-md shadow-md`}>
<h3 className="text-lg font-semibold">Answer:</h3>
<p>{question.answer}</p>
</div>
) : (
<AnswerForm questionId={question.id} />
)}
</div>
);
};

// Function to render the Answer Form
const AnswerForm = ({ questionId }) => {
const [answer, setAnswer] = useState('');

const handleSubmit = (e) => {
e.preventDefault();
if (answer.trim()) {
addAnswer(questionId, answer);
setAnswer('');
}
};

return (
<form onSubmit={handleSubmit} className={`${props.mode === 'dark' ? 'bg-gray-700' : 'bg-white'} p-4 rounded-md shadow-md mt-4`}>
<textarea
value={answer}
onChange={(e) => setAnswer(e.target.value)}
placeholder="Write your answer..."
className={`w-full p-4 border rounded-md ${props.mode === 'dark' ? 'bg-gray-600 text-gray-200' : 'bg-gray-100 text-gray-800'
} focus:outline-none focus:ring-2 focus:ring-gray-500 transition-all`}
/>
<button
type="submit"
className="mt-4 bg-gray-800 text-white px-6 py-2 rounded-md hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-gray-500 transition-colors"
>
Submit Answer
</button>
</form>
);
};

// Function to render the Question Form
const QuestionForm = () => {
const [newQuestion, setNewQuestion] = useState('');

const handleSubmit = (e) => {
e.preventDefault();
if (newQuestion.trim()) {
addQuestion(newQuestion);
setNewQuestion('');
}
};

return (
<div className={`p-6 rounded-lg shadow-lg mb-8 ${props.mode === 'dark' ? 'bg-gray-800 text-gray-200' : 'bg-white text-gray-800'}`}>
<textarea
value={newQuestion}
onChange={(e) => setNewQuestion(e.target.value)}
placeholder="Ask your question..."
className={`w-full p-4 border rounded-md ${props.mode === 'dark' ? 'bg-gray-600 text-gray-200' : 'bg-gray-100 text-gray-800'
} focus:outline-none focus:ring-2 focus:ring-gray-500 transition-all`}
/>
<button
onClick={handleSubmit}
className="mt-4 bg-gray-800 text-white px-6 py-2 rounded-md hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-gray-500 transition-colors"
>
Ask Question
</button>
</div>
);
};

return (
<div className="container mx-auto px-6 py-8 mt-20">
<h1 className="text-4xl font-bold text-center mb-8">
BITBOX Discussion Forum
</h1>

<QuestionForm />

<div>
<h2 className="text-2xl font-semibold mb-6">Unanswered Questions</h2>
<div className="flex flex-wrap gap-6">
{questions
.filter((question) => !question.answered)
.map((question) => renderQuestionCard(question))}
</div>
</div>
<div class="p-[1px] bg-blue-500 text-white rounded-md shadow">
</div>
<div>
<h2 className="text-2xl font-semibold mb-6 mt-8">Answered Questions</h2>
<div className="flex flex-wrap gap-6">
{questions
.filter((question) => question.answered)
.map((question) => renderQuestionCard(question))}
</div>
</div>
</div>
);
};

export default DiscussionForum;
55 changes: 55 additions & 0 deletions client/src/component/faq.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// component/FAQ.jsx
import { useState } from "react";
import "../css/Faq.css";

const FAQ = () => {
const [activeIndex, setActiveIndex] = useState(null);

const toggleAnswer = (index) => {
setActiveIndex(activeIndex === index ? null : index);
};

return (
<div className="faq-container">
<h1>Frequently Asked Questions</h1>
{faqData.map((item, index) => (
<div key={index} className="faq-item">
<h2 onClick={() => toggleAnswer(index)} className="faq-question">
{item.question}
</h2>
{activeIndex === index && <p className="faq-answer">{item.answer}</p>}
</div>
))}
</div>
);
};

const faqData = [
{
question: "What is BitBox?",
answer:
"BitBox is a user-friendly platform that simplifies version control and collaboration for developers.",
},
{
question: "How does BitBox enhance collaboration?",
answer:
"BitBox offers intuitive tools that enable both solo programmers and large teams to manage projects efficiently.",
},
{
question: "How do I get started with BitBox?",
answer:
"You can sign up for an account on BitBox and start managing your projects right away.",
},
{
question: "Is BitBox compatible with modern development workflows?",
answer:
"Yes, BitBox seamlessly integrates with modern development workflows, providing fast and reliable performance.",
},
{
question: "How can I contact support if I need help?",
answer:
"You can reach out to support through the 'Contact Us' page or by emailing [email protected].",
},
];

export default FAQ;
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading