![]() Server : Apache/2 System : Linux server-15-235-50-60 5.15.0-164-generic #174-Ubuntu SMP Fri Nov 14 20:25:16 UTC 2025 x86_64 User : gositeme ( 1004) PHP Version : 8.2.29 Disable Function : exec,system,passthru,shell_exec,proc_close,proc_open,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname Directory : /home/gositeme/domains/soundstudiopro.com/public_html/ |
<?php
// Define development mode (set to true for debugging, false for production)
define('DEVELOPMENT_MODE', false);
// Disable error reporting in production for security
error_reporting(0);
ini_set('display_errors', 0);
session_start();
// Add security headers
header('X-Content-Type-Options: nosniff');
header('X-Frame-Options: DENY');
header('X-XSS-Protection: 1; mode=block');
header('Referrer-Policy: strict-origin-when-cross-origin');
// ALWAYS check if user is logged in - no exceptions
if (!isset($_SESSION['user_id'])) {
header('Location: /auth/login.php');
exit;
}
// Handle track edit form submission
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'update_track') {
require_once 'config/database.php';
try {
$track_id = $_POST['track_id'];
$title = trim($_POST['title']);
$description = trim($_POST['description'] ?? '');
$price = floatval($_POST['price'] ?? 0);
$is_public = isset($_POST['is_public']) ? 1 : 0;
// Validate that the track belongs to the current user
$stmt = $pdo->prepare("SELECT user_id FROM music_tracks WHERE id = ?");
$stmt->execute([$track_id]);
$track = $stmt->fetch();
if (!$track || $track['user_id'] != $_SESSION['user_id']) {
$_SESSION['error_message'] = 'You can only edit your own tracks.';
header('Location: library_fixed.php');
exit;
}
// Update the track
$stmt = $pdo->prepare("
UPDATE music_tracks
SET title = ?, description = ?, price = ?, is_public = ?, updated_at = NOW()
WHERE id = ? AND user_id = ?
");
$result = $stmt->execute([$title, $description, $price, $is_public, $track_id, $_SESSION['user_id']]);
if ($result) {
$_SESSION['success_message'] = 'Track updated successfully!';
} else {
$_SESSION['error_message'] = 'Failed to update track. Please try again.';
}
} catch (Exception $e) {
if (defined('DEVELOPMENT_MODE') && DEVELOPMENT_MODE) {
error_log("Error updating track: " . $e->getMessage());
}
$_SESSION['error_message'] = 'An error occurred while updating the track.';
}
header('Location: library_fixed.php');
exit;
}
// Helper functions for formatting
function formatBytes($bytes, $precision = 2) {
if ($bytes == 0) return '0 B';
$units = ['B', 'KB', 'MB', 'GB'];
$base = log($bytes, 1024);
$unit = $units[floor($base)];
return round(pow(1024, $base - floor($base)), $precision) . ' ' . $unit;
}
function formatTime($seconds) {
if ($seconds < 60) {
return round($seconds, 1) . 's';
} elseif ($seconds < 3600) {
$minutes = floor($seconds / 60);
$remainingSeconds = $seconds % 60;
return $minutes . 'm ' . round($remainingSeconds) . 's';
} else {
$hours = floor($seconds / 3600);
$minutes = floor(($seconds % 3600) / 60);
return $hours . 'h ' . $minutes . 'm';
}
}
// Include database configuration
require_once 'config/database.php';
// Get user info with error handling
try {
$user = getUserById($_SESSION['user_id']);
$user_name = $user['name'] ?? 'User';
} catch (Exception $e) {
if (defined('DEVELOPMENT_MODE') && DEVELOPMENT_MODE) {
error_log("Error getting user info: " . $e->getMessage());
}
$user_name = 'User';
}
$credits = $_SESSION['credits'] ?? 5;
// Get user stats
$pdo = getDBConnection();
if (!$pdo) {
if (defined('DEVELOPMENT_MODE') && DEVELOPMENT_MODE) {
error_log("Database connection failed in library_fixed.php");
}
die("Unable to connect to the database. Please try again later.");
}
$stmt = $pdo->prepare("
SELECT
COUNT(*) as total_tracks,
COUNT(CASE WHEN status = 'complete' THEN 1 END) as completed_tracks,
COUNT(CASE WHEN status = 'processing' THEN 1 END) as processing_tracks,
COUNT(CASE WHEN status = 'failed' THEN 1 END) as failed_tracks,
AVG(CASE WHEN status = 'complete' THEN duration END) as avg_duration,
SUM(CASE WHEN status = 'complete' THEN duration END) as total_duration
FROM music_tracks
WHERE user_id = ?
");
try {
$stmt->execute([$_SESSION['user_id']]);
$user_stats = $stmt->fetch();
} catch (Exception $e) {
if (defined('DEVELOPMENT_MODE') && DEVELOPMENT_MODE) {
error_log("Error getting user stats: " . $e->getMessage());
}
$user_stats = [
'total_tracks' => 0,
'completed_tracks' => 0,
'processing_tracks' => 0,
'failed_tracks' => 0,
'avg_duration' => 0,
'total_duration' => 0
];
}
// Get user's music tracks
$status_filter = $_GET['status'] ?? 'all';
$sort_filter = $_GET['sort'] ?? 'latest';
$time_filter = $_GET['time'] ?? 'all';
$genre_filter = $_GET['genre'] ?? '';
// Build WHERE clause for status filtering
$where_clause = "WHERE mt.user_id = ?";
$params = [$_SESSION['user_id']];
if ($status_filter !== 'all') {
$where_clause .= " AND mt.status = ?";
$params[] = $status_filter;
}
// Build ORDER BY clause for sorting
$order_clause = "ORDER BY ";
switch ($sort_filter) {
case 'oldest':
$order_clause .= "mt.created_at ASC";
break;
case 'popular':
$order_clause = "LEFT JOIN (SELECT track_id, COUNT(*) as like_count FROM track_likes GROUP BY track_id) likes ON mt.id = likes.track_id ORDER BY likes.like_count DESC, mt.created_at DESC";
break;
case 'most-played':
$order_clause = "LEFT JOIN (SELECT track_id, COUNT(*) as play_count FROM track_plays GROUP BY track_id) plays ON mt.id = plays.track_id ORDER BY plays.play_count DESC, mt.created_at DESC";
break;
case 'latest':
default:
$order_clause .= "mt.created_at DESC";
break;
}
// Get tracks
try {
$stmt = $pdo->prepare("
SELECT
mt.*,
COALESCE(vars.variation_count, 0) as variation_count,
CASE
WHEN mt.created_at >= DATE_SUB(NOW(), INTERVAL 1 HOUR) THEN '🔥 Hot'
WHEN mt.created_at >= DATE_SUB(NOW(), INTERVAL 24 HOUR) THEN '⭐ New'
ELSE ''
END as badge
FROM music_tracks mt
LEFT JOIN (
SELECT track_id, COUNT(*) as variation_count
FROM audio_variations
GROUP BY track_id
) vars ON mt.id = vars.track_id
$where_clause
$order_clause
");
$stmt->execute($params);
$user_tracks = $stmt->fetchAll();
} catch (Exception $e) {
if (defined('DEVELOPMENT_MODE') && DEVELOPMENT_MODE) {
error_log("Error getting user tracks: " . $e->getMessage());
}
$user_tracks = [];
}
// Get variations for each track
$tracks_with_variations = [];
foreach ($user_tracks as $track) {
$track['variations'] = [];
if ($track['variation_count'] > 0) {
try {
$stmt = $pdo->prepare("
SELECT
variation_index,
audio_url,
duration,
title,
tags,
image_url,
source_audio_url,
created_at
FROM audio_variations
WHERE track_id = ?
ORDER BY variation_index ASC
");
$stmt->execute([$track['id']]);
$track['variations'] = $stmt->fetchAll();
} catch (Exception $e) {
if (defined('DEVELOPMENT_MODE') && DEVELOPMENT_MODE) {
error_log("Error getting variations for track {$track['id']}: " . $e->getMessage());
}
$track['variations'] = [];
}
}
$tracks_with_variations[] = $track;
}
// Set page variables for header
$current_page = 'library';
$page_title = 'My Library - SoundStudioPro';
$page_description = 'Your personal music library on SoundStudioPro.';
include 'includes/header.php';
?>
<div class="main-content">
<style>
body {
padding-bottom: 120px;
}
.hero {
background: linear-gradient(135deg, rgba(102, 126, 234, 0.1), rgba(118, 75, 162, 0.1));
padding: 6rem 0 4rem;
position: relative;
overflow: hidden;
}
.hero .container {
display: flex;
align-items: center;
justify-content: space-between;
min-height: 300px;
}
.hero-content {
flex: 1;
max-width: 600px;
}
.hero-badge {
display: inline-flex;
align-items: center;
gap: 0.5rem;
background: rgba(102, 126, 234, 0.2);
color: #667eea;
padding: 0.8rem 1.5rem;
border-radius: 25px;
font-size: 1rem;
font-weight: 600;
margin-bottom: 2rem;
border: 1px solid rgba(102, 126, 234, 0.3);
}
.hero-title {
font-size: 3rem;
font-weight: 800;
margin-bottom: 1.5rem;
background: linear-gradient(135deg, #667eea, #764ba2);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
line-height: 1.2;
}
.hero-subtitle {
font-size: 1.1rem;
color: #a0aec0;
line-height: 1.6;
margin-bottom: 2rem;
}
.hero-visual {
flex: 1;
max-width: 400px;
height: 300px;
position: relative;
}
.floating-elements {
position: relative;
height: 100%;
width: 100%;
}
.floating-note {
position: absolute;
font-size: 2.5rem;
color: rgba(102, 126, 234, 0.4);
animation: float 8s ease-in-out infinite;
user-select: none;
pointer-events: none;
}
.floating-note:nth-child(1) {
top: 20%;
left: 10%;
animation-delay: 0s;
font-size: 3rem;
}
.floating-note:nth-child(2) {
top: 60%;
right: 15%;
animation-delay: 1.6s;
font-size: 2.5rem;
}
.floating-note:nth-child(3) {
bottom: 30%;
left: 20%;
animation-delay: 3.2s;
font-size: 2.8rem;
}
.floating-note:nth-child(4) {
top: 40%;
right: 30%;
animation-delay: 4.8s;
font-size: 2.2rem;
}
.floating-note:nth-child(5) {
bottom: 60%;
left: 50%;
animation-delay: 6.4s;
font-size: 2.6rem;
}
@keyframes float {
0%, 100% {
transform: translateY(0px) rotate(0deg);
opacity: 0.4;
}
25% {
transform: translateY(-15px) rotate(5deg);
opacity: 0.7;
}
50% {
transform: translateY(-25px) rotate(10deg);
opacity: 1;
}
75% {
transform: translateY(-15px) rotate(5deg);
opacity: 0.7;
}
}
.empty-state {
text-align: center;
padding: 4rem 2rem;
background: linear-gradient(135deg,
rgba(0, 0, 0, 0.3) 0%,
rgba(15, 15, 25, 0.4) 100%);
border-radius: 20px;
border: 1px solid rgba(102, 126, 234, 0.2);
margin: 2rem 0;
}
.empty-icon {
font-size: 4rem;
color: #667eea;
margin-bottom: 1rem;
opacity: 0.7;
}
.empty-title {
font-size: 1.5rem;
font-weight: 700;
color: #e2e8f0;
margin-bottom: 1rem;
}
.empty-description {
color: #a0aec0;
margin-bottom: 2rem;
line-height: 1.6;
}
.create-first-btn {
background: linear-gradient(135deg, #667eea, #764ba2);
color: white;
border: none;
padding: 1rem 2rem;
border-radius: 12px;
font-size: 1rem;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
text-decoration: none;
display: inline-flex;
align-items: center;
gap: 0.5rem;
}
.create-first-btn:hover {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(102, 126, 234, 0.4);
}
.track-card {
background: linear-gradient(145deg,
rgba(15, 15, 35, 0.95) 0%,
rgba(25, 25, 45, 0.9) 50%,
rgba(35, 35, 55, 0.85) 100%);
border: 1px solid rgba(102, 126, 234, 0.2);
border-radius: 24px;
padding: 1.5rem;
margin-bottom: 2rem;
transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
overflow: hidden;
position: relative;
backdrop-filter: blur(20px);
box-shadow:
0 8px 32px rgba(0, 0, 0, 0.3),
0 2px 16px rgba(102, 126, 234, 0.1),
inset 0 1px 0 rgba(255, 255, 255, 0.1);
}
.track-card:hover {
transform: translateY(-8px) scale(1.02);
border-color: rgba(102, 126, 234, 0.5);
box-shadow:
0 20px 60px rgba(0, 0, 0, 0.4),
0 8px 40px rgba(102, 126, 234, 0.3),
inset 0 1px 0 rgba(255, 255, 255, 0.2);
}
.track-title {
font-size: 1.6rem;
font-weight: 800;
margin-bottom: 1rem;
background: linear-gradient(135deg, #e2e8f0, #f7fafc);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
line-height: 1.3;
}
.track-prompt {
padding: 1rem 1.5rem;
background: linear-gradient(135deg,
rgba(0, 0, 0, 0.3) 0%,
rgba(15, 15, 25, 0.4) 100%);
border-left: 3px solid #667eea;
margin: 1rem 1.5rem;
border-radius: 0 8px 8px 0;
font-size: 0.95rem;
line-height: 1.5;
color: #cbd5e0;
font-style: italic;
position: relative;
}
.track-prompt::before {
content: '"';
position: absolute;
left: -0.5rem;
top: -0.5rem;
font-size: 2rem;
color: #667eea;
font-weight: bold;
}
.track-metadata {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
gap: 1rem;
padding: 1.5rem;
background: linear-gradient(135deg,
rgba(0, 0, 0, 0.2) 0%,
rgba(15, 15, 25, 0.3) 100%);
border-top: 1px solid rgba(255, 255, 255, 0.05);
}
.metadata-item {
text-align: center;
padding: 0.8rem;
background: rgba(255, 255, 255, 0.03);
border-radius: 12px;
border: 1px solid rgba(255, 255, 255, 0.05);
transition: all 0.3s ease;
}
.metadata-item:hover {
background: rgba(102, 126, 234, 0.1);
border-color: rgba(102, 126, 234, 0.3);
transform: translateY(-2px);
}
.metadata-label {
font-size: 0.7rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 1px;
color: #a0aec0;
margin-bottom: 0.3rem;
}
.metadata-value {
font-size: 1rem;
font-weight: 800;
color: #e2e8f0;
}
.track-actions {
display: flex;
gap: 1rem;
margin-top: 1.5rem;
flex-wrap: wrap;
}
.action-btn {
background: linear-gradient(135deg, rgba(102, 126, 234, 0.2), rgba(118, 75, 162, 0.2));
border: 1px solid rgba(102, 126, 234, 0.4);
color: #667eea;
padding: 1rem 1.8rem;
border-radius: 12px;
font-size: 1rem;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
backdrop-filter: blur(10px);
display: flex;
align-items: center;
gap: 0.6rem;
min-width: 120px;
justify-content: center;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
.action-btn:hover {
background: linear-gradient(135deg, rgba(102, 126, 234, 0.3), rgba(118, 75, 162, 0.3));
border-color: rgba(102, 126, 234, 0.6);
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
}
.action-btn.primary {
background: linear-gradient(135deg, #667eea, #764ba2);
border-color: #667eea;
color: white;
}
.action-btn.primary:hover {
background: linear-gradient(135deg, #5a67d8, #6b46c1);
transform: translateY(-3px);
box-shadow: 0 8px 25px rgba(102, 126, 234, 0.4);
}
.status-indicator {
margin-top: 0.5rem;
}
.status-complete {
background: linear-gradient(135deg, #48bb78, #38a169);
color: white;
padding: 0.3rem 0.8rem;
border-radius: 12px;
font-size: 0.7rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.5px;
box-shadow: 0 2px 8px rgba(72, 187, 120, 0.3);
}
.status-processing {
background: linear-gradient(135deg, #f59e0b, #d97706);
color: white;
padding: 0.3rem 0.8rem;
border-radius: 12px;
font-size: 0.7rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.5px;
box-shadow: 0 2px 8px rgba(245, 158, 11, 0.3);
}
.status-failed {
background: linear-gradient(135deg, #ef4444, #dc2626);
color: white;
padding: 0.3rem 0.8rem;
border-radius: 12px;
font-size: 0.7rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.5px;
box-shadow: 0 2px 8px rgba(239, 68, 68, 0.3);
}
.unified-filters {
background: linear-gradient(135deg, rgba(15, 15, 35, 0.95), rgba(25, 25, 45, 0.9));
border: 1px solid rgba(102, 126, 234, 0.2);
border-radius: 16px;
padding: 1.5rem;
margin: 2rem 0;
backdrop-filter: blur(20px);
}
.filter-row {
display: flex;
gap: 1.5rem;
align-items: center;
flex-wrap: wrap;
}
.filter-group {
display: flex;
flex-direction: column;
gap: 0.5rem;
min-width: 150px;
}
.filter-label {
font-size: 0.9rem;
color: #a0aec0;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.filter-select {
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 8px;
color: white;
padding: 0.8rem 1rem;
font-size: 1rem;
transition: all 0.3s ease;
cursor: pointer;
}
.filter-select:hover {
border-color: rgba(102, 126, 234, 0.3);
background: rgba(255, 255, 255, 0.08);
}
.filter-select:focus {
outline: none;
border-color: #667eea;
box-shadow: 0 0 0 2px rgba(102, 126, 234, 0.2);
}
.community-stats {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 2rem;
margin-bottom: 4rem;
}
.stat-card {
background: rgba(255, 255, 255, 0.05);
border-radius: 16px;
padding: 2rem;
text-align: center;
border: 1px solid rgba(255, 255, 255, 0.1);
}
.stat-number {
font-size: 2.5rem;
font-weight: 700;
color: #667eea;
margin-bottom: 0.5rem;
}
.stat-label {
color: #a0aec0;
font-size: 1.1rem;
}
.tracks-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
gap: 2rem;
}
@media (max-width: 768px) {
.hero {
padding: 4rem 0 2rem;
}
.hero .container {
flex-direction: column;
text-align: center;
min-height: auto;
}
.hero-content {
max-width: 100%;
margin-bottom: 2rem;
}
.hero-title {
font-size: 2.5rem;
}
.filter-row {
flex-direction: column;
align-items: stretch;
}
.track-actions {
flex-direction: column;
}
.action-btn {
justify-content: center;
}
.tracks-grid {
grid-template-columns: 1fr;
}
}
</style>
<!-- Hero Section -->
<section class="hero">
<div class="container">
<div class="hero-content">
<div class="hero-badge">
<i class="fas fa-music"></i>
Your Music Library
</div>
<h1 class="hero-title">Your Studio Collection</h1>
<p class="hero-subtitle">Manage, play, and share your AI-generated tracks. Every creation is a masterpiece waiting to be discovered.</p>
</div>
<div class="hero-visual">
<div class="floating-elements">
<div class="floating-note">♪</div>
<div class="floating-note">♫</div>
<div class="floating-note">♬</div>
<div class="floating-note">🎵</div>
<div class="floating-note">🎶</div>
</div>
</div>
</div>
</section>
<!-- Success/Error Messages -->
<?php if (isset($_SESSION['success_message'])): ?>
<div class="alert alert-success" style="margin: 1rem; padding: 1rem; background: #d4edda; color: #155724; border: 1px solid #c3e6cb; border-radius: 8px;">
<?= htmlspecialchars($_SESSION['success_message']) ?>
</div>
<?php unset($_SESSION['success_message']); ?>
<?php endif; ?>
<?php if (isset($_SESSION['error_message'])): ?>
<div class="alert alert-error" style="margin: 1rem; padding: 1rem; background: #f8d7da; color: #721c24; border: 1px solid #f5c6cb; border-radius: 8px;">
<?= htmlspecialchars($_SESSION['error_message']) ?>
</div>
<?php unset($_SESSION['error_message']); ?>
<?php endif; ?>
<!-- Library Content -->
<section class="community-content">
<div class="container">
<!-- Library Stats -->
<div class="community-stats">
<div class="stat-card">
<div class="stat-number"><?= $user_stats['total_tracks'] ?></div>
<div class="stat-label">Total Tracks</div>
</div>
<div class="stat-card">
<div class="stat-number"><?= $user_stats['completed_tracks'] ?></div>
<div class="stat-label">Completed</div>
</div>
<div class="stat-card">
<div class="stat-number"><?= $user_stats['processing_tracks'] ?></div>
<div class="stat-label">Processing</div>
</div>
<div class="stat-card">
<div class="stat-number"><?= $credits ?></div>
<div class="stat-label">Credits Left</div>
</div>
</div>
<!-- Unified Filter Controls -->
<div class="unified-filters">
<div class="filter-row">
<div class="filter-group">
<label class="filter-label">Status:</label>
<select name="status" class="filter-select" onchange="filterTracks()">
<option value="all" <?= $status_filter === 'all' ? 'selected' : '' ?>>All Tracks</option>
<option value="complete" <?= $status_filter === 'complete' ? 'selected' : '' ?>>Completed</option>
<option value="processing" <?= $status_filter === 'processing' ? 'selected' : '' ?>>Processing</option>
<option value="failed" <?= $status_filter === 'failed' ? 'selected' : '' ?>>Failed</option>
</select>
</div>
<div class="filter-group">
<label class="filter-label">Sort By:</label>
<select name="sort" class="filter-select" onchange="filterTracks()">
<option value="latest" <?= $sort_filter === 'latest' ? 'selected' : '' ?>>Latest First</option>
<option value="oldest" <?= $sort_filter === 'oldest' ? 'selected' : '' ?>>Oldest First</option>
<option value="popular" <?= $sort_filter === 'popular' ? 'selected' : '' ?>>Most Popular</option>
<option value="most-played" <?= $sort_filter === 'most-played' ? 'selected' : '' ?>>Most Played</option>
</select>
</div>
</div>
</div>
<!-- Tracks Grid -->
<div class="tracks-grid">
<?php if (empty($tracks_with_variations)): ?>
<div class="empty-state" style="grid-column: 1 / -1;">
<div class="empty-icon">🎵</div>
<h2 class="empty-title">No Tracks Yet</h2>
<p class="empty-description">
Start creating your first AI-generated track and build your music library.
</p>
<a href="/#create" class="create-first-btn">
<i class="fas fa-plus"></i>
Create Your First Track
</a>
</div>
<?php else: ?>
<?php foreach ($tracks_with_variations as $track):
$displayTitle = $track['title'] ?: 'Untitled Track';
$duration = floor($track['duration'] / 60) . 'm ' . ($track['duration'] % 60) . 's';
$created_date = date('M j, Y', strtotime($track['created_at']));
$error_message = $track['error_message'] ?? null;
?>
<div class="track-card" data-track-id="<?= $track['id'] ?>" data-status="<?= $track['status'] ?>">
<!-- Track Header -->
<div class="track-header">
<h2 class="track-title"><?= htmlspecialchars($displayTitle) ?></h2>
<!-- Status Badge -->
<?php if ($track['badge']): ?>
<div class="track-badge"><?= $track['badge'] ?></div>
<?php endif; ?>
<!-- Status Indicator -->
<div class="status-indicator">
<?php if ($track['status'] === 'complete'): ?>
<span class="status-complete">Complete</span>
<?php elseif ($track['status'] === 'processing'): ?>
<span class="status-processing">Processing</span>
<?php elseif ($track['status'] === 'failed'): ?>
<span class="status-failed">Failed</span>
<?php endif; ?>
</div>
</div>
<!-- Track Prompt -->
<?php if ($track['prompt']): ?>
<div class="track-prompt">
<?= htmlspecialchars($track['prompt']) ?>
</div>
<?php endif; ?>
<!-- Error Message for Failed Tracks -->
<?php if ($track['status'] === 'failed' && $error_message): ?>
<div class="error-message-modern">
<div class="error-header">
<i class="fas fa-exclamation-triangle"></i>
<strong>Error Details:</strong>
</div>
<div class="error-content">
<?= htmlspecialchars($error_message) ?>
</div>
</div>
<?php endif; ?>
<!-- Track Metadata -->
<div class="track-metadata">
<div class="metadata-item">
<div class="metadata-label">Duration</div>
<div class="metadata-value"><?= $duration ?></div>
</div>
<div class="metadata-item">
<div class="metadata-label">Created</div>
<div class="metadata-value"><?= $created_date ?></div>
</div>
<?php if ($track['variation_count'] > 0): ?>
<div class="metadata-item">
<div class="metadata-label">Variations</div>
<div class="metadata-value"><?= $track['variation_count'] ?></div>
</div>
<?php endif; ?>
</div>
<!-- Track Actions -->
<div class="track-actions">
<?php if ($track['status'] === 'complete'): ?>
<button class="action-btn primary" onclick="playTrack(<?= $track['id'] ?>, '<?= addslashes($track['audio_url']) ?>', '<?= addslashes($displayTitle) ?>', '<?= addslashes($user_name) ?>')">
<i class="fas fa-play"></i>
<span>Play</span>
</button>
<button class="action-btn" onclick="downloadTrack(<?= $track['id'] ?>)">
<i class="fas fa-download"></i>
<span>Download</span>
</button>
<?php if ($track['variation_count'] > 0): ?>
<button class="action-btn" onclick="showVariations(<?= $track['id'] ?>)">
<i class="fas fa-layer-group"></i>
<span>Variations</span>
</button>
<?php endif; ?>
<?php elseif ($track['status'] === 'processing'): ?>
<button class="action-btn" onclick="checkTrackStatus(<?= $track['id'] ?>)">
<i class="fas fa-sync-alt"></i>
<span>Check Status</span>
</button>
<?php elseif ($track['status'] === 'failed'): ?>
<button class="action-btn primary" onclick="retryTrack(<?= $track['id'] ?>)">
<i class="fas fa-redo"></i>
<span>Retry</span>
</button>
<button class="action-btn" onclick="deleteFailedTrack(<?= $track['id'] ?>)">
<i class="fas fa-trash"></i>
<span>Delete</span>
</button>
<?php endif; ?>
<?php if ($track['user_id'] == $_SESSION['user_id']): ?>
<button class="action-btn" onclick="editTrack(<?= $track['id'] ?>, '<?= addslashes($track['title']) ?>', '<?= addslashes($track['description'] ?? '') ?>', '<?= addslashes($track['price'] ?? '0') ?>', <?= $track['is_public'] ?? 0 ?>)">
<i class="fas fa-edit"></i>
<span>Edit</span>
</button>
<?php endif; ?>
</div>
</div>
<?php endforeach; ?>
<?php endif; ?>
</div>
</div>
</section>
</div>
<script>
// Basic functionality for the library page
function filterTracks() {
const statusFilter = document.querySelector('select[name="status"]').value;
const sortFilter = document.querySelector('select[name="sort"]').value;
const url = new URL(window.location);
url.searchParams.set('status', statusFilter);
url.searchParams.set('sort', sortFilter);
window.location.href = url.toString();
}
function playTrack(trackId, audioUrl, title, artist) {
console.log('Playing track:', { trackId, audioUrl, title, artist });
// Check if global player exists
if (window.enhancedGlobalPlayer && typeof window.enhancedGlobalPlayer.playTrack === 'function') {
window.enhancedGlobalPlayer.playTrack(audioUrl, title, artist, trackId);
showNotification('🎵 Now playing: ' + title, 'success');
} else {
showNotification('Audio player not ready. Please refresh the page.', 'error');
}
}
function downloadTrack(trackId) {
console.log('Downloading track:', trackId);
showNotification('Download feature coming soon!', 'info');
}
function showVariations(trackId) {
console.log('Showing variations for track:', trackId);
showNotification('Variations feature coming soon!', 'info');
}
function checkTrackStatus(trackId) {
console.log('Checking status for track:', trackId);
showNotification('Status check feature coming soon!', 'info');
}
function retryTrack(trackId) {
console.log('Retrying track:', trackId);
showNotification('Retry feature coming soon!', 'info');
}
function deleteFailedTrack(trackId) {
if (confirm('Are you sure you want to delete this failed track?')) {
console.log('Deleting failed track:', trackId);
showNotification('Delete feature coming soon!', 'info');
}
}
function editTrack(trackId, title, description, price, isPublic) {
console.log('Editing track:', { trackId, title, description, price, isPublic });
showNotification('Edit feature coming soon!', 'info');
}
function showNotification(message, type = 'info') {
// Simple notification system
const notification = document.createElement('div');
notification.style.cssText = `
position: fixed;
top: 20px;
right: 20px;
background: ${type === 'success' ? '#48bb78' : type === 'error' ? '#ef4444' : '#667eea'};
color: white;
padding: 1rem 1.5rem;
border-radius: 8px;
font-weight: 600;
z-index: 10000;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
`;
notification.textContent = message;
document.body.appendChild(notification);
setTimeout(() => {
if (notification.parentElement) {
notification.remove();
}
}, 3000);
}
// Initialize when page loads
document.addEventListener('DOMContentLoaded', function() {
console.log('Library page loaded successfully');
});
</script>
<?php include 'includes/footer.php'; ?>