feat: implement extraction event handling and update extraction list on status changes
Some checks failed
Frontend CI / lint (push) Failing after 17s
Frontend CI / build (push) Has been skipped

This commit is contained in:
JSC
2025-08-25 10:58:10 +02:00
parent e029a692a6
commit 8f233aaef7
3 changed files with 52 additions and 4 deletions

View File

@@ -9,10 +9,12 @@ import { Socket, io } from 'socket.io-client'
import { toast } from 'sonner' import { toast } from 'sonner'
import { import {
AUTH_EVENTS, AUTH_EVENTS,
EXTRACTION_EVENTS,
PLAYER_EVENTS, PLAYER_EVENTS,
SOUND_EVENTS, SOUND_EVENTS,
USER_EVENTS, USER_EVENTS,
authEvents, authEvents,
extractionEvents,
playerEvents, playerEvents,
soundEvents, soundEvents,
userEvents, userEvents,
@@ -127,6 +129,10 @@ export function SocketProvider({ children }: SocketProviderProps) {
newSocket.on('extraction_status_update', data => { newSocket.on('extraction_status_update', data => {
const { extraction_id, status, title, error } = data const { extraction_id, status, title, error } = data
// Emit local event for other components to listen to
extractionEvents.emit(EXTRACTION_EVENTS.EXTRACTION_STATUS_UPDATED, data)
// Handle specific status events
switch (status) { switch (status) {
case 'processing': case 'processing':
toast.loading(`Extracting: ${title}`, { toast.loading(`Extracting: ${title}`, {
@@ -139,6 +145,7 @@ export function SocketProvider({ children }: SocketProviderProps) {
toast.success(`Extraction complete: ${title}`, { toast.success(`Extraction complete: ${title}`, {
duration: 4000, duration: 4000,
}) })
extractionEvents.emit(EXTRACTION_EVENTS.EXTRACTION_COMPLETED, data)
break break
case 'failed': case 'failed':
toast.dismiss(`extraction-${extraction_id}`) toast.dismiss(`extraction-${extraction_id}`)
@@ -146,6 +153,7 @@ export function SocketProvider({ children }: SocketProviderProps) {
description: error, description: error,
duration: 6000, duration: 6000,
}) })
extractionEvents.emit(EXTRACTION_EVENTS.EXTRACTION_FAILED, data)
break break
} }
}) })

View File

@@ -36,6 +36,7 @@ export const authEvents = new EventEmitter()
export const playerEvents = new EventEmitter() export const playerEvents = new EventEmitter()
export const soundEvents = new EventEmitter() export const soundEvents = new EventEmitter()
export const userEvents = new EventEmitter() export const userEvents = new EventEmitter()
export const extractionEvents = new EventEmitter()
// Auth event types // Auth event types
export const AUTH_EVENTS = { export const AUTH_EVENTS = {
@@ -60,3 +61,11 @@ export const SOUND_EVENTS = {
export const USER_EVENTS = { export const USER_EVENTS = {
USER_CREDITS_CHANGED: 'user_credits_changed', USER_CREDITS_CHANGED: 'user_credits_changed',
} as const } as const
// Extraction event types
export const EXTRACTION_EVENTS = {
EXTRACTION_STATUS_UPDATED: 'extraction_status_updated',
EXTRACTION_CREATED: 'extraction_created',
EXTRACTION_COMPLETED: 'extraction_completed',
EXTRACTION_FAILED: 'extraction_failed',
} as const

View File

@@ -15,7 +15,8 @@ import {
type ExtractionStatus, type ExtractionStatus,
extractionsService, extractionsService,
} from '@/lib/api/services/extractions' } from '@/lib/api/services/extractions'
import { useEffect, useState } from 'react' import { EXTRACTION_EVENTS, extractionEvents } from '@/lib/events'
import { useCallback, useEffect, useState } from 'react'
import { toast } from 'sonner' import { toast } from 'sonner'
export function ExtractionsPage() { export function ExtractionsPage() {
@@ -51,7 +52,7 @@ export function ExtractionsPage() {
return () => clearTimeout(handler) return () => clearTimeout(handler)
}, [searchQuery]) }, [searchQuery])
const fetchExtractions = async () => { const fetchExtractions = useCallback(async () => {
try { try {
setLoading(true) setLoading(true)
setError(null) setError(null)
@@ -74,11 +75,11 @@ export function ExtractionsPage() {
} finally { } finally {
setLoading(false) setLoading(false)
} }
} }, [debouncedSearchQuery, sortBy, sortOrder, statusFilter, currentPage, pageSize])
useEffect(() => { useEffect(() => {
fetchExtractions() fetchExtractions()
}, [debouncedSearchQuery, sortBy, sortOrder, statusFilter, currentPage, pageSize]) }, [fetchExtractions])
// Reset to page 1 when filters change // Reset to page 1 when filters change
useEffect(() => { useEffect(() => {
@@ -87,6 +88,33 @@ export function ExtractionsPage() {
} }
}, [debouncedSearchQuery, sortBy, sortOrder, statusFilter, pageSize]) }, [debouncedSearchQuery, sortBy, sortOrder, statusFilter, pageSize])
// Listen for extraction events to refresh the list
useEffect(() => {
const handleExtractionStatusUpdate = () => {
fetchExtractions()
}
const handleExtractionCompleted = () => {
fetchExtractions()
}
const handleExtractionFailed = () => {
fetchExtractions()
}
// Subscribe to extraction events
extractionEvents.on(EXTRACTION_EVENTS.EXTRACTION_STATUS_UPDATED, handleExtractionStatusUpdate)
extractionEvents.on(EXTRACTION_EVENTS.EXTRACTION_COMPLETED, handleExtractionCompleted)
extractionEvents.on(EXTRACTION_EVENTS.EXTRACTION_FAILED, handleExtractionFailed)
return () => {
// Cleanup event listeners
extractionEvents.off(EXTRACTION_EVENTS.EXTRACTION_STATUS_UPDATED, handleExtractionStatusUpdate)
extractionEvents.off(EXTRACTION_EVENTS.EXTRACTION_COMPLETED, handleExtractionCompleted)
extractionEvents.off(EXTRACTION_EVENTS.EXTRACTION_FAILED, handleExtractionFailed)
}
}, [fetchExtractions])
const handlePageChange = (page: number) => { const handlePageChange = (page: number) => {
setCurrentPage(page) setCurrentPage(page)
} }
@@ -112,6 +140,9 @@ export function ExtractionsPage() {
setUrl('') setUrl('')
setShowCreateDialog(false) setShowCreateDialog(false)
// Emit event for new extraction created
extractionEvents.emit(EXTRACTION_EVENTS.EXTRACTION_CREATED, response.extraction)
// Refresh the extractions list // Refresh the extractions list
fetchExtractions() fetchExtractions()
} catch (err) { } catch (err) {