Improve club detail layout: enhance logo display, adjust badge styles, refine card layouts, and optimize spacing

This commit is contained in:
2026-07-16 00:06:54 +02:00
parent 91270b0cf8
commit f403128f57
10 changed files with 5456 additions and 120 deletions

View File

@@ -122,7 +122,7 @@
</td> </td>
<td> <td>
<a class="btn btn-sm gap-2" href="{% url "controlpanel:club_detail" club.pk %}">{% lucide "pencil" size=14 %} Edit</a> <a class="btn btn-sm btn-outline gap-2" href="{% url "controlpanel:club_detail" club.pk %}">{% lucide "pencil" size=14 %} Edit</a>
</td> </td>
</tr> </tr>
{% empty %} {% empty %}

View File

@@ -28,8 +28,10 @@
<a class="btn btn-sm gap-2 btn-error btn-soft" href="{% url 'controlpanel:features' %}">{% lucide "unlock" size=16 %} Reopen platform</a> <a class="btn btn-sm gap-2 btn-error btn-soft" href="{% url 'controlpanel:features' %}">{% lucide "unlock" size=16 %} Reopen platform</a>
</div> </div>
{% endif %} {% endif %}
<div class="mb-6 flex flex-wrap items-center justify-between gap-3"> <div class="mb-6 flex flex-wrap flex-row items-center justify-between gap-3">
<div class="flex flex-col gap-2"> {% block logo %}{% endblock logo %}
<div class="flex flex-col gap-2 grow">
<h1 class="text-3xl font-bold"> <h1 class="text-3xl font-bold">
{% block heading %}Control panel{% endblock heading %} {% block heading %}Control panel{% endblock heading %}
</h1> </h1>

View File

@@ -1,19 +1,29 @@
{% extends "controlpanel/base.html" %} {% extends "controlpanel/base.html" %}
{% load static lucide %} {% load static lucide %}
{% block logo %}
{% if club.logo %}
<img class="h-16 w-16 object-contain" src="{{ club.logo.url }}" alt="{{ club.name }}">
{% else %}
<div class="avatar avatar-placeholder">
<div class="w-16 text-xl rounded-full bg-neutral text-neutral-content">
<span>{{ club.initials }}</span>
</div>
</div>
{% endif %}
{% endblock logo %}
{% block heading %}{{ club.name }}{% endblock heading %} {% block heading %}{{ club.name }}{% endblock heading %}
{% block subheading %} {% block subheading %}
<p class="text-sm opacity-70"> {{ club.slug }}.rosterchief.app
{{ club.slug }} {% if club.is_archived %}
{% if club.is_archived %} <span class="badge badge-warning badge-sm ml-2">Archived</span>
<span class="badge badge-warning badge-sm ml-2">Archived</span> {% endif %}
{% endif %}
</p>
{% endblock subheading %} {% endblock subheading %}
{% block actions %} {% block actions %}
<a class="btn btn-ghost gap-2" href="{% url 'controlpanel:club_update' club.pk %}">{% lucide "pencil" size=16 %} Edit</a> <a class="btn btn-outline gap-2" href="{% url 'controlpanel:club_update' club.pk %}">{% lucide "pencil" size=16 %} Edit</a>
{% if club.is_archived %} {% if club.is_archived %}
<form method="post" action="{% url 'controlpanel:club_restore' club.pk %}"> <form method="post" action="{% url 'controlpanel:club_restore' club.pk %}">
{% csrf_token %} {% csrf_token %}
@@ -30,6 +40,7 @@
{% block panel %} {% block panel %}
{% if club.is_archived %} {% if club.is_archived %}
<div class="alert alert-warning mb-6"> <div class="alert alert-warning mb-6">
{% lucide "alert-triangle" size=20 %}
<span>This club is archived: its subdomain no longer resolves. Nothing has been deleted — restore it to bring it back.</span> <span>This club is archived: its subdomain no longer resolves. Nothing has been deleted — restore it to bring it back.</span>
</div> </div>
{% endif %} {% endif %}
@@ -47,96 +58,91 @@
the club's setup, not a statistic: with nobody in a management position the access the club's setup, not a statistic: with nobody in a management position the access
service grants no authority over that team, so nobody can pick the squad. service grants no authority over that team, so nobody can pick the squad.
{% endcomment %} {% endcomment %}
<div class="mb-6 grid gap-4 sm:grid-cols-2 lg:grid-cols-4"> <div class="mb-6 grid gap-4 sm:grid-cols-2 lg:grid-cols-6">
<div class="card bg-base-100 shadow {% if attention.outstanding %}border-l-4 border-error{% endif %}"> {% comment %}<div class="card bg-base-100 shadow {% if attention.outstanding %}border-l-4 border-error{% endif %}">
<div class="card-body p-4"> <div class="card-body p-4">
<div class="flex items-center gap-2 text-sm opacity-70">{% lucide "banknote" size=16 %} Outstanding</div> <div class="flex items-center gap-2 text-sm opacity-70">{% lucide "banknote" size=16 %} Outstanding</div>
<div class="text-3xl font-bold tabular-nums">€{{ attention.outstanding|floatformat:2 }}</div> <div class="text-3xl font-bold tabular-nums">€{{ attention.outstanding|floatformat:2 }}</div>
<div class="text-xs opacity-60">{{ attention.unpaid_members }} member{{ attention.unpaid_members|pluralize }} unpaid this season</div> <div class="text-xs opacity-60">{{ attention.unpaid_members }} member{{ attention.unpaid_members|pluralize }} unpaid this season</div>
</div> </div>
</div> </div>{% endcomment %}
<div class="card bg-base-100 shadow {% if attention.teams_without_manager %}border-l-4 border-error{% endif %}"> <div class="card bg-base-100 shadow border-l-4 {% if attention.teams_without_manager %}border-error{% else %}border-success{% endif %}">
<div class="card-body p-4"> <div class="card-body p-4">
<div class="flex items-center gap-2 text-sm opacity-70">{% lucide "user-x" size=16 %} No coach</div> <div class="flex items-center gap-2 text-sm opacity-70 mb-3">{% lucide "user-x" size=16 %} Teams without coach</div>
<div class="text-3xl font-bold tabular-nums">{{ attention.teams_without_manager }}</div> <div class="text-4xl font-bold tabular-nums font-mono">{{ attention.teams_without_manager }}</div>
<div class="text-xs opacity-60">Teams nobody can pick a squad for</div> <div class="text-xs opacity-60">Teams nobody can pick a squad for</div>
</div> </div>
</div> </div>
<div class="card bg-base-100 shadow {% if attention.unrostered %}border-l-4 border-warning{% endif %}">
<div class="card bg-base-100 shadow border-l-4 {% if attention.unrostered %}border-warning{% else %}border-success{% endif %}">
<div class="card-body p-4"> <div class="card-body p-4">
<div class="flex items-center gap-2 text-sm opacity-70">{% lucide "user-minus" size=16 %} Unrostered</div> <div class="flex items-center gap-2 text-sm opacity-70 mb-3">{% lucide "user-minus" size=16 %} Unrostered members</div>
<div class="text-3xl font-bold tabular-nums">{{ attention.unrostered }}</div> <div class="text-4xl font-bold tabular-nums font-mono">{{ attention.unrostered }}</div>
<div class="text-xs opacity-60">Active members on no team</div> <div class="text-xs opacity-60">Active members on no team</div>
</div> </div>
</div> </div>
<div class="card bg-base-100 shadow {% if attention.pending_approvals %}border-l-4 border-warning{% endif %}">
<div class="card bg-base-100 shadow border-l-4 {% if attention.pending_approvals %}border-warning{% else %}border-success{% endif %}">
<div class="card-body p-4"> <div class="card-body p-4">
<div class="flex items-center gap-2 text-sm opacity-70">{% lucide "clock" size=16 %} Pending</div> <div class="flex items-center gap-2 text-sm opacity-70 mb-3">{% lucide "clock" size=16 %} Pending</div>
<div class="text-3xl font-bold tabular-nums">{{ attention.pending_approvals }}</div> <div class="text-4xl font-bold tabular-nums font-mono">{{ attention.pending_approvals }}</div>
<div class="text-xs opacity-60">Memberships awaiting approval</div> <div class="text-xs opacity-60">Memberships awaiting approval</div>
</div> </div>
</div> </div>
</div>
<div class="mb-6 grid gap-4 lg:grid-cols-4"> <div class="card bg-base-100 shadow border-l-4 border-info">
<div class="card bg-base-100 shadow"> <div class="card-body p-4">
<div class="card-body"> <div class="flex items-center gap-2 text-sm opacity-70 mb-3">{% lucide "sparkles" size=16 %} New members</div>
<h2 class="card-title text-base">{% lucide "sparkles" size=18 %} New members</h2> <div class="text-4xl font-bold tabular-nums font-mono">{{ attention.new_members }}</div>
<div class="text-4xl font-bold tabular-nums">{{ attention.new_members }}</div>
{# First season at this club — someone returning after a year away is a renewal. #} {# First season at this club — someone returning after a year away is a renewal. #}
<p class="text-sm opacity-70">first season at this club</p> <div class="text-xs opacity-60">First season at this club</div>
</div> </div>
</div> </div>
<div class="card bg-base-100 shadow"> <div class="card bg-base-100 shadow border-l-4 {% if attention.renewal_rate is None %}border-info{% elif attention.renewal_rate < 30 %}border-error{% elif attention.renewal_rate < 65 %}border-warning{% else %}border-success{% endif %}">
<div class="card-body"> <div class="card-body p-4">
<h2 class="card-title text-base">{% lucide "repeat" size=18 %} Renewal</h2> <div class="flex items-center gap-2 text-sm opacity-70 mb-3">{% lucide "repeat" size=16 %} Renewal rate</div>
{% if attention.renewal_rate is None %} <div class="text-4xl font-bold tabular-nums font-mono">
{# No prior season to compare against: a first-season club has not failed to renew anyone. #} {% if attention.renewal_rate is None %}
<p class="text-sm opacity-60">No previous season to compare against yet.</p> N/A
{% else %} {% else %}
<div class="text-4xl font-bold tabular-nums">{{ attention.renewal_rate }}%</div> {{ attention.renewal_rate }}%
<p class="text-sm opacity-70">of last season's active members signed up again</p> {% endif %}
<progress class="progress progress-primary w-full" value="{{ attention.renewal_rate }}" max="100"></progress> </div>
{% endif %} <div class="text-xs opacity-60">
{% if attention.renewal_rate is None %}
No previous season
{% else %}
<progress class="progress w-full {% if attention.renewal_rate < 30 %}progress-error{% elif attention.renewal_rate < 65 %}progress-warning{% else %}progress-success{% endif %}" value="{{ attention.renewal_rate }}"
max="100"></progress>
{% endif %}
</div>
</div> </div>
</div> </div>
<div class="card bg-base-100 shadow"> <div class="card bg-base-100 shadow border-l-4 {% if attention.attendance.turnout is None %}border-info{% elif attention.attendance.turnout < 30 %}border-error{% elif attention.attendance.turnout < 65 %}border-warning{% else %}border-success{% endif %}">
<div class="card-body"> <div class="card-body p-4">
<h2 class="card-title text-base">{% lucide "user-check" size=18 %} Attendance</h2> <div class="flex items-center gap-2 text-sm opacity-70 mb-3">{% lucide "user-check" size=16 %} Attendance rate</div>
{% if attention.attendance.turnout is None %} <div class="text-4xl font-bold tabular-nums font-mono">
<p class="text-sm opacity-60">No past events with responses this season.</p> {% if attention.attendance.turnout is None %}
{% else %} N/A
<div class="text-4xl font-bold tabular-nums">{{ attention.attendance.turnout }}%</div> {% else %}
<p class="text-sm opacity-70">turnout of those who answered</p> {{ attention.attendance.turnout }}%
<p class="mt-2 text-sm"> {% endif %}
{# The leading indicator: it measures whether members use the app at all. #} </div>
<span class="font-semibold {% if attention.attendance.no_response > 30 %}text-warning{% endif %}">{{ attention.attendance.no_response }}%</span> <div class="text-xs opacity-60">
<span class="opacity-70">never responded</span> {% if attention.attendance.turnout is None %}
</p> No events this season
{% endif %} {% else %}
</div> <progress class="progress w-full {% if attention.attendance.turnout < 30 %}progress-error{% elif attention.attendance.turnout < 65 %}progress-warning{% else %}progress-success{% endif %}"
</div> value="{{ attention.attendance.turnout }}" max="100"></progress>
{% endif %}
<div class="card bg-base-100 shadow"> </div>
<div class="card-body">
<h2 class="card-title text-base">{% lucide "hourglass" size=18 %} Unpaid, by age</h2>
<table class="table table-sm">
<tbody>
{% for bucket in attention.aging %}
<tr>
<td class="{% if bucket.overdue and bucket.total %}font-semibold text-error{% endif %}">{{ bucket.label }}</td>
<td class="text-right tabular-nums">€{{ bucket.total|floatformat:2 }}</td>
<td class="text-right opacity-60">{{ bucket.count }} order{{ bucket.count|pluralize }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div> </div>
</div> </div>
</div> </div>
<div class="mb-6 grid gap-4 lg:grid-cols-2"> <div class="mb-6 grid gap-4 lg:grid-cols-2">
<div class="card bg-base-100 shadow"> <div class="card bg-base-100 shadow">
<div class="card-body"> <div class="card-body">
@@ -149,7 +155,7 @@
</div> </div>
<div class="card bg-base-100 shadow"> <div class="card bg-base-100 shadow">
<div class="card-body"> <div class="card-body">
<h2 class="card-title text-base">{% lucide "wallet" size=18 %} Fee status this season</h2> <h2 class="card-title text-base">{% lucide "wallet" size=18 %} Club fee status this season</h2>
<div class="h-56"> <div class="h-56">
<canvas id="fees-chart"></canvas> <canvas id="fees-chart"></canvas>
</div> </div>
@@ -157,7 +163,7 @@
</div> </div>
</div> </div>
<div class="mb-6 grid gap-4 md:grid-cols-2"> <div class="mb-6 grid gap-4 md:grid-cols-4">
{% for group in groups %} {% for group in groups %}
<div class="card bg-base-100 shadow"> <div class="card bg-base-100 shadow">
<div class="card-body"> <div class="card-body">
@@ -166,7 +172,7 @@
{% for label, value in group.stats %} {% for label, value in group.stats %}
<div class="flex items-center justify-between py-2"> <div class="flex items-center justify-between py-2">
<dt class="text-sm opacity-70">{{ label }}</dt> <dt class="text-sm opacity-70">{{ label }}</dt>
<dd class="font-semibold tabular-nums">{{ value }}</dd> <dd class="font-semibold tabular-nums font-mono">{% if group.title == "Shop" and label == "Outstanding" or label == "Revenue" %}&euro;{% endif %}{{ value }}</dd>
</div> </div>
{% endfor %} {% endfor %}
</dl> </dl>
@@ -178,7 +184,7 @@
<div class="card-body"> <div class="card-body">
<div class="flex items-center justify-between"> <div class="flex items-center justify-between">
<h2 class="card-title text-base">{% lucide "toggle-right" size=18 %} Features</h2> <h2 class="card-title text-base">{% lucide "toggle-right" size=18 %} Features</h2>
<a class="btn btn-ghost btn-xs" href="{% url 'controlpanel:features' %}">Manage features</a> <a class="btn btn-outline btn-sm gap-2" href="{% url 'controlpanel:features' %}">{% lucide "wrench" size=14 %} Manage features</a>
</div> </div>
<div class="overflow-x-auto"> <div class="overflow-x-auto">
<table class="table"> <table class="table">
@@ -233,7 +239,7 @@
<p class="text-sm opacity-70">This club is not billed for anything. Put it on a tier to start.</p> <p class="text-sm opacity-70">This club is not billed for anything. Put it on a tier to start.</p>
{% else %} {% else %}
<p class="text-sm opacity-70"> <p class="text-sm opacity-70">
On <strong>{{ subscription.tier.name }}</strong>. On plan <strong>{{ subscription.tier.name }}</strong>.
{% if subscription.auto_renew %} {% if subscription.auto_renew %}
Renews automatically 30 days before the period ends. Renews automatically 30 days before the period ends.
{% else %} {% else %}
@@ -253,7 +259,7 @@
<th>Period</th> <th>Period</th>
<th class="text-right">Billed</th> <th class="text-right">Billed</th>
<th class="text-right">Paid</th> <th class="text-right">Paid</th>
<th>Status</th> <th class="text-right">Status</th>
<th></th> <th></th>
</tr> </tr>
</thead> </thead>
@@ -266,17 +272,17 @@
</td> </td>
<td class="text-right tabular-nums">€{{ due.amount|floatformat:2 }}</td> <td class="text-right tabular-nums">€{{ due.amount|floatformat:2 }}</td>
<td class="text-right tabular-nums">€{{ due.amount_paid|floatformat:2 }}</td> <td class="text-right tabular-nums">€{{ due.amount_paid|floatformat:2 }}</td>
<td> <td class="text-right">
{% if due.status == "paid" %} {% if due.status == "paid" %}
<span class="badge badge-success gap-1">{% lucide "check" size=12 %} Paid</span> <span class="badge badge-success gap-1">{% lucide "check" size=12 %} Paid</span>
{% elif due.status == "waived" %} {% elif due.status == "waived" %}
<span class="badge badge-ghost">Waived</span> <span class="badge badge-outline gap-1">{% lucide "check" size=12 %} Waived</span>
{% elif due.grace_until < today %} {% elif due.grace_until < today %}
<span class="badge badge-error gap-1">{% lucide "triangle-alert" size=12 %} Overdue</span> <span class="badge badge-error gap-1">{% lucide "triangle-alert" size=12 %} Overdue</span>
{% elif due.period_end < today %} {% elif due.period_end < today %}
<span class="badge badge-warning gap-1">{% lucide "hourglass" size=12 %} In grace</span> <span class="badge badge-warning gap-1">{% lucide "hourglass" size=12 %} In grace</span>
{% else %} {% else %}
<span class="badge badge-ghost">{{ due.get_status_display }}</span> <span class="badge badge-outline">{{ due.get_status_display }}</span>
{% endif %} {% endif %}
</td> </td>
<td class="text-right"> <td class="text-right">
@@ -289,7 +295,7 @@
</form> </form>
{% endif %} {% endif %}
{% endif %} {% endif %}
<a class="btn btn-ghost btn-xs gap-1" href="{% url 'controlpanel:due_invoice' due.pk %}">{% lucide "file-text" size=14 %} Invoice</a> <a class="btn btn-accent btn-outline btn-sm gap-1" href="{% url 'controlpanel:due_invoice' due.pk %}">{% lucide "file-down" size=14 %} Download invoice</a>
</td> </td>
</tr> </tr>
{% for payment in due.payments.all %} {% for payment in due.payments.all %}
@@ -317,7 +323,7 @@
<div class="card bg-base-100 shadow"> <div class="card bg-base-100 shadow">
<div class="card-body"> <div class="card-body">
<div class="flex items-center justify-between"> <div class="flex items-center justify-between">
<h2 class="card-title text-base">Club admins</h2> <h2 class="card-title text-base">{% lucide "shield-user" size=18 %} Club admins</h2>
<a class="btn btn-primary btn-sm gap-2" href="{% url 'controlpanel:club_admin_add' club.pk %}">{% lucide "user-plus" size=16 %} Add admin</a> <a class="btn btn-primary btn-sm gap-2" href="{% url 'controlpanel:club_admin_add' club.pk %}">{% lucide "user-plus" size=16 %} Add admin</a>
</div> </div>
<div class="overflow-x-auto"> <div class="overflow-x-auto">
@@ -337,7 +343,7 @@
<td class="text-right"> <td class="text-right">
<form method="post" action="{% url 'controlpanel:club_admin_remove' club.pk role.pk %}"> <form method="post" action="{% url 'controlpanel:club_admin_remove' club.pk role.pk %}">
{% csrf_token %} {% csrf_token %}
<button class="btn btn-ghost btn-xs gap-1 text-error" type="submit">{% lucide "trash-2" size=14 %} Remove</button> <button class="btn btn-error btn-outline btn-sm gap-1" type="submit">{% lucide "trash-2" size=14 %} Remove</button>
</form> </form>
</td> </td>
</tr> </tr>
@@ -372,17 +378,17 @@
data: { data: {
labels: data.signups.map((point) => point.month), labels: data.signups.map((point) => point.month),
datasets: [ datasets: [
{ label: "New", data: data.signups.map((point) => point.new), backgroundColor: css("--color-primary", "#4f46e5") }, {label: "New", data: data.signups.map((point) => point.new), backgroundColor: css("--color-primary", "#4f46e5")},
{ label: "Returning", data: data.signups.map((point) => point.returning), backgroundColor: css("--color-accent", "#0ea5e9") }, {label: "Returning", data: data.signups.map((point) => point.returning), backgroundColor: css("--color-accent", "#0ea5e9")},
], ],
}, },
options: { options: {
responsive: true, responsive: true,
maintainAspectRatio: false, maintainAspectRatio: false,
plugins: { legend: { position: "bottom", labels: { color: ink } } }, plugins: {legend: {position: "bottom", labels: {color: ink}}},
scales: { scales: {
x: { stacked: true, ticks: { color: ink }, grid: { color: grid } }, x: {stacked: true, ticks: {color: ink}, grid: {color: grid}},
y: { stacked: true, beginAtZero: true, ticks: { color: ink, precision: 0 }, grid: { color: grid } }, y: {stacked: true, beginAtZero: true, ticks: {color: ink, precision: 0}, grid: {color: grid}},
}, },
}, },
}); });
@@ -403,7 +409,7 @@
options: { options: {
responsive: true, responsive: true,
maintainAspectRatio: false, maintainAspectRatio: false,
plugins: { legend: { position: "right", labels: { color: ink } } }, plugins: {legend: {position: "right", labels: {color: ink}}},
}, },
}); });
@@ -416,7 +422,7 @@
new MutationObserver(() => { new MutationObserver(() => {
charts.forEach((chart) => chart.destroy()); charts.forEach((chart) => chart.destroy());
charts = render(); charts = render();
}).observe(document.documentElement, { attributes: true, attributeFilter: ["data-theme"] }); }).observe(document.documentElement, {attributes: true, attributeFilter: ["data-theme"]});
})(); })();
</script> </script>
{% endblock extra_body %} {% endblock extra_body %}

View File

@@ -4,28 +4,33 @@
{% block heading %}{% if object %}Edit {{ object }}{% else %}New club{% endif %}{% endblock heading %} {% block heading %}{% if object %}Edit {{ object }}{% else %}New club{% endif %}{% endblock heading %}
{% block panel %} {% block panel %}
<div class="card max-w-xl bg-base-100 shadow"> <div class="card w-full bg-base-100 shadow">
<div class="card-body"> <div class="card-body">
<form method="post" enctype="multipart/form-data"> <form method="post" enctype="multipart/form-data">
{% csrf_token %} {% csrf_token %}
{% for error in form.non_field_errors %} {% for error in form.non_field_errors %}
<div class="alert alert-error my-2"> <div class="alert alert-error my-2">
<span>{{ error }}</span> <span>{{ error }}</span>
</div> </div>
{% endfor %} {% endfor %}
{% for field in form %}
<div class="form-control my-3 w-full"> <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<label class="label" for="{{ field.id_for_label }}"> {% for field in form %}
<span class="label-text">{{ field.label }}</span> <div class="my-3 w-full">
</label> <label class="label" for="{{ field.id_for_label }}">
{{ field|daisy }} <span class="label-text">{{ field.label }}</span>
{% if field.help_text %}<span class="label-text-alt mt-1 text-base-content/70">{{ field.help_text }}</span>{% endif %} </label>
{% for error in field.errors %}<span class="label-text-alt mt-1 text-error">{{ error }}</span>{% endfor %} {{ field|daisy }}
</div> {% if field.help_text and not field.errors %}<span class="label-text-alt mt-1 text-base-content/70">{{ field.help_text }}</span>{% endif %}
{% endfor %} {% for error in field.errors %}<span class="label-text-alt mt-1 text-error">{{ error }}</span>{% endfor %}
<div class="card-actions justify-end pt-2"> </div>
<a class="btn btn-outline gap-2" href="{% url 'controlpanel:club_list' %}">{% lucide "arrow-left" size=16 %} Cancel</a> {% endfor %}
<button class="btn btn-primary" type="submit">Save</button> </div>
<div class="card-actions justify-start pt-2 mt-2">
<a class="btn btn-outline gap-2" href="{% if update_view %}{% url "controlpanel:club_detail" object.pk %}{% else %}{% url "controlpanel:club_list" %}{% endif %}">{% lucide "arrow-left" size=16 %} Cancel</a>
<button class="btn btn-primary gap-2" type="submit">{% lucide "save" size=16 %} Save</button>
</div> </div>
</form> </form>
</div> </div>

View File

@@ -5,9 +5,9 @@
{% block actions %} {% block actions %}
{% if show_archived %} {% if show_archived %}
<a class="btn btn-ghost" href="{% url 'controlpanel:club_list' %}">Active clubs</a> <a class="btn btn-outline" href="{% url 'controlpanel:club_list' %}">{% lucide "archive-x" size=16 %} Hide archived clubs</a>
{% else %} {% else %}
<a class="btn btn-ghost" href="{% url 'controlpanel:club_list' %}?archived=1">Archived</a> <a class="btn btn-outline" href="{% url 'controlpanel:club_list' %}?archived=1">{% lucide "archive" size=16 %} Show archived clubs</a>
{% endif %} {% endif %}
<a class="btn btn-primary gap-2" href="{% url 'controlpanel:club_create' %}">{% lucide "plus" size=16 %} New club</a> <a class="btn btn-primary gap-2" href="{% url 'controlpanel:club_create' %}">{% lucide "plus" size=16 %} New club</a>
{% endblock actions %} {% endblock actions %}
@@ -15,12 +15,19 @@
{% block panel %} {% block panel %}
<form method="get" class="mb-4 flex gap-2"> <form method="get" class="mb-4 flex gap-2">
{% if show_archived %}<input type="hidden" name="archived" value="1">{% endif %} {% if show_archived %}<input type="hidden" name="archived" value="1">{% endif %}
<input type="search" <label class="input">
name="q" <span class="opacity-50">{% lucide "search" size=16 %}</span>
value="{{ search }}" <input type="search"
placeholder="Search clubs…" name="q"
class="input input-bordered w-full max-w-xs"> value="{{ search }}"
<button class="btn gap-2" type="submit">{% lucide "search" size=16 %} Search</button> placeholder="Search clubs…"
class="input input-bordered w-full max-w-xs">
</label>
<button class="btn btn-outline gap-2" type="submit">{% lucide "search" size=16 %} Search</button>
{% if search %}
<a class="btn btn-primary gap-2" href="{% url "controlpanel:club_list" %}">{% lucide "x" size=16 %} Clear filter</a>
{% endif %}
</form> </form>
<div class="card bg-base-100 shadow"> <div class="card bg-base-100 shadow">
<div class="card-body"> <div class="card-body">

View File

@@ -91,7 +91,7 @@
<div> <div>
<div class="mb-1 flex items-center justify-between text-sm"> <div class="mb-1 flex items-center justify-between text-sm">
<span class="flex items-center gap-2">{% lucide step.icon size=14 %} {{ step.label }}</span> <span class="flex items-center gap-2">{% lucide step.icon size=14 %} {{ step.label }}</span>
<span class="font-semibold tabular-nums">{{ step.count }}</span> <span class="font-semibold tabular-nums font-mono">{{ step.count }}</span>
</div> </div>
<progress class="progress {% if step.count == funnel.0.count %}progress-success{% elif step.count == 0 %}progress-error{% else %}progress-warning{% endif %} w-full" value="{{ step.count }}" <progress class="progress {% if step.count == funnel.0.count %}progress-success{% elif step.count == 0 %}progress-error{% else %}progress-warning{% endif %} w-full" value="{{ step.count }}"
max="{{ funnel.0.count }}"></progress> max="{{ funnel.0.count }}"></progress>

View File

@@ -18,11 +18,11 @@ DEFAULT_WIDGET_CLASS = "input input-bordered w-full"
#: Icon, default heading and daisyUI colour per message level. #: Icon, default heading and daisyUI colour per message level.
MESSAGE_ALERTS = { MESSAGE_ALERTS = {
"debug": ("bug", "Debug", "alert-info"), "debug": ("bug", "Debug", "alert-info border-info"),
"info": ("info", "Heads up", "alert-info"), "info": ("info", "Heads up", "alert-info border-info"),
"success": ("circle-check", "Done", "alert-success"), "success": ("circle-check", "Done", "alert-success border-success"),
"warning": ("triangle-alert", "Careful", "alert-warning"), "warning": ("triangle-alert", "Careful", "alert-warning border-warning"),
"error": ("circle-x", "Something went wrong", "alert-error"), "error": ("circle-x", "Something went wrong", "alert-error border-error"),
} }
DEFAULT_MESSAGE_ALERT = MESSAGE_ALERTS["info"] DEFAULT_MESSAGE_ALERT = MESSAGE_ALERTS["info"]

View File

@@ -80,6 +80,9 @@ class ClubCreateView(PlatformStaffRequiredMixin, CreateView):
def get_success_url(self): def get_success_url(self):
return reverse("controlpanel:club_detail", args=[self.object.pk]) return reverse("controlpanel:club_detail", args=[self.object.pk])
def get_context_data(self, **kwargs):
return super().get_context_data(nav="clubs", **kwargs)
class ClubUpdateView(PlatformStaffRequiredMixin, UpdateView): class ClubUpdateView(PlatformStaffRequiredMixin, UpdateView):
model = Club model = Club
@@ -94,6 +97,9 @@ class ClubUpdateView(PlatformStaffRequiredMixin, UpdateView):
def get_success_url(self): def get_success_url(self):
return reverse("controlpanel:club_detail", args=[self.object.pk]) return reverse("controlpanel:club_detail", args=[self.object.pk])
def get_context_data(self, **kwargs):
return super().get_context_data(nav="clubs", update_view=True, **kwargs)
class ClubDetailView(PlatformStaffRequiredMixin, DetailView): class ClubDetailView(PlatformStaffRequiredMixin, DetailView):
model = Club model = Club

File diff suppressed because one or more lines are too long

View File

@@ -85,7 +85,7 @@
<div class="mb-6 w-full space-y-2"> <div class="mb-6 w-full space-y-2">
{% for message in messages %} {% for message in messages %}
{% with alert=message|as_alert %} {% with alert=message|as_alert %}
<div class="alert alert-soft {{ alert.css }}" role="alert"> <div class="alert alert-soft border-2 {{ alert.css }}" role="alert">
{% lucide alert.icon size=20 %} {% lucide alert.icon size=20 %}
<div> <div>
<div class="font-bold">{{ alert.title }}</div> <div class="font-bold">{{ alert.title }}</div>