diff --git a/README.md b/README.md index f67db658e67aab65f486833457007eabc6fa6e80..956f9b4a63f5a62240ebed23b795b91ac4fb3b25 100644 --- a/README.md +++ b/README.md @@ -36,11 +36,33 @@ Podcastify is built using the following technologies: ## Tasking -| Name | NIM | Client Side | Server Side | -| :----------------------------: | :------: | :---------: | :---------: | -| Muhammad Bangkit Dwi Cahyono | 13521055 | | | -| Irsyad Nurwidianto Basuki | 13521072 | | | -| Jimly Firdaus | 13521102 | | | +### Server side + +| 13521055 | 13521072 | 13521102 | +| ----------------------------------- | :--------------------: | -------------------------- | +| Setup Docker, DB, and Structure | CRUD Episode | Database Entity Design | +| Migration | | CRUD Podcast | +| Login, Register, Logout | | Pagination | +| CRUD User | | Search Bar | +| Profile | | File Uploader | +| Change Password | | Home Content | +| Home, Routing, Error Handling | | Guest Role Limit | +| Middleware and Helpers | | | +| Storage | | | + +### Client Side + +| 13521055 | 13521072 | 13521102 | +| ----------------------------------- | :--------------------: | -------------------------- | +| Layouts | UI Design | Components | +| Components | Episode List Page | Home Page Load | +| Input Validation | Episode CURD Page | Podcast CRUD Page | +| Login and Register Page | Audio Player | Podcast List Page | +| User List Page | Responsivenese | Responsiveness | +| Profile Page | | | +| Error Page | | | +| Navbars and Home Page | | | +| Responsiveness | | | ## Responsive Layouts & Lighthouse <div align="center"> @@ -87,6 +109,20 @@ Podcastify is built using the following technologies: <img src="readme/responsive/podcast/mobile_edit.png" width=150> <p align="center"><em>Podcast Page</em></p> <br/> + <img src="readme/responsive/episode/laptop_list.png" width=350> + <img src="readme/responsive/episode/ipad_list.png" width=250> + <img src="readme/responsive/episode/iphone_list.png" width=150> + <img src="readme/responsive/episode/laptop_detail.png" width=350> + <img src="readme/responsive/episode/ipad_detail.png" width=250> + <img src="readme/responsive/episode/iphone_detail.png" width=150> + <img src="readme/responsive/episode/laptop_add.png" width=350> + <img src="readme/responsive/episode/ipad_add.png" width=250> + <img src="readme/responsive/episode/iphone_add.png" width=150> + <img src="readme/responsive/episode/laptop_edit.png" width=350> + <img src="readme/responsive/episode/ipad_edit.png" width=250> + <img src="readme/responsive/episode/iphone_edit.png" width=150> + <p align="center"><em>Episode Page</em></p> + <br/> <img src="readme/responsive/error/laptop.png" width=350> <img src="readme/responsive/error/tablet.png" width=250> <img src="readme/responsive/error/mobile.png" width=150> @@ -114,6 +150,12 @@ Podcastify is built using the following technologies: <img src="readme/lighthouse/podcast/podcast_add.png" width=350> <p align="center"><em>Podcast Page</em></p> <br/> + <img src="readme/lighthouse/episode/episode_add.png" width=350> + <img src="readme/lighthouse/episode/episode_detail.png" width=350> + <img src="readme/lighthouse/episode/episode_edit.png" width=350> + <img src="readme/lighthouse/episode/episode_list.png" width=350> + <p align="center"><em>Episode Page</em></p> + <br/> <img src="readme/lighthouse/error/error.jpg" width=350> <p align="center"><em>Error Page</em></p> <br/> diff --git a/readme/lighthouse/episode/episode_add.png b/readme/lighthouse/episode/episode_add.png new file mode 100644 index 0000000000000000000000000000000000000000..c007af6cad3a219858846ba844da61b388c9ad10 Binary files /dev/null and b/readme/lighthouse/episode/episode_add.png differ diff --git a/readme/lighthouse/episode/episode_detail.png b/readme/lighthouse/episode/episode_detail.png new file mode 100644 index 0000000000000000000000000000000000000000..88db8ca73aa2a68a896c43e60dbc7f8256ecf230 Binary files /dev/null and b/readme/lighthouse/episode/episode_detail.png differ diff --git a/readme/lighthouse/episode/episode_edit.png b/readme/lighthouse/episode/episode_edit.png new file mode 100644 index 0000000000000000000000000000000000000000..1d8cf404bfb0720ae282ac3af74711940e6529ff Binary files /dev/null and b/readme/lighthouse/episode/episode_edit.png differ diff --git a/readme/lighthouse/episode/episode_list.png b/readme/lighthouse/episode/episode_list.png new file mode 100644 index 0000000000000000000000000000000000000000..961013b6ff7e98b060a7b31cd467266c18fd64e6 Binary files /dev/null and b/readme/lighthouse/episode/episode_list.png differ diff --git a/readme/responsive/episode/ipad_add.png b/readme/responsive/episode/ipad_add.png new file mode 100644 index 0000000000000000000000000000000000000000..e20fa1bc83e0305382d164cec14e6ef6cae88bfb Binary files /dev/null and b/readme/responsive/episode/ipad_add.png differ diff --git a/readme/responsive/episode/ipad_detail.png b/readme/responsive/episode/ipad_detail.png new file mode 100644 index 0000000000000000000000000000000000000000..992a91505a736f677ab737481fe6514331522753 Binary files /dev/null and b/readme/responsive/episode/ipad_detail.png differ diff --git a/readme/responsive/episode/ipad_edit.png b/readme/responsive/episode/ipad_edit.png new file mode 100644 index 0000000000000000000000000000000000000000..057db19ffe44d8a56d14a490b68f56bfd53018d9 Binary files /dev/null and b/readme/responsive/episode/ipad_edit.png differ diff --git a/readme/responsive/episode/ipad_list.png b/readme/responsive/episode/ipad_list.png new file mode 100644 index 0000000000000000000000000000000000000000..c9a08a2a656b4919fa75b28814960ebc381e48ce Binary files /dev/null and b/readme/responsive/episode/ipad_list.png differ diff --git a/readme/responsive/episode/iphone_add.png b/readme/responsive/episode/iphone_add.png new file mode 100644 index 0000000000000000000000000000000000000000..518ddc939633ca36fafa14ea9b87cbe2c01a1fdd Binary files /dev/null and b/readme/responsive/episode/iphone_add.png differ diff --git a/readme/responsive/episode/iphone_detail.png b/readme/responsive/episode/iphone_detail.png new file mode 100644 index 0000000000000000000000000000000000000000..d18f62a398519216334af2fa80540f91b94a815b Binary files /dev/null and b/readme/responsive/episode/iphone_detail.png differ diff --git a/readme/responsive/episode/iphone_edit.png b/readme/responsive/episode/iphone_edit.png new file mode 100644 index 0000000000000000000000000000000000000000..a91061b080bcd629e378e891b87e4379a59edc7a Binary files /dev/null and b/readme/responsive/episode/iphone_edit.png differ diff --git a/readme/responsive/episode/iphone_list.png b/readme/responsive/episode/iphone_list.png new file mode 100644 index 0000000000000000000000000000000000000000..653e56fa2618a94800aa7b33ee2ff43749e027e5 Binary files /dev/null and b/readme/responsive/episode/iphone_list.png differ diff --git a/readme/responsive/episode/laptop_add.png b/readme/responsive/episode/laptop_add.png new file mode 100644 index 0000000000000000000000000000000000000000..ac0e2b5128bb3eb445a878e7bfc142957e8919d6 Binary files /dev/null and b/readme/responsive/episode/laptop_add.png differ diff --git a/readme/responsive/episode/laptop_detail.png b/readme/responsive/episode/laptop_detail.png new file mode 100644 index 0000000000000000000000000000000000000000..c6ca5a46fa1c86c99ddc35481400ae24b47b5490 Binary files /dev/null and b/readme/responsive/episode/laptop_detail.png differ diff --git a/readme/responsive/episode/laptop_edit.png b/readme/responsive/episode/laptop_edit.png new file mode 100644 index 0000000000000000000000000000000000000000..abcc643beb6558d2247a80f5dc5ea6b9bb24f016 Binary files /dev/null and b/readme/responsive/episode/laptop_edit.png differ diff --git a/readme/responsive/episode/laptop_list.png b/readme/responsive/episode/laptop_list.png new file mode 100644 index 0000000000000000000000000000000000000000..e9d2d8db65f56b78ce97957ca39224b853141925 Binary files /dev/null and b/readme/responsive/episode/laptop_list.png differ diff --git a/src/app/controllers/EpisodeController.php b/src/app/controllers/EpisodeController.php index b6d002488210f6b06ca490d592ceb093234a5b93..c96355fad2af9478bb9fa40676e1369ddaad7ad7 100644 --- a/src/app/controllers/EpisodeController.php +++ b/src/app/controllers/EpisodeController.php @@ -118,7 +118,7 @@ class EpisodeController extends BaseController $podcastMapping = []; foreach ($podcast_data as $podcast) { - $podcastMapping[$podcast->title] = $podcast->podcast_id; + $podcastMapping[$podcast->podcast_id] = $podcast->title; } $data['podcasts'] = $podcastMapping; @@ -126,14 +126,14 @@ class EpisodeController extends BaseController $this->view('layouts/default', $data); break; case 'POST': - $podcast_id = $_POST['podcast_id']; + $podcast_title = $_POST['podcast_title']; // var_dump($podcast_id); $title = $_POST['episode-title-input']; $description = $_POST['episode-description-input']; $image_file = $_POST['preview-poster-filename'] ? $_POST['preview-poster-filename'] : null; $audio_file = $_POST['audio-filename'] ?? ''; - $this->episode_service->addEpisode($podcast_id, 1, $title, $description, 60, $image_file, $audio_file); + $this->episode_service->addEpisode($podcast_title, 1, $title, $description, 60, $image_file, $audio_file); $response = array("success" => true, "redirect_url" => "/episode", "status_message" => "Episode Successfully Added."); http_response_code(ResponseHelper::HTTP_STATUS_OK); diff --git a/src/app/services/episode/EpisodeService.php b/src/app/services/episode/EpisodeService.php index 82f755cff45eb0bfd58ade67c0040e6c2c85144e..78a3fe135b38c6d40da83c2bdffbde5a1d6e22ec 100644 --- a/src/app/services/episode/EpisodeService.php +++ b/src/app/services/episode/EpisodeService.php @@ -4,9 +4,11 @@ require_once BASE_URL . '/src/app/models/Episode.php'; class EpisodeService { private $episode_model; + private $podcast_model; public function __construct() { $this->episode_model = new Episode(); + $this->podcast_model = new Podcast(); } public function getAllEpisode() { @@ -73,8 +75,9 @@ class EpisodeService { return $episode_detail; } - public function addEpisode($podcast_id, $category_id, $title, $description, $duration, $image_url, $audio_url) { - $this->episode_model->createEpisode($podcast_id, $category_id, $title, $description, $duration, $image_url, $audio_url); + public function addEpisode($podcast_title, $category_id, $title, $description, $duration, $image_url, $audio_url) { + $id = $this->podcast_model->getPodcastIdByTitle($podcast_title); + $this->episode_model->createEpisode($id, $category_id, $title, $description, $duration, $image_url, $audio_url); } public function updateEpisode($episode_id, $title, $description, $image_url, $audio_url) { diff --git a/src/app/views/components/privates/episode/episode_detail.php b/src/app/views/components/privates/episode/episode_detail.php index 1bab2bdff2e65b773c34cac6f98ec55a28d869da..06adb5d91b18b851d25851fa364005ba8007c015 100644 --- a/src/app/views/components/privates/episode/episode_detail.php +++ b/src/app/views/components/privates/episode/episode_detail.php @@ -41,7 +41,7 @@ function episode_detail($episode = null) if (Middleware::isAdmin()) { echo " <button class=\"episode-detail-head-edit-button\" onclick=\"showEditEpisode($id)\"> - <img alt=\"edit-button\" src=\"" . ICONS_DIR . "/edit.svg\" /> + <img id=\"edit-button-image\" alt=\"edit-button\" src=\"" . ICONS_DIR . "/edit.svg\" /> </button>"; } echo " diff --git a/src/app/views/components/shares/navbars/media_player.php b/src/app/views/components/shares/navbars/media_player.php index d71452aa6e5249c828577699ee9f0b70a2246137..d6b143493f24e920b9c8922c3450fb4da8d9c322 100644 --- a/src/app/views/components/shares/navbars/media_player.php +++ b/src/app/views/components/shares/navbars/media_player.php @@ -4,7 +4,7 @@ echo '<link rel="stylesheet" href="' . CSS_DIR . 'navbars/media_player.css">'; echo ' <div class="media-player"> - <input id="range" type="range" class="timeline-slider small-screen" min="0" max="100" step="1" value="0"/> + <input id="range" aria-label="audio-slider-small" type="range" class="timeline-slider small-screen" min="0" max="100" step="1" value="0"/> <div id="media-cover" class="media-cover"></div> <div class="player"> <div class="player-controls"> diff --git a/src/app/views/layouts/default.php b/src/app/views/layouts/default.php index 7b701a64883089cf8321fd5fcca8b4b20cc427c0..350b628ee79a69205328f94fa7397a8be02bc34e 100644 --- a/src/app/views/layouts/default.php +++ b/src/app/views/layouts/default.php @@ -5,11 +5,16 @@ <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="description" content="Discover a world of captivating stories and insightful conversations on Podcastify. Explore a diverse range of podcasts, from engaging interviews to gripping narratives. Dive into a seamless listening experience and stay connected to your favorite topics. Start your podcast journey with Podcastify today."> - <link rel="stylesheet" href="<?= CSS_DIR ?>/global.css"> - <link rel="stylesheet" href="<?= CSS_DIR ?>/default.css"> - <link rel="stylesheet" href="<?= CSS_DIR ?>/episode/episode_card.css"> - <link rel="stylesheet" href="<?= CSS_DIR ?>/episode/episode_detail.css"> - <link rel="stylesheet" href="<?= CSS_DIR ?>/episode/add_episode.css"> + <link rel="stylesheet" href="<?= CSS_DIR ?>global.css"> + <link rel="stylesheet" href="<?= CSS_DIR ?>default.css"> + <link rel="stylesheet" href="<?= CSS_DIR ?>episode/episode_card.css"> + <link rel="stylesheet" href="<?= CSS_DIR ?>episode/episode_detail.css"> + <link rel="stylesheet" href="<?= CSS_DIR ?>episode/add_episode.css"> + <link rel="apple-touce-icon" sizes="180x180" href="<?= ICONS_WEB_DIR ?>apple-touch-icon.png"> + <link rel="icon" type="image/png" sizes="32x32" href="<?= ICONS_WEB_DIR ?>favicon-32x32.png"> + <link rel="icon" type="image/png" sizes="16x16" href="<?= ICONS_WEB_DIR ?>favicon-16x16.png"> + <link rel="icon" type="image/x-icon" href="<?= ICONS_WEB_DIR ?>favicon.ico"> + <link rel="manifest" href="<?= ICONS_WEB_DIR ?>manifest.json"> </head> <body> @@ -42,4 +47,4 @@ echoNotification(); <script src="<?= JS_DIR ?>default.js"></script> <script src="<?= JS_DIR ?>topbar.js"></script> -</html> +</html> \ No newline at end of file diff --git a/src/app/views/layouts/error.php b/src/app/views/layouts/error.php index ddfc4e03f86f6adc332ebb98669c0ba0916b8121..6a70a8580551be747b0f1eddd963386750a0aa68 100644 --- a/src/app/views/layouts/error.php +++ b/src/app/views/layouts/error.php @@ -7,6 +7,11 @@ <meta name="description" content="Discover a world of captivating stories and insightful conversations on Podcastify. Explore a diverse range of podcasts, from engaging interviews to gripping narratives. Dive into a seamless listening experience and stay connected to your favorite topics. Start your podcast journey with Podcastify today."> <link rel="stylesheet" href="<?= CSS_DIR ?>global.css"> <link rel="stylesheet" href="<?= CSS_DIR ?>error.css"> + <link rel="apple-touce-icon" sizes="180x180" href="<?= ICONS_WEB_DIR ?>apple-touch-icon.png"> + <link rel="icon" type="image/png" sizes="32x32" href="<?= ICONS_WEB_DIR ?>favicon-32x32.png"> + <link rel="icon" type="image/png" sizes="16x16" href="<?= ICONS_WEB_DIR ?>favicon-16x16.png"> + <link rel="icon" type="image/x-icon" href="<?= ICONS_WEB_DIR ?>favicon.ico"> + <link rel="manifest" href="<?= ICONS_WEB_DIR ?>manifest.json"> <title>Podcastify | Page not found</title> </head> @@ -18,4 +23,4 @@ </div> </body> -</html> +</html> \ No newline at end of file diff --git a/src/app/views/layouts/guest.php b/src/app/views/layouts/guest.php index 1fbcb7f1c50a5854c6981c6da25b324e5d347922..737b73507d7d5bc69c165001814307b84130e5c0 100644 --- a/src/app/views/layouts/guest.php +++ b/src/app/views/layouts/guest.php @@ -7,6 +7,11 @@ <meta name="description" content="Discover a world of captivating stories and insightful conversations on Podcastify. Explore a diverse range of podcasts, from engaging interviews to gripping narratives. Dive into a seamless listening experience and stay connected to your favorite topics. Start your podcast journey with Podcastify today."> <link rel="stylesheet" href="<?= CSS_DIR ?>global.css"> <link rel="stylesheet" href="<?= CSS_DIR ?>guest.css"> + <link rel="apple-touce-icon" sizes="180x180" href="<?= ICONS_WEB_DIR ?>apple-touch-icon.png"> + <link rel="icon" type="image/png" sizes="32x32" href="<?= ICONS_WEB_DIR ?>favicon-32x32.png"> + <link rel="icon" type="image/png" sizes="16x16" href="<?= ICONS_WEB_DIR ?>favicon-16x16.png"> + <link rel="icon" type="image/x-icon" href="<?= ICONS_WEB_DIR ?>favicon.ico"> + <link rel="manifest" href="<?= ICONS_WEB_DIR ?>manifest.json"> </head> <body> @@ -37,4 +42,4 @@ <script src="<?= JS_DIR ?>components/notification.js"></script> -</html> +</html> \ No newline at end of file diff --git a/src/app/views/pages/episode/add_episode.php b/src/app/views/pages/episode/add_episode.php index e2a939f0115217b7545c8fda90159a509c089475..c4a39ca287270fb5c5c0d319f528e493ace824a0 100644 --- a/src/app/views/pages/episode/add_episode.php +++ b/src/app/views/pages/episode/add_episode.php @@ -8,6 +8,7 @@ <?php require_once VIEWS_DIR . "/components/shares/inputs/text.php"; + require_once VIEWS_DIR . "/components/shares/inputs/select.php"; require_once VIEWS_DIR . "/components/shares/upload/baseFileUploader.php"; require_once VIEWS_DIR . "/components/shares/buttons/baseButton.php"; require_once VIEWS_DIR . "/components/shares/modals/baseModal.php"; @@ -21,13 +22,11 @@ <div> <p>Select Podcast: </p> - <select class="add-episode-form-select" id="dropdown" name="podcast_id"> - <?php - foreach ($data['podcasts'] as $name => $id) { - echo "<option value=\"$id\">$name</option>"; - } - ?> - </select> + <?php + $podcasts = $data['podcasts']; + baseSelect($podcasts, '', 'podcast_title'); + ?> + </div> <div> diff --git a/src/config/config.php b/src/config/config.php index 514b09f7fae44d363d78bd953c34b22493dc3dbe..dc81e183988ed2b6a6568a9034d6d540b39ed899 100644 --- a/src/config/config.php +++ b/src/config/config.php @@ -23,6 +23,7 @@ define("IMAGES_DIR", "/src/public/assets/images/"); define("FONTS_DIR", "/src/public/assets/fonts/"); define("CSS_DIR", "/src/public/css/"); define("JS_DIR", "/src/public/js/"); +define("ICONS_WEB_DIR", "/src/public/icon/"); // File define('MAX_SIZE', 8 * 1024 * 1024); // 8 mb diff --git a/src/public/css/episode/episode_detail.css b/src/public/css/episode/episode_detail.css index be2d28a5e4c785a99dc4772b6fc40e707d5e5891..8025d6c79c5f91bf780b758ee96824bb43ad44c0 100644 --- a/src/public/css/episode/episode_detail.css +++ b/src/public/css/episode/episode_detail.css @@ -48,6 +48,16 @@ p { transition: transform 0.2s ease; } +#button-image { + width: 75%; + height: 75%; +} + +#edit-button-image { + width: 100%; + height: 100%; +} + .episode-detail-head-edit-button { background-color: transparent; border: none; diff --git a/src/public/icon/android-chrome-192x192.png b/src/public/icon/android-chrome-192x192.png new file mode 100644 index 0000000000000000000000000000000000000000..0f94a34699c2e499ca94b5fdf953bfa9c35e77df Binary files /dev/null and b/src/public/icon/android-chrome-192x192.png differ diff --git a/src/public/icon/android-chrome-512x512.png b/src/public/icon/android-chrome-512x512.png new file mode 100644 index 0000000000000000000000000000000000000000..5ca2fc234cfe7fd2569e22c48ad188eda4c1afa7 Binary files /dev/null and b/src/public/icon/android-chrome-512x512.png differ diff --git a/src/public/icon/apple-touch-icon.png b/src/public/icon/apple-touch-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..6db5905cdf03fc711d4aafa0165a9d3d3833d323 Binary files /dev/null and b/src/public/icon/apple-touch-icon.png differ diff --git a/src/public/icon/favicon-16x16.png b/src/public/icon/favicon-16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..c7bcdfe886b50b90440d4283803e95704fcf01e0 Binary files /dev/null and b/src/public/icon/favicon-16x16.png differ diff --git a/src/public/icon/favicon-32x32.png b/src/public/icon/favicon-32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..7bbd5828f15e9956bec83fa1ee7b86ad75399bd3 Binary files /dev/null and b/src/public/icon/favicon-32x32.png differ diff --git a/src/public/icon/favicon.ico b/src/public/icon/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..88a625eb929f5b335ef6478cabe1c9469d01fd2c Binary files /dev/null and b/src/public/icon/favicon.ico differ diff --git a/src/public/icon/manifest.json b/src/public/icon/manifest.json new file mode 100644 index 0000000000000000000000000000000000000000..8f73ad97a11b9ca3be8c09ffadb6ce0014c634a5 --- /dev/null +++ b/src/public/icon/manifest.json @@ -0,0 +1,19 @@ +{ + "name": "", + "short_name": "", + "icons": [ + { + "src": "/src/public/icon/android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "/src/public/icon/android-chrome-512x512.png", + "sizes": "512x512", + "type": "image/png" + } + ], + "theme_color": "#000000", + "background_color": "#000000", + "display": "standalone" +} diff --git a/src/public/js/components/notification.js b/src/public/js/components/notification.js index 35cd63602d35eac5b34c18495672cbb046e4c1d6..7f1823ccc62d39d824cb6f6b316c0da55b0a1767 100644 --- a/src/public/js/components/notification.js +++ b/src/public/js/components/notification.js @@ -1,14 +1,11 @@ const showNotificationSuccess = (responseMessage) => { const notification = document.querySelector("#notification"); + notification.classList.remove("danger"); notification.classList.add("success"); const notificationText = document.querySelector("#notification-text"); notificationText.innerHTML = responseMessage; - // Set to local storage - localStorage.setItem("notificationText", responseMessage); - localStorage.setItem("notificationStatus", "success"); - setTimeout(() => { hideNotification(notification); }, 4000); @@ -16,6 +13,7 @@ const showNotificationSuccess = (responseMessage) => { const showNotificationDanger = (responseMessage) => { const notification = document.querySelector("#notification"); + notification.classList.remove("success"); notification.classList.add("danger"); const notificationText = document.querySelector("#notification-text"); diff --git a/src/public/js/default.js b/src/public/js/default.js index e397d34ca918344483ad7c7b743b0bf9d02f61f8..b12063f3f692a3602dac7ae837390bd710952211 100644 --- a/src/public/js/default.js +++ b/src/public/js/default.js @@ -1,24 +1,33 @@ // Slider Function -const sliderEl = document.querySelector("#range"); +const sliderEls = document.querySelectorAll("#range"); const sliderVolumeEl = document.querySelector("#volume-slider"); -function updateSliderBackground(value) { - const progress = (value / sliderEl.max) * 100; - sliderEl.style.background = `linear-gradient(to right, #1bd760 ${progress}%, #a7a7a7 ${progress}%)`; -} - -function updateVolumeSlider(value) { - const progress = (value / sliderVolumeEl.max) * 100; - sliderVolumeEl.style.background = `linear-gradient(to right, #f9f9f9 ${progress}%, #808080 ${progress}%)`; -} - -sliderEl.addEventListener("input", (event) => { - const tempSliderValue = event.target.value; - - requestAnimationFrame(() => { - updateSliderBackground(tempSliderValue); +sliderEls.forEach(sliderEl => { + function updateSliderBackground(value) { + const progress = (value / sliderEl.max) * 100; + sliderEl.style.background = `linear-gradient(to right, #1bd760 ${progress}%, #a7a7a7 ${progress}%)`; + } + + function updateVolumeSlider(value) { + const progress = (value / sliderVolumeEl.max) * 100; + sliderVolumeEl.style.background = `linear-gradient(to right, #f9f9f9 ${progress}%, #808080 ${progress}%)`; + } + + sliderEl.addEventListener("input", (event) => { + const tempSliderValue = event.target.value; + + requestAnimationFrame(() => { + updateSliderBackground(tempSliderValue); + }); }); -}); + // Initial update + updateSliderBackground(sliderEl.value); + audioPlayer.addEventListener("timeupdate", function () { + updateSliderBackground(sliderSmall.value); + updateSliderBackground(sliderBig.value); +}) +}) + sliderVolumeEl.addEventListener("input", (event)=> { const tempSliderValue = event.target.value; @@ -27,8 +36,3 @@ sliderVolumeEl.addEventListener("input", (event)=> { }); }) -// Initial update -updateSliderBackground(sliderEl.value); -audioPlayer.addEventListener("timeupdate", function () { - updateSliderBackground(progressSlider.value); -}) \ No newline at end of file diff --git a/src/public/js/episode/handle_upload.js b/src/public/js/episode/handle_upload.js index 9c7a52d7c7f8055cf7837d33cce005cd05fb72c6..19747a567e4ed3a153aebe1207098f05ab3e817d 100644 --- a/src/public/js/episode/handle_upload.js +++ b/src/public/js/episode/handle_upload.js @@ -120,60 +120,68 @@ handleFormSubmit("add-episode-form", function () { let imgUrl = "/upload?type=image"; let fileField = document.getElementById("poster-file-upload"); let imgFormData = new FormData(); - if(fileField.files[0]){ + if (fileField.files[0]) { imgFormData.append("filename", fileField.files[0].name); imgFormData.append("data", fileField.files[0]); - } else{ + } else { imgFormData.append("data", null); } try { let xhrImg = uploadEpsFile(imgUrl, true, imgFormData); xhrImg.onload = () => { - formData.append("preview-poster-filename", xhrImg.responseText); - - try { - // upload audio to server - let audioUrl = "/upload?type=audio"; - let audioFileField = document.getElementById("audio-file-upload"); - let audioFormData = new FormData(); - audioFormData.append("filename", audioFileField.files[0].name); - audioFormData.append("data", audioFileField.files[0]); - - let xhrAudio = uploadEpsFile(audioUrl, true, audioFormData); - xhrAudio.onload = () => { - formData.append("audio-filename", xhrAudio.responseText); - - try { - let xhr = createEpisode(formData); - xhr.onload = () => { - - const response = JSON.parse(xhr.responseText); - - if (xhr.status === 200) { - // window.location.href = "/episode"; - if (response.success) { - showNotificationSuccess(response.status_message); - setTimeout(() => { - location.replace(response.redirect_url); - }, 3000); - } else { - showNotificationDanger(response.status_message); - } - } else { - console.error("Request failed with status:", xhr.status); + const response = JSON.parse(xhrImg.responseText); + if (xhrImg.status === 200) { + formData.append("preview-poster-filename", xhrImg.responseText); + + try { + // upload audio to server + let audioUrl = "/upload?type=audio"; + let audioFileField = document.getElementById("audio-file-upload"); + let audioFormData = new FormData(); + audioFormData.append("filename", audioFileField.files[0].name); + audioFormData.append("data", audioFileField.files[0]); + + let xhrAudio = uploadEpsFile(audioUrl, true, audioFormData); + xhrAudio.onload = () => { + const response = JSON.parse(xhrAudio.responseText); + if (xhrAudio.status === 200) { + formData.append("audio-filename", xhrAudio.responseText); + + try { + let xhr = createEpisode(formData); + xhr.onload = () => { + const response = JSON.parse(xhr.responseText); + + if (xhr.status === 200) { + if (response.success) { + showNotificationSuccess(response.status_message); + setTimeout(() => { + location.replace(response.redirect_url); + }, 3000); + } else { + showNotificationDanger(response.status_message); + } + } else { + console.error("Request failed with status:", xhr.status); + } + }; + + xhr.onerror = function () { + console.error("Error during XMLHttpRequest"); + }; + } catch (error) { + console.error("Error creating episode:", error); } - }; - - xhr.onerror = function () { - console.error("Error during XMLHttpRequest"); - }; - } catch (error) { - console.error("Error creating episode:", error); - } - }; - } catch (error) { - console.error("Error uploading audio:", error); + } else { + showNotificationDanger(response.error_message); + } + }; + } catch (error) { + console.error("Error uploading audio:", error); + } + } else { + showNotificationDanger(response.error_message); } }; } catch (error) { @@ -181,32 +189,3 @@ handleFormSubmit("add-episode-form", function () { } }); }); - -handleFormSubmit("delete-episode-form", function () { - let form = document.getElementById("delete-episode-form"); - let formData = new FormData(form); - - let episodeId = 0; - for (let [key, value] of formData.entries()) { - if (key == "episode_id") { - episodeId = value; - } - } - try { - let xhr = deleteEpisode(episodeId); - - xhr.onload = () => { - if (xhr.status === 200) { - window.location.href = "/episode"; - } else { - console.error("Request failed with status:", xhr.status); - } - }; - - xhr.onerror = function () { - console.error("Error during XMLHttpRequest"); - }; - } catch (error) { - console.error("Error during XMLHttpRequest:", error); - } -}); diff --git a/src/public/js/episode/handle_upload_edit.js b/src/public/js/episode/handle_upload_edit.js index 13340261bd9f1d332b36d41b34050d42f3d58a55..a5a0d143e987cb6b177a2c1463d51157f3a1a70e 100644 --- a/src/public/js/episode/handle_upload_edit.js +++ b/src/public/js/episode/handle_upload_edit.js @@ -157,11 +157,17 @@ handleFormSubmit("edit-episode-form", function () { try { let xhrImg = uploadEditedEpsFile(imgUrl, true, imgFormData); xhrImg.onload = () => { - formData.append( - "edit-preview-poster-filename", - xhrImg.responseText - ); - resolve(); + const response = JSON.parse(xhrImg.responseText); + + if(xhrImg.status === 200) { + formData.append( + "edit-preview-poster-filename", + xhrImg.responseText + ); + resolve(); + } else { + showNotificationDanger(response.error_message); + } }; xhrImg.onerror = reject; } catch (error) { @@ -184,8 +190,14 @@ handleFormSubmit("edit-episode-form", function () { try { let xhrAudio = uploadEditedEpsFile(audioUrl, true, audioFormData); xhrAudio.onload = () => { - formData.append("edit-audio-filename", xhrAudio.responseText); - resolve(); + const response = JSON.parse(xhrAudio.responseText); + console.log(xhrAudio.responseText); + if (xhrAudio.status === 200) { + formData.append("edit-audio-filename", xhrAudio.responseText); + resolve(); + } else { + showNotificationDanger(response.error_message); + } }; xhrAudio.onerror = reject; } catch (error) { diff --git a/src/public/js/episode/media_player.js b/src/public/js/episode/media_player.js index cf266efff230ca941e3c42eb911bbe5a015ff8b8..1c3d4100bf2ca2334176bece63ff7f431fd21a67 100644 --- a/src/public/js/episode/media_player.js +++ b/src/public/js/episode/media_player.js @@ -1,5 +1,5 @@ const audioPlayer = document.getElementById("audio-player"); -const progressSlider = document.getElementById("range"); +const progressSlider = document.querySelectorAll("#range"); const audioPlayerButton = document.getElementById("play-btn"); const mediaCover = document.getElementById("media-cover"); const currentTimeDisplay = document.getElementById("slider-current-time"); @@ -11,6 +11,8 @@ const muteButtonImg = document.getElementById("mute-button-img"); let storedTime = 0; audioPlayer.volume = 1; let isCover = false; +const sliderSmall = progressSlider[0]; +const sliderBig = progressSlider[1]; const addCover = (divElmt) => { let poster = document.getElementById("episode-detail-head-image"); @@ -114,7 +116,8 @@ audioPlayer.addEventListener("timeupdate", function () { if (!isNaN(duration)) { const progress = (currentTime / duration) * 100; - progressSlider.value = progress; + sliderSmall.value = progress; + sliderBig.value = progress; totalTimeDisplay.textContent = totalTimeFormatted; } storedTime = currentTime; @@ -136,8 +139,13 @@ audioPlayer.addEventListener("error", function (e) { showNotificationDanger("No Audio File Found."); }); -progressSlider.addEventListener("input", function () { - const seekTime = (progressSlider.value / 100) * audioPlayer.duration; +sliderSmall.addEventListener("input", function () { + const seekTime = (sliderSmall.value / 100) * audioPlayer.duration; + audioPlayer.currentTime = seekTime; +}); + +sliderBig.addEventListener("input", function () { + const seekTime = (sliderBig.value / 100) * audioPlayer.duration; audioPlayer.currentTime = seekTime; });