Reestructurar codigo de vista de pc

master
Araozu 2022-10-14 17:20:21 -05:00
parent 314a57d01a
commit 678f266946
19 changed files with 479 additions and 340 deletions

33
src/API/Login.ts Normal file
View File

@ -0,0 +1,33 @@
import { SERVER_PATH } from "../Store";
type IdLaboratorio = number;
type LoginData = {correo_usuario: string};
type LoginResponse = Promise<{matriculas: Array<IdLaboratorio>} | null>;
export type LoginFunction = (data: LoginData) => LoginResponse;
// Mock for a login without courses
export const mockLoginEmpty: LoginFunction = async(data) => ({matriculas: []});
// Mock for a login with courses
export const mockLoginNotEmpty: LoginFunction = async(_) => ({
matriculas: [0, 1, 2, 3],
});
// Error login mock
export const mockLoginWithError: LoginFunction = async(_) => null;
// Standard login
export const loginFn: LoginFunction = async(data) => {
const petition = await fetch(`${SERVER_PATH}/login`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
correo_usuario: data.correo_usuario,
}),
});
if (!petition.ok) return null;
return await petition.json() as {matriculas: Array<IdLaboratorio>};
};

View File

@ -1,4 +1,4 @@
import { Main } from "./Views/Main"; import { Sistemas } from "./Views/pc/Sistemas";
import { Index } from "./Views/Index"; import { Index } from "./Views/Index";
import { Editor } from "./Views/Editor"; import { Editor } from "./Views/Editor";
import { useRouter } from "./Router"; import { useRouter } from "./Router";
@ -7,6 +7,7 @@ import { Wallpaper } from "./Wallpaper";
import { SistemasMovil } from "./Views/SistemasMovil"; import { SistemasMovil } from "./Views/SistemasMovil";
import { SeleccionCursos } from "./Views/SeleccionCursos"; import { SeleccionCursos } from "./Views/SeleccionCursos";
import { VerMatricula } from "./Views/VerMatricula"; import { VerMatricula } from "./Views/VerMatricula";
import {SeleccionCursos as SeleccionCursosPC} from "./Views/pc/SeleccionCursos";
function App() { function App() {
const route = useRouter(); const route = useRouter();
@ -33,8 +34,12 @@ function App() {
<Match when={route() === "/ver-matricula/"}> <Match when={route() === "/ver-matricula/"}>
<VerMatricula /> <VerMatricula />
</Match> </Match>
<Match when={route() === "/sistemas/"}>
<Main /> <Match when={route() === "/pc/seleccion-cursos/"}>
<SeleccionCursosPC />
</Match>
<Match when={route() === "/pc/sistemas/"}>
<Sistemas />
</Match> </Match>
</Switch> </Switch>
</div> </div>

View File

@ -2,8 +2,8 @@ import { BarraSuperior } from "../BarraSuperior";
import { estilosGlobales } from "../Estilos"; import { estilosGlobales } from "../Estilos";
import { StyleSheet, css } from "aphrodite"; import { StyleSheet, css } from "aphrodite";
import { Separador } from "../Separador"; import { Separador } from "../Separador";
import { Tabla } from "../ContenedorHorarios/Tabla"; import { Tabla } from "./pc/Sistemas/ContenedorHorarios/Tabla";
import { TablaObserver } from "../ContenedorHorarios/TablaObserver"; import { TablaObserver } from "./pc/Sistemas/ContenedorHorarios/TablaObserver";
import { Curso, Cursos } from "../types/DatosHorario"; import { Curso, Cursos } from "../types/DatosHorario";
import { For, createMemo } from "solid-js"; import { For, createMemo } from "solid-js";
import {createStore} from "solid-js/store"; import {createStore} from "solid-js/store";

View File

@ -1,9 +1,10 @@
import { estilosGlobales } from "../Estilos"; import { estilosGlobales } from "../Estilos";
import { StyleSheet, css } from "aphrodite/no-important"; import { StyleSheet, css } from "aphrodite/no-important";
import { RouterLink } from "../Router"; import { RouterLink } from "../Router";
import { Show } from "solid-js"; import { batch, createSignal, Show } from "solid-js";
import { isMobile } from "../Store"; import { isMobile, setGruposSeleccionados } from "../Store";
import { MobileIndex } from "./MobileIndex"; import { MobileIndex } from "./MobileIndex";
import { mockLoginEmpty, mockLoginNotEmpty, mockLoginWithError } from "../API/Login";
const e = StyleSheet.create({ const e = StyleSheet.create({
contenedorGlobal: { contenedorGlobal: {
@ -30,11 +31,45 @@ const e = StyleSheet.create({
verticalAlign: "bottom", verticalAlign: "bottom",
marginRight: "0.5rem", marginRight: "0.5rem",
}, },
inputCorreo: {
width: "100%",
backgroundColor: "rgba(159,159,159,0.44)",
border: "none",
borderBottom: "solid 2px var(--color-texto)",
padding: "0.5rem 1rem",
boxSizing: "border-box",
marginTop: "1rem",
borderRadius: "5px",
},
}); });
export function Index() { export function Index() {
const [msgErrorVisible, setMsgErrorVisible] = createSignal(false);
const inputElement = <input className={css(e.inputCorreo)} type="email" required placeholder="correo@unsa.edu.pe" />;
const login = async(ev: Event) => {
ev.preventDefault();
const email = (inputElement as HTMLInputElement).value;
const response = await mockLoginEmpty({correo_usuario: email});
if (response === null) {
setMsgErrorVisible(true);
setTimeout(() => setMsgErrorVisible(false), 2500);
} else if (response.matriculas.length === 0) {
localStorage.setItem("correo", email);
window.location.href = "#/pc/seleccion-cursos/";
} else if (response.matriculas.length > 0) {
localStorage.setItem("correo", email);
batch(() => {
for (const id_lab of response.matriculas) {
setGruposSeleccionados(id_lab, true);
}
});
window.location.href = "#/pc/ver-matricula/";
}
};
return ( return (
<> <>
<Show when={!isMobile()}> <Show when={!isMobile()}>
@ -49,36 +84,19 @@ export function Index() {
Horarios UNSA Horarios UNSA
</h1> </h1>
<p className={css(e.parrafo)}> <p className={css(e.parrafo)}>
Esta página te permite crear tu horario fácilmente, sin importar de que Inicia sesión con tu correo institucional.
año son los cursos. <br />
</p> {inputElement}
<p className={css(e.parrafo)}>
Por ahora solo está disponible para ing. de sistemas. Proximamente se habilitarán
otras carreras.
</p>
<p className={css(e.parrafo)}>
Se recomienda usar un computador/laptop y un navegador actualizado (Firefox, Chrome,
Qutebrowser).
</p> </p>
<span style={msgErrorVisible() ? "opacity: 1; color: red;" : "opacity: 0;"}>
El correo es invalido
</span>
</div> </div>
<RouterLink <button onClick={login} className={css(estilosGlobales.contenedor, estilosGlobales.contenedorCursor, e.botonAccion)}>
to={"/sistemas/"} Iniciar sesion
className={css(estilosGlobales.contenedor, estilosGlobales.contenedorCursor, e.botonAccion)}
>
Ing. de Sistemas
</RouterLink>
{/*
<button disabled className={css(estilosGlobales.contenedor, estilosGlobales.contenedorCursor, e.botonAccion)}>
Otras carreras
</button> </button>
*/} <br />
<RouterLink <br />
to={"/editor/"}
className={css(estilosGlobales.contenedor, estilosGlobales.contenedorCursor, e.botonAccion)}
>
<i className={`${css(e.iconoGitHub)} ph-pencil`} />
Editor
</RouterLink>
<a <a
className={css(estilosGlobales.contenedor, estilosGlobales.contenedorCursor, e.botonAccion)} className={css(estilosGlobales.contenedor, estilosGlobales.contenedorCursor, e.botonAccion)}
href="https://github.com/Araozu/horarios-unsa-2/" href="https://github.com/Araozu/horarios-unsa-2/"

View File

@ -1,49 +0,0 @@
import { BarraSuperior } from "../BarraSuperior";
import { ContenedorHorarios } from "../ContenedorHorarios/ContenedorHorarios";
import { Show, createSignal } from "solid-js";
import { css } from "aphrodite";
import { estilosGlobales } from "../Estilos";
import { Creditos } from "../Creditos";
import { Separador } from "../Separador";
export function Main() {
/// @ts-ignore
const soportaBackdropFilter = document.body.style.backdropFilter !== undefined;
const mostrarMensajeBackdropFilterRaw = !localStorage.getItem("mensaje-backdrop-filter-oculto");
const [mostrarMensajeBackdropFilter, setMostrarMensaje] = createSignal(mostrarMensajeBackdropFilterRaw);
const ocultarMensajeBackdropFilter = () => {
setMostrarMensaje(false);
localStorage.setItem("mensaje-backdrop-filter-oculto", "true");
};
return (
<div>
<BarraSuperior />
<Show when={!soportaBackdropFilter && mostrarMensajeBackdropFilter()}>
<div className={css(estilosGlobales.contenedor)}>
Tu navegador no soporta "backdrop-filter". Este es solo un efecto
visual, no afecta la funcionalidad de la página.&nbsp;
<span
className={css(estilosGlobales.contenedorCursor, estilosGlobales.contenedorCursorSoft)}
onClick={ocultarMensajeBackdropFilter}
>
No volver a mostrar.
</span>
</div>
</Show>
{/*
<div className={css(estilosGlobales.contenedor)}>
Solo teoria por ahora. Actualizado el 2021/03/28. Fuente:&nbsp;
<a className={css(estilosGlobales.linkGenerico)} target="_blank" href="https://www.facebook.com/Escuela-Profesional-de-Ingenieria-de-Sistemas-171720913528/photos/pcb.10159175240878529/10159175239403529">
Página de Facebook de la escuela.
</a>
</div>
*/}
<Separador />
<ContenedorHorarios />
<Creditos />
</div>
);
}

View File

@ -1,6 +1,7 @@
import { css, StyleSheet } from "aphrodite/no-important"; import { css, StyleSheet } from "aphrodite/no-important";
import { batch, createSignal } from "solid-js"; import { batch, createSignal } from "solid-js";
import { SERVER_PATH, setGruposSeleccionados } from "../Store"; import { SERVER_PATH, setGruposSeleccionados } from "../Store";
import { mockLoginEmpty } from "../API/Login";
const e = StyleSheet.create({ const e = StyleSheet.create({
contenedorGlobal: { contenedorGlobal: {
@ -29,34 +30,6 @@ const e = StyleSheet.create({
}, },
}); });
type IdLaboratorio = number;
type LoginData = {correo_usuario: string};
type LoginResponse = Promise<{matriculas: Array<IdLaboratorio>} | null>;
type LoginFunction = (data: LoginData) => LoginResponse;
// Mock for a login without courses
const mockLoginEmpty: LoginFunction = async(data) => ({matriculas: []});
// Mock for a login with courses
const mockLoginNotEmpty: LoginFunction = async(_) => ({
matriculas: [0, 1, 2, 3],
});
// Error login mock
const mockLoginWithError: LoginFunction = async(_) => null;
// Standard login
const loginFn: LoginFunction = async(data) => {
const petition = await fetch(`${SERVER_PATH}/login`, {
method: "POST",
body: JSON.stringify({
correo_usuario: data.correo_usuario,
}),
});
if (!petition.ok) return null;
return await petition.json() as {matriculas: Array<IdLaboratorio>};
};
export function MobileIndex() { export function MobileIndex() {
const s = StyleSheet.create({ const s = StyleSheet.create({
boton: { boton: {
@ -78,7 +51,7 @@ export function MobileIndex() {
}); });
const [msgErrorVisible, setMsgErrorVisible] = createSignal(false); const [msgErrorVisible, setMsgErrorVisible] = createSignal(false);
const inputElement = <input required type="email" placeholder="Correo electronico" className={css(s.entrada)} />; const inputElement = <input required type="email" placeholder="correo@unsa.edu.pe" className={css(s.entrada)} />;
const login = async(ev: Event) => { const login = async(ev: Event) => {
ev.preventDefault(); ev.preventDefault();
@ -89,13 +62,16 @@ export function MobileIndex() {
setMsgErrorVisible(true); setMsgErrorVisible(true);
setTimeout(() => setMsgErrorVisible(false), 2500); setTimeout(() => setMsgErrorVisible(false), 2500);
} else if (response.matriculas.length === 0) { } else if (response.matriculas.length === 0) {
localStorage.setItem("correo", email);
window.location.href = "#/seleccion-cursos/"; window.location.href = "#/seleccion-cursos/";
} else if (response.matriculas.length > 0) { } else if (response.matriculas.length > 0) {
localStorage.setItem("correo", email);
batch(() => { batch(() => {
for (const id_lab of response.matriculas) { for (const id_lab of response.matriculas) {
setGruposSeleccionados(id_lab, true); setGruposSeleccionados(id_lab, true);
} }
}); });
window.location.href = "#/ver-matricula/";
} }
}; };

View File

@ -0,0 +1,135 @@
import { css, StyleSheet } from "aphrodite/no-important";
import { estilosGlobales } from "../../Estilos";
import { createSignal, For } from "solid-js";
import { getAllListaCursosMock, RespuestaListaCursos } from "../../API/ListaCursos";
const e = StyleSheet.create({
contenedorGlobal: {
width: "100vw",
height: "100vh",
display: "flex",
alignItems: "center",
justifyContent: "center",
},
cont: {
width: "30rem",
},
parrafo: {
textAlign: "justify",
lineHeight: "1.4rem",
},
botonAccion: {
width: "30rem",
display: "inline-block",
textAlign: "center",
},
iconoGitHub: {
fontSize: "1.25rem",
verticalAlign: "bottom",
marginRight: "0.5rem",
},
inputCorreo: {
width: "100%",
backgroundColor: "rgba(159,159,159,0.44)",
border: "none",
borderBottom: "solid 2px var(--color-texto)",
padding: "0.5rem 1rem",
boxSizing: "border-box",
marginTop: "1rem",
borderRadius: "5px",
},
checkbox: {
width: "1.25rem",
height: "1.25rem",
margin: "0 0.5rem",
},
grid: {
display: "grid",
gridTemplateColumns: "3rem auto",
gridRowGap: "1rem",
},
});
export function SeleccionCursos() {
const [cursos, setCursos] = createSignal<RespuestaListaCursos>({});
const [msgErr, setMsgError] = createSignal(false);
// Recuperar cursos de back
(async() => setCursos(await getAllListaCursosMock()))();
const submit = (ev: Event) => {
ev.preventDefault();
const form = ev.target as HTMLFormElement;
// Los checkboxes
const elements = form.elements;
const idsAEnviar: Array<string> = [];
for (let i = 0; i < elements.length; i += 1) {
const inputBox = elements[i] as HTMLInputElement;
if (inputBox.checked) {
idsAEnviar.push(inputBox.value);
}
}
if (idsAEnviar.length === 0) {
setMsgError(true);
setTimeout(() => setMsgError(false), 2500);
return;
}
// Almacenar en localStorage
localStorage.setItem("cursos-seleccionados", JSON.stringify(idsAEnviar));
// Ir a sig pantalla
window.location.href = "#/pc/sistemas/";
};
return (
<div className={css(e.contenedorGlobal)}>
<div className={css(e.cont)}>
<form onSubmit={submit}>
<div className={css(estilosGlobales.contenedor, estilosGlobales.inlineBlock, e.cont)}>
<h1 style={{
"text-align": "center",
"font-size": "1.75rem",
}}
>
Seleccion de cursos
</h1>
<p>Selecciona los cursos en los que matricularte</p>
<For each={Object.entries(cursos())}>
{([nombreAnio, infoCurso]) => (
<>
<h2>{nombreAnio} año</h2>
<div className={css(e.grid)}>
<For each={infoCurso}>
{(curso) => (
<>
<input
type="checkbox"
value={curso.id_curso}
className={css(e.checkbox)}
/>
<span>{curso.nombre_curso}</span>
</>
)}
</For>
</div>
</>
)}
</For>
<br />
<span style={msgErr() ? "opacity: 1; color: red;" : "opacity: 0;"}>
Selecciona al menos un curso
</span>
</div>
<button
type="submit"
className={css(estilosGlobales.contenedor, estilosGlobales.contenedorCursor, e.botonAccion)}
>
Iniciar sesion
</button >
</form>
</div>
</div>
);
}

18
src/Views/pc/Sistemas.tsx Normal file
View File

@ -0,0 +1,18 @@
import { BarraSuperior } from "../../BarraSuperior";
import { ContenedorHorarios } from "./Sistemas/ContenedorHorarios";
import { Show, createSignal } from "solid-js";
import { css } from "aphrodite";
import { estilosGlobales } from "../../Estilos";
import { Creditos } from "../../Creditos";
import { Separador } from "../../Separador";
export function Sistemas() {
return (
<div>
<BarraSuperior />
<Separador />
<ContenedorHorarios />
<Creditos />
</div>
);
}

View File

@ -1,42 +1,43 @@
import YAML from "yaml" import YAML from "yaml";
import { css, StyleSheet } from "aphrodite" import { css, StyleSheet } from "aphrodite";
import { MiHorario } from "./MiHorario" import { MiHorario } from "./ContenedorHorarios/MiHorario";
import { Horarios } from "./Horarios" import { Horarios } from "./ContenedorHorarios/Horarios";
import { import {
Anios, Anios,
Cursos, Cursos,
DatosHorario, DatosHorario,
DatosHorarioRaw, DatosHorarioRaw,
DatosGrupo, DatosGrupo,
} from "../types/DatosHorario" } from "../../../types/DatosHorario";
import { estilosGlobales } from "../Estilos" import { estilosGlobales } from "../../../Estilos";
import { batch, createEffect, createMemo, createSignal, Show } from "solid-js" import { batch, createEffect, createMemo, createSignal, Show } from "solid-js";
import { useListaCursos } from "./useListaCursos" import { useListaCursos } from "./ContenedorHorarios/useListaCursos";
const datosPromise = (async() => { const datosPromise = (async() => {
const file = await fetch("/horarios/2022_2_fps_ingenieriadesistemas.yaml") const file = await fetch("/horarios/2022_2_fps_ingenieriadesistemas.yaml");
const text = await file.text() const text = await file.text();
const datosRaw = YAML.parse(text) as DatosHorarioRaw const datosRaw = YAML.parse(text) as DatosHorarioRaw;
console.log(datosRaw);
// Agregar los campos faltantes a DatosHorarioRaw para que sea DatosHorario // Agregar los campos faltantes a DatosHorarioRaw para que sea DatosHorario
const datos: DatosHorario = { const datos: DatosHorario = {
...datosRaw, ...datosRaw,
años: {}, años: {},
} };
const anios: Anios = {} const anios: Anios = {};
for (const [nombreAnio, anio] of Object.entries(datosRaw.años)) { for (const [nombreAnio, anio] of Object.entries(datosRaw.años)) {
const anioData: Cursos = {} const anioData: Cursos = {};
for (const [nombreCurso, curso] of Object.entries(anio)) { for (const [nombreCurso, curso] of Object.entries(anio)) {
const gruposTeoria: { [k: string]: DatosGrupo } = {} const gruposTeoria: { [k: string]: DatosGrupo } = {};
for (const [key, data] of Object.entries(curso.Teoria)) { for (const [key, data] of Object.entries(curso.Teoria)) {
gruposTeoria[key] = Object.assign({seleccionado: false}, data) gruposTeoria[key] = Object.assign({seleccionado: false}, data);
} }
const gruposLab: { [k: string]: DatosGrupo } = {} const gruposLab: { [k: string]: DatosGrupo } = {};
for (const [key, data] of Object.entries(curso.Laboratorio ?? {})) { for (const [key, data] of Object.entries(curso.Laboratorio ?? {})) {
gruposLab[key] = Object.assign({seleccionado: false}, data) gruposLab[key] = Object.assign({seleccionado: false}, data);
} }
anioData[nombreCurso] = { anioData[nombreCurso] = {
@ -44,21 +45,21 @@ const datosPromise = (async() => {
oculto: false, oculto: false,
Teoria: gruposTeoria, Teoria: gruposTeoria,
Laboratorio: gruposLab, Laboratorio: gruposLab,
} };
} }
anios[nombreAnio] = anioData anios[nombreAnio] = anioData;
} }
datos.años = anios datos.años = anios;
return datos return datos;
})() })();
const ElemCargando = () => ( const ElemCargando = () => (
<div className={css(estilosGlobales.contenedor, estilosGlobales.inlineBlock)}> <div className={css(estilosGlobales.contenedor, estilosGlobales.inlineBlock)}>
Recuperando horarios... Recuperando horarios...
</div> </div>
) );
export type EstadoLayout = "MaxPersonal" | "Normal" | "MaxHorarios"; export type EstadoLayout = "MaxPersonal" | "Normal" | "MaxHorarios";
@ -66,48 +67,48 @@ const {
listaCursos: cursosUsuario, listaCursos: cursosUsuario,
setListaCursos: setCursosUsuarios, setListaCursos: setCursosUsuarios,
agregarCursoALista: agregarCursoUsuario, agregarCursoALista: agregarCursoUsuario,
} = useListaCursos() } = useListaCursos();
export function ContenedorHorarios() { export function ContenedorHorarios() {
const [datosCargados, setDatosCargados] = createSignal(false) const [datosCargados, setDatosCargados] = createSignal(false);
const [datos, setDatos] = createSignal<DatosHorario | null>(null) const [datos, setDatos] = createSignal<DatosHorario | null>(null);
const [estadoLayout, setEstadoLayout] = ( const [estadoLayout, setEstadoLayout] = (
createSignal<EstadoLayout>(localStorage.getItem("estadoLayout") as EstadoLayout || "Normal") createSignal<EstadoLayout>(localStorage.getItem("estadoLayout") as EstadoLayout || "Normal")
) );
const e = createMemo(() => { const e = createMemo(() => {
let templateColumns = "" let templateColumns = "";
switch (estadoLayout()) { switch (estadoLayout()) {
case "MaxHorarios": { case "MaxHorarios": {
templateColumns = "0 auto" templateColumns = "0 auto";
break break;
} }
case "MaxPersonal": { case "MaxPersonal": {
templateColumns = "auto 0m" templateColumns = "auto 0m";
break break;
} }
case "Normal": { case "Normal": {
templateColumns = "50% 50%" templateColumns = "50% 50%";
} }
} }
localStorage.setItem("estadoLayout", estadoLayout()) localStorage.setItem("estadoLayout", estadoLayout());
return StyleSheet.create({ return StyleSheet.create({
contenedor: { contenedor: {
display: "grid", display: "grid",
gridTemplateColumns: templateColumns, gridTemplateColumns: templateColumns,
}, },
}) });
}) });
createEffect(async() => { createEffect(async() => {
const datos = await datosPromise const datos = await datosPromise;
batch(() => { batch(() => {
setDatos(datos) setDatos(datos);
setDatosCargados(true) setDatosCargados(true);
}) });
}) });
return ( return (
<div className={css(e().contenedor)}> <div className={css(e().contenedor)}>
@ -133,5 +134,5 @@ export function ContenedorHorarios() {
</Show> </Show>
</div> </div>
</div> </div>
) );
} }

View File

@ -1,5 +1,5 @@
import { css } from "aphrodite" import { css } from "aphrodite";
import { estilosGlobales } from "../Estilos" import {estilosGlobales} from "../../../../Estilos";
interface BotonMaxMinProps { interface BotonMaxMinProps {
icono: string, icono: string,
@ -21,5 +21,5 @@ export function BotonIcono(props: BotonMaxMinProps) {
> >
<i className={`${css(estilosGlobales.botonPhospor)} ${props.icono}`} /> <i className={`${css(estilosGlobales.botonPhospor)} ${props.icono}`} />
</div> </div>
) );
} }

View File

@ -1,6 +1,6 @@
import { css } from "aphrodite" import { css } from "aphrodite";
import { estilosGlobales } from "../Estilos" import { estilosGlobales } from "../../../../Estilos";
import { EstadoLayout } from "./ContenedorHorarios" import {EstadoLayout} from "../ContenedorHorarios";
interface BotonMaxMinProps { interface BotonMaxMinProps {
fnMaximizar: () => void, fnMaximizar: () => void,
@ -10,19 +10,19 @@ interface BotonMaxMinProps {
} }
export function BotonMaxMin(props: BotonMaxMinProps) { export function BotonMaxMin(props: BotonMaxMinProps) {
const horariosMax = () => props.estadoActualLayout() === props.estadoLayoutMax const horariosMax = () => props.estadoActualLayout() === props.estadoLayoutMax;
const tituloBoton = () => (horariosMax() ? "Minimizar" : "Maximizar") const tituloBoton = () => (horariosMax() ? "Minimizar" : "Maximizar");
const iconoBoton = () => (horariosMax() ? "ph-arrows-in" : "ph-arrows-out") const iconoBoton = () => (horariosMax() ? "ph-arrows-in" : "ph-arrows-out");
const funcionBoton = () => { const funcionBoton = () => {
const estaMaximizado = horariosMax() const estaMaximizado = horariosMax();
if (estaMaximizado) { if (estaMaximizado) {
props.fnMinimizar() props.fnMinimizar();
} else { } else {
props.fnMaximizar() props.fnMaximizar();
}
} }
};
return ( return (
<button <button
@ -38,5 +38,5 @@ export function BotonMaxMin(props: BotonMaxMinProps) {
> >
<i className={`${css(estilosGlobales.botonPhospor)} ${iconoBoton()}`} /> <i className={`${css(estilosGlobales.botonPhospor)} ${iconoBoton()}`} />
</button> </button>
) );
} }

View File

@ -1,9 +1,9 @@
import { Cursos, DatosGrupo, ListaCursosUsuario, Curso } from "../types/DatosHorario" import { Cursos, DatosGrupo, ListaCursosUsuario, Curso } from "../../../../types/DatosHorario";
import { createMemo, For } from "solid-js" import { createMemo, For } from "solid-js";
import { produce, SetStoreFunction } from "solid-js/store" import { produce, SetStoreFunction } from "solid-js/store";
import { StyleSheet, css } from "aphrodite" import { StyleSheet, css } from "aphrodite";
import { estilosGlobales } from "../Estilos" import { estilosGlobales } from "../../../../Estilos";
import { TablaObserver } from "./TablaObserver" import { TablaObserver } from "./TablaObserver";
const e = StyleSheet.create({ const e = StyleSheet.create({
inline: { inline: {
@ -33,14 +33,14 @@ const e = StyleSheet.create({
border: "none", border: "none",
color: "var(--color)", color: "var(--color)",
}, },
}) });
const claseCursoNoAgregado = css( const claseCursoNoAgregado = css(
e.contenedorCurso, e.contenedorCurso,
estilosGlobales.contenedor, estilosGlobales.contenedor,
) );
const claseCursoOculto = css(e.cursoOculto) const claseCursoOculto = css(e.cursoOculto);
interface Props { interface Props {
version: number, version: number,
@ -64,7 +64,7 @@ interface PropsIndicadorGrupo {
} }
function IndicadorGrupo(props: PropsIndicadorGrupo) { function IndicadorGrupo(props: PropsIndicadorGrupo) {
const id = `${props.idParcial}_${props.esLab ? "L" : "T"}_${props.nombre}` const id = `${props.idParcial}_${props.esLab ? "L" : "T"}_${props.nombre}`;
return ( return (
<span <span
className={css(e.botonTexto, estilosGlobales.contenedorCursor, estilosGlobales.contenedorCursorSoft)} className={css(e.botonTexto, estilosGlobales.contenedorCursor, estilosGlobales.contenedorCursorSoft)}
@ -75,7 +75,7 @@ function IndicadorGrupo(props: PropsIndicadorGrupo) {
> >
{props.esLab ? "L" : ""}{props.nombre} {props.esLab ? "L" : ""}{props.nombre}
</span> </span>
) );
} }
const agruparProfesores = ( const agruparProfesores = (
@ -84,31 +84,31 @@ const agruparProfesores = (
esLab: boolean, esLab: boolean,
setCursosUsuarios: FnSetCursosUsuarios, setCursosUsuarios: FnSetCursosUsuarios,
) => { ) => {
const profesores: { [k: string]: [string, () => void][] } = {} const profesores: { [k: string]: [string, () => void][] } = {};
for (const [grupo, datosGrupo] of Object.entries(datos)) { for (const [grupo, datosGrupo] of Object.entries(datos)) {
const nombreProfesor = datosGrupo.Docente const nombreProfesor = datosGrupo.Docente;
if (!profesores[nombreProfesor]) { if (!profesores[nombreProfesor]) {
profesores[nombreProfesor] = [] profesores[nombreProfesor] = [];
} }
profesores[nombreProfesor].push([ profesores[nombreProfesor].push([
grupo, grupo,
() => { () => {
setCursosUsuarios("cursos", Number(indiceCurso), "Teoria", produce<{ [p: string]: DatosGrupo }>((x) => { setCursosUsuarios("cursos", Number(indiceCurso), "Teoria", produce<{ [p: string]: DatosGrupo }>((x) => {
const grupoActualSeleccionado = x[grupo].seleccionado const grupoActualSeleccionado = x[grupo].seleccionado;
if (grupoActualSeleccionado) { if (grupoActualSeleccionado) {
x[grupo].seleccionado = false x[grupo].seleccionado = false;
} else { } else {
for (const xKey in x) { for (const xKey in x) {
x[xKey].seleccionado = xKey === grupo x[xKey].seleccionado = xKey === grupo;
} }
} }
})) }));
}, },
]) ]);
}
return profesores
} }
return profesores;
};
function CursoE( function CursoE(
indiceCurso: string, indiceCurso: string,
@ -117,7 +117,7 @@ function CursoE(
claseCursoAgregado: string, claseCursoAgregado: string,
props: Props, props: Props,
) { ) {
const idCurso = `${props.version}_${anio()}_${datosCurso.abreviado}` const idCurso = `${props.version}_${anio()}_${datosCurso.abreviado}`;
const cursoAgregadoMemo = createMemo( const cursoAgregadoMemo = createMemo(
() => props.listaCursosUsuario.cursos.find((x) => x.nombre === datosCurso.nombre && !x.oculto) !== undefined, () => props.listaCursosUsuario.cursos.find((x) => x.nombre === datosCurso.nombre && !x.oculto) !== undefined,
@ -126,33 +126,33 @@ function CursoE(
equals: equals:
(x, y) => x === y, (x, y) => x === y,
}, },
) );
const tituloMemo = createMemo(() => (cursoAgregadoMemo() const tituloMemo = createMemo(() => (cursoAgregadoMemo()
? "Remover de mi horario" ? "Remover de mi horario"
: "Agregar a mi horario")) : "Agregar a mi horario"));
const claseMemo = createMemo(() => { const claseMemo = createMemo(() => {
if (props.esCursoMiHorario && datosCurso.oculto) { if (props.esCursoMiHorario && datosCurso.oculto) {
return claseCursoOculto return claseCursoOculto;
} }
return cursoAgregadoMemo() return cursoAgregadoMemo()
? claseCursoAgregado ? claseCursoAgregado
: claseCursoNoAgregado : claseCursoNoAgregado;
}) });
const profesoresTeoria = createMemo(() => agruparProfesores( const profesoresTeoria = createMemo(() => agruparProfesores(
datosCurso.Teoria, datosCurso.Teoria,
Number(indiceCurso), Number(indiceCurso),
false, false,
props.setCursosUsuarios, props.setCursosUsuarios,
)) ));
const profesoresLab = createMemo(() => agruparProfesores( const profesoresLab = createMemo(() => agruparProfesores(
datosCurso.Laboratorio ?? {}, datosCurso.Laboratorio ?? {},
Number(indiceCurso), Number(indiceCurso),
true, true,
props.setCursosUsuarios, props.setCursosUsuarios,
)) ));
const IndicadorGrupos = (profesor: string, grupos: [string, () => void][], esLab: boolean) => ( const IndicadorGrupos = (profesor: string, grupos: [string, () => void][], esLab: boolean) => (
<td style={{"padding-bottom": "0.5rem", "padding-right": "0.75rem"}}> <td style={{"padding-bottom": "0.5rem", "padding-right": "0.75rem"}}>
@ -172,7 +172,7 @@ function CursoE(
} }
</For> </For>
</td> </td>
) );
return ( return (
<div className={claseMemo()}> <div className={claseMemo()}>
@ -204,17 +204,17 @@ function CursoE(
{tituloMemo} {tituloMemo}
</button> </button>
</div> </div>
) );
} }
export function CursosElem(props: Props) { export function CursosElem(props: Props) {
const anio = () => props.anioActual().substring(0, props.anioActual().indexOf(" ")) const anio = () => props.anioActual().substring(0, props.anioActual().indexOf(" "));
const claseCursoAgregado = css( const claseCursoAgregado = css(
e.contenedorCurso, e.contenedorCurso,
estilosGlobales.contenedor, estilosGlobales.contenedor,
!props.esCursoMiHorario && estilosGlobales.contenedorCursorActivo, !props.esCursoMiHorario && estilosGlobales.contenedorCursorActivo,
) );
return ( return (
<> <>
@ -222,5 +222,5 @@ export function CursosElem(props: Props) {
{([indiceCurso, datosCurso]) => CursoE(indiceCurso, datosCurso, anio, claseCursoAgregado, props)} {([indiceCurso, datosCurso]) => CursoE(indiceCurso, datosCurso, anio, claseCursoAgregado, props)}
</For> </For>
</> </>
) );
} }

View File

@ -1,14 +1,14 @@
import { Curso, Cursos, DatosHorario, ListaCursosUsuario } from "../types/DatosHorario" import { Curso, Cursos, DatosHorario, ListaCursosUsuario } from "../../../../types/DatosHorario";
import { batch, createMemo, createSignal, For, Match, Switch, untrack } from "solid-js" import { batch, createMemo, createSignal, For, Match, Switch, untrack } from "solid-js";
import {SetStoreFunction} from "solid-js/store" import {SetStoreFunction} from "solid-js/store";
import { css } from "aphrodite" import { css } from "aphrodite";
import { estilosGlobales } from "../Estilos" import { estilosGlobales } from "../../../../Estilos";
import { Tabla } from "./Tabla" import { Tabla } from "./Tabla";
import { CursosElem } from "./CursosElem" import { CursosElem } from "./CursosElem";
import { EstadoLayout } from "./ContenedorHorarios" import { EstadoLayout } from "../ContenedorHorarios";
import { BotonMaxMin } from "./BotonMaxMin" import { BotonMaxMin } from "./BotonMaxMin";
import { useListaCursos } from "./useListaCursos" import { useListaCursos } from "./useListaCursos";
import { TablaObserver } from "./TablaObserver" import { TablaObserver } from "./TablaObserver";
interface HorariosProps { interface HorariosProps {
data: DatosHorario, data: DatosHorario,
@ -23,59 +23,59 @@ const {
setListaCursos, setListaCursos,
agregarCursoALista, agregarCursoALista,
eliminarCursosDeLista, eliminarCursosDeLista,
} = useListaCursos() } = useListaCursos();
export function Horarios(props: HorariosProps) { export function Horarios(props: HorariosProps) {
const [anioActual, setAnioActual] = createSignal("1er año") const [anioActual, setAnioActual] = createSignal("1er año");
const tablaObserver = new TablaObserver() const tablaObserver = new TablaObserver();
const elAnios = ( const elAnios = (
<For each={Object.entries(props.data.años)}> <For each={Object.entries(props.data.años)}>
{([nombre]) => { {([nombre]) => {
const clases = createMemo(() => { const clases = createMemo(() => {
const vAnio = anioActual() const vAnio = anioActual();
return css( return css(
estilosGlobales.contenedor, estilosGlobales.contenedor,
estilosGlobales.inlineBlock, estilosGlobales.inlineBlock,
estilosGlobales.contenedorCursor, estilosGlobales.contenedorCursor,
estilosGlobales.contenedorCursorSoft, estilosGlobales.contenedorCursorSoft,
nombre === vAnio && estilosGlobales.contenedorCursorActivo, nombre === vAnio && estilosGlobales.contenedorCursorActivo,
) );
}) });
return ( return (
<button className={clases()} title={`Cambiar a ${nombre}`} onClick={() => setAnioActual(nombre)}> <button className={clases()} title={`Cambiar a ${nombre}`} onClick={() => setAnioActual(nombre)}>
{nombre} {nombre}
</button> </button>
) );
}} }}
</For> </For>
) );
const dataTabla = createMemo(() => { const dataTabla = createMemo(() => {
const anio = anioActual() const anio = anioActual();
const obj: Cursos = {} const obj: Cursos = {};
untrack(() => { untrack(() => {
const cursos = props.data.años[anio] const cursos = props.data.años[anio];
batch(() => { batch(() => {
eliminarCursosDeLista() eliminarCursosDeLista();
let i = 0 let i = 0;
for (const [, curso] of Object.entries(cursos)) { for (const [, curso] of Object.entries(cursos)) {
// El curso devuelto por esta fun. es reactivo // El curso devuelto por esta fun. es reactivo
obj[i] = agregarCursoALista(curso) obj[i] = agregarCursoALista(curso);
i += 1 i += 1;
} }
}) });
}) });
return obj return obj;
}) });
const fnMaximizar = () => props.setEstadoLayout("MaxHorarios") const fnMaximizar = () => props.setEstadoLayout("MaxHorarios");
const fnMinimizar = () => props.setEstadoLayout("Normal") const fnMinimizar = () => props.setEstadoLayout("Normal");
const estadoActualLayout = () => props.estadoLayout const estadoActualLayout = () => props.estadoLayout;
return ( return (
<div> <div>
@ -135,5 +135,5 @@ export function Horarios(props: HorariosProps) {
</Switch> </Switch>
</div> </div>
) );
} }

View File

@ -1,14 +1,14 @@
import { estilosGlobales } from "../Estilos" import { estilosGlobales } from "../../../../Estilos";
import { StyleSheet, css } from "aphrodite" import { StyleSheet, css } from "aphrodite";
import { Tabla } from "./Tabla" import {Tabla} from "./Tabla";
import { EstadoLayout } from "./ContenedorHorarios" import { EstadoLayout } from "../ContenedorHorarios";
import { Switch, Match, createMemo } from "solid-js" import { Switch, Match, createMemo } from "solid-js";
import {SetStoreFunction} from "solid-js/store" import {SetStoreFunction} from "solid-js/store";
import { BotonMaxMin } from "./BotonMaxMin" import { BotonMaxMin } from "./BotonMaxMin";
import { BotonIcono } from "./BotonIcono" import { BotonIcono } from "./BotonIcono";
import { Curso, Cursos, ListaCursosUsuario } from "../types/DatosHorario" import { Curso, Cursos, ListaCursosUsuario } from "../../../../types/DatosHorario";
import { CursosElem } from "./CursosElem" import { CursosElem } from "./CursosElem";
import { TablaObserver } from "./TablaObserver" import { TablaObserver } from "./TablaObserver";
interface MiHorarioProps { interface MiHorarioProps {
estadoLayout: EstadoLayout, estadoLayout: EstadoLayout,
@ -29,22 +29,22 @@ const e = StyleSheet.create({
textDecoration: "none", textDecoration: "none",
}, },
}, },
}) });
export function MiHorario(props: MiHorarioProps) { export function MiHorario(props: MiHorarioProps) {
const tablaObserver = new TablaObserver() const tablaObserver = new TablaObserver();
const datosMiHorario = createMemo(() => { const datosMiHorario = createMemo(() => {
const obj: Cursos = {} const obj: Cursos = {};
props.cursosUsuario.cursos.forEach((x, i) => { props.cursosUsuario.cursos.forEach((x, i) => {
obj[i] = x obj[i] = x;
}) });
return obj return obj;
}) });
const fnMaximizar = () => props.setEstadoLayout("MaxPersonal") const fnMaximizar = () => props.setEstadoLayout("MaxPersonal");
const fnMinimizar = () => props.setEstadoLayout("Normal") const fnMinimizar = () => props.setEstadoLayout("Normal");
const estadoActualLayout = () => props.estadoLayout const estadoActualLayout = () => props.estadoLayout;
/* TODO: En barra superior colocar todos los horarios. En barra inferior el horario /* TODO: En barra superior colocar todos los horarios. En barra inferior el horario
actual. actual.
@ -142,5 +142,5 @@ export function MiHorario(props: MiHorarioProps) {
</Match> </Match>
</Switch> </Switch>
</div> </div>
) );
} }

View File

@ -1,9 +1,9 @@
import { StyleSheet, css } from "aphrodite"; import { StyleSheet, css } from "aphrodite";
import { batch, createMemo, For } from "solid-js"; import { batch, createMemo, For } from "solid-js";
import { produce, SetStoreFunction } from "solid-js/store"; import { produce, SetStoreFunction } from "solid-js/store";
import { estilosGlobales } from "../Estilos"; import {estilosGlobales} from "../../../../Estilos";
import { Cursos, ListaCursosUsuario, DataProcesada, DatosGrupo } from "../types/DatosHorario"; import { Cursos, ListaCursosUsuario, DataProcesada, DatosGrupo } from "../../../../types/DatosHorario";
import { Dia, dias, horas } from "../Store"; import { Dia, dias, horas } from "../../../../Store";
import { FilaTabla } from "./Tabla/FilaTabla"; import { FilaTabla } from "./Tabla/FilaTabla";
import { TablaObserver } from "./TablaObserver"; import { TablaObserver } from "./TablaObserver";

View File

@ -1,8 +1,8 @@
import { StyleSheet, css } from "aphrodite"; import { StyleSheet, css } from "aphrodite";
import { estilosGlobales } from "../../Estilos"; import { estilosGlobales } from "../../../../../Estilos";
import { For, createSignal, createMemo, createEffect, onCleanup } from "solid-js"; import { For, createSignal, createMemo, createEffect, onCleanup } from "solid-js";
import { Dia } from "../../Store"; import { Dia } from "../../../../../Store";
import { DatosGrupo } from "../../types/DatosHorario"; import { DatosGrupo } from "../../../../../types/DatosHorario";
import {TablaObserver} from "../TablaObserver"; import {TablaObserver} from "../TablaObserver";
const e = StyleSheet.create({ const e = StyleSheet.create({
@ -179,7 +179,9 @@ function RenderFila(datos: DatosProps, props: Props) {
return `${css(...clases)} ${adicional}`; return `${css(...clases)} ${adicional}`;
}, },
undefined, undefined,
(x, y) => x === y, {
equals: (x, y) => x === y,
},
); );
return ( return (

View File

@ -1,10 +1,10 @@
import { StyleSheet, css } from "aphrodite"; import { StyleSheet, css } from "aphrodite";
import { estilosGlobales } from "../../Estilos"; import { estilosGlobales } from "../../../../../Estilos";
import { For, createMemo } from "solid-js"; import { For, createMemo } from "solid-js";
import {createStore, Store} from "solid-js/store"; import {createStore, Store} from "solid-js/store";
import { Dia, dias } from "../../Store"; import { Dia, dias } from "../../../../../Store";
import { CeldaFila } from "./CeldaFila"; import { CeldaFila } from "./CeldaFila";
import { DataProcesada } from "../../types/DatosHorario"; import { DataProcesada } from "../../../../../types/DatosHorario";
import { coloresBorde, diaANum } from "../Tabla"; import { coloresBorde, diaANum } from "../Tabla";
import { TablaObserver } from "../TablaObserver"; import { TablaObserver } from "../TablaObserver";

View File

@ -1,6 +1,6 @@
import { createMemo, createEffect, untrack } from "solid-js" import { createMemo, createEffect, untrack } from "solid-js";
import {createStore, SetStoreFunction, Store, produce} from "solid-js/store" import {createStore, SetStoreFunction, Store, produce} from "solid-js/store";
import { DatosGrupo } from "../types/DatosHorario" import { DatosGrupo } from "../../../../types/DatosHorario";
const createMemoDefault = <T>(f: () => T) => createMemo<T>( const createMemoDefault = <T>(f: () => T) => createMemo<T>(
f, f,
@ -8,7 +8,7 @@ const createMemoDefault = <T>(f: () => T) => createMemo<T>(
{ {
equals: (x, y) => x === y, equals: (x, y) => x === y,
}, },
) );
/** /**
* - Normal * - Normal
@ -62,13 +62,13 @@ export class TablaObserver {
curso: undefined, curso: undefined,
esLab: undefined, esLab: undefined,
grupo: undefined, grupo: undefined,
}) });
this.resaltado = resaltado this.resaltado = resaltado;
this.setResaltado = setResaltado this.setResaltado = setResaltado;
const [seleccionado, setSeleccionado] = createStore<ISeleccionado>({}) const [seleccionado, setSeleccionado] = createStore<ISeleccionado>({});
this.seleccionado = seleccionado this.seleccionado = seleccionado;
this.setSeleccionado = setSeleccionado this.setSeleccionado = setSeleccionado;
} }
/** /**
@ -86,83 +86,83 @@ export class TablaObserver {
grupo: string, grupo: string,
datosGrupo: DatosGrupo, datosGrupo: DatosGrupo,
): () => EstadoCelda { ): () => EstadoCelda {
const resaltado = this.resaltado const resaltado = this.resaltado;
const resaltadoMemo = createMemoDefault(() => { const resaltadoMemo = createMemoDefault(() => {
if (resaltado.anio === anio && resaltado.curso === curso) { if (resaltado.anio === anio && resaltado.curso === curso) {
if (resaltado.esLab === undefined) { if (resaltado.esLab === undefined) {
return true return true;
} else if (resaltado.esLab !== esLab) { } else if (resaltado.esLab !== esLab) {
return false return false;
} else { } else {
if (resaltado.grupo === undefined) { if (resaltado.grupo === undefined) {
return true return true;
} else return resaltado.grupo === grupo } else return resaltado.grupo === grupo;
} }
} else { } else {
return false return false;
} }
}) });
// Registrar curso en `seleccionado` // Registrar curso en `seleccionado`
this.setSeleccionado((obj: Store<ISeleccionado>) => { this.setSeleccionado((obj: Store<ISeleccionado>) => {
const nuevoObj = {...obj} const nuevoObj = {...obj};
if (!nuevoObj[anio]) { if (!nuevoObj[anio]) {
nuevoObj[anio] = {} nuevoObj[anio] = {};
} }
if (!nuevoObj[anio][curso]) { if (!nuevoObj[anio][curso]) {
nuevoObj[anio][curso] = { nuevoObj[anio][curso] = {
Laboratorio: [], Laboratorio: [],
Teoria: [], Teoria: [],
} };
} }
return nuevoObj return nuevoObj;
}) });
// Crear un effect para que cada vez que la celda se seleccione se actualize `seleccionado` // Crear un effect para que cada vez que la celda se seleccione se actualize `seleccionado`
createEffect(() => { createEffect(() => {
const seleccionado = datosGrupo.seleccionado const seleccionado = datosGrupo.seleccionado;
if (seleccionado) { if (seleccionado) {
this.setSeleccionado(anio, curso, esLab ? "Laboratorio" : "Teoria", (x) => [...x, grupo]) this.setSeleccionado(anio, curso, esLab ? "Laboratorio" : "Teoria", (x) => [...x, grupo]);
} else { } else {
this.setSeleccionado(anio, curso, esLab ? "Laboratorio" : "Teoria", (x) => x.filter((x) => x !== grupo)) this.setSeleccionado(anio, curso, esLab ? "Laboratorio" : "Teoria", (x) => x.filter((x) => x !== grupo));
} }
}) });
const seleccionadoMemo = createMemoDefault<EstadoSeleccionado>(() => { const seleccionadoMemo = createMemoDefault<EstadoSeleccionado>(() => {
const gruposSeleccionados = this.seleccionado[anio][curso][esLab ? "Laboratorio" : "Teoria"] const gruposSeleccionados = this.seleccionado[anio][curso][esLab ? "Laboratorio" : "Teoria"];
if (gruposSeleccionados.length > 0) { if (gruposSeleccionados.length > 0) {
return gruposSeleccionados.find((x) => x === grupo) ? "Seleccionado" : "Oculto" return gruposSeleccionados.find((x) => x === grupo) ? "Seleccionado" : "Oculto";
} else { } else {
return "Normal" return "Normal";
} }
}) });
return createMemoDefault((): EstadoCelda => { return createMemoDefault((): EstadoCelda => {
const resaltado = resaltadoMemo() const resaltado = resaltadoMemo();
const seleccionado = seleccionadoMemo() const seleccionado = seleccionadoMemo();
switch (seleccionado) { switch (seleccionado) {
case "Normal": { case "Normal": {
return resaltado ? "Resaltado" : "Normal" return resaltado ? "Resaltado" : "Normal";
} }
case "Oculto": { case "Oculto": {
return resaltado ? "ResaltadoOculto" : "Oculto" return resaltado ? "ResaltadoOculto" : "Oculto";
} }
case "Seleccionado": { case "Seleccionado": {
return resaltado ? "ResaltadoSeleccionado" : "Seleccionado" return resaltado ? "ResaltadoSeleccionado" : "Seleccionado";
} }
default: { default: {
let _: never let _: never;
// eslint-disable-next-line prefer-const // eslint-disable-next-line prefer-const
_ = seleccionado _ = seleccionado;
return _ return _;
} }
} }
}) });
} }
/** /**
@ -172,13 +172,13 @@ export class TablaObserver {
*/ */
registrarConId(id: string, datosGrupo: DatosGrupo): () => EstadoCelda { registrarConId(id: string, datosGrupo: DatosGrupo): () => EstadoCelda {
if (this.memos[id]) { if (this.memos[id]) {
return this.memos[id] return this.memos[id];
} }
const [, anio, curso, lab, grupo] = id.split("_") const [, anio, curso, lab, grupo] = id.split("_");
const memo = this.registrar(anio, curso, lab === "L", grupo, datosGrupo) const memo = this.registrar(anio, curso, lab === "L", grupo, datosGrupo);
this.memos[id] = memo this.memos[id] = memo;
return memo return memo;
} }
/** /**
@ -186,24 +186,24 @@ export class TablaObserver {
* @param id Id a resaltar - YYYYMMDD_Año_Curso[\_Lab[_Grupo]] * @param id Id a resaltar - YYYYMMDD_Año_Curso[\_Lab[_Grupo]]
*/ */
resaltar(id: string) { resaltar(id: string) {
const [, anio, curso, lab, grupo] = id.split("_") const [, anio, curso, lab, grupo] = id.split("_");
if (anio === undefined || curso === undefined) { if (anio === undefined || curso === undefined) {
console.error("Error al intentar resaltar celda: anio o curso son undefined:", anio, curso) console.error("Error al intentar resaltar celda: anio o curso son undefined:", anio, curso);
return return;
} }
let esLab: boolean | undefined let esLab: boolean | undefined;
if (lab === undefined) { if (lab === undefined) {
esLab = undefined esLab = undefined;
} else { } else {
esLab = lab === "L" esLab = lab === "L";
} }
this.setResaltado({ this.setResaltado({
anio, anio,
curso, curso,
esLab, esLab,
grupo, grupo,
}) });
} }
quitarResaltado() { quitarResaltado() {
@ -212,10 +212,10 @@ export class TablaObserver {
curso: undefined, curso: undefined,
esLab: undefined, esLab: undefined,
grupo: undefined, grupo: undefined,
}) });
} }
limpiar(id: string) { limpiar(id: string) {
delete this.memos[id] delete this.memos[id];
} }
} }

View File

@ -1,5 +1,5 @@
import {createStore, SetStoreFunction, Store} from "solid-js/store" import {createStore, SetStoreFunction, Store} from "solid-js/store";
import { Curso, ListaCursosUsuario } from "../types/DatosHorario" import { Curso, ListaCursosUsuario } from "../../../../types/DatosHorario";
interface ReturnType { interface ReturnType {
listaCursos: Store<ListaCursosUsuario>, listaCursos: Store<ListaCursosUsuario>,
@ -12,30 +12,30 @@ export const useListaCursos = (): ReturnType => {
const [listaCursos, setListaCursos] = createStore<ListaCursosUsuario>({ const [listaCursos, setListaCursos] = createStore<ListaCursosUsuario>({
sigIndice: 0, sigIndice: 0,
cursos: [], cursos: [],
}) });
const agregarCursoALista = (curso: Curso): Curso => { const agregarCursoALista = (curso: Curso): Curso => {
// Si el horario ya se habia agregado, ocultarlo // Si el horario ya se habia agregado, ocultarlo
const cursoActualIndex = listaCursos.cursos.findIndex((x) => x.nombre === curso.nombre) const cursoActualIndex = listaCursos.cursos.findIndex((x) => x.nombre === curso.nombre);
if (cursoActualIndex !== -1) { if (cursoActualIndex !== -1) {
setListaCursos("cursos", cursoActualIndex, "oculto", (x) => !x) setListaCursos("cursos", cursoActualIndex, "oculto", (x) => !x);
return listaCursos.cursos[cursoActualIndex] return listaCursos.cursos[cursoActualIndex];
} else { } else {
setListaCursos("cursos", listaCursos.sigIndice, curso) setListaCursos("cursos", listaCursos.sigIndice, curso);
setListaCursos("sigIndice", (x) => x + 1) setListaCursos("sigIndice", (x) => x + 1);
return listaCursos.cursos[listaCursos.sigIndice - 1] return listaCursos.cursos[listaCursos.sigIndice - 1];
}
} }
};
const eliminarCursosDeLista = () => { const eliminarCursosDeLista = () => {
setListaCursos("cursos", []) setListaCursos("cursos", []);
setListaCursos("sigIndice", 0) setListaCursos("sigIndice", 0);
} };
return { return {
listaCursos, listaCursos,
setListaCursos, setListaCursos,
agregarCursoALista, agregarCursoALista,
eliminarCursosDeLista, eliminarCursosDeLista,
} };
} };