84 lines
30 KiB
JavaScript
84 lines
30 KiB
JavaScript
import{c as e,d as t,n,t as r}from"./app-C2kGDHB9.js";import{t as i}from"./AuthenticatedLayout-C8h2HS7D.js";var a=t(e(),1),o=r(),s=[{id:`intro`,label:`Pendahuluan`,icon:(0,o.jsx)(`svg`,{className:`w-4 h-4`,fill:`none`,viewBox:`0 0 24 24`,stroke:`currentColor`,strokeWidth:2.5,children:(0,o.jsx)(`path`,{strokeLinecap:`round`,strokeLinejoin:`round`,d:`M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z`})})},{id:`quickstart`,label:`Quick Start`,icon:(0,o.jsx)(`svg`,{className:`w-4 h-4`,fill:`none`,viewBox:`0 0 24 24`,stroke:`currentColor`,strokeWidth:2.5,children:(0,o.jsx)(`path`,{strokeLinecap:`round`,strokeLinejoin:`round`,d:`M13 10V3L4 14h7v7l9-11h-7z`})})},{id:`stack`,label:`Tech Stack`,icon:(0,o.jsx)(`svg`,{className:`w-4 h-4`,fill:`none`,viewBox:`0 0 24 24`,stroke:`currentColor`,strokeWidth:2.5,children:(0,o.jsx)(`path`,{strokeLinecap:`round`,strokeLinejoin:`round`,d:`M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10`})})},{id:`auth`,label:`Autentikasi`,icon:(0,o.jsx)(`svg`,{className:`w-4 h-4`,fill:`none`,viewBox:`0 0 24 24`,stroke:`currentColor`,strokeWidth:2.5,children:(0,o.jsx)(`path`,{strokeLinecap:`round`,strokeLinejoin:`round`,d:`M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z`})})},{id:`roles`,label:`Roles & Permission`,icon:(0,o.jsx)(`svg`,{className:`w-4 h-4`,fill:`none`,viewBox:`0 0 24 24`,stroke:`currentColor`,strokeWidth:2.5,children:(0,o.jsx)(`path`,{strokeLinecap:`round`,strokeLinejoin:`round`,d:`M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z`})})},{id:`features`,label:`Fitur Lengkap`,icon:(0,o.jsx)(`svg`,{className:`w-4 h-4`,fill:`none`,viewBox:`0 0 24 24`,stroke:`currentColor`,strokeWidth:2.5,children:(0,o.jsx)(`path`,{strokeLinecap:`round`,strokeLinejoin:`round`,d:`M4 6h16M4 10h16M4 14h16M4 18h7`})})},{id:`api`,label:`REST API`,icon:(0,o.jsx)(`svg`,{className:`w-4 h-4`,fill:`none`,viewBox:`0 0 24 24`,stroke:`currentColor`,strokeWidth:2.5,children:(0,o.jsx)(`path`,{strokeLinecap:`round`,strokeLinejoin:`round`,d:`M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z`})})},{id:`2fa`,label:`Two-Factor Auth`,icon:(0,o.jsx)(`svg`,{className:`w-4 h-4`,fill:`none`,viewBox:`0 0 24 24`,stroke:`currentColor`,strokeWidth:2.5,children:(0,o.jsx)(`path`,{strokeLinecap:`round`,strokeLinejoin:`round`,d:`M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1121 9z`})})},{id:`settings`,label:`System Settings`,icon:(0,o.jsxs)(`svg`,{className:`w-4 h-4`,fill:`none`,viewBox:`0 0 24 24`,stroke:`currentColor`,strokeWidth:2.5,children:[(0,o.jsx)(`path`,{strokeLinecap:`round`,strokeLinejoin:`round`,d:`M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z`}),(0,o.jsx)(`path`,{strokeLinecap:`round`,strokeLinejoin:`round`,d:`M15 12a3 3 0 11-6 0 3 3 0 016 0z`})]})},{id:`structure`,label:`Struktur Folder`,icon:(0,o.jsx)(`svg`,{className:`w-4 h-4`,fill:`none`,viewBox:`0 0 24 24`,stroke:`currentColor`,strokeWidth:2.5,children:(0,o.jsx)(`path`,{strokeLinecap:`round`,strokeLinejoin:`round`,d:`M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z`})})}];function c({children:e,color:t=`gray`}){return(0,o.jsx)(`span`,{className:`inline-flex items-center px-2.5 py-0.5 rounded-lg text-[10px] font-bold uppercase tracking-widest ${{green:`bg-emerald-50 text-emerald-700 border border-emerald-200`,blue:`bg-blue-50 text-blue-700 border border-blue-200`,amber:`bg-amber-50 text-amber-700 border border-amber-200`,red:`bg-red-50 text-red-700 border border-red-200`,gray:`bg-gray-50 text-gray-600 border border-gray-200`,purple:`bg-purple-50 text-purple-700 border border-purple-200`}[t]}`,children:e})}function l({children:e,lang:t=`bash`}){let[n,r]=(0,a.useState)(!1);return(0,o.jsxs)(`div`,{className:`relative group mt-3`,children:[(0,o.jsxs)(`div`,{className:`flex items-center justify-between bg-[#1E2A28] rounded-t-xl px-4 py-2 border-b border-white/5`,children:[(0,o.jsx)(`span`,{className:`text-[10px] text-gray-400 font-mono font-bold uppercase tracking-widest`,children:t}),(0,o.jsx)(`button`,{onClick:()=>{navigator.clipboard.writeText(e),r(!0),setTimeout(()=>r(!1),2e3)},className:`text-[10px] text-gray-400 font-bold hover:text-white transition-colors`,children:n?`✓ Copied`:`Copy`})]}),(0,o.jsx)(`pre`,{className:`bg-[#152320] text-emerald-300 text-xs font-mono p-4 rounded-b-xl overflow-x-auto leading-relaxed`,children:(0,o.jsx)(`code`,{children:e})})]})}function u({id:e,title:t,badge:n,badgeColor:r}){return(0,o.jsxs)(`div`,{id:e,className:`flex items-center gap-3 mb-6 pt-2 scroll-mt-6`,children:[(0,o.jsx)(`h2`,{className:`text-base font-black text-[#3D4E4B] dark:text-white tracking-tight`,children:t}),n&&(0,o.jsx)(c,{color:r,children:n}),(0,o.jsx)(`div`,{className:`flex-1 h-px bg-gray-100 dark:bg-white/10`})]})}function d({method:e,path:t,desc:n,auth:r=!0}){return(0,o.jsxs)(`div`,{className:`flex items-center gap-3 py-3 border-b border-gray-50 last:border-0`,children:[(0,o.jsx)(`span`,{className:`shrink-0 px-2.5 py-1 rounded-lg text-[10px] font-black tracking-widest uppercase ${{GET:`bg-blue-100 text-blue-700`,POST:`bg-emerald-100 text-emerald-700`,PATCH:`bg-amber-100 text-amber-700`,DELETE:`bg-red-100 text-red-700`,PUT:`bg-purple-100 text-purple-700`}[e]??`bg-gray-100 text-gray-600`}`,children:e}),(0,o.jsx)(`code`,{className:`flex-1 text-xs font-mono text-[#3D4E4B] font-bold`,children:t}),(0,o.jsx)(`span`,{className:`text-xs text-gray-400 font-medium hidden md:block`,children:n}),r&&(0,o.jsx)(`span`,{className:`shrink-0 text-[10px] text-amber-600 font-bold`,children:`🔒 Auth`})]})}function f(){let[e,t]=(0,a.useState)(`intro`),r=(0,a.useRef)(null);(0,a.useEffect)(()=>{let e=s.map(e=>e.id),n=new IntersectionObserver(e=>{let n=e.filter(e=>e.isIntersecting).sort((e,t)=>e.boundingClientRect.top-t.boundingClientRect.top);n.length>0&&t(n[0].target.id)},{rootMargin:`-20% 0px -70% 0px`,threshold:0});return e.forEach(e=>{let t=document.getElementById(e);t&&n.observe(t)}),()=>n.disconnect()},[]);let f=e=>{document.getElementById(e)?.scrollIntoView({behavior:`smooth`,block:`start`})};return(0,o.jsxs)(i,{children:[(0,o.jsx)(n,{title:`Dokumentasi biiproject kit v2`}),(0,o.jsxs)(`div`,{className:`flex items-center justify-between mb-8 anim-down`,children:[(0,o.jsxs)(`div`,{children:[(0,o.jsx)(`h1`,{className:`text-xl font-bold text-[#3D4E4B] dark:text-white tracking-tight leading-none`,children:`Dokumentasi`}),(0,o.jsx)(`p`,{className:`text-sm font-semibold text-gray-400 tracking-tight mt-2`,children:`Panduan lengkap biiproject kit v2`})]}),(0,o.jsx)(c,{color:`green`,children:`v2.0`})]}),(0,o.jsxs)(`div`,{className:`flex gap-8 anim-up`,children:[(0,o.jsx)(`aside`,{className:`hidden lg:block w-52 shrink-0`,children:(0,o.jsx)(`div`,{className:`sticky top-6 bg-white dark:bg-[#1A2120] rounded-2xl border border-gray-100 dark:border-white/10 shadow-sm p-3 space-y-0.5`,children:s.map(t=>(0,o.jsxs)(`button`,{onClick:()=>f(t.id),className:`w-full flex items-center gap-3 px-3 py-2.5 rounded-xl text-xs font-bold text-left transition-all ${e===t.id?`bg-[#3D4E4B] text-white`:`text-gray-500 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-white/5 hover:text-[#3D4E4B] dark:hover:text-white`}`,children:[(0,o.jsx)(`span`,{className:`shrink-0 ${e===t.id?`text-[#D4A017]`:``}`,children:t.icon}),t.label]},t.id))})}),(0,o.jsxs)(`div`,{ref:r,className:`flex-1 min-w-0 space-y-12 pb-20`,children:[(0,o.jsxs)(`section`,{children:[(0,o.jsx)(u,{id:`intro`,title:`Pendahuluan`,badge:`Starter Kit`,badgeColor:`blue`}),(0,o.jsxs)(`div`,{className:`bg-white dark:bg-[#1A2120] rounded-2xl border border-gray-100 dark:border-white/10 shadow-sm p-8 space-y-4`,children:[(0,o.jsxs)(`p`,{className:`text-sm text-gray-600 dark:text-gray-300 font-medium leading-relaxed`,children:[(0,o.jsx)(`strong`,{className:`text-[#3D4E4B] dark:text-white`,children:`biiproject kit v2`}),` adalah starter kit enterprise berbasis `,(0,o.jsx)(`strong`,{children:`Laravel 13 + React (Inertia.js)`}),` yang dirancang untuk mempercepat pembangunan aplikasi web dengan fitur manajemen pengguna, hak akses berbasis peran, monitoring aktivitas, notifikasi, dan konfigurasi sistem yang lengkap.`]}),(0,o.jsx)(`div`,{className:`grid grid-cols-2 md:grid-cols-4 gap-4 pt-2`,children:[{label:`Users & Roles`,icon:`👥`},{label:`Activity Logs`,icon:`📋`},{label:`System Settings`,icon:`⚙️`},{label:`Two-Factor Auth`,icon:`🔒`},{label:`REST API v1`,icon:`🔌`},{label:`Dark Mode`,icon:`🌙`},{label:`Notifikasi`,icon:`🔔`},{label:`Mobile Ready`,icon:`📱`}].map(e=>(0,o.jsxs)(`div`,{className:`p-4 bg-gray-50 dark:bg-white/5 rounded-xl text-center`,children:[(0,o.jsx)(`div`,{className:`text-2xl mb-1`,children:e.icon}),(0,o.jsx)(`div`,{className:`text-[11px] font-bold text-[#3D4E4B] dark:text-white`,children:e.label})]},e.label))})]})]}),(0,o.jsxs)(`section`,{children:[(0,o.jsx)(u,{id:`quickstart`,title:`Quick Start`,badge:`Setup`,badgeColor:`green`}),(0,o.jsxs)(`div`,{className:`bg-white dark:bg-[#1A2120] rounded-2xl border border-gray-100 dark:border-white/10 shadow-sm p-8 space-y-6`,children:[(0,o.jsxs)(`div`,{children:[(0,o.jsx)(`h3`,{className:`text-xs font-black text-[#3D4E4B] dark:text-white uppercase tracking-widest mb-2`,children:`1. Clone & Install`}),(0,o.jsx)(l,{lang:`bash`,children:`git clone https://github.com/your-org/biiskit.git
|
|
cd biiskit
|
|
composer install
|
|
npm install`})]}),(0,o.jsxs)(`div`,{children:[(0,o.jsx)(`h3`,{className:`text-xs font-black text-[#3D4E4B] dark:text-white uppercase tracking-widest mb-2`,children:`2. Konfigurasi Environment`}),(0,o.jsx)(l,{lang:`bash`,children:`cp .env.example .env
|
|
php artisan key:generate
|
|
|
|
# Edit .env sesuai konfigurasi database
|
|
DB_CONNECTION=pgsql
|
|
DB_HOST=127.0.0.1
|
|
DB_PORT=5432
|
|
DB_DATABASE=biiskit
|
|
DB_USERNAME=your_user
|
|
DB_PASSWORD=your_password`})]}),(0,o.jsxs)(`div`,{children:[(0,o.jsx)(`h3`,{className:`text-xs font-black text-[#3D4E4B] dark:text-white uppercase tracking-widest mb-2`,children:`3. Migrasi & Seeder`}),(0,o.jsx)(l,{lang:`bash`,children:`php artisan migrate --seed`}),(0,o.jsxs)(`p`,{className:`text-xs text-gray-400 font-medium mt-2`,children:[`Seeder akan membuat 3 akun default: `,(0,o.jsx)(`code`,{className:`bg-gray-100 dark:bg-white/10 px-1.5 py-0.5 rounded font-mono`,children:`superadmin`}),`, `,(0,o.jsx)(`code`,{className:`bg-gray-100 dark:bg-white/10 px-1.5 py-0.5 rounded font-mono`,children:`admin`}),`, dan `,(0,o.jsx)(`code`,{className:`bg-gray-100 dark:bg-white/10 px-1.5 py-0.5 rounded font-mono`,children:`user`}),`.`]})]}),(0,o.jsxs)(`div`,{children:[(0,o.jsx)(`h3`,{className:`text-xs font-black text-[#3D4E4B] dark:text-white uppercase tracking-widest mb-2`,children:`4. Jalankan Server`}),(0,o.jsx)(l,{lang:`bash`,children:`# Terminal 1 — Laravel
|
|
php artisan serve
|
|
|
|
# Terminal 2 — Vite dev server
|
|
npm run dev`})]}),(0,o.jsx)(`div`,{className:`p-4 bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-700/40 rounded-xl`,children:(0,o.jsxs)(`p`,{className:`text-xs font-bold text-amber-700 dark:text-amber-400`,children:[`Akses aplikasi di `,(0,o.jsx)(`code`,{className:`font-mono`,children:`http://localhost:8000`}),` — redirect otomatis ke halaman login.`]})})]})]}),(0,o.jsxs)(`section`,{children:[(0,o.jsx)(u,{id:`stack`,title:`Tech Stack`}),(0,o.jsx)(`div`,{className:`bg-white dark:bg-[#1A2120] rounded-2xl border border-gray-100 dark:border-white/10 shadow-sm p-8`,children:(0,o.jsx)(`div`,{className:`grid grid-cols-1 md:grid-cols-2 gap-4`,children:[{layer:`Backend`,items:[`Laravel 13`,`PHP 8.3`,`PostgreSQL`,`Laravel Sanctum`,`Spatie Permission`,`Spatie Activity Log`]},{layer:`Frontend`,items:[`React 18`,`Inertia.js v2`,`TypeScript`,`Tailwind CSS v4`,`Vite 6`,`Chart.js`]},{layer:`Keamanan`,items:[`RBAC (Role-Based Access Control)`,`Two-Factor Auth (TOTP)`,`Sanctum API Tokens`,`Gate::before super-admin bypass`,`Bcrypt Password Hashing`]},{layer:`DevOps`,items:[`PostgreSQL + Redis (Docker ready)`,`Laravel Queue (database)`,`Cache: database driver`,`Pest PHP testing suite`]}].map(e=>(0,o.jsxs)(`div`,{className:`p-5 bg-gray-50 dark:bg-white/5 rounded-xl`,children:[(0,o.jsx)(`div`,{className:`text-xs font-black text-[#D4A017] uppercase tracking-widest mb-3`,children:e.layer}),(0,o.jsx)(`div`,{className:`space-y-1.5`,children:e.items.map(e=>(0,o.jsxs)(`div`,{className:`flex items-center gap-2 text-xs font-semibold text-gray-600 dark:text-gray-300`,children:[(0,o.jsx)(`span`,{className:`w-1.5 h-1.5 rounded-full bg-[#3D4E4B] dark:bg-[#D4A017] shrink-0`}),e]},e))})]},e.layer))})})]}),(0,o.jsxs)(`section`,{children:[(0,o.jsx)(u,{id:`auth`,title:`Autentikasi`,badge:`Web + API`,badgeColor:`purple`}),(0,o.jsxs)(`div`,{className:`bg-white dark:bg-[#1A2120] rounded-2xl border border-gray-100 dark:border-white/10 shadow-sm p-8 space-y-6`,children:[(0,o.jsxs)(`div`,{children:[(0,o.jsx)(`h3`,{className:`text-xs font-black text-[#3D4E4B] dark:text-white uppercase tracking-widest mb-4`,children:`Akun Bawaan (Seeder)`}),(0,o.jsx)(`div`,{className:`overflow-x-auto`,children:(0,o.jsxs)(`table`,{className:`w-full text-xs`,children:[(0,o.jsx)(`thead`,{children:(0,o.jsxs)(`tr`,{className:`border-b border-gray-100 dark:border-white/10`,children:[(0,o.jsx)(`th`,{className:`text-left font-black text-gray-400 uppercase tracking-widest py-2 pr-6`,children:`Email`}),(0,o.jsx)(`th`,{className:`text-left font-black text-gray-400 uppercase tracking-widest py-2 pr-6`,children:`Password`}),(0,o.jsx)(`th`,{className:`text-left font-black text-gray-400 uppercase tracking-widest py-2`,children:`Role`})]})}),(0,o.jsx)(`tbody`,{children:[{email:`superadmin@biiskit.com`,pw:`password`,role:`super-admin`,color:`red`},{email:`admin@biiskit.com`,pw:`password`,role:`admin`,color:`amber`},{email:`user@biiskit.com`,pw:`password`,role:`user`,color:`blue`}].map(e=>(0,o.jsxs)(`tr`,{className:`border-b border-gray-50 dark:border-white/5 last:border-0`,children:[(0,o.jsx)(`td`,{className:`py-3 pr-6 font-mono text-[#3D4E4B] dark:text-white font-bold`,children:e.email}),(0,o.jsx)(`td`,{className:`py-3 pr-6 font-mono text-gray-400`,children:e.pw}),(0,o.jsx)(`td`,{className:`py-3`,children:(0,o.jsx)(c,{color:e.color,children:e.role})})]},e.email))})]})})]}),(0,o.jsxs)(`div`,{children:[(0,o.jsx)(`h3`,{className:`text-xs font-black text-[#3D4E4B] dark:text-white uppercase tracking-widest mb-3`,children:`Alur Login Web`}),(0,o.jsx)(`div`,{className:`flex flex-wrap gap-2 items-center text-xs font-bold text-gray-500`,children:[`Form Login`,`→`,`Auth Check`,`→`,`2FA Challenge?`,`→`,`Email Verified?`,`→`,`Dashboard`].map((e,t)=>(0,o.jsx)(`span`,{className:e===`→`?`text-gray-300`:`px-3 py-1.5 bg-gray-50 dark:bg-white/5 rounded-lg text-[#3D4E4B] dark:text-white`,children:e},t))}),(0,o.jsxs)(`p`,{className:`text-xs text-gray-400 font-medium mt-2`,children:[`2FA Challenge hanya muncul jika user telah mengaktifkan Two-Factor Auth di `,(0,o.jsx)(`code`,{className:`bg-gray-100 dark:bg-white/10 px-1 py-0.5 rounded font-mono`,children:`/settings#2fa`}),`.`]})]}),(0,o.jsxs)(`div`,{children:[(0,o.jsx)(`h3`,{className:`text-xs font-black text-[#3D4E4B] dark:text-white uppercase tracking-widest mb-2`,children:`Login via API`}),(0,o.jsx)(l,{lang:`json`,children:`POST /api/v1/login
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"email": "admin@biiskit.com",
|
|
"password": "password"
|
|
}
|
|
|
|
// Response
|
|
{
|
|
"token": "1|abc123...",
|
|
"user": { "id": 1, "email": "admin@biiskit.com", ... }
|
|
}`})]})]})]}),(0,o.jsxs)(`section`,{children:[(0,o.jsx)(u,{id:`roles`,title:`Roles & Permission`,badge:`Spatie`,badgeColor:`green`}),(0,o.jsxs)(`div`,{className:`bg-white dark:bg-[#1A2120] rounded-2xl border border-gray-100 dark:border-white/10 shadow-sm p-8 space-y-6`,children:[(0,o.jsxs)(`p`,{className:`text-sm text-gray-500 dark:text-gray-400 font-medium leading-relaxed`,children:[`Menggunakan `,(0,o.jsx)(`strong`,{className:`text-[#3D4E4B] dark:text-white`,children:`spatie/laravel-permission`}),`. Role `,(0,o.jsx)(c,{color:`red`,children:`super-admin`}),` mendapat akses penuh via `,(0,o.jsx)(`code`,{className:`text-[11px] bg-gray-100 dark:bg-white/10 px-1.5 py-0.5 rounded font-mono`,children:`Gate::before`}),` bypass — tidak perlu assign permission satu per satu.`]}),(0,o.jsx)(`div`,{className:`overflow-x-auto`,children:(0,o.jsxs)(`table`,{className:`w-full text-xs`,children:[(0,o.jsx)(`thead`,{children:(0,o.jsxs)(`tr`,{className:`border-b border-gray-100 dark:border-white/10`,children:[(0,o.jsx)(`th`,{className:`text-left font-black text-gray-400 uppercase tracking-widest py-2 pr-6`,children:`Permission`}),(0,o.jsx)(`th`,{className:`text-center font-black text-gray-400 uppercase tracking-widest py-2 px-4`,children:`user`}),(0,o.jsx)(`th`,{className:`text-center font-black text-gray-400 uppercase tracking-widest py-2 px-4`,children:`admin`}),(0,o.jsx)(`th`,{className:`text-center font-black text-gray-400 uppercase tracking-widest py-2 px-4`,children:`super-admin`})]})}),(0,o.jsx)(`tbody`,{children:[{perm:`user.view`,u:!0,a:!0,s:!0},{perm:`user.create`,u:!1,a:!0,s:!0},{perm:`user.edit`,u:!1,a:!0,s:!0},{perm:`user.delete`,u:!1,a:!0,s:!0},{perm:`role.view`,u:!1,a:!0,s:!0},{perm:`role.manage`,u:!1,a:!1,s:!0},{perm:`settings.manage`,u:!1,a:!1,s:!0},{perm:`reports.view`,u:!1,a:!0,s:!0}].map(e=>(0,o.jsxs)(`tr`,{className:`border-b border-gray-50 dark:border-white/5 last:border-0`,children:[(0,o.jsx)(`td`,{className:`py-3 pr-6 font-mono font-bold text-[#3D4E4B] dark:text-white`,children:e.perm}),[e.u,e.a,e.s].map((e,t)=>(0,o.jsx)(`td`,{className:`py-3 text-center px-4`,children:e?(0,o.jsx)(`span`,{className:`text-emerald-500 font-black text-sm`,children:`✓`}):(0,o.jsx)(`span`,{className:`text-gray-200 font-black text-sm`,children:`✗`})},t))]},e.perm))})]})}),(0,o.jsxs)(`div`,{children:[(0,o.jsx)(`h3`,{className:`text-xs font-black text-[#3D4E4B] dark:text-white uppercase tracking-widest mb-2`,children:`Pengecekan Permission di Controller`}),(0,o.jsx)(l,{lang:`php`,children:`// Via Policy (model instance)
|
|
$this->authorize('update', $user);
|
|
|
|
// Via Gate string (tanpa model)
|
|
$this->authorize('user.delete');
|
|
|
|
// Via Blade / React (shared props)
|
|
// auth.permissions = ['user.view', 'user.create', ...]`})]})]})]}),(0,o.jsxs)(`section`,{children:[(0,o.jsx)(u,{id:`features`,title:`Fitur Lengkap`}),(0,o.jsx)(`div`,{className:`bg-white dark:bg-[#1A2120] rounded-2xl border border-gray-100 dark:border-white/10 shadow-sm p-8 space-y-6`,children:[{title:`Manajemen Pengguna`,icon:`👥`,items:[`CRUD lengkap (tambah, edit, hapus, restore)`,`Soft delete dengan arsip & purge permanen`,`Bulk archive / restore / force-delete`,`Filter by status, role, pencarian nama/email`,`Sorting multi-kolom + pagination`,`Export ke Excel (.xlsx)`,`Import user massal via Excel/CSV`,`Assign multi-role per user`]},{title:`Roles & Permission Manager`,icon:`🛡️`,items:[`Kelola role dari UI (tambah / hapus role)`,`Assign/revoke permission per role via toggle`,`Super-admin bypass via Gate::before`,`3 role default: super-admin, admin, user`]},{title:`Notifikasi`,icon:`🔔`,items:[`Kirim notifikasi (email / in-app)`,`Target: all users, role tertentu, atau user spesifik`,`Log pengiriman dengan status (sent/failed)`,`Badge counter di topbar (unread last 7 hari)`,`Pagination history notifikasi`]},{title:`Activity Logs`,icon:`📋`,items:[`Log otomatis via spatie/laravel-activitylog`,`Filter by user, event, tanggal`,`Bulk delete logs`,`Tampilan subject & properties berubah`]},{title:`Dashboard`,icon:`📊`,items:[`Statistik total users, admin, active, inactive`,`Chart pendaftaran user 30 hari terakhir (Chart.js)`,`Tabel aktivitas terbaru`,`Quick actions (tambah user, lihat logs)`]},{title:`Account Settings`,icon:`👤`,items:[`Tab Profile: nama, email, telepon, bio, avatar upload`,`Tab Security & Password: ganti password`,`Tab Two-Factor Auth: aktifkan/nonaktifkan TOTP 2FA`,`Tab Danger Zone: hapus akun permanen`,`Tab aktif persisten saat reload (via URL hash)`]},{title:`UI/UX`,icon:`🎨`,items:[`Dark mode toggle (persisted di localStorage)`,`Sidebar responsif + burger menu mobile`,`Breadcrumb dinamis di topbar`,`Flash messages (success / error)`,`Animasi masuk halaman (anim-down, anim-up, anim-left)`,`Tab state persisten via URL hash (#tab-name)`,`Custom scrollbar`,`Error pages: 403, 404, 500`]}].map(e=>(0,o.jsxs)(`div`,{className:`p-5 bg-gray-50 dark:bg-white/5 rounded-xl`,children:[(0,o.jsxs)(`div`,{className:`flex items-center gap-3 mb-3`,children:[(0,o.jsx)(`span`,{className:`text-xl`,children:e.icon}),(0,o.jsx)(`div`,{className:`text-sm font-black text-[#3D4E4B] dark:text-white`,children:e.title})]}),(0,o.jsx)(`div`,{className:`grid grid-cols-1 md:grid-cols-2 gap-1.5`,children:e.items.map(e=>(0,o.jsxs)(`div`,{className:`flex items-start gap-2 text-xs font-medium text-gray-500 dark:text-gray-400`,children:[(0,o.jsx)(`span`,{className:`text-emerald-500 font-black mt-0.5 shrink-0`,children:`✓`}),e]},e))})]},e.title))})]}),(0,o.jsxs)(`section`,{children:[(0,o.jsx)(u,{id:`api`,title:`REST API`,badge:`v1`,badgeColor:`blue`}),(0,o.jsxs)(`div`,{className:`bg-white dark:bg-[#1A2120] rounded-2xl border border-gray-100 dark:border-white/10 shadow-sm p-8 space-y-6`,children:[(0,o.jsxs)(`div`,{children:[(0,o.jsx)(`h3`,{className:`text-xs font-black text-[#3D4E4B] dark:text-white uppercase tracking-widest mb-2`,children:`Base URL`}),(0,o.jsx)(l,{lang:`http`,children:`http://your-domain.com/api/v1`})]}),(0,o.jsxs)(`div`,{children:[(0,o.jsx)(`h3`,{className:`text-xs font-black text-[#3D4E4B] dark:text-white uppercase tracking-widest mb-2`,children:`Authentication Header`}),(0,o.jsx)(l,{lang:`http`,children:`Authorization: Bearer {your-sanctum-token}`})]}),(0,o.jsxs)(`div`,{children:[(0,o.jsx)(`h3`,{className:`text-xs font-black text-[#3D4E4B] dark:text-white uppercase tracking-widest mb-4`,children:`Endpoints`}),(0,o.jsxs)(`div`,{className:`border border-gray-100 dark:border-white/10 rounded-xl overflow-hidden`,children:[(0,o.jsx)(`div`,{className:`px-4 py-2.5 bg-gray-50 dark:bg-white/5 border-b border-gray-100 dark:border-white/10`,children:(0,o.jsx)(`span`,{className:`text-[10px] font-black text-gray-400 uppercase tracking-widest`,children:`Auth`})}),(0,o.jsxs)(`div`,{className:`px-4`,children:[(0,o.jsx)(d,{method:`POST`,path:`/api/v1/login`,desc:`Dapatkan Sanctum token`,auth:!1}),(0,o.jsx)(d,{method:`GET`,path:`/api/v1/me`,desc:`Data user aktif`}),(0,o.jsx)(d,{method:`POST`,path:`/api/v1/logout`,desc:`Revoke token`})]}),(0,o.jsx)(`div`,{className:`px-4 py-2.5 bg-gray-50 dark:bg-white/5 border-y border-gray-100 dark:border-white/10`,children:(0,o.jsx)(`span`,{className:`text-[10px] font-black text-gray-400 uppercase tracking-widest`,children:`Users`})}),(0,o.jsxs)(`div`,{className:`px-4`,children:[(0,o.jsx)(d,{method:`GET`,path:`/api/v1/users`,desc:`List semua user`}),(0,o.jsx)(d,{method:`POST`,path:`/api/v1/users`,desc:`Buat user baru`}),(0,o.jsx)(d,{method:`GET`,path:`/api/v1/users/{id}`,desc:`Detail user`}),(0,o.jsx)(d,{method:`PATCH`,path:`/api/v1/users/{id}`,desc:`Update user`}),(0,o.jsx)(d,{method:`DELETE`,path:`/api/v1/users/{id}`,desc:`Hapus user`})]}),(0,o.jsx)(`div`,{className:`px-4 py-2.5 bg-gray-50 dark:bg-white/5 border-y border-gray-100 dark:border-white/10`,children:(0,o.jsx)(`span`,{className:`text-[10px] font-black text-gray-400 uppercase tracking-widest`,children:`App Config`})}),(0,o.jsx)(`div`,{className:`px-4`,children:(0,o.jsx)(d,{method:`GET`,path:`/api/v1/app-config`,desc:`Konfigurasi aplikasi publik`,auth:!1})})]})]})]})]}),(0,o.jsxs)(`section`,{children:[(0,o.jsx)(u,{id:`2fa`,title:`Two-Factor Authentication`,badge:`TOTP`,badgeColor:`amber`}),(0,o.jsxs)(`div`,{className:`bg-white dark:bg-[#1A2120] rounded-2xl border border-gray-100 dark:border-white/10 shadow-sm p-8 space-y-4`,children:[(0,o.jsxs)(`p`,{className:`text-sm text-gray-500 dark:text-gray-400 font-medium leading-relaxed`,children:[`2FA menggunakan protokol `,(0,o.jsx)(`strong`,{className:`text-[#3D4E4B] dark:text-white`,children:`TOTP (Time-based One-Time Password)`}),` yang kompatibel dengan Google Authenticator, Authy, dan 1Password.`]}),(0,o.jsx)(`div`,{className:`space-y-3`,children:[{step:`1`,title:`Buka tab Two-Factor Auth`,desc:`Masuk ke Account Settings (/settings) → tab "Two-Factor Auth"`},{step:`2`,title:`Scan QR Code`,desc:`Gunakan aplikasi authenticator (Google Authenticator / Authy) untuk scan QR`},{step:`3`,title:`Masukkan kode verifikasi`,desc:`Ketik 6 digit dari aplikasi untuk mengaktifkan 2FA`},{step:`4`,title:`Simpan recovery codes`,desc:`8 kode cadangan tersedia — simpan di tempat aman jika kehilangan akses ke authenticator`},{step:`5`,title:`Login berikutnya`,desc:`Setelah diaktifkan, setiap login akan redirect ke halaman 2FA Challenge sebelum masuk dashboard`}].map(e=>(0,o.jsxs)(`div`,{className:`flex items-start gap-4 p-4 bg-gray-50 dark:bg-white/5 rounded-xl`,children:[(0,o.jsx)(`div`,{className:`w-7 h-7 rounded-full bg-[#3D4E4B] text-white text-xs font-black flex items-center justify-center shrink-0`,children:e.step}),(0,o.jsxs)(`div`,{children:[(0,o.jsx)(`div`,{className:`text-sm font-bold text-[#3D4E4B] dark:text-white`,children:e.title}),(0,o.jsx)(`div`,{className:`text-xs text-gray-400 font-medium mt-0.5`,children:e.desc})]})]},e.step))}),(0,o.jsx)(`div`,{className:`p-4 bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-700/40 rounded-xl`,children:(0,o.jsx)(`p`,{className:`text-xs font-bold text-blue-700 dark:text-blue-400`,children:`2FA bersifat opsional per user. Setelah diaktifkan, setiap login akan meminta kode 6 digit dari authenticator.`})})]})]}),(0,o.jsxs)(`section`,{children:[(0,o.jsx)(u,{id:`settings`,title:`System Settings`,badge:`Super Admin`,badgeColor:`red`}),(0,o.jsxs)(`div`,{className:`bg-white dark:bg-[#1A2120] rounded-2xl border border-gray-100 dark:border-white/10 shadow-sm p-8 space-y-4`,children:[(0,o.jsxs)(`p`,{className:`text-sm text-gray-500 dark:text-gray-400 font-medium`,children:[`Hanya bisa diakses oleh pengguna dengan role `,(0,o.jsx)(c,{color:`red`,children:`super-admin`}),`. Tersedia di `,(0,o.jsx)(`code`,{className:`text-xs bg-gray-100 dark:bg-white/10 px-2 py-0.5 rounded font-mono`,children:`/system-settings`}),`.`]}),(0,o.jsx)(`div`,{className:`grid grid-cols-1 md:grid-cols-2 gap-4`,children:[{tab:`General & Branding`,items:[`Nama aplikasi`,`Logo upload`,`Teks logo fallback`,`Registrasi publik on/off`,`Verifikasi email on/off`]},{tab:`Security & OAuth`,items:[`Password minimum panjang`,`Wajib huruf besar/kecil/angka/simbol`,`Google OAuth (Client ID & Secret)`,`GitHub OAuth (Client ID & Secret)`]},{tab:`Email / SMTP`,items:[`Host & port SMTP`,`Enkripsi (TLS/SSL)`,`Username & password SMTP`,`From name & address`,`Test kirim email dari UI`]},{tab:`Mobile App Control`,items:[`Versi terbaru & minimum Android`,`URL Play Store`,`Mode maintenance mobile app`,`Pesan maintenance kustom`]}].map(e=>(0,o.jsxs)(`div`,{className:`p-5 bg-gray-50 dark:bg-white/5 rounded-xl`,children:[(0,o.jsx)(`div`,{className:`text-xs font-black text-[#D4A017] uppercase tracking-widest mb-3`,children:e.tab}),e.items.map(e=>(0,o.jsxs)(`div`,{className:`flex items-center gap-2 text-xs font-semibold text-gray-500 dark:text-gray-400 mb-1.5`,children:[(0,o.jsx)(`span`,{className:`w-1.5 h-1.5 rounded-full bg-gray-300 dark:bg-gray-600 shrink-0`}),e]},e))]},e.tab))})]})]}),(0,o.jsxs)(`section`,{children:[(0,o.jsx)(u,{id:`structure`,title:`Struktur Folder`}),(0,o.jsx)(`div`,{className:`bg-white dark:bg-[#1A2120] rounded-2xl border border-gray-100 dark:border-white/10 shadow-sm p-8 space-y-4`,children:(0,o.jsx)(l,{lang:`text`,children:`biiskit/
|
|
├── app/
|
|
│ ├── Http/
|
|
│ │ ├── Controllers/ # Web + API controllers
|
|
│ │ │ └── Api/V1/ # REST API v1 controllers
|
|
│ │ ├── Middleware/
|
|
│ │ │ └── HandleInertiaRequests.php # Shared props (auth, settings)
|
|
│ │ └── Requests/ # Form request validation
|
|
│ ├── Models/
|
|
│ │ ├── User.php # SoftDeletes + HasRoles + HasPermissions
|
|
│ │ ├── Setting.php # System settings key-value store
|
|
│ │ └── NotificationLog.php # Notifikasi log
|
|
│ └── Policies/
|
|
│ └── UserPolicy.php # Gate policies untuk user CRUD
|
|
│
|
|
├── database/
|
|
│ ├── migrations/ # PostgreSQL migrations
|
|
│ └── seeders/
|
|
│ └── DatabaseSeeder.php # Roles, permissions, demo users
|
|
│
|
|
├── resources/js/
|
|
│ ├── Layouts/
|
|
│ │ ├── AuthenticatedLayout.tsx # Wrapper utama + mobile sidebar
|
|
│ │ └── components/
|
|
│ │ ├── Sidebar.tsx # Nav dengan permission check
|
|
│ │ └── Topbar.tsx # Breadcrumb + notif bell + dark mode
|
|
│ ├── Pages/
|
|
│ │ ├── Auth/ # Login, Register, Password reset
|
|
│ │ ├── Dashboard/ # Dashboard dengan chart
|
|
│ │ ├── Users/ # Index, Show (CRUD)
|
|
│ │ ├── Roles/ # Roles & permission manager
|
|
│ │ ├── Notifications/ # Kirim & history notifikasi
|
|
│ │ ├── ActivityLogs/ # Log aktivitas
|
|
│ │ ├── Settings/ # Account settings (profile, password, 2FA, danger zone)
|
|
│ │ ├── TwoFactor/ # 2FA challenge page (login flow, no auth)
|
|
│ │ ├── SystemSettings/ # Sistem config (super-admin)
|
|
│ │ ├── Docs/ # Halaman dokumentasi ini
|
|
│ │ └── Errors/ # 403, 404, 500 pages
|
|
│ └── Components/
|
|
│ ├── DataTable.tsx # Reusable sortable table
|
|
│ └── FlashMessage.tsx # Success/error flash
|
|
│
|
|
├── routes/
|
|
│ ├── web.php # Web routes (Inertia)
|
|
│ └── api.php # API routes (Sanctum)
|
|
│
|
|
└── tests/
|
|
├── Feature/ # Feature tests (Pest)
|
|
└── Unit/ # Unit tests`})})]})]})]})]})}export{f as default}; |