feat(avocet): Pinia label store with queue, lastAction, easter egg counter
This commit is contained in:
parent
2abda18b92
commit
209f49f7ea
2 changed files with 115 additions and 0 deletions
62
web/src/stores/label.test.ts
Normal file
62
web/src/stores/label.test.ts
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
// src/stores/label.test.ts
|
||||||
|
import { setActivePinia, createPinia } from 'pinia'
|
||||||
|
import { useLabelStore } from './label'
|
||||||
|
import { beforeEach, describe, it, expect } from 'vitest'
|
||||||
|
|
||||||
|
const MOCK_ITEM = {
|
||||||
|
id: 'abc', subject: 'Test', body: 'Body', from: 'a@b.com',
|
||||||
|
date: '2026-03-01', source: 'imap:test',
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('label store', () => {
|
||||||
|
beforeEach(() => setActivePinia(createPinia()))
|
||||||
|
|
||||||
|
it('starts with empty queue', () => {
|
||||||
|
const store = useLabelStore()
|
||||||
|
expect(store.queue).toEqual([])
|
||||||
|
expect(store.current).toBeNull()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('current returns first item', () => {
|
||||||
|
const store = useLabelStore()
|
||||||
|
store.queue = [MOCK_ITEM]
|
||||||
|
expect(store.current).toEqual(MOCK_ITEM)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('removeCurrentFromQueue removes first item', () => {
|
||||||
|
const store = useLabelStore()
|
||||||
|
store.queue = [MOCK_ITEM, { ...MOCK_ITEM, id: 'def' }]
|
||||||
|
store.removeCurrentFromQueue()
|
||||||
|
expect(store.queue[0].id).toBe('def')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('tracks lastAction', () => {
|
||||||
|
const store = useLabelStore()
|
||||||
|
store.queue = [MOCK_ITEM]
|
||||||
|
store.setLastAction('label', MOCK_ITEM, 'interview_scheduled')
|
||||||
|
expect(store.lastAction?.type).toBe('label')
|
||||||
|
expect(store.lastAction?.label).toBe('interview_scheduled')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('incrementLabeled increases sessionLabeled', () => {
|
||||||
|
const store = useLabelStore()
|
||||||
|
store.incrementLabeled()
|
||||||
|
store.incrementLabeled()
|
||||||
|
expect(store.sessionLabeled).toBe(2)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('restoreItem adds to front of queue', () => {
|
||||||
|
const store = useLabelStore()
|
||||||
|
store.queue = [{ ...MOCK_ITEM, id: 'def' }]
|
||||||
|
store.restoreItem(MOCK_ITEM)
|
||||||
|
expect(store.queue[0].id).toBe('abc')
|
||||||
|
expect(store.queue[1].id).toBe('def')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('clearLastAction nulls lastAction', () => {
|
||||||
|
const store = useLabelStore()
|
||||||
|
store.setLastAction('skip', MOCK_ITEM)
|
||||||
|
store.clearLastAction()
|
||||||
|
expect(store.lastAction).toBeNull()
|
||||||
|
})
|
||||||
|
})
|
||||||
53
web/src/stores/label.ts
Normal file
53
web/src/stores/label.ts
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
// src/stores/label.ts
|
||||||
|
import { defineStore } from 'pinia'
|
||||||
|
import { computed, ref } from 'vue'
|
||||||
|
|
||||||
|
export interface QueueItem {
|
||||||
|
id: string
|
||||||
|
subject: string
|
||||||
|
body: string
|
||||||
|
from: string
|
||||||
|
date: string
|
||||||
|
source: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface LastAction {
|
||||||
|
type: 'label' | 'skip' | 'discard'
|
||||||
|
item: QueueItem
|
||||||
|
label?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useLabelStore = defineStore('label', () => {
|
||||||
|
const queue = ref<QueueItem[]>([])
|
||||||
|
const totalRemaining = ref(0)
|
||||||
|
const lastAction = ref<LastAction | null>(null)
|
||||||
|
const sessionLabeled = ref(0) // for easter eggs
|
||||||
|
|
||||||
|
const current = computed(() => queue.value[0] ?? null)
|
||||||
|
|
||||||
|
function removeCurrentFromQueue() {
|
||||||
|
queue.value.shift()
|
||||||
|
}
|
||||||
|
|
||||||
|
function setLastAction(type: LastAction['type'], item: QueueItem, label?: string) {
|
||||||
|
lastAction.value = { type, item, label }
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearLastAction() {
|
||||||
|
lastAction.value = null
|
||||||
|
}
|
||||||
|
|
||||||
|
function restoreItem(item: QueueItem) {
|
||||||
|
queue.value.unshift(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
function incrementLabeled() {
|
||||||
|
sessionLabeled.value++
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
queue, totalRemaining, lastAction, sessionLabeled, current,
|
||||||
|
removeCurrentFromQueue, setLastAction, clearLastAction,
|
||||||
|
restoreItem, incrementLabeled,
|
||||||
|
}
|
||||||
|
})
|
||||||
Loading…
Reference in a new issue