add tailwindcss and daisyui, pinia and fix build error when integrating vue with electron

This commit is contained in:
rizary 2025-06-21 17:58:14 +07:00
parent 13166b7a19
commit 7cc90b8a0d
Signed by untrusted user who does not match committer: rizary
GPG key ID: 2CE8D69D02F1CEB5
18 changed files with 689 additions and 12233 deletions

View file

@ -1,8 +1,8 @@
import tailwindcss from "@tailwindcss/vite";
import { APP } from "../app/utils/app";
export default defineNuxtConfig({
modules: [
"@nuxt/ui",
"@nuxt/eslint",
"@pinia/nuxt"
],
@ -19,23 +19,32 @@ export default defineNuxtConfig({
}
},
css: [
"~/assets/css/ui.tailwind.css",
"~/assets/scss/app.scss"
"~/assets/css/main.css"
],
vite: {
plugins: [
tailwindcss(),
],
server: {
watch: {
ignored: ["./docker-data/*"],
},
},
},
postcss: {
plugins: {
"@tailwindcss/postcss": {}
}
},
router: {
options: {
hashMode: true
}
},
colorMode: {
preference: "dark",
fallback: "dark",
storageKey: "nuxt-color-mode"
},
ui: {
colorMode: true,
fonts: false
},
future: { compatibilityVersion: 4 },
features: {
inlineStyles: false
@ -46,31 +55,9 @@ export default defineNuxtConfig({
renderJsonPayloads: false
},
compatibilityDate: "2025-05-26",
vite: {
css: {
preprocessorOptions: {
scss: {
api: "modern-compiler",
silenceDeprecations: ["mixed-decls", "color-functions", "import", "global-builtin"]
}
}
}
},
postcss: {
plugins: {
"@tailwindcss/postcss": {}
}
},
eslint: {
config: {
autoInit: false,
stylistic: true
}
},
icon: {
provider: "iconify",
clientBundle: {
scan: true
}
}
});
})

View file

@ -0,0 +1,27 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./app/components/**/*.{js,vue,ts}",
"./app/layouts/**/*.vue",
"./app/pages/**/*.vue",
"./app/plugins/**/*.{js,ts}",
"./app.vue",
"./app/**/*.vue"
],
theme: {
extend: {},
},
plugins: [
require('daisyui'),
],
daisyui: {
themes: ["dark", "light", "night", "forest", "aqua", "winter"],
darkTheme: "dark",
base: true,
styled: true,
utils: true,
prefix: "",
logs: true,
themeRoot: ":root",
}
}

View file

@ -7,6 +7,7 @@ const copyNuxtOutput: Plugin = {
async closeBundle () {
const outputDir = fileURLToPath(new URL("../.output/public", import.meta.url));
const targetDir = fileURLToPath(new URL("../.vite/renderer", import.meta.url));
await mkdir(targetDir, { recursive: true });
await cp(outputDir, targetDir, { recursive: true, force: true });
}

View file

@ -1,40 +1,15 @@
<template>
<div class="min-h-screen bg-gray-50 flex items-center justify-center">
<div class="max-w-md w-full bg-white rounded-lg shadow-lg p-8">
<div class="text-center">
<h1 class="text-3xl font-bold text-gray-900 mb-4">
Hello World! 👋
</h1>
<p class="text-gray-600 mb-6">
Welcome to Ziya - Your Vue + Nuxt + Electron App
</p>
<div class="space-y-4">
<UButton
@click="count++"
color="primary"
size="lg"
class="w-full"
>
Click me! ({{ count }})
</UButton>
<p class="text-sm text-gray-500">
Built with Vue {{ vueVersion }}, Nuxt {{ nuxtVersion }}
</p>
</div>
</div>
</div>
<div data-theme="dark" class="min-h-screen">
<NuxtLayout>
<NuxtPage />
</NuxtLayout>
</div>
</template>
<script setup lang="ts">
import { version as vueVersion } from 'vue/package.json'
const count = ref(0)
const nuxtVersion = '3.17.5' // From your package.json
// Page metadata
// App-level setup
useHead({
title: 'Ziya - Hello World',
title: 'Ziya - Trading Platform',
meta: [
{ name: 'description', content: 'One Stop Shop for your trading needs' }
]

14
app/assets/css/main.css Normal file
View file

@ -0,0 +1,14 @@
@import "tailwindcss";
@plugin "daisyui" {
themes:
light --default,
dark --prefersdark;
}
::-webkit-scrollbar {
display: none;
}
body {
overflow: hidden;
}

View file

@ -1,43 +0,0 @@
/* stylelint-disable scss/at-rule-no-unknown, custom-property-empty-line-before */
@import "tailwindcss";
@import "@nuxt/ui";
@custom-variant dark (&:where(.dark, .dark *));
@custom-variant light (&:where(.light, .light *));
@custom-variant hover (&:hover);
@theme static {
--color-green-50: #ebfdf6;
--color-green-100: #d4f8eb;
--color-green-200: #a7f2d9;
--color-green-300: #6ae6c2;
--color-green-400: #00d1a6;
--color-green-500: #00ba91;
--color-green-600: #009775;
--color-green-700: #1B886D;
--color-green-800: #005f4a;
--color-green-900: #164c3d;
--color-green-950: #052c21;
--color-slate-50: #f9fafb;
--color-slate-100: #f3f4f6;
--color-slate-200: #e2e5e9;
--color-slate-300: #cdd5e1;
--color-slate-400: #92a1b7;
--color-slate-500: #63738a;
--color-slate-600: #44546b;
--color-slate-700: #354151;
--color-slate-800: #222830;
--color-slate-900: #15191e;
--color-slate-950: #06090E;
}
:root {
--ui-primary: var(--ui-color-primary-700);
--ui-secondary: var(--ui-color-secondary-600);
}
.dark {
--ui-primary: var(--ui-color-primary-400);
--ui-secondary: var(--ui-color-secondary-300);
}

View file

@ -1,29 +0,0 @@
:root {
scrollbar-width: auto;
scroll-behavior: unset;
}
*::-webkit-scrollbar {
width: 8px;
}
*::-webkit-scrollbar-track {
background-color: var(--ui-bg-muted);
}
*::-webkit-scrollbar-thumb {
height: 56px;
border-radius: 8px;
border: 0 solid transparent;
background-clip: content-box;
background-color: var(--ui-primary);
}
*::-webkit-scrollbar-thumb:hover {
background-color: var(--ui-primary);
}
::selection {
background: var(--ui-primary);
color: var(--ui-bg-muted);
}

View file

@ -1,83 +0,0 @@
.slide-enter-active,
.slide-leave-active,
.slide-right-enter-active,
.slide-right-leave-active,
.slide-left-enter-active,
.slide-left-leave-active {
transition: all 0.2s;
}
.slide-enter-from,
.slide-leave-to {
opacity: 0;
transform: translate(0, -10px);
}
.slide-right-enter-from,
.slide-right-leave-to {
opacity: 0;
transform: translate(10px, 0);
}
.slide-left-enter-from,
.slide-left-leave-to {
opacity: 0;
transform: translate(-10px, 0);
}
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
.bounce-enter-active {
animation: bounce-in 0.5s ease;
}
@keyframes bounce-in {
0% { transform: scale(0);}
50% { transform: scale(1.25);}
100% {transform: scale(1);}
}
.list-move,
.list-enter-active,
.list-leave-active {
transition: all 0.5s ease;
}
.list-enter-from,
.list-leave-to {
opacity: 0;
transform: translateY(30px);
}
.list-leave-active {
position: absolute;
width: 0%;
left: 50%;
top: 100%;
transform: translateY(100%);
}
@each $size in (200, 1000) {
.expand-#{$size} {
&-enter-active,
&-leave-active {
transition: max-height 0.3s ease-in-out, opacity 0.2s ease;
max-height: #{$size}px;
overflow: hidden;
}
&-enter-from,
&-leave-to {
max-height: 0;
opacity: 0;
}
}
}

View file

@ -1,2 +0,0 @@
@import "main";
@import "transitions";

View file

@ -1,11 +1,47 @@
<template>
<div class="min-h-screen">
<div class="min-h-screen bg-base-100">
<!-- Navbar -->
<div class="navbar bg-base-300 shadow-lg">
<div class="navbar-start">
<div class="dropdown">
<div tabindex="0" role="button" class="btn btn-ghost lg:hidden">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h8m-8 6h16" />
</svg>
</div>
</div>
<a class="btn btn-ghost text-xl">Ziya</a>
</div>
<div class="navbar-center hidden lg:flex">
<ul class="menu menu-horizontal px-1">
<li><a>Trading</a></li>
<li><a>Portfolio</a></li>
<li><a>Markets</a></li>
</ul>
</div>
<div class="navbar-end">
<button class="btn btn-primary">Get Started</button>
</div>
</div>
<!-- Main content -->
<main>
<slot />
</main>
<!-- Footer -->
<footer class="footer footer-center p-4 bg-base-200 text-base-content mt-auto">
<aside>
<p>© 2024 Ziya - One Stop Shop for your trading needs</p>
</aside>
</footer>
</div>
</template>
<script setup lang="ts">
// Default layout for the app
// Inject theme from app.vue
const theme = inject('theme') as Ref<string>;
const toggleTheme = inject('toggleTheme') as () => void;
</script>
<style>

View file

@ -1,46 +1,52 @@
<template>
<div class="container mx-auto px-4 py-8">
<div class="text-center">
<h1 class="text-4xl font-bold text-gray-900 mb-6">
🚀 Ziya Dashboard
</h1>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 max-w-4xl mx-auto">
<!-- Trading Card -->
<div class="bg-white rounded-lg shadow-md p-6 hover:shadow-lg transition-shadow">
<div class="text-blue-500 text-3xl mb-4">📈</div>
<h3 class="text-xl font-semibold mb-2">Trading</h3>
<p class="text-gray-600">Access your trading dashboard and monitor your portfolio</p>
</div>
<!-- Analytics Card -->
<div class="bg-white rounded-lg shadow-md p-6 hover:shadow-lg transition-shadow">
<div class="text-green-500 text-3xl mb-4">📊</div>
<h3 class="text-xl font-semibold mb-2">Analytics</h3>
<p class="text-gray-600">View detailed analytics and market insights</p>
</div>
<!-- Settings Card -->
<div class="bg-white rounded-lg shadow-md p-6 hover:shadow-lg transition-shadow">
<div class="text-purple-500 text-3xl mb-4"></div>
<h3 class="text-xl font-semibold mb-2">Settings</h3>
<p class="text-gray-600">Configure your preferences and account settings</p>
<div>
<!-- Hero Section -->
<div class="hero min-h-screen bg-gradient-to-r from-primary to-secondary">
<div class="hero-content text-center">
<div class="max-w-md">
<h1 class="text-5xl font-bold text-primary-content">Hello Ziya!</h1>
<p class="py-6 text-primary-content/80">
Welcome to your trading platform. Get started with the most advanced trading tools and real-time market data.
</p>
<button class="btn btn-accent btn-lg">Get Started</button>
</div>
</div>
</div>
<div class="mt-8">
<UButton
@click="showWelcome = !showWelcome"
color="primary"
size="lg"
>
{{ showWelcome ? 'Hide' : 'Show' }} Welcome Message
</UButton>
<!-- Features Section -->
<div class="py-16 bg-base-200">
<div class="container mx-auto px-4">
<h2 class="text-3xl font-bold text-center mb-12">Features</h2>
<div class="grid grid-cols-1 md:grid-cols-3 gap-8">
<div class="card bg-base-100 shadow-xl">
<div class="card-body">
<h3 class="card-title">Real-time Trading</h3>
<p>Execute trades with lightning speed and real-time market data.</p>
<div class="card-actions justify-end">
<button class="btn btn-primary btn-sm">Learn More</button>
</div>
</div>
</div>
<div v-if="showWelcome" class="mt-4 p-4 bg-blue-50 rounded-lg">
<p class="text-blue-800">
Welcome to your new Electron app! This is running on Nuxt {{ nuxtVersion }} with Vue {{ vueVersion }}.
</p>
<div class="card bg-base-100 shadow-xl">
<div class="card-body">
<h3 class="card-title">Portfolio Management</h3>
<p>Track and manage your investments with advanced analytics.</p>
<div class="card-actions justify-end">
<button class="btn btn-primary btn-sm">Learn More</button>
</div>
</div>
</div>
<div class="card bg-base-100 shadow-xl">
<div class="card-body">
<h3 class="card-title">Market Analysis</h3>
<p>Get insights with powerful charting and analysis tools.</p>
<div class="card-actions justify-end">
<button class="btn btn-primary btn-sm">Learn More</button>
</div>
</div>
</div>
</div>
</div>
</div>
@ -48,20 +54,5 @@
</template>
<script setup lang="ts">
import { version as vueVersion } from 'vue/package.json'
const showWelcome = ref(false)
const nuxtVersion = '3.17.5'
// Page metadata
definePageMeta({
title: 'Dashboard'
})
useHead({
title: 'Ziya - Dashboard',
meta: [
{ name: 'description', content: 'Ziya trading dashboard - One stop shop for your trading needs' }
]
})
// Page-specific setup
</script>

99
app/stores/app.ts Normal file
View file

@ -0,0 +1,99 @@
export const useAppStore = defineStore('app', () => {
// State
const isLoading = ref(false)
const currentUser = ref<{ name: string; email: string } | null>(null)
const appVersion = ref('1.0.0')
// Getters
const isAuthenticated = computed(() => currentUser.value !== null)
const userInitials = computed(() => {
if (!currentUser.value) return '??'
return currentUser.value.name
.split(' ')
.map(n => n[0])
.join('')
.toUpperCase()
})
// Actions
const setLoading = (loading: boolean) => {
isLoading.value = loading
}
const login = async (email: string, password: string) => {
setLoading(true)
try {
// Simulate API call
await new Promise(resolve => setTimeout(resolve, 1000))
// Mock user data
currentUser.value = {
name: 'John Trader',
email: email
}
console.log('Welcome back!')
return true
} catch (error) {
console.log('Login failed. Please try again.')
return false
} finally {
setLoading(false)
}
}
const logout = async () => {
setLoading(true)
try {
// Simulate API call
await new Promise(resolve => setTimeout(resolve, 500))
currentUser.value = null
console.log('You have been logged out')
} finally {
setLoading(false)
}
}
// Persist user data to localStorage
watch(currentUser, (newUser) => {
if (newUser) {
localStorage.setItem('ziya-user', JSON.stringify(newUser))
} else {
localStorage.removeItem('ziya-user')
}
})
// Initialize from localStorage
const initializeFromStorage = () => {
if (process.client) {
const storedUser = localStorage.getItem('ziya-user')
if (storedUser) {
try {
currentUser.value = JSON.parse(storedUser)
} catch (error) {
console.error('Failed to parse stored user data:', error)
localStorage.removeItem('ziya-user')
}
}
}
}
return {
// State
isLoading: readonly(isLoading),
currentUser: readonly(currentUser),
appVersion: readonly(appVersion),
// Getters
isAuthenticated,
userInitials,
// Actions
setLoading,
login,
logout,
initializeFromStorage
}
})

View file

@ -9,20 +9,20 @@ if (started) {
}
const createWindow = () => {
// Create the browser window.
const mainWindow = new BrowserWindow({
minHeight: 800,
minWidth: 1080,
maxHeight: 1080,
maxWidth: 1920,
height: 1024,
width: 1280,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
preload: path.join(__dirname, 'preload.cjs'),
},
});
// Create the browser window.
const mainWindow = new BrowserWindow({
minHeight: 800,
minWidth: 1080,
maxHeight: 1080,
maxWidth: 1920,
height: 1024,
width: 1280,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
preload: path.join(__dirname, 'preload.cjs'),
},
});
mainWindow.setMenuBarVisibility(false);
mainWindow.webContents.on("will-navigate", function (event, reqUrl) {

10072
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -8,13 +8,14 @@
"scripts": {
"start": "electron-forge start",
"dev": "concurrently \"pnpm run dev:nuxt\" \"pnpm run dev:electron\"",
"dev:nuxt": "nuxt dev --config-file .config/nuxt.config.ts",
"dev:nuxt": "nuxt dev --config-file .config/nuxt.ts",
"dev:electron": "cross-env NODE_ENV=development electron-forge start",
"build": "nuxt generate --config-file .config/nuxt.config.ts && electron-forge make",
"build": "nuxt generate --config-file .config/nuxt.ts && electron-forge make",
"package": "electron-forge package",
"make": "electron-forge make",
"publish": "electron-forge publish",
"lint": "eslint --ext .ts,.tsx,.js,.vue --ignore-path .gitignore .",
"lint": "eslint --config .config/eslint.mjs --ext .ts,.tsx,.js,.vue --ignore-path .gitignore .",
"lint:eslint:inspect": "pnpm dlx @eslint/config-inspector --config .config/eslint.mjs",
"format": "prettier --write ."
},
"keywords": [],
@ -33,29 +34,31 @@
"@electron-forge/publisher-github": "^7.8.1",
"@electron/fuses": "^1.8.0",
"@nuxt/eslint": "^1.4.1",
"@nuxt/ui": "^3.1.3",
"@pinia/nuxt": "^0.11.1",
"@tailwindcss/cli": "^4.1.10",
"@tailwindcss/postcss": "^4.1.10",
"@tailwindcss/vite": "^4.1.10",
"@types/electron-squirrel-startup": "^1.0.2",
"@types/node": "^24.0.3",
"@typescript-eslint/eslint-plugin": "^5.62.0",
"@typescript-eslint/parser": "^5.62.0",
"@typescript-eslint/eslint-plugin": "^8.34.1",
"@typescript-eslint/parser": "^8.34.1",
"changelogen": "^0.6.1",
"concurrently": "^9.1.2",
"cross-env": "^7.0.3",
"daisyui": "^5.0.43",
"electron": "36.5.0",
"electron-packager-languages": "^0.6.0",
"eslint": "^8.57.1",
"eslint": "^9.29.0",
"eslint-config-prettier": "^10.1.5",
"eslint-plugin-import": "^2.32.0",
"nuxt": "^3.17.5",
"pinia": "^3.0.3",
"prettier": "3.5.3",
"sass": "^1.89.2",
"stylelint": "^16.21.0",
"stylelint-config-standard-scss": "^15.0.1",
"tailwindcss": "^4.1.10",
"ts-node": "^10.9.2",
"typescript": "~4.5.4",
"vite": "^5.4.19",
"typescript": "^5.8.3",
"vite": "^6.3.5",
"vite-plugin-electron": "^0.29.0",
"vite-plugin-electron-renderer": "^0.14.6",
"vitest": "^3.2.4",

2254
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

View file

@ -1,11 +1,13 @@
nodeLinker: hoisted
packages:
- .
ignoredBuiltDependencies:
- '@parcel/watcher'
- '@tailwindcss/oxide'
- esbuild
- unrs-resolver
nodeLinker: hoisted
onlyBuiltDependencies:
- electron