Skip to content

Commit

Permalink
feat: Add email notifications
Browse files Browse the repository at this point in the history
  • Loading branch information
Tobi2K committed Nov 24, 2024
1 parent 1be4194 commit d626cf8
Show file tree
Hide file tree
Showing 4 changed files with 183 additions and 5 deletions.
34 changes: 34 additions & 0 deletions src/store/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,16 @@ export async function requestUserSeasons(): Promise<AxiosResponse<any, any>> {
});
}

/**
* Gets all email subscriptions for the user
* @return {Promise<AxiosResponse<any, any>>} axios request promise
*/
export async function requestUserSubscriptions(): Promise<AxiosResponse<any, any>> {
return axios.get(process.env.VUE_APP_HOST + "/email/subscribed", {
headers: { Authorization: `Bearer ${store.state.user.accessToken}` },
});
}

/**
* Gets user data
* @return {Promise<AxiosResponse<any, any>>} axios request promise
Expand Down Expand Up @@ -298,6 +308,30 @@ export async function getVersion(): Promise<AxiosResponse<any, any>> {
});
}

/**
* Subscribes a user to email notifications
* @return {Promise<AxiosResponse<any, any>>} axios request promise
*/
export async function subscribeEmail(
parameter: { seasonID: string, isToday: boolean },
): Promise<AxiosResponse<any, any>> {
return axios.post(process.env.VUE_APP_HOST + "/email/subscribe", parameter, {
headers: { Authorization: `Bearer ${store.state.user.accessToken}` },
});
}

/**
* Subscribes a user to email notifications
* @return {Promise<AxiosResponse<any, any>>} axios request promise
*/
export async function unsubscribeEmail(
parameter: { seasonID: string, isToday: boolean },
): Promise<AxiosResponse<any, any>> {
return axios.post(process.env.VUE_APP_HOST + "/email/unsubscribe", parameter, {
headers: { Authorization: `Bearer ${store.state.user.accessToken}` },
});
}

/**
* Generates a toast to be shown at the bottom of the screen
* @param {string} toastMessage the message to be displayed
Expand Down
61 changes: 61 additions & 0 deletions src/store/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export const store = createStore({
competitions: [],
seasons: [],
userSeasons: [],
userSubscriptions: [],
newGroupSeason: {},
groupData: null,
userGroups: [],
Expand Down Expand Up @@ -62,6 +63,9 @@ export const store = createStore({
UPDATE_USER_SEASONS(state, userSeasons) {
state.userSeasons = userSeasons;
},
UPDATE_USER_SUBSCRIPTIONS(state, userSubscriptions) {
state.userSubscriptions = userSubscriptions;
},
UPDATE_NEW_GROUP_SEASON(state, newGroupSeason) {
state.newGroupSeason = newGroupSeason;
},
Expand Down Expand Up @@ -833,6 +837,63 @@ export const store = createStore({
commit("UPDATE_LOADING", false);
});
},
getUserSubscriptions({ commit, dispatch }) {
commit("UPDATE_LOADING", true);
helper
.requestUserSubscriptions()
.then((response) => {
console.log(response.data);

commit("UPDATE_USER_SUBSCRIPTIONS", response.data);
})
.catch((e) => {
dispatch("handleError", {
error: e,
message: "Failed to get your subscriptions.",
});
})
.finally(() => {
commit("UPDATE_LOADING", false);
});
},
subscribeEmail({ commit, dispatch }, parameter: { seasonID: string, isToday: boolean }) {
commit("UPDATE_LOADING", true);
helper
.subscribeEmail(parameter)
.then((response) => {
console.log(response.data);

commit("UPDATE_USER_SUBSCRIPTIONS", response.data);
})
.catch((e) => {
dispatch("handleError", {
error: e,
message: "Failed to add your subscriptions.",
});
})
.finally(() => {
commit("UPDATE_LOADING", false);
});
},
unsubscribeEmail({ commit, dispatch }, parameter: { seasonID: string, isToday: boolean }) {
commit("UPDATE_LOADING", true);
helper
.unsubscribeEmail(parameter)
.then((response) => {
console.log(response.data);

commit("UPDATE_USER_SUBSCRIPTIONS", response.data);
})
.catch((e) => {
dispatch("handleError", {
error: e,
message: "Failed to add your subscriptions.",
});
})
.finally(() => {
commit("UPDATE_LOADING", false);
});
},
handleError({ commit, dispatch }, { error, message }) {
if (error && error.response && error.response.status == 401) {
router.push("/");
Expand Down
83 changes: 78 additions & 5 deletions src/views/Settings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,10 @@
</ion-row>
</ion-list>
<ion-list>
<h3>Notification Settings</h3>
<h3>Device Notification Settings</h3>
<p>
These settings are device-wide. Even when logging out, notifications
are still received.
are still received.
</p>
<ion-row>
<ion-col>
Expand All @@ -102,7 +102,7 @@
</ion-row>
<ion-list-header
>Notifications for group information (e.g. point
distribution).</ion-list-header
distribution or perfect games).</ion-list-header
>
<div v-if="groupNoti">
<ion-item v-for="group in userGroups" :key="group">
Expand Down Expand Up @@ -141,7 +141,7 @@
</ion-button>
</ion-col>
</ion-row>
<ion-list-header>Notifications for pending games.</ion-list-header>
<ion-list-header>Notifications for pending games (at 12 PM CEST).</ion-list-header>
<div v-if="gameNoti">
<ion-item v-for="season in userSeasons" :key="season">
<ion-toggle
Expand All @@ -154,6 +154,60 @@
</ion-item>
</div>
</ion-list>

<ion-list>
<h3>Email Notification Settings</h3>
<p>
You will receive a notification (at 12:15 PM CEST) via the email used to register. Please add <a href="mailto:toptips@kalmbach.dev">toptips@kalmbach.dev</a> to your email contacts for optimal delivery.
</p>
<ion-row>
<ion-col>
<h6>Game Notifications</h6>
</ion-col>
<ion-col>
<ion-button
class="ion-float-right"
v-if="emailNoti"
fill="clear"
@click="emailNoti = !emailNoti"
>
Hide
</ion-button>
<ion-button
class="ion-float-right"
v-else
fill="clear"
@click="emailNoti = !emailNoti"
>
Show
</ion-button>
</ion-col>
</ion-row>
<ion-list-header>Notifications for pending games.</ion-list-header>
<div v-if="emailNoti">
<div v-for="subscription in userSubscriptions" :key="subscription">
<ion-item>
<ion-toggle
@ionChange="subscribeEmail(subscription, true)"
:value="subscription.day_of"
:checked="subscription.day_of"
>
Day-Of Notifications for {{ subscription.season.name }} <small>({{ subscription.season.competition.country }})</small>
</ion-toggle>
</ion-item>
<ion-item>
<ion-toggle
@ionChange="subscribeEmail(subscription, false)"
:value="subscription.day_before"
:checked="subscription.day_before"
>
Day-Before Notifications for {{ subscription.season.name }} <small>({{ subscription.season.competition.country }})</small>
</ion-toggle>
</ion-item>
</div>
</div>
</ion-list>

<p style="text-align: center; margin-top: 100px;">
<small>
If you have any suggestions, questions or complaints, feel free to contact me at
Expand Down Expand Up @@ -257,6 +311,7 @@ export default defineComponent({
newPass: "",
repeatPass: "",
gameNoti: false,
emailNoti: false,
groupNoti: false,
showDeleteButton: false,
consequences: false,
Expand Down Expand Up @@ -499,6 +554,23 @@ export default defineComponent({
const escapedID = id.replaceAll(":", "");
return localStorage.getItem(escapedID) == "true";
},
subscribeEmail(subscription: { day_of: boolean; season: { id: any; }; day_before: boolean; }, dayOf: boolean) {
if (dayOf) {
subscription.day_of = !subscription.day_of
if (subscription.day_of) {
this.$store.dispatch("subscribeEmail", {"seasonID": subscription.season.id, "isToday": dayOf});
} else {
this.$store.dispatch("unsubscribeEmail", {"seasonID": subscription.season.id, "isToday": dayOf});
}
} else {
subscription.day_before = !subscription.day_before
if (subscription.day_before) {
this.$store.dispatch("subscribeEmail", {"seasonID": subscription.season.id, "isToday": dayOf});
} else {
this.$store.dispatch("unsubscribeEmail", {"seasonID": subscription.season.id, "isToday": dayOf});
}
}
},
generateAlert(message: string) {
showToast(message);
},
Expand All @@ -507,8 +579,9 @@ export default defineComponent({
this.$store.dispatch("checkJWT");
this.username = this.$store.state.user.username;
this.$store.dispatch("getUserSeasons");
this.$store.dispatch("getUserSubscriptions");
},
computed: mapState(["userSeasons", "userGroups"]),
computed: mapState(["userSeasons", "userGroups", "userSubscriptions"]),
});
</script>

Expand Down
10 changes: 10 additions & 0 deletions src/vuex-shim.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ declare module "@vue/runtime-core" {
competitions: Competition[];
seasons: Season[];
userSeasons: Season[];
userSubscriptions: Season[];
newGroupSeason: {
name: string;
year: number;
Expand Down Expand Up @@ -68,6 +69,7 @@ export interface State {
competitions: Competition[];
seasons: Season[];
userSeasons: Season[];
userSubscriptions: [];
newGroupSeason: {
name: string;
year: number;
Expand Down Expand Up @@ -126,6 +128,14 @@ export interface Season {
competition: Competition;
}

export interface EmailNotify {
id: number;
user_id: string;
season_id: string;
day_of: boolean;
day_before: boolean;
}

export interface Group {
id: number;
group: {
Expand Down

0 comments on commit d626cf8

Please sign in to comment.