diff --git a/ui/quasar.config.js.temporary.compiled.1770999604634.mjs b/ui/quasar.config.js.temporary.compiled.1770999604634.mjs new file mode 100644 index 0000000..b4f411c --- /dev/null +++ b/ui/quasar.config.js.temporary.compiled.1770999604634.mjs @@ -0,0 +1,83 @@ +/* eslint-disable */ +/** + * THIS FILE IS GENERATED AUTOMATICALLY. + * 1. DO NOT edit this file directly as it won't do anything. + * 2. EDIT the original quasar.config file INSTEAD. + * 3. DO NOT git commit this file. It should be ignored. + * + * This file is still here because there was an error in + * the original quasar.config file and this allows you to + * investigate the Node.js stack error. + * + * After you fix the original file, this file will be + * deleted automatically. + **/ + + +// quasar.config.js +import { defineConfig } from "@quasar/app-webpack/wrappers"; +var quasar_config_default = defineConfig(() => { + return { + // ✅ UYGULAMA KİMLİĞİ (WEB'DE GÖRÜNEN İSİM) + productName: "Baggi BSS", + productDescription: "Baggi Tekstil Business Support System", + // 🔹 Boot dosyaları + boot: ["axios", "dayjs"], + // 🔹 Global CSS + css: ["app.css"], + // 🔹 Ekstra icon/font setleri + extras: [ + "roboto-font", + "material-icons" + ], + // 🔹 Derleme Ayarları + build: { + vueRouterMode: "hash", + env: { + VITE_API_BASE_URL: "http://localhost:8080/api" + }, + esbuildTarget: { + browser: ["es2022", "firefox115", "chrome115", "safari14"], + node: "node20" + } + }, + // 🔹 Geliştirme Sunucusu + devServer: { + server: { type: "http" }, + port: 9e3, + open: true + }, + // 🔹 Quasar Framework ayarları + framework: { + config: { + notify: { position: "top", timeout: 2500 } + }, + lang: "tr", + plugins: ["Loading", "Dialog", "Notify"] + }, + animations: [], + ssr: { + prodPort: 3e3, + middlewares: ["render"], + pwa: false + }, + pwa: { + workboxMode: "GenerateSW" + }, + capacitor: { + hideSplashscreen: true + }, + electron: { + preloadScripts: ["electron-preload"], + inspectPort: 5858, + bundler: "packager", + builder: { appId: "baggisowtfaresystem" } + }, + bex: { + extraScripts: [] + } + }; +}); +export { + quasar_config_default as default +}; diff --git a/ui/src/pages/OrderBulkClose.vue b/ui/src/pages/OrderBulkClose.vue new file mode 100644 index 0000000..46c9f2f --- /dev/null +++ b/ui/src/pages/OrderBulkClose.vue @@ -0,0 +1,296 @@ + + + + + diff --git a/ui/src/pages/RoleDepartmentPermissionGateway.vue b/ui/src/pages/RoleDepartmentPermissionGateway.vue new file mode 100644 index 0000000..7f9615f --- /dev/null +++ b/ui/src/pages/RoleDepartmentPermissionGateway.vue @@ -0,0 +1,55 @@ + + + + + diff --git a/ui/src/pages/RoleDepartmentPermissionList.vue b/ui/src/pages/RoleDepartmentPermissionList.vue new file mode 100644 index 0000000..fcba1a9 --- /dev/null +++ b/ui/src/pages/RoleDepartmentPermissionList.vue @@ -0,0 +1,591 @@ + + + + + diff --git a/ui/src/stores/RoleDeptPermissionListStore.js b/ui/src/stores/RoleDeptPermissionListStore.js new file mode 100644 index 0000000..820c3d9 --- /dev/null +++ b/ui/src/stores/RoleDeptPermissionListStore.js @@ -0,0 +1,93 @@ +import { defineStore } from 'pinia' +import api from 'src/services/api' + +let lastRequestId = 0 + +export const useRoleDeptPermissionListStore = defineStore('roleDeptPermissionList', { + state: () => ({ + modules: [], + moduleActions: [], + rows: [], + loading: false, + error: null, + filters: { + search: '' + } + }), + + getters: { + totalCount (state) { + return state.rows.length + } + }, + + actions: { + async fetchRows () { + const rid = ++lastRequestId + this.loading = true + this.error = null + + try { + const search = String(this.filters.search || '').trim() + const params = {} + if (search) params.search = search + + const res = await api.get('/role-dept-permissions/list', { params }) + + if (rid !== lastRequestId) { + return + } + + const payload = res?.data || {} + this.modules = Array.isArray(payload?.modules) + ? payload.modules.map((m) => ({ + value: String(m.value || '').toLowerCase().trim(), + label: String(m.label || '') + })).filter((m) => m.value) + : [] + + this.moduleActions = Array.isArray(payload?.module_actions) + ? payload.module_actions.map((a) => ({ + module_code: String(a.module_code || '').toLowerCase().trim(), + action: String(a.action || '').toLowerCase().trim() + })).filter((a) => a.module_code && a.action) + : [] + + const rawRows = Array.isArray(payload?.rows) + ? payload.rows + : Array.isArray(res?.data) ? res.data : [] + + this.rows = rawRows.map((r) => { + const rawFlags = (r?.module_flags && typeof r.module_flags === 'object') + ? r.module_flags + : {} + const flags = {} + Object.keys(rawFlags).forEach((k) => { + flags[String(k).toLowerCase().trim()] = Boolean(rawFlags[k]) + }) + + return { + role_id: Number(r.role_id || 0), + role_title: r.role_title || '', + department_code: r.department_code || '', + department_title: r.department_title || '', + module_flags: flags + } + }) + } catch (err) { + if (rid !== lastRequestId) return + this.modules = [] + this.moduleActions = [] + this.rows = [] + this.error = + err?.response?.data || + err?.message || + 'Yetki listesi alınamadı' + } finally { + if (rid === lastRequestId) { + this.loading = false + } + } + } + } +}) diff --git a/ui/src/stores/orderBulkCloseStore.js b/ui/src/stores/orderBulkCloseStore.js new file mode 100644 index 0000000..708041c --- /dev/null +++ b/ui/src/stores/orderBulkCloseStore.js @@ -0,0 +1,127 @@ +import { defineStore } from 'pinia' +import api from 'src/services/api' + +export const useOrderBulkCloseStore = defineStore('orderBulkClose', { + state: () => ({ + orders: [], + selectedOrderNumbers: [], + search: '', + loading: false, + closing: false, + error: null + }), + + getters: { + selectedCount (state) { + return state.selectedOrderNumbers.length + }, + + totalCount (state) { + return state.orders.length + } + }, + + actions: { + isSelected (orderNumber) { + return this.selectedOrderNumbers.includes(orderNumber) + }, + + setSelected (orderNumber, selected) { + if (!orderNumber) return + + if (selected) { + if (!this.selectedOrderNumbers.includes(orderNumber)) { + this.selectedOrderNumbers.push(orderNumber) + } + return + } + + this.selectedOrderNumbers = this.selectedOrderNumbers.filter( + (n) => n !== orderNumber + ) + }, + + toggleSelectMany (orderNumbers, selected) { + const clean = Array.from( + new Set((orderNumbers || []).filter(Boolean)) + ) + + if (selected) { + const current = new Set(this.selectedOrderNumbers) + clean.forEach((n) => current.add(n)) + this.selectedOrderNumbers = Array.from(current) + return + } + + const block = new Set(clean) + this.selectedOrderNumbers = this.selectedOrderNumbers.filter( + (n) => !block.has(n) + ) + }, + + clearSelection () { + this.selectedOrderNumbers = [] + }, + + async fetchOrders () { + this.loading = true + this.error = null + + try { + const search = String(this.search || '').trim() + const params = {} + if (search) params.search = search + + const res = await api.get('/orders/close-ready', { params }) + this.orders = Array.isArray(res?.data) ? res.data : [] + + // new list disinda kalan secimleri temizle + const available = new Set(this.orders.map((o) => o.OrderNumber)) + this.selectedOrderNumbers = this.selectedOrderNumbers.filter( + (n) => available.has(n) + ) + } catch (err) { + this.orders = [] + this.error = + err?.response?.data || + err?.message || + 'Siparişler alınamadı' + } finally { + this.loading = false + } + }, + + async closeSelectedOrders () { + if (!this.selectedOrderNumbers.length) { + return { affected: 0 } + } + + this.closing = true + this.error = null + + try { + const payload = { + order_numbers: this.selectedOrderNumbers + } + + const res = await api.post('/orders/bulk-close', payload) + const affected = Number(res?.data?.affected || 0) + + // local optimizasyon: secilenleri listeden dus + const selected = new Set(this.selectedOrderNumbers) + this.orders = this.orders.filter((o) => !selected.has(o.OrderNumber)) + this.selectedOrderNumbers = [] + + return { affected } + } catch (err) { + this.error = + err?.response?.data || + err?.message || + 'Toplu kapatma başarısız' + throw err + } finally { + this.closing = false + } + } + } +})