Compare commits
34 Commits
b607380a68
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 90bf54e991 | |||
| 6885df22e8 | |||
| 84e1ca555c | |||
| 0fc0aa95d3 | |||
| d65fe6e353 | |||
| 021bd8aae2 | |||
| 82fb58c785 | |||
| 52cfe98a1b | |||
| 36f8bac508 | |||
| a04a66a176 | |||
| 6dc8f5c39e | |||
| 8b55efa318 | |||
| 28beddb785 | |||
| 2abfd38dd7 | |||
| 1cdfafc90f | |||
| b3d4e4e565 | |||
| c624b3ccf6 | |||
| 1ec98f2bf3 | |||
| f7715bb494 | |||
| af91640c2b | |||
| 909d49a3e2 | |||
| c6790ed645 | |||
| 78c4e2b46b | |||
| 3b2198598e | |||
| 29aef78804 | |||
| 3a163721f2 | |||
| 54dbc4465d | |||
| 523620be06 | |||
| 2ecaa348da | |||
| 3e55e82fb7 | |||
| bb08a62e5d | |||
| 129da829e7 | |||
| 9b7a8df99a | |||
| f1205a92df |
29
app/app.vue
29
app/app.vue
@@ -1,18 +1,25 @@
|
||||
<template>
|
||||
<v-app>
|
||||
<NavBar />
|
||||
<v-app>
|
||||
<NavBar />
|
||||
|
||||
<!-- Main content of the application -->
|
||||
<v-main>
|
||||
<NuxtPage />
|
||||
<!-- Main content of the application -->
|
||||
<v-main :theme="$vuetify.theme.current.dark ? 'dark' : 'light'">
|
||||
<NuxtPage />
|
||||
</v-main>
|
||||
|
||||
</v-main>
|
||||
|
||||
<AppFooter />
|
||||
|
||||
</v-app>
|
||||
<AppFooter />
|
||||
</v-app>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import { onMounted } from "vue";
|
||||
import { useTheme } from "vuetify";
|
||||
|
||||
const theme = useTheme();
|
||||
|
||||
onMounted(() => {
|
||||
console.log(theme.name);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style></style>
|
||||
|
||||
@@ -1,9 +1,17 @@
|
||||
<!-- Smaller footer at the bottom of the screen -->
|
||||
<template>
|
||||
<v-footer app color="secondary" height="30">
|
||||
<v-container class="text-caption text-center">
|
||||
© {{ new Date().getFullYear() }} SharedLists - All Rights
|
||||
Reserved
|
||||
</v-container>
|
||||
</v-footer>
|
||||
<template>
|
||||
<v-footer
|
||||
app
|
||||
color="secondary"
|
||||
height="30"
|
||||
v-if="status !== 'unauthenticated'"
|
||||
>
|
||||
<v-container class="text-caption text-center">
|
||||
© {{ new Date().getFullYear() }} SharedLists - All Rights Reserved
|
||||
</v-container>
|
||||
</v-footer>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const { status } = useAuth();
|
||||
</script>
|
||||
|
||||
@@ -1,49 +1,95 @@
|
||||
<template>
|
||||
<!-- Toolbar at the top of the screen -->
|
||||
<v-app-bar color="rgba(27, 94, 32, 0.8)" height="48">
|
||||
<!-- Toolbar at the top of the screen -->
|
||||
<v-app-bar
|
||||
app
|
||||
color="primary-darken-1"
|
||||
class="text-white"
|
||||
height="48"
|
||||
v-if="status !== 'unauthenticated'"
|
||||
>
|
||||
<!-- Title of the application with adjusted margin and font size -->
|
||||
<v-app-bar-title class="text-h6 ms-3 text-white">
|
||||
<v-icon icon="mdi-apps" @click="drawer = !drawer"></v-icon>
|
||||
<v-icon
|
||||
color="info"
|
||||
icon="mdi-apps"
|
||||
@click="drawer = !drawer"
|
||||
></v-icon>
|
||||
|
||||
<span class="ms-1 text-white">Listas de Front</span>
|
||||
<span class="ms-1 text-info"
|
||||
>{{ data?.email ? data?.email : "" }} -
|
||||
{{
|
||||
capitalize($route.name) == "Index"
|
||||
? "Listas"
|
||||
: capitalize($route.name)
|
||||
}}</span
|
||||
>
|
||||
</v-app-bar-title>
|
||||
|
||||
<!-- Spacer to push the following elements to the right -->
|
||||
<v-spacer />
|
||||
|
||||
<!-- Menu icons on the right side of the toolbar -->
|
||||
|
||||
|
||||
<template v-slot:append>
|
||||
<v-btn
|
||||
color="info"
|
||||
@click="theme.toggle()"
|
||||
text="Light / Dark"
|
||||
></v-btn>
|
||||
<v-btn icon="mdi-logout" color="warning" @click="logout"> </v-btn>
|
||||
</template>
|
||||
</v-app-bar>
|
||||
|
||||
|
||||
<v-navigation-drawer
|
||||
v-model="drawer"
|
||||
temporary
|
||||
>
|
||||
<v-navigation-drawer v-model="drawer" temporary>
|
||||
<v-list-item
|
||||
prepend-avatar="https://randomuser.me/api/portraits/men/78.jpg"
|
||||
title="John Leider"
|
||||
class="ma-4 ml-8"
|
||||
: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>
|
||||
|
||||
<v-divider></v-divider>
|
||||
|
||||
<v-list density="compact" nav>
|
||||
<v-list-item prepend-icon="mdi-home" title="Home" value="home" @click="navigateTo('/')"></v-list-item>
|
||||
<v-list-item prepend-icon="mdi-login" title="Login" value="login" @click="navigateTo('/login')"></v-list-item>
|
||||
<v-list-item prepend-icon="mdi-account-plus-outline" title="Register" value="register" @click="navigateTo('/register')"></v-list-item>
|
||||
<v-list-item prepend-icon="mdi-lock-reset" title="Forgot" value="forgot" @click="navigateTo('/forgot-password')"></v-list-item>
|
||||
<v-list density="compact" nav active-class="bg-active">
|
||||
<v-list-item
|
||||
:active="$route.name === 'index'"
|
||||
prepend-icon="mdi-home"
|
||||
title="Home"
|
||||
value="home"
|
||||
@click="navigateTo('/')"
|
||||
></v-list-item>
|
||||
<v-list-item
|
||||
:active="$route.name === 'profile'"
|
||||
prepend-icon="mdi-account"
|
||||
title="Profile"
|
||||
value="profile"
|
||||
@click="navigateTo('/profile')"
|
||||
></v-list-item>
|
||||
</v-list>
|
||||
</v-navigation-drawer>
|
||||
|
||||
</v-navigation-drawer>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
// Drawer state to open/close the navigation drawer
|
||||
import { ref, capitalize } from "vue";
|
||||
import { useSystemStore } from "~/stores/system";
|
||||
import { useTheme } from "vuetify";
|
||||
|
||||
const theme = useTheme();
|
||||
const drawer = ref(false);
|
||||
const { data, status, signOut } = useAuth();
|
||||
const systemStore = useSystemStore();
|
||||
|
||||
const logout = async () => {
|
||||
await systemStore.deleteCookies();
|
||||
await signOut({ callbackUrl: "/login" });
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
.bg-active {
|
||||
background-color: grey;
|
||||
color: white !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
import { fa } from "vuetify/locale";
|
||||
|
||||
// file: ~/middleware/authentication.global.ts
|
||||
export default defineNuxtRouteMiddleware(async (to, next) => {
|
||||
export default defineNuxtRouteMiddleware(async (to, from, next) => {
|
||||
const { status } = useAuth();
|
||||
const auth = status.value === "authenticated" ? true : false;
|
||||
const isProtected = (await to.meta.auth) === true ? true : false;
|
||||
if (!auth && isProtected) {
|
||||
console.log("User is not authenticated and page is protected");
|
||||
return navigateTo("/login");
|
||||
// User is not authenticated and page is protected
|
||||
if (from.meta.auth) {
|
||||
//viene de una pagina protegida
|
||||
return navigateTo("/login");
|
||||
} //viene de una pagina no protegida
|
||||
return abortNavigation();
|
||||
} else if (auth && !isProtected) {
|
||||
console.log("User is authenticated and page is not protected");
|
||||
return navigateTo("/");
|
||||
// User is authenticated and page is not protected
|
||||
return abortNavigation();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -1,25 +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"
|
||||
>
|
||||
<img
|
||||
:src="norrisStore.response.icon_url"
|
||||
alt="chuck norris"
|
||||
size="64"
|
||||
/>
|
||||
<div class="mt-3">My Application's Home Page</div>
|
||||
<div>
|
||||
{{ norrisStore.response }}
|
||||
{{ data }}
|
||||
{{ status }}
|
||||
{{ refreshToken }}
|
||||
</div>
|
||||
<div>
|
||||
<v-btn color="primary" @click="refresh">Refresca token</v-btn>
|
||||
</div>
|
||||
<div>
|
||||
<v-btn color="warning" @click="logout">Logout</v-btn>
|
||||
</div>
|
||||
<div class="mt-3">Listas</div>
|
||||
<v-card
|
||||
class="ma-5 mx-auto"
|
||||
v-if="listasStore.listas.length > 0"
|
||||
max-width="100%"
|
||||
width="1000%"
|
||||
>
|
||||
<v-list-item
|
||||
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-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-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></div>
|
||||
</v-container>
|
||||
</template>
|
||||
|
||||
@@ -27,19 +60,18 @@
|
||||
definePageMeta({
|
||||
auth: true,
|
||||
});
|
||||
import { useWindowSize } from "@vueuse/core";
|
||||
const { data } = useAuth();
|
||||
import { ref, onMounted } from "vue";
|
||||
import { useChuckStore } from "~/stores/chuck";
|
||||
import { useSystemStore } from "~/stores/system";
|
||||
const systemStore = useSystemStore();
|
||||
const norrisStore = useChuckStore();
|
||||
const { data, status, refresh, refreshToken, signOut } = useAuth();
|
||||
import { useListasStore } from "~/stores/listas";
|
||||
|
||||
const logout = async () => {
|
||||
await systemStore.deleteCookies();
|
||||
await signOut({ callbackUrl: "/login" });
|
||||
};
|
||||
const listasStore = useListasStore();
|
||||
const systemStore = useSystemStore();
|
||||
const { width, height } = useWindowSize();
|
||||
|
||||
onMounted(async () => {
|
||||
await norrisStore.getData();
|
||||
await listasStore.getData();
|
||||
console.log(listasStore.listas);
|
||||
});
|
||||
</script>
|
||||
|
||||
134
app/pages/profile.vue
Normal file
134
app/pages/profile.vue
Normal file
@@ -0,0 +1,134 @@
|
||||
<template>
|
||||
<v-container
|
||||
v-if="data"
|
||||
class="fill-height d-flex align-center justify-center text-center"
|
||||
>
|
||||
<div class="full-height flex-column mr-5">
|
||||
<v-avatar class="ma-10" color="primary" size="170">
|
||||
<v-img
|
||||
:width="200"
|
||||
aspect-ratio="16/9"
|
||||
cover
|
||||
:src="data.image"
|
||||
:alt="data.name"
|
||||
></v-img>
|
||||
</v-avatar>
|
||||
|
||||
<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="limpiar_input"
|
||||
clearable
|
||||
/><v-btn
|
||||
color="secundary"
|
||||
:disabled="files.length <= 0 || !validateFileType()"
|
||||
@click="uploadImage"
|
||||
>
|
||||
Button
|
||||
</v-btn>
|
||||
</div>
|
||||
<div class="full-height flex-column">
|
||||
<h3>Último login:</h3>
|
||||
<p>{{ data.last_login ? data.last_login : "Nunca" }}</p>
|
||||
<h3>Username:</h3>
|
||||
<p>{{ data.username }}</p>
|
||||
<h3>Nombre:</h3>
|
||||
<p>{{ data.name }}</p>
|
||||
<h3>Apellidos:</h3>
|
||||
<p>{{ data.last_name }}</p>
|
||||
<h3>Correo:</h3>
|
||||
<p>{{ data.email }}</p>
|
||||
<h3>Listas:</h3>
|
||||
|
||||
<p>
|
||||
{{
|
||||
listasStore.listas.length ? listasStore.listas.length : "0"
|
||||
}}
|
||||
</p>
|
||||
</div>
|
||||
</v-container>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
definePageMeta({
|
||||
auth: true,
|
||||
});
|
||||
const { data, token, getSession } = useAuth();
|
||||
import { ref, onMounted } from "vue";
|
||||
import { useSystemStore } from "~/stores/system";
|
||||
import { useListasStore } from "~/stores/listas";
|
||||
const listasStore = useListasStore();
|
||||
const systemStore = useSystemStore();
|
||||
const { handleFileInput, files } = useFileStorage();
|
||||
let imagen = ref([]);
|
||||
|
||||
const uploadImage = async () => {
|
||||
const url = "http://" + systemStore.url_backend + "/auth/users/me/";
|
||||
let formData = new FormData();
|
||||
|
||||
formData.append("username", data.value.username);
|
||||
formData.append("email", data.value.email);
|
||||
formData.append("name", data.value.name);
|
||||
formData.append("last_name", data.value.last_name);
|
||||
formData.append("image", imagen.value ? imagen.value : null);
|
||||
|
||||
const response = await $fetch(url, {
|
||||
headers: {
|
||||
Authorization: `${token.value}`,
|
||||
},
|
||||
method: "PUT",
|
||||
body: formData,
|
||||
});
|
||||
if (response) {
|
||||
//imagenVista.value = response.image;
|
||||
files.value.pop();
|
||||
if (imagen.value != null) {
|
||||
imagen.value = null;
|
||||
}
|
||||
await getSession();
|
||||
} else {
|
||||
console.error(response);
|
||||
}
|
||||
};
|
||||
|
||||
const validateFileType = () => {
|
||||
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;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const validateTamanyo = () => {
|
||||
//TODO validar tamaño
|
||||
};
|
||||
|
||||
const openImageDialog = () => {
|
||||
// TODO Implement image dialog logic
|
||||
};
|
||||
|
||||
const limpiar_input = () => {
|
||||
imagen.value = null;
|
||||
files.value.pop();
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
await listasStore.getData();
|
||||
});
|
||||
</script>
|
||||
@@ -1,7 +1,149 @@
|
||||
import { createVuetify } from "vuetify";
|
||||
import * as components from "vuetify/components";
|
||||
import * as directives from "vuetify/directives";
|
||||
|
||||
const lightTheme = {
|
||||
dark: false,
|
||||
colors: {
|
||||
background: "#F8FAF7",
|
||||
surface: "#FFFFFF",
|
||||
primary: "#88D8B0",
|
||||
"primary-darken-1": "#6BC49A",
|
||||
secondary: "#C8E6C9",
|
||||
"secondary-darken-1": "#A5D6A7",
|
||||
accent: "#D4EDDA",
|
||||
error: "#FF9A8B",
|
||||
info: "#B3E0FF",
|
||||
success: "#A5D6A7",
|
||||
warning: "#FFE0B2",
|
||||
"on-primary": "#2E3A32",
|
||||
"on-surface": "#2E3A32",
|
||||
},
|
||||
variables: {
|
||||
"border-color": "#E0E0E0",
|
||||
"border-opacity": 0.12,
|
||||
},
|
||||
};
|
||||
|
||||
const darkTheme = {
|
||||
dark: true,
|
||||
colors: {
|
||||
background: "#121F17",
|
||||
surface: "#1E2922",
|
||||
primary: "#4A7856",
|
||||
"primary-darken-1": "#3A6A46",
|
||||
secondary: "#3D5A45",
|
||||
"secondary-darken-1": "#2D4A35",
|
||||
accent: "#5D8C6C",
|
||||
error: "#D32F2F",
|
||||
info: "#2196F3",
|
||||
success: "#4CAF50",
|
||||
warning: "#FFA000",
|
||||
"on-primary": "#E8F5E9",
|
||||
"on-surface": "#E0E0E0",
|
||||
},
|
||||
variables: {
|
||||
"border-color": "#37474F",
|
||||
"border-opacity": 0.24,
|
||||
},
|
||||
};
|
||||
|
||||
const minimalLightTheme = {
|
||||
dark: false,
|
||||
colors: {
|
||||
background: "#FFFFFF",
|
||||
surface: "#F5F5F5",
|
||||
primary: "#7C90DB", // Azul suave
|
||||
"primary-darken-1": "#6A7EC9",
|
||||
secondary: "#E0E0E0", // Gris neutro
|
||||
"secondary-darken-1": "#C7C7C7",
|
||||
accent: "#A5C4D4", // Azul pastel
|
||||
error: "#FF6B6B", // Rojo coral suave
|
||||
info: "#88C9F2",
|
||||
success: "#77DD77", // Verde menta
|
||||
warning: "#FFD166", // Amarillo pastel
|
||||
"on-primary": "#2D3748", // Gris oscuro
|
||||
"on-surface": "#2D3748",
|
||||
},
|
||||
variables: {
|
||||
"border-color": "#E2E8F0",
|
||||
"border-opacity": 0.16,
|
||||
},
|
||||
};
|
||||
|
||||
const minimalDarkTheme = {
|
||||
dark: true,
|
||||
colors: {
|
||||
background: "#1E2B3A",
|
||||
surface: "#2C3E50",
|
||||
primary: "#8A9EFF", // Azul lavanda (inalterado)
|
||||
"primary-darken-1": "#778CEB",
|
||||
secondary: "#4A5568", // Gris azulado (reemplaza grises neutros)
|
||||
"secondary-darken-1": "#3C4758",
|
||||
accent: "#A7BED3", // Azul polvo (inalterado)
|
||||
error: "#FF8A8A",
|
||||
info: "#90CAF9",
|
||||
success: "#81C784",
|
||||
warning: "#FFD54F",
|
||||
"on-primary": "#F7FAFC", // Blanco casi puro (mejor contraste)
|
||||
"on-surface": "#E2E8F0", // Gris claro azulado
|
||||
},
|
||||
variables: {
|
||||
"border-color": "#4A5568", // Coordinado con secondary
|
||||
"border-opacity": 0.3,
|
||||
},
|
||||
};
|
||||
|
||||
const softDarkTheme = {
|
||||
dark: true,
|
||||
colors: {
|
||||
background: "#2C3E50", // Gris-azul medio (como cielo nocturno)
|
||||
surface: "#34495E", // 15% más claro que el fondo
|
||||
primary: "#7F9CF5", // Azul lavanda más claro
|
||||
"primary-darken-1": "#6B8BEA",
|
||||
secondary: "#4B5563", // Gris neutro cálido
|
||||
"secondary-darken-1": "#3E4A5A",
|
||||
accent: "#94A3B8", // Gris-azul claro (para detalles)
|
||||
error: "#FCA5A5", // Rojo suave
|
||||
info: "#93C5FD", // Azul cielo
|
||||
success: "#86EFAC", // Verde menta claro
|
||||
warning: "#FCD34D", // Amarillo miel
|
||||
"on-primary": "#F8FAFC", // Blanco niebla
|
||||
"on-surface": "#E5E7EB", // Gris muy claro
|
||||
},
|
||||
variables: {
|
||||
"border-color": "#475569", // Borde sutil
|
||||
"border-opacity": 0.25,
|
||||
},
|
||||
};
|
||||
|
||||
export default defineNuxtPlugin((nuxtApp) => {
|
||||
const vuetify = createVuetify({ components });
|
||||
const vuetify = createVuetify({
|
||||
components,
|
||||
directives,
|
||||
theme: {
|
||||
defaultTheme: "light",
|
||||
themes: {
|
||||
light: minimalLightTheme,
|
||||
dark: softDarkTheme,
|
||||
},
|
||||
variations: {
|
||||
colors: ["primary", "secondary"],
|
||||
lighten: 2,
|
||||
darken: 2,
|
||||
},
|
||||
},
|
||||
defaults: {
|
||||
VBtn: {
|
||||
color: "primary",
|
||||
variant: "flat",
|
||||
},
|
||||
VCard: {
|
||||
elevation: 1,
|
||||
rounded: "lg",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
nuxtApp.vueApp.use(vuetify);
|
||||
});
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
import { defineStore } from "pinia";
|
||||
|
||||
export const useChuckStore = defineStore("chuckNorris", {
|
||||
state: () => ({
|
||||
response: "",
|
||||
}),
|
||||
actions: {
|
||||
async getData() {
|
||||
const response = await fetch("https://api.chucknorris.io/jokes/random");
|
||||
const data = await response.json();
|
||||
this.response = data;
|
||||
},
|
||||
},
|
||||
});
|
||||
20
app/stores/listas.js
Normal file
20
app/stores/listas.js
Normal file
@@ -0,0 +1,20 @@
|
||||
import { defineStore } from "pinia";
|
||||
const { token } = useAuth();
|
||||
|
||||
export const useListasStore = defineStore("listas", {
|
||||
state: () => ({
|
||||
listas: [],
|
||||
}),
|
||||
actions: {
|
||||
async getData() {
|
||||
const response = await fetch("http://127.0.0.1:8000/lista/", {
|
||||
method: "GET",
|
||||
headers: {
|
||||
Authorization: `${token.value}`,
|
||||
},
|
||||
});
|
||||
const data = await response.json();
|
||||
this.listas = data;
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -3,7 +3,10 @@ export default defineNuxtConfig({
|
||||
compatibilityDate: "2025-07-15",
|
||||
ssr: false,
|
||||
devtools: { enabled: false },
|
||||
modules: ["@pinia/nuxt", "@sidebase/nuxt-auth"],
|
||||
modules: ["@pinia/nuxt", "@sidebase/nuxt-auth", "nuxt-file-storage"],
|
||||
fileStorage: {
|
||||
mount: "/home/clonbg/Programar/git/curso_django/listas_rest/media/media",
|
||||
},
|
||||
runtimeConfig: {
|
||||
baseURL: "http://localhost:3000",
|
||||
},
|
||||
|
||||
99
package-lock.json
generated
99
package-lock.json
generated
@@ -10,11 +10,15 @@
|
||||
"@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",
|
||||
"vue-router": "^4.5.1",
|
||||
"vuetify": "^3.9.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"nuxt-file-storage": "^0.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@ampproject/remapping": {
|
||||
@@ -3871,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",
|
||||
@@ -4295,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",
|
||||
@@ -8564,6 +8612,51 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/nuxt-file-storage": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/nuxt-file-storage/-/nuxt-file-storage-0.3.0.tgz",
|
||||
"integrity": "sha512-5Ey04J0vnNhdeopqIempv2dM9VKvNuCj68qokyJKEno9Dy1MS2lUWNew1djxr2s+5pMm6TLLXzfqku0yLcRtvg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@nuxt/kit": "^3.15.4",
|
||||
"defu": "^6.1.4"
|
||||
}
|
||||
},
|
||||
"node_modules/nuxt-file-storage/node_modules/@nuxt/kit": {
|
||||
"version": "3.18.1",
|
||||
"resolved": "https://registry.npmjs.org/@nuxt/kit/-/kit-3.18.1.tgz",
|
||||
"integrity": "sha512-z6w1Fzv27CIKFlhct05rndkJSfoslplWH5fJ9dtusEvpYScLXp5cATWIbWkte9e9zFSmQTgDQJjNs3geQHE7og==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"c12": "^3.2.0",
|
||||
"consola": "^3.4.2",
|
||||
"defu": "^6.1.4",
|
||||
"destr": "^2.0.5",
|
||||
"errx": "^0.1.0",
|
||||
"exsolve": "^1.0.7",
|
||||
"ignore": "^7.0.5",
|
||||
"jiti": "^2.5.1",
|
||||
"klona": "^2.0.6",
|
||||
"knitwork": "^1.2.0",
|
||||
"mlly": "^1.7.4",
|
||||
"ohash": "^2.0.11",
|
||||
"pathe": "^2.0.3",
|
||||
"pkg-types": "^2.2.0",
|
||||
"scule": "^1.3.0",
|
||||
"semver": "^7.7.2",
|
||||
"std-env": "^3.9.0",
|
||||
"tinyglobby": "^0.2.14",
|
||||
"ufo": "^1.6.1",
|
||||
"unctx": "^2.4.1",
|
||||
"unimport": "^5.2.0",
|
||||
"untyped": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/nypm": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/nypm/-/nypm-0.6.1.tgz",
|
||||
@@ -10993,9 +11086,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/tmp": {
|
||||
"version": "0.2.3",
|
||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz",
|
||||
"integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==",
|
||||
"version": "0.2.5",
|
||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz",
|
||||
"integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=14.14"
|
||||
|
||||
@@ -13,10 +13,14 @@
|
||||
"@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",
|
||||
"vue-router": "^4.5.1",
|
||||
"vuetify": "^3.9.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"nuxt-file-storage": "^0.3.0"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user