Crear TablaObserver para reemplazar la forma en la que se resaltan celdas en la tabla

This commit is contained in:
Araozu 2021-03-26 19:19:09 -05:00
parent f325f08fc8
commit cc36f070b7
10 changed files with 199 additions and 100 deletions

View File

@ -10,6 +10,9 @@
<link rel="stylesheet" href="css/phosphor.min.css"> <link rel="stylesheet" href="css/phosphor.min.css">
<link rel="stylesheet" href="css/global.css"> <link rel="stylesheet" href="css/global.css">
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
</head> </head>
<body> <body>
<noscript>You need to enable JavaScript to run this app.</noscript> <noscript>You need to enable JavaScript to run this app.</noscript>

View File

@ -9,7 +9,7 @@ import { Creditos } from "./Creditos"
function App() { function App() {
/// @ts-ignore /// @ts-ignore
const soportaBackdropFilter = document.body.style.backdropFilter !== undefined const soportaBackdropFilter = document.body.style.backdropFilter !== undefined
const mostrarMensajeBackdropFilterRaw = localStorage.getItem("mensaje-backdrop-filter-oculto") !== undefined const mostrarMensajeBackdropFilterRaw = localStorage.getItem("mensaje-backdrop-filter-oculto") === undefined
const [mostrarMensajeBackdropFilter, setMostrarMensaje] = createSignal(mostrarMensajeBackdropFilterRaw) const [mostrarMensajeBackdropFilter, setMostrarMensaje] = createSignal(mostrarMensajeBackdropFilterRaw)

View File

@ -2,7 +2,7 @@ import { estilosGlobales } from "./Estilos"
import { StyleSheet, css } from "aphrodite" import { StyleSheet, css } from "aphrodite"
import { numWallpaper, setNumWallpaper } from "./Store" import { numWallpaper, setNumWallpaper } from "./Store"
const totalWallpapers = 5 const ultimoIndiceWallpaper = 5
const e = StyleSheet.create({ const e = StyleSheet.create({
contCambiador: { contCambiador: {
@ -36,14 +36,14 @@ const retrocederWallpaper = () => {
setNumWallpaper(num - 1) setNumWallpaper(num - 1)
localStorage.setItem("num-img", (num - 1).toString()) localStorage.setItem("num-img", (num - 1).toString())
} else { } else {
setNumWallpaper(totalWallpapers) setNumWallpaper(ultimoIndiceWallpaper)
localStorage.setItem("num-img", (totalWallpapers).toString()) localStorage.setItem("num-img", (ultimoIndiceWallpaper).toString())
} }
} }
const avanzarWallpaper = () => { const avanzarWallpaper = () => {
const num = numWallpaper() const num = numWallpaper()
if (num < totalWallpapers) { if (num < ultimoIndiceWallpaper) {
setNumWallpaper(num + 1) setNumWallpaper(num + 1)
localStorage.setItem("num-img", (num + 1).toString()) localStorage.setItem("num-img", (num + 1).toString())
} else { } else {

View File

@ -1,7 +1,8 @@
import { Cursos, CursoRaw, DatosGrupo, ListaCursosUsuario, Curso } from "../types/DatosHorario" import { Cursos, DatosGrupo, ListaCursosUsuario, Curso } from "../types/DatosHorario"
import { createEffect, createMemo, For, SetStateFunction } from "solid-js" import { createMemo, For, SetStateFunction } from "solid-js"
import { StyleSheet, css } from "aphrodite" import { StyleSheet, css } from "aphrodite"
import { estilosGlobales } from "../Estilos" import { estilosGlobales } from "../Estilos"
import { TablaObserver } from "./TablaObserver"
const e = StyleSheet.create({ const e = StyleSheet.create({
inline: { inline: {
@ -29,14 +30,14 @@ const e = StyleSheet.create({
}) })
interface Props { interface Props {
version: number,
dataAnio: Cursos, dataAnio: Cursos,
anioActual: () => string, anioActual: () => string,
fnAgregarCurso: (c: Curso) => void, fnAgregarCurso: (c: Curso) => void,
listaCursosUsuario: ListaCursosUsuario, listaCursosUsuario: ListaCursosUsuario,
idHover: () => string,
setIdHover: (v: string) => string,
esCursoMiHorario: boolean, esCursoMiHorario: boolean,
setCursosUsuarios: SetStateFunction<ListaCursosUsuario> setCursosUsuarios: SetStateFunction<ListaCursosUsuario>,
tablaObserver: TablaObserver,
} }
type FnSetCursosUsuarios = SetStateFunction<ListaCursosUsuario>; type FnSetCursosUsuarios = SetStateFunction<ListaCursosUsuario>;
@ -45,7 +46,7 @@ interface PropsIndicadorGrupo {
nombre: string, nombre: string,
esLab: boolean, esLab: boolean,
idParcial: string, idParcial: string,
setIdHover: (v: string) => string, tablaObserver: TablaObserver,
onClick: () => void onClick: () => void
} }
@ -54,8 +55,8 @@ function IndicadorGrupo(props: PropsIndicadorGrupo) {
return ( return (
<span className={css(e.botonTexto, estilosGlobales.contenedorCursor, estilosGlobales.contenedorCursorSoft)} <span className={css(e.botonTexto, estilosGlobales.contenedorCursor, estilosGlobales.contenedorCursorSoft)}
style={props.esLab ? {"font-style": "italic"} : {"font-weight": "bold"}} style={props.esLab ? {"font-style": "italic"} : {"font-weight": "bold"}}
onMouseEnter={() => props.setIdHover(id)} onMouseEnter={() => props.tablaObserver.resaltar(id)}
onMouseLeave={() => props.setIdHover("")} onMouseLeave={() => props.tablaObserver.quitarResaltado()}
onClick={props.onClick} onClick={props.onClick}
> >
{props.esLab ? "L" : ""}{props.nombre} {props.esLab ? "L" : ""}{props.nombre}
@ -114,7 +115,7 @@ export function CursosElem(props: Props) {
<For each={Object.entries(props.dataAnio)}> <For each={Object.entries(props.dataAnio)}>
{([indiceCurso, datosCurso]) => { {([indiceCurso, datosCurso]) => {
const idCurso = `${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,
@ -152,8 +153,8 @@ export function CursosElem(props: Props) {
<div className={claseMemo()}> <div className={claseMemo()}>
<div <div
className={css(e.inline, e.lineaTexto, e.botonTexto, estilosGlobales.contenedorCursor, estilosGlobales.contenedorCursorSoft)} className={css(e.inline, e.lineaTexto, e.botonTexto, estilosGlobales.contenedorCursor, estilosGlobales.contenedorCursorSoft)}
onMouseEnter={() => props.setIdHover(idCurso)} onMouseEnter={() => props.tablaObserver.resaltar(idCurso)}
onMouseLeave={() => props.setIdHover("")} onMouseLeave={() => props.tablaObserver.quitarResaltado()}
> >
{datosCurso.abreviado} - {datosCurso.nombre} {datosCurso.abreviado} - {datosCurso.nombre}
</div> </div>
@ -168,10 +169,11 @@ export function CursosElem(props: Props) {
</span> </span>
<For each={grupos}> <For each={grupos}>
{([x, fnOnClick]) => ( {([x, fnOnClick]) => (
<IndicadorGrupo nombre={x} <IndicadorGrupo
nombre={x}
esLab={false} esLab={false}
idParcial={idCurso} idParcial={idCurso}
setIdHover={props.setIdHover} tablaObserver={props.tablaObserver}
onClick={fnOnClick} onClick={fnOnClick}
/> />
) )
@ -190,10 +192,11 @@ export function CursosElem(props: Props) {
</span> </span>
<For each={grupos}> <For each={grupos}>
{([x, fnOnClick]) => ( {([x, fnOnClick]) => (
<IndicadorGrupo nombre={x} <IndicadorGrupo
nombre={x}
esLab esLab
idParcial={idCurso} idParcial={idCurso}
setIdHover={props.setIdHover} tablaObserver={props.tablaObserver}
onClick={fnOnClick} onClick={fnOnClick}
/> />
) )

View File

@ -7,6 +7,7 @@ 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"
interface HorariosProps { interface HorariosProps {
data: DatosHorario, data: DatosHorario,
@ -25,8 +26,8 @@ const {
export function Horarios(props: HorariosProps) { export function Horarios(props: HorariosProps) {
const [anioActual, setAnioActual] = createSignal("1er año") const [anioActual, setAnioActual] = createSignal("1er año")
// ID que indica cuales celdas resaltar.
const [idHover, setIdHover] = createSignal("") const tablaObserver = new TablaObserver()
const elAnios = ( const elAnios = (
<For each={Object.entries(props.data.años)}> <For each={Object.entries(props.data.años)}>
@ -102,21 +103,20 @@ export function Horarios(props: HorariosProps) {
data={dataTabla()} data={dataTabla()}
version={props.data.version} version={props.data.version}
anio={anioActual()} anio={anioActual()}
idHover={idHover}
setIdHover={setIdHover}
setCursosUsuarios={setListaCursos} setCursosUsuarios={setListaCursos}
tablaObserver={tablaObserver}
/> />
</div> </div>
<div> <div>
<CursosElem <CursosElem
version={props.data.version}
dataAnio={dataTabla()} dataAnio={dataTabla()}
anioActual={anioActual} anioActual={anioActual}
fnAgregarCurso={props.fnAgregarCurso} fnAgregarCurso={props.fnAgregarCurso}
listaCursosUsuario={props.listaCursosUsuario} listaCursosUsuario={props.listaCursosUsuario}
idHover={idHover}
setIdHover={setIdHover}
esCursoMiHorario={false} esCursoMiHorario={false}
setCursosUsuarios={setListaCursos} setCursosUsuarios={setListaCursos}
tablaObserver={tablaObserver}
/> />
</div> </div>
</Match> </Match>

View File

@ -1,13 +1,13 @@
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 { mostrarDescansos } from "../Store"
import { EstadoLayout } from "./ContenedorHorarios" import { EstadoLayout } from "./ContenedorHorarios"
import { Switch, Match, For, createMemo, createSignal, SetStateFunction } from "solid-js" import { Switch, Match, createMemo, SetStateFunction } from "solid-js"
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"
interface MiHorarioProps { interface MiHorarioProps {
estadoLayout: EstadoLayout, estadoLayout: EstadoLayout,
@ -31,7 +31,7 @@ const e = StyleSheet.create({
}) })
export function MiHorario(props: MiHorarioProps) { export function MiHorario(props: MiHorarioProps) {
const [idHover, setIdHover] = createSignal("") const tablaObserver = new TablaObserver()
const datosMiHorario = createMemo(() => { const datosMiHorario = createMemo(() => {
const obj: Cursos = {} const obj: Cursos = {}
@ -110,21 +110,20 @@ export function MiHorario(props: MiHorarioProps) {
data={datosMiHorario()} data={datosMiHorario()}
anio={"Mi horario"} anio={"Mi horario"}
version={1} version={1}
idHover={idHover}
setIdHover={setIdHover}
setCursosUsuarios={props.setCursosUsuarios} setCursosUsuarios={props.setCursosUsuarios}
tablaObserver={tablaObserver}
/> />
</div> </div>
<CursosElem <CursosElem
version={Number(Math.random() * 1_000_000)}
anioActual={() => "Mi horario"} anioActual={() => "Mi horario"}
dataAnio={datosMiHorario()} dataAnio={datosMiHorario()}
fnAgregarCurso={props.fnAgregarCurso} fnAgregarCurso={props.fnAgregarCurso}
listaCursosUsuario={props.cursosUsuario} listaCursosUsuario={props.cursosUsuario}
idHover={idHover}
setIdHover={setIdHover}
esCursoMiHorario esCursoMiHorario
setCursosUsuarios={props.setCursosUsuarios} setCursosUsuarios={props.setCursosUsuarios}
tablaObserver={tablaObserver}
/> />
</Match> </Match>
<Match when={props.estadoLayout === "MaxHorarios"}> <Match when={props.estadoLayout === "MaxHorarios"}>

View File

@ -4,6 +4,7 @@ import { estilosGlobales } from "../Estilos"
import { Cursos, ListaCursosUsuario, DataProcesada } from "../types/DatosHorario" import { Cursos, ListaCursosUsuario, DataProcesada } 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"
export const coloresBorde = Object.freeze([ export const coloresBorde = Object.freeze([
"rgba(33,150,243,1)", "rgba(33,150,243,1)",
@ -160,16 +161,13 @@ interface Props {
data: Cursos, data: Cursos,
anio: string, anio: string,
version: number, version: number,
idHover: () => string, setCursosUsuarios: SetStateFunction<ListaCursosUsuario>,
setIdHover: (v: string) => string, tablaObserver: TablaObserver,
setCursosUsuarios: SetStateFunction<ListaCursosUsuario>
} }
export function Tabla(props: Props) { export function Tabla(props: Props) {
const anio = () => props.anio.substring(0, props.anio.indexOf(" ")) const anio = () => props.anio.substring(0, props.anio.indexOf(" "))
const data = createMemo(() => procesarAnio(props.data, anio(), props.version, props.setCursosUsuarios)) const data = createMemo(() => procesarAnio(props.data, anio(), props.version, props.setCursosUsuarios))
const idHover = props.idHover
const setIdHover = props.setIdHover
const celdas = createMemo(() => { const celdas = createMemo(() => {
// Hace reaccionar a la reactividad de Solid // Hace reaccionar a la reactividad de Solid
@ -180,8 +178,7 @@ export function Tabla(props: Props) {
<FilaTabla <FilaTabla
data={data()} data={data()}
hora={hora} hora={hora}
idHover={idHover} tablaObserver={props.tablaObserver}
setIdHover={setIdHover}
/> />
)} )}
</For> </For>

View File

@ -1,8 +1,9 @@
import { StyleSheet, css } from "aphrodite" import { StyleSheet, css } from "aphrodite"
import { estilosGlobales } from "../../Estilos" import { estilosGlobales } from "../../Estilos"
import { For, createSignal, createMemo, createEffect, SetStateFunction } from "solid-js" import { For, createSignal, createMemo } from "solid-js"
import { Dia } from "../../Store" import { Dia } from "../../Store"
import { DatosGrupo, ListaCursosUsuario } from "../../types/DatosHorario" import { DatosGrupo } from "../../types/DatosHorario"
import { TablaObserver } from "../TablaObserver"
const e = StyleSheet.create({ const e = StyleSheet.create({
celdaComun: { celdaComun: {
@ -19,7 +20,7 @@ const e = StyleSheet.create({
borderRadius: "5px", borderRadius: "5px",
// transition: "background-color 100ms, color 100ms" // transition: "background-color 100ms, color 100ms"
}, },
celdaCursoActiva: { celdaResaltado: {
// color: "#151515" // color: "#151515"
}, },
celdaCursoTeoria: { celdaCursoTeoria: {
@ -28,7 +29,7 @@ const e = StyleSheet.create({
celdaCursoLab: { celdaCursoLab: {
fontStyle: "italic", fontStyle: "italic",
}, },
celdaSeleccionada: { celdaSeleccionado: {
textDecoration: "underline", textDecoration: "underline",
}, },
}) })
@ -78,22 +79,16 @@ interface Props {
datosGrupo: DatosGrupo, datosGrupo: DatosGrupo,
fnSeleccionar: () => void fnSeleccionar: () => void
}[], }[],
idHover: () => string,
setIdHover: (v: string) => string,
fnResaltarFila: () => void, fnResaltarFila: () => void,
fnDesresaltarFila: () => void, fnDesresaltarFila: () => void,
dia: Dia, dia: Dia,
tablaObserver: TablaObserver,
} }
const claseSeldaSeleccionada = css(e.celdaSeleccionada) const claseSeldaSeleccionada = css(e.celdaSeleccionado)
export function CeldaFila(props: Props) { export function CeldaFila(props: Props) {
const datos = props.datos const datos = props.datos
const idHover = props.idHover
const setIdHover = props.setIdHover
const fnOnMouseEnter = (id: string) => setIdHover(id)
const fnOnMouseLeave = () => setIdHover("")
return ( return (
<div className={css(e.celdaComun, estilosGlobales.inlineBlock)}> <div className={css(e.celdaComun, estilosGlobales.inlineBlock)}>
@ -104,6 +99,8 @@ export function CeldaFila(props: Props) {
const esLab = datos.esLab const esLab = datos.esLab
const fnSeleccionar = datos.fnSeleccionar const fnSeleccionar = datos.fnSeleccionar
const estadoCeldaMemo = props.tablaObserver.registrarConId(id)
const [estabaResaltado, setEstabaResaltado] = createSignal(false) const [estabaResaltado, setEstabaResaltado] = createSignal(false)
const estaSeleccionado = createMemo(() => datos.datosGrupo.seleccionado) const estaSeleccionado = createMemo(() => datos.datosGrupo.seleccionado)
@ -113,20 +110,59 @@ export function CeldaFila(props: Props) {
const clases = [ const clases = [
e.celdaCurso, e.celdaCurso,
esLab ? e.celdaCursoLab : e.celdaCursoTeoria, esLab ? e.celdaCursoLab : e.celdaCursoTeoria,
estaSeleccionado() && e.celdaSeleccionada, estaSeleccionado() && e.celdaSeleccionado,
] ]
let adicional = "" let adicional = ""
const idHoverS = idHover()
if (idHoverS !== "" && id.search(idHoverS) !== -1) {
props.fnResaltarFila()
clases.push(e.celdaCursoActiva)
adicional = clasesColores[props.dia]
setEstabaResaltado(true) const estadoCelda = estadoCeldaMemo()
} else if (estabaResaltado()) {
switch (estadoCelda) {
case "Normal": {
if (estabaResaltado()) {
props.fnDesresaltarFila() props.fnDesresaltarFila()
setEstabaResaltado(false) setEstabaResaltado(false)
} }
break
}
case "Oculto": {
if (estabaResaltado()) {
props.fnDesresaltarFila()
setEstabaResaltado(false)
}
// TODO
break
}
case "Resaltado": {
props.fnResaltarFila()
setEstabaResaltado(true)
clases.push(e.celdaResaltado)
adicional = clasesColores[props.dia]
break
}
case "Seleccionado": {
if (estabaResaltado()) {
props.fnDesresaltarFila()
setEstabaResaltado(false)
}
break
}
case "ResaltadoOculto": {
props.fnResaltarFila()
setEstabaResaltado(true)
break
}
case "ResaltadoSeleccionado": {
props.fnResaltarFila()
setEstabaResaltado(true)
break
}
}
return `${css(...clases)} ${adicional}` return `${css(...clases)} ${adicional}`
}, },
undefined, undefined,
@ -135,8 +171,12 @@ export function CeldaFila(props: Props) {
return ( return (
<span className={clases()} <span className={clases()}
onMouseEnter={() => fnOnMouseEnter(id)} onMouseEnter={() => {
onMouseLeave={fnOnMouseLeave} props.tablaObserver.resaltar(id)
}}
onMouseLeave={() => {
props.tablaObserver.quitarResaltado()
}}
onClick={fnSeleccionar} onClick={fnSeleccionar}
> >
{txt} {txt}

View File

@ -1,10 +1,11 @@
import { StyleSheet, css } from "aphrodite" import { StyleSheet, css } from "aphrodite"
import { estilosGlobales } from "../../Estilos" import { estilosGlobales } from "../../Estilos"
import { For, createSignal, createMemo, createState, createEffect, State, SetStateFunction } from "solid-js" import { For, createMemo, createState, State } from "solid-js"
import { Dia, dias } from "../../Store" import { Dia, dias } from "../../Store"
import { CeldaFila } from "./CeldaFila" import { CeldaFila } from "./CeldaFila"
import { DataProcesada, ListaCursosUsuario } from "../../types/DatosHorario" import { DataProcesada } from "../../types/DatosHorario"
import { coloresBorde, diaANum } from "../Tabla" import { coloresBorde, diaANum } from "../Tabla"
import { TablaObserver } from "../TablaObserver"
const e = StyleSheet.create({ const e = StyleSheet.create({
celdaHora: { celdaHora: {
@ -61,8 +62,7 @@ const [diasResaltados, setDiasResaltados] = createState({
interface Props { interface Props {
hora: string, hora: string,
data: DataProcesada, data: DataProcesada,
idHover: () => string, tablaObserver: TablaObserver,
setIdHover: (v: string) => string
} }
const diasFilter = createMemo(() => Object.entries(diasResaltados) const diasFilter = createMemo(() => Object.entries(diasResaltados)
@ -140,11 +140,10 @@ export function FilaTabla(props: Props) {
return ( return (
<CeldaFila <CeldaFila
datos={datos} datos={datos}
idHover={props.idHover}
setIdHover={props.setIdHover}
fnResaltarFila={() => fnResaltar(dia)} fnResaltarFila={() => fnResaltar(dia)}
fnDesresaltarFila={() => fnDesresaltar(dia)} fnDesresaltarFila={() => fnDesresaltar(dia)}
dia={dia} dia={dia}
tablaObserver={props.tablaObserver}
/> />
) )
}} }}

View File

@ -1,18 +1,18 @@
import { createMemo, createState, SetStateFunction, State } from "solid-js"
/** /**
* - Normal * - Normal
* - Oculto - Otro grupo seleccionado * - Oculto - Otro grupo seleccionado
* - Seleccionado - Cursor ensima * - Resaltado - Cursor encima
* - Resaltado - Grupo seleccionado * - Seleccionado - Grupo escogido
* - ResaltadoSeleccionado - Grupo seleccionado y cursor encima * - ResaltadoSeleccionado - Grupo escogido y cursor encima
* - ResaltadoOculto - Otro grupo seleccionado y cursor encima * - ResaltadoOculto - Otro grupo escogido y cursor encima
*/ */
import { createMemo, createState, SetStateFunction, State } from "solid-js";
type EstadoCelda = type EstadoCelda =
| "Normal" | "Normal"
| "Oculto" | "Oculto"
| "Seleccionado"
| "Resaltado" | "Resaltado"
| "Seleccionado"
| "ResaltadoSeleccionado" | "ResaltadoSeleccionado"
| "ResaltadoOculto" | "ResaltadoOculto"
@ -20,7 +20,7 @@ interface Datos {
anio?: string, anio?: string,
curso?: string, curso?: string,
esLab?: boolean, esLab?: boolean,
grupo?: string grupo?: string,
} }
export class TablaObserver { export class TablaObserver {
@ -28,35 +28,93 @@ export class TablaObserver {
private readonly resaltado: State<Datos> private readonly resaltado: State<Datos>
private readonly setResaltado: SetStateFunction<Datos> private readonly setResaltado: SetStateFunction<Datos>
private gruposSeleccionados = {} private gruposSeleccionados = {}
private memos: {[id: string]: () => EstadoCelda} = {};
constructor() { constructor() {
const [resaltado, setResaltado] = createState<Datos>({ const [resaltado, setResaltado] = createState<Datos>({
anio: undefined, anio: undefined,
curso: undefined, curso: undefined,
esLab: undefined, esLab: undefined,
grupo: undefined grupo: undefined,
}); })
this.resaltado = resaltado; this.resaltado = resaltado
this.setResaltado = setResaltado; this.setResaltado = setResaltado
} }
// Cada celda se registra dando estos datos /**
// Devuelve un memo con un valor de EstadoCelda, * Crea un memo que indica el estado de la celda
// el cual cada celda sabra como manejar * @param anio El año
registrar(anio: string, cursoAbreviado: string, esLab: boolean, grupo: string) { * @param curso Curso abreviado
const fn = () => { * @param esLab Si es laboratorio
* @param grupo Una única letra
}; */
private registrar(anio: string, curso: string, esLab: boolean, grupo: string): () => EstadoCelda {
const memo = createMemo( const resaltado = this.resaltado
fn, const resaltadoMemo = createMemo(
() => {
if (resaltado.anio === anio && resaltado.curso === curso) {
if (resaltado.esLab === undefined) {
return true
} else if (resaltado.esLab !== esLab) {
return false
} else {
if (resaltado.grupo === undefined) {
return true
} else return resaltado.grupo === grupo;
}
} else {
return false
}
},
undefined, undefined,
(x, y) => x === y (x, y) => x === y,
); )
return createMemo(
(): EstadoCelda => {
if (resaltadoMemo()) {
return "Resaltado"
} else {
return "Normal"
}
},
undefined,
(x, y) => x === y,
)
} }
resaltar(id: string) { /**
* Crea un memo que indica el estado de la celda a partir de un id
* @param id Id a registrar - YYYYMMDD_Año_Curso[\_Lab[_Grupo]]
*/
registrarConId(id: string): () => EstadoCelda {
if (this.memos[id]) {
return this.memos[id]
}
const [, anio, curso, lab, grupo] = id.split("_")
const memo = this.registrar(anio, curso, lab === "L", grupo)
this.memos[id] = memo;
return memo;
}
/**
* Parsea el id y hace que las celdas registradas se actualizen adecuadamente
* @param id Id a resaltar - YYYYMMDD_Año_Curso[\_Lab[_Grupo]]
*/
resaltar(id: string) {
const [, anio, curso, lab, grupo] = id.split("_")
if (anio === undefined || curso === undefined) {
console.error("Error al intentar resaltar celda: anio o curso son undefined:", anio, curso)
return
}
this.setResaltado({
anio,
curso,
esLab: lab === "L",
grupo,
})
} }
quitarResaltado() { quitarResaltado() {
@ -64,7 +122,7 @@ export class TablaObserver {
anio: undefined, anio: undefined,
curso: undefined, curso: undefined,
esLab: undefined, esLab: undefined,
grupo: undefined grupo: undefined,
}); })
} }
} }