6c0d5a4e63
- Flask-based mold cost calculation application - PostgreSQL database with SQLAlchemy ORM - Docker/Podman containerization - Comprehensive documentation in docs/ - Clean, organized codebase without obsolete files - Production-ready deployment configuration - Enhanced pytest configuration with coverage reporting - Master/Development branch structure
174 lines
7.4 KiB
HTML
174 lines
7.4 KiB
HTML
{% extends "admin/base.html" %}
|
|
{% block title %}Quotations - Admin{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="admin-container">
|
|
<div class="admin-card">
|
|
<div class="admin-card-header">
|
|
<h2 class="mb-0">Quotations Management</h2>
|
|
</div>
|
|
|
|
<div class="admin-card-body">
|
|
<div class="admin-filters">
|
|
<form method="get" class="admin-filter-form" id="quotationFilterForm">
|
|
<div class="admin-form-group">
|
|
<select name="country" class="admin-form-control">
|
|
<option value="">All Countries</option>
|
|
{% for country in countries %}
|
|
<option value="{{ country }}" {% if filters.country == country %}selected{% endif %}>
|
|
{{ country }}
|
|
</option>
|
|
{% endfor %}
|
|
</select>
|
|
</div>
|
|
|
|
<div class="admin-form-group">
|
|
<select name="mold_type" class="admin-form-control">
|
|
<option value="">All Mold Types</option>
|
|
{% for type in mold_types %}
|
|
<option value="{{ type }}" {% if filters.mold_type == type %}selected{% endif %}>
|
|
{{ type }}
|
|
</option>
|
|
{% endfor %}
|
|
</select>
|
|
</div>
|
|
|
|
<div class="admin-form-group">
|
|
<input type="date" name="date_from" id="date_from" class="admin-form-control"
|
|
value="{{ filters.date_from.strftime('%Y-%m-%d') if filters.date_from else '' }}"
|
|
placeholder="From Date">
|
|
</div>
|
|
|
|
<div class="admin-form-group">
|
|
<input type="date" name="date_to" id="date_to" class="admin-form-control"
|
|
value="{{ filters.date_to.strftime('%Y-%m-%d') if filters.date_to else '' }}"
|
|
placeholder="To Date">
|
|
</div>
|
|
|
|
<div class="admin-form-group">
|
|
<button type="submit" class="admin-btn admin-btn-primary">Filter</button>
|
|
<a href="{{ url_for('admin.quotations') }}" class="admin-btn admin-btn-secondary">Clear</a>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
{% if quotations.items %}
|
|
<div class="table-responsive">
|
|
<table class="admin-table">
|
|
<thead>
|
|
<tr>
|
|
<th>ID</th>
|
|
<th>User</th>
|
|
<th>Model</th>
|
|
<th>Country</th>
|
|
<th>Mold Type</th>
|
|
<th>Base Price</th>
|
|
<th>Total Cost</th>
|
|
<th>Date</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for quotation in quotations.items %}
|
|
<tr>
|
|
<td>{{ quotation.id }}</td>
|
|
<td>{{ quotation.user.username }}</td>
|
|
<td>{{ quotation.model_name }}</td>
|
|
<td>{{ quotation.mold_shop_country }}</td>
|
|
<td>{{ quotation.mold_main_type }}</td>
|
|
<td>${{ "%.2f"|format(quotation.base_price) }}</td>
|
|
<td>${{ "%.2f"|format(quotation.total_cost) }}</td>
|
|
<td>{{ quotation.created_at.strftime('%Y-%m-%d %H:%M') }}</td>
|
|
<td>
|
|
<a href="{{ url_for('admin.quotation_detail', id=quotation.id) }}"
|
|
class="admin-btn admin-btn-info admin-btn-sm">
|
|
<i class="fas fa-eye"></i>
|
|
</a>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
{% if quotations.pages > 1 %}
|
|
<div class="admin-pagination">
|
|
{% if quotations.has_prev %}
|
|
<a href="{{ url_for('admin.quotations', page=quotations.prev_num, **filters) }}"
|
|
class="admin-pagination-link">Previous</a>
|
|
{% endif %}
|
|
|
|
<span class="admin-pagination-info">
|
|
Page {{ quotations.page }} of {{ quotations.pages }}
|
|
</span>
|
|
|
|
{% if quotations.has_next %}
|
|
<a href="{{ url_for('admin.quotations', page=quotations.next_num, **filters) }}"
|
|
class="admin-pagination-link">Next</a>
|
|
{% endif %}
|
|
</div>
|
|
{% endif %}
|
|
{% else %}
|
|
<div class="text-center py-4">
|
|
<p class="text-muted mb-0">No quotations found matching your criteria.</p>
|
|
{% if filters.country or filters.mold_type or filters.date_from or filters.date_to %}
|
|
<a href="{{ url_for('admin.quotations') }}" class="admin-btn admin-btn-primary mt-3">Clear Filters</a>
|
|
{% endif %}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block scripts %}
|
|
{{ super() }}
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// Function to get today's date in YYYY-MM-DD format
|
|
function getTodayDate() {
|
|
const today = new Date();
|
|
const year = today.getFullYear();
|
|
const month = String(today.getMonth() + 1).padStart(2, '0');
|
|
const day = String(today.getDate()).padStart(2, '0');
|
|
return `${year}-${month}-${day}`;
|
|
}
|
|
|
|
// Get date input elements
|
|
const dateFromInput = document.getElementById('date_from');
|
|
const dateToInput = document.getElementById('date_to');
|
|
const form = document.getElementById('quotationFilterForm');
|
|
|
|
// Set default values if empty
|
|
if (!dateFromInput.value) {
|
|
dateFromInput.value = getTodayDate();
|
|
}
|
|
if (!dateToInput.value) {
|
|
dateToInput.value = getTodayDate();
|
|
}
|
|
|
|
// Prevent form submission if dates are invalid
|
|
form.addEventListener('submit', function(event) {
|
|
if (!dateFromInput.value || !dateToInput.value) {
|
|
event.preventDefault();
|
|
if (!dateFromInput.value) dateFromInput.value = getTodayDate();
|
|
if (!dateToInput.value) dateToInput.value = getTodayDate();
|
|
}
|
|
});
|
|
|
|
// Add event listeners to handle invalid dates
|
|
dateFromInput.addEventListener('change', function() {
|
|
if (!this.value) this.value = getTodayDate();
|
|
});
|
|
|
|
dateToInput.addEventListener('change', function() {
|
|
if (!this.value) this.value = getTodayDate();
|
|
});
|
|
});
|
|
</script>
|
|
{% endblock %}
|
|
|
|
{% block styles %}
|
|
{{ super() }}
|
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/admin.css') }}">
|
|
{% endblock %} |