- 공용 프리미티브(ui.tsx): PageHeader·Segmented·Button·SearchForm·Legend· ScrollBox·ScrollTable·Modal + Card(fill/compact) 옵션 - 차트 공용 설정(lib/chart.ts): 축·그리드·툴팁 스타일 단일화 - 뷰포트 채우기 레이아웃 + content 영역 스크롤(Layout), 버튼 커서 복구 - 표: 헤더 밴드·행 좌우 패딩·고정/채움/auto 높이·sticky 헤더, 배지 줄바꿈 방지 - 작업 큐: 풀폭 표 + 행별 상세/JSON 모달(복사) - 상품·가격: 가로 배치, Y축 0 기준, 시점 클릭→몰별 비교, 커스텀 툴팁· 그라데이션 area, 몰별 컴팩트 표(소스 뱃지) - 크롤 상태: 도넛 중앙 총계·라운드 세그먼트, 막대 그라데이션, 툴팁 통일 - 테스트 검색: 결과 통일(모달·표·소스 뱃지), 진행상태 좌측 이동, 초기화 전 재검색 차단, 퍼널 가독성(감소량), 배송(로켓배송) 표기, 한 화면 컴팩트 - 사이드바: API 상태 상단 뱃지, 테스트 메뉴 배경색으로 구분 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
51 lines
2.6 KiB
TypeScript
51 lines
2.6 KiB
TypeScript
/** 설정 — API base URL·guard 키(localStorage). prod 에서 X-API-Key 헤더로 자동 첨부. */
|
|
|
|
import { useState } from "react";
|
|
import { settings } from "../api/client";
|
|
import { Button, Card, PageHeader } from "../components/ui";
|
|
|
|
export default function Settings() {
|
|
const [baseUrl, setBaseUrl] = useState(settings.baseUrl());
|
|
const [apiKey, setApiKey] = useState(settings.apiKey());
|
|
const [saved, setSaved] = useState(false);
|
|
|
|
return (
|
|
<div className="max-w-xl space-y-4">
|
|
<PageHeader title="설정" />
|
|
<Card title="API 연결">
|
|
<form
|
|
className="space-y-4"
|
|
onSubmit={(e) => {
|
|
e.preventDefault();
|
|
settings.save(baseUrl.trim(), apiKey.trim());
|
|
setSaved(true);
|
|
setTimeout(() => setSaved(false), 2000);
|
|
}}
|
|
>
|
|
<div>
|
|
<label htmlFor="base" className="mb-1 block text-[12px] font-semibold text-ink-700">API 주소</label>
|
|
<input id="base" value={baseUrl} onChange={(e) => setBaseUrl(e.target.value)}
|
|
placeholder="비우면 현재 주소 기준 (개발: vite 프록시 → :9600)"
|
|
className="w-full rounded-lg border border-line-200 bg-surface px-3 py-2 text-[13px] outline-none focus:border-primary-600" />
|
|
<p className="mt-1 text-[11px] text-ink-400">예: https://lps.example.com — dev 서버를 직접 보려면 해당 주소 입력</p>
|
|
</div>
|
|
<div>
|
|
<label htmlFor="key" className="mb-1 block text-[12px] font-semibold text-ink-700">API 키 (X-API-Key)</label>
|
|
<input id="key" type="password" value={apiKey} onChange={(e) => setApiKey(e.target.value)}
|
|
placeholder="개발(개방 모드)은 비워둠 — prod 만 필요"
|
|
autoComplete="off"
|
|
className="w-full rounded-lg border border-line-200 bg-surface px-3 py-2 text-[13px] outline-none focus:border-primary-600" />
|
|
<p className="mt-1 text-[11px] text-ink-400">서버 toml 의 [WebServerConfig].api_keys 중 하나. 이 브라우저에만 저장됩니다.</p>
|
|
</div>
|
|
<Button type="submit" size="lg">저장</Button>
|
|
{saved && <span className="ml-2 text-[12px] font-medium text-ok-600">저장했습니다</span>}
|
|
</form>
|
|
</Card>
|
|
<p className="text-[11px] leading-relaxed text-ink-400">
|
|
지표 임계·요청 예산 등 서버 동작 설정은 이 화면에서 바꾸지 않습니다 — 설정 소스는 서버의
|
|
config.<env>.toml 하나이며(2026-07-13 협의), 변경은 toml 수정 + 재시작으로 합니다.
|
|
</p>
|
|
</div>
|
|
);
|
|
}
|