mirror of
https://github.com/nfonteyne/octane-website.git
synced 2026-09-03 23:24:48 +02:00
update: one concert tab instead of 2
This commit is contained in:
parent
23fc039ac3
commit
8ef9d1db42
11 changed files with 161 additions and 153 deletions
|
|
@ -239,12 +239,11 @@ erDiagram
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `/index.html` | Tous (lecture et écriture) | Répertoire des morceaux travaillés, avec recherche instantanée (titre/artiste), liens/vignettes YouTube et Spotify, tutos embarqués par morceau et par instrument. Ajout avec autocomplete titre/artiste + liens auto-trouvés ([détails](#recherche-automatique-de-morceaux)) |
|
| `/index.html` | Tous (lecture et écriture) | Répertoire des morceaux travaillés, avec recherche instantanée (titre/artiste), liens/vignettes YouTube et Spotify, tutos embarqués par morceau et par instrument. Ajout avec autocomplete titre/artiste + liens auto-trouvés ([détails](#recherche-automatique-de-morceaux)) |
|
||||||
| `/suggestions.html` | Tous | Proposer un morceau (liens YouTube et Spotify + note libre), voter approuver/rejeter avec commentaire (attribué nominativement), ajouter une suggestion au répertoire |
|
| `/suggestions.html` | Tous | Proposer un morceau (liens YouTube et Spotify + note libre), voter approuver/rejeter avec commentaire (attribué nominativement), ajouter une suggestion au répertoire |
|
||||||
| `/setlist.html` | Tous (lecture et écriture) | Setlist du prochain concert : choix des morceaux du répertoire, ordre, notes, section rappel, lien "Écouter la setlist sur YouTube" |
|
| `/concerts.html` | Tous (lecture et écriture) | Deux onglets sur une même page. **Prochain concert** : choix des morceaux du répertoire, ordre, notes, section rappel, lien "Écouter la setlist sur YouTube". **Historique** : concerts passés, modifiables (date, morceaux, ordre, rappel) et supprimables, avec le même lien playlist ; deux vues, chronologique (par défaut, tous les concerts détaillés avec YouTube embarqué par morceau, du plus récent au plus ancien) et réduite (liste compacte) ; ouvrir un concert passé (`?tab=history&id=...`) reste partageable en lien direct |
|
||||||
| `/history.html`, `/history-detail.html` | Tous (lecture et écriture) | Historique des concerts passés, modifiable (date, morceaux, ordre, rappel) et supprimable, avec le même lien playlist YouTube. `/history.html` propose deux vues : chronologique (par défaut, tous les concerts détaillés avec YouTube embarqué par morceau, du plus récent au plus ancien) et réduite (liste compacte, comme avant) |
|
|
||||||
| `/profile.html` | Chacun voit le sien | Profil issu d'Authentik (nom, avatar, groupes) + activité personnelle (morceaux ajoutés, suggestions, votes) |
|
| `/profile.html` | Chacun voit le sien | Profil issu d'Authentik (nom, avatar, groupes) + activité personnelle (morceaux ajoutés, suggestions, votes) |
|
||||||
| `/calendar.html` | Tous (lecture et écriture) | Disponibilités du groupe pour les 3 prochaines semaines (calendrier, filtres par personne, modale par jour) — [détails](#disponibilités-calendrier) |
|
| `/calendar.html` | Tous (lecture et écriture) | Disponibilités du groupe pour les 3 prochaines semaines (calendrier, filtres par personne, modale par jour) — [détails](#disponibilités-calendrier) |
|
||||||
|
|
||||||
Le mode par défaut est la consultation ; les pages Répertoire, Setlist et Suggestions sont interactives pour toute personne connectée (chaque action reste attribuée nominativement via Authentik).
|
Le mode par défaut est la consultation ; les pages Répertoire, Concerts et Suggestions sont interactives pour toute personne connectée (chaque action reste attribuée nominativement via Authentik).
|
||||||
|
|
||||||
Un bouton clair/sombre dans la barre de navigation permet de forcer un thème (mémorisé par navigateur) ; sans préférence explicite, l'app suit le thème du système.
|
Un bouton clair/sombre dans la barre de navigation permet de forcer un thème (mémorisé par navigateur) ; sans préférence explicite, l'app suit le thème du système.
|
||||||
|
|
||||||
|
|
|
||||||
51
public/concerts.html
Normal file
51
public/concerts.html
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>Concerts — Octane</title>
|
||||||
|
<script src="/js/theme-init.js"></script>
|
||||||
|
<link rel="stylesheet" href="/css/style.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header class="app-header">
|
||||||
|
<nav id="main-nav"></nav>
|
||||||
|
</header>
|
||||||
|
<main>
|
||||||
|
<div class="section-header">
|
||||||
|
<h1 style="margin:0">Concerts</h1>
|
||||||
|
<div class="view-toggle">
|
||||||
|
<button type="button" class="view-toggle-btn active" id="tab-next">Prochain concert</button>
|
||||||
|
<button type="button" class="view-toggle-btn" id="tab-history">Historique</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="error"></div>
|
||||||
|
|
||||||
|
<div id="next-view">
|
||||||
|
<div id="next-content">Chargement…</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="history-view" style="display:none">
|
||||||
|
<div id="history-list-view">
|
||||||
|
<div class="section-header" style="margin:0 0 0.75rem">
|
||||||
|
<p class="page-subtitle" style="margin:0">Du plus récent au plus ancien en défilant vers le bas.</p>
|
||||||
|
<button type="button" class="secondary" id="toggle-history-mode-btn">Vue réduite</button>
|
||||||
|
</div>
|
||||||
|
<div id="timeline-view"></div>
|
||||||
|
<div id="compact-view" class="card-grid" style="display:none"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="history-detail-view" style="display:none">
|
||||||
|
<a href="#" class="back-link" id="back-to-history-link">← Retour à l'historique</a>
|
||||||
|
<div id="history-detail-content"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<script src="/js/api.js"></script>
|
||||||
|
<script src="/js/render.js"></script>
|
||||||
|
<script src="/js/nav.js"></script>
|
||||||
|
<script src="/js/setlistEditor.js"></script>
|
||||||
|
<script src="/js/concerts.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
<!doctype html>
|
|
||||||
<html lang="fr">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<title>Détail du concert — Octane</title>
|
|
||||||
<script src="/js/theme-init.js"></script>
|
|
||||||
<link rel="stylesheet" href="/css/style.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<header class="app-header">
|
|
||||||
<nav id="main-nav"></nav>
|
|
||||||
</header>
|
|
||||||
<main>
|
|
||||||
<a href="/history.html" class="back-link">← Retour à l'historique</a>
|
|
||||||
<div id="error"></div>
|
|
||||||
<div id="content">Chargement…</div>
|
|
||||||
</main>
|
|
||||||
|
|
||||||
<script src="/js/api.js"></script>
|
|
||||||
<script src="/js/render.js"></script>
|
|
||||||
<script src="/js/nav.js"></script>
|
|
||||||
<script src="/js/setlistEditor.js"></script>
|
|
||||||
<script src="/js/history-detail.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
<!doctype html>
|
|
||||||
<html lang="fr">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<title>Historique des concerts — Octane</title>
|
|
||||||
<script src="/js/theme-init.js"></script>
|
|
||||||
<link rel="stylesheet" href="/css/style.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<header class="app-header">
|
|
||||||
<nav id="main-nav"></nav>
|
|
||||||
</header>
|
|
||||||
<main>
|
|
||||||
<div class="section-header">
|
|
||||||
<div>
|
|
||||||
<h1 style="margin:0">Historique des concerts</h1>
|
|
||||||
<p class="page-subtitle" style="margin:0.25rem 0 0">Du plus récent au plus ancien en défilant vers le bas.</p>
|
|
||||||
</div>
|
|
||||||
<button type="button" class="secondary" id="toggle-view-btn">Vue réduite</button>
|
|
||||||
</div>
|
|
||||||
<div id="error"></div>
|
|
||||||
|
|
||||||
<div id="timeline-view"></div>
|
|
||||||
<div id="compact-view" class="card-grid" style="display:none"></div>
|
|
||||||
</main>
|
|
||||||
|
|
||||||
<script src="/js/api.js"></script>
|
|
||||||
<script src="/js/render.js"></script>
|
|
||||||
<script src="/js/nav.js"></script>
|
|
||||||
<script src="/js/history.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
@ -176,7 +176,7 @@ async function onSaveSlotSettings(e) {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2>Créneaux de répétition</h2>
|
<h2>Créneaux de répétition</h2>
|
||||||
<p class="note">Horaires utilisés pour calculer les disponibilités sur `/calendar.html`.</p>
|
<p class="note">Horaires utilisés pour calculer les disponibilités sur <code>/calendar.html</code>.</p>
|
||||||
<div class="panel">
|
<div class="panel">
|
||||||
<form id="slot-settings-form" class="stacked-form">
|
<form id="slot-settings-form" class="stacked-form">
|
||||||
<label>Semaine — début <input type="time" name="weekdayStart" required></label>
|
<label>Semaine — début <input type="time" name="weekdayStart" required></label>
|
||||||
|
|
@ -198,7 +198,7 @@ async function onSaveSlotSettings(e) {
|
||||||
<h2>Calendriers des membres</h2>
|
<h2>Calendriers des membres</h2>
|
||||||
<p class="note">
|
<p class="note">
|
||||||
Chaque utilisateur de l'application peut avoir plusieurs calendriers (Google, Outlook, Apple...).
|
Chaque utilisateur de l'application peut avoir plusieurs calendriers (Google, Outlook, Apple...).
|
||||||
Seuls les utilisateurs avec au moins un calendrier configuré apparaissent sur `/calendar.html`.
|
Seuls les utilisateurs avec au moins un calendrier configuré apparaissent sur <code>/calendar.html</code>.
|
||||||
L'application ne conserve jamais le contenu de ces calendriers — seul un statut disponible/occupé
|
L'application ne conserve jamais le contenu de ces calendriers — seul un statut disponible/occupé
|
||||||
par créneau est déduit et enregistré.
|
par créneau est déduit et enregistré.
|
||||||
</p>
|
</p>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
|
let allSongs = [];
|
||||||
let concerts = [];
|
let concerts = [];
|
||||||
let viewMode = 'timeline';
|
let historyViewMode = 'timeline';
|
||||||
|
|
||||||
function formatDate(dateStr) {
|
function formatDate(dateStr) {
|
||||||
const d = new Date(dateStr);
|
const d = new Date(dateStr);
|
||||||
|
|
@ -11,6 +12,21 @@ function formatDateShort(dateStr) {
|
||||||
return d.toLocaleDateString('fr-FR', { year: 'numeric', month: 'long', day: 'numeric' });
|
return d.toLocaleDateString('fr-FR', { year: 'numeric', month: 'long', day: 'numeric' });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function showError(message) {
|
||||||
|
document.getElementById('error').innerHTML = `<div class="error-banner">${escapeHtml(message)}</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- Tabs ----------
|
||||||
|
|
||||||
|
function switchTab(tab) {
|
||||||
|
document.getElementById('next-view').style.display = tab === 'next' ? '' : 'none';
|
||||||
|
document.getElementById('history-view').style.display = tab === 'history' ? '' : 'none';
|
||||||
|
document.getElementById('tab-next').classList.toggle('active', tab === 'next');
|
||||||
|
document.getElementById('tab-history').classList.toggle('active', tab === 'history');
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- Historique: liste (timeline / compact) ----------
|
||||||
|
|
||||||
function timelineSongRow(song) {
|
function timelineSongRow(song) {
|
||||||
const embed = youtubeEmbedUrl(song.youtube_url);
|
const embed = youtubeEmbedUrl(song.youtube_url);
|
||||||
return `
|
return `
|
||||||
|
|
@ -52,7 +68,7 @@ function timelineConcertBlock(concert) {
|
||||||
<div class="timeline-songs">${encore.map(timelineSongRow).join('')}</div>
|
<div class="timeline-songs">${encore.map(timelineSongRow).join('')}</div>
|
||||||
</div>` : ''}
|
</div>` : ''}
|
||||||
|
|
||||||
<a class="back-link" href="/history-detail.html?id=${concert.id}">Voir / modifier ce concert →</a>
|
<a class="back-link" href="#" data-concert-id="${concert.id}">Voir / modifier ce concert →</a>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
@ -60,7 +76,7 @@ function timelineConcertBlock(concert) {
|
||||||
function concertCardTemplate(c) {
|
function concertCardTemplate(c) {
|
||||||
return `
|
return `
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<a href="/history-detail.html?id=${c.id}" style="text-decoration:none;color:inherit">
|
<a href="#" data-concert-id="${c.id}" style="text-decoration:none;color:inherit">
|
||||||
<div class="card-title">${escapeHtml(c.name || 'Concert')}</div>
|
<div class="card-title">${escapeHtml(c.name || 'Concert')}</div>
|
||||||
<div class="card-subtitle">${escapeHtml(c.venue || '')} · ${formatDateShort(c.concert_date)}</div>
|
<div class="card-subtitle">${escapeHtml(c.venue || '')} · ${formatDateShort(c.concert_date)}</div>
|
||||||
</a>
|
</a>
|
||||||
|
|
@ -68,6 +84,15 @@ function concertCardTemplate(c) {
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function bindConcertLinks(container) {
|
||||||
|
container.querySelectorAll('[data-concert-id]').forEach((el) => {
|
||||||
|
el.addEventListener('click', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
showHistoryDetail(el.dataset.concertId);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function renderTimeline() {
|
function renderTimeline() {
|
||||||
const container = document.getElementById('timeline-view');
|
const container = document.getElementById('timeline-view');
|
||||||
if (!concerts.length) {
|
if (!concerts.length) {
|
||||||
|
|
@ -75,18 +100,20 @@ function renderTimeline() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
container.innerHTML = concerts.map(timelineConcertBlock).join('');
|
container.innerHTML = concerts.map(timelineConcertBlock).join('');
|
||||||
|
bindConcertLinks(container);
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderCompact() {
|
function renderCompact() {
|
||||||
const container = document.getElementById('compact-view');
|
const container = document.getElementById('compact-view');
|
||||||
renderList(container, concerts, concertCardTemplate, 'Aucun concert passé enregistré.');
|
renderList(container, concerts, concertCardTemplate, 'Aucun concert passé enregistré.');
|
||||||
|
bindConcertLinks(container);
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyViewMode() {
|
function applyHistoryViewMode() {
|
||||||
const timelineEl = document.getElementById('timeline-view');
|
const timelineEl = document.getElementById('timeline-view');
|
||||||
const compactEl = document.getElementById('compact-view');
|
const compactEl = document.getElementById('compact-view');
|
||||||
const btn = document.getElementById('toggle-view-btn');
|
const btn = document.getElementById('toggle-history-mode-btn');
|
||||||
if (viewMode === 'timeline') {
|
if (historyViewMode === 'timeline') {
|
||||||
timelineEl.style.display = 'block';
|
timelineEl.style.display = 'block';
|
||||||
compactEl.style.display = 'none';
|
compactEl.style.display = 'none';
|
||||||
btn.textContent = 'Vue réduite';
|
btn.textContent = 'Vue réduite';
|
||||||
|
|
@ -97,23 +124,81 @@ function applyViewMode() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function showError(message) {
|
async function loadHistory() {
|
||||||
document.getElementById('error').innerHTML = `<div class="error-banner">${escapeHtml(message)}</div>`;
|
concerts = await api.get('/api/setlists/history?full=1');
|
||||||
|
renderTimeline();
|
||||||
|
renderCompact();
|
||||||
|
applyHistoryViewMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- Historique: détail d'un concert ----------
|
||||||
|
|
||||||
|
function showHistoryList() {
|
||||||
|
document.getElementById('history-detail-view').style.display = 'none';
|
||||||
|
document.getElementById('history-list-view').style.display = 'block';
|
||||||
|
history.pushState({}, '', '/concerts.html?tab=history');
|
||||||
|
}
|
||||||
|
|
||||||
|
function showHistoryDetail(id) {
|
||||||
|
document.getElementById('history-list-view').style.display = 'none';
|
||||||
|
document.getElementById('history-detail-view').style.display = 'block';
|
||||||
|
history.pushState({}, '', `/concerts.html?tab=history&id=${id}`);
|
||||||
|
|
||||||
|
const editor = createSetlistEditor({
|
||||||
|
containerId: 'history-detail-content',
|
||||||
|
allSongs,
|
||||||
|
getSetlist: async () => {
|
||||||
|
try {
|
||||||
|
return await api.get(`/api/setlists/${id}`);
|
||||||
|
} catch (err) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
emptyMessage: 'Concert introuvable.',
|
||||||
|
allowDelete: true,
|
||||||
|
onDeleted: async () => {
|
||||||
|
showHistoryList();
|
||||||
|
await loadHistory();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
editor.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
(async function init() {
|
(async function init() {
|
||||||
await initNav('history');
|
await initNav('concerts');
|
||||||
|
allSongs = await api.get('/api/songs');
|
||||||
|
|
||||||
document.getElementById('toggle-view-btn').addEventListener('click', () => {
|
const nextEditor = createSetlistEditor({
|
||||||
viewMode = viewMode === 'timeline' ? 'compact' : 'timeline';
|
containerId: 'next-content',
|
||||||
applyViewMode();
|
allSongs,
|
||||||
|
getSetlist: () => api.get('/api/setlists/next'),
|
||||||
|
createSetlist: (data) => api.post('/api/setlists', data),
|
||||||
|
emptyMessage: 'Aucun concert à venir pour le moment.',
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('tab-next').addEventListener('click', () => switchTab('next'));
|
||||||
|
document.getElementById('tab-history').addEventListener('click', () => switchTab('history'));
|
||||||
|
document.getElementById('toggle-history-mode-btn').addEventListener('click', () => {
|
||||||
|
historyViewMode = historyViewMode === 'timeline' ? 'compact' : 'timeline';
|
||||||
|
applyHistoryViewMode();
|
||||||
|
});
|
||||||
|
document.getElementById('back-to-history-link').addEventListener('click', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
showHistoryList();
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
concerts = await api.get('/api/setlists/history?full=1');
|
await nextEditor.load();
|
||||||
renderTimeline();
|
await loadHistory();
|
||||||
renderCompact();
|
|
||||||
applyViewMode();
|
const params = new URLSearchParams(window.location.search);
|
||||||
|
const deepId = params.get('id');
|
||||||
|
if (deepId) {
|
||||||
|
switchTab('history');
|
||||||
|
showHistoryDetail(deepId);
|
||||||
|
} else if (params.get('tab') === 'history') {
|
||||||
|
switchTab('history');
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
showError(err.message);
|
showError(err.message);
|
||||||
}
|
}
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
(async function init() {
|
|
||||||
await initNav('history');
|
|
||||||
const params = new URLSearchParams(window.location.search);
|
|
||||||
const id = params.get('id');
|
|
||||||
const container = document.getElementById('content');
|
|
||||||
if (!id) {
|
|
||||||
container.innerHTML = '<p class="empty">Concert introuvable.</p>';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const allSongs = await api.get('/api/songs');
|
|
||||||
|
|
||||||
const editor = createSetlistEditor({
|
|
||||||
allSongs,
|
|
||||||
getSetlist: async () => {
|
|
||||||
try {
|
|
||||||
return await api.get(`/api/setlists/${id}`);
|
|
||||||
} catch (err) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
emptyMessage: 'Concert introuvable.',
|
|
||||||
allowDelete: true,
|
|
||||||
onDeleted: () => {
|
|
||||||
window.location.href = '/history.html';
|
|
||||||
},
|
|
||||||
});
|
|
||||||
await editor.load();
|
|
||||||
})();
|
|
||||||
|
|
@ -28,9 +28,8 @@ async function initNav(activePage) {
|
||||||
<div class="nav-links" id="nav-links">
|
<div class="nav-links" id="nav-links">
|
||||||
<a href="/index.html" class="${activePage === 'repertoire' ? 'active' : ''}">Répertoire</a>
|
<a href="/index.html" class="${activePage === 'repertoire' ? 'active' : ''}">Répertoire</a>
|
||||||
<a href="/suggestions.html" class="${activePage === 'suggestions' ? 'active' : ''}">Suggestions</a>
|
<a href="/suggestions.html" class="${activePage === 'suggestions' ? 'active' : ''}">Suggestions</a>
|
||||||
<a href="/setlist.html" class="${activePage === 'setlist' ? 'active' : ''}">Prochain concert</a>
|
<a href="/concerts.html" class="${activePage === 'concerts' ? 'active' : ''}">Concerts</a>
|
||||||
<a href="/calendar.html" class="${activePage === 'calendar' ? 'active' : ''}">Disponibilités</a>
|
<a href="/calendar.html" class="${activePage === 'calendar' ? 'active' : ''}">Disponibilités</a>
|
||||||
<a href="/history.html" class="${activePage === 'history' ? 'active' : ''}">Historique</a>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="nav-user">
|
<div class="nav-user">
|
||||||
<div class="nav-profile" id="nav-profile">
|
<div class="nav-profile" id="nav-profile">
|
||||||
|
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
(async function init() {
|
|
||||||
await initNav('setlist');
|
|
||||||
const allSongs = await api.get('/api/songs');
|
|
||||||
|
|
||||||
const editor = createSetlistEditor({
|
|
||||||
allSongs,
|
|
||||||
getSetlist: () => api.get('/api/setlists/next'),
|
|
||||||
createSetlist: (data) => api.post('/api/setlists', data),
|
|
||||||
emptyMessage: 'Aucun concert à venir pour le moment.',
|
|
||||||
});
|
|
||||||
await editor.load();
|
|
||||||
})();
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// Shared setlist editor used by both "prochain concert" (setlist.js) and
|
// Shared setlist editor used by concerts.js for both the "prochain concert"
|
||||||
// "historique" (history-detail.js): choose songs from the repertoire, order
|
// tab and a past concert's detail view: choose songs from the repertoire,
|
||||||
// them, add per-song notes, mark encore songs, save. Parameterized so the
|
// order them, add per-song notes, mark encore songs, save. Parameterized so
|
||||||
// caller decides how to load/create/delete the underlying setlist.
|
// the caller decides how to load/create/delete the underlying setlist.
|
||||||
function createSetlistEditor({
|
function createSetlistEditor({
|
||||||
containerId = 'content',
|
containerId = 'content',
|
||||||
allSongs,
|
allSongs,
|
||||||
|
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
<!doctype html>
|
|
||||||
<html lang="fr">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<title>Prochain concert — Octane</title>
|
|
||||||
<script src="/js/theme-init.js"></script>
|
|
||||||
<link rel="stylesheet" href="/css/style.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<header class="app-header">
|
|
||||||
<nav id="main-nav"></nav>
|
|
||||||
</header>
|
|
||||||
<main>
|
|
||||||
<h1>Prochain concert</h1>
|
|
||||||
<div id="error"></div>
|
|
||||||
<div id="content">Chargement…</div>
|
|
||||||
</main>
|
|
||||||
|
|
||||||
<script src="/js/api.js"></script>
|
|
||||||
<script src="/js/render.js"></script>
|
|
||||||
<script src="/js/nav.js"></script>
|
|
||||||
<script src="/js/setlistEditor.js"></script>
|
|
||||||
<script src="/js/setlist.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue