feat(frontend): Vue 3 + wa-sqlite + sync engine + auth + layouts
- package.json with Vue 3, Pinia, vue-router, wa-sqlite, Tailwind CSS 4, Vite - wa-sqlite database layer with IDBBatchAtomicVFS (offline-first) - Full schema mirroring backend tables (vehicles, orders, invoices, etc.) - SyncEngine: fullSync, incrementalSync, pushQueue for offline queue - Auth store with JWT parsing, login/register, plan tier detection - Router with all routes and auth navigation guards - AppLayout (sidebar desktop / bottom nav mobile) + AuthLayout - Login/Register views connected to API contract - SyncIndicator component (online/offline status) - Reactive SQL query composable (useSqlQuery) - Placeholder views for dashboard, orders, vehicles, appointments, catalog, settings Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
43
frontend/src/db/database.js
Normal file
43
frontend/src/db/database.js
Normal file
@@ -0,0 +1,43 @@
|
||||
import SQLiteESMFactory from '@journeyapps/wa-sqlite/dist/wa-sqlite-async.mjs'
|
||||
import { IDBBatchAtomicVFS } from '@journeyapps/wa-sqlite/src/examples/IDBBatchAtomicVFS.js'
|
||||
import * as SQLite from '@journeyapps/wa-sqlite'
|
||||
import { SCHEMA_SQL } from './schema.js'
|
||||
|
||||
let db = null
|
||||
let sqlite3 = null
|
||||
const tableListeners = new Map()
|
||||
|
||||
export async function initDatabase() {
|
||||
if (db) return db
|
||||
const module = await SQLiteESMFactory()
|
||||
sqlite3 = SQLite.Factory(module)
|
||||
const vfs = await IDBBatchAtomicVFS.create('roaauto', module)
|
||||
sqlite3.vfs_register(vfs, true)
|
||||
db = await sqlite3.open_v2('roaauto.db',
|
||||
SQLite.SQLITE_OPEN_READWRITE | SQLite.SQLITE_OPEN_CREATE, 'roaauto')
|
||||
for (const sql of SCHEMA_SQL.split(';').filter(s => s.trim())) {
|
||||
await sqlite3.exec(db, sql)
|
||||
}
|
||||
return db
|
||||
}
|
||||
|
||||
export function notifyTableChanged(table) {
|
||||
tableListeners.get(table)?.forEach(cb => cb())
|
||||
}
|
||||
|
||||
export function onTableChange(table, cb) {
|
||||
if (!tableListeners.has(table)) tableListeners.set(table, new Set())
|
||||
tableListeners.get(table).add(cb)
|
||||
return () => tableListeners.get(table).delete(cb)
|
||||
}
|
||||
|
||||
export async function execSQL(sql, params = []) {
|
||||
if (!db) throw new Error('DB not initialized')
|
||||
const results = []
|
||||
await sqlite3.exec(db, sql, (row, cols) => {
|
||||
const obj = {}
|
||||
cols.forEach((c, i) => { obj[c] = row[i] })
|
||||
results.push(obj)
|
||||
})
|
||||
return results
|
||||
}
|
||||
Reference in New Issue
Block a user