Proyecto cliente SPA para la API de películas con Nuxt.js

Adaptando el diseño y las páginas

Ya en VSC y con nuestro proyecto en marcha vamos a modificar un poco su estructura.

Seguramente la primera pregunta que tendréis sea... ¿cómo maneja Nuxt.js las páginas?, pues muy fácil, lo hace a través de componentes en el directorio pages.

Ahí encontraremos dos: index.vue e inspire.vue. La página index.vue, como podéis suponer hace referencia a la raíz del sitio, mientras que inspire es una página cualquier. De hecho, dejando de banda index, el nombre que damos al componente de la página concuerda con el que debemos poner en la URL para acceder a ella.

Con eso en mente vamos a modificar el nombre inspire.vue a favoritas.vue.

Al hacerlo dejará de funcionar, eso es porque en el menú el enlace sigue apuntando a la anterior, vamos a editarlo… ¿pero dónde se encuentra?

Si las páginas son componentes, éstas deben cargarse dentro de algún sitio, ¿no? Pues ese sitio es el layout principal. Lo encontraremos en layouts/default.vue, que es que se utiliza por defecto.

Como podréis observar en este fichero no encontramos las típicas cabeceras de html, head y body. Nuxt.js funciona con componentes y código JavaScript, de manera que para configurar esa parte hay que hacerlo editando el fichero de configuración nuxt.config.js.

Sea como sea vamos a editar el enlace del menú. Por defecto se nos ha creado dinámicamente, vamos a ponerlo manual y ya que estamos cambiaremos los iconos y lo haremos un poco más ancho:

layouts/default.vue

<aside class="column is-3 section"> <!-- 3 en lugar de 2 y 9 por 10 -->
  <p class="menu-label is-hidden-touch">General</p>
  <ul class="menu-list">
    <li>
      <nuxt-link to="/" exact-active-class="is-active">
        <b-icon icon="video"/>
        Películas
      </nuxt-link>
    </li>
    <li>
      <nuxt-link to="/favoritas" exact-active-class="is-active">
        <b-icon icon="star"/>
        Favoritas
      </nuxt-link>
    </li>
  </ul>
</aside>

Aprovecharemos para cambiar también el título del proyecto:

<a class="navbar-item" href="/">Super Películas</a>

Lo siguiente que podemos hacer es preparar el menú superior para mostrar los botones de registro y login.

Siguiendo la estructura de un navbar en bulma, tal como indican en la documentación, vamos a añadir un par de botones a la parte derecha:

<!-- Contenido del menú, al nivel del navbar-brand-->
<div class="navbar-menu">
  <div class="navbar-end">
    <div class="navbar-item">
      <div class="buttons">
        <a class="button">
          <strong>Registro</strong>
        </a>
        <a class="button is-light">
          Acceder
        </a>
      </div>
    </div>
  </div>
</div>

Implementar el funcionamiento del menú desplegable sería muy tedioso, pero gracias a Vue podemos implementar su funcionamiento en un santiamén.

Para forzar que se muestre el menú superior al presionar el botón en dispositivos móviles necesitamos forzar su visualización con CSS, ya que éste se esconde automáticamente.

Podríamos crear una variable en el componente llamada isActive, por defecto le daremos false indicando que el menú estará plegado:

export default {
 data() {
   return {
     isActive: false,
   }
 }
}

Cuando hagamos clic en la hamburguesa haremos un toggle, cambiando el valor con un evento clic:

<div class="navbar-burger" @click="isActive = !isActive">

A la clase CSS que siempre visualizará el contenido podríamos llamarla active:

.active{
  display: block !important;
}

Ya sólo nos falta añadirla condicionada al nav-menu usando el bind class:

<div class="navbar-menu" :class="{ active: isActive }">

Finalmente podríamos editar el contenido de las páginas, pero no lo vamos a borrar todo, dejaremos por lo menos una tarjeta para usarla como base de las películas:

pages/index.vue

<template>
 <section class="section">
   <h2 class="title">Películas</h2>
   <div class="columns is-mobile">
     <card
       title="Free"
       icon="github-circle"
     >
       Open source on 
       <a href="https://github.com/buefy/buefy"> GitHub</a>
     </card>
   </div>
 </section>
</template>

pages/favoritas.vue

<template>
 <section class="section">
   <h2 class="title">Favoritas</h2>
 </section>
</template>