+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
Выбор ресторанов
+
+
+
+
+
+
+
+
+
{{ rest.name }}
+
{{ rest.host }}
+
+
+
+
+
+ Рестораны не найдены
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Подключение к БД
+
+
+
+
+
+
+
{{ conn.name }}
+
{{ conn.type }} | {{ conn.host }}:{{ conn.port }}/{{ conn.database }}
+
+
+
+
+ Подключения не найдены
+
+
+
+
+
+
+
+
+
+
@@ -395,7 +508,7 @@ import { useNotification } from '@/composables/useNotification'
const { showNotification } = useNotification()
-// Типы (без изменений)
+// Типы
interface ApiColumn {
fieldKey: string
fieldKeyNormal: string
@@ -456,7 +569,23 @@ interface IikoConfig {
filters: Record
}
-// Refs
+interface Restaurant {
+ id: number
+ name: string
+ host: string
+}
+
+interface DbConnection {
+ id: number
+ name: string
+ type: string
+ host: string
+ port: number
+ database: string
+ user: string
+}
+
+// Состояния
const columnsData = ref([])
const loading = ref(true)
const error = ref(null)
@@ -477,22 +606,126 @@ const reportType = ref<'SALES' | 'DELIVERIES' | 'TRANSACTIONS'>('SALES')
const buildSummary = ref(false)
const searchQuery = ref('')
const activeTab = ref<'table' | 'sql'>('table')
+const collapsed = ref({ number: false, category: false, filter: false })
-// Состояние сворачивания секций
-const collapsed = ref({
- number: false,
- category: false,
- filter: false
+const queryName = ref('') // имя запроса
+const selectedRestaurants = ref([]) // выбранные рестораны
+const selectedDbConnection = ref(null) // выбранное подключение к БД
+
+// Модалка ресторанов
+const restaurantModal = ref({
+ show: false,
+ search: ''
})
+const restaurantsList = ref([])
+const tempSelectedRestaurants = ref([])
+
+// Модалка подключения к БД
+const dbConnectionModal = ref({
+ show: false,
+ search: ''
+})
+const dbConnectionsList = ref([])
+const tempSelectedDbConnection = ref(null)
+
+// Вспомогательные вычисляемые свойства для модалок
+const filteredRestaurantsList = computed(() => {
+ if (!restaurantModal.value.search.trim()) return restaurantsList.value
+ const lower = restaurantModal.value.search.toLowerCase()
+ return restaurantsList.value.filter(r =>
+ r.name.toLowerCase().includes(lower) || r.host.toLowerCase().includes(lower)
+ )
+})
+
+const filteredDbConnectionsList = computed(() => {
+ if (!dbConnectionModal.value.search.trim()) return dbConnectionsList.value
+ const lower = dbConnectionModal.value.search.toLowerCase()
+ return dbConnectionsList.value.filter(c => c.name.toLowerCase().includes(lower))
+})
+
+// Функции для ресторанов
+const openRestaurantModal = async () => {
+ await loadRestaurants()
+ // Копируем текущие выбранные рестораны во временный массив
+ tempSelectedRestaurants.value = [...selectedRestaurants.value]
+ restaurantModal.value.search = ''
+ restaurantModal.value.show = true
+}
+
+const closeRestaurantModal = () => {
+ restaurantModal.value.show = false
+}
+
+const isRestaurantSelected = (rest: Restaurant) => {
+ return tempSelectedRestaurants.value.some(r => r.id === rest.id)
+}
+
+const toggleRestaurantSelection = (rest: Restaurant) => {
+ const idx = tempSelectedRestaurants.value.findIndex(r => r.id === rest.id)
+ if (idx === -1) {
+ tempSelectedRestaurants.value.push(rest)
+ } else {
+ tempSelectedRestaurants.value.splice(idx, 1)
+ }
+}
+
+const confirmRestaurants = () => {
+ selectedRestaurants.value = [...tempSelectedRestaurants.value]
+ closeRestaurantModal()
+ showNotification('Рестораны выбраны', 'success')
+}
+
+// Функции для подключения к БД
+const openDbConnectionModal = async () => {
+ await loadDbConnections()
+ tempSelectedDbConnection.value = selectedDbConnection.value ? { ...selectedDbConnection.value } : null
+ dbConnectionModal.value.search = ''
+ dbConnectionModal.value.show = true
+}
+
+const closeDbConnectionModal = () => {
+ dbConnectionModal.value.show = false
+}
+
+const selectDbConnection = (conn: DbConnection) => {
+ tempSelectedDbConnection.value = conn
+}
+
+const confirmDbConnection = () => {
+ selectedDbConnection.value = tempSelectedDbConnection.value ? { ...tempSelectedDbConnection.value } : null
+ closeDbConnectionModal()
+ showNotification('Подключение к БД выбрано', 'success')
+}
+
+// Загрузка данных для модалок
+const loadRestaurants = async () => {
+ try {
+ const res = await fetch('/api/admin/restaurants')
+ if (!res.ok) throw new Error('Ошибка загрузки ресторанов')
+ const data = await res.json()
+ restaurantsList.value = data
+ } catch (err: any) {
+ showNotification('Не удалось загрузить список ресторанов', 'error')
+ }
+}
+
+const loadDbConnections = async () => {
+ try {
+ const res = await fetch('/api/admin/database-connections')
+ if (!res.ok) throw new Error('Ошибка загрузки подключений')
+ const data = await res.json()
+ dbConnectionsList.value = data
+ } catch (err: any) {
+ showNotification('Не удалось загрузить список подключений к БД', 'error')
+ }
+}
const toggleSection = (section: 'number' | 'category' | 'filter') => {
collapsed.value[section] = !collapsed.value[section]
}
-// Модалка сброса
const resetModal = ref({ show: false })
-// Drag & drop state
let draggedItem: AvailableField | null = null
let draggedFromSidebar = true
const dragOverZone = ref(null)
@@ -784,6 +1017,9 @@ const confirmReset = () => {
tableNameTouched.value = false
buildSummary.value = false
searchQuery.value = ''
+ queryName.value = ''
+ selectedRestaurants.value = []
+ selectedDbConnection.value = null
showNotification('Все настройки сброшены', 'success')
}