spanish-quizzer

An app to quiz you on Spanish vocabulary and verb conjugations
git clone https://git.ashermorgan.net/spanish-quizzer/
Log | Files | Refs | README

app.js (8175B)


      1 // Declare global variables
      2 let app;
      3 
      4 
      5 
      6 // page-header component
      7 const pageHeader = Vue.component("pageHeader", {
      8     props: {
      9         /**
     10          * The 1st header icon
     11          */
     12         icon1: {
     13             type: String
     14         },
     15 
     16         /**
     17          * The 2nd header icon
     18          */
     19         icon2: {
     20             type: String
     21         },
     22 
     23         /**
     24          * The label for the 1st header icon
     25          */
     26         label1: {
     27             type: String
     28         },
     29 
     30         /**
     31          * The label for the 2nd header icon
     32          */
     33         label2: {
     34             type: String
     35         },
     36 
     37         /**
     38          * The header text
     39          */
     40         title: {
     41             type: String,
     42             default: "Spanish-Quizzer",
     43         }
     44     },
     45     computed: {
     46         /**
     47          * The path to the 1st header icon
     48          */
     49         path1: function() {
     50             if (this.icon1) return `images/${this.icon1}.svg`;
     51             else return null;
     52         },
     53 
     54         /**
     55          * The path to the 2nd header icon
     56          */
     57         path2: function() {
     58             if (this.icon2) return `images/${this.icon2}.svg`;
     59             else return null;
     60         }
     61     },
     62     methods: {
     63         /**
     64          * Navigate to the home page
     65          */
     66         goHome: function() {
     67             if (this.$route.name !== 'home') this.$router.push('home');
     68         }
     69     },
     70     template: `
     71         <header>
     72             <button v-if="path1" :title="label1" class="icon"><img :src="path1" alt="" @click="$emit('click1')"/></button>
     73             <span @click="goHome">{{ title }}</span>
     74             <button v-if="path2" :title="label2" class="icon"><img :src="path2" alt="" @click="$emit('click2')"/></button>
     75         </header>
     76     `
     77 });
     78 
     79 
     80 
     81 // App pages
     82 const homePage = Vue.component("homePage", {
     83     data: function() {
     84         return {
     85             isResumable: false,
     86             showResumeBanner: true,
     87         };
     88     },
     89     methods: {
     90         /**
     91          * Handle a keyup event (implements keyboard shortcuts).
     92          * @param {object} e - The event args.
     93          */
     94         keyup: function(e) {
     95             if (this._inactive || e.ctrlKey || e.altKey || e.shiftKey || e.metaKey) return;
     96             if (e.key === "c") this.$router.push("verbs");
     97             if (e.key === "v") this.$router.push("vocab");
     98             if (e.key === ",") this.$router.push("settings");
     99             if (e.key === "t") this.$router.push("reference");
    100             if (e.key === "r") this.$router.push("quizzer");
    101         },
    102     },
    103     activated: function() {
    104         // Update isResumable property
    105         try {
    106             // Get last session
    107             let { prompts, index } = JSON.parse(localStorage.getItem("last-session"));
    108 
    109             // Validate prompts and promptIndex
    110             if (prompts && !isNaN(index) && index >= 0 && index < prompts.length) {
    111                 this.isResumable = true;
    112             }
    113         } catch {}
    114     },
    115     created: function() {
    116         // Add keyup handler
    117         window.addEventListener("keyup", this.keyup);
    118     },
    119     destroyed: function() {
    120         // Remove keyup handler
    121         window.removeEventListener("keyup", this.keyup);
    122     },
    123     template: `
    124         <div class="home">
    125             <page-header icon2="settings" label2="Settings" @click2="$router.push({name:'settings', params:{referer:$route.name}})"></page-header>
    126             <div v-if="isResumable && showResumeBanner" id="resumeBanner">
    127                 <router-link v-if="isResumable" to="/quizzer">Resume previous session</router-link>
    128                 <button @click="showResumeBanner=false" class="icon" title="Dismiss"><img alt="" src="images/x.svg"></button>
    129             </div>
    130             <main>
    131                 <h1>The best way to study Spanish vocabulary and verb conjugations</h1>
    132                 <div>
    133                     <router-link tag="button" to="/verbs">Study Conjugations</router-link>
    134                     <router-link tag="button" to="/vocab">Study Vocab</router-link>
    135                     <router-link tag="button" to="/reference">Reference Tables</router-link>
    136                 </div>
    137             </main>
    138         </div>
    139     `,
    140 });
    141 
    142 
    143 
    144 /**
    145  * Initialize the Vue app
    146  */
    147 function loadVue() {
    148     app = new Vue({
    149         el: "#app", // Mount to app div
    150 
    151         router: new VueRouter({
    152             routes: [
    153                 {
    154                     path: "/",
    155                     redirect: "/home"
    156                 },
    157                 {
    158                     path: "/home",
    159                     name: "home",
    160                     component: homePage
    161                 },
    162                 {
    163                     path: "/verbs",
    164                     name: "verbs",
    165                     meta: { title: "Verb Filters" },
    166                     component: filtersPage,
    167                     props: { category: "verbs" }
    168                 },
    169                 {
    170                     path: "/vocab",
    171                     name: "vocab",
    172                     meta: { title: "Vocab Filters" },
    173                     component: filtersPage,
    174                     props: { category: "vocab" }
    175                 },
    176                 {
    177                     path: "/settings",
    178                     name: "settings",
    179                     meta: { title: "Settings" },
    180                     component: settingsPage,
    181                     props: true
    182                 },
    183                 {
    184                     path: "/quizzer",
    185                     name: "quizzer",
    186                     meta: { title: "Quizzer" },
    187                     component: quizzerPage,
    188                     props: true
    189                 },
    190                 {
    191                     path: "/reference",
    192                     name: "reference",
    193                     meta: { title: "Reference Tables" },
    194                     component: referencePage
    195                 },
    196                 {
    197                     path: "/data",
    198                     beforeEnter: function() { window.location.href = "data"; }
    199                 },
    200                 {
    201                     path: "/tests",
    202                     beforeEnter: function() { window.location.href = "tests"; }
    203                 },
    204                 {
    205                     path: "*",
    206                     redirect: "/home"
    207                 },
    208             ],
    209         }),
    210 
    211         methods: {
    212             /**
    213              * Go back to the previous page.
    214              */
    215             Back: function() {
    216                 switch (this.$route.name) {
    217                     case "home":
    218                         break;
    219                     case "verbs":
    220                     case "vocab":
    221                     case "reference":
    222                         this.$router.push("home");
    223                         break;
    224                     case "settings":
    225                         this.$router.push(this.$route.params.referer || "home");
    226                         break;
    227                     case "quizzer":
    228                         this.$router.push(this.$route.params.referer || "home");
    229                         break;
    230                 }
    231             },
    232 
    233             /**
    234              * Handle a keyup event (implements keyboard shortcuts).
    235              * @param {object} e - The event args.
    236              */
    237             keyup: function(e) {
    238                 if (e.key === "Escape") this.Back();
    239             },
    240         },
    241 
    242         data: {
    243             data: {}
    244         },
    245 
    246         watch: {
    247             $route: function(to, from) {
    248                 if (to.meta.title) document.title = to.meta.title + " - Spanish-Quizzer";
    249                 else document.title = "Spanish-Quizzer";
    250             }
    251         },
    252 
    253         created: function() {
    254             // Add keyup handler
    255             window.addEventListener("keyup", this.keyup);
    256 
    257             // Set page title
    258             if (this.$route.meta.title) document.title = this.$route.meta.title + " - Spanish-Quizzer";
    259             else document.title = "Spanish-Quizzer";
    260         },
    261 
    262         destroyed: function() {
    263             // Remove keyup handler
    264             window.removeEventListener("keyup", this.keyup);
    265         },
    266     });
    267 }
    268 
    269 
    270 
    271 /**
    272  * Load the document.
    273  */
    274 async function Load() {
    275     // Set theme
    276     SetTheme(null);
    277 
    278     // Initialize the Vue app
    279     loadVue();
    280 
    281     // Load Spanish-Quizzer data
    282     app.data = await loadData();
    283 }