Fixes: 1) Fix type annotations for get_revenue, get_returns, get_total_processed_orders; 2) Add missing import for Context; Extra: 1) Add type hint for currency_symbol; 2) Add type ignore comments for image_url; 3) Update UNFOLD config to use dict[str, Any]; 4) Add missing import for typing.Any; 5) Refactor template to conditionally display currency symbol.
200 lines
No EOL
10 KiB
HTML
200 lines
No EOL
10 KiB
HTML
{% extends 'admin/base.html' %}
|
|
{% load i18n unfold %}
|
|
|
|
{% block title %}
|
|
{% if subtitle %}
|
|
{{ subtitle }} |
|
|
{% endif %}
|
|
|
|
{{ title }} | {{ site_title|default:_('Django site admin') }}
|
|
{% endblock %}
|
|
|
|
{% block branding %}
|
|
{% include "unfold/helpers/site_branding.html" %}
|
|
{% endblock %}
|
|
|
|
{% block content %}
|
|
{% component "unfold/components/container.html" %}
|
|
<div class="flex flex-col min-h-screen">
|
|
{% component "unfold/components/title.html" %}
|
|
{% trans "Dashboard" %}
|
|
<br/>
|
|
{% endcomponent %}
|
|
|
|
<div class="grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-4 gap-4 mb-6">
|
|
{% component "unfold/components/card.html" %}
|
|
{% component "unfold/components/text.html" %}
|
|
{% trans "Revenue (gross, 30d)" %}
|
|
{% endcomponent %}
|
|
{% component "unfold/components/title.html" %}
|
|
{% if currency_symbol %}{{ currency_symbol }}{% endif %}{{ revenue_gross_30|default:0 }}
|
|
{% endcomponent %}
|
|
{% endcomponent %}
|
|
|
|
{% component "unfold/components/card.html" %}
|
|
{% component "unfold/components/text.html" %}
|
|
{% trans "Revenue (net, 30d)" %}
|
|
{% endcomponent %}
|
|
{% component "unfold/components/title.html" %}
|
|
{% if currency_symbol %}{{ currency_symbol }}{% endif %}{{ revenue_net_30|default:0 }}
|
|
{% endcomponent %}
|
|
{% endcomponent %}
|
|
|
|
{% component "unfold/components/card.html" %}
|
|
{% component "unfold/components/text.html" %}
|
|
{% trans "Returns (30d)" %}
|
|
{% endcomponent %}
|
|
{% component "unfold/components/title.html" %}
|
|
{% if currency_symbol %}{{ currency_symbol }}{% endif %}{{ returns_30|default:0 }}
|
|
{% endcomponent %}
|
|
{% endcomponent %}
|
|
|
|
{% component "unfold/components/card.html" %}
|
|
{% component "unfold/components/text.html" %}
|
|
{% trans "Processed orders (30d)" %}
|
|
{% endcomponent %}
|
|
{% component "unfold/components/title.html" %}
|
|
{{ processed_orders_30|default:0 }}
|
|
{% endcomponent %}
|
|
{% endcomponent %}
|
|
</div>
|
|
|
|
<div class="grid grid-cols-1 xl:grid-cols-3 gap-6 items-start">
|
|
{% with gross=revenue_gross_30|default:0 returns=returns_30|default:0 %}
|
|
{% with total=gross|add:returns %}
|
|
{% component "unfold/components/card.html" with class="xl:col-span-2" %}
|
|
{% component "unfold/components/title.html" %}
|
|
{% trans "Sales vs Returns (30d)" %}
|
|
{% endcomponent %}
|
|
{% if total and total > 0 %}
|
|
{% widthratio gross total 360 as gross_deg %}
|
|
<div class="flex flex-col sm:flex-row items-center gap-6">
|
|
<div class="relative w-40 h-40">
|
|
<div class="w-40 h-40 rounded-full"
|
|
style="background:
|
|
conic-gradient(
|
|
rgb(34,197,94) 0 {{ gross_deg }}deg,
|
|
rgb(239,68,68) {{ gross_deg }}deg 360deg
|
|
);">
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<div class="flex items-center gap-2 mb-2">
|
|
<span class="inline-block w-3 h-3 rounded-sm"
|
|
style="background:rgb(34,197,94)"></span>
|
|
<span class="text-sm text-gray-600 dark:text-gray-300">{% trans "Gross" %}:</span>
|
|
<span class="font-semibold">{% if currency_symbol %}{{ currency_symbol }}{% endif %}{{ gross }}</span>
|
|
</div>
|
|
<div class="flex items-center gap-2">
|
|
<span class="inline-block w-3 h-3 rounded-sm"
|
|
style="background:rgb(239,68,68)"></span>
|
|
<span class="text-sm text-gray-600 dark:text-gray-300">{% trans "Returns" %}:</span>
|
|
<span class="font-semibold">{% if currency_symbol %}{{ currency_symbol }}{% endif %}{{ returns }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% else %}
|
|
{% component "unfold/components/text.html" %}
|
|
{% trans "Not enough data for chart yet." %}
|
|
{% endcomponent %}
|
|
{% endif %}
|
|
{% endcomponent %}
|
|
{% endwith %}
|
|
{% endwith %}
|
|
|
|
{% component "unfold/components/card.html" %}
|
|
{% component "unfold/components/title.html" %}
|
|
{% trans "Quick Links" %}
|
|
{% endcomponent %}
|
|
{% if quick_links %}
|
|
{% component "unfold/components/navigation.html" with class="flex flex-col gap-1" items=quick_links %}
|
|
{% endcomponent %}
|
|
{% else %}
|
|
{% component "unfold/components/text.html" %}
|
|
{% trans "No links available." %}
|
|
{% endcomponent %}
|
|
{% endif %}
|
|
{% endcomponent %}
|
|
</div>
|
|
|
|
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mt-6">
|
|
{% component "unfold/components/card.html" %}
|
|
{% component "unfold/components/title.html" %}
|
|
{% trans "Most wished product" %}
|
|
{% endcomponent %}
|
|
{% if most_wished_products %}
|
|
<ul class="flex flex-col divide-y divide-gray-200 dark:divide-base-700/50">
|
|
{% for p in most_wished_products %}
|
|
<li class="py-2 first:pt-0 last:pb-0">
|
|
<a href="{{ p.admin_url }}" class="flex items-center gap-4">
|
|
{% if p.image %}
|
|
<img src="{{ p.image }}" alt="{{ p.name }}" class="w-12 h-12 object-cover rounded"/>
|
|
{% endif %}
|
|
<span class="font-medium flex-1 truncate">{{ p.name }}</span>
|
|
<span class="text-xs px-2 py-0.5 rounded bg-base-700/[.06] dark:bg-white/[.06] text-gray-700 dark:text-gray-200">{{ p.count }}</span>
|
|
</a>
|
|
</li>
|
|
{% endfor %}
|
|
</ul>
|
|
{% elif most_wished_product %}
|
|
<a href="{{ most_wished_product.admin_url }}" class="flex items-center gap-4">
|
|
{% if most_wished_product.image %}
|
|
<img src="{{ most_wished_product.image }}" alt="{{ most_wished_product.name }}"
|
|
class="w-16 h-16 object-cover rounded"/>
|
|
{% endif %}
|
|
<span class="font-medium">{{ most_wished_product.name }}</span>
|
|
</a>
|
|
{% else %}
|
|
{% component "unfold/components/text.html" %}
|
|
{% trans "No data yet." %}
|
|
{% endcomponent %}
|
|
{% endif %}
|
|
{% endcomponent %}
|
|
|
|
{% component "unfold/components/card.html" %}
|
|
{% component "unfold/components/title.html" %}
|
|
{% trans "Most popular product" %}
|
|
{% endcomponent %}
|
|
{% if most_popular_products %}
|
|
<ul class="flex flex-col divide-y divide-gray-200 dark:divide-base-700/50">
|
|
{% for p in most_popular_products %}
|
|
<li class="py-2 first:pt-0 last:pb-0">
|
|
<a href="{{ p.admin_url }}" class="flex items-center gap-4">
|
|
{% if p.image %}
|
|
<img src="{{ p.image }}" alt="{{ p.name }}" class="w-12 h-12 object-cover rounded"/>
|
|
{% endif %}
|
|
<span class="font-medium flex-1 truncate">{{ p.name }}</span>
|
|
<span class="text-xs px-2 py-0.5 rounded bg-base-700/[.06] dark:bg-white/[.06] text-gray-700 dark:text-gray-200">{{ p.count }}</span>
|
|
</a>
|
|
</li>
|
|
{% endfor %}
|
|
</ul>
|
|
{% elif most_popular_product %}
|
|
<a href="{{ most_popular_product.admin_url }}" class="flex items-center gap-4">
|
|
{% if most_popular_product.image %}
|
|
<img src="{{ most_popular_product.image }}" alt="{{ most_popular_product.name }}"
|
|
class="w-16 h-16 object-cover rounded"/>
|
|
{% endif %}
|
|
<span class="font-medium">{{ most_popular_product.name }}</span>
|
|
</a>
|
|
{% else %}
|
|
{% component "unfold/components/text.html" %}
|
|
{% trans "No data yet." %}
|
|
{% endcomponent %}
|
|
{% endif %}
|
|
{% endcomponent %}
|
|
</div>
|
|
|
|
|
|
{% component "unfold/components/separator.html" %}
|
|
{% endcomponent %}
|
|
|
|
<div class="mt-4 mt-auto">
|
|
{% component "unfold/components/text.html" with class="text-center text-xs text-gray-500 dark:text-gray-400" %}
|
|
eVibes {{ evibes_version }} · Wiseless Team
|
|
{% endcomponent %}
|
|
</div>
|
|
|
|
</div>
|
|
{% endcomponent %}
|
|
{% endblock %} |