163 lines
5.0 KiB
Vue
163 lines
5.0 KiB
Vue
<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"
|
||
>
|
||
<!-- Блок 1: Поиск + Фильтр (всегда в ряд) -->
|
||
<div class="flex flex-row w-full lg:w-auto">
|
||
<div class="relative w-2/3">
|
||
<img
|
||
v-if="isDarkMode"
|
||
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"
|
||
/>
|
||
<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"
|
||
/>
|
||
<input
|
||
v-model="poisk"
|
||
type="text"
|
||
placeholder="Поиск..."
|
||
class="w-full h-12 dark:bg-gray-900 border-slate-100 shadow rounded-xl p-3 pl-11"
|
||
/>
|
||
</div>
|
||
<select
|
||
@change="onfilterItems($event.target.value)"
|
||
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>
|
||
|
||
<!-- Блок 2: URL + Категория + Кнопка (всегда в ряд) -->
|
||
<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
|
||
@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 lg:grid-cols-2 2xl:grid-cols-3">
|
||
<div v-for="source in filteredSources" :key="source.url" class="mb-4">
|
||
<Istochnik_one_kard :source="source" />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, onMounted, computed } from "vue";
|
||
import axios from "axios";
|
||
import Istochnik_one_kard from "./Istochnik_one_kard.vue";
|
||
|
||
const isDarkMode = ref(false);
|
||
const newSourceUrl = ref("");
|
||
const newSourceCategory = ref("");
|
||
const categories = ref([]);
|
||
const poisk = ref("");
|
||
const sources = ref([]);
|
||
|
||
const fetchCategories = async () => {
|
||
try {
|
||
const data = await axios.get(
|
||
"https://allowlgroup.ru/api/8001/categories_promt",
|
||
);
|
||
categories.value = data.data;
|
||
} catch (err) {
|
||
console.error("Ошибка загрузки категорий:", err);
|
||
}
|
||
};
|
||
|
||
const fetchSources = async () => {
|
||
try {
|
||
const data = await axios.get("https://allowlgroup.ru/api/8001/all_sources");
|
||
sources.value = data.data.sources || [];
|
||
} catch (err) {
|
||
console.error("Ошибка загрузки источников:", err);
|
||
}
|
||
};
|
||
|
||
const filteredSources = computed(() => {
|
||
if (!poisk.value) return sources.value;
|
||
return sources.value.filter(
|
||
(source) =>
|
||
source.url.toLowerCase().includes(poisk.value.toLowerCase()) ||
|
||
source.promt.toLowerCase().includes(poisk.value.toLowerCase()),
|
||
);
|
||
});
|
||
|
||
const addSource = async () => {
|
||
if (!newSourceUrl.value.trim() || !newSourceCategory.value) {
|
||
alert("Заполните все поля");
|
||
return;
|
||
}
|
||
|
||
try {
|
||
await axios.post("https://allowlgroup.ru/api/8001/add_sources", {
|
||
url: newSourceUrl.value,
|
||
promt: newSourceCategory.value,
|
||
});
|
||
newSourceUrl.value = "";
|
||
newSourceCategory.value = "";
|
||
fetchSources(); // Обновляем список после добавления
|
||
} catch (err) {
|
||
console.error("Ошибка добавления источника:", err);
|
||
alert("Ошибка при добавлении источника");
|
||
}
|
||
};
|
||
|
||
const onfilterItems = (filterValue) => {
|
||
console.log("Фильтр:", filterValue);
|
||
};
|
||
|
||
onMounted(() => {
|
||
isDarkMode.value = document.documentElement.classList.contains("dark");
|
||
const mutationObserver = new MutationObserver(() => {
|
||
isDarkMode.value = document.documentElement.classList.contains("dark");
|
||
});
|
||
mutationObserver.observe(document.documentElement, {
|
||
attributes: true,
|
||
attributeFilter: ["class"],
|
||
});
|
||
|
||
fetchCategories();
|
||
fetchSources();
|
||
});
|
||
</script>
|