// fill.jsx — [입력 필요] 채우기: 앱이 사용자에게 값을 요구·검증·반영, 틀리면 재요구 const { Icon, Pill, Button } = window.RAlly; const resolveTid = () => { const t = (typeof window !== 'undefined' && window.__RALLY_TRACK); if (t) return Promise.resolve(t); return fetch('/api/tracks').then((r) => r.json()).then((d) => { const ts = d.tracks || []; const real = ts.filter((x) => x.profile); const pick = (real.length ? real : ts).slice(-1)[0]; const id = pick ? pick.id : 1; if (typeof window !== 'undefined') window.__RALLY_TRACK = id; return id; }).catch(() => 1); }; const Fill = ({ go }) => { const [tid, setTid] = React.useState(null); const [fields, setFields] = React.useState([]); const [vals, setVals] = React.useState({}); const [errors, setErrors] = React.useState({}); const [filled, setFilled] = React.useState({}); const [remaining, setRemaining] = React.useState(null); const [busy, setBusy] = React.useState(false); const [done, setDone] = React.useState(false); const loadFields = React.useCallback((id) => { fetch('/api/track/' + id + '/fields').then((r) => r.json()).then((d) => { setFields(d.fields || []); }).catch(() => {}); }, []); React.useEffect(() => { resolveTid().then((id) => { setTid(id); loadFields(id); }); }, [loadFields]); const submit = () => { if (!tid) return; setBusy(true); setDone(false); fetch('/api/track/' + tid + '/fields', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ values: vals }), }).then((r) => r.json()).then((d) => { setErrors(d.errors || {}); setFilled(d.filled || {}); setRemaining(d.remaining); setBusy(false); setDone(true); loadFields(tid); // 반영 후 남은 슬롯 갱신 }).catch(() => { setBusy(false); }); }; const setVal = (k, v) => setVals((s) => ({ ...s, [k]: v })); return (
정보 입력 [입력 필요] 채우기
문서에 채울 정보를 입력하세요
아래 값을 입력하면 여러 문서의 같은 자리에 일괄 반영됩니다. 형식이 틀리면 다시 요구합니다. 시험결과·측정치 등 실측 증거와 표 데이터는 회사가 문서에서 직접 채웁니다.
{fields.length === 0 && (
채울 항목이 없습니다(모두 채워졌거나 트랙 문서가 없습니다).
)} {fields.map((f) => { const err = errors[f.key]; const ok = done && filled[f.key]; return (
{f.label} · 문서 {f.slots}곳에 반영 {ok ? ✓ {filled[f.key]}곳 반영됨 : null}
setVal(f.key, e.target.value)} placeholder={'예: ' + f.example} style={{ width: '100%', padding: '9px 11px', border: `1px solid ${err ? '#c0392b' : 'var(--line)'}`, borderRadius: 8, fontSize: 13.5, fontFamily: 'inherit' }} /> {err &&
{err} — 다시 입력하세요.
}
); })} {fields.length > 0 && (
{done && ( {Object.keys(errors).length ? `${Object.keys(errors).length}개 항목 형식 오류 — 위에서 수정 후 다시 반영하세요.` : `반영 완료. 남은 [입력 필요] ${remaining}곳(대부분 표 데이터·실측 증거 — 회사가 문서에서 채움).`} )}
)}
); }; window.RAlly.Fill = Fill;