Merge branch 'dev' into lint-action-setup

This commit is contained in:
Tibo De Peuter 2025-03-04 21:45:46 +01:00
commit a4d34afcb3
Signed by: tdpeuter
GPG key ID: 38297DE43F75FFE2
32 changed files with 3116 additions and 2918 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

View file

@ -1,7 +1,186 @@
<script setup lang="ts"></script>
<script setup lang="ts">
import { ref } from "vue";
import { useRoute } from "vue-router";
import dwengoLogo from "../../../assets/img/dwengo-groen-zwart.svg";
const route = useRoute();
// Instantiate variables to use in html to render right
// Links and content dependent on the role (student or teacher)
const isTeacher = route.path.includes("teacher");
const userId = route.params.id as string;
const role = isTeacher ? "teacher" : "student";
const name = "Kurt Cobain";
const initials = name
.split(" ")
.map((n) => {
return n[0];
})
.join("");
const languages = ref([
{ name: "English", code: "en" },
{ name: "Nederlands", code: "nl" },
]);
// Logic to change the language of the website to the selected language
const changeLanguage = (langCode: string) => {
console.log(langCode);
};
</script>
<template>
<main></main>
<main>
<nav class="menu">
<div class="left">
<ul>
<li>
<router-link
:to="`/${role}/${userId}`"
class="dwengo_home"
>
<img
class="dwengo_logo"
:src="dwengoLogo"
/>
<p class="caption">
{{ role }}
</p>
</router-link>
</li>
<li>
<router-link
:to="`/${role}/${userId}/assignment`"
class="menu_item"
>
assignments
</router-link>
</li>
<li>
<router-link
:to="`/${role}/${userId}/class`"
class="menu_item"
>classes</router-link
>
</li>
<li>
<router-link
:to="`/${role}/${userId}/discussion`"
class="menu_item"
>discussions</router-link
>
</li>
<li>
<v-menu open-on-hover>
<template v-slot:activator="{ props }">
<v-btn
v-bind="props"
icon
variant="text"
>
<v-icon
icon="mdi-translate"
size="small"
color="#0e6942"
></v-icon>
</v-btn>
</template>
<v-list>
<v-list-item
v-for="(language, index) in languages"
:key="index"
@click="changeLanguage(language.code)"
>
<v-list-item-title>{{ language.name }}</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>
</li>
</ul>
</div>
<div class="right">
<li>
<router-link :to="`/login`">
<v-tooltip
text="log out"
location="bottom"
>
<template v-slot:activator="{ props }">
<v-icon
v-bind="props"
icon="mdi-logout"
size="x-large"
color="#0e6942"
></v-icon>
</template>
</v-tooltip>
</router-link>
</li>
<li>
<v-avatar
size="large"
color="#0e6942"
style="font-size: large; font-weight: bold"
>{{ initials }}</v-avatar
>
</li>
</div>
</nav>
</main>
</template>
<style scoped></style>
<style scoped>
.menu {
background-color: #f6faf2;
display: flex;
justify-content: space-between;
}
.right {
align-items: center;
padding: 10px;
}
.right li {
margin-left: 15px;
}
nav ul {
display: flex;
list-style-type: none;
margin: 0;
padding: 0;
gap: 15px;
align-items: center;
}
li {
display: inline;
}
.dwengo_home {
text-align: center;
text-decoration: none;
}
.dwengo_logo {
width: 150px;
}
.caption {
color: black;
margin-top: -25px;
}
.menu_item {
color: #0e6942;
text-decoration: none;
font-size: large;
}
nav a.router-link-active {
font-weight: bold;
}
</style>

View file

@ -14,6 +14,11 @@ const app = createApp(App);
app.use(router);
const link = document.createElement("link");
link.rel = "stylesheet";
link.href = "https://cdn.jsdelivr.net/npm/@mdi/font@5.x/css/materialdesignicons.min.css";
document.head.appendChild(link);
const vuetify = createVuetify({
components,
directives,

View file

@ -0,0 +1,20 @@
/**
* Converts a Base64 string to a valid image source URL.
*
* @param base64String - The "image" field from the learning path JSON response.
* @returns A properly formatted data URL for use in an <img> tag.
*
* @example
* // Fetch the learning path data and extract the image
* const response = await fetch( learning path route );
* const data = await response.json();
* const base64String = data.image;
*
* // Use in an <img> element
* <img :src="convertBase64ToImageSrc(base64String)" alt="Learning Path Image" />
*/
export function convertBase64ToImageSrc(base64String: string): string {
return base64String.startsWith("data:image")
? base64String
: `data:image/png;base64,${base64String}`;
}

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,24 @@
import { describe, it, expect, beforeAll } from 'vitest';
import { convertBase64ToImageSrc } from '../../src/utils/base64ToImage.js';
import fs from 'fs';
import path from 'path';
let sampleBase64: string;
beforeAll(() => {
// Load base64 sample from text file
const filePath = path.resolve(__dirname, 'base64Sample.txt');
sampleBase64 = fs.readFileSync(filePath, 'utf8').trim();
});
describe('convertBase64ToImageSrc', () => {
it('should return the same string if it is already a valid data URL', () => {
const base64Image = `data:image/png;base64,${sampleBase64}`;
expect(convertBase64ToImageSrc(base64Image)).toBe(base64Image);
});
it('should correctly format a raw Base64 string as a PNG image URL', () => {
expect(convertBase64ToImageSrc(sampleBase64)).toBe(`data:image/png;base64,${sampleBase64}`);
});
});