Compare commits
No commits in common. "ai-dev" and "master" have entirely different histories.
@ -1,9 +0,0 @@
|
|||||||
<?php
|
|
||||||
require_once __DIR__ . '/../auth.php';
|
|
||||||
|
|
||||||
// Role-based access control
|
|
||||||
if (!isset($_SESSION['role']) || !in_array($_SESSION['role'], ['admin', 'super_admin'])) {
|
|
||||||
// If the user is not an admin, show an error and stop execution.
|
|
||||||
http_response_code(403);
|
|
||||||
die("Forbidden: You do not have permission to access this page.");
|
|
||||||
}
|
|
||||||
@ -1,170 +0,0 @@
|
|||||||
<?php
|
|
||||||
// admin/monitoring.php
|
|
||||||
require_once '../auth.php'; // Ensure user is authenticated and is an admin
|
|
||||||
require_once '../db/config.php'; // Database connection
|
|
||||||
|
|
||||||
// Restrict access to admins
|
|
||||||
if (!isset($_SESSION['role']) || !in_array($_SESSION['role'], ['admin', 'super_admin'])) {
|
|
||||||
header("Location: /index.php");
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
$pageTitle = "Music Monitoring";
|
|
||||||
$message = '';
|
|
||||||
|
|
||||||
if (isset($_POST['upload_csv'])) {
|
|
||||||
if (isset($_FILES['csv_file']) && $_FILES['csv_file']['error'] == 0) {
|
|
||||||
$fileName = $_FILES['csv_file']['tmp_name'];
|
|
||||||
$file = fopen($fileName, "r");
|
|
||||||
|
|
||||||
// Skip the header row
|
|
||||||
fgetcsv($file);
|
|
||||||
|
|
||||||
$stmt = db()->prepare("INSERT INTO monitoring_data (track_id, plays, date) VALUES (?, ?, ?)");
|
|
||||||
|
|
||||||
while (($column = fgetcsv($file, 10000, ",")) !== FALSE) {
|
|
||||||
$track_id = $column[0];
|
|
||||||
$plays = $column[1];
|
|
||||||
$date = $column[2];
|
|
||||||
|
|
||||||
$stmt->execute([$track_id, $plays, $date]);
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose($file);
|
|
||||||
$message = "<div class='alert alert-success'>CSV file has been successfully uploaded and processed.</div>";
|
|
||||||
} else {
|
|
||||||
$message = "<div class='alert alert-danger'>Error uploading file.</div>";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch monitoring data
|
|
||||||
$stmt = db()->query("
|
|
||||||
SELECT t.title, md.plays, md.date
|
|
||||||
FROM monitoring_data md
|
|
||||||
JOIN tracks t ON md.track_id = t.id
|
|
||||||
ORDER BY md.date DESC
|
|
||||||
");
|
|
||||||
$monitoring_data = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
||||||
|
|
||||||
// Prepare data for the chart
|
|
||||||
$chart_labels = [];
|
|
||||||
$chart_data = [];
|
|
||||||
foreach ($monitoring_data as $data) {
|
|
||||||
$chart_labels[] = $data['title'];
|
|
||||||
$chart_data[] = $data['plays'];
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title><?php echo $pageTitle; ?> - Zeal Music</title>
|
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
|
|
||||||
<link rel="stylesheet" href="/assets/css/custom.css?v=<?php echo time(); ?>">
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="dashboard-container">
|
|
||||||
<?php include '../partials/sidebar.php'; ?>
|
|
||||||
<main class="main-content">
|
|
||||||
<header class="page-header">
|
|
||||||
<h1><?php echo $pageTitle; ?></h1>
|
|
||||||
<div class="user-info">
|
|
||||||
<p>Welcome, <?php echo htmlspecialchars($_SESSION['username']); ?></p>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<section class="content-section">
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-header">
|
|
||||||
<h2>Upload CSV for Music Monitoring</h2>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<?php echo $message; ?>
|
|
||||||
<p>Select a CSV file containing music monitoring data to upload. The file should contain columns for Track ID, Play Count, and Date.</p>
|
|
||||||
<form action="monitoring.php" method="post" enctype="multipart/form-data" class="upload-form">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="csv_file">CSV File</label>
|
|
||||||
<input type="file" name="csv_file" id="csv_file" accept=".csv" required>
|
|
||||||
</div>
|
|
||||||
<button type="submit" name="upload_csv" class="btn btn-primary">Upload CSV</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section class="content-section">
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-header">
|
|
||||||
<h2>Monitoring Data Overview</h2>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<canvas id="monitoringChart"></canvas>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section class="content-section">
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-header">
|
|
||||||
<h2>Raw Monitoring Data</h2>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<table class="data-table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Track Title</th>
|
|
||||||
<th>Plays</th>
|
|
||||||
<th>Date</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php if (empty($monitoring_data)): ?>
|
|
||||||
<tr>
|
|
||||||
<td colspan="3">No monitoring data found.</td>
|
|
||||||
</tr>
|
|
||||||
<?php else: ?>
|
|
||||||
<?php foreach ($monitoring_data as $data): ?>
|
|
||||||
<tr>
|
|
||||||
<td><?php echo htmlspecialchars($data['title']); ?></td>
|
|
||||||
<td><?php echo htmlspecialchars($data['plays']); ?></td>
|
|
||||||
<td><?php echo htmlspecialchars($data['date']); ?></td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
<?php endif; ?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
<script src="/assets/js/main.js?v=<?php echo time(); ?>"></script>
|
|
||||||
<script>
|
|
||||||
const ctx = document.getElementById('monitoringChart').getContext('2d');
|
|
||||||
new Chart(ctx, {
|
|
||||||
type: 'bar',
|
|
||||||
data: {
|
|
||||||
labels: <?php echo json_encode($chart_labels); ?>,
|
|
||||||
datasets: [{
|
|
||||||
label: '# of Plays',
|
|
||||||
data: <?php echo json_encode($chart_data); ?>,
|
|
||||||
backgroundColor: 'rgba(75, 192, 192, 0.2)',
|
|
||||||
borderColor: 'rgba(75, 192, 192, 1)',
|
|
||||||
borderWidth: 1
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
scales: {
|
|
||||||
y: {
|
|
||||||
beginAtZero: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,122 +0,0 @@
|
|||||||
<?php
|
|
||||||
require_once '../auth.php';
|
|
||||||
require_once '../db/config.php';
|
|
||||||
|
|
||||||
// Only admins can access this page
|
|
||||||
if (!isset($_SESSION['role']) || !in_array($_SESSION['role'], ['admin', 'super_admin'])) {
|
|
||||||
header('Location: /login.php');
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
$pageTitle = "Manage Packages";
|
|
||||||
|
|
||||||
// Handle form submissions
|
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
||||||
if (isset($_POST['create_package'])) {
|
|
||||||
$name = $_POST['name'];
|
|
||||||
$price = $_POST['price'];
|
|
||||||
$features = $_POST['features'];
|
|
||||||
$is_recommended = isset($_POST['is_recommended']) ? 1 : 0;
|
|
||||||
|
|
||||||
$stmt = db()->prepare("INSERT INTO packages (name, price, features, is_recommended) VALUES (?, ?, ?, ?)");
|
|
||||||
$stmt->execute([$name, $price, $features, $is_recommended]);
|
|
||||||
} elseif (isset($_POST['update_package'])) {
|
|
||||||
$id = $_POST['id'];
|
|
||||||
$name = $_POST['name'];
|
|
||||||
$price = $_POST['price'];
|
|
||||||
$features = $_POST['features'];
|
|
||||||
$is_recommended = isset($_POST['is_recommended']) ? 1 : 0;
|
|
||||||
|
|
||||||
$stmt = db()->prepare("UPDATE packages SET name = ?, price = ?, features = ?, is_recommended = ? WHERE id = ?");
|
|
||||||
$stmt->execute([$name, $price, $features, $is_recommended, $id]);
|
|
||||||
} elseif (isset($_POST['delete_package'])) {
|
|
||||||
$id = $_POST['id'];
|
|
||||||
$stmt = db()->prepare("DELETE FROM packages WHERE id = ?");
|
|
||||||
$stmt->execute([$id]);
|
|
||||||
}
|
|
||||||
header('Location: packages.php');
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch all packages
|
|
||||||
$stmt = db()->query("SELECT * FROM packages ORDER BY price");
|
|
||||||
$packages = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
||||||
|
|
||||||
?>
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title><?php echo htmlspecialchars($pageTitle); ?></title>
|
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
|
||||||
<link rel="stylesheet" href="../assets/css/custom.css?v=<?php echo time(); ?>">
|
|
||||||
</head>
|
|
||||||
<body class="dark-theme">
|
|
||||||
<div class="page-container">
|
|
||||||
<?php include '../partials/sidebar.php'; ?>
|
|
||||||
<main class="main-content">
|
|
||||||
<header class="main-header">
|
|
||||||
<h1><?php echo htmlspecialchars($pageTitle); ?></h1>
|
|
||||||
</header>
|
|
||||||
<div class="content-wrapper">
|
|
||||||
<div class="content-card">
|
|
||||||
<h2>Add New Package</h2>
|
|
||||||
<form action="packages.php" method="POST" class="upload-form">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="name">Package Name</label>
|
|
||||||
<input type="text" id="name" name="name" required>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="price">Price</label>
|
|
||||||
<input type="number" step="0.01" id="price" name="price" required>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="features">Features (comma-separated)</label>
|
|
||||||
<input type="text" id="features" name="features" required>
|
|
||||||
</div>
|
|
||||||
<div class="form-group-checkbox">
|
|
||||||
<input type="checkbox" id="is_recommended" name="is_recommended">
|
|
||||||
<label for="is_recommended">Recommend this package</label>
|
|
||||||
</div>
|
|
||||||
<button type="submit" name="create_package" class="btn btn-primary">Create Package</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="content-card mt-4">
|
|
||||||
<h2>Existing Packages</h2>
|
|
||||||
<div class="table-responsive">
|
|
||||||
<table class="table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Name</th>
|
|
||||||
<th>Price</th>
|
|
||||||
<th>Features</th>
|
|
||||||
<th>Recommended</th>
|
|
||||||
<th>Actions</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php foreach ($packages as $package): ?>
|
|
||||||
<tr>
|
|
||||||
<td><?php echo htmlspecialchars($package['name']); ?></td>
|
|
||||||
<td>$<?php echo htmlspecialchars($package['price']); ?></td>
|
|
||||||
<td><?php echo htmlspecialchars($package['features']); ?></td>
|
|
||||||
<td><?php echo $package['is_recommended'] ? 'Yes' : 'No'; ?></td>
|
|
||||||
<td>
|
|
||||||
<form action="packages.php" method="POST" style="display:inline;">
|
|
||||||
<input type="hidden" name="id" value="<?php echo $package['id']; ?>">
|
|
||||||
<button type="submit" name="delete_package" class="btn btn-danger">Delete</button>
|
|
||||||
</form>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,151 +0,0 @@
|
|||||||
<?php
|
|
||||||
require_once __DIR__ . '/../db/config.php';
|
|
||||||
require_once __DIR__ . '/../auth.php'; // General login check
|
|
||||||
|
|
||||||
// Role-based access control
|
|
||||||
if (!isset($_SESSION['role']) || !in_array($_SESSION['role'], ['admin', 'super_admin'])) {
|
|
||||||
http_response_code(403);
|
|
||||||
die("Forbidden: You do not have permission to access this page.");
|
|
||||||
}
|
|
||||||
|
|
||||||
$pageTitle = "Manage Stations - Zeal Music";
|
|
||||||
$pdo = db();
|
|
||||||
$stations = [];
|
|
||||||
$errors = [];
|
|
||||||
$successMessage = '';
|
|
||||||
|
|
||||||
// Handle POST requests (add/update/delete)
|
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
||||||
$action = $_POST['action'] ?? '';
|
|
||||||
|
|
||||||
try {
|
|
||||||
if ($action === 'add') {
|
|
||||||
$name = trim($_POST['name']);
|
|
||||||
$email = trim($_POST['contact_email']);
|
|
||||||
if (!empty($name) && filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
|
||||||
$stmt = $pdo->prepare("INSERT INTO stations (name, contact_email, genre_focus, website) VALUES (?, ?, ?, ?)");
|
|
||||||
$stmt->execute([$name, $email, $_POST['genre_focus'], $_POST['website']]);
|
|
||||||
$successMessage = "Station added successfully.";
|
|
||||||
} else {
|
|
||||||
$errors[] = "Invalid name or email for new station.";
|
|
||||||
}
|
|
||||||
} elseif ($action === 'delete') {
|
|
||||||
$id = filter_input(INPUT_POST, 'id', FILTER_VALIDATE_INT);
|
|
||||||
if ($id) {
|
|
||||||
$stmt = $pdo->prepare("DELETE FROM stations WHERE id = ?");
|
|
||||||
$stmt->execute([$id]);
|
|
||||||
$successMessage = "Station deleted successfully.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (PDOException $e) {
|
|
||||||
$errors[] = "Database error: " . $e->getMessage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch all stations for display
|
|
||||||
try {
|
|
||||||
$stmt = $pdo->query("SELECT * FROM stations ORDER BY name");
|
|
||||||
$stations = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
||||||
} catch (PDOException $e) {
|
|
||||||
$errors[] = "Error fetching stations: " . $e->getMessage();
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title><?php echo htmlspecialchars($pageTitle); ?></title>
|
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
|
||||||
<link rel="stylesheet" href="../assets/css/custom.css?v=<?php echo time(); ?>">
|
|
||||||
</head>
|
|
||||||
<body class="dark-theme">
|
|
||||||
<div class="page-container">
|
|
||||||
<!-- Sidebar -->
|
|
||||||
<?php include __DIR__ . '/../partials/sidebar.php'; ?>
|
|
||||||
|
|
||||||
<!-- Main Content -->
|
|
||||||
<main class="main-content">
|
|
||||||
<header class="main-header">
|
|
||||||
<h1>Manage Radio Stations</h1>
|
|
||||||
<div class="user-profile">
|
|
||||||
<i class="fa fa-user-shield"></i>
|
|
||||||
<span><?php echo htmlspecialchars($_SESSION['username']); ?> (Admin)</span>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<div class="content-wrapper">
|
|
||||||
<?php if ($successMessage) echo "<div class='alert alert-success'>".htmlspecialchars($successMessage)."</div>"; ?>
|
|
||||||
<?php foreach ($errors as $error) echo "<div class='alert alert-danger'>".htmlspecialchars($error)."</div>"; ?>
|
|
||||||
|
|
||||||
<!-- Add Station Form -->
|
|
||||||
<div class="content-card mb-4">
|
|
||||||
<h2>Add New Station</h2>
|
|
||||||
<form action="stations.php" method="POST" class="upload-form" style="max-width: none;">
|
|
||||||
<input type="hidden" name="action" value="add">
|
|
||||||
<div style="display: flex; gap: 1rem; align-items: flex-end;">
|
|
||||||
<div class="form-group" style="flex: 2;">
|
|
||||||
<label for="name">Station Name</label>
|
|
||||||
<input type="text" name="name" required>
|
|
||||||
</div>
|
|
||||||
<div class="form-group" style="flex: 2;">
|
|
||||||
<label for="contact_email">Contact Email</label>
|
|
||||||
<input type="email" name="contact_email" required>
|
|
||||||
</div>
|
|
||||||
<div class="form-group" style="flex: 1;">
|
|
||||||
<label for="genre_focus">Genres</label>
|
|
||||||
<input type="text" name="genre_focus">
|
|
||||||
</div>
|
|
||||||
<div class="form-group" style="flex: 1;">
|
|
||||||
<label for="website">Website</label>
|
|
||||||
<input type="text" name="website">
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<button type="submit" class="btn btn-primary">Add Station</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Stations List -->
|
|
||||||
<div class="content-card">
|
|
||||||
<h2>Existing Stations</h2>
|
|
||||||
<table style="width: 100%;">
|
|
||||||
<thead>
|
|
||||||
<tr style="text-align: left; border-bottom: 1px solid #404040;">
|
|
||||||
<th style="padding: 10px;">Name</th>
|
|
||||||
<th style="padding: 10px;">Email</th>
|
|
||||||
<th style="padding: 10px;">Genres</th>
|
|
||||||
<th style="padding: 10px;">Website</th>
|
|
||||||
<th style="padding: 10px;">Actions</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php if (empty($stations)): ?>
|
|
||||||
<tr><td colspan="5" style="padding: 20px; text-align: center; color: #b3b3b3;">No stations found.</td></tr>
|
|
||||||
<?php else: ?>
|
|
||||||
<?php foreach ($stations as $station): ?>
|
|
||||||
<tr style="border-bottom: 1px solid #282828;">
|
|
||||||
<td style="padding: 10px;"><?= htmlspecialchars($station['name']) ?></td>
|
|
||||||
<td style="padding: 10px;"><?= htmlspecialchars($station['contact_email']) ?></td>
|
|
||||||
<td style="padding: 10px;"><?= htmlspecialchars($station['genre_focus']) ?></td>
|
|
||||||
<td style="padding: 10px;"><a href="<?= htmlspecialchars($station['website']) ?>" target="_blank"><?= htmlspecialchars($station['website']) ?></a></td>
|
|
||||||
<td style="padding: 10px;">
|
|
||||||
<form action="stations.php" method="POST" onsubmit="return confirm('Are you sure you want to delete this station?');" style="display: inline;">
|
|
||||||
<input type="hidden" name="action" value="delete">
|
|
||||||
<input type="hidden" name="id" value="<?= $station['id'] ?>">
|
|
||||||
<button type="submit" class="btn" style="background: none; color: #e76f51;"><i class="fa fa-trash"></i></button>
|
|
||||||
</form>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
<?php endif; ?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
157
admin/users.php
157
admin/users.php
@ -1,157 +0,0 @@
|
|||||||
<?php
|
|
||||||
require_once __DIR__ . '/../db/config.php';
|
|
||||||
require_once __DIR__ . '/../auth.php'; // General login check
|
|
||||||
|
|
||||||
// Role-based access control
|
|
||||||
if (!isset($_SESSION['role']) || !in_array($_SESSION['role'], ['admin', 'super_admin'])) {
|
|
||||||
http_response_code(403);
|
|
||||||
die("Forbidden: You do not have permission to access this page.");
|
|
||||||
}
|
|
||||||
|
|
||||||
$pageTitle = "Manage Users - Zeal Music";
|
|
||||||
$pdo = db();
|
|
||||||
$users = [];
|
|
||||||
$errors = [];
|
|
||||||
$successMessage = '';
|
|
||||||
|
|
||||||
// Handle POST requests (add/update/delete)
|
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
||||||
$action = $_POST['action'] ?? '';
|
|
||||||
|
|
||||||
try {
|
|
||||||
if ($action === 'add') {
|
|
||||||
$username = trim($_POST['username']);
|
|
||||||
$email = trim($_POST['email']);
|
|
||||||
$password = $_POST['password'];
|
|
||||||
$role = $_POST['role'];
|
|
||||||
|
|
||||||
if (!empty($username) && filter_var($email, FILTER_VALIDATE_EMAIL) && !empty($password)) {
|
|
||||||
$hashedPassword = password_hash($password, PASSWORD_DEFAULT);
|
|
||||||
$stmt = $pdo->prepare("INSERT INTO users (username, email, password, role) VALUES (?, ?, ?, ?)");
|
|
||||||
$stmt->execute([$username, $email, $hashedPassword, $role]);
|
|
||||||
$successMessage = "User added successfully.";
|
|
||||||
} else {
|
|
||||||
$errors[] = "Invalid username, email, or password for new user.";
|
|
||||||
}
|
|
||||||
} elseif ($action === 'delete') {
|
|
||||||
$id = filter_input(INPUT_POST, 'id', FILTER_VALIDATE_INT);
|
|
||||||
if ($id) {
|
|
||||||
$stmt = $pdo->prepare("DELETE FROM users WHERE id = ?");
|
|
||||||
$stmt->execute([$id]);
|
|
||||||
$successMessage = "User deleted successfully.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (PDOException $e) {
|
|
||||||
$errors[] = "Database error: " . $e->getMessage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch all users for display
|
|
||||||
try {
|
|
||||||
$stmt = $pdo->query("SELECT id, username, email, role FROM users ORDER BY username");
|
|
||||||
$users = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
||||||
} catch (PDOException $e) {
|
|
||||||
$errors[] = "Error fetching users: " . $e->getMessage();
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title><?php echo htmlspecialchars($pageTitle); ?></title>
|
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
|
||||||
<link rel="stylesheet" href="../assets/css/custom.css?v=<?php echo time(); ?>">
|
|
||||||
</head>
|
|
||||||
<body class="dark-theme">
|
|
||||||
<div class="page-container">
|
|
||||||
<!-- Sidebar -->
|
|
||||||
<?php include __DIR__ . '/../partials/sidebar.php'; ?>
|
|
||||||
|
|
||||||
<!-- Main Content -->
|
|
||||||
<main class="main-content">
|
|
||||||
<header class="main-header">
|
|
||||||
<h1>Manage Users</h1>
|
|
||||||
<div class="user-profile">
|
|
||||||
<i class="fa fa-user-shield"></i>
|
|
||||||
<span><?php echo htmlspecialchars($_SESSION['username']); ?> (Admin)</span>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<div class="content-wrapper">
|
|
||||||
<?php if ($successMessage) echo "<div class='alert alert-success'>".htmlspecialchars($successMessage)."</div>"; ?>
|
|
||||||
<?php foreach ($errors as $error) echo "<div class='alert alert-danger'>".htmlspecialchars($error)."</div>"; ?>
|
|
||||||
|
|
||||||
<!-- Add User Form -->
|
|
||||||
<div class="content-card mb-4">
|
|
||||||
<h2>Add New User</h2>
|
|
||||||
<form action="users.php" method="POST" class="upload-form" style="max-width: none;">
|
|
||||||
<input type="hidden" name="action" value="add">
|
|
||||||
<div style="display: flex; gap: 1rem; align-items: flex-end;">
|
|
||||||
<div class="form-group" style="flex: 1;">
|
|
||||||
<label for="username">Username</label>
|
|
||||||
<input type="text" name="username" required>
|
|
||||||
</div>
|
|
||||||
<div class="form-group" style="flex: 2;">
|
|
||||||
<label for="email">Email</label>
|
|
||||||
<input type="email" name="email" required>
|
|
||||||
</div>
|
|
||||||
<div class="form-group" style="flex: 1;">
|
|
||||||
<label for="password">Password</label>
|
|
||||||
<input type="password" name="password" required>
|
|
||||||
</div>
|
|
||||||
<div class="form-group" style="flex: 1;">
|
|
||||||
<label for="role">Role</label>
|
|
||||||
<select name="role">
|
|
||||||
<option value="artist">Artist</option>
|
|
||||||
<option value="admin">Admin</option>
|
|
||||||
<option value="super_admin">Super Admin</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<button type="submit" class="btn btn-primary">Add User</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Users List -->
|
|
||||||
<div class="content-card">
|
|
||||||
<h2>Existing Users</h2>
|
|
||||||
<table style="width: 100%;">
|
|
||||||
<thead>
|
|
||||||
<tr style="text-align: left; border-bottom: 1px solid #404040;">
|
|
||||||
<th style="padding: 10px;">Username</th>
|
|
||||||
<th style="padding: 10px;">Email</th>
|
|
||||||
<th style="padding: 10px;">Role</th>
|
|
||||||
<th style="padding: 10px;">Actions</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php if (empty($users)): ?>
|
|
||||||
<tr><td colspan="4" style="padding: 20px; text-align: center; color: #b3b3b3;">No users found.</td></tr>
|
|
||||||
<?php else: ?>
|
|
||||||
<?php foreach ($users as $user): ?>
|
|
||||||
<tr style="border-bottom: 1px solid #282828;">
|
|
||||||
<td style="padding: 10px;"><?= htmlspecialchars($user['username']) ?></td>
|
|
||||||
<td style="padding: 10px;"><?= htmlspecialchars($user['email']) ?></td>
|
|
||||||
<td style="padding: 10px;"><?= htmlspecialchars($user['role']) ?></td>
|
|
||||||
<td style="padding: 10px;">
|
|
||||||
<form action="users.php" method="POST" onsubmit="return confirm('Are you sure you want to delete this user?');" style="display: inline;">
|
|
||||||
<input type="hidden" name="action" value="delete">
|
|
||||||
<input type="hidden" name="id" value="<?= $user['id'] ?>">
|
|
||||||
<button type="submit" class="btn" style="background: none; color: #e76f51;" <?= ($_SESSION['user_id'] == $user['id']) ? 'disabled' : '' ?>><i class="fa fa-trash"></i></button>
|
|
||||||
</form>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
<?php endif; ?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,504 +0,0 @@
|
|||||||
|
|
||||||
/* assets/css/custom.css */
|
|
||||||
@import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@400;700&display=swap');
|
|
||||||
|
|
||||||
body {
|
|
||||||
font-family: 'Montserrat', sans-serif;
|
|
||||||
background-color: #121212;
|
|
||||||
color: #FFFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
height: 100vh;
|
|
||||||
width: 240px;
|
|
||||||
background-color: #000000;
|
|
||||||
padding: 24px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar .nav-link {
|
|
||||||
color: #b3b3b3;
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 1rem;
|
|
||||||
padding: 10px 0;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar .nav-link:hover, .sidebar .nav-link.active {
|
|
||||||
color: #FFFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar .nav-link i {
|
|
||||||
margin-right: 16px;
|
|
||||||
font-size: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar .logo {
|
|
||||||
color: #FFFFFF;
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 1.8rem;
|
|
||||||
margin-bottom: 30px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar .logo i {
|
|
||||||
color: #1DB954;
|
|
||||||
margin-right: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-content {
|
|
||||||
margin-left: 240px;
|
|
||||||
padding: 30px;
|
|
||||||
background: linear-gradient(to bottom, #222326, #121212 40%);
|
|
||||||
min-height: 100vh;
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-header h1 {
|
|
||||||
font-size: 2.5rem;
|
|
||||||
font-weight: 700;
|
|
||||||
margin-bottom: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stat-card, .content-card {
|
|
||||||
background-color: #181818;
|
|
||||||
border-radius: 8px;
|
|
||||||
padding: 20px;
|
|
||||||
border: 1px solid #282828;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stat-card h5 {
|
|
||||||
color: #b3b3b3;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stat-card .stat-value {
|
|
||||||
font-size: 2rem;
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content-card h2 {
|
|
||||||
font-size: 1.5rem;
|
|
||||||
font-weight: 700;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.track-item {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 10px 0;
|
|
||||||
border-bottom: 1px solid #282828;
|
|
||||||
}
|
|
||||||
.track-item:last-child {
|
|
||||||
border-bottom: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.track-item .track-number {
|
|
||||||
color: #b3b3b3;
|
|
||||||
width: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.track-item .track-info {
|
|
||||||
flex-grow: 1;
|
|
||||||
margin-left: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.track-item .track-title {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.track-item .track-artist {
|
|
||||||
color: #b3b3b3;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.track-item .track-plays {
|
|
||||||
color: #b3b3b3;
|
|
||||||
min-width: 100px;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-primary-custom {
|
|
||||||
background-color: #1DB954;
|
|
||||||
border-color: #1DB954;
|
|
||||||
color: #FFFFFF;
|
|
||||||
border-radius: 50px;
|
|
||||||
font-weight: bold;
|
|
||||||
padding: 10px 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-primary-custom:hover {
|
|
||||||
background-color: #1ed760;
|
|
||||||
border-color: #1ed760;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Upload Form Styles */
|
|
||||||
.upload-form-container {
|
|
||||||
background-color: #181818;
|
|
||||||
border-radius: 8px;
|
|
||||||
padding: 30px;
|
|
||||||
max-width: 800px;
|
|
||||||
margin: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.upload-form .form-group {
|
|
||||||
margin-bottom: 25px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.upload-form label {
|
|
||||||
display: block;
|
|
||||||
font-weight: bold;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
font-size: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.upload-form input[type="text"],
|
|
||||||
.upload-form input[type="file"] {
|
|
||||||
width: 100%;
|
|
||||||
padding: 12px 15px;
|
|
||||||
background-color: #282828;
|
|
||||||
border: 1px solid #404040;
|
|
||||||
border-radius: 4px;
|
|
||||||
color: #FFFFFF;
|
|
||||||
font-size: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.upload-form input[type="file"] {
|
|
||||||
padding: 10px 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.upload-form small {
|
|
||||||
display: block;
|
|
||||||
color: #b3b3b3;
|
|
||||||
margin-top: 8px;
|
|
||||||
font-size: 0.85rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.upload-form .form-group-checkbox {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
margin-bottom: 25px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.upload-form .form-group-checkbox input[type="checkbox"] {
|
|
||||||
width: 18px;
|
|
||||||
height: 18px;
|
|
||||||
margin-right: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.upload-form .form-group-checkbox label {
|
|
||||||
margin-bottom: 0;
|
|
||||||
font-weight: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
.upload-form .form-group-checkbox a {
|
|
||||||
color: #1DB954;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.upload-form .form-group-checkbox a:hover {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn {
|
|
||||||
padding: 12px 35px;
|
|
||||||
border-radius: 50px;
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 1rem;
|
|
||||||
cursor: pointer;
|
|
||||||
border: none;
|
|
||||||
text-transform: uppercase;
|
|
||||||
letter-spacing: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-primary {
|
|
||||||
background-color: #1DB954;
|
|
||||||
color: #FFFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-primary:hover {
|
|
||||||
background-color: #1ed760;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-lg {
|
|
||||||
padding: 15px 45px;
|
|
||||||
font-size: 1.1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.alert {
|
|
||||||
padding: 15px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
border-radius: 4px;
|
|
||||||
font-size: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.alert-success {
|
|
||||||
background-color: #2a9d8f;
|
|
||||||
color: #FFFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
.alert-danger {
|
|
||||||
background-color: #e76f51;
|
|
||||||
color: #FFFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Sidebar Refinements from upload.php */
|
|
||||||
.sidebar-header {
|
|
||||||
padding-bottom: 20px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
border-bottom: 1px solid #282828;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar .brand {
|
|
||||||
color: #FFFFFF;
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 1.8rem;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar-nav {
|
|
||||||
list-style: none;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar-nav li a {
|
|
||||||
color: #b3b3b3;
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 1rem;
|
|
||||||
padding: 12px 0;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
text-decoration: none;
|
|
||||||
transition: color 0.2s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar-nav li.active a,
|
|
||||||
.sidebar-nav li a:hover {
|
|
||||||
color: #FFFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar-nav li a i {
|
|
||||||
margin-right: 16px;
|
|
||||||
font-size: 1.25rem; /* Slightly smaller icons */
|
|
||||||
width: 24px; /* Fixed width for alignment */
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Main Content Refinements */
|
|
||||||
.page-container {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-content {
|
|
||||||
flex-grow: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-header {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
margin-bottom: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-profile {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-profile .fa-user-circle {
|
|
||||||
font-size: 2rem;
|
|
||||||
margin-right: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content-wrapper {
|
|
||||||
padding-top: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Landing Page Styles */
|
|
||||||
.landing-container {
|
|
||||||
max-width: 100%;
|
|
||||||
margin: 0 auto;
|
|
||||||
padding: 0;
|
|
||||||
background-color: #000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.landing-header {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
padding: 20px 50px;
|
|
||||||
background-color: transparent;
|
|
||||||
position: absolute;
|
|
||||||
width: 100%;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
z-index: 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.landing-header .logo {
|
|
||||||
font-size: 1.8rem;
|
|
||||||
font-weight: 700;
|
|
||||||
color: #FFFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
.landing-nav a {
|
|
||||||
color: #FFFFFF;
|
|
||||||
text-decoration: none;
|
|
||||||
margin-left: 25px;
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.landing-nav .btn {
|
|
||||||
margin-left: 25px;
|
|
||||||
padding: 10px 25px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-outline {
|
|
||||||
background-color: transparent;
|
|
||||||
border: 1px solid #FFFFFF;
|
|
||||||
color: #FFFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-outline:hover {
|
|
||||||
background-color: #FFFFFF;
|
|
||||||
color: #000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hero {
|
|
||||||
background: linear-gradient(rgba(0,0,0,0.7), rgba(0,0,0,0.7)), url('https://images.pexels.com/photos/1105666/pexels-photo-1105666.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2') no-repeat center center/cover;
|
|
||||||
height: 100vh;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hero-content h1 {
|
|
||||||
font-size: 4rem;
|
|
||||||
font-weight: 700;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
color: #FFFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hero-content p {
|
|
||||||
font-size: 1.2rem;
|
|
||||||
color: #b3b3b3;
|
|
||||||
margin-bottom: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.features-section, .pricing-section {
|
|
||||||
padding: 100px 50px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.features-section h2, .pricing-section h2 {
|
|
||||||
font-size: 2.8rem;
|
|
||||||
font-weight: 700;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.features-section p, .pricing-section p {
|
|
||||||
color: #b3b3b3;
|
|
||||||
margin-bottom: 60px;
|
|
||||||
font-size: 1.1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.features-grid, .pricing-grid {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
|
||||||
gap: 40px;
|
|
||||||
max-width: 1200px;
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.feature-card {
|
|
||||||
background-color: #181818;
|
|
||||||
padding: 40px;
|
|
||||||
border-radius: 8px;
|
|
||||||
border: 1px solid #282828;
|
|
||||||
}
|
|
||||||
|
|
||||||
.feature-card i {
|
|
||||||
font-size: 3rem;
|
|
||||||
color: #1DB954;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.feature-card h3 {
|
|
||||||
font-size: 1.5rem;
|
|
||||||
font-weight: 700;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.feature-card p {
|
|
||||||
color: #b3b3b3;
|
|
||||||
font-size: 1rem;
|
|
||||||
line-height: 1.6;
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pricing-card {
|
|
||||||
background-color: #181818;
|
|
||||||
padding: 40px;
|
|
||||||
border-radius: 8px;
|
|
||||||
border: 1px solid #282828;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pricing-card.recommended {
|
|
||||||
border-color: #1DB954;
|
|
||||||
transform: scale(1.05);
|
|
||||||
}
|
|
||||||
|
|
||||||
.pricing-card h3 {
|
|
||||||
font-size: 1.8rem;
|
|
||||||
font-weight: 700;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pricing-card .price {
|
|
||||||
font-size: 1.2rem;
|
|
||||||
color: #b3b3b3;
|
|
||||||
margin-bottom: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pricing-card .price span {
|
|
||||||
font-size: 3rem;
|
|
||||||
font-weight: 700;
|
|
||||||
color: #FFFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pricing-card ul {
|
|
||||||
list-style: none;
|
|
||||||
padding: 0;
|
|
||||||
margin-bottom: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pricing-card ul li {
|
|
||||||
margin-bottom: 15px;
|
|
||||||
font-size: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pricing-card ul li::before {
|
|
||||||
content: '\2713';
|
|
||||||
color: #1DB954;
|
|
||||||
margin-right: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.landing-footer {
|
|
||||||
text-align: center;
|
|
||||||
padding: 40px 20px;
|
|
||||||
background-color: #121212;
|
|
||||||
border-top: 1px solid #282828;
|
|
||||||
color: #b3b3b3;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,29 +0,0 @@
|
|||||||
// assets/js/main.js
|
|
||||||
document.addEventListener('DOMContentLoaded', function () {
|
|
||||||
console.log('Dashboard loaded.');
|
|
||||||
|
|
||||||
const addTrackBtn = document.getElementById('add-track-btn');
|
|
||||||
const tracksContainer = document.getElementById('tracks-container');
|
|
||||||
let trackIndex = 1;
|
|
||||||
|
|
||||||
if (addTrackBtn && tracksContainer) {
|
|
||||||
addTrackBtn.addEventListener('click', function () {
|
|
||||||
const trackHtml = `
|
|
||||||
<div class="track-input-group">
|
|
||||||
<hr>
|
|
||||||
<h5>Track ${trackIndex + 1}</h5>
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="track-title-${trackIndex}">Track Title</label>
|
|
||||||
<input type="text" id="track-title-${trackIndex}" name="tracks[${trackIndex}][title]" placeholder="Enter the track title" required>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="audio-file-${trackIndex}">Audio File</label>
|
|
||||||
<input type="file" id="audio-file-${trackIndex}" name="tracks[${trackIndex}][audio_file]" accept="audio/mpeg, audio/wav" required>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
tracksContainer.insertAdjacentHTML('beforeend', trackHtml);
|
|
||||||
trackIndex++;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
14
auth.php
14
auth.php
@ -1,14 +0,0 @@
|
|||||||
<?php
|
|
||||||
session_start();
|
|
||||||
|
|
||||||
if (!isset($_SESSION['user_id'])) {
|
|
||||||
// If no user is logged in, redirect to the login page.
|
|
||||||
header("Location: login.php");
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Optional: You could add role-based access control here later.
|
|
||||||
// For example:
|
|
||||||
// if ($_SESSION['role'] !== 'artist') {
|
|
||||||
// die("You do not have permission to access this page.");
|
|
||||||
// }
|
|
||||||
116
collaborate.php
116
collaborate.php
@ -1,116 +0,0 @@
|
|||||||
<?php
|
|
||||||
require_once 'auth.php';
|
|
||||||
require_once 'db/config.php';
|
|
||||||
|
|
||||||
$pageTitle = "Collaborate - Zeal Music";
|
|
||||||
$pdo = db();
|
|
||||||
$errors = [];
|
|
||||||
$successMessage = '';
|
|
||||||
|
|
||||||
// Handle new post submission
|
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'create') {
|
|
||||||
$title = trim($_POST['title'] ?? '');
|
|
||||||
$description = trim($_POST['description'] ?? '');
|
|
||||||
|
|
||||||
if (empty($title) || empty($description)) {
|
|
||||||
$errors[] = "Title and description are required.";
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
$stmt = $pdo->prepare("INSERT INTO collaborations (user_id, title, description) VALUES (?, ?, ?)");
|
|
||||||
$stmt->execute([$_SESSION['user_id'], $title, $description]);
|
|
||||||
$successMessage = "Your collaboration post has been created!";
|
|
||||||
} catch (PDOException $e) {
|
|
||||||
$errors[] = "Database error: " . $e->getMessage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch all open collaboration posts
|
|
||||||
$collaborations = [];
|
|
||||||
try {
|
|
||||||
$stmt = $pdo->query("SELECT c.id, c.title, c.description, c.created_at, u.username FROM collaborations c JOIN users u ON c.user_id = u.id WHERE c.status = 'open' ORDER BY c.created_at DESC");
|
|
||||||
$collaborations = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
||||||
} catch (PDOException $e) {
|
|
||||||
$errors[] = "Error fetching collaboration posts: " . $e->getMessage();
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title><?php echo htmlspecialchars($pageTitle); ?></title>
|
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
|
||||||
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
|
||||||
<style>
|
|
||||||
.collab-post { background-color: #181818; border-radius: 8px; padding: 20px; margin-bottom: 20px; border: 1px solid #282828; }
|
|
||||||
.collab-post h3 { font-size: 1.3rem; margin-bottom: 10px; color: #1DB954; }
|
|
||||||
.collab-post .post-meta { font-size: 0.9rem; color: #b3b3b3; margin-bottom: 15px; }
|
|
||||||
.collab-post p { color: #e0e0e0; }
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body class="dark-theme">
|
|
||||||
<div class="page-container">
|
|
||||||
<?php include 'partials/sidebar.php'; ?>
|
|
||||||
|
|
||||||
<main class="main-content">
|
|
||||||
<header class="main-header">
|
|
||||||
<h1>Collaboration Feed</h1>
|
|
||||||
<div class="user-profile">
|
|
||||||
<i class="fa fa-user-circle"></i>
|
|
||||||
<span><?php echo htmlspecialchars($_SESSION['username']); ?></span>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<div class="content-wrapper">
|
|
||||||
<?php if ($successMessage) echo "<div class='alert alert-success'>".htmlspecialchars($successMessage)."</div>"; ?>
|
|
||||||
<?php foreach ($errors as $error) echo "<div class='alert alert-danger'>".htmlspecialchars($error)."</div>"; ?>
|
|
||||||
|
|
||||||
<!-- Create New Post Form -->
|
|
||||||
<div class="content-card mb-4">
|
|
||||||
<h2>Create a New Collaboration Post</h2>
|
|
||||||
<form action="collaborate.php" method="POST" class="upload-form" style="max-width: none;">
|
|
||||||
<input type="hidden" name="action" value="create">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="title">Title</label>
|
|
||||||
<input type="text" id="title" name="title" placeholder="E.g., 'Vocalist needed for a pop track'" required>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="description">Description</label>
|
|
||||||
<textarea id="description" name="description" rows="4" placeholder="Describe the project, what you're looking for, and include links to demos if you have them." required></textarea>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<button type="submit" class="btn btn-primary">Post Collaboration</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Collaboration Feed -->
|
|
||||||
<div class="content-card">
|
|
||||||
<h2>Open Collaborations</h2>
|
|
||||||
<?php if (empty($collaborations)):
|
|
||||||
?>
|
|
||||||
<p style="text-align: center; color: #b3b3b3; padding: 20px;">No open collaborations at the moment. Why not start one?</p>
|
|
||||||
<?php else:
|
|
||||||
foreach ($collaborations as $collab):
|
|
||||||
?>
|
|
||||||
<div class="collab-post">
|
|
||||||
<h3><?php echo htmlspecialchars($collab['title']); ?></h3>
|
|
||||||
<div class="post-meta">
|
|
||||||
Posted by <strong><?php echo htmlspecialchars($collab['username']); ?></strong> on <?php echo date("F j, Y", strtotime($collab['created_at'])); ?>
|
|
||||||
</div>
|
|
||||||
<p><?php echo nl2br(htmlspecialchars($collab['description'])); ?></p>
|
|
||||||
</div>
|
|
||||||
<?php
|
|
||||||
endforeach;
|
|
||||||
endif; ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
<style>
|
|
||||||
textarea { width: 100%; padding: 12px 15px; background-color: #282828; border: 1px solid #404040; border-radius: 4px; color: #FFFFFF; font-size: 1rem; font-family: inherit; }
|
|
||||||
</style>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
124
dashboard.php
124
dashboard.php
@ -1,124 +0,0 @@
|
|||||||
<?php
|
|
||||||
require_once 'auth.php';
|
|
||||||
require_once 'db/config.php'; // Ensure DB config is included
|
|
||||||
|
|
||||||
// Fetch tracks for the logged-in user
|
|
||||||
$user_id = $_SESSION['user_id'];
|
|
||||||
$tracks = [];
|
|
||||||
|
|
||||||
// For admins, show all tracks. For artists, show only their own.
|
|
||||||
if (isset($_SESSION['role']) && in_array($_SESSION['role'], ['admin', 'super_admin'])) {
|
|
||||||
$stmt = db()->prepare("SELECT t.*, u.username FROM tracks t JOIN users u ON t.user_id = u.id ORDER BY t.created_at DESC");
|
|
||||||
if ($stmt->execute()) {
|
|
||||||
$tracks = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$stmt = db()->prepare("SELECT * FROM tracks WHERE user_id = ? ORDER BY created_at DESC");
|
|
||||||
if ($stmt->execute([$user_id])) {
|
|
||||||
$tracks = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
$pageTitle = "Dashboard - Zeal Music";
|
|
||||||
?>
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title><?php echo htmlspecialchars($pageTitle); ?></title>
|
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
|
||||||
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
|
||||||
</head>
|
|
||||||
<body class="dark-theme">
|
|
||||||
<div class="page-container">
|
|
||||||
|
|
||||||
<?php include 'partials/sidebar.php'; ?>
|
|
||||||
|
|
||||||
<!-- Main Content -->
|
|
||||||
<main class="main-content">
|
|
||||||
<header class="main-header">
|
|
||||||
<h1>Welcome Back, <?php echo htmlspecialchars($_SESSION['username']); ?></h1>
|
|
||||||
<div class="user-profile">
|
|
||||||
<i class="fa fa-user-circle"></i>
|
|
||||||
<span><?php echo htmlspecialchars($_SESSION['username']); ?></span>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<div class="content-wrapper">
|
|
||||||
<!-- Key Metrics -->
|
|
||||||
<div class="row-g-4 mb-4" style="display: flex; gap: 1.5rem;">
|
|
||||||
<div class="col" style="flex: 1;">
|
|
||||||
<div class="stat-card">
|
|
||||||
<h5>Total Plays</h5>
|
|
||||||
<p class="stat-value">1.2M</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col" style="flex: 1;">
|
|
||||||
<div class="stat-card">
|
|
||||||
<h5>Listeners (30 days)</h5>
|
|
||||||
<p class="stat-value">89.4K</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col" style="flex: 1;">
|
|
||||||
<div class="stat-card">
|
|
||||||
<h5>Engagements</h5>
|
|
||||||
<p class="stat-value">12.1K</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- My Tracks -->
|
|
||||||
<div class="content-card">
|
|
||||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
|
||||||
<h2>My Tracks</h2>
|
|
||||||
<?php if (!isset($_SESSION['role']) || !in_array($_SESSION['role'], ['admin', 'super_admin'])):
|
|
||||||
?>
|
|
||||||
<a href="upload.php" class="btn btn-primary">Upload Music</a>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php if (empty($tracks)):
|
|
||||||
?>
|
|
||||||
<div class="text-center p-4">
|
|
||||||
<p>No tracks have been uploaded yet.</p>
|
|
||||||
<?php if (!isset($_SESSION['role']) || !in_array($_SESSION['role'], ['admin', 'super_admin'])):
|
|
||||||
?>
|
|
||||||
<a href="upload.php" class="btn btn-primary mt-2">Upload Your First Track</a>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
<?php else:
|
|
||||||
?>
|
|
||||||
<?php foreach ($tracks as $index => $track):
|
|
||||||
?>
|
|
||||||
<div class="track-item">
|
|
||||||
<div class="track-number"><?php echo $index + 1; ?></div>
|
|
||||||
<img src="<?php echo htmlspecialchars($track['cover_art_path']); ?>" alt="Cover Art" class="track-cover-art-thumb">
|
|
||||||
<div class="track-info">
|
|
||||||
<div class="track-title"><?php echo htmlspecialchars($track['title']); ?></div>
|
|
||||||
<?php
|
|
||||||
$artistName = '';
|
|
||||||
if (isset($_SESSION['role']) && in_array($_SESSION['role'], ['admin', 'super_admin'])) {
|
|
||||||
// For admins, show the username of the uploader
|
|
||||||
$artistName = $track['username'] ?? 'Unknown Artist';
|
|
||||||
} else {
|
|
||||||
// For artists, show their own artist name from the track details
|
|
||||||
$artistName = $track['artist'] ?? 'Unknown Artist';
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
<div class="track-artist"><?php echo htmlspecialchars($artistName); ?></div>
|
|
||||||
</div>
|
|
||||||
<div class="track-album"><?php echo htmlspecialchars($track['album_title']); ?></div>
|
|
||||||
<div class="track-plays">0 plays</div>
|
|
||||||
</div>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script src="assets/js/main.js?v=<?php echo time(); ?>"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,34 +0,0 @@
|
|||||||
<?php
|
|
||||||
// Simple migration script
|
|
||||||
|
|
||||||
require_once __DIR__ . '/config.php';
|
|
||||||
|
|
||||||
function run_migrations() {
|
|
||||||
try {
|
|
||||||
$pdo = db();
|
|
||||||
$migrationsDir = __DIR__ . '/migrations';
|
|
||||||
|
|
||||||
if (!is_dir($migrationsDir)) {
|
|
||||||
echo "Migrations directory not found.\n";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$files = glob($migrationsDir . '/*.sql');
|
|
||||||
sort($files);
|
|
||||||
|
|
||||||
foreach ($files as $file) {
|
|
||||||
echo "Running migration: " . basename($file) . "...\n";
|
|
||||||
$sql = file_get_contents($file);
|
|
||||||
$pdo->exec($sql);
|
|
||||||
echo "Success.\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
echo "\nAll migrations completed.\n";
|
|
||||||
|
|
||||||
} catch (PDOException $e) {
|
|
||||||
die("Database migration failed: " . $e->getMessage() . "\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
run_migrations();
|
|
||||||
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
-- 001_create_users_table.sql
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `users` (
|
|
||||||
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
`username` VARCHAR(50) NOT NULL UNIQUE,
|
|
||||||
`email` VARCHAR(100) NOT NULL UNIQUE,
|
|
||||||
`password` VARCHAR(255) NOT NULL,
|
|
||||||
`role` ENUM('artist', 'publisher', 'admin', 'super_admin') NOT NULL DEFAULT 'artist',
|
|
||||||
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
-- 002_create_stations_table.sql
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `stations` (
|
|
||||||
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
`name` VARCHAR(100) NOT NULL,
|
|
||||||
`contact_email` VARCHAR(100) NOT NULL UNIQUE,
|
|
||||||
`genre_focus` VARCHAR(255) NULL,
|
|
||||||
`website` VARCHAR(255) NULL,
|
|
||||||
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
-- 003_create_collaborations_table.sql
|
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `collaborations` (
|
|
||||||
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
`user_id` INT NOT NULL,
|
|
||||||
`title` VARCHAR(255) NOT NULL,
|
|
||||||
`description` TEXT NOT NULL,
|
|
||||||
`status` ENUM('open', 'closed') NOT NULL DEFAULT 'open',
|
|
||||||
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE CASCADE
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
CREATE TABLE IF NOT EXISTS tracks (
|
|
||||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
user_id INT NOT NULL,
|
|
||||||
title VARCHAR(255) NOT NULL,
|
|
||||||
album VARCHAR(255),
|
|
||||||
genre VARCHAR(100),
|
|
||||||
release_date DATE,
|
|
||||||
file_path VARCHAR(255) NOT NULL,
|
|
||||||
cover_art_path VARCHAR(255),
|
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
|
||||||
);
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
CREATE TABLE IF NOT EXISTS packages (
|
|
||||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
name VARCHAR(255) NOT NULL,
|
|
||||||
price DECIMAL(10, 2) NOT NULL,
|
|
||||||
features TEXT NOT NULL,
|
|
||||||
is_recommended BOOLEAN DEFAULT FALSE,
|
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
||||||
);
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
CREATE TABLE IF NOT EXISTS monitoring_data (
|
|
||||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
track_id INT NOT NULL,
|
|
||||||
plays INT NOT NULL,
|
|
||||||
date DATE NOT NULL,
|
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
FOREIGN KEY (track_id) REFERENCES tracks(id) ON DELETE CASCADE
|
|
||||||
);
|
|
||||||
@ -1 +0,0 @@
|
|||||||
ALTER TABLE users ADD COLUMN package_id INT NULL;
|
|
||||||
152
index.php
152
index.php
@ -1,8 +1,150 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once 'auth.php';
|
declare(strict_types=1);
|
||||||
|
@ini_set('display_errors', '1');
|
||||||
|
@error_reporting(E_ALL);
|
||||||
|
@date_default_timezone_set('UTC');
|
||||||
|
|
||||||
if (is_logged_in()) {
|
$phpVersion = PHP_VERSION;
|
||||||
require 'dashboard.php';
|
$now = date('Y-m-d H:i:s');
|
||||||
} else {
|
?>
|
||||||
require 'landing.php';
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<title>New Style</title>
|
||||||
|
<?php
|
||||||
|
// Read project preview data from environment
|
||||||
|
$projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? '';
|
||||||
|
$projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
|
||||||
|
?>
|
||||||
|
<?php if ($projectDescription): ?>
|
||||||
|
<!-- Meta description -->
|
||||||
|
<meta name="description" content='<?= htmlspecialchars($projectDescription) ?>' />
|
||||||
|
<!-- Open Graph meta tags -->
|
||||||
|
<meta property="og:description" content="<?= htmlspecialchars($projectDescription) ?>" />
|
||||||
|
<!-- Twitter meta tags -->
|
||||||
|
<meta property="twitter:description" content="<?= htmlspecialchars($projectDescription) ?>" />
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php if ($projectImageUrl): ?>
|
||||||
|
<!-- Open Graph image -->
|
||||||
|
<meta property="og:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
|
||||||
|
<!-- Twitter image -->
|
||||||
|
<meta property="twitter:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
|
||||||
|
<?php endif; ?>
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet">
|
||||||
|
<style>
|
||||||
|
:root {
|
||||||
|
--bg-color-start: #6a11cb;
|
||||||
|
--bg-color-end: #2575fc;
|
||||||
|
--text-color: #ffffff;
|
||||||
|
--card-bg-color: rgba(255, 255, 255, 0.01);
|
||||||
|
--card-border-color: rgba(255, 255, 255, 0.1);
|
||||||
}
|
}
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
font-family: 'Inter', sans-serif;
|
||||||
|
background: linear-gradient(45deg, var(--bg-color-start), var(--bg-color-end));
|
||||||
|
color: var(--text-color);
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
min-height: 100vh;
|
||||||
|
text-align: center;
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
body::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100"><path d="M-10 10L110 10M10 -10L10 110" stroke-width="1" stroke="rgba(255,255,255,0.05)"/></svg>');
|
||||||
|
animation: bg-pan 20s linear infinite;
|
||||||
|
z-index: -1;
|
||||||
|
}
|
||||||
|
@keyframes bg-pan {
|
||||||
|
0% { background-position: 0% 0%; }
|
||||||
|
100% { background-position: 100% 100%; }
|
||||||
|
}
|
||||||
|
main {
|
||||||
|
padding: 2rem;
|
||||||
|
}
|
||||||
|
.card {
|
||||||
|
background: var(--card-bg-color);
|
||||||
|
border: 1px solid var(--card-border-color);
|
||||||
|
border-radius: 16px;
|
||||||
|
padding: 2rem;
|
||||||
|
backdrop-filter: blur(20px);
|
||||||
|
-webkit-backdrop-filter: blur(20px);
|
||||||
|
box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
.loader {
|
||||||
|
margin: 1.25rem auto 1.25rem;
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
border: 3px solid rgba(255, 255, 255, 0.25);
|
||||||
|
border-top-color: #fff;
|
||||||
|
border-radius: 50%;
|
||||||
|
animation: spin 1s linear infinite;
|
||||||
|
}
|
||||||
|
@keyframes spin {
|
||||||
|
from { transform: rotate(0deg); }
|
||||||
|
to { transform: rotate(360deg); }
|
||||||
|
}
|
||||||
|
.hint {
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
.sr-only {
|
||||||
|
position: absolute;
|
||||||
|
width: 1px; height: 1px;
|
||||||
|
padding: 0; margin: -1px;
|
||||||
|
overflow: hidden;
|
||||||
|
clip: rect(0, 0, 0, 0);
|
||||||
|
white-space: nowrap; border: 0;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
font-size: 3rem;
|
||||||
|
font-weight: 700;
|
||||||
|
margin: 0 0 1rem;
|
||||||
|
letter-spacing: -1px;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
margin: 0.5rem 0;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
code {
|
||||||
|
background: rgba(0,0,0,0.2);
|
||||||
|
padding: 2px 6px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
||||||
|
}
|
||||||
|
footer {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 1rem;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<main>
|
||||||
|
<div class="card">
|
||||||
|
<h1>Analyzing your requirements and generating your website…</h1>
|
||||||
|
<div class="loader" role="status" aria-live="polite" aria-label="Applying initial changes">
|
||||||
|
<span class="sr-only">Loading…</span>
|
||||||
|
</div>
|
||||||
|
<p class="hint"><?= ($_SERVER['HTTP_HOST'] ?? '') === 'appwizzy.com' ? 'AppWizzy' : 'Flatlogic' ?> AI is collecting your requirements and applying the first changes.</p>
|
||||||
|
<p class="hint">This page will update automatically as the plan is implemented.</p>
|
||||||
|
<p>Runtime: PHP <code><?= htmlspecialchars($phpVersion) ?></code> — UTC <code><?= htmlspecialchars($now) ?></code></p>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
<footer>
|
||||||
|
Page updated: <?= htmlspecialchars($now) ?> (UTC)
|
||||||
|
</footer>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|||||||
89
landing.php
89
landing.php
@ -1,89 +0,0 @@
|
|||||||
|
|
||||||
<?php
|
|
||||||
require_once 'db/config.php';
|
|
||||||
|
|
||||||
// Fetch all packages
|
|
||||||
$stmt = db()->query("SELECT * FROM packages ORDER BY price");
|
|
||||||
$packages = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
||||||
?>
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>Zeal Music - Unleash Your Music's Potential</title>
|
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
|
||||||
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
|
||||||
</head>
|
|
||||||
<body class="dark-theme">
|
|
||||||
<div class="landing-container">
|
|
||||||
<header class="landing-header">
|
|
||||||
<div class="logo">Zeal Music</div>
|
|
||||||
<nav class="landing-nav">
|
|
||||||
<a href="#features">Features</a>
|
|
||||||
<a href="#pricing">Pricing</a>
|
|
||||||
<a href="login.php" class="btn btn-outline">Login</a>
|
|
||||||
<a href="register.php" class="btn btn-primary">Sign Up</a>
|
|
||||||
</nav>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<main>
|
|
||||||
<section class="hero">
|
|
||||||
<div class="hero-content">
|
|
||||||
<h1>Unleash Your Music's Potential</h1>
|
|
||||||
<p>The ultimate platform for artists to manage, distribute, and monetize their work.</p>
|
|
||||||
<a href="register.php" class="btn btn-primary btn-lg">Get Started Now</a>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section id="features" class="features-section">
|
|
||||||
<h2>Why Zeal Music?</h2>
|
|
||||||
<div class="features-grid">
|
|
||||||
<div class="feature-card">
|
|
||||||
<i class="fas fa-chart-line"></i>
|
|
||||||
<h3>Detailed Analytics</h3>
|
|
||||||
<p>Gain deep insights into your listeners and track performance across all platforms.</p>
|
|
||||||
</div>
|
|
||||||
<div class="feature-card">
|
|
||||||
<i class="fas fa-upload"></i>
|
|
||||||
<h3>Direct Uploads</h3>
|
|
||||||
<p>Easily upload your tracks, albums, and cover art with our streamlined process.</p>
|
|
||||||
</div>
|
|
||||||
<div class="feature-card">
|
|
||||||
<i class="fas fa-globe"></i>
|
|
||||||
<h3>Global Reach</h3>
|
|
||||||
<p>Distribute your music to major streaming services and digital stores worldwide.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section id="pricing" class="pricing-section">
|
|
||||||
<h2>Choose Your Plan</h2>
|
|
||||||
<p>Simple, transparent pricing. No hidden fees.</p>
|
|
||||||
<div class="pricing-grid">
|
|
||||||
<?php foreach ($packages as $package): ?>
|
|
||||||
<div class="pricing-card <?php echo $package['is_recommended'] ? 'recommended' : ''; ?>">
|
|
||||||
<h3><?php echo htmlspecialchars($package['name']); ?></h3>
|
|
||||||
<p class="price"><span>$<?php echo htmlspecialchars($package['price']); ?></span>/month</p>
|
|
||||||
<ul>
|
|
||||||
<?php
|
|
||||||
$features = explode(',', $package['features']);
|
|
||||||
foreach ($features as $feature):
|
|
||||||
?>
|
|
||||||
<li><?php echo htmlspecialchars(trim($feature)); ?></li>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</ul>
|
|
||||||
<a href="register.php" class="btn btn-primary">Select Plan</a>
|
|
||||||
</div>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</main>
|
|
||||||
|
|
||||||
<footer class="landing-footer">
|
|
||||||
<p>© <?php echo date("Y"); ?> Zeal Music. All Rights Reserved.</p>
|
|
||||||
</footer>
|
|
||||||
</div>
|
|
||||||
<script src="assets/js/main.js?v=<?php echo time(); ?>"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
101
login.php
101
login.php
@ -1,101 +0,0 @@
|
|||||||
<?php
|
|
||||||
session_start();
|
|
||||||
require_once __DIR__ . '/db/config.php';
|
|
||||||
|
|
||||||
$pageTitle = "Login - Zeal Music";
|
|
||||||
$errors = [];
|
|
||||||
|
|
||||||
// If user is already logged in, redirect to dashboard
|
|
||||||
if (isset($_SESSION['user_id'])) {
|
|
||||||
header("Location: index.php");
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($_SERVER["REQUEST_METHOD"] == "POST") {
|
|
||||||
$email = trim($_POST['email'] ?? '');
|
|
||||||
$password = $_POST['password'] ?? '';
|
|
||||||
|
|
||||||
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
|
||||||
$errors[] = 'Invalid email format.';
|
|
||||||
}
|
|
||||||
if (empty($password)) {
|
|
||||||
$errors[] = 'Password is required.';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($errors)) {
|
|
||||||
try {
|
|
||||||
$pdo = db();
|
|
||||||
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = :email");
|
|
||||||
$stmt->execute(['email' => $email]);
|
|
||||||
$user = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
||||||
|
|
||||||
if ($user && password_verify($password, $user['password'])) {
|
|
||||||
// Password is correct, start session
|
|
||||||
$_SESSION['user_id'] = $user['id'];
|
|
||||||
$_SESSION['username'] = $user['username'];
|
|
||||||
$_SESSION['role'] = $user['role'];
|
|
||||||
header("Location: index.php");
|
|
||||||
exit;
|
|
||||||
} else {
|
|
||||||
$errors[] = 'Invalid email or password.';
|
|
||||||
}
|
|
||||||
} catch (PDOException $e) {
|
|
||||||
$errors[] = "Database error: " . $e->getMessage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title><?php echo htmlspecialchars($pageTitle); ?></title>
|
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
|
||||||
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
|
||||||
</head>
|
|
||||||
<body class="dark-theme">
|
|
||||||
<div class="page-container">
|
|
||||||
<nav class="sidebar">
|
|
||||||
<div class="sidebar-header">
|
|
||||||
<a href="index.php" class="brand">Zeal Music</a>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
<main class="main-content">
|
|
||||||
<div class="content-wrapper">
|
|
||||||
<div class="upload-form-container">
|
|
||||||
<h2>Log In to Your Account</h2>
|
|
||||||
<br>
|
|
||||||
<?php if (!empty($errors)):
|
|
||||||
foreach ($errors as $error):
|
|
||||||
?>
|
|
||||||
<div class="alert alert-danger"><?php echo htmlspecialchars($error); ?></div>
|
|
||||||
<?php
|
|
||||||
endforeach;
|
|
||||||
endif; ?>
|
|
||||||
|
|
||||||
<form action="login.php" method="POST" class="upload-form">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="email">Email Address</label>
|
|
||||||
<input type="email" id="email" name="email" placeholder="Your email" required>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="password">Password</label>
|
|
||||||
<input type="password" id="password" name="password" placeholder="Your password" required>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<button type="submit" class="btn btn-primary btn-lg">Log In</button>
|
|
||||||
</div>
|
|
||||||
<p style="text-align: center; margin-top: 20px;">
|
|
||||||
Don't have an account? <a href="register.php" style="color: #1DB954;">Register Now</a>
|
|
||||||
</p>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
<?php
|
|
||||||
session_start();
|
|
||||||
session_unset();
|
|
||||||
session_destroy();
|
|
||||||
header("Location: login.php");
|
|
||||||
exit;
|
|
||||||
@ -1,38 +0,0 @@
|
|||||||
<?php
|
|
||||||
// partials/sidebar.php
|
|
||||||
|
|
||||||
// Ensure session is started.
|
|
||||||
if (session_status() === PHP_SESSION_NONE) {
|
|
||||||
session_start();
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
<nav class="sidebar">
|
|
||||||
<div class="sidebar-header">
|
|
||||||
<a href="/index.php" class="brand">Zeal Music</a>
|
|
||||||
</div>
|
|
||||||
<ul class="sidebar-nav">
|
|
||||||
<li class="<?php echo (basename($_SERVER['PHP_SELF']) == 'index.php') ? 'active' : ''; ?>"><a href="/index.php"><i class="fa fa-home"></i> Home</a></li>
|
|
||||||
<li><a href="#"><i class="fa fa-music"></i> Tracks</a></li>
|
|
||||||
<li><a href="#"><i class="fa fa-chart-line"></i> Analytics</a></li>
|
|
||||||
<li class="<?php echo (basename($_SERVER['PHP_SELF']) == 'collaborate.php') ? 'active' : ''; ?>"><a href="/collaborate.php"><i class="fa fa-users"></i> Collaborate</a></li>
|
|
||||||
<?php // Show non-admin links
|
|
||||||
if (!isset($_SESSION['role']) || !in_array($_SESSION['role'], ['admin', 'super_admin'])):
|
|
||||||
?>
|
|
||||||
<li class="<?php echo (basename($_SERVER['PHP_SELF']) == 'upload.php') ? 'active' : ''; ?>"><a href="/upload.php"><i class="fa fa-upload"></i> Upload Music</a></li>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<?php // Show Admin links only to admins
|
|
||||||
if (isset($_SESSION['role']) && in_array($_SESSION['role'], ['admin', 'super_admin'])):
|
|
||||||
?>
|
|
||||||
<li class="<?php echo (basename($_SERVER['PHP_SELF']) == 'stations.php') ? 'active' : ''; ?>"><a href="/admin/stations.php"><i class="fa fa-broadcast-tower"></i> Manage Stations</a></li>
|
|
||||||
<li class="<?php echo (basename($_SERVER['PHP_SELF']) == 'users.php') ? 'active' : ''; ?>"><a href="/admin/users.php"><i class="fa fa-users-cog"></i> Manage Users</a></li>
|
|
||||||
<li class="<?php echo (basename($_SERVER['PHP_SELF']) == 'monitoring.php') ? 'active' : ''; ?>"><a href="/admin/monitoring.php"><i class="fa fa-file-csv"></i> Music Monitoring</a></li>
|
|
||||||
<li class="<?php echo (basename($_SERVER['PHP_SELF']) == 'packages.php') ? 'active' : ''; ?>"><a href="/admin/packages.php"><i class="fa fa-box"></i> Manage Packages</a></li>
|
|
||||||
<?php endif; ?>
|
|
||||||
</ul>
|
|
||||||
<div style="margin-top: auto; padding-top: 20px; border-top: 1px solid #282828;">
|
|
||||||
<ul class="sidebar-nav">
|
|
||||||
<li><a href="/logout.php"><i class="fa fa-sign-out-alt"></i> Logout</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
143
register.php
143
register.php
@ -1,143 +0,0 @@
|
|||||||
<?php
|
|
||||||
require_once __DIR__ . '/db/config.php';
|
|
||||||
|
|
||||||
$pageTitle = "Register - Zeal Music";
|
|
||||||
$errors = [];
|
|
||||||
$successMessage = "";
|
|
||||||
|
|
||||||
// Fetch packages from the database
|
|
||||||
try {
|
|
||||||
$pdo = db();
|
|
||||||
$stmt = $pdo->query("SELECT id, name, price, features FROM packages ORDER BY price");
|
|
||||||
$packages = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
||||||
} catch (PDOException $e) {
|
|
||||||
$errors[] = "Database error: " . $e->getMessage();
|
|
||||||
$packages = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($_SERVER["REQUEST_METHOD"] == "POST") {
|
|
||||||
$username = trim($_POST['username'] ?? '');
|
|
||||||
$email = trim($_POST['email'] ?? '');
|
|
||||||
$password = $_POST['password'] ?? '';
|
|
||||||
$password_confirm = $_POST['password_confirm'] ?? '';
|
|
||||||
$package_id = $_POST['package_id'] ?? '';
|
|
||||||
|
|
||||||
// Validation
|
|
||||||
if (empty($username)) $errors[] = 'Username is required.';
|
|
||||||
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) $errors[] = 'A valid email is required.';
|
|
||||||
if (strlen($password) < 8) $errors[] = 'Password must be at least 8 characters long.';
|
|
||||||
if ($password !== $password_confirm) $errors[] = 'Passwords do not match.';
|
|
||||||
if (empty($package_id)) $errors[] = 'Please select a package.';
|
|
||||||
|
|
||||||
// Check if user already exists
|
|
||||||
if (empty($errors)) {
|
|
||||||
try {
|
|
||||||
$pdo = db();
|
|
||||||
$stmt = $pdo->prepare("SELECT id FROM users WHERE username = :username OR email = :email");
|
|
||||||
$stmt->execute(['username' => $username, 'email' => $email]);
|
|
||||||
if ($stmt->fetch()) {
|
|
||||||
$errors[] = 'Username or email already exists.';
|
|
||||||
}
|
|
||||||
} catch (PDOException $e) {
|
|
||||||
$errors[] = "Database error: " . $e->getMessage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert new user
|
|
||||||
if (empty($errors)) {
|
|
||||||
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
|
|
||||||
try {
|
|
||||||
$pdo = db();
|
|
||||||
$stmt = $pdo->prepare("INSERT INTO users (username, email, password, role, package_id) VALUES (:username, :email, :password, 'artist', :package_id)");
|
|
||||||
$stmt->execute(['username' => $username, 'email' => $email, 'password' => $hashed_password, 'package_id' => $package_id]);
|
|
||||||
$successMessage = "Registration successful! You can now <a href='login.php'>log in</a>.";
|
|
||||||
} catch (PDOException $e) {
|
|
||||||
$errors[] = "Database error during registration: " . $e->getMessage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title><?php echo htmlspecialchars($pageTitle); ?></title>
|
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
|
||||||
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
|
||||||
</head>
|
|
||||||
<body class="dark-theme">
|
|
||||||
<div class="page-container">
|
|
||||||
<!-- Simplified Sidebar for Auth Pages -->
|
|
||||||
<nav class="sidebar">
|
|
||||||
<div class="sidebar-header">
|
|
||||||
<a href="index.php" class="brand">Zeal Music</a>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
<!-- Main Content -->
|
|
||||||
<main class="main-content">
|
|
||||||
<div class="content-wrapper">
|
|
||||||
<div class="upload-form-container">
|
|
||||||
<h2>Create Your Artist Account</h2>
|
|
||||||
<br>
|
|
||||||
<?php if (!empty($errors)):
|
|
||||||
foreach ($errors as $error):
|
|
||||||
?>
|
|
||||||
<div class="alert alert-danger"><?php echo htmlspecialchars($error); ?></div>
|
|
||||||
<?php endforeach;
|
|
||||||
endif; ?>
|
|
||||||
|
|
||||||
<?php if ($successMessage): ?>
|
|
||||||
<div class="alert alert-success"><?php echo $successMessage; ?></div>
|
|
||||||
<?php else: ?>
|
|
||||||
<form action="register.php" method="POST" class="upload-form">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="username">Username</label>
|
|
||||||
<input type="text" id="username" name="username" placeholder="Your unique username" required value="<?php echo htmlspecialchars($username ?? ''); ?>">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="email">Email Address</label>
|
|
||||||
<input type="email" id="email" name="email" placeholder="Your contact email" required value="<?php echo htmlspecialchars($email ?? ''); ?>">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="password">Password</label>
|
|
||||||
<input type="password" id="password" name="password" placeholder="Minimum 8 characters" required>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="password_confirm">Confirm Password</label>
|
|
||||||
<input type="password" id="password_confirm" name="password_confirm" placeholder="Enter your password again" required>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label>Select a Package</label>
|
|
||||||
<div class="package-selection">
|
|
||||||
<?php foreach ($packages as $package): ?>
|
|
||||||
<div class="package-option">
|
|
||||||
<input type="radio" id="package_<?php echo $package['id']; ?>" name="package_id" value="<?php echo $package['id']; ?>" required>
|
|
||||||
<label for="package_<?php echo $package['id']; ?>">
|
|
||||||
<strong><?php echo htmlspecialchars($package['name']); ?></strong> - $<?php echo htmlspecialchars($package['price']); ?>/month
|
|
||||||
<p><?php echo htmlspecialchars($package['features']); ?></p>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<button type="submit" class="btn btn-primary btn-lg">Register</button>
|
|
||||||
</div>
|
|
||||||
<p style="text-align: center; margin-top: 20px;">
|
|
||||||
Already have an account? <a href="login.php" style="color: #1DB954;">Log In</a>
|
|
||||||
</p>
|
|
||||||
</form>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
190
upload.php
190
upload.php
@ -1,190 +0,0 @@
|
|||||||
<?php
|
|
||||||
require_once 'auth.php';
|
|
||||||
require_once 'db/config.php';
|
|
||||||
|
|
||||||
$pageTitle = "Upload Album - Zeal Music";
|
|
||||||
$successMessage = "";
|
|
||||||
$errorMessage = "";
|
|
||||||
|
|
||||||
if ($_SERVER["REQUEST_METHOD"] == "POST") {
|
|
||||||
$pdo = db();
|
|
||||||
$userId = $_SESSION['user_id'];
|
|
||||||
|
|
||||||
// Album details
|
|
||||||
$artistName = trim($_POST['artist-name'] ?? 'Unknown Artist');
|
|
||||||
$albumName = trim($_POST['album-name'] ?? 'Untitled Album');
|
|
||||||
$genre = trim($_POST['genre'] ?? '');
|
|
||||||
$releaseDate = !empty($_POST['release-date']) ? $_POST['release-date'] : null;
|
|
||||||
|
|
||||||
// Handle Album Art Upload
|
|
||||||
$coverArtPath = null;
|
|
||||||
if (isset($_FILES['album-art']) && $_FILES['album-art']['error'] == UPLOAD_ERR_OK) {
|
|
||||||
$artTmpName = $_FILES['album-art']['tmp_name'];
|
|
||||||
$artName = basename($_FILES['album-art']['name']);
|
|
||||||
$artExt = pathinfo($artName, PATHINFO_EXTENSION);
|
|
||||||
$newArtName = uniqid('art_', true) . '.' . $artExt;
|
|
||||||
$coverArtPath = 'uploads/cover_art/' . $newArtName;
|
|
||||||
if (!move_uploaded_file($artTmpName, $coverArtPath)) {
|
|
||||||
$errorMessage = "Failed to upload album art.";
|
|
||||||
$coverArtPath = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle Tracks
|
|
||||||
if (empty($errorMessage) && isset($_POST['tracks']) && is_array($_POST['tracks'])) {
|
|
||||||
$tracks = $_POST['tracks'];
|
|
||||||
$files = $_FILES['tracks'];
|
|
||||||
$allSucceeded = true;
|
|
||||||
|
|
||||||
foreach ($tracks as $index => $track) {
|
|
||||||
$trackTitle = trim($track['title']);
|
|
||||||
|
|
||||||
// Restructure FILES array for easier access
|
|
||||||
$audioFile = [
|
|
||||||
'name' => $files['name']['audio_file'][$index],
|
|
||||||
'type' => $files['type']['audio_file'][$index],
|
|
||||||
'tmp_name' => $files['tmp_name']['audio_file'][$index],
|
|
||||||
'error' => $files['error']['audio_file'][$index],
|
|
||||||
'size' => $files['size']['audio_file'][$index]
|
|
||||||
];
|
|
||||||
|
|
||||||
if (!empty($trackTitle) && $audioFile['error'] == UPLOAD_ERR_OK) {
|
|
||||||
$audioTmpName = $audioFile['tmp_name'];
|
|
||||||
$audioName = basename($audioFile['name']);
|
|
||||||
$audioExt = pathinfo($audioName, PATHINFO_EXTENSION);
|
|
||||||
$newAudioName = uniqid('track_', true) . '.' . $audioExt;
|
|
||||||
$audioFilePath = 'uploads/music/' . $newAudioName;
|
|
||||||
|
|
||||||
if (move_uploaded_file($audioTmpName, $audioFilePath)) {
|
|
||||||
try {
|
|
||||||
$stmt = $pdo->prepare(
|
|
||||||
"INSERT INTO tracks (user_id, title, album, genre, release_date, file_path, cover_art_path)
|
|
||||||
VALUES (:user_id, :title, :album, :genre, :release_date, :file_path, :cover_art_path)"
|
|
||||||
);
|
|
||||||
$stmt->execute([
|
|
||||||
':user_id' => $userId,
|
|
||||||
':title' => $trackTitle,
|
|
||||||
':album' => $albumName,
|
|
||||||
':genre' => $genre,
|
|
||||||
':release_date' => $releaseDate,
|
|
||||||
':file_path' => $audioFilePath,
|
|
||||||
':cover_art_path' => $coverArtPath
|
|
||||||
]);
|
|
||||||
} catch (PDOException $e) {
|
|
||||||
$errorMessage = "Database error: " . $e->getMessage();
|
|
||||||
$allSucceeded = false;
|
|
||||||
break; // Exit loop on DB error
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$errorMessage = "Failed to move uploaded audio file for track: " . htmlspecialchars($trackTitle);
|
|
||||||
$allSucceeded = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$errorMessage = "Please provide a title and audio file for all tracks. Error code: " . $audioFile['error'];
|
|
||||||
$allSucceeded = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($allSucceeded) {
|
|
||||||
$successMessage = "Album and all tracks submitted successfully!";
|
|
||||||
}
|
|
||||||
} elseif (empty($errorMessage)) {
|
|
||||||
$errorMessage = "No tracks were submitted. Please add at least one track.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title><?php echo htmlspecialchars($pageTitle); ?></title>
|
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
|
||||||
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
|
||||||
</head>
|
|
||||||
<body class="dark-theme">
|
|
||||||
<div class="page-container">
|
|
||||||
<?php include 'partials/sidebar.php'; ?>
|
|
||||||
|
|
||||||
<main class="main-content">
|
|
||||||
<header class="main-header">
|
|
||||||
<h1>Upload Your Album</h1>
|
|
||||||
<div class="user-profile">
|
|
||||||
<i class="fa fa-user-circle"></i>
|
|
||||||
<span><?php echo htmlspecialchars($_SESSION['username']); ?></span>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<div class="content-wrapper">
|
|
||||||
<div class="upload-form-container">
|
|
||||||
<?php if ($successMessage): ?>
|
|
||||||
<div class="alert alert-success"><?php echo htmlspecialchars($successMessage); ?></div>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php if ($errorMessage): ?>
|
|
||||||
<div class="alert alert-danger"><?php echo htmlspecialchars($errorMessage); ?></div>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<form action="upload.php" method="POST" enctype="multipart/form-data" class="upload-form">
|
|
||||||
|
|
||||||
<fieldset>
|
|
||||||
<legend>Album Details</legend>
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="artist-name">Artist Name</label>
|
|
||||||
<input type="text" id="artist-name" name="artist-name" value="<?php echo htmlspecialchars($_SESSION['username']); ?>" required>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="album-name">Album Name</label>
|
|
||||||
<input type="text" id="album-name" name="album-name" placeholder="Enter the album name" required>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="album-art">Album Art</label>
|
|
||||||
<input type="file" id="album-art" name="album-art" accept="image/png, image/jpeg">
|
|
||||||
<small>Recommended: Square image, 1500x1500px. Applies to all tracks.</small>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="genre">Genre</label>
|
|
||||||
<input type="text" id="genre" name="genre" placeholder="e.g., Pop, Rock, Hip-Hop">
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="release-date">Release Date</label>
|
|
||||||
<input type="date" id="release-date" name="release-date">
|
|
||||||
</div>
|
|
||||||
</fieldset>
|
|
||||||
|
|
||||||
<fieldset>
|
|
||||||
<legend>Tracks</legend>
|
|
||||||
<div id="tracks-container">
|
|
||||||
<div class="track-input-group">
|
|
||||||
<h5>Track 1</h5>
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="track-title-0">Track Title</label>
|
|
||||||
<input type="text" id="track-title-0" name="tracks[0][title]" placeholder="Enter the track title" required>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="audio-file-0">Audio File</label>
|
|
||||||
<input type="file" id="audio-file-0" name="tracks[0][audio_file]" accept="audio/mpeg, audio/wav" required>
|
|
||||||
<small>Required: High-quality MP3 or WAV file.</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<button type="button" id="add-track-btn" class="btn btn-secondary">Add Another Track</button>
|
|
||||||
</fieldset>
|
|
||||||
|
|
||||||
<div class="form-group-checkbox">
|
|
||||||
<input type="checkbox" id="copyright-agree" name="copyright-agree" required>
|
|
||||||
<label for="copyright-agree">I confirm that I own all the rights to this music and agree to the <a href="#">distribution terms</a>.</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<button type="submit" class="btn btn-primary btn-lg">Submit Album</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
<script src="assets/js/main.js?v=<?php echo time(); ?>"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
Loading…
x
Reference in New Issue
Block a user