| ```javascript | |
| document.addEventListener('DOMContentLoaded', function() { | |
| // DOM Elements | |
| const postForm = document.getElementById('post-form'); | |
| const panel1 = document.getElementById('panel-1'); | |
| const panel2 = document.getElementById('panel-2'); | |
| const panel3 = document.getElementById('panel-3'); | |
| const postsList = document.getElementById('posts-list'); | |
| const myPostsList = document.getElementById('my-posts-list'); | |
| const postDetail = document.getElementById('post-detail'); | |
| const unansweredCount = document.getElementById('unanswered-count'); | |
| const allQuestionsLink = document.getElementById('all-questions-link'); | |
| const myPostsLink = document.getElementById('my-posts-link'); | |
| const unansweredLink = document.getElementById('unanswered-link'); | |
| // Data collection variables | |
| let dashboardEntryTime = Date.now(); | |
| let postCreationStartTime = null; | |
| let unansweredFilterStartTime = null; | |
| let unansweredFilterInteractionStartTime = null; | |
| // Sample data | |
| const samplePosts = [ | |
| { | |
| id: 1, | |
| title: "Understanding recursion in binary trees", | |
| body: "I'm having trouble understanding how recursion works with binary tree traversal. Can someone explain the base case and recursive case?", | |
| tags: ["Recursion", "Binary Trees", "Data Structures"], | |
| responses: 3, | |
| isMine: false, | |
| hasNewResponse: false | |
| }, | |
| { | |
| id: 2, | |
| title: "Clarification on HW3 problem 2", | |
| body: "The problem statement says we need to implement a function with O(n) time complexity, but I'm not sure what approach to take.", | |
| tags: ["Homework", "Algorithms"], | |
| responses: 1, | |
| isMine: false, | |
| hasNewResponse: false | |
| } | |
| ]; | |
| // Initialize data collection | |
| initializeDataCollection(); | |
| let userPosts = []; | |
| // Log dashboard entry | |
| console.log('π Dashboard entry time recorded:', dashboardEntryTime); | |
| // Add event listeners for form inputs to start post creation timer | |
| document.getElementById('post-title').addEventListener('focus', function() { | |
| if (!postCreationStartTime) { | |
| postCreationStartTime = Date.now(); | |
| } | |
| }); | |
| document.getElementById('post-body').addEventListener('focus', function() { | |
| if (!postCreationStartTime) { | |
| postCreationStartTime = Date.now(); | |
| } | |
| }); | |
| document.getElementById('post-tags').addEventListener('focus', function() { | |
| if (!postCreationStartTime) { | |
| postCreationStartTime = Date.now(); | |
| } | |
| }); | |
| // Form submission | |
| postForm.addEventListener('submit', function(e) { | |
| e.preventDefault(); | |
| const title = document.getElementById('post-title').value; | |
| const body = document.getElementById('post-body').value; | |
| const tags = document.getElementById('post-tags').value.split(',').map(tag => tag.trim()); | |
| // Validate form data | |
| let formErrors = 0; | |
| if (!title.trim()) { | |
| logFormError('empty_title'); | |
| formErrors++; | |
| console.log('β Form error: Empty title'); | |
| } | |
| if (!body.trim()) { | |
| logFormError('empty_body'); | |
| formErrors++; | |
| console.log('β Form error: Empty body'); | |
| } | |
| if (tags.length === 0 || (tags.length === 1 && !tags[0].trim())) { | |
| logFormError('empty_tags'); | |
| formErrors++; | |
| console.log('β Form error: Empty tags'); | |
| } | |
| // Calculate total post creation time | |
| const totalPostCreationTime = (Date.now() - postCreationStartTime) / 1000; | |
| // Store KPI data | |
| storeKPIData('total_post_creation_time', totalPostCreationTime); | |
| storeKPIData('form_adherance', formErrors); | |
| // Log successful form submission | |
| console.log('β Post creation completed:', { | |
| totalTime: totalPostCreationTime + 's', | |
| formErrors: formErrors, | |
| titleLength: title.length, | |
| bodyLength: body.length, | |
| tagCount: tags.length | |
| }); | |
| // Create new post | |
| const newPost = { | |
| id: Date.now(), | |
| title, | |
| body, | |
| tags, | |
| responses: 0, | |
| isMine: true, | |
| hasNewResponse: false | |
| }; | |
| // Add to user posts | |
| userPosts.unshift(newPost); | |
| // Update UI | |
| updateUnansweredCount(); | |
| showPanel2(newPost); | |
| // Reset form | |
| postForm.reset(); | |
| }); | |
| // Initialize with All Questions panel by default | |
| document.addEventListener('DOMContentLoaded', function() { | |
| setActiveNav(allQuestionsLink); | |
| showPanel1(); | |
| updateUnansweredCount(); | |
| // Store sample posts for later use | |
| window.placeholderPosts = [ | |
| { | |
| title: "Binary Search Tree Implementation", | |
| body: "Need help implementing insert function for BST in Python.", | |
| tags: ["BST", "Python", "Data Structures"], | |
| responses: 0, | |
| time: "30 minutes ago", | |
| status: "unanswered" | |
| }, | |
| { | |
| title: "Lecture 8 Slides Question", | |
| body: "Confused about time complexity analysis on slide 25.", | |
| tags: ["Lecture", "Time Complexity"], | |
| responses: 0, | |
| time: "1 hour ago", | |
| status: "unanswered" | |
| }, | |
| { | |
| title: "HW3 Problem 5 Solution", | |
| body: "Looking for optimal solution approach for problem 5 in homework 3.", | |
| tags: ["Homework", "Algorithms"], | |
| responses: 0, | |
| time: "2 hours ago", | |
| status: "unanswered" | |
| }, | |
| { | |
| title: "Recursion vs Iteration", | |
| body: "When should I prefer recursion over iteration for tree traversal?", | |
| tags: ["Recursion", "Trees"], | |
| responses: 0, | |
| time: "3 hours ago", | |
| status: "unanswered" | |
| }, | |
| { | |
| title: "Debugging Segmentation Fault", | |
| body: "Getting segmentation fault when running my linked list code.", | |
| tags: ["Debugging", "C++"], | |
| responses: 0, | |
| time: "4 hours ago", | |
| status: "unanswered" | |
| }, | |
| { | |
| title: "Midterm Preparation", | |
| body: "What topics should I focus on for the midterm exam?", | |
| tags: ["Exam", "Study"], | |
| responses: 0, | |
| time: "5 hours ago", | |
| status: "unanswered" | |
| }, | |
| { | |
| title: "Project Partner Needed", | |
| body: "Looking for a partner for the final project. Strong in Python.", | |
| tags: ["Project", "Partner"], | |
| responses: 0, | |
| time: "6 hours ago", | |
| status: "unanswered" | |
| }, | |
| { | |
| title: "Time Complexity of Nested Loops", | |
| body: "Can someone explain how to calculate the time complexity for nested loops with different bounds?", | |
| tags: ["Time Complexity", "Algorithms"], | |
| responses: 0, | |
| time: "7 hours ago", | |
| status: "unanswered" | |
| }, | |
| { | |
| title: "Memory Allocation in C++", | |
| body: "When should I use new vs malloc for dynamic memory allocation?", | |
| tags: ["C++", "Memory"], | |
| responses: 0, | |
| time: "8 hours ago", | |
| status: "unanswered" | |
| }, | |
| { | |
| title: "Git Branching Strategy", | |
| body: "What's the best branching strategy for a team project with multiple features?", | |
| tags: ["Git", "Version Control"], | |
| responses: 0, | |
| time: "9 hours ago", | |
| status: "unanswered" | |
| }, | |
| { | |
| title: "Object-Oriented Design Patterns", | |
| body: "Looking for examples of when to use factory pattern vs singleton pattern.", | |
| tags: ["Design Patterns", "OOP"], | |
| responses: 0, | |
| time: "10 hours ago", | |
| status: "unanswered" | |
| }, | |
| { | |
| title: "Database Normalization", | |
| body: "Can someone explain the different normal forms with practical examples?", | |
| tags: ["Database", "SQL"], | |
| responses: 0, | |
| time: "11 hours ago", | |
| status: "unanswered" | |
| }, | |
| { | |
| title: "WebSocket vs REST API", | |
| body: "When should I choose WebSocket over REST for real-time applications?", | |
| tags: ["Web Development", "APIs"], | |
| responses: 0, | |
| time: "12 hours ago", | |
| status: "unanswered" | |
| }, | |
| { | |
| title: "Machine Learning Pipeline", | |
| body: "What are the essential steps in building a machine learning pipeline from scratch?", | |
| tags: ["Machine Learning", "AI"], | |
| responses: 0, | |
| time: "13 hours ago", | |
| status: "unanswered" | |
| }, | |
| { | |
| title: "Docker Container Networking", | |
| body: "How do containers communicate with each other in a Docker network?", | |
| tags: ["Docker", "DevOps"], | |
| responses: 0, | |
| time: "14 hours ago", | |
| status: "unanswered" | |
| }, | |
| { | |
| title: "React State Management", | |
| body: "Should I use Context API or Redux for state management in a medium-sized application?", | |
| tags: ["React", "Frontend"], | |
| responses: 0, | |
| time: "15 hours ago", | |
| status: "unanswered" | |
| }, | |
| { | |
| title: "CSS Grid vs Flexbox", | |
| body: "When is it better to use CSS Grid over Flexbox for layout design?", | |
| tags: ["CSS", "Web Design"], | |
| responses: 0, | |
| time: "16 hours ago", | |
| status: "unanswered" | |
| }, | |
| { | |
| title: "Unit Testing Best Practices", | |
| body: "What are some best practices for writing effective unit tests in JavaScript?", | |
| tags: ["Testing", "JavaScript"], | |
| responses: 0, | |
| time: "17 hours ago", | |
| status: "unanswered" | |
| }, | |
| { | |
| title: "API Rate Limiting", | |
| body: "How should I implement rate limiting for a public API to prevent abuse?", | |
| tags: ["API", "Security"], | |
| responses: 0, | |
| time: "18 hours ago", | |
| status: "unanswered" | |
| }, | |
| { | |
| title: "Microservices Architecture", | |
| body: "What are the main advantages and challenges of using microservices over monolithic architecture?", | |
| tags: ["Architecture", "Backend"], | |
| responses: 0, | |
| time: "19 hours ago", | |
| status: "unanswered" | |
| }, | |
| { | |
| title: "GraphQL vs REST", | |
| body: "In what scenarios would GraphQL be a better choice than traditional REST APIs?", | |
| tags: ["GraphQL", "API Design"], | |
| responses: 0, | |
| time: "20 hours ago", | |
| status: "unanswered" | |
| }, | |
| { | |
| title: "Mobile App Development", | |
| body: "Should I use React Native or Flutter for cross-platform mobile development?", | |
| tags: ["Mobile", "React Native", "Flutter"], | |
| responses: 0, | |
| time: "21 hours ago", | |
| status: "unanswered" | |
| }, | |
| { | |
| title: "Cloud Deployment Strategies", | |
| body: "What are the best practices for deploying applications to cloud platforms like AWS or Azure?", | |
| tags: ["Cloud", "Deployment"], | |
| responses: 0, | |
| time: "22 hours ago", | |
| status: "unanswered" | |
| }, | |
| { | |
| title: "Code Review Process", | |
| body: "What makes an effective code review process in a development team?", | |
| tags: ["Code Review", "Teamwork"], | |
| responses: 0, | |
| time: "23 hours ago", | |
| status: "unanswered" | |
| }, | |
| { | |
| title: "Performance Optimization", | |
| body: "What are the most common performance bottlenecks in web applications and how to address them?", | |
| tags: ["Performance", "Optimization"], | |
| responses: 0, | |
| time: "24 hours ago", | |
| status: "unanswered" | |
| } | |
| ]; | |
| }); | |
| // Navigation | |
| allQuestionsLink.addEventListener('click', function(e) { | |
| e.preventDefault(); | |
| setActiveNav(allQuestionsLink); | |
| showPanel1(); | |
| }); | |
| myPostsLink.addEventListener('click', function(e) { | |
| e.preventDefault(); | |
| setActiveNav(myPostsLink); | |
| showPanel3(); | |
| }); | |
| unansweredLink.addEventListener('click', function(e) { | |
| e.preventDefault(); | |
| setActiveNav(unansweredLink); | |
| showUnansweredPanel(); | |
| // Start unanswered filter interaction timer | |
| unansweredFilterStartTime = Date.now(); | |
| console.log('β±οΈ Unanswered filter interaction timer started'); | |
| }); | |
| // Add event listeners for new navigation items | |
| document.getElementById('recent-link').addEventListener('click', function(e) { | |
| e.preventDefault(); | |
| setActiveNav(this); | |
| showRecentPanel(); | |
| }); | |
| document.getElementById('following-link').addEventListener('click', function(e) { | |
| e.preventDefault(); | |
| setActiveNav(this); | |
| showFollowingPanel(); | |
| }); | |
| // Add event listener for browse tags link | |
| document.getElementById('browse-tags-link').addEventListener('click', function(e) { | |
| e.preventDefault(); | |
| window.location.href = 'tags.html'; | |
| }); | |
| // Helper functions | |
| function setActiveNav(activeElement) { | |
| document.querySelectorAll('.nav-item').forEach(item => { | |
| item.classList.remove('active'); | |
| }); | |
| activeElement.classList.add('active'); | |
| } | |
| // Data collection functions | |
| function initializeDataCollection() { | |
| // Store dashboard entry time | |
| dashboardEntryTime = Date.now(); | |
| // Set up form interaction tracking | |
| const formInputs = postForm.querySelectorAll('input, textarea'); | |
| formInputs.forEach(input => { | |
| input.addEventListener('focus', function() { | |
| if (!postCreationStartTime) { | |
| postCreationStartTime = Date.now(); | |
| } | |
| }); | |
| }); | |
| } | |
| function storeKPIData(kpiName, value) { | |
| const kpiData = JSON.parse(localStorage.getItem('piazza_kpi_data') || {}; | |
| if (!kpiData[kpiName]) { | |
| kpiData[kpiName] = []; | |
| } | |
| kpiData[kpiName].push({ | |
| value: value, | |
| timestamp: Date.now() | |
| }); | |
| localStorage.setItem('piazza_kpi_data', JSON.stringify(kpiData)); | |
| console.log('π KPI Data Stored:', { | |
| metric: kpiName, | |
| value: value, | |
| timestamp: Date.now() | |
| }); | |
| } | |
| function logFormError(errorType) { | |
| const errorData = JSON.parse(localStorage.getItem('piazza_form_errors') || {}; | |
| if (!errorData[errorType]) { | |
| errorData[errorType] = 0; | |
| } | |
| errorData[errorType]++; | |
| localStorage.setItem('piazza_form_errors', JSON.stringify(errorData)); | |
| console.log('β Form Error Logged:', { | |
| type: errorType, | |
| count: errorData[errorType] | |
| }); | |
| } | |
| function showPanel1() { | |
| panel1.classList.remove('hidden'); | |
| panel2.classList.add('hidden'); | |
| panel3.classList.add('hidden'); | |
| } | |
| function showUnansweredPanel() { | |
| panel1.classList.add('hidden'); | |
| panel2.classList.remove('hidden'); | |
| panel3.classList.add('hidden'); | |
| // Start unanswered filter result interaction timer | |
| unansweredFilterInteractionStartTime = Date.now(); | |
| console.log('β±οΈ Unanswered filter result interaction timer started'); | |
| // Clear existing posts and add unanswered content | |
| postsList.innerHTML = ''; | |
| // Create feed container | |
| const feedContainer = document.createElement('div'); | |
| feedContainer.className = 'space-y-4'; | |
| feedContainer.id = 'questions-feed'; | |
| // Add sample posts as unanswered questions | |
| samplePosts.forEach(post => { | |
| const postElement = document.createElement('custom-post-card'); | |
| postElement.setAttribute('post', JSON.stringify({ | |
| title: post.title, | |
| content: post.body, | |
| tags: post.tags, | |
| responses: post.responses, | |
| time: `${Math.floor(Math.random() * 6) + 1} hours ago`, | |
| status: post.responses > 0 ? "answered" : "unanswered", | |
| confidence: Math.floor(Math.random() * 100), | |
| upvotes: Math.floor(Math.random() * 10), | |
| author: "Student " + Math.floor(Math.random() * 100) | |
| })); | |
| feedContainer.appendChild(postElement); | |
| }); | |
| // Add all placeholder posts | |
| window.placeholderPosts.forEach(post => { | |
| const postElement = document.createElement('custom-post-card'); | |
| postElement.setAttribute('post', JSON.stringify({ | |
| title: post.title, | |
| content: post.body, | |
| tags: post.tags, | |
| responses: post.responses, | |
| time: post.time, | |
| status: post.status, | |
| confidence: Math.floor(Math.random() * 100), | |
| upvotes: Math.floor(Math.random() * 10), | |
| author: "Student " + Math.floor(Math.random() * 100) | |
| })); | |
| feedContainer.appendChild(postElement); | |
| }); | |
| // Update unanswered count | |
| unansweredCount.textContent = window.placeholderPosts.length; | |
| postsList.appendChild(feedContainer); | |
| feather.replace(); | |
| // Add click tracking for unanswered posts | |
| setTimeout(() => { | |
| const postCards = document.querySelectorAll('custom-post-card'); | |
| postCards.forEach((card, index) => { | |
| card.addEventListener('click', function() { | |
| // Calculate unanswered filter interaction time | |
| const unansweredFilterInteractionTime = (Date.now() - unansweredFilterInteractionStartTime) / 1000; | |
| // Store KPI data | |
| storeKPIData('unanswered_filter_interaction_time', unansweredFilterInteractionTime); | |
| console.log('β Unanswered filter result clicked:', { | |
| timeToClick: unansweredFilterInteractionTime + 's', | |
| postIndex: index, | |
| postTitle: card.shadowRoot.querySelector('h3').textContent | |
| }); | |
| }); | |
| }, 100); | |
| // Highlight unanswered filter in sidebar | |
| const sidebar = document.querySelector('custom-sidebar'); | |
| if (sidebar) { | |
| const shadow = sidebar.shadowRoot; | |
| const filterItems = shadow.querySelectorAll('.filter-item'); | |
| filterItems.forEach(item => { | |
| item.classList.remove('active'); | |
| if (item.textContent.includes('Unanswered')) { | |
| item.classList.add('active'); | |
| } | |
| }); | |
| } | |
| } | |
| function showRecentPanel() { | |
| panel1.classList.add('hidden'); | |
| panel2.classList.remove('hidden'); | |
| panel3.classList.add('hidden'); | |
| // Clear existing posts and add recent content | |
| postsList.innerHTML = ''; | |
| const feedContainer = document.createElement('div'); | |
| feedContainer.className = 'space-y-4'; | |
| feedContainer.id = 'questions-feed'; | |
| // Sort posts by time (most recent first) | |
| const recentPosts = [...window.placeholderPosts, ...samplePosts] | |
| .sort((a, b) => { | |
| const timeA = parseInt(a.time); | |
| const timeB = parseInt(b.time); | |
| return timeA - timeB; | |
| }) | |
| .slice(0, 10); // Show only 10 most recent | |
| recentPosts.forEach(post => { | |
| const postElement = document.createElement('custom-post-card'); | |
| postElement.setAttribute('post', JSON.stringify({ | |
| title: post.title, | |
| content: post.body, | |
| tags: post.tags, | |
| responses: post.responses, | |
| time: post.time, | |
| status: post.status, | |
| confidence: Math.floor(Math.random() * 100), | |
| upvotes: Math.floor(Math.random() * 10), | |
| author: "Student " + Math.floor(Math.random() * 100) | |
| })); | |
| feedContainer.appendChild(postElement); | |
| }); | |
| postsList.appendChild(feedContainer); | |
| feather.replace(); | |
| // Highlight recent filter in sidebar | |
| const sidebar = document.querySelector('custom-sidebar'); | |
| if (sidebar) { | |
| const shadow = sidebar.shadowRoot; | |
| const filterItems = shadow.querySelectorAll('.filter-item'); | |
| filterItems.forEach(item => { | |
| item.classList.remove('active'); | |
| if (item.textContent.includes('Recent')) { | |
| item.classList.add('active'); | |
| } | |
| }); | |
| } | |
| } | |
| function showFollowingPanel() { | |
| panel1.classList.add('hidden'); | |
| panel2.classList.remove('hidden'); | |
| panel3.classList.add('hidden'); | |
| // Clear existing posts and add followed content | |
| postsList.innerHTML = ''; | |
| const feedContainer = document.createElement('div'); | |
| feedContainer.className = 'space-y-4'; | |
| feedContainer.id = 'questions-feed'; | |
| // Show posts from followed tags/topics | |
| const followedTags = ["Homework", "Algorithms", "Project"]; | |
| const followedPosts = window.placeholderPosts.filter(post => | |
| post.tags.some(tag => followedTags.includes(tag)) | |
| .slice(0, 8); // Show limited number of followed posts | |
| followedPosts.forEach(post => { | |
| const postElement = document.createElement('custom-post-card'); | |
| postElement.setAttribute('post', JSON.stringify({ | |
| title: post.title, | |
| content: post.body, | |
| tags: post.tags, | |
| responses: post.responses, | |
| time: post.time, | |
| status: post.status, | |
| confidence: Math.floor(Math.random() * 100), | |
| upvotes: Math.floor(Math.random() * 10), | |
| author: "Student " + Math.floor(Math.random() * 100) | |
| })); | |
| feedContainer.appendChild(postElement); | |
| }); | |
| postsList.appendChild(feedContainer); | |
| feather.replace(); | |
| // Highlight following filter in sidebar | |
| const sidebar = document.querySelector('custom-sidebar'); | |
| if (sidebar) { | |
| const shadow = sidebar.shadowRoot; | |
| const filterItems = shadow.querySelectorAll('.filter-item'); | |
| filterItems.forEach(item => { | |
| item.classList.remove('active'); | |
| if (item.textContent.includes('Followed')) { | |
| item.classList.add('active'); | |
| } | |
| }); | |
| } | |
| } | |
| function showPanel2(newPost) { | |
| // Add fade out animation to form | |
| postForm.classList.add('fade-out'); | |
| setTimeout(() => { | |
| panel1.classList.add('hidden'); | |
| panel2.classList.remove('hidden'); | |
| // Clear existing posts and add new content | |
| postsList.innerHTML = ''; | |
| // Create feed container | |
| const feedContainer = document.createElement('div'); | |
| feedContainer.className = 'space-y-4'; | |
| feedContainer.id = 'questions-feed'; | |
| // Add new post as first item | |
| const newPostElement = document.createElement('div'); | |
| newPostElement.className = 'bg-white rounded-lg shadow-sm p-6 transition-all hover:shadow-md'; | |
| newPostElement.innerHTML = ` | |
| <div class="flex justify-between items-start mb-2"> | |
| <h3 class="font-bold text-lg">${newPost.title}</h3> | |
| <span class="bg-yellow-100 text-yellow-800 text-xs px-2 py-1 rounded-full flex items-center"> | |
| <i data-feather="help-circle" class="w-3 h-3 mr-1"></i> | |
| Needs help | |
| </span> | |
| </div> | |
| <p class="text-gray-600 mb-3">${newPost.body}</p> | |
| <div class="flex flex-wrap gap-2 mb-3"> | |
| ${newPost.tags.map(tag => `<span class="bg-indigo-100 text-indigo-800 text-xs px-2 py-1 rounded-full">${tag}</span>`).join('')} | |
| </div> | |
| <div class="flex justify-between text-sm text-gray-500"> | |
| <span>0 responses</span> | |
| <span>Just now</span> | |
| </div> | |
| `; | |
| feedContainer.appendChild(newPostElement); | |
| // Add sample posts | |
| samplePosts.forEach(post => { | |
| const postElement = document.createElement('div'); | |
| postElement.className = 'bg-white rounded-lg shadow-sm p-6 transition-all hover:shadow-md'; | |
| postElement.innerHTML = ` | |
| <h3 class="font-bold text-lg mb-2">${post.title}</h3> | |
| <p class="text-gray-600 mb-3">${post.body}</p> | |
| <div class="flex flex-wrap gap-2 mb-3"> | |
| ${post.tags.map(tag => `<span class="bg-indigo-100 text-indigo-800 text-xs px-2 py-1 rounded-full">${tag}</span>`).join('')} | |
| </div> | |
| <div class="flex justify-between text-sm text-gray-500"> | |
| <span>${post.responses} ${post.responses === 1 ? 'response' : 'responses'}</span> | |
| <span>2 hours ago</span> | |
| </div> | |
| `; | |
| feedContainer.appendChild(postElement); | |
| }); | |
| postsList.appendChild(feedContainer); | |
| feather.replace(); | |
| // Update unanswered count | |
| const currentCount = parseInt(unansweredCount.textContent); | |
| unansweredCount.textContent = currentCount + 1; | |
| // Reset form animation | |
| postForm.classList.remove('fade-out'); | |
| }, 300); | |
| } | |
| function showPanel3() { | |
| panel1.classList.add('hidden'); | |
| panel2.classList.add('hidden'); | |
| panel3.classList.remove('hidden'); | |
| // Populate user posts with enhanced styling | |
| myPostsList.innerHTML = ''; | |
| // Add user's actual posts first | |
| userPosts.forEach((post, index) => { | |
| const postItem = document.createElement('li'); | |
| postItem.className = `bg-white rounded-lg shadow-sm p-4 mb-3 cursor-pointer transition-all hover:shadow-md ${index === 0 ? 'border-l-4 border-indigo-500 bg-indigo-50' : ''}`; | |
| postItem.innerHTML = ` | |
| <h3 class="text-lg font-bold mb-2">${post.title}</h3> | |
| ${post.hasNewResponse ? '<span class="new-response-badge inline-block mb-2">New Response</span>' : ''} | |
| <div class="flex flex-wrap gap-2 mb-2"> | |
| ${post.tags.map(tag => `<span class="tag">${tag}</span>`).join('')} | |
| </div> | |
| <div class="text-sm text-gray-500"> | |
| ${post.responses} ${post.responses === 1 ? 'response' : 'responses'} | |
| </div> | |
| `; | |
| postItem.addEventListener('click', () => { | |
| document.querySelectorAll('.post-card').forEach(card => { | |
| card.classList.remove('selected'); | |
| }); | |
| postItem.classList.add('selected'); | |
| showPostDetail(post); | |
| }); | |
| myPostsList.appendChild(postItem); | |
| }); | |
| // Add placeholder posts for scrolling | |
| const placeholderPosts = [ | |
| { | |
| title: "Binary Search Tree Implementation", | |
| body: "Need help implementing insert function for BST in Python.", | |
| tags: ["BST", "Python", "Data Structures"], | |
| responses: 2, | |
| time: "1 hour ago", | |
| status: "answered", | |
| confidence: 45, | |
| upvotes: 3, | |
| author: "Student 42" | |
| }, | |
| { | |
| title: "HW3 Problem 5 Solution", | |
| body: "Looking for optimal solution approach for problem 5 in homework 3.", | |
| tags: ["Homework", "Algorithms"], | |
| responses: 1, | |
| time: "2 hours ago", | |
| status: "answered", | |
| confidence: 78, | |
| upvotes: 5, | |
| author: "Student 24" | |
| }, | |
| { | |
| title: "Lecture 8 Slides Question", | |
| body: "Confused about time complexity analysis on slide 25.", | |
| tags: ["Lecture", "Time Complexity"], | |
| responses: 0, | |
| time: "3 hours ago", | |
| status: "unanswered", | |
| confidence: 32, | |
| upvotes: 1, | |
| author: "Student 17" | |
| }, | |
| { | |
| title: "Recursion vs Iteration", | |
| body: "When should I prefer recursion over iteration for tree traversal?", | |
| tags: ["Recursion", "Trees"], | |
| responses: 3, | |
| time: "4 hours ago", | |
| status: "answered", | |
| confidence: 67, | |
| upvotes: 4, | |
| author: "Student 89" | |
| }, | |
| { | |
| title: "Debugging Segmentation Fault", | |
| body: "Getting segmentation fault when running my linked list code.", | |
| tags: ["Debugging", "C++"], | |
| responses: 1, | |
| time: "5 hours ago", | |
| status: "answered", | |
| confidence: 55, | |
| upvotes: 2, | |
| author: "Student 33" | |
| }, | |
| { | |
| title: "Midterm Preparation", | |
| body: "What topics should I focus on for the midterm exam?", | |
| tags: ["Exam", "Study"], | |
| responses: 0, | |
| time: "6 hours ago", | |
| status: "unanswered", | |
| confidence: 28, | |
| upvotes: 1, | |
| author: "Student 56" | |
| }, | |
| { | |
| title: "Project Partner Needed", | |
| body: "Looking for a partner for the final project. Strong in Python.", | |
| tags: ["Project", "Partner"], | |
| responses: 2, | |
| time: "7 hours ago", | |
| status: "answered", | |
| confidence: 72, | |
| upvotes: 3, | |
| author: "Student 78" | |
| }, | |
| { | |
| title: "Time Complexity of Nested Loops", | |
| body: "Can someone explain how to calculate the time complexity for nested loops with different bounds?", | |
| tags: ["Time Complexity", "Algorithms"], | |
| responses: 1, | |
| time: "8 hours ago", | |
| status: "answered", | |
| confidence: 61, | |
| upvotes: 2, | |
| author: "Student 45" | |
| }, | |
| { | |
| title: "Memory Allocation in C++", | |
| body: "When should I use new vs malloc for dynamic memory allocation?", | |
| tags: ["C++", "Memory"], | |
| responses: 0, | |
| time: "9 hours ago", | |
| status: "unanswered", | |
| confidence: 34, | |
| upvotes: 1, | |
| author: "Student 91" | |
| }, | |
| { | |
| title: "Git Branching Strategy", | |
| body: "What's the best branching strategy for a team project with multiple features?", | |
| tags: ["Git", "Version Control"], | |
| responses: 4, | |
| time: "10 hours ago", | |
| status: "answered", | |
| confidence: 83, | |
| upvotes: 6, | |
| author: "Student 12" | |
| } | |
| ]; | |
| placeholderPosts.forEach((post, index) => { | |
| const postItem = document.createElement('li'); | |
| postItem.className = `bg-white rounded-lg shadow-sm p-4 mb-3 cursor-pointer transition-all hover:shadow-md`; | |
| postItem.innerHTML = ` | |
| <h3 class="text-lg font-bold mb-2">${post.title}</h3> | |
| <div class="flex flex-wrap gap-2 mb-2"> | |
| ${post.tags.map(tag => `<span class="tag">${tag}</span>`).join('')} | |
| </div> | |
| <div class="text-sm text-gray-500"> | |
| ${post.responses} ${post.responses === 1 ? 'response' : 'responses'} | |
| </div> | |
| `; | |
| postItem.addEventListener('click', () => { | |
| document.querySelectorAll('.post-card').forEach(card => { | |
| card.classList.remove('selected'); | |
| }); | |
| postItem.classList.add('selected'); | |
| showPostDetail(post); | |
| }); | |
| myPostsList.appendChild(postItem); | |
| }); | |
| // Show detail of first post | |
| if (userPosts.length > 0) { | |
| showPostDetail(userPosts[0]); | |
| } else if (placeholderPosts.length > 0) { | |
| showPostDetail(placeholderPosts[0]); | |
| } | |
| } | |
| function showPostDetail(post) { | |
| postDetail.innerHTML = ` | |
| <h2 class="text-2xl font-bold mb-4">${post.title}</h2> | |
| <div class="prose max-w-none mb-6"> | |
| <p>${post.body}</p> | |
| </div> | |
| <div class="flex flex-wrap gap-2 mb-8"> | |
| ${post.tags.map(tag => `<span class="tag">${tag}</span>`).join('')} | |
| </div> | |
| <h3 class="text-xl font-bold mb-4">Responses</h3> | |
| <div class="space-y-6"> | |
| <div class="bg-white rounded-lg shadow-sm p-6"> | |
| <div class="flex items-center mb-3"> | |
| <div class="bg-green-100 p-2 rounded-full mr-3"> | |
| <i data-feather="award" class="text-green-600 w-5 h-5"></i> | |
| <h4 class="font-bold text-lg">Instructor Response</h4> | |
| </div> | |
| <p class="text-gray-600">Great question! Here's the approach I recommend for solving this problem...</p> | |
| <div class="text-sm text-gray-500 mt-2">Posted 2 hours ago</p> | |
| </div> | |
| <div class="bg-white rounded-lg shadow-sm p-6"> | |
| <div class="flex items-center mb-3"> | |
| <div class="bg-purple-100 p-2 rounded-full mr-3"> | |
| <i data-feather="users" class="text-purple-600 w-5 h-5"></i> | |
| <h4 class="font-bold text-lg">Peer Response</h4> | |
| </div> | |
| <p class="text-gray-600">I had the same issue. What worked for me was to first...</p> | |
| <div class="text-sm text-gray-500 mt-2">Posted 1 hour ago</p> | |
| </div> | |
| </div> | |
| `; | |
| feather.replace(); | |
| } | |