Skip to content

Commit

Permalink
responsive
Browse files Browse the repository at this point in the history
vis97c committed Oct 31, 2024

Verified

This commit was signed with the committer’s verified signature.
OrionFOTL Orion
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.