feat: add monthly budget field and statistics (#329)

This commit is contained in:
Miguel Ribeiro 2024-05-17 23:14:17 +02:00 committed by GitHub
parent e21500a719
commit b622434ca0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
24 changed files with 286 additions and 14 deletions

57
endpoints/user/budget.php Normal file
View File

@ -0,0 +1,57 @@
<?php
require_once '../../includes/connect_endpoint.php';
require_once '../../includes/inputvalidation.php';
session_start();
if (!isset($_SESSION['loggedin']) || $_SESSION['loggedin'] !== true) {
die(json_encode([
"success" => false,
"message" => translate('session_expired', $i18n)
]));
}
if ($_SERVER["REQUEST_METHOD"] === "POST") {
$postData = file_get_contents("php://input");
$data = json_decode($postData, true);
if (
!isset($data["budget"]) || $data["budget"] == ""
) {
$response = [
"success" => false,
"message" => translate('fill_mandatory_fields', $i18n)
];
echo json_encode($response);
} else {
$budget = $data["budget"];
$userId = $_SESSION['userId'];
$sql = "UPDATE user SET budget = :budget WHERE id = :userId";
$stmt = $db->prepare($sql);
$stmt->bindValue(':budget', $budget, SQLITE3_TEXT);
$stmt->bindValue(':userId', $userId, SQLITE3_TEXT);
$result = $stmt->execute();
if ($result) {
$response = [
"success" => true,
"message" => translate('user_details_saved', $i18n)
];
echo json_encode($response);
} else {
$response = [
"success" => false,
"message" => translate('error_updating_user_data', $i18n)
];
echo json_encode($response);
}
}
}
?>

View File

@ -12,6 +12,8 @@
if ($userData === false) { if ($userData === false) {
header('Location: logout.php'); header('Location: logout.php');
exit(); exit();
} else {
$_SESSION['userId'] = $userData['id'];
} }
if ($userData['avatar'] == "") { if ($userData['avatar'] == "") {
@ -55,6 +57,7 @@
$_SESSION['token'] = $token; $_SESSION['token'] = $token;
$_SESSION['loggedin'] = true; $_SESSION['loggedin'] = true;
$_SESSION['main_currency'] = $main_currency; $_SESSION['main_currency'] = $main_currency;
$_SESSION['userId'] = $userId;
} else { } else {
$db->close(); $db->close();
header("Location: logout.php"); header("Location: logout.php");

View File

@ -85,7 +85,11 @@ $i18n = [
'average_monthly' => "Durchschnittliche monatliche Kosten", 'average_monthly' => "Durchschnittliche monatliche Kosten",
'most_expensive' => "Kosten des teuersten Abonnements", 'most_expensive' => "Kosten des teuersten Abonnements",
'amount_due' => "Diesen Monat fällige Summe", 'amount_due' => "Diesen Monat fällige Summe",
'percentage_budget_used' => "Prozentualer Anteil des Budgets genutzt",
'budget_remaining' => "Verbleibendes Budget",
'amount_over_budget' => "Überzogenes Budget",
'monthly_savings' => "Monatliche Ersparnisse (bei inaktiven Abonnements)", 'monthly_savings' => "Monatliche Ersparnisse (bei inaktiven Abonnements)",
'yearly_savings' => "Jährliche Ersparnisse (bei inaktiven Abonnements)",
'split_views' => "Aufgeteilte Ansichten", 'split_views' => "Aufgeteilte Ansichten",
'category_split' => "Kategorien", 'category_split' => "Kategorien",
'household_split' => "Haushalt", 'household_split' => "Haushalt",
@ -101,7 +105,9 @@ $i18n = [
'upload_avatar' => "Avatar hochladen", 'upload_avatar' => "Avatar hochladen",
'file_type_error' => "Dateityp nicht unterstützt", 'file_type_error' => "Dateityp nicht unterstützt",
'user_details' => "Benutzerdetails", 'user_details' => "Benutzerdetails",
"household" => "Haushalt", "monthly_budget" => "Monatliches Budget",
"budget_info" => "Das monatliche Budget wird für die Berechnung der Statistiken verwendet.",
"household" => "Haushalt",
"save_member" => "Mitglied speichern", "save_member" => "Mitglied speichern",
"delete_member" => "Mitglied löschen", "delete_member" => "Mitglied löschen",
"cant_delete_member" => "Hauptmitglied kann nicht gelöscht werden", "cant_delete_member" => "Hauptmitglied kann nicht gelöscht werden",

View File

@ -85,7 +85,11 @@ $i18n = [
'average_monthly' => "Μέσο μηνιαίο κόστος συνδρομής", 'average_monthly' => "Μέσο μηνιαίο κόστος συνδρομής",
'most_expensive' => "Πιο ακριβό κόστος συνδρομής", 'most_expensive' => "Πιο ακριβό κόστος συνδρομής",
'amount_due' => "Ποσό που οφείλεται αυτόν τον μήνα", 'amount_due' => "Ποσό που οφείλεται αυτόν τον μήνα",
'percentage_budget_used' => "Ποσοστό προϋπολογισμού που χρησιμοποιείται",
'budget_remaining' => "Υπόλοιπο προϋπολογισμού",
'amount_over_budget' => "Ποσό πάνω από τον προϋπολογισμό",
'monthly_savings' => "Μηνιαίες εξοικονομήσεις (σε ανενεργές συνδρομές)", 'monthly_savings' => "Μηνιαίες εξοικονομήσεις (σε ανενεργές συνδρομές)",
'yearly_savings' => "Ετήσιες εξοικονομήσεις (σε ανενεργές συνδρομές)",
'split_views' => "Διαχωρισμένες προβολές", 'split_views' => "Διαχωρισμένες προβολές",
'category_split' => "Διαχωρισμός κατηγορίας", 'category_split' => "Διαχωρισμός κατηγορίας",
'household_split' => "Διαχωρισμός νοικοκυριού", 'household_split' => "Διαχωρισμός νοικοκυριού",
@ -101,7 +105,9 @@ $i18n = [
'upload_avatar' => "μεταφόρτωση άβαταρ", 'upload_avatar' => "μεταφόρτωση άβαταρ",
'file_type_error' => "Το αρχείο πρέπει να είναι τύπου jpg, jpeg, png, webp ή gif", 'file_type_error' => "Το αρχείο πρέπει να είναι τύπου jpg, jpeg, png, webp ή gif",
'user_details' => "Λεπτομέρειες χρήστη", 'user_details' => "Λεπτομέρειες χρήστη",
"household" => "Νοικοκυριό", "monthly_budget" => "Μηνιαίος προϋπολογισμός",
"budget_info" => "Ο μηνιαίος προϋπολογισμός χρησιμοποιείται για τον υπολογισμό των στατιστικών",
"household" => "Νοικοκυριό",
"save_member" => "Αποθήκευση μέλους", "save_member" => "Αποθήκευση μέλους",
"delete_member" => "Διαγραφή μέλους", "delete_member" => "Διαγραφή μέλους",
"cant_delete_member" => "Δεν ειναι δυνατή η διαγραφή του βασικού μέλους", "cant_delete_member" => "Δεν ειναι δυνατή η διαγραφή του βασικού μέλους",

View File

@ -85,7 +85,11 @@ $i18n = [
'average_monthly' => "Average Monthly Subscription Cost", 'average_monthly' => "Average Monthly Subscription Cost",
'most_expensive' => "Most Expensive Subscription Cost", 'most_expensive' => "Most Expensive Subscription Cost",
'amount_due' => "Amount due this month", 'amount_due' => "Amount due this month",
'percentage_budget_used' => "Percentage of budget used",
'budget_remaining' => "Budget Remaining",
'amount_over_budget' => "Amount over budget",
'monthly_savings' => "Monthly Savings (on inactive subscriptions)", 'monthly_savings' => "Monthly Savings (on inactive subscriptions)",
'yearly_savings' => "Yearly Savings (on inactive subscriptions)",
'split_views' => "Split Views", 'split_views' => "Split Views",
'category_split' => "Category Split", 'category_split' => "Category Split",
'household_split' => "Household Split", 'household_split' => "Household Split",
@ -101,7 +105,9 @@ $i18n = [
'upload_avatar' => "Upload Avatar", 'upload_avatar' => "Upload Avatar",
'file_type_error' => "The file type supplied is not supported.", 'file_type_error' => "The file type supplied is not supported.",
'user_details' => "User Details", 'user_details' => "User Details",
"household" => "Household", "monthly_budget" => "Monthly Budget",
"budget_info" => "Monthly budget is used to calculate statistics",
"household" => "Household",
"save_member" => "Save Member", "save_member" => "Save Member",
"delete_member" => "Delete Member", "delete_member" => "Delete Member",
"cant_delete_member" => "Can't delete main member", "cant_delete_member" => "Can't delete main member",

View File

@ -85,7 +85,11 @@ $i18n = [
'average_monthly' => "Costo Promedio Mensual de Suscripción", 'average_monthly' => "Costo Promedio Mensual de Suscripción",
'most_expensive' => "Costo de Suscripción Más Caro", 'most_expensive' => "Costo de Suscripción Más Caro",
'amount_due' => "Monto a pagar este mes", 'amount_due' => "Monto a pagar este mes",
'percentage_budget_used' => "Porcentaje del presupuesto utilizado",
'budget_remaining' => "Presupuesto Restante",
'amount_over_budget' => "Monto sobre el presupuesto",
'monthly_savings' => "Ahorro Mensual (en suscripciones inactivas)", 'monthly_savings' => "Ahorro Mensual (en suscripciones inactivas)",
'yearly_savings' => "Ahorro Anual (en suscripciones inactivas)",
'split_views' => "Vistas Divididas", 'split_views' => "Vistas Divididas",
'category_split' => "División por Categoría", 'category_split' => "División por Categoría",
'household_split' => "División por Hogar", 'household_split' => "División por Hogar",
@ -101,7 +105,9 @@ $i18n = [
'upload_avatar' => "Subir avatar", 'upload_avatar' => "Subir avatar",
'file_type_error' => "El archivo debe ser una imagen en formato PNG, JPG, WEBP o SVG", 'file_type_error' => "El archivo debe ser una imagen en formato PNG, JPG, WEBP o SVG",
'user_details' => "Detalles del Usuario", 'user_details' => "Detalles del Usuario",
"household" => "Hogar", "monthly_budget" => "Presupuesto Mensual",
"budget_info" => "El presupuesto mensual se utiliza para calcular las estadísticas. Si no deseas utilizar esta función, déjalo en 0.",
"household" => "Hogar",
"save_member" => "Guardar Miembro", "save_member" => "Guardar Miembro",
"delete_member" => "Eliminar Miembro", "delete_member" => "Eliminar Miembro",
"cant_delete_member" => "No se puede eliminar el miembro principal", "cant_delete_member" => "No se puede eliminar el miembro principal",

View File

@ -85,7 +85,11 @@ $i18n = [
'average_monthly' => "Coût moyen mensuel de l'abonnement", 'average_monthly' => "Coût moyen mensuel de l'abonnement",
'most_expensive' => "Coût d'abonnement le plus élevé", 'most_expensive' => "Coût d'abonnement le plus élevé",
'amount_due' => "Montant dû ce mois-ci", 'amount_due' => "Montant dû ce mois-ci",
'percentage_budget_used' => "Pourcentage du budget utilisé",
'budget_remaining' => "Budget restant",
'amount_over_budget' => "Montant dépassant le budget",
'monthly_savings' => "Économies mensuelles (sur les abonnements inactifs)", 'monthly_savings' => "Économies mensuelles (sur les abonnements inactifs)",
'yearly_savings' => "Économies annuelles (sur les abonnements inactifs)",
'split_views' => "Vues partagées", 'split_views' => "Vues partagées",
'category_split' => "Répartition par catégorie", 'category_split' => "Répartition par catégorie",
'household_split' => "Répartition du ménage", 'household_split' => "Répartition du ménage",
@ -101,6 +105,8 @@ $i18n = [
'upload_avatar' => "Télécharger un Avatar", 'upload_avatar' => "Télécharger un Avatar",
'file_type_error' => "Le type de fichier n'est pas pris en charge", 'file_type_error' => "Le type de fichier n'est pas pris en charge",
'user_details' => "Détails de l'utilisateur", 'user_details' => "Détails de l'utilisateur",
"monthly_budget" => "Budget mensuel",
"budget_info" => "Le budget mensuel est utilisé pour calculer les statistiques. Laissez vide pour désactiver.",
"household" => "Ménage", "household" => "Ménage",
"save_member" => "Enregistrer le membre", "save_member" => "Enregistrer le membre",
"delete_member" => "Supprimer le membre", "delete_member" => "Supprimer le membre",

View File

@ -88,7 +88,11 @@ $i18n = [
'average_monthly' => "Costo medio mensile dell'abbonamento", 'average_monthly' => "Costo medio mensile dell'abbonamento",
'most_expensive' => "Costo dell'abbonamento più elevato", 'most_expensive' => "Costo dell'abbonamento più elevato",
'amount_due' => 'Importo dovuto questo mese', 'amount_due' => 'Importo dovuto questo mese',
'percentage_budget_used' => 'Percentuale del budget utilizzata',
'budget_remaining' => 'Budget rimanente',
'amount_over_budget' => 'Importo oltre il budget',
'monthly_savings' => 'Risparmi mensili (su abbonamenti inattivi)', 'monthly_savings' => 'Risparmi mensili (su abbonamenti inattivi)',
'yearly_savings' => 'Risparmi annuali (su abbonamenti inattivi)',
'split_views' => 'Visualizzazioni con grafici', 'split_views' => 'Visualizzazioni con grafici',
'category_split' => 'Suddivisione per categoria', 'category_split' => 'Suddivisione per categoria',
'household_split' => 'Suddivisione per nucleo familiare', 'household_split' => 'Suddivisione per nucleo familiare',
@ -106,6 +110,8 @@ $i18n = [
'upload_avatar' => 'Carica avatar', 'upload_avatar' => 'Carica avatar',
'file_type_error' => 'Il tipo di file fornito non è supportato.', 'file_type_error' => 'Il tipo di file fornito non è supportato.',
'user_details' => 'Dettagli utente', 'user_details' => 'Dettagli utente',
"monthly_budget" => "Budget mensile",
"budget_info" => "Il budget mensile viene utilizzato per calcolare le statistiche. Se non si desidera utilizzare questa funzionalità, impostare il budget su 0.",
'household' => 'Nucleo familiare', 'household' => 'Nucleo familiare',
'save_member' => 'Salva membro', 'save_member' => 'Salva membro',
'delete_member' => 'Elimina membro', 'delete_member' => 'Elimina membro',

View File

@ -85,7 +85,11 @@ $i18n = [
'average_monthly' => "月額平均費用", 'average_monthly' => "月額平均費用",
'most_expensive' => "最も高額な定期購入費用", 'most_expensive' => "最も高額な定期購入費用",
'amount_due' => "今月の支払額", 'amount_due' => "今月の支払額",
'percentage_budget_used' => "予算使用率",
'budget_remaining' => "予算残高",
'amount_over_budget' => "予算オーバー",
'monthly_savings' => "月間節約 (非アクティブな定期購入)", 'monthly_savings' => "月間節約 (非アクティブな定期購入)",
'yearly_savings' => "年間節約 (非アクティブな定期購入)",
'split_views' => "分割表示", 'split_views' => "分割表示",
'category_split' => "カテゴリ別", 'category_split' => "カテゴリ別",
'household_split' => "世帯別", 'household_split' => "世帯別",
@ -101,7 +105,9 @@ $i18n = [
'upload_avatar' => "アバターをアップロードする", 'upload_avatar' => "アバターをアップロードする",
'file_type_error' => "ファイルタイプが許可されていません", 'file_type_error' => "ファイルタイプが許可されていません",
'user_details' => "ユーザー詳細", 'user_details' => "ユーザー詳細",
"household" => "世帯", "monthly_budget" => "月間予算",
"budget_info" => "予算を設定すると、統計ページで予算と実際の支出を比較できます。",
"household" => "世帯",
"save_member" => "世帯員を保存", "save_member" => "世帯員を保存",
"delete_member" => "世帯員を削除", "delete_member" => "世帯員を削除",
"cant_delete_member" => "世帯主は削除出ません", "cant_delete_member" => "世帯主は削除出ません",

View File

@ -85,7 +85,11 @@ $i18n = [
'average_monthly' => "월별 평균 구독 비용", 'average_monthly' => "월별 평균 구독 비용",
'most_expensive' => "최고가 구독 비용", 'most_expensive' => "최고가 구독 비용",
'amount_due' => "이달의 결제 비용", 'amount_due' => "이달의 결제 비용",
'percentage_budget_used' => "예산 사용률",
'budget_remaining' => "남은 예산",
'amount_over_budget' => "예산 초과",
'monthly_savings' => "월간 절약 (비활성 구독)", 'monthly_savings' => "월간 절약 (비활성 구독)",
'yearly_savings' => "연간 절약 (비활성 구독)",
'split_views' => "분할 표시", 'split_views' => "분할 표시",
'category_split' => "카테고리별", 'category_split' => "카테고리별",
'household_split' => "가구별", 'household_split' => "가구별",
@ -101,7 +105,9 @@ $i18n = [
'upload_avatar' => "아바타 업로드", 'upload_avatar' => "아바타 업로드",
'file_type_error' => "제공된 파일이 지원하지 않는 타입입니다.", 'file_type_error' => "제공된 파일이 지원하지 않는 타입입니다.",
'user_details' => "유저 상세", 'user_details' => "유저 상세",
"household" => "가구", "monthly_budget" => "월간 예산",
"budget_info" => "예산을 설정하면 통계 페이지에서 예산과 실제 지출을 비교할 수 있습니다.",
"household" => "가구",
"save_member" => "구성원 저장", "save_member" => "구성원 저장",
"delete_member" => "구성원 삭제", "delete_member" => "구성원 삭제",
"cant_delete_member" => "메인 구성원은 삭제할 수 없습니다", "cant_delete_member" => "메인 구성원은 삭제할 수 없습니다",

View File

@ -85,7 +85,11 @@ $i18n = [
'average_monthly' => "Średni miesięczny koszt subskrypcji", 'average_monthly' => "Średni miesięczny koszt subskrypcji",
'most_expensive' => "Najdroższy koszt subskrypcji", 'most_expensive' => "Najdroższy koszt subskrypcji",
'amount_due' => "Kwota należna w tym miesiącu", 'amount_due' => "Kwota należna w tym miesiącu",
'percentage_budget_used' => "Procent wykorzystania budżetu",
'budget_remaining' => "Pozostały budżet",
'amount_over_budget' => "Kwota przekraczająca budżet",
'monthly_savings' => "Miesięczne oszczędności (w przypadku nieaktywnych subskrypcji)", 'monthly_savings' => "Miesięczne oszczędności (w przypadku nieaktywnych subskrypcji)",
'yearly_savings' => "Roczne oszczędności (w przypadku nieaktywnych subskrypcji)",
'split_views' => "Podziel widoki", 'split_views' => "Podziel widoki",
'category_split' => "Podział kategorii", 'category_split' => "Podział kategorii",
'household_split' => "Podział gospodarstwa domowego", 'household_split' => "Podział gospodarstwa domowego",
@ -101,7 +105,9 @@ $i18n = [
'upload_avatar' => "Prześlij awatar", 'upload_avatar' => "Prześlij awatar",
'file_type_error' => "Podany typ pliku nie jest obsługiwany.", 'file_type_error' => "Podany typ pliku nie jest obsługiwany.",
'user_details' => "Szczegóły użytkownika", 'user_details' => "Szczegóły użytkownika",
"household" => "Gospodarstwo domowe", "monthly_budget" => "Miesięczny budżet",
"budget_info" => "Jeśli ustawisz budżet, zobaczysz pasek postępu na stronie głównej.",
"household" => "Gospodarstwo domowe",
"save_member" => "Zapisz użytkownika", "save_member" => "Zapisz użytkownika",
"delete_member" => "Usuń użytkownika", "delete_member" => "Usuń użytkownika",
"cant_delete_member" => "Nie można usunąć głównego użytkownika", "cant_delete_member" => "Nie można usunąć głównego użytkownika",

View File

@ -85,7 +85,11 @@ $i18n = [
'average_monthly' => "Custo Mensal Médio das Subscrições", 'average_monthly' => "Custo Mensal Médio das Subscrições",
'most_expensive' => "Custo da Subscrição Mais Cara", 'most_expensive' => "Custo da Subscrição Mais Cara",
'amount_due' => "Quantia em dívida este mês", 'amount_due' => "Quantia em dívida este mês",
'percentage_budget_used' => "Percentagem do orçamento usada",
'budget_remaining' => "Orçamento Restante",
'amount_over_budget' => "Quantia acima do orçamento",
'monthly_savings' => "Poupança Mensal (em subscrições inactivas)", 'monthly_savings' => "Poupança Mensal (em subscrições inactivas)",
'yearly_savings' => "Poupança Anual (em subscrições inactivas)",
'split_views' => "Vistas Divididas", 'split_views' => "Vistas Divididas",
'category_split' => "Por Categoria", 'category_split' => "Por Categoria",
'household_split' => "Por Membro", 'household_split' => "Por Membro",
@ -101,7 +105,9 @@ $i18n = [
'upload_avatar' => "Enviar avatar", 'upload_avatar' => "Enviar avatar",
'file_type_error' => "Tipo de ficheiro não permitido", 'file_type_error' => "Tipo de ficheiro não permitido",
'user_details' => "Detalhes do utilizador", 'user_details' => "Detalhes do utilizador",
"household" => "Agregado", "monthly_budget" => "Orçamento Mensal",
"budget_info" => "Ao definir um orçamento pode comparar com os gastos reais na página de estatísticas.",
"household" => "Agregado",
"save_member" => "Guardar Membro", "save_member" => "Guardar Membro",
"delete_member" => "Apagar Membro", "delete_member" => "Apagar Membro",
"cant_delete_member" => "Não pode apagar o membro principal", "cant_delete_member" => "Não pode apagar o membro principal",

View File

@ -83,7 +83,11 @@ $i18n = [
'average_monthly' => "Custom médio mensal", 'average_monthly' => "Custom médio mensal",
'most_expensive' => "Assinatura mais cara", 'most_expensive' => "Assinatura mais cara",
'amount_due' => "Valor devido nesse mês", 'amount_due' => "Valor devido nesse mês",
'percentage_budget_used' => "Porcentagem do orçamento utilizado",
'budget_remaining' => "Orçamento restante",
'amount_over_budget' => "Valor acima do orçamento",
'monthly_savings' => "Economia mensal (em assinaturas inativas)", 'monthly_savings' => "Economia mensal (em assinaturas inativas)",
'yearly_savings' => "Economia anual (em assinaturas inativas)",
'split_views' => "Visualizações", 'split_views' => "Visualizações",
'category_split' => "Por categoria", 'category_split' => "Por categoria",
'household_split' => "Por membro", 'household_split' => "Por membro",
@ -99,7 +103,9 @@ $i18n = [
'upload_avatar' => "Carregar avatar", 'upload_avatar' => "Carregar avatar",
'file_type_error' => "Tipo de arquivo não permitido", 'file_type_error' => "Tipo de arquivo não permitido",
'user_details' => "Informações do Usuário", 'user_details' => "Informações do Usuário",
"household" => "Membros", "monthly_budget" => "Orçamento mensal",
"budget_info" => "O orçamento mensal é usado para calcular estatísticas",
"household" => "Membros",
"save_member" => "Salvar membro", "save_member" => "Salvar membro",
"delete_member" => "Excluir membro", "delete_member" => "Excluir membro",
"cant_delete_member" => "Não é possível excluir o membro principal", "cant_delete_member" => "Não é possível excluir o membro principal",

View File

@ -85,7 +85,11 @@ $i18n = [
'average_monthly' => "Средняя ежемесячная стоимость подписки", 'average_monthly' => "Средняя ежемесячная стоимость подписки",
'most_expensive' => "Самая дорогая стоимость подписки", 'most_expensive' => "Самая дорогая стоимость подписки",
'amount_due' => "Сумма к оплате в этом месяце", 'amount_due' => "Сумма к оплате в этом месяце",
'percentage_budget_used' => "Процент использования бюджета",
'budget_remaining' => "Оставшийся бюджет",
'amount_over_budget' => "Сумма превышения бюджета",
'monthly_savings' => "Ежемесячная экономия (при неактивных подписках)", 'monthly_savings' => "Ежемесячная экономия (при неактивных подписках)",
'yearly_savings' => "Годовая экономия (при неактивных подписках)",
'split_views' => "Подробная статистика", 'split_views' => "Подробная статистика",
'category_split' => "По категориям", 'category_split' => "По категориям",
'household_split' => "По членам семьи", 'household_split' => "По членам семьи",
@ -101,7 +105,9 @@ $i18n = [
'upload_avatar' => "Загрузить аватар", 'upload_avatar' => "Загрузить аватар",
'file_type_error' => "Указанный тип файла не поддерживается.", 'file_type_error' => "Указанный тип файла не поддерживается.",
'user_details' => "Данные пользователя", 'user_details' => "Данные пользователя",
"household" => "Семья", "monthly_budget" => "Ежемесячный бюджет",
"budget_info" => "Если вы укажете бюджет, Wallos будет отображать вашу текущую стоимость подписок в сравнении с вашим бюджетом.",
"household" => "Семья",
"save_member" => "Сохранить члена семьи", "save_member" => "Сохранить члена семьи",
"delete_member" => "Удалить члена семьи", "delete_member" => "Удалить члена семьи",
"cant_delete_member" => "Не могу удалить основного члена семьи", "cant_delete_member" => "Не могу удалить основного члена семьи",

View File

@ -85,7 +85,11 @@ $i18n = [
'average_monthly' => "Просечни месечни трошак претплате", 'average_monthly' => "Просечни месечни трошак претплате",
'most_expensive' => "Најскупља претплата", 'most_expensive' => "Најскупља претплата",
'amount_due' => "Износ за уплату овог месеца", 'amount_due' => "Износ за уплату овог месеца",
'percentage_budget_used' => "Проценат искоришћеног буџета",
'budget_remaining' => "Преостали буџет",
'amount_over_budget' => "Износ преко буџета",
'monthly_savings' => "Месечне уштеде (на неактивним претплатама)", 'monthly_savings' => "Месечне уштеде (на неактивним претплатама)",
'yearly_savings' => "Годишње уштеде (на неактивним претплатама)",
'split_views' => "Подељени прикази", 'split_views' => "Подељени прикази",
'category_split' => "Подела по категоријама", 'category_split' => "Подела по категоријама",
'household_split' => "Подела по домаћинству", 'household_split' => "Подела по домаћинству",
@ -101,7 +105,9 @@ $i18n = [
'upload_avatar' => "Постави аватар", 'upload_avatar' => "Постави аватар",
'file_type_error' => "Датотека није у подржаном формату.", 'file_type_error' => "Датотека није у подржаном формату.",
'user_details' => "Кориснички детаљи", 'user_details' => "Кориснички детаљи",
"household" => "Домаћинство", "monthly_budget" => "Месечни буџет",
"budget_info" => "Унесите месечни буџет да бисте видели препоручену максималну цену претплате на почетној страници.",
"household" => "Домаћинство",
"save_member" => "Сачувај члана", "save_member" => "Сачувај члана",
"delete_member" => "Обриши члана", "delete_member" => "Обриши члана",
"cant_delete_member" => "Главни члан не може бити обрисан", "cant_delete_member" => "Главни члан не може бити обрисан",

View File

@ -85,7 +85,11 @@ $i18n = [
'average_monthly' => "Prosečni mesečni trošak pretplate", 'average_monthly' => "Prosečni mesečni trošak pretplate",
'most_expensive' => "Najskuplja pretplata", 'most_expensive' => "Najskuplja pretplata",
'amount_due' => "Iznos za plaćanje ovog meseca", 'amount_due' => "Iznos za plaćanje ovog meseca",
'percentage_budget_used' => "Procenat budžeta iskorišćen",
'budget_remaining' => "Preostali budžet",
'amount_over_budget' => "Iznos preko budžeta",
'monthly_savings' => "Mesečne uštede (na neaktivnim pretplatama)", 'monthly_savings' => "Mesečne uštede (na neaktivnim pretplatama)",
'yearly_savings' => "Godišnje uštede (na neaktivnim pretplatama)",
'split_views' => "Podeljene statistike", 'split_views' => "Podeljene statistike",
'category_split' => "Podela po kategorijama", 'category_split' => "Podela po kategorijama",
'household_split' => "Podela po domaćinstvima", 'household_split' => "Podela po domaćinstvima",
@ -101,7 +105,9 @@ $i18n = [
'upload_avatar' => "Učitaj avatar", 'upload_avatar' => "Učitaj avatar",
'file_type_error' => "Tip datoteke koji ste priložili nije podržan.", 'file_type_error' => "Tip datoteke koji ste priložili nije podržan.",
'user_details' => "Detalji korisnika", 'user_details' => "Detalji korisnika",
"household" => "Domaćinstvo", "monthly_budget" => "Mesečni budžet",
"budget_info" => "Ovo je vaš mesečni budžet za sve pretplate. Ovo je samo informativno i ne ograničava vas.",
"household" => "Domaćinstvo",
"save_member" => "Sačuvaj člana", "save_member" => "Sačuvaj člana",
"delete_member" => "Izbriši člana", "delete_member" => "Izbriši člana",
"cant_delete_member" => "Nemoguće brisanje glavnog člana", "cant_delete_member" => "Nemoguće brisanje glavnog člana",

View File

@ -85,7 +85,11 @@ $i18n = [
'average_monthly' => "Ortalama Aylık Abonelik Maliyeti", 'average_monthly' => "Ortalama Aylık Abonelik Maliyeti",
'most_expensive' => "En Pahalı Abonelik Maliyeti", 'most_expensive' => "En Pahalı Abonelik Maliyeti",
'amount_due' => "Bu ay ödenecek miktar", 'amount_due' => "Bu ay ödenecek miktar",
'percentage_budget_used' => "Bütçe Kullanımı",
'budget_remaining' => "Kalan Bütçe",
'amount_over_budget' => "Bütçe Aşımı",
'monthly_savings' => "Aylık Tasarruf (aktif olmayan aboneliklerde)", 'monthly_savings' => "Aylık Tasarruf (aktif olmayan aboneliklerde)",
'yearly_savings' => "Yıllık Tasarruf (aktif olmayan aboneliklerde)",
'split_views' => "Bölünmüş Görünümler", 'split_views' => "Bölünmüş Görünümler",
'category_split' => "Kategori Bölümü", 'category_split' => "Kategori Bölümü",
'household_split' => "Hane Bölümü", 'household_split' => "Hane Bölümü",
@ -101,6 +105,8 @@ $i18n = [
'upload_avatar' => "Avatarı yükle", 'upload_avatar' => "Avatarı yükle",
'file_type_error' => "Dosya türü izin verilmiyor", 'file_type_error' => "Dosya türü izin verilmiyor",
'user_details' => "Kullanıcı Detayları", 'user_details' => "Kullanıcı Detayları",
"monthly_budget" => "Aylık Bütçe",
"budget_info" => "Bir bütçe belirlemek, istatistik sayfasında bütçe ve gerçek harcamaları karşılaştırmanıza olanak tanır.",
"household" => "Hane", "household" => "Hane",
"save_member" => "Üyeyi Kaydet", "save_member" => "Üyeyi Kaydet",
"delete_member" => "Üyeyi Sil", "delete_member" => "Üyeyi Sil",

View File

@ -90,7 +90,11 @@ $i18n = [
'average_monthly' => "平均每月订阅费用", 'average_monthly' => "平均每月订阅费用",
'most_expensive' => "最昂贵订阅费用", 'most_expensive' => "最昂贵订阅费用",
'amount_due' => "本月应付金额", 'amount_due' => "本月应付金额",
'percentage_budget_used' => "预算使用百分比",
'budget_remaining' => "剩余预算",
'amount_over_budget' => "超出预算",
'monthly_savings' => "每月节省", 'monthly_savings' => "每月节省",
'yearly_savings' => "每年节省",
'split_views' => "拆分视图", 'split_views' => "拆分视图",
'category_split' => "分类视图", 'category_split' => "分类视图",
'household_split' => "家庭视图", 'household_split' => "家庭视图",
@ -108,6 +112,8 @@ $i18n = [
'upload_avatar' => "上传头像", 'upload_avatar' => "上传头像",
'file_type_error' => "文件类型不允许", 'file_type_error' => "文件类型不允许",
'user_details' => "用户详情", 'user_details' => "用户详情",
"monthly_budget" => "每月预算",
"budget_info" => "设置预算后,您可以在统计页面上比较预算和实际支出。",
"household" => "家庭", "household" => "家庭",
"save_member" => "保存成员", "save_member" => "保存成员",
"delete_member" => "删除成员", "delete_member" => "删除成员",

View File

@ -85,7 +85,11 @@ $i18n = [
'average_monthly' => "平均每月訂閱費用", 'average_monthly' => "平均每月訂閱費用",
'most_expensive' => "最高的訂閱費用", 'most_expensive' => "最高的訂閱費用",
'amount_due' => "本月應付金額", 'amount_due' => "本月應付金額",
'percentage_budget_used' => "預算使用率",
'budget_remaining' => "剩餘預算",
'amount_over_budget' => "預算超支",
'monthly_savings' => "每月節省", 'monthly_savings' => "每月節省",
'yearly_savings' => "每年節省",
'split_views' => "分割檢視", 'split_views' => "分割檢視",
'category_split' => "類別分割", 'category_split' => "類別分割",
'household_split' => "家庭分割", 'household_split' => "家庭分割",
@ -101,6 +105,8 @@ $i18n = [
'upload_avatar' => "上传头像", 'upload_avatar' => "上传头像",
'file_type_error' => "文件类型不允许", 'file_type_error' => "文件类型不允许",
'user_details' => "使用者詳細資訊", 'user_details' => "使用者詳細資訊",
"monthly_budget" => "每月預算",
"budget_info" => "設定預算後,您可以在統計頁面上比較預算和實際支出。",
"household" => "家庭", "household" => "家庭",
"save_member" => "儲存成員", "save_member" => "儲存成員",
"delete_member" => "刪除成員", "delete_member" => "刪除成員",

View File

@ -51,6 +51,7 @@ if (isset($_POST['username']) && isset($_POST['password'])) {
$_SESSION['username'] = $username; $_SESSION['username'] = $username;
$_SESSION['loggedin'] = true; $_SESSION['loggedin'] = true;
$_SESSION['main_currency'] = $main_currency; $_SESSION['main_currency'] = $main_currency;
$_SESSION['userId'] = $userId;
$cookieExpire = time() + (30 * 24 * 60 * 60); $cookieExpire = time() + (30 * 24 * 60 * 60);
setcookie('language', $language, $cookieExpire); setcookie('language', $language, $cookieExpire);
if ($rememberMe) { if ($rememberMe) {

15
migrations/000018.php Normal file
View File

@ -0,0 +1,15 @@
<?php
/*
This migration adds a column to the users table to store a monthly budget that will be used to calculate statistics
*/
/** @noinspection PhpUndefinedVariableInspection */
$columnQuery = $db->query("SELECT * FROM pragma_table_info('users') where name='budget'");
$columnRequired = $columnQuery->fetchArray(SQLITE3_ASSOC) === false;
if ($columnRequired) {
$db->exec('ALTER TABLE user ADD COLUMN budget INTEGER DEFAULT 0');
}
?>

View File

@ -69,6 +69,35 @@ function deleteAvatar(path) {
}); });
} }
function saveBudget() {
const button = document.getElementById("saveBudget");
button.disabled = true;
const budget = document.getElementById("budget").value;
fetch('endpoints/user/budget.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ budget: budget })
})
.then(response => response.json())
.then(data => {
if (data.success) {
showSuccessMessage(data.message);
} else {
showErrorMessage(data.message);
}
button.disabled = false;
})
.catch(error => {
showErrorMessage(translate('unknown_error'));
button.disabled = false;
});
}
function addMemberButton(memberId) { function addMemberButton(memberId) {
document.getElementById("addMember").disabled = true; document.getElementById("addMember").disabled = true;
const url = 'endpoints/household/household.php?action=add'; const url = 'endpoints/household/household.php?action=add';

View File

@ -74,13 +74,18 @@
$currencyId = $row['id']; $currencyId = $row['id'];
$currencies[$currencyId] = $row; $currencies[$currencyId] = $row;
} }
$userData['currency_symbol'] = "";
?> ?>
<div class="form-group"> <div class="form-group">
<label for="currency"><?= translate('main_currency', $i18n) ?>:</label> <label for="currency"><?= translate('main_currency', $i18n) ?>:</label>
<select id="currency" name="main_currency" placeholder="Currency"> <select id="currency" name="main_currency" placeholder="Currency">
<?php <?php
foreach ($currencies as $currency) { foreach ($currencies as $currency) {
$selected = ($currency['id'] == $userData['main_currency']) ? 'selected' : ''; $selected = "";
if ($currency['id'] == $userData['main_currency']) {
$selected = "selected";
$userData['currency_symbol'] = $currency['symbol'];
}
?> ?>
<option value="<?= $currency['id'] ?>" <?= $selected ?>><?= $currency['name'] ?></option> <option value="<?= $currency['id'] ?>" <?= $selected ?>><?= $currency['name'] ?></option>
<?php <?php
@ -111,6 +116,24 @@
</section> </section>
<section class="account-section">
<header>
<h2><?= translate('monthly_budget', $i18n) ?></h2>
</header>
<div class="account-budget">
<div class="form-group-inline">
<label for="budget"><?= $userData['currency_symbol'] ?></label>
<input type="number" id="budget" name="budget" value="<?= $userData['budget'] ?>" placeholder="Budget">
<input type="submit" value="<?= translate('save', $i18n) ?>" id="saveBudget" onClick="saveBudget()"/>
</div>
<div class="settings-notes">
<p>
<i class="fa-solid fa-circle-info"></i> <?= translate('budget_info', $i18n) ?></p>
<p>
</div>
</div>
</section>
<?php <?php
$sql = "SELECT * FROM household"; $sql = "SELECT * FROM household";
$result = $db->query($sql); $result = $db->query($sql);

View File

@ -199,6 +199,17 @@ if ($result) {
} }
} }
if (isset($userData['budget']) && $userData['budget'] > 0) {
$budget = $userData['budget'];
$budgetLeft = $budget - $totalCostPerMonth;
$budgetLeft = $budgetLeft < 0 ? 0 : $budgetLeft;
$budgetUsed = ($totalCostPerMonth / $budget) * 100;
$budgetUsed = $budgetUsed > 100 ? 100 : $budgetUsed;
if ($totalCostPerMonth > $budget) {
$overBudgetAmount = $totalCostPerMonth - $budget;
}
}
$numberOfElements = 6; $numberOfElements = 6;
?> ?>
<section class="contain"> <section class="contain">
@ -333,8 +344,35 @@ $numberOfElements = 6;
<div class="title"><?= translate('amount_due', $i18n) ?></div> <div class="title"><?= translate('amount_due', $i18n) ?></div>
</div> </div>
<?php <?php
if (isset($budgetUsed)) {
$numberOfElements += 1;
?>
<div class="statistic">
<span><?= number_format($budgetUsed, 2) ?>%</span>
<div class="title"><?= translate('percentage_budget_used', $i18n) ?></div>
</div>
<?php
}
if (isset($budgetLeft)) {
$numberOfElements += 1;
?>
<div class="statistic">
<span><?= CurrencyFormatter::format($budgetLeft, $code) ?></span>
<div class="title"><?= translate('budget_remaining', $i18n) ?></div>
</div>
<?php
}
if (isset($overBudgetAmount)) {
$numberOfElements += 1;
?>
<div class="statistic">
<span><?= CurrencyFormatter::format($overBudgetAmount, $code) ?></span>
<div class="title"><?= translate('amount_over_budget', $i18n) ?></div>
</div>
<?php
}
if ($inactiveSubscriptions > 0) { if ($inactiveSubscriptions > 0) {
$numberOfElements = 8; $numberOfElements += 3;
?> ?>
<div class="statistic"> <div class="statistic">
<span><?= $inactiveSubscriptions ?></span> <span><?= $inactiveSubscriptions ?></span>
@ -344,6 +382,10 @@ $numberOfElements = 6;
<span><?= CurrencyFormatter::format($totalSavingsPerMonth, $code) ?></span> <span><?= CurrencyFormatter::format($totalSavingsPerMonth, $code) ?></span>
<div class="title"><?= translate('monthly_savings', $i18n) ?></div> <div class="title"><?= translate('monthly_savings', $i18n) ?></div>
</div> </div>
<div class="statistic">
<span><?= CurrencyFormatter::format($totalSavingsPerMonth * 12, $code) ?></span>
<div class="title"><?= translate('yearly_savings', $i18n) ?></div>
</div>
<?php <?php
} }