Agregar linter
This commit is contained in:
parent
e2503967cf
commit
f325f08fc8
89
.eslintrc.yml
Normal file
89
.eslintrc.yml
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
env:
|
||||||
|
browser: true
|
||||||
|
es2021: true
|
||||||
|
extends:
|
||||||
|
- 'eslint:recommended'
|
||||||
|
- 'plugin:@typescript-eslint/recommended'
|
||||||
|
parser: '@typescript-eslint/parser'
|
||||||
|
parserOptions:
|
||||||
|
ecmaVersion: 12
|
||||||
|
sourceType: module
|
||||||
|
plugins:
|
||||||
|
- '@typescript-eslint'
|
||||||
|
- react
|
||||||
|
rules:
|
||||||
|
"@typescript-eslint/ban-ts-comment": off
|
||||||
|
"@typescript-eslint/no-empty-function": off
|
||||||
|
indent:
|
||||||
|
- error
|
||||||
|
- 4
|
||||||
|
- SwitchCase: 1
|
||||||
|
linebreak-style:
|
||||||
|
- error
|
||||||
|
- unix
|
||||||
|
quotes:
|
||||||
|
- error
|
||||||
|
- double
|
||||||
|
semi:
|
||||||
|
- error
|
||||||
|
- never
|
||||||
|
react/jsx-pascal-case: error
|
||||||
|
react/jsx-closing-bracket-location: error
|
||||||
|
react/jsx-closing-tag-location: error
|
||||||
|
no-multi-spaces: error
|
||||||
|
react/jsx-tag-spacing: error
|
||||||
|
react/jsx-boolean-value: error
|
||||||
|
react/jsx-wrap-multilines: error
|
||||||
|
react/self-closing-comp: error
|
||||||
|
prefer-const: error
|
||||||
|
no-const-assign: error
|
||||||
|
no-var: error
|
||||||
|
array-callback-return: error
|
||||||
|
prefer-template: error
|
||||||
|
template-curly-spacing: error
|
||||||
|
no-useless-escape: error
|
||||||
|
wrap-iife: error
|
||||||
|
no-loop-func: error
|
||||||
|
default-param-last: error
|
||||||
|
space-before-function-paren:
|
||||||
|
- error
|
||||||
|
- never
|
||||||
|
space-before-blocks: error
|
||||||
|
no-param-reassign: error
|
||||||
|
function-paren-newline: error
|
||||||
|
comma-dangle:
|
||||||
|
- error
|
||||||
|
- always-multiline
|
||||||
|
arrow-spacing: error
|
||||||
|
arrow-parens: error
|
||||||
|
arrow-body-style: error
|
||||||
|
no-confusing-arrow: error
|
||||||
|
implicit-arrow-linebreak: error
|
||||||
|
no-duplicate-imports: error
|
||||||
|
object-curly-newline: error
|
||||||
|
dot-notation: error
|
||||||
|
one-var:
|
||||||
|
- error
|
||||||
|
- never
|
||||||
|
no-multi-assign: error
|
||||||
|
no-plusplus: error
|
||||||
|
operator-linebreak: error
|
||||||
|
eqeqeq: error
|
||||||
|
no-case-declarations: error
|
||||||
|
no-nested-ternary: error
|
||||||
|
no-unneeded-ternary: error
|
||||||
|
no-mixed-operators: error
|
||||||
|
nonblock-statement-body-position: error
|
||||||
|
brace-style: error
|
||||||
|
keyword-spacing: error
|
||||||
|
space-infix-ops: error
|
||||||
|
eol-last: error
|
||||||
|
newline-per-chained-call: error
|
||||||
|
no-whitespace-before-property: error
|
||||||
|
space-in-parens: error
|
||||||
|
array-bracket-spacing: error
|
||||||
|
key-spacing: error
|
||||||
|
no-trailing-spaces: error
|
||||||
|
comma-style: error
|
||||||
|
radix: error
|
||||||
|
no-new-wrappers: error
|
@ -5,7 +5,11 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/jest": "26.0.20",
|
"@types/jest": "26.0.20",
|
||||||
"@types/node": "14.14.20",
|
"@types/node": "14.14.20",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^4.19.0",
|
||||||
|
"@typescript-eslint/parser": "^4.19.0",
|
||||||
"aphrodite": "^2.4.0",
|
"aphrodite": "^2.4.0",
|
||||||
|
"eslint": "^7.22.0",
|
||||||
|
"eslint-plugin-react": "^7.23.1",
|
||||||
"normalize.css": "^8.0.1",
|
"normalize.css": "^8.0.1",
|
||||||
"solid-js": "^0.23.11",
|
"solid-js": "^0.23.11",
|
||||||
"solid-scripts": "0.0.50",
|
"solid-scripts": "0.0.50",
|
||||||
|
821
pnpm-lock.yaml
821
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
45
src/App.tsx
45
src/App.tsx
@ -1,43 +1,44 @@
|
|||||||
import { BarraSuperior } from "./BarraSuperior";
|
import { BarraSuperior } from "./BarraSuperior"
|
||||||
import { ContenedorHorarios } from "./ContenedorHorarios/ContenedorHorarios";
|
import { ContenedorHorarios } from "./ContenedorHorarios/ContenedorHorarios"
|
||||||
import { Wallpaper } from "./Wallpaper";
|
import { Wallpaper } from "./Wallpaper"
|
||||||
import { Show, createSignal } from "solid-js";
|
import { Show, createSignal } from "solid-js"
|
||||||
import { css } from "aphrodite";
|
import { css } from "aphrodite"
|
||||||
import { estilosGlobales } from "./Estilos";
|
import { estilosGlobales } from "./Estilos"
|
||||||
import { Creditos } from "./Creditos";
|
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)
|
||||||
|
|
||||||
const ocultarMensajeBackdropFilter = () => {
|
const ocultarMensajeBackdropFilter = () => {
|
||||||
setMostrarMensaje(false);
|
setMostrarMensaje(false)
|
||||||
localStorage.setItem("mensaje-backdrop-filter-oculto", "true");
|
localStorage.setItem("mensaje-backdrop-filter-oculto", "true")
|
||||||
};
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="App">
|
<div class="App">
|
||||||
<Wallpaper/>
|
<Wallpaper />
|
||||||
<BarraSuperior/>
|
<BarraSuperior />
|
||||||
<Show when={!soportaBackdropFilter && mostrarMensajeBackdropFilter()}>
|
<Show when={!soportaBackdropFilter && mostrarMensajeBackdropFilter()}>
|
||||||
<div className={css(estilosGlobales.contenedor)}>
|
<div className={css(estilosGlobales.contenedor)}>
|
||||||
Tu navegador no soporta "backdrop-filter". Este es solo un efecto
|
Tu navegador no soporta "backdrop-filter". Este es solo un efecto
|
||||||
visual, no afecta la funcionalidad de la página.
|
visual, no afecta la funcionalidad de la página.
|
||||||
<span className={css(estilosGlobales.contenedorCursor, estilosGlobales.contenedorCursorSoft)}
|
<span
|
||||||
onClick={ocultarMensajeBackdropFilter}
|
className={css(estilosGlobales.contenedorCursor, estilosGlobales.contenedorCursorSoft)}
|
||||||
|
onClick={ocultarMensajeBackdropFilter}
|
||||||
>
|
>
|
||||||
No volver a mostrar.
|
No volver a mostrar.
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</Show>
|
</Show>
|
||||||
<div style={{width: "100%", height: "0.5rem"}}/>
|
<div style={{width: "100%", height: "0.5rem"}} />
|
||||||
<ContenedorHorarios/>
|
<ContenedorHorarios />
|
||||||
<Creditos/>
|
<Creditos />
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default App;
|
export default App
|
||||||
|
@ -1,101 +1,107 @@
|
|||||||
import { estilosGlobales } from "./Estilos";
|
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 totalWallpapers = 5
|
||||||
|
|
||||||
const e = StyleSheet.create({
|
const e = StyleSheet.create({
|
||||||
contCambiador: {
|
contCambiador: {
|
||||||
userSelect: "none"
|
userSelect: "none",
|
||||||
},
|
},
|
||||||
boton: {
|
boton: {
|
||||||
cursor: "pointer",
|
cursor: "pointer",
|
||||||
textDecoration: "underline",
|
textDecoration: "underline",
|
||||||
"::before": {
|
"::before": {
|
||||||
fontSize: "1rem",
|
fontSize: "1rem",
|
||||||
transform: "translateY(0.2rem)"
|
transform: "translateY(0.2rem)",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
botonDesactivado: {
|
botonDesactivado: {
|
||||||
cursor: "not-allowed",
|
cursor: "not-allowed",
|
||||||
textDecoration: "none"
|
textDecoration: "none",
|
||||||
},
|
},
|
||||||
botonLeft: {
|
botonLeft: {
|
||||||
paddingRight: "0.5rem",
|
paddingRight: "0.5rem",
|
||||||
marginRight: "0.25rem"
|
marginRight: "0.25rem",
|
||||||
},
|
},
|
||||||
botonRight: {
|
botonRight: {
|
||||||
paddingLeft: "0.5rem",
|
paddingLeft: "0.5rem",
|
||||||
marginRight: "0.25rem"
|
marginRight: "0.25rem",
|
||||||
}
|
},
|
||||||
});
|
})
|
||||||
|
|
||||||
const retrocederWallpaper = () => {
|
const retrocederWallpaper = () => {
|
||||||
const num = numWallpaper();
|
const num = numWallpaper()
|
||||||
if (num > 0) {
|
if (num > 0) {
|
||||||
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(totalWallpapers)
|
||||||
localStorage.setItem("num-img", (totalWallpapers).toString());
|
localStorage.setItem("num-img", (totalWallpapers).toString())
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
const avanzarWallpaper = () => {
|
const avanzarWallpaper = () => {
|
||||||
const num = numWallpaper();
|
const num = numWallpaper()
|
||||||
if (num < totalWallpapers) {
|
if (num < totalWallpapers) {
|
||||||
setNumWallpaper(num + 1);
|
setNumWallpaper(num + 1)
|
||||||
localStorage.setItem("num-img", (num + 1).toString());
|
localStorage.setItem("num-img", (num + 1).toString())
|
||||||
} else {
|
} else {
|
||||||
setNumWallpaper(0);
|
setNumWallpaper(0)
|
||||||
localStorage.setItem("num-img", (0).toString());
|
localStorage.setItem("num-img", (0).toString())
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
function CambiadorImg() {
|
function CambiadorImg() {
|
||||||
return <div className={css(estilosGlobales.inlineBlock, e.contCambiador)}>
|
return (
|
||||||
<span className={css(estilosGlobales.contenedor, estilosGlobales.inlineBlock)}>
|
<div className={css(estilosGlobales.inlineBlock, e.contCambiador)}>
|
||||||
<i
|
<span className={css(estilosGlobales.contenedor, estilosGlobales.inlineBlock)}>
|
||||||
className={"ph-arrow-left " + css(e.boton, e.botonLeft, estilosGlobales.contenedorCursorSoft)}
|
<i
|
||||||
onClick={retrocederWallpaper}
|
className={`ph-arrow-left ${css(e.boton, e.botonLeft, estilosGlobales.contenedorCursorSoft)}`}
|
||||||
title={"Cambiar imagen de fondo"}
|
onClick={retrocederWallpaper}
|
||||||
/>
|
title={"Cambiar imagen de fondo"}
|
||||||
Img. {numWallpaper() + 1}
|
/>
|
||||||
<i
|
Img. {numWallpaper() + 1}
|
||||||
className={"ph-arrow-right " + css(e.boton, e.botonRight, estilosGlobales.contenedorCursorSoft)}
|
<i
|
||||||
onClick={avanzarWallpaper}
|
className={`ph-arrow-right ${css(e.boton, e.botonRight, estilosGlobales.contenedorCursorSoft)}`}
|
||||||
title={"Cambiar imagen de fondo"}
|
onClick={avanzarWallpaper}
|
||||||
/>
|
title={"Cambiar imagen de fondo"}
|
||||||
</span>
|
/>
|
||||||
</div>;
|
</span>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const estilos = StyleSheet.create({
|
const estilos = StyleSheet.create({
|
||||||
tituloPrincipal: {
|
tituloPrincipal: {
|
||||||
fontWeight: "bold"
|
fontWeight: "bold",
|
||||||
}
|
},
|
||||||
});
|
})
|
||||||
|
|
||||||
export function BarraSuperior() {
|
export function BarraSuperior() {
|
||||||
return <header>
|
return (
|
||||||
<span className={css(
|
<header>
|
||||||
estilosGlobales.contenedor,
|
<span className={css(
|
||||||
estilosGlobales.inlineBlock,
|
estilosGlobales.contenedor,
|
||||||
estilos.tituloPrincipal
|
estilosGlobales.inlineBlock,
|
||||||
)}>
|
estilos.tituloPrincipal,
|
||||||
Horarios Unsa
|
)}
|
||||||
</span>
|
>
|
||||||
<a href="https://github.com/Araozu/horarios-unsa-2/" target="_blank" title={"Ver codigo fuente en GitHub"}
|
Horarios Unsa
|
||||||
className={css(
|
</span>
|
||||||
estilosGlobales.contenedor,
|
<a href="https://github.com/Araozu/horarios-unsa-2/" target="_blank" title={"Ver codigo fuente en GitHub"}
|
||||||
estilosGlobales.inlineBlock,
|
className={css(
|
||||||
estilosGlobales.contenedorCursor
|
estilosGlobales.contenedor,
|
||||||
)}>
|
estilosGlobales.inlineBlock,
|
||||||
GitHub
|
estilosGlobales.contenedorCursor,
|
||||||
<i class="ph-arrow-up-right"/>
|
)}
|
||||||
</a>
|
>
|
||||||
<CambiadorImg/>
|
GitHub
|
||||||
<span className={css(estilosGlobales.contenedor, estilosGlobales.inlineBlock)}>2021-A</span>
|
<i class="ph-arrow-up-right" />
|
||||||
<span className={css(estilosGlobales.contenedor, estilosGlobales.inlineBlock)}>Ingeniería de Sistemas</span>
|
</a>
|
||||||
</header>;
|
<CambiadorImg />
|
||||||
|
<span className={css(estilosGlobales.contenedor, estilosGlobales.inlineBlock)}>2021-A</span>
|
||||||
|
<span className={css(estilosGlobales.contenedor, estilosGlobales.inlineBlock)}>Ingeniería de Sistemas</span>
|
||||||
|
</header>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
@ -8,16 +8,18 @@ interface BotonMaxMinProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function BotonIcono(props: BotonMaxMinProps) {
|
export function BotonIcono(props: BotonMaxMinProps) {
|
||||||
return <div title={props.titulo}
|
return (
|
||||||
onClick={props.onClick}
|
<div title={props.titulo}
|
||||||
className={css(
|
onClick={props.onClick}
|
||||||
estilosGlobales.contenedor,
|
className={css(
|
||||||
estilosGlobales.inlineBlock,
|
estilosGlobales.contenedor,
|
||||||
estilosGlobales.contenedorCursor,
|
estilosGlobales.inlineBlock,
|
||||||
estilosGlobales.contenedorCursorSoft,
|
estilosGlobales.contenedorCursor,
|
||||||
estilosGlobales.contenedorPhospor
|
estilosGlobales.contenedorCursorSoft,
|
||||||
)}
|
estilosGlobales.contenedorPhospor,
|
||||||
>
|
)}
|
||||||
<i className={css(estilosGlobales.botonPhospor) + " " + props.icono}/>
|
>
|
||||||
</div>
|
<i className={`${css(estilosGlobales.botonPhospor)} ${props.icono}`} />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
@ -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,30 +10,33 @@ 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 <div title={tituloBoton()}
|
return (
|
||||||
onClick={funcionBoton}
|
<div
|
||||||
className={css(
|
title={tituloBoton()}
|
||||||
estilosGlobales.contenedor,
|
onClick={funcionBoton}
|
||||||
estilosGlobales.inlineBlock,
|
className={css(
|
||||||
estilosGlobales.contenedorCursor,
|
estilosGlobales.contenedor,
|
||||||
estilosGlobales.contenedorCursorSoft,
|
estilosGlobales.inlineBlock,
|
||||||
estilosGlobales.contenedorPhospor
|
estilosGlobales.contenedorCursor,
|
||||||
)}
|
estilosGlobales.contenedorCursorSoft,
|
||||||
>
|
estilosGlobales.contenedorPhospor,
|
||||||
<i className={css(estilosGlobales.botonPhospor) + " " + iconoBoton()}/>
|
)}
|
||||||
</div>
|
>
|
||||||
|
<i className={`${css(estilosGlobales.botonPhospor)} ${iconoBoton()}`} />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
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 "./MiHorario"
|
||||||
import { Horarios } from "./Horarios";
|
import { Horarios } from "./Horarios"
|
||||||
import {
|
import {
|
||||||
Anios,
|
Anios,
|
||||||
Cursos,
|
Cursos,
|
||||||
@ -10,126 +10,131 @@ import {
|
|||||||
DatosHorario,
|
DatosHorario,
|
||||||
DatosHorarioRaw,
|
DatosHorarioRaw,
|
||||||
DatosGrupo,
|
DatosGrupo,
|
||||||
ListaCursosUsuario
|
ListaCursosUsuario,
|
||||||
} from "../types/DatosHorario";
|
} from "../types/DatosHorario"
|
||||||
import { estilosGlobales } from "../Estilos";
|
import { estilosGlobales } from "../Estilos"
|
||||||
import { batch, createEffect, createMemo, createSignal, createState, Show } from "solid-js";
|
import { batch, createEffect, createMemo, createSignal, createState, Show } from "solid-js"
|
||||||
import { useListaCursos } from "./useListaCursos";
|
import { useListaCursos } from "./useListaCursos"
|
||||||
|
|
||||||
const datosPromise = (async () => {
|
const datosPromise = (async() => {
|
||||||
const file = await fetch("/horarios/2020_2_fps_ingenieriadesistemas.yaml");
|
const file = await fetch("/horarios/2020_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
|
||||||
|
|
||||||
// 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] = {
|
||||||
...curso,
|
...curso,
|
||||||
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";
|
||||||
|
|
||||||
const {
|
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] = createSignal<EstadoLayout>(
|
const [estadoLayout, setEstadoLayout] = (
|
||||||
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 = "4rem auto";
|
templateColumns = "4rem auto"
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
case "MaxPersonal": {
|
case "MaxPersonal": {
|
||||||
templateColumns = "auto 4rem";
|
templateColumns = "auto 4rem"
|
||||||
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 <div className={css(e().contenedor)}>
|
return (
|
||||||
<div>
|
<div className={css(e().contenedor)}>
|
||||||
<MiHorario estadoLayout={estadoLayout()}
|
<div>
|
||||||
setEstadoLayout={setEstadoLayout}
|
<MiHorario
|
||||||
cursosUsuario={cursosUsuario}
|
estadoLayout={estadoLayout()}
|
||||||
fnAgregarCurso={agregarCursoUsuario}
|
setEstadoLayout={setEstadoLayout}
|
||||||
setCursosUsuarios={setCursosUsuarios}
|
cursosUsuario={cursosUsuario}
|
||||||
/>
|
fnAgregarCurso={agregarCursoUsuario}
|
||||||
</div>
|
setCursosUsuarios={setCursosUsuarios}
|
||||||
<div>
|
|
||||||
<Show when={datosCargados()}>
|
|
||||||
<Horarios data={datos()!!}
|
|
||||||
estadoLayout={estadoLayout()}
|
|
||||||
setEstadoLayout={setEstadoLayout}
|
|
||||||
fnAgregarCurso={(c) => agregarCursoUsuario(JSON.parse(JSON.stringify(c)))}
|
|
||||||
listaCursosUsuario={cursosUsuario}
|
|
||||||
setCursosUsuarios={setCursosUsuarios}
|
|
||||||
/>
|
/>
|
||||||
</Show>
|
</div>
|
||||||
|
<div>
|
||||||
|
<Show when={datosCargados()}>
|
||||||
|
<Horarios
|
||||||
|
data={datos()!}
|
||||||
|
estadoLayout={estadoLayout()}
|
||||||
|
setEstadoLayout={setEstadoLayout}
|
||||||
|
fnAgregarCurso={(c) => agregarCursoUsuario(JSON.parse(JSON.stringify(c)))}
|
||||||
|
listaCursosUsuario={cursosUsuario}
|
||||||
|
setCursosUsuarios={setCursosUsuarios}
|
||||||
|
/>
|
||||||
|
</Show>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>;
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,32 +1,32 @@
|
|||||||
import { Cursos, CursoRaw, DatosGrupo, ListaCursosUsuario, Curso } from "../types/DatosHorario";
|
import { Cursos, CursoRaw, DatosGrupo, ListaCursosUsuario, Curso } from "../types/DatosHorario"
|
||||||
import { createEffect, createMemo, For, SetStateFunction } from "solid-js";
|
import { createEffect, createMemo, For, SetStateFunction } from "solid-js"
|
||||||
import { StyleSheet, css } from "aphrodite";
|
import { StyleSheet, css } from "aphrodite"
|
||||||
import { estilosGlobales } from "../Estilos";
|
import { estilosGlobales } from "../Estilos"
|
||||||
|
|
||||||
const e = StyleSheet.create({
|
const e = StyleSheet.create({
|
||||||
inline: {
|
inline: {
|
||||||
display: "inline-block"
|
display: "inline-block",
|
||||||
},
|
},
|
||||||
lineaTexto: {
|
lineaTexto: {
|
||||||
marginBottom: "0.5rem"
|
marginBottom: "0.5rem",
|
||||||
},
|
},
|
||||||
tablaGrupos: {
|
tablaGrupos: {
|
||||||
whiteSpace: "pre",
|
whiteSpace: "pre",
|
||||||
borderCollapse: "collapse",
|
borderCollapse: "collapse",
|
||||||
borderSpacing: 0
|
borderSpacing: 0,
|
||||||
},
|
},
|
||||||
contenedorCurso: {
|
contenedorCurso: {
|
||||||
display: "inline-block",
|
display: "inline-block",
|
||||||
verticalAlign: "top"
|
verticalAlign: "top",
|
||||||
},
|
},
|
||||||
cursoOculto: {
|
cursoOculto: {
|
||||||
display: "none"
|
display: "none",
|
||||||
},
|
},
|
||||||
botonTexto: {
|
botonTexto: {
|
||||||
padding: "0.25rem 0.35rem",
|
padding: "0.25rem 0.35rem",
|
||||||
borderRadius: "5px"
|
borderRadius: "5px",
|
||||||
}
|
},
|
||||||
});
|
})
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
dataAnio: Cursos,
|
dataAnio: Cursos,
|
||||||
@ -50,23 +50,30 @@ 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 <span className={css(e.botonTexto, estilosGlobales.contenedorCursor, estilosGlobales.contenedorCursorSoft)}
|
return (
|
||||||
style={props.esLab ? {"font-style": "italic"} : {"font-weight": "bold"}}
|
<span className={css(e.botonTexto, estilosGlobales.contenedorCursor, estilosGlobales.contenedorCursorSoft)}
|
||||||
onMouseEnter={() => props.setIdHover(id)}
|
style={props.esLab ? {"font-style": "italic"} : {"font-weight": "bold"}}
|
||||||
onMouseLeave={() => props.setIdHover("")}
|
onMouseEnter={() => props.setIdHover(id)}
|
||||||
onClick={props.onClick}
|
onMouseLeave={() => props.setIdHover("")}
|
||||||
>
|
onClick={props.onClick}
|
||||||
{props.esLab ? "L" : ""}{props.nombre}
|
>
|
||||||
</span>
|
{props.esLab ? "L" : ""}{props.nombre}
|
||||||
|
</span>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const agruparProfesores = (datos: { [k: string]: DatosGrupo }, indiceCurso: number, esLab: boolean, setCursosUsuarios: FnSetCursosUsuarios) => {
|
const agruparProfesores = (
|
||||||
const profesores: { [k: string]: [string, () => void][] } = {};
|
datos: { [k: string]: DatosGrupo },
|
||||||
|
indiceCurso: number,
|
||||||
|
esLab: boolean,
|
||||||
|
setCursosUsuarios: FnSetCursosUsuarios,
|
||||||
|
) => {
|
||||||
|
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,
|
||||||
@ -78,133 +85,136 @@ const agruparProfesores = (datos: { [k: string]: DatosGrupo }, indiceCurso: numb
|
|||||||
/// @ts-ignore
|
/// @ts-ignore
|
||||||
grupo,
|
grupo,
|
||||||
"seleccionado",
|
"seleccionado",
|
||||||
x => !x
|
(x) => !x,
|
||||||
);
|
)
|
||||||
}
|
},
|
||||||
]);
|
])
|
||||||
}
|
}
|
||||||
return profesores;
|
return profesores
|
||||||
};
|
}
|
||||||
|
|
||||||
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 claseCursoNoAgregado = css(
|
const claseCursoNoAgregado = css(
|
||||||
e.contenedorCurso,
|
e.contenedorCurso,
|
||||||
estilosGlobales.contenedor
|
estilosGlobales.contenedor,
|
||||||
);
|
)
|
||||||
|
|
||||||
const claseCursoAgregado = css(
|
const claseCursoAgregado = css(
|
||||||
e.contenedorCurso,
|
e.contenedorCurso,
|
||||||
estilosGlobales.contenedor,
|
estilosGlobales.contenedor,
|
||||||
!props.esCursoMiHorario && estilosGlobales.contenedorCursorActivo,
|
!props.esCursoMiHorario && estilosGlobales.contenedorCursorActivo,
|
||||||
);
|
)
|
||||||
|
|
||||||
const claseCursoOculto = css(e.cursoOculto);
|
const claseCursoOculto = css(e.cursoOculto)
|
||||||
|
|
||||||
return <>
|
return (
|
||||||
<For each={Object.entries(props.dataAnio)}>
|
<>
|
||||||
{([indiceCurso, datosCurso]) => {
|
<For each={Object.entries(props.dataAnio)}>
|
||||||
|
{([indiceCurso, datosCurso]) => {
|
||||||
|
|
||||||
const idCurso = `${anio()}_${datosCurso.abreviado}`;
|
const idCurso = `${anio()}_${datosCurso.abreviado}`
|
||||||
|
|
||||||
const cursoAgregadoMemo = createMemo(
|
const cursoAgregadoMemo = createMemo(
|
||||||
() => props.listaCursosUsuario.cursos.find(x => {
|
() => props.listaCursosUsuario.cursos.find((x) => x.nombre === datosCurso.nombre && !x.oculto) !== undefined,
|
||||||
return x.nombre === datosCurso.nombre && !x.oculto
|
undefined,
|
||||||
}) !== undefined,
|
(x, y) => x === y,
|
||||||
undefined,
|
)
|
||||||
(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,
|
||||||
parseInt(indiceCurso),
|
Number(indiceCurso),
|
||||||
false,
|
false,
|
||||||
props.setCursosUsuarios
|
props.setCursosUsuarios,
|
||||||
));
|
))
|
||||||
const profesoresLab = createMemo(() => agruparProfesores(
|
const profesoresLab = createMemo(() => agruparProfesores(
|
||||||
datosCurso.Laboratorio ?? {},
|
datosCurso.Laboratorio ?? {},
|
||||||
parseInt(indiceCurso),
|
Number(indiceCurso),
|
||||||
true,
|
true,
|
||||||
props.setCursosUsuarios
|
props.setCursosUsuarios,
|
||||||
));
|
))
|
||||||
|
|
||||||
return <div className={claseMemo()}>
|
return (
|
||||||
<div
|
<div className={claseMemo()}>
|
||||||
className={css(e.inline, e.lineaTexto, e.botonTexto, estilosGlobales.contenedorCursor, estilosGlobales.contenedorCursorSoft)}
|
<div
|
||||||
onMouseEnter={() => props.setIdHover(idCurso)}
|
className={css(e.inline, e.lineaTexto, e.botonTexto, estilosGlobales.contenedorCursor, estilosGlobales.contenedorCursorSoft)}
|
||||||
onMouseLeave={() => props.setIdHover("")}
|
onMouseEnter={() => props.setIdHover(idCurso)}
|
||||||
>
|
onMouseLeave={() => props.setIdHover("")}
|
||||||
{datosCurso.abreviado} - {datosCurso.nombre}
|
>
|
||||||
</div>
|
{datosCurso.abreviado} - {datosCurso.nombre}
|
||||||
<table>
|
</div>
|
||||||
<tbody>
|
<table>
|
||||||
<tr>
|
<tbody>
|
||||||
<For each={Object.entries(profesoresTeoria())}>
|
<tr>
|
||||||
{([profesor, grupos]) => {
|
<For each={Object.entries(profesoresTeoria())}>
|
||||||
return <td style={{"padding-bottom": "0.5rem", "padding-right": "0.75rem"}}>
|
{([profesor, grupos]) => (
|
||||||
<span>
|
<td style={{"padding-bottom": "0.5rem", "padding-right": "0.75rem"}}>
|
||||||
{profesor}
|
<span>
|
||||||
</span>
|
{profesor}
|
||||||
<For each={grupos}>
|
</span>
|
||||||
{([x, fnOnClick]) =>
|
<For each={grupos}>
|
||||||
<IndicadorGrupo nombre={x}
|
{([x, fnOnClick]) => (
|
||||||
|
<IndicadorGrupo nombre={x}
|
||||||
esLab={false}
|
esLab={false}
|
||||||
idParcial={idCurso}
|
idParcial={idCurso}
|
||||||
setIdHover={props.setIdHover}
|
setIdHover={props.setIdHover}
|
||||||
onClick={fnOnClick}
|
onClick={fnOnClick}
|
||||||
/>
|
/>
|
||||||
}
|
)
|
||||||
|
}
|
||||||
|
</For>
|
||||||
|
</td>
|
||||||
|
)}
|
||||||
</For>
|
</For>
|
||||||
</td>
|
</tr>
|
||||||
}}
|
<tr>
|
||||||
</For>
|
<For each={Object.entries(profesoresLab())}>
|
||||||
</tr>
|
{([profesor, grupos]) => (
|
||||||
<tr>
|
<td style={{"padding-bottom": "0.5rem", "padding-right": "0.75rem"}}>
|
||||||
<For each={Object.entries(profesoresLab())}>
|
<span>
|
||||||
{([profesor, grupos]) => {
|
{profesor}
|
||||||
return <td style={{"padding-bottom": "0.5rem", "padding-right": "0.75rem"}}>
|
</span>
|
||||||
<span>
|
<For each={grupos}>
|
||||||
{profesor}
|
{([x, fnOnClick]) => (
|
||||||
</span>
|
<IndicadorGrupo nombre={x}
|
||||||
<For each={grupos}>
|
esLab
|
||||||
{([x, fnOnClick]) =>
|
|
||||||
<IndicadorGrupo nombre={x}
|
|
||||||
esLab={true}
|
|
||||||
idParcial={idCurso}
|
idParcial={idCurso}
|
||||||
setIdHover={props.setIdHover}
|
setIdHover={props.setIdHover}
|
||||||
onClick={fnOnClick}
|
onClick={fnOnClick}
|
||||||
/>
|
/>
|
||||||
}
|
)
|
||||||
|
}
|
||||||
|
</For>
|
||||||
|
</td>
|
||||||
|
)}
|
||||||
</For>
|
</For>
|
||||||
</td>
|
</tr>
|
||||||
}}
|
</tbody>
|
||||||
</For>
|
</table>
|
||||||
</tr>
|
<span
|
||||||
</tbody>
|
className={css(e.botonTexto, estilosGlobales.contenedorCursor, estilosGlobales.contenedorCursorSoft)}
|
||||||
</table>
|
onClick={() => props.fnAgregarCurso(datosCurso)}
|
||||||
<span
|
>
|
||||||
className={css(e.botonTexto, estilosGlobales.contenedorCursor, estilosGlobales.contenedorCursorSoft)}
|
{tituloMemo}
|
||||||
onClick={() => props.fnAgregarCurso(datosCurso)}
|
</span>
|
||||||
>
|
</div>
|
||||||
{tituloMemo}
|
)
|
||||||
</span>
|
}}
|
||||||
</div>
|
</For>
|
||||||
}}
|
</>
|
||||||
</For>
|
)
|
||||||
</>;
|
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import { Curso, Cursos, DatosHorario, ListaCursosUsuario } from "../types/DatosHorario";
|
import { Curso, Cursos, DatosHorario, ListaCursosUsuario } from "../types/DatosHorario"
|
||||||
import { batch, createMemo, createSignal, For, Match, SetStateFunction, Switch, untrack } from "solid-js";
|
import { batch, createMemo, createSignal, For, Match, SetStateFunction, Switch, untrack } from "solid-js"
|
||||||
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"
|
||||||
|
|
||||||
interface HorariosProps {
|
interface HorariosProps {
|
||||||
data: DatosHorario,
|
data: DatosHorario,
|
||||||
@ -20,107 +20,116 @@ interface HorariosProps {
|
|||||||
const {
|
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")
|
||||||
// ID que indica cuales celdas resaltar.
|
// ID que indica cuales celdas resaltar.
|
||||||
const [idHover, setIdHover] = createSignal("");
|
const [idHover, setIdHover] = createSignal("")
|
||||||
|
|
||||||
const elAnios = <For each={Object.entries(props.data.años)}>
|
const elAnios = (
|
||||||
{([nombre]) => {
|
<For each={Object.entries(props.data.años)}>
|
||||||
const clases = createMemo(() => {
|
{([nombre]) => {
|
||||||
const vAnio = anioActual();
|
const clases = createMemo(() => {
|
||||||
return css(
|
const vAnio = anioActual()
|
||||||
estilosGlobales.contenedor,
|
return css(
|
||||||
estilosGlobales.inlineBlock,
|
estilosGlobales.contenedor,
|
||||||
estilosGlobales.contenedorCursor,
|
estilosGlobales.inlineBlock,
|
||||||
estilosGlobales.contenedorCursorSoft,
|
estilosGlobales.contenedorCursor,
|
||||||
nombre === vAnio && estilosGlobales.contenedorCursorActivo
|
estilosGlobales.contenedorCursorSoft,
|
||||||
);
|
nombre === vAnio && estilosGlobales.contenedorCursorActivo,
|
||||||
});
|
)
|
||||||
|
})
|
||||||
|
|
||||||
return <div className={clases()} title={"Cambiar a " + nombre} onClick={() => setAnioActual(nombre)}>
|
return (
|
||||||
{nombre}
|
<div className={clases()} title={`Cambiar a ${nombre}`} onClick={() => setAnioActual(nombre)}>
|
||||||
</div>
|
{nombre}
|
||||||
}}
|
</div>
|
||||||
</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++;
|
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 <div>
|
return (
|
||||||
<Switch>
|
<div>
|
||||||
<Match when={props.estadoLayout === "Normal" || props.estadoLayout === "MaxHorarios"}>
|
<Switch>
|
||||||
<div>
|
<Match when={props.estadoLayout === "Normal" || props.estadoLayout === "MaxHorarios"}>
|
||||||
<div className={css(
|
<div>
|
||||||
estilosGlobales.inlineBlock,
|
<div className={css(
|
||||||
estilosGlobales.contenedor
|
estilosGlobales.inlineBlock,
|
||||||
)}>
|
estilosGlobales.contenedor,
|
||||||
Horarios disponibles
|
)}
|
||||||
|
>
|
||||||
|
Horarios disponibles
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
{elAnios}
|
||||||
{elAnios}
|
|
|
||||||
|
|
<BotonMaxMin
|
||||||
<BotonMaxMin
|
fnMaximizar={fnMaximizar}
|
||||||
fnMaximizar={fnMaximizar}
|
fnMinimizar={fnMinimizar}
|
||||||
fnMinimizar={fnMinimizar}
|
estadoActualLayout={estadoActualLayout}
|
||||||
estadoActualLayout={estadoActualLayout}
|
estadoLayoutMax={"MaxHorarios"}
|
||||||
estadoLayoutMax={"MaxHorarios"}
|
|
||||||
/>
|
|
||||||
<br/>
|
|
||||||
<div className={css(estilosGlobales.contenedor)}>
|
|
||||||
<Tabla data={dataTabla()}
|
|
||||||
version={props.data.version}
|
|
||||||
anio={anioActual()}
|
|
||||||
idHover={idHover}
|
|
||||||
setIdHover={setIdHover}
|
|
||||||
setCursosUsuarios={setListaCursos}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
<br />
|
||||||
<div>
|
<div className={css(estilosGlobales.contenedor)}>
|
||||||
<CursosElem dataAnio={dataTabla()}
|
<Tabla
|
||||||
anioActual={anioActual}
|
data={dataTabla()}
|
||||||
fnAgregarCurso={props.fnAgregarCurso}
|
version={props.data.version}
|
||||||
listaCursosUsuario={props.listaCursosUsuario}
|
anio={anioActual()}
|
||||||
idHover={idHover}
|
idHover={idHover}
|
||||||
setIdHover={setIdHover}
|
setIdHover={setIdHover}
|
||||||
esCursoMiHorario={false}
|
setCursosUsuarios={setListaCursos}
|
||||||
setCursosUsuarios={setListaCursos}
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<CursosElem
|
||||||
|
dataAnio={dataTabla()}
|
||||||
|
anioActual={anioActual}
|
||||||
|
fnAgregarCurso={props.fnAgregarCurso}
|
||||||
|
listaCursosUsuario={props.listaCursosUsuario}
|
||||||
|
idHover={idHover}
|
||||||
|
setIdHover={setIdHover}
|
||||||
|
esCursoMiHorario={false}
|
||||||
|
setCursosUsuarios={setListaCursos}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Match>
|
||||||
|
<Match when={props.estadoLayout === "MaxPersonal"}>
|
||||||
|
<BotonMaxMin
|
||||||
|
fnMaximizar={fnMaximizar}
|
||||||
|
fnMinimizar={fnMinimizar}
|
||||||
|
estadoActualLayout={estadoActualLayout}
|
||||||
|
estadoLayoutMax={"MaxHorarios"}
|
||||||
/>
|
/>
|
||||||
</div>
|
</Match>
|
||||||
</Match>
|
</Switch>
|
||||||
<Match when={props.estadoLayout === "MaxPersonal"}>
|
|
||||||
<BotonMaxMin
|
|
||||||
fnMaximizar={fnMaximizar}
|
|
||||||
fnMinimizar={fnMinimizar}
|
|
||||||
estadoActualLayout={estadoActualLayout}
|
|
||||||
estadoLayoutMax={"MaxHorarios"}
|
|
||||||
/>
|
|
||||||
</Match>
|
|
||||||
</Switch>
|
|
||||||
|
|
||||||
</div>;
|
</div>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
@ -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 { mostrarDescansos } from "../Store"
|
||||||
import { EstadoLayout } from "./ContenedorHorarios";
|
import { EstadoLayout } from "./ContenedorHorarios"
|
||||||
import { Switch, Match, For, createMemo, createSignal, SetStateFunction } from "solid-js";
|
import { Switch, Match, For, createMemo, createSignal, 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"
|
||||||
|
|
||||||
interface MiHorarioProps {
|
interface MiHorarioProps {
|
||||||
estadoLayout: EstadoLayout,
|
estadoLayout: EstadoLayout,
|
||||||
@ -25,111 +25,117 @@ const e = StyleSheet.create({
|
|||||||
"::before": {
|
"::before": {
|
||||||
fontSize: "1rem",
|
fontSize: "1rem",
|
||||||
// transform: "translateY(0.2rem)",
|
// transform: "translateY(0.2rem)",
|
||||||
textDecoration: "none"
|
textDecoration: "none",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
});
|
})
|
||||||
|
|
||||||
export function MiHorario(props: MiHorarioProps) {
|
export function MiHorario(props: MiHorarioProps) {
|
||||||
const [idHover, setIdHover] = createSignal("");
|
const [idHover, setIdHover] = createSignal("")
|
||||||
|
|
||||||
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.
|
||||||
Al hacer click en un horario de la barra superior, llevarlo al inicio de la lista.
|
Al hacer click en un horario de la barra superior, llevarlo al inicio de la lista.
|
||||||
*/
|
*/
|
||||||
return <div>
|
return (
|
||||||
<Switch>
|
<div>
|
||||||
<Match when={props.estadoLayout === "Normal" || props.estadoLayout === "MaxPersonal"}>
|
<Switch>
|
||||||
|
<Match when={props.estadoLayout === "Normal" || props.estadoLayout === "MaxPersonal"}>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<div className={css(
|
<div className={css(
|
||||||
estilosGlobales.inlineBlock,
|
estilosGlobales.inlineBlock,
|
||||||
estilosGlobales.contenedor
|
estilosGlobales.contenedor,
|
||||||
)}>
|
)}
|
||||||
|
>
|
||||||
Mi horario
|
Mi horario
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<div className={css(
|
<div className={css(
|
||||||
estilosGlobales.inlineBlock,
|
estilosGlobales.inlineBlock,
|
||||||
estilosGlobales.contenedor
|
estilosGlobales.contenedor,
|
||||||
)}>
|
)}
|
||||||
Mi horario
|
>
|
||||||
|
Mi horario
|
||||||
|
</div>
|
||||||
|
|
|
||||||
|
<BotonIcono
|
||||||
|
titulo={"Nuevo horario en blanco"}
|
||||||
|
icono={"ph-plus"}
|
||||||
|
onClick={() => {}}
|
||||||
|
/>
|
||||||
|
<BotonIcono
|
||||||
|
titulo={"Reiniciar horario"}
|
||||||
|
icono={"ph-arrow-counter-clockwise"}
|
||||||
|
onClick={() => {}}
|
||||||
|
/>
|
||||||
|
<BotonIcono
|
||||||
|
titulo={"Duplicar horario"}
|
||||||
|
icono={"ph-copy"}
|
||||||
|
onClick={() => {}}
|
||||||
|
/>
|
||||||
|
<BotonIcono titulo={"Eliminar horario"}
|
||||||
|
icono={"ph-trash"}
|
||||||
|
onClick={() => {}}
|
||||||
|
/>
|
||||||
|
|
|
||||||
|
<BotonMaxMin
|
||||||
|
fnMaximizar={fnMaximizar}
|
||||||
|
fnMinimizar={fnMinimizar}
|
||||||
|
estadoActualLayout={estadoActualLayout}
|
||||||
|
estadoLayoutMax={"MaxPersonal"}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
<BotonIcono titulo={"Nuevo horario en blanco"}
|
<div className={css(
|
||||||
icono={"ph-plus"}
|
e.horario,
|
||||||
onClick={() => {
|
estilosGlobales.contenedor,
|
||||||
}}
|
)}
|
||||||
|
>
|
||||||
|
<Tabla
|
||||||
|
data={datosMiHorario()}
|
||||||
|
anio={"Mi horario"}
|
||||||
|
version={1}
|
||||||
|
idHover={idHover}
|
||||||
|
setIdHover={setIdHover}
|
||||||
|
setCursosUsuarios={props.setCursosUsuarios}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<CursosElem
|
||||||
|
anioActual={() => "Mi horario"}
|
||||||
|
dataAnio={datosMiHorario()}
|
||||||
|
fnAgregarCurso={props.fnAgregarCurso}
|
||||||
|
listaCursosUsuario={props.cursosUsuario}
|
||||||
|
idHover={idHover}
|
||||||
|
setIdHover={setIdHover}
|
||||||
|
esCursoMiHorario
|
||||||
|
setCursosUsuarios={props.setCursosUsuarios}
|
||||||
/>
|
/>
|
||||||
<BotonIcono titulo={"Reiniciar horario"}
|
</Match>
|
||||||
icono={"ph-arrow-counter-clockwise"}
|
<Match when={props.estadoLayout === "MaxHorarios"}>
|
||||||
onClick={() => {
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<BotonIcono titulo={"Duplicar horario"}
|
|
||||||
icono={"ph-copy"}
|
|
||||||
onClick={() => {
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<BotonIcono titulo={"Eliminar horario"}
|
|
||||||
icono={"ph-trash"}
|
|
||||||
onClick={() => {
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
|
||||||
<BotonMaxMin
|
<BotonMaxMin
|
||||||
fnMaximizar={fnMaximizar}
|
fnMaximizar={fnMaximizar}
|
||||||
fnMinimizar={fnMinimizar}
|
fnMinimizar={fnMinimizar}
|
||||||
estadoActualLayout={estadoActualLayout}
|
estadoActualLayout={estadoActualLayout}
|
||||||
estadoLayoutMax={"MaxPersonal"}
|
estadoLayoutMax={"MaxPersonal"}
|
||||||
/>
|
/>
|
||||||
</div>
|
</Match>
|
||||||
|
</Switch>
|
||||||
<div className={css(
|
</div>
|
||||||
e.horario,
|
)
|
||||||
estilosGlobales.contenedor
|
|
||||||
)}>
|
|
||||||
<Tabla data={datosMiHorario()}
|
|
||||||
anio={"Mi horario"}
|
|
||||||
version={1}
|
|
||||||
idHover={idHover}
|
|
||||||
setIdHover={setIdHover}
|
|
||||||
setCursosUsuarios={props.setCursosUsuarios}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<CursosElem anioActual={() => "Mi horario"}
|
|
||||||
dataAnio={datosMiHorario()}
|
|
||||||
fnAgregarCurso={props.fnAgregarCurso}
|
|
||||||
listaCursosUsuario={props.cursosUsuario}
|
|
||||||
idHover={idHover}
|
|
||||||
setIdHover={setIdHover}
|
|
||||||
esCursoMiHorario={true}
|
|
||||||
setCursosUsuarios={props.setCursosUsuarios}
|
|
||||||
/>
|
|
||||||
</Match>
|
|
||||||
<Match when={props.estadoLayout === "MaxHorarios"}>
|
|
||||||
<BotonMaxMin
|
|
||||||
fnMaximizar={fnMaximizar}
|
|
||||||
fnMinimizar={fnMinimizar}
|
|
||||||
estadoActualLayout={estadoActualLayout}
|
|
||||||
estadoLayoutMax={"MaxPersonal"}
|
|
||||||
/>
|
|
||||||
</Match>
|
|
||||||
</Switch>
|
|
||||||
</div>;
|
|
||||||
}
|
}
|
||||||
|
@ -1,31 +1,30 @@
|
|||||||
import { StyleSheet, css } from "aphrodite";
|
import { StyleSheet, css } from "aphrodite"
|
||||||
import { createEffect, createMemo, createSignal, createState, For, SetStateFunction } from "solid-js";
|
import { createMemo, For, SetStateFunction } from "solid-js"
|
||||||
import { estilosGlobales } from "../Estilos";
|
import { estilosGlobales } from "../Estilos"
|
||||||
import { Cursos, Curso, ListaCursosUsuario } from "../types/DatosHorario";
|
import { Cursos, ListaCursosUsuario, DataProcesada } from "../types/DatosHorario"
|
||||||
import { Dia, dias, horas } from "../Store";
|
import { Dia, dias, horas } from "../Store"
|
||||||
import { DataProcesada } from "../types/DatosHorario";
|
import { FilaTabla } from "./Tabla/FilaTabla"
|
||||||
import { FilaTabla } from "./Tabla/FilaTabla";
|
|
||||||
|
|
||||||
export const coloresBorde = Object.freeze([
|
export const coloresBorde = Object.freeze([
|
||||||
"rgba(33,150,243,1)",
|
"rgba(33,150,243,1)",
|
||||||
"rgba(255,214,0 ,1)",
|
"rgba(255,214,0 ,1)",
|
||||||
"rgba(236,64,122 ,1)",
|
"rgba(236,64,122 ,1)",
|
||||||
"rgba(29,233,182 ,1)",
|
"rgba(29,233,182 ,1)",
|
||||||
"rgba(244,67,54,1)"
|
"rgba(244,67,54,1)",
|
||||||
]);
|
])
|
||||||
|
|
||||||
export const diaANum = (d: Dia) => {
|
export const diaANum = (d: Dia) => {
|
||||||
switch (d) {
|
switch (d) {
|
||||||
case "Lunes":
|
case "Lunes":
|
||||||
return 0;
|
return 0
|
||||||
case "Martes":
|
case "Martes":
|
||||||
return 1;
|
return 1
|
||||||
case "Miercoles":
|
case "Miercoles":
|
||||||
return 2;
|
return 2
|
||||||
case "Jueves":
|
case "Jueves":
|
||||||
return 3;
|
return 3
|
||||||
case "Viernes":
|
case "Viernes":
|
||||||
return 4;
|
return 4
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,7 +39,7 @@ const e = StyleSheet.create({
|
|||||||
minHeight: "1.5rem",
|
minHeight: "1.5rem",
|
||||||
":hover": {
|
":hover": {
|
||||||
// backgroundColor: "rgba(200, 200, 200, 0.25)"
|
// backgroundColor: "rgba(200, 200, 200, 0.25)"
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
filaBorde: {
|
filaBorde: {
|
||||||
position: "absolute",
|
position: "absolute",
|
||||||
@ -48,65 +47,65 @@ const e = StyleSheet.create({
|
|||||||
height: "1px",
|
height: "1px",
|
||||||
width: "100%",
|
width: "100%",
|
||||||
backgroundColor: "rgba(200, 200, 200, 0.25)",
|
backgroundColor: "rgba(200, 200, 200, 0.25)",
|
||||||
zIndex: 1
|
zIndex: 1,
|
||||||
},
|
},
|
||||||
celdaHora: {
|
celdaHora: {
|
||||||
textAlign: "center",
|
textAlign: "center",
|
||||||
width: "4rem",
|
width: "4rem",
|
||||||
padding: "0.25rem 0",
|
padding: "0.25rem 0",
|
||||||
position: "absolute",
|
position: "absolute",
|
||||||
top: "-0.75rem"
|
top: "-0.75rem",
|
||||||
},
|
},
|
||||||
celdaComun: {
|
celdaComun: {
|
||||||
width: "20%",
|
width: "20%",
|
||||||
textAlign: "center",
|
textAlign: "center",
|
||||||
padding: "0 0.5rem",
|
padding: "0 0.5rem",
|
||||||
boxSizing: "border-box"
|
boxSizing: "border-box",
|
||||||
},
|
},
|
||||||
celdaDia: {
|
celdaDia: {
|
||||||
padding: "0.3rem 0"
|
padding: "0.3rem 0",
|
||||||
},
|
},
|
||||||
celdaCurso: {
|
celdaCurso: {
|
||||||
display: "inline-block",
|
display: "inline-block",
|
||||||
padding: "0.25rem 0.35rem",
|
padding: "0.25rem 0.35rem",
|
||||||
cursor: "pointer",
|
cursor: "pointer",
|
||||||
borderRadius: "5px",
|
borderRadius: "5px",
|
||||||
transition: "background-color 100ms"
|
transition: "background-color 100ms",
|
||||||
},
|
},
|
||||||
celdaCursoActiva: {
|
celdaCursoActiva: {
|
||||||
backgroundColor: "rgba(200, 200, 200, 0.25)"
|
backgroundColor: "rgba(200, 200, 200, 0.25)",
|
||||||
},
|
},
|
||||||
celdaCursoTeoria: {
|
celdaCursoTeoria: {
|
||||||
fontWeight: "bold"
|
fontWeight: "bold",
|
||||||
}
|
},
|
||||||
});
|
})
|
||||||
|
|
||||||
type FnSetCursosUsuarios = SetStateFunction<ListaCursosUsuario>;
|
type FnSetCursosUsuarios = SetStateFunction<ListaCursosUsuario>;
|
||||||
|
|
||||||
const procesarAnio = (data: Cursos, anio: string, version: number, setCursosUsuarios: FnSetCursosUsuarios) => {
|
const procesarAnio = (data: Cursos, anio: string, version: number, setCursosUsuarios: FnSetCursosUsuarios) => {
|
||||||
const obj: DataProcesada = {};
|
const obj: DataProcesada = {}
|
||||||
|
|
||||||
for (const [indiceCurso, curso] of Object.entries(data)) {
|
for (const [indiceCurso, curso] of Object.entries(data)) {
|
||||||
if (curso.oculto) continue;
|
if (curso.oculto) continue
|
||||||
|
|
||||||
const nombreAbreviado = curso.abreviado;
|
const nombreAbreviado = curso.abreviado
|
||||||
|
|
||||||
for (const [grupoStr, grupo] of Object.entries(curso.Teoria)) {
|
for (const [grupoStr, grupo] of Object.entries(curso.Teoria)) {
|
||||||
for (const hora of grupo.Horas) {
|
for (const hora of grupo.Horas) {
|
||||||
const dia = hora.substring(0, 2);
|
const dia = hora.substring(0, 2)
|
||||||
const horas = hora.substring(2, 4);
|
const horas = hora.substring(2, 4)
|
||||||
const minutos = hora.substr(4);
|
const minutos = hora.substr(4)
|
||||||
|
|
||||||
const horaCompleta = horas + ":" + minutos;
|
const horaCompleta = `${horas}:${minutos}`
|
||||||
|
|
||||||
const id = `${version}_${anio}_${nombreAbreviado}_T_${grupoStr}`;
|
const id = `${version}_${anio}_${nombreAbreviado}_T_${grupoStr}`
|
||||||
|
|
||||||
if (!(horaCompleta in obj)) {
|
if (!(horaCompleta in obj)) {
|
||||||
obj[horaCompleta] = {};
|
obj[horaCompleta] = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(dia in obj[horaCompleta])) {
|
if (!(dia in obj[horaCompleta])) {
|
||||||
obj[horaCompleta][dia] = [];
|
obj[horaCompleta][dia] = []
|
||||||
}
|
}
|
||||||
|
|
||||||
obj[horaCompleta][dia].push({
|
obj[horaCompleta][dia].push({
|
||||||
@ -116,28 +115,28 @@ const procesarAnio = (data: Cursos, anio: string, version: number, setCursosUsua
|
|||||||
datosGrupo: grupo,
|
datosGrupo: grupo,
|
||||||
fnSeleccionar: () => {
|
fnSeleccionar: () => {
|
||||||
/// @ts-ignore
|
/// @ts-ignore
|
||||||
setCursosUsuarios("cursos", indiceCurso, "Teoria", grupoStr, "seleccionado", x => !x);
|
setCursosUsuarios("cursos", indiceCurso, "Teoria", grupoStr, "seleccionado", (x) => !x)
|
||||||
}
|
},
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const [grupoStr, grupo] of Object.entries(curso.Laboratorio ?? {})) {
|
for (const [grupoStr, grupo] of Object.entries(curso.Laboratorio ?? {})) {
|
||||||
for (const hora of grupo.Horas) {
|
for (const hora of grupo.Horas) {
|
||||||
const dia = hora.substring(0, 2);
|
const dia = hora.substring(0, 2)
|
||||||
const horas = hora.substring(2, 4);
|
const horas = hora.substring(2, 4)
|
||||||
const minutos = hora.substr(4);
|
const minutos = hora.substr(4)
|
||||||
|
|
||||||
const horaCompleta = horas + ":" + minutos;
|
const horaCompleta = `${horas}:${minutos}`
|
||||||
|
|
||||||
const id = `${version}_${anio}_${nombreAbreviado}_L_${grupoStr}`;
|
const id = `${version}_${anio}_${nombreAbreviado}_L_${grupoStr}`
|
||||||
|
|
||||||
if (!(horaCompleta in obj)) {
|
if (!(horaCompleta in obj)) {
|
||||||
obj[horaCompleta] = {};
|
obj[horaCompleta] = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(dia in obj[horaCompleta])) {
|
if (!(dia in obj[horaCompleta])) {
|
||||||
obj[horaCompleta][dia] = [];
|
obj[horaCompleta][dia] = []
|
||||||
}
|
}
|
||||||
|
|
||||||
obj[horaCompleta][dia].push({
|
obj[horaCompleta][dia].push({
|
||||||
@ -147,14 +146,14 @@ const procesarAnio = (data: Cursos, anio: string, version: number, setCursosUsua
|
|||||||
datosGrupo: grupo,
|
datosGrupo: grupo,
|
||||||
fnSeleccionar: () => {
|
fnSeleccionar: () => {
|
||||||
/// @ts-ignore
|
/// @ts-ignore
|
||||||
setCursosUsuarios("cursos", indiceCurso, "Laboratorio", grupoStr, "seleccionado", x => !x);
|
setCursosUsuarios("cursos", indiceCurso, "Laboratorio", grupoStr, "seleccionado", (x) => !x)
|
||||||
}
|
},
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return obj;
|
return obj
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@ -167,35 +166,40 @@ interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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 idHover = props.idHover
|
||||||
const setIdHover = props.setIdHover;
|
const setIdHover = props.setIdHover
|
||||||
|
|
||||||
const celdas = createMemo(() => {
|
const celdas = createMemo(() => {
|
||||||
// Hace reaccionar a la reactividad de Solid
|
// Hace reaccionar a la reactividad de Solid
|
||||||
props.data;
|
props.data
|
||||||
return <For each={horas}>
|
return (
|
||||||
{hora => {
|
<For each={horas}>
|
||||||
return <FilaTabla data={data()}
|
{(hora) => (
|
||||||
hora={hora}
|
<FilaTabla
|
||||||
idHover={idHover}
|
data={data()}
|
||||||
setIdHover={setIdHover}
|
hora={hora}
|
||||||
/>
|
idHover={idHover}
|
||||||
}}
|
setIdHover={setIdHover}
|
||||||
</For>
|
/>
|
||||||
});
|
)}
|
||||||
|
|
||||||
return <div>
|
|
||||||
<div className={css(e.fila)}>
|
|
||||||
<For each={dias}>
|
|
||||||
{dia =>
|
|
||||||
<div className={css(e.celdaComun, estilosGlobales.inlineBlock, e.celdaDia)}>
|
|
||||||
{dia}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</For>
|
</For>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div className={css(e.fila)}>
|
||||||
|
<For each={dias}>
|
||||||
|
{(dia) => (
|
||||||
|
<div className={css(e.celdaComun, estilosGlobales.inlineBlock, e.celdaDia)}>
|
||||||
|
{dia}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</For>
|
||||||
|
</div>
|
||||||
|
{celdas()}
|
||||||
</div>
|
</div>
|
||||||
{celdas()}
|
)
|
||||||
</div>
|
|
||||||
}
|
}
|
@ -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, SetStateFunction } from "solid-js";
|
import { For, createSignal, createMemo, createEffect, SetStateFunction } from "solid-js"
|
||||||
import { Dia } from "../../Store";
|
import { Dia } from "../../Store"
|
||||||
import { DatosGrupo, ListaCursosUsuario } from "../../types/DatosHorario";
|
import { DatosGrupo, ListaCursosUsuario } from "../../types/DatosHorario"
|
||||||
|
|
||||||
const e = StyleSheet.create({
|
const e = StyleSheet.create({
|
||||||
celdaComun: {
|
celdaComun: {
|
||||||
@ -10,7 +10,7 @@ const e = StyleSheet.create({
|
|||||||
textAlign: "center",
|
textAlign: "center",
|
||||||
padding: "0 0.7rem",
|
padding: "0 0.7rem",
|
||||||
boxSizing: "border-box",
|
boxSizing: "border-box",
|
||||||
userSelect: "none"
|
userSelect: "none",
|
||||||
},
|
},
|
||||||
celdaCurso: {
|
celdaCurso: {
|
||||||
display: "inline-block",
|
display: "inline-block",
|
||||||
@ -23,39 +23,42 @@ const e = StyleSheet.create({
|
|||||||
// color: "#151515"
|
// color: "#151515"
|
||||||
},
|
},
|
||||||
celdaCursoTeoria: {
|
celdaCursoTeoria: {
|
||||||
fontWeight: "bold"
|
fontWeight: "bold",
|
||||||
},
|
},
|
||||||
celdaCursoLab: {
|
celdaCursoLab: {
|
||||||
fontStyle: "italic"
|
fontStyle: "italic",
|
||||||
}
|
},
|
||||||
});
|
celdaSeleccionada: {
|
||||||
|
textDecoration: "underline",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
const eColores = StyleSheet.create({
|
const eColores = StyleSheet.create({
|
||||||
lunes: {
|
lunes: {
|
||||||
backgroundColor: "rgba(33,150,243,1)"
|
backgroundColor: "rgba(33,150,243,1)",
|
||||||
},
|
},
|
||||||
martes: {
|
martes: {
|
||||||
backgroundColor: "rgba(255,214,0 ,1)",
|
backgroundColor: "rgba(255,214,0 ,1)",
|
||||||
color: "#151515"
|
color: "#151515",
|
||||||
},
|
},
|
||||||
miercoles: {
|
miercoles: {
|
||||||
backgroundColor: "rgba(236,64,122 ,1)"
|
backgroundColor: "rgba(236,64,122 ,1)",
|
||||||
},
|
},
|
||||||
jueves: {
|
jueves: {
|
||||||
backgroundColor: "rgba(29,233,182 ,1)",
|
backgroundColor: "rgba(29,233,182 ,1)",
|
||||||
color: "#151515"
|
color: "#151515",
|
||||||
},
|
},
|
||||||
viernes: {
|
viernes: {
|
||||||
backgroundColor: "rgba(244,67,54,1)"
|
backgroundColor: "rgba(244,67,54,1)",
|
||||||
}
|
},
|
||||||
});
|
})
|
||||||
|
|
||||||
const clasesColores = {
|
const clasesColores = {
|
||||||
Lunes: css(eColores.lunes),
|
Lunes: css(eColores.lunes),
|
||||||
Martes: css(eColores.martes),
|
Martes: css(eColores.martes),
|
||||||
Miercoles: css(eColores.miercoles),
|
Miercoles: css(eColores.miercoles),
|
||||||
Jueves: css(eColores.jueves),
|
Jueves: css(eColores.jueves),
|
||||||
Viernes: css(eColores.viernes)
|
Viernes: css(eColores.viernes),
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@ -79,64 +82,68 @@ interface Props {
|
|||||||
setIdHover: (v: string) => string,
|
setIdHover: (v: string) => string,
|
||||||
fnResaltarFila: () => void,
|
fnResaltarFila: () => void,
|
||||||
fnDesresaltarFila: () => void,
|
fnDesresaltarFila: () => void,
|
||||||
dia: Dia
|
dia: Dia,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const claseSeldaSeleccionada = css(e.celdaSeleccionada)
|
||||||
|
|
||||||
export function CeldaFila(props: Props) {
|
export function CeldaFila(props: Props) {
|
||||||
const datos = props.datos;
|
const datos = props.datos
|
||||||
const idHover = props.idHover;
|
const idHover = props.idHover
|
||||||
const setIdHover = props.setIdHover;
|
const setIdHover = props.setIdHover
|
||||||
|
|
||||||
const fnOnMouseEnter = (id: string) => setIdHover(id);
|
const fnOnMouseEnter = (id: string) => setIdHover(id)
|
||||||
const fnOnMouseLeave = () => setIdHover("");
|
const fnOnMouseLeave = () => setIdHover("")
|
||||||
|
|
||||||
return <div className={css(e.celdaComun, estilosGlobales.inlineBlock)}>
|
return (
|
||||||
<For each={datos}>
|
<div className={css(e.celdaComun, estilosGlobales.inlineBlock)}>
|
||||||
{datos => {
|
<For each={datos}>
|
||||||
const id = datos.id;
|
{(datos) => {
|
||||||
const txt = datos.txt;
|
const id = datos.id
|
||||||
const esLab = datos.esLab;
|
const txt = datos.txt
|
||||||
const fnSeleccionar = datos.fnSeleccionar;
|
const esLab = datos.esLab
|
||||||
|
const fnSeleccionar = datos.fnSeleccionar
|
||||||
|
|
||||||
const [estabaResaltado, setEstabaResaltado] = createSignal(false);
|
const [estabaResaltado, setEstabaResaltado] = createSignal(false)
|
||||||
|
|
||||||
const estaSeleccionado = createMemo(() => {
|
const estaSeleccionado = createMemo(() => datos.datosGrupo.seleccionado)
|
||||||
return datos.datosGrupo.seleccionado;
|
|
||||||
});
|
|
||||||
|
|
||||||
const clases = createMemo(
|
const clases = createMemo(
|
||||||
() => {
|
() => {
|
||||||
const clases = [
|
const clases = [
|
||||||
e.celdaCurso,
|
e.celdaCurso,
|
||||||
esLab ? e.celdaCursoLab : e.celdaCursoTeoria,
|
esLab ? e.celdaCursoLab : e.celdaCursoTeoria,
|
||||||
estaSeleccionado() && estilosGlobales.contenedorCursorActivo
|
estaSeleccionado() && e.celdaSeleccionada,
|
||||||
];
|
]
|
||||||
let adicional = "";
|
let adicional = ""
|
||||||
const idHoverS = idHover();
|
const idHoverS = idHover()
|
||||||
if (idHoverS !== "" && id.search(idHoverS) !== -1) {
|
if (idHoverS !== "" && id.search(idHoverS) !== -1) {
|
||||||
props.fnResaltarFila();
|
props.fnResaltarFila()
|
||||||
clases.push(e.celdaCursoActiva);
|
clases.push(e.celdaCursoActiva)
|
||||||
adicional = clasesColores[props.dia];
|
adicional = clasesColores[props.dia]
|
||||||
|
|
||||||
setEstabaResaltado(true);
|
setEstabaResaltado(true)
|
||||||
} else if (estabaResaltado()) {
|
} else if (estabaResaltado()) {
|
||||||
props.fnDesresaltarFila();
|
props.fnDesresaltarFila()
|
||||||
setEstabaResaltado(false);
|
setEstabaResaltado(false)
|
||||||
}
|
}
|
||||||
return css(...clases) + " " + adicional;
|
return `${css(...clases)} ${adicional}`
|
||||||
},
|
},
|
||||||
undefined,
|
undefined,
|
||||||
(x, y) => x === y
|
(x, y) => x === y,
|
||||||
);
|
)
|
||||||
|
|
||||||
return <span className={clases()}
|
return (
|
||||||
onMouseEnter={() => fnOnMouseEnter(id)}
|
<span className={clases()}
|
||||||
onMouseLeave={fnOnMouseLeave}
|
onMouseEnter={() => fnOnMouseEnter(id)}
|
||||||
onClick={fnSeleccionar}
|
onMouseLeave={fnOnMouseLeave}
|
||||||
>
|
onClick={fnSeleccionar}
|
||||||
{txt}
|
>
|
||||||
</span>;
|
{txt}
|
||||||
}}
|
</span>
|
||||||
</For>
|
)
|
||||||
</div>
|
}}
|
||||||
|
</For>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
}
|
}
|
@ -1,10 +1,10 @@
|
|||||||
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, createSignal, createMemo, createState, createEffect, State, SetStateFunction } 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, ListaCursosUsuario } from "../../types/DatosHorario"
|
||||||
import { coloresBorde, diaANum } from "../Tabla";
|
import { coloresBorde, diaANum } from "../Tabla"
|
||||||
|
|
||||||
const e = StyleSheet.create({
|
const e = StyleSheet.create({
|
||||||
celdaHora: {
|
celdaHora: {
|
||||||
@ -12,13 +12,13 @@ const e = StyleSheet.create({
|
|||||||
width: "3rem",
|
width: "3rem",
|
||||||
padding: "0.25rem 0",
|
padding: "0.25rem 0",
|
||||||
position: "absolute",
|
position: "absolute",
|
||||||
top: "-0.75rem"
|
top: "-0.75rem",
|
||||||
},
|
},
|
||||||
filaResaltado: {
|
filaResaltado: {
|
||||||
position: "absolute",
|
position: "absolute",
|
||||||
zIndex: -1,
|
zIndex: -1,
|
||||||
height: "100%",
|
height: "100%",
|
||||||
transform: "translateX(-1.5rem)"
|
transform: "translateX(-1.5rem)",
|
||||||
},
|
},
|
||||||
fila: {
|
fila: {
|
||||||
position: "relative",
|
position: "relative",
|
||||||
@ -30,7 +30,7 @@ const e = StyleSheet.create({
|
|||||||
minHeight: "1.2rem",
|
minHeight: "1.2rem",
|
||||||
":hover": {
|
":hover": {
|
||||||
// backgroundColor: "rgba(200, 200, 200, 0.25)"
|
// backgroundColor: "rgba(200, 200, 200, 0.25)"
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
filaBorde: {
|
filaBorde: {
|
||||||
position: "absolute",
|
position: "absolute",
|
||||||
@ -38,17 +38,17 @@ const e = StyleSheet.create({
|
|||||||
height: "1px",
|
height: "1px",
|
||||||
width: "100%",
|
width: "100%",
|
||||||
backgroundColor: "rgba(200, 200, 200, 0.25)",
|
backgroundColor: "rgba(200, 200, 200, 0.25)",
|
||||||
zIndex: -1
|
zIndex: -1,
|
||||||
},
|
},
|
||||||
celdaResaltado: {
|
celdaResaltado: {
|
||||||
height: "101%",
|
height: "101%",
|
||||||
width: "5px",
|
width: "5px",
|
||||||
display: "inline-block"
|
display: "inline-block",
|
||||||
},
|
},
|
||||||
celdaResaltadoTransparente: {
|
celdaResaltadoTransparente: {
|
||||||
backgroundColor: "transparent"
|
backgroundColor: "transparent",
|
||||||
}
|
},
|
||||||
});
|
})
|
||||||
|
|
||||||
const [diasResaltados, setDiasResaltados] = createState({
|
const [diasResaltados, setDiasResaltados] = createState({
|
||||||
Lunes: 0,
|
Lunes: 0,
|
||||||
@ -56,7 +56,7 @@ const [diasResaltados, setDiasResaltados] = createState({
|
|||||||
Miercoles: 0,
|
Miercoles: 0,
|
||||||
Jueves: 0,
|
Jueves: 0,
|
||||||
Viernes: 0,
|
Viernes: 0,
|
||||||
} as { [k: string]: number });
|
} as { [k: string]: number })
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
hora: string,
|
hora: string,
|
||||||
@ -65,12 +65,10 @@ interface Props {
|
|||||||
setIdHover: (v: string) => string
|
setIdHover: (v: string) => string
|
||||||
}
|
}
|
||||||
|
|
||||||
const diasFilter = createMemo(() => {
|
const diasFilter = createMemo(() => Object.entries(diasResaltados)
|
||||||
return Object.entries(diasResaltados)
|
.filter((x) => x[1] > 0)
|
||||||
.filter(x => x[1] > 0)
|
.map((x) => x[0] as Dia)
|
||||||
.map(x => x[0] as Dia)
|
.sort((x, y) => (diaANum(x) > diaANum(y) ? 1 : -1)))
|
||||||
.sort((x, y) => diaANum(x) > diaANum(y) ? 1 : -1);
|
|
||||||
});
|
|
||||||
|
|
||||||
const useDiasResaltados: () => [
|
const useDiasResaltados: () => [
|
||||||
State<{ [k: string]: boolean }>,
|
State<{ [k: string]: boolean }>,
|
||||||
@ -83,64 +81,76 @@ const useDiasResaltados: () => [
|
|||||||
Miercoles: false,
|
Miercoles: false,
|
||||||
Jueves: false,
|
Jueves: false,
|
||||||
Viernes: false,
|
Viernes: false,
|
||||||
} as { [k: string]: boolean });
|
} as { [k: string]: boolean })
|
||||||
|
|
||||||
const fnResaltar = (d: Dia) => {
|
const fnResaltar = (d: Dia) => {
|
||||||
setDiasResaltadosLocal(d, true);
|
setDiasResaltadosLocal(d, true)
|
||||||
setDiasResaltados(d, v => v + 1);
|
setDiasResaltados(d, (v) => v + 1)
|
||||||
};
|
}
|
||||||
|
|
||||||
const fnDesresaltar = (d: Dia) => {
|
const fnDesresaltar = (d: Dia) => {
|
||||||
setDiasResaltadosLocal(d, false);
|
setDiasResaltadosLocal(d, false)
|
||||||
setDiasResaltados(d, v => v - 1);
|
setDiasResaltados(d, (v) => v - 1)
|
||||||
};
|
}
|
||||||
|
|
||||||
return [diasResaltadosLocal, fnResaltar, fnDesresaltar];
|
return [diasResaltadosLocal, fnResaltar, fnDesresaltar]
|
||||||
};
|
}
|
||||||
|
|
||||||
export function FilaTabla(props: Props) {
|
export function FilaTabla(props: Props) {
|
||||||
const [diasResaltadosLocal, fnResaltar, fnDesresaltar] = useDiasResaltados();
|
const [diasResaltadosLocal, fnResaltar, fnDesresaltar] = useDiasResaltados()
|
||||||
|
|
||||||
const hora = props.hora;
|
const hora = props.hora
|
||||||
const data = props.data;
|
const data = props.data
|
||||||
|
|
||||||
return <div style={{position: "relative"}}>
|
return (
|
||||||
<div className={css(e.celdaHora, estilosGlobales.inlineBlock)}>
|
<div style={{position: "relative"}}>
|
||||||
{hora.substring(0, 5)}
|
<div className={css(e.celdaHora, estilosGlobales.inlineBlock)}>
|
||||||
</div>
|
{hora.substring(0, 5)}
|
||||||
<div className={css(e.fila)}>
|
|
||||||
<div className={css(estilosGlobales.inlineBlock, e.filaResaltado)}>
|
|
||||||
<div className={css(e.celdaResaltado, diasResaltadosLocal.Lunes ? null : e.celdaResaltadoTransparente)}
|
|
||||||
style={{"background-color": coloresBorde[0]}}/>
|
|
||||||
<div className={css(e.celdaResaltado, diasResaltadosLocal.Martes ? null : e.celdaResaltadoTransparente)}
|
|
||||||
style={{"background-color": coloresBorde[1]}}/>
|
|
||||||
<div
|
|
||||||
className={css(e.celdaResaltado, diasResaltadosLocal.Miercoles ? null : e.celdaResaltadoTransparente)}
|
|
||||||
style={{"background-color": coloresBorde[2]}}/>
|
|
||||||
<div className={css(e.celdaResaltado, diasResaltadosLocal.Jueves ? null : e.celdaResaltadoTransparente)}
|
|
||||||
style={{"background-color": coloresBorde[3]}}/>
|
|
||||||
<div
|
|
||||||
className={css(e.celdaResaltado, diasResaltadosLocal.Viernes ? null : e.celdaResaltadoTransparente)}
|
|
||||||
style={{"background-color": coloresBorde[4]}}/>
|
|
||||||
</div>
|
</div>
|
||||||
<For each={dias}>
|
<div className={css(e.fila)}>
|
||||||
{dia => {
|
<div className={css(estilosGlobales.inlineBlock, e.filaResaltado)}>
|
||||||
const diaStr = dia.substring(0, 2);
|
<div
|
||||||
const horaStr = hora.substring(0, 5);
|
className={css(e.celdaResaltado, diasResaltadosLocal.Lunes ? null : e.celdaResaltadoTransparente)}
|
||||||
|
style={{"background-color": coloresBorde[0]}}
|
||||||
const datos = data?.[horaStr]?.[diaStr] ?? [];
|
|
||||||
|
|
||||||
return <CeldaFila
|
|
||||||
datos={datos}
|
|
||||||
idHover={props.idHover}
|
|
||||||
setIdHover={props.setIdHover}
|
|
||||||
fnResaltarFila={() => fnResaltar(dia)}
|
|
||||||
fnDesresaltarFila={() => fnDesresaltar(dia)}
|
|
||||||
dia={dia}
|
|
||||||
/>
|
/>
|
||||||
}}
|
<div
|
||||||
</For>
|
className={css(e.celdaResaltado, diasResaltadosLocal.Martes ? null : e.celdaResaltadoTransparente)}
|
||||||
<div className={css(e.filaBorde)}/>
|
style={{"background-color": coloresBorde[1]}}
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
className={css(e.celdaResaltado, diasResaltadosLocal.Miercoles ? null : e.celdaResaltadoTransparente)}
|
||||||
|
style={{"background-color": coloresBorde[2]}}
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
className={css(e.celdaResaltado, diasResaltadosLocal.Jueves ? null : e.celdaResaltadoTransparente)}
|
||||||
|
style={{"background-color": coloresBorde[3]}}
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
className={css(e.celdaResaltado, diasResaltadosLocal.Viernes ? null : e.celdaResaltadoTransparente)}
|
||||||
|
style={{"background-color": coloresBorde[4]}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<For each={dias}>
|
||||||
|
{(dia) => {
|
||||||
|
const diaStr = dia.substring(0, 2)
|
||||||
|
const horaStr = hora.substring(0, 5)
|
||||||
|
|
||||||
|
const datos = data?.[horaStr]?.[diaStr] ?? []
|
||||||
|
|
||||||
|
return (
|
||||||
|
<CeldaFila
|
||||||
|
datos={datos}
|
||||||
|
idHover={props.idHover}
|
||||||
|
setIdHover={props.setIdHover}
|
||||||
|
fnResaltarFila={() => fnResaltar(dia)}
|
||||||
|
fnDesresaltarFila={() => fnDesresaltar(dia)}
|
||||||
|
dia={dia}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
</For>
|
||||||
|
<div className={css(e.filaBorde)} />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>;
|
)
|
||||||
}
|
}
|
70
src/ContenedorHorarios/TablaObserver.ts
Normal file
70
src/ContenedorHorarios/TablaObserver.ts
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
/**
|
||||||
|
* - Normal
|
||||||
|
* - Oculto - Otro grupo seleccionado
|
||||||
|
* - Seleccionado - Cursor ensima
|
||||||
|
* - Resaltado - Grupo seleccionado
|
||||||
|
* - ResaltadoSeleccionado - Grupo seleccionado y cursor encima
|
||||||
|
* - ResaltadoOculto - Otro grupo seleccionado y cursor encima
|
||||||
|
*/
|
||||||
|
import { createMemo, createState, SetStateFunction, State } from "solid-js";
|
||||||
|
|
||||||
|
type EstadoCelda =
|
||||||
|
| "Normal"
|
||||||
|
| "Oculto"
|
||||||
|
| "Seleccionado"
|
||||||
|
| "Resaltado"
|
||||||
|
| "ResaltadoSeleccionado"
|
||||||
|
| "ResaltadoOculto"
|
||||||
|
|
||||||
|
interface Datos {
|
||||||
|
anio?: string,
|
||||||
|
curso?: string,
|
||||||
|
esLab?: boolean,
|
||||||
|
grupo?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export class TablaObserver {
|
||||||
|
|
||||||
|
private readonly resaltado: State<Datos>
|
||||||
|
private readonly setResaltado: SetStateFunction<Datos>
|
||||||
|
private gruposSeleccionados = {}
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
const [resaltado, setResaltado] = createState<Datos>({
|
||||||
|
anio: undefined,
|
||||||
|
curso: undefined,
|
||||||
|
esLab: undefined,
|
||||||
|
grupo: undefined
|
||||||
|
});
|
||||||
|
this.resaltado = resaltado;
|
||||||
|
this.setResaltado = setResaltado;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cada celda se registra dando estos datos
|
||||||
|
// Devuelve un memo con un valor de EstadoCelda,
|
||||||
|
// el cual cada celda sabra como manejar
|
||||||
|
registrar(anio: string, cursoAbreviado: string, esLab: boolean, grupo: string) {
|
||||||
|
const fn = () => {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
const memo = createMemo(
|
||||||
|
fn,
|
||||||
|
undefined,
|
||||||
|
(x, y) => x === y
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
resaltar(id: string) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
quitarResaltado() {
|
||||||
|
this.setResaltado({
|
||||||
|
anio: undefined,
|
||||||
|
curso: undefined,
|
||||||
|
esLab: undefined,
|
||||||
|
grupo: undefined
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
import { createState, SetStateFunction, State } from "solid-js";
|
import { createState, SetStateFunction, State } from "solid-js"
|
||||||
import { Curso, ListaCursosUsuario } from "../types/DatosHorario";
|
import { Curso, ListaCursosUsuario } from "../types/DatosHorario"
|
||||||
|
|
||||||
interface ReturnType {
|
interface ReturnType {
|
||||||
listaCursos: State<ListaCursosUsuario>,
|
listaCursos: State<ListaCursosUsuario>,
|
||||||
@ -11,31 +11,31 @@ interface ReturnType {
|
|||||||
export const useListaCursos = (): ReturnType => {
|
export const useListaCursos = (): ReturnType => {
|
||||||
const [listaCursos, setListaCursos] = createState<ListaCursosUsuario>({
|
const [listaCursos, setListaCursos] = createState<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,
|
||||||
};
|
}
|
||||||
};
|
}
|
||||||
|
@ -1,15 +1,17 @@
|
|||||||
import { StyleSheet, css } from "aphrodite";
|
import { StyleSheet, css } from "aphrodite"
|
||||||
|
|
||||||
const e = StyleSheet.create({
|
const e = StyleSheet.create({
|
||||||
creditos: {
|
creditos: {
|
||||||
textAlign: "center",
|
textAlign: "center",
|
||||||
paddingTop: "7.5rem",
|
paddingTop: "7.5rem",
|
||||||
paddingBottom: "1rem"
|
paddingBottom: "1rem",
|
||||||
}
|
},
|
||||||
});
|
})
|
||||||
|
|
||||||
export function Creditos() {
|
export function Creditos() {
|
||||||
return <div className={css(e.creditos)}>
|
return (
|
||||||
Desarrollado por Fernando Araoz con TypeScript, JSX y Solid.js.
|
<div className={css(e.creditos)}>
|
||||||
</div>
|
Desarrollado por Fernando Araoz con TypeScript, JSX y Solid.js.
|
||||||
|
</div>
|
||||||
|
)
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
import {StyleSheet} from "aphrodite";
|
import {StyleSheet} from "aphrodite"
|
||||||
|
|
||||||
export const estilosGlobales = StyleSheet.create({
|
export const estilosGlobales = StyleSheet.create({
|
||||||
contenedor: {
|
contenedor: {
|
||||||
@ -7,7 +7,7 @@ export const estilosGlobales = StyleSheet.create({
|
|||||||
borderRadius: "10px",
|
borderRadius: "10px",
|
||||||
backdropFilter: "blur(40px)",
|
backdropFilter: "blur(40px)",
|
||||||
backgroundColor: "rgba(100, 100, 100, 0.25)",
|
backgroundColor: "rgba(100, 100, 100, 0.25)",
|
||||||
color: "var(--color-texto)"
|
color: "var(--color-texto)",
|
||||||
},
|
},
|
||||||
contenedorCursor: {
|
contenedorCursor: {
|
||||||
cursor: "pointer",
|
cursor: "pointer",
|
||||||
@ -15,27 +15,27 @@ export const estilosGlobales = StyleSheet.create({
|
|||||||
transition: "background-color 200ms",
|
transition: "background-color 200ms",
|
||||||
textDecoration: "underline solid white 2px",
|
textDecoration: "underline solid white 2px",
|
||||||
":hover": {
|
":hover": {
|
||||||
backgroundColor: "rgba(200, 200, 200, 0.3)"
|
backgroundColor: "rgba(200, 200, 200, 0.3)",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
contenedorCursorSoft: {
|
contenedorCursorSoft: {
|
||||||
textDecoration: "underline rgba(255, 255, 255, 0.4)"
|
textDecoration: "underline rgba(255, 255, 255, 0.4)",
|
||||||
},
|
},
|
||||||
contenedorCursorActivo: {
|
contenedorCursorActivo: {
|
||||||
backgroundColor: "rgba(200, 200, 200, 0.3)"
|
backgroundColor: "rgba(200, 200, 200, 0.3)",
|
||||||
},
|
},
|
||||||
contenedorPhospor: {
|
contenedorPhospor: {
|
||||||
padding: "0.5rem 0.65rem",
|
padding: "0.5rem 0.65rem",
|
||||||
transform: "translateY(0.2rem)"
|
transform: "translateY(0.2rem)",
|
||||||
},
|
},
|
||||||
inlineBlock: {
|
inlineBlock: {
|
||||||
display: "inline-block"
|
display: "inline-block",
|
||||||
},
|
},
|
||||||
botonPhospor: {
|
botonPhospor: {
|
||||||
"::before": {
|
"::before": {
|
||||||
fontSize: "1.25rem",
|
fontSize: "1.25rem",
|
||||||
// transform: "translateY(0.2rem)",
|
// transform: "translateY(0.2rem)",
|
||||||
textDecoration: "underline rgba(255, 255, 255, 0.4)",
|
textDecoration: "underline rgba(255, 255, 255, 0.4)",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
|
20
src/Store.ts
20
src/Store.ts
@ -1,4 +1,4 @@
|
|||||||
import { createSignal, createEffect } from "solid-js";
|
import { createSignal} from "solid-js"
|
||||||
|
|
||||||
enum ModoColor {
|
enum ModoColor {
|
||||||
Claro,
|
Claro,
|
||||||
@ -8,7 +8,7 @@ enum ModoColor {
|
|||||||
|
|
||||||
export type Dia = "Lunes" | "Martes" | "Miercoles" | "Jueves" | "Viernes";
|
export type Dia = "Lunes" | "Martes" | "Miercoles" | "Jueves" | "Viernes";
|
||||||
|
|
||||||
export const dias: Dia[] = ["Lunes", "Martes", "Miercoles", "Jueves", "Viernes"];
|
export const dias: Dia[] = ["Lunes", "Martes", "Miercoles", "Jueves", "Viernes"]
|
||||||
export const horas = [
|
export const horas = [
|
||||||
"07:00 - 07:50",
|
"07:00 - 07:50",
|
||||||
"07:50 - 08:40",
|
"07:50 - 08:40",
|
||||||
@ -30,17 +30,17 @@ export const horas = [
|
|||||||
"18:30 - 19:20",
|
"18:30 - 19:20",
|
||||||
"19:20 - 20:10",
|
"19:20 - 20:10",
|
||||||
"20:10 - 21:00",
|
"20:10 - 21:00",
|
||||||
"21:00 - 21:00"
|
"21:00 - 21:00",
|
||||||
];
|
]
|
||||||
export const horasDescanso = [
|
export const horasDescanso = [
|
||||||
"08:40 - 08:50",
|
"08:40 - 08:50",
|
||||||
"10:30 - 10:40",
|
"10:30 - 10:40",
|
||||||
"15:40 - 15:50",
|
"15:40 - 15:50",
|
||||||
"17:30 - 17:40"
|
"17:30 - 17:40",
|
||||||
];
|
]
|
||||||
|
|
||||||
const numImgGuardado = parseInt(localStorage.getItem("num-img") ?? "3");
|
const numImgGuardado = Number(localStorage.getItem("num-img") ?? "3")
|
||||||
|
|
||||||
export const [modoColor, setModoColor] = createSignal(ModoColor.Oscuro);
|
export const [modoColor, setModoColor] = createSignal(ModoColor.Oscuro)
|
||||||
export const [numWallpaper, setNumWallpaper] = createSignal(numImgGuardado);
|
export const [numWallpaper, setNumWallpaper] = createSignal(numImgGuardado)
|
||||||
export const [mostrarDescansos, setMostrarDescansos] = createSignal(true);
|
export const [mostrarDescansos, setMostrarDescansos] = createSignal(true)
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import { StyleSheet, css } from "aphrodite";
|
import { StyleSheet, css } from "aphrodite"
|
||||||
import { numWallpaper } from "./Store";
|
import { numWallpaper } from "./Store"
|
||||||
import { createEffect, createState } from "solid-js";
|
import { createEffect, createState } from "solid-js"
|
||||||
|
|
||||||
const duracionTransicion = 250;
|
const duracionTransicion = 250
|
||||||
|
|
||||||
export function Wallpaper() {
|
export function Wallpaper() {
|
||||||
/// @ts-ignore
|
/// @ts-ignore
|
||||||
const soportaBackdropFilter = document.body.style.backdropFilter !== undefined;
|
const soportaBackdropFilter = document.body.style.backdropFilter !== undefined
|
||||||
|
|
||||||
const estilos = StyleSheet.create({
|
const estilos = StyleSheet.create({
|
||||||
contenedorCover: {
|
contenedorCover: {
|
||||||
@ -16,7 +16,7 @@ export function Wallpaper() {
|
|||||||
top: "0",
|
top: "0",
|
||||||
left: "0",
|
left: "0",
|
||||||
backgroundColor: "#212121",
|
backgroundColor: "#212121",
|
||||||
zIndex: -1
|
zIndex: -1,
|
||||||
},
|
},
|
||||||
cover: {
|
cover: {
|
||||||
width: "100vw",
|
width: "100vw",
|
||||||
@ -25,43 +25,45 @@ export function Wallpaper() {
|
|||||||
backgroundSize: "cover",
|
backgroundSize: "cover",
|
||||||
zIndex: -1,
|
zIndex: -1,
|
||||||
transition: `opacity ${duracionTransicion}ms`,
|
transition: `opacity ${duracionTransicion}ms`,
|
||||||
filter: soportaBackdropFilter? "": "blur(40px)"
|
filter: soportaBackdropFilter ? "" : "blur(40px)",
|
||||||
},
|
},
|
||||||
coverTransicion: {
|
coverTransicion: {
|
||||||
opacity: 0
|
opacity: 0,
|
||||||
}
|
},
|
||||||
});
|
})
|
||||||
|
|
||||||
const [estilosRaw, setEstilosRaw] = createState({
|
const [estilosRaw, setEstilosRaw] = createState({
|
||||||
"background-image": `none`,
|
"background-image": "none",
|
||||||
opacity: 1
|
opacity: 1,
|
||||||
});
|
})
|
||||||
|
|
||||||
createEffect(() => {
|
createEffect(() => {
|
||||||
const numImg = numWallpaper();
|
const numImg = numWallpaper()
|
||||||
setEstilosRaw("opacity", 0);
|
setEstilosRaw("opacity", 0)
|
||||||
|
|
||||||
const promesa250ms = new Promise(resolve => {
|
const promesa250ms = new Promise((resolve) => {
|
||||||
setTimeout(resolve, duracionTransicion);
|
setTimeout(resolve, duracionTransicion)
|
||||||
});
|
})
|
||||||
|
|
||||||
const url = `/img/wall${numImg}.webp`;
|
const url = `/img/wall${numImg}.webp`
|
||||||
const img = new Image();
|
const img = new Image()
|
||||||
img.addEventListener("load", async () => {
|
img.addEventListener("load", async() => {
|
||||||
await promesa250ms;
|
await promesa250ms
|
||||||
setEstilosRaw({
|
setEstilosRaw({
|
||||||
"background-image": `url('${url}')`,
|
"background-image": `url('${url}')`,
|
||||||
opacity: 1
|
opacity: 1,
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
img.src = url;
|
img.src = url
|
||||||
});
|
})
|
||||||
|
|
||||||
return <div className={css(estilos.contenedorCover)}>
|
return (
|
||||||
<div
|
<div className={css(estilos.contenedorCover)}>
|
||||||
className={css(estilos.cover)}
|
<div
|
||||||
style={{"background-image": estilosRaw["background-image"], opacity: estilosRaw.opacity}}
|
className={css(estilos.cover)}
|
||||||
/>
|
style={{"background-image": estilosRaw["background-image"], opacity: estilosRaw.opacity}}
|
||||||
</div>
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import "solid-js";
|
import "solid-js"
|
||||||
import { render } from 'solid-js/web';
|
import { render } from "solid-js/web"
|
||||||
import App from './App';
|
import App from "./App"
|
||||||
import "normalize.css";
|
import "normalize.css"
|
||||||
import "./styles/global.css";
|
import "./styles/global.css"
|
||||||
|
|
||||||
render(App, document.getElementById('root') as Node);
|
render(App, document.getElementById("root") as Node)
|
||||||
|
Loading…
Reference in New Issue
Block a user