round 3
This commit is contained in:
24
web/vue-app/src/common/backendEvents.ts
Normal file
24
web/vue-app/src/common/backendEvents.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { onMounted, onBeforeUnmount } from 'vue'
|
||||
import { eventBus } from './eventBus'
|
||||
|
||||
export function useBackendEvents(userId: string) {
|
||||
let eventSource: EventSource | null = null
|
||||
|
||||
onMounted(() => {
|
||||
console.log('Connecting to backend events for user:', userId)
|
||||
eventSource = new EventSource(`/events?user_id=${userId}`)
|
||||
|
||||
eventSource.onmessage = (event) => {
|
||||
const data = JSON.parse(event.data)
|
||||
|
||||
// Emit globally for any component that cares
|
||||
eventBus.emit(data.type, data)
|
||||
eventBus.emit('sse', data) // optional: catch-all channel
|
||||
}
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
console.log('Disconnecting from backend events for user:', userId)
|
||||
eventSource?.close()
|
||||
})
|
||||
}
|
||||
29
web/vue-app/src/common/eventBus.ts
Normal file
29
web/vue-app/src/common/eventBus.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
type Callback = (payload: any) => void
|
||||
|
||||
class EventBus {
|
||||
private listeners: Map<string, Callback[]> = new Map()
|
||||
|
||||
on(event: string, callback: Callback) {
|
||||
if (!this.listeners.has(event)) {
|
||||
this.listeners.set(event, [])
|
||||
}
|
||||
this.listeners.get(event)!.push(callback)
|
||||
}
|
||||
|
||||
off(event: string, callback: Callback) {
|
||||
const list = this.listeners.get(event)
|
||||
if (!list) return
|
||||
|
||||
const index = list.indexOf(callback)
|
||||
if (index !== -1) list.splice(index, 1)
|
||||
}
|
||||
|
||||
emit(event: string, payload?: any) {
|
||||
const list = this.listeners.get(event)
|
||||
if (!list) return
|
||||
|
||||
list.forEach((callback) => callback(payload))
|
||||
}
|
||||
}
|
||||
|
||||
export const eventBus = new EventBus()
|
||||
120
web/vue-app/src/common/models.ts
Normal file
120
web/vue-app/src/common/models.ts
Normal file
@@ -0,0 +1,120 @@
|
||||
export interface Task {
|
||||
id: string
|
||||
name: string
|
||||
points: number
|
||||
is_good: boolean
|
||||
image_id: string | null
|
||||
image_url?: string | null // optional, for resolved URLs
|
||||
}
|
||||
|
||||
export interface Child {
|
||||
id: string | number
|
||||
name: string
|
||||
age: number
|
||||
points?: number
|
||||
image_id: string | null
|
||||
image_url?: string | null // optional, for resolved URLs
|
||||
}
|
||||
|
||||
export interface Reward {
|
||||
id: string
|
||||
name: string
|
||||
cost: number
|
||||
points_needed: number
|
||||
image_id: string | null
|
||||
image_url?: string | null // optional, for resolved URLs
|
||||
}
|
||||
|
||||
export interface RewardStatus {
|
||||
id: string
|
||||
name: string
|
||||
points_needed: number
|
||||
cost: number
|
||||
image_id: string | null
|
||||
image_url?: string | null // optional, for resolved URLs
|
||||
}
|
||||
|
||||
export interface Event {
|
||||
type: string
|
||||
payload:
|
||||
| TaskUpdateEventPayload
|
||||
| RewardUpdateEventPayload
|
||||
| ChildUpdateEventPayload
|
||||
| ChildDeleteEventPayload
|
||||
| TaskCreatedEventPayload
|
||||
| TaskDeletedEventPayload
|
||||
| TaskEditedEventPayload
|
||||
| RewardCreatedEventPayload
|
||||
| RewardDeletedEventPayload
|
||||
| RewardEditedEventPayload
|
||||
| RewardSetEventPayload
|
||||
| TaskSetEventPayload
|
||||
| ChildAddEventPayload
|
||||
}
|
||||
|
||||
export interface TaskUpdateEventPayload {
|
||||
task_id: string
|
||||
child_id: string
|
||||
status: string
|
||||
points: number
|
||||
}
|
||||
|
||||
export interface TaskSetEventPayload {
|
||||
child_id: string
|
||||
status: string
|
||||
}
|
||||
|
||||
export interface RewardUpdateEventPayload {
|
||||
reward_id: string
|
||||
child_id: string
|
||||
status: string
|
||||
points: number
|
||||
}
|
||||
|
||||
export interface RewardSetEventPayload {
|
||||
child_id: string
|
||||
status: string
|
||||
}
|
||||
|
||||
export interface ChildAddEventPayload {
|
||||
child_id: string
|
||||
status: string
|
||||
}
|
||||
|
||||
export interface ChildUpdateEventPayload {
|
||||
child_id: string
|
||||
status: string
|
||||
}
|
||||
|
||||
export interface ChildDeleteEventPayload {
|
||||
child_id: string
|
||||
status: string
|
||||
}
|
||||
export interface TaskCreatedEventPayload {
|
||||
task_id: string
|
||||
status: string
|
||||
}
|
||||
|
||||
export interface TaskDeletedEventPayload {
|
||||
task_id: string
|
||||
status: string
|
||||
}
|
||||
|
||||
export interface TaskEditedEventPayload {
|
||||
task_id: string
|
||||
status: string
|
||||
}
|
||||
|
||||
export interface RewardCreatedEventPayload {
|
||||
reward_id: string
|
||||
}
|
||||
|
||||
export interface RewardDeletedEventPayload {
|
||||
reward_id: string
|
||||
status: string
|
||||
}
|
||||
|
||||
export interface RewardEditedEventPayload {
|
||||
reward_id: string
|
||||
status: string
|
||||
}
|
||||
Reference in New Issue
Block a user