feat: Initialize FastAPI application with Azure authentication and transaction management
- Added .env.example for environment variable configuration. - Created app initialization files and core settings management. - Implemented API routers for reporting and transaction endpoints. - Developed transaction management service with CRUD operations. - Integrated Azure OAuth for user authentication. - Designed dashboard view with transaction filtering and display. - Added Swagger UI documentation with custom dark theme. - Created static and template files for frontend styling and layout.
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Recon Ranger</title>
|
||||
<link id="favicon" rel="icon" type="image/x-icon" href="static/images/favicon.ico">
|
||||
<link rel="stylesheet" href="static/css/styles.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header>
|
||||
<nav>
|
||||
<div class="menu">
|
||||
<div class="logo">
|
||||
<a href="#">Recon Ranger</a>
|
||||
</div>
|
||||
<ul>
|
||||
<li><a href="/">Home</a></li>
|
||||
<li><a href="/api/docs">API</a></li>
|
||||
<li><a href="mailto:someone@example.com">Contact</a></li>
|
||||
{% if request.session.get('user') %}
|
||||
<li><a href="/logout">Logout</a></li>
|
||||
{% else %}
|
||||
<li><a href="/login">Login</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
<main>
|
||||
{% block content %}{% endblock %}
|
||||
</main>
|
||||
<footer>
|
||||
{% block footer %}© 2026 ASB Financial Crime{% endblock %}
|
||||
</footer>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,94 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="dashboard-container">
|
||||
<h1>{{ title }}</h1>
|
||||
|
||||
{# ── Filter bar ─────────────────────────────────────────── #}
|
||||
<form class="filter-bar" method="get" id="filter-form" onsubmit="
|
||||
this.querySelectorAll('input').forEach(function(el){ if(!el.value) el.disabled = true; });
|
||||
">
|
||||
<div class="filter-group">
|
||||
<label for="recon_job_name">Job Name</label>
|
||||
<input type="text" id="recon_job_name" name="recon_job_name"
|
||||
placeholder="e.g. daily-fx-recon"
|
||||
value="{{ recon_job_name or '' }}">
|
||||
</div>
|
||||
<div class="filter-group">
|
||||
<label for="as_at_date">As-at Date</label>
|
||||
<input type="date" id="as_at_date" name="as_at_date"
|
||||
value="{{ as_at_date or '' }}">
|
||||
</div>
|
||||
<div class="filter-actions">
|
||||
<button type="submit" class="btn btn-primary">Apply</button>
|
||||
<a href="?" class="btn btn-secondary">Clear</a>
|
||||
</div>
|
||||
</form>
|
||||
<script>
|
||||
(function () {
|
||||
var params = new URLSearchParams(window.location.search);
|
||||
["recon_job_name", "as_at_date"].forEach(function (key) {
|
||||
var val = params.get(key);
|
||||
if (val) {
|
||||
var el = document.getElementById(key);
|
||||
if (el) el.value = val;
|
||||
}
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
|
||||
{% if results | length > 0 %}
|
||||
<div class="table-scroll">
|
||||
<table class="data-table">
|
||||
<thead>
|
||||
<tr>
|
||||
{% for key in results[0].keys() %}
|
||||
<th>{{ key }}</th>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for row in results %}
|
||||
<tr>
|
||||
{% for key, value in row.items() %}
|
||||
<td>
|
||||
{% if key == 'Status' %}
|
||||
<span class="badge badge-{{ value | lower }}">{{ value }}</span>
|
||||
{% elif key == 'Flag' %}
|
||||
<span class="badge badge-{{ 'none' if value == 'None' else 'flag' }}">{{ value }}</span>
|
||||
{% else %}
|
||||
{{ value }}
|
||||
{% endif %}
|
||||
</td>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{# ── Pagination ─────────────────────────────────────────── #}
|
||||
{# Build filter params string only for values that are set #}
|
||||
{% set filter_qs %}{% if recon_job_name %}&recon_job_name={{ recon_job_name }}{% endif %}{% if as_at_date %}&as_at_date={{ as_at_date }}{% endif %}{% endset %}
|
||||
<div class="pagination">
|
||||
{% if prev_cursor %}
|
||||
<a class="btn btn-secondary"
|
||||
href="?cursor={{ prev_cursor }}{{ filter_qs }}">
|
||||
← Previous
|
||||
</a>
|
||||
{% else %}
|
||||
<span class="btn btn-secondary btn-disabled">← Previous</span>
|
||||
{% endif %}
|
||||
|
||||
{% if next_cursor %}
|
||||
<a class="btn btn-secondary"
|
||||
href="?cursor={{ next_cursor }}{{ filter_qs }}">
|
||||
Next →
|
||||
</a>
|
||||
{% else %}
|
||||
<span class="btn btn-secondary btn-disabled">Next →</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user