Files
front/src/components/Istochnik_section/Istochnik.vue
Игорь Бандурист d10a74eea5
All checks were successful
continuous-integration/drone/push Build is passing
полный рефакторинг всей системы
2026-05-08 17:01:37 +10:00

168 lines
4.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="w-full sm:w-4/5 dark:text-neutral-300">
<div
class="bg-white flex flex-col lg:flex-row justify-between items-center p-3 lg:p-5 dark:bg-gray-800 gap-3 lg:gap-4"
>
<div class="flex flex-row w-full lg:w-auto">
<div class="relative w-2/3">
<img
v-if="isDark"
src="https://img.icons8.com/?size=100&id=WwWusvLMTFd7&format=png&color=000000"
class="absolute top-1/2 -translate-y-1/2 left-3 h-5"
alt=""
/>
<img
v-else
src="https://img.icons8.com/?size=100&id=zR5EBMqZTIBz&format=png&color=000000"
class="absolute top-1/2 -translate-y-1/2 left-3 h-5"
alt=""
/>
<input
v-model="searchQuery"
type="text"
placeholder="Поиск..."
class="w-full h-12 dark:bg-gray-900 border-slate-100 shadow rounded-xl p-3 pl-11"
/>
</div>
<select
v-model="activeCategory"
@change="onFilterChange"
class="w-1/3 h-12 dark:bg-gray-900 border-slate-100 shadow rounded-xl p-3 ml-2"
>
<option value="all">Все</option>
<option
v-for="category in categories"
:key="category"
:value="category"
>
{{ category }}
</option>
</select>
</div>
<div
class="flex flex-row w-full lg:w-auto gap-2 p-2 bg-gray-50 dark:bg-gray-700 rounded-xl border border-gray-200 dark:border-gray-600"
>
<input
v-model="newSourceUrl"
type="text"
placeholder="https://example.com"
class="flex-1 h-12 dark:bg-gray-900 border-slate-100 shadow rounded-xl p-3 min-w-0"
/>
<select
v-model="newSourceCategory"
class="w-28 h-12 dark:bg-gray-900 border-slate-100 shadow rounded-xl p-3 min-w-30"
>
<option value="" disabled>Категория</option>
<option
v-for="category in categories"
:key="category"
:value="category"
>
{{ category }}
</option>
</select>
<button
type="button"
@click="addSource"
class="w-20 h-12 bg-green-600 text-white px-2 rounded-xl shadow hover:bg-green-700 cursor-pointer whitespace-nowrap"
>
+ Add
</button>
</div>
</div>
<div class="p-4 grid gap-2 grid-cols-1 xl:grid-cols-2 2xl:grid-cols-3">
<div
v-for="source in filteredSources"
:key="source.url"
class="mb-4 hover:-translate-y-2 hover:shadow-2xl transition"
>
<SourceCard
:source="source"
@sourceStarted="handleSourceStarted"
@sourceDeleted="handleSourceDeleted"
/>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, computed } from 'vue'
import SourceCard from './Istochnik_one_kard.vue'
import { useDarkMode } from '@/composables/useDarkMode.js'
import { fetchCategories, fetchSources, addSource as apiAddSource } from '@/services/sourceService.js'
const { isDark } = useDarkMode()
const newSourceUrl = ref('')
const newSourceCategory = ref('')
const categories = ref([])
const searchQuery = ref('')
const sources = ref([])
const activeCategory = ref('all')
const filteredSources = computed(() => {
if (!searchQuery.value) return sources.value
const q = searchQuery.value.toLowerCase()
return sources.value.filter(
(source) =>
source.url.toLowerCase().includes(q) ||
source.promt.toLowerCase().includes(q),
)
})
async function loadCategories() {
try {
categories.value = await fetchCategories()
} catch (err) {
console.error('Ошибка загрузки категорий:', err)
}
}
async function loadSources(category = 'all') {
try {
sources.value = await fetchSources(category)
} catch (err) {
console.error('Ошибка загрузки источников:', err)
}
}
async function addSource() {
if (!newSourceUrl.value.trim() || !newSourceCategory.value) {
alert('Заполните все поля')
return
}
try {
await apiAddSource(newSourceUrl.value, newSourceCategory.value)
newSourceUrl.value = ''
newSourceCategory.value = ''
await loadSources(activeCategory.value)
} catch (err) {
console.error('Ошибка добавления источника:', err)
alert('Ошибка при добавлении источника')
}
}
function onFilterChange() {
loadSources(activeCategory.value)
}
function handleSourceStarted(url) {
console.log('Парсинг запущен для:', url)
}
function handleSourceDeleted(deletedUrl) {
sources.value = sources.value.filter((source) => source.url !== deletedUrl)
}
onMounted(() => {
loadCategories()
loadSources('all')
})
</script>