<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>FT-TASK-MGMT-01 · Tài liệu Triển khai Module Quản lý Task Nội bộ — NolimitHub</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600&family=Noto+Sans+SC:wght@400;500;600;700&family=Noto+Serif+SC:wght@500;600;700&display=swap" rel="stylesheet">
<script>
tailwind.config = {
theme: {
extend: {
colors: {
ink: { 50:'#fafafa', 100:'#f5f5f5', 200:'#e7e7e7', 300:'#d4d4d4', 400:'#a3a3a3', 500:'#737373', 600:'#525252', 700:'#404040', 800:'#262626', 900:'#171717', 950:'#0a0a0a' },
brand: { 50:'#eef4ff', 100:'#dbe6ff', 200:'#bccfff', 300:'#8eabff', 400:'#5b7ffb', 500:'#3a5bf0', 600:'#2843d9', 700:'#1f33b0', 800:'#1d2f8a', 900:'#1c2a6e' },
accent: { 500:'#f59e0b', 600:'#d97706' }
},
fontFamily: {
sans: ['Inter','Noto Sans SC','system-ui','sans-serif'],
serif: ['Noto Serif SC','serif'],
mono: ['JetBrains Mono','ui-monospace','monospace']
}
}
}
}
</script>
<style>
html { scroll-behavior: smooth; scroll-padding-top: 88px; }
body { font-feature-settings: "ss01","cv11"; }
.prose-doc h2 { font-family: 'Inter','Noto Serif SC',serif; }
.prose-doc p, .prose-doc li { color: #404040; line-height: 1.78; }
.prose-doc a { color: #2843d9; text-decoration: underline; text-underline-offset: 3px; text-decoration-color: #bccfff; }
.toc-link.active { color:#1f33b0; border-color:#3a5bf0; font-weight:600; }
.nav-link.active { background:#eef4ff; color:#1f33b0; font-weight:600; }
.nav-link.active .nav-bar { background:#3a5bf0; }
.gridline { background-image: linear-gradient(to right, #f5f5f5 1px, transparent 1px); background-size: 8px 100%; }
.scrollbar-thin::-webkit-scrollbar { width: 6px; }
.scrollbar-thin::-webkit-scrollbar-thumb { background: #d4d4d4; border-radius: 999px; }
details > summary { list-style: none; cursor: pointer; }
details > summary::-webkit-details-marker { display: none; }
.chip { font-feature-settings: "tnum"; }
.lifecycle-arrow::after {
content: '→'; color: #a3a3a3; margin: 0 .35rem;
}
.dark body { background:#0a0a0a; color:#fafafa; }
.dark .prose-doc p, .dark .prose-doc li { color:#d4d4d4; }
.dark .bg-white { background:#171717 !important; }
.dark .bg-ink-50 { background:#0a0a0a !important; }
.dark .border-ink-200 { border-color:#262626 !important; }
.dark .text-ink-900 { color:#fafafa !important; }
.dark .text-ink-800 { color:#e7e7e7 !important; }
.dark .text-ink-700 { color:#d4d4d4 !important; }
.dark .text-ink-600 { color:#a3a3a3 !important; }
.dark .text-ink-500 { color:#737373 !important; }
.dark code:not(pre code) { background:#262626 !important; color:#fafafa; }
</style>
</head>
<body class="font-sans bg-ink-50 text-ink-900 antialiased">
<!-- ============ TOP BAR ============ -->
<header class="sticky top-0 z-40 bg-white/85 backdrop-blur border-b border-ink-200">
<div class="max-w-[1440px] mx-auto px-6 h-16 flex items-center gap-6">
<a href="#top" class="flex items-center gap-2.5 shrink-0">
<div class="w-8 h-8 rounded-lg bg-ink-950 flex items-center justify-center">
<span class="text-white font-bold text-sm">N</span>
</div>
<div class="leading-tight">
<div class="text-[13px] font-semibold tracking-tight">NolimitHub <span class="text-ink-400 font-normal">/ docs</span></div>
<div class="text-[10px] text-ink-500 uppercase tracking-widest">internal feature spec</div>
</div>
</a>
<nav class="hidden md:flex items-center gap-1 text-[13px] text-ink-600">
<a href="#overview" class="px-2.5 py-1 rounded hover:bg-ink-100">Overview</a>
<a href="#context" class="px-2.5 py-1 rounded hover:bg-ink-100">Context</a>
<a href="#lifecycle" class="px-2.5 py-1 rounded hover:bg-ink-100">Lifecycle</a>
<a href="#api-ref" class="px-2.5 py-1 rounded hover:bg-ink-100">Reference</a>
</nav>
<div class="flex-1"></div>
<!-- Search -->
<div class="hidden sm:flex items-center gap-2 px-3 h-9 w-72 bg-ink-50 border border-ink-200 rounded-lg text-ink-500 text-[13px] focus-within:border-brand-500 focus-within:bg-white transition-all">
<svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><circle cx="11" cy="11" r="7"/><path d="m21 21-4.3-4.3"/></svg>
<input type="text" placeholder="Tìm trong tài liệu..." class="bg-transparent outline-none w-full placeholder:text-ink-400">
<kbd class="text-[10px] font-mono px-1.5 py-0.5 bg-white border border-ink-200 rounded text-ink-500">⌘ K</kbd>
</div>
<!-- Version -->
<div class="flex items-center gap-1.5 px-2.5 h-9 bg-white border border-ink-200 rounded-lg text-[12px] font-mono text-ink-700">
<span class="w-1.5 h-1.5 rounded-full bg-emerald-500"></span>
v0.1 · Draft
<svg class="w-3 h-3 text-ink-400" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="m6 9 6 6 6-6"/></svg>
</div>
<!-- Theme toggle -->
<button onclick="document.documentElement.classList.toggle('dark')" class="w-9 h-9 flex items-center justify-center rounded-lg border border-ink-200 hover:bg-ink-100 transition-all" aria-label="Toggle theme">
<svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg>
</button>
</div>
<!-- Breadcrumb -->
<div class="max-w-[1440px] mx-auto px-6 h-10 flex items-center gap-2 text-[12px] text-ink-500 border-t border-ink-200 bg-ink-50">
<span>NolimitHub</span>
<span class="text-ink-300">/</span>
<span>Internal Modules</span>
<span class="text-ink-300">/</span>
<span>Task Management</span>
<span class="text-ink-300">/</span>
<span class="text-ink-900 font-medium">FT-TASK-MGMT-01 — Triển khai vòng đời, phân phối, task con, chat & thông báo</span>
<div class="flex-1"></div>
<span class="font-mono">Last reviewed · 08/06/2026</span>
</div>
</header>
<div id="top" class="max-w-[1440px] mx-auto px-6 grid grid-cols-12 gap-8">
<!-- ============ INLINE-START NAV ============ -->
<aside class="hidden lg:block col-span-2 pt-10">
<div class="sticky top-32 max-h-[calc(100vh-9rem)] overflow-y-auto scrollbar-thin pr-2">
<div class="text-[10px] font-semibold uppercase tracking-[0.18em] text-ink-400 mb-3">Specification</div>
<nav id="sideNav" class="space-y-0.5 text-[13px] mb-8">
<a href="#overview" class="nav-link flex items-center gap-2 px-2.5 py-1.5 rounded text-ink-600 hover:text-ink-900">
<span class="nav-bar w-0.5 h-3.5 bg-ink-200 rounded"></span>1. Thông tin chung
</a>
<a href="#context" class="nav-link flex items-center gap-2 px-2.5 py-1.5 rounded text-ink-600 hover:text-ink-900">
<span class="nav-bar w-0.5 h-3.5 bg-ink-200 rounded"></span>2. Bối cảnh & Mục tiêu
</a>
<a href="#context-detail" class="nav-link flex items-center gap-2 pl-6 pr-2.5 py-1.5 rounded text-ink-600 hover:text-ink-900 text-[12px]">
<span class="text-ink-400">2.1</span> Bối cảnh
</a>
<a href="#pain-points" class="nav-link flex items-center gap-2 pl-6 pr-2.5 py-1.5 rounded text-ink-600 hover:text-ink-900 text-[12px]">
<span class="text-ink-400">2.1a</span> Hệ quả
</a>
<a href="#lifecycle" class="nav-link flex items-center gap-2 pl-6 pr-2.5 py-1.5 rounded text-ink-600 hover:text-ink-900 text-[12px]">
<span class="text-ink-400">(a)</span> Vòng đời task
</a>
<a href="#task-fields" class="nav-link flex items-center gap-2 pl-6 pr-2.5 py-1.5 rounded text-ink-600 hover:text-ink-900 text-[12px]">
<span class="text-ink-400">(b)</span> Trường dữ liệu
</a>
<a href="#assignment" class="nav-link flex items-center gap-2 pl-6 pr-2.5 py-1.5 rounded text-ink-600 hover:text-ink-900 text-[12px]">
<span class="text-ink-400">(c)</span> 2 cách giao
</a>
<a href="#subtask" class="nav-link flex items-center gap-2 pl-6 pr-2.5 py-1.5 rounded text-ink-600 hover:text-ink-900 text-[12px]">
<span class="text-ink-400">(d)</span> Task con
</a>
<a href="#chat" class="nav-link flex items-center gap-2 pl-6 pr-2.5 py-1.5 rounded text-ink-600 hover:text-ink-900 text-[12px]">
<span class="text-ink-400">(e)</span> Chat
</a>
<a href="#history" class="nav-link flex items-center gap-2 pl-6 pr-2.5 py-1.5 rounded text-ink-600 hover:text-ink-900 text-[12px]">
<span class="text-ink-400">(f)</span> Lịch sử & log
</a>
<a href="#notify" class="nav-link flex items-center gap-2 pl-6 pr-2.5 py-1.5 rounded text-ink-600 hover:text-ink-900 text-[12px]">
<span class="text-ink-400">(g)</span> Thông báo
</a>
<a href="#objectives" class="nav-link flex items-center gap-2 pl-6 pr-2.5 py-1.5 rounded text-ink-600 hover:text-ink-900 text-[12px]">
<span class="text-ink-400">2.2</span> Mục tiêu
</a>
<a href="#metrics" class="nav-link flex items-center gap-2 pl-6 pr-2.5 py-1.5 rounded text-ink-600 hover:text-ink-900 text-[12px]">
<span class="text-ink-400">KPI</span> Đo lường
</a>
<a href="#api-ref" class="nav-link flex items-center gap-2 px-2.5 py-1.5 rounded text-ink-600 hover:text-ink-900">
<span class="nav-bar w-0.5 h-3.5 bg-ink-200 rounded"></span>3. Reference
</a>
<a href="#footer-meta" class="nav-link flex items-center gap-2 px-2.5 py-1.5 rounded text-ink-600 hover:text-ink-900">
<span class="nav-bar w-0.5 h-3.5 bg-ink-200 rounded"></span>4. Meta & Author
</a>
</nav>
<div class="border-t border-ink-200 pt-4">
<div class="text-[10px] font-semibold uppercase tracking-[0.18em] text-ink-400 mb-2">Resources</div>
<a href="#" class="block px-2.5 py-1 text-[12px] text-ink-600 hover:text-ink-900">↗ Changelog</a>
<a href="#" class="block px-2.5 py-1 text-[12px] text-ink-600 hover:text-ink-900">↗ Figma flows</a>
<a href="#" class="block px-2.5 py-1 text-[12px] text-ink-600 hover:text-ink-900">↗ Edit on Git</a>
</div>
</div>
</aside>
<!-- ============ ARTICLE BODY ============ -->
<main class="col-span-12 lg:col-span-8 pt-10 pb-24 prose-doc">
<!-- ===== Hero / Section 1 ===== -->
<section id="overview" class="mb-16 scroll-mt-32">
<div class="flex items-center gap-2 mb-5">
<span class="chip text-[10px] font-mono font-semibold uppercase tracking-widest text-brand-700 bg-brand-50 px-2 py-1 rounded">Feature ID · FT-TASK-MGMT-01</span>
<span class="chip text-[10px] font-mono font-semibold uppercase tracking-widest text-rose-700 bg-rose-50 px-2 py-1 rounded">Priority · P1 High</span>
<span class="chip text-[10px] font-mono font-semibold uppercase tracking-widest text-amber-700 bg-amber-50 px-2 py-1 rounded">Status · Draft</span>
</div>
<h1 class="text-[44px] leading-[1.1] font-extrabold tracking-tight mb-4 text-ink-950">
Tài liệu Yêu cầu Triển khai<br>
<span class="text-ink-500 font-medium">Hệ thống Quản lý Task Nội bộ</span>
</h1>
<p class="text-[17px] text-ink-600 leading-relaxed max-w-[65ch] mb-8">
Vòng đời · Phân phối · Task con · Chat & Thông báo — module Quản lý công việc được xây ngay
trên nền tảng <strong class="text-ink-900">NolimitHub</strong>, tận dụng tài khoản người dùng và hạ tầng
thông báo sẵn có thay vì dựng app rời.
</p>
<!-- Metadata table -->
<div class="grid grid-cols-2 md:grid-cols-4 border border-ink-200 rounded-2xl overflow-hidden bg-white">
<div class="p-5 border-r border-b md:border-b-0 border-ink-200">
<div class="text-[10px] font-semibold uppercase tracking-widest text-ink-400 mb-1.5">Owner / PO</div>
<div class="text-[15px] font-semibold text-ink-900">CTO</div>
</div>
<div class="p-5 border-r border-b md:border-b-0 border-ink-200">
<div class="text-[10px] font-semibold uppercase tracking-widest text-ink-400 mb-1.5">Hệ thống chủ</div>
<div class="text-[15px] font-semibold text-ink-900">NolimitHub</div>
</div>
<div class="p-5 border-r border-ink-200">
<div class="text-[10px] font-semibold uppercase tracking-widest text-ink-400 mb-1.5">Ngày tạo</div>
<div class="text-[15px] font-semibold font-mono text-ink-900">08/06/2026</div>
</div>
<div class="p-5">
<div class="text-[10px] font-semibold uppercase tracking-widest text-ink-400 mb-1.5">Cập nhật cuối</div>
<div class="text-[15px] font-semibold font-mono text-ink-900">08/06/2026</div>
</div>
</div>
<!-- Info callout -->
<div class="mt-6 flex gap-4 p-5 rounded-xl border border-brand-200 bg-brand-50">
<div class="shrink-0 w-8 h-8 rounded-lg bg-brand-500 text-white flex items-center justify-center font-bold text-sm">i</div>
<div>
<div class="text-[13px] font-semibold text-brand-900 uppercase tracking-wider mb-1">Info · Phạm vi triển khai</div>
<p class="text-[14px] text-brand-900/90 leading-relaxed m-0">
Bổ sung <strong>module Quản lý công việc (Task)</strong> vào NolimitHub: tạo task, giao trực tiếp hoặc qua
người phân phối, task con (parent–child), chat theo task, lịch sử & log, thông báo có gộp.
</p>
</div>
</div>
<!-- Danger callout: out of scope -->
<div class="mt-3 flex gap-4 p-5 rounded-xl border border-rose-200 bg-rose-50">
<div class="shrink-0 w-8 h-8 rounded-lg bg-rose-500 text-white flex items-center justify-center font-bold text-sm">!</div>
<div>
<div class="text-[13px] font-semibold text-rose-900 uppercase tracking-wider mb-1">Danger · KHÔNG nằm trong phạm vi</div>
<p class="text-[14px] text-rose-900/90 leading-relaxed m-0">
<strong>KHÔNG</strong> xây nền tảng quản lý dự án đầy đủ kiểu Jira/Asana — không Gantt, không timesheet,
không workflow builder tự do. Chỉ đúng các trạng thái & hành vi mô tả trong tài liệu này.
</p>
</div>
</div>
</section>
<!-- ===== Section 2 — Context ===== -->
<section id="context" class="mb-16 scroll-mt-32">
<div class="flex items-baseline gap-3 mb-2">
<span class="text-[11px] font-mono font-semibold uppercase tracking-[0.18em] text-ink-400">§ 02</span>
<h2 class="text-[28px] font-bold tracking-tight text-ink-950 m-0">Bối cảnh & Mục tiêu</h2>
</div>
<p class="text-[15px] text-ink-600 max-w-[65ch] mb-6">
⭐ Đây là 2 mục quan trọng nhất. Dev đọc kỹ phần này để hiểu đúng vấn đề và phạm vi
<strong>trước khi nghĩ tới cách làm</strong>. Toàn bộ thiết kế kỹ thuật (API/DB/cronjob/cấu trúc code)
<strong class="text-ink-900">dev tự lo</strong>.
</p>
<!-- 2.1 Context -->
<div id="context-detail" class="scroll-mt-32">
<h3 class="text-[20px] font-bold tracking-tight text-ink-900 mt-10 mb-3">2.1 · Bối cảnh hiện tại</h3>
<p class="max-w-[65ch]">
Hiện tại việc giao và theo dõi công việc nội bộ chủ yếu diễn ra <strong>rời rạc</strong> — qua tin nhắn chat,
trao đổi miệng, hoặc mỗi người tự ghi chú riêng. Không có một nơi tập trung để biết: ai đang làm gì, task đang
ở bước nào, bao giờ hết hạn, đã xong và được duyệt hay chưa.
</p>
<!-- Visual: status quo vs target -->
<div class="grid md:grid-cols-2 gap-4 my-7 not-prose">
<div class="p-5 rounded-2xl border border-ink-200 bg-white">
<div class="text-[10px] font-mono font-semibold uppercase tracking-widest text-rose-600 mb-2">Trước</div>
<div class="text-[15px] font-semibold text-ink-900 mb-3">Giao việc rời rạc</div>
<div class="space-y-2">
<div class="flex items-center gap-2 text-[13px] text-ink-600"><span class="w-1.5 h-1.5 rounded-full bg-rose-400"></span>Tin nhắn chat trôi đi</div>
<div class="flex items-center gap-2 text-[13px] text-ink-600"><span class="w-1.5 h-1.5 rounded-full bg-rose-400"></span>Trao đổi miệng không lưu</div>
<div class="flex items-center gap-2 text-[13px] text-ink-600"><span class="w-1.5 h-1.5 rounded-full bg-rose-400"></span>Ghi chú cá nhân, mỗi người một kiểu</div>
<div class="flex items-center gap-2 text-[13px] text-ink-600"><span class="w-1.5 h-1.5 rounded-full bg-rose-400"></span>Không nghiệm thu, không log</div>
</div>
</div>
<div class="p-5 rounded-2xl border border-brand-200 bg-brand-50">
<div class="text-[10px] font-mono font-semibold uppercase tracking-widest text-brand-600 mb-2">Sau</div>
<div class="text-[15px] font-semibold text-brand-900 mb-3">Module Task tập trung</div>
<div class="space-y-2">
<div class="flex items-center gap-2 text-[13px] text-brand-900/80"><span class="w-1.5 h-1.5 rounded-full bg-brand-500"></span>1 nơi tạo · giao · theo dõi</div>
<div class="flex items-center gap-2 text-[13px] text-brand-900/80"><span class="w-1.5 h-1.5 rounded-full bg-brand-500"></span>Vòng đời trạng thái rõ ràng</div>
<div class="flex items-center gap-2 text-[13px] text-brand-900/80"><span class="w-1.5 h-1.5 rounded-full bg-brand-500"></span>Chat & lịch sử gắn theo task</div>
<div class="flex items-center gap-2 text-[13px] text-brand-900/80"><span class="w-1.5 h-1.5 rounded-full bg-brand-500"></span>Thông báo gộp, log khi đóng</div>
</div>
</div>
</div>
</div>
<!-- Pain points -->
<div id="pain-points" class="scroll-mt-32">
<h3 class="text-[20px] font-bold tracking-tight text-ink-900 mt-10 mb-4">Hệ quả của trạng thái hiện tại</h3>
<div class="grid md:grid-cols-2 gap-3 not-prose">
<!-- 1 -->
<div class="p-5 rounded-xl border border-ink-200 bg-white hover:border-ink-300 transition-all">
<div class="flex items-start gap-3">
<div class="font-mono text-[11px] font-bold text-ink-400 mt-0.5">01</div>
<div>
<div class="font-semibold text-ink-900 text-[14px] mb-1">Thất lạc / bỏ sót</div>
<p class="text-[13px] text-ink-600 leading-relaxed m-0">Việc giao qua chat dễ bị trôi, không ai nhận rõ ràng → công việc rơi mà không ai hay biết.</p>
</div>
</div>
</div>
<!-- 2 -->
<div class="p-5 rounded-xl border border-ink-200 bg-white hover:border-ink-300 transition-all">
<div class="flex items-start gap-3">
<div class="font-mono text-[11px] font-bold text-ink-400 mt-0.5">02</div>
<div>
<div class="font-semibold text-ink-900 text-[14px] mb-1">Không rõ trách nhiệm</div>
<p class="text-[13px] text-ink-600 leading-relaxed m-0">Một việc không biết chính xác ai là người làm, ai là người giao / điều phối.</p>
</div>
</div>
</div>
<!-- 3 -->
<div class="p-5 rounded-xl border border-ink-200 bg-white hover:border-ink-300 transition-all">
<div class="flex items-start gap-3">
<div class="font-mono text-[11px] font-bold text-ink-400 mt-0.5">03</div>
<div>
<div class="font-semibold text-ink-900 text-[14px] mb-1">Không theo dõi được tiến độ & hạn</div>
<p class="text-[13px] text-ink-600 leading-relaxed m-0">Không nhìn ra task nào đang chờ, đang làm, hay đã quá hạn.</p>
</div>
</div>
</div>
<!-- 4 -->
<div class="p-5 rounded-xl border border-ink-200 bg-white hover:border-ink-300 transition-all">
<div class="flex items-start gap-3">
<div class="font-mono text-[11px] font-bold text-ink-400 mt-0.5">04</div>
<div>
<div class="font-semibold text-ink-900 text-[14px] mb-1">Thiếu bước nghiệm thu</div>
<p class="text-[13px] text-ink-600 leading-relaxed m-0">Làm xong là coi như xong, không có bước review trước khi đóng → chất lượng không kiểm soát được.</p>
</div>
</div>
</div>
<!-- 5 -->
<div class="p-5 rounded-xl border border-ink-200 bg-white hover:border-ink-300 transition-all">
<div class="flex items-start gap-3">
<div class="font-mono text-[11px] font-bold text-ink-400 mt-0.5">05</div>
<div>
<div class="font-semibold text-ink-900 text-[14px] mb-1">Không truy vết</div>
<p class="text-[13px] text-ink-600 leading-relaxed m-0">Không biết task đã bị đổi gì, ai đổi, khi nào; không lưu vết lúc đóng task.</p>
</div>
</div>
</div>
<!-- 6 -->
<div class="p-5 rounded-xl border border-ink-200 bg-white hover:border-ink-300 transition-all">
<div class="flex items-start gap-3">
<div class="font-mono text-[11px] font-bold text-ink-400 mt-0.5">06</div>
<div>
<div class="font-semibold text-ink-900 text-[14px] mb-1">Nhiễu thông báo</div>
<p class="text-[13px] text-ink-600 leading-relaxed m-0">Trao đổi quanh một việc nằm tản mát, mỗi tin nhắn là một thông báo riêng → loạn, dễ bỏ lỡ tin quan trọng.</p>
</div>
</div>
</div>
</div>
<!-- Root cause callout -->
<div class="mt-6 flex gap-4 p-5 rounded-xl border-l-4 border-amber-500 bg-amber-50">
<div class="shrink-0 w-8 h-8 rounded-lg bg-amber-500 text-white flex items-center justify-center font-bold text-sm">⚠</div>
<div>
<div class="text-[13px] font-semibold text-amber-900 uppercase tracking-wider mb-1">Warning · Nguyên nhân gốc</div>
<p class="text-[14px] text-amber-900/90 leading-relaxed m-0">
Chưa có <strong>một hệ thống quản lý task tập trung</strong> với vòng đời rõ ràng, cơ chế giao – điều phối,
và truy vết. Mọi thứ đang phụ thuộc thao tác thủ công & trí nhớ.
</p>
</div>
</div>
<p class="mt-6 max-w-[65ch]">
<strong>Tính năng cần bổ sung:</strong> xây <strong>module Quản lý Task nội bộ</strong> gồm các khối nghiệp vụ
dưới đây (mô tả ở mức nghiệp vụ — cách hiện thực do dev tự thiết kế).
</p>
</div>
</section>
<!-- ===== (a) Lifecycle ===== -->
<section id="lifecycle" class="mb-16 scroll-mt-32">
<div class="flex items-baseline gap-3 mb-2">
<span class="chip text-[11px] font-mono font-semibold tracking-widest text-brand-700 bg-brand-50 px-2 py-0.5 rounded">(a)</span>
<h2 class="text-[26px] font-bold tracking-tight text-ink-950 m-0">Vòng đời của task lớn</h2>
</div>
<p class="max-w-[65ch]">
Các trạng thái và ý nghĩa được khoá cứng theo mô tả nghiệp vụ. Không thêm trạng thái ngoài danh sách dưới đây.
</p>
<!-- Lifecycle states -->
<div class="my-6 space-y-2 not-prose">
<!-- state row template -->
<div class="grid grid-cols-12 gap-3 items-center p-4 rounded-xl border border-ink-200 bg-white">
<div class="col-span-1 font-mono text-[11px] font-bold text-ink-400">S0</div>
<div class="col-span-3 flex items-center gap-2">
<span class="w-2 h-2 rounded-full bg-slate-400"></span>
<span class="font-semibold text-[14px] text-ink-900">Tạo</span>
</div>
<div class="col-span-8 text-[13px] text-ink-600">Task vừa được khởi tạo.</div>
</div>
<div class="grid grid-cols-12 gap-3 items-center p-4 rounded-xl border border-ink-200 bg-white">
<div class="col-span-1 font-mono text-[11px] font-bold text-ink-400">S1</div>
<div class="col-span-3 flex items-center gap-2">
<span class="w-2 h-2 rounded-full bg-amber-400"></span>
<span class="font-semibold text-[14px] text-ink-900">Chờ giao</span>
</div>
<div class="col-span-8 text-[13px] text-ink-600">Đã tạo nhưng <strong>chưa</strong> xác định người làm → chờ người phân phối giao. <em class="text-ink-500">(Chỉ xuất hiện ở luồng đi qua người phân phối.)</em></div>
</div>
<div class="grid grid-cols-12 gap-3 items-center p-4 rounded-xl border border-ink-200 bg-white">
<div class="col-span-1 font-mono text-[11px] font-bold text-ink-400">S2</div>
<div class="col-span-3 flex items-center gap-2">
<span class="w-2 h-2 rounded-full bg-sky-400"></span>
<span class="font-semibold text-[14px] text-ink-900">Chờ làm</span>
</div>
<div class="col-span-8 text-[13px] text-ink-600">Đã có người nhận, chờ bắt đầu.</div>
</div>
<div class="grid grid-cols-12 gap-3 items-center p-4 rounded-xl border border-ink-200 bg-white">
<div class="col-span-1 font-mono text-[11px] font-bold text-ink-400">S3</div>
<div class="col-span-3 flex items-center gap-2">
<span class="w-2 h-2 rounded-full bg-brand-500"></span>
<span class="font-semibold text-[14px] text-ink-900">Đang làm</span>
</div>
<div class="col-span-8 text-[13px] text-ink-600">Người nhận đang thực hiện.</div>
</div>
<div class="grid grid-cols-12 gap-3 items-center p-4 rounded-xl border border-rose-200 bg-rose-50/50">
<div class="col-span-1 font-mono text-[11px] font-bold text-rose-500">S3*</div>
<div class="col-span-3 flex items-center gap-2">
<span class="w-2 h-2 rounded-full bg-rose-500"></span>
<span class="font-semibold text-[14px] text-ink-900">Quá hạn <span class="text-ink-400 font-normal">(nếu có)</span></span>
</div>
<div class="col-span-8 text-[13px] text-ink-700">Quá thời gian hết hạn mà task chưa xong — đánh dấu cảnh báo, có thể <strong>chồng lên</strong> "Chờ làm" / "Đang làm".</div>
</div>
<div class="grid grid-cols-12 gap-3 items-center p-4 rounded-xl border border-ink-200 bg-white">
<div class="col-span-1 font-mono text-[11px] font-bold text-ink-400">S4</div>
<div class="col-span-3 flex items-center gap-2">
<span class="w-2 h-2 rounded-full bg-violet-500"></span>
<span class="font-semibold text-[14px] text-ink-900">Hoàn thành, chờ review</span>
</div>
<div class="col-span-8 text-[13px] text-ink-600">Người làm báo đã xong, chờ người có thẩm quyền nghiệm thu.</div>
</div>
<div class="grid grid-cols-12 gap-3 items-center p-4 rounded-xl border border-emerald-200 bg-emerald-50/50">
<div class="col-span-1 font-mono text-[11px] font-bold text-emerald-600">S5</div>
<div class="col-span-3 flex items-center gap-2">
<span class="w-2 h-2 rounded-full bg-emerald-500"></span>
<span class="font-semibold text-[14px] text-ink-900">Đóng task</span>
</div>
<div class="col-span-8 text-[13px] text-ink-700">Review đạt → task kết thúc <strong>(ghi log lúc đóng)</strong>.</div>
</div>
<div class="grid grid-cols-12 gap-3 items-center p-4 rounded-xl border border-orange-200 bg-orange-50/50">
<div class="col-span-1 font-mono text-[11px] font-bold text-orange-600">↩</div>
<div class="col-span-3 flex items-center gap-2">
<span class="w-2 h-2 rounded-full bg-orange-500"></span>
<span class="font-semibold text-[14px] text-ink-900">Cần làm lại</span>
</div>
<div class="col-span-8 text-[13px] text-ink-700">Review không đạt → task <strong>quay lại "Chờ làm"</strong>.</div>
</div>
</div>
<!-- Lifecycle flow diagram -->
<div class="my-8 not-prose">
<div class="text-[10px] font-mono font-semibold uppercase tracking-widest text-ink-400 mb-3">Diagram · Lifecycle flow</div>
<div class="p-6 rounded-2xl border border-ink-200 bg-white overflow-x-auto">
<svg viewBox="0 0 1180 260" class="w-full min-w-[920px]" xmlns="http://www.w3.org/2000/svg">
<defs>
<marker id="arr" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto">
<path d="M0,0 L10,5 L0,10 z" fill="#737373"/>
</marker>
<marker id="arrRed" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto">
<path d="M0,0 L10,5 L0,10 z" fill="#e11d48"/>
</marker>
</defs>
<!-- Top row: main flow -->
<g font-family="Inter, sans-serif" font-size="12">
<!-- S0 -->
<rect x="10" y="80" width="110" height="50" rx="10" fill="#fafafa" stroke="#d4d4d4"/>
<text x="65" y="103" text-anchor="middle" fill="#171717" font-weight="600">Tạo</text>
<text x="65" y="120" text-anchor="middle" fill="#737373" font-size="10">S0</text>
<!-- S1 -->
<rect x="160" y="80" width="120" height="50" rx="10" fill="#fef3c7" stroke="#fcd34d"/>
<text x="220" y="103" text-anchor="middle" fill="#92400e" font-weight="600">Chờ giao</text>
<text x="220" y="120" text-anchor="middle" fill="#a16207" font-size="10">S1 · cách 2</text>
<!-- S2 -->
<rect x="320" y="80" width="120" height="50" rx="10" fill="#e0f2fe" stroke="#7dd3fc"/>
<text x="380" y="103" text-anchor="middle" fill="#075985" font-weight="600">Chờ làm</text>
<text x="380" y="120" text-anchor="middle" fill="#0c4a6e" font-size="10">S2</text>
<!-- S3 -->
<rect x="480" y="80" width="120" height="50" rx="10" fill="#dbe6ff" stroke="#8eabff"/>
<text x="540" y="103" text-anchor="middle" fill="#1d2f8a" font-weight="600">Đang làm</text>
<text x="540" y="120" text-anchor="middle" fill="#1f33b0" font-size="10">S3</text>
<!-- S4 -->
<rect x="640" y="80" width="160" height="50" rx="10" fill="#ede9fe" stroke="#c4b5fd"/>
<text x="720" y="100" text-anchor="middle" fill="#5b21b6" font-weight="600">Hoàn thành</text>
<text x="720" y="115" text-anchor="middle" fill="#6d28d9" font-size="10">chờ review · S4</text>
<!-- S5 -->
<rect x="840" y="80" width="120" height="50" rx="10" fill="#d1fae5" stroke="#6ee7b7"/>
<text x="900" y="103" text-anchor="middle" fill="#065f46" font-weight="600">Đóng task</text>
<text x="900" y="120" text-anchor="middle" fill="#047857" font-size="10">S5 · ghi log</text>
<!-- Arrows main -->
<line x1="120" y1="105" x2="160" y2="105" stroke="#737373" stroke-width="1.5" marker-end="url(#arr)"/>
<line x1="280" y1="105" x2="320" y2="105" stroke="#737373" stroke-width="1.5" marker-end="url(#arr)"/>
<line x1="440" y1="105" x2="480" y2="105" stroke="#737373" stroke-width="1.5" marker-end="url(#arr)"/>
<line x1="600" y1="105" x2="640" y2="105" stroke="#737373" stroke-width="1.5" marker-end="url(#arr)"/>
<line x1="800" y1="105" x2="840" y2="105" stroke="#737373" stroke-width="1.5" marker-end="url(#arr)"/>
<!-- Skip S1 (cách 1) -->
<path d="M 65 80 Q 200 20 380 80" fill="none" stroke="#3a5bf0" stroke-width="1.5" stroke-dasharray="5 3" marker-end="url(#arr)"/>
<text x="222" y="40" text-anchor="middle" fill="#1f33b0" font-size="10" font-weight="600">Cách 1 · giao thẳng người làm</text>
<!-- Overdue overlay -->
<rect x="380" y="170" width="240" height="40" rx="8" fill="#ffe4e6" stroke="#fda4af" stroke-dasharray="4 3"/>
<text x="500" y="195" text-anchor="middle" fill="#9f1239" font-weight="600">Quá hạn · chồng lên S2 / S3</text>
<line x1="380" y1="130" x2="395" y2="170" stroke="#e11d48" stroke-width="1" stroke-dasharray="3 3"/>
<line x1="540" y1="130" x2="500" y2="170" stroke="#e11d48" stroke-width="1" stroke-dasharray="3 3"/>
<!-- Cần làm lại loop -->
<path d="M 720 130 Q 560 230 380 130" fill="none" stroke="#e11d48" stroke-width="1.5" marker-end="url(#arrRed)"/>
<text x="540" y="232" text-anchor="middle" fill="#9f1239" font-size="11" font-weight="600">Cần làm lại · trả về Chờ làm ↩</text>
</g>
</svg>
</div>
</div>
<!-- Summary box -->
<div class="p-5 rounded-xl bg-ink-950 text-ink-50 my-6">
<div class="text-[10px] font-mono uppercase tracking-widest text-ink-400 mb-2">Tóm tắt vòng đời</div>
<div class="font-mono text-[13px] leading-relaxed text-emerald-200">
Tạo → Chờ giao → Chờ làm → Đang làm → (Quá hạn) → Hoàn thành, chờ review → <span class="text-emerald-400 font-bold">Đóng task</span>
<br><span class="text-ink-400">// hoặc</span><br>
Cần làm lại ↩ <span class="text-amber-300">Chờ làm</span>
</div>
</div>
</section>
<!-- ===== (b) Task fields ===== -->
<section id="task-fields" class="mb-16 scroll-mt-32">
<div class="flex items-baseline gap-3 mb-2">
<span class="chip text-[11px] font-mono font-semibold tracking-widest text-brand-700 bg-brand-50 px-2 py-0.5 rounded">(b)</span>
<h2 class="text-[26px] font-bold tracking-tight text-ink-950 m-0">Thông tin một task lớn</h2>
</div>
<p class="max-w-[65ch]">
Mỗi task lớn mang các trường thông tin sau. Đây là <strong>danh sách trường nghiệp vụ</strong>;
kiểu dữ liệu / bảng / index do dev tự thiết kế.
</p>
<div class="not-prose my-6 overflow-hidden rounded-2xl border border-ink-200 bg-white">
<table class="w-full text-[13px]">
<thead class="bg-ink-50 text-ink-500 text-[11px] uppercase tracking-widest">
<tr>
<th class="text-left font-semibold py-3 px-4 w-12">#</th>
<th class="text-left font-semibold py-3 px-4">Trường</th>
<th class="text-left font-semibold py-3 px-4">Ghi chú</th>
<th class="text-left font-semibold py-3 px-4 w-32">Bắt buộc</th>
</tr>
</thead>
<tbody class="divide-y divide-ink-200">
<tr>
<td class="py-3 px-4 font-mono text-ink-400">01</td>
<td class="py-3 px-4 font-semibold text-ink-900">Tên task</td>
<td class="py-3 px-4 text-ink-600">Tiêu đề ngắn gọn của công việc.</td>
<td class="py-3 px-4"><span class="chip text-[10px] font-mono px-1.5 py-0.5 bg-rose-50 text-rose-700 rounded">required</span></td>
</tr>
<tr>
<td class="py-3 px-4 font-mono text-ink-400">02</td>
<td class="py-3 px-4 font-semibold text-ink-900">Mô tả</td>
<td class="py-3 px-4 text-ink-600">Chi tiết công việc, yêu cầu, bối cảnh.</td>
<td class="py-3 px-4"><span class="chip text-[10px] font-mono px-1.5 py-0.5 bg-rose-50 text-rose-700 rounded">required</span></td>
</tr>
<tr>
<td class="py-3 px-4 font-mono text-ink-400">03</td>
<td class="py-3 px-4 font-semibold text-ink-900">Tài liệu đính kèm</td>
<td class="py-3 px-4 text-ink-600">File / link tham chiếu (nếu có).</td>
<td class="py-3 px-4"><span class="chip text-[10px] font-mono px-1.5 py-0.5 bg-ink-100 text-ink-600 rounded">optional</span></td>
</tr>
<tr>
<td class="py-3 px-4 font-mono text-ink-400">04</td>
<td class="py-3 px-4 font-semibold text-ink-900">Thời gian tạo</td>
<td class="py-3 px-4 text-ink-600">Timestamp khi task được khởi tạo.</td>
<td class="py-3 px-4"><span class="chip text-[10px] font-mono px-1.5 py-0.5 bg-ink-100 text-ink-600 rounded">auto</span></td>
</tr>
<tr>
<td class="py-3 px-4 font-mono text-ink-400">05</td>
<td class="py-3 px-4 font-semibold text-ink-900">Người tạo</td>
<td class="py-3 px-4 text-ink-600">Tài khoản NolimitHub khởi tạo task.</td>
<td class="py-3 px-4"><span class="chip text-[10px] font-mono px-1.5 py-0.5 bg-rose-50 text-rose-700 rounded">required</span></td>
</tr>
<tr>
<td class="py-3 px-4 font-mono text-ink-400">06</td>
<td class="py-3 px-4 font-semibold text-ink-900">Người phân phối</td>
<td class="py-3 px-4 text-ink-600">Chỉ có ở luồng "cách 2".</td>
<td class="py-3 px-4"><span class="chip text-[10px] font-mono px-1.5 py-0.5 bg-amber-50 text-amber-700 rounded">conditional</span></td>
</tr>
<tr>
<td class="py-3 px-4 font-mono text-ink-400">07</td>
<td class="py-3 px-4 font-semibold text-ink-900">Thời gian hết hạn</td>
<td class="py-3 px-4 text-ink-600">Deadline; vượt qua → trạng thái "Quá hạn".</td>
<td class="py-3 px-4"><span class="chip text-[10px] font-mono px-1.5 py-0.5 bg-rose-50 text-rose-700 rounded">required</span></td>
</tr>
<tr>
<td class="py-3 px-4 font-mono text-ink-400">08</td>
<td class="py-3 px-4 font-semibold text-ink-900">Mức độ ưu tiên</td>
<td class="py-3 px-4 text-ink-600">Priority do người tạo gán.</td>
<td class="py-3 px-4"><span class="chip text-[10px] font-mono px-1.5 py-0.5 bg-rose-50 text-rose-700 rounded">required</span></td>
</tr>
<tr>
<td class="py-3 px-4 font-mono text-ink-400">09</td>
<td class="py-3 px-4 font-semibold text-ink-900">Trạng thái</td>
<td class="py-3 px-4 text-ink-600">Một trong các giá trị ở vòng đời (a).</td>
<td class="py-3 px-4"><span class="chip text-[10px] font-mono px-1.5 py-0.5 bg-ink-100 text-ink-600 rounded">auto</span></td>
</tr>
<tr>
<td class="py-3 px-4 font-mono text-ink-400">10</td>
<td class="py-3 px-4 font-semibold text-ink-900">Danh sách người nhận</td>
<td class="py-3 px-4 text-ink-600"><strong>Có thể nhiều người</strong> ở cấp task lớn.</td>
<td class="py-3 px-4"><span class="chip text-[10px] font-mono px-1.5 py-0.5 bg-amber-50 text-amber-700 rounded">conditional</span></td>
</tr>
<tr>
<td class="py-3 px-4 font-mono text-ink-400">11</td>
<td class="py-3 px-4 font-semibold text-ink-900">Đoạn chat của task</td>
<td class="py-3 px-4 text-ink-600">Xem mục (e).</td>
<td class="py-3 px-4"><span class="chip text-[10px] font-mono px-1.5 py-0.5 bg-ink-100 text-ink-600 rounded">embedded</span></td>
</tr>
<tr>
<td class="py-3 px-4 font-mono text-ink-400">12</td>
<td class="py-3 px-4 font-semibold text-ink-900">Danh sách task con</td>
<td class="py-3 px-4 text-ink-600">Xem mục (d).</td>
<td class="py-3 px-4"><span class="chip text-[10px] font-mono px-1.5 py-0.5 bg-ink-100 text-ink-600 rounded">embedded</span></td>
</tr>
<tr>
<td class="py-3 px-4 font-mono text-ink-400">13</td>
<td class="py-3 px-4 font-semibold text-ink-900">Lịch sử thay đổi</td>
<td class="py-3 px-4 text-ink-600">Xem mục (f).</td>
<td class="py-3 px-4"><span class="chip text-[10px] font-mono px-1.5 py-0.5 bg-ink-100 text-ink-600 rounded">embedded</span></td>
</tr>
</tbody>
</table>
</div>
<!-- Pseudo schema code block -->
<div class="not-prose my-6 rounded-xl overflow-hidden border border-ink-800 bg-ink-950">
<div class="flex items-center justify-between px-4 py-2 bg-ink-900 border-b border-ink-800">
<div class="flex items-center gap-2">
<span class="w-2.5 h-2.5 rounded-full bg-rose-400"></span>
<span class="w-2.5 h-2.5 rounded-full bg-amber-400"></span>
<span class="w-2.5 h-2.5 rounded-full bg-emerald-400"></span>
<span class="ml-3 text-[11px] font-mono text-ink-400">task.entity.pseudo</span>
</div>
<div class="flex items-center gap-3">
<span class="text-[10px] font-mono px-2 py-0.5 bg-brand-900/40 text-brand-300 rounded">pseudo-code</span>
<button onclick="navigator.clipboard&&navigator.clipboard.writeText(this.parentElement.parentElement.nextElementSibling.innerText)" class="text-[11px] font-mono text-ink-400 hover:text-white transition-all flex items-center gap-1.5">
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>
Copy
</button>
</div>
</div>
<pre class="p-5 text-[12.5px] leading-relaxed font-mono text-ink-100 overflow-x-auto"><span class="text-ink-500">// Entity gợi ý — schema thực do dev tự thiết kế</span>
<span class="text-violet-300">Task</span> {
id : <span class="text-emerald-300">UUID</span>
name : <span class="text-emerald-300">String</span> <span class="text-ink-500">// Tên task</span>
description : <span class="text-emerald-300">Text</span> <span class="text-ink-500">// Mô tả</span>
attachments : <span class="text-emerald-300">List<File></span> <span class="text-ink-500">// Tài liệu đính kèm</span>
createdAt : <span class="text-emerald-300">Timestamp</span>
createdBy : <span class="text-emerald-300">User</span> <span class="text-ink-500">// Người tạo</span>
dispatcher : <span class="text-emerald-300">User?</span> <span class="text-ink-500">// Người phân phối (cách 2)</span>
dueAt : <span class="text-emerald-300">Timestamp</span> <span class="text-ink-500">// Thời gian hết hạn</span>
priority : <span class="text-amber-300">Priority</span>
status : <span class="text-amber-300">LifecycleStatus</span> <span class="text-ink-500">// Tạo / Chờ giao / Chờ làm / ...</span>
assignees : <span class="text-emerald-300">List<User></span> <span class="text-ink-500">// Người nhận — có thể nhiều</span>
chat : <span class="text-emerald-300">Thread</span> <span class="text-ink-500">// Chat gắn theo task lớn (e)</span>
subtasks : <span class="text-emerald-300">List<SubTask></span> <span class="text-ink-500">// Task con (d)</span>
history : <span class="text-emerald-300">List<Change></span> <span class="text-ink-500">// Lịch sử thay đổi (f)</span>
closeLog : <span class="text-emerald-300">CloseLog?</span> <span class="text-ink-500">// Log ghi khi đóng task</span>
}</pre>
</div>
</section>
<!-- ===== (c) Assignment ===== -->
<section id="assignment" class="mb-16 scroll-mt-32">
<div class="flex items-baseline gap-3 mb-2">
<span class="chip text-[11px] font-mono font-semibold tracking-widest text-brand-700 bg-brand-50 px-2 py-0.5 rounded">(c)</span>
<h2 class="text-[26px] font-bold tracking-tight text-ink-950 m-0">Tạo & phân phối task — 2 cách đưa việc</h2>
</div>
<p class="max-w-[65ch]">
Khi tạo: nhập <strong>Tên</strong>, <strong>Mô tả</strong>, đính kèm tài liệu (nếu có),
<strong>mức ưu tiên</strong>, <strong>thời gian hết hạn</strong>. Sau đó chọn 1 trong 2 cách.
</p>
<div class="grid md:grid-cols-2 gap-4 my-7 not-prose">
<!-- Cách 1 -->
<div class="p-6 rounded-2xl border border-brand-200 bg-gradient-to-br from-brand-50 to-white">
<div class="flex items-center justify-between mb-4">
<span class="text-[10px] font-mono font-bold uppercase tracking-widest text-brand-700 bg-brand-100 px-2 py-1 rounded">Cách 1</span>
<span class="text-[11px] font-mono text-brand-700/70">đã xác định người làm</span>
</div>
<div class="text-[16px] font-bold text-ink-900 mb-3">Giao thẳng người nhận</div>
<p class="text-[13px] text-ink-700 leading-relaxed mb-4">
Chọn luôn <strong>người nhận</strong> → task vào thẳng trạng thái <strong>"Chờ làm"</strong>
(bỏ qua "Chờ giao").
</p>
<div class="font-mono text-[11px] bg-white border border-brand-200 rounded-lg p-3 leading-relaxed">
<span class="text-ink-400">flow </span><span class="text-brand-700 font-semibold">→</span> Tạo
<span class="text-brand-500"> ⟶ </span><span class="bg-sky-100 text-sky-800 px-1.5 py-0.5 rounded">Chờ làm</span>
</div>
</div>
<!-- Cách 2 -->
<div class="p-6 rounded-2xl border border-amber-200 bg-gradient-to-br from-amber-50 to-white">
<div class="flex items-center justify-between mb-4">
<span class="text-[10px] font-mono font-bold uppercase tracking-widest text-amber-700 bg-amber-100 px-2 py-1 rounded">Cách 2</span>
<span class="text-[11px] font-mono text-amber-700/70">chưa xác định người làm</span>
</div>
<div class="text-[16px] font-bold text-ink-900 mb-3">Qua người phân phối / tự nhận</div>
<p class="text-[13px] text-ink-700 leading-relaxed mb-4">
Chọn <strong>người phân phối</strong> → task ở <strong>"Chờ giao"</strong>. Người phân phối giao cho
người phù hợp; <strong>hoặc</strong> ai phù hợp có thể <strong>tự nhận</strong>. Có người nhận → chuyển <strong>"Chờ làm"</strong>.
</p>
<div class="font-mono text-[11px] bg-white border border-amber-200 rounded-lg p-3 leading-relaxed">
<span class="text-ink-400">flow </span><span class="text-amber-700 font-semibold">→</span> Tạo
<span class="text-amber-500"> ⟶ </span><span class="bg-amber-100 text-amber-800 px-1.5 py-0.5 rounded">Chờ giao</span>
<span class="text-amber-500"> ⟶ </span><span class="bg-sky-100 text-sky-800 px-1.5 py-0.5 rounded">Chờ làm</span>
</div>
</div>
</div>
<!-- Decision matrix -->
<div class="not-prose my-6 rounded-2xl border border-ink-200 bg-white overflow-hidden">
<div class="px-5 py-3 border-b border-ink-200 bg-ink-50 flex items-center justify-between">
<div class="text-[12px] font-semibold text-ink-700">Ma trận quyết định khi tạo task</div>
<div class="text-[10px] font-mono text-ink-400">decision-matrix</div>
</div>
<div class="divide-y divide-ink-200">
<div class="grid grid-cols-12 gap-4 px-5 py-4 text-[13px]">
<div class="col-span-4 text-ink-500 font-mono text-[11px] uppercase tracking-widest">if</div>
<div class="col-span-4 text-ink-500 font-mono text-[11px] uppercase tracking-widest">action</div>
<div class="col-span-4 text-ink-500 font-mono text-[11px] uppercase tracking-widest">result</div>
</div>
<div class="grid grid-cols-12 gap-4 px-5 py-4 text-[13px]">
<div class="col-span-4 text-ink-700">Người tạo đã biết ai làm</div>
<div class="col-span-4 text-ink-700">Chọn người nhận trực tiếp</div>
<div class="col-span-4"><span class="text-brand-700 font-semibold">→ vào "Chờ làm"</span></div>
</div>
<div class="grid grid-cols-12 gap-4 px-5 py-4 text-[13px]">
<div class="col-span-4 text-ink-700">Chưa biết ai làm</div>
<div class="col-span-4 text-ink-700">Chọn người phân phối</div>
<div class="col-span-4"><span class="text-amber-700 font-semibold">→ vào "Chờ giao"</span></div>
</div>
<div class="grid grid-cols-12 gap-4 px-5 py-4 text-[13px]">
<div class="col-span-4 text-ink-700">Task đang ở "Chờ giao"</div>
<div class="col-span-4 text-ink-700">Người phân phối giao / có người tự nhận</div>
<div class="col-span-4"><span class="text-sky-700 font-semibold">→ chuyển "Chờ làm"</span></div>
</div>
</div>
</div>
</section>
<!-- ===== (d) Subtask ===== -->
<section id="subtask" class="mb-16 scroll-mt-32">
<div class="flex items-baseline gap-3 mb-2">
<span class="chip text-[11px] font-mono font-semibold tracking-widest text-brand-700 bg-brand-50 px-2 py-0.5 rounded">(d)</span>
<h2 class="text-[26px] font-bold tracking-tight text-ink-950 m-0">Task con (sub-task)</h2>
</div>
<p class="max-w-[65ch]">
Một task lớn có thể chứa <strong>nhiều task con</strong> bên trong. Đây là quan hệ <strong>parent–child</strong>
bắt buộc trong tài liệu này.
</p>
<!-- Subtask fields -->
<h3 class="text-[16px] font-bold text-ink-900 mt-7 mb-3">Thông tin task con</h3>
<div class="grid sm:grid-cols-2 lg:grid-cols-5 gap-3 not-prose">
<div class="p-4 rounded-xl border border-ink-200 bg-white">
<div class="text-[10px] font-mono uppercase tracking-widest text-ink-400 mb-1">field 01</div>
<div class="font-semibold text-[14px] text-ink-900">Tên</div>
</div>
<div class="p-4 rounded-xl border border-ink-200 bg-white">
<div class="text-[10px] font-mono uppercase tracking-widest text-ink-400 mb-1">field 02</div>
<div class="font-semibold text-[14px] text-ink-900">Mô tả</div>
</div>
<div class="p-4 rounded-xl border border-ink-200 bg-white">
<div class="text-[10px] font-mono uppercase tracking-widest text-ink-400 mb-1">field 03</div>
<div class="font-semibold text-[14px] text-ink-900">Trạng thái</div>
</div>
<div class="p-4 rounded-xl border border-brand-200 bg-brand-50">
<div class="text-[10px] font-mono uppercase tracking-widest text-brand-600 mb-1">field 04 · unique</div>
<div class="font-semibold text-[14px] text-brand-900">Người làm <span class="text-[11px] font-normal text-brand-700">(duy nhất 1)</span></div>
</div>
<div class="p-4 rounded-xl border border-ink-200 bg-white">
<div class="text-[10px] font-mono uppercase tracking-widest text-ink-400 mb-1">field 05</div>
<div class="font-semibold text-[14px] text-ink-900">Thời gian hết hạn</div>
</div>
</div>
<!-- Subtask lifecycle -->
<h3 class="text-[16px] font-bold text-ink-900 mt-8 mb-3">Vòng đời task con</h3>
<div class="not-prose flex flex-wrap items-center gap-2 p-5 rounded-xl border border-ink-200 bg-white font-mono text-[13px]">
<span class="px-3 py-1.5 rounded-md bg-sky-100 text-sky-800 font-semibold">Chờ làm</span>
<span class="text-ink-400">→</span>
<span class="px-3 py-1.5 rounded-md bg-brand-100 text-brand-800 font-semibold">Đang làm</span>
<span class="text-ink-400">→</span>
<span class="px-3 py-1.5 rounded-md bg-rose-100 text-rose-800 font-semibold">(Quá hạn)</span>
<span class="text-ink-400">→</span>
<span class="px-3 py-1.5 rounded-md bg-violet-100 text-violet-800 font-semibold">Hoàn thành, chờ review</span>
<span class="text-ink-400">→</span>
<span class="px-3 py-1.5 rounded-md bg-emerald-100 text-emerald-800 font-semibold">Đóng</span>
<span class="text-ink-300 mx-2">|</span>
<span class="text-orange-700">Cần làm lại ↩ Chờ làm</span>
</div>
<!-- Key rules -->
<div class="grid md:grid-cols-2 gap-3 my-6 not-prose">
<div class="flex gap-3 p-5 rounded-xl border border-ink-200 bg-white">
<div class="shrink-0 w-7 h-7 rounded-md bg-brand-500 text-white flex items-center justify-center text-[13px] font-bold">1</div>
<p class="text-[13.5px] text-ink-700 m-0 leading-relaxed">Mỗi task con <strong>chỉ 1 người</strong> thực hiện.</p>
</div>
<div class="flex gap-3 p-5 rounded-xl border border-emerald-200 bg-emerald-50">
<div class="shrink-0 w-7 h-7 rounded-md bg-emerald-500 text-white flex items-center justify-center text-[13px] font-bold">2</div>
<p class="text-[13.5px] text-emerald-900 m-0 leading-relaxed">Task lớn <strong>tự chuyển "Hoàn thành"</strong> khi <strong>TẤT CẢ task con đã được Đóng</strong>.</p>
</div>
</div>
<!-- Open question callout -->
<div class="flex gap-4 p-5 rounded-xl border-l-4 border-amber-500 bg-amber-50 my-4">
<div class="shrink-0 w-8 h-8 rounded-lg bg-amber-500 text-white flex items-center justify-center font-bold text-sm">?</div>
<div>
<div class="text-[13px] font-semibold text-amber-900 uppercase tracking-wider mb-1">Cần chốt</div>
<p class="text-[14px] text-amber-900/90 leading-relaxed m-0">
Với task lớn <strong>không có</strong> task con thì chính người nhận báo hoàn thành → review → đóng
như vòng đời ở mục (a).
</p>
</div>
</div>
<!-- Parent-child diagram -->
<div class="my-6 not-prose">
<div class="text-[10px] font-mono font-semibold uppercase tracking-widest text-ink-400 mb-3">Diagram · Parent ↔ Child rollup</div>
<div class="p-6 rounded-2xl border border-ink-200 bg-white">
<div class="mb-4 p-4 rounded-xl bg-brand-50 border border-brand-200">
<div class="flex items-center justify-between mb-1">
<div class="flex items-center gap-2">
<span class="text-[10px] font-mono text-brand-700 font-bold">PARENT</span>
<span class="font-semibold text-ink-900 text-[14px]">Task lớn — "Triển khai module Task"</span>
</div>
<span class="chip text-[11px] font-mono px-2 py-0.5 rounded bg-violet-100 text-violet-700">Hoàn thành, chờ review</span>
</div>
<div class="text-[11px] text-brand-700/80 font-mono">auto-completed khi 3/3 child = Đóng</div>
</div>
<div class="ml-6 space-y-2">
<div class="flex items-center gap-3 p-3 rounded-lg border border-ink-200 bg-ink-50">
<div class="w-1 h-6 bg-emerald-500 rounded"></div>
<div class="flex-1">
<div class="text-[13px] font-medium text-ink-900">Child #1 — Vẽ DB schema</div>
<div class="text-[11px] text-ink-500 font-mono">assignee: 1 dev</div>
</div>
<span class="chip text-[11px] font-mono px-2 py-0.5 rounded bg-emerald-100 text-emerald-700">Đóng</span>
</div>
<div class="flex items-center gap-3 p-3 rounded-lg border border-ink-200 bg-ink-50">
<div class="w-1 h-6 bg-emerald-500 rounded"></div>
<div class="flex-1">
<div class="text-[13px] font-medium text-ink-900">Child #2 — Cài vòng đời S0–S5</div>
<div class="text-[11px] text-ink-500 font-mono">assignee: 1 dev</div>
</div>
<span class="chip text-[11px] font-mono px-2 py-0.5 rounded bg-emerald-100 text-emerald-700">Đóng</span>
</div>
<div class="flex items-center gap-3 p-3 rounded-lg border border-ink-200 bg-ink-50">
<div class="w-1 h-6 bg-emerald-500 rounded"></div>
<div class="flex-1">
<div class="text-[13px] font-medium text-ink-900">Child #3 — UI & notification</div>
<div class="text-[11px] text-ink-500 font-mono">assignee: 1 dev</div>
</div>
<span class="chip text-[11px] font-mono px-2 py-0.5 rounded bg-emerald-100 text-emerald-700">Đóng</span>
</div>
</div>
</div>
</div>
</section>
<!-- ===== (e) Chat ===== -->
<section id="chat" class="mb-16 scroll-mt-32">
<div class="flex items-baseline gap-3 mb-2">
<span class="chip text-[11px] font-mono font-semibold tracking-widest text-brand-700 bg-brand-50 px-2 py-0.5 rounded">(e)</span>
<h2 class="text-[26px] font-bold tracking-tight text-ink-950 m-0">Chat theo task</h2>
</div>
<p class="max-w-[65ch]">
Mỗi <strong>task lớn</strong> có một đoạn chat riêng để trao đổi xoay quanh task đó.
Chat gắn ở <strong>cấp task lớn</strong> — <em>task con dùng chung chat của task lớn</em>,
không có thread riêng cho task con.
</p>
<!-- Chat UI mockup -->
<div class="my-6 not-prose grid lg:grid-cols-5 gap-4">
<div class="lg:col-span-3 rounded-2xl border border-ink-200 bg-white overflow-hidden">
<div class="px-4 py-3 border-b border-ink-200 bg-ink-50 flex items-center justify-between">
<div class="flex items-center gap-2">
<svg class="w-4 h-4 text-ink-500" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>
<span class="text-[13px] font-semibold text-ink-900">Chat · Task ABC</span>
</div>
<span class="text-[10px] font-mono text-ink-400">cấp · task lớn</span>
</div>
<div class="p-4 space-y-3">
<div class="flex gap-2">
<div class="w-7 h-7 rounded-full bg-brand-500 text-white text-[11px] font-bold flex items-center justify-center shrink-0">PO</div>
<div>
<div class="text-[11px] text-ink-500 mb-0.5">CTO · 14:02</div>
<div class="bg-ink-100 rounded-lg rounded-tl-none px-3 py-2 text-[13px] max-w-md">Mn tập trung làm vòng đời S0–S5 trước nhé, UI để sau.</div>
</div>
</div>
<div class="flex gap-2">
<div class="w-7 h-7 rounded-full bg-emerald-500 text-white text-[11px] font-bold flex items-center justify-center shrink-0">D1</div>
<div>
<div class="text-[11px] text-ink-500 mb-0.5">Dev 1 · 14:05</div>
<div class="bg-ink-100 rounded-lg rounded-tl-none px-3 py-2 text-[13px] max-w-md">Đã nắm. Em handle child #1 (DB schema).</div>
</div>
</div>
<div class="flex gap-2">
<div class="w-7 h-7 rounded-full bg-amber-500 text-white text-[11px] font-bold flex items-center justify-center shrink-0">D2</div>
<div>
<div class="text-[11px] text-ink-500 mb-0.5">Dev 2 · 14:07</div>
<div class="bg-ink-100 rounded-lg rounded-tl-none px-3 py-2 text-[13px] max-w-md">Em đính kèm tài liệu spec NolimitHub auth ở trên cùng nhé.</div>
</div>
</div>
</div>
</div>
<div class="lg:col-span-2 p-5 rounded-2xl border border-ink-200 bg-white">
<div class="text-[10px] font-mono font-semibold uppercase tracking-widest text-ink-400 mb-3">Quy tắc</div>
<ul class="space-y-3 text-[13px] text-ink-700">
<li class="flex gap-2"><span class="text-brand-500 font-bold">•</span><span>1 task lớn = 1 thread chat duy nhất.</span></li>
<li class="flex gap-2"><span class="text-brand-500 font-bold">•</span><span>Task con <strong>không có</strong> chat riêng — dùng chung chat của task lớn.</span></li>
<li class="flex gap-2"><span class="text-brand-500 font-bold">•</span><span>Mọi tin nhắn liên quan đến task (kể cả thuộc 1 task con) đều nằm gọn ở thread này.</span></li>
<li class="flex gap-2"><span class="text-brand-500 font-bold">•</span><span>Là nguồn cho cơ chế <em>gộp thông báo tin nhắn</em> ở mục (g).</span></li>
</ul>
</div>
</div>
</section>
<!-- ===== (f) History & log ===== -->
<section id="history" class="mb-16 scroll-mt-32">
<div class="flex items-baseline gap-3 mb-2">
<span class="chip text-[11px] font-mono font-semibold tracking-widest text-brand-700 bg-brand-50 px-2 py-0.5 rounded">(f)</span>
<h2 class="text-[26px] font-bold tracking-tight text-ink-950 m-0">Lịch sử & log</h2>
</div>
<div class="grid md:grid-cols-2 gap-4 my-6 not-prose">
<div class="p-5 rounded-2xl border border-ink-200 bg-white">
<div class="text-[10px] font-mono font-semibold uppercase tracking-widest text-ink-400 mb-2">f.1 · Change history</div>
<div class="text-[15px] font-bold text-ink-900 mb-2">Lịch sử thay đổi của task</div>
<p class="text-[13px] text-ink-600 leading-relaxed mb-3">
Mỗi task lưu <strong>lịch sử thay đổi</strong> để biết task đã được đổi gì, khi nào.
</p>
<div class="space-y-1.5 text-[12px] font-mono text-ink-700">
<div class="flex items-center gap-2"><span class="w-1.5 h-1.5 rounded-full bg-brand-500"></span>đổi trạng thái</div>
<div class="flex items-center gap-2"><span class="w-1.5 h-1.5 rounded-full bg-brand-500"></span>đổi người nhận</div>
<div class="flex items-center gap-2"><span class="w-1.5 h-1.5 rounded-full bg-brand-500"></span>đổi hạn</div>
<div class="flex items-center gap-2"><span class="w-1.5 h-1.5 rounded-full bg-brand-500"></span>đổi ưu tiên</div>
<div class="flex items-center gap-2"><span class="w-1.5 h-1.5 rounded-full bg-brand-500"></span>...</div>
</div>
</div>
<div class="p-5 rounded-2xl border border-emerald-200 bg-emerald-50">
<div class="text-[10px] font-mono font-semibold uppercase tracking-widest text-emerald-600 mb-2">f.2 · Close log</div>
<div class="text-[15px] font-bold text-ink-900 mb-2">Ghi log khi đóng task</div>
<p class="text-[13px] text-emerald-900/90 leading-relaxed mb-3">
Khi task chuyển sang trạng thái <strong>Đóng</strong>, hệ thống ghi 1 bản log riêng.
</p>
<div class="space-y-1.5 text-[12px] font-mono text-emerald-900/80">
<div>· ai đóng</div>
<div>· khi nào</div>
<div>· kết quả review</div>
</div>
</div>
</div>
<!-- History timeline mockup -->
<div class="my-6 not-prose rounded-2xl border border-ink-200 bg-white overflow-hidden">
<div class="px-5 py-3 border-b border-ink-200 bg-ink-50 flex items-center justify-between">
<div class="text-[12px] font-semibold text-ink-700">Ví dụ · Timeline thay đổi của 1 task</div>
<div class="text-[10px] font-mono text-ink-400">history.example</div>
</div>
<div class="p-5">
<ol class="relative border-l-2 border-ink-200 ml-2 space-y-4">
<li class="pl-5 relative">
<span class="absolute -left-[7px] top-1.5 w-3 h-3 rounded-full bg-slate-400 border-2 border-white"></span>
<div class="text-[11px] font-mono text-ink-400">08/06/2026 · 09:14</div>
<div class="text-[13px] text-ink-800"><strong>CTO</strong> đã tạo task → trạng thái <span class="font-mono text-slate-700">Tạo</span></div>
</li>
<li class="pl-5 relative">
<span class="absolute -left-[7px] top-1.5 w-3 h-3 rounded-full bg-amber-400 border-2 border-white"></span>
<div class="text-[11px] font-mono text-ink-400">08/06/2026 · 09:14</div>
<div class="text-[13px] text-ink-800">Trạng thái: <span class="font-mono">Tạo → Chờ giao</span> · gán người phân phối <strong>PM A</strong></div>
</li>
<li class="pl-5 relative">
<span class="absolute -left-[7px] top-1.5 w-3 h-3 rounded-full bg-sky-400 border-2 border-white"></span>
<div class="text-[11px] font-mono text-ink-400">08/06/2026 · 10:32</div>
<div class="text-[13px] text-ink-800"><strong>PM A</strong> giao cho <strong>Dev 1, Dev 2</strong> · trạng thái <span class="font-mono">Chờ giao → Chờ làm</span></div>
</li>
<li class="pl-5 relative">
<span class="absolute -left-[7px] top-1.5 w-3 h-3 rounded-full bg-brand-500 border-2 border-white"></span>
<div class="text-[11px] font-mono text-ink-400">08/06/2026 · 14:00</div>
<div class="text-[13px] text-ink-800">Trạng thái <span class="font-mono">Chờ làm → Đang làm</span></div>
</li>
<li class="pl-5 relative">
<span class="absolute -left-[7px] top-1.5 w-3 h-3 rounded-full bg-violet-500 border-2 border-white"></span>
<div class="text-[11px] font-mono text-ink-400">10/06/2026 · 17:40</div>
<div class="text-[13px] text-ink-800">3/3 task con đã Đóng → tự chuyển <span class="font-mono">Hoàn thành, chờ review</span></div>
</li>
<li class="pl-5 relative">
<span class="absolute -left-[7px] top-1.5 w-3 h-3 rounded-full bg-emerald-500 border-2 border-white"></span>
<div class="text-[11px] font-mono text-ink-400">10/06/2026 · 18:05</div>
<div class="text-[13px] text-ink-800"><strong>CTO</strong> review đạt · trạng thái <span class="font-mono text-emerald-700">Đóng task</span> · <em>close log ghi</em></div>
</li>
</ol>
</div>
</div>
</section>
<!-- ===== (g) Notify ===== -->
<section id="notify" class="mb-16 scroll-mt-32">
<div class="flex items-baseline gap-3 mb-2">
<span class="chip text-[11px] font-mono font-semibold tracking-widest text-brand-700 bg-brand-50 px-2 py-0.5 rounded">(g)</span>
<h2 class="text-[26px] font-bold tracking-tight text-ink-950 m-0">Thông báo</h2>
</div>
<!-- g.1 Status notify -->
<h3 class="text-[16px] font-bold text-ink-900 mt-7 mb-3">g.1 · Thông báo trạng thái</h3>
<p class="max-w-[65ch]">
Báo cho người liên quan khi task có diễn biến để mọi người nắm được tình hình. Các tình huống bắn thông báo:
</p>
<div class="grid sm:grid-cols-2 lg:grid-cols-4 gap-2 my-4 not-prose">
<div class="px-3 py-2 rounded-lg border border-ink-200 bg-white text-[12px] text-ink-800">được giao</div>
<div class="px-3 py-2 rounded-lg border border-ink-200 bg-white text-[12px] text-ink-800">được nhận</div>
<div class="px-3 py-2 rounded-lg border border-ink-200 bg-white text-[12px] text-ink-800">đổi trạng thái</div>
<div class="px-3 py-2 rounded-lg border border-ink-200 bg-white text-[12px] text-ink-800">sắp / đã quá hạn</div>
<div class="px-3 py-2 rounded-lg border border-ink-200 bg-white text-[12px] text-ink-800">chờ review</div>
<div class="px-3 py-2 rounded-lg border border-ink-200 bg-white text-[12px] text-ink-800">bị trả về làm lại</div>
<div class="px-3 py-2 rounded-lg border border-ink-200 bg-white text-[12px] text-ink-800">đóng task</div>
<div class="px-3 py-2 rounded-lg border border-dashed border-ink-300 bg-ink-50 text-[12px] text-ink-500 italic">… các diễn biến khác</div>
</div>
<!-- g.2 Chat aggregation -->
<h3 class="text-[16px] font-bold text-ink-900 mt-9 mb-3">g.2 · Thông báo tin nhắn — phải <span class="text-rose-600">GỘP theo task lớn</span></h3>
<p class="max-w-[65ch]">
Khi có tin nhắn mới trong một task, <strong>cộng dồn vào một thông báo của chính task đó</strong>
— <em>KHÔNG</em> tạo thông báo mới cho từng tin nhắn. Khi người dùng mở / đọc task thì
<strong>reset bộ đếm</strong>.
</p>
<!-- Visual: bad vs good -->
<div class="grid md:grid-cols-2 gap-4 my-6 not-prose">
<div class="p-5 rounded-2xl border border-rose-200 bg-rose-50">
<div class="flex items-center justify-between mb-3">
<span class="text-[10px] font-mono font-bold uppercase tracking-widest text-rose-700 bg-rose-100 px-2 py-1 rounded">✗ Sai</span>
<span class="text-[11px] text-rose-700/70">cách KHÔNG được làm</span>
</div>
<div class="space-y-1.5">
<div class="flex items-center gap-2 p-2 bg-white rounded border border-rose-100 text-[12px]"><span class="w-2 h-2 rounded-full bg-rose-500"></span>Tin nhắn mới trong task ABC</div>
<div class="flex items-center gap-2 p-2 bg-white rounded border border-rose-100 text-[12px]"><span class="w-2 h-2 rounded-full bg-rose-500"></span>Tin nhắn mới trong task ABC</div>
<div class="flex items-center gap-2 p-2 bg-white rounded border border-rose-100 text-[12px]"><span class="w-2 h-2 rounded-full bg-rose-500"></span>Tin nhắn mới trong task ABC</div>
<div class="flex items-center gap-2 p-2 bg-white rounded border border-rose-100 text-[12px]"><span class="w-2 h-2 rounded-full bg-rose-500"></span>Tin nhắn mới trong task ABC</div>
<div class="flex items-center gap-2 p-2 bg-white rounded border border-rose-100 text-[12px]"><span class="w-2 h-2 rounded-full bg-rose-500"></span>Tin nhắn mới trong task ABC</div>
</div>
<div class="mt-3 text-[12px] text-rose-800">→ 5 thông báo riêng = nhiễu</div>
</div>
<div class="p-5 rounded-2xl border border-emerald-200 bg-emerald-50">
<div class="flex items-center justify-between mb-3">
<span class="text-[10px] font-mono font-bold uppercase tracking-widest text-emerald-700 bg-emerald-100 px-2 py-1 rounded">✓ Đúng</span>
<span class="text-[11px] text-emerald-700/70">gộp theo task</span>
</div>
<div class="flex items-center gap-3 p-3 bg-white rounded-lg border border-emerald-200">
<div class="w-10 h-10 rounded-lg bg-emerald-500 text-white flex items-center justify-center font-bold relative">
<svg class="w-5 h-5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>
<span class="absolute -top-1.5 -right-1.5 bg-rose-500 text-white text-[10px] font-mono px-1.5 py-0.5 rounded-full leading-none">5</span>
</div>
<div>
<div class="text-[13px] font-semibold text-ink-900">Có <strong>5 tin nhắn mới</strong> trong task ABC</div>
<div class="text-[11px] text-ink-500">CTO, Dev 1, Dev 2 · 2 phút trước</div>
</div>
</div>
<div class="mt-3 text-[12px] text-emerald-800">→ 1 thông báo duy nhất, đếm cộng dồn</div>
</div>
</div>
<!-- Pseudo code rule -->
<div class="not-prose my-6 rounded-xl overflow-hidden border border-ink-800 bg-ink-950">
<div class="flex items-center justify-between px-4 py-2 bg-ink-900 border-b border-ink-800">
<div class="flex items-center gap-2">
<span class="w-2.5 h-2.5 rounded-full bg-rose-400"></span>
<span class="w-2.5 h-2.5 rounded-full bg-amber-400"></span>
<span class="w-2.5 h-2.5 rounded-full bg-emerald-400"></span>
<span class="ml-3 text-[11px] font-mono text-ink-400">notification.rules.pseudo</span>
</div>
<span class="text-[10px] font-mono px-2 py-0.5 bg-rose-900/40 text-rose-300 rounded">rule</span>
</div>
<pre class="p-5 text-[12.5px] leading-relaxed font-mono text-ink-100 overflow-x-auto"><span class="text-ink-500">// Khi có chat mới trong taskId</span>
<span class="text-violet-300">on</span> <span class="text-amber-300">newChatMessage</span>(taskId, message) {
<span class="text-violet-300">for</span> recipient <span class="text-violet-300">in</span> task.participants {
<span class="text-emerald-300">notif</span> = findExisting(recipient, taskId, <span class="text-amber-200">"chat"</span>)
<span class="text-violet-300">if</span> notif <span class="text-violet-300">exists</span> {
notif.unreadCount += 1 <span class="text-ink-500">// CỘNG DỒN, không tạo mới</span>
notif.text = <span class="text-amber-200">"Có {n} tin nhắn mới trong task ABC"</span>
} <span class="text-violet-300">else</span> {
create(recipient, taskId, type=<span class="text-amber-200">"chat"</span>, count=1)
}
}
}
<span class="text-violet-300">on</span> <span class="text-amber-300">userOpensTask</span>(userId, taskId) {
reset(userId, taskId, <span class="text-amber-200">"chat"</span>) <span class="text-ink-500">// reset bộ đếm</span>
}</pre>
</div>
</section>
<!-- ===== 2.2 Objectives ===== -->
<section id="objectives" class="mb-16 scroll-mt-32">
<h2 class="text-[28px] font-bold tracking-tight text-ink-950 mt-2 mb-2">2.2 · Mục tiêu & phạm vi</h2>
<div class="flex gap-4 p-5 rounded-xl border-l-4 border-brand-500 bg-brand-50 my-5">
<div class="shrink-0 w-8 h-8 rounded-lg bg-brand-500 text-white flex items-center justify-center font-bold text-sm">🎯</div>
<div>
<div class="text-[13px] font-semibold text-brand-900 uppercase tracking-wider mb-1">Phạm vi · chốt rõ để dev không làm quá tay</div>
<p class="text-[14px] text-brand-900/90 leading-relaxed m-0">
Chỉ hiện thực <strong>đúng các trạng thái & hành vi</strong> ở 2.1.
<strong>KHÔNG</strong> workflow builder tự do, <strong>không</strong> hệ thống phân quyền /
loại trạng thái phức tạp ngoài mô tả, <strong>không</strong> phình thành nền tảng PM đầy đủ.
Giữ tính năng <strong>đơn giản, đúng nhu cầu</strong>.
</p>
</div>
</div>
<!-- After release -->
<h3 class="text-[18px] font-bold text-ink-900 mt-8 mb-3">Sau khi làm xong</h3>
<div class="grid md:grid-cols-2 gap-3 not-prose">
<div class="p-5 rounded-xl border border-ink-200 bg-white">
<div class="flex items-start gap-3">
<div class="font-mono text-[10px] font-bold text-brand-500 mt-0.5">O1</div>
<p class="text-[13.5px] text-ink-700 leading-relaxed m-0">Mọi công việc nội bộ được <strong>tạo – giao – theo dõi</strong> trong một hệ thống tập trung; mỗi task luôn rõ: <em>ai tạo, ai làm/điều phối, hạn khi nào, đang ở bước nào</em>.</p>
</div>
</div>
<div class="p-5 rounded-xl border border-ink-200 bg-white">
<div class="flex items-start gap-3">
<div class="font-mono text-[10px] font-bold text-brand-500 mt-0.5">O2</div>
<p class="text-[13.5px] text-ink-700 leading-relaxed m-0">Có đủ <strong>2 cách đưa việc</strong>: giao thẳng người làm, hoặc qua người phân phối / để người phù hợp tự nhận.</p>
</div>
</div>
<div class="p-5 rounded-xl border border-ink-200 bg-white">
<div class="flex items-start gap-3">
<div class="font-mono text-[10px] font-bold text-brand-500 mt-0.5">O3</div>
<p class="text-[13.5px] text-ink-700 leading-relaxed m-0">Task lớn <strong>chia được thành task con</strong> (mỗi task con 1 người); task lớn <strong>tự hoàn thành</strong> khi mọi task con đã đóng.</p>
</div>
</div>
<div class="p-5 rounded-xl border border-ink-200 bg-white">
<div class="flex items-start gap-3">
<div class="font-mono text-[10px] font-bold text-brand-500 mt-0.5">O4</div>
<p class="text-[13.5px] text-ink-700 leading-relaxed m-0">Có <strong>bước review</strong> trước khi đóng; review trượt thì trả về <strong>làm lại</strong>.</p>
</div>
</div>
<div class="p-5 rounded-xl border border-ink-200 bg-white">
<div class="flex items-start gap-3">
<div class="font-mono text-[10px] font-bold text-brand-500 mt-0.5">O5</div>
<p class="text-[13.5px] text-ink-700 leading-relaxed m-0">Mọi thay đổi được lưu <strong>lịch sử</strong>; lúc đóng task có <strong>log</strong>.</p>
</div>
</div>
<div class="p-5 rounded-xl border border-ink-200 bg-white">
<div class="flex items-start gap-3">
<div class="font-mono text-[10px] font-bold text-brand-500 mt-0.5">O6</div>
<p class="text-[13.5px] text-ink-700 leading-relaxed m-0">Trao đổi của một task nằm gọn trong <strong>chat của task</strong>; <strong>thông báo tin nhắn được gộp theo task</strong>, không gây nhiễu.</p>
</div>
</div>
</div>
<!-- Short-term release -->
<h3 class="text-[18px] font-bold text-ink-900 mt-10 mb-3">Ngắn hạn — release đầu</h3>
<div class="not-prose p-5 rounded-2xl border border-ink-200 bg-white">
<div class="text-[10px] font-mono font-semibold uppercase tracking-widest text-ink-400 mb-3">scope · release 01</div>
<div class="grid sm:grid-cols-2 lg:grid-cols-3 gap-2">
<div class="flex items-center gap-2 px-3 py-2 rounded-lg bg-ink-50 border border-ink-200 text-[12.5px]">✓ Vòng đời task lớn</div>
<div class="flex items-center gap-2 px-3 py-2 rounded-lg bg-ink-50 border border-ink-200 text-[12.5px]">✓ Task con</div>
<div class="flex items-center gap-2 px-3 py-2 rounded-lg bg-ink-50 border border-ink-200 text-[12.5px]">✓ 2 cách giao</div>
<div class="flex items-center gap-2 px-3 py-2 rounded-lg bg-ink-50 border border-ink-200 text-[12.5px]">✓ Chat theo task lớn</div>
<div class="flex items-center gap-2 px-3 py-2 rounded-lg bg-ink-50 border border-ink-200 text-[12.5px]">✓ Lịch sử + log đóng</div>
<div class="flex items-center gap-2 px-3 py-2 rounded-lg bg-ink-50 border border-ink-200 text-[12.5px]">✓ Thông báo (trạng thái + gộp tin nhắn)</div>
</div>
<div class="mt-4 pt-4 border-t border-ink-200 flex items-center gap-2 text-[12.5px] text-ink-600">
<span class="text-[10px] font-mono font-bold px-2 py-0.5 rounded bg-brand-100 text-brand-700">Channel</span>
Kênh thông báo tối thiểu: <strong class="text-ink-900">in-app</strong>.
</div>
</div>
</section>
<!-- ===== Metrics ===== -->
<section id="metrics" class="mb-16 scroll-mt-32">
<h2 class="text-[24px] font-bold tracking-tight text-ink-950 mt-4 mb-3">Chỉ số đo lường thành công</h2>
<p class="max-w-[65ch]">5 KPI dưới đây để xác định module đã giải quyết đúng vấn đề ở mục 2.1.</p>
<div class="grid sm:grid-cols-2 lg:grid-cols-5 gap-3 my-6 not-prose">
<div class="p-5 rounded-2xl border border-ink-200 bg-white">
<div class="text-[10px] font-mono uppercase tracking-widest text-ink-400 mb-1">KPI 1</div>
<div class="text-[28px] font-extrabold text-brand-600 font-mono mb-2">↑</div>
<div class="text-[13px] font-semibold text-ink-900 mb-1">Tập trung hóa</div>
<p class="text-[12px] text-ink-600 leading-relaxed m-0">Tỷ lệ công việc nội bộ được quản lý qua hệ thống tăng dần tới <strong>phần lớn</strong> task đi qua hệ thống.</p>
</div>
<div class="p-5 rounded-2xl border border-ink-200 bg-white">
<div class="text-[10px] font-mono uppercase tracking-widest text-ink-400 mb-1">KPI 2</div>
<div class="text-[28px] font-extrabold text-brand-600 font-mono mb-2">100%</div>
<div class="text-[13px] font-semibold text-ink-900 mb-1">Không còn task "vô chủ"</div>
<p class="text-[12px] text-ink-600 leading-relaxed m-0">Có người làm <em>hoặc</em> người phân phối rõ ràng + có trạng thái + có hạn.</p>
</div>
<div class="p-5 rounded-2xl border border-ink-200 bg-white">
<div class="text-[10px] font-mono uppercase tracking-widest text-ink-400 mb-1">KPI 3</div>
<div class="text-[28px] font-extrabold text-brand-600 font-mono mb-2">100%</div>
<div class="text-[13px] font-semibold text-ink-900 mb-1">Truy vết đầy đủ</div>
<p class="text-[12px] text-ink-600 leading-relaxed m-0">Mọi thay đổi và mỗi lần đóng task đều có log.</p>
</div>
<div class="p-5 rounded-2xl border border-ink-200 bg-white">
<div class="text-[10px] font-mono uppercase tracking-widest text-ink-400 mb-1">KPI 4</div>
<div class="text-[28px] font-extrabold text-brand-600 font-mono mb-2">✓</div>
<div class="text-[13px] font-semibold text-ink-900 mb-1">Có nghiệm thu</div>
<p class="text-[12px] text-ink-600 leading-relaxed m-0">Task chỉ <strong>Đóng</strong> sau khi đi qua "Hoàn thành, chờ review".</p>
</div>
<div class="p-5 rounded-2xl border border-ink-200 bg-white">
<div class="text-[10px] font-mono uppercase tracking-widest text-ink-400 mb-1">KPI 5</div>
<div class="text-[28px] font-extrabold text-brand-600 font-mono mb-2">1 ↑</div>
<div class="text-[13px] font-semibold text-ink-900 mb-1">Thông báo gọn</div>
<p class="text-[12px] text-ink-600 leading-relaxed m-0">Tin nhắn mới trong 1 task chỉ <strong>làm tăng bộ đếm</strong> của 1 thông báo, không sinh notif lẻ.</p>
</div>
</div>
</section>
<!-- ===== Reference / cheatsheet ===== -->
<section id="api-ref" class="mb-16 scroll-mt-32">
<div class="flex items-baseline gap-3 mb-2">
<span class="text-[11px] font-mono font-semibold uppercase tracking-[0.18em] text-ink-400">§ 03</span>
<h2 class="text-[26px] font-bold tracking-tight text-ink-950 m-0">Quick reference</h2>
</div>
<p class="max-w-[65ch]">Bảng tham chiếu nhanh — không phải spec kỹ thuật chính thức; thiết kế API do dev tự lo.</p>
<!-- States table -->
<details open class="my-5 not-prose rounded-2xl border border-ink-200 bg-white overflow-hidden">
<summary class="px-5 py-4 flex items-center justify-between border-b border-ink-200 bg-ink-50">
<div>
<div class="text-[10px] font-mono font-semibold uppercase tracking-widest text-ink-400 mb-1">ref-01</div>
<div class="text-[14px] font-semibold text-ink-900">Bảng trạng thái — Task lớn vs Task con</div>
</div>
<svg class="w-4 h-4 text-ink-400 transition-transform" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="m6 9 6 6 6-6"/></svg>
</summary>
<table class="w-full text-[13px]">
<thead class="bg-white text-ink-500 text-[11px] uppercase tracking-widest">
<tr>
<th class="text-left font-semibold py-3 px-5 w-16">Code</th>
<th class="text-left font-semibold py-3 px-5">Trạng thái</th>
<th class="text-left font-semibold py-3 px-5">Task lớn</th>
<th class="text-left font-semibold py-3 px-5">Task con</th>
</tr>
</thead>
<tbody class="divide-y divide-ink-200">
<tr><td class="py-2.5 px-5 font-mono text-ink-500">S0</td><td class="py-2.5 px-5 font-semibold">Tạo</td><td class="py-2.5 px-5 text-emerald-600">✓</td><td class="py-2.5 px-5 text-ink-300">—</td></tr>
<tr><td class="py-2.5 px-5 font-mono text-ink-500">S1</td><td class="py-2.5 px-5 font-semibold">Chờ giao</td><td class="py-2.5 px-5 text-emerald-600">✓ (cách 2)</td><td class="py-2.5 px-5 text-ink-300">—</td></tr>
<tr><td class="py-2.5 px-5 font-mono text-ink-500">S2</td><td class="py-2.5 px-5 font-semibold">Chờ làm</td><td class="py-2.5 px-5 text-emerald-600">✓</td><td class="py-2.5 px-5 text-emerald-600">✓</td></tr>
<tr><td class="py-2.5 px-5 font-mono text-ink-500">S3</td><td class="py-2.5 px-5 font-semibold">Đang làm</td><td class="py-2.5 px-5 text-emerald-600">✓</td><td class="py-2.5 px-5 text-emerald-600">✓</td></tr>
<tr><td class="py-2.5 px-5 font-mono text-ink-500">S3*</td><td class="py-2.5 px-5 font-semibold">Quá hạn</td><td class="py-2.5 px-5 text-emerald-600">✓ (overlay)</td><td class="py-2.5 px-5 text-emerald-600">✓ (overlay)</td></tr>
<tr><td class="py-2.5 px-5 font-mono text-ink-500">S4</td><td class="py-2.5 px-5 font-semibold">Hoàn thành, chờ review</td><td class="py-2.5 px-5 text-emerald-600">✓ (auto từ con)</td><td class="py-2.5 px-5 text-emerald-600">✓</td></tr>
<tr><td class="py-2.5 px-5 font-mono text-ink-500">S5</td><td class="py-2.5 px-5 font-semibold">Đóng</td><td class="py-2.5 px-5 text-emerald-600">✓ (+log)</td><td class="py-2.5 px-5 text-emerald-600">✓</td></tr>
<tr><td class="py-2.5 px-5 font-mono text-ink-500">↩</td><td class="py-2.5 px-5 font-semibold">Cần làm lại</td><td class="py-2.5 px-5 text-emerald-600">→ S2</td><td class="py-2.5 px-5 text-emerald-600">→ S2</td></tr>
</tbody>
</table>
</details>
<!-- Quantifier table -->
<details class="my-5 not-prose rounded-2xl border border-ink-200 bg-white overflow-hidden">
<summary class="px-5 py-4 flex items-center justify-between border-b border-ink-200 bg-ink-50">
<div>
<div class="text-[10px] font-mono font-semibold uppercase tracking-widest text-ink-400 mb-1">ref-02</div>
<div class="text-[14px] font-semibold text-ink-900">Quan hệ số lượng người</div>
</div>
<svg class="w-4 h-4 text-ink-400" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="m6 9 6 6 6-6"/></svg>
</summary>
<table class="w-full text-[13px]">
<thead class="bg-white text-ink-500 text-[11px] uppercase tracking-widest">
<tr><th class="text-left font-semibold py-3 px-5">Đối tượng</th><th class="text-left font-semibold py-3 px-5">Số lượng người</th><th class="text-left font-semibold py-3 px-5">Ghi chú</th></tr>
</thead>
<tbody class="divide-y divide-ink-200">
<tr><td class="py-2.5 px-5">Task lớn · Người tạo</td><td class="py-2.5 px-5 font-mono">1</td><td class="py-2.5 px-5 text-ink-600">Người khởi tạo task</td></tr>
<tr><td class="py-2.5 px-5">Task lớn · Người phân phối</td><td class="py-2.5 px-5 font-mono">0 hoặc 1</td><td class="py-2.5 px-5 text-ink-600">Chỉ có ở cách 2</td></tr>
<tr><td class="py-2.5 px-5">Task lớn · Người nhận</td><td class="py-2.5 px-5 font-mono">1..n</td><td class="py-2.5 px-5 text-ink-600">Có thể nhiều người</td></tr>
<tr class="bg-brand-50/40"><td class="py-2.5 px-5 font-semibold">Task con · Người làm</td><td class="py-2.5 px-5 font-mono font-bold text-brand-700">1</td><td class="py-2.5 px-5 text-brand-900">Duy nhất, không nhiều</td></tr>
<tr><td class="py-2.5 px-5">Chat thread</td><td class="py-2.5 px-5 font-mono">1 / task lớn</td><td class="py-2.5 px-5 text-ink-600">Task con dùng chung</td></tr>
</tbody>
</table>
</details>
<!-- Notification triggers -->
<details class="my-5 not-prose rounded-2xl border border-ink-200 bg-white overflow-hidden">
<summary class="px-5 py-4 flex items-center justify-between border-b border-ink-200 bg-ink-50">
<div>
<div class="text-[10px] font-mono font-semibold uppercase tracking-widest text-ink-400 mb-1">ref-03</div>
<div class="text-[14px] font-semibold text-ink-900">Trigger thông báo & quy tắc gộp</div>
</div>
<svg class="w-4 h-4 text-ink-400" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="m6 9 6 6 6-6"/></svg>
</summary>
<table class="w-full text-[13px]">
<thead class="bg-white text-ink-500 text-[11px] uppercase tracking-widest">
<tr><th class="text-left font-semibold py-3 px-5">Event</th><th class="text-left font-semibold py-3 px-5">Loại notify</th><th class="text-left font-semibold py-3 px-5">Gộp?</th></tr>
</thead>
<tbody class="divide-y divide-ink-200">
<tr><td class="py-2.5 px-5">Được giao task</td><td class="py-2.5 px-5">status</td><td class="py-2.5 px-5 text-ink-300">—</td></tr>
<tr><td class="py-2.5 px-5">Được nhận task</td><td class="py-2.5 px-5">status</td><td class="py-2.5 px-5 text-ink-300">—</td></tr>
<tr><td class="py-2.5 px-5">Đổi trạng thái</td><td class="py-2.5 px-5">status</td><td class="py-2.5 px-5 text-ink-300">—</td></tr>
<tr><td class="py-2.5 px-5">Sắp / đã quá hạn</td><td class="py-2.5 px-5">status</td><td class="py-2.5 px-5 text-ink-300">—</td></tr>
<tr><td class="py-2.5 px-5">Chờ review</td><td class="py-2.5 px-5">status</td><td class="py-2.5 px-5 text-ink-300">—</td></tr>
<tr><td class="py-2.5 px-5">Bị trả về làm lại</td><td class="py-2.5 px-5">status</td><td class="py-2.5 px-5 text-ink-300">—</td></tr>
<tr><td class="py-2.5 px-5">Đóng task</td><td class="py-2.5 px-5">status</td><td class="py-2.5 px-5 text-ink-300">—</td></tr>
<tr class="bg-emerald-50/40"><td class="py-2.5 px-5 font-semibold">Tin nhắn mới trong chat</td><td class="py-2.5 px-5 font-semibold">chat</td><td class="py-2.5 px-5 text-emerald-700 font-bold">✓ GỘP theo task lớn</td></tr>
</tbody>
</table>
</details>
<!-- Out-of-scope reminder -->
<div class="my-6 not-prose p-5 rounded-2xl border-2 border-dashed border-rose-300 bg-rose-50">
<div class="text-[10px] font-mono font-semibold uppercase tracking-widest text-rose-600 mb-2">⚠ Out-of-scope · không làm</div>
<div class="grid sm:grid-cols-2 lg:grid-cols-3 gap-2">
<div class="px-3 py-2 rounded bg-white border border-rose-200 text-[12px] text-rose-900 line-through opacity-80">Gantt chart</div>
<div class="px-3 py-2 rounded bg-white border border-rose-200 text-[12px] text-rose-900 line-through opacity-80">Timesheet</div>
<div class="px-3 py-2 rounded bg-white border border-rose-200 text-[12px] text-rose-900 line-through opacity-80">Workflow builder tự do</div>
<div class="px-3 py-2 rounded bg-white border border-rose-200 text-[12px] text-rose-900 line-through opacity-80">Phân quyền phức tạp</div>
<div class="px-3 py-2 rounded bg-white border border-rose-200 text-[12px] text-rose-900 line-through opacity-80">Loại trạng thái ngoài mô tả</div>
<div class="px-3 py-2 rounded bg-white border border-rose-200 text-[12px] text-rose-900 line-through opacity-80">App tách rời NolimitHub</div>
</div>
</div>
</section>
<!-- ===== Footer meta ===== -->
<section id="footer-meta" class="scroll-mt-32 mt-20 pt-8 border-t border-ink-200">
<div class="text-[10px] font-mono font-semibold uppercase tracking-widest text-ink-400 mb-3">§ 04 · Document meta</div>
<div class="grid md:grid-cols-2 gap-6">
<div>
<div class="text-[13px] text-ink-500 mb-1">Last reviewed</div>
<div class="text-[16px] font-mono font-semibold text-ink-900">08/06/2026</div>
</div>
<div>
<div class="text-[13px] text-ink-500 mb-1">Author context</div>
<p class="text-[13px] text-ink-700 leading-relaxed m-0">
CTO mô tả dự tính cấu hình cho <strong>hệ thống quản lý task nội bộ</strong> — vòng đời task
(Tạo → Chờ giao → Chờ làm → Đang làm → Quá hạn → Hoàn thành/chờ review → Đóng / Cần làm lại),
các trường của task, 2 cách giao (trực tiếp / qua người phân phối / tự nhận), task con
(mỗi con 1 người, task lớn tự hoàn thành khi mọi con đã đóng), chat gắn theo task lớn, lịch sử &
log khi đóng, và thông báo gộp tin nhắn theo task lớn.
</p>
</div>
</div>
<div class="mt-8 pt-6 border-t border-ink-200 flex flex-wrap items-center justify-between gap-3 text-[11px] font-mono text-ink-400">
<div>FT-TASK-MGMT-01 · v0.1 Draft · NolimitHub Internal</div>
<div>© 2026 · Tài liệu nội bộ — Spec ở mức nghiệp vụ, thiết kế kỹ thuật do dev tự lo.</div>
</div>
</section>
</main>
<!-- ============ INLINE-END TOC ============ -->
<aside class="hidden xl:block col-span-2 pt-10">
<div class="sticky top-32 max-h-[calc(100vh-9rem)] overflow-y-auto scrollbar-thin pr-2">
<div class="text-[10px] font-semibold uppercase tracking-[0.18em] text-ink-400 mb-3">On this page</div>
<ul id="tocList" class="space-y-1 text-[12px] border-l border-ink-200">
<li><a href="#overview" class="toc-link block pl-3 py-1 border-l-2 -ml-px border-transparent text-ink-500 hover:text-ink-900 transition-colors">Thông tin chung</a></li>
<li><a href="#context" class="toc-link block pl-3 py-1 border-l-2 -ml-px border-transparent text-ink-500 hover:text-ink-900 transition-colors">Bối cảnh & Mục tiêu</a></li>
<li><a href="#context-detail" class="toc-link block pl-6 py-1 border-l-2 -ml-px border-transparent text-ink-500 hover:text-ink-900 transition-colors text-[11.5px]">2.1 Bối cảnh</a></li>
<li><a href="#pain-points" class="toc-link block pl-6 py-1 border-l-2 -ml-px border-transparent text-ink-500 hover:text-ink-900 transition-colors text-[11.5px]">— Hệ quả</a></li>
<li><a href="#lifecycle" class="toc-link block pl-6 py-1 border-l-2 -ml-px border-transparent text-ink-500 hover:text-ink-900 transition-colors text-[11.5px]">(a) Vòng đời</a></li>
<li><a href="#task-fields" class="toc-link block pl-6 py-1 border-l-2 -ml-px border-transparent text-ink-500 hover:text-ink-900 transition-colors text-[11.5px]">(b) Trường dữ liệu</a></li>
<li><a href="#assignment" class="toc-link block pl-6 py-1 border-l-2 -ml-px border-transparent text-ink-500 hover:text-ink-900 transition-colors text-[11.5px]">(c) 2 cách giao</a></li>
<li><a href="#subtask" class="toc-link block pl-6 py-1 border-l-2 -ml-px border-transparent text-ink-500 hover:text-ink-900 transition-colors text-[11.5px]">(d) Task con</a></li>
<li><a href="#chat" class="toc-link block pl-6 py-1 border-l-2 -ml-px border-transparent text-ink-500 hover:text-ink-900 transition-colors text-[11.5px]">(e) Chat</a></li>
<li><a href="#history" class="toc-link block pl-6 py-1 border-l-2 -ml-px border-transparent text-ink-500 hover:text-ink-900 transition-colors text-[11.5px]">(f) Lịch sử & log</a></li>
<li><a href="#notify" class="toc-link block pl-6 py-1 border-l-2 -ml-px border-transparent text-ink-500 hover:text-ink-900 transition-colors text-[11.5px]">(g) Thông báo</a></li>
<li><a href="#objectives" class="toc-link block pl-6 py-1 border-l-2 -ml-px border-transparent text-ink-500 hover:text-ink-900 transition-colors text-[11.5px]">2.2 Mục tiêu</a></li>
<li><a href="#metrics" class="toc-link block pl-6 py-1 border-l-2 -ml-px border-transparent text-ink-500 hover:text-ink-900 transition-colors text-[11.5px]">— KPI</a></li>
<li><a href="#api-ref" class="toc-link block pl-3 py-1 border-l-2 -ml-px border-transparent text-ink-500 hover:text-ink-900 transition-colors">Quick reference</a></li>
<li><a href="#footer-meta" class="toc-link block pl-3 py-1 border-l-2 -ml-px border-transparent text-ink-500 hover:text-ink-900 transition-colors">Document meta</a></li>
</ul>
<div class="mt-6 pt-4 border-t border-ink-200">
<div class="text-[10px] font-semibold uppercase tracking-[0.18em] text-ink-400 mb-2">Quick actions</div>
<a href="#top" class="block px-2.5 py-1 text-[12px] text-ink-600 hover:text-ink-900">↑ Back to top</a>
<button onclick="window.print()" class="block w-full text-left px-2.5 py-1 text-[12px] text-ink-600 hover:text-ink-900">🖨 Print spec</button>
</div>
</div>
</aside>
</div>
<script>
// Scroll-spy
const sections = document.querySelectorAll('section[id]');
const tocLinks = document.querySelectorAll('#tocList a, #sideNav a');
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const id = entry.target.id;
tocLinks.forEach(link => {
const isActive = link.getAttribute('href') === '#' + id;
link.classList.toggle('active', isActive);
});
}
});
}, { rootMargin: '-30% 0px -60% 0px', threshold: 0 });
sections.forEach(s => observer.observe(s));
// Details rotate caret
document.querySelectorAll('details').forEach(d => {
d.addEventListener('toggle', () => {
const svg = d.querySelector('summary svg');
if (svg) svg.style.transform = d.open ? 'rotate(180deg)' : 'rotate(0deg)';
});
});
</script>
</body>
</html>
Số dòng: 1416