`backend` 옆에 `front` 가 있을 이유가 없었다. negosium 의 negodata/front 를 그대로 베꼈고 그게 왜 front 인지는 따져보지 않았다 — 근거 없이 들여온 이름이라 바로잡는다. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019uYhHQdssRubirPirrdJJC
74 lines
3.1 KiB
TypeScript
74 lines
3.1 KiB
TypeScript
/**
|
|
* 수집·분석·소개문 잡이 끝났을 때의 알림 문구.
|
|
*
|
|
* ★ "몇 건이 새로 들어왔는가"를 말해 주지 않으면 사장님은 버튼을 눌렀는데 아무 일도
|
|
* 일어나지 않은 것으로 읽는다. 숫자는 job.result 에만 있으므로 판독은 collectJobResult 가
|
|
* 맡고, 여기서는 문구만 만든다.
|
|
*/
|
|
import type {JobData} from '@/api';
|
|
import {notify} from '@/lib/notify';
|
|
import {readGroup, readNote, readNumber} from './collectJobResult';
|
|
|
|
/**
|
|
* 재수집(정보) 결과 알림.
|
|
*
|
|
* ★ `facts.stored` 하나만 보여주면 "N건이 반영됐다"로 읽힌다 — 사실이 아니다.
|
|
* stored 는 **후보로 새로 쌓인 것(candidate)** 과 **값이 같아 다시 확인만 된 것(refreshed)** 의
|
|
* 합이고, 노출 중인 값은 어느 쪽이든 그대로다(fact_service 의 업데이트 프로세스).
|
|
* 그래서 둘을 갈라 보여주고, 승인이 남았다는 사실을 같이 적는다.
|
|
*/
|
|
export function notifyCollected(job: JobData) {
|
|
const facts = readGroup(job, 'facts');
|
|
const media = readGroup(job, 'media');
|
|
const stored = readNumber(facts, 'stored');
|
|
const candidate = readNumber(facts, 'candidate');
|
|
const refreshed = readNumber(facts, 'refreshed');
|
|
const photos = readNumber(media, 'stored');
|
|
|
|
if (stored === 0 && photos === 0) {
|
|
notify.warn(
|
|
'새로 들어온 정보가 없습니다.',
|
|
readNote(job) ?? '확정된 채널에서 달라진 값을 찾지 못했습니다.',
|
|
);
|
|
return;
|
|
}
|
|
|
|
const parts = [`확인할 새 값 ${candidate}건`, `그대로인 값 ${refreshed}건`];
|
|
if (photos > 0) parts.push(`새 사진 ${photos}장`);
|
|
notify.success(
|
|
'다시 수집했습니다',
|
|
`${parts.join(' · ')} — 새 값은 [맞아요]를 눌러야 사이트에 나갑니다.`,
|
|
);
|
|
}
|
|
|
|
/** 재분석(사진) 결과 알림. 신뢰도가 낮은 건은 자동 반영되지 않고 확인 큐에 남는다. */
|
|
export function notifyVision(job: JobData) {
|
|
const analyzed = readNumber(job.result, 'analyzed');
|
|
if (analyzed === 0) {
|
|
notify.warn('분석한 사진이 없습니다.', readNote(job) ?? '수집된 사진이 없습니다.');
|
|
return;
|
|
}
|
|
notify.success(
|
|
'사진을 다시 분석했습니다',
|
|
`${analyzed}장 · 자동 반영 ${readNumber(job.result, 'approved')}장 · ` +
|
|
`확인 대기 ${readNumber(job.result, 'needs_review')}장`,
|
|
);
|
|
}
|
|
|
|
/** 재생성(소개문·FAQ) 결과 알림. 생성물도 미검증으로 들어가 사람이 승인해야 나간다. */
|
|
export function notifyCopy(job: JobData) {
|
|
const faqCount = readNumber(job.result, 'faqs');
|
|
const hasIntro = (job.result as {intro?: unknown} | undefined)?.intro === true;
|
|
if (!hasIntro && faqCount === 0) {
|
|
notify.warn(
|
|
'새로 만든 문장이 없습니다.',
|
|
readNote(job) ?? '근거로 쓸 확인된 정보가 부족합니다. 정보를 먼저 확인해 주세요.',
|
|
);
|
|
return;
|
|
}
|
|
notify.success(
|
|
'소개문을 다시 만들었습니다',
|
|
`소개문 ${hasIntro ? '1건' : '없음'} · FAQ ${faqCount}건 — 확인하신 뒤 사이트에 나갑니다.`,
|
|
);
|
|
}
|