familyHub/tabs/currency.php

179 lines
9.7 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
require_once __DIR__ . '/../includes/db.php';
require_once __DIR__ . '/../includes/utils.php';
require_once __DIR__ . '/../includes/persona.php';
require_once __DIR__ . '/../includes/expense_helpers.php';
require_once __DIR__ . '/../includes/family_settings.php';
$sym = trim((string) ($familySettings['currency_symbol'] ?? '★'));
$name = trim((string) ($familySettings['currency_name'] ?? ''));
$tabTitle = currencyTabLabel($familySettings);
$canRecordExpense = $activePerson !== null
&& ($activePerson['role'] ?? '') === ROLE_HEAD
&& isHohVerified();
$leaderboard = $people;
usort($leaderboard, static function ($a, $b) {
$ba = is_numeric($a['currency_balance'] ?? null) ? (float) $a['currency_balance'] : 0.0;
$bb = is_numeric($b['currency_balance'] ?? null) ? (float) $b['currency_balance'] : 0.0;
$cmp = $bb <=> $ba;
if ($cmp !== 0) {
return $cmp;
}
return strcmp((string) ($a['name'] ?? ''), (string) ($b['name'] ?? ''));
});
$nameById = [];
foreach ($people as $p) {
if (!empty($p['id'])) {
$nameById[(string) $p['id']] = (string) ($p['name'] ?? '');
}
}
$expenses = normalizeExpensesList(readJsonFile('expenses.json'));
usort($expenses, static function ($a, $b) {
$da = (string) ($a['date'] ?? '');
$db = (string) ($b['date'] ?? '');
if ($db !== $da) {
return strcmp($db, $da);
}
return strcmp((string) ($b['created_at'] ?? ''), (string) ($a['created_at'] ?? ''));
});
$recentExpenses = array_slice($expenses, 0, 50);
$today = gmdate('Y-m-d');
?>
<div id="currency" class="tab-content">
<h2 class="mb-2"><?= htmlspecialchars($tabTitle, ENT_QUOTES, 'UTF-8') ?></h2>
<p class="text-muted small mb-4">Leaderboard and expenses use the family currency from Family settings.</p>
<div class="row g-4">
<div class="col-lg-5">
<div class="card h-100">
<div class="card-header">
<i class="fa fa-trophy me-1" aria-hidden="true"></i> Leaderboard
</div>
<div class="card-body p-0">
<?php if (count($leaderboard) === 0): ?>
<p class="p-3 text-muted mb-0">Add people in Family settings to see balances.</p>
<?php else: ?>
<div class="table-responsive">
<table class="table table-striped mb-0 leaderboard-table">
<thead>
<tr>
<th scope="col" class="text-muted">#</th>
<th scope="col">Name</th>
<th scope="col" class="text-end">Balance</th>
</tr>
</thead>
<tbody>
<?php foreach ($leaderboard as $rank => $p): ?>
<?php
$pid = (string) ($p['id'] ?? '');
$bal = is_numeric($p['currency_balance'] ?? null) ? (float) $p['currency_balance'] : 0.0;
$isSelf = $activePerson && ($activePerson['id'] ?? '') === $pid;
?>
<tr class="<?= $isSelf ? 'table-primary' : '' ?>">
<td class="text-muted"><?= (int) $rank + 1 ?></td>
<td><?= sanitizeInput($p['name'] ?? '') ?><?php if ($isSelf): ?> <span class="badge text-bg-info">You</span><?php endif; ?></td>
<td class="text-end text-nowrap"><strong><?= htmlspecialchars(number_format($bal, 2, '.', ''), ENT_QUOTES, 'UTF-8') ?></strong> <?= htmlspecialchars($sym, ENT_QUOTES, 'UTF-8') ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
</div>
</div>
</div>
<div class="col-lg-7">
<?php if ($canRecordExpense): ?>
<div class="card border-secondary mb-4">
<div class="card-header d-flex justify-content-between align-items-center">
<span><i class="fa fa-minus-circle me-1"></i> Record expense</span>
<button class="btn btn-sm btn-outline-secondary" type="button" data-bs-toggle="collapse" data-bs-target="#expenseFormCollapse" aria-expanded="false" aria-controls="expenseFormCollapse">
Show form
</button>
</div>
<div class="collapse" id="expenseFormCollapse">
<div class="card-body">
<p class="small text-muted">Deducts from one persons balance (e.g. spent allowance). Requires enough balance.</p>
<form id="expenseForm" class="row g-3">
<div class="col-md-6">
<label class="form-label" for="expense_title">Title</label>
<input class="form-control" id="expense_title" required maxlength="120">
</div>
<div class="col-md-6">
<label class="form-label" for="expense_value">Amount (<?= htmlspecialchars($sym, ENT_QUOTES, 'UTF-8') ?>)</label>
<input type="number" class="form-control" id="expense_value" min="0.01" step="0.01" required>
</div>
<div class="col-md-6">
<label class="form-label" for="expense_date">Date</label>
<input type="date" class="form-control" id="expense_date" value="<?= htmlspecialchars($today, ENT_QUOTES, 'UTF-8') ?>" required>
</div>
<div class="col-md-6">
<label class="form-label" for="expense_assignee">Charged to</label>
<select class="form-select" id="expense_assignee" required>
<option value="">Choose person…</option>
<?php foreach ($people as $p): ?>
<?php if (empty($p['id'])) { continue; } ?>
<option value="<?= htmlspecialchars((string) $p['id'], ENT_QUOTES, 'UTF-8') ?>"><?= sanitizeInput($p['name'] ?? '') ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-12">
<label class="form-label" for="expense_description">Description</label>
<textarea class="form-control" id="expense_description" rows="2"></textarea>
</div>
<div class="col-12">
<button type="submit" class="btn btn-danger">Apply expense</button>
</div>
<div class="col-12">
<div class="alert d-none" id="expenseFormFeedback" role="status"></div>
</div>
</form>
</div>
</div>
</div>
<?php elseif (count($people) > 0): ?>
<p class="text-muted small">Switch to a verified Head of household to record expenses.</p>
<?php endif; ?>
<div class="card">
<div class="card-header">Recent expenses</div>
<div class="card-body p-0">
<?php if (count($recentExpenses) === 0): ?>
<p class="p-3 text-muted mb-0">No expenses recorded yet.</p>
<?php else: ?>
<div class="table-responsive">
<table class="table table-sm mb-0">
<thead>
<tr>
<th>Date</th>
<th>Title</th>
<th>To</th>
<th class="text-end">Amount</th>
</tr>
</thead>
<tbody>
<?php foreach ($recentExpenses as $ex): ?>
<tr>
<td class="text-nowrap"><?= sanitizeInput((string) ($ex['date'] ?? '')) ?></td>
<td><?= sanitizeInput((string) ($ex['title'] ?? '')) ?></td>
<td><?= sanitizeInput($nameById[(string) ($ex['assignee_id'] ?? '')] ?? '') ?></td>
<td class="text-end text-nowrap"><?= htmlspecialchars(number_format((float) ($ex['value'] ?? 0), 2, '.', ''), ENT_QUOTES, 'UTF-8') ?> <?= htmlspecialchars($sym, ENT_QUOTES, 'UTF-8') ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
</div>
</div>
</div>
</div>
</div>