Skip to content

Commit 173bf34

Browse files
committed
refactor favouriteSection.js to replace hardcoded audio URLs with Spotify IDs and enhance song item display with Spotify embed
1 parent 2393370 commit 173bf34

1 file changed

Lines changed: 51 additions & 155 deletions

File tree

app/favouriteSection.js

Lines changed: 51 additions & 155 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ function favouriteSection() {
22
const section = document.createElement("section");
33
section.classList.add("favourite-section", "py-5");
44

5-
// Data lagu dengan URL Hardcoded untuk performa maksimal di mobile
5+
// Data lagu dengan Spotify ID
6+
// CARA CARI ID: Buka Spotify > Klik 3 titik di lagu > Share > Copy Song Link
7+
// Ambil kode setelah "track/" sampai sebelum tanda tanya "?"
8+
// Contoh: https://open.spotify.com/track/4uUG5RXrOk84mYEfFvj3cK?si=... -> ID: 4uUG5RXrOk84mYEfFvj3cK
69
const songs = [
710
{
811
title: "Secukupnya",
@@ -12,8 +15,7 @@ function favouriteSection() {
1215
icon: "fa-music",
1316
color: "#ccff00",
1417
delay: 0,
15-
previewUrl:
16-
"https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview116/v4/a6/5c/52/a65c529e-74a4-7b98-3e70-7f812a504a96/mzaf_1626184544281484870.plus.aac.p.m4a",
18+
spotifyId: "5drW6PGRxkE6MxttzVLNk5", // Ganti dengan ID asli
1719
},
1820
{
1921
title: "Andai Saja",
@@ -23,8 +25,7 @@ function favouriteSection() {
2325
icon: "fa-magic",
2426
color: "#ffffff",
2527
delay: 100,
26-
previewUrl:
27-
"https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview221/v4/34/a5/23/34a52368-643a-43a6-c96c-fd89c8d077cf/mzaf_14381344851997934839.plus.aac.p.m4a",
28+
spotifyId: "2hb8n44vpefszgLwkEVXhU", // Ganti dengan ID asli
2829
},
2930
{
3031
title: "Kenangan Manis",
@@ -34,8 +35,7 @@ function favouriteSection() {
3435
icon: "fa-guitar",
3536
color: "#ccff00",
3637
delay: 200,
37-
previewUrl:
38-
"https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview221/v4/09/89/1b/09891b19-1eb0-2f88-3339-1fad9861b6ed/mzaf_15403338971115180038.plus.aac.p.m4a",
38+
spotifyId: "5jLzpxUOnCsX5tfq7TGY9v", // Ganti dengan ID asli
3939
},
4040
{
4141
title: "33x",
@@ -45,8 +45,7 @@ function favouriteSection() {
4545
icon: "fa-briefcase",
4646
color: "#ffffff",
4747
delay: 300,
48-
previewUrl:
49-
"https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview126/v4/c6/be/d3/c6bed396-2b3c-0aee-dcec-d06a9506c781/mzaf_9218744999071382246.plus.aac.p.m4a",
48+
spotifyId: "0I3I9hgBRat6HR5Gzy26jx", // Ganti dengan ID asli
5049
},
5150
{
5251
title: "Sedia Aku Sebelum Hujan",
@@ -56,8 +55,7 @@ function favouriteSection() {
5655
icon: "fa-cloud-rain",
5756
color: "#ccff00",
5857
delay: 400,
59-
previewUrl:
60-
"https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview221/v4/9a/8a/f5/9a8af565-7b11-030b-6dc4-72a354411691/mzaf_1147188470658269281.plus.aac.p.m4a",
58+
spotifyId: "64qfw9JZl3RYCrq4Mn0WvT", // Ganti dengan ID asli
6159
},
6260
{
6361
title: "Mesra-mesraanya kecil-kecilan dulu",
@@ -67,30 +65,41 @@ function favouriteSection() {
6765
icon: "fa-heart",
6866
color: "#ffffff",
6967
delay: 500,
70-
previewUrl:
71-
"https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview126/v4/57/db/a8/57dba8ad-c886-2178-69bb-1ea1ca93380f/mzaf_13362817603498077160.plus.aac.p.m4a",
68+
spotifyId: "1NzyVlr2fOWOfigbwDabme", // Ganti dengan ID asli
7269
},
7370
];
7471

75-
// Helper untuk bikin item lagu
72+
// Helper untuk bikin item lagu dengan Spotify Embed
7673
const createSongItem = (song, index) => `
7774
<div class="col-lg-6" data-aos="fade-up" data-aos-delay="${song.delay}">
78-
<div class="song-neo">
79-
<div class="song-icon" style="background: ${song.color}">
80-
<i class="fas ${song.icon}"></i>
81-
</div>
82-
<div class="song-details">
83-
<div class="d-flex justify-content-between align-items-start">
84-
<div>
85-
<h4 class="mb-0 song-title">${song.title}</h4>
86-
<div class="artist-badge song-artist">${song.artist}</div>
75+
<div class="song-neo h-100">
76+
<div class="song-details d-flex flex-column h-100">
77+
<div class="d-flex justify-content-between align-items-start mb-3">
78+
<div class="d-flex align-items-center">
79+
<div class="song-icon-small me-3" style="background: ${song.color}">
80+
<i class="fas ${song.icon}"></i>
81+
</div>
82+
<div>
83+
<h4 class="mb-0 song-title">${song.title}</h4>
84+
<div class="artist-badge song-artist">${song.artist}</div>
85+
</div>
8786
</div>
88-
<button class="btn btn-sm btn-icon play-btn-neo" data-index="${index}">
89-
<i class="fas fa-play"></i>
90-
</button>
9187
</div>
92-
<p class="album-text mt-2 mb-2"><i class="fas fa-compact-disc me-1"></i> ${song.album}</p>
93-
<p class="desc-text">${song.desc}</p>
88+
89+
<p class="desc-text mb-3 flex-grow-1">${song.desc}</p>
90+
91+
<!-- Spotify Embed -->
92+
<div class="spotify-embed-wrapper">
93+
<iframe style="border-radius:12px"
94+
src="https://open.spotify.com/embed/track/${song.spotifyId}?utm_source=generator&theme=0"
95+
width="100%"
96+
height="80"
97+
frameBorder="0"
98+
allowfullscreen=""
99+
allow="autoplay; clipboard-write; encrypted-media; fullscreen; picture-in-picture"
100+
loading="lazy">
101+
</iframe>
102+
</div>
94103
</div>
95104
</div>
96105
</div>
@@ -126,31 +135,29 @@ function favouriteSection() {
126135
background: var(--neo-white);
127136
border: 3px solid var(--neo-black);
128137
box-shadow: 5px 5px 0px rgba(0,0,0,0.2);
129-
display: flex;
130-
align-items: stretch;
131-
height: 100%;
132138
transition: transform 0.2s;
139+
overflow: hidden;
133140
}
134141
135142
.song-neo:hover {
136143
transform: translateX(-5px);
137144
box-shadow: 8px 8px 0px var(--neo-black);
138145
}
139146
140-
.song-icon {
141-
width: 100px;
142-
border-right: 3px solid var(--neo-black);
147+
.song-icon-small {
148+
width: 50px;
149+
height: 50px;
150+
border: 2px solid var(--neo-black);
143151
display: flex;
144152
align-items: center;
145153
justify-content: center;
146-
font-size: 2.5rem;
154+
font-size: 1.2rem;
147155
color: var(--neo-black);
148156
flex-shrink: 0;
149157
}
150158
151159
.song-details {
152-
padding: 1.2rem;
153-
flex-grow: 1;
160+
padding: 1.5rem;
154161
}
155162
156163
.artist-badge {
@@ -164,132 +171,21 @@ function favouriteSection() {
164171
text-transform: uppercase;
165172
}
166173
167-
.album-text {
168-
font-size: 0.85rem;
169-
color: #666;
170-
border-bottom: 2px dashed #ccc;
171-
padding-bottom: 5px;
172-
}
173-
174174
.desc-text {
175-
font-size: 0.9rem;
176-
line-height: 1.4;
177-
margin-bottom: 0;
175+
font-size: 0.95rem;
176+
line-height: 1.5;
177+
color: #333;
178178
}
179179
180-
.btn-icon {
180+
.spotify-embed-wrapper {
181+
margin-top: auto;
181182
border: 2px solid var(--neo-black);
182-
border-radius: 50%;
183-
width: 35px; height: 35px;
184-
display: flex; align-items: center; justify-content: center;
185-
}
186-
187-
.btn-icon:hover {
188-
background: var(--neo-green);
189-
}
190-
191-
.btn-black {
192-
background: var(--neo-black);
193-
color: var(--neo-white);
194-
border-radius: 0;
195-
font-weight: bold;
196-
}
197-
.btn-black:hover {
198-
background: #333;
199-
color: var(--neo-green);
183+
border-radius: 14px; /* Sedikit lebih besar dari iframe radius */
184+
background: #000;
200185
}
201186
</style>
202187
`;
203188

204-
// Audio Logic - Single Instance untuk Mobile Stability
205-
const audioPlayer = new Audio();
206-
let currentPlayingIndex = -1; // Track index lagu yang sedang diputar
207-
208-
// Reset UI saat lagu selesai
209-
audioPlayer.onended = () => {
210-
const activeBtn = section.querySelector(
211-
`.play-btn-neo[data-index="${currentPlayingIndex}"]`
212-
);
213-
if (activeBtn) {
214-
const icon = activeBtn.querySelector("i");
215-
icon.classList.remove("fa-pause");
216-
icon.classList.add("fa-play");
217-
}
218-
currentPlayingIndex = -1;
219-
};
220-
221-
// Handle Error Playback
222-
audioPlayer.onerror = (e) => {
223-
console.error("Audio Error:", e);
224-
alert("Gagal memutar audio. Koneksi internet mungkin tidak stabil.");
225-
currentPlayingIndex = -1;
226-
227-
// Reset semua icon loading
228-
section.querySelectorAll(".fa-spinner").forEach((icon) => {
229-
icon.classList.remove("fa-spinner", "fa-spin");
230-
icon.classList.add("fa-play");
231-
});
232-
};
233-
234-
section.querySelectorAll(".play-btn-neo").forEach((btn) => {
235-
btn.addEventListener("click", async function () {
236-
const icon = this.querySelector("i");
237-
const index = parseInt(this.getAttribute("data-index"));
238-
const song = songs[index];
239-
240-
// 1. Logika Pause: Jika klik tombol yang sama dan sedang main
241-
if (currentPlayingIndex === index && !audioPlayer.paused) {
242-
audioPlayer.pause();
243-
icon.classList.remove("fa-pause");
244-
icon.classList.add("fa-play");
245-
return;
246-
}
247-
248-
// 2. Logika Ganti Lagu: Reset tombol lagu sebelumnya
249-
if (currentPlayingIndex !== -1 && currentPlayingIndex !== index) {
250-
const prevBtn = section.querySelector(
251-
`.play-btn-neo[data-index="${currentPlayingIndex}"]`
252-
);
253-
if (prevBtn) {
254-
const prevIcon = prevBtn.querySelector("i");
255-
prevIcon.classList.remove("fa-pause", "fa-spinner", "fa-spin");
256-
prevIcon.classList.add("fa-play");
257-
}
258-
}
259-
260-
// 3. Logika Play
261-
// Set loading state
262-
icon.classList.remove("fa-play");
263-
icon.classList.add("fa-spinner", "fa-spin");
264-
265-
try {
266-
// Set source langsung (tanpa fetch)
267-
audioPlayer.src = song.previewUrl;
268-
currentPlayingIndex = index;
269-
270-
// Promise play() untuk handle autoplay policy
271-
await audioPlayer.play();
272-
273-
// Jika berhasil play
274-
icon.classList.remove("fa-spinner", "fa-spin");
275-
icon.classList.add("fa-pause");
276-
} catch (error) {
277-
console.error("Playback failed:", error);
278-
icon.classList.remove("fa-spinner", "fa-spin");
279-
icon.classList.add("fa-play");
280-
281-
if (error.name === "NotAllowedError") {
282-
alert(
283-
"Browser memblokir audio. Silakan klik tombol play sekali lagi."
284-
);
285-
} else {
286-
alert("Gagal memutar lagu: " + error.message);
287-
}
288-
currentPlayingIndex = -1;
289-
}
290-
});
291-
});
292-
293189
return section;
294190
}
295191

0 commit comments

Comments
 (0)