Chuyển tới nội dung chính

<form_P_MO / P_ROI> - <BSSPopup>

Mô tả​

BSSPopup là component React dạng Drawer (panel trượt từ bên phải màn hình), thay thế cho cơ chế mở form popup cũ qua hàm JavaScript form_P_MO() và control <Cthuvien:roi>.

Điểm nổi bật của BSSPopup:

  • Panel trượt (Drawer): Thay vì mở cửa sổ popup riêng biệt (window.open) như hệ thống cũ, BSSPopup hiển thị panel trượt vào từ cạnh phải, phủ lên giao diện chính mà không làm mất ngữ cảnh làm việc.
  • Backdrop mờ: Khi mở, một lớp nền bán trong suốt (bg-slate-900/40) có hiệu ứng backdrop-blur phủ lên phía sau panel. Click vào backdrop sẽ đóng popup.
  • Khóa cuộn (Scroll Lock): Tự động khóa document.body.style.overflow = 'hidden' khi mở để ngăn người dùng cuộn nội dung phía sau. Tự động gỡ bỏ khi đóng.
  • Phím tắt Esc: Đăng ký listener keydown trên window để đóng nhanh bằng phím Escape.
  • Responsive: Hỗ trợ 5 kích thước (sm, md, lg, xl, full) với breakpoint tự co giãn theo viewport (mobile sẽ tự mở gần full chiều rộng).

Thuộc tính​

So sánh cơ chế cũ và mới​

Cơ chế Cũ<BSSPopup>Mô tả / Chú ý khi chuyển đổi
form_P_MO(url, ...)isOpen={true}Cũ: Gọi hàm JS mở cửa sổ popup riêng. Mới: Đơn giản bật cờ state isOpen để hiện panel.
P_ROI('dong#url#gui#ham#id#dtuong')onClose + logic riêngCũ: Chuỗi tham số gộp phân cách #. Mới: Truyền dữ liệu qua props/callback React chuẩn, không cần encode chuỗi.
<Cthuvien:roi f_tkhao="..."><BSSButton onClick={...}>Cũ: Control nhãn liên kết tự gắn sự kiện mở form. Mới: Dùng BSSButton hoặc bất kỳ element nào kết hợp state useState.
Cửa sổ popup (window.open)Drawer panel (CSS transform)Cũ: Tab/cửa sổ trình duyệt riêng biệt. Mới: Panel nằm trong cùng trang, không bị trình duyệt chặn popup.

Các thuộc tính của <BSSPopup>​

TênKiểuMặc địnhCó thể cóMục đích
isOpenbooltrue / falseTrạng thái mở/đóng. Điều khiển animation trượt vào/ra và hiển thị backdrop.
onClosefunction() => voidCallback đóng popup (kích hoạt khi click backdrop, nhấn Esc, hoặc click nút X).
titlestringTiêu đề hiển thị trên header. Tự động dịch theo ngôn ngữ.
childrenReactNodeNội dung bên trong body (có thể là form, grid, hoặc bất kỳ component nào).
sizestring'md''sm', 'md', 'lg', 'xl', 'full'Kích thước (độ rộng) của panel.

Kích thước (size)​

Giá trịChiều rộng DesktopChiều rộng MobileMục đích sử dụng
sm320pxcalc(100vw - 16px)Ghi chú ngắn, thông tin tóm tắt
md500pxcalc(100vw - 16px)Tra cứu lịch sử, form đơn giản
lg850pxcalc(100vw - 16px)Danh sách lưới dữ liệu
xl1100pxcalc(100vw - 16px)Form nghiệp vụ lớn, nhiều trường
full100vw100vwToàn màn hình (thay thế hoàn toàn view chính)

Hoạt động phía Client​

  • Mở Drawer: Khi isOpen chuyển từ false → true, panel trượt vào từ phải bằng CSS translate-x-0 với animation ease-out 300ms. Đồng thời backdrop mờ hiện ra.
  • Đóng Drawer: Có 3 cách đóng:
    1. Click nút X trên header.
    2. Click vào vùng backdrop mờ phía sau.
    3. Bấm phím Escape trên bàn phím.
  • Scroll Lock: Khi mở, document.body.style.overflow = 'hidden' ngăn cuộn trang chính. Khi đóng (hoặc unmount), tự động khôi phục overflow = 'unset'.
  • Header chuẩn ERP: Header có nền xanh đậm (#001529), chữ trắng in hoa, thanh trang trí xanh dương nhỏ bên trái tiêu đề. Hỗ trợ Dark Mode (dark:bg-slate-800).

Ví dụ​

1. Popup tra cứu danh sách (size lớn):

import { useState } from 'react';
import BSSPopup from '@/components/BSSPopup';
import { BSSButton } from '@/components/BSSButton';

export default function ExamplePage() {
const [isOpen, setIsOpen] = useState(false);

return (
<>
<BSSButton onClick={() => setIsOpen(true)}>Tra cứu nhân viên</BSSButton>

<BSSPopup
isOpen={isOpen}
onClose={() => setIsOpen(false)}
title="Tra cứu nhân viên"
size="lg"
>
{/* Nội dung bên trong: Grid, Form, hoặc bất kỳ component nào */}
<div>Danh sách nhân viên sẽ hiển thị ở đây...</div>
</BSSPopup>
</>
);
}

2. Popup form nhập liệu nghiệp vụ:

<BSSPopup
isOpen={showForm}
onClose={handleClose}
title="Thêm mới hợp đồng"
size="xl"
>
<div id="dt_ct">
<BSSInput label="Số hợp đồng" name="so_hd" value={data.so_hd} onChange={handleChange} />
<BSSCalendar label="Ngày ký" name="ngay_ky" value={data.ngay_ky} onChange={handleChange} />
<BSSLke label="Nhân viên" name="ma_nv" ktra="ns_nhanvien,ma,ten" value={data.ma_nv} onChange={handleChange} />
</div>
</BSSPopup>