From 32cc8d5cc65b684357f361629cf015153d3269d3 Mon Sep 17 00:00:00 2001 From: pqhuy1987 Date: Wed, 5 Aug 2026 21:21:08 +0700 Subject: [PATCH] =?UTF-8?q?[CLAUDE]=20Contract:=20KHKK=20UAT=20S175=20dot-?= =?UTF-8?q?E=20=E2=80=94=20rut=20gon=20man=20theo=20anh=20khoanh=20do=20(F?= =?UTF-8?q?E-only,=200-mig)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Anh review truc tiep tren prod, khoanh do tung cho. Land dung nhung gi anh chi: === GO (anh: "Bo di" / "Bo het di" / "Bo may dong nay di") === · 2 o TONG (Sigma de xuat / Sigma duyet) — chinh anh chon "hien 2 tong rieng" khi em hoi o vong AskUser truoc, nhin that thi thua => go. Giu 1 dong vet trong ma de lan sau khong ai dung lai tuong la thieu. · 3 dong chu-thich duoi bang gia (SNAPSHOT / gan hang muc / dong them tay). Noi dung khong mat: rang-buoc "phai gan hang muc moi trinh duyet" van do submit-guard BE chan THAT, va o Hang muc o muc 1 da dem "con N dong chua gan". · Muc 1: GO **Phong ban · Quy trinh · Han xu ly** — Quy trinh van xem duoc o PANEL 3, go o day la bo cho ve TRUNG chu khong mat thong tin. · Muc 1: GO **Link ho so · Ghi chu** khoi o xem (form Sua van con 2 truong nay). · Chip "Giai doan 2 · " o header — ten nhom da co trong tieu de ("— N2") va dai 4 giai doan da chi ro dang o GD2 => chip la lan ke thu BA. · Dong "Dang loc — danh sach lay thang tu may chu…" + dai dau cot "DANH SACH KE HOACH". 🔸 Dai dau cot chinh la thu em THEM o dot B de chua "cot cut dau" — anh xem that roi bao bo. Ghi lai de khong tu dung lai. === THEM / DOI === · Muc 1 +o **Hang muc**: 1 phieu nay duoc N hang muc => liet ke DUY-NHAT theo thu tu dong, kem badge amber "con N dong chua gan" (dong chua gan KHONG bia ten). · Header phieu +**ma phieu PE nguon** +**NCC trung thau** (anh: "Dua len tren phieu — NCC"). NCC lay duy-nhat tu lines nen lien-danh N NCC liet ke het. · Cho tai file: be DUNG khuon Duyet NCC (`PeDetailTabs.tsx:3527-3531` + `:3601-3608`) — dong chu mo-ta o TREN, nut vien DUT nen brand-nhat o DUOI danh sach, thay nut dac o goc header. Nut vien dut doc ra la "cho tha them vao"; nut dac o header doc ra la "hanh dong cua ca khoi" — day la cai thu nhat. +`accept` bo loc dinh dang y PE. · Cay panel Thao tac: 2 cap Du an > Hang muc nay GAP/MO duoc (anh: "Cho hien thi theo cay"). 🔴 Dung tap-GAP (khong phai tap-MO) => mac dinh MO HET: du an/hang muc moi xuat hien sau nay tu mo, khong bi an im lang vi chua ai bam mo bao gio. === CON NO (chua land, ghi ra de khong roi) === 🔴 "So tien CCM va PRO duyet" dua len header — CHUA lam duoc: `KhkkDetailDto` hien 0 truong ngan sach (do: grep -c ccm khkk.ts = 0, control-duong pro = 50) => can BE tra them. 🔴 Gom nut thao tac: go "+ Lap ke hoach" (header) · "Sua" (muc 1) · khoi "HANH DONG" (panel 3) · banner "Dang xem ke hoach" => THAY bang 1 THANH NUT DAY khuon PE workspace (Xoa phieu | Luu | Luu & Gui Duyet). 🔴 "Bo cai dam ke ben" — dai doc giua panel 1 va panel 2, chua dinh vi duoc. 🔴 Danh sach hien theo ngay thang > du an > hang muc > phieu PE + phieu KHKK tuong ung. 🔴 CHUA soi mat prod 375/1366/1440. Co-Authored-By: Claude Opus 5 --- .../src/components/khkk/KhkkDetailContent.tsx | 170 ++++++++++-------- .../src/components/khkk/KhkkListPanel.tsx | 26 +-- .../src/components/khkk/KhkkWorkListPanel.tsx | 55 +++++- fe-admin/src/pages/khkk/KhkkListPage.tsx | 7 +- .../src/components/khkk/KhkkDetailContent.tsx | 170 ++++++++++-------- fe-user/src/components/khkk/KhkkListPanel.tsx | 26 +-- .../src/components/khkk/KhkkWorkListPanel.tsx | 55 +++++- fe-user/src/pages/khkk/KhkkListPage.tsx | 7 +- 8 files changed, 296 insertions(+), 220 deletions(-) diff --git a/fe-admin/src/components/khkk/KhkkDetailContent.tsx b/fe-admin/src/components/khkk/KhkkDetailContent.tsx index b1cdcbc..a674f0a 100644 --- a/fe-admin/src/components/khkk/KhkkDetailContent.tsx +++ b/fe-admin/src/components/khkk/KhkkDetailContent.tsx @@ -361,6 +361,28 @@ export function KhkkDetailContent({
{plan.maKeHoach ?? '(chưa cấp mã)'} {plan.peTenGoiThau ?? '—'} + {/* [S175 — anh: "Đưa lên trên phiếu — NCC"] Mã phiếu PE nguồn + NCC trúng thầu dời từ + mục 1 lên ĐÂY. Đây là 2 thứ người xem cần biết ngay khi mở phiếu, không phải cuộn + xuống bảng mới thấy. NCC lấy DUY-NHẤT từ `lines` (liên danh N NCC ⇒ liệt kê hết). + 🔴 CÒN NỢ: "số tiền CCM và PRO duyệt" anh yêu cầu CHƯA đưa lên được — `KhkkDetailDto` + hiện 0 trường ngân sách (đo: `grep -c ccm khkk.ts` = 0); cần BE trả thêm. */} + {plan.peMaPhieu && ( + + {plan.peMaPhieu} + + )} + {[...new Set(plan.lines.map(l => l.supplierName).filter(Boolean))].map(n => ( + + {n} + + ))} {plan.approvalGroup != null && ( + {/* [S175 — anh chốt trên ảnh khoanh đỏ] Mục 1 RÚT GỌN còn 4 ô: + · "Bỏ hết đi" → GỠ **Phòng ban · Quy trình · Hạn xử lý** + 🔸 Quy trình vẫn xem được ở PANEL 3 (`KhkkWorkflowPanel` đầu khối) — gỡ ở đây + là bỏ chỗ vẽ TRÙNG, không mất thông tin. + · "Bỏ đi" → GỠ **Link hồ sơ · Ghi chú** khỏi ô xem (form Sửa vẫn còn, xem dưới) + · "Thêm hạng mục vào đây" → +ô **Hạng mục** ngay cạnh Dự án + · "Đưa lên trên phiếu" → **NCC** + mã phiếu PE dời lên dải header (xem `:361`) */}
- - {plan.peMaPhieu ?? '—'} - - - - - {plan.workflowCode ? ( - - {plan.workflowCode} - {plan.workflowVersion != null && v{plan.workflowVersion}} - {plan.workflowName ? ` · ${plan.workflowName}` : ''} - - ) : ( - — Chưa chọn — - )} + {/* 1 phiếu nay được N hạng mục (S175) ⇒ liệt kê DUY-NHẤT, giữ thứ tự dòng. + Dòng chưa gán KHÔNG bịa tên — đếm riêng để người soạn biết còn nợ mấy dòng, + vì submit-guard sẽ chặn trình duyệt khi còn dòng chưa gán. */} + + {(() => { + const names = [...new Set(plan.lines.map(l => l.tenHangMuc).filter(Boolean))] as string[] + const unassigned = plan.lines.filter(l => !l.catalogEntryId).length + if (names.length === 0 && unassigned === 0) return DASH + return ( + + {names.map(n => ( + + {n} + + ))} + {unassigned > 0 && ( + + còn {unassigned} dòng chưa gán + + )} + + ) + })()} + -
{editHeader ? ( @@ -468,49 +505,9 @@ export function KhkkDetailContent({
Phiếu nguồn chưa có NCC trúng thầu.
) : ( <> - {/* [S175 · O3 — ANH CHỐT] TỔNG đặt PHÍA TRÊN bảng, đúng 2 con số: - ① trục = CHỈ TỔNG TOÀN PHIẾU (anh bác phương án tổng-mỗi-NCC); - ② hiện 2 TỔNG RIÊNG cạnh nhau — Σ giá ĐỀ XUẤT ⟂ Σ giá DUYỆT. - 🔴 KHÔNG cộng gộp 2 cột thành một số "hiện hành": đề-xuất và duyệt là hai - con số có ý nghĩa pháp-lý khác nhau (một cái chưa ai chốt, một cái đã qua - choke-point `ApplyApprovedValuesOnFinalize`); trộn lại là bịa ra một số - không tồn tại trong hồ-sơ nào. - 🔸 Dòng chưa có giá duyệt ⇒ `null`, `moneyOrDash` in em-dash mờ; tổng duyệt - chỉ cộng phần ĐÃ có, và nói rõ còn bao nhiêu dòng chưa chốt. */} - {(() => { - const sumProposed = plan.lines.reduce((s, l) => s + (l.proposedAmount ?? 0), 0) - const approvedLines = plan.lines.filter(l => l.approvedAmount != null) - const sumApproved = approvedLines.reduce((s, l) => s + (l.approvedAmount ?? 0), 0) - const pending = plan.lines.length - approvedLines.length - return ( -
-
-
Tổng giá đề xuất
-
- {formatVnd(sumProposed)} -
-
{plan.lines.length} dòng
-
-
-
Tổng giá duyệt
-
- {approvedLines.length === 0 ? '—' : formatVnd(sumApproved)} -
-
- {pending === 0 - ? 'đã chốt đủ mọi dòng' - : `còn ${pending}/${plan.lines.length} dòng chưa chốt giá`} -
-
-
- ) - })()} + {/* 🧊 [S175] 2 ô TỔNG (Σ đề xuất ⟂ Σ duyệt) đã GỠ — anh xem trên màn rồi chốt "Bỏ đi". + Trước đó chính anh chọn "hiện 2 tổng riêng" khi em hỏi; nhìn thật thì thừa. Giữ 1 dòng + vết để lần sau khỏi ai dựng lại tưởng là thiếu. */} {/* [S175 · B2 · P0] `table-fixed` + `` + `min-w-[880px]`: bảng co giãn tự-do trước đây để cột tiền nhảy bề rộng theo độ dài tên NCC ⇒ 3 cột số không thẳng hàng giữa các phiếu. Chốt bề rộng rồi thì hẹp màn hình sẽ CUỘN NGANG @@ -729,11 +726,9 @@ export function KhkkDetailContent({ )} )} -
- Giá tham chiếu là SNAPSHOT tổng báo giá được chọn của NCC trên phiếu Duyệt NCC tại thời điểm lập kế hoạch. - {' '}Cột Hạng mục gán ngay tại bảng khi phiếu ở Nháp/Trả lại — mọi dòng phải gán xong mới trình duyệt được. - {' '}🔴 Dòng THÊM TAY không có giá tham chiếu (hiện “—”) — số tham chiếu là của cả NCC, đã nằm ở dòng gốc. -
+ {/* 🧊 [S175] 3 dòng chú-thích dưới bảng ĐÃ GỠ — anh: "Bỏ mấy dòng này đi". + Nội dung không mất: ràng-buộc "phải gán hạng mục mới trình duyệt được" vẫn do + submit-guard BE chặn thật, và ô Hạng mục ở mục 1 đã đếm "còn N dòng chưa gán". */} {/* ─────── 3 — GỘP "Căn cứ hồ sơ" + "File đính kèm" (anh chốt S175) ─────── */} @@ -752,22 +747,22 @@ export function KhkkDetailContent({ chipFg="var(--color-teal-700)" count={mergedRows.length} actions={ - readOnly ? undefined : ( -
- {isDraft && ( - - )} - -
+ readOnly || !isDraft ? undefined : ( + ) } > + {/* [S175 — anh chốt] Chỗ tải file bê ĐÚNG khuôn Duyệt NCC (`PeDetailTabs.tsx:3527-3531` + + `:3601-3608`): dòng chữ mô-tả ở TRÊN, nút viền ĐỨT nền brand-nhạt ở DƯỚI danh + sách — thay cho nút đặc nằm ở góc header. Nút viền đứt đọc ra là "chỗ thả thêm + vào", nút đặc ở header đọc ra là "hành động của cả khối"; đây là cái thứ nhất. */} + {!readOnly && ( +

+ File căn cứ hồ sơ / shopdrawing của kế hoạch. Gắn vào 1 căn cứ cụ thể bằng nút ⬆ ở dòng căn cứ đó. +

+ )} {mergedRows.length === 0 ? (
Chưa có căn cứ hồ sơ hay file đính kèm nào.
) : ( @@ -854,6 +849,27 @@ export function KhkkDetailContent({ ))}
)} + {/* Nút tải lên — viền ĐỨT, đặt DƯỚI danh sách, y khuôn PE `:3601-3608`. + `accept` bê nguyên danh-sách của PE: chặn ngay ở hộp chọn file đỡ được vòng + upload-rồi-mới-biết-sai-định-dạng. */} + {!readOnly && ( + + )} {previewAtt && ( {KHKK_PHASE_LABELS[Number(p) as KhkkPhaseValue]} ))} - {flatMode && !deletedView && canPe && ( -

- Đang lọc — danh sách lấy thẳng từ máy chủ (không giới hạn 200 phiếu của cây). -

- )} + {/* 🧊 [S175] Dòng "Đang lọc — danh sách lấy thẳng từ máy chủ…" ĐÃ GỠ (anh: "Bỏ mấy dòng + này đi"). Đó là chú-thích về CƠ-CHẾ bên trong, người dùng không cần biết cây tải 200 + phiếu hay lấy thẳng máy chủ — họ chỉ cần thấy đúng phiếu. */} {!canPe && (

Bạn chưa có quyền xem phiếu Duyệt NCC nên cây toàn trình không dựng được — danh @@ -298,20 +296,8 @@ export function KhkkListPanel({ không số đếm ⇒ cột "cụt đầu": lệch cả với màn Thao tác (`KhkkWorkListPanel` có `Tier` header) LẪN với chính chế-độ phẳng (có dòng đếm ở chân). Mirror đúng khuôn `Tier` để 2 màn KHKK cùng một hình. */} -

- - {flatMode ? : } - - - {deletedView ? 'Phiếu đã xóa' : flatMode ? 'Danh sách kế hoạch' : 'Cây toàn trình'} - - {flatMode && !list.isLoading && !list.isError && ( - - {total} - - )} -
- + {/* 🧊 [S175] Dải "ĐẦU CỘT" (thêm ở đợt B để chữa "cột cụt đầu") ĐÃ GỠ — anh khoanh đỏ + cùng dòng "Đang lọc" và bảo bỏ. Tiêu-đề cột đã có ở header trang ngay trên. */}
{!flatMode && ( void }) { + // [S175 — anh: "Cho hiển thị theo cây nằm dự án hạng mục"] Tập KHOÁ đang GẬP. + // Dùng tập-gập (không phải tập-mở) để mặc-định là MỞ HẾT: dự án/hạng mục mới xuất hiện sau + // này tự mở, không bị ẩn im lặng vì chưa ai bấm mở bao giờ. + const [collapsed, setCollapsed] = useState>(new Set()) const { can } = usePermission() // 🔴 ĐÚNG key policy của endpoint — KHÔNG dùng `Khkk_*` (đó là key MENU, tầng hiển thị). const canKhkk = can('KeHoachKyKet', 'Read') @@ -193,23 +198,52 @@ export function KhkkWorkListPanel({ {/* [S175 · O8] CẤP 1 = Dự án (sticky, `z-20`) · CẤP 2 = Hạng mục (sticky dưới nó, `z-10` + thụt lề + vạch trái). 🔴 Hai `z` khác nhau là BẮT BUỘC: cùng `z` thì header hạng mục trượt ĐÈ lên header dự án khi cuộn, mất mất cấp cha. */} - {[...byProject.entries()].map(([projectName, byWorkItem]) => ( + {[...byProject.entries()].map(([projectName, byWorkItem]) => { + const pCollapsed = collapsed.has(projectName) + return (
-
+ {/* [S175 — anh: "Cho hiển thị theo cây nằm dự án hạng mục"] Header CẤP 1 nay là + NÚT gập/mở. Mặc-định MỞ: gập sẵn thì mở panel ra thấy toàn thư-mục đóng, + người dùng tưởng chưa có việc nào. */} +
- {[...byWorkItem.entries()].map(([workItemName, items]) => ( + + {!pCollapsed && [...byWorkItem.entries()].map(([workItemName, items]) => { + const wKey = `${projectName}${workItemName}` + const wCollapsed = collapsed.has(wKey) + return (
-
+
+ + {!wCollapsed && (
    {items.map((pe) => (
  • @@ -239,10 +273,13 @@ export function KhkkWorkListPanel({
  • ))}
+ )}
- ))} + ) + })}
- ))} + ) + })}
diff --git a/fe-admin/src/pages/khkk/KhkkListPage.tsx b/fe-admin/src/pages/khkk/KhkkListPage.tsx index 7b28f4b..1f5be3d 100644 --- a/fe-admin/src/pages/khkk/KhkkListPage.tsx +++ b/fe-admin/src/pages/khkk/KhkkListPage.tsx @@ -41,7 +41,6 @@ import { useAuth } from '@/contexts/AuthContext' import { api } from '@/lib/api' import { KhkkPhase, - khkkGroupMenuLabel, type KhkkDetailDto, type KhkkPhaseValue, } from '@/types/khkk' @@ -159,9 +158,9 @@ export function KhkkListPage() {

{headerTitle}

- - Giai đoạn 2{group !== null ? ` · ${khkkGroupMenuLabel(group)}` : ''} - + {/* 🧊 [S175] Chip "Giai đoạn 2 · " ĐÃ GỠ — anh: "Bỏ mấy dòng này đi". + Tên nhóm đã có trong `headerTitle` ngay bên trái (dạng ngắn "— N2"), và dải 4 giai + đoạn ở panel giữa đã chỉ rõ đang đứng ở GĐ2 ⇒ chip này là lần kể thứ ba. */}
{!deletedView && ( - )} - -
+ readOnly || !isDraft ? undefined : ( + ) } > + {/* [S175 — anh chốt] Chỗ tải file bê ĐÚNG khuôn Duyệt NCC (`PeDetailTabs.tsx:3527-3531` + + `:3601-3608`): dòng chữ mô-tả ở TRÊN, nút viền ĐỨT nền brand-nhạt ở DƯỚI danh + sách — thay cho nút đặc nằm ở góc header. Nút viền đứt đọc ra là "chỗ thả thêm + vào", nút đặc ở header đọc ra là "hành động của cả khối"; đây là cái thứ nhất. */} + {!readOnly && ( +

+ File căn cứ hồ sơ / shopdrawing của kế hoạch. Gắn vào 1 căn cứ cụ thể bằng nút ⬆ ở dòng căn cứ đó. +

+ )} {mergedRows.length === 0 ? (
Chưa có căn cứ hồ sơ hay file đính kèm nào.
) : ( @@ -854,6 +849,27 @@ export function KhkkDetailContent({ ))}
)} + {/* Nút tải lên — viền ĐỨT, đặt DƯỚI danh sách, y khuôn PE `:3601-3608`. + `accept` bê nguyên danh-sách của PE: chặn ngay ở hộp chọn file đỡ được vòng + upload-rồi-mới-biết-sai-định-dạng. */} + {!readOnly && ( + + )} {previewAtt && ( {KHKK_PHASE_LABELS[Number(p) as KhkkPhaseValue]} ))} - {flatMode && !deletedView && canPe && ( -

- Đang lọc — danh sách lấy thẳng từ máy chủ (không giới hạn 200 phiếu của cây). -

- )} + {/* 🧊 [S175] Dòng "Đang lọc — danh sách lấy thẳng từ máy chủ…" ĐÃ GỠ (anh: "Bỏ mấy dòng + này đi"). Đó là chú-thích về CƠ-CHẾ bên trong, người dùng không cần biết cây tải 200 + phiếu hay lấy thẳng máy chủ — họ chỉ cần thấy đúng phiếu. */} {!canPe && (

Bạn chưa có quyền xem phiếu Duyệt NCC nên cây toàn trình không dựng được — danh @@ -298,20 +296,8 @@ export function KhkkListPanel({ không số đếm ⇒ cột "cụt đầu": lệch cả với màn Thao tác (`KhkkWorkListPanel` có `Tier` header) LẪN với chính chế-độ phẳng (có dòng đếm ở chân). Mirror đúng khuôn `Tier` để 2 màn KHKK cùng một hình. */} -

- - {flatMode ? : } - - - {deletedView ? 'Phiếu đã xóa' : flatMode ? 'Danh sách kế hoạch' : 'Cây toàn trình'} - - {flatMode && !list.isLoading && !list.isError && ( - - {total} - - )} -
- + {/* 🧊 [S175] Dải "ĐẦU CỘT" (thêm ở đợt B để chữa "cột cụt đầu") ĐÃ GỠ — anh khoanh đỏ + cùng dòng "Đang lọc" và bảo bỏ. Tiêu-đề cột đã có ở header trang ngay trên. */}
{!flatMode && ( void }) { + // [S175 — anh: "Cho hiển thị theo cây nằm dự án hạng mục"] Tập KHOÁ đang GẬP. + // Dùng tập-gập (không phải tập-mở) để mặc-định là MỞ HẾT: dự án/hạng mục mới xuất hiện sau + // này tự mở, không bị ẩn im lặng vì chưa ai bấm mở bao giờ. + const [collapsed, setCollapsed] = useState>(new Set()) const { can } = usePermission() // 🔴 ĐÚNG key policy của endpoint — KHÔNG dùng `Khkk_*` (đó là key MENU, tầng hiển thị). const canKhkk = can('KeHoachKyKet', 'Read') @@ -193,23 +198,52 @@ export function KhkkWorkListPanel({ {/* [S175 · O8] CẤP 1 = Dự án (sticky, `z-20`) · CẤP 2 = Hạng mục (sticky dưới nó, `z-10` + thụt lề + vạch trái). 🔴 Hai `z` khác nhau là BẮT BUỘC: cùng `z` thì header hạng mục trượt ĐÈ lên header dự án khi cuộn, mất mất cấp cha. */} - {[...byProject.entries()].map(([projectName, byWorkItem]) => ( + {[...byProject.entries()].map(([projectName, byWorkItem]) => { + const pCollapsed = collapsed.has(projectName) + return (
-
+ {/* [S175 — anh: "Cho hiển thị theo cây nằm dự án hạng mục"] Header CẤP 1 nay là + NÚT gập/mở. Mặc-định MỞ: gập sẵn thì mở panel ra thấy toàn thư-mục đóng, + người dùng tưởng chưa có việc nào. */} +
- {[...byWorkItem.entries()].map(([workItemName, items]) => ( + + {!pCollapsed && [...byWorkItem.entries()].map(([workItemName, items]) => { + const wKey = `${projectName}${workItemName}` + const wCollapsed = collapsed.has(wKey) + return (
-
+
+ + {!wCollapsed && (
    {items.map((pe) => (
  • @@ -239,10 +273,13 @@ export function KhkkWorkListPanel({
  • ))}
+ )}
- ))} + ) + })}
- ))} + ) + })}
diff --git a/fe-user/src/pages/khkk/KhkkListPage.tsx b/fe-user/src/pages/khkk/KhkkListPage.tsx index 7b28f4b..1f5be3d 100644 --- a/fe-user/src/pages/khkk/KhkkListPage.tsx +++ b/fe-user/src/pages/khkk/KhkkListPage.tsx @@ -41,7 +41,6 @@ import { useAuth } from '@/contexts/AuthContext' import { api } from '@/lib/api' import { KhkkPhase, - khkkGroupMenuLabel, type KhkkDetailDto, type KhkkPhaseValue, } from '@/types/khkk' @@ -159,9 +158,9 @@ export function KhkkListPage() {

{headerTitle}

- - Giai đoạn 2{group !== null ? ` · ${khkkGroupMenuLabel(group)}` : ''} - + {/* 🧊 [S175] Chip "Giai đoạn 2 · " ĐÃ GỠ — anh: "Bỏ mấy dòng này đi". + Tên nhóm đã có trong `headerTitle` ngay bên trái (dạng ngắn "— N2"), và dải 4 giai + đoạn ở panel giữa đã chỉ rõ đang đứng ở GĐ2 ⇒ chip này là lần kể thứ ba. */}
{!deletedView && (