<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>Project Management Board</title>

    <!-- Load Tailwind CSS -->

    <script src="https://cdn.tailwindcss.com"></script>

    <!-- Load Lucide Icons - FIX: Changed to standard script tag to ensure global 'lucide' is defined -->

    <script src="https://cdn.jsdelivr.net/npm/@lucide/web@latest/lib/umd/lucide.js"></script>

    <style>

        /* Custom styles for the table grid structure */

        .board-grid-header, .board-grid-row {

            display: grid;

            grid-template-columns: 32px 300px 100px 140px 160px 100px 100px 100px 100px 32px; /* Defines the columns */

            min-width: 1064px; /* Ensure content doesn't wrap */

        }

        .board-grid-row {

            transition: background-color 0.15s;

        }

        .board-grid-row:hover {

            background-color: #f5f5f5;

        }

        .status-pill {

            display: flex;

            align-items: center;

            justify-content: center;

            padding: 2px 8px;

            border-radius: 9999px;

            font-weight: 500;

            font-size: 0.8rem;

            border: 1px solid transparent;

            cursor: pointer;

            user-select: none;

            transition: all 0.2s;

        }

        /* Style for the date input which is hidden by default */

        .date-input-overlay {

            position: absolute;

            z-index: 20;

            background: white;

            padding: 8px;

            border: 1px solid #ccc;

            border-radius: 6px;

            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);

        }

        .timeline-bar {

            height: 10px;

            border-radius: 9999px;

        }

        /* Custom scrollbar for wide tables */

        .table-container::-webkit-scrollbar {

            height: 8px;

        }

        .table-container::-webkit-scrollbar-thumb {

            background-color: #d1d5db; /* gray-300 */

            border-radius: 4px;

        }

        .table-container::-webkit-scrollbar-track {

            background-color: #f3f4f6; /* gray-100 */

        }

    </style>

</head>

<body class="bg-gray-50 min-h-screen font-sans">


    <!-- Header / Top Bar -->

    <header class="flex items-center justify-between p-4 bg-white border-b border-gray-200 shadow-sm">

        <h1 class="text-2xl font-bold text-gray-800 flex items-center">

            <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="w-6 h-6 mr-3 text-blue-600"><rect width="18" height="18" x="3" y="3" rx="2"></rect><path d="M7 3v18"></path><path d="M3 7h18"></path><path d="M3 17h18"></path><path d="M17 3v18"></path></svg>

            Zella Games Project Board

        </h1>

        <div class="flex items-center space-x-4 text-sm text-gray-600">

            <button class="flex items-center hover:text-blue-600">

                <i data-lucide="bell" class="w-4 h-4 mr-1"></i> Notifications

            </button>

            <span id="user-display" class="flex items-center bg-blue-500 text-white rounded-full p-1 text-xs font-medium cursor-pointer">

                <i data-lucide="user" class="w-4 h-4"></i>

            </span>

        </div>

    </header>


    <!-- Project Tabs/Menu -->

    <div class="flex p-4 bg-white border-b border-gray-200 sticky top-0 z-10">

        <span class="text-sm font-semibold text-gray-800 px-3 py-1 border-b-2 border-blue-600">Main Table</span>

        <span class="text-sm text-gray-500 px-3 py-1 cursor-pointer hover:text-blue-600">Gantt</span>

        <span class="text-sm text-gray-500 px-3 py-1 cursor-pointer hover:text-blue-600">Tasks Assigned To Me</span>

    </div>


    <!-- Controls Bar -->

    <div class="p-4 bg-white shadow-md flex items-center space-x-4 border-b">

        <button id="add-task-btn" class="bg-blue-600 text-white px-4 py-2 rounded-lg text-sm font-semibold hover:bg-blue-700 transition duration-150">

            <i data-lucide="plus" class="w-4 h-4 inline-block mr-1"></i> New Task

        </button>

        <input type="text" placeholder="Search tasks..." class="border border-gray-300 p-2 rounded-lg text-sm w-64 focus:ring-blue-500 focus:border-blue-500">

        <span class="text-sm text-gray-500">Filters:</span>

        <span class="text-sm text-gray-800 font-medium cursor-pointer flex items-center hover:bg-gray-100 p-1 rounded-md">

            <i data-lucide="person-standing" class="w-4 h-4 mr-1 text-gray-500"></i> Owner

        </span>

        <span class="text-sm text-gray-800 font-medium cursor-pointer flex items-center hover:bg-gray-100 p-1 rounded-md">

            <i data-lucide="calendar" class="w-4 h-4 mr-1 text-gray-500"></i> Date

        </span>

    </div>


    <!-- Main Board Container -->

    <div class="p-4 table-container overflow-x-auto">

        <div id="board-header" class="board-grid-header text-xs font-semibold text-gray-500 border-b border-gray-300 py-2 sticky top-24 bg-gray-50 z-10">

            <div class="px-2"></div>

            <div class="px-2 text-left">TASK</div>

            <div class="px-2 text-center">OWNER</div>

            <div class="px-2 text-center">STATUS</div>

            <div class="px-2 text-center">TIMELINE</div>

            <div class="px-2 text-center">DURATION</div>

            <div class="px-2 text-center">PLANNED EFFORT (h)</div>

            <div class="px-2 text-center">EFFORT SPENT (h)</div>

            <div class="px-2 text-center">COMPLETION DATE</div>

            <div class="px-2"></div>

        </div>


        <div id="tasks-container" class="space-y-4">

            <!-- Tasks will be rendered here by JavaScript -->

        </div>


        <!-- Pop-up for Status change (hidden by default) -->

        <div id="status-popup" class="hidden absolute bg-white shadow-xl rounded-lg p-2 z-30 border border-gray-200">

            <div class="text-xs font-semibold text-gray-500 mb-1 px-2">Change Status</div>

            <div id="status-options" class="space-y-1">

                <!-- Status options will be populated here -->

            </div>

        </div>


        <!-- Pop-up for Timeline change (hidden by default) -->

        <div id="timeline-popup" class="hidden absolute bg-white shadow-xl rounded-lg p-3 z-30 border border-gray-200">

            <div class="text-xs font-semibold text-gray-500 mb-2">Set Timeline</div>

            <div class="space-y-2 text-sm">

                <label class="block">Start Date:</label>

                <input type="date" id="popup-start-date" class="border p-1 rounded text-gray-700 w-full">

                <label class="block">End Date:</label>

                <input type="date" id="popup-end-date" class="border p-1 rounded text-gray-700 w-full">

                <button id="save-timeline-btn" class="mt-3 bg-green-500 text-white px-3 py-1 rounded w-full hover:bg-green-600 transition">Save</button>

            </div>

        </div>

    </div>


    <!-- Firebase Imports and Script -->

    <script type="module">

        import { initializeApp } from "https://www.gstatic.com/firebasejs/11.6.1/firebase-app.js";

        import { getAuth, signInAnonymously, signInWithCustomToken, onAuthStateChanged } from "https://www.gstatic.com/firebasejs/11.6.1/firebase-auth.js";

        import { getFirestore, doc, getDoc, setDoc, onSnapshot, collection, query, orderBy, addDoc, updateDoc, where, getDocs, deleteDoc, runTransaction } from "https://www.gstatic.com/firebasejs/11.6.1/firebase-firestore.js";

        import { setLogLevel } from "https://www.gstatic.com/firebasejs/11.6.1/firebase-firestore.js";


        // IMPORTANT: Global variables for Firebase context provided by the canvas environment

        const appId = typeof __app_id !== 'undefined' ? __app_id : 'default-app-id';

        const firebaseConfig = typeof __firebase_config !== 'undefined' ? JSON.parse(__firebase_config) : { /* Mock Config */ };

        const initialAuthToken = typeof __initial_auth_token !== 'undefined' ? __initial_auth_token : null;


        setLogLevel('Debug');


        // --- App State & Constants ---

        let app;

        let db;

        let auth;

        let userId = null;

        let userName = 'Guest User';

        let tasks = [];

        let isAuthReady = false;


        const STATUS_OPTIONS = ['Working On It', 'Done', 'Stuck', 'Future Step'];

        const STATUS_COLORS = {

            'Working On It': 'bg-yellow-100 text-yellow-800 border-yellow-300 hover:bg-yellow-200',

            'Done': 'bg-teal-100 text-teal-800 border-teal-300 hover:bg-teal-200',

            'Stuck': 'bg-red-100 text-red-800 border-red-300 hover:bg-red-200',

            'Future Step': 'bg-blue-100 text-blue-800 border-blue-300 hover:bg-blue-200',

        };

        const SECTIONS = ['Pre-Production', 'Production'];

        const FIRESTORE_PATH = `/artifacts/${appId}/public/data/tasks`;


        // Utility to format date for input fields

        const formatDate = (dateString) => {

            if (!dateString) return '';

            return new Date(dateString).toISOString().split('T')[0];

        };


        // Utility to calculate duration in days

        const calculateDuration = (start, end) => {

            if (!start || !end) return 0;

            const diffTime = Math.abs(new Date(end) - new Date(start));

            const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));

            return diffDays;

        };


        // --- Firebase Initialization and Auth ---


        const initializeFirebase = async () => {

            try {

                app = initializeApp(firebaseConfig);

                db = getFirestore(app);

                auth = getAuth(app);


                onAuthStateChanged(auth, async (user) => {

                    if (user) {

                        userId = user.uid;

                        // For simplicity, generate a short display name from UID

                        userName = `User-${user.uid.substring(0, 4)}`;

                        document.getElementById('user-display').innerHTML = `<i data-lucide="user" class="w-4 h-4"></i> ${userName}`;

                        // Since lucide is loaded globally, we can call createIcons here

                        if (typeof lucide !== 'undefined') {

                            lucide.createIcons(); 

                        }


                        if (!isAuthReady) {

                            console.log("Authentication successful. Starting real-time listener.");

                            isAuthReady = true;

                            setupRealtimeListener();

                        }

                    } else if (initialAuthToken) {

                        await signInWithCustomToken(auth, initialAuthToken);

                    } else {

                        // Fallback to anonymous sign-in if no token is available

                        await signInAnonymously(auth);

                    }

                });


            } catch (e) {

                console.error("Error initializing Firebase:", e);

                document.getElementById('tasks-container').innerHTML = '<p class="text-red-600">Failed to connect to the database. Check console for details.</p>';

            }

        };


        // --- Data Handling ---


        const setupRealtimeListener = () => {

            if (!db || !isAuthReady) return;


            const q = query(collection(db, FIRESTORE_PATH));

            

            onSnapshot(q, (snapshot) => {

                tasks = snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() }));

                tasks.sort((a, b) => (SECTIONS.indexOf(a.section) - SECTIONS.indexOf(b.section)) || a.order - b.order);


                console.log(`Fetched ${tasks.length} tasks.`);

                renderBoard();

            }, (error) => {

                console.error("Error listening to tasks:", error);

            });

        };


        const updateTaskField = async (taskId, field, value) => {

            if (!db || !userId) return console.error("Database not ready or user not authenticated.");

            try {

                const taskRef = doc(db, FIRESTORE_PATH, taskId);

                await updateDoc(taskRef, { [field]: value });

                console.log(`Task ${taskId} updated: ${field} = ${value}`);

            } catch (e) {

                console.error("Error updating task:", e);

            }

        };


        const addTask = async (isSubtask = false, parentId = null, section = SECTIONS[0]) => {

            if (!db || !userId) return console.error("Database not ready or user not authenticated.");


            const maxOrder = tasks

                .filter(t => t.section === section && t.parentId === parentId)

                .reduce((max, t) => Math.max(max, t.order || 0), 0);


            const newTask = {

                title: isSubtask ? 'New Subtask' : 'New Task',

                section: section,

                isSubtask: isSubtask,

                parentId: parentId,

                ownerId: userId,

                ownerName: userName,

                status: 'Working On It',

                startDate: formatDate(new Date()),

                endDate: formatDate(new Date(Date.now() + 7 * 24 * 60 * 60 * 1000)), // 7 days later

                durationDays: 7,

                plannedEffortHours: 8,

                effortSpentHours: 0,

                comments: [],

                order: maxOrder + 1,

            };


            try {

                await addDoc(collection(db, FIRESTORE_PATH), newTask);

            } catch (e) {

                console.error("Error adding task:", e);

            }

        };


        const updateTaskTimeline = async (taskId, start, end) => {

            if (!db || !userId) return console.error("Database not ready or user not authenticated.");

            const durationDays = calculateDuration(start, end);


            try {

                const taskRef = doc(db, FIRESTORE_PATH, taskId);

                await updateDoc(taskRef, {

                    startDate: start,

                    endDate: end,

                    durationDays: durationDays

                });

                // Close popup after successful update (handled in global listeners)

            } catch (e) {

                console.error("Error updating task timeline:", e);

            }

        };


        // --- UI Rendering ---


        const getStatusPillHtml = (status, taskId) => {

            const colorClass = STATUS_COLORS[status] || 'bg-gray-100 text-gray-800 border-gray-300';

            return `<div data-task-id="${taskId}" class="status-pill ${colorClass} update-status">${status}</div>`;

        };


        const getTimelineBarHtml = (startDate, endDate) => {

            if (!startDate || !endDate) return '';

            const today = new Date();

            const start = new Date(startDate);

            const end = new Date(endDate);

            const totalDuration = end.getTime() - start.getTime();

            const elapsed = today.getTime() - start.getTime();


            let percentage = 0;

            if (elapsed > 0) {

                percentage = Math.min(100, Math.max(0, (elapsed / totalDuration) * 100));

            }


            // Simple color logic based on status

            const barColor = 'bg-blue-500';


            return `

                <div class="w-full h-2 bg-gray-200 rounded-full relative">

                    <div class="timeline-bar absolute top-0 left-0 ${barColor}" style="width: ${percentage}%;"></div>

                </div>

            `;

        };


        const renderTaskRow = (task) => {

            const isSubtask = task.isSubtask;

            const indentation = isSubtask ? 'ml-4' : 'ml-0';

            const rowClasses = isSubtask ? 'bg-white border-b border-gray-100 text-sm' : 'bg-white border-b border-gray-200 text-base font-medium';

            const taskTitleClasses = isSubtask ? 'text-gray-600' : 'text-gray-800';


            const durationText = task.durationDays > 0 ? `${task.durationDays} days` : '0 days';

            const timelineDates = task.startDate && task.endDate ? `${formatDate(task.startDate)} - ${formatDate(task.endDate)}` : '-';


            return `

                <div data-task-id="${task.id}" class="board-grid-row py-2 items-center ${rowClasses}">

                    <div class="px-2">

                        ${isSubtask ? '' : `<i data-lucide="plus-circle" class="w-4 h-4 text-gray-400 hover:text-blue-500 cursor-pointer add-subtask-btn" data-parent-id="${task.id}" data-section="${task.section}"></i>`}

                    </div>

                    <div class="px-2 flex items-center ${indentation} update-title" data-task-id="${task.id}" contenteditable="true">

                        <span class="${taskTitleClasses} whitespace-nowrap">${task.title}</span>

                    </div>

                    <div class="px-2 text-center text-xs text-gray-700 font-normal">

                        <div class="flex items-center justify-center space-x-1">

                            <i data-lucide="user" class="w-4 h-4 text-gray-500"></i>

                            <span>${task.ownerName}</span>

                        </div>

                    </div>

                    <div class="px-2 text-center">

                        ${getStatusPillHtml(task.status, task.id)}

                    </div>

                    <div class="px-2 text-center timeline-cell" data-task-id="${task.id}">

                        <div class="text-xs text-gray-600 font-normal timeline-display cursor-pointer" data-task-id="${task.id}" data-start="${task.startDate}" data-end="${task.endDate}">

                            ${timelineDates === '-' ? '-' : timelineDates}

                            ${getTimelineBarHtml(task.startDate, task.endDate)}

                        </div>

                    </div>

                    <div class="px-2 text-center text-xs text-gray-600 font-normal">${durationText}</div>

                    <div class="px-2 text-center text-xs text-gray-600 font-normal">${task.plannedEffortHours}</div>

                    <div class="px-2 text-center text-xs text-gray-600 font-normal">${task.effortSpentHours}</div>

                    <div class="px-2 text-center text-xs text-gray-600 font-normal">-</div>

                    <div class="px-2 text-center">

                        <i data-lucide="message-square" class="w-4 h-4 text-gray-400 hover:text-blue-500 cursor-pointer"></i>

                    </div>

                </div>

            `;

        };


        const renderBoard = () => {

            const container = document.getElementById('tasks-container');

            container.innerHTML = ''; // Clear existing content


            let html = '';


            SECTIONS.forEach(section => {

                const sectionTasks = tasks.filter(t => t.section === section && !t.parentId);


                if (sectionTasks.length === 0) return;


                // Section Header

                html += `

                    <div class="flex items-center space-x-2 text-lg font-semibold text-gray-800 mt-6 mb-2">

                        <i data-lucide="chevrons-down-up" class="w-5 h-5 text-gray-400"></i>

                        <span>${section}</span>

                    </div>

                `;


                sectionTasks.forEach(task => {

                    html += renderTaskRow(task);


                    // Render subtasks immediately after parent

                    const subtasks = tasks.filter(t => t.parentId === task.id);

                    subtasks.forEach(subtask => {

                        html += renderTaskRow(subtask);

                    });

                });


                // Add "Add task" row for the section

                html += `

                    <button class="flex items-center text-sm text-gray-500 hover:text-blue-600 mt-2 px-2 py-1" onclick="addTask(false, null, '${section}')">

                        <i data-lucide="plus" class="w-4 h-4 mr-1"></i> Add task

                    </button>

                `;

            });


            container.innerHTML = html;

            // Since lucide is loaded globally, we can call createIcons here

            if (typeof lucide !== 'undefined') {

                lucide.createIcons();

            }

        };


        // --- Event Listeners and Popups ---


        let activeTaskId = null;

        let activeStatusElement = null;

        let activeTimelineElement = null;


        const statusPopup = document.getElementById('status-popup');

        const timelinePopup = document.getElementById('timeline-popup');


        // Close popups when clicking outside

        document.addEventListener('click', (e) => {

            if (activeStatusElement && !statusPopup.contains(e.target) && e.target !== activeStatusElement) {

                statusPopup.classList.add('hidden');

                activeStatusElement = null;

                activeTaskId = null;

            }

            if (activeTimelineElement && !timelinePopup.contains(e.target) && e.target.closest('.timeline-cell') !== activeTimelineElement) {

                timelinePopup.classList.add('hidden');

                activeTimelineElement = null;

                activeTaskId = null;

            }

        });


        // Delegate click events for dynamic elements

        document.addEventListener('click', (e) => {

            // 1. Status Pill Click

            const statusPill = e.target.closest('.update-status');

            if (statusPill) {

                e.stopPropagation();

                activeTaskId = statusPill.getAttribute('data-task-id');

                activeStatusElement = statusPill;


                // Position the popup

                const rect = statusPill.getBoundingClientRect();

                statusPopup.style.top = `${rect.bottom + 5}px`;

                statusPopup.style.left = `${rect.left}px`;


                // Populate and show status options

                const optionsContainer = document.getElementById('status-options');

                optionsContainer.innerHTML = STATUS_OPTIONS.map(status => {

                    const colorClass = STATUS_COLORS[status].replace('hover:bg-', 'hover:bg-');

                    return `<div class="status-pill ${colorClass} w-full" data-status="${status}">${status}</div>`;

                }).join('');


                statusPopup.classList.remove('hidden');

            }


            // 2. Add Task Button

            if (e.target.closest('#add-task-btn')) {

                addTask();

            }


            // 3. Add Subtask Button

            const addSubtaskBtn = e.target.closest('.add-subtask-btn');

            if (addSubtaskBtn) {

                const parentId = addSubtaskBtn.getAttribute('data-parent-id');

                const section = addSubtaskBtn.getAttribute('data-section');

                addTask(true, parentId, section);

            }


            // 4. Timeline Click

            const timelineCell = e.target.closest('.timeline-cell');

            if (timelineCell) {

                e.stopPropagation();

                activeTaskId = timelineCell.getAttribute('data-task-id');

                activeTimelineElement = timelineCell;


                const task = tasks.find(t => t.id === activeTaskId);


                // Position the popup

                const rect = timelineCell.getBoundingClientRect();

                timelinePopup.style.top = `${rect.bottom + 5}px`;

                timelinePopup.style.left = `${rect.left}px`;


                // Populate dates

                document.getElementById('popup-start-date').value = formatDate(task.startDate);

                document.getElementById('popup-end-date').value = formatDate(task.endDate);


                timelinePopup.classList.remove('hidden');

            }

        });


        // Delegate click for status options

        document.getElementById('status-options').addEventListener('click', (e) => {

            const selectedStatus = e.target.closest('.status-pill');

            if (selectedStatus && activeTaskId) {

                const status = selectedStatus.getAttribute('data-status');

                updateTaskField(activeTaskId, 'status', status);

                statusPopup.classList.add('hidden');

            }

        });


        // Save Timeline button handler

        document.getElementById('save-timeline-btn').addEventListener('click', () => {

            const start = document.getElementById('popup-start-date').value;

            const end = document.getElementById('popup-end-date').value;

            if (activeTaskId && start && end) {

                updateTaskTimeline(activeTaskId, start, end);

                timelinePopup.classList.add('hidden');

            } else {

                console.warn("Missing dates or active task ID.");

            }

        });


        // Delegate blur event for editable title

        document.addEventListener('blur', async (e) => {

            const titleElement = e.target.closest('.update-title');

            if (titleElement) {

                const taskId = titleElement.getAttribute('data-task-id');

                const newTitle = titleElement.innerText.trim();

                const currentTask = tasks.find(t => t.id === taskId);


                if (currentTask && currentTask.title !== newTitle) {

                     if (newTitle === "") {

                        // Prevent empty title, revert or set default

                        titleElement.innerText = currentTask.title;

                        return;

                    }

                    await updateTaskField(taskId, 'title', newTitle);

                }

            }

        }, true); // Use capture phase to catch blur on contenteditable elements


        // --- Application Start ---

        window.onload = initializeFirebase;


    </script>

</body>

</html>