Frontend: Composables useConfirm/useChat/usePolling; Guide-Chat abbrechbar

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
team3
2026-06-12 08:12:11 +02:00
parent 601237bbbf
commit 5c35939eab
6 changed files with 178 additions and 94 deletions

View File

@@ -1,6 +1,7 @@
<script setup>
import { ref, computed, watch, onMounted, onUnmounted, nextTick } from 'vue'
import { ref, computed, watch, onMounted, nextTick } from 'vue'
import { fetchGuides, fetchTopics, createTopic as apiCreateTopic, deleteTopic as apiDeleteTopic, createGuide as apiCreate, deleteGuide, cancelGuide as apiCancel, fetchBausteineStatus, fetchActiveBausteine, createBausteine as apiCreateBausteine, cancelBausteine as apiCancelBausteine, deleteBausteine as apiDeleteBausteine, fetchProjects, deleteProject as apiDeleteProject, fetchProviders, fetchStats, fetchTopicFortschritt } from './api.js'
import { usePolling } from './composables/usePolling.js'
import TopicSidebar from './components/TopicSidebar.vue'
import TopicDetail from './components/TopicDetail.vue'
import ElementsSidebar from './components/ElementsSidebar.vue'
@@ -56,7 +57,6 @@ async function loadProviders() {
console.error('Fehler beim Laden der Provider:', e)
}
}
let pollTimer = null
function applyTheme() {
document.documentElement.classList.toggle('dark', darkMode.value)
@@ -158,7 +158,7 @@ async function loadBausteine() {
bausteine.value = { ...EMPTY_BAUSTEINE }
fortschritt.value = {}
}
if (activeBausteine.value.length && !pollTimer) startPolling()
if (activeBausteine.value.length && !polling.running()) startPolling()
} catch (e) {
console.error('Fehler beim Laden der Bausteine:', e)
}
@@ -276,20 +276,11 @@ async function handleDeleteGuide(guideId, slots = false) {
await loadGuides()
}
function startPolling() {
stopPolling()
pollTimer = setInterval(async () => {
await Promise.all([loadGuides(), loadBausteine(), loadTopics()])
if (!hasActiveGuides.value && !activeBausteine.value.length) stopPolling()
}, 3000)
}
function stopPolling() {
if (pollTimer) {
clearInterval(pollTimer)
pollTimer = null
}
}
const polling = usePolling(
() => Promise.all([loadGuides(), loadBausteine(), loadTopics()]),
() => hasActiveGuides.value || activeBausteine.value.length > 0,
)
const startPolling = polling.start
async function handleCancel(guideId) {
await apiCancel(guideId)
@@ -311,16 +302,6 @@ async function handleDeleteTopic(topic) {
await loadGuides()
}
function onVisibility() {
if (document.hidden) {
stopPolling()
} else {
loadGuides()
loadBausteine()
if (hasActiveGuides.value || activeBausteine.value.length) startPolling()
}
}
onMounted(async () => {
await Promise.all([loadGuides(), loadTopics(), loadProjects(), loadProviders()])
const savedTopic = localStorage.getItem('lastTopic')
@@ -333,12 +314,6 @@ onMounted(async () => {
} else if (!selectedTopic.value && topics.value.length) {
selectTopic(topics.value[0])
}
document.addEventListener('visibilitychange', onVisibility)
})
onUnmounted(() => {
stopPolling()
document.removeEventListener('visibilitychange', onVisibility)
})
</script>