mirror of
https://github.com/ellite/Wallos.git
synced 2026-05-06 11:59:23 -05:00
feat: edit and delete options now available directly on the subscription list
fix: typo on webhook payload refactor: split currency endpoint feat: add option to clone subscription
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
require_once '../../includes/connect_endpoint.php';
|
||||
require_once '../../includes/inputvalidation.php';
|
||||
|
||||
if (isset($_SESSION['loggedin']) && $_SESSION['loggedin'] === true) {
|
||||
$currencyName = "Currency";
|
||||
$currencySymbol = "$";
|
||||
$currencyCode = "CODE";
|
||||
$currencyRate = 1;
|
||||
$sqlInsert = "INSERT INTO currencies (name, symbol, code, rate, user_id) VALUES (:name, :symbol, :code, :rate, :userId)";
|
||||
$stmtInsert = $db->prepare($sqlInsert);
|
||||
$stmtInsert->bindParam(':name', $currencyName, SQLITE3_TEXT);
|
||||
$stmtInsert->bindParam(':symbol', $currencySymbol, SQLITE3_TEXT);
|
||||
$stmtInsert->bindParam(':code', $currencyCode, SQLITE3_TEXT);
|
||||
$stmtInsert->bindParam(':rate', $currencyRate, SQLITE3_TEXT);
|
||||
$stmtInsert->bindParam(':userId', $userId, SQLITE3_INTEGER);
|
||||
$resultInsert = $stmtInsert->execute();
|
||||
|
||||
if ($resultInsert) {
|
||||
$currencyId = $db->lastInsertRowID();
|
||||
echo $currencyId;
|
||||
} else {
|
||||
echo translate('error_adding_currency', $i18n);
|
||||
}
|
||||
} else {
|
||||
$response = [
|
||||
"success" => false,
|
||||
"message" => translate('session_expired', $i18n)
|
||||
];
|
||||
echo json_encode($response);
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
require_once '../../includes/connect_endpoint.php';
|
||||
require_once '../../includes/inputvalidation.php';
|
||||
|
||||
if (isset($_SESSION['loggedin']) && $_SESSION['loggedin'] === true) {
|
||||
if (isset($_GET['currencyId']) && $_GET['currencyId'] != "" && isset($_GET['name']) && $_GET['name'] != "" && isset($_GET['symbol']) && $_GET['symbol'] != "") {
|
||||
$currencyId = $_GET['currencyId'];
|
||||
$name = validate($_GET['name']);
|
||||
$symbol = validate($_GET['symbol']);
|
||||
$code = validate($_GET['code']);
|
||||
$sql = "UPDATE currencies SET name = :name, symbol = :symbol, code = :code WHERE id = :currencyId AND user_id = :userId";
|
||||
$stmt = $db->prepare($sql);
|
||||
$stmt->bindParam(':name', $name, SQLITE3_TEXT);
|
||||
$stmt->bindParam(':symbol', $symbol, SQLITE3_TEXT);
|
||||
$stmt->bindParam(':code', $code, SQLITE3_TEXT);
|
||||
$stmt->bindParam(':currencyId', $currencyId, SQLITE3_INTEGER);
|
||||
$stmt->bindParam(':userId', $userId, SQLITE3_INTEGER);
|
||||
$result = $stmt->execute();
|
||||
|
||||
if ($result) {
|
||||
$response = [
|
||||
"success" => true,
|
||||
"message" => $name . " " . translate('currency_saved', $i18n)
|
||||
];
|
||||
echo json_encode($response);
|
||||
} else {
|
||||
$response = [
|
||||
"success" => false,
|
||||
"message" => translate('failed_to_store_currency', $i18n)
|
||||
];
|
||||
echo json_encode($response);
|
||||
}
|
||||
} else {
|
||||
$response = [
|
||||
"success" => false,
|
||||
"message" => translate('fields_missing', $i18n)
|
||||
];
|
||||
echo json_encode($response);
|
||||
}
|
||||
} else {
|
||||
$response = [
|
||||
"success" => false,
|
||||
"message" => translate('session_expired', $i18n)
|
||||
];
|
||||
echo json_encode($response);
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
require_once '../../includes/connect_endpoint.php';
|
||||
require_once '../../includes/inputvalidation.php';
|
||||
|
||||
if (isset($_SESSION['loggedin']) && $_SESSION['loggedin'] === true) {
|
||||
if (isset($_GET['currencyId']) && $_GET['currencyId'] != "") {
|
||||
$query = "SELECT main_currency FROM user WHERE id = :userId";
|
||||
$stmt = $db->prepare($query);
|
||||
$stmt->bindParam(':userId', $userId, SQLITE3_INTEGER);
|
||||
$result = $stmt->execute();
|
||||
$row = $result->fetchArray(SQLITE3_ASSOC);
|
||||
$mainCurrencyId = $row['main_currency'];
|
||||
|
||||
$currencyId = $_GET['currencyId'];
|
||||
$checkQuery = "SELECT COUNT(*) FROM subscriptions WHERE currency_id = :currencyId AND user_id = :userId";
|
||||
$checkStmt = $db->prepare($checkQuery);
|
||||
$checkStmt->bindParam(':currencyId', $currencyId, SQLITE3_INTEGER);
|
||||
$checkStmt->bindParam(':userId', $userId, SQLITE3_INTEGER);
|
||||
$checkResult = $checkStmt->execute();
|
||||
$row = $checkResult->fetchArray();
|
||||
$count = $row[0];
|
||||
|
||||
if ($count > 0) {
|
||||
$response = [
|
||||
"success" => false,
|
||||
"message" => translate('currency_in_use', $i18n)
|
||||
];
|
||||
echo json_encode($response);
|
||||
exit;
|
||||
} else {
|
||||
if ($currencyId == $mainCurrencyId) {
|
||||
$response = [
|
||||
"success" => false,
|
||||
"message" => translate('currency_is_main', $i18n)
|
||||
];
|
||||
echo json_encode($response);
|
||||
exit;
|
||||
} else {
|
||||
$sql = "DELETE FROM currencies WHERE id = :currencyId AND user_id = :userId";
|
||||
$stmt = $db->prepare($sql);
|
||||
$stmt->bindParam(':currencyId', $currencyId, SQLITE3_INTEGER);
|
||||
$stmt->bindParam(':userId', $userId, SQLITE3_INTEGER);
|
||||
$result = $stmt->execute();
|
||||
if ($result) {
|
||||
echo json_encode(["success" => true, "message" => translate('currency_removed', $i18n)]);
|
||||
} else {
|
||||
$response = [
|
||||
"success" => false,
|
||||
"message" => translate('failed_to_remove_currency', $i18n)
|
||||
];
|
||||
echo json_encode($response);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$response = [
|
||||
"success" => false,
|
||||
"message" => translate('fields_missing', $i18n)
|
||||
];
|
||||
echo json_encode($response);
|
||||
}
|
||||
} else {
|
||||
$response = [
|
||||
"success" => false,
|
||||
"message" => translate('session_expired', $i18n)
|
||||
];
|
||||
echo json_encode($response);
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
require_once '../../includes/connect_endpoint.php';
|
||||
|
||||
if (isset($_SESSION['loggedin']) && $_SESSION['loggedin'] === true) {
|
||||
if ($_SERVER["REQUEST_METHOD"] === "GET") {
|
||||
$subscriptionId = $_GET["id"];
|
||||
$query = "SELECT * FROM subscriptions WHERE id = :id AND user_id = :user_id";
|
||||
$stmt = $db->prepare($query);
|
||||
$stmt->bindValue(':id', $subscriptionId, SQLITE3_INTEGER);
|
||||
$stmt->bindValue(':user_id', $userId, SQLITE3_INTEGER);
|
||||
$result = $stmt->execute();
|
||||
$subscriptionToClone = $result->fetchArray(SQLITE3_ASSOC);
|
||||
if ($subscriptionToClone === false) {
|
||||
die(json_encode([
|
||||
"success" => false,
|
||||
"message" => translate("error", $i18n)
|
||||
]));
|
||||
}
|
||||
|
||||
$query = "INSERT INTO subscriptions (name, logo, price, currency_id, next_payment, cycle, frequency, notes, payment_method_id, payer_user_id, category_id, notify, url, inactive, notify_days_before, user_id) VALUES (:name, :logo, :price, :currency_id, :next_payment, :cycle, :frequency, :notes, :payment_method_id, :payer_user_id, :category_id, :notify, :url, :inactive, :notify_days_before, :user_id)";
|
||||
$cloneStmt = $db->prepare($query);
|
||||
$cloneStmt->bindValue(':name', $subscriptionToClone['name'], SQLITE3_TEXT);
|
||||
$cloneStmt->bindValue(':logo', $subscriptionToClone['logo'], SQLITE3_TEXT);
|
||||
$cloneStmt->bindValue(':price', $subscriptionToClone['price'], SQLITE3_TEXT);
|
||||
$cloneStmt->bindValue(':currency_id', $subscriptionToClone['currency_id'], SQLITE3_INTEGER);
|
||||
$cloneStmt->bindValue(':next_payment', $subscriptionToClone['next_payment'], SQLITE3_TEXT);
|
||||
$cloneStmt->bindValue(':cycle', $subscriptionToClone['cycle'], SQLITE3_TEXT);
|
||||
$cloneStmt->bindValue(':frequency', $subscriptionToClone['frequency'], SQLITE3_INTEGER);
|
||||
$cloneStmt->bindValue(':notes', $subscriptionToClone['notes'], SQLITE3_TEXT);
|
||||
$cloneStmt->bindValue(':payment_method_id', $subscriptionToClone['payment_method_id'], SQLITE3_INTEGER);
|
||||
$cloneStmt->bindValue(':payer_user_id', $subscriptionToClone['payer_user_id'], SQLITE3_INTEGER);
|
||||
$cloneStmt->bindValue(':category_id', $subscriptionToClone['category_id'], SQLITE3_INTEGER);
|
||||
$cloneStmt->bindValue(':notify', $subscriptionToClone['notify'], SQLITE3_INTEGER);
|
||||
$cloneStmt->bindValue(':url', $subscriptionToClone['url'], SQLITE3_TEXT);
|
||||
$cloneStmt->bindValue(':inactive', $subscriptionToClone['inactive'], SQLITE3_INTEGER);
|
||||
$cloneStmt->bindValue(':notify_days_before', $subscriptionToClone['notify_days_before'], SQLITE3_INTEGER);
|
||||
$cloneStmt->bindValue(':user_id', $userId, SQLITE3_INTEGER);
|
||||
|
||||
if ($cloneStmt->execute()) {
|
||||
$response = [
|
||||
"success" => true,
|
||||
"message" => translate('success', $i18n)
|
||||
];
|
||||
echo json_encode($response);
|
||||
} else {
|
||||
die(json_encode([
|
||||
"success" => false,
|
||||
"message" => translate("error", $i18n)
|
||||
]));
|
||||
}
|
||||
} else {
|
||||
die(json_encode([
|
||||
"success" => false,
|
||||
"message" => translate('invalid_request_method', $i18n)
|
||||
]));
|
||||
}
|
||||
}
|
||||
$db->close();
|
||||
?>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.0 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1006 B |
@@ -65,6 +65,7 @@ $i18n = [
|
||||
"empty_page" => "Leere Seite",
|
||||
"clear_filters" => "Filter zurücksetzen",
|
||||
"no_matching_subscriptions" => "Keine passenden Abonnements gefunden",
|
||||
"clone" => "Klonen",
|
||||
// Subscription form
|
||||
"add_subscription" => "Abonnement hinzufügen",
|
||||
"edit_subscription" => "Abonnement editieren",
|
||||
|
||||
@@ -65,6 +65,7 @@ $i18n = [
|
||||
"empty_page" => "Κενή σελίδα",
|
||||
"clear_filters" => "Καθαρισμός φίλτρων",
|
||||
"no_matching_subscriptions" => "Δεν υπάρχουν συνδρομές που ταιριάζουν με τα φίλτρα σου",
|
||||
"clone" => "Κλώνος",
|
||||
// Subscription form
|
||||
"add_subscription" => "Προσθήκη συνδρομής",
|
||||
"edit_subscription" => "Επεξεργασία συνδρομής",
|
||||
|
||||
@@ -65,6 +65,7 @@ $i18n = [
|
||||
"empty_page" => "Empty Page",
|
||||
"clear_filters" => "Clear Filters",
|
||||
"no_matching_subscriptions" => "No matching subscriptions",
|
||||
"clone" => "Clone",
|
||||
// Subscription form
|
||||
"add_subscription" => "Add subscription",
|
||||
"edit_subscription" => "Edit subscription",
|
||||
|
||||
@@ -65,6 +65,7 @@ $i18n = [
|
||||
"empty_page" => "Página Vacía",
|
||||
"clear_filters" => "Limpiar Filtros",
|
||||
"no_matching_subscriptions" => "No hay suscripciones que coincidan con los filtros",
|
||||
"clone" => "Clonar",
|
||||
// Subscription form
|
||||
"add_subscription" => "Añadir suscripción",
|
||||
"edit_subscription" => "Editar suscripción",
|
||||
|
||||
@@ -65,6 +65,7 @@ $i18n = [
|
||||
"empty_page" => "Page vide",
|
||||
"clear_filters" => "Effacer les filtres",
|
||||
"no_matching_subscriptions" => "Aucun abonnement ne correspond à vos critères de recherche",
|
||||
"clone" => "Cloner",
|
||||
// Formulaire d'abonnement
|
||||
"add_subscription" => "Ajouter un abonnement",
|
||||
"edit_subscription" => "Modifier l'abonnement",
|
||||
|
||||
@@ -69,6 +69,7 @@ $i18n = [
|
||||
'empty_page' => 'Pagina vuota',
|
||||
'clear_filters' => 'Pulisci filtri',
|
||||
'no_matching_subscriptions' => 'Nessun abbonamento corrispondente',
|
||||
"clone" => "Clona",
|
||||
|
||||
// Add/Edit Subscription
|
||||
'add_subscription' => 'Aggiungi abbonamento',
|
||||
|
||||
@@ -65,6 +65,7 @@ $i18n = [
|
||||
"empty_page" => "空のページ",
|
||||
"clear_filters" => "フィルタをクリア",
|
||||
"no_matching_subscriptions" => "一致する定期購入がありません",
|
||||
"clone" => "複製",
|
||||
// Subscription form
|
||||
"add_subscription" => "定期購入の追加",
|
||||
"edit_subscription" => "定期購入の編集",
|
||||
|
||||
@@ -65,6 +65,7 @@ $i18n = [
|
||||
"empty_page" => "빈 페이지",
|
||||
"clear_filters" => "필터 제거",
|
||||
"no_matching_subscriptions" => "해당하는 구독이 없습니다.",
|
||||
"clone" => "복제",
|
||||
// Subscription form
|
||||
"add_subscription" => "구독 추가",
|
||||
"edit_subscription" => "구독 편집",
|
||||
|
||||
@@ -65,6 +65,7 @@ $i18n = [
|
||||
"empty_page" => "Pusta strona",
|
||||
"clear_filters" => "Wyczyść filtry",
|
||||
"no_matching_subscriptions" => "Brak pasujących subskrypcji",
|
||||
"clone" => "Klonuj",
|
||||
// Subscription form
|
||||
"add_subscription" => "Dodaj subskrypcję",
|
||||
"edit_subscription" => "Edytuj subskrypcję",
|
||||
|
||||
@@ -65,6 +65,7 @@ $i18n = [
|
||||
"empty_page" => "Página Vazia",
|
||||
"clear_filters" => "Limpar Filtros",
|
||||
"no_matching_subscriptions" => "Sem subscrições correspondentes",
|
||||
"clone" => "Clonar",
|
||||
// Subscription form
|
||||
"add_subscription" => "Adicionar subscrição",
|
||||
"edit_subscription" => "Modificar subscrição",
|
||||
|
||||
@@ -65,6 +65,7 @@ $i18n = [
|
||||
"empty_page" => "Página vazia",
|
||||
"clear_filters" => "Limpar filtros",
|
||||
"no_matching_subscriptions" => "Nenhuma assinatura encontrada",
|
||||
"clone" => "Clonar",
|
||||
// Subscription form
|
||||
"add_subscription" => "Adicionar assinatura",
|
||||
"edit_subscription" => "Editar assinatura",
|
||||
|
||||
@@ -65,6 +65,7 @@ $i18n = [
|
||||
"empty_page" => "Пустая страница",
|
||||
"clear_filters" => "Очистить фильтры",
|
||||
"no_matching_subscriptions" => "Нет подходящих подписок",
|
||||
"clone" => "Клонировать",
|
||||
// Subscription form
|
||||
"add_subscription" => "Добавить подписку",
|
||||
"edit_subscription" => "Изменить подписку",
|
||||
|
||||
@@ -65,6 +65,7 @@ $i18n = [
|
||||
"empty_page" => "Prazna stran",
|
||||
"clear_filters" => "Počisti filter",
|
||||
"no_matching_subscriptions" => "Ni ustreznih naročnin",
|
||||
"clone" => "Klon",
|
||||
// Subscription form
|
||||
"add_subscription" => "Dodaj naročnino",
|
||||
"edit_subscription" => "Uredi naročnino",
|
||||
|
||||
@@ -65,6 +65,7 @@ $i18n = [
|
||||
"empty_page" => "Празна страница",
|
||||
"clear_filters" => "Очисти филтере",
|
||||
"no_matching_subscriptions" => "Нема подударајућих претплата",
|
||||
"clone" => "Клонирај",
|
||||
// Форма за претплату
|
||||
"add_subscription" => "Додај претплату",
|
||||
"edit_subscription" => "Уреди претплату",
|
||||
|
||||
@@ -65,6 +65,7 @@ $i18n = [
|
||||
"empty_page" => "Prazna stranica",
|
||||
"clear_filters" => "Očisti filtere",
|
||||
"no_matching_subscriptions" => "Nema podudarajućih pretplata",
|
||||
"clone" => "Kloniraj",
|
||||
// Forma za pretplatu
|
||||
"add_subscription" => "Dodaj pretplatu",
|
||||
"edit_subscription" => "Uredi pretplatu",
|
||||
|
||||
@@ -65,6 +65,7 @@ $i18n = [
|
||||
"empty_page" => "Boş Sayfa",
|
||||
"clear_filters" => "Filtreleri Temizle",
|
||||
"no_matching_subscriptions" => "Eşleşen abonelik bulunamadı",
|
||||
"clone" => "Kopyala",
|
||||
// Subscription form
|
||||
"add_subscription" => "Abonelik ekle",
|
||||
"edit_subscription" => "Aboneliği düzenle",
|
||||
|
||||
@@ -69,6 +69,7 @@ $i18n = [
|
||||
"empty_page" => "空白页面",
|
||||
"clear_filters" => "清除筛选",
|
||||
"no_matching_subscriptions" => "没有匹配的订阅",
|
||||
"clone" => "克隆",
|
||||
|
||||
// 订阅表单
|
||||
"add_subscription" => "添加订阅",
|
||||
|
||||
@@ -65,6 +65,7 @@ $i18n = [
|
||||
"empty_page" => "空白頁面",
|
||||
"clear_filters" => "清除篩選",
|
||||
"no_matching_subscriptions" => "沒有符合的訂閱",
|
||||
"clone" => "複製",
|
||||
// 訂閱表單
|
||||
"add_subscription" => "新增訂閱",
|
||||
"edit_subscription" => "編輯訂閱",
|
||||
|
||||
@@ -108,11 +108,23 @@
|
||||
<img src="<?= $subscription['payment_method_icon'] ?>" title="<?= translate('payment_method', $i18n) ?>: <?= $subscription['payment_method_name'] ?>"/>
|
||||
<?= CurrencyFormatter::format($subscription['price'], $subscription['currency_code']) ?>
|
||||
</span>
|
||||
<span class="actions">
|
||||
<button class="image-button medium" onClick="openEditSubscription(event, <?= $subscription['id'] ?>)" name="edit">
|
||||
<img src="images/siteicons/<?= $colorTheme ?>/edit.png" title="<?= translate('edit_subscription', $i18n) ?>">
|
||||
<button type="button" class="actions-expand" onClick="expandActions(event, <?= $subscription['id'] ?>)">
|
||||
<i class="fas fa-ellipsis-v"></i>
|
||||
</button>
|
||||
</span>
|
||||
<ul class="actions">
|
||||
<li class="edit" title="<?= translate('edit_subscription', $i18n) ?>" onClick="openEditSubscription(event, <?= $subscription['id'] ?>)">
|
||||
<img src="images/siteicons/<?= $colorTheme ?>/edit.png" title="<?= translate('edit_subscription', $i18n) ?>">
|
||||
<?= translate('edit_subscription', $i18n) ?>
|
||||
</li>
|
||||
<li class="delete" title="<?= translate('delete', $i18n) ?>" onClick="deleteSubscription(event, <?= $subscription['id'] ?>)">
|
||||
<img src="images/siteicons/<?= $colorTheme ?>/delete.png" title="<?= translate('edit_subscription', $i18n) ?>">
|
||||
<?= translate('delete', $i18n) ?>
|
||||
</li>
|
||||
<li class="clone" title="<?= translate('clone', $i18n) ?>" onClick="cloneSubscription(event, <?= $subscription['id'] ?>)">
|
||||
<img src="images/siteicons/<?= $colorTheme ?>/clone.png" title="<?= translate('edit_subscription', $i18n) ?>">
|
||||
<?= translate('clone', $i18n) ?>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="subscription-secondary">
|
||||
<span class="name"><img src="images/siteicons/<?= $colorTheme ?>/subscription.png" alt="<?= translate('subscription', $i18n) ?>" /><?= $subscription['name'] ?></span>
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
<?php
|
||||
$version = "v2.4.2";
|
||||
$version = "v2.5.0";
|
||||
?>
|
||||
|
||||
+66
-2
@@ -160,7 +160,9 @@ function handleFileSelect(event) {
|
||||
}
|
||||
}
|
||||
|
||||
function deleteSubscription(id) {
|
||||
function deleteSubscription(event, id) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
if (confirm(translate('confirm_delete_subscription'))) {
|
||||
fetch(`endpoints/subscription/delete.php?id=${id}`, {
|
||||
method: 'DELETE',
|
||||
@@ -171,7 +173,7 @@ function deleteSubscription(id) {
|
||||
fetchSubscriptions();
|
||||
closeAddSubscription();
|
||||
} else {
|
||||
alert(translate('error_deleting_subscription'));
|
||||
showErrorMessage(translate('error_deleting_subscription'));
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
@@ -180,6 +182,32 @@ function deleteSubscription(id) {
|
||||
}
|
||||
}
|
||||
|
||||
function cloneSubscription(event, id) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
|
||||
const url = `endpoints/subscription/clone.php?id=${id}`;
|
||||
|
||||
fetch(url)
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error(translate('network_response_error'));
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
fetchSubscriptions();
|
||||
showSuccessMessage(decodeURI(data.message));
|
||||
} else {
|
||||
showErrorMessage(data.message || translate('error'));
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
showErrorMessage(error.message || translate('error'));
|
||||
});
|
||||
}
|
||||
|
||||
function setSearchButtonStatus() {
|
||||
|
||||
const nameInput = document.querySelector("#name");
|
||||
@@ -468,4 +496,40 @@ function clearFilters() {
|
||||
});
|
||||
document.querySelector('#clear-filters').classList.add('hide');
|
||||
fetchSubscriptions();
|
||||
}
|
||||
|
||||
let currentActions = null;
|
||||
|
||||
document.addEventListener('click', function(event) {
|
||||
// Check if click was outside currentActions
|
||||
if (currentActions && !currentActions.contains(event.target)) {
|
||||
// Click was outside currentActions, close currentActions
|
||||
currentActions.classList.remove('is-open');
|
||||
currentActions = null;
|
||||
}
|
||||
});
|
||||
|
||||
function expandActions(event, subscriptionId) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
const subscriptionDiv = document.querySelector(`.subscription[data-id="${subscriptionId}"]`);
|
||||
const actions = subscriptionDiv.querySelector('.actions');
|
||||
|
||||
// Close all other open actions
|
||||
const allActions = document.querySelectorAll('.actions.is-open');
|
||||
allActions.forEach((openAction) => {
|
||||
if (openAction !== actions) {
|
||||
openAction.classList.remove('is-open');
|
||||
}
|
||||
});
|
||||
|
||||
// Toggle the clicked actions
|
||||
actions.classList.toggle('is-open');
|
||||
|
||||
// Update currentActions
|
||||
if (actions.classList.contains('is-open')) {
|
||||
currentActions = actions;
|
||||
} else {
|
||||
currentActions = null;
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -360,7 +360,7 @@ function editCategory(categoryId) {
|
||||
|
||||
function addCurrencyButton(currencyId) {
|
||||
document.getElementById("addCurrency").disabled = true;
|
||||
const url = 'endpoints/currency/currency.php?action=add';
|
||||
const url = 'endpoints/currency/add.php';
|
||||
fetch(url)
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
@@ -442,7 +442,7 @@ function addCurrencyButton(currencyId) {
|
||||
}
|
||||
|
||||
function removeCurrency(currencyId) {
|
||||
let url = `endpoints/currency/currency.php?action=delete¤cyId=${currencyId}`;
|
||||
let url = `endpoints/currency/remove.php?currencyId=${currencyId}`;
|
||||
fetch(url)
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
@@ -477,7 +477,7 @@ function editCurrency(currencyId) {
|
||||
var currencyName = encodeURIComponent(inputNameElement.value);
|
||||
var currencySymbol = encodeURIComponent(inputSymbolElement.value);
|
||||
var currencyCode = encodeURIComponent(inputCodeElement.value);
|
||||
var url = `endpoints/currency/currency.php?action=edit¤cyId=${currencyId}&name=${currencyName}&symbol=${currencySymbol}&code=${currencyCode}`;
|
||||
var url = `endpoints/currency/edit.php?currencyId=${currencyId}&name=${currencyName}&symbol=${currencySymbol}&code=${currencyCode}`;
|
||||
|
||||
fetch(url)
|
||||
.then(response => {
|
||||
|
||||
+1
-1
@@ -364,7 +364,7 @@
|
||||
"category": "{{subscription_category}}",
|
||||
"date": "{{subscription_date}}",
|
||||
"payer": "{{subscription_payer}}"
|
||||
"dyas": "{{subscription_days_until_payment}}"
|
||||
"days": "{{subscription_days_until_payment}}"
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
+25
-1
@@ -25,7 +25,8 @@ header .logo .logo-image {
|
||||
.sort-options,
|
||||
.statistic,
|
||||
.graph,
|
||||
.filtermenu-content {
|
||||
.filtermenu-content,
|
||||
.subscription-main .actions {
|
||||
background-color: #222;
|
||||
border: 1px solid #333;
|
||||
box-shadow: 0 2px 5px rgba(120, 120, 120, 0.1);
|
||||
@@ -53,6 +54,29 @@ header .logo .logo-image {
|
||||
border-bottom: 1px solid #EEE;
|
||||
}
|
||||
|
||||
.subscription.inactive {
|
||||
background-color: rgba(24,24,24,0.3);
|
||||
color: rgba(200,200,200,0.6);
|
||||
box-shadow: 0 2px 5px rgba(50, 50, 50, 0.1);
|
||||
}
|
||||
|
||||
.subscription-main .actions {
|
||||
color: #E0E0E0
|
||||
}
|
||||
|
||||
.subscription-main .actions > li {
|
||||
border-bottom: 1px solid #555;
|
||||
border-color: #666;
|
||||
}
|
||||
|
||||
.subscription-main .actions > li:hover {
|
||||
background-color: #333;
|
||||
}
|
||||
|
||||
.subscription-main .actions > li:last-of-type {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.close-form {
|
||||
color: #EEE;
|
||||
}
|
||||
|
||||
+58
-1
@@ -262,7 +262,9 @@ main > .contain {
|
||||
}
|
||||
|
||||
.subscription.inactive {
|
||||
opacity: 0.6;
|
||||
background-color: rgba(255,255,255,0.6);
|
||||
color: rgba(100,100,100,0.6);
|
||||
box-shadow: 0 2px 5px rgba(100, 100, 100, 0.1);
|
||||
}
|
||||
|
||||
.subscription.inactive span.price {
|
||||
@@ -274,8 +276,63 @@ main > .contain {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.subscription-main .actions-expand {
|
||||
font-size: 21px;
|
||||
padding: 8px 16px;
|
||||
color: var(--main-color);
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.subscription-main .actions-expand:hover {
|
||||
color: var(--hover-color);
|
||||
}
|
||||
|
||||
.subscription-main .actions {
|
||||
display: none;
|
||||
position: absolute;
|
||||
right: -16px;
|
||||
top: 60px;
|
||||
z-index: 2;
|
||||
flex-direction: column;
|
||||
color: #202020;
|
||||
background-color: #FFFFFF;
|
||||
border: 1px solid #eee;
|
||||
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
|
||||
border-radius: 16px;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.subscription-main .actions.is-open {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.subscription-main .actions > li {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
padding: 14px 35px 14px 18px;
|
||||
gap: 12px;
|
||||
cursor: pointer;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
.subscription-main .actions > li:hover {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
.subscription-main .actions > li > i {
|
||||
color: var(--main-color);
|
||||
}
|
||||
|
||||
.subscription-main .actions > li:hover > i {
|
||||
color: var(--hover-color);
|
||||
}
|
||||
|
||||
.subscription-secondary {
|
||||
display: none;
|
||||
|
||||
Reference in New Issue
Block a user