Feature: config UI split across Schedule and Venue panels

This commit is contained in:
Dejvino 2026-01-04 06:17:57 +00:00
parent 03474298a9
commit 066fcc26cc
2 changed files with 85 additions and 24 deletions

View File

@ -9,12 +9,14 @@ export class ConfigUI extends SceneFeature {
super(); super();
sceneFeatureManager.register(this); sceneFeatureManager.register(this);
this.toggles = {}; this.toggles = {};
this.containers = [];
} }
init() { init() {
const container = document.createElement('div'); // --- Left Panel: Party Schedule ---
container.id = 'config-ui'; const leftContainer = document.createElement('div');
Object.assign(container.style, { leftContainer.id = 'config-ui-left';
Object.assign(leftContainer.style, {
position: 'absolute', position: 'absolute',
top: '70px', top: '70px',
left: '20px', left: '20px',
@ -29,6 +31,47 @@ export class ConfigUI extends SceneFeature {
gap: '10px', gap: '10px',
minWidth: '200px' minWidth: '200px'
}); });
this.containers.push(leftContainer);
const heading = document.createElement('h3');
heading.innerText = 'Party schedule';
Object.assign(heading.style, {
margin: '0 0 15px 0',
textAlign: 'center',
borderBottom: '1px solid #555',
paddingBottom: '10px'
});
leftContainer.appendChild(heading);
// --- Right Panel: Party Venue ---
const rightContainer = document.createElement('div');
rightContainer.id = 'config-ui-right';
Object.assign(rightContainer.style, {
position: 'absolute',
top: '70px',
right: '20px',
zIndex: '1000',
backgroundColor: 'rgba(0, 0, 0, 0.8)',
padding: '15px',
borderRadius: '8px',
color: 'white',
fontFamily: 'sans-serif',
display: 'flex',
flexDirection: 'column',
gap: '10px',
minWidth: '200px'
});
this.containers.push(rightContainer);
const venueHeading = document.createElement('h3');
venueHeading.innerText = 'Party venue';
Object.assign(venueHeading.style, {
margin: '0 0 15px 0',
textAlign: 'center',
borderBottom: '1px solid #555',
paddingBottom: '10px'
});
rightContainer.appendChild(venueHeading);
const saveConfig = () => { const saveConfig = () => {
localStorage.setItem('partyConfig', JSON.stringify(state.config)); localStorage.setItem('partyConfig', JSON.stringify(state.config));
@ -56,7 +99,7 @@ export class ConfigUI extends SceneFeature {
this.toggles[configKey] = { checkbox: chk, callback: onChange }; this.toggles[configKey] = { checkbox: chk, callback: onChange };
row.appendChild(lbl); row.appendChild(lbl);
row.appendChild(chk); row.appendChild(chk);
container.appendChild(row); rightContainer.appendChild(row);
}; };
// Torches Toggle // Torches Toggle
@ -99,14 +142,11 @@ export class ConfigUI extends SceneFeature {
hatRow.appendChild(hatLabel); hatRow.appendChild(hatLabel);
hatRow.appendChild(hatSelect); hatRow.appendChild(hatSelect);
container.appendChild(hatRow); rightContainer.appendChild(hatRow);
// --- Status & Control Section --- // --- Status & Control Section ---
const statusContainer = document.createElement('div'); const statusContainer = document.createElement('div');
Object.assign(statusContainer.style, { Object.assign(statusContainer.style, {
marginTop: '15px',
paddingTop: '10px',
borderTop: '1px solid #555',
display: 'flex', display: 'flex',
flexDirection: 'column', flexDirection: 'column',
gap: '8px' gap: '8px'
@ -143,7 +183,7 @@ export class ConfigUI extends SceneFeature {
marginTop: '10px', marginTop: '10px',
padding: '8px', padding: '8px',
cursor: 'pointer', cursor: 'pointer',
backgroundColor: '#555', backgroundColor: '#ff9800', // Default orange
color: 'white', color: 'white',
border: 'none', border: 'none',
borderRadius: '4px', borderRadius: '4px',
@ -168,6 +208,7 @@ export class ConfigUI extends SceneFeature {
loadPosterBtn.onclick = () => { loadPosterBtn.onclick = () => {
posterInput.click(); posterInput.click();
}; };
this.loadPosterBtn = loadPosterBtn;
statusContainer.appendChild(loadPosterBtn); statusContainer.appendChild(loadPosterBtn);
// Load Tapes Button // Load Tapes Button
@ -178,7 +219,7 @@ export class ConfigUI extends SceneFeature {
marginTop: '10px', marginTop: '10px',
padding: '8px', padding: '8px',
cursor: 'pointer', cursor: 'pointer',
backgroundColor: '#555', backgroundColor: '#ff9800', // Default orange
color: 'white', color: 'white',
border: 'none', border: 'none',
borderRadius: '4px', borderRadius: '4px',
@ -194,7 +235,7 @@ export class ConfigUI extends SceneFeature {
marginTop: '10px', marginTop: '10px',
padding: '8px', padding: '8px',
cursor: 'pointer', cursor: 'pointer',
backgroundColor: '#555', backgroundColor: '#ff9800', // Default orange
color: 'white', color: 'white',
border: 'none', border: 'none',
borderRadius: '4px', borderRadius: '4px',
@ -204,6 +245,7 @@ export class ConfigUI extends SceneFeature {
const fileInput = document.getElementById('musicFileInput'); const fileInput = document.getElementById('musicFileInput');
if (fileInput) fileInput.click(); if (fileInput) fileInput.click();
}; };
this.chooseSongBtn = chooseSongBtn;
statusContainer.appendChild(chooseSongBtn); statusContainer.appendChild(chooseSongBtn);
// Start Party Button // Start Party Button
@ -214,8 +256,8 @@ export class ConfigUI extends SceneFeature {
marginTop: '10px', marginTop: '10px',
padding: '10px', padding: '10px',
cursor: 'not-allowed', cursor: 'not-allowed',
backgroundColor: '#333', backgroundColor: '#dc3545', // Default red
color: '#777', color: 'white',
border: 'none', border: 'none',
borderRadius: '4px', borderRadius: '4px',
fontSize: '16px', fontSize: '16px',
@ -227,7 +269,7 @@ export class ConfigUI extends SceneFeature {
if (musicPlayer) musicPlayer.startSequence(); if (musicPlayer) musicPlayer.startSequence();
}; };
statusContainer.appendChild(this.startButton); statusContainer.appendChild(this.startButton);
container.appendChild(statusContainer); leftContainer.appendChild(statusContainer);
// Reset Button // Reset Button
const resetBtn = document.createElement('button'); const resetBtn = document.createElement('button');
@ -293,10 +335,10 @@ export class ConfigUI extends SceneFeature {
if (this.hatSelect) this.hatSelect.value = defaults.djHat; if (this.hatSelect) this.hatSelect.value = defaults.djHat;
this.updateStatus(); this.updateStatus();
}; };
container.appendChild(resetBtn); leftContainer.appendChild(resetBtn);
document.body.appendChild(container); document.body.appendChild(leftContainer);
this.container = container; document.body.appendChild(rightContainer);
this.updateStatus(); this.updateStatus();
// Restore poster // Restore poster
@ -311,23 +353,40 @@ export class ConfigUI extends SceneFeature {
updateStatus() { updateStatus() {
if (!this.songLabel) return; if (!this.songLabel) return;
const orange = '#ff9800';
const green = '#28a745';
const red = '#dc3545';
// Update Song Info // Update Song Info
if (state.music && state.music.songTitle) { if (state.music && state.music.songTitle) {
this.songLabel.innerText = `Song: ${state.music.songTitle}`; this.songLabel.innerText = `Song: ${state.music.songTitle}`;
this.songLabel.style.color = '#fff'; this.songLabel.style.color = '#fff';
this.startButton.disabled = false; this.startButton.disabled = false;
this.startButton.style.backgroundColor = '#28a745'; this.startButton.style.backgroundColor = green;
this.startButton.style.color = 'white'; this.startButton.style.color = 'white';
this.startButton.style.cursor = 'pointer'; this.startButton.style.cursor = 'pointer';
this.startButton.style.opacity = '1';
if (this.chooseSongBtn) this.chooseSongBtn.style.backgroundColor = green;
} else { } else {
this.songLabel.innerText = 'Song: (None)'; this.songLabel.innerText = 'Song: (None)';
this.songLabel.style.color = '#aaa'; this.songLabel.style.color = '#aaa';
this.startButton.disabled = true; this.startButton.disabled = true;
this.startButton.style.backgroundColor = '#333'; this.startButton.style.backgroundColor = red;
this.startButton.style.color = '#777'; this.startButton.style.color = 'white';
this.startButton.style.opacity = '0.6';
this.startButton.style.cursor = 'not-allowed'; this.startButton.style.cursor = 'not-allowed';
if (this.chooseSongBtn) this.chooseSongBtn.style.backgroundColor = orange;
}
if (this.loadPosterBtn) {
this.loadPosterBtn.style.backgroundColor = state.posterImage ? green : orange;
}
if (state.loadTapeButton) {
state.loadTapeButton.style.backgroundColor = (state.videoUrls && state.videoUrls.length > 0) ? green : orange;
} }
// Update Tape List // Update Tape List
@ -356,10 +415,10 @@ export class ConfigUI extends SceneFeature {
} }
onPartyStart() { onPartyStart() {
if (this.container) this.container.style.display = 'none'; this.containers.forEach(c => c.style.display = 'none');
} }
onPartyEnd() { onPartyEnd() {
if (this.container) this.container.style.display = 'flex'; this.containers.forEach(c => c.style.display = 'flex');
} }
} }

View File

@ -77,10 +77,12 @@ export class MusicPlayer extends SceneFeature {
startSequence() { startSequence() {
const uiContainer = document.getElementById('ui-container'); const uiContainer = document.getElementById('ui-container');
const configUI = document.getElementById('config-ui'); const configUILeft = document.getElementById('config-ui-left');
const configUIRight = document.getElementById('config-ui-right');
if (uiContainer) uiContainer.style.display = 'none'; if (uiContainer) uiContainer.style.display = 'none';
if (configUI) configUI.style.display = 'none'; if (configUILeft) configUILeft.style.display = 'none';
if (configUIRight) configUIRight.style.display = 'none';
if (state.loadTapeButton) state.loadTapeButton.classList.add('hidden'); if (state.loadTapeButton) state.loadTapeButton.classList.add('hidden');
showStandbyScreen(); showStandbyScreen();