Several improvements before second concert

- Add end timestamp to concerts
- Add ability to view booklets for past concerts
- Filled concerts/nadal2020nens.json

Change-Id: Ic83b0b46661d1557468b0ffe678ac78e794ec179
diff --git a/concerts/nadal2020joves.json b/concerts/nadal2020joves.json
index 93c6542..028488f 100644
--- a/concerts/nadal2020joves.json
+++ b/concerts/nadal2020joves.json
@@ -2,6 +2,7 @@
   "title": "Concert de Nadal 2020",
   "subtitle": "Joves i adults",
   "begins": 1608312600,
+  "ends": 1608339600,
   "songs": [
     {
       "title": "Santa Nit",
diff --git a/concerts/nadal2020nens.json b/concerts/nadal2020nens.json
index 1e927da..7f11ce4 100644
--- a/concerts/nadal2020nens.json
+++ b/concerts/nadal2020nens.json
@@ -2,5 +2,371 @@
   "title": "Concert de Nadal 2020",
   "subtitle": "Nens i nenes",
   "begins": 1608571800,
-  "songs": []
+  "ends": 1608598800,
+  "songs": [
+    {
+      "title": "Que tinguis un bon Nadal",
+      "author": "Nadala popular anglesa",
+      "performers": [
+        {
+          "instrument": "Veus i percussió",
+          "names": ["Inés Coll", "Marcos Cruz", "Júlia Ferreira", "Lucía Mayorgas", "Diego Merino", "Anna Ros", "Gabriel Dale Villalba", "Hugo Montero", "Virgínia Pesquer"]
+        },
+        {
+          "instrument": "Guitarres",
+          "names": ["Alejandro Mora", "Pablo Jiménez"]
+        },
+        {
+          "instrument": "Bateria",
+          "names": ["Xavi Martín"]
+        }
+      ]
+    },
+    {
+      "title": "Minuet en Sol major",
+      "author": "Johann Sebastian Bach",
+      "performers": [
+        {
+          "instrument": "Piano",
+          "names": ["Julia Ndanda"]
+        }
+      ]
+    },
+    {
+      "title": "Bailes",
+      "author": "Lamote de Grignon",
+      "performers": [
+        {
+          "instrument": "Piano",
+          "names": ["Natalia Cruz"]
+        }
+      ]
+    },
+    {
+      "title": "Campana del campanar",
+      "author": "Nadala popular",
+      "performers": [
+        {
+          "instrument": "Veus i percussió",
+          "names": ["Paula Alcaraz", "Nerea Martínez", "Unai Mendo", "Clara Girona", "Iván Vergara", "Guiu Xuclà"]
+        },
+        {
+          "instrument": "Piano",
+          "names": ["Carme Martínez"]
+        }
+      ]
+    },
+    {
+      "title": "Chandelier",
+      "author": "Sia",
+      "performers": [
+        {
+          "instrument": "Veu",
+          "names": ["Noa Chacón"]
+        },
+        {
+          "instrument": "Piano",
+          "names": ["Tesi Osuna"]
+        }
+      ]
+    },
+    {
+      "title": "Bohemian Rhapsody",
+      "author": "Queen",
+      "performers": [
+        {
+          "instrument": "Piano",
+          "names": ["Iker Serrano"]
+        }
+      ]
+    },
+    {
+      "title": "Oda a l'alegria",
+      "author": "Ludwig van Beethoven",
+      "performers": [
+        {
+          "instrument": "Piano",
+          "names": ["Marc Baena"]
+        }
+      ]
+    },
+    {
+      "title": "El pastoret",
+      "author": "Popular francesa",
+      "performers": [
+        {
+          "instrument": "Piano",
+          "names": ["Marc Baena", "Montse González"]
+        }
+      ]
+    },
+    {
+      "title": "Santa Nit",
+      "author": "Franz Grüber",
+      "performers": [
+        {
+          "instrument": "Guitarres",
+          "names": ["Carla Revilla", "Alan Gareth Villalba", "Paula Alcaraz", "Clara Girona", "Inés Coll", "Guiu Xuclà", "Nerea Martínez", "Iván Vergara"]
+        },
+        {
+          "instrument": "Piano",
+          "names": ["Marcela Bou"]
+        },
+        {
+          "instrument": "Violí",
+          "names": ["Anna Ros"]
+        },
+        {
+          "instrument": "Ukelele",
+          "names": ["Lucía Mayorgas"]
+        },
+        {
+          "instrument": "Bateria",
+          "names": ["Pol Sicart"]
+        }
+      ]
+    },
+    {
+      "title": "Jingle Bells",
+      "author": "Popular nordamericana",
+      "performers": [
+        {
+          "instrument": "Piano",
+          "names": ["Claudia Ponce", "Lucía Burgos"]
+        }
+      ]
+    },
+    {
+      "title": "Cançó de bressol",
+      "author": "Johannes Brahms",
+      "performers": [
+        {
+          "instrument": "Piano",
+          "names": ["Marcos Cruz", "Victor Martín"]
+        }
+      ]
+    },
+    {
+      "title": "Dies d'alegria",
+      "author": "Thord Gummesson",
+      "performers": [
+        {
+          "instrument": "Veus",
+          "names": ["Carlota Bou", "Natalia Cruz", "Montserrat González", "Júlia Sicart", "Laura Matencio", "Lucía Ariza", "Raquel Caballero", "Ester Sánchez"]
+        },
+        {
+          "instrument": "Guitarres",
+          "names": ["Alejandro Mora", "Pablo Jiménez"]
+        },
+        {
+          "instrument": "Bateria",
+          "names": ["Xavi Martín"]
+        }
+      ]
+    },
+    {
+      "title": "Març",
+      "author": "N. Baklanowa",
+      "performers": [
+        {
+          "instrument": "Violí",
+          "names": ["Júlia Sicart"]
+        },
+        {
+          "instrument": "Piano",
+          "names": ["Carme Martínez"]
+        }
+      ]
+    },
+    {
+      "title": "Serra que serra",
+      "author": "Nadala popular catalana",
+      "performers": [
+        {
+          "instrument": "Veus",
+          "names": ["Olaia García", "Oriol Macías", "Víctor Martín", "Erik Plata", "Iker Serrano", "Alan Gareth Villalba"]
+        },
+        {
+          "instrument": "Violí",
+          "names": ["Júlia Sicart"]
+        },
+        {
+          "instrument": "Piano",
+          "names": ["Carme Martínez"]
+        }
+      ]
+    },
+    {
+      "title": "Mi burrito sabanero",
+      "author": "Villancico colombiano",
+      "performers": [
+        {
+          "instrument": "Saxo",
+          "names": ["Marc Baena", "Marlon Gómez"]
+        }
+      ]
+    },
+    {
+      "title": "This House Is Not For Sale",
+      "author": "Bon Jovi",
+      "performers": [
+        {
+          "instrument": "Veu",
+          "names": ["Gabriel Dale Villalba"]
+        },
+        {
+          "instrument": "Guitarres",
+          "names": ["Alejandro Mora", "Pablo Jiménez"]
+        },
+        {
+          "instrument": "Baix",
+          "names": ["Gabriel Villalba"]
+        },
+        {
+          "instrument": "Bateria",
+          "names": ["Xavi Martín"]
+        }
+      ]
+    },
+    {
+      "title": "El noi de la mare",
+      "author": "Popular catalana",
+      "performers": [
+        {
+          "instrument": "Piano",
+          "names": ["Julia Ferreira", "Laura Matencio"]
+        }
+      ]
+    },
+    {
+      "title": "The pipers are coming",
+      "author": "Johann Sebastian Bach",
+      "performers": [
+        {
+          "instrument": "Piano",
+          "names": ["Noa Chacón"]
+        },
+        {
+          "instrument": "Bateria",
+          "names": ["Unai Mendo"]
+        }
+      ]
+    },
+    {
+      "title": "La patinadora",
+      "author": "J. Thompson",
+      "performers": [
+        {
+          "instrument": "Piano",
+          "names": ["Noa Chacón"]
+        },
+        {
+          "instrument": "Bateria",
+          "names": ["Unai Mendo"]
+        }
+      ]
+    },
+    {
+      "title": "Huahuanaca",
+      "author": "Nadala popular boliviana",
+      "performers": [
+        {
+          "instrument": "Veus",
+          "names": ["Marc Baena", "Lucía Burgos", "Kimberly Calizaya", "Júlia Ndanda", "Claudia Ponce", "Carla Revilla", "Ester Sánchez", "Lucía Ariza"]
+        },
+        {
+          "instrument": "Guitarres",
+          "names": ["Abner Llacha", "Víctor Martín", "Erik Plata"]
+        },
+        {
+          "instrument": "Bateria",
+          "names": ["Diego merino"]
+        },
+        {
+          "instrument": "Flautes travesseres",
+          "names": ["Raquel Caballero", "Marta Albiol"]
+        },
+        {
+          "instrument": "Percussió",
+          "names": ["Unai Mendo"]
+        }
+      ]
+    },
+    {
+      "title": "Déjame",
+      "author": "Los Secretos",
+      "performers": [
+        {
+          "instrument": "Guitarres",
+          "names": ["Abner Llacha", "Víctor Martín", "Erik Plata"]
+        },
+        {
+          "instrument": "Bateria",
+          "names": ["Pol Sicart"]
+        }
+      ]
+    },
+    {
+      "title": "Oda a l'alegria",
+      "author": "Ludwig van Beethoven",
+      "performers": [
+        {
+          "instrument": "Piano",
+          "names": ["Olaia García", "Kimberly Calizaya"]
+        }
+      ]
+    },
+    {
+      "title": "Mad World",
+      "author": "Roland Orzabal",
+      "performers": [
+        {
+          "instrument": "Piano",
+          "names": ["Carlota Bou", "Marcela Bou"]
+        }
+      ]
+    },
+    {
+      "title": "Minuet",
+      "author": "C. Stamitz",
+      "performers": [
+        {
+          "instrument": "Flauta travessera",
+          "names": ["Raquel Caballero", "Marta Albiol"]
+        }
+      ]
+    },
+    {
+      "title": "Récréation de la Flauta Màgica",
+      "author": "W. A. Mozart",
+      "performers": [
+        {
+          "instrument": "Flauta travessera",
+          "names": ["Raquel Caballero", "Marta Albiol"]
+        }
+      ]
+    },
+    {
+      "title": "All I Want for Christmas Is You",
+      "author": "Mariah Carey",
+      "performers": [
+        {
+          "instrument": "Veu",
+          "names": ["Lucía Ariza", "Raquel Caballero", "Noa Chacón", "Ester Sánchez"]
+        },
+        {
+          "instrument": "Piano",
+          "names": ["Adrià Vilanova"]
+        },
+        {
+          "instrument": "Guitarres",
+          "names": ["Alejandro Mora", "Pablo Jiménez"]
+        },
+        {
+          "instrument": "Bateria",
+          "names": ["Xavi Martín"]
+        }
+      ]
+    }
+  ]
 }
diff --git a/css/styles.css b/css/styles.css
index 435b652..530397f 100644
--- a/css/styles.css
+++ b/css/styles.css
@@ -12,6 +12,7 @@
 .header {
   display: flex;
   justify-content: flex-start;
+  align-items: center;
   position: fixed;
   top: 0;
   width: calc(100% - 16px);
@@ -21,9 +22,18 @@
 }
 
 .header .header-logo {
+  display: flex;
+  flex: 1;
+}
+
+.header .header-logo img {
   height: 42px;
 }
 
+.header button {
+  margin-left: 8px;
+}
+
 .app-content {
   max-width: min(calc(100% - 32px), 800px);
   margin: 74px auto 16px auto;
@@ -104,6 +114,104 @@
   color: white;
 }
 
+button.primary-btn {
+  font-family: inherit;
+  font-size: 100%;
+  line-height: 1.15;
+  margin: 0;
+  text-transform: none;
+  -webkit-appearance: button;
+  border: 0;
+  border-radius: 4px;
+  padding: 8px;
+  color: white;
+  background-color: #0277BD;
+  cursor: pointer;
+}
+
+button.primary-btn:hover {
+  background-color: #1591DC;
+}
+
+button.primary-btn:active {
+  background-color: #22A3F1;
+}
+
+/* Section adapted from
+ * https://chromium.googlesource.com/infra/infra/+/master/appengine/monorail/static_src/elements/projects/mr-projects-page/mr-projects-page.js
+ * Copyright 2019 The Chromium Authors. All rights reserved.
+ * License: https://chromium.googlesource.com/infra/infra/+/master/LICENSE
+ **/
+.concerts-list {
+  display: flex;
+  align-items: stretch;
+  flex-wrap: wrap;
+  width: 100%;
+  padding: 0.5em 0;
+  margin-bottom: 3em;
+}
+
+.concert {
+  text-align: left;
+  width: 200px;
+  margin-left: 16px;
+  margin-right: 16px;
+  margin-bottom: 32px;
+  display: flex;
+  flex-direction: column;
+  align-items: flex-start;
+  justify-content: flex-start;
+  border-radius: 4px;
+  border: 1px solid #aaa;
+  padding: 16px;
+  font-weight: normal;
+  line-height: 16px;
+  transition: all 0.1s ease-in-out;
+}
+
+.concert:hover {
+  text-decoration: none;
+  cursor: pointer;
+  box-shadow: 0 2px 6px hsla(0,0%,0%,0.12),
+    0 1px 3px hsla(0,0%,0%,0.24);
+}
+
+.concert-title {
+  font-size: 16px;
+  line-height: 24px;
+  margin: 0;
+  margin-bottom: 16px;
+  padding-top: 0.1em;
+  padding-bottom: 16px;
+  letter-spacing: 0.1px;
+  font-weight: 600;
+  width: 100%;
+  border-bottom: 1px solid #aaa;
+}
+
+.concert-subtitle {
+  margin: 0 0 32px;
+  flex-grow: 1;
+}
+
+.linkify {
+  display: inline;
+  padding: 0px;
+  margin: 0px;
+  border: 0px;
+  background: 0px center;
+  cursor: pointer;
+  color: #0277BD;
+}
+
+.concert-btn {
+  text-transform: uppercase;
+  margin: 0px;
+  font-weight: 600;
+  flex-grow: 0;
+}
+/* End of section */
+
 /* DARK THEME */
 @media screen {
   .dark-theme {
@@ -129,6 +237,15 @@
     background: white;
     color: black;
   }
+
+  .dark-theme .concert:hover {
+    box-shadow: 0 2px 6px hsla(0,0%,100%,0.12),
+      0 1px 3px hsla(0,0%,100%,0.24);
+  }
+
+  .dark-theme .linkify {
+    color: #4cb9fb;
+  }
 }
 
 @media print {
diff --git a/index.html b/index.html
index 9e280e7..872039a 100644
--- a/index.html
+++ b/index.html
@@ -9,7 +9,10 @@
   </head>
   <body class="dark-theme">
     <header class="header">
-      <img class="header-logo" src="img/logo.svg">
+      <div class="header-logo">
+        <img src="img/logo.svg">
+      </div>
+      <button id="previous-concerts-btn" class="primary-btn" hidden>Concerts anteriors</button>
     </header>
     <div class="app-content">
       <section id="no-service-worker" class="message message--error" hidden>
@@ -24,6 +27,10 @@
         <div class="message-text">S'ha baixat una còpia d'aquesta app al teu dispositiu i està disponible sense connexió a Internet.</div>
         <div class="message-text">Obre aquesta pàgina quan comenci el concert per veure el programa.</div>
       </section>
+      <section id="previous-concerts" class="message" hidden>
+        <h2 class="message-title">Concerts anteriors</h2>
+        <div id="previous-concerts-list" class="concerts-list"></div>
+      </section>
       <section id="booklet" class="booklet" hidden>
         <div class="booklet-header">
           <h2 id="concert-title" class="booklet-header-title">Concert de Nadal 2020</h2>
diff --git a/js/script.js b/js/script.js
index 1c2ff15..03f66ee 100644
--- a/js/script.js
+++ b/js/script.js
@@ -3,6 +3,7 @@
   'nadal2020nens',
 ];
 
+var interval = null;
 var isBookletShown = false;
 
 function showSection(section) {
@@ -47,19 +48,60 @@
   return div;
 }
 
-function loadBooklet(booklet) {
+function loadBooklet(booklet, showBackButton = false) {
   console.info('Booklet: ', booklet);
 
   document.getElementById('concert-title').textContent = booklet.title;
   document.getElementById('concert-subtitle').textContent = booklet.subtitle;
 
   var bookletContent = document.getElementById('booklet-content');
+  bookletContent.textContent = '';
   booklet.songs.forEach(song => {
     var songEl = songElement(song);
     bookletContent.append(songEl);
   });
 
   showSection('booklet');
+  if (showBackButton)
+    document.getElementById('previous-concerts-btn').removeAttribute('hidden');
+}
+
+function loadPreviousBookletsList(booklets) {
+  var now = Date.now();
+  var list = document.getElementById('previous-concerts-list');
+
+  var existsPreviousConcert = false;
+  booklets.forEach(booklet => {
+    if (booklet.ends * 1000 <= now) {
+      existsPreviousConcert = true;
+
+      var el = document.createElement('div');
+      el.classList.add('concert');
+
+      var title = document.createElement('div');
+      title.classList.add('concert-title');
+      title.textContent = booklet.title;
+
+      var subtitle = document.createElement('div');
+      subtitle.classList.add('concert-subtitle');
+      subtitle.textContent = booklet.subtitle;
+
+      var view = document.createElement('button');
+      view.classList.add('concert-btn', 'linkify');
+      view.textContent = 'Obre el programa';
+
+      el.append(title, subtitle, view);
+
+      el.addEventListener('click', _ => {
+        loadBooklet(booklet, true);
+      });
+
+      list.append(el);
+    }
+  });
+
+  if (existsPreviousConcert)
+    document.getElementById('previous-concerts-btn').removeAttribute('hidden');
 }
 
 function checkBooklets(booklets) {
@@ -69,15 +111,15 @@
   var now = Date.now();
   var latest = null;
   booklets.forEach(booklet => {
-    if (booklet.begins * 1000 <= now &&
-        (latest === null || booklet.begins * 1000 < booklet.begins))
+    if (booklet['begins'] * 1000 <= now && booklet['ends'] * 1000 >= now &&
+        (latest === null || latest['begins'] < booklet['begins']))
       latest = booklet;
   });
 
-  if (latest === null)
-    showSection('wait-screen');
-  else {
+  if (latest !== null) {
+    document.getElementById('previous-concerts-btn').setAttribute('hidden', '');
     loadBooklet(latest);
+    window.clearInterval(interval);
     isBookletShown = true;
   }
 }
@@ -87,6 +129,13 @@
 }
 
 window.addEventListener('load', _ => {
+  document.getElementById('previous-concerts-btn')
+      .addEventListener('click', e => {
+        showSection('previous-concerts');
+        document.getElementById('previous-concerts-btn')
+            .setAttribute('hidden', '');
+      });
+
   if ('serviceWorker' in navigator) {
     navigator.serviceWorker.register('/sw.js')
         .then(reg => {
@@ -101,8 +150,12 @@
           });
 
           Promise.all(promises).then(booklets => {
+            showSection('wait-screen');
+            loadPreviousBookletsList(booklets);
             checkBooklets(booklets);
-            window.setInterval(_ => { checkBooklets(booklets); }, 60 * 1000);
+            interval = window.setInterval(_ => {
+              checkBooklets(booklets);
+            }, 15 * 1000);
           });
         })
         .catch(err => {
diff --git a/sw.js b/sw.js
index 403b19e..14fb7fd 100644
--- a/sw.js
+++ b/sw.js
@@ -1,4 +1,4 @@
-// Version: 1.0.4
+// Version: 1.0.5
 var CACHE_NAME = 'all-v1';
 var urlsToCache = [
   '/',