XPrivate · admin-MVP-1 · Wireframes — Pricing Matrix + Approval Queue ALIGNED aligned 2026-05-31
Pricing source-of-truth → admin-mvp-1-pricing-base-override.html · model = Base + Override cascade (SubjectLevel ?? Subject ?? Base) · Stack: React 19 + TanStack Start (SPA) · shadcn amber b1MJ9vRwY6

XPrivate Admin-MVP-1 — Wireframe Preview v4 · Base+Override

Mockup mid-fidelity 2 heavy screens · v4 reshape Pricing ke Base + Override cascade (per-subject matrix lama di-drop) · Approval Queue unchanged dari v2 (P0/P1/P2 fixes) · Tailwind v4 light mode · Indonesian UX · WIB locale

v3 → v4 (Pricing reshape ke Base + Override cascade 2026-05-31)

Lock doc: ~/Documents/Obsidian Vault/XPrivate/Projects/admin-mvp-1/pricing-implementation-lock.md · detail effective+bulk: admin-mvp-1-pricing-effective-bulk-preview.html

Wireframe 1 / 10 · v4

Pricing — Harga Dasar + Override

Route: /pricing/base & /pricing/subject/:subject_id · Model: Base + Override cascade (SubjectLevel ?? Subject ?? Base) · Role: ADMIN

Harga Dasar + Override

Cascade SubjectLevel ?? Subject ?? Base · sebagian besar mata pelajaran mewarisi Harga Dasar (nol kerja) · hanya yang khusus di-override.

Matriks Harga Dasar

subject-agnostic

Harga dasar per Tingkat × Segmentasi. Semua mata pelajaran memakai ini secara default. Klik sel untuk mengubah Harga Dasar.

Audiens:
Golongan (honor tutor):GOL 1 ▾
SegmentasiSD 1-6SMP 7-9SMA 10-12MahasiswaUmumProfesional
REGRp 130.000Rp 150.000Rp 170.000Rp 175.000Rp 180.000Rp 200.000
REG+Rp 180.000Rp 200.000Rp 220.000Rp 225.000Rp 230.000Rp 250.000
INTRp 230.000Rp 250.000Rp 270.000Rp 275.000Rp 280.000Rp 300.000

Harga Dasar = satu sumber kebenaran. 6 Tingkat × 3 Segmentasi. Honor tutor diturunkan via Golongan (GOL 1/2/3). Ubah Harga Dasar → otomatis berlaku ke semua mata pelajaran yang mewarisi. Effective-dated (late-bind di billing).


Harga per Mata Pelajaran

override + ditawarkan ke
Mata Pelajaran:
Ditawarkan ke default: semua OFF (opt-in)
SD 1-6 SMP 7-9 SMA 10-12 Mahasiswa Umum Profesional

Kategori PROGRAM_KHUSUS · ditawarkan ke 3 Tingkat · sel kuning = Harga Khusus (override), sel abu = mewarisi Harga Dasar.

SegmentasiSD 1-6SMP 7-9SMA 10-12MahasiswaUmumProfesional
REG tidak ditawarkan tidak ditawarkan Rp 170.000dasar Rp 175.000dasar Rp 250.000dasar Rp 180.000 tidak ditawarkan
REG+ tidak ditawarkan tidak ditawarkan Rp 220.000dasar Rp 225.000dasar Rp 230.000dasar tidak ditawarkan
INT tidak ditawarkan tidak ditawarkan Rp 300.000dasar Rp 270.000 Rp 275.000dasar Rp 280.000dasar tidak ditawarkan
mewarisi Harga Dasar (abu, redup) Harga Khusus / override (kuning, tebal) tidak ditawarkan (toggle OFF)

Resolusi tiap sel: Harga Khusus (override) ?? Harga Dasar. Cell ini punya 2 override (INT · SMA, REG · Umum), sisanya mewarisi dasar. Klik sel yang ditawarkan → ubah jadi Harga Khusus; klik lagi → kembali ke Harga Dasar. Toggle "ditawarkan ke" di atas menggeser kolom ditawarkan/tidak.

2 perubahan belum disimpan
💡 Klik sel di Harga Dasar → ubah harga dasar · klik sel ditawarkan di Harga per Mapel → toggle override · ⌘S simpan.

Komponen Kunci · v4 (synced ke canonical Base + Override)

Harga Dasar (subject-agnostic)

Satu matriks Tingkat × Segmentasi (+ Golongan untuk honor tutor), di-set sekali. Semua mata pelajaran mewarisi ini. base_price = sumber kebenaran. Ubah dasar → kena semua yang inherit.

Override sparse (absolut, iter-1)

Hanya sel yang beda dari dasar yang disimpan (subject_price_override, sparse). Kuning+tebal = Harga Khusus, menampilkan harga dasar yang digantikan. Klik untuk override / batalkan. Mapel umum = nol override.

Applicability (ditawarkan ke)

subject_offer terpisah dari harga, default OFF (opt-in per Tingkat). Tingkat yang tidak ditawarkan = hatch, tidak dihargai. Toggle independen dari override.

Cascade resolution

SubjectLevel ?? Subject ?? Base. Sel abu = mewarisi dasar (tag "dasar"). SubjectLevel (mis. HSK) menimpa Subject, Subject menimpa Base. Tingkat ≠ SubjectLevel ≠ Kategori (grouping, bukan harga).

📊 Matriks (Stripe-anchor)

Sticky header + first col. tabular-nums. AAA contrast angka. Hover outline pada sel yang dapat diedit.

💾 Dirty-cue + escape guard

Sel berubah = highlight + dot. Save bar hitung yang belum disimpan. beforeunload warning saat keluar. Manual Simpan (⌘S), bukan autosave.

Terminologi BI

Harga Dasar (base) · Harga Khusus/Override · Mata Pelajaran · Tingkat · Segmentasi (REG/REG+/INT) · Golongan · "ditawarkan ke". Mata uang Rp 150.000.

⏰ Effective-dating (LATE-BIND)

Harga + kebijakan pembatalan late-bind di billing. Harga Dasar & override effective-dated; carry-forward sampai diubah.

Locked Decisions

  • Model = Base + Override cascade (SubjectLevel ?? Subject ?? Base) — canonical admin-mvp-1-pricing-base-override.html
  • Harga Dasar subject-agnostic (Tingkat × Segmentasi + Golongan), di-set sekali
  • Override sparse + absolut (iter-1) · hanya simpan sel yang beda dari dasar
  • Applicability (subject_offer) terpisah dari harga · default OFF (opt-in)
  • Harga + cancel-policy LATE-BIND di billing · effective-dated carry-forward
  • Override relatif (% dari dasar) — iter-2 kalo pola override konsisten
  • SubjectLevel matrix (mis. HSK 1-6) sebagai layer ke-3 — saat subject ber-level masuk
Wireframe 2 / 10 · v2

Antrian Persetujuan Sesi (Approval Queue)

Route: /schedule/approval-queue · Recipe: A + Linear-anchor · Speed: Single <5s · Bulk 10 <15s · Role: ADMIN, OPS

Antrian Persetujuan 3 menunggu

Sesi REQUESTED menunggu disetujui / ditolak · ditandai SLA bila >24 jam

TenggatTanggal & LokasiTutorSiswaMata PelajaranAksi
⚠ 26j
28 Mei 2026 · 19:00 WIB
📍 Rumah siswa · Jl. Cikini 5
Budi Santoso
GOL_2 · 12,4 km
Andi Rahman
SMP 8 · Reguler+
Bahasa Mandarin
HSK 2
18j
28 Mei 2026 · 16:00 WIB✓ Tekan A lagi untuk konfirmasi · 1.5s
📍 Rumah siswa · Jl. Kemang Raya 12
Sari Maharani
GOL_1 · 5,2 km
Putri Damayanti
SD 5 · Reguler
Piano
Grade 3
12j
29 Mei 2026 · 09:00 WIB
📍 Online (Zoom manual)
Dedi Kurniawan
GOL_3 · online
Reza Aditya
Umum · Internasional
CPNS Bimbel
1 sesi dipilih
Menampilkan 3 dari 3 antrian · halaman tampil bila >50 sesi

Komponen Kunci · v2 (unchanged)

P0-1: Arm-then-commit

Press A → armed (green glow + "Tekan A lagi" + 1.5s decay). Press A again → commit. Bulk (Space-select) = single-keystroke OK. Row 2 = armed demo.

P1-1: Bulk bar bottom-of-viewport

position fixed, Linear pattern. Count selalu visible.

P1-2: Row indicators orthogonal

SLA = left-border amber · focus = inset shadow · selected = bg+checkbox. No collision.

WhatsApp embed cue

💬 button = one-tap WA tutor pre-filled sesi context. Saves copy-paste cycle.

🏷 Quick filter chips

1-tap common cases. SLA Pending = amber.

↩ Sonner undo 5s + Honor removed

Undo after commit. Honor preview removed (privacy boundary, Q5).

Keyboard Shortcuts (arm-then-commit)

J/KNext/prev row focus
SpaceToggle select (bulk mode)
AAArm → confirm approve (single, 1.5s decay)
XXArm → confirm reject
A (bulk)Approve selected (Space = arming step, single OK)
EnterOpen detail · Esc cancel/clear · ⌘/ search · R refresh · ? cheatsheet

Locked Decisions

  • P0-1 arm-then-commit · P1-1 fixed bulk bar · P1-2 orthogonal indicators
  • WhatsApp cue · SLA-top sort · 24h threshold config · undo 5s · saved filters
  • Q5 Honor preview removed (privacy)
  • Per-user "confirm destructive" toggle iter-2
  • Shortcut index: ? icon → Dialog cheatsheet + optional /settings/keyboard-shortcuts page