From eb2a4fa54ca783e1a53c9a0ef86a3cceb8b7080d Mon Sep 17 00:00:00 2001 From: Raajheer1 Date: Mon, 27 May 2024 14:59:39 -0500 Subject: [PATCH] Add backend integration --- .gitignore | 1 + package.json | 34 +- src/App.vue | 12 + src/components/profile/Profile.vue | 73 +- src/router/index.ts | 63 +- src/stores/user.ts | 35 +- src/types/index.d.ts | 3 + src/utils/rating.ts | 57 + src/views/Home.vue | 6 +- src/views/Profile.vue | 5 +- src/views/partials/Header.vue | 8 +- tsconfig.json | 3 - vite.config.ts | 12 +- yarn.lock | 1599 +++++++++++++++------------- 14 files changed, 1063 insertions(+), 848 deletions(-) create mode 100644 src/utils/rating.ts diff --git a/.gitignore b/.gitignore index 7ceb59f..df708e2 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,4 @@ dist-ssr *.sln *.sw? .env +/certs/* diff --git a/package.json b/package.json index 5c3af1d..1864a7a 100644 --- a/package.json +++ b/package.json @@ -12,31 +12,33 @@ "lint:fix": "eslint src --ext .ts,.js,.vue --fix" }, "dependencies": { - "axios": "^1.6.7", + "@vitejs/plugin-basic-ssl": "^1.1.0", + "axios": "^1.7.2", "pinia": "^2.1.6", - "vue": "^3.3.4", - "vue-router": "4" + "vue": "^3.4.27", + "vue-router": "4.3.2" }, "devDependencies": { - "@typescript-eslint/eslint-plugin": "^7.1.1", - "@typescript-eslint/parser": "^7.1.1", - "@vitejs/plugin-vue": "^4.2.3", - "@vue/eslint-config-prettier": "^8.0.0", - "@vue/eslint-config-typescript": "^12.0.0", - "autoprefixer": "^10.4.15", - "eslint": "^8.49.0", + "@typescript-eslint/eslint-plugin": "^7.10.0", + "@typescript-eslint/parser": "^7.10.0", + "@vitejs/plugin-vue": "^5.0.4", + "@vue/eslint-config-prettier": "^9.0.0", + "@vue/eslint-config-typescript": "^13.0.0", + "autoprefixer": "^10.4.19", + "eslint": "8.57.0", "eslint-config-airbnb-base": "^15.0.0", "eslint-config-airbnb-typescript": "latest", "eslint-import-resolver-typescript": "latest", "eslint-plugin-import": "latest", "eslint-plugin-prettier": "latest", - "eslint-plugin-vue": "latest", - "postcss": "^8.4.30", + "eslint-plugin-vue": "9.26.0", + "postcss": "^8.4.38", "prettier": "^3.2.5", - "tailwindcss": "^3.3.3", - "typescript": "^5.0.2", - "vite": "^4.4.5", + "tailwindcss": "^3.4.3", + "typescript": "^5.4.5", + "vite": "^5.2.11", + "vite-plugin-mkcert": "^1.17.5", "vite-plugin-vue-type-imports": "^0.2.5", - "vue-tsc": "latest" + "vue-tsc": "2.0.19" } } diff --git a/src/App.vue b/src/App.vue index 0f8d04b..2d17720 100644 --- a/src/App.vue +++ b/src/App.vue @@ -9,8 +9,20 @@ diff --git a/src/components/profile/Profile.vue b/src/components/profile/Profile.vue index e37b837..7a6c2a7 100644 --- a/src/components/profile/Profile.vue +++ b/src/components/profile/Profile.vue @@ -3,11 +3,11 @@

Personal Details

-
+

First name

Last name

Email

Preferred Name

@@ -42,7 +42,7 @@

Preferred OIs

@@ -50,7 +50,7 @@

Pilot Rating

Controller Rating

Facility Details

-
+
Facility
Type
@@ -78,7 +78,7 @@
Exit Date
import { ref } from "vue"; -import { User } from "@/types"; +import { User, Roster } from "@/types"; + +const props = defineProps<{ + user: User | null; + rosters: Roster[] | null; +}>(); -const user = ref({ - cid: 1, - first_name: "John", - last_name: "Doe", - preferred_name: "Johnny", - email: "vatusa6@vatusa.net", - preferred_ois: "JD", - pilot_rating: 1, - controller_rating: 1, - discord_id: "1234567890", - rosters: [ - { - id: 1, - cid: 1, - facility: "ZAB", - operating_initials: "ZZ", - home: true, - visiting: false, - status: "active", - created_at: "2021-08-01T00:00:00.000Z", - deleted_at: "2021-08-01T00:00:00.000Z", - }, - { - id: 2, - cid: 1, - facility: "ZDV", - operating_initials: "ZZ", - home: false, - visiting: true, - status: "active", - created_at: "2021-08-01T00:00:00.000Z", - deleted_at: "2021-08-01T00:00:00.000Z", - }, - { - id: 3, - cid: 1, - facility: "ZLC", - operating_initials: "ZZ", - home: true, - visiting: false, - status: "active", - created_at: "2021-08-01T00:00:00.000Z", - }, - ], -} as User); +const editableUser = ref(props.user); diff --git a/src/router/index.ts b/src/router/index.ts index 89b80e7..7a51d6d 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -1,6 +1,5 @@ -import { createRouter, createWebHistory, Router } from "vue-router"; -// -// import useUserStore from "@/stores/user"; +import { createRouter, createWebHistory, NavigationGuard, Router } from "vue-router"; +import useUserStore from "@/stores/user"; declare module "vue-router" { interface RouteMeta { @@ -60,40 +59,30 @@ const buildRouter = (): Router => { const router = buildRouter(); -// const check: NavigationGuard = (to, from, next): void => { -// const userStore = useUserStore(); -// const { requiresAuth } = to.meta; -// -// if (requiresAuth && !userStore.user) { -// next({ name: "Login" }); -// return; -// } -// -// if (requiresAuth && userStore.user) { -// const { requiresRole } = to.meta; -// if (requiresRole) { -// if (!requiresRole.includes(userStore.user.role)) { -// next({ name: "Forbidden" }); -// return; -// } -// } -// } -// -// next(); -// }; +const check: NavigationGuard = (to, from, next): void => { + const userStore = useUserStore(); -// router.beforeEach((to, from, next) => { -// const userStore = useUserStore(); -// if (!userStore.hasFetched) { -// if (userStore.loading === null || userStore.loading === undefined) { -// userStore.loading = userStore.fetchUser(); -// } -// userStore.loading.then(() => { -// check(to, from, next); -// }); -// } else { -// check(to, from, next); -// } -// }); + if (!userStore.user) { + // TODO - Redirect to SSO with a return URL + next({ name: "Login" }); + return; + } + + next(); +}; + +router.beforeEach((to, from, next) => { + const userStore = useUserStore(); + if (!userStore.hasFetched) { + if (userStore.loading === null || userStore.loading === undefined) { + userStore.loading = userStore.fetchUser(); + } + userStore.loading.then(() => { + check(to, from, next); + }); + } else { + check(to, from, next); + } +}); export default router; diff --git a/src/stores/user.ts b/src/stores/user.ts index b0c8656..fe3a184 100644 --- a/src/stores/user.ts +++ b/src/stores/user.ts @@ -1,4 +1,7 @@ import { defineStore } from "pinia"; +import { API } from "@/utils/api"; +import { User } from "@/types"; +import { getControllerRating, getPilotRating } from "@/utils/rating"; interface UserState { user: User | null; @@ -8,14 +11,6 @@ interface UserState { loading: Promise | null; } -interface User { - id: number; - firstName: string; - lastName: string; - email: string; - role: string; -} - const useUserStore = defineStore("user", { state: () => ({ @@ -26,6 +21,30 @@ const useUserStore = defineStore("user", { }) as UserState, getters: { isLoggedIn: (state) => !!state.user, + fullName: (state) => { + if (!state.user) return ""; + return `${state.user.first_name} ${state.user.last_name}`; + }, + }, + actions: { + async fetchUser() { + this.fetching = true; + try { + const { data } = await API.get("/v3/user"); + this.user = data; + if (this.user?.controller_rating) { + this.user.controller_rating_string = getControllerRating(this.user?.controller_rating); + } + if (this.user?.pilot_rating) { + this.user.pilot_rating_string = getPilotRating(this.user?.pilot_rating); + } + } catch (e) { + this.user = null; + } finally { + this.fetching = false; + this.hasFetched = true; + } + }, }, }); diff --git a/src/types/index.d.ts b/src/types/index.d.ts index f60ac85..3061158 100644 --- a/src/types/index.d.ts +++ b/src/types/index.d.ts @@ -30,10 +30,13 @@ export interface User { first_name: string; last_name: string; preferred_name: string; + pref_name_enabled: boolean; email: string; preferred_ois: string; pilot_rating: number; + pilot_rating_string: string; controller_rating: number; + controller_rating_string: string; discord_id: string; rosters?: Roster[]; } diff --git a/src/utils/rating.ts b/src/utils/rating.ts new file mode 100644 index 0000000..cfbae21 --- /dev/null +++ b/src/utils/rating.ts @@ -0,0 +1,57 @@ +export const getControllerRating = (rating: number | undefined): string => { + if (rating === undefined) return "UNK"; + switch (rating) { + case -1: + return "AFK"; + case 0: + return "SUS"; + case 1: + return "OBS"; + case 2: + return "S1"; + case 3: + return "S2"; + case 4: + return "S3"; + case 5: + return "C1"; + case 6: + return "C2"; + case 7: + return "C3"; + case 8: + return "I1"; + case 9: + return "I2"; + case 10: + return "I3"; + case 11: + return "SUP"; + case 12: + return "ADM"; + default: + return "UNK"; + } +}; + +export const getPilotRating = (rating: number | undefined): string => { + if (rating === undefined) return "UNK"; + switch (rating) { + case 0: + return "NA"; + case 1: + return "PPL"; + case 3: + return "IR"; + case 7: + return "CMEL"; + case 15: + return "ATPL"; + case 31: + return "FI"; + case 63: + return "FE"; + default: + return "UNK"; + } +}; diff --git a/src/views/Home.vue b/src/views/Home.vue index e051254..59e3116 100644 --- a/src/views/Home.vue +++ b/src/views/Home.vue @@ -1,5 +1,5 @@