diff options
Diffstat (limited to 'pages/money.inc')
-rw-r--r-- | pages/money.inc | 822 |
1 files changed, 0 insertions, 822 deletions
diff --git a/pages/money.inc b/pages/money.inc deleted file mode 100644 index 881c618..0000000 --- a/pages/money.inc +++ /dev/null @@ -1,822 +0,0 @@ -<?php - -$minimumRaindrops = 100; -//$minimumCloudburst = 2762.89; -//$minimumCloudburst = 700; -$minimumCloudburst = 0; - -require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/init.inc"; global $title; global $isLoggedIn; global $lang; global $pages; global $_PROFILE; -$parts = explode("/", $_GET["_"]); - -$accounts = array_map(function ($i) { - $name = substr($i, 0, -5); - $data = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/money/" . $i), true); - $data["_name"] = $name; - return $data; -}, array_values(array_filter(scandir($_SERVER['DOCUMENT_ROOT'] . "/includes/data/money"), function ($i) { return !str_starts_with($i, "."); }))); - -require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/util/functions.inc"; - -global $parts; -if (isset($parts[2])) { - if (str_contains($parts[2], "/") || !file_exists($_SERVER['DOCUMENT_ROOT'] . "/includes/data/money/" . $parts[2] . ".json")) { - header("Location: /-/money"); - die(); - } -} - -$systemID = $_PROFILE["login"] === "cloudburst" ? "ynmuc" : "gdapd"; -$fronters = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/" . ($_PROFILE["login"] === "cloudburst" ? "ynmuc" : "gdapd") . "/fronters.json"), true)["members"]; - -if (!isset($parts[2])) { - unset($systemID); -} else { - $systemID = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/money/" . $parts[2] . ".json"), true)["owner"] === "cloudburst" ? "ynmuc" : "gdapd"; -} - -if (count($fronters) > 0) { - $myId = $fronters[0]["id"]; -} else { - $myId = "zdtsg"; -} - -if ((isset($_GET["create"]) || isset($_GET["delete"])) && isset($parts[2])) { - $account = array_values(array_filter($accounts, function ($i) use ($parts) { return $i["_name"] === $parts[2]; }))[0]; - - header("Content-Type: text/plain"); - - if (isset($_GET["create"])) { - if (!(isset($_GET["amount"]) && is_numeric($_GET["amount"]) && (float)$_GET["amount"] < 9999 && (float)$_GET["amount"] > -9999)) { - header("Location: /-/money/" . $parts[2]); - die(); - } - if (!isset($_GET["description"])) $_GET["description"] = ""; - $_GET["description"] = substr($_GET["description"], 0, 150); - - $ntfy = $GLOBALS["ColdHazeApp"]["ntfy"]; - file_get_contents('https://' . $ntfy["server"] . '/' . $ntfy["topic"], false, stream_context_create([ - 'http' => [ - 'method' => 'POST', - 'header' => - "Content-Type: text/plain\r\n" . - "Title: " . formatPonypush((getMember($myId)["display_name"] ?? getMember($myId)["name"]) . " created a transaction to " . $account["name"] . " (" . ucfirst($account["owner"]) . ")") . "\r\n" . - "Tags: bits\r\n" . - "Authorization: Basic " . base64_encode($ntfy["user"] . ":" . $ntfy["password"]), - 'content' => formatPonypush(($account["currency"] === "gbp" ? "£" : "€") . abs((float)$_GET["amount"]) . " were " . ((float)$_GET["amount"] >= 0 ? "added" : "removed") . " just now" . (trim($_GET["description"]) !== "" ? ": " . $_GET["description"] : "")) - ] - ])); - - if ((float)$_GET["amount"] !== 0.0) array_unshift($account["transactions"], [ - "author" => $myId, - "description" => $_GET["description"], - "amount" => (float)$_GET["amount"], - "date" => date('c') - ]); - - $name = $account["_name"]; - unset($account["_name"]); - - file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/money/" . $name . ".json", json_encode($account, JSON_PRETTY_PRINT)); - } else { - if (isset($_GET["id"]) && is_numeric($_GET["id"]) && isset($account["transactions"][(int)$_GET["id"]])) { - $ntfy = $GLOBALS["ColdHazeApp"]["ntfy"]; - file_get_contents('https://' . $ntfy["server"] . '/' . $ntfy["topic"], false, stream_context_create([ - 'http' => [ - 'method' => 'POST', - 'header' => - "Content-Type: text/plain\r\n" . - "Title: " . formatPonypush((getMember($myId)["display_name"] ?? getMember($myId)["name"]) . " deleted a transaction from " . $account["name"] . " (" . ucfirst($account["owner"]) . ")") . "\r\n" . - "Tags: bits\r\n" . - "Authorization: Basic " . base64_encode($ntfy["user"] . ":" . $ntfy["password"]), - 'content' => formatPonypush(($account["currency"] === "gbp" ? "£" : "€") . abs((float)$account["transactions"][(int)$_GET["id"]]["amount"]) . " " . ((float)$account["transactions"][(int)$_GET["id"]]["amount"] >= 0 ? "advance" : "withdrawal") . " created by " . (getMemberWithoutSystem($account["transactions"][(int)$_GET["id"]]["author"])["display_name"] ?? getMemberWithoutSystem($account["transactions"][(int)$_GET["id"]]["author"])["name"]) . " " . timeAgo($account["transactions"][(int)$_GET["id"]]["date"])) - ] - ])); - - unset($account["transactions"][(int)$_GET["id"]]); - - $name = $account["_name"]; - unset($account["_name"]); - - file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/money/" . $name . ".json", json_encode($account, JSON_PRETTY_PRINT)); - } - } - - header("Location: /-/money/" . $parts[2]); - die(); -} - -$rate = (float)trim(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/exchange.txt")); - -require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/components/header.inc'; -$transactionMonths = []; - -foreach ($accounts as $account) { - array_push($transactionMonths, ...array_map(function ($i) { return date('Y-m', strtotime($i["date"])); }, array_filter($account["transactions"], function ($i) { return !isset($i["initial"]) || !$i["initial"]; }))); -} - -$months = [ - ...[ - "2022-12", "2022-11", "2022-10", "2022-09", - "2022-08", "2022-07", "2022-06" - ], - ...array_values(array_filter(array_unique(array_reduce($transactionMonths, function ($a, $b) { - return [...$a, $b]; - }, [])), function ($i) { - return $i !== date('Y-m'); - })) -]; - -$monthlyCloudburst = []; -$monthlyRaindrops = []; - -$bits = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/bits.json"), true); -$projects = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/projects.json"), true); - -foreach ($bits["cloudburst"] as $month => $value) { - $monthlyCloudburst[$month] = $value; -} - -foreach ($bits["raindrops"] as $month => $value) { - $monthlyRaindrops[$month] = $value; -} - -foreach ($months as $month) { - $gainedCloudburst = $monthlyCloudburst[$month] ?? 0; - $gainedRaindrops = $monthlyRaindrops[$month] ?? 0; - - foreach ($accounts as $account) { - foreach ($account["transactions"] as $transaction) { - if (isset($transaction["initial"]) && $transaction["initial"]) continue; - if (date('Y-m', strtotime($transaction["date"])) !== $month) continue; - - if ($account["owner"] === "raindrops") { - $gainedRaindrops += $transaction["amount"]; - } else { - $gainedCloudburst += $transaction["amount"]; - } - } - } - - $monthlyCloudburst[$month] = $gainedCloudburst; - $monthlyRaindrops[$month] = $gainedRaindrops; -} - -uksort($monthlyCloudburst, function ($k1, $k2) { - return strtotime($k2) - strtotime($k1); -}); - -uksort($monthlyRaindrops, function ($k1, $k2) { - return strtotime($k2) - strtotime($k1); -}); - -function getMonthlyEarnings(): array { - global $monthlyRaindrops; - global $monthlyCloudburst; - - return [ - "cloudburst" => array_sum(array_values($monthlyCloudburst)) / count($monthlyCloudburst), - "raindrops" => array_sum(array_values($monthlyRaindrops)) / count($monthlyRaindrops) - ]; -} - -?> - -<script src="/assets/editor/chart.js"></script> - -<style> - a:hover > .card { - opacity: .75; - } - - a:active > .card, a:focus > .card { - opacity: .5; - } - - <?php global $use2023UI; if (!$use2023UI): ?> - .list-group-item { - color: #fff; - background-color: #222; - border: 1px solid rgba(255, 255, 255, .125); - } - - .list-group-item.disabled { - color: #fff; - background-color: #222; - border-color: rgba(255, 255, 255, .125); - opacity: .75; - } - - .list-group-item-action:hover { - background-color: #252525; - color: #ddd; - } - - .list-group-item-action:active, .list-group-item-action:focus { - background-color: #272727; - color: #bbb; - } - - .modal-header { - border-bottom: 1px solid #353738; - } - - .modal-content { - border: 1px solid rgba(255, 255, 255, .2); - background-color: #111; - } - <?php endif; ?> - - .btn-close { - filter: invert(1); - } - - .text-danger, .text-success { - filter: invert(1) brightness(150%) hue-rotate(180deg); - } -</style> - -<br> -<div class="container"> - <?php if (count($parts) < 3): ?> - <div> - <h2>Money tracker</h2> - - <div class="alert alert-danger"> - <b>The Ponycule money tracker is deprecated and will be removed.</b> Data currently in the money tracker will be moved to individual accounts on a dedicated money tracking application that Equestria.dev will not have control over. - </div> - - <hr> - - <?php - - $allAccounts = array_reduce(array_map(function ($i) { - return calculateFullAmount($i, true, true); - }, $accounts), function ($a, $b) { - return $a + $b; - }); - - ?> - <h2>£<?= number_format($allAccounts, 2, '.', ',') ?> · €<?= number_format($allAccounts * (1 / $rate), 2, '.', ',') ?></h2> - <p>As of <?= date('j F Y') ?> · €1.00 = £<?= number_format($rate, 2, '.', ',') ?></p> - - <canvas id="history" style="margin-top: 10px; width: 100%; height: 400px; max-height: 100%;"></canvas> - <?php - - $balance = 0; - $history = []; - $dates = []; - - $transactions1 = array_reduce(array_values(array_filter($accounts, function ($i) { return $i["owner"] === "raindrops"; })), function ($a, $b) { - return [...$a, ...$b["transactions"]]; - }, []); - - $transactions2 = array_reduce(array_values(array_filter($accounts, function ($i) { return $i["owner"] === "cloudburst"; })), function ($a, $b) { - return [...$a, ...$b["transactions"]]; - }, []); - $transactions2 = array_map(function ($i) use ($rate) { - $i["amount"] = $i["amount"] * (1/$rate); - return $i; - }, $transactions2); - - $transactions = [...$transactions1, ...$transactions2]; - usort($transactions, function ($a, $b) { - return strtotime($a["date"]) - strtotime($b["date"]); - }); - - foreach ($transactions as $transaction) { - $balance += $transaction["amount"]; - $history[] = $balance; - $dates[] = date('j M Y, H:i', strtotime($transaction["date"])); - } - - global $palette; - - ?> - <script> - const ctx3 = document.getElementById('history').getContext('2d'); - const graph3 = new Chart(ctx3, { - type: 'line', - data: { - labels: JSON.parse(`<?= json_encode($dates) ?>`), - datasets: [{ - label: 'Balance', - data: JSON.parse(`<?= json_encode($history) ?>`), - borderColor: '#<?= $use2023UI ? $palette[9] : "b9f1ef" ?>', - backgroundColor: '#<?= $use2023UI ? $palette[9] : "b9f1ef77" ?>', - lineTension: 0.4 - }] - }, - options: { - animation: { - duration: 0 - }, - scales: { - y: { - ticks: { - callback: function(label) { - return '€' + Math.round(label); - } - }, - grid: { - color: "rgba(255,255,255,0.25)" - } - } - }, - elements: { - point: { - radius: 0 - } - }, - plugins: { - legend: { - display: false - }, - tooltip: { - callbacks: { - label: function(tooltipItem) { - return '€' + tooltipItem.raw.toFixed(2); - } - }, - intersect: false - } - } - } - }) - </script> - - <hr> - - <h4>Cloudburst System (<?php - - $allAccounts = array_reduce(array_map(function ($i) { - return calculateFullAmount($i, true, true); - }, array_values(array_filter($accounts, function ($i) { return $i["owner"] === "cloudburst"; }))), function ($a, $b) { - return $a + $b; - }); - - ?>£<?= number_format($allAccounts, 2, '.', ',') ?>, earning £<?= number_format(getMonthlyEarnings()["cloudburst"], 2, '.', ',') ?>/month)</h4> - <div class="list-group"> - <details class="list-group-item list-group-item-action" style="margin-bottom: 10px;"> - <summary>Show monthly earnings</summary> - - <table style="margin-top: 10px;"> - <?php foreach ($monthlyCloudburst as $month => $value): ?> - <tr> - <td style="padding-right: 20px;"><b><?= date('F Y', strtotime($month)) ?>:</b></td> - <td class="text-<?= $value > 0 ? "success" : ($value === 0 ? "warning" : "danger") ?>">£<?= number_format($value, 2, '.', ',') ?></td> - </tr> - <?php endforeach; ?> - </table> - </details> - </div> - <div style="display: grid; grid-template-columns: repeat(3, 1fr); grid-gap: 20px;"> - <?php foreach ($accounts as $index => $account): if ($account["owner"] === "cloudburst"): ?> - <a style="color: white; text-decoration: none;" href="/-/money/<?= $account["_name"] ?>"> - <div class="card"> - <div class="card-body"> - <h4 class="card-title"><?= $account["currency"] === "gbp" ? "£" : "€" ?><?= calculateFullAmount($account); ?></h4> - <?= $account["name"] ?><?php if ($account["default"]): ?> <span class="badge bg-success rounded-pill">Default</span><?php endif; ?><?php if (isset($account["interests"])): ?> · <?= $account["interests"] * 100 ?>% interests<?php endif; ?> - <?php if (isset($account["max"])): ?><br><span class="text-muted">Max balance: <?= $account["currency"] === "gbp" ? "£" : "€" ?><?= number_format($account["max"], 2, '.', ',') ?> (<?= round((calculateFullAmount($account, true) / $account["max"]) * 100, 2) ?>% used)</span><?php else: ?><br><span class="text-muted">No maximum balance</span><?php endif; ?> - </div> - </div> - </a> - <?php endif; endforeach; ?> - </div> - - <div class="progress" style="margin-top: 20px;"> - <?php - - $part1 = 0; - $part2 = 1; - $difference = 0; - - if ($allAccounts > $minimumCloudburst) { - $part2 = ($allAccounts - $minimumCloudburst) / $allAccounts; - $part1 = 1 - $part2; - $difference = $allAccounts - $minimumCloudburst; - } else { - $part1 = 1; - $part2 = 0; - $difference = $minimumCloudburst - $allAccounts; - } - - ?> - <div class="progress-bar bg-danger" style="width:<?= $part1 * 100 ?>%"></div> - <div class="progress-bar bg-success" style="width:<?= $part2 * 100 ?>%"></div> - </div> - <p style="text-align: center; margin-top: 5px;" class="<?= $allAccounts > $minimumCloudburst ? "" : "bold text-danger" ?>">£<?= number_format($difference, 2, '.', ',') ?><?php if ($allAccounts > $minimumCloudburst): ?> (<?= round($part2 * 100, 2) ?>%)<?php endif; ?> <?= $allAccounts > $minimumCloudburst ? "over" : "under" ?> the minimum</p> - - <?php if (isset($projects["cloudburst"]) && $projects["cloudburst"]["enable"]): ?> - <div class="grid" style="margin-bottom: 10px; display: grid; grid-template-columns: 25% 1fr; grid-gap: 20px;"> - <div style="width: 100%; display: flex; align-items: center; justify-content: center;"> - <img src="<?= $projects["cloudburst"]["image"] ?>" style="width: 100%;"> - </div> - <div style="display: flex; align-items: center;"> - <div style="width: 100%;"> - <h2><?= strip_tags($projects["cloudburst"]["name"]) ?></h2> - <div class="progress" style="margin-top: 20px; margin-bottom: 20px; width: 100%; background-color: #222;"> - <div class="progress-bar bg-success" style="width: <?= ($allAccounts - $minimumRaindrops >= 0) ? (($allAccounts - $minimumRaindrops) / $projects["raindrops"]["cost"]) * 100 : 0 ?>%"></div> - </div> - <?php $missing = $projects["cloudburst"]["cost"] - ($allAccounts - $minimumCloudburst); if ($missing > 0): $months = ceil($missing / getMonthlyEarnings()["cloudburst"]); ?> - <div>Costs £<?= number_format($projects["cloudburst"]["cost"], 2, '.', ',') ?> · Missing £<?= number_format($missing, 2, '.', ',') ?> · Can afford it in <?= date('F Y', time() + ($months * 2678400)) ?> (in <?= $months ?> month<?= $months > 1 ? "s" : "" ?>)</div> - <?php elseif ($missing === 0): ?><div>You can afford it now, this will take you to the minimum.</div> - <?php else: ?><div>You can afford it now, this will take you £<?= -$missing ?> above the minimum.</div><?php endif; ?> - </div> - </div> - </div> - <?php endif; ?> - - <canvas id="history-cloudburst" style="margin-top: 10px; width: 100%; height: 200px; max-height: 100%;"></canvas> - <?php - - $balance = 0; - $history = []; - $dates = []; - - $transactions = array_reduce(array_values(array_filter($accounts, function ($i) { return $i["owner"] === "cloudburst"; })), function ($a, $b) { - return [...$a, ...$b["transactions"]]; - }, []); - usort($transactions, function ($a, $b) { - return strtotime($a["date"]) - strtotime($b["date"]); - }); - - foreach ($transactions as $transaction) { - $balance += $transaction["amount"]; - $history[] = $balance; - $dates[] = date('j M Y, H:i', strtotime($transaction["date"])); - } - - ?> - <script> - const ctx = document.getElementById('history-cloudburst').getContext('2d'); - const graph = new Chart(ctx, { - type: 'line', - data: { - labels: JSON.parse(`<?= json_encode($dates) ?>`), - datasets: [{ - label: 'Balance', - data: JSON.parse(`<?= json_encode($history) ?>`), - borderColor: '#<?= $use2023UI ? $palette[9] : "ff6ae6" ?>', - backgroundColor: '#<?= $use2023UI ? $palette[9] : "ff6ae677" ?>', - lineTension: 0.4 - }] - }, - options: { - animation: { - duration: 0 - }, - scales: { - y: { - ticks: { - callback: function(label) { - return '£' + Math.round(label); - } - }, - grid: { - color: "rgba(255,255,255,0.25)" - } - } - }, - elements: { - point: { - radius: 0 - } - }, - plugins: { - legend: { - display: false - }, - tooltip: { - callbacks: { - label: function(tooltipItem) { - return '£' + tooltipItem.raw.toFixed(2); - } - }, - intersect: false - } - } - } - }) - </script> - - <h4 style="margin-top: 20px;">Raindrops System (<?php - - $allAccounts = array_reduce(array_map(function ($i) { - return calculateFullAmount($i, true); - }, array_values(array_filter($accounts, function ($i) { return $i["owner"] === "raindrops"; }))), function ($a, $b) { - return $a + $b; - }); - - ?>€<?= number_format($allAccounts, 2, '.', ',') ?>, earning €<?= number_format(getMonthlyEarnings()["raindrops"], 2, '.', ',') ?>/month)</h4> - <div class="list-group"> - <details class="list-group-item list-group-item-action" style="margin-bottom: 10px;"> - <summary>Show monthly earnings</summary> - - <table style="margin-top: 10px;"> - <?php foreach ($monthlyRaindrops as $month => $value): ?> - <tr> - <td style="padding-right: 20px;"><b><?= date('F Y', strtotime($month)) ?>:</b></td> - <td class="text-<?= $value > 0 ? "success" : ($value === 0 ? "warning" : "danger") ?>">€<?= number_format($value, 2, '.', ',') ?></td> - </tr> - <?php endforeach; ?> - </table> - </details> - </div> - <div style="display: grid; grid-template-columns: repeat(3, 1fr); grid-gap: 20px;"> - <?php foreach ($accounts as $index => $account): if ($account["owner"] === "raindrops"): ?> - <a style="color: white; text-decoration: none;" href="/-/money/<?= $account["_name"] ?>"> - <div class="card"> - <div class="card-body"> - <h4 class="card-title"><?= $account["currency"] === "gbp" ? "£" : "€" ?><?= calculateFullAmount($account); ?></h4> - <?= $account["name"] ?><?php if ($account["default"]): ?> <span class="badge bg-success rounded-pill">Default</span><?php endif; ?><?php if (isset($account["interests"])): ?> · <?= $account["interests"] * 100 ?>% interests<?php endif; ?> - <?php if (isset($account["max"])): ?><br><span class="text-muted">Max balance: <?= $account["currency"] === "gbp" ? "£" : "€" ?><?= number_format($account["max"], 2, '.', ',') ?> (<?= round((calculateFullAmount($account, true) / $account["max"]) * 100, 2) ?>% used)</span><?php else: ?><br><span class="text-muted">No maximum balance</span><?php endif; ?> - </div> - </div> - </a> - <?php endif; endforeach; ?> - </div> - - <div class="progress" style="margin-top: 20px;"> - <?php - - $part1 = 0; - $part2 = 1; - $difference = 0; - - if ($allAccounts > $minimumRaindrops) { - $part2 = ($allAccounts - $minimumRaindrops) / $allAccounts; - $part1 = 1 - $part2; - $difference = $allAccounts - $minimumRaindrops; - } else { - $part1 = 1; - $part2 = 0; - $difference = $minimumRaindrops - $allAccounts; - } - - ?> - <div class="progress-bar bg-danger" style="width:<?= $part1 * 100 ?>%"></div> - <div class="progress-bar bg-success" style="width:<?= $part2 * 100 ?>%"></div> - </div> - <p style="text-align: center; margin-top: 5px;" class="<?= $allAccounts > $minimumRaindrops ? "" : "bold text-danger" ?>">€<?= number_format($difference, 2, '.', ',') ?><?php if ($allAccounts > $minimumRaindrops): ?> (<?= round($part2 * 100, 2) ?>%)<?php endif; ?> <?= $allAccounts > $minimumRaindrops ? "over" : "under" ?> the minimum</p> - - <?php if (isset($projects["raindrops"]) && $projects["raindrops"]["enable"]): ?> - <div class="grid" style="margin-bottom: 10px; display: grid; grid-template-columns: 25% 1fr; grid-gap: 20px;"> - <div style="width: 100%; display: flex; align-items: center; justify-content: center;"> - <img src="<?= $projects["raindrops"]["image"] ?>" style="width: 100%;"> - </div> - <div style="display: flex; align-items: center;"> - <div style="width: 100%;"> - <h2><?= strip_tags($projects["raindrops"]["name"]) ?></h2> - <div class="progress" style="margin-top: 20px; margin-bottom: 20px; width: 100%; background-color: #222;"> - <div class="progress-bar bg-success" style="width: <?= ($allAccounts - $minimumRaindrops >= 0) ? (($allAccounts - $minimumRaindrops) / $projects["raindrops"]["cost"]) * 100 : 0 ?>%"></div> - </div> - <?php $missing = $projects["raindrops"]["cost"] - ($allAccounts - $minimumRaindrops); if ($missing > 0): $months = ceil($missing / getMonthlyEarnings()["raindrops"]); ?> - <div>Costs €<?= number_format($projects["raindrops"]["cost"], 2, '.', ',') ?> · Missing €<?= number_format($missing, 2, '.', ',') ?> · Can afford it in <?= date('F Y', time() + ($months * 2678400)) ?> (in <?= $months ?> month<?= $months > 1 ? "s" : "" ?>)</div> - <?php elseif ($missing === 0): ?><div>You can afford it now, this will take you to the minimum.</div> - <?php else: ?><div>You can afford it now, this will take you €<?= -$missing ?> above the minimum.</div><?php endif; ?> - </div> - </div> - </div> - <?php endif; ?> - - <canvas id="history-raindrops" style="margin-top: 10px; width: 100%; height: 200px; max-height: 100%;"></canvas> - <?php - - $balance = 0; - $history = []; - $dates = []; - - $transactions = array_reduce(array_values(array_filter($accounts, function ($i) { return $i["owner"] === "raindrops"; })), function ($a, $b) { - return [...$a, ...$b["transactions"]]; - }, []); - usort($transactions, function ($a, $b) { - return strtotime($a["date"]) - strtotime($b["date"]); - }); - - foreach ($transactions as $transaction) { - $balance += $transaction["amount"]; - $history[] = $balance; - $dates[] = date('j M Y, H:i', strtotime($transaction["date"])); - } - - ?> - <script> - const ctx2 = document.getElementById('history-raindrops').getContext('2d'); - const graph2 = new Chart(ctx2, { - type: 'line', - data: { - labels: JSON.parse(`<?= json_encode($dates) ?>`), - datasets: [{ - label: 'Balance', - data: JSON.parse(`<?= json_encode($history) ?>`), - borderColor: '#<?= $use2023UI ? $palette[9] : "d7e1ff" ?>', - backgroundColor: '#<?= $use2023UI ? $palette[9] : "d7e1ff77" ?>', - lineTension: 0.4 - }] - }, - options: { - animation: { - duration: 0 - }, - scales: { - y: { - ticks: { - callback: function(label) { - return '€' + Math.round(label); - } - }, - grid: { - color: "rgba(255,255,255,0.25)" - } - } - }, - elements: { - point: { - radius: 0 - } - }, - plugins: { - legend: { - display: false - }, - tooltip: { - callbacks: { - label: function(tooltipItem) { - return '€' + tooltipItem.raw.toFixed(2); - } - }, - intersect: false - } - } - } - }) - </script> - </div> - <?php else: $account = array_values(array_filter($accounts, function ($i) use ($parts) { return $i["_name"] === $parts[2]; }))[0]; ?> - <h2> - <?= $account["owner"] === "cloudburst" ? "Cloudburst System" : "Raindrops System" ?> · <?= $account["name"] ?><?php if ($account["default"]): ?><span class="text-muted"> (default)</span><?php endif; ?> - <a href="/-/money" class="small btn btn-outline-<?= $use2023UI ? "primary" : "light" ?>" style="float:right;margin-top:5px;vertical-align:middle;opacity:1 !important; <?= $use2023UI ? "" : "color: white;" ?>">Back</a> - </h2> - <div style="display: grid; grid-template-columns: max-content 1fr; grid-gap: 15px;"> - <h3 style="margin-bottom: 0; display: flex; align-items: center; justify-content: center;"><?= $account["currency"] === "gbp" ? "£" : "€" ?><?= calculateFullAmount($account) ?></h3> - <div> - <div><b>Maximum balance:</b> <?php if (isset($account["max"])): ?><?= $account["currency"] === "gbp" ? "£" : "€" ?><?= number_format($account["max"], 2, '.', ',') ?> (<?= round((calculateFullAmount($account, true) / $account["max"]) * 100, 2) ?>% used)<?php else: ?>No maximum balance<?php endif; ?></div> - <div><b>Interests:</b> <?php if (isset($account["interests"])): ?><?= $account["interests"] * 100 ?>% interests<?php else: ?>None<?php endif; ?></div> - </div> - </div> - <canvas id="history" style="margin-top: 10px; width: 100%; height: 200px; max-height: 100%;"></canvas> - <?php - - $balance = 0; - $history = []; - $dates = []; - - $transactions = $account["transactions"]; - usort($transactions, function ($a, $b) { - return strtotime($a["date"]) - strtotime($b["date"]); - }); - - foreach ($transactions as $transaction) { - $balance += $transaction["amount"]; - $history[] = $balance; - $dates[] = date('j M Y, H:i', strtotime($transaction["date"])); - } - - global $palette; - - ?> - <script> - const ctx = document.getElementById('history').getContext('2d'); - const graph = new Chart(ctx, { - type: 'line', - data: { - labels: JSON.parse(`<?= json_encode($dates) ?>`), - datasets: [{ - label: 'Balance', - data: JSON.parse(`<?= json_encode($history) ?>`), - borderColor: '#<?= $use2023UI ? $palette[9] : ($account["owner"] === "cloudburst" ? "ff6ae6" : "d7e1ff") ?>', - backgroundColor: '#<?=$use2023UI ? $palette[9] : ($account["owner"] === "cloudburst" ? "ff6ae677" : "d7e1ff77") ?>', - lineTension: 0.4 - }] - }, - options: { - animation: { - duration: 0 - }, - scales: { - y: { - ticks: { - callback: function(label) { - return '<?= $account["currency"] === "gbp" ? "£" : "€" ?>' + Math.round(label); - } - }, - grid: { - color: "rgba(255,255,255,0.25)" - } - } - }, - elements: { - point: { - radius: 0 - } - }, - plugins: { - legend: { - display: false - }, - tooltip: { - callbacks: { - label: function(tooltipItem) { - return '<?= $account["currency"] === "gbp" ? "£" : "€" ?>' + tooltipItem.raw.toFixed(2); - } - }, - intersect: false - } - } - } - }) - </script> - - <hr> - - <div class="list-group"> - <a href="#" data-bs-toggle="modal" data-bs-target="#create" class="list-group-item list-group-item-action" style="display: grid; grid-template-columns: max-content 1fr;"><img src="<?= $use2023UI ? icon('add', null, true) : "/assets/icons/add.svg" ?>" style="filter: invert(1); margin-right: 10px; height: 32px; width: 32px;"><div style="display: flex; align-items: center;"><b>Add new transaction</b></div></a> - <?php foreach ($account["transactions"] as $index => $transaction): $member = getMemberWithoutSystem($transaction["author"]) ?? getMemberWithoutSystem("zdtsg"); ?> - <a id="transaction-<?= $index ?>" onclick="deleteTransaction(<?= $index ?>)" class="list-group-item list-group-item-action" style="display: grid; grid-template-columns: max-content 1fr;cursor:pointer;"><div style="display: flex; align-items: center;"><img src="<?= getAsset($member["_system"], $member["id"]) ?>" style="border-radius: 999px; width: 32px; height: 32px; margin-right: 10px;"></div><div style="display: flex; align-items: center;"><div><b><?= $member["display_name"] ?? $member["name"] ?></b><?= $transaction["amount"] < 0 ? " removed" : " added" ?> <span class="<?= $transaction["amount"] < 0 ? "text-danger" : "text-success" ?>"><?= $account["currency"] === "gbp" ? "£" : "€" ?><?= number_format(abs($transaction["amount"]), 2, '.', ',') ?> </span><?= timeAgo($transaction["date"]) ?><?php if (isset($transaction["description"]) && trim($transaction["description"]) !== "" && (!isset($transaction["initial"]) || !$transaction["initial"])): ?>: <?= strip_tags(trim($transaction["description"])) ?><?php endif; ?><?php if (isset($transaction["initial"]) && $transaction["initial"]): ?> <span class="badge bg-<?= $use2023UI ? "success" : "secondary" ?> rounded-pill">Initial amount</span><?php endif; ?></div></div></a> - <?php endforeach; ?> - </div> - - <script> - window.transactions = JSON.parse(atob("<?= base64_encode(json_encode($account["transactions"])) ?>")); - - function deleteTransaction(index) { - document.getElementById("delete-item").innerHTML = document.getElementById("transaction-" + index).innerHTML; - document.getElementById("delete-link").href = location.pathname + "/?delete&id=" + index; - new bootstrap.Modal(document.getElementById("delete")).show(); - } - </script> - - <div class="modal fade" id="delete"> - <div class="modal-dialog"> - <div class="modal-content"> - <div class="modal-header"> - <h4 class="modal-title">Delete transaction?</h4> - <button type="button" class="btn-close" data-bs-dismiss="modal"></button> - </div> - - <div class="modal-body"> - <p>Are you sure you want to delete the following transaction?</p> - - <p> - <div class="list-group"> - <div class="list-group-item" id="delete-item" style="display: grid; grid-template-columns: max-content 1fr;">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ab eum facere minima officiis quas. Architecto ea eius impedit incidunt ipsa itaque laudantium pariatur quae repudiandae sunt unde vel, veritatis, voluptates.</div> - </div> - </p> - - <p>Deleting a transaction takes effect immediately and cannot be undone.</p> - <a href="#" id="delete-link" class="btn btn-<?= $use2023UI ? "primary" : "danger" ?>">Delete</a> - </div> - </div> - </div> - </div> - - <div class="modal fade" id="create"> - <div class="modal-dialog"> - <div class="modal-content"> - <div class="modal-header"> - <h4 class="modal-title">Create new transaction</h4> - <button type="button" class="btn-close" data-bs-dismiss="modal"></button> - </div> - - <div class="modal-body"> - <form> - <input type="hidden" name="create"> - - <label style="display: grid; grid-template-columns: 1fr 1fr; grid-gap: 20px;"> - <span style="align-items: center; justify-content: right; display: flex;">Amount (<?= $account["currency"] === "gbp" ? "£" : "€" ?>):</span> - <input required type="text" pattern="^(-|)\d{1,4}([,.]\d{0,2}|)$" name="amount" class="form-control" placeholder="Amount" style="filter: invert(1) hue-rotate(180deg);" maxlength="7" minlength="1"> - </label> - - <label style="margin-top: 10px;display: grid; grid-template-columns: 1fr 1fr; grid-gap: 20px;"> - <span style="align-items: center; justify-content: right; display: flex;">Description:</span> - <input maxlength="150" type="text" name="description" class="form-control" placeholder="Description" style="filter: invert(1) hue-rotate(180deg);"> - </label> - - <p> - <label style="margin-top: 10px;display: grid; grid-template-columns: 1fr 1fr; grid-gap: 20px;"> - <span style="align-items: center; justify-content: right; display: flex;">Author:</span> - <input type="text" disabled class="form-control" placeholder="Description" style="filter: invert(1) hue-rotate(180deg);" value="<?= getMemberWithoutSystem($myId)["display_name"] ?? getMemberWithoutSystem($myId)["name"] ?>"> - </label> - </p> - - <p>Adding a transaction takes effect immediately and cannot be modified afterward.</p> - <button id="delete-link" class="btn btn-<?= $use2023UI ? "primary" : "success" ?>">Create</button> - </form> - </div> - </div> - </div> - </div> - <?php endif; ?> -</div> - -<?php require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/components/footer.inc'; ?> |