add back user profiles on subscription form

This commit is contained in:
imperosol 2024-11-29 15:48:40 +01:00
parent fc0e689d4e
commit 04b4b34bfe
12 changed files with 229 additions and 126 deletions

View File

@ -0,0 +1,89 @@
@import "colors";
/**
* Style related to forms
*/
a.button,
button,
input[type="button"],
input[type="submit"],
input[type="reset"],
input[type="file"] {
border: none;
text-decoration: none;
background-color: $background-button-color;
padding: 0.4em;
margin: 0.1em;
font-size: 1.2em;
border-radius: 5px;
color: black;
&:hover {
background: hsl(0, 0%, 83%);
}
}
a.button,
input[type="button"],
input[type="submit"],
input[type="reset"],
input[type="file"] {
font-weight: bold;
}
a.button:not(:disabled),
button:not(:disabled),
input[type="button"]:not(:disabled),
input[type="submit"]:not(:disabled),
input[type="reset"]:not(:disabled),
input[type="checkbox"]:not(:disabled),
input[type="file"]:not(:disabled) {
cursor: pointer;
}
input,
textarea[type="text"],
[type="number"] {
border: none;
text-decoration: none;
background-color: $background-button-color;
padding: 0.4em;
margin: 0.1em;
font-size: 1.2em;
border-radius: 5px;
max-width: 95%;
}
textarea {
border: none;
text-decoration: none;
background-color: $background-button-color;
padding: 7px;
font-size: 1.2em;
border-radius: 5px;
font-family: sans-serif;
}
select {
border: none;
text-decoration: none;
font-size: 1.2em;
background-color: $background-button-color;
padding: 10px;
border-radius: 5px;
cursor: pointer;
}
a:not(.button) {
text-decoration: none;
color: $primary-dark-color;
&:hover {
color: $primary-light-color;
}
&:active {
color: $primary-color;
}
}

View File

@ -1,4 +1,5 @@
@import "colors";
@import "forms";
/*--------------------------MEDIA QUERY HELPERS------------------------*/
$small-devices: 576px;
@ -13,91 +14,6 @@ body {
font-family: sans-serif;
}
a.button,
button,
input[type="button"],
input[type="submit"],
input[type="reset"],
input[type="file"] {
border: none;
text-decoration: none;
background-color: $background-button-color;
padding: 0.4em;
margin: 0.1em;
font-size: 1.2em;
border-radius: 5px;
color: black;
&:hover {
background: hsl(0, 0%, 83%);
}
}
a.button,
input[type="button"],
input[type="submit"],
input[type="reset"],
input[type="file"] {
font-weight: bold;
}
a.button:not(:disabled),
button:not(:disabled),
input[type="button"]:not(:disabled),
input[type="submit"]:not(:disabled),
input[type="reset"]:not(:disabled),
input[type="checkbox"]:not(:disabled),
input[type="file"]:not(:disabled) {
cursor: pointer;
}
input,
textarea[type="text"],
[type="number"] {
border: none;
text-decoration: none;
background-color: $background-button-color;
padding: 0.4em;
margin: 0.1em;
font-size: 1.2em;
border-radius: 5px;
max-width: 95%;
}
textarea {
border: none;
text-decoration: none;
background-color: $background-button-color;
padding: 7px;
font-size: 1.2em;
border-radius: 5px;
font-family: sans-serif;
}
select {
border: none;
text-decoration: none;
font-size: 1.2em;
background-color: $background-button-color;
padding: 10px;
border-radius: 5px;
cursor: pointer;
}
a:not(.button) {
text-decoration: none;
color: $primary-dark-color;
&:hover {
color: $primary-light-color;
}
&:active {
color: $primary-color;
}
}
[aria-busy] {
--loading-size: 50px;
--loading-stroke: 5px;
@ -1281,26 +1197,26 @@ u,
/*-----------------------------USER PROFILE----------------------------*/
.user_mini_profile {
height: 100%;
width: 100%;
--gap-size: 1em;
max-height: 100%;
max-width: 100%;
display: flex;
flex-direction: column;
gap: var(--gap-size);
img {
max-width: 100%;
max-height: 100%;
max-width: 100%;
}
.user_mini_profile_infos {
padding: 0.2em;
height: 20%;
max-height: 20%;
display: flex;
flex-wrap: nowrap;
justify-content: space-around;
font-size: 0.9em;
div {
max-height: 100%;
}
.user_mini_profile_infos_text {
text-align: center;
@ -1311,10 +1227,10 @@ u,
}
.user_mini_profile_picture {
height: 80%;
display: flex;
justify-content: center;
align-items: center;
max-height: calc(80% - var(--gap-size));
max-width: 100%;
display: block;
margin: auto;
}
}

View File

@ -66,7 +66,12 @@
</div>
{% if user.promo and user.promo_has_logo() %}
<div class="user_mini_profile_promo">
<img src="{{ static('core/img/promo_%02d.png' % user.promo) }}" title="Promo {{ user.promo }}" alt="Promo {{ user.promo }}" class="promo_pict" />
<img
src="{{ static('core/img/promo_%02d.png' % user.promo) }}"
title="Promo {{ user.promo }}"
alt="Promo {{ user.promo }}"
class="promo_pict"
/>
</div>
{% endif %}
</div>
@ -74,8 +79,11 @@
{% if user.profile_pict %}
<img src="{{ user.profile_pict.get_download_url() }}" alt="{% trans %}Profile{% endtrans %}" />
{% else %}
<img src="{{ static('core/img/unknown.jpg') }}" alt="{% trans %}Profile{% endtrans %}"
title="{% trans %}Profile{% endtrans %}" />
<img
src="{{ static('core/img/unknown.jpg') }}"
alt="{% trans %}Profile{% endtrans %}"
title="{% trans %}Profile{% endtrans %}"
/>
{% endif %}
</div>
</div>
@ -286,6 +294,13 @@
<p x-text="current_tab"></p>
{{ tabs([("tab 1", "Hello"), ("tab 2", "World")], "x-model=current_tab") }}
</div>
If you want to have translated tab titles, you can enclose the macro call
in a with block :
{% with title=_("title"), content=_("Content") %}
{{ tabs([(tab1, content)]) }}
{% endwith %}
#}
<div
class="tabs"

View File

@ -6,7 +6,7 @@
msgid ""
msgstr ""
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-11-27 15:24+0100\n"
"POT-Creation-Date: 2024-11-29 18:04+0100\n"
"PO-Revision-Date: 2016-07-18\n"
"Last-Translator: Maréchal <thomas.girod@utbm.fr\n"
"Language-Team: AE info <ae.info@utbm.fr>\n"
@ -362,8 +362,8 @@ msgstr "Compte en banque : "
#: core/templates/core/file_detail.jinja:62
#: core/templates/core/file_moderation.jinja:48
#: core/templates/core/group_detail.jinja:26
#: core/templates/core/group_list.jinja:25 core/templates/core/macros.jinja:96
#: core/templates/core/macros.jinja:115 core/templates/core/page_prop.jinja:14
#: core/templates/core/group_list.jinja:25 core/templates/core/macros.jinja:104
#: core/templates/core/macros.jinja:123 core/templates/core/page_prop.jinja:14
#: core/templates/core/user_account_detail.jinja:41
#: core/templates/core/user_account_detail.jinja:77
#: core/templates/core/user_clubs.jinja:34
@ -1334,7 +1334,7 @@ msgid "No mailing list existing for this club"
msgstr "Aucune mailing liste n'existe pour ce club"
#: club/templates/club/mailing.jinja:72
#: subscription/templates/subscription/subscription.jinja:34
#: subscription/templates/subscription/subscription.jinja:39
msgid "New member"
msgstr "Nouveau membre"
@ -2204,8 +2204,8 @@ msgstr "profil visible par les cotisants"
msgid "A user with that username already exists"
msgstr "Un utilisateur de ce nom d'utilisateur existe déjà"
#: core/models.py:761 core/templates/core/macros.jinja:75
#: core/templates/core/macros.jinja:77 core/templates/core/macros.jinja:78
#: core/models.py:761 core/templates/core/macros.jinja:80
#: core/templates/core/macros.jinja:84 core/templates/core/macros.jinja:85
#: core/templates/core/user_detail.jinja:100
#: core/templates/core/user_detail.jinja:101
#: core/templates/core/user_detail.jinja:103
@ -2753,29 +2753,29 @@ msgstr "Partager sur Facebook"
msgid "Tweet"
msgstr "Tweeter"
#: core/templates/core/macros.jinja:85
#: core/templates/core/macros.jinja:93
#, python-format
msgid "Subscribed until %(subscription_end)s"
msgstr "Cotisant jusqu'au %(subscription_end)s"
#: core/templates/core/macros.jinja:86
#: core/templates/core/macros.jinja:94
msgid "Account number: "
msgstr "Numéro de compte : "
#: core/templates/core/macros.jinja:91 launderette/models.py:188
#: core/templates/core/macros.jinja:99 launderette/models.py:188
msgid "Slot"
msgstr "Créneau"
#: core/templates/core/macros.jinja:104
#: core/templates/core/macros.jinja:112
#: launderette/templates/launderette/launderette_admin.jinja:20
msgid "Tokens"
msgstr "Jetons"
#: core/templates/core/macros.jinja:258
#: core/templates/core/macros.jinja:266
msgid "Select All"
msgstr "Tout sélectionner"
#: core/templates/core/macros.jinja:259
#: core/templates/core/macros.jinja:267
msgid "Unselect All"
msgstr "Tout désélectionner"
@ -3137,7 +3137,7 @@ msgstr "Non cotisant"
#: core/templates/core/user_detail.jinja:162
#: subscription/templates/subscription/subscription.jinja:6
#: subscription/templates/subscription/subscription.jinja:31
#: subscription/templates/subscription/subscription.jinja:37
msgid "New subscription"
msgstr "Nouvelle cotisation"
@ -5791,7 +5791,7 @@ msgstr "Weekmail envoyé avec succès"
msgid "AE tee-shirt"
msgstr "Tee-shirt AE"
#: subscription/forms.py:83
#: subscription/forms.py:93
msgid "A user with that email address already exists"
msgstr "Un utilisateur avec cette adresse email existe déjà"
@ -5841,7 +5841,7 @@ msgstr ""
msgid "Go to user profile"
msgstr "Voir le profil de l'utilisateur"
#: subscription/templates/subscription/fragments/creation_success.jinja:25
#: subscription/templates/subscription/fragments/creation_success.jinja:24
msgid "Create another subscription"
msgstr "Créer une nouvelle cotisation"

View File

@ -61,6 +61,8 @@ class SubscriptionNewUserForm(SubscriptionForm):
assert user.is_subscribed
"""
template_name = "subscription/forms/create_new_user.html"
__user_fields = forms.fields_for_model(
User,
["first_name", "last_name", "email", "date_of_birth"],
@ -114,6 +116,8 @@ class SubscriptionNewUserForm(SubscriptionForm):
class SubscriptionExistingUserForm(SubscriptionForm):
"""Form to add a subscription to an existing user."""
template_name = "subscription/forms/create_existing_user.html"
class Meta:
model = Subscription
fields = ["member", "subscription_type", "payment_method", "location"]

View File

@ -0,0 +1,25 @@
document.addEventListener("alpine:init", () => {
Alpine.data("existing_user_subscription_form", () => ({
loading: false,
profileFragment: "" as string,
async init() {
const userSelect = document.getElementById("id_member") as HTMLSelectElement;
userSelect.addEventListener("change", async () => {
await this.loadProfile(Number.parseInt(userSelect.value));
});
await this.loadProfile(Number.parseInt(userSelect.value));
},
async loadProfile(userId: number) {
if (!Number.isInteger(userId)) {
this.profileFragment = "";
return;
}
this.loading = true;
const response = await fetch(`/user/${userId}/mini/`);
this.profileFragment = await response.text();
this.loading = false;
},
}));
});

View File

@ -0,0 +1,28 @@
#subscription-form form {
.form-content.existing-user {
max-height: 100%;
display: flex;
flex: 1 1 auto;
flex-direction: row;
@media screen and (max-width: 700px) {
flex-direction: column-reverse;
}
/* Make the form fields take exactly the space they need,
* then display the user profile right in the middle of the remaining space. */
fieldset {
flex: 0 1 auto;
}
#subscription-form-user-mini-profile {
display: flex;
flex: 1 1 auto;
justify-content: center;
}
.user_mini_profile {
height: 300px;
}
}
}

View File

@ -0,0 +1,14 @@
{% load static %}
{% load i18n %}
<div x-data="existing_user_subscription_form" class="form-content existing-user">
<fieldset>
{{ form.as_p }}
</fieldset>
<div
id="subscription-form-user-mini-profile"
x-html="profileFragment"
:aria-busy="loading"
></div>
</div>

View File

@ -0,0 +1 @@
{{ form.as_p }}

View File

@ -5,6 +5,6 @@
hx-swap="outerHTML"
>
{% csrf_token %}
{{ form.as_p() }}
{{ form }}
<input type="submit" value="{% trans %}Save{% endtrans %}">
</form>

View File

@ -4,18 +4,21 @@
{% trans user=subscription.member %}Subscription created for {{ user }}{% endtrans %}
</h3>
<p>
{% trans trimmed user=subscription.member.get_short_name(), type=subscription.subscription_type, end=subscription.subscription_end %}
{{ user }} received its new {{ type }} subscription.
It will be active until {{ end }} included.
{% trans trimmed
user=subscription.member.get_short_name(),
type=subscription.subscription_type,
end=subscription.subscription_end
%}
{{ user }} received its new {{ type }} subscription.
It will be active until {{ end }} included.
{% endtrans %}
</p>
</div>
<div class="alert-aside">
<a class="btn btn-blue" href="{{ subscription.member.get_absolute_url() }}">
<a class="btn btn-blue" href="{{ subscription.member.get_absolute_url() }}">
{% trans %}Go to user profile{% endtrans %}
</a>
<a class="btn btn-grey" href="{{ url("subscription:subscription") }}">
<a class="btn btn-grey" href="{{ url("subscription:subscription") }}">
{# We don't know if this fragment is displayed after creating a subscription
for a previously existing user or for a newly created one.
Thus, we don't know which form should be used to create another subscription

View File

@ -13,10 +13,16 @@
If the aforementioned bug is resolved, you can remove this. #}
{% block additional_js %}
<script type="module" defer src="{{ static("bundled/core/components/ajax-select-index.ts") }}"></script>
<script
type="module"
defer
src="{{ static("bundled/subscription/creation-form-existing-user-index.ts") }}"
></script>
{% endblock %}
{% block additional_css %}
<link rel="stylesheet" href="{{ static("bundled/core/components/ajax-select-index.css") }}">
<link rel="stylesheet" href="{{ static("core/components/ajax-select.scss") }}">
<link rel="stylesheet" href="{{ static("subscription/css/subscription.scss") }}">
{% endblock %}
{% macro form_fragment(form_object, post_url) %}
@ -30,9 +36,11 @@
{% block content %}
<h3>{% trans %}New subscription{% endtrans %}</h3>
<div id="subscription-form" hx-ext="response-targets">
{{ tabs([
(_("Existing member"), form_fragment(existing_user_form, existing_user_post_url)),
(_("New member"), form_fragment(new_user_form, new_user_post_url)),
]) }}
{% with title1=_("Existing member"), title2=_("New member") %}
{{ tabs([
(title1, form_fragment(existing_user_form, existing_user_post_url)),
(title2, form_fragment(new_user_form, new_user_post_url)),
]) }}
{% endwith %}
</div>
{% endblock %}