diff --git a/README.md b/README.md index e9b59c4c..fde878f4 100644 --- a/README.md +++ b/README.md @@ -1,25 +1,31 @@ -# Data Dashboard +# Proyecto: Dashboard Laboratoria -* **Track:** _Common Core_ -* **Curso:** _Creando tu primer sitio web interactivo_ -* **Unidad:** _Producto final_ +![Dashboard](assets/images/mvp.jpg) -*** +## Descripción del Proyecto: -## Flujo de trabajo +El siguiente repositorio contiene el desarrollo de un MVP, de un dashboard, con la información relevante de la estadística de Laboratoria y su data respecto al rendimiento de sus estudiantes y el de sus profesores. -1. Debes realizar un [**fork**](https://gist.github.com/ivandevp/1de47ae69a5e139a6622d78c882e1f74) - de este repositorio. +## Procedimiento: -2. Luego deberás **clonar** tu fork en tu máquina. Recuerda que el comando a usar - es `git clone` y su estructura normalmente se ve así: +1. Primero se realizó un sketching del producto - ```bash - git clone https://github.com//freelancer.git - ``` +2. Segundo, se realizó una entrevista a la Training Manager de Laboratoria Lima: Alejandra Ramirez, para conocer sus necesidades y requirimientos del producto. +Ella señaló que le era necesario tener la data del número de estudiantes actuales y que desertaron a primera mano. Así también un ranking del desempeño de sus profesores y la aprobación que Laboratoria obtiene como centro de enseñanza. También sugirió la implementación de un perfil de usuario visible. -3. Cuando hayas terminado tu producto, envía un Pull Request a este repositorio - (puedes solicitar apoyo de tus profes para este paso). +3. La segunda persona entrevistada fue Franco Chamochumbi, encargado de Finanzas de Laboratoria; quien también indicó que tenía relevancia poder ver la cantidad de estudiantes actuales y el número de deserciones. Además poder filtrarlo por sede y generación. -> Nota: No olvides que es una buena práctica describir tu proyecto en este -> archivo `README.md` y también desplegar tu web a Github Pages :smiley:. +4. Posteriormente se pasó a modificae el sketching de el producto, replicando las necesidades del usuario. + +5. Desarrollo del maquetado. + +6. Programación de funcionalidades. + + +## Herramientas utilizadas: + +1. HTML5 + +2. CSS3 + +3. JS diff --git a/assets/images/logo-laboratoria.png b/assets/images/logo-laboratoria.png new file mode 100644 index 00000000..ac238f85 Binary files /dev/null and b/assets/images/logo-laboratoria.png differ diff --git a/assets/images/mvp.jpg b/assets/images/mvp.jpg new file mode 100644 index 00000000..a1896b1b Binary files /dev/null and b/assets/images/mvp.jpg differ diff --git a/assets/images/user.jpg b/assets/images/user.jpg new file mode 100644 index 00000000..2fef0b20 Binary files /dev/null and b/assets/images/user.jpg differ diff --git a/css/main.css b/css/main.css index 6355c827..291170ee 100644 --- a/css/main.css +++ b/css/main.css @@ -1,3 +1,382 @@ /* * Estilos de tu proyecto */ + + * { + box-sizing: border-box; + margin: 0; + padding: 0; + } + +.body { + overflow: auto; +} +.uppercase { + text-transform: uppercase; +} + +header { + width: 100%; + height: 120px; +} + +.logo { + width: 15%; + height: 20px; + margin: 0 auto; +} + +.logo img { + padding-top: 10px; + width: 100%; +} + +#menu { + font-size: 30px; + float: left; + margin-top: 10px; + margin-left: 150px; + } + + +/*Estilo para select sede */ + +.sede { + margin-left: 320px; + background: transparent; + border: none; + font-size: 18px; + height: 30px; + padding: 5px; + width: 250px; + outline: none; + } + +/*Estilo para select semestre*/ +.semestre{ + margin-left: 150px; + background: transparent; + border: none; + font-size: 18px; + height: 30px; + padding: 5px; + width: 250px; + outline: none; + } + +/*Estilo a sections-container */ + +.sections-container { + height: 100px; + width: 80%; + float: right; + background-color: #d4d4d4; + font-family: sans-serif; +} + + + div#sections span { + line-height: 100px; + display: inline-block; + padding-left: 50px; + padding-bottom: 20px; + font-weight: bold; + font-size: 20px; + } + + div#sections a { + padding: 10px; + text-decoration: none; + color: #000; + } + + div#sections a:hover { + display: inline; + background: #ffc107; + color: white; + } + + /*Estilo para esconder el modal*/ + .hidden { + display: none; + margin-top: 170px; + margin-left: 170px; + } + + +/*Estilo del usuario */ +section.user { + float: left; + width: 20%; + /*outline: 1px solid red; */ + font-family: sans-serif; + border: 2px solid #ffc107; +} + +div.user-name { + text-align: center; +} + +section.user img { + width: 30%; + height: 30%; + margin-top: 30px; + border-radius: 10px; +} + +div.name { + float: right; +} +section.user h3.name { + display: inline-block; + margin-left: 20px; +} + +section.user h4 { + display: inline-block; +} + +div.home { + border-bottom: 1px solid #ffc107; + margin-top: 60px; + padding-top: 20px; + padding-bottom: 10px; +} + +div.tables, div.calendar { + border-bottom: 1px solid #ffc107; + padding: 20px 0px; + padding-bottom: 10px; +} + +div.out { + padding: 20px 0px; +} + +.home h4, .tables h4, .calendar h4, .out h4 { + display: inline-block; + margin-left: 30px; +} + +section.user i { + margin-left: 30px; +} + +div.home:hover, div.tables:hover, div.calendar:hover, div.out:hover { + background-color: #ffc107; + color: #fff; +} + + /*Estilo de la sección teacher */ + + .teachers-data { + float: right; + margin: auto; + width: 80%; + height: 300px; + background-color: #e9e3e3; + } + +.average-container{ + font-family: sans-serif; + margin-top: 40px; + margin-left: 80px; + width: 40%; + height: 200px; + background-color: #fff; + display: inline-block; + text-align: center; +} + + .average-title { + padding-top: 15px; + } + + /*Estilos para la seccion data*/ +.data{ + + font-family: 'Montserrat', sans-serif; + font-weight: bold; + /*margin-top: 210px;*/ + background-color: #f7f7f7; + /*padding-left: 50px;*/ + width: 80%; + float: right; +} +/* Estilos para part 1, 4 y 5*/ +.part1 div, .part4 div, .part5 div{ + display: inline-block; + background-color: #ffffff; + margin-top: 65px; + margin-left: 60px; +} +.part2, .part3{ + width: 90%; + height: 200px; + margin-top: 20px; + background-color: #ffffff; + margin-left: 50px; +} + +.part1 div, .part4 div, .part5 div{ + width: 42%; + height: 200px; +} + /* Estilos para los box donde iran los datos*/ +.part1 .box, .part2 .box, .part3 .box, .part4 .box, .part5 .box{ + width: 100px; + height: 60px; + margin: 0px; + margin-left: 20px; + display: inline-block; + +} +/*estilos de los datos*/ +.box .total-students, .box .desercion{ + width: 42px; + height: 32px; + margin: 0px; +} + +.part1 p, .part2 p, .part3 p, .part4 p, .part5 p{ + padding: 20px; +} + +.a p, .selection{ + display: inline-block; +} +.b p, .selection{ + display: inline-block; +} + +.part5 div{ + margin-bottom: 65px; + /*Estilo de la sección students */ +} + +.students-data { + float: right; + margin: 0; + width: 80%; + height: 100%; + background-color: #e9e3e3; + display: block; + padding: 20px; + position: relative; +} +#search { + padding: 10px; +} +#search-input { + width: 90%; + height: 50px; + margin-left: 60px; + margin-right: 55px; + margin-bottom: 15px; + padding: 15px; + border: 2px solid #ffc107; + border-radius: 10px; +} +/*container-data: Se agregaran con DOM-classLists */ +.container-data{ + width: 90%; + height: 20%; + margin-left: 60px; + margin-right: 50px; + padding: 15px; + background-color: #fff; + display: inline-block; +} +/*---create:div>img - classLists:photo-profile---*/ +.photo-profile{ + width: 200px; + height: 245px; + margin: 15px; + background-color: black; + display: block; + position: relative; + float: left; + text-align: center; +} +/*---create:div>div*2 - classLists:info-profile---*/ +.info-profile{ + margin: 5px; + padding: 5px; + display: block; + position: relative; + float: left; +} + +.name-profile{ + padding: 5px; + color: black; + display: block; + position: relative; + font-size: 1.5rem; + font-weight: 800; + text-align: center; + text-transform: uppercase; +} + +.status-profile{ + margin: 2px; + color: black; + display: block; + position: relative; + font-size: 1.2rem; + font-weight: 500; + text-transform: capitalize; + text-align: center; +} +/*---create:div>div*2 - classLists:skills-profile---*/ +.skills-profile{ + margin: 15px; + margin-left: 120px; + display: block; + position: relative; + float: left; +} + +.skill { + margin-bottom: 10px; + padding: 10px; + background-color: #e9e3e3; + height: 70px; + width: 150px; + text-align: center; + align-content: center; + font-size: 20px; + font-weight: 800; + text-transform: uppercase; +} + +.skill-text { + margin: 2px; + font-size: 1rem; + font-weight: 600; + text-transform: uppercase; +} +/*---create:div>button - classLists:info-profile---*/ +.button { + margin-top: 15px; +} +.remove { + margin: 15px; + padding: 10px; + width: 120px; + height: 50px; + background-color: #ffc107; + color: black; + font-size: 1rem; + font-weight: 700; + border: none; + border-radius: 10px; +} +.remove:hover { + background-color: black; + color: white; +} + +.display-none { + display: none; +} diff --git a/index.html b/index.html index 8930fa03..e7c18b0f 100644 --- a/index.html +++ b/index.html @@ -3,12 +3,205 @@ Data Dashboard + + +
+ + +
- - - - + + + + + + + + +
+ +
+ + +
+
+ Alejandra Ramirez +
+

Alejandra Ramirez

+

Training Manager

+
+
+
+ +

Home

+
+
+ +

Tables

+
+
+ +

Calendar

+
+
+ +

Sign out

+
+
+ + +
+
+
+ +

ENROLLMENT

+
+
6
+

Inscritas

+
+
+
57
+

desercion

+
+
+ +
+ +

SKILLS

+
+
+
+ +
+
+
+ +

TECH SKILLS

+ + +
+
+
+
+ +
+
+ +

HSC SKILLS

+ + +
+
+
+
+ +
+
+ +

STUDENT SATISFACTION

+
+
+
+ +

NET PROMOTER SCORE (NPS)

+
+
+
+
+
+ +

TEACHER RATING

+
+
+
+
+ +

JEDI MASTER RATING

+
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/js/app.js b/js/app.js index 895ae2dd..0ea4c959 100644 --- a/js/app.js +++ b/js/app.js @@ -3,4 +3,332 @@ */ // Puedes hacer uso de la base de datos a través de la variable `data` +/* console.log(data.AQP); +console.log(data.LIM); +console.log(data.CDMX); +console.log(data.SCL); +/* var AQP = data.AQP["2017-2"];*/ +/* var arequipa = data.AQP; +var lima = data.LIM; +var mexico = data.CDMX; +var chile = data.SCL; +/* console.log(AQP); */ console.log(data); + +window.addEventListener('load', function(event) { + var sede = document.getElementById('sede'); + var semestre = document.getElementById('semestre'); + + + sede.addEventListener('change', jalarData); + document.addEventListener('change', inscritas); + /* funcion para sacar data de acuerdo a la sede y semestre que se elige*/ + function jalarData(event) { + for (var i = 0; i < Object.keys(data).length; i++) { + if (event.target.value === Object.keys(data)[i]) { + semestre.innerHTML = ''; + /* Metodo reverse para que salga el ultimo semestre primero*/ + var todosSemestres = Object.keys(data[sede.value]).reverse(); + console.log(todosSemestres); + for (var j = 0; j < todosSemestres.length; j++) { + var optionSemestre = document.createElement('option'); + optionSemestre.value = todosSemestres[j]; + optionSemestre.textContent = todosSemestres[j]; + semestre.appendChild(optionSemestre); + } + } + } + } + /* Funcion para jalar data de alumnas inscritas y desercion por sede */ + function inscritas(event) { + if (event.target === sede || event.target === semestre) { + var alumnas = data[sede.value][semestre.value].students; + var alumnasInscritas = 0; + var alumnasDesercion = 0; + + for (var i = 0; i < alumnas.length; i++) { + if (alumnas[i]['active'] === true) { + alumnasInscritas++; + } else { + alumnasDesercion++; + } + } + document.getElementById('total-students').textContent = alumnasInscritas; + document.getElementById('desercion').textContent = Math.round((alumnasDesercion / alumnas.length) * 100) * 10 / 10 + '%'; + } + averageTeachers(); + } + + /* Función para obtener promedio de profesores */ + function averageTeachers(event) { + if (sede === sede || event.target === semestre) { + var ratings = data[sede.value][semestre.value].ratings; + console.log(ratings); + var sum = 0; + + for (var i = 0; i < ratings.length; i++) { + var teacherNote = ratings[i]['teacher']; + sum += teacherNote; + console.log(sum); + var average = Math.round(sum / ratings.length); + console.log(average); + } + var averageText = document.createTextNode(average); + console.log(averageText); // '4' + var box = document.getElementById('teachers-average'); + console.log(box); + var averageContainer = document.createElement('h4'); + averageContainer.appendChild(averageText); + box.appendChild(averageContainer); + } + averageJedis(); + } + + /* Función para obtener el promedio de los profesores */ + function averageJedis(event) { + if (sede === sede || event.target === semestre) { + var ratings = data[sede.value][semestre.value].ratings; + console.log(ratings); + var sum = 0; + + for (var i = 0; i < ratings.length; i++) { + var jediNote = ratings[i]['jedi']; + sum += jediNote; + console.log(sum); + var average = Math.round(sum / ratings.length); + console.log(average); + } + var averageTextJedi = document.createTextNode(average); + console.log(averageTextJedi); + var box = document.getElementById('jedis-average'); + console.log(box); + var averageContainerJedi = document.createElement('h4'); + averageContainerJedi.appendChild(averageTextJedi); + box.appendChild(averageContainerJedi); + } + + nps(); + } + /* Funcion para el rendimiento hse-tech */ + function hscTech(event) { + if (event.target === sede || event.target === semestre) { + var alumnas = data[sede.value][semestre.value].students; + var sprints = data[sede.value][semestre.value].ratings.length; + var alumnasInscritas = 0; + var superaAlumnas = 0; + for (var i = 0; i < alumnas.length; i++) { + if (alumnas[i]['active'] === true) { + alumnasInscritas++; + var sumHsc = 0; + var sumTech = 0; + var superaTech = 0; + var superaHse = 0; + for (var j = 0; j < sprints; j++) { + sumTech = sumTech + alumnas[i].sprints[j].score.tech; + if (alumnas[i].sprints[j].score.tech > 1260) { + superaTech++; + } + sumHse = sumHsc + alumnas[i].sprints[j].score.hse; + if (alumnas[i].sprints[j].score.hse > 840) { + superaHse++; + } + } + var tech1 = Math.floor(sumTech / sprints); + var hse1 = Math.floor(sumHsc / sprints); + if (tech1 > 1260 && hse1 > 840) { + superaAlumnas++; + } + } + } + var tech2 = superaTech / sprints; + var hsc2 = superaHse / sprints; + document.getElementById('supera').textContent = superaAlumnas; + document.getElementById('porcentaje').textContent = Math.round((superaAlumnas / alumnasInscritas) * 100) * 10 / 10 + '%'; + } + } + function satisfaction(event) { + if (event.target === sede || event.target === semestre) { + var divSatisfaction = document.getElementById('satis1'); + var total = 0; + var totalSatisfaccion = 0; + for (var i in contentData['ratings']) { + var byTotalCumple = 0; + var byTotalSupera = 0; + var ratingS = contentData['ratings'][i]; + byTotalCumple += ratingS['student']['cumple']; + byTotalSupera += ratingS['student']['supera']; + console.log(byTotalCumple); + console.log(byTotalSupera); + total = byTotalCumple + byTotalSupera; + totalSatisfaccion += total; + } + /* for (var indiceSprint in contentData['ratings'][i]) { + var sprint = contentData['sprints'][indiceSprint]; + console.log(sprint); + }*/ + + console.log(totalSatisfaccion); + divSatisfaction.innerHTML = totalSatisfaccion; + } + } + function achievement(event) { + if (event.target === sede || event.target === semestre) { + // Llenando datos del ACHIEVEMENT + /* op3 - N° de students que superan la meta de puntos en promedio de los sprints(70%) del total de puntos en HSE y en tech.*/ + /* op4 - El porcentaje que representa el dato anterior en relación al total de estudiantes.*/ + var ach1 = document.getElementById('ach1'); + var ach2 = document.getElementById('ach2'); + + console.log(' Estudiantes: '); + var totalTotal = 0; + console.log(contentData['students']); + for (var indiceStudent in contentData['students']) { + var student = contentData['students'][indiceStudent]; + console.log(' Estudiante: ' + student['name']); + console.log(student); + var totalByStudent = 0; + for (var indiceSprint in student['sprints']) { + var sprint = student['sprints'][indiceSprint]; + console.log(' Sprint number: ' + sprint['number']); + console.log(sprint); + totalByStudent += sprint['score']['tech']; + } + console.log('Total del alumno: ' + student['name'] + '=' + totalByStudent); + totalTotal += totalByStudent; + } + ach1.innerHTML = totalTotal; + } + } + + + function nps(event) { + if (sede === sede || event.target === semestre) { + var ratings = data[sede.value][semestre.value].ratings; + console.log(ratings); + var students = data[sede.value][semestre.value].students; + var totalStudents = students.length; + console.log(totalStudents); + var arrSprints = []; + for (var i = 0; i < ratings.length; i++) { + var promoters = ratings[i]['nps']['promoters']; + console.log(promoters); // 97, 81, 87 + var detractors = ratings[i]['nps']['detractors']; + console.log(detractors); + var sprints = ratings[i]['sprint']; + console.log(sprints); // 1 , 2 : me da el número de sprint + arrSprints.push(sprints); + console.log(arrSprints); + } + /* Aplicando la fórmula + [Promoters] = [Respuestas 9 o 10] / [Total respuestas] * 100 + [Passive] = [Respuestas 7 u 8] / [Total respuestas] * 100 + [Detractors] = [Respuestas entre 1 y 6] / [Total respuestas] * 100 + + [NPS] = [Promoters] - [Detractors] */ + + var numberOfSprints = arrSprints.length; + console.log(numberOfSprints); + // var averagePromoters = ((promoters / totalStudents) * 100); + // console.log(averagePromoters); + // var averageDetractors = ((detractors / totalStudents) * 100); + // console.log(averageDetractors); + var averageNps = ((Math.round((promoters - detractors) / numberOfSprints)) * 100) / 100 + '%'; + console.log(averageNps); + } + var npsContainer = document.getElementById('nps-container'); + /* Creando nodo te texto */ + var averageTextNps = document.createTextNode(averageNps); + console.log(averageTextNps); + var npsTextContainer = document.createElement('h4'); + /* Insertando el texto a h4 */ + npsTextContainer.appendChild(averageTextNps); + npsContainer.appendChild(npsTextContainer); + } + + var students = document.getElementById('students'); + students.addEventListener('click', function(event) { + var sectionEstudents = document.getElementById('section-students'); + var sectionData = document.getElementById('section-data'); + var section = document.getElementById('teachers-ratings'); + var formSearch = document.getElementById('search'); + /* Creando el contenedor-data de students.*/ + var containerData = document.createElement('div'); + /* Creando elementos para la foto del estudiante.*/ + var photoProfile = document.createElement('div'); + var img = document.createElement('img'); + /* Creando elementos para la nombre y status del estudiante.*/ + var infoProfile = document.createElement('div'); + var name = document.createElement('div'); + // var textName = document.createElement('p'); + var status = document.createElement('div'); + // var texStatus = document.createElement('p'); + /* Creando elementos para skills del estudiante.*/ + var skillsProfile = document.createElement('div'); + var skillTech = document.createElement('div'); + // var percentT = document.createElement('p'); + // var textSkillt = document.createElement('p'); + var skillHse = document.createElement('div'); + // var percentH = document.createElement('p'); + // var textSkillh = document.createElement('p'); + var divButton = document.createElement('div'); + var buttonRemove = document.createElement('button'); + + sectionEstudents.appendChild(containerData); + sectionEstudents.insertBefore(formSearch, containerData); + containerData.appendChild(photoProfile); + containerData.appendChild(infoProfile); + infoProfile.appendChild(name); + infoProfile.appendChild(status); + infoProfile.insertBefore(name, status); + containerData.appendChild(skillsProfile); + skillsProfile.appendChild(skillTech); + skillsProfile.appendChild(skillHse); + skillsProfile.appendChild(divButton); + skillsProfile.insertBefore(skillTech, skillHse); + skillsProfile.insertBefore(skillHse, divButton); + divButton.appendChild(buttonRemove); + buttonRemove.textContent = 'Remove'; + sectionData.classList.add('display-none'); + sectionEstudents.classList.remove('display-none'); + buttonRemove.setAttribute('type', 'submit'); + containerData.classList.add('container-data'); + photoProfile.classList.add('photo-profile'); + infoProfile.classList.add('info-profile'); + name.classList.add('name-profile'); + status.classList.add('status-profile'); + skillsProfile.classList.add('skills-profile'); + skillTech.classList.add('skill'); + skillHse.classList.add('skill'); + divButton.classList.add('button'); + buttonRemove.classList.add('remove'); + }); + + + teachers.addEventListener('click', function showData(event) { + // Creando el contenedor del promedio de los Teachers. + var sectionEstudents = document.getElementById('section-students'); + var sectionData = document.getElementById('section-data'); + var section = document.getElementById('teachers-ratings'); + var teachersOption = document.getElementById('teachers'); + var containerData = document.createElement('div'); + var containerTeacher = document.createElement('div'); + var titleData = document.createElement('h1'); + titleData.textContent = 'Overall Teacher Rating'; + containerData.appendChild(containerTeacher); + containerTeacher.appendChild(titleData); + containerTeacher.setAttribute('id', 'teacher-data'); + section.appendChild(containerData); + containerTeacher.classList.add('average-container'); + containerData.classList.add('teachers-data'); + titleData.classList.add('average-title'); + + // Creando el contenedor del promedio de los Jedis-masters + var containerJedis = document.createElement('div'); + var titleJedi = document.createElement('h1'); + titleJedi.textContent = 'Jedi Master Rating'; + containerData.appendChild(containerJedis); + containerJedis.appendChild(titleJedi); + containerJedis.classList.add('average-container'); + titleJedi.classList.add('average-title'); + }); +});