# Segmentasi Kontak


Segment adalah filter kontak yang disimpan. Setiap segment menyimpan sekumpulan
**aturan filter** (`filter_rules`) dalam format JSON, dan setiap kali segment
dikueri, sistem mengevaluasi ulang aturan tersebut terhadap tabel `contacts`
di PostgreSQL untuk menghasilkan daftar kontak yang cocok secara real-time.

**Rute frontend:** `/contacts/segments`

## Dinamis vs. Statis

| Mode | Perilaku |
|------|----------|
| **Dinamis** (default) | Filter dievaluasi ulang setiap kali segment dikueri — jumlah kontak selalu mencerminkan data terkini |
| **Statis** | Filter tidak dievaluasi ulang secara otomatis; `contact_count` hanya diperbarui saat segment dibuka atau kontak segment dimuat |

:::note
Pada praktiknya, perbedaan utama ada pada kapan `contact_count` diperbarui.
Kedua mode menggunakan query SQL yang sama saat memuat daftar kontak —
perbedaannya hanya pada pembaruan cache hitungan.
:::

## Filter yang Tersedia

Semua aturan filter bersifat opsional dan dapat dikombinasikan. Jika tidak ada
filter yang diatur, segment akan cocok dengan semua kontak.

| Filter | Tipe | Keterangan |
|--------|------|------------|
| **Channel** | Pilihan | Cocokkan kontak berdasarkan channel asal: `whatsapp`, `instagram`, `email`, `messenger` |
| **Tags** | Teks (pisahkan dengan koma) | Kontak yang memiliki **salah satu** tag yang disebutkan (operator `contains any`) |
| **Setelah tanggal** (`created_after`) | Tanggal | Kontak yang dibuat pada atau setelah tanggal ini |
| **Sebelum tanggal** (`created_before`) | Tanggal | Kontak yang dibuat pada atau sebelum tanggal ini |
| **Has Email** | Yes / No / Any | `Yes` = email tidak kosong; `No` = email kosong; `Any` = tidak difilter |
| **Has Phone** | Yes / No / Any | `Yes` = nomor telepon tidak kosong; `No` = nomor telepon kosong; `Any` = tidak difilter |
| **Search** | Teks | Pencarian case-insensitive pada nama, email, atau nomor telepon (`ILIKE '%…%'`) |

:::tip
Filter **Tags** menggunakan logika **OR** — kontak yang memiliki *setidaknya satu*
tag dari daftar yang Anda masukkan akan dicocokkan. Pisahkan beberapa tag dengan
koma, contoh: `vip, premium`.
:::

## Preview Langsung

Saat Anda mengatur filter di form pembuatan/edit segment, sistem secara otomatis
menampilkan **preview** (dengan jeda 500ms) yang menunjukkan:

- Jumlah total kontak yang cocok.
- Hingga 10 contoh kontak (nama, nomor, email).

Preview ini tidak menyimpan apa pun — berguna untuk memvalidasi filter sebelum
menyimpan segment.

## Membuat Segment

:::note
Membuat, mengedit, dan menghapus segment memerlukan izin `contacts.manage`.
Peran **Admin**, **Supervisor**, dan **Agent** semuanya memiliki izin ini.
Melihat dan mem-preview segment memerlukan izin `contacts.view`.
:::

1. Buka `/contacts/segments`.
2. Klik **New Segment**.
3. Isi **Name** (wajib, 1–255 karakter) dan **Description** (opsional).
4. Pilih apakah segment bersifat **Dynamic** (centang kotak) atau statis (kosongkan).
5. Atur satu atau lebih filter di bagian **Filter Rules**.
6. Perhatikan panel **Preview** — pastikan jumlah kontak sesuai harapan.
7. Klik **Create**.

## Mengedit Segment

1. Di daftar segment, klik ikon pensil pada segment yang ingin diubah.
2. Modifikasi nama, deskripsi, mode dinamis/statis, atau aturan filter.
3. Jika filter rules diubah, `contact_count` akan dihitung ulang secara otomatis.
4. Klik **Update**.

## Melihat Kontak dalam Segment

Klik ikon **mata** (👁) di samping segment untuk melihat daftar kontak yang
cocok, lengkap dengan nama, nomor telepon, email, channel, dan tanggal dibuat.
Daftar ini dipaginasi (20 kontak per halaman).

## Aksi Massal pada Segment

Untuk segment yang memiliki setidaknya satu kontak, tersedia tiga aksi massal
(hanya untuk Admin dan Supervisor):

| Aksi | Keterangan |
|------|------------|
| **Add Tags** | Tambahkan satu atau lebih tag ke semua kontak yang cocok dengan filter segment |
| **Remove Tags** | Hapus satu atau lebih tag dari semua kontak yang cocok |
| **Export CSV** | Unduh semua kontak segment sebagai file CSV (nama file: `segment_contacts_YYYY-MM-DD.csv`) |

:::warning
Aksi **Add Tags** dan **Remove Tags** bersifat massal — semua kontak yang cocok
dengan filter segment saat aksi dijalankan akan terpengaruh. Pastikan filter
sudah benar sebelum mengonfirmasi.

Aksi **hapus kontak** secara massal melalui segment **tidak didukung** — gunakan
endpoint `/api/contacts/bulk` dengan daftar `contact_ids` eksplisit.
:::

## Menghapus Segment

1. Klik ikon tempat sampah pada segment.
2. Konfirmasi penghapusan di dialog yang muncul.

Menghapus segment hanya menghapus definisi segment — tidak menghapus kontak
yang ada di dalamnya.

## Endpoint API

| Method | Path | Keterangan |
|--------|------|------------|
| `GET` | `/api/contact-segments` | Daftar semua segment (paginasi) |
| `POST` | `/api/contact-segments` | Buat segment baru |
| `GET` | `/api/contact-segments/{id}` | Detail satu segment |
| `PATCH` | `/api/contact-segments/{id}` | Update segment |
| `DELETE` | `/api/contact-segments/{id}` | Hapus segment |
| `POST` | `/api/contact-segments/preview` | Preview filter tanpa menyimpan |
| `GET` | `/api/contact-segments/{id}/contacts` | Daftar kontak dalam segment (paginasi) |
| `POST` | `/api/contacts/bulk-by-segment` | Aksi massal (add_tags, remove_tags, export) |

## Rute Terkait

- [Manajemen Kontak](/panduan/agent/kontak) — direktori kontak dan detail kontak
- [Kampanye Broadcast](/panduan/admin/kampanye-broadcast) — mengirim pesan WhatsApp massal
- [API Reference](/api) — dokumentasi endpoint lengkap
