o2o-negosium-original/lps-admin/src/pages/Settings.tsx
민헌 d111610555 feat(lps-admin): 관리자 페이지 디자인 개선 및 컴포넌트 통일
- 공용 프리미티브(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>
2026-07-16 08:48:43 +09:00

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.&lt;env&gt;.toml 하나이며(2026-07-13 협의), 변경은 toml 수정 + 재시작으로 합니다.
</p>
</div>
);
}