Add Club.website; rebuild Colours per D9's exact markup; add a mobile app preview
- club.website (URLField, blank) editable from both the club's own Identity
page and the platform control panel's club form.
- Colours card rebuilt from the design canvas's literal D9 markup rather
than the prior in-between version: swatch + mono hex merged into one
bordered row (the swatch input and hex text input are the same real form
field, just laid out together), and a contrast-check row of two colour-
filled boxes instead of a plain text list -- labelled dynamically
("Black"/"White" on primary/secondary) since a club can pick a colour
light enough that black, not white, is the real computed text colour.
- Logo card restyled to D9's dashed drop-zone look.
- Live preview gains a mobile app mock (marked "Coming soon") alongside the
existing sidebar mock, using the same primary/secondary colours, ahead of
that surface actually being built.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ECGMEwrc2k4D8VQuwjstj9
This commit is contained in:
@@ -1737,23 +1737,73 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* --- Club identity live preview (management/templates/management/club_settings.html) ---
|
||||
A mini mock of this app's own sidebar + a sample button -- genuinely what
|
||||
primary_color/secondary_color affect (base.html's --tenant-* custom
|
||||
properties), not a fabricated App/Website/Email mockup. Colours are set
|
||||
inline by that template's own script as the form fields change; only
|
||||
layout/typography lives here. */
|
||||
/* --- Club identity page (management/templates/management/club_settings.html) ---
|
||||
Colours: swatch + mono hex merged into one bordered row (D9's own look),
|
||||
not a labelled field with a decorative swatch floating below it. Live
|
||||
preview: a mini mock of this app's own sidebar/button (the real, live
|
||||
surface primary_color/secondary_color affect today, via base.html's
|
||||
--tenant-* custom properties) plus a mobile app mock (the same colours
|
||||
applied to the surface that's built next) -- not D9's fabricated App/
|
||||
Website/Email tabs. Colours are set inline by that template's own script
|
||||
as the form fields change; only layout/typography lives here. */
|
||||
@layer components {
|
||||
.club-color-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.625rem;
|
||||
border: 1px solid var(--color-edge);
|
||||
border-radius: 0.5rem;
|
||||
padding: 0.5rem 0.625rem;
|
||||
}
|
||||
|
||||
.club-color-swatch {
|
||||
width: 2rem;
|
||||
height: 1.5rem;
|
||||
width: 1.625rem;
|
||||
height: 1.625rem;
|
||||
flex-shrink: 0;
|
||||
padding: 0;
|
||||
border: 1px solid var(--color-line);
|
||||
border: none;
|
||||
border-radius: 0.375rem;
|
||||
background: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.club-color-hex-input {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
border: none;
|
||||
background: none;
|
||||
outline: none;
|
||||
padding: 0;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.875rem;
|
||||
color: var(--color-ink);
|
||||
}
|
||||
|
||||
.club-contrast-box {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 0.5rem;
|
||||
border-radius: 0.5rem;
|
||||
padding: 0.625rem 0.75rem;
|
||||
font-size: 0.8125rem;
|
||||
transition: background-color 0.15s ease, color 0.15s ease;
|
||||
}
|
||||
|
||||
.club-logo-dropzone {
|
||||
display: flex;
|
||||
width: 4.75rem;
|
||||
height: 4.75rem;
|
||||
flex-shrink: 0;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
border: 1.5px dashed var(--color-stroke);
|
||||
border-radius: 0.5rem;
|
||||
background: var(--color-paper);
|
||||
}
|
||||
|
||||
.preview-frame {
|
||||
display: flex;
|
||||
height: 220px;
|
||||
@@ -1856,10 +1906,119 @@
|
||||
width: 60%;
|
||||
}
|
||||
|
||||
.contrast-icon {
|
||||
display: inline-flex;
|
||||
width: 1rem;
|
||||
/* The mobile app mock -- not built yet, but its header/role-switcher take
|
||||
the same primary/secondary colours the sidebar mock above does, so this
|
||||
preview stays accurate once it exists rather than needing a rework. */
|
||||
.preview-phone {
|
||||
width: 11rem;
|
||||
flex-shrink: 0;
|
||||
overflow: hidden;
|
||||
border: 5px solid var(--color-ink);
|
||||
border-radius: 1.375rem;
|
||||
background: var(--color-paper);
|
||||
}
|
||||
|
||||
.preview-phone-header {
|
||||
padding: 0.75rem 0.625rem 0.625rem;
|
||||
background: var(--color-ink);
|
||||
color: #fff;
|
||||
transition: background-color 0.15s ease, color 0.15s ease;
|
||||
}
|
||||
|
||||
.preview-phone-header-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.375rem;
|
||||
}
|
||||
|
||||
.preview-crest-sm {
|
||||
width: 1.125rem;
|
||||
height: 1.125rem;
|
||||
font-size: 0.5rem;
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
|
||||
.preview-phone-name {
|
||||
font-family: var(--font-display);
|
||||
font-size: 0.6875rem;
|
||||
font-weight: 800;
|
||||
letter-spacing: 0.04em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.preview-phone-roles {
|
||||
display: flex;
|
||||
gap: 2px;
|
||||
margin-top: 0.5rem;
|
||||
padding: 2px;
|
||||
border-radius: 999px;
|
||||
background: rgba(255, 255, 255, 0.12);
|
||||
}
|
||||
|
||||
.preview-phone-role {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: 700;
|
||||
height: 1.25rem;
|
||||
border-radius: 999px;
|
||||
font-family: var(--font-display);
|
||||
font-size: 0.5625rem;
|
||||
font-weight: 800;
|
||||
letter-spacing: 0.04em;
|
||||
text-transform: uppercase;
|
||||
color: var(--color-on-dark);
|
||||
}
|
||||
|
||||
.preview-phone-role-active {
|
||||
background: #fff;
|
||||
color: var(--color-ink);
|
||||
}
|
||||
|
||||
.preview-phone-body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
padding: 0.625rem;
|
||||
}
|
||||
|
||||
.preview-phone-card {
|
||||
border-radius: 0.5rem;
|
||||
padding: 0.5rem;
|
||||
background: var(--color-club);
|
||||
color: #fff;
|
||||
transition: background-color 0.15s ease, color 0.15s ease;
|
||||
}
|
||||
|
||||
.preview-phone-eyebrow {
|
||||
font-family: var(--font-display);
|
||||
font-size: 0.5625rem;
|
||||
font-weight: 800;
|
||||
letter-spacing: 0.06em;
|
||||
text-transform: uppercase;
|
||||
color: var(--color-info);
|
||||
}
|
||||
|
||||
.preview-phone-title {
|
||||
margin-top: 0.125rem;
|
||||
font-family: var(--font-display);
|
||||
font-size: 0.75rem;
|
||||
line-height: 1.05;
|
||||
font-weight: 800;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.preview-phone-bar {
|
||||
height: 1rem;
|
||||
margin-top: 0.5rem;
|
||||
border-radius: 0.25rem;
|
||||
background: var(--color-ok);
|
||||
}
|
||||
|
||||
.preview-phone-skeleton-card {
|
||||
border: 1px solid var(--color-line);
|
||||
border-radius: 0.5rem;
|
||||
padding: 0.5rem;
|
||||
background: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
18
club/migrations/0027_club_website.py
Normal file
18
club/migrations/0027_club_website.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 6.0.6 on 2026-08-20 07:08
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('club', '0026_memberrequirementstatus_is_bypassed_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='club',
|
||||
name='website',
|
||||
field=models.URLField(blank=True, help_text="The club's own site, if it has one -- shown alongside its RosterChief pages, not used for anything else yet.", verbose_name='website'),
|
||||
),
|
||||
]
|
||||
@@ -48,6 +48,7 @@ class Club(UUIDModel):
|
||||
blank=True,
|
||||
help_text=_("The club's public address, shown to people the club writes to or asks to get in touch -- e.g. a parent claiming a child. Falls back to nothing being shown at all, so it's worth setting."),
|
||||
)
|
||||
website = models.URLField(_("website"), blank=True, help_text=_("The club's own site, if it has one -- shown alongside its RosterChief pages, not used for anything else yet."))
|
||||
|
||||
logo = models.FileField(
|
||||
_("logo"),
|
||||
|
||||
@@ -14,7 +14,7 @@ from .services.admins import find_member_by_email
|
||||
class ClubForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Club
|
||||
fields = ["name", "legal_name", "contact_email", "slug", "sport_type", "logo", "primary_color", "secondary_color", "season_start", "season_duration_months"]
|
||||
fields = ["name", "legal_name", "contact_email", "website", "slug", "sport_type", "logo", "primary_color", "secondary_color", "season_start", "season_duration_months"]
|
||||
help_texts = {"slug": _("Drives the club's subdomain. Left blank, it is derived from the name.")}
|
||||
# Deliberately a text input, not <input type="color">: a colour picker cannot
|
||||
# express "no colour" -- it would submit #000000 for every club that never
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
{% form_field form.name %}
|
||||
{% form_field form.legal_name %}
|
||||
{% form_field form.contact_email %}
|
||||
{% form_field form.website %}
|
||||
{% form_field form.slug %}
|
||||
{% form_field form.sport_type %}
|
||||
</div>
|
||||
|
||||
@@ -881,7 +881,7 @@ class ClubSettingsForm(forms.ModelForm):
|
||||
|
||||
class Meta:
|
||||
model = Club
|
||||
fields = ["name", "legal_name", "contact_email", "logo", "primary_color", "secondary_color"]
|
||||
fields = ["name", "legal_name", "contact_email", "website", "logo", "primary_color", "secondary_color"]
|
||||
widgets = {
|
||||
"primary_color": forms.TextInput(attrs={"placeholder": "#1e40af"}),
|
||||
"secondary_color": forms.TextInput(attrs={"placeholder": "#be185d"}),
|
||||
|
||||
@@ -5,16 +5,18 @@
|
||||
A club's own self-service identity/branding editor -- see
|
||||
management/forms.py's ClubSettingsForm for exactly which fields are
|
||||
editable here versus platform-staff-only (slug, seasons). D9 "Club
|
||||
identity & branding" in the design handoff is the reference: two columns,
|
||||
form fields on the left and a live preview on the right. The preview here
|
||||
is scoped to what actually exists in this app rather than D9's aspirational
|
||||
App/Website/Email tabs -- primary_color drives the sidebar
|
||||
(--tenant-sidebar-bg/fg, base.html), secondary_color drives the club accent
|
||||
(--tenant-club/-dark/-content, buttons/active nav/crest) -- so the mini
|
||||
sidebar + button mock below is genuinely what changing these fields does,
|
||||
not a fabricated mockup. The colour math (content colour, contrast ratio)
|
||||
mirrors Club._content_color_for exactly, so the "computed ratio" shown is
|
||||
the real number the server will use, not an approximation.
|
||||
identity & branding" in the design handoff is the reference, followed
|
||||
closely for the Colours card (merged swatch+hex row, side-by-side
|
||||
contrast-check boxes) and the Logo card (dashed drop zone) -- markup
|
||||
pulled straight from the design canvas (RosterChief Platform.dc.html),
|
||||
not the prose summary. The live preview is scoped to surfaces that are
|
||||
(or will genuinely be) this app rather than D9's aspirational App/
|
||||
Website/Email tabs: the sidebar mock is what primary_color/secondary_color
|
||||
affect today (base.html's --tenant-* custom properties); the phone mock
|
||||
is the same colours applied ahead of the mobile app being built. The
|
||||
colour math (content colour, contrast ratio) mirrors
|
||||
Club._content_color_for exactly, so what's shown is the real number the
|
||||
server computes on save, not an approximation.
|
||||
{% endcomment %}
|
||||
|
||||
{% block panel_title %}{% trans "Club identity" %}{% endblock panel_title %}
|
||||
@@ -39,10 +41,11 @@
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="card-title">{% lucide "building-2" size=16 %} {% trans "Club" %}</div>
|
||||
<div class="flex flex-col gap-4">
|
||||
<div class="grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||
{% form_field form.name %}
|
||||
{% form_field form.legal_name %}
|
||||
{% form_field form.contact_email %}
|
||||
{% form_field form.website %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -53,37 +56,37 @@
|
||||
<div class="card-title">{% lucide "palette" size=16 %} {% trans "Colours" %}</div>
|
||||
<span class="font-mono text-xs text-dim">{% trans "Accents only" %}</span>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-2 gap-4">
|
||||
<div>
|
||||
{% form_field form.primary_color %}
|
||||
<div class="mt-1.5 flex items-center gap-2">
|
||||
<div class="mb-1.5 font-display text-[11px] font-bold tracking-[.12em] text-muted uppercase">{{ form.primary_color.label|capfirst }}</div>
|
||||
<label class="club-color-row">
|
||||
<input type="color" id="primary_color_swatch" class="club-color-swatch" value="{{ form.primary_color.value|default:"#0b1220" }}" aria-label="{% trans "Pick the primary colour" %}">
|
||||
<span class="font-mono text-xs text-muted">{% trans "Sidebar background" %}</span>
|
||||
</div>
|
||||
<input type="text" name="{{ form.primary_color.html_name }}" id="{{ form.primary_color.id_for_label }}" value="{{ form.primary_color.value|default:"" }}" placeholder="#0b1220" class="club-color-hex-input">
|
||||
</label>
|
||||
{% if form.primary_color.errors %}<p class="mt-1 text-xs text-club-dark">{{ form.primary_color.errors|join:" " }}</p>{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
{% form_field form.secondary_color %}
|
||||
<div class="mt-1.5 flex items-center gap-2">
|
||||
<div class="mb-1.5 font-display text-[11px] font-bold tracking-[.12em] text-muted uppercase">{{ form.secondary_color.label|capfirst }}</div>
|
||||
<label class="club-color-row">
|
||||
<input type="color" id="secondary_color_swatch" class="club-color-swatch" value="{{ form.secondary_color.value|default:"#e4002b" }}" aria-label="{% trans "Pick the secondary colour" %}">
|
||||
<span class="font-mono text-xs text-muted">{% trans "Buttons & accents" %}</span>
|
||||
</div>
|
||||
<input type="text" name="{{ form.secondary_color.html_name }}" id="{{ form.secondary_color.id_for_label }}" value="{{ form.secondary_color.value|default:"" }}" placeholder="#e4002b" class="club-color-hex-input">
|
||||
</label>
|
||||
{% if form.secondary_color.errors %}<p class="mt-1 text-xs text-club-dark">{{ form.secondary_color.errors|join:" " }}</p>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 flex flex-col gap-1.5 border-t border-rule pt-3">
|
||||
<div class="contrast-row flex items-center justify-between gap-2 text-xs">
|
||||
<span class="text-muted">{% trans "Sidebar text on sidebar background" %}</span>
|
||||
<span class="flex items-center gap-1 font-mono">
|
||||
<span id="primary-contrast-ratio">—</span>
|
||||
<span class="contrast-icon"></span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="contrast-row flex items-center justify-between gap-2 text-xs">
|
||||
<span class="text-muted">{% trans "Button text on accent colour" %}</span>
|
||||
<span class="flex items-center gap-1 font-mono">
|
||||
<span id="secondary-contrast-ratio">—</span>
|
||||
<span class="contrast-icon"></span>
|
||||
</span>
|
||||
<div class="mt-4">
|
||||
<div class="mb-2 font-display text-[11px] font-bold tracking-[.12em] text-muted uppercase">{% trans "Contrast check" %}</div>
|
||||
<div class="flex gap-2">
|
||||
<div id="contrast-box-primary" class="club-contrast-box">
|
||||
<span id="contrast-label-primary"></span>
|
||||
<span id="contrast-ratio-primary" class="font-mono"></span>
|
||||
</div>
|
||||
<div id="contrast-box-secondary" class="club-contrast-box">
|
||||
<span id="contrast-label-secondary"></span>
|
||||
<span id="contrast-ratio-secondary" class="font-mono"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -92,12 +95,17 @@
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="card-title">{% lucide "image" size=16 %} {% trans "Logo" %}</div>
|
||||
<div class="flex items-center gap-3.5">
|
||||
{% if club.logo %}
|
||||
<img class="h-14 w-14 shrink-0 rounded-lg border border-line bg-paper object-contain p-1" src="{{ club.logo.url }}" alt="">
|
||||
{% else %}
|
||||
<span class="flex h-14 w-14 shrink-0 items-center justify-center rounded-lg border border-line bg-paper font-display text-sm font-extrabold text-muted">{{ club.initials }}</span>
|
||||
{% endif %}
|
||||
<div class="flex items-end gap-4">
|
||||
<div>
|
||||
<div class="mb-1.5 font-display text-[11px] font-bold tracking-[.12em] text-muted uppercase">{% trans "Crest" %}</div>
|
||||
<div class="club-logo-dropzone">
|
||||
{% if club.logo %}
|
||||
<img class="h-full w-full object-contain p-1.5" src="{{ club.logo.url }}" alt="">
|
||||
{% else %}
|
||||
<span class="font-display text-sm font-extrabold text-muted">{{ club.initials }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-1">{% form_field form.logo %}</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -108,9 +116,10 @@
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="card-title">{% lucide "eye" size=16 %} {% trans "Live preview" %}</div>
|
||||
<p class="text-xs text-muted">{% trans "Where these colours actually show up in the management app -- updates as you edit, before you save anything." %}</p>
|
||||
<p class="text-xs text-muted">{% trans "Where these colours actually show up -- updates as you edit, before you save anything." %}</p>
|
||||
|
||||
<div class="preview-frame mt-2">
|
||||
<div class="mt-2 font-display text-[11px] font-bold tracking-[.12em] text-muted uppercase">{% trans "Management app" %}</div>
|
||||
<div class="preview-frame mt-1.5">
|
||||
<div id="preview-sidebar" class="preview-sidebar">
|
||||
<div class="preview-crest">{{ club.initials|default:"CL" }}</div>
|
||||
<div class="preview-club-name">{{ club.name|default:_("Your club") }}</div>
|
||||
@@ -126,6 +135,34 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 flex items-center justify-between gap-2">
|
||||
<div class="font-display text-[11px] font-bold tracking-[.12em] text-muted uppercase">{% trans "Mobile app" %}</div>
|
||||
<span class="badge badge-sm badge-ghost">{% trans "Coming soon" %}</span>
|
||||
</div>
|
||||
<div class="mt-1.5 preview-phone">
|
||||
<div id="preview-phone-header" class="preview-phone-header">
|
||||
<div class="preview-phone-header-row">
|
||||
<span class="preview-crest preview-crest-sm">{{ club.initials|default:"CL" }}</span>
|
||||
<span class="preview-phone-name">{{ club.name|default:_("Your club") }}</span>
|
||||
</div>
|
||||
<div class="preview-phone-roles">
|
||||
<span class="preview-phone-role preview-phone-role-active">{% trans "Member" %}</span>
|
||||
<span class="preview-phone-role">{% trans "Coach" %}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="preview-phone-body">
|
||||
<div id="preview-phone-card" class="preview-phone-card">
|
||||
<div class="preview-phone-eyebrow">{% trans "Next up" %}</div>
|
||||
<div class="preview-phone-title">{% trans "U16 vs Leuven" %}</div>
|
||||
<div class="preview-phone-bar"></div>
|
||||
</div>
|
||||
<div class="preview-phone-skeleton-card">
|
||||
<div class="preview-skeleton-line"></div>
|
||||
<div class="preview-skeleton-line preview-skeleton-line-short"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 text-xs text-dim">
|
||||
{% trans "Never used for: status colours (paid/overdue, present/absent), table styling, or form fields -- those stay consistent for everyone regardless of club branding." %}
|
||||
</div>
|
||||
@@ -164,15 +201,15 @@
|
||||
const secondarySwatch = document.getElementById("secondary_color_swatch");
|
||||
if (!primaryText || !secondaryText) return;
|
||||
|
||||
const setContrastRow = (elementId, hex, contentHex) => {
|
||||
const CONTENT_LABEL = { "#000000": "{% trans 'Black' %}", "#ffffff": "{% trans 'White' %}" };
|
||||
|
||||
const setContrastBox = (boxId, labelId, ratioId, hex, contentHex, onLabel) => {
|
||||
const ratio = contrastRatio(hex, contentHex);
|
||||
const cell = document.getElementById(elementId);
|
||||
cell.textContent = `${ratio.toFixed(1)}:1`;
|
||||
const row = cell.closest(".contrast-row");
|
||||
const icon = row.querySelector(".contrast-icon");
|
||||
icon.textContent = ratio >= 4.5 ? "✓" : "⚠";
|
||||
icon.classList.toggle("text-ok", ratio >= 4.5);
|
||||
icon.classList.toggle("text-warn", ratio < 4.5);
|
||||
document.getElementById(labelId).textContent = `${CONTENT_LABEL[contentHex]} ${onLabel}`;
|
||||
document.getElementById(ratioId).textContent = `${ratio.toFixed(1)} ${ratio >= 4.5 ? "✓" : "⚠"}`;
|
||||
const box = document.getElementById(boxId);
|
||||
box.style.background = hex;
|
||||
box.style.color = contentHex;
|
||||
};
|
||||
|
||||
const updatePreview = () => {
|
||||
@@ -188,8 +225,13 @@
|
||||
document.getElementById("preview-button").style.background = secondary;
|
||||
document.getElementById("preview-button").style.color = secondaryContent;
|
||||
|
||||
setContrastRow("primary-contrast-ratio", primary, primaryContent);
|
||||
setContrastRow("secondary-contrast-ratio", secondary, secondaryContent);
|
||||
document.getElementById("preview-phone-header").style.background = primary;
|
||||
document.getElementById("preview-phone-header").style.color = primaryContent;
|
||||
document.getElementById("preview-phone-card").style.background = secondary;
|
||||
document.getElementById("preview-phone-card").style.color = secondaryContent;
|
||||
|
||||
setContrastBox("contrast-box-primary", "contrast-label-primary", "contrast-ratio-primary", primary, primaryContent, "{% trans 'on primary' %}");
|
||||
setContrastBox("contrast-box-secondary", "contrast-label-secondary", "contrast-ratio-secondary", secondary, secondaryContent, "{% trans 'on secondary' %}");
|
||||
|
||||
if (primarySwatch && isHex(primary)) primarySwatch.value = primary;
|
||||
if (secondarySwatch && isHex(secondary)) secondarySwatch.value = secondary;
|
||||
|
||||
@@ -4472,16 +4472,27 @@ class ClubSettingsPreviewTests(ManagementTestBase):
|
||||
self.assertContains(response, 'id="primary_color_swatch"')
|
||||
self.assertContains(response, 'id="secondary_color_swatch"')
|
||||
|
||||
def test_the_mobile_app_preview_renders(self):
|
||||
response = self.club_get("club_settings")
|
||||
|
||||
self.assertContains(response, "preview-phone")
|
||||
self.assertContains(response, "Coming soon")
|
||||
|
||||
def test_the_website_field_is_editable(self):
|
||||
response = self.club_get("club_settings")
|
||||
self.assertContains(response, 'name="website"')
|
||||
|
||||
def test_saving_still_updates_the_club(self):
|
||||
response = self.club_post(
|
||||
"club_settings",
|
||||
{"name": "Ajax United", "legal_name": "", "contact_email": "", "primary_color": "#123456", "secondary_color": "#654321"},
|
||||
{"name": "Ajax United", "legal_name": "", "contact_email": "", "website": "https://ajax-united.example", "primary_color": "#123456", "secondary_color": "#654321"},
|
||||
)
|
||||
|
||||
self.assertRedirects(response, reverse("management:club_settings"))
|
||||
self.club.refresh_from_db()
|
||||
self.assertEqual(self.club.primary_color, "#123456")
|
||||
self.assertEqual(self.club.secondary_color, "#654321")
|
||||
self.assertEqual(self.club.website, "https://ajax-united.example")
|
||||
|
||||
|
||||
class BillingEndingBannerTests(ManagementTestBase):
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user