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

<Cthuvien:ngay> / <Cthuvien:thang> - <BSSCalendar>

Mô tả​

BSSCalendar là component React thay thế cho các control nhập ngày/tháng cũ (<Cthuvien:ngay>, <Cthuvien:thang>). Nó được sử dụng để nhập và chọn ngày, giờ, tháng, năm một cách chuẩn xác.

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

  • Đa năng (All-in-one): Gộp chung xử lý nhập date, datetime, time, month, year vào cùng một component (thông qua thuộc tính type).
  • Chống giật Grid (Local State): Giá trị gõ vào chỉ nằm ở state nội bộ (local). Nó tự động format (thêm dấu /, :) và chặn gõ chữ cái. Khi bấm Tab, Enter (hoặc onBlur), component mới đẩy giá trị đã format chuẩn ra ngoài (onChange) để cập nhật form/grid, giúp UI mượt mà.
  • Phím tắt điều hướng: Hỗ trợ chuyển focus tự động sang control kế tiếp khi bấm Enter (nếu nằm trong form có id dt_ct).
  • Popup Native: Tận dụng Date Picker gốc (native HTML5) của trình duyệt bằng một input ẩn (type date/time...). Khi click vào icon lịch/đồng hồ, picker sẽ tự mở.
  • Xử lý linh hoạt Format (kieu_luu): Tự động parse và build kết quả trả ra theo chuỗi string ("01/01/2023"), số nguyên integer (20230101), hoặc Date object tùy cấu hình.

Thuộc tính​

So sánh thuộc tính cũ và mới​

Dưới đây là bảng tham chiếu các thuộc tính từ control cũ chuyển đổi sang <BSSCalendar>:

Control Cũ<BSSCalendar>KiểuMô tả / Chú ý khi chuyển đổi
tenlabelstringTên/Nhãn của vùng nhập (tự động dịch đa ngôn ngữ).
nhapreadOnlyboolCũ: nhap="K" -> Mới: readOnly={true}.
kieu_luukieu_luustringVẫn giữ nguyên ý nghĩa: I (số Integer, mặc định), S (chuỗi String), D (Date Object).
kt_xoa(Không còn)Việc xóa nội dung khi clear form được quản lý bởi form handler (như Formik/React Hook Form hoặc store).

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

TênKiểuMặc địnhCó thể cóMục đích
idstringuseId()Định danh của control. Render ra HTML với prefix BSS_.
namestringsinh tự độngTên của input (name property). Dùng để nhận diện trong event onChange và validation.
labelstringNhãn hiển thị bên trái của ô nhập. Tự động dịch theo ngôn ngữ.
labelWidthnumber / stringvar(--bss-label-width)110, '120px', '30%'Độ rộng của nhãn.
valueanystring, number, DateGiá trị binding từ form state. Tự động parse và hiển thị tùy theo type và kieu_luu.
typestring'date''date', 'datetime', 'time', 'month', 'year'Quyết định định dạng hiển thị và xử lý format logic.
kieu_luustring'I''I', 'S', 'D'Kiểu lưu trữ kết quả gửi ra onChange. I=Số, S=Chuỗi, D=Object Date.
requiredboolfalsetrue / falseĐánh dấu bắt buộc nhập (hiển thị dấu sao * đỏ).
errorstringHiển thị lỗi tùy chỉnh. Nếu để rỗng, tự lấy lỗi từ context useValidation.
readOnlyboolfalsetrue / falseKhóa ô nhập liệu, không cho sửa tay cũng như không gọi picker.
classNamestring''Class CSS bổ sung cho thẻ bao ngoài.
onChangefunction(e) => voidHàm callback phát ra event chứa { target: { name, value } } khi xác nhận cập nhật.

Quy tắc định dạng (Format)​

Dựa vào type và kieu_luu, giá trị gửi vào (value) và xuất ra (onChange) sẽ được xử lý:

typeHiển thị lúc nhập tayLưu trữ (kieu_luu = 'I')Lưu trữ (kieu_luu = 'S')Lưu trữ (kieu_luu = 'D')
'date'dd/mm/yyyy20240525 (number)"25/05/2024" (string)Date object
'datetime'dd/mm/yyyy hh:mm"20240525 10|30" (string)——
'time'hh:mm"10|30" (string)——
'month'mm"12" (string)——
'year'yyyy"2024" (string)——

Lưu ý: Component tự động ngăn chặn người dùng nhập ký tự không phải số và tự chèn ký tự phân cách /, :, khoảng trắng tùy theo type.

Ví dụ​

Nhập ngày (mặc định):

import { BSSCalendar } from '@/components/BSSCalendar';

export default function ExampleForm() {
const handleChange = (e) => {
// Nếu kieu_luu="I", e.target.value sẽ là số (VD: 20240115)
console.log(e.target.name, e.target.value);
};

return (
<BSSCalendar
id="ngay_sinh"
name="ngaySinh"
label="Ngày sinh"
labelWidth={120}
required={true}
type="date"
kieu_luu="I"
value={data.ngaySinh}
onChange={handleChange}
/>
);
}

Nhập ngày giờ (datetime):

<BSSCalendar
label="Thời gian bắt đầu"
name="tg_batdau"
type="datetime"
value={data.tg_batdau}
onChange={handleChange}
/>

Nhập tháng / năm riêng biệt:

<div className="flex gap-4">
<BSSCalendar label="Tháng" name="thang" type="month" value={data.thang} onChange={handleChange} />
<BSSCalendar label="Năm" name="nam" type="year" value={data.nam} onChange={handleChange} />
</div>

Sử dụng trong lưới (không có label):

<BSSCalendar
type="date"
kieu_luu="S"
value={row.ngay_cap}
onChange={(e) => updateRowField(row.id, 'ngay_cap', e.target.value)}
className="w-full"
/>