feat: update package copy and admin control room

This commit is contained in:
Codex Agent
2026-01-15 19:54:04 +01:00
parent ad829ae509
commit 7e32d8f706
42 changed files with 1310 additions and 2017 deletions

View File

@@ -0,0 +1,47 @@
import { describe, expect, it } from 'vitest';
import { normalizeLiveStatus, resolveLiveShowApproveMode, resolveStatusTone } from './controlRoom';
describe('normalizeLiveStatus', () => {
it('maps nullish statuses to none', () => {
expect(normalizeLiveStatus(null)).toBe('none');
expect(normalizeLiveStatus(undefined)).toBe('none');
expect(normalizeLiveStatus('')).toBe('none');
});
it('passes through supported statuses', () => {
expect(normalizeLiveStatus('pending')).toBe('pending');
expect(normalizeLiveStatus('approved')).toBe('approved');
expect(normalizeLiveStatus('rejected')).toBe('rejected');
});
});
describe('resolveLiveShowApproveMode', () => {
it('prefers approve-and-live for pending gallery', () => {
expect(resolveLiveShowApproveMode('pending')).toBe('approve-and-live');
});
it('returns approve-only for approved gallery', () => {
expect(resolveLiveShowApproveMode('approved')).toBe('approve-only');
});
it('returns not-eligible for rejected or hidden gallery', () => {
expect(resolveLiveShowApproveMode('rejected')).toBe('not-eligible');
expect(resolveLiveShowApproveMode('hidden')).toBe('not-eligible');
});
});
describe('resolveStatusTone', () => {
it('maps approved to success', () => {
expect(resolveStatusTone('approved')).toBe('success');
});
it('maps pending to warning', () => {
expect(resolveStatusTone('pending')).toBe('warning');
});
it('maps other statuses to muted', () => {
expect(resolveStatusTone('rejected')).toBe('muted');
expect(resolveStatusTone('hidden')).toBe('muted');
expect(resolveStatusTone(undefined)).toBe('muted');
});
});

View File

@@ -0,0 +1,28 @@
export type LiveShowApproveMode = 'approve-and-live' | 'approve-only' | 'not-eligible';
export function resolveStatusTone(status?: string | null): 'success' | 'warning' | 'muted' {
if (status === 'approved') {
return 'success';
}
if (status === 'pending') {
return 'warning';
}
return 'muted';
}
export function normalizeLiveStatus(status?: string | null): 'pending' | 'approved' | 'rejected' | 'none' {
if (status === 'approved' || status === 'pending' || status === 'rejected') {
return status;
}
return 'none';
}
export function resolveLiveShowApproveMode(galleryStatus?: string | null): LiveShowApproveMode {
if (galleryStatus === 'pending') {
return 'approve-and-live';
}
if (galleryStatus === 'approved') {
return 'approve-only';
}
return 'not-eligible';
}

View File

@@ -23,9 +23,9 @@ describe('tabHistory', () => {
});
it('reuses stored event route when slug matches', () => {
setTabHistory('uploads', adminPath('/mobile/events/summer/photos'));
setTabHistory('uploads', adminPath('/mobile/events/summer/control-room'));
const target = resolveTabTarget('uploads', 'summer');
expect(target).toBe(adminPath('/mobile/events/summer/photos'));
expect(target).toBe(adminPath('/mobile/events/summer/control-room'));
});
it('falls back to active slug when stored slug differs', () => {

View File

@@ -20,7 +20,7 @@ function readHistory(): TabHistory {
return { paths: {}, updatedAt: 0 };
}
const parsed = JSON.parse(raw) as TabHistory;
// Check for expiry
if (Date.now() - parsed.updatedAt > EXPIRY_MS) {
window.localStorage.removeItem(STORAGE_KEY);
@@ -61,7 +61,7 @@ export function resolveDefaultTarget(key: NavKey, slug?: string | null): string
return slug ? adminPath(`/mobile/events/${slug}/tasks`) : adminPath('/mobile/tasks');
}
if (key === 'uploads') {
return slug ? adminPath(`/mobile/events/${slug}/photos`) : adminPath('/mobile/uploads');
return slug ? adminPath(`/mobile/events/${slug}/control-room`) : adminPath('/mobile/uploads');
}
if (key === 'profile') {
return adminPath('/mobile/profile');
@@ -78,7 +78,7 @@ function resolveEventScopedTarget(path: string, slug: string | null | undefined,
return path;
}
const match = path.match(/\/event-admin\/mobile\/events\/([^/]+)\/(tasks|photos)(?:\/.*)?$/);
const match = path.match(/\/event-admin\/mobile\/events\/([^/]+)\/(tasks|control-room)(?:\/.*)?$/);
if (!match) {
return resolveDefaultTarget(key, slug);
}