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"; import { APP } from "../app/utils/app";
export default defineNuxtConfig({ export default defineNuxtConfig({
modules: [ modules: [
"@nuxt/ui",
"@nuxt/eslint", "@nuxt/eslint",
"@pinia/nuxt" "@pinia/nuxt"
], ],
@ -19,23 +19,32 @@ export default defineNuxtConfig({
} }
}, },
css: [ css: [
"~/assets/css/ui.tailwind.css", "~/assets/css/main.css"
"~/assets/scss/app.scss"
], ],
vite: {
plugins: [
tailwindcss(),
],
server: {
watch: {
ignored: ["./docker-data/*"],
},
},
},
postcss: {
plugins: {
"@tailwindcss/postcss": {}
}
},
router: { router: {
options: { options: {
hashMode: true hashMode: true
} }
}, },
colorMode: {
preference: "dark",
fallback: "dark",
storageKey: "nuxt-color-mode"
},
ui: {
colorMode: true,
fonts: false
},
future: { compatibilityVersion: 4 }, future: { compatibilityVersion: 4 },
features: { features: {
inlineStyles: false inlineStyles: false
@ -46,31 +55,9 @@ export default defineNuxtConfig({
renderJsonPayloads: false renderJsonPayloads: false
}, },
compatibilityDate: "2025-05-26", compatibilityDate: "2025-05-26",
vite: {
css: {
preprocessorOptions: {
scss: {
api: "modern-compiler",
silenceDeprecations: ["mixed-decls", "color-functions", "import", "global-builtin"]
}
}
}
},
postcss: {
plugins: {
"@tailwindcss/postcss": {}
}
},
eslint: { eslint: {
config: { config: {
autoInit: false,
stylistic: true 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 () { async closeBundle () {
const outputDir = fileURLToPath(new URL("../.output/public", import.meta.url)); const outputDir = fileURLToPath(new URL("../.output/public", import.meta.url));
const targetDir = fileURLToPath(new URL("../.vite/renderer", import.meta.url)); const targetDir = fileURLToPath(new URL("../.vite/renderer", import.meta.url));
await mkdir(targetDir, { recursive: true }); await mkdir(targetDir, { recursive: true });
await cp(outputDir, targetDir, { recursive: true, force: true }); await cp(outputDir, targetDir, { recursive: true, force: true });
} }

View file

@ -1,40 +1,15 @@
<template> <template>
<div class="min-h-screen bg-gray-50 flex items-center justify-center"> <div data-theme="dark" class="min-h-screen">
<div class="max-w-md w-full bg-white rounded-lg shadow-lg p-8"> <NuxtLayout>
<div class="text-center"> <NuxtPage />
<h1 class="text-3xl font-bold text-gray-900 mb-4"> </NuxtLayout>
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> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { version as vueVersion } from 'vue/package.json' // App-level setup
const count = ref(0)
const nuxtVersion = '3.17.5' // From your package.json
// Page metadata
useHead({ useHead({
title: 'Ziya - Hello World', title: 'Ziya - Trading Platform',
meta: [ meta: [
{ name: 'description', content: 'One Stop Shop for your trading needs' } { 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> <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 /> <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> </div>
</template> </template>
<script setup lang="ts"> <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> </script>
<style> <style>

View file

@ -1,46 +1,52 @@
<template> <template>
<div class="container mx-auto px-4 py-8"> <div>
<div class="text-center"> <!-- Hero Section -->
<h1 class="text-4xl font-bold text-gray-900 mb-6"> <div class="hero min-h-screen bg-gradient-to-r from-primary to-secondary">
🚀 Ziya Dashboard <div class="hero-content text-center">
</h1> <div class="max-w-md">
<h1 class="text-5xl font-bold text-primary-content">Hello Ziya!</h1>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 max-w-4xl mx-auto"> <p class="py-6 text-primary-content/80">
<!-- Trading Card --> Welcome to your trading platform. Get started with the most advanced trading tools and real-time market data.
<div class="bg-white rounded-lg shadow-md p-6 hover:shadow-lg transition-shadow"> </p>
<div class="text-blue-500 text-3xl mb-4">📈</div> <button class="btn btn-accent btn-lg">Get Started</button>
<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> </div>
</div> </div>
</div>
<div class="mt-8">
<UButton <!-- Features Section -->
@click="showWelcome = !showWelcome" <div class="py-16 bg-base-200">
color="primary" <div class="container mx-auto px-4">
size="lg" <h2 class="text-3xl font-bold text-center mb-12">Features</h2>
> <div class="grid grid-cols-1 md:grid-cols-3 gap-8">
{{ showWelcome ? 'Hide' : 'Show' }} Welcome Message <div class="card bg-base-100 shadow-xl">
</UButton> <div class="card-body">
<h3 class="card-title">Real-time Trading</h3>
<div v-if="showWelcome" class="mt-4 p-4 bg-blue-50 rounded-lg"> <p>Execute trades with lightning speed and real-time market data.</p>
<p class="text-blue-800"> <div class="card-actions justify-end">
Welcome to your new Electron app! This is running on Nuxt {{ nuxtVersion }} with Vue {{ vueVersion }}. <button class="btn btn-primary btn-sm">Learn More</button>
</p> </div>
</div>
</div>
<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> </div>
</div> </div>
@ -48,20 +54,5 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { version as vueVersion } from 'vue/package.json' // Page-specific setup
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' }
]
})
</script> </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 = () => { const createWindow = () => {
// Create the browser window. // Create the browser window.
const mainWindow = new BrowserWindow({ const mainWindow = new BrowserWindow({
minHeight: 800, minHeight: 800,
minWidth: 1080, minWidth: 1080,
maxHeight: 1080, maxHeight: 1080,
maxWidth: 1920, maxWidth: 1920,
height: 1024, height: 1024,
width: 1280, width: 1280,
webPreferences: { webPreferences: {
nodeIntegration: false, nodeIntegration: false,
contextIsolation: true, contextIsolation: true,
preload: path.join(__dirname, 'preload.cjs'), preload: path.join(__dirname, 'preload.cjs'),
}, },
}); });
mainWindow.setMenuBarVisibility(false); mainWindow.setMenuBarVisibility(false);
mainWindow.webContents.on("will-navigate", function (event, reqUrl) { 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": { "scripts": {
"start": "electron-forge start", "start": "electron-forge start",
"dev": "concurrently \"pnpm run dev:nuxt\" \"pnpm run dev:electron\"", "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", "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", "package": "electron-forge package",
"make": "electron-forge make", "make": "electron-forge make",
"publish": "electron-forge publish", "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 ." "format": "prettier --write ."
}, },
"keywords": [], "keywords": [],
@ -33,29 +34,31 @@
"@electron-forge/publisher-github": "^7.8.1", "@electron-forge/publisher-github": "^7.8.1",
"@electron/fuses": "^1.8.0", "@electron/fuses": "^1.8.0",
"@nuxt/eslint": "^1.4.1", "@nuxt/eslint": "^1.4.1",
"@nuxt/ui": "^3.1.3",
"@pinia/nuxt": "^0.11.1", "@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/electron-squirrel-startup": "^1.0.2",
"@types/node": "^24.0.3", "@types/node": "^24.0.3",
"@typescript-eslint/eslint-plugin": "^5.62.0", "@typescript-eslint/eslint-plugin": "^8.34.1",
"@typescript-eslint/parser": "^5.62.0", "@typescript-eslint/parser": "^8.34.1",
"changelogen": "^0.6.1", "changelogen": "^0.6.1",
"concurrently": "^9.1.2", "concurrently": "^9.1.2",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
"daisyui": "^5.0.43",
"electron": "36.5.0", "electron": "36.5.0",
"electron-packager-languages": "^0.6.0", "electron-packager-languages": "^0.6.0",
"eslint": "^8.57.1", "eslint": "^9.29.0",
"eslint-config-prettier": "^10.1.5", "eslint-config-prettier": "^10.1.5",
"eslint-plugin-import": "^2.32.0", "eslint-plugin-import": "^2.32.0",
"nuxt": "^3.17.5", "nuxt": "^3.17.5",
"pinia": "^3.0.3", "pinia": "^3.0.3",
"prettier": "3.5.3", "prettier": "3.5.3",
"sass": "^1.89.2",
"stylelint": "^16.21.0", "stylelint": "^16.21.0",
"stylelint-config-standard-scss": "^15.0.1", "tailwindcss": "^4.1.10",
"ts-node": "^10.9.2", "ts-node": "^10.9.2",
"typescript": "~4.5.4", "typescript": "^5.8.3",
"vite": "^5.4.19", "vite": "^6.3.5",
"vite-plugin-electron": "^0.29.0", "vite-plugin-electron": "^0.29.0",
"vite-plugin-electron-renderer": "^0.14.6", "vite-plugin-electron-renderer": "^0.14.6",
"vitest": "^3.2.4", "vitest": "^3.2.4",

2254
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

View file

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