# Hướng dẫn tích hợp hiển thị Từ vựng phương ngữ Nam Bộ vào ReactJS Tài liệu này hướng dẫn cách tích hợp tính năng **Hiển thị thẻ từ vựng tham khảo (Vocabulary Cards)** vào dự án ReactJS (`namky-cultural-project`) sau khi backend đã nâng cấp lên bản v4 (trả về danh sách `relevant_words`). --- ## 1. Khai báo State lưu dữ liệu Mở component chính xử lý tính năng dịch (thường là `App.js`), thêm state `relevantWords` để lưu trữ dữ liệu từ vựng nhận từ API: ```javascript import React, { useState } from 'react'; // Trong component của bạn: const [relevantWords, setRelevantWords] = useState([]); ``` --- ## 2. Cập nhật Hàm gọi API (`fetch`) Cập nhật phần xử lý phản hồi API để lưu danh sách từ vựng được gợi ý từ hệ thống RAG: ```javascript const handleConvert = async () => { setLoading(true); try { const response = await fetch("https://fivec-bau-rag-backend.hf.space/api/convert", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ text: inputText }), }); const data = await response.json(); // Lưu kết quả dịch setConvertedText(data.converted); // Lưu danh sách từ vựng tham khảo vào state setRelevantWords(data.relevant_words || []); } catch (error) { console.error("Lỗi kết nối API:", error); } finally { setLoading(false); } }; ``` *(Lưu ý: Nếu có hàm reset/xóa nội dung dịch, hãy gọi thêm `setRelevantWords([])` để dọn dẹp giao diện).* --- ## 3. Render giao diện thẻ từ vựng (JSX) Đặt đoạn mã JSX này ở phía dưới phần hiển thị kết quả dịch câu để vẽ ra các Card từ vựng: ```jsx {/* Hiển thị danh sách từ vựng tham chiếu */} {relevantWords.length > 0 && (

📖 Từ vựng Nam Bộ tham chiếu ({relevantWords.length})

{relevantWords.map((wordObj, idx) => { let posList = []; let viDuList = []; // Parse dữ liệu từ loại (pos) và ví dụ (vi_du) được lưu dạng JSON string try { posList = JSON.parse(wordObj.pos || "[]"); } catch (e) { posList = Array.isArray(wordObj.pos) ? wordObj.pos : []; } try { viDuList = JSON.parse(wordObj.vi_du || "[]"); } catch (e) { viDuList = Array.isArray(wordObj.vi_du) ? wordObj.vi_du : []; } return (
{wordObj.tu}
{posList.map((pos, pIdx) => ( {pos} ))}
{wordObj.tu_hien_nay && (
Nói cách khác: {wordObj.tu_hien_nay}
)}

{wordObj.nghia}

{viDuList.length > 0 && (
Ví dụ ngữ cảnh xưa: {viDuList.map((vidu, vIdx) => (

💡 "{vidu}"

))}
)}
); })}
)} ``` --- ## 4. Thiết lập CSS Modern Glassmorphism Thêm đoạn mã CSS này vào tệp CSS chính của bạn (`App.css` hoặc `index.css`): ```css /* Container khu vực từ vựng */ .vocab-section { margin-top: 2.5rem; padding-top: 2rem; border-top: 1px solid rgba(255, 255, 255, 0.1); text-align: left; } .vocab-section-title { font-size: 1.3rem; font-weight: 600; color: #f3f4f6; margin-bottom: 1.25rem; display: flex; align-items: center; gap: 0.6rem; } /* Grid xếp các thẻ từ vựng */ .vocab-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 1.25rem; } /* Thẻ từ vựng (Card) phong cách Glassmorphism */ .vocab-card { background: rgba(255, 255, 255, 0.03); border: 1px solid rgba(255, 255, 255, 0.07); border-radius: 14px; padding: 1.25rem; transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1); backdrop-filter: blur(10px); display: flex; flex-direction: column; } .vocab-card:hover { transform: translateY(-3px); background: rgba(255, 255, 255, 0.06); border-color: rgba(251, 191, 36, 0.4); /* Màu viền hổ phách khi hover */ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.25); } /* Tiêu đề từ và Badge Từ loại */ .vocab-card-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.75rem; } .vocab-word { font-size: 1.2rem; font-weight: 700; color: #fbbf24; /* Màu vàng hổ phách nổi bật */ letter-spacing: -0.01em; } .vocab-pos-container { display: flex; gap: 0.35rem; } .vocab-pos-badge { font-size: 0.7rem; padding: 0.15rem 0.5rem; border-radius: 9999px; background: rgba(251, 191, 36, 0.1); color: #fcd34d; border: 1px solid rgba(251, 191, 36, 0.25); font-weight: 600; text-transform: capitalize; } /* Phần từ tương đương hiện nay */ .vocab-modern-eq { font-size: 0.85rem; color: #9ca3af; margin-bottom: 0.75rem; padding: 0.35rem 0.6rem; background: rgba(255, 255, 255, 0.02); border-radius: 6px; width: fit-content; } /* Định nghĩa */ .vocab-meaning { font-size: 0.95rem; color: #e5e7eb; line-height: 1.55; margin-bottom: 1rem; flex-grow: 1; } /* Ví dụ ngữ cảnh xưa */ .vocab-examples { border-left: 2px solid rgba(251, 191, 36, 0.4); padding-left: 0.85rem; margin-top: auto; } .vocab-example-label { display: block; font-size: 0.75rem; color: #6b7280; margin-bottom: 0.25rem; font-weight: 600; text-transform: uppercase; } .vocab-example-item { font-size: 0.85rem; color: #9ca3af; line-height: 1.45; margin-top: 0.15rem; } ```