diff --git a/frontend/src/components/Navbar.js b/frontend/src/components/Navbar.js index 065fc36..cfb4f2b 100644 --- a/frontend/src/components/Navbar.js +++ b/frontend/src/components/Navbar.js @@ -26,6 +26,7 @@ export function renderNavbar() { About Contact Feedback + Discussion Forum diff --git a/frontend/src/pages/DiscussionForum.js b/frontend/src/pages/DiscussionForum.js new file mode 100644 index 0000000..8fa5099 --- /dev/null +++ b/frontend/src/pages/DiscussionForum.js @@ -0,0 +1,209 @@ +export async function renderDiscussionForum(container) { + // Initialize questions data + let questions = JSON.parse(localStorage.getItem('questions')) || []; + + // Helper function to save questions to localStorage + const saveQuestions = () => { + localStorage.setItem('questions', JSON.stringify(questions)); + }; + + // Function to handle adding a new question + const addQuestion = (content) => { + const newQuestion = { + id: Date.now(), + content: content, + answered: false, + answer: '', + }; + questions.push(newQuestion); + saveQuestions(); + render(); + }; + + // Function to handle adding an answer to a question + const addAnswer = (questionId, answerContent) => { + questions = questions.map(q => + q.id === questionId ? { ...q, answered: true, answer: answerContent } : q + ); + saveQuestions(); + render(); + }; + + // Function to render the Question Card + const renderQuestionCard = (question) => { + const card = document.createElement('div'); + card.classList.add('bg-white', 'dark:bg-gray-800', 'p-4', 'rounded-md', 'shadow-md', 'mb-4', 'w-[30%]'); + + const questionText = document.createElement('p'); + questionText.textContent = question.content; + questionText.classList.add('text-lg', 'text-gray-800', 'dark:text-gray-100'); + + card.appendChild(questionText); + + if (question.answered) { + const answerSection = document.createElement('div'); + answerSection.classList.add('mt-4', 'text-gray-600', 'dark:text-gray', 'dark:bg-gray-700', 'p-5', 'rounded-lg') + const answerTitle = document.createElement('h3'); + answerTitle.textContent = 'Answer:'; + answerTitle.classList.add('text-indigo-600', 'dark:text-indigo-400'); + + const answerText = document.createElement('p'); + answerText.textContent = question.answer; + answerText.classList.add('text-gray-700', 'dark:text-gray-300'); + + answerSection.appendChild(answerTitle); + answerSection.appendChild(answerText); + card.appendChild(answerSection); + } else { + const answerForm = renderAnswerForm(question.id); + card.appendChild(answerForm); + } + + return card; + }; + // Function to render the Question Form + const renderQuestionForm = () => { + const formContainer = document.createElement('div'); + formContainer.classList.add('bg-white', 'dark:bg-gray-800', 'p-4', 'rounded-md', 'shadow-md', 'mb-6'); + + const textarea = document.createElement('textarea'); + textarea.placeholder = 'Ask your question...'; + textarea.classList.add('w-full', 'p-3', 'border', 'rounded-md', 'dark:bg-gray-700', 'dark:text-white', 'focus:outline-none', 'focus:ring-2', 'focus:ring-indigo-500'); + + const button = document.createElement('button'); + button.textContent = 'Ask Question'; + button.classList.add('mt-4', 'bg-indigo-500', 'text-white', 'px-4', 'py-2', 'rounded-md', 'hover:bg-indigo-600', 'focus:outline-none', 'focus:ring-2', 'focus:ring-indigo-500'); + + formContainer.appendChild(textarea); + formContainer.appendChild(button); + + button.addEventListener('click', (e) => { + e.preventDefault(); + const content = textarea.value.trim(); + if (content) { + addQuestion(content); + textarea.value = ''; + } + }); + + return formContainer; + }; + + // Function to render the Answer Form + const renderAnswerForm = (questionId) => { + const formContainer = document.createElement('div'); + formContainer.classList.add('bg-white', 'dark:bg-gray-800', 'p-4', 'rounded-md', 'shadow-md', 'mt-4'); + + const textarea = document.createElement('textarea'); + textarea.placeholder = 'Write your answer...'; + textarea.classList.add('w-full', 'p-3', 'border', 'rounded-md', 'dark:bg-gray-700', 'dark:text-white', 'focus:outline-none', 'focus:ring-2', 'focus:ring-indigo-500'); + + const button = document.createElement('button'); + button.textContent = 'Submit Answer'; + button.classList.add('mt-4', 'bg-green-500', 'text-white', 'px-4', 'py-2', 'rounded-md', 'hover:bg-green-600', 'focus:outline-none', 'focus:ring-2', 'focus:ring-green-500'); + + formContainer.appendChild(textarea); + formContainer.appendChild(button); + + button.addEventListener('click', (e) => { + e.preventDefault(); + const answerContent = textarea.value.trim(); + if (answerContent) { + addAnswer(questionId, answerContent); + textarea.value = ''; + } + }); + + return formContainer; + }; + + + + // Function to render the list of questions + const renderQuestionList = () => { + // Create container divs for unanswered and answered sections + const unansweredContainer = document.createElement('div'); + const answeredContainer = document.createElement('div'); + + // Create titles for unanswered and answered questions + const unansweredTitle = document.createElement('h2'); + unansweredTitle.textContent = 'Unanswered Questions'; + unansweredTitle.classList.add('text-2xl', 'font-semibold', 'mb-4', 'text-gray-800', 'dark:text-white'); + + const answeredTitle = document.createElement('h2'); + answeredTitle.textContent = 'Answered Questions'; + answeredTitle.classList.add('text-2xl', 'font-semibold', 'mb-4', 'text-gray-800', 'dark:text-white', 'mt-8'); + + // Append the titles to their respective containers + unansweredContainer.appendChild(unansweredTitle); + answeredContainer.appendChild(answeredTitle); + + // Filter questions into answered and unanswered arrays + const unansweredQuestions = questions.filter(q => !q.answered); + const answeredQuestions = questions.filter(q => q.answered); + + // Create a wrapper div for unanswered questions + const unansweredCardsContainer = document.createElement('div'); + unansweredCardsContainer.classList.add('flex', 'gap-9', 'flex-wrap'); // Add space between cards + + // Handle unanswered questions + if (unansweredQuestions.length === 0) { + const noUnansweredMessage = document.createElement('p'); + noUnansweredMessage.textContent = 'No unanswered questions yet.'; + unansweredCardsContainer.appendChild(noUnansweredMessage); + } else { + unansweredQuestions.forEach(q => { + const questionCard = renderQuestionCard(q); + unansweredCardsContainer.appendChild(questionCard); + }); + } + + // Create a wrapper div for answered questions + const answeredCardsContainer = document.createElement('div'); + answeredCardsContainer.classList.add('flex', 'gap-9', 'flex-wrap'); // Add space between cards + + // Handle answered questions + if (answeredQuestions.length === 0) { + const noAnsweredMessage = document.createElement('p'); + noAnsweredMessage.textContent = 'No answered questions yet.'; + answeredCardsContainer.appendChild(noAnsweredMessage); + } else { + answeredQuestions.forEach(q => { + const questionCard = renderQuestionCard(q); + answeredCardsContainer.appendChild(questionCard); + }); + } + + // Append the card containers to their respective sections + unansweredContainer.appendChild(unansweredCardsContainer); + answeredContainer.appendChild(answeredCardsContainer); + + // Append both sections to the container + container.appendChild(unansweredContainer); + container.appendChild(answeredContainer); + }; + + + + const render = () => { + container.innerHTML = ''; // Clear the container + + // Create the heading for the forum + const heading = document.createElement('h1'); + heading.textContent = 'Wordwise Discussion Forum'; + heading.classList.add('text-3xl', 'font-bold', 'mb-6', 'text-gray-800', 'dark:text-white'); + container.appendChild(heading); + + // First, append the question form at the top + const questionForm = renderQuestionForm(); + container.appendChild(questionForm); + + // Then, append the question list (answered and unanswered) + const questionList = renderQuestionList(); + container.appendChild(questionList); + }; + + + + render(); // Initial render +} diff --git a/frontend/src/styles/output.css b/frontend/src/styles/output.css index 396c5ae..390a629 100644 --- a/frontend/src/styles/output.css +++ b/frontend/src/styles/output.css @@ -782,6 +782,10 @@ video { height: 2rem; } +.min-h-screen { + min-height: 100vh; +} + .w-1\/3 { width: 33.333333%; } @@ -835,6 +839,22 @@ video { width: 100%; } +.w-\[27\%\] { + width: 27%; +} + +.w-\[28\%\] { + width: 28%; +} + + .w-\[29\%\] { + width: 29%; +} + +.w-\[30\%\] { + width: 30%; +} + .max-w-4xl { max-width: 56rem; } @@ -843,6 +863,7 @@ video { max-width: 1280px; } + .transform { transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } @@ -903,6 +924,14 @@ video { gap: 2rem; } +.gap-2 { + gap: 0.5rem; +} + +.gap-9 { + gap: 2.25rem; +} + .space-x-3 > :not([hidden]) ~ :not([hidden]) { --tw-space-x-reverse: 0; margin-right: calc(0.75rem * var(--tw-space-x-reverse)); @@ -1132,6 +1161,30 @@ video { background-color: rgb(254 249 195 / var(--tw-bg-opacity)); } + .bg-green-500 { + --tw-bg-opacity: 1; + background-color: rgb(34 197 94 / var(--tw-bg-opacity)); +} + +.bg-indigo-500 { + --tw-bg-opacity: 1; + background-color: rgb(99 102 241 / var(--tw-bg-opacity)); +} + +.bg-gradient-to-r { + background-image: linear-gradient(to right, var(--tw-gradient-stops)); +} + +.from-indigo-100 { + --tw-gradient-from: #e0e7ff var(--tw-gradient-from-position); + --tw-gradient-to: rgb(224 231 255 / 0) var(--tw-gradient-to-position); + --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to); +} + +.to-purple-100 { + --tw-gradient-to: #f3e8ff var(--tw-gradient-to-position); +} + .object-cover { -o-object-fit: cover; object-fit: cover; @@ -1161,9 +1214,11 @@ video { padding: 2rem; } -.p-1 { + .p-5 { + padding: 1.25rem; + .p-1 { padding: 0.25rem; -} + } .px-12 { padding-left: 3rem; @@ -1440,6 +1495,12 @@ video { color: rgb(133 77 14 / var(--tw-text-opacity)); } + .text-indigo-400 { + --tw-text-opacity: 1; + color: rgb(129 140 248 / var(--tw-text-opacity)); +} + + .shadow-lg { --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color); @@ -1458,6 +1519,12 @@ video { box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); } +.shadow { + --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1); + --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} + .shadow-gray-200 { --tw-shadow-color: #e5e7eb; --tw-shadow: var(--tw-shadow-colored); @@ -1541,6 +1608,12 @@ body.dark-mode { padding: 20px; } +.hover\:scale-105:hover { + --tw-scale-x: 1.05; + --tw-scale-y: 1.05; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + .hover\:bg-\[\#753ff1\]:hover { --tw-bg-opacity: 1; background-color: rgb(117 63 241 / var(--tw-bg-opacity)); @@ -1596,6 +1669,16 @@ body.dark-mode { background-color: rgb(255 255 255 / var(--tw-bg-opacity)); } +.hover\:bg-green-600:hover { + --tw-bg-opacity: 1; + background-color: rgb(22 163 74 / var(--tw-bg-opacity)); +} + +.hover\:bg-indigo-600:hover { + --tw-bg-opacity: 1; + background-color: rgb(79 70 229 / var(--tw-bg-opacity)); +} + .hover\:text-blue-700:hover { --tw-text-opacity: 1; color: rgb(29 78 216 / var(--tw-text-opacity)); @@ -1702,6 +1785,11 @@ body.dark-mode { --tw-ring-color: rgb(248 113 113 / var(--tw-ring-opacity)); } +.focus\:ring-green-500:focus { + --tw-ring-opacity: 1; + --tw-ring-color: rgb(34 197 94 / var(--tw-ring-opacity)); +} + .focus\:ring-opacity-50:focus { --tw-ring-opacity: 0.5; } diff --git a/frontend/src/utils/router.js b/frontend/src/utils/router.js index 618b72c..038232a 100644 --- a/frontend/src/utils/router.js +++ b/frontend/src/utils/router.js @@ -8,6 +8,7 @@ import { renderFeedback } from '../pages/Feedback.js'; import { renderProfilePage } from '../pages/BloggerProfile.js'; import { renderFullBlogPost } from '../pages/ReadMoreBlog.js'; import { renderTermsOfUse } from '../pages/TermsOfUse.js'; +import { renderDiscussionForum } from '../pages/DiscussionForum.js'; const routes = { '/': renderHome, @@ -18,10 +19,10 @@ const routes = { '/contact': renderContact, '/feedback': renderFeedback, '/profile': renderProfilePage, - + '/discussion': renderDiscussionForum, '/readmore': renderFullBlogPost, '/termsOfUse': renderTermsOfUse, - }; +}; export function router() { const path = window.location.pathname; diff --git a/index.html b/index.html index ba77994..d25ee61 100644 --- a/index.html +++ b/index.html @@ -421,12 +421,16 @@ WordWise + - + - + + @@ -454,6 +458,7 @@ WordWise menu.style.display = 'none'; } } + @@ -461,6 +466,7 @@ WordWise + × Login @@ -505,8 +511,9 @@ Login + + style="max-width: 400px; margin: auto;"> × Signup @@ -752,6 +759,7 @@ Forgot Password + +