From 57fbbf17a595963b049cb43c17287ad4e140199b Mon Sep 17 00:00:00 2001 From: Jonathan Bourdon Date: Fri, 25 Apr 2025 01:22:11 -0400 Subject: [PATCH] feat(creator): allow text for description --- .../src/Web/Features/Contents/Data/Creator.cs | 2 +- .../ContentDbContextModelSnapshot.cs | 3 +- .../Handlers/ChangePresentationInfos.cs | 4 +- frontend/src/views/creators/AboutCreator.vue | 60 ++++++++++++------- frontend/src/views/profile/ProfilePage.vue | 4 +- 5 files changed, 47 insertions(+), 26 deletions(-) diff --git a/backend/src/Web/Features/Contents/Data/Creator.cs b/backend/src/Web/Features/Contents/Data/Creator.cs index ba8e24e..19a5a6e 100644 --- a/backend/src/Web/Features/Contents/Data/Creator.cs +++ b/backend/src/Web/Features/Contents/Data/Creator.cs @@ -42,7 +42,7 @@ public class Socials public class Presentation { - [MaxLength(2000)] public string Description { get; set; } = null!; + public string Description { get; set; } = null!; [MaxLength(2048)] public string? VideoUrl { get; set; } [MaxLength(255)] public string? PhoneNumber { get; set; } [MaxLength(255)] public string? Email { get; set; } diff --git a/backend/src/Web/Features/Contents/Data/Migrations/ContentDbContextModelSnapshot.cs b/backend/src/Web/Features/Contents/Data/Migrations/ContentDbContextModelSnapshot.cs index 6aced8d..3e84c3e 100644 --- a/backend/src/Web/Features/Contents/Data/Migrations/ContentDbContextModelSnapshot.cs +++ b/backend/src/Web/Features/Contents/Data/Migrations/ContentDbContextModelSnapshot.cs @@ -311,8 +311,7 @@ namespace Hutopy.Web.Features.Contents.Data.Migrations b1.Property("Description") .IsRequired() - .HasMaxLength(2000) - .HasColumnType("character varying(2000)"); + .HasColumnType("text"); b1.Property("Email") .HasMaxLength(255) diff --git a/backend/src/Web/Features/Contents/Handlers/ChangePresentationInfos.cs b/backend/src/Web/Features/Contents/Handlers/ChangePresentationInfos.cs index 739461f..c9a880d 100644 --- a/backend/src/Web/Features/Contents/Handlers/ChangePresentationInfos.cs +++ b/backend/src/Web/Features/Contents/Handlers/ChangePresentationInfos.cs @@ -20,7 +20,9 @@ public sealed class ChangePresentationInfosRequestValidator : Validator x.Description) .NotEmpty() - .WithMessage("Description is required"); + .WithMessage("Description is required") + .MaximumLength(2000) + .WithMessage("Description cannot exceed 2000 characters"); RuleFor(x => x.VideoUrl) .Must(url => url == null || YouTubeUrlHelper.IsValidYouTubeUrlOrId(url)) diff --git a/frontend/src/views/creators/AboutCreator.vue b/frontend/src/views/creators/AboutCreator.vue index 2ef8885..8ab3ca0 100644 --- a/frontend/src/views/creators/AboutCreator.vue +++ b/frontend/src/views/creators/AboutCreator.vue @@ -23,6 +23,7 @@ class="w-12 h-12 bg-hutopyPrimary rounded-full flex items-center justify-center shadow-lg" @click="saveChanges()" :title="t('save')" + :disabled="editableDescription.length > 2000" > mdi-check @@ -49,7 +50,7 @@
-

+

{{ description }}

@@ -57,6 +58,11 @@ v-model="editableDescription" class="w-full p-2 py-6" :label="t('creator.sections.about.description')" + :error-messages="descriptionError" + :counter="2000" + :rules="[v => v.length <= 2000 || t('creator.validation.descriptionTooLong')]" + auto-grow + rows="5" variant="outlined">
@@ -140,8 +146,6 @@ const showEditButtons = ref(false); // Variables réactives pour les données const description = ref(""); const videoUrl = ref(""); -const phoneNumber = ref(""); -const email = ref(""); const imageUrls = ref([]); const albumId = ref(null); const originalPhotos = ref([]); @@ -149,9 +153,8 @@ const originalPhotos = ref([]); // Editable fields const editableDescription = ref(""); const editableVideoUrl = ref(""); -const editablePhoneNumber = ref(""); -const editableEmail = ref(""); const videoUrlError = ref(""); +const descriptionError = ref(""); // Computed property to check if there are images const hasImages = computed(() => { @@ -193,8 +196,6 @@ function toggleEditMode() { // Charger les valeurs pour l'édition editableDescription.value = description.value; editableVideoUrl.value = videoUrl.value; - editablePhoneNumber.value = phoneNumber.value; - editableEmail.value = email.value; videoUrlError.value = ""; } } @@ -252,6 +253,12 @@ async function saveChanges() { return; } + // Validate description length + if (editableDescription.value.length > 2000) { + descriptionError.value = t('creator.validation.descriptionTooLong'); + return; + } + // Validate video URL before saving if (!validateVideoUrl(editableVideoUrl.value)) { return; @@ -265,17 +272,13 @@ async function saveChanges() { `/api/creators/${brandingStore.value.id}/presentation-infos`, { description: editableDescription.value || "", - videoUrl: editableVideoUrl.value || "", - phoneNumber: editablePhoneNumber.value || "", - email: editableEmail.value || "" + videoUrl: editableVideoUrl.value || null } ); // Mettre à jour les valeurs locales pour refléter les changements description.value = editableDescription.value; videoUrl.value = extractVideoId(editableVideoUrl.value) || ""; - phoneNumber.value = editablePhoneNumber.value; - email.value = editableEmail.value; // Save album photos if they've changed if (imageUrls.value.length > 0) { @@ -354,8 +357,6 @@ function cancelEdit() { // Restaurer les valeurs d'origine editableDescription.value = description.value; editableVideoUrl.value = videoUrl.value; - editablePhoneNumber.value = phoneNumber.value; - editableEmail.value = email.value; // Désactiver le mode édition isEditMode.value = false; @@ -406,6 +407,16 @@ function cancelEdit() { .contact-item { @apply text-lg text-center mb-2 font-semibold; } + +/* Formatting styles for description */ +.text-justify { + line-height: 1.6; +} + +/* Add some spacing between paragraphs */ +.text-justify p { + margin-bottom: 1rem; +} @@ -419,7 +430,9 @@ function cancelEdit() { "about": { "title": "About", "description": "Description", - "contactInfo": "Contact Information" + "contactInfo": "Contact Information", + "characters": "characters", + "formattingHint": "Tip: Use line breaks and emojis to make your description more engaging!" }, "photos": { "title": "Photos", @@ -432,7 +445,8 @@ function cancelEdit() { "email": "Email" }, "validation": { - "invalidYoutubeUrl": "Please enter a valid YouTube URL or video ID" + "invalidYoutubeUrl": "Please enter a valid YouTube URL or video ID", + "descriptionTooLong": "Description cannot exceed 2000 characters" } } }, @@ -445,7 +459,9 @@ function cancelEdit() { "about": { "title": "À propos", "description": "Description", - "contactInfo": "Informations de contact" + "contactInfo": "Informations de contact", + "characters": "caractères", + "formattingHint": "Astuce : Utilisez des sauts de ligne et des émojis pour rendre votre description plus attrayante !" }, "photos": { "title": "Photos", @@ -458,7 +474,8 @@ function cancelEdit() { "email": "Email" }, "validation": { - "invalidYoutubeUrl": "Veuillez entrer une URL YouTube ou un ID de vidéo valide" + "invalidYoutubeUrl": "Veuillez entrer une URL YouTube ou un ID de vidéo valide", + "descriptionTooLong": "La description ne peut pas dépasser 2000 caractères" } } }, @@ -471,7 +488,9 @@ function cancelEdit() { "about": { "title": "Acerca de", "description": "Descripción", - "contactInfo": "Información de contacto" + "contactInfo": "Información de contacto", + "characters": "caracteres", + "formattingHint": "Consejo: ¡Usa saltos de línea y emojis para hacer tu descripción más atractiva!" }, "photos": { "title": "Fotos", @@ -484,7 +503,8 @@ function cancelEdit() { "email": "Correo electrónico" }, "validation": { - "invalidYoutubeUrl": "Por favor, introduce una URL de YouTube o un ID de video válido" + "invalidYoutubeUrl": "Por favor, introduce una URL de YouTube o un ID de video válido", + "descriptionTooLong": "La descripción no puede exceder los 2000 caracteres" } } } diff --git a/frontend/src/views/profile/ProfilePage.vue b/frontend/src/views/profile/ProfilePage.vue index 799e38a..473a023 100644 --- a/frontend/src/views/profile/ProfilePage.vue +++ b/frontend/src/views/profile/ProfilePage.vue @@ -260,7 +260,7 @@ async function deconfigureStripe() {
- mdi-chevron-right - +