My changes
This commit is contained in:
@@ -77,6 +77,10 @@ $('div.modal#cargando').modal({
|
||||
|
||||
const store = reactive({
|
||||
loading: false,
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
perido: null as Periodo | null,
|
||||
>>>>>>> 7688f1aac1824c234bc5f19b154e9ad1f4808d4f
|
||||
current: {
|
||||
comentario: '',
|
||||
clase_vista: null,
|
||||
@@ -216,8 +220,13 @@ const store = reactive({
|
||||
registro_fecha_justificacion: Date;
|
||||
};
|
||||
try {
|
||||
<<<<<<< HEAD
|
||||
const res = await fetch('action/action_justificar.php', {
|
||||
method: 'PUT',
|
||||
=======
|
||||
const res = await fetch('action/justificar.php', {
|
||||
method: 'POST',
|
||||
>>>>>>> 7688f1aac1824c234bc5f19b154e9ad1f4808d4f
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
@@ -237,6 +246,44 @@ const store = reactive({
|
||||
store.current.justificada.justificador_rol = data.justificador_rol
|
||||
store.current.justificada.registro_fecha_justificacion = data.registro_fecha_justificacion
|
||||
},
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
async justificarBloque(fecha: Date, bloques: Array<number>, justificacion: string) {
|
||||
if (bloques.length === 0) {
|
||||
alert('No se ha seleccionado ningún bloque');
|
||||
return;
|
||||
}
|
||||
if (!justificacion) {
|
||||
alert('No se ha ingresado ninguna observación');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const res = await fetch('action/action_justificar.php', {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
fecha,
|
||||
bloques,
|
||||
justificacion,
|
||||
})
|
||||
})
|
||||
const resData = await res.json();
|
||||
if (resData.status === 'success') {
|
||||
alert('Se ha justificado el bloque');
|
||||
store.current.modal_state = 'Cargando datos...';
|
||||
$('div.modal#cargando').modal('show');
|
||||
await store.registros.fetch();
|
||||
$('div.modal#cargando').modal('hide');
|
||||
} else {
|
||||
alert('No se ha podido justificar el bloque');
|
||||
}
|
||||
} catch (error) {
|
||||
alert('Error al justificar');
|
||||
}
|
||||
},
|
||||
>>>>>>> 7688f1aac1824c234bc5f19b154e9ad1f4808d4f
|
||||
registros: {
|
||||
data: [] as Registro[],
|
||||
async fetch(fecha?: Date, fecha_inicio?: Date, fecha_fin?: Date) {
|
||||
@@ -284,7 +331,11 @@ const store = reactive({
|
||||
if one of the filters is null, then it is not relevant
|
||||
|
||||
*/
|
||||
<<<<<<< HEAD
|
||||
const filters = Object.keys(store.filters).filter((filtro) => store.filters[filtro] !== null || store.filters[filtro]?.length > 0 )
|
||||
=======
|
||||
const filters = Object.keys(store.filters).filter((filtro) => store.filters[filtro] !== null || store.filters[filtro]?.length > 0)
|
||||
>>>>>>> 7688f1aac1824c234bc5f19b154e9ad1f4808d4f
|
||||
return this.data.filter((registro: Registro) => {
|
||||
return filters.every((filtro) => {
|
||||
switch (filtro) {
|
||||
@@ -365,6 +416,10 @@ type Profesor = {
|
||||
}
|
||||
createApp({
|
||||
store,
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
messages: [] as Array<{ title: string, text: string, type: string, timestamp: string }>,
|
||||
>>>>>>> 7688f1aac1824c234bc5f19b154e9ad1f4808d4f
|
||||
get clase_vista() {
|
||||
return store.current.clase_vista
|
||||
},
|
||||
@@ -381,6 +436,7 @@ createApp({
|
||||
profesores: [] as Profesor[],
|
||||
async mounted() {
|
||||
$('div.modal#cargando').modal('show');
|
||||
<<<<<<< HEAD
|
||||
|
||||
// await store.registros.fetch()
|
||||
await store.facultades.fetch()
|
||||
@@ -390,5 +446,24 @@ createApp({
|
||||
this.profesores = await (await fetch('action/action_profesor.php')).json() as Profesor[];
|
||||
|
||||
$('div.modal#cargando').modal('hide');
|
||||
=======
|
||||
try {
|
||||
|
||||
// await store.registros.fetch()
|
||||
await store.facultades.fetch()
|
||||
await store.estados.fetch()
|
||||
await store.bloques_horario.fetch()
|
||||
await store.filters.switchFechas();
|
||||
store.periodo = await fetch('action/periodo_datos.php').then(res => res.json()) as Periodo;
|
||||
this.profesores = await (await fetch('action/action_profesor.php')).json() as Profesor[];
|
||||
|
||||
this.messages.push({ title: 'Datos cargados', text: 'Los datos se han cargado correctamente', type: 'success', timestamp: new Date() })
|
||||
} catch (error) {
|
||||
this.messages.push({ title: 'Error al cargar datos', text: 'No se pudieron cargar los datos', type: 'danger', timestamp: new Date() })
|
||||
}
|
||||
finally {
|
||||
$('div.modal#cargando').modal('hide');
|
||||
}
|
||||
>>>>>>> 7688f1aac1824c234bc5f19b154e9ad1f4808d4f
|
||||
}
|
||||
}).mount('#app')
|
||||
|
||||
207
ts/avisos.ts
Normal file
207
ts/avisos.ts
Normal file
@@ -0,0 +1,207 @@
|
||||
import { createApp, reactive } from 'https://unpkg.com/petite-vue?module'
|
||||
|
||||
type Profesor = {
|
||||
profesor_clave: string;
|
||||
profesor_correo: null | string;
|
||||
profesor_grado: null | string;
|
||||
profesor_id: number;
|
||||
profesor_nombre: string;
|
||||
}
|
||||
|
||||
type Carrera = {
|
||||
carrera_activa: boolean;
|
||||
carrera_comun: boolean;
|
||||
carrera_id: number;
|
||||
carrera_nombre: string;
|
||||
clave_carrera: string;
|
||||
facultad_id: number | null;
|
||||
nivel_id: number;
|
||||
}
|
||||
|
||||
type Periodo = {
|
||||
created_at: Date;
|
||||
estado_id: number;
|
||||
fecha_final: Date;
|
||||
id_periodo_sgu: number;
|
||||
nivel_id: number;
|
||||
periodo_clave: string;
|
||||
periodo_fecha_fin: Date;
|
||||
periodo_fecha_inicio: Date;
|
||||
periodo_id: number;
|
||||
periodo_nombre: string;
|
||||
}
|
||||
|
||||
type Aviso = {
|
||||
aviso_estado: boolean;
|
||||
aviso_titulo: string;
|
||||
aviso_fecha_final: Date;
|
||||
aviso_fecha_inicial: Date;
|
||||
aviso_id: number;
|
||||
aviso_texto: string;
|
||||
carreras: Carrera[];
|
||||
facultad_id: null;
|
||||
profesores: Profesor[];
|
||||
}
|
||||
|
||||
const new_aviso = reactive({
|
||||
titulo: '',
|
||||
descripcion: '',
|
||||
fechaInicio: '',
|
||||
fechaFin: '',
|
||||
profesores: [] as Array<Profesor>,
|
||||
carreras: [] as Array<Carrera>,
|
||||
reset() {
|
||||
this.titulo = ''
|
||||
this.descripcion = ''
|
||||
this.fechaInicio = ''
|
||||
this.fechaFin = ''
|
||||
this.profesores = []
|
||||
this.carreras = []
|
||||
},
|
||||
get isValid() {
|
||||
return this.titulo !== '' && this.descripcion !== '' && this.fechaInicio !== '' && this.fechaFin !== '' && (this.profesores.length > 0 || this.carreras.length > 0) && this.facultad_id !== null
|
||||
},
|
||||
})
|
||||
// define datepicker method
|
||||
|
||||
const app = createApp({
|
||||
new_aviso,
|
||||
profesores: [] as Array<Profesor>,
|
||||
carreras: [] as Array<Carrera>,
|
||||
avisos: [] as Array<Aviso>,
|
||||
|
||||
profesor: null as String | null,
|
||||
formatProfesor(profesor: Profesor) {
|
||||
return `(${profesor.profesor_clave}) ${profesor.profesor_nombre}`
|
||||
},
|
||||
addProfesor() {
|
||||
const profesorObj = this.profesores.find((profesor: Profesor) => this.profesor === this.formatProfesor(profesor))
|
||||
if (profesorObj) {
|
||||
this.new_aviso.profesores.push(profesorObj)
|
||||
this.profesor = null
|
||||
}
|
||||
},
|
||||
|
||||
aviso_shown: null as Aviso | null,
|
||||
// int?
|
||||
aviso_suspendido: null as number | null,
|
||||
suspenderAviso() {
|
||||
if (this.aviso_suspendido) {
|
||||
const aviso = this.avisos.find((aviso: Aviso) => aviso.aviso_id === this.aviso_suspendido)
|
||||
if (aviso) {
|
||||
this.deleteAviso(aviso)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
get relevant_profesores() {
|
||||
// not in array new_aviso.profesores
|
||||
const relevant = this.profesores.filter((profesor: Profesor) => !this.new_aviso.profesores.map((profesor: Profesor) => profesor.profesor_id).includes(profesor.profesor_id))
|
||||
// console.log('profesores:', this.profesores.map((profesor: Profesor) => profesor.profesor_nombre), 'relevant:', relevant.map((profesor: Profesor) => profesor.profesor_nombre), 'new_aviso:', this.new_aviso.profesores.map((profesor: Profesor) => profesor.profesor_nombre))
|
||||
return relevant
|
||||
},
|
||||
|
||||
get relevant_carreras() {
|
||||
// not in array new_aviso.carreras
|
||||
return this.carreras.filter((carrera: Carrera) => !this.new_aviso.carreras.includes(carrera))
|
||||
},
|
||||
|
||||
createAviso() {
|
||||
const data = {
|
||||
aviso_titulo: this.new_aviso.titulo,
|
||||
aviso_texto: this.new_aviso.descripcion,
|
||||
aviso_fecha_inicial: this.new_aviso.fechaInicio,
|
||||
aviso_fecha_final: this.new_aviso.fechaFin,
|
||||
profesores: this.new_aviso.profesores.map((profesor: Profesor) => profesor.profesor_id),
|
||||
carreras: this.new_aviso.carreras.map((carrera: Carrera) => carrera.carrera_id),
|
||||
}
|
||||
fetch('/action/avisos.php', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data)
|
||||
}).then(res => res.json()).then(res => {
|
||||
if (res.success) {
|
||||
// hydrate with carreras and profesores
|
||||
this.avisos.push({
|
||||
...data,
|
||||
carreras: this.carreras.filter((carrera: Carrera) => data.carreras.includes(carrera.carrera_id)),
|
||||
profesores: this.profesores.filter((profesor: Profesor) => data.profesores.includes(profesor.profesor_id)),
|
||||
aviso_estado: true,
|
||||
aviso_id: res.aviso_id,
|
||||
})
|
||||
this.new_aviso.reset()
|
||||
}
|
||||
else {
|
||||
alert(res.error)
|
||||
console.log(res.errors)
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
deleteAviso(aviso: Aviso) {
|
||||
fetch(`/action/avisos.php`, {
|
||||
method: 'DELETE',
|
||||
body: JSON.stringify({ aviso_id: aviso.aviso_id })
|
||||
}).then(res => res.json()).then(res => {
|
||||
if (res.success) {
|
||||
this.avisos = this.avisos.filter((aviso: Aviso) => aviso.aviso_id !== this.aviso_suspendido)
|
||||
this.aviso_suspendido = null
|
||||
}
|
||||
else {
|
||||
alert(res.error)
|
||||
console.log(res.errors)
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
updateAviso() {
|
||||
fetch(`/action/avisos.php`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify({
|
||||
aviso_id: this.aviso_shown.aviso_id,
|
||||
aviso_fecha_final: this.aviso_shown.aviso_fecha_final,
|
||||
})
|
||||
}).then(res => res.json()).then(res => {
|
||||
if (res.success) {
|
||||
}
|
||||
else {
|
||||
alert(res.error)
|
||||
console.log(res.errors)
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
async initializeDatepickers($el: HTMLElement) {
|
||||
const periodo = await fetch('action/periodo_datos.php');
|
||||
const periodo_data = await periodo.json() as Periodo;
|
||||
|
||||
$('.date-picker').datepicker({
|
||||
dateFormat: 'yy-mm-dd',
|
||||
maxDate: periodo_data.periodo_fecha_fin,
|
||||
minDate: 0,
|
||||
});
|
||||
|
||||
$($el).on('change', () => {
|
||||
this.aviso_shown.aviso_fecha_final = $($el).val() as string;
|
||||
});
|
||||
},
|
||||
|
||||
async mounted() {
|
||||
this.avisos = await fetch("/action/avisos.php").then(res => res.json()) as Array<Aviso>
|
||||
this.profesores = await fetch('/action/action_profesor.php').then(res => res.json()) as Array<Profesor>
|
||||
this.carreras = await fetch('/action/action_carreras.php').then(res => res.json()) as Array<Carrera>
|
||||
|
||||
await this.initializeDatepickers()
|
||||
|
||||
const fechaInicio = $('#fechaInicio.date-picker')
|
||||
const fechaFin = $('#fechaFin.date-picker')
|
||||
fechaInicio.on("change", function () {
|
||||
new_aviso.fechaInicio = fechaInicio.val() as string
|
||||
fechaFin.datepicker("option", "minDate", fechaInicio.val());
|
||||
});
|
||||
|
||||
fechaFin.on("change", function () {
|
||||
new_aviso.fechaFin = fechaFin.val() as string
|
||||
fechaInicio.datepicker("option", "maxDate", fechaFin.val());
|
||||
});
|
||||
}
|
||||
}).mount('#app')
|
||||
63
ts/carreras.ts
Normal file
63
ts/carreras.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import { createApp, reactive } from 'https://unpkg.com/petite-vue?module'
|
||||
|
||||
type Carrera = {
|
||||
carrera_id: number;
|
||||
carrera_nombre: string;
|
||||
clave_carrera: string;
|
||||
facultad_id: number;
|
||||
facultad_nombre: string;
|
||||
nivel_id: number;
|
||||
nivel_nombre: string;
|
||||
}
|
||||
|
||||
type Nivel = {
|
||||
nivel_id: number;
|
||||
nivel_nombre: string;
|
||||
}
|
||||
|
||||
const app = createApp({
|
||||
carreras: [] as Carrera[],
|
||||
niveles: [] as Nivel[],
|
||||
message: {} as Record<string, string>,
|
||||
async setNivel(carrera: Carrera, nivel: Nivel) {
|
||||
if (carrera.nivel_id === nivel.nivel_id) {
|
||||
return
|
||||
}
|
||||
carrera.nivel_id = nivel.nivel_id
|
||||
carrera.nivel_nombre = nivel.nivel_nombre
|
||||
|
||||
await fetch('action/carrera.php', {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify({
|
||||
carrera_id: carrera.carrera_id,
|
||||
nivel_id: nivel.nivel_id
|
||||
})
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(res => {
|
||||
this.message.title = "Actualización"
|
||||
this.message.text = res.error ?? res.success
|
||||
this.message.type = res.error ? 'danger' : 'success'
|
||||
this.message.timestamp = new Date().toLocaleTimeString()
|
||||
})
|
||||
|
||||
|
||||
},
|
||||
async mounted() {
|
||||
this.carreras = await fetch('action/carrera.php').then(res => res.json())
|
||||
this.niveles = await fetch('action/nivel.php').then(res => res.json())
|
||||
// group by facultad_id
|
||||
const carreras = this.carreras.reduce((acc, cur) => {
|
||||
const { facultad_nombre } = cur
|
||||
if (!acc[facultad_nombre]) {
|
||||
acc[facultad_nombre] = []
|
||||
}
|
||||
acc[facultad_nombre].push(cur)
|
||||
return acc
|
||||
}, {} as Record<number, Carrera[]>)
|
||||
this.carreras = Object.entries(carreras).map(([facultad_nombre, carreras]) => ({
|
||||
facultad_nombre: facultad_nombre,
|
||||
carreras
|
||||
}))
|
||||
}
|
||||
}).mount('#app')
|
||||
149
ts/client.ts
Normal file
149
ts/client.ts
Normal file
@@ -0,0 +1,149 @@
|
||||
// @ts-ignore Import module
|
||||
import { createApp, reactive } from 'https://unpkg.com/petite-vue?module'
|
||||
|
||||
export interface PeridoV1 {
|
||||
IdNivel: number;
|
||||
IdPeriodo: number;
|
||||
NombreNivel: string;
|
||||
NombrePeriodo: string;
|
||||
in_db: boolean;
|
||||
linked: boolean;
|
||||
}
|
||||
|
||||
|
||||
export interface PeridoV2 {
|
||||
ClaveCarrera: string;
|
||||
FechaFin: string;
|
||||
FechaInicio: string;
|
||||
IdPeriodo: number;
|
||||
NombreCarrera: string;
|
||||
}
|
||||
|
||||
const webServices = {
|
||||
getPeriodosV1: async (): Promise<PeridoV1[]> => {
|
||||
try {
|
||||
const response = await fetch('periodos.v1.php');
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
return [];
|
||||
}
|
||||
},
|
||||
getPeriodosV2: async (): Promise<PeridoV2[]> => {
|
||||
try {
|
||||
const response = await fetch('periodos.v2.php');
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const store = reactive({
|
||||
periodosV1: [] as PeridoV1[],
|
||||
periodosV2: [] as PeridoV2[],
|
||||
|
||||
errors: [] as string[],
|
||||
fechas(idPeriodo: number): { inicio: string, fin: string } {
|
||||
const periodo = this.periodosV2.find((periodo: PeridoV2) => periodo.IdPeriodo === idPeriodo);
|
||||
return {
|
||||
inicio: periodo ? periodo.FechaInicio : '',
|
||||
fin: periodo ? periodo.FechaFin : ''
|
||||
}
|
||||
},
|
||||
periodov1(idPeriodo: number): PeridoV1 | undefined {
|
||||
return this.periodosV1.find((periodo: PeridoV1) => periodo.IdPeriodo === idPeriodo);
|
||||
},
|
||||
periodov2(idPeriodo: number): PeridoV2[] {
|
||||
return this.periodosV2.filter((periodo: PeridoV2) => periodo.IdPeriodo === idPeriodo);
|
||||
},
|
||||
async addPeriodo(periodo: PeridoV1 | PeridoV2) {
|
||||
try {
|
||||
const result = await fetch('backend/periodos.php', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
...periodo,
|
||||
...this.fechas(periodo.IdPeriodo)
|
||||
}),
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}).then((response) => response.json());
|
||||
if (result.success) {
|
||||
this.periodosV1 = this.periodosV1.map((periodoV1: PeridoV1) => {
|
||||
if (periodoV1.IdPeriodo === periodo.IdPeriodo) {
|
||||
periodoV1.in_db = true;
|
||||
}
|
||||
return periodoV1;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
this.errors.push(result.message);
|
||||
}
|
||||
} catch (error) {
|
||||
this.errors.push(error);
|
||||
}
|
||||
},
|
||||
|
||||
async addCarreras(idPeriodo: number) {
|
||||
try {
|
||||
const periodoV1 = this.periodov1(idPeriodo) as PeridoV1;
|
||||
const periodoV2 = this.periodov2(idPeriodo) as PeridoV2[];
|
||||
|
||||
const data = periodoV2.map(({ ClaveCarrera, NombreCarrera }: PeridoV2) =>
|
||||
({
|
||||
ClaveCarrera: ClaveCarrera,
|
||||
NombreCarrera: NombreCarrera,
|
||||
IdNivel: periodoV1.IdNivel,
|
||||
})
|
||||
);
|
||||
|
||||
const result = await fetch('backend/carreras.php', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}).then((response) => response.json());
|
||||
if (result.success) {
|
||||
await webServices.getPeriodosV1().then((periodosV1) => {
|
||||
this.periodosV1 = periodosV1;
|
||||
});
|
||||
|
||||
await webServices.getPeriodosV2().then((periodosV2) => {
|
||||
this.periodosV2 = periodosV2;
|
||||
});
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
this.errors.push(error);
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
createApp({
|
||||
store,
|
||||
info(IdPeriodo: number): PeridoV2 {
|
||||
const periodo = store.periodosV2.find((periodo: PeridoV2) => periodo.IdPeriodo === IdPeriodo &&
|
||||
periodo.FechaInicio != '' && periodo.FechaFin != '');
|
||||
return periodo
|
||||
},
|
||||
complete(IdPeriodo: number): boolean {
|
||||
const info = this.info(IdPeriodo);
|
||||
return info !== undefined;
|
||||
},
|
||||
mounted: async () => {
|
||||
|
||||
await webServices.getPeriodosV1().then((periodosV1) => {
|
||||
store.periodosV1 = periodosV1;
|
||||
});
|
||||
|
||||
await webServices.getPeriodosV2().then((periodosV2) => {
|
||||
store.periodosV2 = periodosV2;
|
||||
});
|
||||
|
||||
}
|
||||
}).mount()
|
||||
1
ts/declaration.ts
Normal file
1
ts/declaration.ts
Normal file
@@ -0,0 +1 @@
|
||||
declare module 'https://*'
|
||||
@@ -23,8 +23,12 @@ const app = createApp({
|
||||
},
|
||||
|
||||
async refresh() {
|
||||
<<<<<<< HEAD
|
||||
alert(`Facultad: ${filter.facultad} - Profesor: ${filter.profesor} - Porcentaje: ${filter.porcentaje}%`
|
||||
if(filter.facultad == -1 || filter.porcetaje < 10) {
|
||||
=======
|
||||
if(filter.facultad == -1 || filter.porcentaje < 10) {
|
||||
>>>>>>> 7688f1aac1824c234bc5f19b154e9ad1f4808d4f
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
181
ts/horario.ts
Normal file
181
ts/horario.ts
Normal file
@@ -0,0 +1,181 @@
|
||||
import { createApp, reactive } from 'https://unpkg.com/petite-vue?module'
|
||||
type Profesor = {
|
||||
profesor_clave: string;
|
||||
profesor_correo: string;
|
||||
profesor_grado: null | string;
|
||||
profesor_id: number;
|
||||
profesor_nombre: string;
|
||||
}
|
||||
|
||||
type Horario = {
|
||||
carrera: string;
|
||||
carrera_id: number;
|
||||
dia: string;
|
||||
duracion: string;
|
||||
duracion_id: number;
|
||||
facultad: string;
|
||||
facultad_id: number;
|
||||
fecha_carga: Date;
|
||||
horario_dia: number;
|
||||
horario_fecha_fin: null;
|
||||
horario_fecha_inicio: Date;
|
||||
horario_fin: string;
|
||||
horario_grupo: string;
|
||||
horario_hora: string;
|
||||
horario_id: number;
|
||||
limite: null;
|
||||
materia: string;
|
||||
materia_id: number;
|
||||
nivel: string;
|
||||
nivel_id: number;
|
||||
periodo: string;
|
||||
periodo_fecha_fin: Date;
|
||||
periodo_fecha_inicio: Date;
|
||||
periodo_id: number;
|
||||
profesor_id: number;
|
||||
salon: string;
|
||||
salon_id: number;
|
||||
bloques: number;
|
||||
}
|
||||
|
||||
type Facultad = {
|
||||
clave_dependencia: string;
|
||||
facultad_id: number;
|
||||
facultad_nombre: string;
|
||||
carreras: Carrera[];
|
||||
}
|
||||
|
||||
type Carrera = {
|
||||
carrera_id: number;
|
||||
carrera_nombre: string;
|
||||
clave_carrera: string;
|
||||
facultad_id: number;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const profesores = reactive({
|
||||
data: [] as Profesor[],
|
||||
search: null as null | string,
|
||||
fetch: async function () {
|
||||
const response = await fetch('action/action_profesor.php')
|
||||
this.data = await response.json() as Profesor[]
|
||||
},
|
||||
get clave() {
|
||||
const match = this.search.match(/^\((.+)\)/)
|
||||
return match ? match[1] : ''
|
||||
},
|
||||
get current() {
|
||||
return this.data.find((profesor: Profesor) => profesor.profesor_clave === profesores.clave)
|
||||
},
|
||||
})
|
||||
|
||||
const facultades = reactive({
|
||||
data: [] as Facultad[],
|
||||
fetch: async function () {
|
||||
const facultades = await fetch('action/action_facultad.php').then(response => response.json()) as Facultad[]
|
||||
const carreras = await fetch(`action/carrera.php`).then(response => response.json()) as Carrera[]
|
||||
this.data = await Promise.all(facultades.map(async facultad => ({
|
||||
...facultad,
|
||||
carreras: await Promise.all(carreras.filter((carrera: Carrera) => carrera.facultad_id === facultad.facultad_id).map(async (carrera: Carrera) => {
|
||||
const grupos = await fetch(`action/action_grupo.php?carrera_id=${carrera.carrera_id}`).then(response => response.json())
|
||||
return {
|
||||
...carrera,
|
||||
grupos,
|
||||
}
|
||||
})),
|
||||
})))
|
||||
|
||||
this.data = this.data.filter((facultad: Facultad) => facultad.carreras.length > 0)
|
||||
}
|
||||
})
|
||||
|
||||
type Structure = {
|
||||
sábado: boolean;
|
||||
hora_mínima: number;
|
||||
hora_máxima: number;
|
||||
horas_totales: number;
|
||||
}
|
||||
|
||||
const horarios = reactive({
|
||||
data: [] as Horario[],
|
||||
fetch: async function (grupo: number | null = null, carrera_id: number | null = null) {
|
||||
if (grupo && carrera_id) {
|
||||
const response = await fetch(`action/action_horario.php?grupo=${grupo}&carrera_id=${carrera_id}`)
|
||||
this.data = await response.json()
|
||||
}
|
||||
else if (profesores.current) {
|
||||
const response = await fetch(`action/action_horario.php?profesor_id=${profesores.current.profesor_id}`)
|
||||
this.data = await response.json()
|
||||
}
|
||||
},
|
||||
get structure() {
|
||||
if (this.data.length === 0) return null;
|
||||
|
||||
const structure: Structure = {
|
||||
sábado: this.data.some((horario: Horario) => horario.horario_dia === 6),
|
||||
hora_mínima: Math.min(...this.data.map((horario: Horario) => parseInt(horario.horario_hora.split(':')[0]))),
|
||||
hora_máxima: Math.max(...this.data.map((horario: Horario) => {
|
||||
const [hour, minute] = horario.horario_fin.split(':').map(Number);
|
||||
return hour + Math.ceil(minute / 60);
|
||||
})),
|
||||
horas_totales: 0
|
||||
};
|
||||
|
||||
structure.horas_totales = structure.hora_máxima - structure.hora_mínima;
|
||||
|
||||
return structure;
|
||||
},
|
||||
get blocks() {
|
||||
if (this.data.length === 0) return null;
|
||||
return [...Array(this.structure.horas_totales).keys()].flatMap(hora => {
|
||||
const baseHour = hora + this.structure.hora_mínima;
|
||||
return [0, 15, 30, 45].map(block => ({ hour: baseHour, block }));
|
||||
});
|
||||
},
|
||||
getHorarioData(hour: number, block: number, día: number) {
|
||||
const foundHorario = this.data.find((horario: Horario) =>
|
||||
parseInt(horario.horario_hora.split(':')[0]) === hour &&
|
||||
parseInt(horario.horario_hora.split(':')[1]) === block &&
|
||||
horario.horario_dia === día
|
||||
);
|
||||
return foundHorario;
|
||||
},
|
||||
isOccupied(hora: number, bloque: number, day: number) {
|
||||
if (this.getHorarioData(hora, bloque, day)) {
|
||||
return false;
|
||||
}
|
||||
const currentTimeInMinutes = hora * 60 + bloque;
|
||||
|
||||
for (const item of this.data) {
|
||||
if (item.horario_dia !== day) {
|
||||
continue; // Skip items that are not on the specified day
|
||||
}
|
||||
|
||||
// Split the hour and minute from horario_hora
|
||||
const [startHour, startMinute] = item.horario_hora.split(":").map(Number);
|
||||
const startTimeInMinutes = startHour * 60 + startMinute;
|
||||
|
||||
// Calculate end time using duracion
|
||||
const [durationHours, durationMinutes] = item.duracion.split(":").map(Number);
|
||||
const endTimeInMinutes = startTimeInMinutes + (durationHours * 60) + durationMinutes;
|
||||
|
||||
if (currentTimeInMinutes >= startTimeInMinutes && currentTimeInMinutes < endTimeInMinutes) {
|
||||
return true; // The block is occupied
|
||||
}
|
||||
}
|
||||
|
||||
return false; // The block is not occupied by any class
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
const app = createApp({
|
||||
profesores,
|
||||
horarios,
|
||||
facultades,
|
||||
mounted: async function () {
|
||||
await profesores.fetch()
|
||||
await facultades.fetch()
|
||||
}
|
||||
}).mount('#app')
|
||||
145
ts/periodos.ts
Normal file
145
ts/periodos.ts
Normal file
@@ -0,0 +1,145 @@
|
||||
import { createApp, reactive } from 'https://unpkg.com/petite-vue?module'
|
||||
|
||||
interface Periodo {
|
||||
created_at: Date;
|
||||
estado_id: number;
|
||||
id_periodo_sgu: number;
|
||||
nivel: string;
|
||||
nivel_id: number | '';
|
||||
periodo_clave: string;
|
||||
periodo_fecha_fin: Date;
|
||||
periodo_fecha_inicio: Date;
|
||||
periodo_id: number;
|
||||
periodo_nombre: string;
|
||||
}
|
||||
|
||||
interface Nivel {
|
||||
nivel_id: number;
|
||||
nivel_nombre: string;
|
||||
}
|
||||
|
||||
const app = createApp({
|
||||
periodos: [] as Array<Periodo>,
|
||||
niveles: [] as Array<Nivel>,
|
||||
messages: [] as Array<{ title: string, text: string, type: string, timestamp: string }>,
|
||||
|
||||
addMessage(title: string, text: string, type: string) {
|
||||
this.messages.push({ title, text, type, timestamp: new Date() });
|
||||
},
|
||||
|
||||
async sendRequest(action: string, periodo_id: number, data: any) {
|
||||
const response = await fetch('action/periodos.php', {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
action: action,
|
||||
periodo_id: periodo_id,
|
||||
...data
|
||||
})
|
||||
})
|
||||
return await response.json()
|
||||
},
|
||||
|
||||
async changeNivel(periodo: Periodo, nivel_id: number) {
|
||||
if (periodo.nivel_id === nivel_id) return
|
||||
|
||||
const result = await this.sendRequest('changeNivel', periodo.periodo_id, { nivel_id: nivel_id })
|
||||
if (result.success) {
|
||||
this.addMessage('Nivel cambiado', `El nivel del periodo ${periodo.periodo_nombre} ha sido cambiado a ${this.niveles.find((nivel: Nivel) => nivel.nivel_id === nivel_id)?.nivel_nombre}`, 'success')
|
||||
periodo.nivel_id = nivel_id
|
||||
periodo.nivel = this.niveles.find((nivel: Nivel) => nivel.nivel_id === nivel_id)?.nivel_nombre || ''
|
||||
} else {
|
||||
this.addMessage('Error al cambiar nivel', `No se pudo cambiar el nivel del periodo ${periodo.periodo_nombre}`, 'danger')
|
||||
}
|
||||
},
|
||||
|
||||
async changeFechaInicio(periodo: Periodo, fecha_inicio: Date) {
|
||||
const result = await this.sendRequest('changeFechaInicio', periodo.periodo_id, { periodo_fecha_inicio: fecha_inicio })
|
||||
if (result.success) {
|
||||
this.addMessage('Fecha de inicio cambiada', `La fecha de inicio del periodo ${periodo.periodo_nombre} ha sido cambiada a ${fecha_inicio}`, 'success')
|
||||
|
||||
periodo.periodo_fecha_inicio = fecha_inicio
|
||||
} else {
|
||||
this.addMessage('Error al cambiar fecha de inicio', `No se pudo cambiar la fecha de inicio del periodo ${periodo.periodo_nombre}`, 'danger')
|
||||
}
|
||||
},
|
||||
|
||||
async changeFechaFin(periodo: Periodo, fecha_fin: Date) {
|
||||
const result = await this.sendRequest('changeFechaFin', periodo.periodo_id, { periodo_fecha_fin: fecha_fin })
|
||||
if (result.success) {
|
||||
this.addMessage('Fecha de fin cambiada', `La fecha de fin del periodo ${periodo.periodo_nombre} ha sido cambiada a ${fecha_fin}`, 'success')
|
||||
periodo.periodo_fecha_fin = fecha_fin
|
||||
} else {
|
||||
this.addMessage('Error al cambiar fecha de fin', `No se pudo cambiar la fecha de fin del periodo ${periodo.periodo_nombre}`, 'danger')
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
async updatePeriodo(periodo: Periodo) {
|
||||
const result = await this.sendRequest('updatePeriodo', periodo.periodo_id, {
|
||||
periodo_nombre: periodo.periodo_nombre,
|
||||
id_periodo_sgu: periodo.id_periodo_sgu,
|
||||
periodo_clave: periodo.periodo_clave,
|
||||
})
|
||||
if (result.success) {
|
||||
this.addMessage('Periodo actualizado', `El periodo ${periodo.periodo_nombre} ha sido actualizado`, 'success')
|
||||
} else {
|
||||
this.addMessage('Error al actualizar periodo', `No se pudo actualizar el periodo ${periodo.periodo_nombre}`, 'danger')
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
async createPeriodo(newPeriodo: Periodo) {
|
||||
|
||||
if (newPeriodo.periodo_nombre === null || newPeriodo.nivel_id === null || newPeriodo.periodo_fecha_inicio === null || newPeriodo.periodo_fecha_fin === null) {
|
||||
this.addMessage('Error al crear periodo', `No se pudo crear el periodo ${newPeriodo.periodo_nombre}`, 'danger')
|
||||
return
|
||||
}
|
||||
|
||||
const result = await fetch('action/periodos.php', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(newPeriodo)
|
||||
}).then(res => res.json())
|
||||
|
||||
if (result.success) {
|
||||
this.addMessage('Periodo creado', `El periodo ${newPeriodo.periodo_nombre} ha sido creado`, 'success')
|
||||
|
||||
this.periodos
|
||||
Object.keys(newPeriodo).forEach(key => newPeriodo[key] = null);
|
||||
newPeriodo.nivel_id = '';
|
||||
this.periodos = await fetch('action/periodos.php').then(res => res.json())
|
||||
} else {
|
||||
this.addMessage('Error al crear periodo', `No se pudo crear el periodo ${newPeriodo.periodo_nombre}`, 'danger')
|
||||
}
|
||||
},
|
||||
|
||||
async deletePeriodo(periodo: Periodo) {
|
||||
const response = await fetch('action/periodos.php', {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
periodo_id: periodo.periodo_id,
|
||||
})
|
||||
})
|
||||
const result = await response.json()
|
||||
|
||||
if (result.success) {
|
||||
this.addMessage('Periodo eliminado', `El periodo ${periodo.periodo_nombre} ha sido eliminado`, 'success')
|
||||
this.periodos = this.periodos.filter((p: Periodo) => p.periodo_id !== periodo.periodo_id)
|
||||
} else {
|
||||
this.addMessage('Error al eliminar periodo', `No se pudo eliminar el periodo ${periodo.periodo_nombre}`, 'danger')
|
||||
}
|
||||
},
|
||||
|
||||
async mounted() {
|
||||
this.periodos = await fetch('action/periodos.php').then(res => res.json())
|
||||
this.niveles = await fetch('action/nivel.php').then(res => res.json())
|
||||
}
|
||||
}).mount('#app')
|
||||
106
ts/puestos.ts
Normal file
106
ts/puestos.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
import { createApp, reactive } from 'https://unpkg.com/petite-vue?module'
|
||||
type Puesto = {
|
||||
puesto_id: number,
|
||||
nombre: string,
|
||||
facultad_id: number,
|
||||
}
|
||||
|
||||
type Carrera = {
|
||||
carrera_id: number;
|
||||
carrera_nombre: string;
|
||||
clave_carrera: string;
|
||||
}
|
||||
|
||||
type Materia = {
|
||||
carrera_id: number;
|
||||
clave_materia: string;
|
||||
materia_id: number;
|
||||
materia_nombre: string;
|
||||
}
|
||||
|
||||
type Usuario = {
|
||||
usuario_clave: string;
|
||||
usuario_id: number;
|
||||
usuario_nombre: string;
|
||||
}
|
||||
|
||||
const app = createApp({
|
||||
message: null,
|
||||
puestos: [] as Puesto[],
|
||||
carreras: [] as Carrera[],
|
||||
materias: [] as Materia[],
|
||||
usuarios: [] as Usuario[],
|
||||
|
||||
async nuevoPuesto(nuevoPuesto: string) {
|
||||
try {
|
||||
const res = await fetch('action/puesto.php', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
puesto_nombre: nuevoPuesto
|
||||
})
|
||||
})
|
||||
const data = await res.json()
|
||||
this.puestos.push(data)
|
||||
// order by puesto.nombre
|
||||
this.puestos.sort((a: Puesto, b: Puesto) => a.nombre.localeCompare(b.nombre))
|
||||
} catch (error) {
|
||||
alert(`Error: ${error}`)
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
to_delete: null as Puesto | null,
|
||||
async eliminarPuesto(puesto_id: number) {
|
||||
try {
|
||||
const res = await fetch('action/puesto.php', {
|
||||
method: 'DELETE',
|
||||
body: JSON.stringify({
|
||||
puesto_id
|
||||
})
|
||||
})
|
||||
const data = await res.json()
|
||||
this.message = data.msg;
|
||||
|
||||
// after 3 seconds, remove the message
|
||||
setTimeout(() => {
|
||||
this.message = null
|
||||
}, 3000)
|
||||
|
||||
this.puestos = this.puestos.filter((p: Puesto) => p.puesto_id !== puesto_id)
|
||||
// order by puesto.nombre
|
||||
this.puestos.sort((a: Puesto, b: Puesto) => a.nombre.localeCompare(b.nombre))
|
||||
} catch (error) {
|
||||
alert(`Error: ${error}`)
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
async actualizarPuesto(puesto_id: number, materias: Materia[], usuario_id: number | null) {
|
||||
try {
|
||||
const res = await fetch('action/puesto.php', {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify({
|
||||
puesto_id,
|
||||
materias: materias.map(m => m.materia_id),
|
||||
usuario_id
|
||||
})
|
||||
})
|
||||
const data = await res.json()
|
||||
this.message = data.msg;
|
||||
|
||||
// after 3 seconds, remove the message
|
||||
setTimeout(() => {
|
||||
this.message = null
|
||||
}, 3000)
|
||||
} catch (error) {
|
||||
alert(`Error: ${error}`)
|
||||
}
|
||||
},
|
||||
|
||||
async mounted() {
|
||||
this.puestos = await fetch('action/puesto.php').then(res => res.json())
|
||||
this.carreras = await fetch('action/action_carreras.php').then(res => res.json())
|
||||
this.materias = await fetch('action/action_materias.php').then(res => res.json())
|
||||
this.usuarios = await fetch('action/usuarios.php').then(res => res.json())
|
||||
}
|
||||
}).mount('#app')
|
||||
272
ts/reposiciones.ts
Normal file
272
ts/reposiciones.ts
Normal file
@@ -0,0 +1,272 @@
|
||||
import { type } from "os";
|
||||
|
||||
declare function triggerMessage(message: string, title: string, type?: string): void;
|
||||
declare const write: boolean;
|
||||
declare const moment: any;
|
||||
// from this 'horario_id', 'fecha', 'hora', 'duracion_id', 'descripcion', 'profesor_id', 'salon', 'unidad', 'periodo_id', 'fecha_clase' make a type of ReposicionParams
|
||||
export interface ReposicionParams {
|
||||
horario_id: number;
|
||||
fecha: string;
|
||||
hora: string;
|
||||
duracion_id: number;
|
||||
descripcion: string;
|
||||
profesor_id: number;
|
||||
salon: string;
|
||||
unidad: number;
|
||||
periodo_id: number;
|
||||
fecha_clase: string;
|
||||
}
|
||||
|
||||
type Horario = {
|
||||
id: number;
|
||||
carrera_id: number;
|
||||
materia_id: number;
|
||||
grupo: string;
|
||||
profesores: Profesor[];
|
||||
dia: string;
|
||||
hora: string;
|
||||
hora_final: string;
|
||||
salon: string;
|
||||
fecha_inicio: string;
|
||||
fecha_final: string;
|
||||
fecha_carga: string;
|
||||
nivel_id: number;
|
||||
periodo_id: number;
|
||||
facultad_id: number;
|
||||
materia: string;
|
||||
horas: number;
|
||||
minutos: number;
|
||||
duracion: number;
|
||||
retardo: boolean;
|
||||
original_id: number;
|
||||
last: boolean;
|
||||
bloques: number;
|
||||
};
|
||||
|
||||
type Profesor = {
|
||||
id: number;
|
||||
clave: string;
|
||||
grado: string;
|
||||
profesor: string;
|
||||
nombre: string;
|
||||
facultad_id: number;
|
||||
};
|
||||
// Get references to the HTML elements
|
||||
const form = document.getElementById('form') as HTMLFormElement;
|
||||
const steps = Array.from(form.querySelectorAll('.step')) as HTMLElement[];
|
||||
|
||||
const nextButton = document.getElementById('next-button') as HTMLButtonElement;
|
||||
const prevButton = document.getElementById('prev-button') as HTMLButtonElement;
|
||||
|
||||
let currentStep = 0;
|
||||
|
||||
// #clave_profesor on change => show step 2
|
||||
const clave_profesor = document.getElementById('clave_profesor') as HTMLInputElement;
|
||||
const horario_reponer = document.getElementById('horario_reponer') as HTMLInputElement;
|
||||
const fechas_clase = document.getElementById('fechas_clase') as HTMLInputElement;
|
||||
|
||||
const fecha_reponer = $('#fecha_reponer') as JQuery<HTMLElement>;
|
||||
const hora_reponer = $('#hora_reponer') as JQuery<HTMLElement>;
|
||||
const minutos_reponer = $('#minutos_reponer') as JQuery<HTMLElement>;
|
||||
|
||||
clave_profesor.addEventListener('change', async () => {
|
||||
const step2 = document.getElementById('step-2') as HTMLElement;
|
||||
clave_profesor.disabled = true;
|
||||
// get option which value is the same as clave_profesor.value
|
||||
const option = document.querySelector(`option[value="${clave_profesor.value}"]`) as HTMLOptionElement;
|
||||
|
||||
// make a form data with #form
|
||||
const profesor_id = document.getElementById('profesor_id') as HTMLInputElement;
|
||||
profesor_id.value = option.dataset.id;
|
||||
|
||||
const formData = new FormData(form);
|
||||
|
||||
const response = await fetch(`./action/action_horario_profesor.php`, {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
});
|
||||
const data = await response.json();
|
||||
if (data['success'] === false) {
|
||||
const message = "Hubo un error al obtener los horarios del profesor."
|
||||
const title = 'Error';
|
||||
const color = 'danger';
|
||||
triggerMessage(message, title, color);
|
||||
return;
|
||||
}
|
||||
const horarios = data.data as Horario[];
|
||||
const initial = document.createElement('option');
|
||||
initial.value = '';
|
||||
initial.textContent = 'Seleccione un horario';
|
||||
initial.selected = true;
|
||||
initial.disabled = true;
|
||||
horario_reponer.innerHTML = '';
|
||||
horario_reponer.appendChild(initial);
|
||||
|
||||
horarios.forEach((horario) => {
|
||||
const dias = ['Lunes', 'Martes', 'Miercoles', 'Jueves', 'Viernes', 'Sabado', 'Domingo'];
|
||||
const option = document.createElement('option');
|
||||
option.value = `${horario.id}`;
|
||||
// materia máx 25 caracteres, if materia.length > 25 then slice(0, 20)
|
||||
const max = 25;
|
||||
option.textContent = `${horario.materia.slice(0, max) + (horario.materia.length > max ? '...' : '')} - Grupo: ${horario.grupo} - ${horario.hora.slice(0, 5)}-${horario.hora_final.slice(0, 5)} - Salon: ${horario.salon} - ${horario.dia}`;
|
||||
|
||||
option.dataset.materia = `${horario.materia}`;
|
||||
option.dataset.grupo = `${horario.grupo}`;
|
||||
option.dataset.hora = `${horario.hora.slice(0, 5)}`; // slice(0, 5) => HH:MM
|
||||
option.dataset.hora_final = `${horario.hora_final.slice(0, 5)}`;
|
||||
option.dataset.salon = `${horario.salon}`;
|
||||
option.dataset.dia = `${horario.dia}`;
|
||||
|
||||
option.dataset.id = `${horario.id}`;
|
||||
horario_reponer.appendChild(option);
|
||||
});
|
||||
currentStep = 1;
|
||||
step2.style.display = 'block';
|
||||
prevButton.disabled = false;
|
||||
});
|
||||
// disable clave_profesor
|
||||
|
||||
// from second step to first step
|
||||
prevButton.addEventListener('click', () => {
|
||||
const inputs = [clave_profesor, horario_reponer, fechas_clase, fecha_reponer, hora_reponer] as HTMLInputElement[];
|
||||
switch (currentStep) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
const step = document.getElementById(`step-${currentStep + 1}`) as HTMLElement;
|
||||
step.style.display = 'none';
|
||||
inputs[currentStep - 1].disabled = false;
|
||||
inputs[currentStep - 1].value = '';
|
||||
if (--currentStep === 0) {
|
||||
prevButton.disabled = true;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
const step5 = document.getElementById('step-5') as HTMLElement;
|
||||
step5.style.display = 'none';
|
||||
fecha_reponer.prop('disabled', false);
|
||||
fecha_reponer.val('');
|
||||
|
||||
hora_reponer.parent().removeClass('disabled');
|
||||
hora_reponer.siblings('.datalist-input').text('hh');
|
||||
hora_reponer.val('');
|
||||
|
||||
minutos_reponer.parent().removeClass('disabled');
|
||||
minutos_reponer.siblings('.datalist-input').text('mm');
|
||||
minutos_reponer.val('');
|
||||
|
||||
currentStep--;
|
||||
break;
|
||||
}
|
||||
|
||||
nextButton.disabled = true;
|
||||
|
||||
});
|
||||
|
||||
// #horario_reponer on change => show step 3
|
||||
horario_reponer.addEventListener('change', async () => {
|
||||
const selected = horario_reponer.querySelector(`option[value="${horario_reponer.value}"]`) as HTMLOptionElement;
|
||||
horario_reponer.title = `Materia: ${selected.dataset.materia} - Grupo: ${selected.dataset.grupo} - Horario: ${selected.dataset.hora}-${selected.dataset.hora_final} - Salon: ${selected.dataset.salon} - Día: ${selected.dataset.dia}`;
|
||||
const step3 = document.getElementById('step-3') as HTMLElement;
|
||||
horario_reponer.disabled = true;
|
||||
// make a form data with #form
|
||||
const response = await fetch(`./action/action_fechas_clase.php?horario_id=${horario_reponer.value}`, {
|
||||
method: 'GET',
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
if (data['success'] === false) {
|
||||
const message = "Hubo un error al obtener las fechas de clase."
|
||||
const title = 'Error';
|
||||
const color = 'danger';
|
||||
triggerMessage(message, title, color);
|
||||
return;
|
||||
}
|
||||
type Fecha = {
|
||||
fecha: string;
|
||||
dia_mes: number;
|
||||
day: number;
|
||||
month: number;
|
||||
year: number;
|
||||
}
|
||||
|
||||
const meses = ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'];
|
||||
|
||||
const fechas = data.data as Fecha[];
|
||||
const initial = document.createElement('option');
|
||||
initial.value = '';
|
||||
initial.textContent = 'Seleccione la fecha de la falta';
|
||||
initial.selected = true;
|
||||
initial.disabled = true;
|
||||
fechas_clase.innerHTML = '';
|
||||
fechas_clase.appendChild(initial);
|
||||
fechas_clase.title = 'Seleccione la fecha de la falta';
|
||||
|
||||
fechas.forEach((fecha) => {
|
||||
const option = document.createElement('option');
|
||||
option.value = `${fecha}`;
|
||||
option.textContent = `${fecha.dia_mes} de ${meses[fecha.month - 1]} de ${fecha.year}`;
|
||||
fechas_clase.appendChild(option);
|
||||
});
|
||||
|
||||
|
||||
step3.style.display = 'block';
|
||||
currentStep = 2;
|
||||
});
|
||||
|
||||
// #fechas_clase on change => show step 4
|
||||
fechas_clase.addEventListener('change', () => {
|
||||
const step4 = document.getElementById('step-4') as HTMLElement;
|
||||
step4.style.display = 'block';
|
||||
fechas_clase.disabled = true;
|
||||
currentStep = 3;
|
||||
});
|
||||
|
||||
// when both #fecha_reponer and #hora_reponer are selected => show step 5
|
||||
|
||||
const lastStep = () => {
|
||||
// timeout to wait for the value to be set
|
||||
setTimeout(() => {
|
||||
if (fecha_reponer.val() !== '' && hora_reponer.val() !== '' && minutos_reponer.val() !== '') {
|
||||
const step5 = document.getElementById('step-5') as HTMLElement;
|
||||
step5.style.display = 'block';
|
||||
// disable both
|
||||
fecha_reponer.prop('disabled', true);
|
||||
hora_reponer.parent().addClass('disabled');
|
||||
minutos_reponer.parent().addClass('disabled');
|
||||
|
||||
const nextButton = document.getElementById('next-button') as HTMLButtonElement;
|
||||
// remove property disabled
|
||||
nextButton.removeAttribute('disabled');
|
||||
currentStep = 4;
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
fecha_reponer.on('change', lastStep);
|
||||
// on click on the sibling ul>li of #hora_reponer and #minutos_reponer
|
||||
|
||||
hora_reponer.siblings('ul').children('li').on('click', lastStep);
|
||||
minutos_reponer.siblings('ul').children('li').on('click', lastStep);
|
||||
|
||||
// Initialize the form
|
||||
hideSteps();
|
||||
showCurrentStep();
|
||||
|
||||
|
||||
function hideSteps() {
|
||||
steps.forEach((step) => {
|
||||
step.style.display = 'none';
|
||||
});
|
||||
}
|
||||
|
||||
function showCurrentStep() {
|
||||
steps[currentStep].style.display = 'block';
|
||||
prevButton.disabled = currentStep === 0;
|
||||
}
|
||||
|
||||
function handleSubmit(event: Event) {
|
||||
event.preventDefault();
|
||||
|
||||
// Handle form submission
|
||||
// You can access the form data using the FormData API or serialize it manually
|
||||
}
|
||||
Reference in New Issue
Block a user