|
@@ -4,92 +4,151 @@
|
|
|
<i class="fas fa-arrow-left"></i> Regresar
|
|
|
</button>
|
|
|
</form>
|
|
|
-<main class="container">
|
|
|
+<main class="container" @vue:mounted="mounted">
|
|
|
<form class="mb-4">
|
|
|
<div class="row mb-3 form-box">
|
|
|
- <label for="item.value" class="col-sm-1 col-form-label form-group barra">Alumno</label>
|
|
|
+ <label for="alumno.grupo" class="col-sm-1 col-form-label form-group barra">Grupo</label>
|
|
|
<div class="col-sm-10">
|
|
|
- <input type="item.type" name="item.name" list="item.name" id="item.value" class="form-control col-form-label">
|
|
|
+ <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 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 value="option.id">Alumno_nombre</option>
|
|
|
+ <option v-for="alumno in alumnos_por_grupo" :value="alumno.username">
|
|
|
+ {{ alumno.nombre }}
|
|
|
+ </option>
|
|
|
</datalist>
|
|
|
</div>
|
|
|
- <button type="reset" class="btn btn-danger btn-sm col-sm-1">
|
|
|
- <i class="fas fa-eraser"></i>
|
|
|
- </button>
|
|
|
</div>
|
|
|
+ <button type="reset" class="btn btn-danger btn-sm">
|
|
|
+ <i class="fas fa-eraser"></i>
|
|
|
+ </button>
|
|
|
</form>
|
|
|
|
|
|
- <section>
|
|
|
+ <section v-if="datos != null">
|
|
|
<h2>Gráficos</h2>
|
|
|
<div class="row">
|
|
|
<div class="col-md-6">
|
|
|
- <canvas id="chart1" width="400" height="400"></canvas>
|
|
|
+ <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">
|
|
|
- <canvas id="chart2" width="400" height="400"></canvas>
|
|
|
+ <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')">
|
|
|
</div>
|
|
|
</div>
|
|
|
</section>
|
|
|
</main>
|
|
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
|
|
- <script>
|
|
|
- const ctx1 = document.getElementById('chart1').getContext('2d');
|
|
|
- const chart1 = new Chart(ctx1, {
|
|
|
- type: 'bar',
|
|
|
- data: {
|
|
|
- labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
|
|
|
- datasets: [{
|
|
|
- label: '# of Votes',
|
|
|
- data: [12, 19, 3, 5, 2, 3],
|
|
|
- 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)'
|
|
|
- ],
|
|
|
- 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)'
|
|
|
- ],
|
|
|
- borderWidth: 1
|
|
|
- }]
|
|
|
- },
|
|
|
- options: {
|
|
|
- scales: {
|
|
|
- y: {
|
|
|
- beginAtZero: true
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- });
|
|
|
+<script>
|
|
|
+ const filter = PetiteVue.reactive({
|
|
|
+ grupo: null,
|
|
|
+ username: null,
|
|
|
+ });
|
|
|
|
|
|
- const ctx2 = document.getElementById('chart2').getContext('2d');
|
|
|
- const chart2 = new Chart(ctx2, {
|
|
|
- type: 'line',
|
|
|
- data: {
|
|
|
- labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
|
|
|
- datasets: [{
|
|
|
- label: '# of Votes',
|
|
|
- data: [12, 19, 3, 5, 2, 3],
|
|
|
- backgroundColor: 'rgba(255, 99, 132, 0.2)',
|
|
|
- borderColor: 'rgba(255, 99, 132, 1)',
|
|
|
- borderWidth: 1
|
|
|
- }]
|
|
|
- },
|
|
|
- options: {
|
|
|
- scales: {
|
|
|
- y: {
|
|
|
- beginAtZero: true
|
|
|
+ const graph = PetiteVue.reactive({
|
|
|
+ calificaciones: null,
|
|
|
+ snapshot: null,
|
|
|
+ })
|
|
|
+
|
|
|
+ PetiteVue.createApp({
|
|
|
+ store,
|
|
|
+ filter,
|
|
|
+ graph,
|
|
|
+ alumnos: [], // schema: { grupo: string, alumnos: Array<{ nombre: string, username: string }> }
|
|
|
+ get alumnos_por_grupo() { // returns Array<{ nombre: string, username: string }>
|
|
|
+ if (this.filter.grupo)
|
|
|
+ return this.alumnos.find(alumno => alumno.grupo === this.filter.grupo).alumnos;
|
|
|
+
|
|
|
+ return this.alumnos.flatMap(alumno => alumno.alumnos);
|
|
|
+ },
|
|
|
+ datos: null,
|
|
|
+ async mounted() {
|
|
|
+ store.loading = true;
|
|
|
+ const response = await fetch('fetch/alumnos.php');
|
|
|
+ const data = await response.json();
|
|
|
+ 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)',
|
|
|
+ ];
|
|
|
+
|
|
|
+ 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,
|
|
|
+ data: {
|
|
|
+ labels: labels,
|
|
|
+ datasets: [{
|
|
|
+ label: title,
|
|
|
+ data: data,
|
|
|
+ backgroundColor: backgroundColor.slice(0, data.length),
|
|
|
+ borderColor: borderColor.slice(0, data.length),
|
|
|
+ borderWidth: 1
|
|
|
+ }]
|
|
|
+ },
|
|
|
+ options: {
|
|
|
+ scales: {
|
|
|
+ y: {
|
|
|
+ beginAtZero: true
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
- }
|
|
|
- });
|
|
|
- </script>
|
|
|
+ });
|
|
|
+ },
|
|
|
+ async fetchDatos() {
|
|
|
+ if (this.filter.username == null) return;
|
|
|
+ if (this.alumnos_por_grupo.find(alumno => alumno.username === this.filter.username) == null) return;
|
|
|
+ store.loading = true;
|
|
|
+ // params POST (formadata [username])
|
|
|
+ const params = new FormData();
|
|
|
+ params.append('username', this.filter.username);
|
|
|
+
|
|
|
+ const response = await fetch('fetch/calificaciones.php', {
|
|
|
+ method: 'POST',
|
|
|
+ body: params,
|
|
|
+ });
|
|
|
+ const data = await response.json();
|
|
|
+ this.datos = data;
|
|
|
+ store.loading = false;
|
|
|
+
|
|
|
+ /* this.createGraph(); */
|
|
|
+ }
|
|
|
+ }).mount()
|
|
|
+</script>
|