Jelajahi Sumber

Alumno y clave

Alejandro Rosales 1 tahun lalu
induk
melakukan
f935f95b91
1 mengubah file dengan 115 tambahan dan 76 penghapusan
  1. 115 76
      pages/graph.html

+ 115 - 76
pages/graph.html

@@ -5,54 +5,63 @@
     </button>
 </form>
 <main class="container" @vue:mounted="mounted">
-    <form class="mb-4">
-        <div class="row mb-3 form-box">
-            <label for="alumno.grupo" class="col-sm-1 col-form-label form-group barra">Grupo</label>
-            <div class="col-sm-10">
-                <select name="alumno.grupo" id="alumno.grupo" class="form-control col-form-label"
-                    v-model="filter.grupo">
-                    <option :value="null">Todos los grupos</option>
-                    <option v-for="alumno in alumnos.filter(alumno => alumno.grupo)" :value="alumno.grupo">
-                        {{ alumno.grupo }}
-                    </option>
-                </select>
+    <fieldset class="mb-4">
+        <legend v-if="alumno_y_clave">
+            {{ alumno_y_clave }}
+        </legend>
+        <legend v-else>
+            Gráficos
+        </legend>
+        <form>
+            <div class="row mb-3 form-box">
+                <label for="alumno.grupo" class="col-sm-1 col-form-label form-group barra">Grupo</label>
+                <div class="col-sm-10">
+                    <select name="alumno.grupo" id="alumno.grupo" class="form-control col-form-label"
+                        v-model="filter.grupo">
+                        <option :value="null">Todos los grupos</option>
+                        <option v-for="alumno in alumnos.filter(alumno => alumno.grupo)" :value="alumno.grupo">
+                            {{ alumno.grupo }}
+                        </option>
+                    </select>
+                </div>
             </div>
-        </div>
-        <div class="row mb-3 form-box">
-            <label for="alumno" class="col-sm-1 col-form-label form-group barra">Alumno</label>
-            <div class="col-sm-10">
-                <input type="item.type" name="item.name" list="item.name" id="alumno"
-                    class="form-control col-form-label" @input="fetchDatos" v-model="filter.username">
-                <datalist id="item.name">
-                    <option v-for="alumno in alumnos_por_grupo" :value="alumno.username">
-                        {{ alumno.nombre }}
-                    </option>
-                </datalist>
+            <div class="row mb-3 form-box">
+                <label for="alumno" class="col-sm-1 col-form-label form-group barra">Alumno</label>
+                <div class="col-sm-10">
+                    <input type="item.type" name="item.name" list="item.name" id="alumno"
+                        class="form-control col-form-label" @input="fetchDatos" v-model="filter.username">
+                    <datalist id="item.name">
+                        <option v-for="alumno in alumnos_por_grupo" :value="alumno.username">
+                            {{ alumno.nombre }}
+                        </option>
+                    </datalist>
+                </div>
             </div>
-        </div>
-        <button type="reset" class="btn btn-danger btn-sm">
-            <i class="fas fa-eraser"></i>
-        </button>
-    </form>
-
+            <!-- <button type="reset" class="btn btn-danger btn-sm">
+                <i class="fas fa-eraser"></i>
+            </button> -->
+        </form>
+    </fieldset>
     <section v-if="datos != null">
         <h2>Gráficos</h2>
-        <div class="row">
-            <div class="col-md-6">
-                <canvas id="calificaciones" width="400" height="400" @vue:mounted="createGraph($el,
-                    datos.calificaciones.map(calificacion => calificacion.course_name),
-                    datos.calificaciones.map(calificacion => calificacion.calificación_final),
-                    'bar', 'Calificaciones')">
-            </div>
-            <div class="col-md-6">
+        <div class="row d-flex justify-content-center">
+            <div class="col-md-8">
                 <canvas id="snapshot" width="400" height="400"
-                    @vue:mounted="createGraph($el, datos.timeline.map(snapshot => snapshot.created_at), datos.timeline.map(snapshot => snapshot.promedio_calificacion_final), 'line', 'Snapshot')">
+                    @vue:mounted="createMultiLineGraph($el, datos.snapshots)">
+            </div>
+            <div class="col-md-8">
+                <div id="calificaciones"
+                    @vue:mounted="createGraph($el, datos.calificaciones.map(calificacion => calificacion.course_name), datos.calificaciones.map(calificacion => calificacion.calificación_final))">
+                </div>
             </div>
+
         </div>
     </section>
 </main>
 
 <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
+<script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
+
 <script>
     const filter = PetiteVue.reactive({
         grupo: null,
@@ -75,6 +84,11 @@
 
             return this.alumnos.flatMap(alumno => alumno.alumnos);
         },
+        get alumno_y_clave() { // returns string: (username) nombre
+            if (this.filter.username == null) return null;
+            const alumno = this.alumnos_por_grupo.find(alumno => alumno.username === this.filter.username);
+            return alumno ? `(${alumno.username}) ${alumno.nombre}` : null;
+        },
         datos: null,
         async mounted() {
             store.loading = true;
@@ -83,52 +97,76 @@
             this.alumnos = data;
             store.loading = false;
         },
-        createGraph($el, labels, data, type, title) {
-            const backgroundColor = [
-                'rgba(255, 99, 132, 0.2)',
-                'rgba(54, 162, 235, 0.2)',
-                'rgba(255, 206, 86, 0.2)',
-                'rgba(75, 192, 192, 0.2)',
-                'rgba(153, 102, 255, 0.2)',
-                'rgba(255, 159, 64, 0.2)',
-                'rgba(255, 99, 132, 0.2)',
-                'rgba(54, 162, 235, 0.2)',
-                'rgba(255, 206, 86, 0.2)',
-                'rgba(75, 192, 192, 0.2)',
-            ];
+        createGraph($el, labels, data) {
+            var options = {
+                series: [{
+                    data: data
+                }],
+                chart: {
+                    type: 'bar',
+                    height: 350
+                },
+                plotOptions: {
+                    bar: {
+                        borderRadius: 4,
+                        horizontal: true,
+                    }
+                },
+                dataLabels: {
+                    enabled: false
+                },
+                xaxis: {
+                    categories: labels,
+                },
+                colors: [
+                    'rgba(54, 162, 235, 0.7)', // Blue
+                    'rgba(255, 99, 132, 0.7)', // Red
+                    'rgba(255, 159, 64, 0.7)', // Orange
+                    'rgba(255, 206, 86, 0.7)', // Yellow
+                    'rgba(75, 192, 192, 0.7)', // Green
+                    'rgba(153, 102, 255, 0.7)', // Purple
+                    'rgba(201, 203, 207, 0.7)', // gray
+                ]
+
+            };
+
+            var chart = new ApexCharts($el, options);
+            chart.render();
+        },
+        createMultiLineGraph($el, snapshots) {
+            const labels = snapshots.map(snapshot => snapshot.fecha);
+            const datasets = snapshots[0].calificaciones.map(calificacion => {
+                return {
+                    label: calificacion.course_name,
+                    data: snapshots.map(snapshot => snapshot.calificaciones.find(c => c.course_name === calificacion.course_name).calificación_final),
+                    fill: false,
+                    // borderColor: borderColor.slice(0, snapshots[0].calificaciones.length),
+                    tension: 0.1,
+                }
+            });
+
 
-            const borderColor = [
-                'rgba(255, 99, 132, 1)',
-                'rgba(54, 162, 235, 1)',
-                'rgba(255, 206, 86, 1)',
-                'rgba(75, 192, 192, 1)',
-                'rgba(153, 102, 255, 1)',
-                'rgba(255, 159, 64, 1)',
-                'rgba(255, 99, 132, 1)',
-                'rgba(54, 162, 235, 1)',
-                'rgba(255, 206, 86, 1)',
-                'rgba(75, 192, 192, 1)',
-            ];
-            if (this.datos == null) return;
-            const ctx1 = $el.getContext('2d');
-            const chart1 = new Chart(ctx1, {
-                type: type,
+
+            const ctx = $el.getContext('2d');
+            const multiLineChart = new Chart(ctx, {
+                type: 'line',
                 data: {
-                    labels: labels,
-                    datasets: [{
-                        label: title,
-                        data: data,
-                        backgroundColor: backgroundColor.slice(0, data.length),
-                        borderColor: borderColor.slice(0, data.length),
-                        borderWidth: 1
-                    }]
+                    labels: labels, // Las fechas de tus snapshots
+                    datasets: datasets, // Un array de objetos, cada uno representando una materia
                 },
                 options: {
                     scales: {
                         y: {
-                            beginAtZero: true
+                            beginAtZero: true,
+                            max: 1, // Asumiendo que las calificaciones están normalizadas entre 0 y 1
                         }
-                    }
+                    },
+                    plugins: {
+                        title: {
+                            display: true,
+                            text: 'Calificaciones por Materia a lo largo del Tiempo',
+                        },
+                    },
                 }
             });
         },
@@ -136,6 +174,7 @@
             if (this.filter.username == null) return;
             if (this.alumnos_por_grupo.find(alumno => alumno.username === this.filter.username) == null) return;
             store.loading = true;
+            this.datos = null;
             // params POST (formadata [username])
             const params = new FormData();
             params.append('username', this.filter.username);