diff --git a/admin/auth.php b/admin/auth.php new file mode 100644 index 0000000..3020bb3 --- /dev/null +++ b/admin/auth.php @@ -0,0 +1,9 @@ +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 = "
CSV file has been successfully uploaded and processed.
"; + } else { + $message = "
Error uploading file.
"; + } +} + +// 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']; +} + +?> + + + + + + <?php echo $pageTitle; ?> - Zeal Music + + + + + +
+ +
+ + +
+
+
+

Upload CSV for Music Monitoring

+
+
+ +

Select a CSV file containing music monitoring data to upload. The file should contain columns for Track ID, Play Count, and Date.

+
+
+ + +
+ +
+
+
+
+ +
+
+
+

Monitoring Data Overview

+
+
+ +
+
+
+ +
+
+
+

Raw Monitoring Data

+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
Track TitlePlaysDate
No monitoring data found.
+
+
+
+ +
+
+ + + + \ No newline at end of file diff --git a/admin/packages.php b/admin/packages.php new file mode 100644 index 0000000..f43c812 --- /dev/null +++ b/admin/packages.php @@ -0,0 +1,122 @@ +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); + +?> + + + + + + <?php echo htmlspecialchars($pageTitle); ?> + + + + +
+ +
+
+

+
+
+
+

Add New Package

+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+
+ +
+

Existing Packages

+
+ + + + + + + + + + + + + + + + + + + + + +
NamePriceFeaturesRecommendedActions
$ +
+ + +
+
+
+
+
+
+
+ + diff --git a/admin/stations.php b/admin/stations.php new file mode 100644 index 0000000..41aa6eb --- /dev/null +++ b/admin/stations.php @@ -0,0 +1,151 @@ +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(); +} + +?> + + + + + + <?php echo htmlspecialchars($pageTitle); ?> + + + + +
+ + + + +
+
+

Manage Radio Stations

+ +
+ +
+ ".htmlspecialchars($successMessage)."
"; ?> + ".htmlspecialchars($error)."
"; ?> + + +
+

Add New Station

+
+ +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+
+
+
+ + +
+

Existing Stations

+ + + + + + + + + + + + + + + + + + + + + + + + + +
NameEmailGenresWebsiteActions
No stations found.
+
+ + + +
+
+
+ + + + + diff --git a/admin/users.php b/admin/users.php new file mode 100644 index 0000000..d61e112 --- /dev/null +++ b/admin/users.php @@ -0,0 +1,157 @@ +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(); +} + +?> + + + + + + <?php echo htmlspecialchars($pageTitle); ?> + + + + +
+ + + + +
+
+

Manage Users

+ +
+ +
+ ".htmlspecialchars($successMessage)."
"; ?> + ".htmlspecialchars($error)."
"; ?> + + +
+

Add New User

+
+ +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+
+
+
+ + +
+

Existing Users

+ + + + + + + + + + + + + + + + + + + + + + + +
UsernameEmailRoleActions
No users found.
+
+ + + +
+
+
+ + + + + diff --git a/assets/css/custom.css b/assets/css/custom.css new file mode 100644 index 0000000..5653eb5 --- /dev/null +++ b/assets/css/custom.css @@ -0,0 +1,504 @@ + +/* 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; +} + diff --git a/assets/js/main.js b/assets/js/main.js new file mode 100644 index 0000000..fc9f106 --- /dev/null +++ b/assets/js/main.js @@ -0,0 +1,29 @@ +// 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 = ` +
+
+
Track ${trackIndex + 1}
+
+ + +
+
+ + +
+
+ `; + tracksContainer.insertAdjacentHTML('beforeend', trackHtml); + trackIndex++; + }); + } +}); \ No newline at end of file diff --git a/auth.php b/auth.php new file mode 100644 index 0000000..2672304 --- /dev/null +++ b/auth.php @@ -0,0 +1,14 @@ +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(); +} + +?> + + + + + + <?php echo htmlspecialchars($pageTitle); ?> + + + + + +
+ + +
+
+

Collaboration Feed

+ +
+ +
+ ".htmlspecialchars($successMessage)."
"; ?> + ".htmlspecialchars($error)."
"; ?> + + +
+

Create a New Collaboration Post

+
+ +
+ + +
+
+ + +
+
+ +
+
+
+ + +
+

Open Collaborations

+ +

No open collaborations at the moment. Why not start one?

+ +
+

+ +

+
+ +
+ + + + + + diff --git a/dashboard.php b/dashboard.php new file mode 100644 index 0000000..e78da6d --- /dev/null +++ b/dashboard.php @@ -0,0 +1,124 @@ +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"; +?> + + + + + + <?php echo htmlspecialchars($pageTitle); ?> + + + + +
+ + + + +
+
+

Welcome Back,

+ +
+ +
+ +
+
+
+
Total Plays
+

1.2M

+
+
+
+
+
Listeners (30 days)
+

89.4K

+
+
+
+
+
Engagements
+

12.1K

+
+
+
+ + +
+
+

My Tracks

+ + Upload Music + +
+ + +
+

No tracks have been uploaded yet.

+ + Upload Your First Track + +
+ + $track): + ?> +
+
+ Cover Art +
+
+ +
+
+
+
0 plays
+
+ + +
+
+
+
+ + + + \ No newline at end of file diff --git a/db/migrate.php b/db/migrate.php new file mode 100644 index 0000000..5c3a838 --- /dev/null +++ b/db/migrate.php @@ -0,0 +1,34 @@ +exec($sql); + echo "Success.\n"; + } + + echo "\nAll migrations completed.\n"; + + } catch (PDOException $e) { + die("Database migration failed: " . $e->getMessage() . "\n"); + } +} + +run_migrations(); + diff --git a/db/migrations/001_create_users_table.sql b/db/migrations/001_create_users_table.sql new file mode 100644 index 0000000..eca9742 --- /dev/null +++ b/db/migrations/001_create_users_table.sql @@ -0,0 +1,10 @@ +-- 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; diff --git a/db/migrations/002_create_stations_table.sql b/db/migrations/002_create_stations_table.sql new file mode 100644 index 0000000..3babb69 --- /dev/null +++ b/db/migrations/002_create_stations_table.sql @@ -0,0 +1,10 @@ +-- 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; diff --git a/db/migrations/003_create_collaborations_table.sql b/db/migrations/003_create_collaborations_table.sql new file mode 100644 index 0000000..98dbdac --- /dev/null +++ b/db/migrations/003_create_collaborations_table.sql @@ -0,0 +1,11 @@ +-- 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; diff --git a/db/migrations/004_create_tracks_table.sql b/db/migrations/004_create_tracks_table.sql new file mode 100644 index 0000000..7f2f69a --- /dev/null +++ b/db/migrations/004_create_tracks_table.sql @@ -0,0 +1,12 @@ +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 +); diff --git a/db/migrations/005_create_packages_table.sql b/db/migrations/005_create_packages_table.sql new file mode 100644 index 0000000..5f2d9f6 --- /dev/null +++ b/db/migrations/005_create_packages_table.sql @@ -0,0 +1,8 @@ +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 +); \ No newline at end of file diff --git a/db/migrations/006_create_monitoring_data_table.sql b/db/migrations/006_create_monitoring_data_table.sql new file mode 100644 index 0000000..8ef28cb --- /dev/null +++ b/db/migrations/006_create_monitoring_data_table.sql @@ -0,0 +1,8 @@ +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 +); \ No newline at end of file diff --git a/db/migrations/007_add_package_id_to_users.sql b/db/migrations/007_add_package_id_to_users.sql new file mode 100644 index 0000000..02ba574 --- /dev/null +++ b/db/migrations/007_add_package_id_to_users.sql @@ -0,0 +1 @@ +ALTER TABLE users ADD COLUMN package_id INT NULL; \ No newline at end of file diff --git a/index.php b/index.php index 7205f3d..bc096b5 100644 --- a/index.php +++ b/index.php @@ -1,150 +1,8 @@ - - - - - - New Style - - - - - - - - - - - - - - - - - - - - - -
-
-

Analyzing your requirements and generating your website…

-
- Loading… -
-

AI is collecting your requirements and applying the first changes.

-

This page will update automatically as the plan is implemented.

-

Runtime: PHP — UTC

-
-
- - - +if (is_logged_in()) { + require 'dashboard.php'; +} else { + require 'landing.php'; +} \ No newline at end of file diff --git a/landing.php b/landing.php new file mode 100644 index 0000000..561db1d --- /dev/null +++ b/landing.php @@ -0,0 +1,89 @@ + +query("SELECT * FROM packages ORDER BY price"); +$packages = $stmt->fetchAll(PDO::FETCH_ASSOC); +?> + + + + + + Zeal Music - Unleash Your Music's Potential + + + + +
+
+ + +
+ +
+
+
+

Unleash Your Music's Potential

+

The ultimate platform for artists to manage, distribute, and monetize their work.

+ Get Started Now +
+
+ +
+

Why Zeal Music?

+
+
+ +

Detailed Analytics

+

Gain deep insights into your listeners and track performance across all platforms.

+
+
+ +

Direct Uploads

+

Easily upload your tracks, albums, and cover art with our streamlined process.

+
+
+ +

Global Reach

+

Distribute your music to major streaming services and digital stores worldwide.

+
+
+
+ +
+

Choose Your Plan

+

Simple, transparent pricing. No hidden fees.

+
+ +
+

+

$/month

+
    + +
  • + +
+ Select Plan +
+ +
+
+
+ + +
+ + + diff --git a/login.php b/login.php new file mode 100644 index 0000000..f006423 --- /dev/null +++ b/login.php @@ -0,0 +1,101 @@ +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(); + } + } +} +?> + + + + + + <?php echo htmlspecialchars($pageTitle); ?> + + + + +
+ + +
+
+
+

Log In to Your Account

+
+ +
+ + +
+
+ + +
+ +
+ + +
+ +
+ +
+

+ Don't have an account? Register Now +

+
+
+
+
+
+ + diff --git a/logout.php b/logout.php new file mode 100644 index 0000000..766a593 --- /dev/null +++ b/logout.php @@ -0,0 +1,6 @@ + + diff --git a/register.php b/register.php new file mode 100644 index 0000000..9f70372 --- /dev/null +++ b/register.php @@ -0,0 +1,143 @@ +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 log in."; + } catch (PDOException $e) { + $errors[] = "Database error during registration: " . $e->getMessage(); + } + } +} +?> + + + + + + <?php echo htmlspecialchars($pageTitle); ?> + + + + +
+ + + + +
+
+
+

Create Your Artist Account

+
+ +
+ + + +
+ +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ +
+ +
+ + +
+ +
+
+ +
+ +
+

+ Already have an account? Log In +

+
+ +
+
+
+
+ + \ No newline at end of file diff --git a/upload.php b/upload.php new file mode 100644 index 0000000..ff7ffa7 --- /dev/null +++ b/upload.php @@ -0,0 +1,190 @@ + $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."; + } +} +?> + + + + + + <?php echo htmlspecialchars($pageTitle); ?> + + + + +
+ + +
+
+

Upload Your Album

+ +
+ +
+
+ +
+ + +
+ + +
+ +
+ Album Details +
+ + +
+
+ + +
+
+ + + Recommended: Square image, 1500x1500px. Applies to all tracks. +
+
+ + +
+
+ + +
+
+ +
+ Tracks +
+
+
Track 1
+
+ + +
+
+ + + Required: High-quality MP3 or WAV file. +
+
+
+ +
+ +
+ + +
+ +
+ +
+
+
+
+
+
+ + + \ No newline at end of file