```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 = `

${newPost.title}

Needs help

${newPost.body}

${newPost.tags.map(tag => `${tag}`).join('')}
0 responses Just now
`; 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 = `

${post.title}

${post.body}

${post.tags.map(tag => `${tag}`).join('')}
${post.responses} ${post.responses === 1 ? 'response' : 'responses'} 2 hours ago
`; 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 = `

${post.title}

${post.hasNewResponse ? 'New Response' : ''}
${post.tags.map(tag => `${tag}`).join('')}
${post.responses} ${post.responses === 1 ? 'response' : 'responses'}
`; 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 = `

${post.title}

${post.tags.map(tag => `${tag}`).join('')}
${post.responses} ${post.responses === 1 ? 'response' : 'responses'}
`; 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 = `

${post.title}

${post.body}

${post.tags.map(tag => `${tag}`).join('')}

Responses

Instructor Response

Great question! Here's the approach I recommend for solving this problem...

Posted 2 hours ago

Peer Response

I had the same issue. What worked for me was to first...

Posted 1 hour ago

`; feather.replace(); }