Socialify

Folder ..

Viewing notficationComponent.ts
115 lines (108 loc) • 6.3 KB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
/**
 * notfications Component
 * 
 * generates a HTML component which will be used to display notifications
 */

import { getAuth } from "firebase/auth";
import { app } from "../handlers/firebaseHandler";
import { collection, query, where, onSnapshot, setDoc, orderBy, limit } from "firebase/firestore";
import { db } from "../handlers/databaseHandler";
import { mutationObserver } from "../handlers/mutationObserver";
import { notify } from "../functions/toasts";

const auth = getAuth(app);

export const notificationsComponent = () => {
    mutationObserver('notificationsButton', () => {
        const notifications = document.getElementById('notificationsButton');
        const handleLoginContainer = document.getElementById("handleLoginContainer");
        if (notifications && handleLoginContainer) {
            const user = auth.currentUser?.uid;
            if (user) {
                const notificationsRef = collection(db, "userProfiles", user, "notifications");
                const notificationsQuery = query(notificationsRef, where("read", "==", false));
                notifications.classList.add('has-notifications');
                onSnapshot(notificationsQuery, (snapshot) => {
                    if (snapshot.size > 0) {
                        notifications.classList.add('has-notifications');
                        // Notifications which are not read and also not shown are shown
                        snapshot.forEach((doc) => {
                            const notification = doc.data();
                            if (!notification.shown) {
                                notify({ title: notification.title, body: notification.body });
                                setDoc(doc.ref, { shown: true }, { merge: true });
                            }
                        });

                    } else {
                        notifications.classList.remove('has-notifications');
                    }
                });
            }
        }
    });
}

export const notificationDropdownComponent = () => {
    mutationObserver('notificationsButton', () => {
        const handleLoginContainer = document.getElementById("handleLoginContainer");
        const dropdownContainer = document.createElement("div");
        dropdownContainer.id = "notificationDropdown";
        dropdownContainer.classList.add("dropdown");
        dropdownContainer.style.display = "none";
        const dropdownContents = document.createElement("div");
        dropdownContents.style.maxHeight = "300px";
        dropdownContents.style.overflowY = "auto";
        dropdownContainer.appendChild(dropdownContents);
        if (handleLoginContainer) {
            const user = auth.currentUser?.uid;
            if (user) {
                const allNotificationsQuery = query(collection(db, "userProfiles", user, "notifications"), orderBy("timestamp", "desc"), limit(50));
                onSnapshot(allNotificationsQuery, (snapshot) => {
                    const snapshotData = snapshot.docs.map((doc) => {
                        const data = doc.data();
                        data.ref = doc.ref;
                        return data;
                    });
                    document.getElementById("notificationDropdown") && document.getElementById("notificationDropdown")?.innerHTML === "" ? null : dropdownContents.innerHTML = "";
                    const notificationContainers = document.getElementsByClassName("notificationContainer");
                    while (notificationContainers[0]) {
                        notificationContainers[0].parentNode?.removeChild(notificationContainers[0]);
                    }
                    if (snapshotData.length > 0) {
                        snapshotData.forEach((notification) => {
                            const notificationContainer = document.createElement("div");
                            notificationContainer.classList.add("notificationContainer");
                            const readIndicator = document.createElement("div");
                            notification.read ? readIndicator.classList.add("readIndicator", "read") : readIndicator.classList.add("readIndicator", "unread");
                            notificationContainer.appendChild(readIndicator);
                            const textContainer = document.createElement("div");
                            const notificationTitle = document.createElement("h3");
                            notificationTitle.classList.add("notificationTitle");
                            notificationTitle.appendChild(document.createTextNode(notification.title));
                            const notificationBody = document.createElement("p");
                            notificationBody.classList.add("notificationBody");
                            notificationBody.appendChild(document.createTextNode(notification.body));
                            textContainer.appendChild(notificationTitle);
                            textContainer.appendChild(notificationBody);
                            notificationContainer.appendChild(textContainer);

                            readIndicator.addEventListener("click", () => {
                                event?.stopPropagation();
                                notification.read ? setDoc(notification.ref, { read: false }, { merge: true }) : setDoc(notification.ref, { read: true }, { merge: true });
                            });

                            textContainer.addEventListener("click", () => {
                                event?.stopPropagation();
                                setDoc(notification.ref, { read: true }, { merge: true });
                                window.location.href = '/' + notification.link;
                            });
                            dropdownContents.appendChild(notificationContainer);
                        });
                    } else {
                        const notificationContainer = document.createElement("div");
                        notificationContainer.innerHTML = "No notifications";
                        notificationContainer.style.textAlign = "center";
                        notificationContainer.style.padding = "1rem";
                        dropdownContents.appendChild(notificationContainer);
                    }
                });
            }
            handleLoginContainer.appendChild(dropdownContainer);
        }
    });
}