diff --git a/endpoints/admin/deleteunusedlogos.php b/endpoints/admin/deleteunusedlogos.php
new file mode 100644
index 0000000..2fba6eb
--- /dev/null
+++ b/endpoints/admin/deleteunusedlogos.php
@@ -0,0 +1,76 @@
+ false,
+ "message" => translate('session_expired', $i18n)
+ ]));
+}
+
+// Check that user is an admin
+if ($userId !== 1) {
+ die(json_encode([
+ "success" => false,
+ "message" => translate('error', $i18n)
+ ]));
+}
+
+$query = 'SELECT logo FROM subscriptions';
+$stmt = $db->prepare($query);
+$result = $stmt->execute();
+
+$logosOnDB = [];
+while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
+ $logosOnDB[] = $row['logo'];
+}
+
+$logosOnDB = array_unique($logosOnDB);
+
+$uploadDir = '../../images/uploads/logos/';
+$uploadFiles = scandir($uploadDir);
+
+foreach ($uploadFiles as $file) {
+ if ($file != '.' && $file != '..' && $file != 'avatars') {
+ $logosOnDisk[] = ['logo' => $file];
+ }
+}
+
+ // Get all logos in the payment_methods table
+ $query = 'SELECT icon FROM payment_methods';
+ $stmt = $db->prepare($query);
+ $result = $stmt->execute();
+
+ while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
+ if (!strstr($row['icon'], "images/uploads/icons/")) {
+ $logosOnDB[] = $row['icon'];
+ }
+ }
+
+ $logosOnDB = array_unique($logosOnDB);
+
+// Find and delete unused logos
+$count = 0;
+foreach ($logosOnDisk as $disk) {
+ foreach ($logosOnDB as $db) {
+ $found = false;
+ if ($disk['logo'] == $db) {
+ $found = true;
+ break;
+ }
+ }
+ if (!$found) {
+ unlink($uploadDir . $disk['logo']);
+ $count++;
+ }
+}
+
+echo json_encode([
+ "success" => true,
+ "message" => translate('success', $i18n),
+ 'count' => $count
+]);
+
+
+?>
\ No newline at end of file
diff --git a/includes/i18n/de.php b/includes/i18n/de.php
index aeb1e05..3c8c8a5 100644
--- a/includes/i18n/de.php
+++ b/includes/i18n/de.php
@@ -297,6 +297,8 @@ $i18n = [
"create_user" => "Benutzer erstellen",
"smtp_settings" => "SMTP Einstellungen",
"smtp_usage_info" => "Wird für die Passwortwiederherstellung und andere System-E-Mails verwendet",
+ "maintenance_tasks" => "Wartungsaufgaben",
+ "orphaned_logos" => "Verwaiste Logos",
// Email Verification
"email_verified" => "E-Mail verifiziert",
"email_verification_failed" => "E-Mail konnte nicht verifiziert werden",
diff --git a/includes/i18n/el.php b/includes/i18n/el.php
index 8a123ab..12e277a 100644
--- a/includes/i18n/el.php
+++ b/includes/i18n/el.php
@@ -297,6 +297,8 @@ $i18n = [
"create_user" => "Δημιουργία χρήστη",
"smtp_settings" => "SMTP ρυθμίσεις",
"smtp_usage_info" => "Θα χρησιμοποιηθεί για ανάκτηση κωδικού πρόσβασης και άλλα μηνύματα ηλεκτρονικού ταχυδρομείου συστήματος.",
+ "maintenance_tasks" => "Εργασίες συντήρησης",
+ "orphaned_logos" => "Ορφανά λογότυπα",
// Email Verification
"email_verified" => "Το email επιβεβαιώθηκε",
"email_verification_failed" => "Η επαλήθευση email απέτυχε",
diff --git a/includes/i18n/en.php b/includes/i18n/en.php
index 8e53989..a085be2 100644
--- a/includes/i18n/en.php
+++ b/includes/i18n/en.php
@@ -297,6 +297,8 @@ $i18n = [
"create_user" => "Create User",
"smtp_settings" => "SMTP Settings",
"smtp_usage_info" => "Will be used for password recovery and other system emails.",
+ "maintenance_tasks" => "Maintenance Tasks",
+ "orphaned_logos" => "Orphaned Logos",
// Email Verification
"email_verified" => "Email verified successfully",
"email_verification_failed" => "Email verification failed",
diff --git a/includes/i18n/es.php b/includes/i18n/es.php
index d0267c9..bbd8828 100644
--- a/includes/i18n/es.php
+++ b/includes/i18n/es.php
@@ -297,6 +297,8 @@ $i18n = [
"create_user" => "Crear Usuario",
"smtp_settings" => "Configuración SMTP",
"smtp_usage_info" => "Se utilizará para recuperar contraseñas y otros correos electrónicos del sistema.",
+ "maintenance_tasks" => "Tareas de Mantenimiento",
+ "orphaned_logos" => "Logotipos huérfanos",
// Email Verification
"email_verified" => "Correo electrónico verificado",
"email_verification_failed" => "Error al verificar el correo electrónico",
diff --git a/includes/i18n/fr.php b/includes/i18n/fr.php
index 307e50b..8d47de3 100644
--- a/includes/i18n/fr.php
+++ b/includes/i18n/fr.php
@@ -297,6 +297,8 @@ $i18n = [
"create_user" => "Créer un utilisateur",
"smtp_settings" => "Paramètres SMTP",
"smtp_usage_info" => "Sera utilisé pour la récupération du mot de passe et d'autres e-mails système.",
+ "maintenance_tasks" => "Tâches de maintenance",
+ "orphaned_logos" => "Logos orphelins",
// Email Verification
"email_verified" => "Votre adresse courriel a été vérifiée avec succès",
"email_verification_failed" => "La vérification de l'adresse courriel a échoué",
diff --git a/includes/i18n/it.php b/includes/i18n/it.php
index 5b76206..42d00ff 100644
--- a/includes/i18n/it.php
+++ b/includes/i18n/it.php
@@ -315,6 +315,8 @@ $i18n = [
"create_user" => "Crea utente",
"smtp_settings" => "Impostazioni SMTP",
"smtp_usage_info" => "Verrà utilizzato per il recupero della password e altre e-mail di sistema.",
+ "maintenance_tasks" => "Compiti di manutenzione",
+ "orphaned_logos" => "Loghi orfani",
// Email Verification
"email_verified" => "L'indirizzo email è stato verificato con successo",
diff --git a/includes/i18n/jp.php b/includes/i18n/jp.php
index 138adad..88441f1 100644
--- a/includes/i18n/jp.php
+++ b/includes/i18n/jp.php
@@ -297,6 +297,8 @@ $i18n = [
"create_user" => "ユーザーを作成",
"smtp_settings" => "SMTP設定",
"smtp_usage_info" => "パスワードの回復やその他のシステム電子メールに使用されます。",
+ "maintenance_tasks" => "メンテナンスタスク",
+ "orphaned_logos" => "孤立したロゴ",
// Email Verification
"email_verified" => "メールアドレスが確認されました",
"email_verification_failed" => "メールアドレスの確認に失敗しました",
diff --git a/includes/i18n/ko.php b/includes/i18n/ko.php
index cbed404..c58b2cb 100644
--- a/includes/i18n/ko.php
+++ b/includes/i18n/ko.php
@@ -298,6 +298,8 @@ $i18n = [
"create_user" => "유저 생성",
"smtp_settings" => "SMTP 설정",
"smtp_usage_info" => "비밀번호 복구 및 기타 시스템 이메일에 사용됩니다.",
+ "maintenance_tasks" => "유지보수 작업",
+ "orphaned_logos" => "고아 로고",
// Email Verification
"email_verified" => "이메일 인증 완료",
"email_verification_failed" => "이메일 인증 실패",
diff --git a/includes/i18n/pl.php b/includes/i18n/pl.php
index d34c561..01c6aaf 100644
--- a/includes/i18n/pl.php
+++ b/includes/i18n/pl.php
@@ -297,6 +297,8 @@ $i18n = [
"create_user" => "Utwórz użytkownika",
"smtp_settings" => "Ustawienia SMTP",
"smtp_usage_info" => "Będzie używany do odzyskiwania hasła i innych e-maili systemowych.",
+ "maintenance_tasks" => "Zadania konserwacyjne",
+ "orphaned_logos" => "Osierocone logo",
// Email Verification
"email_verified" => "E-mail został zweryfikowany",
"email_verification_failed" => "Weryfikacja e-maila nie powiodła się",
diff --git a/includes/i18n/pt.php b/includes/i18n/pt.php
index 09b1fd0..2072f3b 100644
--- a/includes/i18n/pt.php
+++ b/includes/i18n/pt.php
@@ -297,6 +297,8 @@ $i18n = [
"create_user" => "Criar Utilizador",
"smtp_settings" => "Definições SMTP",
"smtp_usage_info" => "Será usado para recuperações de password e outros emails do sistema.",
+ "maintenance_tasks" => "Tarefas de Manutenção",
+ "orphaned_logos" => "Logos Órfãos",
// Email Verification
"email_verified" => "Email verificado",
"email_verification_failed" => "Verificação de email falhou",
diff --git a/includes/i18n/pt_br.php b/includes/i18n/pt_br.php
index e1a3f5d..bf57bf7 100644
--- a/includes/i18n/pt_br.php
+++ b/includes/i18n/pt_br.php
@@ -297,6 +297,8 @@ $i18n = [
"create_user" => "Criar usuário",
"smtp_settings" => "Configurações SMTP",
"smtp_usage_info" => "Será usado para recuperação de senha e outros e-mails do sistema.",
+ "maintenance_tasks" => "Tarefas de manutenção",
+ "orphaned_logos" => "Logos órfãos",
// Email Verification
"email_verified" => "Email verificado",
"email_verification_failed" => "Falha na verificação do email",
diff --git a/includes/i18n/ru.php b/includes/i18n/ru.php
index d84bff6..0187f1a 100644
--- a/includes/i18n/ru.php
+++ b/includes/i18n/ru.php
@@ -297,6 +297,8 @@ $i18n = [
"create_user" => "Создать пользователя",
"smtp_settings" => "Настройки SMTP",
"smtp_usage_info" => "Будет использоваться для восстановления пароля и других системных писем.",
+ "maintenance_tasks" => "Задачи обслуживания",
+ "orphaned_logos" => "Одинокие логотипы",
// Email Verification
"email_verified" => "Ваш адрес электронной почты подтвержден. Теперь вы можете войти.",
"email_verification_failed" => "Не удалось подтвердить ваш адрес электронной почты.",
diff --git a/includes/i18n/sl.php b/includes/i18n/sl.php
index e11e288..3bdaf27 100644
--- a/includes/i18n/sl.php
+++ b/includes/i18n/sl.php
@@ -297,6 +297,8 @@ $i18n = [
"create_user" => "Ustvari uporabnika",
"smtp_settings" => "Nastavitve SMTP",
"smtp_usage_info" => "Uporabljeno bo za obnovitev gesla in druge sistemske e-pošte.",
+ "maintenance_tasks" => "Vzdrževalne naloge",
+ "orphaned_logos" => "Osamljeni logotipi",
// Email Verification
"email_verified" => "E-pošta je bila uspešno preverjena",
"email_verification_failed" => "Preverjanje e-pošte ni uspelo",
diff --git a/includes/i18n/sr.php b/includes/i18n/sr.php
index 0c0a062..34ee487 100644
--- a/includes/i18n/sr.php
+++ b/includes/i18n/sr.php
@@ -297,6 +297,8 @@ $i18n = [
"create_user" => "Креирај корисника",
"smtp_settings" => "SMTP подешавања",
"smtp_usage_info" => "SMTP се користи за слање е-поште за обавештења.",
+ "maintenance_tasks" => "Одржавање",
+ "orphaned_logos" => "Породични логотипови",
// Email Verification
"email_verified" => "Е-пошта је верификована",
"email_verification_failed" => "Верификација е-поште није успела",
diff --git a/includes/i18n/sr_lat.php b/includes/i18n/sr_lat.php
index 78b2ab0..601ffed 100644
--- a/includes/i18n/sr_lat.php
+++ b/includes/i18n/sr_lat.php
@@ -297,6 +297,8 @@ $i18n = [
"create_user" => "Kreiraj korisnika",
"smtp_settings" => "SMTP podešavanja",
"smtp_usage_info" => "Koristiće se za oporavak lozinke i druge sistemske e-poruke.",
+ "maintenance_tasks" => "Održavanje",
+ "orphaned_logos" => "Nepovezani logotipi",
// Email Verification
"email_verified" => "E-pošta je uspešno verifikovana",
"email_verification_failed" => "Verifikacija e-pošte nije uspela",
diff --git a/includes/i18n/tr.php b/includes/i18n/tr.php
index 433ec43..ddb1f48 100644
--- a/includes/i18n/tr.php
+++ b/includes/i18n/tr.php
@@ -297,6 +297,8 @@ $i18n = [
"create_user" => "Kullanıcı Oluştur",
"smtp_settings" => "SMTP Ayarları",
"smtp_usage_info" => "Şifre kurtarma ve diğer sistem e-postaları için kullanılacaktır.",
+ "maintenance_tasks" => "Bakım Görevleri",
+ "orphaned_logos" => "Yetim Logolar",
// Email Verification
"email_verified" => "E-posta doğrulandı",
"email_verification_failed" => "E-posta doğrulaması başarısız oldu",
diff --git a/includes/i18n/zh_cn.php b/includes/i18n/zh_cn.php
index 86c4a0d..5c398f0 100644
--- a/includes/i18n/zh_cn.php
+++ b/includes/i18n/zh_cn.php
@@ -315,6 +315,8 @@ $i18n = [
"create_user" => "创建用户",
"smtp_settings" => "SMTP 设置",
"smtp_usage_info" => "将用于密码恢复和其他系统电子邮件。",
+ "maintenance_tasks" => "维护任务",
+ "orphaned_logos" => "孤立的 Logo",
// Email Verification
"email_verified" => "电子邮件已验证",
diff --git a/includes/i18n/zh_tw.php b/includes/i18n/zh_tw.php
index 7a7a63c..a40829d 100644
--- a/includes/i18n/zh_tw.php
+++ b/includes/i18n/zh_tw.php
@@ -297,6 +297,8 @@ $i18n = [
"create_user" => "建立使用者",
"smtp_settings" => "SMTP 設定",
"smtp_usage_info" => "將用於密碼恢復和其他系統電子郵件。",
+ "maintenance_tasks" => "維護任務",
+ "orphaned_logos" => "孤立的圖示",
// Email Verification
"email_verified" => "電子郵件已驗證",
"email_verification_failed" => "電子郵件驗證失敗",
diff --git a/includes/version.php b/includes/version.php
index f54ba72..7d2339a 100644
--- a/includes/version.php
+++ b/includes/version.php
@@ -1,3 +1,3 @@
\ No newline at end of file
diff --git a/index.php b/index.php
index 87168b4..f9d5aec 100644
--- a/index.php
+++ b/index.php
@@ -237,7 +237,7 @@ $headerClass = count($subscriptions) > 0 ? "main-actions" : "main-actions hidden
-
response.json())
+ .then(data => {
+ if (data.success) {
+ showSuccessMessage(data.message);
+ const numberOfLogos = document.querySelector('.number-of-logos');
+ numberOfLogos.innerText = '0';
+ } else {
+ showErrorMessage(data.message);
+ button.disabled = false;
+ }
+ })
+ .catch(error => {
+ showErrorMessage(error);
+ button.disabled = false;
+ });
}
\ No newline at end of file
diff --git a/scripts/dashboard.js b/scripts/dashboard.js
index c7b381e..d5a98b0 100644
--- a/scripts/dashboard.js
+++ b/scripts/dashboard.js
@@ -20,27 +20,27 @@ function toggleNotificationDays() {
}
function resetForm() {
- const id = document.querySelector("#id");
- id.value = "";
- const formTitle = document.querySelector("#form-title");
- formTitle.textContent = translate('add_subscription');
- const logo = document.querySelector("#form-logo");
- logo.src = "";
- logo.style = 'display: none';
- const logoUrl = document.querySelector("#logo-url");
- logoUrl.value = "";
- const logoSearchButton = document.querySelector("#logo-search-button");
- logoSearchButton.classList.add("disabled");
- const submitButton = document.querySelector("#save-button");
- submitButton.disabled = false;
- const notifyDaysBefore = document.querySelector("#notify_days_before");
- notifyDaysBefore.disabled = true;
- const form = document.querySelector("#subs-form");
- form.reset();
- closeLogoSearch();
- const deleteButton = document.querySelector("#deletesub");
- deleteButton.style = 'display: none';
- deleteButton.removeAttribute("onClick");
+ const id = document.querySelector("#id");
+ id.value = "";
+ const formTitle = document.querySelector("#form-title");
+ formTitle.textContent = translate('add_subscription');
+ const logo = document.querySelector("#form-logo");
+ logo.src = "";
+ logo.style = 'display: none';
+ const logoUrl = document.querySelector("#logo-url");
+ logoUrl.value = "";
+ const logoSearchButton = document.querySelector("#logo-search-button");
+ logoSearchButton.classList.add("disabled");
+ const submitButton = document.querySelector("#save-button");
+ submitButton.disabled = false;
+ const notifyDaysBefore = document.querySelector("#notify_days_before");
+ notifyDaysBefore.disabled = true;
+ const form = document.querySelector("#subs-form");
+ form.reset();
+ closeLogoSearch();
+ const deleteButton = document.querySelector("#deletesub");
+ deleteButton.style = 'display: none';
+ deleteButton.removeAttribute("onClick");
}
function fillEditFormFields(subscription) {
@@ -106,12 +106,12 @@ function fillEditFormFields(subscription) {
}
function openEditSubscription(event, id) {
- event.stopPropagation();
- scrollTopBeforeOpening = window.scrollY;
- const body = document.querySelector('body');
- body.classList.add('no-scroll');
- const url = `endpoints/subscription/get.php?id=${id}`;
- fetch(url)
+ event.stopPropagation();
+ scrollTopBeforeOpening = window.scrollY;
+ const body = document.querySelector('body');
+ body.classList.add('no-scroll');
+ const url = `endpoints/subscription/get.php?id=${id}`;
+ fetch(url)
.then((response) => {
if (response.ok) {
return response.json();
@@ -133,41 +133,41 @@ function openEditSubscription(event, id) {
}
function addSubscription() {
- resetForm();
- const modal = document.getElementById('subscription-form');
- modal.classList.add("is-open");
- const body = document.querySelector('body');
- body.classList.add('no-scroll');
+ resetForm();
+ const modal = document.getElementById('subscription-form');
+ modal.classList.add("is-open");
+ const body = document.querySelector('body');
+ body.classList.add('no-scroll');
}
function closeAddSubscription() {
- const modal = document.getElementById('subscription-form');
- modal.classList.remove("is-open");
- const body = document.querySelector('body');
- body.classList.remove('no-scroll');
- if (shouldScroll) {
- window.scrollTo(0, scrollTopBeforeOpening);
- }
- resetForm();
+ const modal = document.getElementById('subscription-form');
+ modal.classList.remove("is-open");
+ const body = document.querySelector('body');
+ body.classList.remove('no-scroll');
+ if (shouldScroll) {
+ window.scrollTo(0, scrollTopBeforeOpening);
+ }
+ resetForm();
}
function handleFileSelect(event) {
- const fileInput = event.target;
- const logoPreview = document.querySelector('.logo-preview');
- const logoImg = logoPreview.querySelector('img');
- const logoUrl = document.querySelector("#logo-url");
- logoUrl.value = "";
+ const fileInput = event.target;
+ const logoPreview = document.querySelector('.logo-preview');
+ const logoImg = logoPreview.querySelector('img');
+ const logoUrl = document.querySelector("#logo-url");
+ logoUrl.value = "";
- if (fileInput.files && fileInput.files[0]) {
- const reader = new FileReader();
+ if (fileInput.files && fileInput.files[0]) {
+ const reader = new FileReader();
- reader.onload = function (e) {
- logoImg.src = e.target.result;
- logoImg.style.display = 'block';
- };
+ reader.onload = function (e) {
+ logoImg.src = e.target.result;
+ logoImg.style.display = 'block';
+ };
- reader.readAsDataURL(fileInput.files[0]);
- }
+ reader.readAsDataURL(fileInput.files[0]);
+ }
}
function deleteSubscription(event, id) {
@@ -177,7 +177,7 @@ function deleteSubscription(event, id) {
fetch(`endpoints/subscription/delete.php?id=${id}`, {
method: 'DELETE',
})
- .then(response => {
+ .then(response => {
if (response.ok) {
showSuccessMessage(translate('subscription_deleted'));
fetchSubscriptions();
@@ -185,10 +185,10 @@ function deleteSubscription(event, id) {
} else {
showErrorMessage(translate('error_deleting_subscription'));
}
- })
- .catch(error => {
+ })
+ .catch(error => {
console.error('Error:', error);
- });
+ });
}
}
@@ -216,7 +216,7 @@ function cloneSubscription(event, id) {
.catch(error => {
showErrorMessage(error.message || translate('error'));
});
- }
+}
function setSearchButtonStatus() {
@@ -239,17 +239,17 @@ function searchLogo() {
logoSearchPopup.classList.add("is-open");
const imageSearchUrl = `endpoints/logos/search.php?search=${searchTerm}`;
fetch(imageSearchUrl)
- .then(response => response.json())
- .then(data => {
- if (data.imageUrls) {
- displayImageResults(data.imageUrls);
- } else if (data.error) {
- console.error(data.error);
- }
- })
- .catch(error => {
- console.error(translate('error_fetching_image_results'), error);
- });
+ .then(response => response.json())
+ .then(data => {
+ if (data.imageUrls) {
+ displayImageResults(data.imageUrls);
+ } else if (data.error) {
+ console.error(data.error);
+ }
+ })
+ .catch(error => {
+ console.error(translate('error_fetching_image_results'), error);
+ });
} else {
nameInput.focus();
}
@@ -260,15 +260,15 @@ function displayImageResults(imageSources) {
logoResults.innerHTML = "";
imageSources.forEach(src => {
- const img = document.createElement("img");
- img.src = src;
- img.onclick = function() {
- selectWebLogo(src);
- };
- img.onerror = function() {
- this.parentNode.removeChild(this);
- };
- logoResults.appendChild(img);
+ const img = document.createElement("img");
+ img.src = src;
+ img.onclick = function () {
+ selectWebLogo(src);
+ };
+ img.onerror = function () {
+ this.parentNode.removeChild(this);
+ };
+ logoResults.appendChild(img);
});
}
@@ -323,7 +323,7 @@ function fetchSubscriptions() {
function setSortOption(sortOption) {
const sortOptionsContainer = document.querySelector("#sort-options");
const sortOptionsList = sortOptionsContainer.querySelectorAll("li");
- sortOptionsList.forEach((option) => {
+ sortOptionsList.forEach((option) => {
if (option.getAttribute("id") === "sort-" + sortOption) {
option.classList.add("selected");
} else {
@@ -339,21 +339,46 @@ function setSortOption(sortOption) {
toggleSortOptions();
}
-document.addEventListener('DOMContentLoaded', function() {
- const subscriptionForm = document.querySelector("#subs-form");
- const submitButton = document.querySelector("#save-button");
- const endpoint = "endpoints/subscription/add.php";
+function convertSvgToPng(file, callback) {
+ const reader = new FileReader();
- subscriptionForm.addEventListener("submit", function (e) {
- e.preventDefault();
-
- submitButton.disabled = true;
- const formData = new FormData(subscriptionForm);
+ reader.onload = function (e) {
+ const img = new Image();
+ img.src = e.target.result;
+ img.onload = function() {
+ const canvas = document.createElement('canvas');
+ canvas.width = img.width;
+ canvas.height = img.height;
+ const ctx = canvas.getContext('2d');
+ ctx.drawImage(img, 0, 0);
+ const pngDataUrl = canvas.toDataURL('image/png');
+ const pngFile = dataURLtoFile(pngDataUrl, file.name.replace(".svg", ".png"));
+ callback(pngFile);
+ };
+ };
- fetch(endpoint, {
- method: "POST",
- body: formData,
- })
+ reader.readAsDataURL(file);
+}
+
+function dataURLtoFile(dataurl, filename) {
+ let arr = dataurl.split(','),
+ mime = arr[0].match(/:(.*?);/)[1],
+ bstr = atob(arr[1]),
+ n = bstr.length,
+ u8arr = new Uint8Array(n);
+
+ while(n--){
+ u8arr[n] = bstr.charCodeAt(n);
+ }
+
+ return new File([u8arr], filename, {type:mime});
+}
+
+function submitFormData(formData, submitButton, endpoint) {
+ fetch(endpoint, {
+ method: "POST",
+ body: formData,
+ })
.then((response) => response.json())
.then((data) => {
if (data.status === "Success") {
@@ -363,45 +388,69 @@ document.addEventListener('DOMContentLoaded', function() {
}
})
.catch((error) => {
- showErrorMessage(error);
- submitButton.disabled = false;
- });
+ showErrorMessage(error);
+ submitButton.disabled = false;
});
+}
- document.addEventListener('mousedown', function(event) {
- const sortOptions = document.querySelector('#sort-options');
- const sortButton = document.querySelector("#sort-button");
+document.addEventListener('DOMContentLoaded', function () {
+ const subscriptionForm = document.querySelector("#subs-form");
+ const submitButton = document.querySelector("#save-button");
+ const endpoint = "endpoints/subscription/add.php";
- if (!sortOptions.contains(event.target) && !sortButton.contains(event.target) && isSortOptionsOpen) {
- sortOptions.classList.remove('is-open');
- isSortOptionsOpen = false;
- }
- });
+ subscriptionForm.addEventListener("submit", function (e) {
+ e.preventDefault();
+
+ submitButton.disabled = true;
+ const formData = new FormData(subscriptionForm);
- document.querySelector('#sort-options').addEventListener('focus', function() {
- isSortOptionsOpen = true;
- });
+ const fileInput = document.querySelector("#logo");
+ const file = fileInput.files[0];
+
+ if (file && file.type === "image/svg+xml") {
+ convertSvgToPng(file, function(pngFile) {
+ formData.set("logo", pngFile);
+ submitFormData(formData, submitButton, endpoint);
+ });
+ } else {
+ submitFormData(formData, submitButton, endpoint);
+ }
+ });
+
+ document.addEventListener('mousedown', function (event) {
+ const sortOptions = document.querySelector('#sort-options');
+ const sortButton = document.querySelector("#sort-button");
+
+ if (!sortOptions.contains(event.target) && !sortButton.contains(event.target) && isSortOptionsOpen) {
+ sortOptions.classList.remove('is-open');
+ isSortOptionsOpen = false;
+ }
+ });
+
+ document.querySelector('#sort-options').addEventListener('focus', function () {
+ isSortOptionsOpen = true;
+ });
});
function searchSubscriptions() {
- const searchInput = document.querySelector("#search");
- const searchTerm = searchInput.value.trim().toLowerCase();
+ const searchInput = document.querySelector("#search");
+ const searchTerm = searchInput.value.trim().toLowerCase();
- const subscriptions = document.querySelectorAll(".subscription");
- subscriptions.forEach(subscription => {
- const name = subscription.getAttribute('data-name').toLowerCase();
- if (!name.includes(searchTerm)) {
- subscription.classList.add("hide");
- } else {
- subscription.classList.remove("hide");
- }
- });
+ const subscriptions = document.querySelectorAll(".subscription");
+ subscriptions.forEach(subscription => {
+ const name = subscription.getAttribute('data-name').toLowerCase();
+ if (!name.includes(searchTerm)) {
+ subscription.classList.add("hide");
+ } else {
+ subscription.classList.remove("hide");
+ }
+ });
}
function closeSubMenus() {
var subMenus = document.querySelectorAll('.filtermenu-submenu-content');
subMenus.forEach(subMenu => {
- subMenu.classList.remove('is-open');
+ subMenu.classList.remove('is-open');
});
}
@@ -411,84 +460,84 @@ activeFilters['category'] = "";
activeFilters['member'] = "";
activeFilters['payment'] = "";
-document.addEventListener("DOMContentLoaded", function() {
+document.addEventListener("DOMContentLoaded", function () {
var filtermenu = document.querySelector('#filtermenu-button');
- filtermenu.addEventListener('click', function() {
- this.parentElement.querySelector('.filtermenu-content').classList.toggle('is-open');
- closeSubMenus();
+ filtermenu.addEventListener('click', function () {
+ this.parentElement.querySelector('.filtermenu-content').classList.toggle('is-open');
+ closeSubMenus();
});
- document.addEventListener('click', function(e) {
- var filtermenuContent = document.querySelector('.filtermenu-content');
- if (filtermenuContent.classList.contains('is-open')) {
- var subMenus = document.querySelectorAll('.filtermenu-submenu');
- var clickedInsideSubmenu = Array.from(subMenus).some(subMenu => subMenu.contains(e.target) || subMenu === e.target);
+ document.addEventListener('click', function (e) {
+ var filtermenuContent = document.querySelector('.filtermenu-content');
+ if (filtermenuContent.classList.contains('is-open')) {
+ var subMenus = document.querySelectorAll('.filtermenu-submenu');
+ var clickedInsideSubmenu = Array.from(subMenus).some(subMenu => subMenu.contains(e.target) || subMenu === e.target);
- if (!filtermenu.contains(e.target) && !clickedInsideSubmenu) {
- closeSubMenus();
- filtermenuContent.classList.remove('is-open');
- }
+ if (!filtermenu.contains(e.target) && !clickedInsideSubmenu) {
+ closeSubMenus();
+ filtermenuContent.classList.remove('is-open');
}
+ }
});
});
function toggleSubMenu(subMenu) {
var subMenu = document.getElementById("filter-" + subMenu);
if (subMenu.classList.contains("is-open")) {
- closeSubMenus();
+ closeSubMenus();
} else {
- closeSubMenus();
- subMenu.classList.add("is-open");
+ closeSubMenus();
+ subMenu.classList.add("is-open");
}
}
-document.querySelectorAll('.filter-item').forEach(function(item) {
- item.addEventListener('click', function(e) {
+document.querySelectorAll('.filter-item').forEach(function (item) {
+ item.addEventListener('click', function (e) {
const searchInput = document.querySelector("#search");
searchInput.value = "";
if (this.hasAttribute('data-categoryid')) {
- const categoryId = this.getAttribute('data-categoryid');
- if (activeFilters['category'] === categoryId) {
- activeFilters['category'] = "";
- this.classList.remove('selected');
- } else {
- activeFilters['category'] = categoryId;
- Array.from(this.parentNode.children).forEach(sibling => {
- sibling.classList.remove('selected');
- });
- this.classList.add('selected');
- }
+ const categoryId = this.getAttribute('data-categoryid');
+ if (activeFilters['category'] === categoryId) {
+ activeFilters['category'] = "";
+ this.classList.remove('selected');
+ } else {
+ activeFilters['category'] = categoryId;
+ Array.from(this.parentNode.children).forEach(sibling => {
+ sibling.classList.remove('selected');
+ });
+ this.classList.add('selected');
+ }
} else if (this.hasAttribute('data-memberid')) {
- const memberId = this.getAttribute('data-memberid');
- if (activeFilters['member'] === memberId) {
- activeFilters['member'] = "";
- this.classList.remove('selected');
- } else {
- activeFilters['member'] = memberId;
- Array.from(this.parentNode.children).forEach(sibling => {
- sibling.classList.remove('selected');
- });
- this.classList.add('selected');
- }
+ const memberId = this.getAttribute('data-memberid');
+ if (activeFilters['member'] === memberId) {
+ activeFilters['member'] = "";
+ this.classList.remove('selected');
+ } else {
+ activeFilters['member'] = memberId;
+ Array.from(this.parentNode.children).forEach(sibling => {
+ sibling.classList.remove('selected');
+ });
+ this.classList.add('selected');
+ }
} else if (this.hasAttribute('data-paymentid')) {
- const paymentId = this.getAttribute('data-paymentid');
- if (activeFilters['payment'] === paymentId) {
- activeFilters['payment'] = "";
- this.classList.remove('selected');
- } else {
- activeFilters['payment'] = paymentId;
- Array.from(this.parentNode.children).forEach(sibling => {
- sibling.classList.remove('selected');
- });
- this.classList.add('selected');
- }
+ const paymentId = this.getAttribute('data-paymentid');
+ if (activeFilters['payment'] === paymentId) {
+ activeFilters['payment'] = "";
+ this.classList.remove('selected');
+ } else {
+ activeFilters['payment'] = paymentId;
+ Array.from(this.parentNode.children).forEach(sibling => {
+ sibling.classList.remove('selected');
+ });
+ this.classList.add('selected');
+ }
}
if (activeFilters['category'] !== "" || activeFilters['member'] !== "" || activeFilters['payment'] !== "") {
- document.querySelector('#clear-filters').classList.remove('hide');
+ document.querySelector('#clear-filters').classList.remove('hide');
} else {
- document.querySelector('#clear-filters').classList.add('hide');
+ document.querySelector('#clear-filters').classList.add('hide');
}
fetchSubscriptions();
@@ -501,7 +550,7 @@ function clearFilters() {
activeFilters['category'] = "";
activeFilters['member'] = "";
activeFilters['payment'] = "";
- document.querySelectorAll('.filter-item').forEach(function(item) {
+ document.querySelectorAll('.filter-item').forEach(function (item) {
item.classList.remove('selected');
});
document.querySelector('#clear-filters').classList.add('hide');
@@ -510,7 +559,7 @@ function clearFilters() {
let currentActions = null;
-document.addEventListener('click', function(event) {
+document.addEventListener('click', function (event) {
// Check if click was outside currentActions
if (currentActions && !currentActions.contains(event.target)) {
// Click was outside currentActions, close currentActions
diff --git a/styles/styles.css b/styles/styles.css
index ef6c14f..98fd25d 100644
--- a/styles/styles.css
+++ b/styles/styles.css
@@ -117,7 +117,7 @@ header .logo .logo-image svg {
.dropbtn > img {
width: 35px;
height: 35px;
- object-fit: contain;
+ object-fit: cover;
}
.dropdown-content {
@@ -630,7 +630,7 @@ header #avatar {
cursor: pointer;
width: 80px;
height: 80px;
- object-fit: contain;
+ object-fit: cover;
max-width: 80px;
border-radius: 50%;
border: 1px solid #ccc;
@@ -701,7 +701,7 @@ header #avatar {
.avatar-select .avatar-list .avatar-container > img {
width: 60px;
height: 60px;
- object-fit: contain;
+ object-fit: cover;
cursor: pointer;
border: 1px solid #ccc;
box-sizing: border-box
@@ -2249,6 +2249,10 @@ button.dark-theme-button i {
}
}
+.bold {
+ font-weight: 700;
+}
+
/* Checkbox */
input[type="checkbox"] {
opacity: 0;