Vue JS and Firebase Music Song Playlist
by Keith Rowles • 05/01/2024Vue
Summary
A Vue JS web application where you can create your favourite music playlist and add songs to the playlist.
This project is using the Vue 3 composition API instead of the options API.
You can register and login to the application.
You can also create, read, update and delete playlists and songs.
Google Firebase is used for the backend - user authentication, database to store chats, storage and web hosting.
The project has been deployed to Google hosting.
Tech and Tools
- HTML
- CSS
- JavaScript
- Vue JS
- Vue Router
- Google Firebase
- Vue CLI
- Route Guards
- Firebase Rules
Sample Code
login.vue
<template>
<form @submit.prevent="handleSubmit">
<h3>Login</h3>
<input type="email" placeholder="Email" v-model="email" />
<input type="password" placeholder="Password" v-model="password" />
<div v-if="error" class="error">{{ error }}</div>
<button v-if="!isPending">Login</button>
<button v-if="isPending" disabled>Loading</button>
</form>
</template>
<script>
import useLogin from '@/composables/useLogin.js';
import { ref } from 'vue';
import { useRouter } from 'vue-router';
export default {
setup() {
const { error, login, isPending } = useLogin();
const router = useRouter();
const email = ref('');
const password = ref('');
const handleSubmit = async () => {
const res = await login(email.value, password.value);
if (!error.value) {
// console.log('user logged in');
router.push({ name: 'UserPlaylists' });
}
};
return { email, password, handleSubmit, error, isPending };
},
};
</script>
<style></style>
navbar.vue
<template>
<div class="navbar">
<nav>
<img src="@/assets/avatar.png" alt="Logo" />
<h1><RouterLink :to="{ name: 'Home' }">Music PlayList</RouterLink></h1>
<div class="links">
<div v-if="user">
<RouterLink class="btn" :to="{ name: 'CreatePlaylist' }"
>Create Playlist</RouterLink
>
<RouterLink class="btn" :to="{ name: 'UserPlaylists' }"
>My Playlists</RouterLink
>
<span>Hi There, {{ user.displayName }}</span>
<button @click="handleClick">Logout</button>
</div>
<div v-else>
<RouterLink class="btn" :to="{ name: 'Signup' }">Signup</RouterLink>
<RouterLink class="btn" :to="{ name: 'Login' }">Login</RouterLink>
</div>
</div>
</nav>
</div>
</template>
<script>
import useLogout from '@/composables/useLogout.js';
import getUser from '@/composables/getUser.js';
import { useRouter } from 'vue-router';
export default {
setup() {
const { error, logout, isPending } = useLogout();
const router = useRouter();
const { user } = getUser();
const handleClick = async () => {
await logout();
if (!error.value) {
console.log('user logged out');
router.push({ name: 'Login' });
}
};
return { error, logout, isPending, handleClick, user };
},
};
</script>
<style scoped>
.navbar {
padding: 16px 10px;
margin-bottom: 60px;
background: white;
}
nav {
display: flex;
align-items: center;
max-width: 1200px;
margin: 0 auto;
}
nav img {
max-height: 60px;
border: 1px solid gray;
border-radius: 50%;
}
nav h1 {
margin-left: 20px;
}
nav .links {
margin-left: auto;
}
nav .links a,
button {
margin-left: 16px;
font-size: 14px;
}
span {
font-size: 14px;
display: inline-block;
margin-left: 16px;
padding-left: 16px;
border-left: 1px solid #898989;
}
</style>
Demo
Open demo on Google hosting.
Link to Demo