Skip to content
Snippets Groups Projects
Commit 7da8bab7 authored by Henrik Teksle Sandok's avatar Henrik Teksle Sandok
Browse files

Merge branch 'main' into 'Badges'

# Conflicts:
#   spec.json
#   src/components/BaseComponents/NavBar.vue
parents f2a19046 f3f0eab4
Branches Badges
No related tags found
1 merge request!80feat: Adding badges and menu selected visual
Pipeline #283382 passed with warnings
......@@ -24,44 +24,47 @@ install_dependencies:
build_project:
stage: build
script:
- npm ci
- npm run build
dependencies:
- install_dependencies
cache:
key: "${CI_COMMIT_REF_SLUG}"
paths:
- node_modules/
policy: pull
vitest_unit-tests:
stage: test
script:
- npm ci
- npm run test:unit
- npm run build
dependencies:
- install_dependencies
vitest_unit-tests:
stage: test
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- node_modules/
policy: pull
eslint_run-lint:
stage: lint
script:
- npm ci
- npm run lint
- npm run test:unit
dependencies:
- install_dependencies
eslint_run-lint:
stage: lint
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- node_modules/
policy: pull
script:
- npm ci
- npm run lint
dependencies:
- install_dependencies
allow_failure: true
......@@ -79,8 +79,8 @@
}
],
"responses": {
"404": {
"description": "Friend request not found",
"200": {
"description": "Friend request successfully accepted",
"content": {
"*/*": {
"schema": {
......@@ -89,8 +89,8 @@
}
}
},
"200": {
"description": "Friend request successfully accepted",
"404": {
"description": "Friend request not found",
"content": {
"*/*": {
"schema": {
......@@ -120,8 +120,8 @@
}
],
"responses": {
"404": {
"description": "Friend or friend request not found",
"200": {
"description": "Friend successfully deleted or friend request cancelled",
"content": {
"*/*": {
"schema": {
......@@ -130,8 +130,8 @@
}
}
},
"200": {
"description": "Friend successfully deleted or friend request cancelled",
"404": {
"description": "Friend or friend request not found",
"content": {
"*/*": {
"schema": {
......@@ -162,8 +162,8 @@
"required": true
},
"responses": {
"404": {
"description": "Bank profile id does not exist",
"200": {
"description": "No accounts associated with a bank user",
"content": {
"*/*": {
"schema": {
......@@ -172,8 +172,8 @@
}
}
},
"200": {
"description": "No accounts associated with a bank user",
"404": {
"description": "Bank profile id does not exist",
"content": {
"*/*": {
"schema": {
......@@ -204,8 +204,8 @@
"required": true
},
"responses": {
"400": {
"description": "Could not create profile",
"200": {
"description": "Successfully created a bank profile",
"content": {
"*/*": {
"schema": {
......@@ -214,8 +214,8 @@
}
}
},
"200": {
"description": "Successfully created a bank profile",
"400": {
"description": "Could not create profile",
"content": {
"*/*": {
"schema": {
......@@ -246,8 +246,8 @@
"required": true
},
"responses": {
"404": {
"description": "Provided bank profile id could not be found",
"200": {
"description": "Successfully created account",
"content": {
"*/*": {
"schema": {
......@@ -256,8 +256,8 @@
}
}
},
"200": {
"description": "Successfully created account",
"404": {
"description": "Provided bank profile id could not be found",
"content": {
"*/*": {
"schema": {
......@@ -339,11 +339,11 @@
"required": true
},
"responses": {
"403": {
"description": "Invalid token"
},
"204": {
"description": "Password was reset successfully"
},
"403": {
"description": "Invalid token"
}
},
"security": []
......@@ -368,8 +368,8 @@
"required": true
},
"responses": {
"500": {
"description": "User is not found",
"200": {
"description": "Successfully updated notification",
"content": {
"*/*": {
"schema": {
......@@ -378,8 +378,8 @@
}
}
},
"200": {
"description": "Successfully updated notification",
"500": {
"description": "User is not found",
"content": {
"*/*": {
"schema": {
......@@ -411,6 +411,12 @@
}
],
"responses": {
"201": {
"description": "Item purchased and added to inventory successfully",
"content": {
"application/json": {}
}
},
"403": {
"description": "Insufficient points to purchase the item",
"content": {
......@@ -420,14 +426,6 @@
}
}
}
},
"201": {
"description": "Item purchased and added to inventory successfully",
"content": {
"application/json": {
}
}
}
}
}
......@@ -547,6 +545,9 @@
"required": true
},
"responses": {
"200": {
"description": "Successfully updated the challenge"
},
"401": {
"description": "Day is already completed or day outside of range",
"content": {
......@@ -556,9 +557,6 @@
}
}
}
},
"200": {
"description": "Successfully updated the challenge"
}
}
}
......@@ -594,7 +592,7 @@
"Friend"
],
"summary": "Send a friend request",
"description": "Sends a new friend request to another user.",
"description": "Sends a new friend request to another user. A notification is sent to this user",
"operationId": "addFriendRequest",
"parameters": [
{
......@@ -644,8 +642,8 @@
"required": true
},
"responses": {
"500": {
"description": "Budget is not found",
"200": {
"description": "Successfully updated budget",
"content": {
"application/json": {
"schema": {
......@@ -654,8 +652,8 @@
}
}
},
"200": {
"description": "Successfully updated budget",
"500": {
"description": "Budget is not found",
"content": {
"application/json": {
"schema": {
......@@ -697,8 +695,8 @@
"required": true
},
"responses": {
"500": {
"description": "Error updating expense",
"200": {
"description": "Successfully updated budget",
"content": {
"application/json": {
"schema": {
......@@ -707,8 +705,8 @@
}
}
},
"200": {
"description": "Successfully updated budget",
"500": {
"description": "Error updating expense",
"content": {
"application/json": {
"schema": {
......@@ -771,22 +769,22 @@
}
],
"responses": {
"409": {
"description": "Email already exists",
"200": {
"description": "Email is valid",
"content": {
"*/*": {
"schema": {
"$ref": "#/components/schemas/ExceptionResponse"
"type": "object"
}
}
}
},
"200": {
"description": "Email is valid",
"409": {
"description": "Email already exists",
"content": {
"*/*": {
"schema": {
"type": "object"
"$ref": "#/components/schemas/ExceptionResponse"
}
}
}
......@@ -814,22 +812,22 @@
"required": true
},
"responses": {
"409": {
"description": "Email already exists",
"201": {
"description": "Successfully signed up",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ExceptionResponse"
"$ref": "#/components/schemas/AuthenticationResponse"
}
}
}
},
"201": {
"description": "Successfully signed up",
"409": {
"description": "Email already exists",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/AuthenticationResponse"
"$ref": "#/components/schemas/ExceptionResponse"
}
}
}
......@@ -1112,8 +1110,8 @@
}
],
"responses": {
"404": {
"description": "Bank profile id does not exist",
"200": {
"description": "No accounts associated with a bank user",
"content": {
"*/*": {
"schema": {
......@@ -1125,8 +1123,8 @@
}
}
},
"200": {
"description": "No accounts associated with a bank user",
"404": {
"description": "Bank profile id does not exist",
"content": {
"*/*": {
"schema": {
......@@ -1741,8 +1739,8 @@
}
],
"responses": {
"500": {
"description": "Budget is not found",
"200": {
"description": "Successfully got budget",
"content": {
"application/json": {
"schema": {
......@@ -1751,8 +1749,8 @@
}
}
},
"200": {
"description": "Successfully got budget",
"500": {
"description": "Budget is not found",
"content": {
"application/json": {
"schema": {
......@@ -1863,8 +1861,8 @@
}
],
"responses": {
"500": {
"description": "Budget is not found",
"200": {
"description": "Successfully deleted budget",
"content": {
"application/json": {
"schema": {
......@@ -1873,8 +1871,8 @@
}
}
},
"200": {
"description": "Successfully deleted budget",
"500": {
"description": "Budget is not found",
"content": {
"application/json": {
"schema": {
......@@ -1974,8 +1972,8 @@
}
],
"responses": {
"500": {
"description": "Badge is not found",
"200": {
"description": "Successfully got budget",
"content": {
"application/json": {
"schema": {
......@@ -1984,8 +1982,8 @@
}
}
},
"200": {
"description": "Successfully got budget",
"500": {
"description": "Badge is not found",
"content": {
"application/json": {
"schema": {
......
......@@ -13,6 +13,7 @@ export type { AccountResponseDTO } from './models/AccountResponseDTO';
export type { AuthenticationResponse } from './models/AuthenticationResponse';
export type { BadgeDTO } from './models/BadgeDTO';
export type { BankAccountDTO } from './models/BankAccountDTO';
export type { BankIDRequest } from './models/BankIDRequest';
export type { BankProfile } from './models/BankProfile';
export type { BankProfileDTO } from './models/BankProfileDTO';
export type { BankProfileResponseDTO } from './models/BankProfileResponseDTO';
......@@ -34,6 +35,7 @@ export type { LeaderboardDTO } from './models/LeaderboardDTO';
export type { LeaderboardEntryDTO } from './models/LeaderboardEntryDTO';
export type { LoginRequest } from './models/LoginRequest';
export type { MarkChallengeDTO } from './models/MarkChallengeDTO';
export { NotificationDTO } from './models/NotificationDTO';
export type { PasswordResetDTO } from './models/PasswordResetDTO';
export type { PasswordUpdateDTO } from './models/PasswordUpdateDTO';
export type { ProfileDTO } from './models/ProfileDTO';
......@@ -53,5 +55,7 @@ export { GoalService } from './services/GoalService';
export { ImageService } from './services/ImageService';
export { ItemService } from './services/ItemService';
export { LeaderboardService } from './services/LeaderboardService';
export { NotificationService } from './services/NotificationService';
export { RedirectService } from './services/RedirectService';
export { TransactionControllerService } from './services/TransactionControllerService';
export { UserService } from './services/UserService';
/* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export type BankIDRequest = {
code?: string;
state?: string;
};
/* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export type NotificationDTO = {
id?: number;
message?: string;
unread?: boolean;
notificationType?: NotificationDTO.notificationType;
createdAt?: string;
};
export namespace NotificationDTO {
export enum notificationType {
BADGE = 'BADGE',
FRIEND_REQUEST = 'FRIEND_REQUEST',
COMPLETED_GOAL = 'COMPLETED_GOAL',
}
}
......@@ -3,6 +3,7 @@
/* tslint:disable */
/* eslint-disable */
import type { AuthenticationResponse } from '../models/AuthenticationResponse';
import type { BankIDRequest } from '../models/BankIDRequest';
import type { LoginRequest } from '../models/LoginRequest';
import type { SignUpRequest } from '../models/SignUpRequest';
import type { CancelablePromise } from '../core/CancelablePromise';
......@@ -74,4 +75,22 @@ export class AuthenticationService {
},
});
}
/**
* Authenticate a BankID request
* Authenticate a BankID request
* @returns AuthenticationResponse If the authentication is successful
* @throws ApiError
*/
public static bankIdAuthentication({
requestBody,
}: {
requestBody: BankIDRequest,
}): CancelablePromise<AuthenticationResponse> {
return __request(OpenAPI, {
method: 'POST',
url: '/api/auth/bank-id',
body: requestBody,
mediaType: 'application/json',
});
}
}
......@@ -53,7 +53,7 @@ export class FriendService {
}
/**
* Send a friend request
* Sends a new friend request to another user.
* Sends a new friend request to another user. A notification is sent to this user
* @returns any Friend request successfully created
* @throws ApiError
*/
......
......@@ -79,9 +79,7 @@ export class GoalService {
});
}
/**
* Update a challenge
* Update a challenge day as completed
* @returns any Successfully updated the challenge
* @returns GoalDTO OK
* @throws ApiError
*/
public static getGoal({
......
/* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import type { NotificationDTO } from '../models/NotificationDTO';
import type { CancelablePromise } from '../core/CancelablePromise';
import { OpenAPI } from '../core/OpenAPI';
import { request as __request } from '../core/request';
export class NotificationService {
/**
* Updates a notification
* Updates a notification based on the request
* @returns any Successfully updated notification
* @throws ApiError
*/
public static updateNotification({
requestBody,
}: {
requestBody: NotificationDTO,
}): CancelablePromise<Record<string, any>> {
return __request(OpenAPI, {
method: 'POST',
url: '/api/notification/update',
body: requestBody,
mediaType: 'application/json',
errors: {
500: `User is not found`,
},
});
}
/**
* Get the list of notifications
* Get all notifications to a user
* @returns NotificationDTO Successfully got notifications
* @throws ApiError
*/
public static getNotificationByUser(): CancelablePromise<Array<NotificationDTO>> {
return __request(OpenAPI, {
method: 'GET',
url: '/api/notification',
});
}
/**
* Get the notification
* Get notification by its id
* @returns NotificationDTO Successfully got notification
* @throws ApiError
*/
public static getNotification({
notificationId,
}: {
notificationId: number,
}): CancelablePromise<NotificationDTO> {
return __request(OpenAPI, {
method: 'GET',
url: '/api/notification/{notificationId}',
path: {
'notificationId': notificationId,
},
errors: {
500: `Notification is not found`,
},
});
}
/**
* Get the list of unread notifications
* Get all unread notifications to a user
* @returns NotificationDTO Successfully got notifications
* @throws ApiError
*/
public static getUnreadNotificationByUser(): CancelablePromise<Array<NotificationDTO>> {
return __request(OpenAPI, {
method: 'GET',
url: '/api/notification/unread',
});
}
}
/* generated using openapi-typescript-codegen -- do not edit */
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
import type { CancelablePromise } from '../core/CancelablePromise';
import { OpenAPI } from '../core/OpenAPI';
import { request as __request } from '../core/request';
export class RedirectService {
/**
* @returns any OK
* @throws ApiError
*/
public static consumeCallback({
state,
}: {
state: string,
}): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'GET',
url: '/redirect',
query: {
'state': state,
},
});
}
}
......@@ -4,10 +4,6 @@
/* eslint-disable */
import type { Account } from '../models/Account';
import type { BankAccountDTO } from '../models/BankAccountDTO';
import type { BudgetRequestDTO } from '../models/BudgetRequestDTO';
import type { BudgetResponseDTO } from '../models/BudgetResponseDTO';
import type { ExpenseRequestDTO } from '../models/ExpenseRequestDTO';
import type { ExpenseResponseDTO } from '../models/ExpenseResponseDTO';
import type { FeedbackRequestDTO } from '../models/FeedbackRequestDTO';
import type { FeedbackResponseDTO } from '../models/FeedbackResponseDTO';
import type { PasswordResetDTO } from '../models/PasswordResetDTO';
......
......@@ -36,6 +36,30 @@
<img src="@/assets/icons/storefront.svg">Butikk
</router-link>
</li>
<li class="nav-item dropdown">
<a data-mdb-dropdown-init class=" nav-link dropdown-toggle hidden-arrow notification" href="#" id="navbarDropdownMenuLink"
role="button" data-bs-toggle="dropdown" aria-expanded="false">
<img src="/src/assets/icons/bell-white.svg">
<span v-if="notificationListRef.length > 0" class="badge rounded-pill badge-notification bg-danger">{{ notificationListRef.length }}</span>
</a>
<ul v-if="notificationListRef.length > 0" class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
<li v-for="(item, index) in notificationListRef" :key="index" >
<router-link :to="notificationPathMapper[String(item.notificationType)]"
class="d-flex align-items-center"
@click="readNotification(item)">
<div class="flex-shrink-0">
<img :src="notificationImageMapper[String(item.notificationType)]" alt="Varslingsikon" class="notification-icon">
</div>
<div class="flex-grow-1 ms-3">
<div class="not-item dropdown-item">{{item.message}}</div>
</div>
</router-link>
</li>
</ul>
<ul v-else class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
<li>Ingen varslinger</li>
</ul>
</li>
<li v-if="userStore.isLoggedIn" class="nav-item dropdown">
......@@ -134,6 +158,8 @@
import { useRouter, useRoute } from "vue-router";
import { useUserInfoStore } from '@/stores/UserStore';
import {onMounted, ref} from "vue";
import { type NotificationDTO, NotificationService } from '@/api'
import { afterWrite } from '@popperjs/core'
......@@ -150,21 +176,11 @@ if (useUserInfoStore().profileImage !== 0) {
profileImage = 'src/assets/userprofile.png';
}
//Hashmap that contains the path to the Badges, The Friend, The dashboard etc.
//The key value pair is the message of the notification and the path of the route
let notifMap = ref (new Map<number, any[]>);
let notifId = ref(0);
let path = ref('#');
let counter = ref(0)
let notificationListRef = ref<NotificationDTO[]>([]);
/* id: 0 -> /roadmap
id: 1 -> /profile
id: 2 -> /friend
*/
function isAnyActivePage() {
const activeRoutes = ['/roadmap', '/leaderboard', '/news', '/shop']; // Add other pages here
......@@ -178,20 +194,36 @@ function toggleDropdown(event: any) {
}
}
function getNotification(){
//axios call
let response: any = ref( ['1', 'You have recived a award for getting 200 points'])
let response2: any = ref( ['2', 'You have recived a friend request from Jens Aanestad'])
let response3: any = ref( ['3', 'You have lost your streak. Come back to try again'])
notifMap.value.set(notifId.value,response.value)
notifId.value++
notifMap.value.set(notifId.value,response2.value)
notifId.value++
notifMap.value.set(notifId.value,response3.value)
notifId.value++
counter.value = notifMap.value.size
const notificationImageMapper: any = {
"FRIEND_REQUEST": "/src/assets/userprofile.png",
"BADGE": "/src/assets/icons/medal.png",
"COMPLETED_GOAL": "/src/assets/icons/piggybank.svg"
}
const notificationPathMapper: any = {
"FRIEND_REQUEST": "/friends",
"BADGE": "/profile",
"COMPLETED_GOAL": "/roadmap"
}
const getNotifications = async () => {
try {
notificationListRef.value = await NotificationService.getUnreadNotificationByUser()
} catch (error) {
notificationListRef.value = []
}
}
const readNotification = async (notification: NotificationDTO) => {
try {
notification.unread = false;
await NotificationService.updateNotification({requestBody: notification});
notificationListRef.value = await NotificationService.getUnreadNotificationByUser()
} catch (error) {
notificationListRef.value = [];
}
}
function toBadges(){
}
......@@ -264,7 +296,7 @@ function toLogout() {
router.push('login')
}
onMounted(() => {
getNotification()
getNotifications()
})
</script>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment