base:set_up_auto_import+dark_theme

This commit is contained in:
NguyenAnhQuan 2025-11-24 19:12:46 +07:00
parent 570a5f5317
commit 4bba111113
15 changed files with 416 additions and 155 deletions

5
.gitignore vendored
View File

@ -41,6 +41,11 @@ Thumbs.db
# TypeScript # TypeScript
*.tsbuildinfo *.tsbuildinfo
# Auto-generated files
src/auto-imports.d.ts
src/components.d.ts
.eslintrc-auto-import.json
# Optional npm cache directory # Optional npm cache directory
.npm .npm

View File

@ -6,8 +6,7 @@
"config": "tailwind.config.ts", "config": "tailwind.config.ts",
"css": "src/style.css", "css": "src/style.css",
"baseColor": "neutral", "baseColor": "neutral",
"cssVariables": true, "cssVariables": true
"prefix": ""
}, },
"iconLibrary": "lucide", "iconLibrary": "lucide",
"aliases": { "aliases": {

View File

@ -1,11 +1,35 @@
<!doctype html> <!doctype html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.ico" /> <link rel="icon" type="image/x-icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Neptune Wallet - Secure cryptocurrency wallet for Neptune network" /> <!-- Mobile-optimized viewport -->
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover"
/>
<!-- PWA Meta Tags -->
<meta name="theme-color" content="#3f51b5" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta name="apple-mobile-web-app-title" content="Neptune Wallet" />
<!-- App Description -->
<meta
name="description"
content="Neptune Wallet - Secure cryptocurrency wallet for Neptune blockchain"
/>
<!-- Google Fonts - Inter (Modern, clean, mobile-optimized) -->
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap"
rel="stylesheet"
/>
<title>Neptune Wallet</title> <title>Neptune Wallet</title>
</head> </head>
@ -13,5 +37,4 @@
<div id="app"></div> <div id="app"></div>
<script type="module" src="/src/main.ts"></script> <script type="module" src="/src/main.ts"></script>
</body> </body>
</html> </html>

View File

@ -40,6 +40,8 @@
"eslint-plugin-vue": "^9.30.0", "eslint-plugin-vue": "^9.30.0",
"prettier": "^3.4.0", "prettier": "^3.4.0",
"typescript": "~5.9.3", "typescript": "~5.9.3",
"unplugin-auto-import": "^20.2.0",
"unplugin-vue-components": "^30.0.0",
"vite": "^7.2.4", "vite": "^7.2.4",
"vue-tsc": "^3.1.4" "vue-tsc": "^3.1.4"
} }

216
pnpm-lock.yaml generated
View File

@ -87,6 +87,12 @@ importers:
typescript: typescript:
specifier: ~5.9.3 specifier: ~5.9.3
version: 5.9.3 version: 5.9.3
unplugin-auto-import:
specifier: ^20.2.0
version: 20.2.0(@vueuse/core@14.0.0(vue@3.5.24(typescript@5.9.3)))
unplugin-vue-components:
specifier: ^30.0.0
version: 30.0.0(@babel/parser@7.28.5)(vue@3.5.24(typescript@5.9.3))
vite: vite:
specifier: ^7.2.4 specifier: ^7.2.4
version: 7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2) version: 7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)
@ -840,6 +846,10 @@ packages:
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
engines: {node: '>=10'} engines: {node: '>=10'}
chokidar@4.0.3:
resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==}
engines: {node: '>= 14.16.0'}
class-variance-authority@0.7.1: class-variance-authority@0.7.1:
resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==} resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==}
@ -861,6 +871,12 @@ packages:
concat-map@0.0.1: concat-map@0.0.1:
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
confbox@0.1.8:
resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==}
confbox@0.2.2:
resolution: {integrity: sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==}
cross-spawn@7.0.6: cross-spawn@7.0.6:
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
engines: {node: '>= 8'} engines: {node: '>= 8'}
@ -933,6 +949,10 @@ packages:
resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
engines: {node: '>=10'} engines: {node: '>=10'}
escape-string-regexp@5.0.0:
resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==}
engines: {node: '>=12'}
eslint-config-prettier@10.1.8: eslint-config-prettier@10.1.8:
resolution: {integrity: sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==} resolution: {integrity: sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==}
hasBin: true hasBin: true
@ -1008,10 +1028,16 @@ packages:
estree-walker@2.0.2: estree-walker@2.0.2:
resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
estree-walker@3.0.3:
resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
esutils@2.0.3: esutils@2.0.3:
resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
exsolve@1.0.8:
resolution: {integrity: sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==}
fast-deep-equal@3.1.3: fast-deep-equal@3.1.3:
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
@ -1165,6 +1191,9 @@ packages:
resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==}
hasBin: true hasBin: true
js-tokens@9.0.1:
resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==}
js-yaml@4.1.1: js-yaml@4.1.1:
resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==}
hasBin: true hasBin: true
@ -1255,6 +1284,10 @@ packages:
resolution: {integrity: sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==} resolution: {integrity: sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==}
engines: {node: '>= 12.0.0'} engines: {node: '>= 12.0.0'}
local-pkg@1.1.2:
resolution: {integrity: sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A==}
engines: {node: '>=14'}
locate-path@6.0.0: locate-path@6.0.0:
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
engines: {node: '>=10'} engines: {node: '>=10'}
@ -1300,6 +1333,9 @@ packages:
resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==}
engines: {node: '>=16 || 14 >=14.17'} engines: {node: '>=16 || 14 >=14.17'}
mlly@1.8.0:
resolution: {integrity: sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==}
ms@2.1.3: ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
@ -1347,6 +1383,9 @@ packages:
resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
engines: {node: '>=8'} engines: {node: '>=8'}
pathe@2.0.3:
resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
picocolors@1.1.1: picocolors@1.1.1:
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
@ -1367,6 +1406,12 @@ packages:
typescript: typescript:
optional: true optional: true
pkg-types@1.3.1:
resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==}
pkg-types@2.3.0:
resolution: {integrity: sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==}
postcss-selector-parser@6.1.2: postcss-selector-parser@6.1.2:
resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==}
engines: {node: '>=4'} engines: {node: '>=4'}
@ -1395,9 +1440,16 @@ packages:
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
engines: {node: '>=6'} engines: {node: '>=6'}
quansync@0.2.11:
resolution: {integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==}
queue-microtask@1.2.3: queue-microtask@1.2.3:
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
readdirp@4.1.2:
resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==}
engines: {node: '>= 14.18.0'}
reka-ui@2.6.0: reka-ui@2.6.0:
resolution: {integrity: sha512-NrGMKrABD97l890mFS3TNUzB0BLUfbL3hh0NjcJRIUSUljb288bx3Mzo31nOyUcdiiW0HqFGXJwyCBh9cWgb0w==} resolution: {integrity: sha512-NrGMKrABD97l890mFS3TNUzB0BLUfbL3hh0NjcJRIUSUljb288bx3Mzo31nOyUcdiiW0HqFGXJwyCBh9cWgb0w==}
peerDependencies: peerDependencies:
@ -1419,6 +1471,9 @@ packages:
run-parallel@1.2.0: run-parallel@1.2.0:
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
scule@1.3.0:
resolution: {integrity: sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==}
semver@7.7.3: semver@7.7.3:
resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==}
engines: {node: '>=10'} engines: {node: '>=10'}
@ -1440,6 +1495,9 @@ packages:
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
engines: {node: '>=8'} engines: {node: '>=8'}
strip-literal@3.1.0:
resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==}
supports-color@7.2.0: supports-color@7.2.0:
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
engines: {node: '>=8'} engines: {node: '>=8'}
@ -1500,9 +1558,49 @@ packages:
engines: {node: '>=14.17'} engines: {node: '>=14.17'}
hasBin: true hasBin: true
ufo@1.6.1:
resolution: {integrity: sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==}
undici-types@7.16.0: undici-types@7.16.0:
resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==}
unimport@5.5.0:
resolution: {integrity: sha512-/JpWMG9s1nBSlXJAQ8EREFTFy3oy6USFd8T6AoBaw1q2GGcF4R9yp3ofg32UODZlYEO5VD0EWE1RpI9XDWyPYg==}
engines: {node: '>=18.12.0'}
unplugin-auto-import@20.2.0:
resolution: {integrity: sha512-vfBI/SvD9hJqYNinipVOAj5n8dS8DJXFlCKFR5iLDp2SaQwsfdnfLXgZ+34Kd3YY3YEY9omk8XQg0bwos3Q8ug==}
engines: {node: '>=14'}
peerDependencies:
'@nuxt/kit': ^4.0.0
'@vueuse/core': '*'
peerDependenciesMeta:
'@nuxt/kit':
optional: true
'@vueuse/core':
optional: true
unplugin-utils@0.3.1:
resolution: {integrity: sha512-5lWVjgi6vuHhJ526bI4nlCOmkCIF3nnfXkCMDeMJrtdvxTs6ZFCM8oNufGTsDbKv/tJ/xj8RpvXjRuPBZJuJog==}
engines: {node: '>=20.19.0'}
unplugin-vue-components@30.0.0:
resolution: {integrity: sha512-4qVE/lwCgmdPTp6h0qsRN2u642tt4boBQtcpn4wQcWZAsr8TQwq+SPT3NDu/6kBFxzo/sSEK4ioXhOOBrXc3iw==}
engines: {node: '>=14'}
peerDependencies:
'@babel/parser': ^7.15.8
'@nuxt/kit': ^3.2.2 || ^4.0.0
vue: 2 || 3
peerDependenciesMeta:
'@babel/parser':
optional: true
'@nuxt/kit':
optional: true
unplugin@2.3.11:
resolution: {integrity: sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww==}
engines: {node: '>=18.12.0'}
uri-js@4.4.1: uri-js@4.4.1:
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
@ -1600,6 +1698,9 @@ packages:
typescript: typescript:
optional: true optional: true
webpack-virtual-modules@0.6.2:
resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==}
which@2.0.2: which@2.0.2:
resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
engines: {node: '>= 8'} engines: {node: '>= 8'}
@ -2299,6 +2400,10 @@ snapshots:
ansi-styles: 4.3.0 ansi-styles: 4.3.0
supports-color: 7.2.0 supports-color: 7.2.0
chokidar@4.0.3:
dependencies:
readdirp: 4.1.2
class-variance-authority@0.7.1: class-variance-authority@0.7.1:
dependencies: dependencies:
clsx: 2.1.1 clsx: 2.1.1
@ -2317,6 +2422,10 @@ snapshots:
concat-map@0.0.1: {} concat-map@0.0.1: {}
confbox@0.1.8: {}
confbox@0.2.2: {}
cross-spawn@7.0.6: cross-spawn@7.0.6:
dependencies: dependencies:
path-key: 3.1.1 path-key: 3.1.1
@ -2398,6 +2507,8 @@ snapshots:
escape-string-regexp@4.0.0: {} escape-string-regexp@4.0.0: {}
escape-string-regexp@5.0.0: {}
eslint-config-prettier@10.1.8(eslint@9.39.1(jiti@2.6.1)): eslint-config-prettier@10.1.8(eslint@9.39.1(jiti@2.6.1)):
dependencies: dependencies:
eslint: 9.39.1(jiti@2.6.1) eslint: 9.39.1(jiti@2.6.1)
@ -2504,8 +2615,14 @@ snapshots:
estree-walker@2.0.2: {} estree-walker@2.0.2: {}
estree-walker@3.0.3:
dependencies:
'@types/estree': 1.0.8
esutils@2.0.3: {} esutils@2.0.3: {}
exsolve@1.0.8: {}
fast-deep-equal@3.1.3: {} fast-deep-equal@3.1.3: {}
fast-diff@1.3.0: {} fast-diff@1.3.0: {}
@ -2638,6 +2755,8 @@ snapshots:
jiti@2.6.1: {} jiti@2.6.1: {}
js-tokens@9.0.1: {}
js-yaml@4.1.1: js-yaml@4.1.1:
dependencies: dependencies:
argparse: 2.0.1 argparse: 2.0.1
@ -2706,6 +2825,12 @@ snapshots:
lightningcss-win32-arm64-msvc: 1.30.2 lightningcss-win32-arm64-msvc: 1.30.2
lightningcss-win32-x64-msvc: 1.30.2 lightningcss-win32-x64-msvc: 1.30.2
local-pkg@1.1.2:
dependencies:
mlly: 1.8.0
pkg-types: 2.3.0
quansync: 0.2.11
locate-path@6.0.0: locate-path@6.0.0:
dependencies: dependencies:
p-locate: 5.0.0 p-locate: 5.0.0
@ -2745,6 +2870,13 @@ snapshots:
dependencies: dependencies:
brace-expansion: 2.0.2 brace-expansion: 2.0.2
mlly@1.8.0:
dependencies:
acorn: 8.15.0
pathe: 2.0.3
pkg-types: 1.3.1
ufo: 1.6.1
ms@2.1.3: {} ms@2.1.3: {}
muggle-string@0.4.1: {} muggle-string@0.4.1: {}
@ -2786,6 +2918,8 @@ snapshots:
path-key@3.1.1: {} path-key@3.1.1: {}
pathe@2.0.3: {}
picocolors@1.1.1: {} picocolors@1.1.1: {}
picomatch@2.3.1: {} picomatch@2.3.1: {}
@ -2802,6 +2936,18 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- '@vue/composition-api' - '@vue/composition-api'
pkg-types@1.3.1:
dependencies:
confbox: 0.1.8
mlly: 1.8.0
pathe: 2.0.3
pkg-types@2.3.0:
dependencies:
confbox: 0.2.2
exsolve: 1.0.8
pathe: 2.0.3
postcss-selector-parser@6.1.2: postcss-selector-parser@6.1.2:
dependencies: dependencies:
cssesc: 3.0.0 cssesc: 3.0.0
@ -2825,8 +2971,12 @@ snapshots:
punycode@2.3.1: {} punycode@2.3.1: {}
quansync@0.2.11: {}
queue-microtask@1.2.3: {} queue-microtask@1.2.3: {}
readdirp@4.1.2: {}
reka-ui@2.6.0(typescript@5.9.3)(vue@3.5.24(typescript@5.9.3)): reka-ui@2.6.0(typescript@5.9.3)(vue@3.5.24(typescript@5.9.3)):
dependencies: dependencies:
'@floating-ui/dom': 1.7.4 '@floating-ui/dom': 1.7.4
@ -2880,6 +3030,8 @@ snapshots:
dependencies: dependencies:
queue-microtask: 1.2.3 queue-microtask: 1.2.3
scule@1.3.0: {}
semver@7.7.3: {} semver@7.7.3: {}
shebang-command@2.0.0: shebang-command@2.0.0:
@ -2892,6 +3044,10 @@ snapshots:
strip-json-comments@3.1.1: {} strip-json-comments@3.1.1: {}
strip-literal@3.1.0:
dependencies:
js-tokens: 9.0.1
supports-color@7.2.0: supports-color@7.2.0:
dependencies: dependencies:
has-flag: 4.0.0 has-flag: 4.0.0
@ -2944,8 +3100,66 @@ snapshots:
typescript@5.9.3: {} typescript@5.9.3: {}
ufo@1.6.1: {}
undici-types@7.16.0: {} undici-types@7.16.0: {}
unimport@5.5.0:
dependencies:
acorn: 8.15.0
escape-string-regexp: 5.0.0
estree-walker: 3.0.3
local-pkg: 1.1.2
magic-string: 0.30.21
mlly: 1.8.0
pathe: 2.0.3
picomatch: 4.0.3
pkg-types: 2.3.0
scule: 1.3.0
strip-literal: 3.1.0
tinyglobby: 0.2.15
unplugin: 2.3.11
unplugin-utils: 0.3.1
unplugin-auto-import@20.2.0(@vueuse/core@14.0.0(vue@3.5.24(typescript@5.9.3))):
dependencies:
local-pkg: 1.1.2
magic-string: 0.30.21
picomatch: 4.0.3
unimport: 5.5.0
unplugin: 2.3.11
unplugin-utils: 0.3.1
optionalDependencies:
'@vueuse/core': 14.0.0(vue@3.5.24(typescript@5.9.3))
unplugin-utils@0.3.1:
dependencies:
pathe: 2.0.3
picomatch: 4.0.3
unplugin-vue-components@30.0.0(@babel/parser@7.28.5)(vue@3.5.24(typescript@5.9.3)):
dependencies:
chokidar: 4.0.3
debug: 4.4.3
local-pkg: 1.1.2
magic-string: 0.30.21
mlly: 1.8.0
tinyglobby: 0.2.15
unplugin: 2.3.11
unplugin-utils: 0.3.1
vue: 3.5.24(typescript@5.9.3)
optionalDependencies:
'@babel/parser': 7.28.5
transitivePeerDependencies:
- supports-color
unplugin@2.3.11:
dependencies:
'@jridgewell/remapping': 2.3.5
acorn: 8.15.0
picomatch: 4.0.3
webpack-virtual-modules: 0.6.2
uri-js@4.4.1: uri-js@4.4.1:
dependencies: dependencies:
punycode: 2.3.1 punycode: 2.3.1
@ -3025,6 +3239,8 @@ snapshots:
optionalDependencies: optionalDependencies:
typescript: 5.9.3 typescript: 5.9.3
webpack-virtual-modules@0.6.2: {}
which@2.0.2: which@2.0.2:
dependencies: dependencies:
isexe: 2.0.0 isexe: 2.0.0

View File

@ -1,13 +1,15 @@
<script setup lang="ts"> <script setup lang="ts">
import { Switch } from '@/components/ui/switch'
import { useTheme } from '@/composables/useTheme'
import { Moon, Sun } from 'lucide-vue-next' import { Moon, Sun } from 'lucide-vue-next'
import { watchEffect } from 'vue'; import { Switch } from '@/components/ui/switch'
const { isDark } = useTheme() const mode = useColorMode()
watchEffect(() => console.log('isDark :>> ', isDark.value))
const isDark = computed({
get: () => mode.value === 'dark',
set: (value: boolean) => {
mode.value = value ? 'dark' : 'light'
},
})
</script> </script>
<template> <template>

View File

@ -1,53 +0,0 @@
import { ref, watch } from 'vue'
type Theme = 'light' | 'dark'
const theme = ref<Theme>('light')
const isDark = ref(false)
// Initialize theme immediately
function initTheme() {
if (window != null) return
// Load saved theme or default to light
const savedTheme = localStorage.getItem('theme') as Theme | null
if (savedTheme && ['light', 'dark'].includes(savedTheme)) {
theme.value = savedTheme
}
applyTheme(theme.value)
}
function applyTheme(newTheme: Theme) {
const root = document.documentElement
root.classList.toggle('dark', newTheme === 'dark')
isDark.value = newTheme === 'dark'
// Save to localStorage
localStorage.setItem('theme', newTheme)
}
// Initialize on module load
if (window != null) initTheme()
export function useTheme() {
const setTheme = (newTheme: Theme) => {
theme.value = newTheme
applyTheme(newTheme)
}
const toggleTheme = () => {
setTheme(isDark.value ? 'light' : 'dark')
}
watch(isDark, () => setTheme(isDark.value ? 'dark' : 'light'))
return {
theme,
isDark,
setTheme,
toggleTheme,
}
}

View File

@ -3,12 +3,8 @@ import { createPinia } from 'pinia'
import router from './router' import router from './router'
import i18n from './i18n' import i18n from './i18n'
import App from './App.vue' import App from './App.vue'
import { useTheme } from './composables/useTheme'
import './style.css' import './style.css'
// Initialize theme before mounting app
useTheme()
const app = createApp(App) const app = createApp(App)
// Install plugins // Install plugins
@ -17,4 +13,3 @@ app.use(router)
app.use(i18n) app.use(i18n)
app.mount('#app') app.mount('#app')

View File

@ -1,4 +1,4 @@
@import "tailwindcss"; @import 'tailwindcss';
@plugin "tailwindcss-animate"; @plugin "tailwindcss-animate";
@ -24,6 +24,7 @@
--color-accent: var(--accent); --color-accent: var(--accent);
--color-accent-foreground: var(--accent-foreground); --color-accent-foreground: var(--accent-foreground);
--color-destructive: var(--destructive); --color-destructive: var(--destructive);
--color-destructive-foreground: var(--destructive-foreground);
--color-border: var(--border); --color-border: var(--border);
--color-input: var(--input); --color-input: var(--input);
--color-ring: var(--ring); --color-ring: var(--ring);
@ -44,78 +45,123 @@
:root { :root {
--radius: 0.625rem; --radius: 0.625rem;
/* Base Colors - Light Mode (oklch format) */
--background: oklch(1 0 0); --background: oklch(1 0 0);
--foreground: oklch(0.145 0 0); --foreground: oklch(0.145 0 0);
--card: oklch(1 0 0); --card: oklch(1 0 0);
--card-foreground: oklch(0.145 0 0); --card-foreground: oklch(0.145 0 0);
--popover: oklch(1 0 0); --popover: oklch(1 0 0);
--popover-foreground: oklch(0.145 0 0); --popover-foreground: oklch(0.145 0 0);
--primary: oklch(0.205 0 0);
/* Primary - Royal Blue #3f51b5 */
--primary: oklch(0.488 0.15 264.5);
--primary-foreground: oklch(0.985 0 0); --primary-foreground: oklch(0.985 0 0);
--secondary: oklch(0.97 0 0);
--secondary-foreground: oklch(0.205 0 0); /* Secondary - Soft Purple #9fa8da */
--secondary: oklch(0.7 0.08 265);
--secondary-foreground: oklch(0.145 0 0);
/* Accent - Vibrant Blue #5c6bc0 */
--accent: oklch(0.58 0.12 265);
--accent-foreground: oklch(0.985 0 0);
/* Muted - Neutral Gray */
--muted: oklch(0.97 0 0); --muted: oklch(0.97 0 0);
--muted-foreground: oklch(0.556 0 0); --muted-foreground: oklch(0.556 0 0);
--accent: oklch(0.97 0 0);
--accent-foreground: oklch(0.205 0 0); /* Destructive - Soft Red #ef5350 */
--destructive: oklch(0.577 0.245 27.325); --destructive: oklch(0.63 0.22 27);
--destructive-foreground: oklch(0.985 0 0);
/* Border & Input */
--border: oklch(0.922 0 0); --border: oklch(0.922 0 0);
--input: oklch(0.922 0 0); --input: oklch(0.922 0 0);
--ring: oklch(0.708 0 0); --ring: oklch(0.488 0.15 264.5);
--chart-1: oklch(0.646 0.222 41.116);
--chart-2: oklch(0.6 0.118 184.704); /* Chart Colors - Royal Blue variations */
--chart-3: oklch(0.398 0.07 227.392); --chart-1: oklch(0.488 0.15 264.5);
--chart-4: oklch(0.828 0.189 84.429); --chart-2: oklch(0.58 0.12 265);
--chart-5: oklch(0.769 0.188 70.08); --chart-3: oklch(0.64 0.1 265);
--chart-4: oklch(0.7 0.08 265);
--chart-5: oklch(0.78 0.06 265);
/* Sidebar Colors */
--sidebar: oklch(0.985 0 0); --sidebar: oklch(0.985 0 0);
--sidebar-foreground: oklch(0.145 0 0); --sidebar-foreground: oklch(0.145 0 0);
--sidebar-primary: oklch(0.205 0 0); --sidebar-primary: oklch(0.488 0.15 264.5);
--sidebar-primary-foreground: oklch(0.985 0 0); --sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.97 0 0); --sidebar-accent: oklch(0.97 0 0);
--sidebar-accent-foreground: oklch(0.205 0 0); --sidebar-accent-foreground: oklch(0.145 0 0);
--sidebar-border: oklch(0.922 0 0); --sidebar-border: oklch(0.922 0 0);
--sidebar-ring: oklch(0.708 0 0); --sidebar-ring: oklch(0.488 0.15 264.5);
} }
.dark { .dark {
--background: oklch(0.145 0 0); /* Base Colors - Dark Mode (oklch format) - Smooth & Soft */
--foreground: oklch(0.985 0 0); --background: oklch(0.17 0.012 265);
--card: oklch(0.205 0 0); --foreground: oklch(0.94 0.008 265);
--card-foreground: oklch(0.985 0 0);
--popover: oklch(0.205 0 0); --card: oklch(0.25 0.018 265);
--popover-foreground: oklch(0.985 0 0); --card-foreground: oklch(0.93 0.008 265);
--primary: oklch(0.922 0 0);
--primary-foreground: oklch(0.205 0 0); --popover: oklch(0.24 0.018 265);
--secondary: oklch(0.269 0 0); --popover-foreground: oklch(0.93 0.008 265);
--secondary-foreground: oklch(0.985 0 0);
--muted: oklch(0.269 0 0); /* Primary - Soft Royal Blue for dark mode */
--muted-foreground: oklch(0.708 0 0); --primary: oklch(0.67 0.13 267);
--accent: oklch(0.269 0 0); --primary-foreground: oklch(0.96 0.005 265);
--accent-foreground: oklch(0.985 0 0);
--destructive: oklch(0.704 0.191 22.216); /* Secondary - Gentle Lavender */
--border: oklch(1 0 0 / 10%); --secondary: oklch(0.62 0.1 268);
--input: oklch(1 0 0 / 15%); --secondary-foreground: oklch(0.96 0.005 265);
--ring: oklch(0.556 0 0);
--chart-1: oklch(0.488 0.243 264.376); /* Accent - Muted Purple */
--chart-2: oklch(0.696 0.17 162.48); --accent: oklch(0.72 0.08 270);
--chart-3: oklch(0.769 0.188 70.08); --accent-foreground: oklch(0.18 0.012 265);
--chart-4: oklch(0.627 0.265 303.9);
--chart-5: oklch(0.645 0.246 16.439); /* Muted - Soft Gray with hint of blue */
--sidebar: oklch(0.205 0 0); --muted: oklch(0.28 0.012 265);
--sidebar-foreground: oklch(0.985 0 0); --muted-foreground: oklch(0.73 0.01 265);
--sidebar-primary: oklch(0.488 0.243 264.376);
--sidebar-primary-foreground: oklch(0.985 0 0); /* Destructive - Softer Coral Red */
--sidebar-accent: oklch(0.269 0 0); --destructive: oklch(0.64 0.19 25);
--sidebar-accent-foreground: oklch(0.985 0 0); --destructive-foreground: oklch(0.96 0.005 265);
--sidebar-border: oklch(1 0 0 / 10%);
--sidebar-ring: oklch(0.556 0 0); /* Border & Input - Subtle visibility */
--border: oklch(0.35 0.015 265);
--input: oklch(0.25 0.018 265);
--ring: oklch(0.67 0.13 267);
/* Chart Colors - Harmonious gradient */
--chart-1: oklch(0.67 0.13 267);
--chart-2: oklch(0.7 0.11 270);
--chart-3: oklch(0.74 0.09 273);
--chart-4: oklch(0.62 0.14 264);
--chart-5: oklch(0.55 0.16 261);
/* Sidebar Colors */
--sidebar: oklch(0.19 0.013 265);
--sidebar-foreground: oklch(0.93 0.008 265);
--sidebar-primary: oklch(0.67 0.13 267);
--sidebar-primary-foreground: oklch(0.96 0.005 265);
--sidebar-accent: oklch(0.26 0.012 265);
--sidebar-accent-foreground: oklch(0.93 0.008 265);
--sidebar-border: oklch(0.32 0.015 265);
--sidebar-ring: oklch(0.67 0.13 267);
} }
@layer base { @layer base {
* { * {
@apply border-border outline-ring/50; @apply border-border;
} }
body { body {
@apply bg-background text-foreground; @apply bg-background text-foreground;
/* Mobile-first optimizations */
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: transparent;
} }
} }

View File

@ -1,6 +1,4 @@
<script setup lang="ts"> <script setup lang="ts">
import { useI18n } from 'vue-i18n'
const { t } = useI18n() const { t } = useI18n()
</script> </script>

View File

@ -1,6 +1,4 @@
<script setup lang="ts"> <script setup lang="ts">
import { useI18n } from 'vue-i18n'
const { t } = useI18n() const { t } = useI18n()
</script> </script>

View File

@ -1,7 +1,4 @@
<script setup lang="ts"> <script setup lang="ts">
import { useRouter } from 'vue-router'
import { Button } from '@/components/ui/button'
const router = useRouter() const router = useRouter()
const goHome = () => { const goHome = () => {

View File

@ -1,4 +1,5 @@
// Tailwind CSS v4 uses CSS-first configuration // Tailwind CSS v4 uses CSS-first configuration
// This file is kept for shadcn-vue compatibility but configuration is done in CSS // This file is kept for shadcn-vue compatibility but configuration is done in CSS
export default {} export default {
// No prefix for Tailwind v4 CSS-first approach
}

View File

@ -1,14 +1,10 @@
{ {
"extends": "@vue/tsconfig/tsconfig.dom.json", "extends": "@vue/tsconfig/tsconfig.dom.json",
"compilerOptions": { "compilerOptions": {
"types": [ "types": ["vite/client"],
"vite/client"
],
"baseUrl": ".", "baseUrl": ".",
"paths": { "paths": {
"@/*": [ "@/*": ["./src/*"]
"./src/*"
]
}, },
/* Linting */ /* Linting */
"strict": true, "strict": true,
@ -19,6 +15,8 @@
"include": [ "include": [
"src/**/*.ts", "src/**/*.ts",
"src/**/*.tsx", "src/**/*.tsx",
"src/**/*.vue" "src/**/*.vue",
"src/auto-imports.d.ts",
"src/components.d.ts"
] ]
} }

View File

@ -2,10 +2,44 @@ import path from 'node:path'
import { defineConfig } from 'vite' import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite' import tailwindcss from '@tailwindcss/vite'
import vue from '@vitejs/plugin-vue' import vue from '@vitejs/plugin-vue'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
// https://vite.dev/config/ // https://vite.dev/config/
export default defineConfig({ export default defineConfig({
plugins: [vue(), tailwindcss()], plugins: [
vue(),
tailwindcss(),
// Auto import Vue APIs (ref, computed, watch, etc.)
AutoImport({
imports: [
'vue',
'vue-router',
'pinia',
'@vueuse/core',
{
'vue-i18n': ['useI18n'],
},
],
dts: 'src/auto-imports.d.ts',
dirs: ['src/composables', 'src/stores'],
vueTemplate: true,
eslintrc: {
enabled: true,
filepath: './.eslintrc-auto-import.json',
},
}),
// Auto import components
Components({
dts: 'src/components.d.ts',
dirs: ['src/components'],
extensions: ['vue'],
deep: true,
directoryAsNamespace: false,
}),
],
resolve: { resolve: {
alias: { alias: {
'@': path.resolve(__dirname, './src'), '@': path.resolve(__dirname, './src'),