Spaces:
Running
Running
File size: 10,207 Bytes
044250c 3951d02 044250c 3951d02 044250c |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Admin - Mr.FLEN</title>
<link rel="icon" type="image/x-icon" href="/static/favicon.ico">
<link rel="stylesheet" href="style.css">
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
<script src="https://unpkg.com/feather-icons"></script>
<script>
tailwind.config = {
theme: {
extend: {
colors: {
primary: '#0B2D2F',
accent: '#FF914D',
magenta: '#C5427A',
paper: '#0A0F10'
}
}
}
}
</script>
</head>
<body class="bg-paper text-white min-h-screen flex flex-col">
<custom-navbar></custom-navbar>
<main class="flex-1 py-12 px-4">
<div class="max-w-6xl mx-auto">
<!-- Admin Header -->
<div class="text-center mb-12">
<h1 class="text-4xl md:text-5xl font-bold mb-4">
<span class="bg-gradient-to-r from-accent to-magenta bg-clip-text text-transparent">
EMBEDS MANAGER
</span>
</h1>
<p class="text-lg text-gray-400 max-w-2xl mx-auto">
Manage track embeds and export configuration
</p>
</div>
<!-- Security Check -->
<div id="securityCheck" class="max-w-md mx-auto bg-primary/20 rounded-2xl p-8 backdrop-blur-sm border border-accent/20">
<h3 class="text-xl font-semibold mb-4">Admin Access</h3>
<p class="text-gray-400 mb-4">Enter PIN to access embeds manager</p>
<input type="password" id="adminPin"
placeholder="Enter 6-digit PIN"
class="w-full bg-primary/10 border border-accent/20 rounded-full py-3 px-6 mb-4 focus:border-accent focus:outline-none transition-all duration-300">
<button onclick="checkAdminAccess()"
class="w-full bg-accent hover:bg-accent/80 text-paper font-bold py-3 px-8 rounded-full transition-all duration-300">
Access Admin
</button>
</div>
</div>
</div>
<!-- Embeds Manager (Hidden by default) -->
<div id="embedsManager" class="hidden">
<!-- Export Controls -->
<div class="flex justify-between items-center mb-8">
<h2 class="text-2xl font-bold">Track Embeds</h2>
<div class="flex gap-4">
<button onclick="exportAlbumData()"
class="flex items-center gap-2 bg-green-500 hover:bg-green-600 text-white font-bold py-2 px-4 rounded-full transition-all duration-300">
<i data-feather="download" class="w-4 h-4"></i>
Export JSON
</button>
<button onclick="resetAlbumData()"
class="flex items-center gap-2 bg-red-500 hover:bg-red-600 text-white font-bold py-2 px-4 rounded-full transition-all duration-300">
<i data-feather="refresh-cw" class="w-4 h-4"></i>
Reset Data
</button>
</div>
</div>
<!-- Tracks List -->
<div id="tracksAdminList" class="space-y-6">
<!-- Tracks will be populated by JavaScript -->
</div>
</div>
</div>
</main>
<custom-footer></custom-footer>
<script src="components/navbar.js"></script>
<script src="components/footer.js"></script>
<script src="script.js"></script>
<script>
feather.replace();
document.addEventListener('DOMContentLoaded', function() {
// Check if already authenticated
if (localStorage.getItem('mrflen_admin_auth') === 'true') {
showEmbedsManager();
}
});
function checkAdminAccess() {
const pinInput = document.getElementById('adminPin');
const enteredPin = pinInput.value;
// For MVP, use a simple PIN (in production, use environment variable)
const adminPin = '123456'; // Should be from environment variable
if (enteredPin === adminPin) {
localStorage.setItem('mrflen_admin_auth', 'true');
showEmbedsManager();
} else {
alert('Invalid PIN. Please try again.');
}
}
function showEmbedsManager() {
document.getElementById('securityCheck').classList.add('hidden');
document.getElementById('embedsManager').classList.remove('hidden');
loadAdminTracks();
}
function loadAdminTracks() {
const container = document.getElementById('tracksAdminList');
if (!container) return;
container.innerHTML = albumData.tracks.map(track => `
<div class="bg-primary/20 rounded-2xl p-6 backdrop-blur-sm border border-accent/20">
<div class="flex items-start justify-between mb-4">
<h3 class="text-xl font-semibold">${track.no}. ${track.title}</h3>
<span class="text-sm ${track.embeds && track.embeds.length > 0 ? 'text-green-400' : 'text-red-400'}">
${track.embeds && track.embeds.length > 0 ? `${track.embeds.length} embed(s)` : 'No embeds'}</span>
</div>
<!-- Embeds List for this track -->
<div id="embeds-${track.slug}" class="space-y-4 mb-4">
${track.embeds ? track.embeds.map((embed, index) => `
<div class="bg-primary/10 rounded-xl p-4">
<div class="flex items-center gap-4 mb-2">
<select class="provider-select bg-primary/20 border border-accent/20 rounded-full py-2 px-4 focus:border-accent focus:outline-none transition-all duration-300"
onchange="updateEmbedProvider('${track.slug}', ${index}, this.value)">
<option value="soundcloud" ${embed.provider === 'soundcloud' ? 'selected' : ''}>SoundCloud</option>
<option value="spotify" ${embed.provider === 'spotify' ? 'selected' : ''}>Spotify</option>
<option value="youtube" ${embed.provider === 'youtube' ? 'selected' : ''}>YouTube</option>
<option value="bandcamp" ${embed.provider === 'bandcamp' ? 'selected' : ''}>Bandcamp</option>
</select>
<input type="text"
value="${embed.url}"
placeholder="Embed URL"
class="flex-1 bg-primary/20 border border-accent/20 rounded-full py-2 px-4 focus:border-accent focus:outline-none transition-all duration-300"
oninput="updateEmbedUrl('${track.slug}', ${index}, this.value)"
class="w-full">
</div>
<div class="aspect-video rounded-lg bg-primary/10 border border-accent/20">
<iframe src="${embed.url}" class="w-full h-full rounded-lg" loading="lazy" allow="autoplay"></iframe>
</div>
`).join('') : '<p class="text-gray-400 text-sm">No embeds configured</p>'}
</div>
<!-- Add New Embed Button -->
<button onclick="addNewEmbed('${track.slug}')"
class="w-full border border-dashed border-accent/30 hover:border-accent/50 text-accent font-medium py-3 rounded-xl transition-all duration-300">
<i data-feather="plus" class="w-4 h-4 inline mr-2"></i>
Add Embed
</button>
</div>
</div>
`).join('');
feather.replace();
}
function updateEmbedProvider(trackSlug, embedIndex, newProvider) {
const track = albumData.tracks.find(t => t.slug === trackSlug);
if (track && track.embeds[embedIndex]) {
track.embeds[embedIndex].provider = newProvider;
saveAlbumData();
loadAdminTracks(); // Refresh to show updated preview
}
function updateEmbedUrl(trackSlug, embedIndex, newUrl) {
const track = albumData.tracks.find(t => t.slug === trackSlug);
if (track && track.embeds[embedIndex]) {
track.embeds[embedIndex].url = newUrl;
saveAlbumData();
loadAdminTracks(); // Refresh to show updated preview
}
function addNewEmbed(trackSlug) {
const track = albumData.tracks.find(t => t.slug === trackSlug);
if (track) {
if (!track.embeds) track.embeds = [];
track.embeds.push({
provider: 'soundcloud',
url: ''
});
saveAlbumData();
loadAdminTracks();
}
}
function resetAlbumData() {
if (confirm('Are you sure you want to reset all album data? This cannot be undone.')) {
localStorage.removeItem('mrflen_album_data');
window.location.reload();
}
}
</script>
</body>
</html> |