mirror of
https://github.com/ellite/Wallos.git
synced 2025-12-23 23:18:07 -05:00
feat: make container shutdown instant & graceful (#916) feat: add pushplus notification service (#911) feat: option to delete ai recommendations fix: parsing ai recommendations from gemini (#909)
367 lines
18 KiB
PHP
367 lines
18 KiB
PHP
<?php
|
|
|
|
require_once 'includes/header.php';
|
|
require_once 'includes/getdbkeys.php';
|
|
|
|
function formatPrice($price, $currencyCode, $currencies)
|
|
{
|
|
$formattedPrice = CurrencyFormatter::format($price, $currencyCode);
|
|
if (strstr($formattedPrice, $currencyCode)) {
|
|
$symbol = $currencyCode;
|
|
|
|
foreach ($currencies as $currency) {
|
|
|
|
if ($currency['code'] === $currencyCode) {
|
|
if ($currency['symbol'] != "") {
|
|
$symbol = $currency['symbol'];
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
$formattedPrice = str_replace($currencyCode, $symbol, $formattedPrice);
|
|
}
|
|
|
|
return $formattedPrice;
|
|
}
|
|
|
|
function formatDate($date, $lang = 'en')
|
|
{
|
|
$currentYear = date('Y');
|
|
$dateYear = date('Y', strtotime($date));
|
|
|
|
// Determine the date format based on whether the year matches the current year
|
|
$dateFormat = ($currentYear == $dateYear) ? 'MMM d' : 'MMM yyyy';
|
|
|
|
// Validate the locale and fallback to 'en' if unsupported
|
|
if (!in_array($lang, ResourceBundle::getLocales(''))) {
|
|
$lang = 'en'; // Fallback to English
|
|
}
|
|
|
|
// Create an IntlDateFormatter instance for the specified language
|
|
$formatter = new IntlDateFormatter(
|
|
$lang,
|
|
IntlDateFormatter::SHORT,
|
|
IntlDateFormatter::NONE,
|
|
null,
|
|
null,
|
|
$dateFormat
|
|
);
|
|
|
|
// Format the date
|
|
$formattedDate = $formatter->format(new DateTime($date));
|
|
|
|
return $formattedDate;
|
|
}
|
|
|
|
// Get the first name of the user
|
|
$stmt = $db->prepare("SELECT username, firstname FROM user WHERE id = :userId");
|
|
$stmt->bindValue(':userId', $userId, SQLITE3_INTEGER);
|
|
$result = $stmt->execute();
|
|
$user = $result->fetchArray(SQLITE3_ASSOC);
|
|
$first_name = $user['firstname'] ?? $user['username'] ?? '';
|
|
|
|
// Fetch the next 3 enabled subscriptions up for payment
|
|
$stmt = $db->prepare("SELECT id, logo, name, price, currency_id, next_payment, inactive FROM subscriptions WHERE user_id = :userId AND next_payment >= date('now') AND inactive = 0 ORDER BY next_payment ASC LIMIT 3");
|
|
$stmt->bindValue(':userId', $userId, SQLITE3_INTEGER);
|
|
$result = $stmt->execute();
|
|
$upcomingSubscriptions = [];
|
|
while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
|
|
$upcomingSubscriptions[] = $row;
|
|
}
|
|
|
|
// Fetch enabled subscriptions with manual renewal that are overdue
|
|
$stmt = $db->prepare("SELECT id, logo, name, price, currency_id, next_payment, inactive, auto_renew FROM subscriptions WHERE user_id = :userId AND next_payment < date('now') AND auto_renew = 0 AND inactive = 0 ORDER BY next_payment ASC");
|
|
$stmt->bindValue(':userId', $userId, SQLITE3_INTEGER);
|
|
$result = $stmt->execute();
|
|
$overdueSubscriptions = [];
|
|
while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
|
|
$overdueSubscriptions[] = $row;
|
|
}
|
|
$hasOverdueSubscriptions = !empty($overdueSubscriptions);
|
|
|
|
require_once 'includes/stats_calculations.php';
|
|
|
|
// Get AI Recommendations for user
|
|
$stmt = $db->prepare("SELECT * FROM ai_recommendations WHERE user_id = :userId");
|
|
$stmt->bindValue(':userId', $userId, SQLITE3_INTEGER);
|
|
$result = $stmt->execute();
|
|
$aiRecommendations = [];
|
|
while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
|
|
$aiRecommendations[] = $row;
|
|
}
|
|
|
|
?>
|
|
|
|
<section class="contain dashboard">
|
|
<h1><?= translate('hello', $i18n) ?> <?= htmlspecialchars($first_name) ?></h1>
|
|
|
|
<?php
|
|
// If there are overdue subscriptions, display them
|
|
if ($hasOverdueSubscriptions) {
|
|
?>
|
|
<div class="overdue-subscriptions">
|
|
<h2><?= translate('overdue_renewals', $i18n) ?></h2>
|
|
<div class="dashboard-subscriptions-container">
|
|
<div class="dashboard-subscriptions-list">
|
|
<?php
|
|
|
|
foreach ($overdueSubscriptions as $subscription) {
|
|
$subscriptionLogo = "images/uploads/logos/" . $subscription['logo'];
|
|
$subscriptionName = htmlspecialchars($subscription['name']);
|
|
$subscriptionPrice = $subscription['price'];
|
|
$subscriptionCurrency = $subscription['currency_id'];
|
|
$subscriptionNextPayment = $subscription['next_payment'];
|
|
$subscriptionDisplayNextPayment = date('F j', strtotime($subscriptionNextPayment));
|
|
$subscriptionDisplayPrice = formatPrice($subscriptionPrice, $currencies[$subscriptionCurrency]['code'], $currencies);
|
|
|
|
?>
|
|
<div class="subscription-item">
|
|
<?php
|
|
if (empty($subscription['logo'])) {
|
|
?>
|
|
<p class="subscription-item-title"><?= $subscriptionName ?></p>
|
|
<?php
|
|
} else {
|
|
?>
|
|
<img src="<?= $subscriptionLogo ?>" alt="<?= $subscriptionName ?> logo"
|
|
class="subscription-item-logo" title="<?= $subscriptionName ?>">
|
|
<?php
|
|
}
|
|
?>
|
|
<div class="subscription-item-info">
|
|
<p class="subscription-item-date"> <?= formatDate($subscriptionDisplayNextPayment, $lang) ?>
|
|
</p>
|
|
<p class="subscription-item-price"> <?= $subscriptionDisplayPrice ?></p>
|
|
</div>
|
|
</div>
|
|
<?php
|
|
}
|
|
?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<?php
|
|
}
|
|
?>
|
|
|
|
<div class="upcoming-subscriptions">
|
|
<h2><?= translate('upcoming_payments', $i18n) ?></h2>
|
|
<div class="dashboard-subscriptions-container">
|
|
<div class="dashboard-subscriptions-list">
|
|
<?php
|
|
if (empty($upcomingSubscriptions)) {
|
|
?>
|
|
<p><?= translate('no_upcoming_payments', $i18n) ?></p>
|
|
<?php
|
|
} else {
|
|
foreach ($upcomingSubscriptions as $subscription) {
|
|
$subscriptionLogo = "images/uploads/logos/" . $subscription['logo'];
|
|
$subscriptionName = htmlspecialchars($subscription['name']);
|
|
$subscriptionPrice = $subscription['price'];
|
|
$subscriptionCurrency = $subscription['currency_id'];
|
|
$subscriptionNextPayment = $subscription['next_payment'];
|
|
$subscriptionDisplayNextPayment = date('F j', strtotime($subscriptionNextPayment));
|
|
$subscriptionDisplayPrice = formatPrice($subscriptionPrice, $currencies[$subscriptionCurrency]['code'], $currencies);
|
|
|
|
?>
|
|
<div class="subscription-item">
|
|
<?php
|
|
if (empty($subscription['logo'])) {
|
|
?>
|
|
<p class="subscription-item-title"><?= $subscriptionName ?></p>
|
|
<?php
|
|
} else {
|
|
?>
|
|
<img src="<?= $subscriptionLogo ?>" alt="<?= $subscriptionName ?> logo"
|
|
class="subscription-item-logo" title="<?= $subscriptionName ?>">
|
|
<?php
|
|
}
|
|
?>
|
|
<div class="subscription-item-info">
|
|
<p class="subscription-item-date"> <?= formatDate($subscriptionDisplayNextPayment, $lang) ?></p>
|
|
<p class="subscription-item-price"> <?= $subscriptionDisplayPrice ?></p>
|
|
</div>
|
|
</div>
|
|
<?php
|
|
}
|
|
}
|
|
?>
|
|
</div>
|
|
</div>
|
|
|
|
<?php if (!empty($aiRecommendations)) { ?>
|
|
<div class="ai-recommendations">
|
|
<h2><?= translate('ai_recommendations', $i18n) ?></h2>
|
|
<div class="ai-recommendations-container">
|
|
<ul class="ai-recommendations-list">
|
|
<?php
|
|
|
|
foreach ($aiRecommendations as $key => $recommendation) { ?>
|
|
<li class="ai-recommendation-item" data-id="<?= $recommendation['id'] ?>">
|
|
<div class="ai-recommendation-header">
|
|
<h3>
|
|
<span><?= ($key + 1) . ". " ?></span>
|
|
<?= htmlspecialchars($recommendation['title']) ?>
|
|
</h3>
|
|
<span class="item-arrow-down fa fa-caret-down"></span>
|
|
</div>
|
|
<p class="collapsible"><?= htmlspecialchars($recommendation['description']) ?></p>
|
|
<p class="ai-recommendation-savings">
|
|
<?= htmlspecialchars($recommendation['savings']) ?>
|
|
<span>
|
|
<a href="#" class="delete-ai-recommendation" title="<?= translate('delete', $i18n) ?>">
|
|
<i class="fa fa-trash"></i>
|
|
</a>
|
|
</span>
|
|
</p>
|
|
</li>
|
|
<?php } ?>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<?php } ?>
|
|
|
|
<?php if (isset($amountDueThisMonth) || isset($budget) || isset($budgetUsed) || isset($budgetLeft) || isset($overBudgetAmount)) { ?>
|
|
<div class="budget-subscriptions">
|
|
<h2><?= translate('your_budget', $i18n) ?></h2>
|
|
<div class="dashboard-subscriptions-container">
|
|
<div class="dashboard-subscriptions-list">
|
|
<?php if (isset($amountDueThisMonth)) { ?>
|
|
<div class="subscription-item thin">
|
|
<p class="subscription-item-title"><?= translate("amount_due", $i18n) ?></p>
|
|
<div class="subscription-item-info">
|
|
<p class="subscription-item-value">
|
|
<?= CurrencyFormatter::format($amountDueThisMonth, $currencies[$userData['main_currency']]['code']) ?>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<?php } ?>
|
|
<?php if (isset($budget) && $budget > 0) { ?>
|
|
<div class="subscription-item thin">
|
|
<p class="subscription-item-title"><?= translate("budget", $i18n) ?></p>
|
|
<div class="subscription-item-info">
|
|
<p class="subscription-item-value">
|
|
<?= formatPrice($budget, $currencies[$userData['main_currency']]['code'], $currencies) ?>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<?php } ?>
|
|
<?php if (isset($budgetUsed)) { ?>
|
|
<div class="subscription-item thin">
|
|
<p class="subscription-item-title"><?= translate("budget_used", $i18n) ?></p>
|
|
<div class="subscription-item-info">
|
|
<p class="subscription-item-value">
|
|
<?= number_format($budgetUsed, 2) ?>%
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<?php } ?>
|
|
<?php if (isset($budgetLeft)) { ?>
|
|
<div class="subscription-item thin">
|
|
<p class="subscription-item-title"><?= translate("budget_remaining", $i18n) ?></p>
|
|
<div class="subscription-item-info">
|
|
<p class="subscription-item-value">
|
|
<?= formatPrice($budgetLeft, $currencies[$userData['main_currency']]['code'], $currencies) ?>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<?php } ?>
|
|
<?php if (isset($overBudgetAmount) && $overBudgetAmount > 0) { ?>
|
|
<div class="subscription-item thin">
|
|
<p class="subscription-item-title"><?= translate("over_budget", $i18n) ?></p>
|
|
<div class="subscription-item-info">
|
|
<p class="subscription-item-value">
|
|
<?= formatPrice($overBudgetAmount, $currencies[$userData['main_currency']]['code'], $currencies) ?>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<?php } ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<?php } ?>
|
|
</div>
|
|
|
|
<?php if (isset($activeSubscriptions) && $activeSubscriptions > 0) { ?>
|
|
<div class="current-subscriptions">
|
|
<h2><?= translate('your_subscriptions', $i18n) ?></h2>
|
|
<div class="dashboard-subscriptions-container">
|
|
<div class="dashboard-subscriptions-list">
|
|
<div class="subscription-item thin">
|
|
<p class="subscription-item-title"><?= translate('active_subscriptions', $i18n) ?></p>
|
|
<div class="subscription-item-info">
|
|
<p class="subscription-item-value"><?= $activeSubscriptions ?></p>
|
|
</div>
|
|
</div>
|
|
|
|
<?php if (isset($totalCostPerMonth)) { ?>
|
|
<div class="subscription-item thin">
|
|
<p class="subscription-item-title"><?= translate('monthly_cost', $i18n) ?></p>
|
|
<div class="subscription-item-info">
|
|
<p class="subscription-item-value">
|
|
<?= CurrencyFormatter::format($totalCostPerMonth, $currencies[$userData['main_currency']]['code']) ?>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<?php } ?>
|
|
|
|
<?php if (isset($totalCostPerYear)) { ?>
|
|
<div class="subscription-item thin">
|
|
<p class="subscription-item-title"><?= translate('yearly_cost', $i18n) ?></p>
|
|
<div class="subscription-item-info">
|
|
<p class="subscription-item-value">
|
|
<?= CurrencyFormatter::format($totalCostPerYear, $currencies[$userData['main_currency']]['code']) ?>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<?php } ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<?php } ?>
|
|
|
|
<?php if (isset($inactiveSubscriptions) && $inactiveSubscriptions > 0) { ?>
|
|
<div class="savings-subscriptions">
|
|
<h2><?= translate('your_savings', $i18n) ?></h2>
|
|
<div class="dashboard-subscriptions-container">
|
|
<div class="dashboard-subscriptions-list">
|
|
<div class="subscription-item thin">
|
|
<p class="subscription-item-title"><?= translate('inactive_subscriptions', $i18n) ?></p>
|
|
<div class="subscription-item-info">
|
|
<p class="subscription-item-value"><?= $inactiveSubscriptions ?></p>
|
|
</div>
|
|
</div>
|
|
|
|
<?php if (isset($totalSavingsPerMonth) && $totalSavingsPerMonth > 0) { ?>
|
|
<div class="subscription-item thin">
|
|
<p class="subscription-item-title"><?= translate('monthly_savings', $i18n) ?></p>
|
|
<div class="subscription-item-info">
|
|
<p class="subscription-item-value">
|
|
<?= CurrencyFormatter::format($totalSavingsPerMonth, $currencies[$userData['main_currency']]['code']) ?>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="subscription-item thin">
|
|
<p class="subscription-item-title"><?= translate('yearly_savings', $i18n) ?></p>
|
|
<div class="subscription-item-info">
|
|
<p class="subscription-item-value">
|
|
<?= CurrencyFormatter::format($totalSavingsPerMonth * 12, $currencies[$userData['main_currency']]['code']) ?>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<?php } ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<?php } ?>
|
|
|
|
</section>
|
|
|
|
|
|
<script src="scripts/dashboard.js?<?= $version ?>"></script>
|
|
|
|
<?php
|
|
require_once 'includes/footer.php';
|
|
?>
|