feat(agent-office): centralize AGENT_META + grid slot layout
- 5 active agents (stock/music/insta/realestate/lotto) + 4 placeholders - AGENT_META, GRID_SLOTS, STATE_COLORS in single constants module - blog removed (replaced by insta) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
44
src/pages/agent-office/constants.js
Normal file
44
src/pages/agent-office/constants.js
Normal file
@@ -0,0 +1,44 @@
|
||||
// src/pages/agent-office/constants.js
|
||||
import stockImg from './assets/agent_stock.png';
|
||||
import musicImg from './assets/agent_music.png';
|
||||
import instaImg from './assets/agent_insta.png';
|
||||
import realestateImg from './assets/agent_realestate.png';
|
||||
import lottoImg from './assets/agent_lotto.png';
|
||||
import undeterminedImg from './assets/agent_undetermined.png';
|
||||
|
||||
export const AGENT_META = {
|
||||
stock: { displayName: '주식 트레이더', color: '#4488cc', image: stockImg },
|
||||
music: { displayName: '음악 프로듀서', color: '#44aa88', image: musicImg },
|
||||
insta: { displayName: '인스타 큐레이터', color: '#d97706', image: instaImg },
|
||||
realestate: { displayName: '청약 애널리스트', color: '#c026d3', image: realestateImg },
|
||||
lotto: { displayName: '로또 큐레이터', color: '#ef4444', image: lottoImg },
|
||||
};
|
||||
|
||||
export const ACTIVE_AGENT_IDS = ['stock', 'music', 'insta', 'realestate', 'lotto'];
|
||||
|
||||
// 3x3 슬롯 (좌→우, 위→아래). 처음 5칸은 active, 나머지 4칸은 placeholder.
|
||||
export const GRID_SLOTS = [
|
||||
{ agentId: 'stock' },
|
||||
{ agentId: 'music' },
|
||||
{ agentId: 'insta' },
|
||||
{ agentId: 'realestate' },
|
||||
{ agentId: 'lotto' },
|
||||
{ agentId: null },
|
||||
{ agentId: null },
|
||||
{ agentId: null },
|
||||
{ agentId: null },
|
||||
];
|
||||
|
||||
export const PLACEHOLDER_IMAGE = undeterminedImg;
|
||||
export const PLACEHOLDER_LABEL = '준비 중';
|
||||
|
||||
// 상태 → dot 색상 매핑 (AgentCard에서 공유)
|
||||
export const STATE_COLORS = {
|
||||
idle: { color: '#6b7280', pulse: false },
|
||||
working: { color: '#22c55e', pulse: true },
|
||||
error: { color: '#ef4444', pulse: false },
|
||||
waiting_approval: { color: '#f59e0b', pulse: true },
|
||||
break: { color: '#94a3b8', pulse: false },
|
||||
};
|
||||
|
||||
export const DEFAULT_STATE_COLOR = STATE_COLORS.idle;
|
||||
35
src/pages/agent-office/constants.test.js
Normal file
35
src/pages/agent-office/constants.test.js
Normal file
@@ -0,0 +1,35 @@
|
||||
// src/pages/agent-office/constants.test.js
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { AGENT_META, GRID_SLOTS, ACTIVE_AGENT_IDS } from './constants.js';
|
||||
|
||||
describe('agent-office constants', () => {
|
||||
it('5명의 active 에이전트가 정의됨', () => {
|
||||
expect(ACTIVE_AGENT_IDS).toEqual(['stock', 'music', 'insta', 'realestate', 'lotto']);
|
||||
});
|
||||
|
||||
it('각 active 에이전트에 displayName/color/image 메타가 있음', () => {
|
||||
for (const id of ACTIVE_AGENT_IDS) {
|
||||
expect(AGENT_META[id]).toBeDefined();
|
||||
expect(AGENT_META[id].displayName).toBeTruthy();
|
||||
expect(AGENT_META[id].color).toMatch(/^#/);
|
||||
expect(AGENT_META[id].image).toBeTruthy();
|
||||
}
|
||||
});
|
||||
|
||||
it('blog 메타는 존재하지 않음 (insta로 대체됨)', () => {
|
||||
expect(AGENT_META.blog).toBeUndefined();
|
||||
});
|
||||
|
||||
it('GRID_SLOTS는 9칸, 처음 5칸은 active 에이전트', () => {
|
||||
expect(GRID_SLOTS).toHaveLength(9);
|
||||
expect(GRID_SLOTS.slice(0, 5).map(s => s.agentId)).toEqual(
|
||||
['stock', 'music', 'insta', 'realestate', 'lotto']
|
||||
);
|
||||
});
|
||||
|
||||
it('GRID_SLOTS의 마지막 4칸은 placeholder (agentId=null)', () => {
|
||||
for (const slot of GRID_SLOTS.slice(5)) {
|
||||
expect(slot.agentId).toBeNull();
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user