From 0602aa503f664b7b6f7bf2fec7878e4b8e4234c5 Mon Sep 17 00:00:00 2001 From: Dimitra Angelidou Date: Tue, 5 May 2026 23:46:33 +0300 Subject: [PATCH 01/16] Fixed #329 (about us bottom being clipped) --- src/routes/personalInfo/about.svelte | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/routes/personalInfo/about.svelte b/src/routes/personalInfo/about.svelte index 6f149393..b3af4290 100644 --- a/src/routes/personalInfo/about.svelte +++ b/src/routes/personalInfo/about.svelte @@ -9,6 +9,7 @@ import contributors from "$lib/components/personalInfo/contributors.json"; import { t, locale, locales} from "$lib/i18n"; import SubPageHeader from '$shared/subPageHeader.svelte'; + import IonPage from 'ionic-svelte/components/IonPage.svelte'; import { construct } from 'ionicons/icons'; interface Contributor { @@ -51,7 +52,7 @@ - +
@@ -121,6 +122,7 @@
+
- \ No newline at end of file From b52854f81e595cc082b7b6f4ce7b8351645e10be Mon Sep 17 00:00:00 2001 From: Dimitra Angelidou Date: Mon, 25 May 2026 21:49:20 +0300 Subject: [PATCH 02/16] Maps opening OSETH app or correspondent webpage as it should, fixed #334, #335 --- src/routes/pages/maps/MapFooter.svelte | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/routes/pages/maps/MapFooter.svelte b/src/routes/pages/maps/MapFooter.svelte index 5ff4ed70..749d2b23 100644 --- a/src/routes/pages/maps/MapFooter.svelte +++ b/src/routes/pages/maps/MapFooter.svelte @@ -4,6 +4,9 @@ import { getMetroInfo } from '$lib/metroScraper/scraper'; import { onMount } from "svelte"; import { darkMode } from '$src/lib/globalFunctions/darkMode'; + import { registerPlugin } from '@capacitor/core'; + + const AppLauncherPlugin = registerPlugin('AppLauncherPlugin'); $: isDarkMode = $darkMode; @@ -16,7 +19,7 @@ async function handleTransportAppClick() { const packageName = 'com.amco.city.thessaloniki'; const iosAppStoreUrl = 'https://apps.apple.com/gr/app/oseth-bus/id6748433667'; - const fallbackUrl = 'https://telematics.oasth.gr/en/#main'; + const fallbackUrl = 'https://oseth.com.gr/el/anazitisi-dromologion-leoforeion/'; //@ts-ignore const ua = navigator.userAgent || navigator.vendor || window.opera; const isAndroid = /android/i.test(ua); From 598f4acfd980b5221081bdfaf19dc0264434b2a7 Mon Sep 17 00:00:00 2001 From: Neron-png Date: Sun, 14 Jun 2026 00:50:01 +0300 Subject: [PATCH 03/16] refactored personal info --- .mcp.json | 13 ++ src/routes/personalInfo/infoItem.svelte | 144 -------------- src/routes/personalInfo/personalInfo.svelte | 208 +++++++++++++++----- src/routes/personalInfo/settings.svelte | 5 +- 4 files changed, 178 insertions(+), 192 deletions(-) create mode 100644 .mcp.json delete mode 100644 src/routes/personalInfo/infoItem.svelte diff --git a/.mcp.json b/.mcp.json new file mode 100644 index 00000000..7c4f96a0 --- /dev/null +++ b/.mcp.json @@ -0,0 +1,13 @@ +{ + "mcpServers": { + "svelte": { + "type": "stdio", + "command": "npx", + "args": [ + "-y", + "@sveltejs/mcp" + ], + "env": {} + } + } +} \ No newline at end of file diff --git a/src/routes/personalInfo/infoItem.svelte b/src/routes/personalInfo/infoItem.svelte deleted file mode 100644 index 531d29bd..00000000 --- a/src/routes/personalInfo/infoItem.svelte +++ /dev/null @@ -1,144 +0,0 @@ - - - - - {#if gender === 'Άντρας'} - man - {:else} - woman - {/if} - {givenName} {familyName} - - {aem} - - - - - - {#if departmentName} - - - - {departmentName} - - {/if} - - {#if username} - - - - {username} - - {/if} - - {#if apm} - - - - {apm} - - {/if} - - {#if birthDate} - - - - {birthDate} - - {/if} - - {#if email} - - - - {email} - - {/if} - - {#if gender} - - - - {gender} - - {/if} - - {#if semester} - - - - {semester} - - {/if} - - {#if study_level} - - - - {study_level} - - {/if} - - - diff --git a/src/routes/personalInfo/personalInfo.svelte b/src/routes/personalInfo/personalInfo.svelte index 05d6e4f4..777af421 100644 --- a/src/routes/personalInfo/personalInfo.svelte +++ b/src/routes/personalInfo/personalInfo.svelte @@ -1,29 +1,41 @@ @@ -56,23 +94,90 @@ {#await getPersonalInfo()} {:then} - + + + {#if gender === 'Άντρας'} + man + {:else} + woman + {/if} + {givenName} {familyName} + + {aem} + + + + + + {#if departmentName} + + + + {departmentName} + + {/if} + + {#if username} + + + + {username} + + {/if} + + {#if apm} + + + + {apm} + + {/if} + + {#if birthDate} + + + + {birthDate} + + {/if} + + {#if email} + + + + {email} + + {/if} + + {#if gender} + + + + {gender} + + {/if} + + {#if semester} + + + + {semester} + + {/if} + + {#if study_level} + + + + {study_level} + + {/if} + {:catch error} {/await} - + @@ -81,4 +186,19 @@ --padding-end: 0.6rem; --padding-start: 0.6rem; } + + .info { + display: flex; + flex-direction: column; + align-items: center; + } + + ion-icon { + color: var(--app-color-icons); + } + + ion-card-subtitle { + font-size: 1.2rem; + padding-left: 5px; + } diff --git a/src/routes/personalInfo/settings.svelte b/src/routes/personalInfo/settings.svelte index b27334c2..70496ee4 100644 --- a/src/routes/personalInfo/settings.svelte +++ b/src/routes/personalInfo/settings.svelte @@ -18,11 +18,8 @@ import About from './about.svelte'; import Faq from './faq.svelte'; import { darkMode } from '$lib/globalFunctions/darkMode'; + import { logOut } from '$lib/globalFunctions/logOut'; - /** - * @type {any} - */ - export let logOut; let languageModalOpen = false; onMount(() => { From 86c86f31c2ac5a418da3c28272600243bae4ae37 Mon Sep 17 00:00:00 2001 From: Neron-png Date: Sun, 14 Jun 2026 23:58:03 +0300 Subject: [PATCH 04/16] Fixed types, deduplicated code, tidied some stuff --- src/lib/components/grades/chips.svelte | 12 +- src/lib/components/grades/courseRow.svelte | 90 +++++++++++ src/lib/components/grades/gradeCard.svelte | 169 ++------------------ src/lib/components/grades/grades.svelte | 13 +- src/lib/components/grades/gradesPage.svelte | 92 +++++------ src/lib/components/grades/statsCard.svelte | 15 +- src/lib/components/shared/Chips.svelte | 2 +- src/lib/functions/gradeAverages/averages.js | 5 +- 8 files changed, 169 insertions(+), 229 deletions(-) create mode 100644 src/lib/components/grades/courseRow.svelte diff --git a/src/lib/components/grades/chips.svelte b/src/lib/components/grades/chips.svelte index 7c59e3d5..96305336 100644 --- a/src/lib/components/grades/chips.svelte +++ b/src/lib/components/grades/chips.svelte @@ -1,13 +1,11 @@ + +
+
+ {course.courseTitle} + + {#if course.examPeriod != null} + + {#if course.examPeriod && course.gradeYear} + {course.examPeriod.name} {course.gradeYear.name} + {:else if course.registrationType === 1} + {$t('progress.exempted')} + {:else} + {$t('progress.declared')} + {/if} + + {:else} + - + {/if} +
+ {#if course.grade != null && !isNaN(course.grade)} + {#if course.grade * 10 >= 5} + +

{course.formattedGrade}

+
+ {:else} + +

{course.formattedGrade}

+
+ {/if} + {/if} +
+ + diff --git a/src/lib/components/grades/gradeCard.svelte b/src/lib/components/grades/gradeCard.svelte index b60b36a9..c9e7e92b 100644 --- a/src/lib/components/grades/gradeCard.svelte +++ b/src/lib/components/grades/gradeCard.svelte @@ -1,22 +1,25 @@ diff --git a/src/lib/components/grades/gradesPage.svelte b/src/lib/components/grades/gradesPage.svelte index 31bd075b..5956f450 100644 --- a/src/lib/components/grades/gradesPage.svelte +++ b/src/lib/components/grades/gradesPage.svelte @@ -12,6 +12,8 @@ import { flipped } from "./flipstore"; import { averagesPerSemester } from '$lib/functions/gradeAverages/averagesPerSemester'; import { writable } from 'svelte/store'; + import type { Writable } from 'svelte/store'; + import type { course } from '$lib/types/courseType'; import Fuse from 'fuse.js'; import { onMount } from 'svelte'; import { t } from "$lib/i18n"; @@ -34,8 +36,14 @@ classes: {id: string;finalGrade: number;coefficient: number;isPassed: number;registration: number;course: string}[]; } - let courseBySemester = writable([]); - let filteredSubjects = writable([]); + interface SemesterGroup { + semesterId: string; + average: string; + courses: course[]; + } + + let semesterGroups: Writable = writable([]); + let filteredSubjects: Writable = writable([]); let registrationsInDegree: Registration[]; const fuseOptions = { @@ -47,17 +55,8 @@ let searchQuery = ''; let subjects = 0; let passedSubjects = 0; - let coursesBySemester = {}; - let subjectsJSON: number | null | undefined; - - /** - * @type {string} - */ - let semesterId: any; - - /** - * @param {{ target: { value: string; }; }} event - */ + let coursesBySemester: { [key: string]: course[] } = {}; + let subjectsJSON: course[] = []; // Search function handleChange(event: { target: { value: string } }) { @@ -69,25 +68,22 @@ $flipped = !$flipped; } - async function getSubjects(subjectsJSON: any) { - coursesBySemester = await coursesPerSemester(subjectsJSON); - // @ts-ignore - passedSubjects = subjects - .filter((/** @type {{ grade: number; }} */ course) => course.grade * 10 >= 5) - .filter(/** @type {{parentCourse: string;}} */ (course) => course.parentCourse === null); - - // @ts-ignore - subjects = subjects.length; - // @ts-ignore - passedSubjects = passedSubjects.length; + async function getSubjects(courses: course[]) { + coursesBySemester = await coursesPerSemester(courses); + const passed = courses + .filter((course) => course.grade * 10 >= 5) + .filter((course) => course.parentCourse == null); + + subjects = courses.length; + passedSubjects = passed.length; } - async function gatherGrades(subjectsJSON: any) { + async function gatherGrades(subjectsJSON: course[]) { const courses = await coursesPerSemester(subjectsJSON); const semesterAverage = await averagesPerSemester(subjectsJSON); // keep semester id, average, and courses in an array - const semesters = Object.keys(courses).map((key) => { + const semesters: SemesterGroup[] = Object.keys(courses).map((key) => { return { semesterId: key, average: semesterAverage[key] ? semesterAverage[key] : '-', @@ -95,32 +91,30 @@ }; }); - semesters.sort((a, b) => a.semesterId - b.semesterId); + semesters.sort((a, b) => Number(a.semesterId) - Number(b.semesterId)); - courseBySemester.set(semesters); + semesterGroups.set(semesters); return semesters; } async function gatherProgressionData(){ - const registration_options = "$select=id,semester,classes&$expand=classes($select=id,finalGrade,coefficient,isPassed,course;$filter=isPassed eq 1)&$orderBy=semester&$top=-1" - const all_registrations: Registration[] = (await neoUniversisGet(`students/me/registrations?${registration_options}`, { lifetime: 1200 })).value - - const calculateGrade_options = "$select=id,course,calculateGrade,isPassed,courseTitle&$filter=calculateGrade eq 0,isPassed eq 1&$top=-1" - const nonCalculatedGrades: {"id": string;"course": string;"calculateGrade": 0;"isPassed": 1;}[] = (await neoUniversisGet(`students/me/courses?${calculateGrade_options}`, { lifetime: 1200 })).value - - const disallowed_courses = new Set(nonCalculatedGrades.map(item => item.course)) - registrationsInDegree = all_registrations.map(registration => ({ + const registrationOptions = "$select=id,semester,classes&$expand=classes($select=id,finalGrade,coefficient,isPassed,course;$filter=isPassed eq 1)&$orderBy=semester&$top=-1" + const allRegistrations: Registration[] = (await neoUniversisGet(`students/me/registrations?${registrationOptions}`, { lifetime: 1200 })).value + + const calculateGradeOptions = "$select=id,course,calculateGrade,isPassed,courseTitle&$filter=calculateGrade eq 0,isPassed eq 1&$top=-1" + const nonCalculatedGrades: { id: string; course: string; calculateGrade: 0; isPassed: 1 }[] = (await neoUniversisGet(`students/me/courses?${calculateGradeOptions}`, { lifetime: 1200 })).value + + const disallowedCourses = new Set(nonCalculatedGrades.map(item => item.course)) + registrationsInDegree = allRegistrations.map(registration => ({ ...registration, - classes: registration.classes.filter(class_instance => !disallowed_courses.has(class_instance.course) && class_instance.isPassed == 1) + classes: registration.classes.filter(classInstance => !disallowedCourses.has(classInstance.course) && classInstance.isPassed == 1) })) - } + } async function gatherData() { - subjects = (await neoUniversisGet('students/me/courses?$top=-1', { lifetime: 600 })).value; - - subjectsJSON = subjects; + subjectsJSON = (await neoUniversisGet('students/me/courses?$top=-1', { lifetime: 600 })).value; await getSubjects(subjectsJSON); await gatherGrades(subjectsJSON); @@ -130,12 +124,12 @@ // Filter the results based on the searchQuery $: { - const courses = $courseBySemester; + const courses = $semesterGroups; if (searchQuery.length === 0) { filteredSubjects.set(courses); } else { - const subjects = courses.reduce((acc, curr) => acc.concat(curr.courses), []); - const fuse = new Fuse(subjects, fuseOptions); + const allCourses = courses.reduce((acc, curr) => acc.concat(curr.courses), []); + const fuse = new Fuse(allCourses, fuseOptions); const searchResults = fuse.search(searchQuery); const filtered = courses.map((semester) => { @@ -170,7 +164,7 @@ /> {#if Object.entries(coursesBySemester).length > 0} - + {/if} @@ -188,12 +182,8 @@ {/if} - - - - - - {:catch error} + + {:catch error} {/await} diff --git a/src/lib/components/grades/statsCard.svelte b/src/lib/components/grades/statsCard.svelte index 665df18d..2b975ce1 100644 --- a/src/lib/components/grades/statsCard.svelte +++ b/src/lib/components/grades/statsCard.svelte @@ -5,12 +5,13 @@ import * as allIonicIcons from 'ionicons/icons'; import Chip from '$components/shared/Chips.svelte'; import { t } from '$lib/i18n'; + import type { course } from '$lib/types/courseType'; - export let subjects; - export let passedSubjects; - export let searchQuery; - export let flip; - export let subjectsJSON: null | undefined; + export let subjects: number; + export let passedSubjects: number; + export let searchQuery: string; + export let flip: () => void; + export let subjectsJSON: course[]; interface Registration { id: number; @@ -20,7 +21,7 @@ interface AveragesResult { avg: number; weighted_avg: number; - grades: never[]; + grades: number[]; ects: number; } @@ -33,7 +34,7 @@ let chart: Chart<'line', any, any>; let chartElement: HTMLCanvasElement; - let gradesObject = { + let gradesObject: { average: number; weightedAverage: number; grades: number[]; ects: number } = { average: 0, weightedAverage: 0, grades: [], diff --git a/src/lib/components/shared/Chips.svelte b/src/lib/components/shared/Chips.svelte index 099f2ac4..2a183041 100644 --- a/src/lib/components/shared/Chips.svelte +++ b/src/lib/components/shared/Chips.svelte @@ -1,6 +1,6 @@ - +
@@ -121,6 +122,7 @@
+
- \ No newline at end of file From 0c2aec60fc0fe795ca82123894eaf05ddf47e215 Mon Sep 17 00:00:00 2001 From: Dimitra Angelidou Date: Mon, 25 May 2026 21:49:20 +0300 Subject: [PATCH 09/16] Maps opening OSETH app or correspondent webpage as it should, fixed #334, #335 --- src/routes/pages/maps/MapFooter.svelte | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/routes/pages/maps/MapFooter.svelte b/src/routes/pages/maps/MapFooter.svelte index 5ff4ed70..749d2b23 100644 --- a/src/routes/pages/maps/MapFooter.svelte +++ b/src/routes/pages/maps/MapFooter.svelte @@ -4,6 +4,9 @@ import { getMetroInfo } from '$lib/metroScraper/scraper'; import { onMount } from "svelte"; import { darkMode } from '$src/lib/globalFunctions/darkMode'; + import { registerPlugin } from '@capacitor/core'; + + const AppLauncherPlugin = registerPlugin('AppLauncherPlugin'); $: isDarkMode = $darkMode; @@ -16,7 +19,7 @@ async function handleTransportAppClick() { const packageName = 'com.amco.city.thessaloniki'; const iosAppStoreUrl = 'https://apps.apple.com/gr/app/oseth-bus/id6748433667'; - const fallbackUrl = 'https://telematics.oasth.gr/en/#main'; + const fallbackUrl = 'https://oseth.com.gr/el/anazitisi-dromologion-leoforeion/'; //@ts-ignore const ua = navigator.userAgent || navigator.vendor || window.opera; const isAndroid = /android/i.test(ua); From 8e4d3cf807d011f269587ac957c1dd2d649f7fc3 Mon Sep 17 00:00:00 2001 From: Christos Balaktsis Date: Mon, 15 Jun 2026 00:53:09 +0300 Subject: [PATCH 10/16] Remove background color for selectable days Remove background color for selectable days in calendar grid. --- src/lib/components/calendar/CalendarGrid.svelte | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lib/components/calendar/CalendarGrid.svelte b/src/lib/components/calendar/CalendarGrid.svelte index 0ded7cf9..f37371d6 100644 --- a/src/lib/components/calendar/CalendarGrid.svelte +++ b/src/lib/components/calendar/CalendarGrid.svelte @@ -200,7 +200,6 @@ gap: 0.15rem; } .day.selectable { - background: var(--ion-color-light); cursor: pointer; transform: scale(1.05); } From ea6eccca2218c373670384b7964f6cade41daf7f Mon Sep 17 00:00:00 2001 From: Christos Balaktsis Date: Mon, 15 Jun 2026 00:54:26 +0300 Subject: [PATCH 11/16] Remove background from month title in CalendarGrid Removed background color from month title in calendar header. --- src/lib/components/calendar/CalendarGrid.svelte | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/lib/components/calendar/CalendarGrid.svelte b/src/lib/components/calendar/CalendarGrid.svelte index f37371d6..33e1fd6d 100644 --- a/src/lib/components/calendar/CalendarGrid.svelte +++ b/src/lib/components/calendar/CalendarGrid.svelte @@ -163,9 +163,6 @@ transition: background 0.15s ease; font-weight: 500; } - .header .month-title { - background: var(--ion-color-light); - } .header ion-icon { font-size: 1.15rem; From 26fb3fd75170a4aef90399d2a1a44657b471d7e0 Mon Sep 17 00:00:00 2001 From: Neron-png Date: Sun, 14 Jun 2026 23:58:03 +0300 Subject: [PATCH 12/16] Fixed types, deduplicated code, tidied some stuff --- src/lib/components/grades/chips.svelte | 12 +- src/lib/components/grades/courseRow.svelte | 90 +++++++++++ src/lib/components/grades/gradeCard.svelte | 169 ++------------------ src/lib/components/grades/grades.svelte | 13 +- src/lib/components/grades/gradesPage.svelte | 92 +++++------ src/lib/components/grades/statsCard.svelte | 15 +- src/lib/components/shared/Chips.svelte | 2 +- src/lib/functions/gradeAverages/averages.js | 5 +- 8 files changed, 169 insertions(+), 229 deletions(-) create mode 100644 src/lib/components/grades/courseRow.svelte diff --git a/src/lib/components/grades/chips.svelte b/src/lib/components/grades/chips.svelte index 7c59e3d5..96305336 100644 --- a/src/lib/components/grades/chips.svelte +++ b/src/lib/components/grades/chips.svelte @@ -1,13 +1,11 @@ + +
+
+ {course.courseTitle} + + {#if course.examPeriod != null} + + {#if course.examPeriod && course.gradeYear} + {course.examPeriod.name} {course.gradeYear.name} + {:else if course.registrationType === 1} + {$t('progress.exempted')} + {:else} + {$t('progress.declared')} + {/if} + + {:else} + - + {/if} +
+ {#if course.grade != null && !isNaN(course.grade)} + {#if course.grade * 10 >= 5} + +

{course.formattedGrade}

+
+ {:else} + +

{course.formattedGrade}

+
+ {/if} + {/if} +
+ + diff --git a/src/lib/components/grades/gradeCard.svelte b/src/lib/components/grades/gradeCard.svelte index b60b36a9..c9e7e92b 100644 --- a/src/lib/components/grades/gradeCard.svelte +++ b/src/lib/components/grades/gradeCard.svelte @@ -1,22 +1,25 @@ diff --git a/src/lib/components/grades/gradesPage.svelte b/src/lib/components/grades/gradesPage.svelte index 31bd075b..5956f450 100644 --- a/src/lib/components/grades/gradesPage.svelte +++ b/src/lib/components/grades/gradesPage.svelte @@ -12,6 +12,8 @@ import { flipped } from "./flipstore"; import { averagesPerSemester } from '$lib/functions/gradeAverages/averagesPerSemester'; import { writable } from 'svelte/store'; + import type { Writable } from 'svelte/store'; + import type { course } from '$lib/types/courseType'; import Fuse from 'fuse.js'; import { onMount } from 'svelte'; import { t } from "$lib/i18n"; @@ -34,8 +36,14 @@ classes: {id: string;finalGrade: number;coefficient: number;isPassed: number;registration: number;course: string}[]; } - let courseBySemester = writable([]); - let filteredSubjects = writable([]); + interface SemesterGroup { + semesterId: string; + average: string; + courses: course[]; + } + + let semesterGroups: Writable = writable([]); + let filteredSubjects: Writable = writable([]); let registrationsInDegree: Registration[]; const fuseOptions = { @@ -47,17 +55,8 @@ let searchQuery = ''; let subjects = 0; let passedSubjects = 0; - let coursesBySemester = {}; - let subjectsJSON: number | null | undefined; - - /** - * @type {string} - */ - let semesterId: any; - - /** - * @param {{ target: { value: string; }; }} event - */ + let coursesBySemester: { [key: string]: course[] } = {}; + let subjectsJSON: course[] = []; // Search function handleChange(event: { target: { value: string } }) { @@ -69,25 +68,22 @@ $flipped = !$flipped; } - async function getSubjects(subjectsJSON: any) { - coursesBySemester = await coursesPerSemester(subjectsJSON); - // @ts-ignore - passedSubjects = subjects - .filter((/** @type {{ grade: number; }} */ course) => course.grade * 10 >= 5) - .filter(/** @type {{parentCourse: string;}} */ (course) => course.parentCourse === null); - - // @ts-ignore - subjects = subjects.length; - // @ts-ignore - passedSubjects = passedSubjects.length; + async function getSubjects(courses: course[]) { + coursesBySemester = await coursesPerSemester(courses); + const passed = courses + .filter((course) => course.grade * 10 >= 5) + .filter((course) => course.parentCourse == null); + + subjects = courses.length; + passedSubjects = passed.length; } - async function gatherGrades(subjectsJSON: any) { + async function gatherGrades(subjectsJSON: course[]) { const courses = await coursesPerSemester(subjectsJSON); const semesterAverage = await averagesPerSemester(subjectsJSON); // keep semester id, average, and courses in an array - const semesters = Object.keys(courses).map((key) => { + const semesters: SemesterGroup[] = Object.keys(courses).map((key) => { return { semesterId: key, average: semesterAverage[key] ? semesterAverage[key] : '-', @@ -95,32 +91,30 @@ }; }); - semesters.sort((a, b) => a.semesterId - b.semesterId); + semesters.sort((a, b) => Number(a.semesterId) - Number(b.semesterId)); - courseBySemester.set(semesters); + semesterGroups.set(semesters); return semesters; } async function gatherProgressionData(){ - const registration_options = "$select=id,semester,classes&$expand=classes($select=id,finalGrade,coefficient,isPassed,course;$filter=isPassed eq 1)&$orderBy=semester&$top=-1" - const all_registrations: Registration[] = (await neoUniversisGet(`students/me/registrations?${registration_options}`, { lifetime: 1200 })).value - - const calculateGrade_options = "$select=id,course,calculateGrade,isPassed,courseTitle&$filter=calculateGrade eq 0,isPassed eq 1&$top=-1" - const nonCalculatedGrades: {"id": string;"course": string;"calculateGrade": 0;"isPassed": 1;}[] = (await neoUniversisGet(`students/me/courses?${calculateGrade_options}`, { lifetime: 1200 })).value - - const disallowed_courses = new Set(nonCalculatedGrades.map(item => item.course)) - registrationsInDegree = all_registrations.map(registration => ({ + const registrationOptions = "$select=id,semester,classes&$expand=classes($select=id,finalGrade,coefficient,isPassed,course;$filter=isPassed eq 1)&$orderBy=semester&$top=-1" + const allRegistrations: Registration[] = (await neoUniversisGet(`students/me/registrations?${registrationOptions}`, { lifetime: 1200 })).value + + const calculateGradeOptions = "$select=id,course,calculateGrade,isPassed,courseTitle&$filter=calculateGrade eq 0,isPassed eq 1&$top=-1" + const nonCalculatedGrades: { id: string; course: string; calculateGrade: 0; isPassed: 1 }[] = (await neoUniversisGet(`students/me/courses?${calculateGradeOptions}`, { lifetime: 1200 })).value + + const disallowedCourses = new Set(nonCalculatedGrades.map(item => item.course)) + registrationsInDegree = allRegistrations.map(registration => ({ ...registration, - classes: registration.classes.filter(class_instance => !disallowed_courses.has(class_instance.course) && class_instance.isPassed == 1) + classes: registration.classes.filter(classInstance => !disallowedCourses.has(classInstance.course) && classInstance.isPassed == 1) })) - } + } async function gatherData() { - subjects = (await neoUniversisGet('students/me/courses?$top=-1', { lifetime: 600 })).value; - - subjectsJSON = subjects; + subjectsJSON = (await neoUniversisGet('students/me/courses?$top=-1', { lifetime: 600 })).value; await getSubjects(subjectsJSON); await gatherGrades(subjectsJSON); @@ -130,12 +124,12 @@ // Filter the results based on the searchQuery $: { - const courses = $courseBySemester; + const courses = $semesterGroups; if (searchQuery.length === 0) { filteredSubjects.set(courses); } else { - const subjects = courses.reduce((acc, curr) => acc.concat(curr.courses), []); - const fuse = new Fuse(subjects, fuseOptions); + const allCourses = courses.reduce((acc, curr) => acc.concat(curr.courses), []); + const fuse = new Fuse(allCourses, fuseOptions); const searchResults = fuse.search(searchQuery); const filtered = courses.map((semester) => { @@ -170,7 +164,7 @@ /> {#if Object.entries(coursesBySemester).length > 0} - + {/if} @@ -188,12 +182,8 @@ {/if} - - - - - - {:catch error} + + {:catch error} {/await} diff --git a/src/lib/components/grades/statsCard.svelte b/src/lib/components/grades/statsCard.svelte index 665df18d..2b975ce1 100644 --- a/src/lib/components/grades/statsCard.svelte +++ b/src/lib/components/grades/statsCard.svelte @@ -5,12 +5,13 @@ import * as allIonicIcons from 'ionicons/icons'; import Chip from '$components/shared/Chips.svelte'; import { t } from '$lib/i18n'; + import type { course } from '$lib/types/courseType'; - export let subjects; - export let passedSubjects; - export let searchQuery; - export let flip; - export let subjectsJSON: null | undefined; + export let subjects: number; + export let passedSubjects: number; + export let searchQuery: string; + export let flip: () => void; + export let subjectsJSON: course[]; interface Registration { id: number; @@ -20,7 +21,7 @@ interface AveragesResult { avg: number; weighted_avg: number; - grades: never[]; + grades: number[]; ects: number; } @@ -33,7 +34,7 @@ let chart: Chart<'line', any, any>; let chartElement: HTMLCanvasElement; - let gradesObject = { + let gradesObject: { average: number; weightedAverage: number; grades: number[]; ects: number } = { average: 0, weightedAverage: 0, grades: [], diff --git a/src/lib/components/shared/Chips.svelte b/src/lib/components/shared/Chips.svelte index 099f2ac4..2a183041 100644 --- a/src/lib/components/shared/Chips.svelte +++ b/src/lib/components/shared/Chips.svelte @@ -1,6 +1,6 @@ - - - - {#if gender === 'Άντρας'} - man - {:else} - woman - {/if} - {givenName} {familyName} - - {aem} - - - - - - {#if departmentName} - - - - {departmentName} - - {/if} - - {#if username} - - - - {username} - - {/if} - - {#if apm} - - - - {apm} - - {/if} - - {#if birthDate} - - - - {birthDate} - - {/if} - - {#if email} - - - - {email} - - {/if} - - {#if gender} - - - - {gender} - - {/if} - - {#if semester} - - - - {semester} - - {/if} - - {#if study_level} - - - - {study_level} - - {/if} - - - diff --git a/src/routes/personalInfo/personalInfo.svelte b/src/routes/personalInfo/personalInfo.svelte index 05d6e4f4..777af421 100644 --- a/src/routes/personalInfo/personalInfo.svelte +++ b/src/routes/personalInfo/personalInfo.svelte @@ -1,29 +1,41 @@ @@ -56,23 +94,90 @@ {#await getPersonalInfo()} {:then} - + + + {#if gender === 'Άντρας'} + man + {:else} + woman + {/if} + {givenName} {familyName} + + {aem} + + + + + + {#if departmentName} + + + + {departmentName} + + {/if} + + {#if username} + + + + {username} + + {/if} + + {#if apm} + + + + {apm} + + {/if} + + {#if birthDate} + + + + {birthDate} + + {/if} + + {#if email} + + + + {email} + + {/if} + + {#if gender} + + + + {gender} + + {/if} + + {#if semester} + + + + {semester} + + {/if} + + {#if study_level} + + + + {study_level} + + {/if} + {:catch error} {/await} - + @@ -81,4 +186,19 @@ --padding-end: 0.6rem; --padding-start: 0.6rem; } + + .info { + display: flex; + flex-direction: column; + align-items: center; + } + + ion-icon { + color: var(--app-color-icons); + } + + ion-card-subtitle { + font-size: 1.2rem; + padding-left: 5px; + } diff --git a/src/routes/personalInfo/settings.svelte b/src/routes/personalInfo/settings.svelte index b27334c2..70496ee4 100644 --- a/src/routes/personalInfo/settings.svelte +++ b/src/routes/personalInfo/settings.svelte @@ -18,11 +18,8 @@ import About from './about.svelte'; import Faq from './faq.svelte'; import { darkMode } from '$lib/globalFunctions/darkMode'; + import { logOut } from '$lib/globalFunctions/logOut'; - /** - * @type {any} - */ - export let logOut; let languageModalOpen = false; onMount(() => { From 08a75c9b7d15917e08b432d19ecf9f8065ded524 Mon Sep 17 00:00:00 2001 From: Neron-png Date: Fri, 19 Jun 2026 11:49:12 +0300 Subject: [PATCH 14/16] Made gis optional --- src/routes/pages/maps/maps.svelte | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/routes/pages/maps/maps.svelte b/src/routes/pages/maps/maps.svelte index ee163618..cbecee56 100644 --- a/src/routes/pages/maps/maps.svelte +++ b/src/routes/pages/maps/maps.svelte @@ -106,11 +106,14 @@ async function loadRooms() { isLoading = true; - const [roomsData, gisSpaceIds] = await Promise.all([ - helpers.fetchRoomsForBuildings(buildingIds), - gis.getAllSpaceIds() - ]); - buildingsRooms = roomsData; + let gisSpaceIds: Set; + try { + gisSpaceIds = await gis.getAllSpaceIds(); + } catch (e) { + console.warn("GIS service unavailable, room locations will not be shown:", e); + gisSpaceIds = new Set(); + } + buildingsRooms = await helpers.fetchRoomsForBuildings(buildingIds); allRooms = helpers.markRoomsWithGis(helpers.flattenRooms(buildingsRooms), gisSpaceIds); fuse = helpers.createRoomSearch(allRooms); isLoading = false; From 99d4cc65d02fff1af8c5aa976a17e97805e77769 Mon Sep 17 00:00:00 2001 From: Neron-png Date: Fri, 19 Jun 2026 11:58:52 +0300 Subject: [PATCH 15/16] Android version bump --- android/app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 5de6a56d..2866e095 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -10,8 +10,8 @@ android { applicationId "app.aristomate.gr" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion 35 - versionCode 60 - versionName '2.1.8 Lonely' + versionCode 61 + versionName '2.1.9 Flying Whales' testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" aaptOptions { // Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps. From 8b67c74d500a63e676d22881b8025d02ff15778f Mon Sep 17 00:00:00 2001 From: Neron-png Date: Fri, 19 Jun 2026 13:15:33 +0300 Subject: [PATCH 16/16] Fixed averages being broken --- android/app/build.gradle | 4 ++-- src/lib/functions/gradeAverages/averages.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 2866e095..f99979f2 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -10,8 +10,8 @@ android { applicationId "app.aristomate.gr" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion 35 - versionCode 61 - versionName '2.1.9 Flying Whales' + versionCode 62 + versionName '2.1.10 Flying Whales' testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" aaptOptions { // Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps. diff --git a/src/lib/functions/gradeAverages/averages.js b/src/lib/functions/gradeAverages/averages.js index 72cc33ad..c5187a0e 100644 --- a/src/lib/functions/gradeAverages/averages.js +++ b/src/lib/functions/gradeAverages/averages.js @@ -77,7 +77,7 @@ export async function averages(subjectsJSON = null) { // Calculate the weighted average // w_avg = Number((w_sum / ects_sum_countable).toFixed(3)).toFixed(2); - grades = { + const grades = { "grades": g_grades, "avg": g_avg, "weighted_avg": w_avg,