ocw/front/src/index.ts

569 lines
25 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

// eslint-disable-next-line spaced-comment
///<reference path="../node_modules/@types/leaflet/index.d.ts" />
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 SMSach 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 = <HTMLDivElement>document.querySelector(".error-box")!;
const txt = <HTMLParagraphElement>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<void>((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 &copy; <a href="https://openstreetmap.org/copyright">OpenStreetMap contributors</a>',
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");
}
});
});