// eslint-disable-next-line spaced-comment /// interface Package { openCode: string; pickupPoint: Locker; senderName: string; shipmentNumber: string; status: PackageStatus; } interface Locker { name: string; status: string; description: string; location: Location; address: Address; } interface Address { buildingNumber: string; city: string; postCode: string; province: string; street: string; } interface Location { latitude: number; longitude: number; } enum PackageStatus { /** Przesyłka została utworzona, ale nie jest gotowa do nadania. */ CREATED = "created", /** Oferty dla przesyłki zostały przygotowane. */ OFFERS_PREPARED = "offers_prepared", /** Klient wybrał jedną z zaproponowanych ofert. */ OFFER_SELECTED = "offer_selected", /** Nadawca poinformował nas, że przygotował przesyłkę do nadania. Podróż przesyłki jeszcze się nie rozpoczęła. */ CONFIRMED = "confirmed", /** Paczka oczekuje na wyjęcie z Paczkomatu przez doręczyciela. Stąd trafi do najbliższego oddziału InPost i wyruszy w trasę do Paczkomatu odbiorczego. */ DISPATCHED_BY_SENDER = "dispatched_by_sender", /** Kurier odebrał paczkę od Nadawcy i przekazuje ją do oddziału InPost. */ COLLECTED_FROM_SENDER = "collected_from_sender", /** Przesyłka została odebrana od Nadawcy i wyruszyła w dalszą drogę. */ TAKEN_BY_COURIER = "taken_by_courier", /** Przesyłka trafiła do oddziału InPost, skąd wkrótce wyruszy w dalszą drogę. */ ADOPTED_AT_SOURCE_BRANCH = "adopted_at_source_branch", /** Przesyłka jest transportowana między oddziałami InPost. */ SENT_FROM_SOURCE_BRANCH = "sent_from_source_branch", /** Prosimy o odebranie przesyłki z punktu InPost w ciągu 3 dni. */ READY_TO_PICKUP_FROM_POK = "ready_to_pickup_from_pok", /** Prosimy o odebranie przesyłki z punktu InPost w ciągu 3 dni. Adres. */ READY_TO_PICKUP_FROM_POK_REGISTERED = "ready_to_pickup_from_pok_registered", /** Paczka nie mieści się w skrytce Paczkomatu. */ OVERSIZED = "oversized", /** Przesyłka czeka na przesiadkę do miasta docelowego. W Sortowni Głównej zatrzymuje się na chwilę większość przesyłek InPost. W supernowoczesnym magazynie sortowanych jest nawet milion przesyłek dziennie! */ ADOPTED_AT_SORTING_CENTER = "adopted_at_sorting_center", /** Przesyłka jedzie do miasta Odbiorcy. */ SENT_FROM_SORTING_CENTER = "sent_from_sorting_center", /** Przesyłka jest już w mieście Odbiorcy. Wkrótce trafi do rąk doręczyciela i rozpocznie ostatni etap podróży. */ ADOPTED_AT_TARGET_BRANCH = "adopted_at_target_branch", /** Przesyłka trafi do odbiorcy najpóźniej w najbliższym dniu roboczym. Doręczyciel InPost rozwozi przesyłki nawet do późnych godzin wieczornych, dlatego warto mieć włączony telefon. */ OUT_FOR_DELIVERY = "out_for_delivery", /** I gotowe! Paczka poczeka na odbiór 48 godzin od momentu umieszczenia w Paczkomacie. Odbiorca otrzymuje SMS-a i e-maila z kodem odbioru. Jeśli paczka nie zostanie odebrana w tym czasie, zostanie zwrócona do Nadawcy, o czym poinformujemy Odbiorcę w osobnych komunikatach. */ READY_TO_PICKUP = "ready_to_pickup", /** Paczka oczekuje w Paczkomacie. Przetrzymamy ją tylko przez kolejne 24 godziny. Jeśli nie zostanie odebrana z Paczkomatu, zostanie zwrócona do Nadawcy. Jeśli chcesz odpłatnie przedłużyć pobyt przesyłki w Paczkomacie, przeczytaj o SMS’ach Premium na naszej stronie https://inpost.pl/pomoc-jak-przedluzyc-termin-odbioru-paczki-w-paczkomacie. */ PICKUP_REMINDER_SENT = "pickup_reminder_sent", /** Podróż przesyłki od Nadawcy do Odbiorcy zakończyła się, ale nie musi to oznaczać końca naszej znajomości:) Jeśli lubisz InPost, odwiedź nasz fanpage na Facebooku. Dziękujemy! */ DELIVERED = "delivered", /** Czas na odbiór Paczki z Paczkomatu już minął. Paczka zostanie zwrócona do Nadawcy. Odbiorca jeszcze ma szansę odebrać paczkę, jeśli dotrze do Paczkomatu przed Doręczycielem InPost. */ PICKUP_TIME_EXPIRED = "pickup_time_expired", /** Kurier InPost ponownie nie zastał Odbiorcy pod wskazanym adresem. Przesyłka wyruszyła w drogę powrotną do Nadawcy. */ AVIZO = "avizo", /** Prosimy o dokończenie procesu reklamacji poprzez wypełnienie formularza na stronie InPost. */ CLAIMED = "claimed", /** Przesyłka wyruszyła w drogę powrotną do Nadawcy. */ RETURNED_TO_SENDER = "returned_to_sender", /** Etykieta nadawcza została anulowana lub utraciła ważność. Przesyłka nie została wysłana do Odbiorcy. */ CANCELED = "canceled", /** Przesyłka znajduje się w nierozpoznanym statusie. */ OTHER = "other", /** Nadawca przekazał przesyłkę pracownikowi punktu InPost. Tu rozpoczyna się jej podróż do Odbiorcy. */ DISPATCHED_BY_SENDER_TO_POK = "dispatched_by_sender_to_pok", /** Przesyłka jest już na ostatnim etapie podróży - została przekazana kurierowi w celu dostarczenia pod wskazany adres. */ OUT_FOR_DELIVERY_TO_ADDRESS = "out_for_delivery_to_address", /** Kurier InPost nie zastał Odbiorcy pod wskazanym adresem. Kolejna próba doręczenia nastąpi w następnym dniu roboczym. */ PICKUP_REMINDER_SENT_ADDRESS = "pickup_reminder_sent_address", /** Odbiorca odmówił przyjęcia przesyłki. */ REJECTED_BY_RECEIVER = "rejected_by_receiver", /** Brak możliwości doręczenia w dniu dzisiejszym. Powód: błędne dane adresowe. */ UNDELIVERED_WRONG_ADDRESS = "undelivered_wrong_address", /** Brak możliwości doręczenia w dniu dzisiejszym. Powód: niepełne dane adresowe. */ UNDELIVERED_INCOMPLETE_ADDRESS = "undelivered_incomplete_address", /** Brak możliwości doręczenia w dniu dzisiejszym. Powód: Odbiorca nieznany. */ UNDELIVERED_UNKNOWN_RECEIVER = "undelivered_unknown_receiver", /** Brak możliwości doręczenia w dniu dzisiejszym - Odbiorca nie miał gotówki do opłacenia kwoty pobrania. */ UNDELIVERED_COD_CASH_RECEIVER = "undelivered_cod_cash_receiver", /** Doręczyciel InPost odebrał przesyłkę nadaną w Punkcie Obsługi Klienta i przekazuje ją do oddziału InPost, skąd zostanie wysłana w dalszą drogę. */ TAKEN_BY_COURIER_FROM_POK = "taken_by_courier_from_pok", /** Przekazanie do magazynu przesyłek niedoręczalnych. */ UNDELIVERED = "undelivered", /** Przesyłka została odebrana. Zwrotne Potwierdzenie Odbioru zostało wysłane do Nadawcy. */ RETURN_PICKUP_CONFIRMATION_TO_SENDER = "return_pickup_confirmation_to_sender", /** Jeśli Twoja paczka trafiła do oddziału InPost, skontaktuj się z Infolinią, aby sprawdzić możliwości jej odbioru. */ READY_TO_PICKUP_FROM_BRANCH = "ready_to_pickup_from_branch", /** Dostawa się opóźni - najmocniej przepraszamy. W kolejnych wiadomościach poinformujemy Odbiorcę o nowym terminie doręczenia. */ DELAY_IN_DELIVERY = "delay_in_delivery", /** Adresat tej paczki kurierskiej skorzystał z darmowej opcji dynamicznego przekierowania do Paczkomatu InPost. Po dostarczeniu paczki do wybranej maszyny, odbiorca otrzyma komunikat e-mail/SMS zawierający dane potrzebne do jej odbioru. */ REDIRECT_TO_BOX = "redirect_to_box", /** Przekierowanie tej paczki kurierskiej do Paczkomatu InPost okazało się niemożliwe ze względu na zbyt duży gabaryt. Przesyłka zostanie doręczona do Odbiorcy na adres wskazany w zamówieniu. */ CANCELED_REDIRECT_TO_BOX = "canceled_redirect_to_box", /** Przesyłka kurierska została bezpłatnie przekierowana na inny adres na życzenie Odbiorcy. */ READDRESSED = "readdressed", /** Brak możliwości doręczenia w dniu dzisiejszym. Powód: brak skrzynki pocztowej. */ UNDELIVERED_NO_MAILBOX = "undelivered_no_mailbox", /** Brak możliwości doręczenia w dniu dzisiejszym. Powód: Odbiorca nie mieszka pod wskazanym adresem. */ UNDELIVERED_NOT_LIVE_ADDRESS = "undelivered_not_live_address", /** Paczka wyruszyła w drogę powrotną do Nadawcy. */ UNDELIVERED_LACK_OF_ACCESS_LETTERBOX = "undelivered_lack_of_access_letterbox", /** translation missing: pl_PL.statuses.missing.description */ MISSING = "missing", /** Kliknij i dowiedz się więcej na temat magazynowania paczek w POP. https://inpost.pl/pomoc-czym-jest-magazynowanie-paczek-w-pop */ STACK_IN_CUSTOMER_SERVICE_POINT = "stack_in_customer_service_point", /** Upłynął termin odebrania paczki z POP, ale paczka nadal jest w nim magazynowana - czeka na przyjazd kuriera, który ją zabierze do paczkomatu. */ STACK_PARCEL_PICKUP_TIME_EXPIRED = "stack_parcel_pickup_time_expired", /** Kurier wiezie Twoją paczkę do paczkomatu. */ UNSTACK_FROM_CUSTOMER_SERVICE_POINT = "unstack_from_customer_service_point", /** Paczka została awizowana w Punkcie Obsługi Paczek. Jeśli jej nie odbierzesz w ciągu trzech dni roboczych, wróci do Nadawcy. */ COURIER_AVIZO_IN_CUSTOMER_SERVICE_POINT = "courier_avizo_in_customer_service_point", /** Czas na odbiór paczki minął. Została odebrana przez Kuriera z Punktu Obsługi Paczek i niebawem wyruszy w podróż powrotną do Nadawcy. */ TAKEN_BY_COURIER_FROM_CUSTOMER_SERVICE_POINT = "taken_by_courier_from_customer_service_point", /** Kliknij i dowiedz się więcej na temat magazynowania paczek w Paczkomatach tymczasowych: https://inpost.pl/pomoc-czym-jest-magazynowanie-paczek-w-paczkomatach-tymczasowych */ STACK_IN_BOX_MACHINE = "stack_in_box_machine", /** Czas na odbiór paczki magazynowanej w Paczkomacie tymczasowym upłynął. Paczka jest w drodze do pierwotnie wybranego Paczkomatu. Poinformujemy Cię, gdy będzie na miejscu. */ UNSTACK_FROM_BOX_MACHINE = "unstack_from_box_machine", /** Upłynął termin odebrania paczki z Paczkomatu tymczasowego, ale paczka nadal jest w nim magazynowana - czeka na przyjazd kuriera, który ją zabierze do pierwotnie wybranego Paczkomatu. */ STACK_PARCEL_IN_BOX_MACHINE_PICKUP_TIME_EXPIRED = "stack_parcel_in_box_machine_pickup_time_expired", } let phone: string | null = localStorage.getItem("phone"); let map: L.Map | null = null; const markers: L.Marker[] = []; const leafletLoaderJS = document.createElement("script"); leafletLoaderJS.setAttribute("src", "https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"); leafletLoaderJS.setAttribute( "integrity", "sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA==", ); leafletLoaderJS.setAttribute("crossorigin", "anonymous"); const leafletLoaderCSS = document.createElement("link"); leafletLoaderCSS.setAttribute("rel", "stylesheet"); leafletLoaderCSS.setAttribute("href", "https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"); leafletLoaderCSS.setAttribute( "integrity", "sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A==", ); leafletLoaderCSS.setAttribute("crossorigin", "anonymous"); const showElements = (elements: string[]) => elements.forEach((elementName) => { (document.querySelector(elementName)! as HTMLElement).style.display = "block"; }); const hideElements = (elements: string[]) => elements.forEach((elementName) => { (document.querySelector(elementName)! as HTMLElement).style.display = "none"; }); const toggleElements = (elements: string[]) => elements.forEach((elementName) => { const element = document.querySelector(elementName)! as HTMLElement; element.style.display = element.style.display === "block" ? "none" : "block"; }); const openError = (content: string) => { const errorBox = document.querySelector(".error-box")!; const txt = errorBox.querySelector(".error-box-text")!; txt.innerText = content; errorBox.style.display = "block"; }; const request = (resource: string, data: any) => fetch(`/api/${resource}.shs`, { method: "POST", body: new URLSearchParams(data).toString(), credentials: "include", headers: { "Content-Type": "application/x-www-form-urlencoded", }, }) .then((res) => res.json()) .then((res) => { if (res.status) { switch (parseInt(res.status, 10)) { case 200: // logged in lol break; case -1: // not logged in showElements([".login-box", ".register-box", ".description"]); hideElements([".mail-box", ".sms-box", ".package-list", ".logout-button"]); break; case -2: // mail unverified showElements([".mail-box"]); hideElements([ ".login-box", ".register-box", ".sms-box", ".package-list", ".logout-button", ]); break; case -3: // phone unverified showElements([".sms-box"]); hideElements([ ".login-box", ".register-box", ".mail-box", ".package-list", ".logout-button", ]); break; default: openError(res.description || res.msg || `Session error: ${res.status}`); } } return res; }) .catch((err: Error) => { openError(err.message); throw new Error(`Rejected promise ${err.message}`); }); const openLockerConfirm = (lat: string, lon: string, openCode: string, id: string) => { hideElements([".areyousure-box"]); request("collect", { lat, lon, openCode, id, }).then((res) => { if (res.status != 200) { openError(res.description || res.msg); } }); }; const openLocker = (lat: string, lon: string, openCode: string, id: string) => { showElements([".areyousure-box"]); (document.querySelector(".areyousure-button") as HTMLElement)!.onclick = () => { openLockerConfirm(lat, lon, openCode, id); }; }; const refreshPackages = async (response?: Package[]) => { const res: Package[] = response || (await request("packages", {})); const table = document.querySelector("tbody")!; res.reverse().forEach((shipment) => { const row = table.insertRow(); const id = row.insertCell(0); const sender = row.insertCell(1); const status = row.insertCell(2); const locker = row.insertCell(3); const details = row.insertCell(4); const opener = row.insertCell(5); // apparently there are rick-roll pickup points if (shipment.pickupPoint.location) { row.dataset.pickupPointLat = shipment.pickupPoint.location.latitude.toString(); row.dataset.pickupPointLon = shipment.pickupPoint.location.longitude.toString(); } row.dataset.pickupPointDescription = shipment.pickupPoint.description; row.dataset.pickupPointName = shipment.pickupPoint.name; row.dataset.pickupPointStatus = shipment.pickupPoint.status; if (shipment.pickupPoint.address) { row.dataset.pickupPointStreet = shipment.pickupPoint.address.street; row.dataset.pickupPointStreetNumber = shipment.pickupPoint.address.buildingNumber; row.dataset.pickupPointCity = shipment.pickupPoint.address.city; row.dataset.pickupPointProvince = shipment.pickupPoint.address.province; row.dataset.pickupPointPostCode = shipment.pickupPoint.address.postCode; } row.dataset.openCode = shipment.openCode; row.dataset.id = shipment.shipmentNumber; row.dataset.sender = shipment.senderName; row.dataset.status = shipment.status; id.innerText = shipment.shipmentNumber; sender.innerText = shipment.senderName; status.innerText = shipment.status; locker.innerText = `${shipment.pickupPoint.name} - ${shipment.pickupPoint.description}`; const showDetailsAction = document.createElement("a"); showDetailsAction.classList.add("button", "is-light", "is-small"); showDetailsAction.innerHTML = "Info"; showDetailsAction.addEventListener("click", async (event) => { const detailsBox = document.querySelector(".details-box")! as HTMLDivElement; detailsBox.style.display = "block"; const data = ((event.target as Element).parentNode!.parentNode as HTMLElement).dataset; if (data.pickupPointLat && data.pickupPointLon) { showElements(["#map"]); // maybe this looks like shit, but it works let leafletLoaded = false; try { leafletLoaded = !!L; } catch (e) { if (!(e instanceof ReferenceError)) { throw e; } } if (!leafletLoaded) { document.querySelector("head")!.appendChild(leafletLoaderCSS); document.querySelector("head")!.appendChild(leafletLoaderJS); await new Promise((resolve, reject) => { leafletLoaderJS.addEventListener("load", () => { resolve(); }); leafletLoaderJS.addEventListener("error", () => { reject(); }); }); map = L.map("map"); } map!.setView([parseFloat(data.pickupPointLat!), parseFloat(data.pickupPointLon!)], 17); L.tileLayer("https://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png", { attribution: 'Map data © OpenStreetMap contributors', maxZoom: 19, }).addTo(map!); // delete previous markers while (markers.length > 0) { // @ts-ignore it's always marker, while loop checks length map.removeLayer(markers.pop()); } const marker = L.marker([ parseFloat(data.pickupPointLat!), parseFloat(data.pickupPointLon!), ]).addTo(map!); markers.push(marker); } else { hideElements(["#map"]); } const openButton = detailsBox.querySelector( ".modal-card-foot button.is-primary", )! as HTMLButtonElement; if (data.status === PackageStatus.READY_TO_PICKUP) { openButton.removeAttribute("disabled"); openButton.onclick = (e: Event) => { e.preventDefault(); (document.querySelector(".details-box")! as HTMLElement).style.display = "none"; const { dataset } = (event.target as Element).parentNode!.parentNode as HTMLElement; openLocker( dataset.pickupPointLat!, dataset.pickupPointLon!, dataset.openCode!, dataset.id!, ); }; } else { openButton.setAttribute("disabled", "true"); openButton.onclick = null; } const infoTable = detailsBox.querySelector(".details-text")! as HTMLTableElement; // remove previous data from table Array.from(infoTable.tBodies).forEach((tbody) => tbody.remove()); ([ ["Status", "status"], [ "Pickup point", (d) => `${d.pickupPointName} (${d.pickupPointStatus}) ${d.pickupPointDescription} ${d.pickupPointStreet} ${d.pickupPointStreetNumber} ${d.pickupPointProvince} ${d.pickupPointPostCode} ${d.pickupPointCity}`, ], ["Sender", "sender"], ["Open code", "openCode"], ["Package number", "id"], ] as [string, string | ((d: typeof data) => string)][]).forEach(([key, value]) => { const infoRow = infoTable.insertRow(); const keyCell = infoRow.insertCell(); keyCell.innerText = key; const valueCell = infoRow.insertCell(); if (typeof value === "string") { valueCell.innerText = `${data[value]}`; } else { valueCell.innerText = value(data); } }); }); const openAction = document.createElement("a"); openAction.classList.add("button", "is-light", "is-small"); openAction.innerHTML = "Open"; if (shipment.status === PackageStatus.READY_TO_PICKUP) { openAction.addEventListener("click", (event) => { const data = ((event.target as Element).parentNode!.parentNode as HTMLElement).dataset; openLocker(data.pickupPointLat!, data.pickupPointLon!, data.openCode!, data.id!); }); } else { openAction.setAttribute("disabled", ""); } opener.appendChild(openAction); details.appendChild(showDetailsAction); }); }; window.addEventListener("load", () => { const login = document.querySelector(".login-form")! as HTMLFormElement; login.addEventListener("submit", (event) => { event.preventDefault(); request("login", { login: (login.querySelector('input[name="login"]')! as HTMLInputElement).value, password: (login.querySelector('input[name="password"]')! as HTMLInputElement).value, }).then((res) => { if (res.status == 200) { refreshPackages().then(() => { hideElements([".login-box", ".register-box", ".description"]); showElements([".package-list", ".logout-button"]); }); } else { openError(res.msg || "Error during login. Try again in a while?"); } }); }); const logout = document.querySelector(".logout-button")!; logout.addEventListener("click", () => { request("logout", {}).then(() => { document.location.reload(); }); }); const pwdResetOpen = document.querySelector(".password-reset-open-box button")!; pwdResetOpen.addEventListener("click", () => { toggleElements([".password-reset-box"]); }); const pwdReset = document.querySelector(".password-reset-form")! as HTMLFormElement; pwdReset.addEventListener("submit", (event) => { event.preventDefault(); request("reset_request", { login: (pwdReset.querySelector('input[name="login"]')! as HTMLInputElement).value, }).then((res) => { if (res.status == 200) { hideElements([".login-box", ".register-box", ".description", ".password-reset-box"]); showElements([".password-reset-verify-box"]); } else { openError(res.msg || "Error during password reset. Try again in a while?"); } }); }); const pwdResetVerify = document.querySelector(".password-reset-verify-form")! as HTMLFormElement; pwdResetVerify.addEventListener("submit", (event) => { event.preventDefault(); request("reset_confirm", { login: (pwdReset.querySelector('input[name="login"]')! as HTMLInputElement).value, hash: (pwdResetVerify.querySelector('input[name="hash"]')! as HTMLInputElement).value, password: (pwdResetVerify.querySelector('input[name="password"]')! as HTMLInputElement).value, }).then((res) => { if (res.status == 200) { // yes, error, I'm too lazy to implement a separate information modal 🤷‍♀️ openError("Your password has been reset successfully."); hideElements([".password-reset-verify-box"]); showElements([".login-box", ".register-box", ".description"]); } else { openError(res.msg || "Error during password reset. Try again in a while?"); } }); }); const register = document.querySelector(".register-form")!; register.addEventListener("submit", async (event) => { event.preventDefault(); const form = event.target as HTMLFormElement; phone = (form.querySelector('input[name="phone"]')! as HTMLInputElement).value; localStorage.setItem("phone", phone); const res = await request("register", { login: (form.querySelector('input[name="login"]')! as HTMLInputElement).value, password: (form.querySelector('input[name="password"]')! as HTMLInputElement).value, mail: (form.querySelector('input[name="email"]')! as HTMLInputElement).value, hcaptcha: (form.querySelector('textarea[name="h-captcha-response"]')! as HTMLTextAreaElement) .value, }); if (res.status == 200) { hideElements([".register-box", ".login-box"]); showElements([".mail-box"]); } else { openError(res.description || res.msg); } }); const mail = document.querySelector(".mail-form")!; mail.addEventListener("submit", async (event) => { event.preventDefault(); const form = event.target as HTMLFormElement; const res = await request("mailcode", { code: form.code.value, phone, }); if (res.status == 200) { hideElements([".mail-box"]); showElements([".sms-box"]); if (!phone) { showElements([".sms-phone-field"]); } } else { openError(res.description || res.msg); } }); const sms = document.querySelector(".sms-form")!; sms.addEventListener("submit", async (event) => { event.preventDefault(); const form = event.target as HTMLFormElement; if (!phone) { phone = (form.querySelector('input[name="phone"]')! as HTMLInputElement).value; } const res = await request("smscode", { code: form.code.value, phone, }); if (res.status == 200) { hideElements([".sms-box"]); phone = null; localStorage.removeItem("phone"); await refreshPackages(); showElements([".package-list", ".logout-button"]); } else { openError(res.description || res.msg); } }); [...Array.from(document.querySelectorAll(".modal-background"))].forEach((element) => { element.addEventListener("click", () => { // eslint-disable-next-line no-param-reassign element.parentElement!.style.display = "none"; }); }); ([ ...Array.from(document.querySelectorAll(".modal button.delete")), document.querySelector(".modal .error-box-button"), document.querySelector(".modal .areyousure-button-deny"), ].filter((e) => !!e) as HTMLElement[]).forEach((element) => { element.addEventListener("click", () => { // eslint-disable-next-line no-param-reassign element.parentElement!.parentElement!.parentElement!.style.display = "none"; }); }); request("packages", {}).then((res) => { if (Array.isArray(res)) { // logged in, verified e-mail and phone, res is the package list refreshPackages(res); showElements([".package-list", ".logout-button"]); hideElements([".description"]); // just to be sure localStorage.removeItem("phone"); } }); });