Skip to main content

ĐẶT LỊCH

https://www.figma.com/design/jM4Xopoh41pK1UhYEnxWUq/Workplace-Home?node-id=17609-14166&p=f&t=HbmhJyk4P6KSO4pP-0

1. Màn hình Danh sách Lịch Checklist (Calendar View)

image.png
Màn hình 1
Tên trường / Chức năng Loại (Type) Mô tả giao diện (UI) Logic xử lý (System/Business Logic)
Tab View Button Group

- Hiển thị 2 nút: "Lịch" và "Danh sách".

- Mặc định chọn: Tab "Lịch".
- Trạng thái Active: Màu nền tím nhạt, chữ tím đậm.

Khi switch tab, hệ thống render lại dữ liệu hiển thị theo dạng view tương ứng (Calendar view hoặc List view).
Thanh tìm kiếm Input Text

- Placeholder: "Tìm theo tên lịch...".


- Icon kính lúp ở bên phải.

- Điều kiện tìm: So khớp chuỗi ký tự gần đúng (LIKE %keyword%) với trường "Tên lịch checklist".


- Phạm vi dữ liệu: Query tất cả các lịch trong quá khứ + Lịch hiện tại + Lịch tương lai (trong phạm vi 30 ngày kể từ ngày hiện tại đối với lịch có tần suất).

Bộ lọc Địa điểm Dropdown (Multi-select)

- Hiển thị danh sách các địa điểm đã được cấu hình (site)


- Cho phép tích chọn nhiều.

- Cho phép nhập tìm kiếm theo tên và mã địa điểm

- Quan hệ OR giữa các giá trị chọn.

Bộ lọc Phân loại Dropdown (Multi-select) - Hiển thị danh sách loại checklist. - Lọc theo category_id.
Bộ lọc Nhãn dán Dropdown (Multi-select) - Hiển thị danh sách Tags/Label. - Lọc theo tag_id.
Bộ lọc Năm Dropdown - Hiển thị số năm (VD: 2025, 2026).

- Mặc định: Get Current Year của hệ thống để hiển thị.


- Khi thay đổi, reload lại lịch theo năm chọn.

Bộ lọc Tháng Dropdown - Hiển thị tháng (Jan - Dec).

- Mặc định: Get Current Month của hệ thống.


- Khi thay đổi, reload lại lịch theo tháng chọn.

Lưới lịch (Calendar Grid) UI Component

- Lưới 7 cột (Su - Sa).


- Các ngày có sự kiện: Hiển thị chấm tròn màu (theo trạng thái) hoặc tên vắn tắt.


- Ô ngày hiện tại: Highlight viền hoặc màu nền khác biệt.

- Click vào ô trống (Ngày chưa có lịch): Gọi sự kiện mở Modal "Tạo mới" (Màn hình 2.1). Truyền tham số start_date = Ngày vừa click.


- Click vào item lịch: Gọi API lấy chi tiết lịch -> Mở Drawer "Chi tiết" (Màn hình 3).

Nút "Đặt lịch" Button

- Nút màu tím (Primary Color).


- Icon dấu cộng (+).

- Sự kiện onClick: Mở Modal "Tạo mới lịch checklist".

2. Màn hình Tạo mới Đặt lịch

2.1. Màn hình tạo mới với tần suất 1 lần

 

image.png
Màn hình 2.1 - Màn hình mặc định khi bấm Tạo mới Đặt lịch và mặc định là tần suất 1 lần

 

Khu vực Tên trường Bắt buộc Mô tả giao diện (UI) Logic xử lý (System/Business Logic)
Header Nút Đóng / Lưu -

- Nút "Đóng": Góc phải trên.


- Nút "Lưu": Nút màu tím nổi bật.

- Đóng: Đóng modal, không lưu dữ liệu, clear form.


- Lưu: Trigger validate form -> Nếu Pass -> Gọi API CreateSchedule -> Thông báo thành công -> Reload lại lịch.

Thông tin chung Tên lịch checklist Có

- Input text.


- Hiển thị bộ đếm ký tự góc phải (0/200).

- Validate: Không được để trống.


- Validate: Max length = 200 ký tự.

  Biểu mẫu sử dụng Có

- Dropdown single select.


- Có dòng note hướng dẫn bên dưới.

- Load danh sách Template đang Active.


- Khi chọn, hệ thống mapping ID questionnaire vào lịch.

- Validate: Không được để trống.

Thực hiện Người thực hiện Có

 

1. Trạng thái đóng: Khi chưa chọn


- Hiển thị input box.


- Placeholder: "Chọn người thực hiện".



2. Trạng thái mở (Dropdown):


- Có 2 Tab: Cá nhân và Nhóm.


- Có thanh tìm kiếm (Search bar) trên cùng.


- Nút "Lưu" màu tím ở dưới cùng của dropdown.



3. Tab Cá nhân (Default):


- List user (Display name)


- Mỗi dòng cho phép có cơ chế chọn nhiều.


- Đã chọn: Hiển thị dấu tích (Checkmark) bên phải.



4. Tab Nhóm:


- List danh sách các nhóm (Nhóm 1, Nhóm 2...).


- Cơ chế chọn: Single select (Chọn 1). 



 

- Validate: Không được để trống.

-Mặc định khi bấm tạo mới lịch sẽ hiển thị nút gán người thực hiện mà chưa có các lựa chọn ở phía dưới.

1. Logic Tìm kiếm:


- Filter danh sách user/nhóm theo từ khóa nhập vào (Local search hoặc API search).

-Chỉ có thể chọn cá nhân hoặc nhóm, khi đang chọn cá nhân mà đổi sang tab nhóm và chọn 1 giá trị sẽ clear toàn bộ giá trị cá nhân đã chọn tương tự với khi chọn nhóm mà đổi sang và chọn cá nhân.



2. Logic Tab Cá nhân (Multi-select):


- Cho phép tích chọn nhiều User ID vào mảng selected_users.


- Quy tắc Reset: Ngay khi user thực hiện chọn (click) vào 1 user bất kỳ tại tab này -> Hệ thống tự động Clear (Xóa rỗng) giá trị của selected_group_id (nếu trước đó đã chọn nhóm).



3. Logic Tab Nhóm (Single-select):


- Chỉ cho phép chọn duy nhất 1 Group ID 


- Quy tắc Reset: Ngay khi user thực hiện chọn (click) vào 1 nhóm bất kỳ -> Hệ thống tự động Clear (Xóa rỗng) toàn bộ mảng selected_users (nếu trước đó đã chọn cá nhân).



4. Nút Lưu (trong dropdown):


- Sự kiện: Đóng dropdown.


- Hiển thị text lên input box:


+ Nếu chọn Cá nhân: Hiển thị tên các user (cách nhau dấu phẩy) hoặc dạng Tags.


+ Nếu chọn Nhóm: Hiển thị tên nhóm.

 

 

 


Tất cả hoàn thành Không

Quy tắc hoàn thành  Chỉ xuất hiện khi trường "Người thực hiện" có dữ liệu chọn "nhiều người" hoặc "Nhóm thực hiện"


- Dạng nút chọn (Radio Button).

Tất cả hoàn thành: Khi tạo lịch, hệ thống sẽ yêu cầu mọi user được gán đều phải submit checklist thì checklist mới được tính là "Done" 


Chỉ cần 1 người

Quy tắc hoàn thành  Chỉ xuất hiện khi trường "Người thực hiện" có dữ liệu chọn nhiều "người thực hiện" hoặc/và "Nhóm thực hiện"


- Dạng nút chọn (Radio Button).

  • Giá trị chọn Mặc định

Check list được chia sẻ chung. Chỉ cần 1 trong số các user được gán submit là  check list hoàn thành (First-come first-served).


☑ Tự lấy người theo địa điểm.


- Chỉ xuất hiện khi trường "Người thực hiện" có dữ liệu.


- Dạng Checkbox.

- Khi Uncheck (False): Giữ nguyên danh sách người/nhóm đã chọn ở trên.


- Khi Check (True): Kích hoạt logic giao điểm (Intersection).


+ Hệ thống sẽ lấy danh sách User trong Nhóm/List đã chọn VÀ (AND) User đó phải thuộc Site được chọn ở trường "Địa điểm thực hiện".


+ Ví dụ: Chọn "Nhóm Quản lý" + Check "Tự lấy theo địa điểm" + Địa điểm "Kho A" -> Hệ thống chỉ gán check list cho các Quản lý đang làm việc tại Kho A.

  Địa điểm thực hiện Không - Dropdown Multi-select.
  • Lưu danh sách Site_ID
  • Nếu số lượng địa điểm = 1 → hệ thống tạo 1 lịch checklist
  • Nếu số lượng địa điểm > 1 → hệ thống tạo N lịch checklist, với N = số địa điểm. Mỗi lịch sinh ra sẽ có:
    • Cùng tên lịch
    • Cùng biểu mẫu checklist
    • Cùng người thực hiện
    • Cùng thời gian & tần suất
    • Khác địa điểm
  • Các lịch sinh ra được xem là độc lập, có ID riêng
  • Nếu tạo lịch lặp (recurring) + nhiều địa điểm → số bản ghi sinh ra = số địa điểm × số lần lặp
Thời gian Múi giờ Có - Dropdown chọn múi giờ.
  • Các giá trị enum. Hiện tại  Mặc định: Auto-detect múi giờ theo setting của User hiện tại (Client time).
  • Không xóa 
  Thời lượng thực hiện Có

- 2 ô Input: Ngày bắt đầu (Date) + Giờ (Time) và Ngày kết thúc (Date) + Giờ (time)


- Note: "Mỗi lịch được thực hiện trong X giờ".

- Validate: End_Time phải lớn hơn  bằng Start_Time.


- Hệ thống tự tính toán Duration = End - Start để hiển thị gợi ý.

-Mặc định là ngày hiện tại . Giờ mặc định là giờ hiện tại  

  Tần suất Có
  • Dropdown select. 
  • Các giá trị gồm:
    • Một lần
    • Hàng ngày
    • Hàng ngày làm việc 
    • Hàng tuần
    • Hàng tháng
    • Hàng năm
    • Tùy biến
  • Note " Lịch sẽ được lặp đi lặp lại hay không?" 

- Mặc định: Set giá trị là "Một lần" (One-time).

 

LƯU Ý KHI LỰA CHỌN ĐỔI GIÁ TRỊ TỪ MỘT LẦN SANG CÁC TẦN SUẤT KHÁC

  • Nếu thời lượng thực hiện có tổng time < = 24 giờ (Tính từ ngày bắt đầu - giờ bắt đầu đến ngày kết thúc đến giờ kết thúc < =24h) --> THì hiện thị toàn bộ các tần suất
    • Một lần
    • Hàng ngày
    • Hàng ngày làm việc 
    • Hàng tuần
    • Hàng tháng
    • Hàng năm
    • Tùy biến

--> Lý do : Tần suất hàng ngày và hàng ngày lv cho phép vắt ngày thực hiện .  (- Miễn là tổng thời gian thực hiện không quá 1 ngày thì vẫn đảm bảo logic lặp lại hàng ngày được.)

  • Nếu thời lượng thực hiện có tổng time >24h thì chỉ hiển thì các tần suất:
    • Một lần
    • Hàng tuần
    • Hàng Tháng
    • Hàng năm
    • Tùy biến

--> Lý do: Nếu một checklist kéo dài > 24h (Ví dụ: Từ 8:00 Thứ 2 đến 8:00 Thứ 4), nó không thể lặp lại "Hàng ngày" vì sẽ gây xung đột chồng chéo thời gian (Overlap) giữa lịch cũ chưa xong và lịch mới sinh ra.)

 

Nếu người dùng đang chọn Tần suất là "Hàng ngày", sau đó quay lại sửa giờ kết thúc thì disable không cho chọn ngày vượt quá 24h. Nếu nhập thời gian >24h thì tự động reset về tần suất 1 lần

 

- Nếu chọn loại khác (Hàng ngày/tuần...), hiển thị thêm UI cấu hình lặp lại (Recurrence Rules).

Các màn hình tiếp theo số: 2.2; 2.3; 2.4; 2.5

  Hoàn thành sau thời hạn Không

- Toggle Switch (On/Off).


- Note: "Cho phép ngườii dùng hoàn thành check list sau thời gian quy định lên tới 14 ngày"

- OFF (False): Đến End_Time trạng thái chuyển sang "Hết hạn", không cho submit 


- ON (True): Cho phép submit sau End_Time nhưng đánh dấu là "Late".

Cho phép người dùng được làm checklist theo lịch ngay cả khi hết hạn hoàn thành theo thời gian làm khi bật tính năng này.

Sau 14 ngày mà k được thực hiện thì Checklist được tính về Bỏ lỡ.

2.2. Màn hình tạo mới với tần suất "Hằng ngày"    

image.png
Màn hình 2.2 - Tạo mới đặt lịch với tần suất hàng ngày

Modal tạo mới đặt lịch với tần suất hàng ngày, các cụm thông tin tương tự với tần suất 1 lần gồm

  • Thông tin chung
  • Thực hiện
  • Thời gian

Các thông tin khác khi lựa chọn tần suất hàng ngày , cụ thẻ mô tả chi tiết và logic xử lý như sau:

Tên trường / Chức năng Bắt buộc Mô tả giao diện (UI) Logic xử lý (System/Business Logic)




Múi giờ Có - Dropdown chọn múi giờ.
  • Các giá trị enum. Hiện tại  Mặc định: Auto-detect múi giờ theo setting của User hiện tại (Client time).
  • Không xóa 
Thời lượng thực hiện Có

- 2 ô Input: Ngày bắt đầu (Date) + Giờ (Time) và Ngày kết thúc (Date) + Giờ (time)


- Note: "Mỗi lịch được thực hiện trong X giờ".

- Validate: End_Time phải lớn hơn  bằng Start_Time.


- Hệ thống tự tính toán Duration = End - Start để hiển thị gợi ý.

-Mặc định là ngày hiện tại . Giờ mặc định là giờ hiện tại  

Tần suất Có

- Dropdown select.


- Giá trị chọn: "Hàng ngày" (Daily).

- Khi giá trị thay đổi sang "Hàng ngày" (hoặc Hàng tuần/tháng) 

  • Lưu ý trường hợp đặt lịch vắt ngày
    • Nếu thời lượng thực hiện có tổng time < = 24 giờ (Tính từ ngày bắt đầu - giờ bắt đầu đến ngày kết thúc đến giờ kết thúc < =24h) --> THì hiện thị toàn bộ các tần suất
      • Một lần
      • Hàng ngày
      • Hàng ngày làm việc 
      • Hàng tuần
      • Hàng tháng
      • Hàng năm
      • Tùy biến

    --> Lý do : Tần suất hàng ngày và hàng ngày lv cho phép vắt ngày thực hiện .  (- Miễn là tổng thời gian thực hiện không quá 1 ngày thì vẫn đảm bảo logic lặp lại hàng ngày được.)

    • Nếu thời lượng thực hiện có tổng time >24h thì chỉ hiển thì các tần suất:
      • Một lần
      • Hàng tuần
      • Hàng Tháng
      • Hàng năm
      • Tùy biến

    --> Lý do: Nếu một checklist kéo dài > 24h (Ví dụ: Từ 8:00 Thứ 2 đến 8:00 Thứ 4), nó không thể lặp lại "Hàng ngày" vì sẽ gây xung đột chồng chéo thời gian (Overlap) giữa lịch cũ chưa xong và lịch mới sinh ra.)

     

    Nếu người dùng đang chọn Tần suất là "Hàng ngày", sau đó quay lại sửa giờ kết thúc thì disable không cho chọn ngày vượt quá 24h. Nếu nhập thời gian >24h thì tự động reset về tần suất 1 lần

 

Kết thúc


(Cấu hình vòng lặp)

Có

Hiển thị:


- Label: "Kết thúc".


- Dạng: Radio Group (Chọn 1 trong 3).



Các tùy chọn:


1. 🔘 Không bao giờ (Never). --> Mặc định



2. ⚪ Vào ngày (On Date):


- Kèm theo 1 Date Picker bên cạnh.


- Placeholder: DD/MM/YYYY.



3. ⚪ Sau (After):


- Kèm theo 1 Input Number.


- Placeholder: "10".


- Label đuôi: "Vòng lặp" (Occurrences).

1. Tùy chọn "Không bao giờ":


- Hệ thống sẽ sinh lịch vô hạn (Yêu cầu sinh cho 05 năm tới để tránh ảnh hưởng tới performance hệ thống)



2. Tùy chọn "Vào ngày":


- Cho phép user chọn ngày kết thúc chuỗi lặp.


- Validate: End_Recurrence_Date phải lớn hơn Start_Date của lịch.


- Hệ thống sẽ sinh lịch từ ngày bắt đầu cho đến ngày này thì dừng.

 

Chỉ cho phép chọn ngày tương lai. Nếu cùng 1 ngày với trên Block thời lượng thì lịch sẽ chỉ diễn ra 1 ngày.

 



3. Tùy chọn "Sau [N] vòng lặp":


- Cho phép user nhập số lần lặp lại mong muốn.


- Validate: Input phải là số nguyên dương (Integer > 0) . Tối đa 500 vòng lặp


- Ví dụ: Nhập 10 -> Hệ thống sinh đúng 10 bản ghi lịch checklist rồi dừng. 

2.2.1 Cơ chế hiển thị sinh lịch tại trang chủ "Của tôi" (Check list được sinh ra của hôm nay với user hiện tại)

checklist có: Ngày thực hiện là T, Giờ bắt đầu là Start_Time, Giờ kết thúc là End_Time.

Giai đoạn Điều kiện thời gian (Current Time) Trạng thái hiển thị  Hành động cho phép (Action)

1. Sắp diễn ra


(Early View)

00:00 Ngày T ≤ Hiện tại < Start_Time

👁️ HIỂN THỊ (Visible)


- Style: Màu xám hoặc mờ nhẹ (Dimmed).


- Label/Badge: ⚠️ "Chưa đến hạn thực hiện" (hoặc "Sắp diễn ra").


- Icon: 🔒 (Ổ khóa - tùy chọn).

⛔ KHÓA (Disabled)


- Không cho phép mở form nhập liệu.


- Khi bấm vào: Hiển thị thông báo (Toast): "Công việc bắt đầu lúc [Start_Time]. Vui lòng quay lại sau."

2. Đang diễn ra


(Active)

Start_Time ≤ Hiện tại ≤ End_Time

👁️ HIỂN THỊ (Visible)


- Style: Nổi bật, bình thường.


- Label/Badge: 🟢 "Cần làm" / "Đang thực hiện".

✅ CHO PHÉP (Enabled)


- Bấm vào để mở form checklist.


- Cho phép thực hiện, lưu nháp, hoàn thành.

3. Quá hạn


(Expired)

Hiện tại > End_Time

❌ ẨN (Hidden)


- Biến mất khỏi danh sách "Cần làm" ngay lập tức.


- (Logic Backend): Hệ thống update trạng thái bản ghi thành "Missed" (Bỏ lỡ) hoặc "Expired" nếu chưa hoàn thành.

⛔ CHẶN


- Nếu user đang mở form dở dang mà đồng hồ điểm qua End_Time -> Khi bấm Submit sẽ báo lỗi: "Đã hết thời gian thực hiện checklist này".


2.2.2. Logic Xử lý Lịch Vắt ngày (Straddling Logic)

Áp dụng cho trường hợp checklist bắt đầu từ ngày hôm trước và kéo dài sang sáng hôm sau.

Ví dụ cụ thể:

  • Ca làm việc: Ca 3 (22:00 -> 02:00 sáng hôm sau).

  • Tần suất: Hàng ngày.

Mô phỏng hiển thị vào lúc 01:00 sáng ngày 02/01:

Lúc này là 01:00 sáng, hệ thống sẽ hiển thị đồng thời 2 checklist trong danh sách của nhân viên:

Tên Checklist Thời gian quy định Trạng thái lúc 01:00 Giải thích logic

Checklist A


(Của đêm hôm qua)

22:00 (01/01) -> 02:00 (02/01)  Đang diễn ra Vì Hiện tại (01:00) vẫn nằm trong khoảng cho phép (<= 02:00). User đang thực hiện nốt checklist này.

Checklist B


(Của đêm nay)

22:00 (02/01) -> 02:00 (03/01) Chưa đến hạn Vì Hiện tại (01:00) đã qua mốc 00:00 của ngày 02/01 nên checklist này được sinh ra và hiển thị sớm. Tuy nhiên, do chưa đến 22:00 nên bị Khóa.

Kết quả UX: Nhân viên trực ca đêm lúc 1h sáng sẽ thấy:

  1. Checklist Ca 3 đang làm dở (để vào check nốt).

  2. Checklist Ca 3 của tối nay (để biết tối nay mình vẫn có lịch, nhưng chưa làm được).


2.2.3. Lưu ý kỹ thuật cho Dev (Technical Notes)

  1. Job sinh lịch (Daily Job):

    • Job quét để sinh checklist hàng ngày cần chạy vào lúc 00:00 (Midnight) của ngày đó (hoặc sớm hơn).

    • Dữ liệu Start_Time và End_Time phải được lưu chính xác kèm Date (DateTime format).

  2. Real-time Update (Cập nhật thời gian thực):

    • Frontend cần có cơ chế setInterval hoặc Timer để check thời gian mỗi phút.

    • Mục đích: Để tự động chuyển trạng thái từ "Chưa đến hạn" -> "Đang diễn ra" -> "Ẩn" mà không cần user phải F5 (Reload) lại trang. Đặc biệt quan trọng với việc Ẩn ngay khi quá hạn.

 

2.3. Màn hình tạo mới với tần suất "Hàng ngày làm việc" 

 

image.png
Màn hình 2.3 - Đặt lịch với tần suất hàng ngày làm việc

 

  Modal tạo mới đặt lịch với tần suất hàng ngày, các cụm thông tin tương tự với tần suất 1 lần gồm

  • Thông tin chung
  • Thực hiện
  • Thời gian

Các thông tin khác khi lựa chọn tần suất " hàng ngày làm việc" , cụ thẻ mô tả chi tiết và logic xử lý như sau:

Tên trường / Chức năng Bắt buộc Mô tả giao diện (UI) Logic xử lý (System/Business Logic)
Múi giờ Có - Dropdown chọn múi giờ.
  • Các giá trị enum. Hiện tại  Mặc định: Auto-detect múi giờ theo setting của User hiện tại (Client time).
  • Không xóa 
Thời lượng thực hiện Có

- 2 ô Input: Ngày bắt đầu (Date) + Giờ (Time) và Ngày kết thúc (Date) + Giờ (time)


- Note: "Mỗi lịch được thực hiện trong X giờ".

- Validate: End_Time phải lớn hơn  bằng Start_Time.


- Hệ thống tự tính toán Duration = End - Start để hiển thị gợi ý.

-Mặc định là ngày hiện tại . Giờ mặc định là giờ hiện tại  

Tần suất Có

- Dropdown select.


- Giá trị chọn: "Hàng ngày làm việc".


- Note bên dưới: "Lịch sẽ được lặp đi lặp lại hay không?".

- Khi chọn giá trị này, hệ thống cũng Hiển thị (Unhide) khối cấu hình "Kết thúc" (tương tự như chọn Hàng ngày).


- Logic sinh lịch (Generation Logic):


+ Hệ thống xác định "Ngày làm việc" dựa trên cấu hình Lịch làm việc của Công ty (Working Calendar) hoặc mặc định là từ Thứ 2 đến Thứ 6.


+ Bỏ qua (Skip): Thứ 7, Chủ Nhật và các ngày Lễ/Tết (nếu hệ thống có cấu hình nghỉ lễ).

HIỆN TẠI CHƯA LÀM CẤU HÌNH NGHỈ LỄ

LƯU Ý KHI LỰA CHỌN ĐỔI GIÁ TRỊ TỪ MỘT LẦN SANG CÁC TẦN SUẤT KHÁC

  • Nếu thời lượng thực hiện có tổng time < = 24 giờ (Tính từ ngày bắt đầu - giờ bắt đầu đến ngày kết thúc đến giờ kết thúc < =24h) --> THì hiện thị toàn bộ các tần suất
    • Một lần
    • Hàng ngày
    • Hàng ngày làm việc 
    • Hàng tuần
    • Hàng tháng
    • Hàng năm
    • Tùy biến

--> Lý do : Tần suất hàng ngày và hàng ngày lv cho phép vắt ngày thực hiện .  (- Miễn là tổng thời gian thực hiện không quá 1 ngày thì vẫn đảm bảo logic lặp lại hàng ngày được.)

  • Nếu thời lượng thực hiện có tổng time >24h thì chỉ hiển thì các tần suất:
    • Một lần
    • Hàng tuần
    • Hàng Tháng
    • Hàng năm
    • Tùy biến

--> Lý do: Nếu một checklist kéo dài > 24h (Ví dụ: Từ 8:00 Thứ 2 đến 8:00 Thứ 4), nó không thể lặp lại "Hàng ngày" vì sẽ gây xung đột chồng chéo thời gian (Overlap) giữa lịch cũ chưa xong và lịch mới sinh ra.)

 

Nếu người dùng đang chọn Tần suất là "Hàng ngày làm việc", sau đó quay lại sửa giờ kết thúc thì disable không cho chọn ngày vượt quá 24h. Nếu nhập thời gian >24h thì tự động reset về tần suất 1 lần

 

 

Kết thúc Có

(Giữ nguyên giao diện như phiên bản 2.4)


- 🔘 Không bao giờ.


- ⚪ Vào ngày [Date].


- ⚪ Sau [N] vòng lặp.

Logic áp dụng cho "Hàng ngày làm việc":


1. Không bao giờ: Sinh lịch vô hạn vào các ngày làm việc. (Yêu cầu sinh cho 05 năm tới để tránh ảnh hưởng tới performance hệ thống)


2. Vào ngày: Sinh lịch vào các ngày làm việc cho đến mốc thời gian này.


3. Sau [N] vòng lặp:


- Ví dụ: User nhập "Sau 5 vòng lặp" và bắt đầu từ Thứ 6. Nhập số nguyên dương, tối đa 500 vòng lặp


- Hệ thống sinh: T6, T2, T3, T4, T5 (Bỏ qua T7, CN). Đủ 5 bản ghi thì dừng.


So sánh Logic sinh lịch Hàng ngày vs Hàng ngày làm việc

Tiêu chí Hàng ngày (Daily) Hàng ngày làm việc (Daily on Workdays)
Định nghĩa Lặp lại vào tất cả các ngày trong tuần (Mon - Sun). Chỉ lặp lại vào ngày làm việc (thường là Mon - Fri).
Xử lý T7, CN CÓ sinh lịch. KHÔNG sinh lịch (Bỏ qua).
Xử lý ngày Lễ CÓ sinh lịch (trừ khi có rule đặc biệt khác). KHÔNG sinh lịch (Nếu lịch làm việc định nghĩa đó là ngày nghỉ). --> HIỆN TẠI CHƯA CÓ CẤU HÌNH NÀY
Ví dụ Input Bắt đầu T6, Lặp 3 lần. Bắt đầu T6, Lặp 3 lần.
Kết quả Output T6, T7, CN. T6, T2, T3 (Bỏ qua T7, CN).

2.2.1 Cơ chế hiển thị sinh lịch tại trang chủ "Của tôi" (Check list được sinh ra của hôm nay với user hiện tại)

Giai đoạn Điều kiện thời gian (Current Time) Trạng thái hiển thị  Hành động cho phép (Action)

1. Sắp diễn ra


(Early View)

00:00 Ngày T ≤ Hiện tại < Start_Time

👁️ HIỂN THỊ (Visible)


- Style: Màu xám hoặc mờ nhẹ (Dimmed).


- Label/Badge: ⚠️ "Chưa đến hạn thực hiện" (hoặc "Sắp diễn ra").


- Icon: 🔒 (Ổ khóa - tùy chọn).

⛔ KHÓA (Disabled)


- Không cho phép mở form nhập liệu.


- Khi bấm vào: Hiển thị thông báo (Toast): "Công việc bắt đầu lúc [Start_Time]. Vui lòng quay lại sau."

2. Đang diễn ra


(Active)

Start_Time ≤ Hiện tại ≤ End_Time

👁️ HIỂN THỊ (Visible)


- Style: Nổi bật, bình thường.


- Label/Badge: 🟢 "Cần làm" / "Đang thực hiện".

✅ CHO PHÉP (Enabled)


- Bấm vào để mở form checklist.


- Cho phép thực hiện, lưu nháp, hoàn thành.

3. Quá hạn


(Expired)

Hiện tại > End_Time

❌ ẨN (Hidden)


- Biến mất khỏi danh sách "Cần làm" ngay lập tức.


- (Logic Backend): Hệ thống update trạng thái bản ghi thành "Missed" (Bỏ lỡ) hoặc "Expired" nếu chưa hoàn thành.

⛔ CHẶN


- Nếu user đang mở form dở dang mà đồng hồ điểm qua End_Time -> Khi bấm Submit sẽ báo lỗi: "Đã hết thời gian thực hiện checklist này".

2.2.2. Logic Xử lý Lịch Vắt ngày (Straddling Logic)

  • Nếu Start_Date là Ngày làm việc (T2 - T6) -> SINH LỊCH (Kể cả khi giờ kết thúc rơi vào T7/CN).

  • Nếu Start_Date là Ngày nghỉ (T7, CN) -> BỎ QUA (Không sinh lịch).

  • Ví du: Ca làm việc từ 22:00 đêm đến 02:00 sáng hôm sau. Ngày nghỉ là T7, CN.

    Bảng kịch bản Sinh lịch (Scenario Table)

    Thứ (Ngày bắt đầu) Thời gian thực hiện Hành động hệ thống Giải thích
    Thứ 2 22:00 T2 -> 02:00 T3 Sinh lịch T2 là ngày làm việc.
    Thứ 3- Thứ 4 ... ... ... tương tự thứ 2
    Thứ 5 22:00 T5 -> 02:00 T6 Sinh lịch T5 là ngày làm việc.
    Thứ 6 22:00 T6 -> 02:00 T7 SINH LỊCH Quan trọng: Dù kết thúc vào sáng T7 (Ngày nghỉ), nhưng ca này bắt đầu vào T6 (Ngày làm việc) nên vẫn hợp lệ. Nhân viên làm ca đêm T6 vẫn phải có checklist.
    Thứ 7 22:00 T7 -> 02:00 CN  Bỏ qua T7 là ngày nghỉ -> Không có ca đêm bắt đầu vào T7.
    Chủ Nhật 22:00 CN -> 02:00 T2 Bỏ qua CN là ngày nghỉ -> Không có ca đêm bắt đầu vào CN.
    Thứ 2 (Tuần sau) 22:00 T2 -> 02:00 T3  Sinh lịch Quay lại chu kỳ làm việc

2.4. Màn hình tạo mới với tần suất "Hàng tuần"

image.png
Màn hình 2.4- Đặt lịch với tần suất Hàng tuần

  Modal tạo mới đặt lịch với tần suất "Hàng tuần", các cụm thông tin tương tự với tần suất 1 lần gồm

  • Thông tin chung
  • Thực hiện
  • Thời gian

Các thông tin khác khi lựa chọn tần suất " hàng ngày làm việc" , cụ thẻ mô tả chi tiết và logic xử lý như sau:

Tên trường / Chức năng Bắt buộc Mô tả giao diện (UI)
Logic xử lý (System/Business Logic)
Tần suất Có - Dropdown select.- Giá trị chọn: "Hàng tuần".- Note bên dưới: "Lịch sẽ được lặp đi lặp lại hay không?".
- Khi chọn giá trị này, hệ thống Hiển thị (Unhide) khối cấu hình "Kết thúc".Logic sinh lịch (Generation Logic):
1. Xác định ngày cơ sở: Hệ thống lấy Day_Of_Week (Thứ) của trường Start_Date.
- Ví dụ: Ngày bắt đầu 02/11/2020 là Thứ Hai.
2. Quy tắc lặp: Hệ thống sẽ sinh lịch vào Thứ Hai của các tuần tiếp theo.
 - Interval (Khoảng cách) = 7 ngày.
Kết thúc Có (Giữ nguyên giao diện như các phiên bản trước)- 🔘 Không bao giờ.- ⚪ Vào ngày [Date].- ⚪ Sau [N] vòng lặp.
Logic áp dụng cho "Hàng tuần":
1. Không bao giờ: Sinh lịch vào thứ định sẵn vô hạn.
2. Vào ngày:
- Sinh lịch hàng tuần cho đến khi ngày dự kiến > ngày kết thúc cấu hình.
- Ví dụ: Nếu ngày kết thúc rơi vào giữa tuần (T4) mà lịch lặp vào T6 -> Bản ghi cuối cùng là T6 tuần trước đó.
3. Sau [N] vòng lặp: - Sinh đúng N bản ghi. Ví dụ nhập 4 vòng lặp -> Hệ thống tạo lịch cho 4 tuần liên tiếp.

3. Màn hình Chi tiết Lịch (View Mode)

Tên trường / Nút Loại hiển thị Mô tả giao diện (UI) Logic xử lý (System/Business Logic)
Header Nút Action

- Nút "Tạm ngừng": Style Danger/Warning.


- Nút "Sửa": Style Primary.


- Mã lịch: Hiển thị ID dạng text (Read-only).

- Tạm ngừng: Update status = Inactive (hoặc Paused). Ngăn chặn sinh ra checklist mới từ lịch này.


- Sửa: Mở lại form Tạo mới (Màn hình 2) nhưng bind dữ liệu cũ vào các trường để user chỉnh sửa.

Thông tin chính Tiêu đề & Trạng thái

- Tiêu đề: Font to, in đậm.


- Trạng thái: Badge màu (Xanh: Active, Xám: Inactive).

- Hiển thị đúng tên lịch đã lưu.


- Mapping trạng thái từ DB ra màu sắc tương ứng.

Chi tiết Các trường thông tin

- Hiển thị dạng Label: Value.


- Các trường: Biểu mẫu, Người thực hiện, Địa điểm, Múi giờ...

- Tất cả đều ở trạng thái Read-only (Chỉ xem).


- Dữ liệu Người thực hiện: Nếu > 5 người, hiển thị Avatar stack (+5) để tiết kiệm diện tích.

Cấu hình Tần suất & Deadline

- Tần suất: Hiển thị text.


- Hoàn thành sau hạn: Text "Cho phép" / "Không".

- Hiển thị cấu hình hiện tại của lịch.