# Live Collaboration & Multi-Community System - Part 2 ## Task Documentation: GIT-9 through GIT-11 This is a continuation of the Live Collaboration & Multi-Community System task documentation. --- ## GIT-9: Community Tab UI/UX **Priority**: High **Estimated Hours**: 80-100 **Dependencies**: GIT-5, GIT-7, GIT-8 ### Purpose Create the Community tab UI that serves as the central hub for all community features: browsing communities, discovering sessions, exploring components, viewing tutorials, and accessing discussions. ### Technical Requirements #### 1. Community Tab Layout **File: `packages/noodl-editor/src/editor/src/views/panels/CommunityPanel/CommunityPanel.tsx`** ```typescript import React, { useState, useEffect } from 'react'; import { CommunityManager } from '../../../services/CommunityManager'; import { CollaborationManager } from '../../../services/CollaborationManager'; import { NotificationManager } from '../../../services/NotificationManager'; interface CommunityPanelProps { communityManager: CommunityManager; collaborationManager: CollaborationManager; notificationManager: NotificationManager; } export function CommunityPanel({ communityManager, collaborationManager, notificationManager }: CommunityPanelProps) { const [activeTab, setActiveTab] = useState<'home' | 'sessions' | 'components' | 'learn' | 'discuss' | 'jobs'>('home'); const [activeCommunity, setActiveCommunity] = useState(communityManager.getActiveCommunity()); const [communities, setCommunities] = useState(communityManager.getCommunities()); useEffect(() => { const handleCommunityChanged = (community: any) => { setActiveCommunity(community); }; const handleCommunitiesUpdated = () => { setCommunities(communityManager.getCommunities()); }; communityManager.on('active-community-changed', handleCommunityChanged); communityManager.on('community-added', handleCommunitiesUpdated); communityManager.on('community-removed', handleCommunitiesUpdated); return () => { communityManager.off('active-community-changed', handleCommunityChanged); communityManager.off('community-added', handleCommunitiesUpdated); communityManager.off('community-removed', handleCommunitiesUpdated); }; }, [communityManager]); return (
communityManager.setActiveCommunity(id)} onAddCommunity={() => showAddCommunityDialog()} />
setActiveTab('home')} /> setActiveTab('sessions')} /> setActiveTab('components')} /> setActiveTab('learn')} /> setActiveTab('discuss')} /> setActiveTab('jobs')} />
{activeTab === 'home' && ( )} {activeTab === 'sessions' && ( )} {activeTab === 'components' && ( )} {activeTab === 'learn' && ( )} {activeTab === 'discuss' && ( )} {activeTab === 'jobs' && ( )}
); } ``` #### 2. Home View (Featured Content) **File: `CommunityPanel/views/HomeView.tsx`** ```typescript import React, { useEffect, useState } from 'react'; export function HomeView({ community, collaborationManager, notificationManager }) { const [featured, setFeatured] = useState({ sessions: [], components: [], tutorials: [], discussions: [] }); useEffect(() => { loadFeaturedContent(); }, [community]); async function loadFeaturedContent() { // Fetch from community repository const response = await fetch( `https://raw.githubusercontent.com/${getCommunityRepo()}/main/featured.json` ); const data = await response.json(); setFeatured(data); } return (
joinSession(sessionId)} />
startNewSession()} onShareComponent={() => shareComponent()} onAskQuestion={() => startDiscussion()} />
); } function WelcomeBanner({ community }) { return (
{community.name}

{community.name}

{community.description}

); } function ActiveSessionsList({ sessions, onJoin }) { if (sessions.length === 0) { return ; } return (
{sessions.map(session => ( onJoin(session.id)} /> ))}
); } function SessionCard({ session, onJoin }) { return (
{session.host.name}

{session.title}

{session.description}

👥 {session.participants.length}/{session.maxParticipants} 🕐 {formatDuration(session.duration)} {session.audioEnabled && 🎤 Audio} {session.videoEnabled && 📹 Video}
); } function QuickActions({ onStartSession, onShareComponent, onAskQuestion }) { return (
); } ``` #### 3. Sessions View (Collaboration Discovery) **File: `CommunityPanel/views/SessionsView.tsx`** ```typescript import React, { useState, useEffect } from 'react'; export function SessionsView({ community, collaborationManager }) { const [view, setView] = useState<'browse' | 'create' | 'join'>('browse'); const [sessions, setSessions] = useState([]); const [filter, setFilter] = useState({ status: 'all', // 'live', 'scheduled', 'all' hasAudio: false, hasSlots: false }); useEffect(() => { loadSessions(); }, [community, filter]); async function loadSessions() { // Fetch from community's collaboration/public-sessions.json const response = await fetch( `https://raw.githubusercontent.com/${getCommunityRepo()}/main/collaboration/public-sessions.json` ); const data = await response.json(); setSessions(filterSessions(data, filter)); } return (

Collaboration Sessions

{view === 'browse' && ( <>
{sessions.length === 0 ? ( setView('create') }} /> ) : ( sessions.map(session => ( joinSession(session.roomId)} /> )) )}
)} {view === 'create' && ( setView('browse')} onCreate={(session) => { createSession(session); setView('browse'); }} /> )} {view === 'join' && ( setView('browse')} onJoin={(roomId) => { joinSession(roomId); setView('browse'); }} /> )}
); } function SessionFilters({ filter, onChange }) { return (
onChange({ ...filter, status: 'all' })} /> onChange({ ...filter, status: 'live' })} /> onChange({ ...filter, status: 'scheduled' })} /> onChange({ ...filter, hasAudio: checked })} /> onChange({ ...filter, hasSlots: checked })} />
); } function CreateSessionDialog({ onCancel, onCreate }) { const [form, setForm] = useState({ title: '', description: '', isPublic: true, maxParticipants: 10, audioEnabled: true, videoEnabled: false, projectId: window.ProjectModel?.id || '' }); return (
setForm({ ...form, title })} placeholder="e.g., Building a User Dashboard" required />