E-Commerce & Business System β platform produksi untuk SAMAQU, brand pakaian muslim pria (Thobe Β· Kandora Β· Koko Β· Vest Β· Kabak Β· Cover & Hanger).
Live: https://www.samaqu.id/
SAMAQU adalah satu sistem yang melayani tiga sisi sekaligus: storefront untuk pelanggan, dashboard admin untuk operasional penjualan, dan dashboard ops untuk CRM, stok, dan follow-up. Semuanya berbagi satu sumber data di Supabase (PostgreSQL) β tidak ada duplikasi aturan bisnis antar sisi.
| Sisi | Untuk | Isi utama |
|---|---|---|
| ποΈ Storefront | Pelanggan | Katalog, Create Your Price, Open Order, keranjang, checkout, akun & lacak pesanan, halaman konten, live chat AI |
| π§πΌ Admin | Pemilik / admin | Pesanan (termasuk resi J&T & label), produk, Open Order, pelanggan, live chat, voucher, seluruh konten website, pengaturan |
| π Ops | Tim operasional | Leads & follow-up (CRM), pelanggan, produk & stok, pembelian, laporan |
| Fitur | Kenapa Istimewa |
|---|---|
| Hierarchical catalog | Taksonomi Kategori β Jenis Kain β Series β Produk/Varian (warna Γ ukuran), lengkap dengan media per varian |
| Create Your Price (CYP) | Pelanggan menentukan harganya sendiri; divalidasi ulang di server terhadap harga minimum di database β harga dari klien tidak pernah dipercaya |
| Open Order wizard | Alur 6 langkah terpisah dengan harga minimum per series, memotong stok yang sama dengan katalog, dan wajib punya akun |
| Atomic stock | samaqu_decrement_stock dengan row-lock; kalau ada satu item gagal, semua decrement di-rollback |
| Status pesanan β status pengiriman | orders.status dan orders.shipping_status dipisah; resi terbit β paket berangkat |
| J&T lifecycle penuh | Tariff, Order (AWB), Cancel (void), Track β dengan pemetaan 7.128 baris area |
| RajaOngkir V2 | Ongkir + pencarian tujuan dengan caching bertingkat |
| Live Chat AI | Asisten AI (Xiaomi MiMo) di storefront, dengan log & pengaturan dari admin |
| CRM internal | Leads, Follow-up Center, dan sinkronisasi otomatis order β lead |
| Shared admin & ops | Pusat data pelanggan, aturan urutan, dan filter β satu modul, dua dashboard |
| Halaman / Fitur | Rute | Keterangan |
|---|---|---|
| Home | / |
Hero, koleksi, jaminan, testimoni, Instagram |
| Katalog | /katalog |
Daftar produk lintas kategori + filter jenis kain |
| Detail produk | /katalog/[id] |
Galeri per varian, pemilih warna/series/ukuran, harga minimum (CYP) |
| Create Your Price | /create-your-price |
Halaman promo + alur CYP |
| Open Order | /open-order |
Wizard 6 langkah: produk β detail β keranjang β data pemesan β review β sukses |
| Keranjang | /cart |
State keranjang + add-on Cover & Hanger |
| Checkout | /checkout |
Multi-langkah: alamat tersimpan/manual, ongkir otomatis, voucher, metode pembayaran |
| Sukses | /checkout/success |
Nomor pesanan + status "Menunggu Konfirmasi Admin" |
| Akun & pesanan | /akun, /akun/pesanan, /akun/pesanan/[no], .../lacak |
Dashboard, daftar pesanan (tab Semua/Belum Bayar/Diproses/Dikirim/Selesai), detail bergaya marketplace, lacak paket |
| Alamat & profil | /akun/alamat, /akun/profil |
Alamat tersimpan (kota/kecamatan RajaOngkir), profil read-only + Edit |
| Wishlist | /akun/wishlist |
Produk favorit |
| Konten | /tentang-kami, /faq, /panduan-ukuran, /testimoni, /cara-pesan, /garansi-retur, /sama-quran, /bio |
Halaman konten yang diatur dari admin |
| Live Chat AI | widget | Asisten AI + eskalasi ke WhatsApp toko |
- Dwibahasa (ID / EN) lewat
next-intl. - Meta Pixel + CAPI β ViewContent, AddToCart, InitiateCheckout, Purchase.
- Nav bawah ala aplikasi di mobile (Beranda Β· Kategori Β· Open Order Β· Pesanan Β· Akun).
Tiga grup menu di sidebar:
Menu Utama β Dashboard Β· Order Management Β· Open Order Β· Produk Β· Pelanggan Β· Live Chat Konten β Konten Website Β· Biolink Β· Foto Carousel Β· Testimoni Β· Panduan Ukuran Β· Halaman Garansi & Retur Lainnya β Voucher Β· Pengaturan
- Daftar pesanan ala Shopee Seller Centre: sub-tab Pesanan Website / Open Order, kotak cari, dan tahap Semua Β· Belum Bayar Β· Perlu Dikirim Β· Dikirim Β· Selesai Β· Dibatalkan.
- Drawer detail pesanan berisi banner status β Info Pengiriman (kurir + nomor resi + status pengiriman) β Metode Pembayaran β Alamat β produk β Total β linimasa status β aksi.
- Atur Pesanan menerbitkan resi J&T (khusus status
diproses), Lacak Paket menyinkronkan tracking dari J&T, Batalkan J&T mem-void resi, Cetak Label membuka/admin/label/[orderNumber]. - Aksi hanya ada di drawer detail (tabel daftar tetap bersih).
- Form produk bersama (tambah/edit) dengan grid ukuran, SKU per ukuran, berat per size, dan toggle Tampilkan di Open Order.
- Drawer detail produk: stok & SKU per varian, harga, riwayat penjualan.
- CMS konten: hero, koleksi, testimoni, panduan ukuran, biolink, foto carousel, halaman garansi & retur.
- Voucher: diskon persen/nominal, minimal belanja, batas pemakaian, dan batas per nomor WhatsApp.
Dashboard terpisah (/ops) untuk tim operasional:
| Menu | Isi |
|---|---|
| Dashboard | Ringkasan penjualan, tren harian, stok menipis |
| Leads / Laporan Leads | Daftar lead + statistik konversi, closing, nominal |
| Follow-up | Follow-up Center: Perlu Dijadwalkan Β· Hari Ini Β· Terlambat Β· Riwayat |
| Pelanggan | Pusat data pelanggan (modul yang sama dengan admin) |
| Produk | Master produk & stok, barang masuk/keluar, rekap pembelian |
Order baru tidak membuat lead baru. Kalau nomor order cocok dengan lead aktif, lead itu otomatis ditandai
closing+outcome: buy(src/lib/ops-lead-sync.ts) β idempoten.
| Layanan | Fungsi | Auth |
|---|---|---|
| Supabase (PostgreSQL) | Seluruh data + Auth | anon key (publik) & service role (server-only) |
| J&T Express | Tariff, Order/AWB, Cancel, Track | Signature base64(md5(data + key)) (order/tariff/cancel) & Basic Auth (track) |
| RajaOngkir V2 | Ongkir + pencarian tujuan (cached) | API key (DB, env sebagai fallback) |
| Cloudinary | Media produk & konten (+ akun terpisah untuk gambar live chat) | signed upload |
| Fonnte | Notifikasi WhatsApp ke admin saat ada pesanan baru | token (DB/env) |
| Xiaomi MiMo | Asisten Live Chat AI (OpenAI-compatible) | API key (DB/env) |
| Meta Pixel + CAPI | Tracking event e-commerce | Pixel ID + access token |
Nama wilayah RajaOngkir diterjemahkan ke kode internal J&T lewat dataset 7.128 baris
(src/lib/jnt/area-data.json), dengan fallback bertingkat: kecamatan+kota β kecamatan β kota.
Tanpa webhook dari J&T β sinkronisasi memakai polling dari penjadwal eksternal
(cron-job.org), diakses dengan header Authorization: Bearer $CRON_SECRET:
| Endpoint | Fungsi | Jadwal saran |
|---|---|---|
GET /api/cron/sync-tracking |
Tarik tracking J&T β naikkan status (dikirim) & tandai selesai saat paket diterima |
tiap jam |
GET /api/cron/auto-cancel |
Reminder pembayaran (jendela 20β24 jam, sekali per pesanan) + batalkan pesanan yang melewati batas pembayaran | tiap jam |
stateDiagram-v2
[*] --> pending: checkout / open order
pending --> diproses: pembayaran diverifikasi admin
diproses --> diproses: "Atur Pesanan" terbitkan resi
diproses --> dikirim: J&T memindai paket
dikirim --> selesai: paket diterima penerima
pending --> dibatalkan
diproses --> dibatalkan
Dua status yang dipisah (orders.status vs orders.shipping_status):
| Nilai | |
|---|---|
orders.status |
pending β diproses β dikirim β selesai (+ dibatalkan) |
orders.shipping_status |
NULL (belum ada resi) β menunggu_pickup β dikirim β selesai |
- Resi diterbitkan admin lewat Atur Pesanan, bukan saat checkout (
awb_noawalnyanull). - Nomor pesanan:
SMQ-(checkout website) danCYO-(Open Order). - Stok: dipotong atomik sebelum pesanan ditulis, dengan rollback bila ada yang gagal;
dikembalikan saat pembatalan hanya jika
orders.stock_reservedbernilai true. - Satu jalur pembatalan β
cancelOrderCompletely(): void resi J&T β kembalikan stok β statusdibatalkan.
flowchart TB
C[Pelanggan] --> SF[Storefront]
A[Admin] --> AD[Admin Dashboard]
O[Ops] --> OP[Ops Dashboard]
SF --> API[API Routes]
AD --> API
OP --> API
API --> DB[(Supabase / PostgreSQL)]
API --> JNT[J&T Express API]
API --> RO[RajaOngkir API]
API --> CL[Cloudinary]
API --> AI[Live Chat AI]
API --> FN[Fonnte]
CRON[Penjadwal eksternal] --> API
| Layer | Isi |
|---|---|
| Presentation | Next.js App Router, React 19, Tailwind 4, Framer Motion |
| Application | API Routes (validasi bisnis & integrasi) |
| Data | Supabase / PostgreSQL (+ RLS) |
| External | J&T, RajaOngkir, Cloudinary, Fonnte, MiMo, Meta |
| Auth | Supabase Auth β sesi admin & pelanggan dipisah |
| Kategori | Teknologi |
|---|---|
| Framework | Next.js 16 (App Router, Turbopack) |
| UI | React 19, Tailwind CSS 4, Framer Motion, Radix/Ark/Base UI, Lucide + Phosphor |
| Data | Supabase (PostgreSQL), @supabase/supabase-js |
| Data fetching | TanStack Query |
| Chart | Recharts |
| PDF / Barcode | pdf-lib, pdfjs-dist, jsbarcode |
| i18n | next-intl (ID/EN) |
| Deploy | Vercel |
- Harga CYP divalidasi di server β harga minimum selalu dibaca dari database.
- Ongkir tidak dipercaya dari klien β dihitung/diverifikasi lewat API.
- Stok atomik dengan row-lock + rollback.
- Kredensial sensitif hanya di server β service role key, kredensial J&T, token Fonnte, dan API key live chat tidak pernah dikirim ke browser (tabel pengaturan bersifat service-role-only).
- Admin & ops diverifikasi lewat tabel
admins+ sesi Supabase. - Rahasia tidak ada di repo β
.env*di-.gitignore, tidak ada token di kode maupun riwayat commit.
src/
βββ app/
β βββ (customer)/ # Storefront (root, redirect ke /<locale>)
β βββ [locale]/ # Storefront + akun pelanggan (ID/EN)
β β βββ (customer)/ # katalog, cart, checkout, open-order, kontenβ¦
β β βββ akun/ # dashboard pelanggan, pesanan, lacak, alamat, profil
β β βββ admin/ # salinan subhalaman admin (route /admin juga ada)
β βββ admin/ # Dashboard admin (+ label, produk, konten, voucherβ¦)
β βββ ops/ # Dashboard ops (leads, follow-up, pelanggan, stok)
β βββ api/ # API routes
β βββ admin/ # orders, customers, chat/fonnte/jnt settings
β βββ ops/ # leads, followups, customers, products, stock-in
β βββ jnt/ # track, mapping, test
β βββ shipping/ # cost, jnt-cost, provinces, districts, search
β βββ cron/ # sync-tracking, auto-cancel
β βββ orders/, open-order/, chat/, cloudinary/, meta-events/
βββ components/ # UI (admin/, ops/, akun/, open-order/β¦)
βββ lib/ # Logika bisnis & integrasi (jnt/, cancel-order, order-flowβ¦)
βββ i18n/ # Pesan ID/EN
βββ middleware.ts # Routing locale
supabase/ # SQL migrasi (dijalankan manual) + RPC stok
public/ # Aset statis
# ββ Supabase (wajib) ββ
NEXT_PUBLIC_SUPABASE_URL=
NEXT_PUBLIC_SUPABASE_ANON_KEY=
SUPABASE_SERVICE_ROLE_KEY= # atau SUPABASE_SECRET_KEY
# ββ J&T Express ββ
JNT_ENV=production
JNT_ORDER_USERNAME=
JNT_ORDER_API_KEY=
JNT_ORDER_KEY=
JNT_TARIFF_KEY=
JNT_TARIFF_CUS_NAME=
JNT_TRACK_USERNAME=
JNT_TRACK_PASSWORD=
JNT_COMPANY_ID=
# ββ RajaOngkir (tersimpan di DB, env sebagai fallback) ββ
RAJAONGKIR_API_KEY=
# ββ Cloudinary (upload bertanda tangan) ββ
NEXT_PUBLIC_CLOUDINARY_CLOUD=
CLOUDINARY_API_KEY=
CLOUDINARY_API_SECRET=
# ββ Cloudinary khusus gambar live chat (opsional; kosong = ikut akun di atas) ββ
CHAT_CLOUDINARY_CLOUD=
CHAT_CLOUDINARY_API_KEY=
CHAT_CLOUDINARY_API_SECRET=
# ββ Meta Pixel ββ
NEXT_PUBLIC_META_PIXEL_ID=
META_ACCESS_TOKEN=
META_TEST_EVENT_CODE=
# ββ Fonnte β notifikasi WhatsApp ke admin ββ
FONNTE_TOKEN=
ADMIN_WHATSAPP_NUMBER= # boleh beberapa, dipisah koma
# ββ Live Chat AI β Xiaomi MiMo (bisa juga diatur dari admin) ββ
MIMO_API_KEY=
MIMO_MODEL=mimo-v2.6-flash
MIMO_BASE_URL=https://api.xiaomimimo.com/v1
# ββ Internal ββ
CRON_SECRET=
REVALIDATE_SECRET=
NEXT_PUBLIC_SITE_URL=
NEXT_PUBLIC_*di-inline saat build β pastikan sudah diisi sebelum deploy.
npm install
npm run dev # http://localhost:3000
npm run build- Database: proyek ini memakai Supabase ter-hosting. File di
supabase/*.sql(skema, kolom baru, RPC stok, tabel pengaturan) dijalankan manual di SQL Editor Supabase. - Deploy: Vercel β import repo ini, isi environment variables, deploy.
- Cron: daftarkan
/api/cron/sync-tracking&/api/cron/auto-canceldi penjadwal eksternal (mis. cron-job.org) dengan headerAuthorization: Bearer <CRON_SECRET>. - Domain: pasang di Vercel β Settings β Domains (apex
A 76.76.21.21, subdomainCNAME cname.vercel-dns.com).
Private β SAMAQU Business System. All rights reserved.