Skip to content

Commit ce69c40

Browse files
Merge pull request #105 from Daniel-Alvarenga/main
Load ranking from server on public pages
2 parents e5ddfd1 + 529dd6b commit ce69c40

File tree

5 files changed

+194
-51
lines changed

5 files changed

+194
-51
lines changed

client/src/router/routes/shared.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import PublicPerfilProfessor from '../../views/shared/PerfilProfessor.vue';
55
import Pesquisa from '../../views/shared/Pesquisa.vue';
66
import Vagas from '../../views/shared/Vagas.vue';
77
import Vaga from '../../views/shared/Vaga.vue';
8+
import Ranking from '../../views/shared/Ranking.vue';
89
import { isAuthAluno, isAuthSomebody } from '../guards/guards';
910

1011
export const sharedRoutes = [
@@ -58,6 +59,14 @@ export const sharedRoutes = [
5859
(await isAuthAluno()) ? next(`/aluno/vaga/${to.params.id}`) : next();
5960
}
6061
},
62+
{
63+
path: '/ranking',
64+
name: 'RankingPublico',
65+
component: Ranking,
66+
beforeEnter: async (to, from, next) => {
67+
(await isAuthAluno()) ? next(`/aluno/ranking}`) : next();
68+
}
69+
},
6170
{
6271
path: '/:pathMatch(.*)*',
6372
name: 'NotFound',

client/src/services/api/shared.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,4 +75,15 @@ export const getExtracurriculares = async (rm) => {
7575
console.log('Erro: ' + error);
7676
return error.response.data;
7777
}
78+
}
79+
80+
export const getNotaRanking = async (rm) => {
81+
try {
82+
const response = await api.get('/shared/ranking/boletim', {
83+
});
84+
return response;
85+
} catch (error) {
86+
console.log('Erro: ' + error);
87+
return error.response.data;
88+
}
7889
}

client/src/views/aluno/Ranking.vue

Lines changed: 37 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -6,51 +6,18 @@
66
<section class="content">
77
<div class="box" id="box1">
88
<H1>Rankings</H1>
9-
<h2>Rankings gerados a partir das atividades dos alunos. O objetivo desses rankings é proporcionar competitividade e destacar os alunos para as empresas.</h2>
9+
<h2>Ranking gerados a partir das notas dos alunos. O objetivo desse ranking é proporcionar competitividade e destacar os alunos para as empresas.</h2>
1010

1111
<div class="alunos">
1212
<p class="info">Ranking geral:</p>
13-
<router-link to="" class="aluno">
14-
<b>#1</b>
15-
<img src="../../assets/icons/m1.png" alt="">
16-
<img src="../../assets/icons/artwork.png" alt="">
17-
<p class="name">Beatriz Rodriges de Oliveira - 3º DS</p>
18-
<p class="pontos">XXXX pontos</p>
19-
</router-link>
20-
<router-link to="" class="aluno">
21-
<b>#2</b>
22-
<img src="../../assets/icons/m2.png" alt="">
23-
<img src="../../assets/icons/artwork.png" alt="">
24-
<p class="name">Maria Clara Dias Soares De Souza - 3º DS</p>
25-
<p class="pontos">XXXX pontos</p>
26-
</router-link>
27-
<router-link to="" class="aluno">
28-
<b>#3</b>
29-
<img src="../../assets/icons/m3.png" alt="">
30-
<img src="../../assets/icons/artwork.png" alt="">
31-
<p class="name">Daniel Rocha Alvarenga - 3º DS</p>
32-
<p class="pontos">XXXX pontos</p>
33-
</router-link>
34-
<router-link to="" class="aluno">
35-
<b>#4</b>
36-
<img src="../../assets/icons/m3.png" class="normal" alt="">
37-
<img src="../../assets/icons/artwork.png" alt="">
38-
<p class="name">Amanda Barbosa Godinho - 3º DS</p>
39-
<p class="pontos">XXXX pontos</p>
40-
</router-link>
41-
<router-link to="" class="aluno">
42-
<b>#5</b>
43-
<img src="../../assets/icons/m3.png" class="normal" alt="">
44-
<img src="../../assets/icons/artwork.png" alt="">
45-
<p class="name">Gustavo do Nascimento Paulo - 3º DS</p>
46-
<p class="pontos">XXXX pontos</p>
47-
</router-link>
48-
<router-link to="" class="aluno">
49-
<b>#6</b>
50-
<img src="../../assets/icons/m3.png" class="normal" alt="">
51-
<img src="../../assets/icons/artwork.png" alt="">
52-
<p class="name">Guilherme de Almeida Rodrigues - 3º DS</p>
53-
<p class="pontos">XXXX pontos</p>
13+
14+
<router-link v-for="(item, index) in ranking" :key="index" :to="`/aluno/profile/${item.aluno.rm}`" class="aluno">
15+
<b>#{{ index + 1 }}</b>
16+
<img :src="(index + 1 < 4) ? '../assets/icons/m' + (index + 1) + '.png' : '../../assets/icons/m3.png'" :class="(index + 1 < 4) ? 'medalha' : 'medalha normal' " alt="">
17+
<img v-if="item.aluno.imagem != 'default'" :src="item.aluno.imagem" alt="Foto do aluno">
18+
<img v-else src="../../assets/icons/artwork.png" alt="Foto padrão">
19+
<p class="name">{{ item.aluno.nome }} - 3º DS</p>
20+
<p class="pontos">{{ (item.rankingNota * 1000).toFixed(2) }} pontos</p>
5421
</router-link>
5522
</div>
5623
</div>
@@ -66,6 +33,8 @@ import searchIcon from '../../assets/icons/procurar.png';
6633
6734
import Cookies from 'js-cookie';
6835
36+
import { getNotaRanking } from '../../services/api/shared';
37+
6938
export default {
7039
name: 'Ranking',
7140
components: {
@@ -76,12 +45,36 @@ export default {
7645
return {
7746
aluno: {
7847
token: ''
48+
},
49+
ranking: {
50+
7951
}
8052
};
8153
},
8254
methods: {
83-
84-
}
55+
async getRanking() {
56+
try {
57+
const response = await getNotaRanking();
58+
if (response.status >= 200 && response.status < 300) {
59+
this.ranking = response.data;
60+
console.log(this.ranking)
61+
} else {
62+
console.error(
63+
"Erro ao carregar ranking",
64+
response.message,
65+
);
66+
}
67+
} catch (error) {
68+
console.error(
69+
"Erro ao carregar ranking",
70+
error.message,
71+
);
72+
}
73+
},
74+
},
75+
async created() {
76+
await this.getRanking();
77+
},
8578
};
8679
</script>
8780

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
<template>
2+
<Header />
3+
<div id="app">
4+
<main>
5+
<section class="content">
6+
<div class="box" id="box1">
7+
<H1>Rankings</H1>
8+
<h2>Ranking gerados a partir das notas dos alunos. O objetivo desse ranking é proporcionar competitividade e destacar os alunos para as empresas.</h2>
9+
10+
<div class="alunos">
11+
<p class="info">Ranking geral:</p>
12+
13+
<router-link v-for="(item, index) in ranking" :key="index" :to="`/aluno/profile/${item.aluno.rm}`" class="aluno">
14+
<b>#{{ index + 1 }}</b>
15+
<img :src="(index + 1 < 4) ? '../assets/icons/m' + (index + 1) + '.png' : '../../assets/icons/m3.png'" :class="(index + 1 < 4) ? 'medalha' : 'medalha normal' " alt="">
16+
<img v-if="item.aluno.imagem != 'default'" :src="item.aluno.imagem" alt="Foto do aluno">
17+
<img v-else src="../../assets/icons/artwork.png" alt="Foto padrão">
18+
<p class="name">{{ item.aluno.nome }} - 3º DS</p>
19+
<p class="pontos">{{ (item.rankingNota * 1000).toFixed(2) }} pontos</p>
20+
</router-link>
21+
</div>
22+
</div>
23+
</section>
24+
</main>
25+
</div>
26+
</template>
27+
28+
<script>
29+
import Header from '../../components/aluno/Header.vue';
30+
import searchIcon from '../../assets/icons/procurar.png';
31+
32+
import Cookies from 'js-cookie';
33+
34+
import { getNotaRanking } from '../../services/api/shared';
35+
36+
export default {
37+
name: 'Ranking',
38+
components: {
39+
Header,
40+
},
41+
data() {
42+
return {
43+
aluno: {
44+
token: ''
45+
},
46+
ranking: {
47+
48+
}
49+
};
50+
},
51+
methods: {
52+
async getRanking() {
53+
try {
54+
const response = await getNotaRanking();
55+
if (response.status >= 200 && response.status < 300) {
56+
this.ranking = response.data;
57+
console.log(this.ranking)
58+
} else {
59+
console.error(
60+
"Erro ao carregar ranking",
61+
response.message,
62+
);
63+
}
64+
} catch (error) {
65+
console.error(
66+
"Erro ao carregar ranking",
67+
error.message,
68+
);
69+
}
70+
},
71+
},
72+
async created() {
73+
await this.getRanking();
74+
},
75+
};
76+
</script>
77+
78+
<style lang="scss" scoped>
79+
@import "../../scss/pages/shared/_ranking.scss";
80+
81+
#app {
82+
display: flex;
83+
flex-direction: column;
84+
min-height: calc(100vh - 80px);
85+
min-height: 510px;
86+
87+
main {
88+
display: flex;
89+
flex: 1;
90+
min-height: calc(100vh - 80px);
91+
overflow: hidden;
92+
93+
.content {
94+
flex: 1;
95+
min-height: calc(100vh - 80px);
96+
padding: 20px;
97+
overflow-y: auto;
98+
99+
@media (max-width: 1000px) {
100+
width: calc(100% - 100px);
101+
}
102+
}
103+
}
104+
}
105+
</style>

server/src/modules/services/shared/GetRanking.ts

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { prisma } from "../../../prisma/client";
22
import { AppError } from "../../../errors/error";
3+
import { minioClient } from "../../../minioService";
34

45
const notaValores: { [key: string]: number } = {
56
MB: 10,
@@ -58,13 +59,37 @@ export class GetRankingUseCase {
5859
}
5960
});
6061

61-
const rankingDetalhado = ranking.map(rank => {
62-
const aluno = alunos.find(a => a.id === rank.alunoId);
63-
return {
64-
aluno,
65-
rankingNota: rank.rankingNota
66-
};
67-
});
62+
const rankingDetalhado = await Promise.all(
63+
ranking.map(async rank => {
64+
const aluno = alunos.find(a => a.id === rank.alunoId);
65+
if (aluno) {
66+
const bucketName = 'boot';
67+
const imageName = aluno.imagem as string;
68+
69+
let entityUrl = "default";
70+
71+
if (imageName) {
72+
try {
73+
await minioClient.statObject(bucketName, imageName);
74+
entityUrl = await minioClient.presignedUrl('GET', bucketName, imageName, 24 * 60 * 60);
75+
} catch (error) {
76+
console.error(`Erro ao verificar objeto ${imageName}:`, error);
77+
}
78+
}
79+
80+
return {
81+
aluno: {
82+
nome: aluno.name,
83+
rm: aluno.rm,
84+
imagem: entityUrl,
85+
},
86+
rankingNota: rank.rankingNota,
87+
};
88+
}
89+
90+
return null; // Retorna null caso não encontre o aluno
91+
})
92+
);
6893

6994
return rankingDetalhado;
7095
}

0 commit comments

Comments
 (0)