File: //home/arjun/projects/buyercall/buyercall/assets/vue/widgets/AppNotification/index.vue
<template>
<div class="dropdown d-inline-block">
<button
type="button"
class="btn header-item noti-icon waves-effect"
@click="showNotficationsSlider = true"
>
<!-- <i class="bx bx-bell bx-tada"></i> -->
<Icon icon="bx:bell" height="20" />
<span class="badge bg-danger rounded-pill" v-if="unreadNotifications > 0">{{
unreadNotifications
}}</span>
</button>
<b-modal
v-model="showNotficationsSlider"
dialog-class="modal-dialog-slideout notification-modal"
:hide-footer="true"
content-class="rounded-0"
header-class="mb-2"
id="workflow-modal"
>
<template #modal-header>
<div class="d-flex justify-content-between align-items-center">
<button
type="button"
class="btn btn-primary"
@click="showNotficationsSlider = false"
>
Close
</button>
<a
href="#"
class="text-reset bg-success badge rounded-pill bg-success p-2"
@click.prevent="reloadNotifications"
v-if="newNotficationsHaveCome"
>You have recieneved new notifications. Reload!<i
class="mdi mdi-arrow-right"
></i
></a>
</div>
</template>
<div class="spinner-main">
<Loader :loading="isLoading || newNotificationsLoading"> </Loader>
</div>
<template v-if="!(isLoading || newNotificationsLoading)">
<div class="row justify-content-center">
<div class="col-xl-12">
<div class="card">
<div class="card-body">
<div class="d-flex justify-content-between align-items-baseline">
<h4 class="card-title mb-4">Notifications</h4>
<b-dropdown
dropleft
class="btn btn-sm px-3 font-size-16 me-2 mb-2 mb-sm-0 notification-dropdown"
>
<template slot="button-content">
<i class="bx bx-dots-vertical-rounded font-size-16"></i>
</template>
<a class="dropdown-item" href="javascript: void(0);">Settings</a>
<a
class="dropdown-item"
:class="{
'hello-world': pushEngageSubscribed ? false : true,
}"
@click="updateUserNotificationStatus"
><i
class="bx bx-loader bx-spin font-size-16 align-middle me-2"
v-if="updateUserNotificationStatusLoading"
></i>
{{ getMuteStatusText }}</a
>
</b-dropdown>
</div>
<p class="card-text text-center" v-if="!notifications.length">
There is no new notifications at this time.
</p>
<div v-else>
<notification-by-day
v-for="(notification, index) in notifications"
:key="index"
:notification="notification"
:bucketLimit="bucketLimit"
></notification-by-day>
<div class="mt-4 text-center" v-if="showViewMoreButton">
<button
type="button"
class="btn btn-primary"
@click="isViewMoreClicked = true"
>
<i
class="bx bx-loader bx-spin font-size-16 align-middle me-2"
v-if="fetchNotificationLoading && isViewMoreClicked"
></i>
View More
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
</b-modal>
</div>
</template>
<script>
import Loader from "../../components/Loader/loader.vue";
import NotificationService from "../../service/notificationService";
import ProfileService from "../../service/profileService";
import NotificationByDay from "./NotificationByDay.vue";
import { toastConfig } from "../../utils/util";
import * as _ from "lodash";
import moment from "moment";
import { BModal, BDropdown } from "bootstrap-vue-next";
import { Icon } from "@iconify/vue";
export default {
components: {
NotificationByDay,
Loader,
BDropdown,
BModal,
Icon,
},
data() {
return {
userDetails: CURRENT_USER_DETAILS,
isSubscribed: false,
pushEngageSubscribed: false,
showNotficationsSlider: false,
unreadNotifications: 0,
unreadNotificationsLoading: false,
fetchNotificationLoading: false,
notifications: [],
rawNotifications: [],
totalNotificationCount: 0,
notificationfetchLimit: 50,
currentPage: 1,
bucketLimit: 4,
updateUserNotificationStatusLoading: false,
unviewedCountIntervalId: null,
newNotficationsHaveCome: false,
isViewMoreClicked: false,
profileLoading: false,
profileData: {},
latestNotificationDetails: null,
syncSubscriptionStatusIntervalId: null,
modalOptions: {
dialogClass: "modal-dialog-slideout notification-modal",
hideFooter: true,
contentClass: "rounded-0",
headerClass: "mb-2",
},
};
},
mounted() {
this.getPushEngageSubscribeStatus();
this.getProfileInfo();
this.getUnviewiedCount();
this.unviewedCountIntervalId = setInterval(() => {
// this.getUnviewiedCount();
}, 5000);
// this.syncSubscriptionStatusIntervalId = setInterval(() => {
// this.getPushEngageSubscribeStatus();
// }, 10000);
},
destroyed() {
clearInterval(this.unviewedCountIntervalId);
clearInterval(this.syncSubscriptionStatusIntervalId);
},
computed: {
isLoading() {
return this.fetchNotificationLoading && !this.isViewMoreClicked;
},
newNotificationsLoading() {
return this.fetchNotificationLoading && this.newNotficationsHaveCome;
},
getMuteStatusText() {
return this.isSubscribed ? "Unsubscribe" : "Subscribe";
},
showViewMoreButton() {
if (this.totalNotificationCount > 0) {
const totalNumberOfPages = Math.ceil(
this.totalNotificationCount / this.notificationfetchLimit
);
if (totalNumberOfPages !== this.currentPage) {
return true;
}
}
return false;
},
},
methods: {
getPushEngageSubscribeStatus() {
let that = this;
window._peq.push([
// we can show a button
"subscriber-status",
function (res) {
// console.log(res);
if (res.statuscode === 1) {
that.pushEngageSubscribed = true;
}
if (res.statuscode === 1) {
if (that.profileData && !that.profileData.isSubscribed) {
that.pushEngageSubscribed = true;
}
} else {
if (that.profileData && that.profileData.isSubscribed) {
that.pushEngageSubscribed = false;
that.updateUserNotificationStatusCustom(false);
}
}
},
]);
},
logNotification() {
const validTypes = ["MISSED_CALL", "TEXT_MESSAGE", "FORM_SUBMISSION", "VOICE_MAIL"];
NotificationService.logNotifications(
this.userDetails.userID,
validTypes[Math.floor(Math.random() * validTypes.length)]
)
.then(({ data: { success, data } }) => {
console.log(success, data);
})
.catch((e) => {
console.log("error", e);
});
},
updateUserNotificationStatus() {
// first execute script, then API
this.updateUserNotificationStatusLoading = true;
NotificationService.updateUserNotificationStatus(!this.isSubscribed)
.then(({ data: { success, message } }) => {
if (success) {
this.updateUserNotificationStatusLoading = false;
this.$toast.open(toastConfig.toastSuccess(message));
this.getProfileInfo();
} else {
this.updateUserNotificationStatusLoading = false;
}
})
.catch((e) => {
this.updateUserNotificationStatusLoading = false;
console.log("error", e);
});
},
updateUserNotificationStatusCustom(status) {
// first execute script, then API
NotificationService.updateUserNotificationStatus(status)
.then(({ data: { success, message } }) => {
if (success) {
this.getProfileInfo();
} else {
}
})
.catch((e) => {
console.log("error", e);
});
},
getProfileInfo() {
this.profileLoading = true;
ProfileService.getProfileInfo()
.then(({ data: { success, message, data } }) => {
if (success) {
this.profileLoading = false;
this.profileData = data;
this.isSubscribed = data.isSubscribed;
} else {
this.$toast.open(toastConfig.toastError(message));
this.profileLoading = false;
this.profileData = null;
}
})
.catch((e) => {
this.profileLoading = false;
this.profileData = null;
console.log("error", e);
this.$toast.open(
toastConfig.toastError("Something went wrong while fetching profile details!")
);
});
},
getUnviewiedCount() {
this.unreadNotificationsLoading = true;
NotificationService.getUnviewiedCount()
.then(({ data: { success, data } }) => {
if (success) {
this.unreadNotificationsLoading = false;
this.unreadNotifications = data.count;
if (this.showNotficationsSlider) {
this.latestNotificationDetails = { ...data };
}
} else {
this.unreadNotificationsLoading = false;
}
})
.catch((e) => {
this.unreadNotificationsLoading = false;
console.log("error", e);
});
},
getUserNotifications(limit, offset) {
this.fetchNotificationLoading = true;
NotificationService.getUserNotifications(limit, offset)
.then(({ data: { success, data } }) => {
this.isViewMoreClicked = false;
this.newNotficationsHaveCome = false;
if (success) {
this.fetchNotificationLoading = false;
if (data.notifications.length) {
this.rawNotifications = [...this.rawNotifications, ...data.notifications];
let tempNotifications = _.map(this.rawNotifications, (n) => {
const createdAt = new Date(n.createdAt);
const createdDay = moment(createdAt).format("L");
const isyesterday =
createdDay === moment().subtract(1, "days").format("L");
const istoday = createdDay === moment().format("L");
return {
...n,
createdAt,
createdByDay: moment(createdAt).format("L"),
timeFormattedString: moment(createdAt).fromNow(),
dateFormattedString: moment(createdAt).format("MMM Do"),
isyesterday,
istoday,
};
});
tempNotifications = _.groupBy(tempNotifications, "createdByDay");
this.notifications = _.map(
_.orderBy(_.keys(tempNotifications), (k) => moment(k), ["desc"]),
(d) => ({
day: d,
notifications: _.orderBy(
tempNotifications[d],
(k) => moment(k.createdAt),
["desc"]
),
})
);
this.totalNotificationCount = data.totalRecordCount;
}
this.currentPage = offset / limit + 1;
} else {
this.fetchNotificationLoading = false;
}
})
.catch((e) => {
this.isViewMoreClicked = false;
this.fetchNotificationLoading = false;
console.log("error", e);
});
},
reloadNotifications() {
this.notifications = [];
this.rawNotifications = [];
this.totalNotificationCount = 0;
this.currentPage = 1;
this.newNotficationsHaveCome = false;
this.isViewMoreClicked = false;
this.getUserNotifications(this.notificationfetchLimit, 0);
},
},
watch: {
showNotficationsSlider(v) {
if (v) {
this.getUserNotifications(this.notificationfetchLimit, 0);
} else {
this.notifications = [];
this.rawNotifications = [];
this.totalNotificationCount = 0;
this.currentPage = 1;
this.newNotficationsHaveCome = false;
this.isViewMoreClicked = false;
this.latestNotificationDetails = null;
}
},
latestNotificationDetails(v, prevValue) {
if (
this.showNotficationsSlider &&
v !== null &&
prevValue !== null &&
v.lastFetchedNotficationId !== prevValue.lastFetchedNotficationId
) {
if (new Date(v.createdAt) > new Date(prevValue.createdAt)) {
this.newNotficationsHaveCome = true;
}
}
},
isViewMoreClicked(v) {
if (v) {
this.getUserNotifications(
this.notificationfetchLimit,
this.notificationfetchLimit * this.currentPage
);
}
},
},
};
</script>