Komponen / Tampilan data
Checklist
Daftar tugas ala Reminders dengan tenggat dan penanggung jawab: langkah serah terima, kelengkapan sebelum diajukan, tindakan yang menunggu Anda.
Tugas dengan tenggat & PIC
Tenggat memakai DueDate (status dihitung dari `today`), penanggung jawab memakai Avatar 20. Saat dicentang, tenggat turun ke Done dan label menjadi abu. Ringkasan "x dari y selesai" di subjudul Card + ProgressBar.
Serah terima · PRJ-2026-0088
2 dari 5 selesai
- Selesai: Penanggung jawab: Rina Kartika
- Selesai: Penanggung jawab: Rina Kartika
- Tenggat terlewat: Terlambat 2 hari, Penanggung jawab: Dimas Prasetyo
- Tenggat dekat: 2 hari lagi, Penanggung jawab: Anisa Nugraha
- Tenggat: Penanggung jawab: Dimas Prasetyo
import { useState } from 'react';
import { Card, Checklist, ProgressBar } from '@divistant/circca-react';
// Daftar tugas proyek PRJ-2026-0088 dengan tenggat dan penanggung jawab. Status selesai menurunkan tenggat ke Done.
const today = new Date(2026, 9, 8);
const awal = [
{ id: 'tenant', label: 'Siapkan tenant', due: '2026-09-28', pic: 'Rina Kartika', done: true },
{ id: 'lisensi', label: 'Aktivasi lisensi 25 user', due: '2026-10-01', pic: 'Rina Kartika', done: true },
{ id: 'login', label: 'Verifikasi login 25 user', due: '2026-10-06', pic: 'Dimas Prasetyo', done: false },
{ id: 'bast', label: 'Serah terima ke customer', due: '2026-10-10', pic: 'Anisa Nugraha', done: false },
{ id: 'pelatihan', label: 'Pelatihan admin (2 sesi)', due: '2026-10-24', pic: 'Dimas Prasetyo', done: false },
];
export default function Example() {
const [tugas, setTugas] = useState(awal);
const selesai = tugas.filter(t => t.done).length;
return (
<Card className="max-w-[520px]" title="Serah terima · PRJ-2026-0088" subtitle={`${selesai} dari ${tugas.length} selesai`}>
<div className="grid gap-3">
<ProgressBar aria-label="Progres serah terima" value={selesai} max={tugas.length} />
<Checklist className="-mx-2.5" today={today} aria-label="Tugas serah terima PRJ-2026-0088">
{tugas.map(t => (
<Checklist.Item
key={t.id}
checked={t.done}
onCheckedChange={v => setTugas(list => list.map(x => (x.id === t.id ? { ...x, done: v } : x)))}
due={t.due}
assignee={t.pic}
>
{t.label}
</Checklist.Item>
))}
</Checklist>
</div>
</Card>
);
}Perlu tindakan Anda
Item yang sudah tercapai `readOnly`; tombol utama baru aktif setelah semua terpenuhi. `summary` menghitung ringkasan otomatis.
Perlu tindakan Anda
Tenggat dekat:
Terbitkan BAST instalasi agar Termin 2 (Rp 60.000.000) bisa ditagih.
2 dari 3 selesai
import { useState } from 'react';
import { Button, Card, Checklist, DueDate, formatMoney } from '@divistant/circca-react';
// Kartu "Perlu tindakan Anda" di detail PO: tenggat di header, checklist serah terima, satu tombol utama.
const today = new Date(2026, 9, 8);
export default function Example() {
const [ttd, setTtd] = useState(false);
return (
<Card
className="max-w-[400px]"
elevation="raised"
title="Perlu tindakan Anda"
action={<DueDate date={today} today={today} relative={false} label="Hari ini" />}
>
<div className="grid gap-2">
<p className="type-callout-default text-default">
Terbitkan BAST instalasi agar Termin 2 ({formatMoney(60_000_000)}) bisa ditagih.
</p>
<Checklist className="-mx-2.5" today={today} summary aria-label="Syarat terbit BAST">
<Checklist.Item checked readOnly>Instalasi & aktivasi 25 lisensi</Checklist.Item>
<Checklist.Item checked readOnly>Uji akses pengguna oleh customer</Checklist.Item>
<Checklist.Item checked={ttd} onCheckedChange={setTtd}>
Tanda tangan BAST oleh customer
</Checklist.Item>
</Checklist>
<Button variant="primary" block disabled={!ttd}>
Terbitkan BAST
</Button>
</div>
</Card>
);
}Kelengkapan sebelum diajukan
Seluruh daftar `readOnly`: centang diturunkan dari isi form, bukan diklik pengguna. Menjelaskan kenapa tombol Ajukan belum aktif.
Kelengkapan sebelum diajukan
2 dari 3 terpenuhi
Tidak ada baris lisensi — PO distributor dan cek margin tidak diperlukan.
import { useState } from 'react';
import { Card, Checklist, Checkbox } from '@divistant/circca-react';
// Kartu "Kelengkapan sebelum diajukan" di form PO: item hanya baca, dicentang otomatis dari isi form.
export default function Example() {
const [ttd, setTtd] = useState(false);
const syarat = [
{ label: 'Customer, nomor & nilai kontrak', ok: true },
{ label: 'Termin berjumlah 100%', ok: true },
{ label: 'PO customer bertanda tangan', ok: ttd },
];
const terpenuhi = syarat.filter(s => s.ok).length;
return (
<div className="grid max-w-[360px] gap-4">
<Checkbox checked={ttd} onCheckedChange={setTtd}>
(Simulasi) Unggah PO customer bertanda tangan
</Checkbox>
<Card
title="Kelengkapan sebelum diajukan"
subtitle={`${terpenuhi} dari ${syarat.length} terpenuhi`}
footer="Tidak ada baris lisensi — PO distributor dan cek margin tidak diperlukan."
>
<Checklist className="-mx-2.5" readOnly aria-label="Kelengkapan sebelum diajukan">
{syarat.map(s => (
<Checklist.Item key={s.label} checked={s.ok}>
{s.label}
</Checklist.Item>
))}
</Checklist>
</Card>
</div>
);
}