User experience improvements in profile

This commit is contained in:
2025-04-19 03:19:07 -04:00
parent 1c390d3095
commit 98c598f3c6
6 changed files with 60 additions and 28 deletions

View File

@@ -25,7 +25,6 @@
"required": "This field is required", "required": "This field is required",
"invalidEmail": "Invalid email address", "invalidEmail": "Invalid email address",
"invalidPassword": "Invalid password", "invalidPassword": "Invalid password",
"socialNetworks": "Social Networks",
"facebook": "Facebook", "facebook": "Facebook",
"instagram": "Instagram", "instagram": "Instagram",
"linkedin": "LinkedIn", "linkedin": "LinkedIn",

View File

@@ -25,7 +25,6 @@
"required": "Este campo es obligatorio", "required": "Este campo es obligatorio",
"invalidEmail": "Correo electrónico inválido", "invalidEmail": "Correo electrónico inválido",
"invalidPassword": "Contraseña inválida", "invalidPassword": "Contraseña inválida",
"socialNetworks": "Redes Sociales",
"facebook": "Facebook", "facebook": "Facebook",
"instagram": "Instagram", "instagram": "Instagram",
"linkedin": "LinkedIn", "linkedin": "LinkedIn",

View File

@@ -25,7 +25,6 @@
"required": "Ce champ est requis", "required": "Ce champ est requis",
"invalidEmail": "Adresse email invalide", "invalidEmail": "Adresse email invalide",
"invalidPassword": "Mot de passe invalide", "invalidPassword": "Mot de passe invalide",
"socialNetworks": "Réseaux Sociaux",
"facebook": "Facebook", "facebook": "Facebook",
"instagram": "Instagram", "instagram": "Instagram",
"linkedin": "LinkedIn", "linkedin": "LinkedIn",

View File

@@ -1,5 +1,5 @@
<script setup> <script setup>
import {ref, onMounted, onUnmounted} from "vue"; import {ref, onMounted, onUnmounted, computed} from "vue";
import {v7} from "uuid"; import {v7} from "uuid";
import {useClient} from "@/plugins/api.js"; import {useClient} from "@/plugins/api.js";
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
@@ -10,6 +10,10 @@ const props = defineProps({
}, },
creatorNameReservationId: { creatorNameReservationId: {
required: true required: true
},
originalSlug: {
type: String,
default: null
} }
}); });
@@ -27,11 +31,21 @@ const reservationState = ref(null);
// Use the reservationId from props if provided, otherwise generate a new one // Use the reservationId from props if provided, otherwise generate a new one
const reservationId = ref(props.creatorNameReservationId || v7()); const reservationId = ref(props.creatorNameReservationId || v7());
// Check if the current name is the same as the original slug
const isCurrentSlug = computed(() => {
return props.originalSlug && name.value === props.originalSlug;
});
// Ensure we emit the reservationId on mount if we generated a new one // Ensure we emit the reservationId on mount if we generated a new one
onMounted(() => { onMounted(() => {
if (!props.creatorNameReservationId) { if (!props.creatorNameReservationId) {
emits('update:creatorNameReservationId', reservationId.value); emits('update:creatorNameReservationId', reservationId.value);
} }
// If the name is the same as the original slug, set reservation state to "reserved"
if (isCurrentSlug.value) {
reservationState.value = "reserved";
}
}); });
// Request handling // Request handling
@@ -53,6 +67,15 @@ const handleInput = () => {
if (currentName === lastProcessedName) { if (currentName === lastProcessedName) {
return; // Skip if we've already processed this exact name return; // Skip if we've already processed this exact name
} }
// If the name is the same as the original slug, set reservation state to "reserved"
if (props.originalSlug && currentName === props.originalSlug) {
reservationState.value = "reserved";
lastProcessedName = currentName;
emits('update:name', currentName);
return;
}
checkNameAvailability(currentName); checkNameAvailability(currentName);
}, 200); }, 200);
}; };
@@ -141,21 +164,21 @@ onUnmounted(() => {
"en": { "en": {
"creator": { "creator": {
"name": { "name": {
"label": "Page name" "label": "Your creator handle"
} }
} }
}, },
"fr": { "fr": {
"creator": { "creator": {
"name": { "name": {
"label": "Nom de la page" "label": "Votre identifiant de créateur"
} }
} }
}, },
"es": { "es": {
"creator": { "creator": {
"name": { "name": {
"label": "Nombre de la página" "label": "Tu identificador de creador"
} }
} }
} }

View File

@@ -224,6 +224,12 @@ function handleDelete() {
</div> </div>
<div class="content"> <div class="content">
<button class="action" @click="openDialog('ChangeSlugDialog')">
<span class="label">{{ t('handle') }}</span>
<span class="value">@{{ creatorProfileStore.creator.slug }}</span>
<span class="chevron"><v-icon>mdi-chevron-right</v-icon></span>
</button>
<!-- NAME --> <!-- NAME -->
<button class="action" @click="openDialog('ChangeNameDialog')"> <button class="action" @click="openDialog('ChangeNameDialog')">
<span class="label">{{ t('name') }}</span> <span class="label">{{ t('name') }}</span>
@@ -231,12 +237,6 @@ function handleDelete() {
<span class="chevron"><v-icon>mdi-chevron-right</v-icon></span> <span class="chevron"><v-icon>mdi-chevron-right</v-icon></span>
</button> </button>
<button class="action" @click="openDialog('ChangeSlugDialog')">
<span class="label">{{ t('username') }}</span>
<span class="value">@{{ creatorProfileStore.creator.slug }}</span>
<span class="chevron"><v-icon>mdi-chevron-right</v-icon></span>
</button>
<!-- TITLE --> <!-- TITLE -->
<button class="action" @click="openDialog('ChangeTitleDialog')"> <button class="action" @click="openDialog('ChangeTitleDialog')">
<span class="label">{{ t('title') }}</span> <span class="label">{{ t('title') }}</span>
@@ -410,7 +410,10 @@ function handleDelete() {
"deleteWarning": "Are you sure you want to delete your creator page? This action cannot be undone.", "deleteWarning": "Are you sure you want to delete your creator page? This action cannot be undone.",
"restoreWarning": "Are you sure you want to restore your creator page? This will make your page visible again.", "restoreWarning": "Are you sure you want to restore your creator page? This will make your page visible again.",
"deleteCreatorPage": "Delete Creator Page", "deleteCreatorPage": "Delete Creator Page",
"restoreCreatorPage": "Restore Creator Page" "restoreCreatorPage": "Restore Creator Page",
"stripeAccountId": "Stripe Account ID",
"socialNetworks": "Social Networks",
"handle": "Creator Handle"
}, },
"fr": { "fr": {
"personalInfo": "Informations Personnelles", "personalInfo": "Informations Personnelles",
@@ -424,7 +427,10 @@ function handleDelete() {
"deleteWarning": "Êtes-vous sûr de vouloir supprimer votre page de créateur ? Cette action est irréversible.", "deleteWarning": "Êtes-vous sûr de vouloir supprimer votre page de créateur ? Cette action est irréversible.",
"restoreWarning": "Êtes-vous sûr de vouloir restaurer votre page de créateur ? Cela rendra votre page à nouveau visible.", "restoreWarning": "Êtes-vous sûr de vouloir restaurer votre page de créateur ? Cela rendra votre page à nouveau visible.",
"deleteCreatorPage": "Supprimer la Page Créateur", "deleteCreatorPage": "Supprimer la Page Créateur",
"restoreCreatorPage": "Restaurer la Page Créateur" "restoreCreatorPage": "Restaurer la Page Créateur",
"stripeAccountId": "ID de Compte Stripe",
"socialNetworks": "Réseaux Sociaux",
"handle": "Identifiant du créateur"
}, },
"es": { "es": {
"personalInfo": "Información Personal", "personalInfo": "Información Personal",
@@ -438,7 +444,10 @@ function handleDelete() {
"deleteWarning": "¿Estás seguro de que quieres eliminar tu página de creador? Esta acción no se puede deshacer.", "deleteWarning": "¿Estás seguro de que quieres eliminar tu página de creador? Esta acción no se puede deshacer.",
"restoreWarning": "¿Estás seguro de que quieres restaurar tu página de creador? Esto hará que tu página sea visible nuevamente.", "restoreWarning": "¿Estás seguro de que quieres restaurar tu página de creador? Esto hará que tu página sea visible nuevamente.",
"deleteCreatorPage": "Eliminar Página de Creador", "deleteCreatorPage": "Eliminar Página de Creador",
"restoreCreatorPage": "Restaurar Página de Creador" "restoreCreatorPage": "Restaurar Página de Creador",
"stripeAccountId": "ID de Cuenta Stripe",
"socialNetworks": "Redes Sociales",
"handle": "Identificador del creador"
} }
} }
</i18n> </i18n>

View File

@@ -1,5 +1,5 @@
<script setup> <script setup>
import {computed, ref} from 'vue'; import {computed, ref, watch} from 'vue';
import {useCreatorProfileStore} from '@/stores/creatorProfileStore.js'; import {useCreatorProfileStore} from '@/stores/creatorProfileStore.js';
import {useClient} from "@/plugins/api.js"; import {useClient} from "@/plugins/api.js";
import NameEditor from "@/views/creators/NameEditor.vue"; import NameEditor from "@/views/creators/NameEditor.vue";
@@ -21,8 +21,17 @@ const newSlug = ref(props.creator.slug);
const slugReservationId = ref(undefined); const slugReservationId = ref(undefined);
const isOperationPending = ref(false); const isOperationPending = ref(false);
const errorMessage = ref(''); const errorMessage = ref('');
const isCurrentHandle = ref(false);
const canSave = computed(() => slugReservationId.value !== undefined); // Watch for changes to the new slug to check if it's the same as the current one
watch(newSlug, (newValue) => {
isCurrentHandle.value = newValue === props.creator.slug;
if (isCurrentHandle.value) {
slugReservationId.value = undefined;
}
});
const canSave = computed(() => slugReservationId.value !== undefined && !isCurrentHandle.value);
function handleSlugReservationIdChanged($event) { function handleSlugReservationIdChanged($event) {
slugReservationId.value = $event; slugReservationId.value = $event;
@@ -62,14 +71,11 @@ const cancel = () => {
</div> </div>
<div class="card-content"> <div class="card-content">
<p class="mb-4">
{{ t('label') }} <strong>@{{ creator.slug }}</strong>
</p>
<name-editor <name-editor
v-model:name="newSlug" v-model:name="newSlug"
:creator-name-reservation-id="slugReservationId" :creator-name-reservation-id="slugReservationId"
@update:creator-name-reservation-id="handleSlugReservationIdChanged" @update:creator-name-reservation-id="handleSlugReservationIdChanged"
:original-slug="creator.slug"
></name-editor> ></name-editor>
<v-alert <v-alert
@@ -101,16 +107,13 @@ const cancel = () => {
<i18n> <i18n>
{ {
"en": { "en": {
"title": "Change URL", "title": "Change Creator Handle"
"label": "Your current URL is"
}, },
"fr": { "fr": {
"title": "Modifier l'URL", "title": "Modifier l'identifiant du créateur"
"label": "Votre URL actuelle est"
}, },
"es": { "es": {
"title": "Cambiar URL", "title": "Cambiar identificador del creador"
"label": "Tu URL actual es"
} }
} }
</i18n> </i18n>