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 "colors";
@import "forms";
/*--------------------------MEDIA QUERY HELPERS------------------------*/ /*--------------------------MEDIA QUERY HELPERS------------------------*/
$small-devices: 576px; $small-devices: 576px;
@ -13,91 +14,6 @@ body {
font-family: sans-serif; 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] { [aria-busy] {
--loading-size: 50px; --loading-size: 50px;
--loading-stroke: 5px; --loading-stroke: 5px;
@ -1281,26 +1197,26 @@ u,
/*-----------------------------USER PROFILE----------------------------*/ /*-----------------------------USER PROFILE----------------------------*/
.user_mini_profile { .user_mini_profile {
height: 100%; --gap-size: 1em;
width: 100%; max-height: 100%;
max-width: 100%;
display: flex;
flex-direction: column;
gap: var(--gap-size);
img { img {
max-width: 100%;
max-height: 100%; max-height: 100%;
max-width: 100%;
} }
.user_mini_profile_infos { .user_mini_profile_infos {
padding: 0.2em; padding: 0.2em;
height: 20%; max-height: 20%;
display: flex; display: flex;
flex-wrap: nowrap; flex-wrap: nowrap;
justify-content: space-around; justify-content: space-around;
font-size: 0.9em; font-size: 0.9em;
div {
max-height: 100%;
}
.user_mini_profile_infos_text { .user_mini_profile_infos_text {
text-align: center; text-align: center;
@ -1311,10 +1227,10 @@ u,
} }
.user_mini_profile_picture { .user_mini_profile_picture {
height: 80%; max-height: calc(80% - var(--gap-size));
display: flex; max-width: 100%;
justify-content: center; display: block;
align-items: center; margin: auto;
} }
} }

View File

@ -66,7 +66,12 @@
</div> </div>
{% if user.promo and user.promo_has_logo() %} {% if user.promo and user.promo_has_logo() %}
<div class="user_mini_profile_promo"> <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> </div>
{% endif %} {% endif %}
</div> </div>
@ -74,8 +79,11 @@
{% if user.profile_pict %} {% if user.profile_pict %}
<img src="{{ user.profile_pict.get_download_url() }}" alt="{% trans %}Profile{% endtrans %}" /> <img src="{{ user.profile_pict.get_download_url() }}" alt="{% trans %}Profile{% endtrans %}" />
{% else %} {% else %}
<img src="{{ static('core/img/unknown.jpg') }}" alt="{% trans %}Profile{% endtrans %}" <img
title="{% trans %}Profile{% endtrans %}" /> src="{{ static('core/img/unknown.jpg') }}"
alt="{% trans %}Profile{% endtrans %}"
title="{% trans %}Profile{% endtrans %}"
/>
{% endif %} {% endif %}
</div> </div>
</div> </div>
@ -286,6 +294,13 @@
<p x-text="current_tab"></p> <p x-text="current_tab"></p>
{{ tabs([("tab 1", "Hello"), ("tab 2", "World")], "x-model=current_tab") }} {{ tabs([("tab 1", "Hello"), ("tab 2", "World")], "x-model=current_tab") }}
</div> </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 <div
class="tabs" class="tabs"

View File

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

View File

@ -61,6 +61,8 @@ class SubscriptionNewUserForm(SubscriptionForm):
assert user.is_subscribed assert user.is_subscribed
""" """
template_name = "subscription/forms/create_new_user.html"
__user_fields = forms.fields_for_model( __user_fields = forms.fields_for_model(
User, User,
["first_name", "last_name", "email", "date_of_birth"], ["first_name", "last_name", "email", "date_of_birth"],
@ -114,6 +116,8 @@ class SubscriptionNewUserForm(SubscriptionForm):
class SubscriptionExistingUserForm(SubscriptionForm): class SubscriptionExistingUserForm(SubscriptionForm):
"""Form to add a subscription to an existing user.""" """Form to add a subscription to an existing user."""
template_name = "subscription/forms/create_existing_user.html"
class Meta: class Meta:
model = Subscription model = Subscription
fields = ["member", "subscription_type", "payment_method", "location"] 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" hx-swap="outerHTML"
> >
{% csrf_token %} {% csrf_token %}
{{ form.as_p() }} {{ form }}
<input type="submit" value="{% trans %}Save{% endtrans %}"> <input type="submit" value="{% trans %}Save{% endtrans %}">
</form> </form>

View File

@ -4,18 +4,21 @@
{% trans user=subscription.member %}Subscription created for {{ user }}{% endtrans %} {% trans user=subscription.member %}Subscription created for {{ user }}{% endtrans %}
</h3> </h3>
<p> <p>
{% trans trimmed
{% trans trimmed user=subscription.member.get_short_name(), type=subscription.subscription_type, end=subscription.subscription_end %} user=subscription.member.get_short_name(),
{{ user }} received its new {{ type }} subscription. type=subscription.subscription_type,
It will be active until {{ end }} included. end=subscription.subscription_end
%}
{{ user }} received its new {{ type }} subscription.
It will be active until {{ end }} included.
{% endtrans %} {% endtrans %}
</p> </p>
</div> </div>
<div class="alert-aside"> <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 %} {% trans %}Go to user profile{% endtrans %}
</a> </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 {# We don't know if this fragment is displayed after creating a subscription
for a previously existing user or for a newly created one. 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 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. #} If the aforementioned bug is resolved, you can remove this. #}
{% block additional_js %} {% block additional_js %}
<script type="module" defer src="{{ static("bundled/core/components/ajax-select-index.ts") }}"></script> <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 %} {% endblock %}
{% block additional_css %} {% block additional_css %}
<link rel="stylesheet" href="{{ static("bundled/core/components/ajax-select-index.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("core/components/ajax-select.scss") }}">
<link rel="stylesheet" href="{{ static("subscription/css/subscription.scss") }}">
{% endblock %} {% endblock %}
{% macro form_fragment(form_object, post_url) %} {% macro form_fragment(form_object, post_url) %}
@ -30,9 +36,11 @@
{% block content %} {% block content %}
<h3>{% trans %}New subscription{% endtrans %}</h3> <h3>{% trans %}New subscription{% endtrans %}</h3>
<div id="subscription-form" hx-ext="response-targets"> <div id="subscription-form" hx-ext="response-targets">
{{ tabs([ {% with title1=_("Existing member"), title2=_("New member") %}
(_("Existing member"), form_fragment(existing_user_form, existing_user_post_url)), {{ tabs([
(_("New member"), form_fragment(new_user_form, new_user_post_url)), (title1, form_fragment(existing_user_form, existing_user_post_url)),
]) }} (title2, form_fragment(new_user_form, new_user_post_url)),
]) }}
{% endwith %}
</div> </div>
{% endblock %} {% endblock %}