diff --git a/frontend/package.json b/frontend/package.json index e9ef71e8..87765826 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -9,6 +9,11 @@ "lint": "eslint . --fix --ignore-path .gitignore" }, "dependencies": { + "@fortawesome/fontawesome-svg-core": "^6.4.0", + "@fortawesome/free-brands-svg-icons": "^6.4.0", + "@fortawesome/free-regular-svg-icons": "^6.4.0", + "@fortawesome/free-solid-svg-icons": "^6.4.0", + "@fortawesome/vue-fontawesome": "^3.0.3", "@mdi/font": "7.0.96", "@mdi/js": "^7.2.96", "@vuepic/vue-datepicker": "^5.0.1", diff --git a/frontend/src/assets/stylesheets/components/0_components.scss b/frontend/src/assets/stylesheets/components/0_components.scss index 20071c30..86f6650c 100644 --- a/frontend/src/assets/stylesheets/components/0_components.scss +++ b/frontend/src/assets/stylesheets/components/0_components.scss @@ -1,4 +1,5 @@ @import "./admin-dashboard.scss"; +@import "./alerts.scss"; @import "./buttons.scss"; @import "./cards.scss"; @import "./events.scss"; diff --git a/frontend/src/assets/stylesheets/components/alerts.scss b/frontend/src/assets/stylesheets/components/alerts.scss new file mode 100644 index 00000000..49a28ee4 --- /dev/null +++ b/frontend/src/assets/stylesheets/components/alerts.scss @@ -0,0 +1,10 @@ +.v-alert-title { + text-transform: capitalize !important; +} + +.v-alert__close { + .v-icon:before { + position: relative; + content: "✖"; + } +} \ No newline at end of file diff --git a/frontend/src/components/auth/UserForm.vue b/frontend/src/components/auth/UserForm.vue index 7b2e4929..d30e29e9 100644 --- a/frontend/src/components/auth/UserForm.vue +++ b/frontend/src/components/auth/UserForm.vue @@ -91,7 +91,6 @@ import { PropType, toRefs } from 'vue'; import { Form, Field } from 'vee-validate'; import * as Yup from 'yup'; -import router from '@/router'; import { getSubmitFn } from '@/helpers'; import { User } from "@/models/user.model"; import { useAuthStore, useUsersStore } from "@/store" @@ -141,7 +140,6 @@ const onSubmit = getSubmitFn(schema, async (values: User) => { await usersStore.updateAccount(values, authStore.currentUser.id); } else { await usersStore.register(values); - router.push("/login"); } } catch (err) { console.log(err) diff --git a/frontend/src/components/events/EventCard.vue b/frontend/src/components/events/EventCard.vue index 06c2dc00..0c51150f 100644 --- a/frontend/src/components/events/EventCard.vue +++ b/frontend/src/components/events/EventCard.vue @@ -13,7 +13,7 @@ \ No newline at end of file diff --git a/frontend/src/layouts/Event.vue b/frontend/src/layouts/Event.vue index c27e9350..51889c11 100644 --- a/frontend/src/layouts/Event.vue +++ b/frontend/src/layouts/Event.vue @@ -1,15 +1,20 @@ \ No newline at end of file diff --git a/frontend/src/layouts/View.vue b/frontend/src/layouts/View.vue index 9e5778ed..f4c31f8e 100644 --- a/frontend/src/layouts/View.vue +++ b/frontend/src/layouts/View.vue @@ -1,9 +1,12 @@ diff --git a/frontend/src/models/alert.model.ts b/frontend/src/models/alert.model.ts new file mode 100644 index 00000000..a1dec298 --- /dev/null +++ b/frontend/src/models/alert.model.ts @@ -0,0 +1,5 @@ +export interface Alert { + type: string; + message: string; + icon?: string; +} \ No newline at end of file diff --git a/frontend/src/models/event.model.ts b/frontend/src/models/event.model.ts index 17bca911..8cfcbae4 100644 --- a/frontend/src/models/event.model.ts +++ b/frontend/src/models/event.model.ts @@ -1,9 +1,9 @@ export interface Event { - id?: number, - event_title: string, - description?: string, - start_date: Date, - end_date?: Date, - uid: string, - user_id: string + id?: number; + event_title: string; + description?: string; + start_date: Date; + end_date?: Date; + uid: string; + user_id: string; } \ No newline at end of file diff --git a/frontend/src/models/user.model.ts b/frontend/src/models/user.model.ts index 8ea3c201..504b3deb 100644 --- a/frontend/src/models/user.model.ts +++ b/frontend/src/models/user.model.ts @@ -1,15 +1,15 @@ export interface User { - id?: number, - first_name: string, - last_name: string, - preferred_username: string, - email: string, - current_password?: string, - password?: string, - password_confirmation?: string + id?: number; + first_name: string; + last_name: string; + preferred_username: string; + email: string; + current_password?: string; + password?: string; + password_confirmation?: string; } export interface Login { - email: string, - password: string + email: string; + password: string; } diff --git a/frontend/src/plugins/index.ts b/frontend/src/plugins/index.ts index 2966c439..d68b74d1 100644 --- a/frontend/src/plugins/index.ts +++ b/frontend/src/plugins/index.ts @@ -9,11 +9,19 @@ import { loadFonts } from './webfontloader' import vuetify from './vuetify' import { createPinia } from 'pinia' import router from '@/router' -import VueDatePicker from '@vuepic/vue-datepicker'; + +import VueDatePicker from '@vuepic/vue-datepicker' +import { library } from "@fortawesome/fontawesome-svg-core" +import { fas } from "@fortawesome/free-solid-svg-icons" +import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome" + import '@vuepic/vue-datepicker/dist/main.css' +import '@fortawesome/fontawesome-free/css/all.css' import { Vue3Mq } from "vue3-mq"; +library.add(fas) + // Types import type { App } from 'vue' @@ -21,6 +29,7 @@ export function registerPlugins (app: App) { loadFonts() app .component('VueDatePicker', VueDatePicker) + .component("font-awesome-icon", FontAwesomeIcon) .use(vuetify) .use(router) .use(Vue3Mq, { diff --git a/frontend/src/store/alert.store.ts b/frontend/src/store/alert.store.ts new file mode 100644 index 00000000..b433ea80 --- /dev/null +++ b/frontend/src/store/alert.store.ts @@ -0,0 +1,20 @@ +import { defineStore } from "pinia"; +import { Alert } from "@/models/alert.model"; + +export const useAlertStore = defineStore({ + id: "alert", + state: () => ({ + alert: null as Alert | null + }), + actions: { + success(message) { + this.alert = { message, type: "success", icon: "mdi:mdi-checkbox-marked-circle" } + }, + error(message) { + this.alert = {message, type: "error", icon: "mdi:mdi-alert" } + }, + clear() { + this.alert = null; + } + } +}) diff --git a/frontend/src/store/event.store.ts b/frontend/src/store/event.store.ts index e8d9ddf3..3e41e4d0 100644 --- a/frontend/src/store/event.store.ts +++ b/frontend/src/store/event.store.ts @@ -2,7 +2,7 @@ import { defineStore } from "pinia"; import router from "@/router"; import { BASE_URL, fetchWrapper } from "@/helpers"; -import { useAuthStore } from "./auth.store"; +import { useAlertStore, useAuthStore } from "@/store"; import { Event } from "@/models/event.model"; export const useEventStore = defineStore({ @@ -16,6 +16,7 @@ export const useEventStore = defineStore({ actions: { async createEvent(params: Event) { const authStore = useAuthStore(); + const alertStore = useAlertStore(); try { const userId = authStore.currentUser.id; params.user_id = userId @@ -24,8 +25,9 @@ export const useEventStore = defineStore({ }); this.getAllUserEvents(); router.push("/events"); + alertStore.success("Yay") } catch (err) { - console.log(err); + alertStore.error(err) } }, async getAllEvents() { diff --git a/frontend/src/store/index.ts b/frontend/src/store/index.ts index a23e9d20..5fef74ac 100644 --- a/frontend/src/store/index.ts +++ b/frontend/src/store/index.ts @@ -1,4 +1,5 @@ export * from "./admin.store"; +export * from "./alert.store"; export * from "./auth.store"; export * from "./event.store"; export * from "./users.store"; diff --git a/frontend/src/store/users.store.ts b/frontend/src/store/users.store.ts index 54d950a2..679fb0b4 100644 --- a/frontend/src/store/users.store.ts +++ b/frontend/src/store/users.store.ts @@ -2,7 +2,7 @@ import { defineStore } from "pinia"; import { BASE_URL, fetchWrapper } from "@/helpers"; import { User } from "@/models/user.model"; -import { useAuthStore } from "./auth.store"; +import { useAlertStore, useAuthStore } from "@/store"; import router from "@/router"; export const useUsersStore = defineStore({ @@ -16,10 +16,18 @@ export const useUsersStore = defineStore({ localStorage.setItem("users", JSON.stringify(response)); }, async register(user: User) { - const newAccount = { user }; - await fetchWrapper.post(`${BASE_URL}signup`, newAccount); + const alertStore = useAlertStore(); + try { + const newAccount = { user }; + await fetchWrapper.post(`${BASE_URL}signup`, newAccount); + alertStore.success("A message with a confirmation link has been sent to your email address. Please follow the link to activate your account.") + router.push("/login"); + } catch (err) { + alertStore.error(err); + } }, async updateAccount(user: User, userId: number) { + const alertStore = useAlertStore(); const authStore = useAuthStore(); const updates = { user }; const currentUser = authStore.currentUser; @@ -28,13 +36,15 @@ export const useUsersStore = defineStore({ if (currentUser.id === userId) { const response = await fetchWrapper.put(`${BASE_URL}signup`, updates); authStore.updateCurrentUser(response.data); + alertStore.success("Your account was successfully updated.") router.push("/account"); } } catch (err) { - console.log(err); + alertStore.error(err); } }, async deleteAccount(value: string) { + const alertStore = useAlertStore(); const authStore = useAuthStore(); const currentUser = authStore.currentUser; @@ -46,8 +56,9 @@ export const useUsersStore = defineStore({ }); authStore.logout(); router.push("/login") + alertStore.success("Your account was successfully deleted.") } catch (err) { - console.log(err); + alertStore.error(err); } } } diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 25ae599e..83e70dd3 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -175,6 +175,44 @@ resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.39.0.tgz#58b536bcc843f4cd1e02a7e6171da5c040f4d44b" integrity sha512-kf9RB0Fg7NZfap83B3QOqOGg9QmD9yBudqQXzzOtn3i4y7ZUXe5ONeW34Gwi+TxhH4mvj72R1Zc300KUMa9Bng== +"@fortawesome/fontawesome-common-types@6.4.0": + version "6.4.0" + resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.4.0.tgz#88da2b70d6ca18aaa6ed3687832e11f39e80624b" + integrity sha512-HNii132xfomg5QVZw0HwXXpN22s7VBHQBv9CeOu9tfJnhsWQNd2lmTNi8CSrnw5B+5YOmzu1UoPAyxaXsJ6RgQ== + +"@fortawesome/fontawesome-svg-core@^6.4.0": + version "6.4.0" + resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.4.0.tgz#3727552eff9179506e9203d72feb5b1063c11a21" + integrity sha512-Bertv8xOiVELz5raB2FlXDPKt+m94MQ3JgDfsVbrqNpLU9+UE2E18GKjLKw+d3XbeYPqg1pzyQKGsrzbw+pPaw== + dependencies: + "@fortawesome/fontawesome-common-types" "6.4.0" + +"@fortawesome/free-brands-svg-icons@^6.4.0": + version "6.4.0" + resolved "https://registry.yarnpkg.com/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.4.0.tgz#c785cf5563231eadc5ef5f8cd0274e0b8920433f" + integrity sha512-qvxTCo0FQ5k2N+VCXb/PZQ+QMhqRVM4OORiO6MXdG6bKolIojGU/srQ1ptvKk0JTbRgaJOfL2qMqGvBEZG7Z6g== + dependencies: + "@fortawesome/fontawesome-common-types" "6.4.0" + +"@fortawesome/free-regular-svg-icons@^6.4.0": + version "6.4.0" + resolved "https://registry.yarnpkg.com/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.4.0.tgz#cacc53bd8d832d46feead412d9ea9ce80a55e13a" + integrity sha512-ZfycI7D0KWPZtf7wtMFnQxs8qjBXArRzczABuMQqecA/nXohquJ5J/RCR77PmY5qGWkxAZDxpnUFVXKwtY/jPw== + dependencies: + "@fortawesome/fontawesome-common-types" "6.4.0" + +"@fortawesome/free-solid-svg-icons@^6.4.0": + version "6.4.0" + resolved "https://registry.yarnpkg.com/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.4.0.tgz#48c0e790847fa56299e2f26b82b39663b8ad7119" + integrity sha512-kutPeRGWm8V5dltFP1zGjQOEAzaLZj4StdQhWVZnfGFCvAPVvHh8qk5bRrU4KXnRRRNni5tKQI9PBAdI6MP8nQ== + dependencies: + "@fortawesome/fontawesome-common-types" "6.4.0" + +"@fortawesome/vue-fontawesome@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@fortawesome/vue-fontawesome/-/vue-fontawesome-3.0.3.tgz#633e2998d11f7d4ed41f0d5ea461a22ec9b9d034" + integrity sha512-KCPHi9QemVXGMrfuwf3nNnNo129resAIQWut9QTAMXmXqL2ErABC6ohd2yY5Ipq0CLWNbKHk8TMdTXL/Zf3ZhA== + "@humanwhocodes/config-array@^0.11.8": version "0.11.8" resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.8.tgz#03595ac2075a4dc0f191cc2131de14fbd7d410b9"