Skip to content

Commit 0efc0bf

Browse files
Create a styleable Select Element and replace all native ones with it
1 parent 96a0fea commit 0efc0bf

File tree

8 files changed

+385
-161
lines changed

8 files changed

+385
-161
lines changed

client/src/components/Select.vue

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<template>
2+
<div class="custom-select" @click="toggleOptions" @blur="closeOptions" tabindex="0">
3+
<div class="selected">
4+
<label>
5+
{{ dataSelect.description }}
6+
</label>
7+
<div class="description">
8+
<p>{{ selected ? selected.description : dataSelect.title }}</p>
9+
<img src="../assets/icons/angulo.png" alt="">
10+
</div>
11+
</div>
12+
<ul v-if="showOptions" class="options">
13+
<li>
14+
{{ dataSelect.title }}
15+
</li>
16+
<li v-for="option in dataSelect.options" :key="option.value" @click.stop="selectOption(option)">
17+
{{ option.description }}
18+
</li>
19+
</ul>
20+
</div>
21+
</template>
22+
23+
<script>
24+
export default {
25+
name: 'Select',
26+
props: {
27+
dataSelect: {
28+
description: {
29+
type: String,
30+
required: true
31+
},
32+
title: {
33+
type: String,
34+
required: true
35+
},
36+
options: {
37+
type: Array,
38+
required: true
39+
}
40+
}
41+
},
42+
data() {
43+
return {
44+
showOptions: false,
45+
selected: '',
46+
valor: '',
47+
};
48+
},
49+
methods: {
50+
toggleOptions() {
51+
this.showOptions = !this.showOptions;
52+
},
53+
closeOptions() {
54+
this.showOptions = false;
55+
},
56+
selectOption(option) {
57+
this.selected = option;
58+
this.valor = option.value;
59+
this.$emit('input', option.value);
60+
this.showOptions = false;
61+
}
62+
}
63+
};
64+
</script>
65+
66+
<style scoped>
67+
@import "../scss/layouts/_select.scss";
68+
</style>

client/src/scss/layouts/_select.scss

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
.custom-select {
2+
@include font-inter(300);
3+
@include flex(column, center, flex-start);
4+
position: relative;
5+
display: inline-block;
6+
width: 200px;
7+
cursor: pointer;
8+
border-radius: 5px;
9+
10+
&:focus {
11+
border-left: solid 3px $secondary-color-orange;
12+
border-radius: 0px 5px 5px 0px;
13+
.selected {
14+
border-radius: 0px 5px 5px 0px;
15+
}
16+
}
17+
18+
.selected {
19+
@include flex(column, center, flex-start);
20+
padding: 10px;
21+
border: 1px solid $terciary-color-dark;
22+
background-color: $terciary-color-dark;
23+
color: $font-color-dark;
24+
border-radius: 5px;
25+
26+
.description{
27+
@include flex(row, space-between, center);
28+
width: 100%;
29+
font-size: 0.8rem;
30+
31+
p {
32+
font-size: 0.9rem;
33+
}
34+
35+
img{
36+
transform: rotate(-90deg);
37+
width: 10px;
38+
filter: invert(100%);
39+
margin-right: 10px;
40+
}
41+
}
42+
43+
44+
label {
45+
letter-spacing: 1.5px;
46+
@include font-inter(200);
47+
font-size: 0.8rem;
48+
color: $font-color-dark-2;
49+
}
50+
}
51+
52+
.options {
53+
position: absolute;
54+
top: 100%;
55+
left: 0;
56+
width: 100%;
57+
border: 1px solid $terciary-color-dark;
58+
background-color: $terciary-color-dark;
59+
max-height: 200px;
60+
overflow-y: auto;
61+
z-index: 1000;
62+
list-style: none;
63+
margin: 0;
64+
padding: 0;
65+
font-size: 0.9rem;
66+
67+
li {
68+
padding: 10px;
69+
cursor: pointer;
70+
color: $font-color-dark-2;
71+
72+
&:hover {
73+
background-color: $secondary-color-orange;
74+
color: $terciary-color-dark;
75+
}
76+
}
77+
78+
li:first-child{
79+
opacity: 0.8;
80+
}
81+
}
82+
}

client/src/views/admin/RegisterCoordenador.vue

+17-7
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,20 @@
66
<h1>Registro de Coordenador</h1>
77

88
<label for="professor">Professor a se tornar coordenador:</label>
9-
<select id="professor" v-model="coordenador.name" required>
10-
<option value="" disabled>Selecione um professor</option>
11-
<option v-for="professor in professores" :key="professor.name" :value="professor.name">{{
12-
professor.name }}</option>
13-
</select>
9+
<Select :dataSelect="dataSelect" @input="coordenador.name = $event"/>
1410

1511
<button type="submit">Registrar</button>
1612

1713
</form>
1814
</div>
1915
</main>
2016
<Footer />
21-
2217
</template>
2318

2419
<script>
2520
import Header from '../../components/Header.vue';
2621
import Footer from '../../components/Footer.vue';
22+
import Select from '../../components/Select.vue';
2723
2824
import { mixinAdmin } from '../../util/authMixins.js';
2925
import { getProfessores, registerCoordenador } from '../../services/api/admin';
@@ -32,13 +28,19 @@ export default {
3228
name: 'RegisterCoordenador',
3329
components: {
3430
Header,
35-
Footer
31+
Footer,
32+
Select
3633
},
3734
data() {
3835
return {
3936
coordenador: {
4037
name: '',
4138
},
39+
dataSelect: {
40+
title: "Selecione um professor",
41+
description: "Professor",
42+
options: [],
43+
},
4244
professores: [],
4345
}
4446
},
@@ -61,6 +63,14 @@ export default {
6163
try {
6264
const response = await getProfessores(this.admin.token);
6365
this.professores = response.data
66+
67+
68+
this.dataSelect.options = this.professores.map(professor => ({
69+
value: professor.name,
70+
description: professor.name
71+
}));
72+
73+
console.log(this.dataSelect.options);
6474
} catch (error) {
6575
alert("Ops.. Algo deu errado. 😕\n" + error.message);
6676
}

client/src/views/admin/RegisterCurso.vue

+39-18
Original file line numberDiff line numberDiff line change
@@ -11,32 +11,21 @@
1111
</div>
1212

1313
<div>
14-
<label for="turno">Turno:</label>
15-
<select id="turno" name="turno" v-model="curso.turno" required>
16-
<option value="MANHA">Manhã</option>
17-
<option value="TARDE">Tarde</option>
18-
<option value="NOITE">Noite</option>
19-
<option value="INTEGRAL">Integral</option>
20-
</select>
14+
<Select :dataSelect="dataSelectTurno" @input="curso.turno = $event"/>
2115
</div>
2216

2317
<div>
2418
<label>Duração:</label>
2519
<div>
2620
<input type="number" v-model="curso.duracao_quantidade" required>
27-
<select id="duracao" name="duracao" v-model="curso.duracao_periodo" required>
28-
<option value="anos">Anos</option>
29-
<option value="meses">Meses</option>
30-
</select>
21+
<Select :dataSelect="dataSelectDuracao" @input="curso.duracao_periodo = $event"/>
3122
</div>
3223
</div>
3324

34-
<label for="coordenador">Coordenador:</label>
35-
<select id="coordenador" v-model="curso.coordenador" required>
36-
<option value="" disabled>Selecione um coordenador</option>
37-
<option v-for="coordenador in coordenadores" :key="coordenador.name" :value="coordenador.name">{{
38-
coordenador.name }}</option>
39-
</select>
25+
<div>
26+
<Select :dataSelect="dataSelectCoordenador" @input="curso.coordenador = $event"/>
27+
</div>
28+
4029
<br>
4130
<button type="submit">Registrar</button>
4231

@@ -50,6 +39,7 @@
5039
<script>
5140
import Header from '../../components/Header.vue';
5241
import Footer from '../../components/Footer.vue';
42+
import Select from '../../components/Select.vue';
5343
5444
import { mixinAdmin } from '../../util/authMixins.js';
5545
import { getCoordenadores, registerCurso } from '../../services/api/admin';
@@ -58,7 +48,8 @@ export default {
5848
name: 'RegisterCurso',
5949
components: {
6050
Header,
61-
Footer
51+
Footer,
52+
Select
6253
},
6354
data() {
6455
return {
@@ -69,6 +60,29 @@ export default {
6960
duracao_periodo: '',
7061
coordenador: ''
7162
},
63+
dataSelectTurno: {
64+
title: "Selecione um turno",
65+
description: "Turno",
66+
options: [
67+
{ value: 'MANHA', description: 'Manhã' },
68+
{ value: 'TARDE', description: 'Tarde' },
69+
{ value: 'NOITE', description: 'Noite' },
70+
{ value: 'INTEGRAL', description: 'Integral' }
71+
],
72+
},
73+
dataSelectDuracao: {
74+
title: "Selecione um período",
75+
description: "Período",
76+
options: [
77+
{ value: 'anos', description: 'Anos' },
78+
{ value: 'meses', description: 'Meses' },
79+
],
80+
},
81+
dataSelectCoordenador: {
82+
title: "Selecione um coordenador",
83+
description: "Coordenador",
84+
options: [],
85+
},
7286
coordenadores: [],
7387
}
7488
},
@@ -87,6 +101,8 @@ export default {
87101
88102
if (response.status >= 200 && response.status < 300) {
89103
alert("Tudo certo! 😉");
104+
await this.GetCoordenadores();
105+
90106
} else {
91107
alert("Ops.. Algo deu errado. 😕\n" + response.message);
92108
}
@@ -98,6 +114,11 @@ export default {
98114
try {
99115
const response = await getCoordenadores(this.admin.token);
100116
this.coordenadores = response.data;
117+
118+
this.dataSelectCoordenador.options = this.coordenadores.map(coordenador => ({
119+
value: coordenador.name,
120+
description: coordenador.name
121+
}));
101122
} catch (error) {
102123
alert("Ops.. Algo deu errado. 😕\n" + error.message);
103124
}

client/src/views/admin/RegisterFuncionario.vue

+15-9
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,7 @@
99
<input type="text" id="name" v-model="funcionario.name" required>
1010
</div>
1111
<div>
12-
<label for="cargo">Cargo de:</label>
13-
<select id="cargo" name="cargo" v-model="funcionario.cargo" required>
14-
<option value="GESTAO">Gestão</option>
15-
<option value="ADMINISTRACAO">Administração</option>
16-
<option value="DIRECAO">Direção</option>
17-
<option value="ORIENTACAO">Orientação</option>
18-
</select>
12+
<Select :dataSelect="dataSelect" @input="funcionario.cargo = $event"/>
1913
</div>
2014
<div>
2115
<label for="email">Email:</label>
@@ -38,6 +32,7 @@
3832
<script>
3933
import Header from '../../components/Header.vue';
4034
import Footer from '../../components/Footer.vue';
35+
import Select from '../../components/Select.vue';
4136
4237
import { mixinAdmin } from '../../util/authMixins.js';
4338
import { registerFuncionario } from '../../services/api/admin';
@@ -46,15 +41,26 @@ export default {
4641
name: 'RegisterFuncionario',
4742
components: {
4843
Header,
49-
Footer
44+
Footer,
45+
Select
5046
},
5147
data() {
5248
return {
5349
funcionario: {
5450
name: '',
55-
tituloPrincipal: '',
51+
cargo: '',
5652
email: '',
5753
},
54+
dataSelect: {
55+
title: "Selecione um cargo",
56+
description: "Cargo",
57+
options: [
58+
{ value: 'GESTAO', description: 'Gestão' },
59+
{ value: 'ADMINISTRACAO', description: 'Administração' },
60+
{ value: 'DIRECAO', description: 'Direção' },
61+
{ value: 'ORIENTACAO', description: 'Orientação' }
62+
],
63+
},
5864
}
5965
},
6066
computed: {

0 commit comments

Comments
 (0)