Enterprise Movie Studio Hub
by LuckyFlare17761 lines26.0 KB
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Enterprise Movie Studio Hub</title>
<style>
:root {
--bg-color: #0f0f12;
--card-bg: #16161a;
--card-hover: #1f1f26;
--primary: #e50914;
--primary-hover: #b80710;
--text: #ffffff;
--text-muted: #8e8e93;
--border: #2c2c35;
--success: #2ecc71;
--danger: #e74c3c;
--warning: #f1c40f;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
font-family: 'Segoe UI', -apple-system, BlinkMacSystemFont, Roboto, sans-serif;
}
body {
background-color: var(--bg-color);
color: var(--text);
padding: 20px;
display: flex;
justify-content: center;
}
.container {
width: 100%;
max-width: 1300px;
display: grid;
grid-template-columns: 1fr;
gap: 20px;
}
@media (min-width: 992px) {
.container {
grid-template-columns: 380px 1fr;
}
}
header {
grid-column: 1 / -1;
text-align: center;
padding: 15px 0;
border-bottom: 3px solid var(--primary);
background: var(--card-bg);
border-radius: 8px;
}
header h1 {
font-size: 2.2rem;
letter-spacing: 1px;
}
header span {
color: var(--primary);
}
.stats-grid {
grid-column: 1 / -1;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 15px;
}
.stat-card {
background: var(--card-bg);
padding: 15px;
border-radius: 8px;
border: 1px solid var(--border);
text-align: center;
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
}
.stat-card .num {
font-size: 1.6rem;
font-weight: bold;
margin-top: 5px;
}
.stat-card .label {
font-size: 0.75rem;
color: var(--text-muted);
text-transform: uppercase;
letter-spacing: 0.5px;
}
.color-primary { color: var(--primary); }
.color-success { color: var(--success); }
.color-danger { color: var(--danger); }
.filter-bar {
grid-column: 1 / -1;
background: var(--card-bg);
padding: 15px;
border-radius: 8px;
border: 1px solid var(--border);
display: grid;
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
gap: 15px;
}
.form-box {
background-color: var(--card-bg);
padding: 20px;
border-radius: 8px;
border: 1px solid var(--border);
height: fit-content;
box-shadow: 0 4px 10px rgba(0,0,0,0.2);
}
.form-box h2 {
font-size: 1.3rem;
margin-bottom: 15px;
color: var(--primary);
border-bottom: 1px solid var(--border);
padding-bottom: 8px;
}
.form-grid-2 {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px;
}
.form-group {
margin-bottom: 12px;
}
label {
display: block;
font-size: 0.8rem;
margin-bottom: 4px;
color: var(--text-muted);
font-weight: 600;
}
input, select, textarea {
width: 100%;
padding: 10px;
background: #202026;
border: 1px solid var(--border);
color: white;
border-radius: 6px;
font-size: 0.9rem;
transition: border 0.2s;
}
input:focus, select:focus, textarea:focus {
outline: none;
border-color: var(--primary);
}
button.btn-submit {
width: 100%;
padding: 12px;
background: var(--primary);
color: white;
border: none;
border-radius: 6px;
font-weight: bold;
cursor: pointer;
font-size: 1rem;
margin-top: 10px;
transition: background 0.2s, transform 0.1s;
}
button.btn-submit:hover {
background: var(--primary-hover);
}
button.btn-submit:active {
transform: scale(0.98);
}
.main-content {
display: flex;
flex-direction: column;
gap: 15px;
}
.movie-list {
display: grid;
grid-template-columns: 1fr;
gap: 15px;
align-content: start;
}
@media (min-width: 1200px) {
.movie-list {
grid-template-columns: 1fr 1fr;
}
}
.movie-card {
background: var(--card-bg);
border: 1px solid var(--border);
border-radius: 8px;
padding: 18px;
position: relative;
display: flex;
flex-direction: column;
justify-content: space-between;
transition: transform 0.2s, background-color 0.2s;
}
.movie-card:hover {
background-color: var(--card-hover);
transform: translateY(-2px);
}
.delete-btn {
position: absolute;
top: 12px;
right: 15px;
background: none;
border: none;
color: var(--text-muted);
font-size: 1.4rem;
cursor: pointer;
width: auto;
margin: 0;
padding: 0;
}
.delete-btn:hover {
color: var(--primary);
}
.movie-card h3 {
font-size: 1.4rem;
margin-bottom: 5px;
padding-right: 25px;
color: #fff;
}
.movie-meta-tags {
display: flex;
flex-wrap: wrap;
gap: 5px;
margin-bottom: 12px;
}
.tag {
font-size: 0.75rem;
background: #252530;
padding: 3px 8px;
border-radius: 4px;
color: #e0e0e6;
border: 1px solid #3a3a4a;
}
.tag-fsk {
background: #34495e;
font-weight: bold;
}
.movie-card p.story-text {
font-size: 0.9rem;
line-height: 1.45;
margin-bottom: 12px;
color: #d1d1d6;
font-style: italic;
}
.movie-details-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 8px;
font-size: 0.85rem;
border-top: 1px solid var(--border);
padding-top: 10px;
margin-bottom: 12px;
color: #b0b0b5;
}
/* Szenen-Bereich im Projekt */
.scenes-section {
border-top: 1px solid var(--border);
padding-top: 12px;
margin-bottom: 12px;
}
.scenes-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
}
.scenes-header h4 {
font-size: 0.95rem;
color: var(--primary);
}
.btn-small {
background: #252530;
border: 1px solid var(--border);
color: white;
padding: 4px 8px;
border-radius: 4px;
cursor: pointer;
font-size: 0.75rem;
}
.btn-small:hover {
border-color: var(--primary);
}
.scenes-list {
display: flex;
flex-direction: column;
gap: 6px;
max-height: 150px;
overflow-y: auto;
margin-bottom: 8px;
}
.scene-item {
background: #1f1f26;
padding: 6px 10px;
border-radius: 4px;
font-size: 0.8rem;
display: flex;
justify-content: space-between;
align-items: center;
border-left: 3px solid var(--warning);
}
.scene-item.done {
border-left-color: var(--success);
}
.scene-info {
display: flex;
gap: 10px;
align-items: center;
}
.footer-row {
display: flex;
justify-content: space-between;
align-items: center;
border-top: 1px solid var(--border);
padding-top: 10px;
margin-top: auto;
}
.status-badge {
font-size: 0.75rem;
padding: 4px 10px;
border-radius: 20px;
font-weight: bold;
text-transform: uppercase;
}
.status-plan { background: #d35400; color: white; }
.status-prod { background: #2980b9; color: white; }
.status-done { background: #27ae60; color: white; }
.profit-badge {
font-size: 0.85rem;
font-weight: bold;
}
/* Modal für Szene hinzufügen */
.modal {
display: none;
position: fixed;
top: 0; left: 0; width: 100%; height: 100%;
background: rgba(0,0,0,0.7);
justify-content: center;
align-items: center;
z-index: 1000;
}
.modal-content {
background: var(--card-bg);
padding: 20px;
border-radius: 8px;
width: 100%;
max-width: 400px;
border: 1px solid var(--border);
}
</style>
</head>
<body>
<div class="container">
<header>
<h1>Enterprise <span>Movie Studio Hub</span></h1>
</header>
<!-- Dashboard Statistik -->
<div class="stats-grid">
<div class="stat-card">
<div class="label">Gesamtprojekte</div>
<div class="num" id="stat-count">0</div>
</div>
<div class="stat-card">
<div class="label">Gesamtbudget</div>
<div class="num" id="stat-budget">0 Mio. €</div>
</div>
<div class="stat-card">
<div class="label">Erwartetes Box-Office</div>
<div class="num" id="stat-revenue">0 Mio. €</div>
</div>
<div class="stat-card">
<div class="label">Netto-Bilanz (ROI)</div>
<div class="num" id="stat-profit">0 Mio. €</div>
</div>
</div>
<!-- Filter & Suche -->
<div class="filter-bar">
<div class="form-group" style="margin: 0;">
<label for="search-input">Projektsuche</label>
<input type="text" id="search-input" placeholder="Titel oder Regisseur..." oninput="filterMovies()">
</div>
<div class="form-group" style="margin: 0;">
<label for="filter-genre">Genre Filter</label>
<select id="filter-genre" onchange="filterMovies()">
<option value="all">Alle Genres</option>
<option value="Sci-Fi">Sci-Fi</option>
<option value="Action">Action</option>
<option value="Drama">Drama</option>
<option value="Komödie">Komödie</option>
<option value="Horror">Horror</option>
<option value="Thriller">Thriller</option>
<option value="Animation">Animation</option>
</select>
</div>
<div class="form-group" style="margin: 0;">
<label for="filter-status">Status Filter</label>
<select id="filter-status" onchange="filterMovies()">
<option value="all">Alle Phasen</option>
<option value="plan">In Planung</option>
<option value="prod">In Produktion</option>
<option value="done">Fertiggestellt</option>
</select>
</div>
</div>
<!-- Formular zum Erfassen -->
<div class="form-box">
<h2>Neues Projekt erfassen</h2>
<form id="movie-form">
<div class="form-group">
<label for="title">Filmtitel / Projekttitel</label>
<input type="text" id="title" required>
</div>
<div class="form-grid-2">
<div class="form-group">
<label for="genre">Genre</label>
<select id="genre">
<option value="Sci-Fi">Sci-Fi</option>
<option value="Action">Action</option>
<option value="Drama">Drama</option>
<option value="Komödie">Komödie</option>
<option value="Horror">Horror</option>
<option value="Thriller">Thriller</option>
<option value="Animation">Animation</option>
</select>
</div>
<div class="form-group">
<label for="format">Format</label>
<select id="format">
<option value="Kinofilm">Kinofilm</option>
<option value="Streaming-Serie">Streaming-Serie</option>
<option value="Dokumentation">Dokumentation</option>
</select>
</div>
</div>
<div class="form-grid-2">
<div class="form-group">
<label for="director">Regisseur / Showrunner</label>
<input type="text" id="director" required>
</div>
<div class="form-group">
<label for="fsk">FSK Freigabe</label>
<select id="fsk">
<option value="FSK 0">FSK 0</option>
<option value="FSK 6">FSK 6</option>
<option value="FSK 12">FSK 12</option>
<option value="FSK 16">FSK 16</option>
<option value="FSK 18">FSK 18</option>
</select>
</div>
</div>
<div class="form-group">
<label for="cast">Hauptbesetzung (Kommagetrennt)</label>
<input type="text" id="cast">
</div>
<div class="form-grid-2">
<div class="form-group">
<label for="budget">Budget (Mio. €)</label>
<input type="number" step="0.1" id="budget" required>
</div>
<div class="form-group">
<label for="revenue">Erw. Umsatz (Mio. €)</label>
<input type="number" step="0.1" id="revenue" required>
</div>
</div>
<div class="form-grid-2">
<div class="form-group">
<label for="release">Geplanter Start</label>
<input type="date" id="release" required>
</div>
<div class="form-group">
<label for="status">Projektstatus</label>
<select id="status">
<option value="plan">In Planung</option>
<option value="prod">In Produktion</option>
<option value="done">Fertiggestellt</option>
</select>
</div>
</div>
<div class="form-group">
<label for="story">Logline / Core Story</label>
<textarea id="story" rows="3"></textarea>
</div>
<button type="submit" class="btn-submit">Projekt einbuchen</button>
</form>
</div>
<!-- Hauptbereich / Projektliste -->
<div class="main-content">
<div id="movie-display" class="movie-list"></div>
</div>
</div>
<!-- Modal zum Hinzufügen einer Szene -->
<div id="scene-modal" class="modal">
<div class="modal-content">
<h2 style="color: var(--primary); margin-bottom: 12px; font-size: 1.1rem;">Szene aufnehmen</h2>
<form id="scene-form">
<input type="hidden" id="modal-movie-index">
<div class="form-group">
<label for="scene-num">Szenennummer / Titel</label>
<input type="text" id="scene-num" placeholder="z.B. Szene 1: Intro" required>
</div>
<div class="form-group">
<label for="scene-loc">Drehort</label>
<input type="text" id="scene-loc" placeholder="z.B. Studio A / Berlin" required>
</div>
<div class="form-group">
<label for="scene-desc">Beschreibung</label>
<textarea id="scene-desc" rows="2" placeholder="Was passiert in der Szene?"></textarea>
</div>
<div class="form-group">
<label for="scene-status">Status</label>
<select id="scene-status">
<option value="Geplant">Geplant</option>
<option value="Gedreht">Gedreht</option>
</select>
</div>
<div style="display: flex; gap: 10px; margin-top: 15px;">
<button type="button" class="btn-small" style="flex:1; padding: 8px;" onclick="closeSceneModal()">Abbrechen</button>
<button type="submit" class="btn-submit" style="flex:1; margin-top:0;">Speichern</button>
</div>
</form>
</div>
</div>
<script>
let movies = JSON.parse(localStorage.getItem('enterprise_studio_movies')) || [];
const movieForm = document.getElementById('movie-form');
const movieDisplay = document.getElementById('movie-display');
const sceneModal = document.getElementById('scene-modal');
const sceneForm = document.getElementById('scene-form');
function updateApp() {
localStorage.setItem('enterprise_studio_movies', JSON.stringify(movies));
filterMovies();
calculateDashboard();
}
function calculateDashboard() {
const count = movies.length;
const totalBudget = movies.reduce((sum, m) => sum + parseFloat(m.budget || 0), 0);
const totalRevenue = movies.reduce((sum, m) => sum + parseFloat(m.revenue || 0), 0);
const netProfit = totalRevenue - totalBudget;
document.getElementById('stat-count').textContent = count;
document.getElementById('stat-budget').textContent = totalBudget.toFixed(1) + ' Mio. €';
document.getElementById('stat-revenue').textContent = totalRevenue.toFixed(1) + ' Mio. €';
const profitElement = document.getElementById('stat-profit');
profitElement.textContent = (netProfit >= 0 ? '+' : '') + netProfit.toFixed(1) + ' Mio. €';
profitElement.className = 'num ' + (netProfit >= 0 ? 'color-success' : 'color-danger');
}
function filterMovies() {
const searchQuery = document.getElementById('search-input').value.toLowerCase();
const genreFilter = document.getElementById('filter-genre').value;
const statusFilter = document.getElementById('filter-status').value;
movieDisplay.innerHTML = '';
const filtered = movies.filter(movie => {
const matchesSearch = movie.title.toLowerCase().includes(searchQuery) ||
movie.director.toLowerCase().includes(searchQuery);
const matchesGenre = genreFilter === 'all' || movie.genre === genreFilter;
const matchesStatus = statusFilter === 'all' || movie.status === statusFilter;
return matchesSearch && matchesGenre && matchesStatus;
});
if (filtered.length === 0) {
movieDisplay.innerHTML = '<p style="color: var(--text-muted); grid-column: 1/-1; text-align: center; padding: 20px;">Keine Filmprojekte gefunden, die den Filtern entsprechen.</p>';
return;
}
filtered.forEach((movie) => {
const realIndex = movies.indexOf(movie);
const card = document.createElement('div');
card.className = 'movie-card';
let statusText = 'In Planung';
let statusClass = 'status-plan';
if(movie.status === 'prod') { statusText = 'In Produktion'; statusClass = 'status-prod'; }
if(movie.status === 'done') { statusText = 'Fertiggestellt'; statusClass = 'status-done'; }
const singleProfit = parseFloat(movie.revenue) - parseFloat(movie.budget);
const profitClass = singleProfit >= 0 ? 'color-success' : 'color-danger';
const dateFormatted = movie.release ? new Date(movie.release).toLocaleDateString('de-DE', {
year: 'numeric', month: '2-digit', day: '2-digit'
}) : 'Unbekannt';
// Szenen HTML generieren
let scenesHtml = '';
if (movie.scenes && movie.scenes.length > 0) {
movie.scenes.forEach((scene, sIdx) => {
const isDone = scene.status === 'Gedreht';
scenesHtml += `
<div class="scene-item ${isDone ? 'done' : ''}">
<div class="scene-info">
<strong>${scene.number}</strong>
<span style="color: var(--text-muted);">(${scene.location})</span>
</div>
<div style="display: flex; gap: 8px; align-items: center;">
<span style="font-size: 0.75rem; color: ${isDone ? 'var(--success)' : 'var(--warning)'};">${scene.status}</span>
<button class="btn-small" onclick="deleteScene(${realIndex}, ${sIdx})" title="Szene löschen">×</button>
</div>
</div>
`;
});
} else {
scenesHtml = '<p style="font-size: 0.8rem; color: var(--text-muted); text-align: center; padding: 5px;">Keine Szenen erfasst.</p>';
}
card.innerHTML = `
<button class="delete-btn" onclick="deleteMovie(${realIndex})" title="Projekt löschen">×</button>
<div>
<h3>${movie.title}</h3>
<div class="movie-meta-tags">
<span class="tag">${movie.format}</span>
<span class="tag">${movie.genre}</span>
<span class="tag tag-fsk">${movie.fsk}</span>
</div>
<p class="story-text">"${movie.story || 'Keine Logline vorhanden.'}"</p>
<div class="movie-details-grid">
<div><strong>Regie:</strong> ${movie.director}</div>
<div><strong>Start:</strong> ${dateFormatted}</div>
<div style="grid-column: 1 / -1;"><strong>Cast:</strong> ${movie.cast || 'Keine Angaben'}</div>
</div>
<div class="scenes-section">
<div class="scenes-header">
<h4>Szenen (${movie.scenes ? movie.scenes.length : 0})</h4>
<button class="btn-small" onclick="openSceneModal(${realIndex})">+ Szene hinzufügen</button>
</div>
<div class="scenes-list">
${scenesHtml}
</div>
</div>
</div>
<div class="footer-row">
<span class="status-badge ${statusClass}">${statusText}</span>
<span class="profit-badge ${profitClass}">Bilanz: ${singleProfit >= 0 ? '+' : ''}${singleProfit.toFixed(1)} Mio. €</span>
</div>
`;
movieDisplay.appendChild(card);
});
}
movieForm.addEventListener('submit', function(e) {
e.preventDefault();
const newMovie = {
title: document.getElementById('title').value,
genre: document.getElementById('genre').value,
format: document.getElementById('format').value,
director: document.getElementById('director').value,
fsk: document.getElementById('fsk').value,
cast: document.getElementById('cast').value,
budget: document.getElementById('budget').value,
revenue: document.getElementById('revenue').value,
release: document.getElementById('release').value,
status: document.getElementById('status').value,
story: document.getElementById('story').value,
scenes: [] // Initial leeres Array für Szenen
};
movies.push(newMovie);
updateApp();
movieForm.reset();
});
function deleteMovie(index) {
if(confirm('Möchtest du dieses Filmprojekt wirklich unwiderruflich löschen?')) {
movies.splice(index, 1);
updateApp();
}
}
// Szenen Management Funktionen
function openSceneModal(movieIndex) {
document.getElementById('modal-movie-index').value = movieIndex;
sceneModal.style.display = 'flex';
}
function closeSceneModal() {
sceneModal.style.display = 'none';
sceneForm.reset();
}
sceneForm.addEventListener('submit', function(e) {
e.preventDefault();
const mIndex = document.getElementById('modal-movie-index').value;
const newScene = {
number: document.getElementById('scene-num').value,
location: document.getElementById('scene-loc').value,
description: document.getElementById('scene-desc').value,
status: document.getElementById('scene-status').value
};
if (!movies[mIndex].scenes) {
movies[mIndex].scenes = [];
}
movies[mIndex].scenes.push(newScene);
updateApp();
closeSceneModal();
});
function deleteScene(movieIndex, sceneIndex) {
movies[movieIndex].scenes.splice(sceneIndex, 1);
updateApp();
}
updateApp();
</script>
</body>
</html>Game Source: Enterprise Movie Studio Hub
Creator: LuckyFlare17
Libraries: none
Complexity: complex (761 lines, 26.0 KB)
The full source code is displayed above on this page.
Remix Instructions
To remix this game, copy the source code above and modify it. Add a ARCADELAB header at the top with "remix_of: enterprise-movie-studio-hub-luckyflare17" to link back to the original. Then publish at arcadelab.ai/publish.