Skip to content

Commit

Permalink
responsive
Browse files Browse the repository at this point in the history
vis97c committed Oct 31, 2024
1 parent d9be472 commit d7a297e
Showing 8 changed files with 120 additions and 29 deletions.
19 changes: 14 additions & 5 deletions app.vue
Original file line number Diff line number Diff line change
@@ -19,19 +19,19 @@
<section class="view-item --minHeightVh-100 --pY-30">
<div class="holder flx --flxColumn --flx-center --gap-30">
<div
class="flx --flxColumn --flx-center --pTop-30 --width-100 --minHeight-100"
class="flx --flxColumn --flx-center --pY-50 --width-100 --minHeight-100"
>
<div
v-if="SESSION.user"
class="x-navigation flx --flxRow --flx-between-center --width-100"
class="x-navigation flx --flxRow-wrap --flx-between-center --width-100"
>
<div class="">
<XamuActionLink
v-if="routeCourseId"
@click="$router.push('/')"
>
<XamuIconFa name="chevron-left" />
<span>Volver a la búsqueda</span>
<span>Volver</span>
</XamuActionLink>
</div>
<XamuDropdown :position="['bottom', 'right']" invert-theme>
@@ -43,18 +43,21 @@
tooltip-position="bottom"
@click="setModel()"
>
<span>{{ SESSION.user.name || "Sin nombre" }}</span>
<span>{{ userName || "Sin nombre" }}</span>
<XamuIconFa indicator name="chevron-down" />
</XamuActionLink>
</template>
<template #default>
<nav
class="list flx --flxColumn --gap-20 --minWidth-max --txtColor"
>
<ul class="list-group">
<ul class="list-group --gap-5">
<li>
<p class="--txtSize-xs">Cuenta</p>
</li>
<li>
<p>{{ SESSION.user.email }}</p>
</li>
<hr />
<li>
<XamuActionLink
@@ -109,6 +112,12 @@
const { indexable } = useRuntimeConfig().public;
const routeCourseId = computed(() => <string>route.params.courseId);
const userName = computed(() => {
const fullName = (SESSION.user?.name || "").split(" ");
const [firstName = "Sin Nombre", secondName = "", firstLastName = ""] = fullName;
return `${firstName} ${firstLastName || secondName}`.trim();
});
// lifecycle
useHead(() => {
6 changes: 5 additions & 1 deletion assets/scss/overrides.scss
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
@use "sass:color";

// override xamu style system parameters
// @use "@open-xamu-co/ui-styles/src/utils/module" with ();

@use "@open-xamu-co/ui-styles/src/utils/module" with (
// allowances
$allow-responsive-upscaling: false
);

@forward "@open-xamu-co/ui-styles/src/utils/module";
14 changes: 10 additions & 4 deletions composables/sia.ts
Original file line number Diff line number Diff line change
@@ -12,10 +12,10 @@ export function useSIACourses(values: CourseValues, page = 1) {

return $fetch<SIACoursesResponse>(coursesEndpoint, {
query: {
planEstudio: values.program,
codigo_asignatura: values.code,
nombre_asignatura: values.name,
tipologia: values.typology,
planEstudio: values.program || undefined,
codigo_asignatura: values.code || undefined,
nombre_asignatura: values.name || undefined,
tipologia: values.typology || undefined,
limit: 30, // firebase compound limit
page,
},
@@ -71,3 +71,9 @@ export async function useIndexCourse({
groups,
});
}

export function useCountSpots({ groups, spotsCount }: Partial<Course> = {}): number {
const withReduce = groups?.reduce((sum, { availableSpots = 0 }) => sum + availableSpots, 0);

return (withReduce || spotsCount) ?? 0;
}
10 changes: 5 additions & 5 deletions firestore.rules
Original file line number Diff line number Diff line change
@@ -76,10 +76,10 @@ service cloud.firestore {
// lectura explicita, moderadores hacia arriba
allow read: if canModerate() || isOwnUser(id);
// modificacion granular, administradores hacia arriba
allow create: if canAdmin() && getRole(id) >= 0 || canDevelop() || isOwnUser(id);
allow create: if canAdmin() || isOwnUser(id);
// administradores no puede modificar desarrolladores
allow update: if canAdmin() && getRole(id) >= 0 || canDevelop() || isOwnUser(id);
allow delete: if canAdmin() && getRole(id) >= 0 || canDevelop() || isOwnUser(id);
allow update: if canAdmin() || isOwnUser(id);
allow delete: if canAdmin() || isOwnUser(id);
}

match /teachers/{id} {
@@ -88,7 +88,7 @@ service cloud.firestore {
// modificacion granular, usuarios hacia arriba
allow create: if canUse();
allow update: if canUse();
allow delete: if canDevelop();
allow delete: if canModerate();
}

match /courses/{id} {
@@ -97,7 +97,7 @@ service cloud.firestore {
// modificacion granular, usuarios hacia arriba
allow create: if canUse();
allow update: if canUse();
allow delete: if canDevelop();
allow delete: if canModerate();
}
}
}
12 changes: 10 additions & 2 deletions nuxt.config.ts
Original file line number Diff line number Diff line change
@@ -3,7 +3,13 @@ import path from "node:path";

import locale from "@open-xamu-co/ui-common-helpers/es";

import { debugNuxt, production, runtimeConfig, countriesUrl } from "./resources/utils/enviroment";
import {
debugCSS,
debugNuxt,
production,
runtimeConfig,
countriesUrl,
} from "./resources/utils/enviroment";

/**
* Preload stylesheet and once loaded call them
@@ -27,9 +33,11 @@ const stylesheets: string[] = [
"https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,300;0,400;0,500;0,600;1,300;1,400;1,500;1,600&display=swap",
"https://unpkg.com/@fortawesome/fontawesome-free@^6/css/all.min.css",
"https://unpkg.com/sweetalert2@^11/dist/sweetalert2.min.css",
"https://unpkg.com/@open-xamu-co/ui-styles@^3.0.0-next.23/dist/index.min.css",
];

// compile on runtime when debuggin CSS
debugCSS ? css.push("@/assets/scss/vendor.scss") : stylesheets.push("/dist/vendor.min.css");

// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
devtools: { enabled: debugNuxt, timeline: { enabled: debugNuxt } },
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -2,12 +2,15 @@
"private": true,
"scripts": {
"dev": "nuxt dev",
"build": "nuxt build --preset=firebase && cp .env .output/server/.env",
"build": "yarn vendor && nuxt build --preset=firebase && cp .env .output/server/.env",
"start": "node .output/server/index.mjs",
"lint:eslint": "eslint --ext .ts,.js,.vue --ignore-path .prettierignore .",
"lint:stylelint": "stylelint **/{*,**/*,**/**/*}.{vue,css} --ignore-path .prettierignore",
"lint:prettier": "prettier . --check --ignore-unknown",
"lint": "yarn lint:eslint && yarn lint:stylelint && yarn lint:prettier",
"vendor:sass": "sass --load-path=node_modules assets/scss/vendor.scss public/dist/vendor.css",
"vendor:postcss": "postcss public/dist/vendor.css -o public/dist/vendor.min.css --no-map",
"vendor": "yarn vendor:sass && yarn vendor:postcss --verbose",
"typecheck": "nuxi typecheck",
"firebase:deploy": "yarn build && firebase deploy",
"firebase:start": "yarn build && firebase emulators:start",
70 changes: 65 additions & 5 deletions pages/curso/[courseId].vue
Original file line number Diff line number Diff line change
@@ -10,15 +10,22 @@
>
<div class="txt">
<h2 :key="content.id">{{ content.name }}</h2>
<p class="">Actualizado {{ useTimeAgo(new Date(content.updatedAt || "")) }}</p>
</div>
<div class="grd --grdColumns-auto2">
<div v-if="SESSION.canModerate && !fromSIA" class="txt">
<p class="">El curso contiene datos erroneos y no se pudo reindexar</p>
<XamuActionButton :theme="eColors.DANGER" @click="() => removeCourse(content)">
Eliminar
</XamuActionButton>
</div>
<div class="grd --grdColumns-auto2 --gap">
<div class="grd-item">
<XamuValueList
:value="{
sede: content.place,
facultad: content.faculty,
programa: content.program || 'No reportado',
cuposDisponibles: content.groupCount || content.groups?.length || 0,
cuposDisponibles: useCountSpots(content),
}"
/>
</div>
@@ -48,8 +55,11 @@

<script setup lang="ts">
import type { iPageEdge } from "@open-xamu-co/ui-common-types";
import { eColors } from "@open-xamu-co/ui-common-enums";
import { eSIATypology } from "~/functions/src/types/SIA";
import type { Course, Teacher } from "~/resources/types/entities";
import { debounce } from "lodash-es";
/**
* Course page
@@ -64,10 +74,36 @@
});
const SESSION = useSessionStore();
const router = useRouter();
const route = useRoute();
const Swal = useSwal();
const fromSIA = ref(true);
const routeCourseId = computed(() => <string>route.params.courseId);
const removeCourse = debounce(async (course: Course) => {
if (!SESSION.canModerate) return;
const removed = await useDocumentDelete(course);
if (removed) {
// Notify user of the success
await Swal.fire({
title: "Curso eliminado",
text: "Este podra ser reindexado mas tarde",
icon: "success",
});
return router.push("/");
}
Swal.fire({
title: "Curso eliminado",
text: "Algo paso, el curso pudo no ser eliminado",
icon: "error",
});
});
/**
* Get course from firebase, then SIA & reindex
*/
@@ -78,11 +114,18 @@
headers: { canModerate: SESSION.token || "" },
});
const { id, code = "", typology = eSIATypology.LIBRE_ELECCIÓN } = firebaseCourse;
if (!firebaseCourse) throw new Error("El curso que buscas no existe");
const {
id,
program,
code = "",
typology = eSIATypology.LIBRE_ELECCIÓN,
} = firebaseCourse;
// Get data from sia & reindex, do not await
Promise.all([
useSIACourses({ code, typology }),
useSIACourses({ program, code, typology }),
$fetch<iPageEdge<Teacher, string>[]>("/api/teachers/search", {
query: { courses: [code] },
cache: "no-cache",
@@ -92,7 +135,11 @@
const courses = data.map(useMapCourseFromSia);
const SIACourse = courses.find((c) => c.id === id);
if (!SIACourse) return;
if (!SIACourse) {
fromSIA.value = false;
return;
}
// refresh if same course
if (SIACourse.code === toHydrate.value?.code) toHydrate.value = SIACourse;
@@ -110,5 +157,18 @@
@use "@/assets/scss/overrides" as utils;
@media only screen {
tbody [data-column-name="name"] span {
color: transparent;
}
tbody [data-column-name="name"] span:before {
content: attr(title);
position: absolute;
top: 0;
left: 0;
color: utils.color(dark, 0.7);
}
tbody [data-column-name="programs"] {
max-width: none;
}
}
</style>
13 changes: 7 additions & 6 deletions pages/index.vue
Original file line number Diff line number Diff line change
@@ -31,7 +31,7 @@
>
<div
v-if="!isCodeSearch"
class="flx --flxRow --flx-start-center --gap-5 --width-100"
class="flx --flxRow-wrap --flx-start-center --gap-5 --width-100"
>
<div class="flx --flxColumn --flx-start --gap-5 --width-100">
<p class="">Facultad</p>
@@ -83,12 +83,13 @@
class="txt --gap-0 --txtColor-dark5 --width-100"
>
<XamuActionLink
class="--maxWidth-100"
:tooltip="`Ver: ${match.name}`"
tooltip-as-text
@click="() => goToCourse(match)"
>
<XamuIconFa name="chess-knight" />
<span class="--maxWidth-440 ellipsis">
<span class="--width-440 ellipsis">
{{ match.name }}
</span>
</XamuActionLink>
@@ -97,7 +98,7 @@
<span title="Programa">{{ match.program }}</span>
</p>
<div
class="flx --flxRow --flx-between-center --width-100 --txtSize-xs"
class="flx --flxRow-wrap --flx-between-center --gap-5 --width-100 --txtSize-xs"
>
<p>
<b title="Creditos">{{ match.credits || 0 }}</b>
@@ -107,11 +108,11 @@
<span title="Tipologia">{{ match.typology }}</span>
</p>
<p>
<template v-if="match.groups.length">
<span>{{ tGroup(match.groups.length || 0) }}</span>
<template v-if="match.groups?.length">
<span>{{ tGroup(match.groups?.length || 0) }}</span>
</template>
<b>{{ tSpot(match.spotsCount || 0) }}</b>
<b>{{ tSpot(useCountSpots(match)) }}</b>
<span
:title="`Ultima actualizacion ${match.updatedAt}`"

0 comments on commit d7a297e

Please sign in to comment.