Compare commits
8 Commits
5d080bba47
...
0.1.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
84c9552b1b | ||
| ed2dff4cda | |||
|
|
4e6cb4a350 | ||
|
|
ca50a353e2 | ||
| ecc78ab1b3 | |||
|
|
84c0668eae | ||
| aa399bf035 | |||
| 7bc6ac89f0 |
36
CHANGELOG.md
Normal file
36
CHANGELOG.md
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
## 0.0.0 (2025-12-07)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* FRO-16 Switch to Quasar ([#1](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Frontend/issues/1)) ([7bc6ac8](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Frontend/commit/7bc6ac89f01df9a6bd5ec236d79041772839d907))
|
||||||
|
## 0.0.0 (2025-12-07)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* FRO-16 Switch to Quasar ([#1](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Frontend/issues/1)) ([7bc6ac8](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Frontend/commit/7bc6ac89f01df9a6bd5ec236d79041772839d907))
|
||||||
|
* FRO-28 Integrate Frontend Build as a seperate image ([#2](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Frontend/issues/2)) ([aa399bf](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Frontend/commit/aa399bf035d4c0f2702c2adf296865ec99e03fbb))
|
||||||
|
## 0.0.0 (2025-12-07)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* FRO-16 Switch to Quasar ([#1](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Frontend/issues/1)) ([7bc6ac8](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Frontend/commit/7bc6ac89f01df9a6bd5ec236d79041772839d907))
|
||||||
|
* FRO-28 Integrate Frontend Build as a seperate image ([#2](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Frontend/issues/2)) ([aa399bf](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Frontend/commit/aa399bf035d4c0f2702c2adf296865ec99e03fbb))
|
||||||
|
## 0.0.0 (2025-12-07)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* FRO-16 Switch to Quasar ([#1](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Frontend/issues/1)) ([7bc6ac8](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Frontend/commit/7bc6ac89f01df9a6bd5ec236d79041772839d907))
|
||||||
|
* FRO-28 Integrate Frontend Build as a seperate image ([#2](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Frontend/issues/2)) ([aa399bf](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Frontend/commit/aa399bf035d4c0f2702c2adf296865ec99e03fbb))
|
||||||
|
## 0.0.0 (2025-12-07)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* FRO-16 Switch to Quasar ([#1](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Frontend/issues/1)) ([7bc6ac8](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Frontend/commit/7bc6ac89f01df9a6bd5ec236d79041772839d907))
|
||||||
|
* FRO-28 Integrate Frontend Build as a seperate image ([#2](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Frontend/issues/2)) ([aa399bf](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Frontend/commit/aa399bf035d4c0f2702c2adf296865ec99e03fbb))
|
||||||
|
## [0.0.0](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Frontend/compare/0.1.0...0.0.0) (2025-12-07)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* FRO-28 Integrate Frontend Build as a seperate image ([#3](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Frontend/issues/3)) ([ecc78ab](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Frontend/commit/ecc78ab1b3772bffbae62a7b926cfc0ca8be4ff4))
|
||||||
|
## [0.0.0](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Frontend/compare/0.1.1...0.0.0) (2025-12-07)
|
||||||
|
## [0.0.0](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Frontend/compare/0.1.2...0.0.0) (2025-12-08)
|
||||||
24
Dockerfile
Normal file
24
Dockerfile
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
FROM node:lts-alpine3.23 AS builder
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY package*.json ./
|
||||||
|
COPY pnpm-lock.yaml* yarn.lock* ./
|
||||||
|
|
||||||
|
RUN npm install
|
||||||
|
COPY . .
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
FROM nginx:stable-alpine AS production
|
||||||
|
|
||||||
|
RUN apk add --no-cache gettext
|
||||||
|
|
||||||
|
RUN rm -rf /usr/share/nginx/html/*
|
||||||
|
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||||
|
|
||||||
|
COPY public/env.template.js /usr/share/nginx/html/env.template.js
|
||||||
|
COPY docker-entrypoint.sh /docker-entrypoint.sh
|
||||||
|
RUN chmod +x /docker-entrypoint.sh
|
||||||
|
|
||||||
|
EXPOSE 80
|
||||||
|
ENTRYPOINT ["/docker-entrypoint.sh"]
|
||||||
19
docker-entrypoint.sh
Normal file
19
docker-entrypoint.sh
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Replace placeholders in env.template.js with environment variables and write env.js
|
||||||
|
TEMPLATE_PATH="/usr/share/nginx/html/env.template.js"
|
||||||
|
TARGET_PATH="/usr/share/nginx/html/env.js"
|
||||||
|
|
||||||
|
if [ -f "$TEMPLATE_PATH" ]; then
|
||||||
|
echo "Rendering runtime config from $TEMPLATE_PATH"
|
||||||
|
# export all variables for envsubst to access
|
||||||
|
# only substitute variables present in the template
|
||||||
|
envsubst < "$TEMPLATE_PATH" > "$TARGET_PATH"
|
||||||
|
else
|
||||||
|
echo "No runtime template found at $TEMPLATE_PATH, skipping"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Start nginx in foreground
|
||||||
|
exec nginx -g 'daemon off;'
|
||||||
|
|
||||||
6
env.d.ts
vendored
6
env.d.ts
vendored
@@ -1 +1,7 @@
|
|||||||
/// <reference types="vite/client" />
|
/// <reference types="vite/client" />
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface Window { __RUNTIME_CONFIG__?: { API_URL?: string } }
|
||||||
|
}
|
||||||
|
|
||||||
|
export {};
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<link rel="icon" href="/favicon.ico">
|
<link rel="icon" href="/favicon.ico">
|
||||||
@@ -8,6 +8,8 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
<!-- runtime config injected at container start -->
|
||||||
|
<script src="/env.js"></script>
|
||||||
<script type="module" src="/src/main.ts"></script>
|
<script type="module" src="/src/main.ts"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
1267
package-lock.json
generated
1267
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -16,13 +16,18 @@
|
|||||||
"format": "prettier --write --experimental-cli src/"
|
"format": "prettier --write --experimental-cli src/"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@quasar/extras": "^1.17.0",
|
||||||
|
"quasar": "^2.18.6",
|
||||||
"vue": "^3.5.25",
|
"vue": "^3.5.25",
|
||||||
"vue-router": "^4.6.3",
|
"vue-router": "^4.6.3",
|
||||||
"tsparticles": "~3.9.1",
|
"tsparticles": "~3.9.1",
|
||||||
"@tsparticles/vue3": "~3.0.1",
|
"@tsparticles/vue3": "~3.0.1",
|
||||||
"bootstrap-vue-next": "~0.40.9"
|
"axios": "^1.13.2",
|
||||||
|
"vue-axios": "^3.5.2",
|
||||||
|
"pinia": "^3.0.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@quasar/vite-plugin": "^1.10.0",
|
||||||
"@tsconfig/node24": "^24.0.3",
|
"@tsconfig/node24": "^24.0.3",
|
||||||
"@types/node": "^24.10.1",
|
"@types/node": "^24.10.1",
|
||||||
"@vitejs/plugin-vue": "^6.0.2",
|
"@vitejs/plugin-vue": "^6.0.2",
|
||||||
@@ -35,6 +40,7 @@
|
|||||||
"jiti": "^2.6.1",
|
"jiti": "^2.6.1",
|
||||||
"npm-run-all2": "^8.0.4",
|
"npm-run-all2": "^8.0.4",
|
||||||
"prettier": "3.6.2",
|
"prettier": "3.6.2",
|
||||||
|
"sass-embedded": "^1.93.3",
|
||||||
"typescript": "~5.9.0",
|
"typescript": "~5.9.0",
|
||||||
"vite": "^7.2.4",
|
"vite": "^7.2.4",
|
||||||
"vite-plugin-vue-devtools": "^8.0.5",
|
"vite-plugin-vue-devtools": "^8.0.5",
|
||||||
|
|||||||
4
public/env.template.js
Normal file
4
public/env.template.js
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
globalThis.__RUNTIME_CONFIG__ = {
|
||||||
|
API_URL: "${API_URL}"
|
||||||
|
};
|
||||||
|
|
||||||
BIN
public/logo.png
Normal file
BIN
public/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
18
src/App.vue
18
src/App.vue
@@ -1,26 +1,22 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { RouterLink, RouterView } from 'vue-router'
|
import { RouterLink, RouterView } from 'vue-router'
|
||||||
import HelloWorld from './components/HelloWorld.vue'
|
import HelloWorld from './components/HelloWorld.vue'
|
||||||
import LoginView from "@/views/LoginView.vue";
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<header>
|
<header>
|
||||||
<img alt="Vue logo" class="logo" src="@/assets/logo.svg" width="125" height="125" />
|
|
||||||
|
|
||||||
<div class="wrapper">
|
<div class="wrapper">
|
||||||
<!-- <HelloWorld msg="You did it!" />-->
|
<HelloWorld msg="You did it!" />
|
||||||
|
|
||||||
<!-- <nav>-->
|
<nav>
|
||||||
<!-- <RouterLink to="/">Home</RouterLink>-->
|
<RouterLink to="/">Home</RouterLink>
|
||||||
<!-- <RouterLink to="/about">About</RouterLink>-->
|
<RouterLink to="/about">About</RouterLink>
|
||||||
<!-- <RouterLink to="/login">Login</RouterLink>-->
|
<RouterLink to="/login">Login</RouterLink>
|
||||||
<!-- </nav>-->
|
</nav>
|
||||||
<LoginView/>
|
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<!-- <RouterView />-->
|
<RouterView />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|||||||
14
src/main.ts
14
src/main.ts
@@ -5,10 +5,24 @@ import App from './App.vue'
|
|||||||
import router from './router'
|
import router from './router'
|
||||||
import Particles from "@tsparticles/vue3";
|
import Particles from "@tsparticles/vue3";
|
||||||
import { loadFull } from "tsparticles";
|
import { loadFull } from "tsparticles";
|
||||||
|
import { Quasar, Notify } from 'quasar'
|
||||||
|
import '@quasar/extras/material-icons/material-icons.css'
|
||||||
|
import 'quasar/dist/quasar.css'
|
||||||
|
import { createPinia } from 'pinia'
|
||||||
|
import axios from 'axios'
|
||||||
|
import VueAxios from 'vue-axios'
|
||||||
|
|
||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
|
const pinia = createPinia()
|
||||||
|
|
||||||
app.use(router)
|
app.use(router)
|
||||||
|
app.use(Quasar, {
|
||||||
|
plugins: {
|
||||||
|
Notify
|
||||||
|
},
|
||||||
|
})
|
||||||
|
app.use(pinia)
|
||||||
|
app.use(VueAxios, axios)
|
||||||
app.use(Particles, {
|
app.use(Particles, {
|
||||||
init: async engine => {
|
init: async engine => {
|
||||||
await loadFull(engine);
|
await loadFull(engine);
|
||||||
|
|||||||
14
src/runtimeConfig.ts
Normal file
14
src/runtimeConfig.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
// runtimeConfig.ts
|
||||||
|
// Reads runtime configuration injected into window.__RUNTIME_CONFIG__ (created by env.js at container start)
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface Window { __RUNTIME_CONFIG__?: { API_URL?: string } }
|
||||||
|
}
|
||||||
|
|
||||||
|
const runtime = (globalThis as any).__RUNTIME_CONFIG__ || {};
|
||||||
|
|
||||||
|
export const API_URL = runtime.API_URL || (import.meta.env.VITE_API_URL as string) || 'http://localhost:9000';
|
||||||
|
|
||||||
|
export function getApiUrl(): string {
|
||||||
|
return API_URL;
|
||||||
|
}
|
||||||
60
src/stores/auth.ts
Normal file
60
src/stores/auth.ts
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
import {type credentials, type token, type user} from '@/types/authTypes'
|
||||||
|
import { defineStore } from 'pinia'
|
||||||
|
import {ref, computed, type Ref} from 'vue'
|
||||||
|
|
||||||
|
export const useAuthStore = defineStore('auth', () => {
|
||||||
|
const user: Ref<user | null> = ref(null)
|
||||||
|
const token = ref(localStorage.getItem('token') || null)
|
||||||
|
|
||||||
|
const isAuthenticated = computed(() => !!token.value)
|
||||||
|
|
||||||
|
async function login(credentials: credentials) {
|
||||||
|
const response = await fakeLoginApi(credentials)
|
||||||
|
|
||||||
|
token.value = response.token
|
||||||
|
user.value = response.user
|
||||||
|
|
||||||
|
localStorage.setItem('token', token.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
function setToken(newToken: string) {
|
||||||
|
token.value = newToken
|
||||||
|
localStorage.setItem('token', newToken)
|
||||||
|
}
|
||||||
|
|
||||||
|
function logout() {
|
||||||
|
token.value = null
|
||||||
|
user.value = null
|
||||||
|
localStorage.removeItem('token')
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchUser() {
|
||||||
|
if (!token.value) return
|
||||||
|
|
||||||
|
const response = await fakeFetchUserApi(token.value)
|
||||||
|
user.value = response.user
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
user,
|
||||||
|
token,
|
||||||
|
isAuthenticated,
|
||||||
|
login,
|
||||||
|
setToken,
|
||||||
|
logout,
|
||||||
|
fetchUser,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
async function fakeLoginApi(credentials: credentials): Promise<token> {
|
||||||
|
return {
|
||||||
|
token: 'abc123',
|
||||||
|
user: { id: 1, name: 'John Doe' }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fakeFetchUserApi(token: string): Promise<{ user: user }> {
|
||||||
|
return {
|
||||||
|
user: { id: 1, name: 'John Doe' }
|
||||||
|
}
|
||||||
|
}
|
||||||
16
src/types/authTypes.ts
Normal file
16
src/types/authTypes.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
|
||||||
|
type token = {
|
||||||
|
token: string
|
||||||
|
user: user
|
||||||
|
}
|
||||||
|
type user = {
|
||||||
|
id: number
|
||||||
|
name: string
|
||||||
|
}
|
||||||
|
type credentials = {
|
||||||
|
username: string
|
||||||
|
password: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type { token, user, credentials }
|
||||||
|
|
||||||
@@ -1,5 +1,92 @@
|
|||||||
|
<template>
|
||||||
|
<div class="login-box q-col-gutter-sm">
|
||||||
|
<div class="text-h3 text-center row">
|
||||||
|
<img src="/logo.png" alt="Logo" style="height: 60px; margin-right: 10px;" />
|
||||||
|
</div>
|
||||||
|
<q-form @submit.prevent="onSubmit"
|
||||||
|
class="q-gutter-md row justify-center"
|
||||||
|
style="width: 100%">
|
||||||
|
|
||||||
|
<div class="row q-col-gutter-sm" style="width: 100%">
|
||||||
|
<q-input
|
||||||
|
style="width: 100%"
|
||||||
|
filled
|
||||||
|
dark
|
||||||
|
label-color="white"
|
||||||
|
color="white"
|
||||||
|
v-model="username"
|
||||||
|
label="Username *"
|
||||||
|
|
||||||
|
:error="!!loginError"
|
||||||
|
:error-message="loginError"
|
||||||
|
|
||||||
|
lazy-rules
|
||||||
|
:rules="[ val => val && val.length > 0 || 'Username is required']"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row q-col-gutter-sm" style="width: 100%">
|
||||||
|
<q-input
|
||||||
|
style="width: 100%"
|
||||||
|
filled
|
||||||
|
dark
|
||||||
|
label-color="white"
|
||||||
|
color="white"
|
||||||
|
v-model="password"
|
||||||
|
label="Password *"
|
||||||
|
:error="!!loginError"
|
||||||
|
:error-message="loginError"
|
||||||
|
|
||||||
|
lazy-rules
|
||||||
|
:rules="[
|
||||||
|
val => !!val || 'Password is required'
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row justify-center">
|
||||||
|
<q-btn type="submit" label="Login" push color="dark" />
|
||||||
|
</div>
|
||||||
|
</q-form>
|
||||||
|
</div>
|
||||||
|
<vue-particles
|
||||||
|
id="particles-js"
|
||||||
|
:options='options'
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
|
||||||
|
import { useQuasar } from 'quasar'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import axios from "axios";
|
||||||
|
import {useAuthStore} from "@/stores/auth.ts";
|
||||||
|
import router from "@/router";
|
||||||
|
|
||||||
|
const api = window?.__RUNTIME_CONFIG__?.API_URL;
|
||||||
|
|
||||||
|
const $q = useQuasar()
|
||||||
|
|
||||||
|
const username = ref(null)
|
||||||
|
const password = ref(null)
|
||||||
|
const inProgress = ref(false)
|
||||||
|
const loginError = ref('')
|
||||||
|
|
||||||
|
const onSubmit = () => {
|
||||||
|
if (inProgress.value) return
|
||||||
|
inProgress.value = true
|
||||||
|
loginError.value = ''
|
||||||
|
axios.post(`${api}/login`, {username: username.value, password: password.value}).then(response => {
|
||||||
|
const auth = useAuthStore()
|
||||||
|
auth.setToken(response.data.token)
|
||||||
|
router.push("/")
|
||||||
|
}).catch(() => {
|
||||||
|
loginError.value = 'Invalid username or password'
|
||||||
|
}).finally(() =>
|
||||||
|
inProgress.value = false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
"particles": {
|
"particles": {
|
||||||
"number": {
|
"number": {
|
||||||
@@ -116,16 +203,6 @@ const options = {
|
|||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="login-box">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<vue-particles
|
|
||||||
id="particles-js"
|
|
||||||
:options='options'
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.login-box {
|
.login-box {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
@@ -139,12 +216,7 @@ const options = {
|
|||||||
max-width: 420px;
|
max-width: 420px;
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
}
|
background-color: var(--color-background);
|
||||||
|
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
|
||||||
#loginParticles {
|
|
||||||
background-color: rgb(11, 8, 8);
|
|
||||||
background-size: cover;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-position: 50% 50%;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
3
versions.env
Normal file
3
versions.env
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
MAJOR=0
|
||||||
|
MINOR=1
|
||||||
|
PATCH=3
|
||||||
@@ -2,15 +2,17 @@ import { fileURLToPath, URL } from 'node:url'
|
|||||||
|
|
||||||
import { defineConfig } from 'vite'
|
import { defineConfig } from 'vite'
|
||||||
import vue from '@vitejs/plugin-vue'
|
import vue from '@vitejs/plugin-vue'
|
||||||
|
import { quasar, transformAssetUrls } from '@quasar/vite-plugin'
|
||||||
import vueJsx from '@vitejs/plugin-vue-jsx'
|
import vueJsx from '@vitejs/plugin-vue-jsx'
|
||||||
import vueDevTools from 'vite-plugin-vue-devtools'
|
import vueDevTools from 'vite-plugin-vue-devtools'
|
||||||
|
|
||||||
// https://vite.dev/config/
|
// https://vite.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [
|
plugins: [
|
||||||
vue(),
|
vue({ template: { transformAssetUrls } }),
|
||||||
vueJsx(),
|
vueJsx(),
|
||||||
vueDevTools(),
|
vueDevTools(),
|
||||||
|
quasar(),
|
||||||
],
|
],
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
|
|||||||
Reference in New Issue
Block a user