feat(creator): allow text for description

This commit is contained in:
2025-04-25 01:22:11 -04:00
parent dcd4ec3b75
commit 57fbbf17a5
5 changed files with 47 additions and 26 deletions

View File

@@ -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; }

View File

@@ -311,8 +311,7 @@ namespace Hutopy.Web.Features.Contents.Data.Migrations
b1.Property<string>("Description")
.IsRequired()
.HasMaxLength(2000)
.HasColumnType("character varying(2000)");
.HasColumnType("text");
b1.Property<string>("Email")
.HasMaxLength(255)

View File

@@ -20,7 +20,9 @@ public sealed class ChangePresentationInfosRequestValidator : Validator<ChangePr
RuleFor(x => 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))

View File

@@ -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"
>
<v-icon large>mdi-check</v-icon>
</button>
@@ -49,7 +50,7 @@
<!-- Description Section -->
<div>
<div v-if="!isEditMode">
<p v-if="description" class="text-lg text-justify mb-6">
<p v-if="description" class="text-lg text-justify mb-6 whitespace-pre-line">
{{ description }}
</p>
</div>
@@ -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"></v-textarea>
</div>
@@ -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;
}
</style>
<i18n>
@@ -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"
}
}
}

View File

@@ -260,7 +260,7 @@ async function deconfigureStripe() {
</div>
<div class="content">
<button class="action" @click="openDialog('ChangeSlugDialog')">
<div class="action" @click="openDialog('ChangeSlugDialog')">
<span class="label">{{ t('handle') }}</span>
<span class="value">{{ baseURL }}/@{{ creatorProfileStore.creator.slug }}</span>
<button
@@ -272,7 +272,7 @@ async function deconfigureStripe() {
<v-icon>{{ copySuccess ? 'mdi-check' : 'mdi-content-copy' }}</v-icon>
</button>
<span class="chevron"><v-icon>mdi-chevron-right</v-icon></span>
</button>
</div>
<!-- NAME -->
<button class="action" @click="openDialog('ChangeNameDialog')">