Enhance reports page UI with colorful gradient cards and improved filter layout

- Add gradient backgrounds to summary cards (Total Payin, Total Payout, Total Balance, CAP Redistribution)
- Include circular icon boxes with relevant icons for each metric
- Implement dynamic color for Total Balance (green for positive, red for negative)
- Reorganize filters into compact, collapsible layout with logical grouping
- Add collapsible header with animated chevron icon
- Enhance filter sections with icons and improved spacing
- Add comprehensive CSS styles for gradients, flexbox utilities, and visual effects
- Include JavaScript for smooth collapsible animation with icon rotation
parent 6a5e8b04
...@@ -169,6 +169,146 @@ ...@@ -169,6 +169,146 @@
.gap-1 { .gap-1 {
gap: 1rem; gap: 1rem;
} }
.gap-2 {
gap: 0.5rem;
}
.flex-shrink-0 {
flex-shrink: 0;
}
.flex-grow-1 {
flex-grow: 1;
}
.ms-3 {
margin-left: 1rem;
}
.me-1 {
margin-right: 0.25rem;
}
.me-2 {
margin-right: 0.5rem;
}
.mb-1 {
margin-bottom: 0.25rem;
}
.mb-3 {
margin-bottom: 1rem;
}
.mb-4 {
margin-bottom: 1.5rem;
}
.mb-0 {
margin-bottom: 0;
}
.fw-bold {
font-weight: bold;
}
.fw-semibold {
font-weight: 600;
}
.text-white-50 {
color: rgba(255, 255, 255, 0.75);
}
.text-muted {
color: #6c757d;
}
.text-success {
color: #28a745;
}
.text-danger {
color: #dc3545;
}
.text-end {
text-align: right;
}
.shadow-sm {
box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
}
.border-0 {
border: 0;
}
.rounded-circle {
border-radius: 50%;
}
.bg-opacity-25 {
background-color: rgba(255, 255, 255, 0.25);
}
.bg-gradient-primary {
background: linear-gradient(135deg, #007bff 0%, #0056b3 100%);
}
.bg-gradient-info {
background: linear-gradient(135deg, #17a2b8 0%, #138496 100%);
}
.bg-gradient-success {
background: linear-gradient(135deg, #28a745 0%, #1e7e34 100%);
}
.bg-gradient-danger {
background: linear-gradient(135deg, #dc3545 0%, #c82333 100%);
}
.bg-gradient-warning {
background: linear-gradient(135deg, #ffc107 0%, #e0a800 100%);
}
.bg-white {
background-color: white;
}
.icon-box {
display: inline-flex;
align-items: center;
justify-content: center;
}
.input-group {
display: flex;
width: 100%;
}
.input-group input {
border-radius: 4px 0 0 4px;
}
.input-group input:last-child {
border-radius: 0 4px 4px 0;
border-left: 0;
}
.btn-outline-secondary {
background-color: transparent;
border: 1px solid #6c757d;
color: #6c757d;
}
.btn-outline-secondary:hover {
background-color: #6c757d;
color: white;
}
.btn-link {
background: none;
border: none;
color: #007bff;
text-decoration: none;
cursor: pointer;
}
.btn-link:hover {
text-decoration: underline;
}
.text-decoration-none {
text-decoration: none;
}
.w-100 {
width: 100%;
}
.text-start {
text-align: left;
}
.p-0 {
padding: 0;
}
.p-3 {
padding: 1rem;
}
.fa-2x {
font-size: 2em;
}
.fa-chevron-down {
transition: transform 0.3s ease;
}
.collapsed .fa-chevron-down {
transform: rotate(-90deg);
}
{% block extra_css %}{% endblock %} {% block extra_css %}{% endblock %}
</style> </style>
</head> </head>
......
...@@ -23,48 +23,95 @@ ...@@ -23,48 +23,95 @@
<!-- Summary Cards --> <!-- Summary Cards -->
<div class="row mb-4"> <div class="row mb-4">
<div class="col-md-3"> <div class="col-md-3">
<div class="card bg-primary text-white mb-3"> <div class="card bg-gradient-primary text-white mb-3 shadow-sm border-0">
<div class="card-body"> <div class="card-body">
<h6 class="card-title">Total Payin</h6> <div class="d-flex align-items-center">
<h3 class="mb-0">{{ "{:,.2f}".format(totals.total_payin) }}</h3> <div class="flex-shrink-0">
<div class="icon-box bg-white bg-opacity-25 rounded-circle p-3">
<i class="fas fa-arrow-down fa-2x"></i>
</div>
</div>
<div class="flex-grow-1 ms-3">
<h6 class="card-title mb-1 text-white-50">Total Payin</h6>
<h3 class="mb-0 fw-bold">{{ "{:,.2f}".format(totals.total_payin) }}</h3>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
<div class="col-md-3"> <div class="col-md-3">
<div class="card bg-info text-white mb-3"> <div class="card bg-gradient-info text-white mb-3 shadow-sm border-0">
<div class="card-body"> <div class="card-body">
<h6 class="card-title">Total Payout</h6> <div class="d-flex align-items-center">
<h3 class="mb-0">{{ "{:,.2f}".format(totals.total_payout) }}</h3> <div class="flex-shrink-0">
<div class="icon-box bg-white bg-opacity-25 rounded-circle p-3">
<i class="fas fa-arrow-up fa-2x"></i>
</div>
</div>
<div class="flex-grow-1 ms-3">
<h6 class="card-title mb-1 text-white-50">Total Payout</h6>
<h3 class="mb-0 fw-bold">{{ "{:,.2f}".format(totals.total_payout) }}</h3>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
<div class="col-md-3"> <div class="col-md-3">
<div class="card {% if totals.total_balance >= 0 %}bg-success{% else %}bg-danger{% endif %} text-white mb-3"> <div class="card {% if totals.total_balance >= 0 %}bg-gradient-success{% else %}bg-gradient-danger{% endif %} text-white mb-3 shadow-sm border-0">
<div class="card-body"> <div class="card-body">
<h6 class="card-title">Total Balance</h6> <div class="d-flex align-items-center">
<h3 class="mb-0">{{ "{:,.2f}".format(totals.total_balance) }}</h3> <div class="flex-shrink-0">
<div class="icon-box bg-white bg-opacity-25 rounded-circle p-3">
<i class="fas fa-balance-scale fa-2x"></i>
</div>
</div>
<div class="flex-grow-1 ms-3">
<h6 class="card-title mb-1 text-white-50">Total Balance</h6>
<h3 class="mb-0 fw-bold">{{ "{:,.2f}".format(totals.total_balance) }}</h3>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
<div class="col-md-3"> <div class="col-md-3">
<div class="card bg-warning text-white mb-3"> <div class="card bg-gradient-warning text-white mb-3 shadow-sm border-0">
<div class="card-body"> <div class="card-body">
<h6 class="card-title">CAP Redistribution Balance</h6> <div class="d-flex align-items-center">
<h3 class="mb-0">{{ "{:,.2f}".format(totals.cap_balance) }}</h3> <div class="flex-shrink-0">
<div class="icon-box bg-white bg-opacity-25 rounded-circle p-3">
<i class="fas fa-exchange-alt fa-2x"></i>
</div>
</div>
<div class="flex-grow-1 ms-3">
<h6 class="card-title mb-1 text-white-50">CAP Redistribution</h6>
<h3 class="mb-0 fw-bold">{{ "{:,.2f}".format(totals.cap_balance) }}</h3>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<!-- Filters --> <!-- Filters -->
<div class="card mb-4"> <div class="card mb-4 shadow-sm">
<div class="card-header"> <div class="card-header bg-white">
<h5 class="mb-0"><i class="fas fa-filter"></i> Filters</h5> <button class="btn btn-link text-decoration-none w-100 text-start p-0" type="button" data-bs-toggle="collapse" data-bs-target="#filterCollapse" aria-expanded="true" aria-controls="filterCollapse">
<h5 class="mb-0 d-flex align-items-center">
<i class="fas fa-filter me-2 text-primary"></i>
Filters
<i class="fas fa-chevron-down ms-auto" id="filterIcon"></i>
</h5>
</button>
</div> </div>
<div class="collapse show" id="filterCollapse">
<div class="card-body"> <div class="card-body">
<form method="GET" action="{{ url_for('main.reports') }}" class="row g-3"> <form method="GET" action="{{ url_for('main.reports') }}">
<div class="col-md-3"> <!-- Client Selection -->
<label for="client_id" class="form-label">Client</label> <div class="row mb-3">
<div class="col-12">
<label for="client_id" class="form-label fw-semibold">
<i class="fas fa-user me-1"></i> Client
</label>
<select class="form-select" id="client_id" name="client_id"> <select class="form-select" id="client_id" name="client_id">
<option value="">All Clients</option> <option value="">All Clients</option>
{% for client in client_data %} {% for client in client_data %}
...@@ -72,8 +119,14 @@ ...@@ -72,8 +119,14 @@
{% endfor %} {% endfor %}
</select> </select>
</div> </div>
<div class="col-md-2"> </div>
<label for="date_range" class="form-label">Date Range</label>
<!-- Date Range Selection -->
<div class="row mb-3">
<div class="col-md-6">
<label for="date_range" class="form-label fw-semibold">
<i class="fas fa-calendar me-1"></i> Date Range
</label>
<select class="form-select" id="date_range" name="date_range"> <select class="form-select" id="date_range" name="date_range">
<option value="today" {% if filters.date_range == 'today' %}selected{% endif %}>Today</option> <option value="today" {% if filters.date_range == 'today' %}selected{% endif %}>Today</option>
<option value="yesterday" {% if filters.date_range == 'yesterday' %}selected{% endif %}>Yesterday</option> <option value="yesterday" {% if filters.date_range == 'yesterday' %}selected{% endif %}>Yesterday</option>
...@@ -84,24 +137,10 @@ ...@@ -84,24 +137,10 @@
<option value="custom" {% if filters.date_range == 'custom' %}selected{% endif %}>Custom</option> <option value="custom" {% if filters.date_range == 'custom' %}selected{% endif %}>Custom</option>
</select> </select>
</div> </div>
<div class="col-md-2"> <div class="col-md-6">
<label for="start_date" class="form-label">Start Date</label> <label for="sort_by" class="form-label fw-semibold">
<input type="date" class="form-control" id="start_date" name="start_date" value="{{ filters.start_date }}"> <i class="fas fa-sort me-1"></i> Sort By
</div> </label>
<div class="col-md-1">
<label for="start_time" class="form-label">Start Time</label>
<input type="time" class="form-control" id="start_time" name="start_time" value="{{ filters.start_time }}">
</div>
<div class="col-md-2">
<label for="end_date" class="form-label">End Date</label>
<input type="date" class="form-control" id="end_date" name="end_date" value="{{ filters.end_date }}">
</div>
<div class="col-md-1">
<label for="end_time" class="form-label">End Time</label>
<input type="time" class="form-control" id="end_time" name="end_time" value="{{ filters.end_time }}">
</div>
<div class="col-md-1">
<label for="sort_by" class="form-label">Sort By</label>
<select class="form-select" id="sort_by" name="sort_by"> <select class="form-select" id="sort_by" name="sort_by">
<option value="last_match_timestamp" {% if filters.sort_by == 'last_match_timestamp' %}selected{% endif %}>Last Match</option> <option value="last_match_timestamp" {% if filters.sort_by == 'last_match_timestamp' %}selected{% endif %}>Last Match</option>
<option value="token_name" {% if filters.sort_by == 'token_name' %}selected{% endif %}>Client Name</option> <option value="token_name" {% if filters.sort_by == 'token_name' %}selected{% endif %}>Client Name</option>
...@@ -113,17 +152,47 @@ ...@@ -113,17 +152,47 @@
<option value="cap_balance" {% if filters.sort_by == 'cap_balance' %}selected{% endif %}>CAP Balance</option> <option value="cap_balance" {% if filters.sort_by == 'cap_balance' %}selected{% endif %}>CAP Balance</option>
</select> </select>
</div> </div>
</div>
<!-- Custom Date Range -->
<div class="row mb-3">
<div class="col-md-6">
<label class="form-label fw-semibold">
<i class="fas fa-play me-1"></i> Start
</label>
<div class="input-group">
<input type="date" class="form-control" id="start_date" name="start_date" value="{{ filters.start_date }}">
<input type="time" class="form-control" id="start_time" name="start_time" value="{{ filters.start_time }}">
</div>
</div>
<div class="col-md-6">
<label class="form-label fw-semibold">
<i class="fas fa-stop me-1"></i> End
</label>
<div class="input-group">
<input type="date" class="form-control" id="end_date" name="end_date" value="{{ filters.end_date }}">
<input type="time" class="form-control" id="end_time" name="end_time" value="{{ filters.end_time }}">
</div>
</div>
</div>
<!-- Action Buttons -->
<div class="row">
<div class="col-12"> <div class="col-12">
<button type="submit" class="btn btn-primary"> <div class="d-flex gap-2">
<i class="fas fa-search"></i> Apply Filters <button type="submit" class="btn btn-primary flex-grow-1">
<i class="fas fa-search me-1"></i> Apply Filters
</button> </button>
<a href="{{ url_for('main.reports') }}" class="btn btn-secondary"> <a href="{{ url_for('main.reports') }}" class="btn btn-outline-secondary">
<i class="fas fa-times"></i> Clear Filters <i class="fas fa-times me-1"></i> Clear
</a> </a>
</div> </div>
</div>
</div>
</form> </form>
</div> </div>
</div> </div>
</div>
<!-- Clients Table --> <!-- Clients Table -->
<div class="card"> <div class="card">
...@@ -217,4 +286,24 @@ ...@@ -217,4 +286,24 @@
</div> </div>
</div> </div>
</div> </div>
{% block extra_js %}
<script>
document.addEventListener('DOMContentLoaded', function() {
const filterCollapse = document.getElementById('filterCollapse');
const filterIcon = document.getElementById('filterIcon');
if (filterCollapse && filterIcon) {
filterCollapse.addEventListener('show.bs.collapse', function() {
filterIcon.classList.remove('fa-chevron-up');
filterIcon.classList.add('fa-chevron-down');
});
filterCollapse.addEventListener('hide.bs.collapse', function() {
filterIcon.classList.remove('fa-chevron-down');
filterIcon.classList.add('fa-chevron-up');
});
}
});
</script>
{% endblock %}
{% endblock %} {% endblock %}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment