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/android/app/build.gradle b/android/app/build.gradle
index 5de6a56d..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 60
- versionName '2.1.8 Lonely'
+ 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/components/calendar/CalendarGrid.svelte b/src/lib/components/calendar/CalendarGrid.svelte
index 0ded7cf9..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;
@@ -200,7 +197,6 @@
gap: 0.15rem;
}
.day.selectable {
- background: var(--ion-color-light);
cursor: pointer;
transform: scale(1.05);
}
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
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 === 'Άντρας'}
-
- {:else}
-
- {/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 === 'Άντρας'}
+
+ {:else}
+
+ {/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(() => {