diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..d48f257 --- /dev/null +++ b/.env.example @@ -0,0 +1 @@ +NUXT_PUBLIC_API_BASE_URL=http://localhost:3000 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..720eeb0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +node_modules/ +.nuxt/ +.output/ +.env +dist/ +coverage/ diff --git a/app.vue b/app.vue new file mode 100644 index 0000000..62cd98b --- /dev/null +++ b/app.vue @@ -0,0 +1,6 @@ + diff --git a/middleware/auth.ts b/middleware/auth.ts new file mode 100644 index 0000000..f558d49 --- /dev/null +++ b/middleware/auth.ts @@ -0,0 +1,6 @@ +import { useAuthStore } from '~/stores/auth'; + +export default defineNuxtRouteMiddleware(() => { + const auth = useAuthStore(); + if (!auth.isAuthenticated) return navigateTo('/login'); +}); diff --git a/nuxt.config.ts b/nuxt.config.ts new file mode 100644 index 0000000..7c11e34 --- /dev/null +++ b/nuxt.config.ts @@ -0,0 +1,9 @@ +export default defineNuxtConfig({ + devtools: { enabled: true }, + modules: ['@nuxtjs/tailwindcss', '@pinia/nuxt'], + runtimeConfig: { + public: { + apiBaseUrl: '', // set via NUXT_PUBLIC_API_BASE_URL + }, + }, +}) diff --git a/package.json b/package.json new file mode 100644 index 0000000..b572b4a --- /dev/null +++ b/package.json @@ -0,0 +1,27 @@ +{ + "name": "nest-intranet", + "version": "0.0.1", + "private": true, + "scripts": { + "build": "nuxt build", + "dev": "nuxt dev", + "generate": "nuxt generate", + "preview": "nuxt preview", + "test": "vitest run", + "test:watch": "vitest", + "test:update": "vitest --update-snapshots" + }, + "dependencies": { + "@pinia/nuxt": "^0.10.0", + "nuxt": "^3.15.0", + "pinia": "^2.3.0", + "vue": "^3.5.0" + }, + "devDependencies": { + "@nuxt/test-utils": "^3.15.0", + "@nuxtjs/tailwindcss": "^6.13.0", + "@vitest/coverage-v8": "^3.0.0", + "typescript": "^5.7.0", + "vitest": "^3.0.0" + } +} diff --git a/pages/dashboard.vue b/pages/dashboard.vue new file mode 100644 index 0000000..0ba8e06 --- /dev/null +++ b/pages/dashboard.vue @@ -0,0 +1,9 @@ + + + diff --git a/pages/login.vue b/pages/login.vue new file mode 100644 index 0000000..3622516 --- /dev/null +++ b/pages/login.vue @@ -0,0 +1,46 @@ + + + diff --git a/stores/auth.ts b/stores/auth.ts new file mode 100644 index 0000000..4807398 --- /dev/null +++ b/stores/auth.ts @@ -0,0 +1,31 @@ +import { defineStore } from 'pinia'; + +interface AuthUser { + id: string; + email: string; + username: string; + role: 'ADMIN' | 'DEV' | 'MEMBER'; +} + +export const useAuthStore = defineStore('auth', () => { + const user = ref(null); + const token = ref(null); + const isAuthenticated = computed(() => !!token.value); + + async function login(credentials: { email: string; password: string }) { + const config = useRuntimeConfig(); + const data = await $fetch<{ token: string; user: AuthUser }>( + `${config.public.apiBaseUrl}/auth/login`, + { method: 'POST', body: credentials }, + ); + token.value = data.token; + user.value = data.user; + } + + function logout() { + token.value = null; + user.value = null; + } + + return { user, token, isAuthenticated, login, logout }; +}); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..4b34df1 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "./.nuxt/tsconfig.json" +} diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 0000000..b519c1f --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,7 @@ +import { defineVitestConfig } from '@nuxt/test-utils/config'; + +export default defineVitestConfig({ + test: { + environment: 'nuxt', + }, +});