https://stories.radiocorax.de/story-scripts.js

archived 12 Oct 2025 02:08:47 UTC
let stories = [];
let contacts = [];

// Connect to SSE endpoint
const eventSource = new EventSource('/updates');

// Load stories and contacts when the page is loaded
document.addEventListener('DOMContentLoaded', async () => {
    await loadContacts();
    loadStories();
});

// Listen for updates from the server
eventSource.onmessage = function(event) {
    const data = JSON.parse(event.data);
    if (data.type === 'UPDATE') {
        loadStories(data.stories);
    }
};

document.addEventListener('DOMContentLoaded', async function() {
    // Wait for contacts to load first
    await loadContacts();

    // Wait for stories to load before proceeding
    await loadStories();

    // Now fetch the current user
    await fetchCurrentUser();

    // Add New Story button
    const addStoryButton = document.getElementById('add-story-button');
    if (addStoryButton) {
        addStoryButton.addEventListener('click', addNewStory);
    }

    // Reload Entries button
    const reloadButton = document.getElementById('reload-button');
    if (reloadButton) {
        reloadButton.addEventListener('click', loadStories);
    }

    // Editor filter input
    const editorFilterInput = document.getElementById('editor-filter');
    const clearEditorFilter = document.getElementById('clear-editor-filter');

    if (editorFilterInput) {
        // Event listener for autocomplete
        editorFilterInput.addEventListener('input', function(event) {
            updateEditorFilterAutocomplete(event);
            filterStories(); // Ensure filtering is applied when typing
        });

        // Event listener for showing/hiding the "X" icon
        editorFilterInput.addEventListener('input', function() {
            clearEditorFilter.style.display = this.value ? 'block' : 'none';
        });

        if (clearEditorFilter) {
            clearEditorFilter.addEventListener('click', function() {
                editorFilterInput.value = '';
                clearEditorFilter.style.display = 'none';
                editorFilterInput.focus();
                filterStories(); // Ensure filtering is applied after clearing
            });
        }
    } else {
        console.error('Editor filter input not found!');
    }

    // Filter checkboxes
    const filterCheckboxes = document.querySelectorAll('.filter-checkbox');
    filterCheckboxes.forEach(checkbox => {
        checkbox.addEventListener('change', filterStories); // Apply filters on checkbox change
    });

    // Dropdown button
    const dropdownButton = document.querySelector('.dropdown-button');
    if (dropdownButton) {
        dropdownButton.addEventListener('click', function() {
            const dropdownContent = document.querySelector('.dropdown-content');
            dropdownContent.style.display = dropdownContent.style.display === 'block' ? 'none' : 'block';
        });
    }
    
    const storyDivs = document.querySelectorAll('.storyDiv');
    storyDivs.forEach(storyDiv => {
        console.log("Attaching background listener to: ", storyDiv);  // Check if we are selecting the correct storyDiv
        attachBackgroundListeners(storyDiv);  // This will attach the background listeners to each story div
    });
});


async function fetchCurrentUser() {
    try {
        const response = await fetch('/api/current-user');
        if (response.ok) {
            const user = await response.json();
            const editorFilterInput = document.getElementById('editor-filter');
            const clearEditorFilter = document.getElementById('clear-editor-filter');

            if (editorFilterInput) {
                // Set the editor filter value from the current user
                editorFilterInput.value = user.fullName;

                // Show or hide the clear button based on the input value
                if (clearEditorFilter) {
                    clearEditorFilter.style.display = user.fullName ? 'block' : 'none';
                }

                // Manually trigger the input event to apply the filter immediately
                editorFilterInput.dispatchEvent(new Event('input'));

                // Manually call filterStories to ensure the stories are filtered
                filterStories();
            }
        } else {
            console.error('Failed to fetch current user');
        }
    } catch (error) {
        console.error('Error fetching current user:', error);
    }
}


async function loadContacts() {
    const response = await fetch('/api/contacts');
    if (response.ok) {
        contacts = await response.json();
    } else {
        console.error('Failed to load contacts');
    }
}

async function loadStories(storiesData = null) {
    let data = storiesData || [];
    if (!data.length) {
        const response = await fetch('/api/stories');
        if (response.ok) {
            const result = await response.json();
            data = Array.isArray(result) ? result : [];
        } else {
            console.error('Failed to load stories');
            return;
        }
    }
    
    const container = document.getElementById('stories-container');
    container.innerHTML = '';

    
    data.forEach(story => {
        const storyDiv = document.createElement('div');
        storyDiv.className = story.modified ? 'story modified' : 'story saved';
        storyDiv.dataset.id = story.id;
        storyDiv.dataset.deleted = story.deleted;
        let interviewPartnerInputs = story.interviewPartners.map((partner, index) => `
            <div class="interview-partner">
                <div class="autocomplete-container">
                    <input type="text" placeholder="Interview Partner" value="${partner.name}"
                        data-index="${index}" class="interview-partner-input">
                    <div class="autocomplete-results" id="autocomplete-results-${index}"></div>
                </div>
                <input type="text" placeholder="Organization" value="${partner.organization || ''}" class="partner-org-input" data-index="${index}">
                <input type="text" placeholder="Telephone" value="${partner.telephone || ''}" class="partner-tel-input" data-index="${index}">
                <input type="text" placeholder="Second Telephone" value="${partner.secondTelephone || ''}" class="partner-second-tel-input" data-index="${index}">
                <input type="text" placeholder="Email" value="${partner.email || ''}" class="partner-email-input" data-index="${index}">
            </div>
        `).join('');

        let helpIcon = '';
        if (story.helpNeeded && (story.helpNeeded.feedback || story.helpNeeded.voiceRecordings)) {
            let backgroundStyle;
            if (story.helpNeeded.voiceRecordings && story.helpNeeded.feedback) {
                backgroundStyle = 'linear-gradient(135deg, orange 50%, red 50%)';
            } else if (story.helpNeeded.voiceRecordings) {
                backgroundStyle = '#dc3545';
            } else if (story.helpNeeded.feedback) {
                backgroundStyle = 'orange';
            }
            helpIcon = `
                <i class="material-icons help-icon"
                style="
                    color: white;
                    background: ${backgroundStyle};
                    padding: 4px 4px;
                    border-radius: 0px;
                    display: inline-block;">
                error_outline
                </i>`;
        }

        // Check if the story is LIVE
        let liveStatusHTML = '';
        if (story.isLive) {
            liveStatusHTML = `
                <div class="status-selection">
                    <label>
                        <input type="radio" name="story-status-${story.id}" value="planned" class="status-radio" data-story-id="${story.id}">
                        Planned
                    </label>
                    <label>
                        <input type="radio" name="story-status-${story.id}" value="live" checked class="status-radio" data-story-id="${story.id}">
                        LIVE
                    </label>
                    <div id="live-options-${story.id}" style="display: block;">
                        <label>
                            Date: <input type="date" class="live-date-input" data-story-id="${story.id}" value="${story.liveDate}">
                        </label>
                        <label>
                            <select class="live-channel-select" data-story-id="${story.id}">
                                <option value="MoMa" ${story.liveChannel === 'MoMa' ? 'selected' : ''}>MoMa</option>
                                <option value="WiHa" ${story.liveChannel === 'WiHa' ? 'selected' : ''}>WiHa</option>
                            </select>
                        </label>
                    </div>
                </div>
            `;
        } else {
            liveStatusHTML = `
                <div class="status-selection">
                    <label>
                        <input type="radio" name="story-status-${story.id}" value="planned" checked class="status-radio" data-story-id="${story.id}">
                        Planned
                    </label>
                    <label>
                        <input type="radio" name="story-status-${story.id}" value="live" class="status-radio" data-story-id="${story.id}">
                        LIVE
                    </label>
                    <div id="live-options-${story.id}" style="display: none;">
                        <label>
                            Date: <input type="date" class="live-date-input" data-story-id="${story.id}" value="${new Date().toISOString().split('T')[0]}">
                        </label>
                        <label>
                            <select class="live-channel-select" data-story-id="${story.id}">
                                <option value="MoMa">MoMa</option>
                                <option value="WiHa">WiHa</option>
                            </select>
                        </label>
                    </div>
                </div>
            `;
        }

        storyDiv.innerHTML = `
            <div class="story-top" style="display: flex; justify-content: space-between; align-items: center;">
                <div style="display: flex; align-items: center;">
                    <div class="support-request-container" style="display: flex; align-items: center;">
                        ${helpIcon}
                        <span style="margin-left: 8px;">Support Request?</span>
                    </div>
                    <label style="margin-left: 20px;">
                        <input type="checkbox" class="feedback-checkbox" data-story-id="${story.id}" ${story.helpNeeded && story.helpNeeded.feedback ? 'checked' : ''}>
                        Feedback
                    </label>
                    <label style="margin-left: 20px;">
                        <input type="checkbox" class="voice-recordings-checkbox" data-story-id="${story.id}" ${story.helpNeeded && story.helpNeeded.voiceRecordings ? 'checked' : ''}>
                        Voice Recordings
                    </label>
                </div>
                <div class="sbutton-container" style="display: flex; align-items: center;">
                    <span class="last-edited" style="margin-right: 10px;">Last edited: ${new Date(story.lastEdited).toLocaleString()}</span>
                    <button class="save-button" data-story-id="${story.id}" style="margin-left: 5px;">Save</button>
                    <button class="delete-button" data-story-id="${story.id}" style="margin-left: 5px;">Delete</button>
                </div>
            </div>
            <div class="story-inputs">
                <input type="text" placeholder="Story Title" class="story-title-input" data-story-id="${story.id}" value="${story.title}">
                <div class="autocomplete-container">
                    <input type="text" placeholder="Responsible Editor" class="editor-input" data-story-id="${story.id}" value="${story.editor}">
                    <div class="autocomplete-results" id="autocomplete-results-editor-${story.id}"></div>
                </div>
                <input type="text" placeholder="Story Format" class="story-format-input" data-story-id="${story.id}" value="${story.format}">
                <input type="number" placeholder="Length in Minutes" class="story-length-input" data-story-id="${story.id}" value="${story.length}">
            </div>
            <div class="status">
                ${liveStatusHTML}
                <label><input type="checkbox" class="status-checkbox" data-story-id="${story.id}" data-status-index="1" ${story.status[1] ? 'checked' : ''}> Recorded</label>
                <label><input type="checkbox" class="status-checkbox" data-story-id="${story.id}" data-status-index="2" ${story.status[2] ? 'checked' : ''}> Produced</label>
                <label><input type="checkbox" class="status-checkbox" data-story-id="${story.id}" data-status-index="3" ${story.status[3] ? 'checked' : ''}> Aired (MoMa)</label>
                <label><input type="checkbox" class="status-checkbox" data-story-id="${story.id}" data-status-index="4" ${story.status[4] ? 'checked' : ''}> Aired (WiHa)</label>
                <label><input type="checkbox" class="status-checkbox" data-story-id="${story.id}" data-status-index="5" ${story.status[5] ? 'checked' : ''}> Published (FRN)</label>
                <label><input type="checkbox" class="status-checkbox" data-story-id="${story.id}" data-status-index="6" ${story.status[6] ? 'checked' : ''}> Cross-Media-Published (Corax-Webseite)</label>
                <label><input type="checkbox" class="status-checkbox" data-story-id="${story.id}" data-status-index="7" ${story.status[7] ? 'checked' : ''}> Link sent to Interviewees</label>
            </div>
            <div>
                <details>
                    <summary>Story Details</summary>
                    <div class="interview-partners">
                        ${interviewPartnerInputs}
                        <button class="add-interview-partner-button" data-story-id="${story.id}">+</button>
                    </div>
                    <details>
                        <summary>Moderation</summary>
                        <textarea placeholder="Enter moderation text here..." class="moderation-textarea" data-story-id="${story.id}">${story.moderation}</textarea>
                    </details>
                    <details>
                        <summary>Teasertext</summary>
                        <textarea placeholder="Enter teaser text here..." class="teasertext-textarea" data-story-id="${story.id}">${story.teasertext}</textarea>
                    </details>
                    <details>
                        <summary>FRN Link</summary>
                        <textarea placeholder="Enter FRN link here..." class="frn-link-textarea" data-story-id="${story.id}">${story.frnLink}</textarea>
                    </details>
                </details>
            </div>
        `;

        container.appendChild(storyDiv);
    });

    // Add event listeners to dynamically created elements
    addDynamicEventListeners();
    updateStoryOrder();
    
    // Call filterStories after stories are loaded and rendered
    filterStories();
}

async function addNewStory() {
    const container = document.getElementById('stories-container');
    const storyDiv = document.createElement('div');
    storyDiv.className = 'story modified';
    const uniqueId = uuidv4();
    storyDiv.dataset.id = uniqueId;

    // Radio buttons for selecting "Planned" or "LIVE"
    const statusSelectionHTML = `
        <div class="status-selection">
            <label>
                <input type="radio" name="story-status-${uniqueId}" value="planned" checked class="status-radio" data-story-id="${uniqueId}">
                Planned
            </label>
            <label>
                <input type="radio" name="story-status-${uniqueId}" value="live" class="status-radio" data-story-id="${uniqueId}">
                LIVE
            </label>
            <div id="live-options-${uniqueId}" style="display: none;">
                <label>
                    Date: <input type="date" class="live-date-input" data-story-id="${uniqueId}" value="${new Date().toISOString().split('T')[0]}">
                </label>
                <label>
                    <select class="live-channel-select" data-story-id="${uniqueId}">
                        <option value="MoMa">MoMa</option>
                        <option value="WiHa">WiHa</option>
                    </select>
                </label>
            </div>
        </div>
    `;

    storyDiv.innerHTML = `
        <div class="story-top">
            <div>
                <span style="position:absolute; left:60px">Support Request?</span>
                <label style="position:absolute; left:200px">
                    <input type="checkbox" class="feedback-checkbox" data-story-id="${uniqueId}">
                    Feedback
                </label>
                <label style="position:absolute; left:300px">
                    <input type="checkbox" class="voice-recordings-checkbox" data-story-id="${uniqueId}">
                    Voice Recordings
                </label>
            </div>
            <div class="sbutton-container">
                <span class="last-edited">Last edited: Just now</span>
                <span class="button-separator"></span>
                <button class="save-button" data-story-id="${uniqueId}" style="margin-left: 5px;">Save</button>
                <span class="button-separator"></span>
                <button class="delete-button" data-story-id="${uniqueId}" style="margin-left: 5px;">Delete</button>
            </div>
        </div>
        <div class="story-inputs">
            <input type="text" placeholder="Story Title" class="story-title-input" data-story-id="${uniqueId}">
            <div class="autocomplete-container">
                <input type="text" placeholder="Responsible Editor" class="editor-input" data-story-id="${uniqueId}">
                <div class="autocomplete-results" id="autocomplete-results-editor-${uniqueId}"></div>
            </div>
            <input type="text" placeholder="Story Format" class="story-format-input" data-story-id="${uniqueId}">
            <input type="number" placeholder="Length in Minutes" class="story-length-input" data-story-id="${uniqueId}">
        </div>
        <div class="status">
            ${statusSelectionHTML}
            <label><input type="checkbox" class="status-checkbox" data-story-id="${uniqueId}" data-status-index="1"> Recorded</label>
            <label><input type="checkbox" class="status-checkbox" data-story-id="${uniqueId}" data-status-index="2"> Produced</label>
            <label><input type="checkbox" class="status-checkbox" data-story-id="${uniqueId}" data-status-index="3"> Aired (MoMa)</label>
            <label><input type="checkbox" class="status-checkbox" data-story-id="${uniqueId}" data-status-index="4"> Aired (WiHa)</label>
            <label><input type="checkbox" class="status-checkbox" data-story-id="${uniqueId}" data-status-index="5"> Published (FRN)</label>
            <label><input type="checkbox" class="status-checkbox" data-story-id="${uniqueId}" data-status-index="6"> Cross-Media-Published (Corax-Webseite)</label>
            <label><input type="checkbox" class="status-checkbox" data-story-id="${uniqueId}" data-status-index="7"> Link sent to Interviewees</label>
        </div>
        <details>
            <summary>Story Details</summary>
            <div class="interview-partners">
                <div class="interview-partner">
                    <div class="autocomplete-container">
                        <input type="text" placeholder="Interview Partner" class="interview-partner-input" data-index="0" data-story-id="${uniqueId}">
                        <div class="autocomplete-results" id="autocomplete-results-0"></div>
                    </div>
                    <input type="text" placeholder="Organization" class="partner-org-input" data-index="0" data-story-id="${uniqueId}">
                    <input type="text" placeholder="Telephone" class="partner-tel-input" data-index="0" data-story-id="${uniqueId}">
                    <input type="text" placeholder="Second Telephone" class="partner-second-tel-input" data-index="0" data-story-id="${uniqueId}">
                    <input type="text" placeholder="Email" class="partner-email-input" data-index="0" data-story-id="${uniqueId}">
                </div>
                <button class="add-interview-partner-button" data-story-id="${uniqueId}">+</button>
                <details>
                    <summary>Moderation</summary>
                    <textarea placeholder="Enter moderation text here..." class="moderation-textarea" data-story-id="${uniqueId}"></textarea>
                </details>
                <details>
                    <summary>Teasertext</summary>
                    <textarea placeholder="Enter teaser text here..." class="teasertext-textarea" data-story-id="${uniqueId}"></textarea>
                </details>
                <details>
                    <summary>FRN Link</summary>
                    <textarea placeholder="Enter FRN link here..." class="frn-link-textarea" data-story-id="${uniqueId}"></textarea>
                </details>
            </div>
        </details>
    `;

    container.insertBefore(storyDiv, container.firstChild);
    addDynamicEventListeners();
}

function handleStatusSelection(event) {
    const radio = event.target;
    const uniqueId = radio.dataset.storyId;
    const liveOptionsDiv = document.getElementById(`live-options-${uniqueId}`);
    if (radio.value === 'planned') {
        liveOptionsDiv.style.display = 'none';
    } else if (radio.value === 'live') {
        liveOptionsDiv.style.display = 'block';
    }
    markStoryAsModified(radio);
}

function addInterviewPartner(event) {
    const button = event.target;
    const storyId = button.dataset.storyId;
    const partnerIndex = document.querySelectorAll(`.interview-partner[data-story-id="${storyId}"]`).length;
    const partnerDiv = document.createElement('div');
    partnerDiv.className = 'interview-partner';
    partnerDiv.dataset.storyId = storyId;
    partnerDiv.innerHTML = `
        <div class="autocomplete-container">
            <input type="text" placeholder="Interview Partner" class="interview-partner-input" data-index="${partnerIndex}" data-story-id="${storyId}">
            <div class="autocomplete-results" id="autocomplete-results-${partnerIndex}"></div>
        </div>
        <input type="text" placeholder="Organization" class="partner-org-input" data-index="${partnerIndex}" data-story-id="${storyId}">
        <input type="text" placeholder="Telephone" class="partner-tel-input" data-index="${partnerIndex}" data-story-id="${storyId}">
        <input type="text" placeholder="Second Telephone" class="partner-second-tel-input" data-index="${partnerIndex}" data-story-id="${storyId}">
        <input type="text" placeholder="Email" class="partner-email-input" data-index="${partnerIndex}" data-story-id="${storyId}">
    `;
    button.parentNode.insertBefore(partnerDiv, button);
    addDynamicEventListeners();
}

function markStoryAsModified(element) {
    const storyDiv = element.closest('.story');
    storyDiv.classList.add('modified');
    storyDiv.classList.remove('saved');
    updateStoryBackground(storyDiv);
}

async function saveStory(event) {
    const button = event.target;
    const storyDiv = button.closest('.story');
    const storyId = button.dataset.storyId;
    const checkboxes = storyDiv.querySelectorAll('.status-checkbox');
    const feedbackCheckbox = storyDiv.querySelector('.feedback-checkbox');
    const voiceRecordingsCheckbox = storyDiv.querySelector('.voice-recordings-checkbox');
    const interviewPartnerDivs = storyDiv.querySelectorAll('.interview-partner');
    const isLive = storyDiv.querySelector(`input[name="story-status-${storyId}"]:checked`).value === 'live';
    let liveDate = '';
    let liveChannel = '';
    if (isLive) {
        liveDate = storyDiv.querySelector('.live-date-input').value;
        liveChannel = storyDiv.querySelector('.live-channel-select').value;
    }

    const interviewPartners = Array.from(interviewPartnerDivs).map(div => {
        const inputs = div.querySelectorAll('input[type="text"]');
        return {
            name: inputs[0].value,
            organization: inputs[1].value,
            telephone: inputs[2].value,
            secondTelephone: inputs[3].value,
            email: inputs[4].value
        };
    });

    const status = [false]; // Initialize story.status[0] to false
    checkboxes.forEach(checkbox => {
        status[parseInt(checkbox.dataset.statusIndex)] = checkbox.checked;
    });

    const storyData = {
        id: storyId,
        title: storyDiv.querySelector('.story-title-input').value,
        editor: storyDiv.querySelector('.editor-input').value,
        format: storyDiv.querySelector('.story-format-input').value,
        length: storyDiv.querySelector('.story-length-input').value,
        interviewPartners: interviewPartners,
        moderation: storyDiv.querySelector('.moderation-textarea').value,
        teasertext: storyDiv.querySelector('.teasertext-textarea').value,
        frnLink: storyDiv.querySelector('.frn-link-textarea').value,
        status: status,
        helpNeeded: {
            feedback: feedbackCheckbox ? feedbackCheckbox.checked : false,
            voiceRecordings: voiceRecordingsCheckbox ? voiceRecordingsCheckbox.checked : false
        },
        isLive: isLive,
        liveDate: liveDate,
        liveChannel: liveChannel,
        lastEdited: new Date().toISOString()
    };

    try {
        const response = await fetch('/api/stories', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify(storyData),
        });
        if (response.ok) {
            console.log('Story updated successfully');
            storyDiv.querySelector('.last-edited').textContent = `Last edited: ${new Date(storyData.lastEdited).toLocaleString()}`;
            storyDiv.classList.remove('modified');
            storyDiv.classList.add('saved');
            updateStoryOrder();
            // Store current filter settings
            const filterCheckboxes = Array.from(document.querySelectorAll('.dropdown-content input[type="checkbox"]'));
            const editorFilterValue = document.getElementById('editor-filter').value;
            const supportNeededFilterValue = document.getElementById('support-needed-filter').checked;
            // Reload stories to ensure the UI reflects the current saved state
            await loadStories();
            // Reapply filter settings
            document.getElementById('editor-filter').value = editorFilterValue;
            document.getElementById('support-needed-filter').checked = supportNeededFilterValue;
            filterCheckboxes.forEach((checkbox, index) => {
                checkbox.checked = checkbox.checked;
            });
            // Reapply the filter
            filterStories();
        } else {
            console.error('Failed to update story');
        }
    } catch (error) {
        console.error('Error updating story:', error);
    }
}

async function deleteStory(event) {
    const button = event.target;
    const storyId = button.dataset.storyId;

    // Save current filter settings
    const editorFilterValue = document.getElementById('editor-filter').value;
    const supportNeededFilterValue = document.getElementById('support-needed-filter').checked;
    const filterCheckboxes = Array.from(document.querySelectorAll('.dropdown-content input[type="checkbox"]'));

    try {
        const response = await fetch('/api/stories', {
            method: 'DELETE',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({ id: storyId }),
        });

        if (response.ok) {
            console.log('Story marked as deleted successfully');
            // Reload stories to update the UI
            await loadStories();

            // Reapply filter settings
            document.getElementById('editor-filter').value = editorFilterValue;
            document.getElementById('support-needed-filter').checked = supportNeededFilterValue;
            filterCheckboxes.forEach((checkbox, index) => {
                const savedCheckbox = document.querySelector(`.dropdown-content input[type="checkbox"][data-filter="${checkbox.dataset.filter}"]`);
                if (savedCheckbox) {
                    savedCheckbox.checked = checkbox.checked;
                }
            });

            // Reapply the filter
            filterStories();
        } else {
            console.error('Failed to mark story as deleted');
        }
    } catch (error) {
        console.error('Error marking story as deleted:', error);
    }
}



function uuidv4() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
        const r = Math.random() * 16 | 0;
        const v = c === 'x' ? r : (r & 0x3 | 0x8);
        return v.toString(16);
    });
}

function updateStoryOrder() {
    const container = document.getElementById('stories-container');
    const stories = Array.from(container.getElementsByClassName('story'));
    stories.sort((a, b) => {
        const aChecked = a.querySelectorAll('.status-checkbox:checked').length;
        const bChecked = b.querySelectorAll('.status-checkbox:checked').length;
        return aChecked - bChecked;
    });
    container.innerHTML = '';
    stories.forEach(story => container.appendChild(story));
}

function updateStoryBackground(storyDiv) {
    if (storyDiv.classList.contains('modified')) {
        storyDiv.style.background = '#ffe59d';
        return;
    }
    const checkboxes = storyDiv.querySelectorAll('.status-checkbox');
    const total = checkboxes.length;
    const checkedCount = Array.from(checkboxes).filter(cb => cb.checked).length;
    const fillPercent = (checkedCount / total) * 100;
    const transitionWidth = 15;
    const fadeEnd = Math.min(fillPercent + transitionWidth, 100);
    storyDiv.style.background = `
        linear-gradient(to right,
            #6C9AC4 0%,
            #81A9CE ${fillPercent}%,
            #ACC8E1 ${fadeEnd}%,
            #c1d7eb 100%)
    `;
}

function attachBackgroundListeners(storyDiv) {
    const checkboxes = storyDiv.querySelectorAll('.status-checkbox');
    checkboxes.forEach(cb => {
        cb.addEventListener('change', () => {
            updateStoryBackground(storyDiv);
        });
    });
}

function attachBackgroundListeners(storyDiv) {
    console.log("Inside attachBackgroundListeners for:", storyDiv);

    const checkboxes = storyDiv.querySelectorAll('.status-checkbox');
    if (checkboxes.length === 0) {
        console.log("No checkboxes found inside storyDiv:", storyDiv);
        return;
    }

    checkboxes.forEach(cb => {
        console.log("Attaching listener to checkbox:", cb);
        cb.addEventListener('change', () => {
            console.log("Checkbox state changed for checkbox:", cb);
            updateStoryBackground(storyDiv);  // This will update the background
        });
    });
}


function autocomplete(input, inputIndex) {
    const inputValue = input.value.toLowerCase();
    return contacts.filter(contact =>
        contact.name.toLowerCase().includes(inputValue)
    );
}

function updateAutocomplete(event) {
    const input = event.target;
    const inputIndex = input.dataset.index;
    const storyId = input.dataset.storyId;
    const resultsContainer = document.getElementById(`autocomplete-results-${inputIndex}`);
    resultsContainer.style.top = `${input.offsetHeight}px`;
    resultsContainer.style.left = `0`;
    const suggestions = autocomplete(input, inputIndex);
    resultsContainer.innerHTML = '';
    suggestions.forEach((contact, index) => {
        const div = document.createElement('div');
        div.textContent = contact.name;
        div.dataset.index = index;
        div.addEventListener('click', function() {
            input.value = contact.name;
            const inputs = input.closest('.interview-partner').querySelectorAll('input[type="text"]');
            inputs[1].value = contact.organization || '';
            inputs[2].value = contact.telephone || '';
            inputs[3].value = contact.secondTelephone || '';
            inputs[4].value = contact.email || '';
            markStoryAsModified(input);
            resultsContainer.innerHTML = '';
            resultsContainer.style.display = 'none';
        });
        resultsContainer.appendChild(div);
    });
    if (suggestions.length > 0) {
        resultsContainer.style.display = 'block';
        // Add keyboard navigation
        let selectedIndex = -1;
        input.addEventListener('keydown', function(event) {
            const divs = resultsContainer.querySelectorAll('div');
            if (event.key === 'ArrowDown') {
                event.preventDefault();
                selectedIndex = (selectedIndex + 1) % divs.length;
                divs.forEach((div, i) => {
                    div.style.backgroundColor = i === selectedIndex ? '#ddd' : '';
                });
            } else if (event.key === 'ArrowUp') {
                event.preventDefault();
                selectedIndex = (selectedIndex - 1 + divs.length) % divs.length;
                divs.forEach((div, i) => {
                    div.style.backgroundColor = i === selectedIndex ? '#ddd' : '';
                });
            } else if (event.key === 'Enter' && selectedIndex >= 0) {
                event.preventDefault();
                input.value = suggestions[selectedIndex].name;
                const inputs = input.closest('.interview-partner').querySelectorAll('input[type="text"]');
                inputs[1].value = suggestions[selectedIndex].organization || '';
                inputs[2].value = suggestions[selectedIndex].telephone || '';
                inputs[3].value = suggestions[selectedIndex].secondTelephone || '';
                inputs[4].value = suggestions[selectedIndex].email || '';
                markStoryAsModified(input);
                resultsContainer.innerHTML = '';
                resultsContainer.style.display = 'none';
            }
        });
    } else {
        resultsContainer.style.display = 'none';
    }
}

function updateEditorAutocomplete(event) {
    const input = event.target;
    const storyId = input.dataset.storyId;
    const resultsContainer = document.getElementById(`autocomplete-results-editor-${storyId}`);
    const inputValue = input.value.toLowerCase();
    const suggestions = contacts.filter(contact =>
        contact.name.toLowerCase().includes(inputValue)
    );
    resultsContainer.innerHTML = '';
    suggestions.forEach((contact, index) => {
        const div = document.createElement('div');
        div.textContent = contact.name;
        div.dataset.index = index;
        div.addEventListener('click', function() {
            input.value = contact.name;
            markStoryAsModified(input);
            resultsContainer.innerHTML = '';
            resultsContainer.style.display = 'none';
        });
        resultsContainer.appendChild(div);
    });
    if (suggestions.length > 0) {
        resultsContainer.style.display = 'block';
        resultsContainer.style.top = `${input.offsetHeight + input.offsetTop}px`;
        resultsContainer.style.left = `${input.offsetLeft}px`;
        resultsContainer.style.position = 'absolute';
        // Add keyboard navigation
        let selectedIndex = -1;
        input.addEventListener('keydown', function(event) {
            const divs = resultsContainer.querySelectorAll('div');
            if (event.key === 'ArrowDown') {
                event.preventDefault();
                selectedIndex = (selectedIndex + 1) % divs.length;
                divs.forEach((div, i) => {
                    div.style.backgroundColor = i === selectedIndex ? '#ddd' : '';
                });
            } else if (event.key === 'ArrowUp') {
                event.preventDefault();
                selectedIndex = (selectedIndex - 1 + divs.length) % divs.length;
                divs.forEach((div, i) => {
                    div.style.backgroundColor = i === selectedIndex ? '#ddd' : '';
                });
            } else if (event.key === 'Enter' && selectedIndex >= 0) {
                event.preventDefault();
                input.value = suggestions[selectedIndex].name;
                markStoryAsModified(input);
                resultsContainer.innerHTML = '';
                resultsContainer.style.display = 'none';
            }
        });
    } else {
        resultsContainer.style.display = 'none';
    }
}

function updateEditorFilterAutocomplete(event) {
    const input = event.target;
    const resultsContainer = document.getElementById('autocomplete-results-editor-filter');
    const inputValue = input.value.toLowerCase();
    const suggestions = contacts.filter(contact =>
        contact.name.toLowerCase().includes(inputValue)
    );
    resultsContainer.innerHTML = ''; // Clear previous results

    // Create and display suggestions
    suggestions.forEach((contact, index) => {
        const div = document.createElement('div');
        div.textContent = contact.name;
        div.dataset.index = index;
        
        // Add click handler to fill input with selected contact
        div.addEventListener('click', function() {
            input.value = contact.name;
            resultsContainer.innerHTML = ''; // Clear suggestions
            resultsContainer.style.display = 'none'; // Hide suggestions
        });
        
        resultsContainer.appendChild(div);
    });

    // Show or hide the results container based on suggestions
    if (suggestions.length > 0) {
        resultsContainer.style.display = 'block';
    } else {
        resultsContainer.style.display = 'none';
    }

    // Add keyboard navigation only if there are results
    if (suggestions.length > 0) {
        let selectedIndex = -1;

        // Add a keydown listener for keyboard navigation
        input.addEventListener('keydown', function(event) {
            const divs = resultsContainer.querySelectorAll('div');
            if (event.key === 'ArrowDown') {
                event.preventDefault();
                selectedIndex = (selectedIndex + 1) % divs.length;
                updateSelectedItem(divs, selectedIndex);
            } else if (event.key === 'ArrowUp') {
                event.preventDefault();
                selectedIndex = (selectedIndex - 1 + divs.length) % divs.length;
                updateSelectedItem(divs, selectedIndex);
            } else if (event.key === 'Enter' && selectedIndex >= 0) {
                event.preventDefault();
                input.value = suggestions[selectedIndex].name;
                resultsContainer.innerHTML = ''; // Clear suggestions
                resultsContainer.style.display = 'none'; // Hide suggestions
            }
        });
    }
}

// Helper function to update the selected item's background
function updateSelectedItem(divs, selectedIndex) {
    divs.forEach((div, i) => {
        div.style.backgroundColor = i === selectedIndex ? '#ddd' : '';
    });
}


function filterStories() {
    const filterCheckboxes = Array.from(document.querySelectorAll('.dropdown-content input[type="checkbox"]')).slice(0, -1);
    const editorFilter = document.getElementById('editor-filter').value.toLowerCase();
    const supportNeededFilter = document.getElementById('support-needed-filter').checked;
    const stories = document.querySelectorAll('.story');
    stories.forEach(story => {
        // Check if the story is deleted and immediately hide it if true
        if (story.dataset.deleted === 'true') {
            story.style.display = 'none';
            return; // Skip to the next story
        }

        const storyCheckboxes = story.querySelectorAll('.status-checkbox');
        const editorName = story.querySelector('.editor-input').value.toLowerCase();
        const feedbackCheckbox = story.querySelector('.feedback-checkbox');
        const voiceRecordingsCheckbox = story.querySelector('.voice-recordings-checkbox');
        const isLive = story.querySelector('input[name^="story-status"]:checked').value === 'live';
        const isPlanned = story.querySelector('input[name^="story-status"]:checked').value === 'planned';
        const editorMatch = editorName.includes(editorFilter);
        const supportNeededMatch = !supportNeededFilter || (feedbackCheckbox?.checked || voiceRecordingsCheckbox?.checked);
        let shouldDisplay = false;
        const anyFilterChecked = filterCheckboxes.some(checkbox => checkbox.checked);

        if (!anyFilterChecked && editorFilter === '' && !supportNeededFilter) {
            shouldDisplay = true;
        } else {
            const plannedFilterChecked = filterCheckboxes[0].checked;
            const liveFilterChecked = filterCheckboxes[1].checked;
            // Check if all selected filters match the story's status
            const statusMatch = filterCheckboxes.every((filterCheckbox, index) => {
                if (!filterCheckbox.checked) {
                    return true; // Skip unchecked filters
                }
                if (index === 0) {
                    return isPlanned;
                }
                if (index === 1) {
                    return isLive;
                }
                return storyCheckboxes[index - 2]?.checked;
            });
            shouldDisplay = statusMatch && editorMatch && supportNeededMatch;
        }

        // Apply the final display logic
        story.style.display = shouldDisplay ? 'block' : 'none';
    });
}


function addDynamicEventListeners() {
    // Add event listeners to dynamically created elements
    document.querySelectorAll('.save-button').forEach(button => {
        button.addEventListener('click', saveStory);
    });

    document.querySelectorAll('.delete-button').forEach(button => {
        button.addEventListener('click', deleteStory);
    });

    document.querySelectorAll('.status-radio').forEach(radio => {
        radio.addEventListener('change', handleStatusSelection);
    });

    document.querySelectorAll('.add-interview-partner-button').forEach(button => {
        button.addEventListener('click', addInterviewPartner);
    });

    document.querySelectorAll('.interview-partner-input').forEach(input => {
        input.addEventListener('input', updateAutocomplete);
    });

    document.querySelectorAll('.editor-input').forEach(input => {
        input.addEventListener('input', updateEditorAutocomplete);
    });

    document.querySelectorAll('.story-title-input, .story-format-input, .story-length-input, .moderation-textarea, .teasertext-textarea, .frn-link-textarea, .partner-org-input, .partner-tel-input, .partner-second-tel-input, .partner-email-input').forEach(input => {
        input.addEventListener('change', function() {
            markStoryAsModified(this);
        });
    });

    document.querySelectorAll('.feedback-checkbox, .voice-recordings-checkbox, .status-checkbox').forEach(checkbox => {
        checkbox.addEventListener('change', function() {
            markStoryAsModified(this);
        });
    });
}

// Close dropdowns when clicking outside
document.addEventListener('click', function(event) {
    const dropdownContents = document.querySelectorAll('.dropdown-content, .autocomplete-results');
    dropdownContents.forEach(dropdown => {
        if (!dropdown.contains(event.target) &&
            !event.target.classList.contains('dropdown-button') &&
            !event.target.closest('.autocomplete-container') &&
            !event.target.closest('.dropdown-button')) {
            dropdown.style.display = 'none';
        }
    });
});

// Close dropdowns and clear input when ESC key is pressed
document.addEventListener('keydown', function(event) {
    if (event.key === 'Escape') {
        // Close the dropdowns
        const dropdownContents = document.querySelectorAll('.dropdown-content, .autocomplete-results');
        dropdownContents.forEach(dropdown => {
            dropdown.style.display = 'none';
        });

        // Clear the input field if it's an editor filter input
        const editorFilterInput = document.getElementById('editor-filter');
        if (editorFilterInput) {
            editorFilterInput.value = '';  // Clear the text input
        }
    }
});

0%
10%
20%
30%
40%
50%
60%
70%
80%
90%
100%
word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word

mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1