Kartu Sumber Pindah ke Bawah Jawaban Chat
Kartu sumber kini dirender inline di bawah jawaban chat; komponen dipakai ulang lewat named export dengan id unik per panel dan state expand terpisah.
Ringkasan
Commit kecil memindahkan render kartu sumber ke bawah jawaban di panel tengah, bukan cuma di sidebar. Yang kelihatan sepele ternyata nyeret dua kontrak lama: SourceCard harus jadi named export karena filenya kini punya dua komponen, dan id kartu perlu sufiks biar tetap unik di satu dokumen. Expanded state juga dibuat milik panel tengah sendiri, direset otomatis tiap pindah turn.
Jawaban chat di panel tengah udah muncul rapi, lengkap sama penjelasannya. Tapi pas saya perhatiin, kartu sumber yang jadi rujukan jawaban itu cuma nongol di sidebar. Pembaca yang scroll di panel tengah, tempat jawabannya berada, nggak akan pernah lihat kartu-kartu itu.
Dari situ ada commit kecil, 1d35066: kartu knowledge sekarang dirender inline di bawah jawaban, di panel yang sama dengan tempat orang baca. Sidebar tetep ada, cuma tugasnya fokus ke artikel dan halaman situs. Rencananya kedengeran sepele, dan pas mulai saya beneran mikirnya gitu. Yang belum saya sadari: mindahin render itu sekalian nyeret dua kontrak lama ke tempat baru.
Kayaknya cuma render ulang
Komponennya kan udah ada. SourceCard udah dirender ChatContextPanel buat sidebar, tinggal dipanggil lagi dari ChatOutputPanel. Selesai dalam semalam, begitu dugaan saya.
Tiga baris pertama emang segitu. Sisanya nggak.
Hal pertama yang keburu: ekspor. Konvensi di dokumentasi React soal ekspor komponen bilang file yang ngekspor satu komponen enak pakai default export, tapi begitu file itu ngekspor beberapa komponen sekaligus, pakai named export [2]. Begitu panel tengah ikut pakai SourceCard, file ChatContextPanel resmi punya dua komponen, jadi SourceCard ganti jadi named export. Perubahannya satu kata di depan, tapi artinya komponen itu sekarang bagian publik dari file, bukan lagi detail tersembunyi di dalamnya.
Hal kedua: id. Dua panel sekarang merender kartu untuk sources yang sama. Kalo atribut id-nya disalin mentah, satu dokumen punya id ganda, dan aturan id di MDN nyatakan id harus unik di seluruh dokumen [3]. Bug jenis ini nggak meledak di muka. Dia nyimpen diri buat bikin hal aneh belakangan, kayak anchor yang lompat ke tempat salah.
Solusinya sufiks. Kartu di panel tengah dapat id berupa prefiks ai-source-center diikuti turnId dan urutan kartu:
id={`ai-source-center-${turn.id}-${n}`}Sidebar punya ruang nama id-nya sendiri. Dua panel, dua set id, nggak tabrakan.
Expanded state punya rumah sendiri
Kartunya expandable. Klik, kontennya kebuka. Yang nggak saya pikirin pas mulai: expand-nya punya siapa.
Kalo state-nya dipinjem bareng dua panel, buka kartu di sidebar bakal bikin kartu yang sama kebuka di tengah. Bisa aja dijual sebagai fitur, tapi saya nggak mau. Dua panel itu dua konteks baca yang beda, dan expand di satu tempat nggak harus nular ke tempat lain.
Jadi expanded state sekarang milik panel tengah sendiri, isinya {turnId, slug}. Dua info dalam satu state: kartu mana yang kebuka, di turn mana. Dan karena variabel lokal biasa nggak persist antar render menurut dokumentasi state React [1], ini wajib Hook state, titik.
Resetnya nggak pake useEffect tambahan. Pas render, panel tinggal ngecek apakah expanded.turnId masih nyambung ke turn.id yang lagi aktif. Beda turn, ya anggep aja nggak ada kartu yang kebuka. Pindah turn, state lupa sendiri.
Saya sempat mikir buat angkat state ini ke parent, sekalian dibagi rapi buat dua panel. Batal. Duplikasi state per panel itu harga murah buat perilaku yang jelas: panel A buka, panel B nggak ikut-ikutan. Sharing state worth it kalo dua panel emang dimaksudin sinkron, dan di sini nggak.
Satu filter kecil nutup semuanya: yang dirender inline cuma knowledgeSources, alias sources yang punya content. Nomor badge-nya tetap dihitung dari indeks asli di turn.sources, bukan urutan baru hasil filter, supaya rujukan [n] di jawaban masih nyambung ke kartu yang bener. Kartu kosong nggak layak nimpa ruang di bawah jawaban.
Yang kebawa dari commit ini sebenernya bukan caranya render kartu. Ekspor ulang, impor, render, itu bagian lima menit. Yang bikin mikir justru kontrak yang kebawa tanpa keliatan: id harus tetap unik di satu dokumen, state harus tetap punya pemilik yang jelas. Dua hal itulah yang gampang kelewat, dan mulai sekarang saya ngeceknya dulu sebelum ngomong "tinggal render ulang".