# Produktivitas Inbox


Halaman ini mencakup empat fitur pendukung yang membantu Anda bekerja lebih efisien di inbox:
bookmark pesan, snooze percakapan, pencarian tersimpan, dan pintasan keyboard.

## Bookmark percakapan

Bookmark memungkinkan Anda menandai pesan tertentu untuk ditemukan kembali dengan cepat.
Setiap bookmark terikat pada satu pesan (`message_id`) di dalam satu percakapan, dan hanya terlihat
oleh Anda — bukan agent lain.

**Rute frontend:** `/bookmarks`

### Cara menambahkan bookmark

Gunakan tombol bookmark pada konteks pesan di panel chat. Saat membuat bookmark, Anda
dapat menyertakan catatan pendek (`note`) untuk mengingatkan konteks pesan tersebut.

:::tip
Bookmark bersifat upsert: membookmark pesan yang sama dua kali hanya memperbarui catatan,
tidak membuat entri duplikat.
:::

### Halaman Bookmarks

Buka `/bookmarks` untuk melihat seluruh bookmark Anda lintas percakapan. Setiap kartu menampilkan:

- ID percakapan (8 karakter pertama) — klik untuk langsung membuka percakapan di inbox.
- Catatan (jika ada), atau teks _No note_ jika kosong.
- Timestamp waktu bookmark dibuat.

Klik ikon tempat sampah di kartu untuk menghapus bookmark.

### API yang digunakan

| Metode | Endpoint | Keterangan |
|--------|----------|------------|
| `GET` | `/api/bookmarks` | Daftar bookmark Anda; opsional filter `?conversation_id=` |
| `POST` | `/api/bookmarks` | Buat atau perbarui bookmark |
| `DELETE` | `/api/bookmarks/{id}` | Hapus bookmark |

Paginasi default: 50 item per halaman, maksimum 100 (`per_page`).

```json
{
  "conversation_id": "550e8400-e29b-41d4-a716-446655440000",
  "message_id": "wamid.abc123",
  "note": "Pelanggan minta callback jam 3 sore"
}
```

:::note
Anda hanya dapat menghapus bookmark milik sendiri. Backend memvalidasi `agent_id` sebelum
mengeksekusi `DELETE`.
:::

---

## Snooze percakapan

Snooze menyembunyikan percakapan dari inbox untuk sementara dan memunculkannya kembali
secara otomatis saat waktu yang ditentukan tiba.

### Cara snooze percakapan

1. Buka percakapan dari inbox.
2. Klik tombol **Snooze** di header percakapan (ikon jam).
3. Pilih salah satu preset atau atur waktu kustom:

| Preset | Waktu |
|--------|-------|
| 1 hour | 1 jam dari sekarang |
| 3 hours | 3 jam dari sekarang |
| Tomorrow 9am | Besok pukul 09:00 |
| Next Monday 9am | Senin depan pukul 09:00 |
| Custom… | Pilih tanggal dan waktu via `datetime-local` |

4. (Opsional) Tambahkan `reason` untuk mencatat alasan snooze.

:::warning
Nilai `snooze_until` harus di masa depan. Jika Anda memasukkan waktu yang sudah lewat,
server mengembalikan error `422 Unprocessable Entity`.
:::

### Membatalkan snooze lebih awal

Jika percakapan sudah ter-snooze, tombol **Snooze** berubah menjadi **Unsnooze** (ikon
jam dengan tanda silang). Klik tombol tersebut untuk mengembalikan percakapan ke status
open segera.

Badge amber `Snoozed until …` di header percakapan menampilkan sisa waktu hingga
percakapan bangun kembali.

### Halaman Snoozed Conversations

Buka `/conversations/snoozed` untuk melihat semua percakapan yang sedang di-snooze.
Halaman ini memperbarui countdown setiap detik secara real-time. Kartu ditampilkan dalam
urutan `snooze_until` terdekat lebih dulu.

Indikator warna countdown:
- **Biru** — lebih dari 1 jam tersisa.
- **Amber** — kurang dari 1 jam tersisa.
- Teks _Waking up…_ — waktu snooze sudah terlewat dan percakapan sebentar lagi muncul kembali.

### API yang digunakan

| Metode | Endpoint | Keterangan |
|--------|----------|------------|
| `POST` | `/api/conversations/{id}/snooze` | Snooze percakapan |
| `DELETE` | `/api/conversations/{id}/snooze` | Batalkan snooze aktif |
| `GET` | `/api/conversations/snoozed` | Daftar semua snooze aktif milik Anda |

```json
{
  "snooze_until": "2026-06-10T09:00:00Z",
  "reason": "Tunggu konfirmasi dari tim gudang"
}
```

:::note
Setiap percakapan hanya boleh memiliki satu snooze aktif. Snooze baru secara otomatis
menonaktifkan snooze sebelumnya pada percakapan yang sama.
:::

---

## Pencarian tersimpan

Pencarian tersimpan adalah filter inbox yang Anda beri nama dan simpan untuk digunakan
kembali kapan saja. Filter disimpan sebagai objek JSON bebas-bentuk (`filters`) sehingga
bisa menyimpan kombinasi parameter apapun.

**Rute frontend:** `/settings/saved-searches`

### Cara membuat pencarian tersimpan

1. Buka **Settings → Saved Searches**.
2. Klik **New Search**.
3. Isi nama dan definisikan filter dalam format JSON di textarea.
4. (Opsional) Centang **Set as default** agar pencarian ini aktif otomatis saat membuka inbox.
5. Klik **Save**.

:::note
Hanya satu pencarian tersimpan yang dapat ditetapkan sebagai default. Menetapkan default
baru secara otomatis menghapus flag default dari pencarian sebelumnya.
:::

### Mengelola pencarian tersimpan

Di halaman Settings → Saved Searches, setiap baris menampilkan:

- **Ikon bintang kuning** — pencarian ini adalah default; ikon kaca pembesar abu-abu berarti bukan default.
- **Nama** pencarian.
- **Jumlah filter** aktif (ditampilkan sebagai `n filters`).
- Tombol edit (pensil) dan hapus (tempat sampah).

### API yang digunakan

| Metode | Endpoint | Keterangan |
|--------|----------|------------|
| `GET` | `/api/saved-searches` | Daftar semua pencarian tersimpan Anda, urut nama |
| `POST` | `/api/saved-searches` | Buat pencarian baru |
| `PATCH` | `/api/saved-searches/{id}` | Perbarui nama, filter, atau status default |
| `DELETE` | `/api/saved-searches/{id}` | Hapus pencarian |

```json
{
  "name": "Open WhatsApp Urgent",
  "filters": {
    "status": "open",
    "channel": "whatsapp",
    "priority": "urgent"
  },
  "is_default": false
}
```

---

## Pintasan keyboard

OmniStream mendukung pintasan keyboard global yang dikelola oleh `shortcutStore`
(`frontend/src/lib/stores/shortcuts.svelte.ts`). Pintasan dikelompokkan dalam tiga
kategori: **General**, **Navigation**, dan **Conversation**.

:::tip
Pintasan dengan modifier (`Ctrl+K`) aktif bahkan saat kursor berada di dalam kotak input.
Pintasan huruf tunggal (`j`, `k`, dll.) otomatis dinonaktifkan saat Anda sedang mengetik
di input, textarea, atau elemen `contenteditable`.
:::

### General

| Kombinasi | Aksi |
|-----------|------|
| `Ctrl+K` | Buka modal pencarian (command palette) |
| `?` | Tampilkan daftar pintasan keyboard |
| `Escape` | Tutup modal / batalkan seleksi |

### Navigation

Pintasan navigasi menggunakan **sekuens dua tombol**: tekan `g`, lalu dalam 1 detik tekan
tombol kedua.

| Kombinasi | Aksi |
|-----------|------|
| `g` lalu `i` | Pergi ke Inbox (`/inbox`) |
| `g` lalu `c` | Pergi ke Contacts (`/contacts`) |
| `g` lalu `a` | Pergi ke Analytics (`/analytics`) |
| `g` lalu `d` | Pergi ke Dashboard (`/dashboard`) |
| `g` lalu `s` | Pergi ke Settings (`/settings`) |

### Conversation (aktif di halaman Inbox)

Pintasan berikut hanya terdaftar selama halaman `/inbox` terbuka dan akan dibatalkan
pendaftarannya secara otomatis saat meninggalkan halaman.

| Kombinasi | Aksi |
|-----------|------|
| `j` | Pilih percakapan berikutnya dalam daftar |
| `k` | Pilih percakapan sebelumnya dalam daftar |
| `Enter` | Buka percakapan yang sedang dipilih |
| `r` | Fokuskan kotak input balas pesan |
| `e` | Tandai percakapan aktif sebagai Resolved |

:::warning
Pintasan `e` (resolve) langsung mengirim request ke server tanpa konfirmasi. Pastikan
Anda memang ingin menyelesaikan percakapan sebelum menekannya.
:::
