style: 신규 UI 아이콘을 라인 드로잉(stroke) 방식으로 통일 [auto-sync]
This commit is contained in:
parent
829a658048
commit
7775cc3b07
@ -97,3 +97,11 @@ export const IconSpider = (p: IcoProps) => <Ico {...p}><circle cx="12" cy="12
|
||||
/* ── 라이선스 ── */
|
||||
export const IconBadge = (p: IcoProps) => <Ico {...p}><path d="M12 2l2.4 4.8 5.3.8-3.9 3.7.9 5.3L12 14l-4.7 2.6.9-5.3L4.3 7.6l5.3-.8z"/></Ico>
|
||||
export const IconTag = (p: IcoProps) => <Ico {...p}><path d="M20.6 11.4l-9-9A2 2 0 0010.2 2H4a2 2 0 00-2 2v6.2a2 2 0 00.6 1.4l9 9a2 2 0 002.8 0l6.2-6.2a2 2 0 000-2.8z"/><circle cx="7" cy="7" r="1" fill="currentColor" stroke="none"/></Ico>
|
||||
|
||||
/* ── 입찰 모니터 / 공통 UI ── */
|
||||
export const IconGovt = (p: IcoProps) => <Ico {...p}><path d="M3 21h18M3 10h18M5 10V21M19 10V21M12 3L3 10h18L12 3z"/><rect x="8" y="13" width="3" height="5"/><rect x="13" y="13" width="3" height="5"/></Ico>
|
||||
export const IconX = (p: IcoProps) => <Ico {...p}><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></Ico>
|
||||
export const IconCheck = (p: IcoProps) => <Ico {...p}><polyline points="20 6 9 17 4 12"/></Ico>
|
||||
export const IconTrash = (p: IcoProps) => <Ico {...p}><path d="M3 6h18M8 6V4a2 2 0 012-2h4a2 2 0 012 2v2m3 0v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6h14z"/><path d="M10 11v6M14 11v6"/></Ico>
|
||||
export const IconPaperclip = (p: IcoProps) => <Ico {...p}><path d="M21.4 11.6l-9.1 9.1a4.5 4.5 0 01-6.4-6.4l9-9a3 3 0 014.3 4.3l-9 9a1.5 1.5 0 01-2.1-2.1l8.5-8.5"/></Ico>
|
||||
export const IconPause = (p: IcoProps) => <Ico {...p}><line x1="8" y1="5" x2="8" y2="19"/><line x1="16" y1="5" x2="16" y2="19"/></Ico>
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { useState, useEffect, useCallback } from 'react'
|
||||
import axios from 'axios'
|
||||
import { IconGovt, IconRefresh, IconX, IconCheck, IconTrash, IconPaperclip, IconPause } from '../components/Icons'
|
||||
|
||||
const API = import.meta.env.VITE_ITSM_API ?? 'http://localhost:9001'
|
||||
|
||||
@ -224,13 +225,15 @@ export default function BidWatcher() {
|
||||
return (
|
||||
<div style={{ padding: '24px 28px', background: '#f8fafc', minHeight: '100%' }}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 20 }}>
|
||||
<h2 style={{ margin: 0, fontSize: 20, fontWeight: 800 }}>📋 나라장터 입찰 모니터</h2>
|
||||
<h2 style={{ margin: 0, fontSize: 20, fontWeight: 800, display: 'flex', alignItems: 'center', gap: 8 }}>
|
||||
<IconGovt size={20} color="#003366" /> 나라장터 입찰 모니터
|
||||
</h2>
|
||||
<span style={{ fontSize: 12, color: '#94a3b8' }}>
|
||||
당일 SW개발용역·유지보수·시스템구축·고도화(SI/SM) 입찰정보 자동 수집
|
||||
{stats && <> · {stats.network_mode === 'open' ? '개방망 연동' : '폐쇄망 샘플 모드'}</>}
|
||||
</span>
|
||||
<button onClick={handleCrawl} disabled={crawling} style={{ ...btnPrimary, marginLeft: 'auto' }}>
|
||||
{crawling ? '수집 중...' : '🔄 당일 입찰 수집 실행'}
|
||||
<button onClick={handleCrawl} disabled={crawling} style={{ ...btnPrimary, marginLeft: 'auto', display: 'inline-flex', alignItems: 'center', gap: 6 }}>
|
||||
{crawling ? '수집 중...' : <><IconRefresh size={14} color="#fff" /> 당일 입찰 수집 실행</>}
|
||||
</button>
|
||||
<button onClick={load} disabled={loading} style={{
|
||||
padding: '4px 12px', borderRadius: 6, border: '1px solid #cbd5e1',
|
||||
@ -386,7 +389,7 @@ export default function BidWatcher() {
|
||||
<div style={{ padding: '16px 20px', borderBottom: '1px solid #e2e8f0', display: 'flex', alignItems: 'center', gap: 12 }}>
|
||||
<strong style={{ flex: 1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{selected.title}</strong>
|
||||
<Badge status={selected.status} />
|
||||
<button onClick={() => setSelected(null)} style={{ background: 'none', border: 'none', fontSize: 18, cursor: 'pointer' }}>✕</button>
|
||||
<button onClick={() => setSelected(null)} style={{ background: 'none', border: 'none', cursor: 'pointer', display: 'flex' }}><IconX size={18} color="#003366" /></button>
|
||||
</div>
|
||||
<div style={{ flex: 1, overflowY: 'auto', padding: '16px 20px' }}>
|
||||
<Info label="공고번호" value={selected.bid_no} />
|
||||
@ -412,7 +415,7 @@ export default function BidWatcher() {
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
|
||||
{docs.map(d => (
|
||||
<div key={d.doc_id} style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 12 }}>
|
||||
<span style={{ flex: 1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>📎 {d.name}</span>
|
||||
<span style={{ flex: 1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', display: 'inline-flex', alignItems: 'center', gap: 6 }}><IconPaperclip size={14} color="#003366" /> {d.name}</span>
|
||||
<span style={{ fontSize: 10, color: '#94a3b8' }}>{d.doc_type}</span>
|
||||
<button onClick={() => handleDownloadDoc(selected, d)} style={btnSm('#6366f1')}>다운로드</button>
|
||||
</div>
|
||||
@ -430,9 +433,9 @@ export default function BidWatcher() {
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ padding: '12px 20px', borderTop: '1px solid #e2e8f0', display: 'flex', gap: 8, flexWrap: 'wrap' }}>
|
||||
{selected.status !== 'JOIN' && <button onClick={() => handleStatusChange(selected, 'JOIN')} style={{ ...btnPrimary, background: '#16a34a' }}>✅ 참가</button>}
|
||||
{selected.status !== 'HOLD' && <button onClick={() => handleStatusChange(selected, 'HOLD')} style={{ ...btnPrimary, background: '#f59e0b' }}>⏸ 보류</button>}
|
||||
{selected.status !== 'DELETED' && <button onClick={() => handleStatusChange(selected, 'DELETED')} style={{ ...btnPrimary, background: '#dc2626' }}>🗑 삭제</button>}
|
||||
{selected.status !== 'JOIN' && <button onClick={() => handleStatusChange(selected, 'JOIN')} style={{ ...btnPrimary, background: '#16a34a', display: 'inline-flex', alignItems: 'center', gap: 6 }}><IconCheck size={14} color="#fff" /> 참가</button>}
|
||||
{selected.status !== 'HOLD' && <button onClick={() => handleStatusChange(selected, 'HOLD')} style={{ ...btnPrimary, background: '#f59e0b', display: 'inline-flex', alignItems: 'center', gap: 6 }}><IconPause size={14} color="#fff" /> 보류</button>}
|
||||
{selected.status !== 'DELETED' && <button onClick={() => handleStatusChange(selected, 'DELETED')} style={{ ...btnPrimary, background: '#dc2626', display: 'inline-flex', alignItems: 'center', gap: 6 }}><IconTrash size={14} color="#fff" /> 삭제</button>}
|
||||
{selected.status !== 'NEW' && <button onClick={() => handleStatusChange(selected, 'NEW')} style={{ ...btnPrimary, background: '#64748b' }}>↩ 신규로</button>}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user