diff --git a/assets/css/custom.css b/assets/css/custom.css new file mode 100644 index 0000000..3e43185 --- /dev/null +++ b/assets/css/custom.css @@ -0,0 +1,53 @@ +body { + font-family: 'Heebo', sans-serif; + background-color: #F8FAFC; +} + +.navbar-brand { + font-weight: 700; + font-size: 1.5rem; +} + +.btn-primary { + background-color: #1D4ED8; + border-color: #1D4ED8; +} +.btn-primary:hover { + background-color: #1E40AF; + border-color: #1E40AF; +} + +.btn-secondary { + background-color: #F97316; + border-color: #F97316; +} +.btn-secondary:hover { + background-color: #EA580C; + border-color: #EA580C; +} + +.card { + border-radius: 0.5rem; + border: 1px solid #e2e8f0; + box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.05), 0 1px 2px -1px rgb(0 0 0 / 0.05); +} + +.form-control, .form-select { + border-radius: 0.5rem; +} +.form-control:focus, .form-select:focus { + border-color: #1D4ED8; + box-shadow: 0 0 0 0.25rem rgba(29, 78, 216, 0.25); +} + +.table { + vertical-align: middle; +} + +.duration-input-group { + direction: ltr; +} + +.toast-container { + z-index: 1080; +} diff --git a/assets/js/main.js b/assets/js/main.js new file mode 100644 index 0000000..c19d73a --- /dev/null +++ b/assets/js/main.js @@ -0,0 +1,81 @@ +document.addEventListener('DOMContentLoaded', function () { + // Initialize toast notifications + const toastEl = document.getElementById('notificationToast'); + if (toastEl) { + const toast = new bootstrap.Toast(toastEl, { delay: 3000 }); + toast.show(); + } + + const songModalEl = document.getElementById('songModal'); + if (!songModalEl) return; + + const songModal = new bootstrap.Modal(songModalEl); + const modalTitle = songModalEl.querySelector('.modal-title'); + const songForm = document.getElementById('songForm'); + const actionInput = document.getElementById('action'); + const songIdInput = document.getElementById('song_id'); + + // Function to reset the modal to its "Add Song" state + const resetModal = () => { + songForm.reset(); + actionInput.value = 'create'; + songIdInput.value = ''; + modalTitle.textContent = 'הוספת שיר חדש'; + }; + + // Handle clicks on edit buttons + document.querySelectorAll('.edit-btn').forEach(button => { + button.addEventListener('click', function () { + const song = JSON.parse(this.dataset.song); + + resetModal(); // Start with a clean slate + + actionInput.value = 'update'; + modalTitle.textContent = 'עריכת שיר'; + songIdInput.value = song.id; + + document.getElementById('name').value = song.name; + document.getElementById('bpm').value = song.bpm; + + if (song.song_key && song.song_key.trim() !== '') { + const keyParts = song.song_key.split(' '); + document.getElementById('key_note').value = keyParts[0]; + document.getElementById('key_scale').value = keyParts[1] || 'Major'; + } else { + document.getElementById('key_note').value = ''; + document.getElementById('key_scale').value = 'Major'; + } + + document.getElementById('notes').value = song.notes; + document.getElementById('tags').value = song.tags; + + if (song.duration_seconds) { + const minutes = Math.floor(song.duration_seconds / 60); + const seconds = song.duration_seconds % 60; + document.getElementById('duration_minutes').value = minutes; + document.getElementById('duration_seconds').value = seconds; + } + + songModal.show(); + }); + }); + + // Handle click on the link to add the first song + const addSongBtnLink = document.getElementById('addSongBtnLink'); + if(addSongBtnLink) { + addSongBtnLink.addEventListener('click', (e) => { + e.preventDefault(); + resetModal(); + songModal.show(); + }); + } + + // Reset the modal form when it's opened via the main "Add Song" button + // The main button works via data-attributes, so we just need to hook into the event + songModalEl.addEventListener('show.bs.modal', function (event) { + // If the trigger was NOT an edit button, reset the form for adding. + if (event.relatedTarget && !event.relatedTarget.classList.contains('edit-btn')) { + resetModal(); + } + }); +}); \ No newline at end of file diff --git a/db/migrate.php b/db/migrate.php new file mode 100644 index 0000000..7065604 --- /dev/null +++ b/db/migrate.php @@ -0,0 +1,38 @@ + PDO::ERRMODE_EXCEPTION, + ]); + $pdo_admin->exec("CREATE DATABASE IF NOT EXISTS `".DB_NAME."` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"); + // echo "Database '".DB_NAME."' created or already exists.\n"; + + // 2. Connect to the specific database to create tables + $pdo = db(); + if ($pdo === null) { + throw new Exception("Failed to connect to the database. The db() function returned null."); + } + $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + + $sql = " + CREATE TABLE IF NOT EXISTS songs ( + id INT AUTO_INCREMENT PRIMARY KEY, + name VARCHAR(255) NOT NULL, + bpm INT, + song_key VARCHAR(50), + duration_seconds INT, + notes TEXT, + tags VARCHAR(255), + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP + ) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"; + + $pdo->exec($sql); + // echo "Table 'songs' created successfully (if it didn\'t exist).\n"; + +} catch (Exception $e) { + http_response_code(500); + die("DB ERROR: " . $e->getMessage()); +} \ No newline at end of file diff --git a/includes/footer.php b/includes/footer.php new file mode 100644 index 0000000..85bc74f --- /dev/null +++ b/includes/footer.php @@ -0,0 +1,9 @@ + + + + + + + diff --git a/includes/header.php b/includes/header.php new file mode 100644 index 0000000..78fbcf0 --- /dev/null +++ b/includes/header.php @@ -0,0 +1,44 @@ + + + + + + Ari Stage - ניהול מופעים + + + + + + + + + + + + + + + + + +
diff --git a/index.php b/index.php index 7205f3d..a54858a 100644 --- a/index.php +++ b/index.php @@ -1,150 +1,14 @@ - -$phpVersion = PHP_VERSION; -$now = date('Y-m-d H:i:s'); -?> - - - - - - 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

+
+

ברוכים הבאים ל-Ari Stage

+

+ הכלי המושלם לזמרים ומפיקים לניהול מאגר השירים, יצירת ליינאפים דינמיים, וארגון הופעות. +

+ -
- - - + + + \ No newline at end of file diff --git a/songs.php b/songs.php new file mode 100644 index 0000000..fe62850 --- /dev/null +++ b/songs.php @@ -0,0 +1,231 @@ +prepare("INSERT INTO songs (name, bpm, song_key, duration_seconds, notes, tags) VALUES (?, ?, ?, ?, ?, ?)"); + $stmt->execute([$name, $bpm, $song_key, $duration_seconds, $notes, $tags]); + $_SESSION['notification'] = ['message' => 'השיר נוצר בהצלחה!', 'type' => 'success']; + } else { // update + $id = (int)($_POST['id'] ?? 0); + if ($id > 0) { + $stmt = $pdo->prepare("UPDATE songs SET name=?, bpm=?, song_key=?, duration_seconds=?, notes=?, tags=? WHERE id=?"); + $stmt->execute([$name, $bpm, $song_key, $duration_seconds, $notes, $tags, $id]); + $_SESSION['notification'] = ['message' => 'השיר עודכן בהצלחה!', 'type' => 'success']; + } + } + } elseif ($action === 'delete') { + $id = (int)($_POST['id'] ?? 0); + if ($id > 0) { + $stmt = $pdo->prepare("DELETE FROM songs WHERE id=?"); + $stmt->execute([$id]); + $_SESSION['notification'] = ['message' => 'השיר נמחק בהצלחה.', 'type' => 'danger']; + } + } + } catch (Exception $e) { + $_SESSION['notification'] = ['message' => 'אירעה שגיאה: ' . $e->getMessage(), 'type' => 'danger']; + } + + // Redirect to avoid form resubmission + header("Location: songs.php"); + exit(); +} + +// Check for notification from session +if (isset($_SESSION['notification'])) { + $notification = $_SESSION['notification']; + unset($_SESSION['notification']); +} + + +// Fetch all songs to display +$songs = $pdo->query("SELECT * FROM songs ORDER BY name ASC")->fetchAll(); + +function format_duration($seconds) { + if ($seconds === null || $seconds < 0) return '00:00'; + $mins = floor($seconds / 60); + $secs = $seconds % 60; + return sprintf('%02d:%02d', $mins, $secs); +} + +// --- Presentation --- +include 'includes/header.php'; +?> + + + +
+ +
+ + + +
+

מאגר השירים

+ +
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
שם השירBPMסולםמשךתגיםפעולות
עדיין אין שירים במאגר. הוסף את השיר הראשון שלך!
+ + + + + + + +
+ + + +
+
+
+
+
+ + + + +