Keith

Vue JS and Firebase Music Song Playlist

by Keith Rowles • 05/01/2024Vue

Air balloons floating in the bly sky

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