![]() 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/private_html/ |
<?php
session_start();
require_once 'config/database.php';
require_once 'includes/translations.php';
// Debug session
error_log("🛒 Session ID: " . session_id());
error_log("🛒 Session status: " . session_status());
error_log("🛒 Request method: " . $_SERVER['REQUEST_METHOD']);
// Initialize cart if not exists
if (!isset($_SESSION['cart'])) {
$_SESSION['cart'] = [];
error_log("🛒 Initialized new cart session");
} else {
error_log("🛒 Existing cart found with " . count($_SESSION['cart']) . " items");
}
// Handle POST requests (add to cart, etc.)
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Set JSON header for all POST responses
header('Content-Type: application/json');
// Prevent any output before JSON (if output buffering is active)
if (ob_get_level() > 0) {
ob_clean();
}
try {
$pdo = getDBConnection();
$action = $_POST['action'] ?? '';
switch ($action) {
case 'add':
$track_id = intval($_POST['track_id'] ?? 0);
$artist_plan = $_POST['artist_plan'] ?? 'free';
if (!$track_id) {
echo json_encode(['success' => false, 'message' => 'Invalid track ID']);
exit;
}
// Get track information with artist details
$stmt = $pdo->prepare("
SELECT mt.*, u.name as artist_name, u.plan as user_plan, u.id as artist_id
FROM music_tracks mt
JOIN users u ON mt.user_id = u.id
WHERE mt.id = ? AND mt.status = 'complete'
");
$stmt->execute([$track_id]);
$track = $stmt->fetch();
if (!$track) {
echo json_encode(['success' => false, 'message' => 'Track not found']);
exit;
}
// Prevent artists from buying their own tracks
if (isset($_SESSION['user_id']) && $_SESSION['user_id'] == $track['artist_id']) {
echo json_encode([
'success' => false,
'message' => t('cart.error.own_track') ?? 'You cannot purchase your own track',
'own_track' => true
]);
exit;
}
// Determine revenue recipient based on artist plan
$is_free_user = (strtolower($track['user_plan']) === 'free');
$revenue_recipient = $is_free_user ? 'platform' : 'artist';
$recipient_id = $is_free_user ? 1 : $track['artist_id']; // Admin ID = 1
// Check if user has already purchased this track
if (isset($_SESSION['user_id'])) {
$purchase_check = $pdo->prepare("
SELECT id FROM track_purchases
WHERE user_id = ? AND track_id = ?
");
$purchase_check->execute([$_SESSION['user_id'], $track_id]);
$existing_purchase = $purchase_check->fetch();
if ($existing_purchase) {
// Calculate current cart count
$total_cart_count = 0;
if (isset($_SESSION['cart']) && !empty($_SESSION['cart'])) {
foreach ($_SESSION['cart'] as $item) {
$total_cart_count += $item['quantity'] ?? 1;
}
}
if (isset($_SESSION['credit_cart']) && !empty($_SESSION['credit_cart'])) {
foreach ($_SESSION['credit_cart'] as $item) {
$total_cart_count += $item['quantity'] ?? 1;
}
}
echo json_encode([
'success' => false,
'message' => 'You have already purchased this track. Check your purchases library.',
'already_purchased' => true,
'cart_count' => $total_cart_count
]);
exit;
}
}
// Check if track already in cart - prevent duplicate addition (only 1 license per track)
$found = false;
foreach ($_SESSION['cart'] as $item) {
if (isset($item['track_id']) && $item['track_id'] == $track_id) {
$found = true;
break;
}
}
if ($found) {
// Track already in cart - return error (don't increment quantity)
// Calculate current cart count
$total_cart_count = 0;
if (isset($_SESSION['cart']) && !empty($_SESSION['cart'])) {
foreach ($_SESSION['cart'] as $item) {
$total_cart_count += $item['quantity'] ?? 1;
}
}
if (isset($_SESSION['credit_cart']) && !empty($_SESSION['credit_cart'])) {
foreach ($_SESSION['credit_cart'] as $item) {
$total_cart_count += $item['quantity'] ?? 1;
}
}
echo json_encode([
'success' => false,
'message' => t('cart.error.already_in_cart'),
'already_in_cart' => true,
'cart_count' => $total_cart_count
]);
exit;
}
// Track not in cart - add it with quantity = 1 (only 1 license per track)
$_SESSION['cart'][] = [
'track_id' => $track_id,
'title' => $track['title'],
'artist_name' => $track['artist_name'],
'artist_id' => $track['artist_id'],
'price' => floatval($track['price']),
'quantity' => 1, // Always 1 - only one license per track
'audio_url' => $track['audio_url'],
'user_plan' => $track['user_plan'],
'revenue_recipient' => $revenue_recipient,
'recipient_id' => $recipient_id,
'is_free_user_track' => $is_free_user,
'type' => 'track'
];
// Log the cart addition and current cart state
error_log("🛒 Track added to cart: ID $track_id, Price: $" . $track['price'] . ", Revenue goes to: $revenue_recipient (ID: $recipient_id)");
error_log("🛒 Artist name: " . ($track['artist_name'] ?? 'NULL'));
error_log("🛒 Artist ID: " . ($track['artist_id'] ?? 'NULL'));
error_log("🛒 Cart now contains: " . count($_SESSION['cart']) . " items");
error_log("🛒 Full cart: " . json_encode($_SESSION['cart']));
// Explicitly save session
session_write_close();
session_start();
// Calculate total cart count (music + credits) - sum quantities like header does
$total_cart_count = 0;
// Count music cart items (sum quantities)
if (isset($_SESSION['cart']) && !empty($_SESSION['cart'])) {
foreach ($_SESSION['cart'] as $item) {
$total_cart_count += $item['quantity'];
}
}
// Count credit cart items (sum quantities)
if (isset($_SESSION['credit_cart']) && !empty($_SESSION['credit_cart'])) {
foreach ($_SESSION['credit_cart'] as $item) {
$total_cart_count += $item['quantity'];
}
}
echo json_encode([
'success' => true,
'message' => 'Track added to cart',
'cart_count' => $total_cart_count,
'cart_total' => array_sum(array_map(function($item) {
return $item['price'] * $item['quantity'];
}, $_SESSION['cart'])),
'debug' => [
'session_id' => session_id(),
'total_items' => $total_cart_count,
'track_added' => $track_id
],
'revenue_info' => [
'recipient' => $revenue_recipient,
'is_free_user' => $is_free_user
]
]);
exit;
case 'remove':
$track_id = intval($_POST['track_id'] ?? 0);
$_SESSION['cart'] = array_filter($_SESSION['cart'], function($item) use ($track_id) {
return $item['track_id'] != $track_id;
});
// Reindex array
$_SESSION['cart'] = array_values($_SESSION['cart']);
echo json_encode(['success' => true, 'message' => 'Item removed from cart']);
exit;
case 'clear':
$_SESSION['cart'] = [];
if (isset($_SESSION['ticket_cart'])) {
$_SESSION['ticket_cart'] = [];
}
echo json_encode(['success' => true, 'message' => 'Cart cleared']);
exit;
case 'checkout':
$user_id = $_SESSION['user_id'] ?? null;
if (!$user_id) {
echo json_encode(['success' => false, 'message' => 'Please log in to complete checkout']);
exit;
}
if (empty($_SESSION['cart'])) {
echo json_encode(['success' => false, 'message' => 'Cart is empty']);
exit;
}
try {
$pdo->beginTransaction();
$total_cart_value = 0;
$platform_revenue = 0;
$artist_revenue = 0;
// Process each cart item
foreach ($_SESSION['cart'] as $item) {
$item_total = $item['price'] * $item['quantity'];
$total_cart_value += $item_total;
if ($item['is_free_user_track']) {
$platform_revenue += $item_total;
} else {
$artist_revenue += $item_total;
}
// Record sale
$stmt = $pdo->prepare("
INSERT INTO sales (
track_id, buyer_id, artist_id, amount, quantity,
revenue_recipient, recipient_id, is_free_user_track,
created_at
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NOW())
");
$stmt->execute([
$item['track_id'],
$user_id,
$item['artist_id'],
$item_total,
$item['quantity'],
$item['revenue_recipient'],
$item['recipient_id'],
$item['is_free_user_track'] ? 1 : 0
]);
// Add to user's library
$stmt = $pdo->prepare("
INSERT IGNORE INTO user_library (user_id, track_id, purchase_date)
VALUES (?, ?, NOW())
");
$stmt->execute([$user_id, $item['track_id']]);
}
// Update platform revenue (add to admin account)
if ($platform_revenue > 0) {
$stmt = $pdo->prepare("
UPDATE users SET credits = credits + ? WHERE id = 1
");
$stmt->execute([$platform_revenue * 100]); // Convert to credits (assuming $1 = 100 credits)
// Log platform revenue
$stmt = $pdo->prepare("
INSERT INTO credit_transactions (user_id, amount, type, description, created_at)
VALUES (1, ?, 'platform_revenue', 'Free user track sales revenue', NOW())
");
$stmt->execute([$platform_revenue * 100]);
}
$pdo->commit();
// Clear cart after successful checkout
$_SESSION['cart'] = [];
echo json_encode([
'success' => true,
'message' => 'Purchase completed successfully!',
'total' => $total_cart_value,
'platform_revenue' => $platform_revenue,
'artist_revenue' => $artist_revenue
]);
exit;
} catch (Exception $e) {
$pdo->rollback();
error_log("Checkout error: " . $e->getMessage());
echo json_encode(['success' => false, 'message' => 'Checkout failed. Please try again.']);
exit;
}
break;
default:
echo json_encode(['success' => false, 'message' => 'Invalid action']);
exit;
}
} catch (Exception $e) {
error_log("Cart error: " . $e->getMessage());
echo json_encode(['success' => false, 'message' => 'An error occurred: ' . $e->getMessage()]);
exit;
}
exit; // Ensure we don't continue to HTML output
}
// Only continue to HTML output for GET requests
$pdo = getDBConnection();
// Handle GET requests (view cart)
$user_id = $_SESSION['user_id'] ?? null;
// Merge both carts for display
$credit_cart = $_SESSION['credit_cart'] ?? [];
$music_cart = $_SESSION['cart'] ?? [];
$ticket_cart = $_SESSION['ticket_cart'] ?? [];
$all_cart_items = array_merge($music_cart, $credit_cart, $ticket_cart);
// Debug logging for cart display
error_log("🛒 Cart display - Session cart items: " . count($all_cart_items));
error_log("🛒 Cart display - User ID: " . ($user_id ?: 'null'));
if (!empty($all_cart_items)) {
error_log("🛒 Cart display - First item: " . json_encode($all_cart_items[0]));
}
$cart_total = array_sum(array_map(function($item) {
return $item['price'] * $item['quantity'];
}, $all_cart_items));
// Calculate revenue split for display
$platform_revenue = 0;
$artist_revenue = 0;
foreach ($all_cart_items as $item) {
$item_total = $item['price'] * $item['quantity'];
if ($item['is_free_user_track']) {
$platform_revenue += $item_total;
} else {
$artist_revenue += $item_total;
}
}
// Set page variables for header
$page_title = 'Shopping Cart - SoundStudioPro';
$page_description = 'Review your music purchases and complete your order.';
$current_page = 'cart';
include 'includes/header.php';
?>
<style>
/* Cart page specific styles matching credits.php pattern */
.cart-hero {
padding: 8rem 0 6rem;
text-align: center;
color: white;
background: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 50%, #0a0a0a 100%);
position: relative;
overflow: hidden;
margin-bottom: 4rem;
margin-top: 0;
}
.cart-hero::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="grid" width="10" height="10" patternUnits="userSpaceOnUse"><path d="M 10 0 L 0 0 0 10" fill="none" stroke="rgba(102,126,234,0.1)" stroke-width="0.5"/></pattern></defs><rect width="100" height="100" fill="url(%23grid)"/></svg>');
opacity: 0.3;
}
.cart-hero-content {
max-width: 90rem;
margin: 0 auto;
position: relative;
z-index: 2;
}
.cart-badge {
display: inline-block;
background: linear-gradient(135deg, rgba(102, 126, 234, 0.2), rgba(118, 75, 162, 0.2));
color: #667eea;
padding: 1.2rem 2.4rem;
border-radius: 50px;
font-size: 1.4rem;
font-weight: 600;
margin-bottom: 3rem;
backdrop-filter: blur(10px);
border: 1px solid rgba(102, 126, 234, 0.3);
}
.cart-title {
font-size: 4rem;
font-weight: 800;
line-height: 1.2;
margin-bottom: 1.5rem;
background: linear-gradient(135deg, #ffffff, #667eea);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.cart-subtitle {
font-size: 1.6rem;
color: #a0aec0;
margin-bottom: 3rem;
max-width: 50rem;
margin-left: auto;
margin-right: auto;
line-height: 1.5;
}
.cart-container {
max-width: 120rem;
margin: 0 auto;
padding: 0 2rem;
}
.cart-content {
max-width: 800px;
margin: 0 auto;
display: flex;
flex-direction: column;
gap: 4rem;
}
.cart-items-section {
background: linear-gradient(135deg, rgba(20, 20, 20, 0.95) 0%, rgba(30, 30, 30, 0.95) 100%);
border: 2px solid;
border-image: linear-gradient(135deg, #667eea, #764ba2) 1;
border-radius: 24px;
padding: 3rem;
backdrop-filter: blur(30px);
box-shadow: 0 25px 50px rgba(0, 0, 0, 0.3);
position: relative;
}
.cart-items-section::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="grid" width="10" height="10" patternUnits="userSpaceOnUse"><path d="M 10 0 L 0 0 0 10" fill="none" stroke="rgba(102,126,234,0.1)" stroke-width="0.5"/></pattern></defs><rect width="100" height="100" fill="url(%23grid)"/></svg>');
opacity: 0.3;
pointer-events: none;
border-radius: 24px;
}
.section-title {
font-size: 2.4rem;
font-weight: 700;
margin-bottom: 2.5rem;
display: flex;
align-items: center;
gap: 1rem;
background: linear-gradient(135deg, #ffffff, #667eea);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
position: relative;
z-index: 2;
}
.section-title i {
font-size: 2.2rem;
background: linear-gradient(135deg, #667eea, #764ba2);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.cart-item {
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 16px;
padding: 2rem;
margin-bottom: 2rem;
position: relative;
z-index: 2;
transition: all 0.3s ease;
}
.cart-item:hover {
background: rgba(255, 255, 255, 0.08);
border-color: rgba(102, 126, 234, 0.3);
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(102, 126, 234, 0.15);
}
.cart-section {
margin-bottom: 3rem;
padding-bottom: 2rem;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.cart-section:last-child {
border-bottom: none;
margin-bottom: 0;
}
.section-subtitle {
font-size: 1.8rem;
font-weight: 600;
color: #667eea;
margin-bottom: 1.5rem;
display: flex;
align-items: center;
gap: 0.8rem;
}
.section-subtitle i {
font-size: 1.6rem;
}
.music-item {
border-left: 4px solid #667eea;
}
.credit-item {
border-left: 4px solid #48bb78;
}
.summary-breakdown {
margin-bottom: 2rem;
}
.summary-section {
background: rgba(255, 255, 255, 0.05);
border-radius: 12px;
padding: 1.5rem;
margin-bottom: 1rem;
}
.summary-section h4 {
font-size: 1.4rem;
font-weight: 600;
color: white;
margin-bottom: 1rem;
display: flex;
align-items: center;
gap: 0.5rem;
}
.summary-row {
display: flex;
justify-content: space-between;
align-items: center;
color: #a0aec0;
font-size: 1.2rem;
margin-bottom: 0.5rem;
}
.summary-row:last-child {
margin-bottom: 0;
color: white;
font-weight: 600;
}
.checkout-actions {
display: flex;
gap: 1rem;
margin-top: 2rem;
}
.checkout-btn {
flex: 2;
background: linear-gradient(135deg, #667eea, #764ba2);
border: none;
color: white;
padding: 1.2rem 2rem;
border-radius: 12px;
font-size: 1.4rem;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
justify-content: center;
gap: 0.8rem;
}
.checkout-btn:hover {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(102, 126, 234, 0.3);
}
.clear-btn {
flex: 1;
background: rgba(255, 255, 255, 0.1);
border: 1px solid rgba(255, 255, 255, 0.2);
color: #a0aec0;
padding: 1.2rem 1.5rem;
border-radius: 12px;
font-size: 1.2rem;
font-weight: 500;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
}
.clear-btn:hover {
background: rgba(255, 255, 255, 0.15);
color: white;
}
.item-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 1rem;
gap: 2rem;
}
.item-info {
flex: 1;
min-width: 0;
}
.item-info h4 {
font-size: 1.8rem;
font-weight: 700;
color: white;
margin-bottom: 0.5rem;
line-height: 1.3;
}
.item-info p {
color: #a0aec0;
font-size: 1.4rem;
margin-bottom: 0.8rem;
line-height: 1.4;
}
.item-price {
font-size: 2rem;
font-weight: 700;
color: white;
text-align: right;
min-width: 120px;
flex-shrink: 0;
}
.price-free {
color: #48bb78;
display: flex;
align-items: center;
gap: 0.5rem;
flex-wrap: wrap;
word-break: break-word;
margin-bottom: 0.5rem;
}
.price-free i {
font-size: 1.8rem;
flex-shrink: 0;
}
.price-free span {
font-size: 1.4rem;
font-weight: 600;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.price-info {
color: #48bb78;
font-size: 1.2rem;
font-weight: 600;
margin-top: 0.3rem;
margin-bottom: 0.5rem;
display: flex;
align-items: center;
gap: 0.5rem;
}
.price-details {
color: #48bb78;
font-size: 1.4rem;
font-weight: 600;
margin-bottom: 0.5rem;
display: flex;
align-items: center;
gap: 0.5rem;
}
.revenue-info {
color: #ed8936;
font-size: 1.2rem;
margin-top: 0.3rem;
margin-bottom: 0.5rem;
display: flex;
align-items: center;
gap: 0.5rem;
}
.item-actions {
display: flex;
gap: 1rem;
margin-top: 1rem;
}
.btn-remove {
background: linear-gradient(135deg, #e53e3e, #c53030);
color: white;
border: none;
padding: 1rem 2rem;
border-radius: 12px;
font-size: 1.4rem;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
gap: 0.5rem;
}
.btn-remove:hover {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(229, 62, 62, 0.3);
}
.cart-summary {
background: linear-gradient(135deg, rgba(20, 20, 20, 0.95) 0%, rgba(30, 30, 30, 0.95) 100%);
border: 2px solid;
border-image: linear-gradient(135deg, #667eea, #764ba2) 1;
border-radius: 24px;
padding: 3rem;
backdrop-filter: blur(30px);
box-shadow: 0 25px 50px rgba(0, 0, 0, 0.3);
position: sticky;
top: 2rem;
height: fit-content;
}
.revenue-split {
margin-bottom: 2rem;
}
.revenue-split-free {
background: rgba(72, 187, 120, 0.1);
padding: 2rem;
border-radius: 16px;
border: 1px solid rgba(72, 187, 120, 0.3);
text-align: center;
margin-bottom: 2rem;
}
.free-ownership {
color: #48bb78;
font-size: 1.6rem;
font-weight: bold;
margin-bottom: 1rem;
display: flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
flex-wrap: wrap;
text-align: center;
word-break: break-word;
}
.ownership-details {
display: flex;
justify-content: space-between;
margin-bottom: 1rem;
font-size: 1.4rem;
}
.ownership-details span:first-child {
color: #a0aec0;
display: flex;
align-items: center;
gap: 0.5rem;
}
.ownership-details span:last-child {
color: #48bb78;
font-weight: bold;
}
.revenue-row {
display: flex;
justify-content: space-between;
margin-bottom: 1rem;
font-size: 1.6rem;
}
.revenue-row span:first-child {
color: #a0aec0;
}
.revenue-row.artist span:last-child {
color: #48bb78;
font-weight: 600;
}
.revenue-row.platform span:last-child {
color: #ed8936;
font-weight: 600;
}
.total-section {
border-top: 2px solid rgba(102, 126, 234, 0.2);
padding-top: 2rem;
margin-top: 2rem;
}
.total-row {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 2.2rem;
font-weight: 700;
color: white;
gap: 1rem;
}
.total-row span:first-child {
flex: 1;
min-width: 0;
}
.total-row span:last-child {
flex-shrink: 0;
white-space: nowrap;
}
.total-free {
color: #48bb78;
font-size: 2.2rem;
font-weight: 700;
display: flex;
align-items: center;
gap: 0.5rem;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
min-width: 0;
flex-shrink: 1;
}
.checkout-section {
margin-top: 2rem;
text-align: center;
}
.btn-checkout {
width: 100%;
background: linear-gradient(135deg, #667eea, #764ba2);
color: white;
border: none;
padding: 2rem;
border-radius: 16px;
font-size: 1.6rem;
font-weight: 700;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
justify-content: center;
gap: 1rem;
text-decoration: none;
}
.btn-checkout:hover {
transform: translateY(-2px);
box-shadow: 0 12px 30px rgba(102, 126, 234, 0.4);
color: white;
text-decoration: none;
}
.btn-checkout-free {
background: linear-gradient(135deg, #48bb78, #38a169);
}
.btn-checkout-free:hover {
box-shadow: 0 12px 30px rgba(72, 187, 120, 0.4);
}
.checkout-info {
margin-top: 1rem;
color: #48bb78;
font-size: 1.2rem;
display: flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
}
.empty-cart {
text-align: center;
padding: 6rem 2rem;
position: relative;
z-index: 2;
}
.empty-cart i {
font-size: 6rem;
color: rgba(102, 126, 234, 0.3);
margin-bottom: 2rem;
}
.empty-cart h3 {
font-size: 2.4rem;
color: white;
margin-bottom: 1rem;
}
.empty-cart p {
color: #a0aec0;
font-size: 1.6rem;
margin-bottom: 3rem;
}
.empty-cart .empty-highlight {
color: #c3dafe;
font-size: 1.3rem;
margin-bottom: 2rem;
letter-spacing: 0.2px;
}
.empty-cart-cta-group {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 1rem;
width: 100%;
}
.empty-cart-cta {
display: flex;
align-items: center;
gap: 0.7rem;
padding: 1rem 1.8rem;
border-radius: 999px;
text-decoration: none;
font-size: 1.4rem;
font-weight: 600;
border: 1px solid rgba(255, 255, 255, 0.15);
color: white;
transition: transform 0.2s ease, box-shadow 0.2s ease;
background: rgba(255, 255, 255, 0.04);
min-width: 220px;
justify-content: center;
}
.empty-cart-cta .cta-icon {
width: 36px;
height: 36px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.5rem;
background: rgba(255, 255, 255, 0.12);
}
.empty-cart-cta.primary {
background: linear-gradient(135deg, #667eea, #764ba2);
border-color: rgba(102, 126, 234, 0.4);
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.3);
}
.empty-cart-cta.secondary {
background: linear-gradient(135deg, rgba(59, 130, 246, 0.18), rgba(14, 165, 233, 0.18));
border-color: rgba(59, 130, 246, 0.3);
}
.empty-cart-cta.tertiary {
background: linear-gradient(135deg, rgba(16, 185, 129, 0.18), rgba(56, 189, 248, 0.18));
border-color: rgba(16, 185, 129, 0.35);
}
.empty-cart-cta:hover {
transform: translateY(-2px);
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.25);
}
.empty-cart a {
color: #48bb78;
text-decoration: none;
font-weight: 600;
}
.empty-cart a:hover {
text-decoration: underline;
}
.btn-primary {
background: linear-gradient(135deg, #667eea, #764ba2);
color: white;
border: none;
padding: 1.5rem 3rem;
border-radius: 12px;
font-size: 1.4rem;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
display: inline-flex;
align-items: center;
gap: 0.8rem;
text-decoration: none;
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(102, 126, 234, 0.3);
}
.btn-secondary {
background: rgba(255, 255, 255, 0.1);
color: white;
border: 1px solid rgba(255, 255, 255, 0.2);
padding: 1rem 1.5rem;
border-radius: 12px;
font-size: 1.4rem;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
}
.btn-secondary:hover {
background: rgba(255, 255, 255, 0.15);
border-color: rgba(255, 255, 255, 0.3);
transform: translateY(-2px);
color: white;
text-decoration: none;
}
.btn-outline {
background: transparent;
color: #a0aec0;
border: 1px solid rgba(160, 174, 192, 0.3);
padding: 1rem 1.5rem;
border-radius: 12px;
font-size: 1.4rem;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
}
.btn-outline:hover {
background: rgba(160, 174, 192, 0.1);
border-color: rgba(160, 174, 192, 0.5);
color: white;
transform: translateY(-2px);
}
@media (max-width: 768px) {
.cart-container {
padding: 0 1rem;
}
.cart-content {
grid-template-columns: 1fr;
gap: 2rem;
}
.cart-title {
font-size: 2.5rem;
}
.cart-subtitle {
font-size: 1.2rem;
}
.cart-summary {
position: static;
order: -1;
}
.cart-items-section {
padding: 2rem;
}
.cart-item {
padding: 1.5rem;
}
.item-header {
flex-direction: column;
gap: 1rem;
align-items: flex-start;
}
.item-actions {
flex-direction: column;
gap: 0.5rem;
}
.item-actions button {
width: 100%;
justify-content: center;
}
.section-title {
font-size: 2rem;
}
.item-info h4 {
font-size: 1.6rem;
}
.item-info p {
font-size: 1.2rem;
}
}
@media (max-width: 480px) {
.cart-container {
padding: 0 0.5rem;
}
.cart-title {
font-size: 2rem;
}
.cart-subtitle {
font-size: 1rem;
}
.cart-items-section {
padding: 1.5rem;
}
.cart-item {
padding: 1rem;
}
.section-title {
font-size: 1.8rem;
}
.item-info h4 {
font-size: 1.4rem;
}
.item-info p {
font-size: 1.1rem;
}
.btn-primary,
.btn-secondary {
padding: 1rem 1.5rem;
font-size: 1rem;
min-height: 44px;
touch-action: manipulation;
}
/* Touch-friendly improvements */
.cart-item {
touch-action: manipulation;
}
.item-actions button {
min-height: 44px;
touch-action: manipulation;
}
.empty-cart-cta {
width: 100%;
min-width: 0;
}
.empty-cart-cta-group {
gap: 0.75rem;
}
}
</style>
<div class="cart-hero">
<div class="cart-hero-content">
<div class="cart-badge">
<i class="fas fa-shopping-cart"></i>
<?= t('cart.hero_badge') ?>
</div>
<h1 class="cart-title"><?= t('cart.hero_title') ?></h1>
<p class="cart-subtitle"><?= t('cart.hero_subtitle') ?></p>
</div>
</div>
<div class="cart-container">
<div class="cart-content">
<!-- Cart Items -->
<div class="cart-items-section">
<h2 class="section-title">
<i class="fas fa-shopping-cart"></i>
<?= t('common.cart') ?> (<?= count($all_cart_items) ?>)
</h2>
<?php if (empty($all_cart_items)): ?>
<div class="empty-cart">
<i class="fas fa-shopping-cart"></i>
<h3><?= t('cart.empty_title') ?></h3>
<p><?= t('cart.empty_subtitle') ?></p>
<p class="empty-highlight"><?= t('cart.empty_highlight') ?></p>
<div class="empty-cart-cta-group">
<a href="/community_fixed.php" class="empty-cart-cta primary">
<span class="cta-icon"><i class="fas fa-music"></i></span>
<span><?= t('cart.cta.browse_tracks') ?></span>
</a>
<a href="/events.php" class="empty-cart-cta secondary">
<span class="cta-icon"><i class="fas fa-ticket-alt"></i></span>
<span><?= t('cart.cta.browse_tickets') ?></span>
</a>
<a href="/credits.php" class="empty-cart-cta tertiary">
<span class="cta-icon"><i class="fas fa-coins"></i></span>
<span><?= t('cart.cta.browse_credits') ?></span>
</a>
</div>
</div>
<?php else: ?>
<?php
// Separate items by type for better organization
$music_items = array_filter($all_cart_items, function($item) {
return !isset($item['type']) || $item['type'] === 'track';
});
$credit_items = array_filter($all_cart_items, function($item) {
return isset($item['type']) && $item['type'] === 'credit';
});
$ticket_items = array_filter($all_cart_items, function($item) {
return isset($item['type']) && $item['type'] === 'ticket';
});
?>
<!-- Music Tracks Section -->
<?php if (!empty($music_items)): ?>
<div class="cart-section">
<h3 class="section-subtitle">
<i class="fas fa-music"></i>
<?= t('cart.section.tracks') ?> (<?= count($music_items) ?>)
</h3>
<?php foreach ($music_items as $item): ?>
<div class="cart-item music-item">
<div class="item-header">
<div class="item-info">
<h4><?= htmlspecialchars($item['title']) ?></h4>
<p>
<i class="fas fa-user"></i>
<?= str_replace(':artist', htmlspecialchars($item['artist_name'] ?? $item['artist'] ?? t('checkout.unknown_artist')), t('cart.item.by_artist')) ?>
</p>
<?php if (isset($item['price']) && $item['price'] == 0): ?>
<div class="price-free">
<i class="fas fa-gift"></i>
<span><?= t('cart.item.free_label') ?> × <?= $item['quantity'] ?></span>
</div>
<?php elseif (isset($item['price'])): ?>
<div class="price-details">
$<?= number_format($item['price'], 2) ?> × <?= $item['quantity'] ?>
</div>
<?php endif; ?>
</div>
<div class="item-price">
<?php if (isset($item['price']) && $item['price'] == 0): ?>
<?= t('cart.item.free_label') ?>
<?php elseif (isset($item['price'])): ?>
$<?= number_format($item['price'] * $item['quantity'], 2) ?>
<?php endif; ?>
</div>
</div>
<div class="item-actions">
<?php if (isset($item['track_id'])): ?>
<button class="btn-remove" onclick="removeFromCart(<?= $item['track_id'] ?>)">
<i class="fas fa-trash"></i> <?= t('cart.button.remove') ?>
</button>
<button class="btn-secondary" onclick="playPreview('<?= htmlspecialchars($item['audio_url'] ?? '', ENT_QUOTES) ?>', '<?= htmlspecialchars($item['title'], ENT_QUOTES) ?>')" style="margin-left: 1rem;">
<i class="fas fa-play"></i> <?= t('cart.button.preview') ?>
</button>
<?php endif; ?>
</div>
</div>
<?php endforeach; ?>
</div>
<?php endif; ?>
<!-- Event Tickets Section -->
<?php if (!empty($ticket_items)): ?>
<div class="cart-section">
<h3 class="section-subtitle">
<i class="fas fa-ticket-alt"></i>
<?= t('cart.section.tickets') ?> (<?= count($ticket_items) ?>)
</h3>
<?php foreach ($ticket_items as $item): ?>
<div class="cart-item ticket-item">
<div class="item-header">
<div class="item-info">
<h4><?= htmlspecialchars($item['event_title'] ?? 'Event Ticket') ?></h4>
<p>
<i class="fas fa-ticket-alt"></i>
<?= $item['quantity'] ?> <?= $item['quantity'] > 1 ? t('cart.summary.ticket_label') : t('events.ticket') ?>
</p>
<?php if (!empty($item['is_free'])): ?>
<div class="price-free">
<i class="fas fa-gift"></i>
<span><?= t('cart.item.free_label') ?> × <?= $item['quantity'] ?></span>
</div>
<?php elseif (isset($item['price'])): ?>
<div class="price-details">
$<?= number_format($item['price'], 2) ?> × <?= $item['quantity'] ?>
</div>
<?php endif; ?>
</div>
<div class="item-price">
<?php if (!empty($item['is_free'])): ?>
<?= t('cart.item.free_label') ?>
<?php elseif (isset($item['price'])): ?>
$<?= number_format($item['price'] * $item['quantity'], 2) ?>
<?php endif; ?>
</div>
</div>
<div class="item-actions">
<button class="btn-remove" onclick="removeTicketFromCart(<?= (int)($item['event_id'] ?? 0) ?>)">
<i class="fas fa-times"></i> <?= t('cart.button.remove') ?>
</button>
</div>
</div>
<?php endforeach; ?>
</div>
<?php endif; ?>
<!-- Credit Packages Section -->
<?php if (!empty($credit_items)): ?>
<div class="cart-section">
<h3 class="section-subtitle">
<i class="fas fa-coins"></i>
<?= t('cart.section.credits') ?> (<?= count($credit_items) ?>)
</h3>
<?php foreach ($credit_items as $item): ?>
<div class="cart-item credit-item">
<div class="item-header">
<div class="item-info">
<h4><?= htmlspecialchars(ucfirst($item['package'])) ?> <?= t('checkout.package') ?></h4>
<p><i class="fas fa-coins"></i> <?= $item['credits'] ?> <?= t('common.credits') ?> × <?= $item['quantity'] ?></p>
<div class="price-details">
$<?= number_format($item['price'], 2) ?> × <?= $item['quantity'] ?>
</div>
</div>
<div class="item-price">
$<?= number_format($item['price'] * $item['quantity'], 2) ?>
</div>
</div>
<div class="item-actions">
<button class="btn-remove" onclick="removeCreditFromCart('<?= $item['package'] ?>')">
<i class="fas fa-trash"></i> <?= t('cart.button.remove') ?>
</button>
</div>
</div>
<?php endforeach; ?>
</div>
<?php endif; ?>
<?php endif; ?>
</div>
<!-- Cart Summary -->
<?php if (!empty($all_cart_items)): ?>
<div class="cart-summary">
<h2 class="section-title">
<i class="fas fa-receipt"></i>
<?= t('cart.summary.title') ?>
</h2>
<?php
$music_total = array_sum(array_map(function($item) {
return ($item['price'] ?? 0) * ($item['quantity'] ?? 1);
}, $music_items));
$credit_total = array_sum(array_map(function($item) {
return ($item['price'] ?? 0) * ($item['quantity'] ?? 1);
}, $credit_items));
$ticket_total = array_sum(array_map(function($item) {
return ($item['price'] ?? 0) * ($item['quantity'] ?? 1);
}, $ticket_items));
$grand_total = $music_total + $credit_total + $ticket_total;
?>
<?php if ($grand_total == 0): ?>
<div class="revenue-split-free">
<div class="free-ownership">
<i class="fas fa-star"></i>
<?= t('cart.summary.free_total') ?>
</div>
<div class="ownership-details">
<span><i class="fas fa-music"></i> <?= t('cart.summary.music_label') ?>:</span>
<span><?= count($music_items) ?></span>
</div>
<div class="ownership-details">
<span><i class="fas fa-coins"></i> <?= t('cart.summary.credit_label') ?>:</span>
<span><?= count($credit_items) ?></span>
</div>
<div class="ownership-details">
<span><i class="fas fa-ticket-alt"></i> <?= t('cart.summary.ticket_label') ?>:</span>
<span><?= count($ticket_items) ?></span>
</div>
<div class="ownership-details">
<span><i class="fas fa-download"></i> <?= t('checkout.download_access') ?>:</span>
<span><?= t('common.unlimited') ?></span>
</div>
<div class="ownership-details">
<span><i class="fas fa-infinity"></i> <?= t('checkout.library_storage') ?>:</span>
<span><?= t('common.forever') ?></span>
</div>
</div>
<div class="total-section">
<div class="total-row">
<span><i class="fas fa-gift"></i> <?= t('cart.summary.total') ?>:</span>
<span class="total-free"><?= t('cart.item.free_label') ?>!</span>
</div>
</div>
<?php else: ?>
<div class="summary-breakdown">
<?php if (!empty($music_items)): ?>
<div class="summary-section">
<h4><i class="fas fa-music"></i> <?= t('cart.summary.music_label') ?></h4>
<div class="summary-row">
<span><?= t('cart.summary.music_label') ?>:</span>
<span><?= count($music_items) ?></span>
</div>
<div class="summary-row">
<span><?= t('cart.summary.subtotal') ?>:</span>
<span>$<?= number_format($music_total, 2) ?></span>
</div>
</div>
<?php endif; ?>
<?php if (!empty($credit_items)): ?>
<div class="summary-section">
<h4><i class="fas fa-coins"></i> <?= t('cart.summary.credit_label') ?></h4>
<div class="summary-row">
<span><?= t('cart.summary.credit_label') ?>:</span>
<span><?= count($credit_items) ?></span>
</div>
<div class="summary-row">
<span><?= t('cart.summary.subtotal') ?>:</span>
<span>$<?= number_format($credit_total, 2) ?></span>
</div>
</div>
<?php endif; ?>
<?php if (!empty($ticket_items)): ?>
<div class="summary-section">
<h4><i class="fas fa-ticket-alt"></i> <?= t('cart.summary.ticket_label') ?></h4>
<div class="summary-row">
<span><?= t('cart.summary.ticket_label') ?>:</span>
<span><?= count($ticket_items) ?></span>
</div>
<div class="summary-row">
<span><?= t('cart.summary.subtotal') ?>:</span>
<span>$<?= number_format($ticket_total, 2) ?></span>
</div>
</div>
<?php endif; ?>
</div>
<div class="total-section">
<div class="total-row">
<span><?= t('cart.summary.subtotal') ?>:</span>
<span>$<?= number_format($grand_total, 2) ?></span>
</div>
<div class="total-row">
<span><?= t('cart.summary.tax') ?>:</span>
<span>$0.00</span>
</div>
<div class="total-row final">
<span><?= t('cart.summary.total') ?>:</span>
<span>$<?= number_format($grand_total, 2) ?></span>
</div>
</div>
<?php endif; ?>
<div class="checkout-actions">
<button onclick="if(window.ajaxNavigation){window.ajaxNavigation.navigateToPage('/checkout.php')}else{window.location.href='/checkout.php'}" class="btn-primary checkout-btn">
<i class="fas fa-credit-card"></i>
<?= t('cart.button.checkout') ?>
</button>
<button onclick="clearAllCarts()" class="btn-secondary clear-btn">
<i class="fas fa-trash"></i>
<?= t('cart.button.clear') ?>
</button>
</div>
</div>
<?php endif; ?>
</div>
</div>
<script>
const CART_I18N = {
confirmRemoveTrack: <?= json_encode(t('cart.confirm.remove_track')) ?>,
confirmRemoveCredit: <?= json_encode(t('cart.confirm.remove_credit')) ?>,
confirmRemoveTicket: <?= json_encode(t('cart.confirm.remove_ticket')) ?>,
confirmClear: <?= json_encode(t('cart.confirm.clear')) ?>,
errorRemoveItem: <?= json_encode(t('cart.error.remove_item')) ?>,
errorRemoveCredit: <?= json_encode(t('cart.error.remove_credit')) ?>,
errorRemoveTicket: <?= json_encode(t('cart.error.remove_ticket')) ?>,
errorClear: <?= json_encode(t('cart.error.clear_cart')) ?>,
noPreview: <?= json_encode(t('cart.alert.no_preview')) ?>,
saved: <?= json_encode(t('cart.success.saved')) ?>
};
function cartNotify(message, type = 'info') {
if (typeof window.showNotification === 'function') {
window.showNotification(message, type);
} else {
alert(message);
}
}
function removeFromCart(trackId) {
if (!confirm(CART_I18N.confirmRemoveTrack)) {
return;
}
fetch('cart.php', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: `action=remove&track_id=${trackId}`
})
.then(response => response.json())
.then(data => {
if (data.success) {
location.reload();
} else {
cartNotify(CART_I18N.errorRemoveItem, 'error');
}
})
.catch(error => {
console.error('Error:', error);
cartNotify(CART_I18N.errorRemoveItem, 'error');
});
}
function removeCreditFromCart(packageName) {
if (!confirm(CART_I18N.confirmRemoveCredit)) {
return;
}
fetch('remove_cart_item.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
type: 'credit',
identifier: packageName
})
})
.then(response => response.json())
.then(data => {
if (data.success) {
location.reload();
} else {
cartNotify(CART_I18N.errorRemoveCredit, 'error');
}
})
.catch(error => {
console.error('Error:', error);
cartNotify(CART_I18N.errorRemoveCredit, 'error');
});
}
function clearAllCarts() {
if (!confirm(CART_I18N.confirmClear)) {
return;
}
// Clear music cart
fetch('cart.php', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: 'action=clear'
})
.then(response => response.json())
.then(data => {
// Clear credit and ticket carts
return fetch('empty_cart.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' }
});
})
.then(response => response.json())
.then(data => {
if (data.success) {
location.reload();
} else {
cartNotify(CART_I18N.errorClear, 'error');
}
})
.catch(error => {
console.error('Error:', error);
cartNotify(CART_I18N.errorClear, 'error');
});
}
function saveCart() {
cartNotify(CART_I18N.saved, 'success');
}
if (typeof window.removeTicketFromCart !== 'function') {
window.removeTicketFromCart = function(eventId) {
if (!eventId) {
return;
}
if (!confirm(CART_I18N.confirmRemoveTicket)) {
return;
}
fetch('/remove_cart_item.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
type: 'ticket',
identifier: eventId
})
})
.then(response => response.json())
.then(data => {
if (data.success) {
location.reload();
} else {
cartNotify(CART_I18N.errorRemoveTicket, 'error');
}
})
.catch(error => {
console.error('Error:', error);
cartNotify(CART_I18N.errorRemoveTicket, 'error');
});
};
}
function playPreview(audioUrl, title) {
if (!audioUrl) {
cartNotify(CART_I18N.noPreview, 'info');
return;
}
// Use the global player if available
if (window.enhancedGlobalPlayer && window.enhancedGlobalPlayer.playTrack) {
window.enhancedGlobalPlayer.playTrack(audioUrl, title, 'Cart Preview');
} else if (window.playTrack) {
window.playTrack(audioUrl, title);
} else {
// Fallback - simple audio element (no auto-play)
const audio = new Audio(audioUrl);
// Don't auto-play - let user control
cartNotify(CART_I18N.noPreview, 'info');
}
}
// Add some nice touches
document.addEventListener('DOMContentLoaded', function() {
// Auto-save cart every 30 seconds (visual feedback only)
setInterval(function() {
const saveButton = document.querySelector('.btn-outline');
if (saveButton && saveButton.textContent.includes('Save Cart')) {
const originalText = saveButton.innerHTML;
saveButton.innerHTML = `<i class="fas fa-check"></i> ${CART_I18N.saved}`;
saveButton.style.color = '#48bb78';
saveButton.style.borderColor = 'rgba(72, 187, 120, 0.3)';
setTimeout(() => {
saveButton.innerHTML = originalText;
saveButton.style.color = '';
saveButton.style.borderColor = '';
}, 2000);
}
}, 30000);
});
</script>
<?php include 'includes/footer.php'; ?>