Skip to content

Commit

Permalink
FE add GetRecommendationWithPlaylist view, update router, app.vue
Browse files Browse the repository at this point in the history
  • Loading branch information
yennanliu committed Oct 20, 2024
1 parent 90cdf98 commit f04a5c1
Show file tree
Hide file tree
Showing 3 changed files with 266 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
<router-link to="/search_album">Get Albums</router-link> |
<router-link to="/search_artist">Get Artists</router-link> |
<router-link to="/playlist">Create Playlist</router-link> |
<router-link to="/recommendation">Recommendation</router-link>
<router-link to="/recommendation">Recommendation</router-link> |
<router-link to="/recommendationWithPlayList">RecommendationWithPlayList</router-link>
</nav>
</header>
<div class="auth-button">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import UserPlayList from "../views/Profile/ListUserPlayList.vue";

// Recommendation
import GetRecommendation from "../views/Recommendation/GetRecommendation.vue";
import GetRecommendationWithPlaylist from "../views/Recommendation/GetRecommendationWithPlaylist.vue";

// search
import SearchAlbum from "../views/Search/GetAlbumWithKeyword.vue";
Expand Down Expand Up @@ -61,6 +62,12 @@ const routes = [
component: GetRecommendation,
},

{
path: "/recommendationWithPlayList",
name: "GetRecommendationWithPlaylist",
component: GetRecommendationWithPlaylist,
},

// search album
{
path: "/search_album",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,257 @@
<template>
<div class="container">
<h1>Song Recommendation With ML</h1>
<form @submit.prevent="getRecommendWithPlayList" class="recommendation-form">
<!-- Amount Input -->
<!-- <div class="form-group">
<label>Amount</label>
<input type="number" class="form-control large-input" v-model="amount" required />
</div> -->

<!-- Market Dropdown -->
<!-- <div class="form-group">
<label>Market</label>
<select v-model="market" class="form-control large-input" required>
<option value="JP">Japan (JP)</option>
<option value="TW">Taiwan (TW)</option>
<option value="US">United States (US)</option>
<option value="UK">United Kingdom (UK)</option>
<option value="FR">France (FR)</option>
<option value="TH">Thailand (TH)</option>
</select>
</div> -->

<!-- Max Popularity Slider -->
<!-- <div class="form-group">
<label>Max Popularity ({{ maxPopularity }})</label>
<input type="range" min="0" max="100" v-model="maxPopularity" class="slider" />
</div> -->

<!-- Min Popularity Slider -->
<!-- <div class="form-group">
<label>Min Popularity ({{ minPopularity }})</label>
<input type="range" min="0" max="100" v-model="minPopularity" class="slider" />
</div> -->

<!-- Seed Artist ID Input -->
<!-- <div class="form-group">
<label>Seed Artist ID</label>
<input type="text" class="form-control large-input" v-model="seedArtistId" required />
</div> -->

<!-- Seed Genres Input -->
<!-- <div class="form-group">
<label>Seed Genres</label>
<input type="text" class="form-control large-input" v-model="seedGenres" required />
</div> -->

<!-- Genres Dropdown -->
<!-- <div class="form-group">
<label>Genres</label>
<select v-model="seedGenres" class="form-control large-input" required>
<option value="rock">rock</option>
<option value="electro">electro</option>
<option value="hip-hop">hip-hop</option>
<option value="j-pop">j-pop</option>
<option value="k-pop">k-pop</option>
<option value="soul">soul</option>
<option value="house">house</option>
<option value="jazz">jazz</option>
</select>
</div> -->


<!-- Seed Track Input -->
<!-- <div class="form-group">
<label>Seed Track</label>
<input type="text" class="form-control large-input" v-model="seedTrack" required />
</div> -->

<!-- Target Popularity Slider -->
<!-- <div class="form-group">
<label>Target Popularity ({{ targetPopularity }})</label>
<input type="range" min="0" max="100" v-model="targetPopularity" class="slider" />
</div> -->

<!-- Playlist ID for feature recommendation -->
<div class="form-group">
<label>Playlist ID</label>
<input type="text" class="form-control large-input" v-model="playlistId" placeholder="Enter Playlist ID for feature recommendation" />
</div>

<!-- Playlist ID Input for adding new songs -->
<div class="form-group">
<label>Playlist ID</label>
<input type="text" class="form-control large-input" v-model="playlistId" placeholder="Enter Playlist ID for adding new songs" />
</div>

<div class="button-group">
<button type="submit" class="btn btn-outline-light">Submit</button>
<button type="button" class="btn btn-outline-light" @click="addSongToPlayList">
Add Songs to Playlist
</button>
<div v-if="addToPlayList">Songs added to Playlist successfully!</div>
</div>
</form>

<!-- Display Tracks -->
<div v-if="tracks">
<div v-for="track in tracks.tracks" :key="track.id" class="track-card">
<p>Track: {{ track.name }} | Artist: {{ track.artists[0].name }}</p>
<p>
URL:
<a :href="track.externalUrls.externalUrls.spotify" target="_blank">{{
track.externalUrls.externalUrls.spotify
}}</a>
</p>

<img v-if="track.album.images && track.album.images.length > 0" :src="track.album.images[0].url"
:alt="track.name" class="album-img" />

<p>
Preview URL:
<audio controls>
<source :src="track.previewUrl" type="audio/mpeg" />
Your browser does not support the audio element.
</audio>
</p>
<hr />
</div>
</div>
<div v-else>Loading...</div>
</div>
</template>

<script>
export default {
props: ["baseURL"],
data() {
return {
// amount: 10,
// market: "JP",
// maxPopularity: 100,
// minPopularity: 0,
// seedArtistId: "4sJCsXNYmUMeumUKVz4Abm",
// seedGenres: "electro",
// seedTrack: "1ZFQgnAwHaAhAn1o2bkwVs",
// targetPopularity: 50,
tracks: null,
trackURIs: "",
playlistFeatureId: "",
playlistId: "",
addToPlayList: false,
};
},
methods: {
async getRecommendWithPlayList() {
try {
console.log(">>> this.playlistFeatureId = " + this.playlistFeatureId)
const response = await fetch(`${this.baseURL}/recommend/platlist/${this.playlistFeatureId}`, {
method: "GET",
});
if (!response.ok) {
throw new Error("Failed to fetch recommendations");
}
const data = await response.json();
this.tracks = data;
} catch (error) {
console.error(error);
}
},
async addSongToPlayList() {
try {
this.trackURIs = this.tracks.tracks.map((track) => track.uri);
const response = await fetch(`${this.baseURL}/playlist/addSong`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
songUris: this.trackURIs.toString(),
playlistId: this.playlistId,
}),
});
if (response.status === 200) {
console.log("Songs added successfully");
this.addToPlayList = true;
} else {
throw new Error("Failed to add songs to playlist");
}
} catch (error) {
console.error(error);
}
},
},
};
</script>

<style scoped>
.container {
padding: 20px;
max-width: 800px;
margin: 0 auto;
}
.recommendation-form {
background-color: #f9f9f9;
padding: 20px;
border-radius: 10px;
}
.form-group {
margin-bottom: 20px;
}
.large-input {
font-size: 1.25rem;
padding: 10px;
}
.slider {
width: 100%;
margin-top: 10px;
}
.button-group {
display: flex;
gap: 15px;
}
.track-card {
margin-top: 20px;
padding: 10px;
border: 1px solid #ddd;
border-radius: 8px;
}
.album-img {
max-width: 300px;
max-height: 300px;
margin-top: 10px;
}
.btn-outline-light {
border-color: #1db954;
color: #1db954;
font-size: 1.2rem;
font-weight: bold;
padding: 10px 20px;
border-radius: 30px;
text-transform: uppercase;
cursor: pointer;
transition: background-color 0.3s ease, color 0.3s ease;
}
.btn-outline-light:hover {
background-color: #1db954;
color: #fff;
}
.button-group {
display: flex;
gap: 15px;
margin-top: 20px;
}
</style>

0 comments on commit f04a5c1

Please sign in to comment.