feat(v0210): NoteCard 원문 영역 편집 UI (textarea + 저장/취소 + updateRawText)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
altair823
2026-05-09 20:47:51 +09:00
parent b4c2d85b26
commit ff1a015226
2 changed files with 75 additions and 6 deletions

View File

@@ -118,6 +118,9 @@ export function NoteCard({ note, onDeleted, onUpdated, mode = 'inbox', onRestore
// v0.2.9 Cut B Task 6 — 이동 메뉴 dropdown + MoveStatusModal target.
const [moveTarget, setMoveTarget] = useState<NoteStatus | null>(null);
const [menuOpen, setMenuOpen] = useState(false);
const [editingRaw, setEditingRaw] = useState(false);
const [draftRaw, setDraftRaw] = useState('');
const [showRevisions, setShowRevisions] = useState(false);
const possibleTargets: NoteStatus[] = (
['active', 'completed', 'archived', 'trashed'] as NoteStatus[]
@@ -150,6 +153,17 @@ export function NoteCard({ note, onDeleted, onUpdated, mode = 'inbox', onRestore
setLocal(updated); onUpdated(updated);
}
async function saveRaw() {
const next = draftRaw;
if (next.trim().length === 0) return;
const r = await inboxApi.updateRawText(note.id, next);
if (!r.ok) return;
const updated = { ...local, rawText: next, updatedAt: new Date().toISOString() };
setLocal(updated);
onUpdated(updated);
setEditingRaw(false);
}
async function removeTag(tagName: string) {
const removed = local.tags.find((t) => t.name === tagName);
const nextTagNames = local.tags.filter((t) => t.name !== tagName).map((t) => t.name);
@@ -371,9 +385,32 @@ export function NoteCard({ note, onDeleted, onUpdated, mode = 'inbox', onRestore
{rawOpen ? '▾ 원문 접기' : '▸ 원문 보기'}
</button>
{rawOpen && (
<pre style={{ marginTop: 6, whiteSpace: 'pre-wrap', fontSize: 12, color: '#555', background: '#fafafa', padding: 8, borderRadius: 4 }}>
{local.rawText}
</pre>
<div style={{ marginTop: 6 }}>
{editingRaw ? (
<div>
<textarea
aria-label="원문 편집"
value={draftRaw}
onChange={(e) => setDraftRaw(e.target.value)}
style={{ width: '100%', minHeight: 80, fontSize: 12, fontFamily: 'inherit', padding: 8, border: '1px solid #ddd', borderRadius: 4, boxSizing: 'border-box' }}
/>
<div style={{ marginTop: 4, display: 'flex', gap: 6, justifyContent: 'flex-end' }}>
<button onClick={() => setEditingRaw(false)} style={{ background: 'none', border: '1px solid #ccc', color: '#444', cursor: 'pointer', fontSize: 12, padding: '3px 10px', borderRadius: 4 }}></button>
<button onClick={() => { void saveRaw(); }} style={{ background: '#0a4b80', border: 'none', color: '#fff', cursor: 'pointer', fontSize: 12, padding: '3px 10px', borderRadius: 4 }}></button>
</div>
</div>
) : (
<>
<pre style={{ margin: 0, whiteSpace: 'pre-wrap', fontSize: 12, color: '#555', background: '#fafafa', padding: 8, borderRadius: 4 }}>
{local.rawText}
</pre>
<div style={{ marginTop: 4, display: 'flex', gap: 6, justifyContent: 'flex-end' }}>
<button onClick={() => setShowRevisions(true)} style={{ background: 'none', border: 'none', color: '#0a4b80', cursor: 'pointer', fontSize: 12, padding: 0 }}></button>
<button onClick={() => { setDraftRaw(local.rawText); setEditingRaw(true); }} style={{ background: 'none', border: '1px solid #ccc', color: '#444', cursor: 'pointer', fontSize: 12, padding: '3px 10px', borderRadius: 4 }}></button>
</div>
</>
)}
</div>
)}
</div>