Annoucement Web -Depreciated

This commit is contained in:
Media Rogc
2025-06-30 20:27:28 -05:00
commit 44cee37384
2068 changed files with 468776 additions and 0 deletions
+311
View File
@@ -0,0 +1,311 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Control Panel - Church Announcements</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- SortableJS & Flatpickr CSS -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/Sortable/1.15.0/Sortable.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">
<style>
/* Basic styling */
body { background: #222; color: #fff; font-family: sans-serif; margin: 0; padding: 0; }
#pageTitle { text-align: center; margin: 1rem 0; font-family: 'Roboto', sans-serif; text-transform: uppercase; font-weight: bold; letter-spacing: 1px; font-size: 2rem; }
.preview-container { max-width: 1000px; margin: 0 auto 1rem; text-align: center; }
.preview-iframe { width: 50%; aspect-ratio: 16/9; border: 3px solid #fff; border-radius: 10px; box-shadow: 0 0 10px rgba(0,0,0,0.5); }
.tab-nav { display: flex; justify-content: center; margin-bottom: 1rem; }
.tab-nav button { background: #444; border: none; color: #fff; padding: .5rem 1rem; margin: 0 .5rem; cursor: pointer; font-size: 1rem; border-radius: 4px; transition: background .3s; }
.tab-nav button:hover { background: #666; }
.active-tab { background: #4caf50 !important; }
#announcementsSection { display: block; }
#bibleSection { display: none; max-width: 1000px; margin: 0 auto; padding: 1rem 0; }
#bibleSection h2 { text-align: center; margin-bottom: 1rem; }
/* Slider-style toggle */
#activeFilterContainer { text-align: right; padding: 0 1rem; }
.toggle-label { position: relative; display: inline-block; width: 60px; height: 34px; }
.toggle-label input { opacity: 0; width: 0; height: 0; position: absolute; }
.toggle-slider { position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: #888; border-radius: 34px; transition: .4s; cursor: pointer; }
.toggle-slider:before { content: ""; position: absolute; height: 26px; width: 26px; left: 4px; bottom: 4px; background: #fff; border-radius: 50%; transition: .4s; }
.toggle-label input:checked + .toggle-slider { background: #4caf50; }
.toggle-label input:checked + .toggle-slider:before { transform: translateX(26px); }
.toggle-slider .icon { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-size: 14px; pointer-events: none; opacity: 0; transition: opacity .2s; color: #4caf50; }
.toggle-label input:checked + .toggle-slider .icon.check { opacity: 1; }
.toggle-label input:not(:checked) + .toggle-slider .icon.cross { opacity: 1; }
/* Slides grid */
.slides-container { display: grid; grid-template-columns: repeat(auto-fill, minmax(325px,1fr)); gap: 2rem; padding: 1rem; justify-items: center; }
.slide-item { width: 150px; cursor: pointer; position: relative; transition: outline-color .3s ease; }
.slide-item img { width: 100%; border-radius: 10px; outline: 3px solid transparent; outline-offset: -3px; box-shadow: 0 0 10px rgba(0,0,0,0.5); transition: outline-color .3s ease; }
.slide-item.active img { outline-color: lime; }
@media(min-width:768px){ .slide-item{ width:325px; } }
/* Bible search table */
#bibleSearchContainer { text-align: center; margin-bottom: 1rem; }
#bibleSearchInput { width: 60%; padding: .5rem; font-size:1rem; background:#333; border:1px solid #555; border-radius:4px; color:#fff; }
#bibleSearchButton { padding:.5rem 1rem; margin-left:.5rem; background:#4caf50; border:none; border-radius:4px; color:#fff; cursor:pointer; }
#bibleTable { width:100%; border-collapse:collapse; }
#bibleTable th, #bibleTable td { border:1px solid #555; padding:.5rem; text-align:left; }
#bibleTable th { background:#333; }
.custom-context-menu { position:absolute; display:none; z-index:9999; background:#333; border:1px solid #444; border-radius:8px; padding:8px; box-shadow:0 2px 5px rgba(0,0,0,0.5); min-width:160px; }
</style>
</head>
<body>
<h1 id="pageTitle">Announcements</h1>
<div class="preview-container">
<iframe id="previewIframe" class="preview-iframe" src="http://127.0.0.1:5000/"></iframe>
</div>
<!-- Slider toggle -->
<div id="activeFilterContainer">
<label class="toggle-label">
<input type="checkbox" id="activeFilterToggle">
<span class="toggle-slider">
<span class="icon check">✔</span>
<span class="icon cross">✖</span>
</span>
</label>
</div>
<!-- Tabs -->
<div class="tab-nav">
<button id="announcementsTab" class="active-tab">Announcements</button>
<button id="bibleTab">Bible Verses</button>
</div>
<!-- Announcements Section -->
<div id="announcementsSection">
<div class="slides-container" id="slidesContainer">
{% for slide, data in statuses %}
<div class="slide-item {% if data.active %}active{% endif %}"
data-slide="{{ slide }}"
data-duration="{{ data.duration|default(7) }}"
data-title="{{ data.title|default(slide.split('.')[0]) }}"
data-end_date="{{ data.end_date|default('') }}">
<img src="{{ slide_urls[slide] }}" alt="{{ slide }}">
</div>
{% endfor %}
</div>
</div>
<!-- Bible Verses Section -->
<div id="bibleSection">
<h2>Bible Verses</h2>
<div id="bibleSearchContainer">
<input type="text" id="bibleSearchInput" placeholder="Search verses..." />
<button id="bibleSearchButton">Search</button>
</div>
<table id="bibleTable">
<thead>
<tr>
<th>Book</th><th>Chapter</th><th>Verse</th><th>Text</th><th>Translation</th><th>Add/Remove</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
<!-- Context Menu -->
<div class="custom-context-menu" id="customContextMenu">
<!-- existing context-menu items + submenus -->
</div>
<!-- Scripts -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.5.4/socket.io.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/flatpickr"></script>
<script>
// 1) Load persisted registry
let bibleRegistry = [];
document.addEventListener('DOMContentLoaded', () => {
fetch('/bible_registry')
.then(r => r.json())
.then(data => { bibleRegistry = data; })
.catch(console.error);
});
// 2) Tab switching
const announcementsTab = document.getElementById('announcementsTab'),
bibleTab = document.getElementById('bibleTab'),
announcementsSec = document.getElementById('announcementsSection'),
bibleSec = document.getElementById('bibleSection'),
pageTitle = document.getElementById('pageTitle'),
activeToggle = document.getElementById('activeFilterToggle'),
slidesContainer = document.getElementById('slidesContainer');
announcementsTab.addEventListener('click', () => {
announcementsSec.style.display = 'block';
bibleSec.style.display = 'none';
announcementsTab.classList.add('active-tab');
bibleTab.classList.remove('active-tab');
pageTitle.innerText = 'Announcements';
activeToggle.parentElement.style.display = 'block';
});
bibleTab.addEventListener('click', () => {
announcementsSec.style.display = 'none';
bibleSec.style.display = 'block';
bibleTab.classList.add('active-tab');
announcementsTab.classList.remove('active-tab');
pageTitle.innerText = 'Bible Verses';
activeToggle.parentElement.style.display = 'none';
});
// 3) Drag-and-drop ordering
let isDragging = false;
Sortable.create(slidesContainer, {
animation: 150, delay: 50,
onStart: () => { isDragging = true; },
onEnd: () => {
isDragging = false;
const order = Array.from(slidesContainer.children).map(c => c.dataset.slide);
fetch('/update_order', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ order })
});
}
});
// 4) Toggle hiding inactive slides
activeToggle.addEventListener('change', () => {
slidesContainer.querySelectorAll('.slide-item').forEach(item => {
item.style.display = activeToggle.checked && !item.classList.contains('active')
? 'none' : 'block';
});
});
// 5) Click slide to activate/deactivate
slidesContainer.addEventListener('click', e => {
if (isDragging) return;
const item = e.target.closest('.slide-item');
if (item && e.button === 0) {
item.classList.toggle('active');
fetch('/update_active', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
slide: item.dataset.slide,
active: item.classList.contains('active')
})
});
}
});
// 6) Bible search & add/remove logic
const bibleSearchInput = document.getElementById('bibleSearchInput'),
bibleSearchButton = document.getElementById('bibleSearchButton'),
bibleTableBody = document.querySelector('#bibleTable tbody');
bibleSearchButton.addEventListener('click', () => {
const q = bibleSearchInput.value.trim();
bibleTableBody.innerHTML = '';
// Empty query → show what's in registry
if (!q) {
bibleRegistry.forEach(entry => {
const idx = entry.reference.lastIndexOf(' '),
book = entry.reference.slice(0, idx),
[chapter, verse] = entry.reference.slice(idx + 1).split(':'),
tr = document.createElement('tr');
tr.innerHTML = `
<td>${book}</td>
<td>${chapter}</td>
<td>${verse}</td>
<td>${entry.verse}</td>
<td></td>
<td></td>
`;
const btn = document.createElement('button');
btn.textContent = '–';
btn.style.width = '2rem';
btn.dataset.id = entry.id;
btn.addEventListener('click', () => {
fetch('/remove_bible_verse', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ id: Number(btn.dataset.id) })
})
.then(r => r.json())
.then(resp => {
if (resp.status === 'success') {
bibleRegistry = bibleRegistry.filter(e => e.id !== entry.id);
tr.remove();
}
});
});
tr.cells[5].appendChild(btn);
bibleTableBody.appendChild(tr);
});
return;
}
// Non-empty → query DB
fetch('/search_verses?q=' + encodeURIComponent(q))
.then(r => r.json())
.then(results => {
results.forEach(verse => {
const ref = `${verse.book} ${verse.chapter}:${verse.verse}`,
exist = bibleRegistry.find(e => e.reference === ref),
tr = document.createElement('tr');
tr.innerHTML = `
<td>${verse.book}</td>
<td>${verse.chapter}</td>
<td>${verse.verse}</td>
<td>${verse.text}</td>
<td>${verse.translation}</td>
<td></td>
`;
const btn = document.createElement('button');
btn.style.width = '2rem';
if (exist) {
btn.textContent = '–';
btn.dataset.id = exist.id;
} else {
btn.textContent = '+';
}
btn.addEventListener('click', () => {
if (btn.textContent === '+') {
// Add
fetch('/add_bible_verse', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ verse: verse.text, reference: ref })
})
.then(r => r.json())
.then(resp => {
if (resp.status === 'success') {
btn.textContent = '–';
btn.dataset.id = resp.entry.id;
bibleRegistry.push(resp.entry);
}
});
} else {
// Remove
const id = Number(btn.dataset.id);
fetch('/remove_bible_verse', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ id })
})
.then(r => r.json())
.then(resp => {
if (resp.status === 'success') {
bibleRegistry = bibleRegistry.filter(e => e.id !== id);
btn.textContent = '+';
}
});
}
});
tr.cells[5].appendChild(btn);
bibleTableBody.appendChild(tr);
});
});
});
bibleSearchInput.addEventListener('keydown', e => {
if (e.key === 'Enter') bibleSearchButton.click();
});
</script>
</body>
</html>