Agents: - content-analyst: scan static content, design JPA entities - content-db-engineer: implement Entity/Repo/Controller/Hook - admin-ui-builder: implement AdminXxx.jsx + sidebar + routes Skills: - homepage-cms-orchestrator: E2E pipeline orchestrator - content-db-engineer: Spring Boot + React implementation guide - admin-ui-builder: AdminHistory.jsx pattern reference CLAUDE.md: homepage project context + harness pointer Next DB targets: Reference, FAQ, Partner, KpiStat, CeoGreeting, OrgDept Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
78 lines
2.7 KiB
Markdown
78 lines
2.7 KiB
Markdown
---
|
|
name: admin-ui-builder
|
|
description: "지오정보기술 홈페이지 관리자(zioinfo-web) UI 구현 스킬. FAQ, 레퍼런스, 파트너사, CEO인사말, 조직도 등 새 DB 항목의 관리자 CRUD 페이지(AdminXxx.jsx)를 AdminHistory.jsx 패턴으로 구현하고 AdminLayout.jsx 사이드바와 App.jsx 라우트를 등록한다. 다음 상황에서 반드시 사용: (1) '관리자에서 XXX 관리', '관리자 페이지 추가', 'CRUD UI 추가' 요청; (2) AdminXxx.jsx 신규 생성; (3) 사이드바 메뉴 추가; (4) 다시 실행, 업데이트, 수정, 보완."
|
|
---
|
|
|
|
# 홈페이지 관리자 UI 구현 스킬
|
|
|
|
## 기본 패턴 파일
|
|
|
|
`workspace/zioinfo-web/frontend/src/pages/admin/AdminHistory.jsx` — 모든 관리자 페이지의 기준 템플릿.
|
|
|
|
## AdminXxx.jsx 필수 구성 요소
|
|
|
|
```jsx
|
|
const authFetch = (url, opts={}) =>
|
|
fetch(url, { ...opts, headers: {
|
|
'Content-Type':'application/json',
|
|
Authorization:`Bearer ${localStorage.getItem('admin_token')}`,
|
|
...opts.headers
|
|
}});
|
|
|
|
// 필수 상태
|
|
const [items, setItems] = useState([]);
|
|
const [modal, setModal] = useState(null); // null | 'create' | 'edit'
|
|
const [form, setForm] = useState(EMPTY);
|
|
const [editId, setEditId] = useState(null);
|
|
const [saving, setSaving] = useState(false);
|
|
const [toast, setToast] = useState(null);
|
|
const [search, setSearch] = useState('');
|
|
|
|
// 필수 기능: load, openCreate, openEdit, closeModal, save, del, toggleVisible
|
|
```
|
|
|
|
## AdminLayout.jsx 사이드바 추가
|
|
|
|
```js
|
|
// NAV 배열에 추가 (콘텐츠 관리 섹션 아래)
|
|
{ path: '/admin/{path}', icon: '{이모지}', label: '{메뉴명}' },
|
|
```
|
|
|
|
## App.jsx 라우트 추가
|
|
|
|
```jsx
|
|
// lazy import 추가
|
|
const Admin{Name} = lazy(() => import('./pages/admin/Admin{Name}'));
|
|
|
|
// AdminLayout Route 자식에 추가
|
|
<Route path="{path}" element={<Admin{Name} />} />
|
|
```
|
|
|
|
## 항목별 아이콘 가이드
|
|
|
|
| 항목 | 아이콘 |
|
|
|------|------|
|
|
| FAQ | ❓ |
|
|
| 레퍼런스 | 🏆 |
|
|
| 파트너사 | 🤝 |
|
|
| KPI 통계 | 📊 |
|
|
| CEO 인사말 | 👔 |
|
|
| 핵심 가치 | ⭐ |
|
|
| 조직도 | 🏢 |
|
|
| 솔루션 | 💡 |
|
|
|
|
## 공통 스타일 변수 (AdminHistory.jsx 재사용)
|
|
|
|
```jsx
|
|
const btnStyle = color => ({
|
|
padding:'7px 16px', background:color, color:'#fff',
|
|
border:'none', borderRadius:6, cursor:'pointer', fontSize:13, fontWeight:600,
|
|
});
|
|
const btnSmall = color => ({
|
|
padding:'3px 10px', background:color, color:'#fff',
|
|
border:'none', borderRadius:4, cursor:'pointer', fontSize:11, fontWeight:600,
|
|
});
|
|
const labelStyle = { display:'flex', flexDirection:'column', gap:4, fontSize:13, fontWeight:600, color:'#475569' };
|
|
const inputStyle = { padding:'8px 10px', border:'1px solid #cbd5e1', borderRadius:6, fontSize:13, outline:'none', marginTop:2 };
|
|
```
|