Compare commits

...

7 Commits

Author SHA1 Message Date
90bf54e991 Update list display layout and responsiveness 2025-08-31 18:12:34 +02:00
6885df22e8 Add @vueuse/core dependency 2025-08-31 18:12:19 +02:00
84e1ca555c Add default avatar for users without profile image 2025-08-16 15:58:10 +02:00
0fc0aa95d3 Add error handling to login and improve user profile
The login changes add try/catch error handling with a user-friendly
message, while the profile page now displays first and last names
separately. Also includes a fix for optional chaining in index.vue.
2025-08-16 15:07:09 +02:00
d65fe6e353 Fix image upload validation and clearing 2025-08-16 12:56:58 +02:00
021bd8aae2 Enhance list items UI and progress display 2025-08-16 12:00:33 +02:00
82fb58c785 Add user email and improve nav title formatting 2025-08-16 12:00:18 +02:00
6 changed files with 134 additions and 43 deletions

View File

@@ -15,8 +15,13 @@
@click="drawer = !drawer"
></v-icon>
<span class="ms-1 text-warning"
>Listas de Front - {{ capitalize($route.name) }}</span
<span class="ms-1 text-info"
>{{ data?.email ? data?.email : "" }} -
{{
capitalize($route.name) == "Index"
? "Listas"
: capitalize($route.name)
}}</span
>
</v-app-bar-title>
@@ -37,7 +42,11 @@
<v-navigation-drawer v-model="drawer" temporary>
<v-list-item
class="ma-4 ml-8"
:prepend-avatar="data && data.image ? data.image : ''"
:prepend-avatar="
data && data.image
? data.image
: 'https://cdn.vuetifyjs.com/images/logos/v-alt.svg'
"
:title="data && data.name ? data.name : ''"
></v-list-item>

View File

@@ -123,11 +123,16 @@ const passwordRules = [
"La contraseña debe tener al menos 5 caracteres",
];
// TODO - cuando hace login cambiar el último login del usuario
const login = async () => {
await signIn(
{ username: "admin", password: "admin" },
{ callbackUrl: "/" },
);
try {
await signIn(
{ username: "joseko", password: "kpdrlp00" },
{ callbackUrl: "/" },
);
} catch (error) {
alert("Ha ocurrido un error. Comprueba tus credenciales");
}
};
</script>

View File

@@ -1,38 +1,58 @@
<template>
<v-container
class="fill-height d-flex flex-column align-center justify-center text-center"
class="d-flex flex-column align-center justify-center text-center"
>
<div class="mt-3">My Application's Home Page</div>
<div class="mt-3">Listas</div>
<v-card
class="mx-auto"
class="ma-5 mx-auto"
v-if="listasStore.listas.length > 0"
min-width="50vw"
max-width="100%"
width="1000%"
>
<v-list-item
class="text-black bg-primary"
class="text-black ma-10 pa-5 rounded-lg full-height flex-column"
:class="
lista.owner == data?.email
? 'bg-green-lighten-2'
: 'bg-green-darken-1'
"
v-for="lista in listasStore.listas"
:key="lista.id"
:subtitle="lista.descripcion"
:title="lista.name"
>
<template v-slot:prepend>
<v-avatar color="grey-lighten-1">
<v-icon color="white">mdi-account</v-icon>
</v-avatar>
<template v-slot:prepend v-if="width > 600">
<div class="d-flex flex-column full-height">
<small class="ml-2 text-red">{{ lista.owner }}</small>
<template v-if="lista.sharedListas.length > 0">
<small
v-for="shared in lista.sharedListas"
:key="shared"
class="ml-2 text-orange-darken-3"
>{{ shared }}</small
></template
>
</div>
</template>
<!-- TODO template número de compartidos -->
<template v-slot:append>
<v-btn
color="grey-lighten-1"
icon="mdi-information"
variant="text"
></v-btn>
<v-badge
class="mr-3"
location="top right"
color="grey-lighten-2"
:content="`${lista.countItems}/${lista.completedItems}`"
>
<v-btn
color="black"
icon="mdi-counter"
variant="text"
></v-btn>
</v-badge>
</template> </v-list-item
></v-card>
<div>
{{ listasStore.listas }}
{{ data }}
</div>
<div></div>
</v-container>
</template>
@@ -40,6 +60,7 @@
definePageMeta({
auth: true,
});
import { useWindowSize } from "@vueuse/core";
const { data } = useAuth();
import { ref, onMounted } from "vue";
import { useSystemStore } from "~/stores/system";
@@ -47,8 +68,10 @@ import { useListasStore } from "~/stores/listas";
const listasStore = useListasStore();
const systemStore = useSystemStore();
const { width, height } = useWindowSize();
onMounted(async () => {
await listasStore.getData();
console.log(listasStore.listas);
});
</script>

View File

@@ -14,14 +14,13 @@
></v-img>
</v-avatar>
//No funciona $clear
<v-file-input
accept="image/apng, image/avif, image/gif, image/jpeg, image/png, image/svg+xml, image/webp"
label="Subir imagen"
@input="handleFileInput"
type="file"
v-model="imagen"
click:clear="$clear"
click:clear="limpiar_input"
clearable
/><v-btn
color="secundary"
@@ -37,7 +36,9 @@
<h3>Username:</h3>
<p>{{ data.username }}</p>
<h3>Nombre:</h3>
<p>{{ data.name }} {{ data.last_name }}</p>
<p>{{ data.name }}</p>
<h3>Apellidos:</h3>
<p>{{ data.last_name }}</p>
<h3>Correo:</h3>
<p>{{ data.email }}</p>
<h3>Listas:</h3>
@@ -94,21 +95,23 @@ const uploadImage = async () => {
};
const validateFileType = () => {
var fileName = imagen.value.name;
var idxDot = fileName.lastIndexOf(".") + 1;
var extFile = fileName.substr(idxDot, fileName.length).toLowerCase();
if (
extFile == "jpg" ||
extFile == "jpeg" ||
extFile == "png" ||
extFile == "gif"
) {
return true;
} else {
alert("Only jpg, jpeg, png and gif files are allowed!");
files.value.pop();
imagen.value = null;
return false;
if (imagen.value != null) {
var fileName = imagen.value.name;
var idxDot = fileName.lastIndexOf(".") + 1;
var extFile = fileName.substr(idxDot, fileName.length).toLowerCase();
if (
extFile == "jpg" ||
extFile == "jpeg" ||
extFile == "png" ||
extFile == "gif"
) {
return true;
} else {
alert("Only jpg, jpeg, png and gif files are allowed!");
files.value.pop();
imagen.value = null;
return false;
}
}
};
@@ -120,6 +123,11 @@ const openImageDialog = () => {
// TODO Implement image dialog logic
};
const limpiar_input = () => {
imagen.value = null;
files.value.pop();
};
onMounted(async () => {
await listasStore.getData();
});

45
package-lock.json generated
View File

@@ -10,6 +10,7 @@
"@mdi/font": "^7.4.47",
"@pinia/nuxt": "^0.11.2",
"@sidebase/nuxt-auth": "^1.0.1",
"@vueuse/core": "^13.8.0",
"nuxt": "^4.0.1",
"pinia": "^3.0.3",
"vue": "^3.5.18",
@@ -3874,6 +3875,12 @@
"integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==",
"license": "MIT"
},
"node_modules/@types/web-bluetooth": {
"version": "0.0.21",
"resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz",
"integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==",
"license": "MIT"
},
"node_modules/@types/yauzl": {
"version": "2.10.3",
"resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz",
@@ -4298,6 +4305,44 @@
"integrity": "sha512-cZy8Dq+uuIXbxCZpuLd2GJdeSO/lIzIspC2WtkqIpje5QyFbvLaI5wZtdUjLHjGZrlVX6GilejatWwVYYRc8tA==",
"license": "MIT"
},
"node_modules/@vueuse/core": {
"version": "13.8.0",
"resolved": "https://registry.npmjs.org/@vueuse/core/-/core-13.8.0.tgz",
"integrity": "sha512-rmBcgpEpxY0ZmyQQR94q1qkUcHREiLxQwNyWrtjMDipD0WTH/JBcAt0gdcn2PsH0SA76ec291cHFngmyaBhlxA==",
"license": "MIT",
"dependencies": {
"@types/web-bluetooth": "^0.0.21",
"@vueuse/metadata": "13.8.0",
"@vueuse/shared": "13.8.0"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"vue": "^3.5.0"
}
},
"node_modules/@vueuse/metadata": {
"version": "13.8.0",
"resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-13.8.0.tgz",
"integrity": "sha512-BYMp3Gp1kBUPv7AfQnJYP96mkX7g7cKdTIgwv/Jgd+pfQhz678naoZOAcknRtPLP4cFblDDW7rF4e3KFa+PfIA==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@vueuse/shared": {
"version": "13.8.0",
"resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-13.8.0.tgz",
"integrity": "sha512-x4nfM0ykW+RmNJ4/1IzZsuLuWWrNTxlTWUiehTGI54wnOxIgI9EDdu/O5S77ac6hvQ3hk2KpOVFHaM0M796Kbw==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"vue": "^3.5.0"
}
},
"node_modules/@whatwg-node/disposablestack": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/@whatwg-node/disposablestack/-/disposablestack-0.0.6.tgz",

View File

@@ -13,6 +13,7 @@
"@mdi/font": "^7.4.47",
"@pinia/nuxt": "^0.11.2",
"@sidebase/nuxt-auth": "^1.0.1",
"@vueuse/core": "^13.8.0",
"nuxt": "^4.0.1",
"pinia": "^3.0.3",
"vue": "^3.5.18",