feat: extract shared stage-list module and humanize stage labels in ItemModal

This commit is contained in:
pyr0ball 2026-07-14 13:05:16 -07:00
parent 48a6d38d53
commit d75e6d3c49
3 changed files with 50 additions and 9 deletions

View file

@ -1,6 +1,7 @@
<script setup>
import { ref, watch } from 'vue'
import { updateItem } from '../api.js'
import { DONATION_STAGES, OTHER_STAGES, OUTBOUND_STAGES, UNSORTED_STAGES, STAGE_LABELS } from '../stages.js'
const props = defineProps({ item: { type: Object, default: null } })
const emit = defineEmits(['close', 'saved'])
@ -11,13 +12,6 @@ const stage = ref('')
const notes = ref('')
const followUpDate = ref('')
const DONATION_STAGES = ['new', 'replied', 'pickup_scheduled', 'picked_up', 'logged_in_bookmark']
const OTHER_STAGES = ['new', 'done']
const OUTBOUND_STAGES = [
'new', 'reviewed', 'outreach_drafted', 'outreach_sent',
'replied', 'pickup_scheduled', 'picked_up', 'logged_in_bookmark',
]
watch(() => props.item, (item) => {
if (!item) return
senderId.value = item.sender_id || ''
@ -31,7 +25,7 @@ function stagesForType() {
if (props.item?.direction === 'outbound') return OUTBOUND_STAGES
if (type.value === 'donation') return DONATION_STAGES
if (type.value === 'other') return OTHER_STAGES
return ['new']
return UNSORTED_STAGES
}
watch(type, () => {
@ -71,7 +65,7 @@ async function save() {
<label>Stage
<select v-model="stage">
<option v-for="s in stagesForType()" :key="s" :value="s">{{ s }}</option>
<option v-for="s in stagesForType()" :key="s" :value="s">{{ STAGE_LABELS[s] || s }}</option>
</select>
</label>

19
frontend/src/stages.js Normal file
View file

@ -0,0 +1,19 @@
export const DONATION_STAGES = ['new', 'replied', 'pickup_scheduled', 'picked_up', 'logged_in_bookmark']
export const OTHER_STAGES = ['new', 'done']
export const OUTBOUND_STAGES = [
'new', 'reviewed', 'outreach_drafted', 'outreach_sent',
'replied', 'pickup_scheduled', 'picked_up', 'logged_in_bookmark',
]
export const UNSORTED_STAGES = ['new']
export const STAGE_LABELS = {
new: 'New',
replied: 'Replied',
pickup_scheduled: 'Pickup Scheduled',
picked_up: 'Picked Up',
logged_in_bookmark: 'Logged in Bookmark',
done: 'Done',
reviewed: 'Reviewed',
outreach_drafted: 'Outreach Drafted',
outreach_sent: 'Outreach Sent',
}

View file

@ -0,0 +1,28 @@
import { describe, it, expect } from 'vitest'
import {
DONATION_STAGES, OTHER_STAGES, OUTBOUND_STAGES, UNSORTED_STAGES, STAGE_LABELS,
} from '../src/stages.js'
describe('stages.js', () => {
it('exports the expected stage lists', () => {
expect(DONATION_STAGES).toEqual([
'new', 'replied', 'pickup_scheduled', 'picked_up', 'logged_in_bookmark',
])
expect(OTHER_STAGES).toEqual(['new', 'done'])
expect(OUTBOUND_STAGES).toEqual([
'new', 'reviewed', 'outreach_drafted', 'outreach_sent',
'replied', 'pickup_scheduled', 'picked_up', 'logged_in_bookmark',
])
expect(UNSORTED_STAGES).toEqual(['new'])
})
it('has a human-readable label for every stage across all lists', () => {
const allStages = new Set([
...DONATION_STAGES, ...OTHER_STAGES, ...OUTBOUND_STAGES, ...UNSORTED_STAGES,
])
for (const stage of allStages) {
expect(STAGE_LABELS[stage]).toBeTruthy()
expect(STAGE_LABELS[stage]).not.toBe(stage)
}
})
})