{% extends "controlpanel/base.html" %} {% load static lucide %} {% block logo %} {% if club.logo %} {{ club.name }} {% else %}
{{ club.initials }}
{% endif %} {% endblock logo %} {% block heading %}{{ club.name }}{% endblock heading %} {% block subheading %} {{ club.slug }}.rosterchief.app {% if club.is_archived %} Archived {% endif %} {% endblock subheading %} {% block actions %} {% lucide "pencil" size=16 %} Edit {% if club.is_archived %}
{% csrf_token %}
{% else %}
{% csrf_token %}
{% endif %} {% endblock actions %} {% block panel %} {% if club.is_archived %}
{% lucide "alert-triangle" size=20 %} This club is archived: its subdomain no longer resolves. Nothing has been deleted — restore it to bring it back.
{% endif %} {% if attention.no_season %}
{% lucide "calendar-x" size=20 %} No season covers today, so this club cannot take a signup or schedule a match. Nothing errors — it is simply inert.
{% endif %} {% comment %} The club's own numbers that should be zero. Teams without a manager is a defect in 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. {% endcomment %}
{% comment %}
{% lucide "banknote" size=16 %} Outstanding
€{{ attention.outstanding|floatformat:2 }}
{{ attention.unpaid_members }} member{{ attention.unpaid_members|pluralize }} unpaid this season
{% endcomment %}
{% lucide "user-x" size=16 %} Teams without coach
{{ attention.teams_without_manager }}
Teams nobody can pick a squad for
{% lucide "user-minus" size=16 %} Unrostered members
{{ attention.unrostered }}
Active members on no team
{% lucide "clock" size=16 %} Pending
{{ attention.pending_approvals }}
Memberships awaiting approval
{% lucide "sparkles" size=16 %} New members
{{ attention.new_members }}
{# First season at this club — someone returning after a year away is a renewal. #}
First season at this club
{% lucide "repeat" size=16 %} Renewal rate
{% if attention.renewal_rate is None %} N/A {% else %} {{ attention.renewal_rate }}% {% endif %}
{% if attention.renewal_rate is None %} No previous season {% else %} {% endif %}
{% lucide "user-check" size=16 %} Attendance rate
{% if attention.attendance.turnout is None %} N/A {% else %} {{ attention.attendance.turnout }}% {% endif %}
{% if attention.attendance.turnout is None %} No events this season {% else %} {% endif %}

{% lucide "user-plus" size=18 %} Signups per month

New members against returning ones.

{% lucide "wallet" size=18 %} Club fee status this season

{% for group in groups %}

{% lucide group.icon size=18 %} {{ group.title }}

{% for label, value in group.stats %}
{{ label }}
{% if group.title == "Shop" and label == "Outstanding" or label == "Revenue" %}€{% endif %}{{ value }}
{% endfor %}
{% endfor %}

{% lucide "toggle-right" size=18 %} Features

{% lucide "wrench" size=14 %} Manage features
{% for entry in flags %} {% empty %} {% endfor %}
{{ entry.flag.name }} {{ entry.flag.note|default:"—" }} {% if entry.overridden %} {# `everyone` overrides club targeting, so a per-club toggle would be a lie. #} {% if entry.flag.everyone %}On for all clubs{% else %}Off everywhere{% endif %} {% else %}
{% csrf_token %}
{% endif %}
No features defined yet.
{% if not subscription %}

This club is not billed for anything. Put it on a tier to start.

{% else %}

On plan {{ subscription.tier.name }}. {% if subscription.auto_renew %} Renews automatically 30 days before the period ends. {% else %} Auto-renew off — you must open each period by hand, or this club uses the platform for free. {% endif %} {% if subscription.auto_archive %} Archived automatically when a period goes unpaid past its grace period. {% else %} Auto-archive off — it will never be archived for non-payment. {% endif %}

{% for due in dues %} {% for payment in due.payments.all %} {% endfor %} {% empty %} {% endfor %}
Period Billed Paid Status
{{ due.period_start|date:"j M Y" }} — {{ due.period_end|date:"j M Y" }}
{{ due.tier.name }} · {{ due.invoice.number }} · grace to {{ due.grace_until|date:"j M Y" }}
€{{ due.amount|floatformat:2 }} €{{ due.amount_paid|floatformat:2 }} {% if due.status == "paid" %} {% lucide "check" size=12 %} Paid {% elif due.status == "waived" %} {% lucide "check" size=12 %} Waived {% elif due.grace_until < today %} {% lucide "triangle-alert" size=12 %} Overdue {% elif due.period_end < today %} {% lucide "hourglass" size=12 %} In grace {% else %} {{ due.get_status_display }} {% endif %} {% if due.is_owing %} {% lucide "banknote" size=14 %} Pay {% if not due.payments.all %}
{% csrf_token %}
{% endif %} {% endif %} {% lucide "file-down" size=14 %} Download invoice
{% lucide "corner-down-right" size=12 %} {{ payment.paid_at|date:"j M Y" }} · {{ payment.get_method_display }}{% if payment.reference %} · {{ payment.reference }}{% endif %} €{{ payment.amount|floatformat:2 }}
No periods billed yet.
{% endif %}

{% lucide "shield-user" size=18 %} Club admins

{% lucide "user-plus" size=16 %} Add admin
{% for role in admins %} {% empty %} {% endfor %}
Name Email
{{ role.member }} {{ role.member.user.email|default:"—" }}
{% csrf_token %}
No admins yet.
{% endblock panel %} {% block extra_body %} {{ charts|json_script:"chart-data" }} {% endblock extra_body %}