// users.jsx — USER MANAGEMENT & PERMISSIONS module + widget.
const US_APP = APPS.find(a => a.id === 'users');
function deptName(id, lang){ const d = DEPARTMENTS.find(x => x.id === id); return d ? d[lang] || d.vi : id; }
function roleOf(id, roles){ return roles.find(r => r.id === id) || { name:{ vi:id, en:id }, color:'var(--gray-400)' }; }

function UsRoleBadge({ role }){
  const { lang } = useLang();
  return <span className="badge" style={{ background:'transparent', color:role.color, border:'1px solid currentColor' }}><i className="dot"></i>{role.name[lang] || role.name.vi}</span>;
}
function UsStatusBadge({ status }){
  const { lang } = useLang(); const s = USER_STATUS[status];
  return <span className={'badge ' + s.cls}><i className="dot"></i>{s[lang] || s.vi}</span>;
}

function UserModule(){
  const p = usePortal();
  const { t } = useLang();
  const sub = p.route.sub || 'overview';
  const items = [
    { id:'overview', icon:'bi-pie-chart', label:t('c.overview') },
    { id:'list', icon:'bi-people', label:t('us.directory'), count:p.accounts.length },
    { id:'roles', icon:'bi-shield-lock', label:t('us.roles'), count:p.roles.length },
    { id:'settings', icon:'bi-gear', label:t('c.settings') },
  ];
  const go = (id, extra) => p.navigate({ name:'module', module:'users', sub:id, ...extra });
  return (<>
    <ModuleSidebar app={US_APP} items={items} active={sub === 'detail' ? 'list' : sub} onNavigate={go} />
    <main className="main">
      {sub === 'overview' && <UsOverview go={go} />}
      {sub === 'list' && <UsList go={go} />}
      {sub === 'detail' && <UsDetail id={p.route.id} go={go} />}
      {sub === 'roles' && <UsRoles />}
      {sub === 'help' && <ModuleHelp moduleId="users" app={US_APP} />}
      {sub === 'settings' && <UsSettings />}
    </main>
  </>);
}

function cnt(arr, key){ const m = {}; arr.forEach(x => { m[x[key]] = (m[x[key]] || 0) + 1; }); return m; }

function UsOverview({ go }){
  const p = usePortal();
  const { t, lang } = useLang();
  const us = p.accounts;
  const byRole = cnt(us, 'role'); const byDept = cnt(us, 'dept');
  const recent = [...us].sort((a, b) => (a.last === '—' ? 1 : 0) - (b.last === '—' ? 1 : 0)).map(u => {
    const r = roleOf(u.role, p.roles);
    return { date:u.joined, icon:u.status === 'invited' ? 'bi-person-plus' : 'bi-person-check', color:r.color,
      title:u.name,
      sub:deptName(u.dept, lang) + ' · ' + r.name[lang],
      tag:USER_STATUS[u.status] ? USER_STATUS[u.status][lang] : null,
      tagCls:USER_STATUS[u.status] ? USER_STATUS[u.status].cls : 'badge-neutral',
      time:u.last, onClick:() => go('detail', { id:u.id }) };
  });
  return (
    <div className="page pagefade">
      <div className="page-head"><div><h1>{t('us.title')}</h1><div className="sub">{lang === 'vi' ? 'Quản lý tài khoản và phân quyền truy cập.' : 'Manage accounts and access permissions.'}</div></div>
        <button className="btn btn-primary" onClick={() => p.quick('users')}><i className="bi bi-person-plus"></i>{t('us.invite')}</button></div>
      <div className="kpi-strip">
        <Kpi label={t('us.title')} value={us.length} icon="bi-people" />
        <Kpi label={USER_STATUS.active[lang]} value={us.filter(u => u.status === 'active').length} icon="bi-person-check" />
        <Kpi label={USER_STATUS.invited[lang]} value={us.filter(u => u.status === 'invited').length} icon="bi-person-plus" />
        <Kpi label={t('us.roles')} value={p.roles.length} icon="bi-shield-lock" />
      </div>
      <div className="dash-grid">
        <div className="card"><div className="card-head"><h3>{lang === 'vi' ? 'Theo vai trò' : 'By role'}</h3></div><div className="card-body">
          <DistribBars rows={p.roles.filter(r => byRole[r.id]).map(r => ({ label:r.name[lang], value:byRole[r.id] || 0, color:r.color }))} />
        </div></div>
        <div className="card span2"><div className="card-head"><h3>{lang === 'vi' ? 'Theo phòng ban' : 'By department'}</h3></div><div className="card-body">
          <DistribBars rows={DEPARTMENTS.filter(d => byDept[d.id]).map((d, i) => ({ label:d[lang], value:byDept[d.id] || 0, color:['var(--primary)','var(--accent)','#7A5AF8','var(--warning)','var(--success)','#D14343','#0B4FBF'][i % 7] }))} />
        </div></div>
      </div>
      <RecentActivity items={recent} title={lang === 'vi' ? 'Hoạt động người dùng mới nhất' : 'Latest user activity'} />
    </div>
  );
}

function UsList({ go }){
  const p = usePortal();
  const { t, lang } = useLang();
  const [q, setQ] = React.useState('');
  const [role, setRole] = React.useState('all');
  const [status, setStatus] = React.useState('all');
  const srt = useTableSort();
  const list = srt.sortRows(p.accounts.filter(u =>
    (role === 'all' || u.role === role) && (status === 'all' || u.status === status) &&
    (!q || (u.name + u.email).toLowerCase().includes(q.toLowerCase()))),
    { name:u => u.name, dept:u => u.dept, role:u => (roleOf(u.role, p.roles) || {}).name && roleOf(u.role, p.roles).name[lang], last:u => u.lastActive, status:u => u.status });
  return (
    <div className="page pagefade">
      <div className="page-head"><div><h1>{t('us.directory')}</h1><div className="sub">{list.length} {t('us.members')}</div></div>
        <button className="btn btn-primary" onClick={() => p.quick('users')}><i className="bi bi-person-plus"></i>{t('us.invite')}</button></div>
      <div className="toolbar">
        <div className="topsearch" style={{ width:220, background:'var(--bg)', border:'1px solid var(--border-strong)' }}><i className="bi bi-search"></i>
          <input value={q} onChange={e => setQ(e.target.value)} placeholder={t('c.search')} style={{ border:'none', outline:'none', background:'transparent', flex:1 }} /></div>
        <select className="select" style={{ width:'auto' }} value={role} onChange={e => setRole(e.target.value)}>
          <option value="all">{t('us.role')}: {t('c.all')}</option>{p.roles.map(r => <option key={r.id} value={r.id}>{r.name[lang]}</option>)}</select>
        <div className="seg">{['all','active','invited','disabled'].map(s => <button key={s} className={status === s ? 'is-active' : ''} onClick={() => setStatus(s)}><i className={'bi ' + ({ all:'bi-grid-1x2', active:'bi-check-circle', invited:'bi-envelope', disabled:'bi-slash-circle' }[s])}></i>{s === 'all' ? t('c.all') : USER_STATUS[s][lang]}</button>)}</div>
      </div>
      <div className="card"><div style={{ overflow:'auto' }}>
        <table className="tbl">
          <thead><tr><ThSort k="name" sort={srt}>{t('us.name')}</ThSort><ThSort k="dept" sort={srt}>{t('us.dept')}</ThSort><ThSort k="role" sort={srt}>{t('us.role')}</ThSort><ThSort k="last" sort={srt}>{t('us.lastActive')}</ThSort><ThSort k="status" sort={srt}>{t('c.status')}</ThSort></tr></thead>
          <tbody>
            {list.map(u => { const r = roleOf(u.role, p.roles); return (
              <tr key={u.id} onClick={() => go('detail', { id:u.id })}>
                <td><span className="flex g8 items-center"><Avatar name={u.name} size={26} color={r.color} /><div><div style={{ fontWeight:500 }}>{u.name}</div><div className="subtle mono" style={{ fontSize:'var(--fs-sm)' }}>{u.email}</div></div></span></td>
                <td className="muted">{deptName(u.dept, lang)}</td>
                <td><UsRoleBadge role={r} /></td>
                <td className="muted">{u.last}</td>
                <td><UsStatusBadge status={u.status} /></td>
              </tr>
            ); })}
          </tbody>
        </table>
        {!list.length && <EmptyState text={t('c.empty')} />}
      </div></div>
    </div>
  );
}

function PermGrid({ perms, readOnly, onToggle }){
  const { t, lang } = useLang();
  return (
    <div style={{ overflow:'auto' }}>
      <table className="tbl">
        <thead><tr><th>{t('us.resource')}</th>{PERM_ACTIONS.map(a => <th key={a.id} style={{ textAlign:'center', width:78 }}>{a[lang]}</th>)}</tr></thead>
        <tbody>
          {PERM_RESOURCES.map(r => (
            <tr key={r.id} style={{ cursor:'default' }}>
              <td style={{ fontWeight:500 }}>{r[lang]}</td>
              {PERM_ACTIONS.map(a => { const on = perms[r.id] && perms[r.id][a.id]; return (
                <td key={a.id} style={{ textAlign:'center' }}>
                  <button className={'ckbox' + (on ? ' done' : '')} disabled={readOnly} style={{ margin:'0 auto', opacity:readOnly && !on ? .4 : 1, cursor:readOnly ? 'default' : 'pointer' }}
                    onClick={() => !readOnly && onToggle(r.id, a.id)}>{on && <i className="bi bi-check2"></i>}</button>
                </td>
              ); })}
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

function UsDetail({ id, go }){
  const p = usePortal();
  const { t, lang } = useLang();
  const toast = useToast();
  const [editing, setEditing] = React.useState(false);
  const u = p.accounts.find(x => x.id === id);
  if (!u) return <div className="page"><EmptyState text={t('c.empty')} /></div>;
  const r = roleOf(u.role, p.roles);
  return (
    <div className="page pagefade">
      <div className="page-head">
        <div className="flex g12 items-center">
          <button className="btn btn-ghost btn-icon" onClick={() => go('list')}><i className="bi bi-arrow-left"></i></button>
          <Avatar name={u.name} size={42} color={r.color} />
          <div><h1 style={{ fontSize:'var(--fs-2xl)' }}>{u.name}</h1><div className="sub flex g8 items-center mono">{u.email} · <UsStatusBadge status={u.status} /></div></div>
        </div>
        <div className="flex g8">
          <button className="btn" onClick={() => setEditing(true)}><i className="bi bi-pencil"></i>{t('c.edit')}</button>
          {u.status === 'disabled'
            ? <button className="btn btn-primary" onClick={() => { p.patchAccount(u.id, { status:'active' }); toast(lang === 'vi' ? 'Đã kích hoạt' : 'Enabled', 'success'); }}><i className="bi bi-person-check"></i>{t('us.enable')}</button>
            : <button className="btn" onClick={() => { p.patchAccount(u.id, { status:'disabled' }); toast(lang === 'vi' ? 'Đã vô hiệu hóa' : 'Disabled', 'info'); }}><i className="bi bi-person-slash"></i>{t('us.disable')}</button>}
          <button className="btn" onClick={() => toast(lang === 'vi' ? 'Đã gửi email đặt lại mật khẩu' : 'Reset email sent', 'success')}><i className="bi bi-key"></i>{t('us.resetPw')}</button>
        </div>
      </div>
      {editing && <EditUserModal user={u} onClose={() => setEditing(false)} />}
      <div className="split">
        <div className="col g12">
          <div className="card"><div className="card-head"><h3>{t('us.profile')}</h3></div><div className="card-body">
            <div className="det-row"><span className="dk">{t('us.name')}</span><span className="dv">{u.name}</span></div>
            <div className="det-row"><span className="dk">{t('us.email')}</span><span className="dv mono">{u.email}</span></div>
            <div className="det-row"><span className="dk">{t('us.dept')}</span><span className="dv">{deptName(u.dept, lang)}</span></div>
            <div className="det-row"><span className="dk">{t('us.joined')}</span><span className="dv mono">{fmtDate(u.joined)}</span></div>
            <div className="det-row"><span className="dk">{t('us.lastActive')}</span><span className="dv">{u.last}</span></div>
          </div></div>
          <div className="card"><div className="card-head"><h3 style={{ fontSize:'var(--fs-md)' }}>{t('us.assignRole')}</h3></div><div className="card-body col g8">
            <select className="select" value={u.role} onChange={e => { p.patchAccount(u.id, { role:e.target.value }); toast(lang === 'vi' ? 'Đã đổi vai trò' : 'Role updated', 'success'); }}>
              {p.roles.map(rr => <option key={rr.id} value={rr.id}>{rr.name[lang]}</option>)}
            </select>
            <div className="subtle" style={{ fontSize:'var(--fs-sm)' }}>{r.desc ? r.desc[lang] : ''}</div>
          </div></div>
          {p.role === 'admin' && (() => {
            const cur = (p.appSettings.costViewOverrides || {})[u.id] || '';
            const setOv = (v) => { const map = { ...(p.appSettings.costViewOverrides || {}) }; if (v) map[u.id] = v; else delete map[u.id]; p.setSetting('costViewOverrides', map); toast(lang === 'vi' ? 'Đã cập nhật quyền xem giá vốn' : 'Cost visibility updated', 'success'); };
            return (
              <div className="card"><div className="card-head"><h3 style={{ fontSize:'var(--fs-md)' }}>{lang === 'vi' ? 'Quyền xem giá vốn & lợi nhuận' : 'Cost & profit visibility'}</h3></div><div className="card-body col g8">
                <div className="seg">
                  {[['', lang === 'vi' ? 'Theo vai trò' : 'By role'], ['allow', lang === 'vi' ? 'Cho xem' : 'Allow'], ['deny', lang === 'vi' ? 'Ẩn' : 'Hide']].map(([k, lbl]) => (
                    <button key={k || 'def'} className={cur === k ? 'is-active' : ''} onClick={() => setOv(k)}>{lbl}</button>
                  ))}
                </div>
                <div className="subtle" style={{ fontSize:'var(--fs-sm)' }}>{lang === 'vi' ? 'Ngoại lệ cho riêng người này; "Theo vai trò" = dùng thiết lập chung (Bảng quản trị → Hệ thống).' : 'Per-user exception; "By role" follows the global setting.'}</div>
              </div></div>
            );
          })()}
        </div>
        <div className="card"><div className="card-head"><h3 style={{ fontSize:'var(--fs-md)' }}>{t('us.access')}</h3><UsRoleBadge role={r} /></div>
          <PermGrid perms={r.perms} readOnly={true} />
          <div className="card-body" style={{ paddingTop:8 }}><button className="btn btn-sm btn-ghost" onClick={() => go('roles')}><i className="bi bi-pencil"></i>{lang === 'vi' ? 'Chỉnh quyền vai trò này' : 'Edit this role'}</button></div>
        </div>
      </div>
    </div>
  );
}

/* Sửa hồ sơ người dùng: Họ tên + Phòng ban (email = định danh đăng nhập, không đổi) */
function EditUserModal({ user, onClose }){
  const p = usePortal();
  const { t, lang } = useLang();
  const toast = useToast();
  const [f, setF] = React.useState({ name:user.name || '', dept:user.dept || '' });
  const set = (k, v) => setF(s => ({ ...s, [k]:v }));
  const save = () => {
    if (!f.name.trim()) { toast(lang === 'vi' ? 'Nhập họ tên' : 'Enter a name', 'error'); return; }
    p.patchAccount(user.id, { name:f.name.trim(), dept:f.dept });
    toast(lang === 'vi' ? 'Đã lưu hồ sơ' : 'Profile saved', 'success');
    onClose();
  };
  return (
    <Modal title={lang === 'vi' ? 'Sửa thông tin người dùng' : 'Edit user'} width={460} onClose={onClose}
      footer={<><button className="btn" onClick={onClose}>{t('c.cancel')}</button><button className="btn btn-primary" onClick={save}>{t('c.save')}</button></>}>
      <div className="col g16">
        <Field label={t('us.name')}><input className="input" autoFocus value={f.name} onChange={e => set('name', e.target.value)} /></Field>
        <Field label={t('us.email')} hint={lang === 'vi' ? 'Email đăng nhập — không đổi' : 'Login email — read-only'}>
          <input className="input mono" value={user.email} disabled style={{ background:'var(--bg-sunken)' }} /></Field>
        <Field label={t('us.dept')}>
          <select className="select" value={f.dept} onChange={e => set('dept', e.target.value)}>
            <option value="">— {lang === 'vi' ? 'chưa gán' : 'unassigned'} —</option>
            {DEPARTMENTS.map(d => <option key={d.id} value={d.id}>{d[lang] || d.vi}</option>)}
          </select>
        </Field>
      </div>
    </Modal>
  );
}

function UsRoles(){
  const p = usePortal();
  const { t, lang } = useLang();
  const toast = useToast();
  const [sel, setSel] = React.useState((p.roles.find(r => r.id !== 'admin') || p.roles[0]).id);  // mặc định vai trò sửa được (admin bị khóa)
  const [adding, setAdding] = React.useState(false);
  const [newName, setNewName] = React.useState('');
  const role = p.roles.find(r => r.id === sel) || p.roles[0];
  const locked = role.id === 'admin';
  const toggle = (res, act) => {
    const np = { ...role.perms, [res]:{ ...role.perms[res], [act]:!role.perms[res][act] } };
    p.updateRole(role.id, { perms:np });
  };
  const memberCount = (rid) => p.accounts.filter(u => u.role === rid).length;
  return (
    <div className="page pagefade">
      <div className="page-head"><div><h1>{t('us.roles')}</h1><div className="sub">{lang === 'vi' ? 'Định nghĩa vai trò và ma trận phân quyền.' : 'Define roles and the permission matrix.'}</div></div>
        <button className="btn btn-primary" onClick={() => setAdding(true)}><i className="bi bi-plus-lg"></i>{t('us.newRole')}</button></div>
      <div className="split">
        <div className="card"><div className="card-head"><h3 style={{ fontSize:'var(--fs-md)' }}>{t('us.permMatrix')} — <span style={{ color:role.color }}>{role.name[lang]}</span></h3>
          {locked && <span className="badge badge-info"><i className="bi bi-lock"></i> {t('us.systemRole')}</span>}</div>
          <PermGrid perms={role.perms} readOnly={locked} onToggle={toggle} />
          <div className="card-body flex justify-between items-center" style={{ paddingTop:10 }}>
            <span className="subtle" style={{ fontSize:'var(--fs-sm)' }}>{rolePermCount(role)} {lang === 'vi' ? 'quyền được cấp' : 'permissions granted'}</span>
            {!locked && <button className="btn btn-sm btn-primary" onClick={() => toast(lang === 'vi' ? 'Đã lưu phân quyền' : 'Permissions saved', 'success')}><i className="bi bi-check2"></i>{t('us.savePerms')}</button>}
          </div>
        </div>
        <div className="card"><div className="card-head"><h3 style={{ fontSize:'var(--fs-md)' }}>{lang === 'vi' ? 'Vai trò' : 'Roles'}</h3></div><div className="card-body col g4" style={{ paddingTop:8 }}>
          {p.roles.map(rr => (
            <button key={rr.id} className="flex g8 items-center" onClick={() => setSel(rr.id)}
              style={{ textAlign:'left', border:'1px solid ' + (sel === rr.id ? 'var(--primary)' : 'var(--border)'), background:sel === rr.id ? 'var(--primary-light)' : 'var(--bg)', borderRadius:'var(--r-md)', padding:'8px 10px', cursor:'pointer' }}>
              <span style={{ width:8, height:8, borderRadius:'50%', background:rr.color, flex:'none' }}></span>
              <div style={{ flex:1, minWidth:0 }}><div style={{ fontWeight:600 }}>{rr.name[lang]}</div><div className="subtle truncate" style={{ fontSize:'var(--fs-sm)' }}>{rr.desc ? rr.desc[lang] : ''}</div></div>
              <span className="badge badge-neutral">{memberCount(rr.id)}</span>
            </button>
          ))}
        </div></div>
      </div>
      {adding && (
        <Modal title={t('us.newRole')} width={420} onClose={() => setAdding(false)}
          footer={<><button className="btn" onClick={() => setAdding(false)}>{t('c.cancel')}</button>
            <button className="btn btn-primary" onClick={() => { if (!newName.trim()) return; const id = 'role' + Date.now(); p.addRole({ id, name:{ vi:newName, en:newName }, color:'#7A5AF8', system:false, desc:{ vi:'Vai trò tùy chỉnh', en:'Custom role' }, perms:mkPerms({ dashboard:'v' }) }); setSel(id); setAdding(false); setNewName(''); toast(lang === 'vi' ? 'Đã tạo vai trò' : 'Role created', 'success'); }}>{t('c.create')}</button></>}>
          <Field label={lang === 'vi' ? 'Tên vai trò' : 'Role name'}><input className="input" autoFocus value={newName} onChange={e => setNewName(e.target.value)} placeholder={lang === 'vi' ? 'VD: Trưởng nhóm' : 'e.g. Team lead'} /></Field>
        </Modal>
      )}
    </div>
  );
}

function UsSettings(){
  const { t, lang } = useLang();
  return (
    <div className="page pagefade">
      <div className="page-head"><div><h1>{t('c.settings')}</h1><div className="sub">{lang === 'vi' ? 'Phòng ban & chính sách bảo mật.' : 'Departments & security policy.'}</div></div></div>
      <div className="dash-grid">
        <div className="card"><div className="card-head"><h3 style={{ fontSize:'var(--fs-md)' }}>{t('us.dept')}</h3></div><div className="card-body flex g8 wrap">
          {DEPARTMENTS.map(d => <span key={d.id} className="badge badge-neutral" style={{ height:24 }}>{d[lang]}</span>)}
        </div></div>
        <div className="card span2"><div className="card-head"><h3 style={{ fontSize:'var(--fs-md)' }}>{lang === 'vi' ? 'Chính sách bảo mật' : 'Security policy'}</h3></div><div className="card-body col g12">
          {[[lang === 'vi' ? 'Bắt buộc xác thực 2 lớp (2FA)' : 'Require 2FA', true], [lang === 'vi' ? 'Đăng nhập bằng Google SSO' : 'Google SSO sign-in', true], [lang === 'vi' ? 'Mật khẩu tối thiểu 8 ký tự' : 'Min 8-char password', true], [lang === 'vi' ? 'Tự đăng xuất sau 30 phút' : 'Auto sign-out after 30 min', false]].map(([label, on], i) => (
            <div key={i} className="flex items-center justify-between"><span style={{ fontWeight:500 }}>{label}</span>
              <span style={{ width:38, height:22, borderRadius:999, background:on ? 'var(--primary)' : 'var(--gray-300)', position:'relative', flex:'none' }}><span style={{ position:'absolute', top:2, left:on ? 18 : 2, width:18, height:18, borderRadius:'50%', background:'#fff', boxShadow:'var(--sh-xs)' }}></span></span>
            </div>
          ))}
        </div></div>
      </div>
    </div>
  );
}

function InviteUserModal({ onClose }){
  const p = usePortal();
  const { t, lang } = useLang();
  const toast = useToast();
  const [f, setF] = React.useState({ name:'', email:'', dept:DEPARTMENTS[1].id, role:'staff' });
  const set = (k, v) => setF(s => ({ ...s, [k]:v }));
  const create = () => {
    if (!f.name.trim() || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(f.email)) { toast(lang === 'vi' ? 'Nhập tên và email hợp lệ' : 'Enter name and valid email', 'error'); return; }
    p.addAccount({ id:'u' + Date.now(), name:f.name, email:f.email, dept:f.dept, role:f.role, status:'invited', last:'—', joined:TODAY });
    toast(lang === 'vi' ? 'Đã gửi lời mời tới ' + f.email : 'Invite sent to ' + f.email, 'success'); onClose();
  };
  return (
    <Modal title={t('us.invite')} width={500} onClose={onClose}
      footer={<><button className="btn" onClick={onClose}>{t('c.cancel')}</button><button className="btn btn-primary" onClick={create}><i className="bi bi-send"></i>{lang === 'vi' ? 'Gửi lời mời' : 'Send invite'}</button></>}>
      <div className="col g16">
        <Field label={t('us.name')}><input className="input" autoFocus value={f.name} onChange={e => set('name', e.target.value)} placeholder={lang === 'vi' ? 'Họ và tên' : 'Full name'} /></Field>
        <Field label={t('us.email')}><input className="input mono" value={f.email} onChange={e => set('email', e.target.value)} placeholder="ten@swo.vn" /></Field>
        <div className="flex g12">
          <div style={{ flex:1 }}><Field label={t('us.dept')}><select className="select" value={f.dept} onChange={e => set('dept', e.target.value)}>{DEPARTMENTS.map(d => <option key={d.id} value={d.id}>{d[lang]}</option>)}</select></Field></div>
          <div style={{ flex:1 }}><Field label={t('us.role')}><select className="select" value={f.role} onChange={e => set('role', e.target.value)}>{p.roles.map(r => <option key={r.id} value={r.id}>{r.name[lang]}</option>)}</select></Field></div>
        </div>
      </div>
    </Modal>
  );
}

function UserWidget(){
  const p = usePortal();
  const { t, lang } = useLang();
  const us = p.accounts;
  return (
    <WidgetShell wid="users" icon="bi-people" iconColor="#0B4FBF" title={t('us.title')}
      onViewAll={() => p.openApp(US_APP)} onNew={() => p.quick('users')} newLabel={t('us.invite')} newIcon="bi-person-plus">
        <div className="flex g16" style={{ marginBottom:8 }}>
          <div><div className="k-val" style={{ fontSize:'var(--fs-2xl)', fontWeight:700 }}>{us.length}</div><div className="subtle" style={{ fontSize:'var(--fs-sm)' }}>{t('us.members')}</div></div>
          <div><div className="k-val" style={{ fontSize:'var(--fs-2xl)', fontWeight:700, color:'var(--success)' }}>{us.filter(u => u.status === 'active').length}</div><div className="subtle" style={{ fontSize:'var(--fs-sm)' }}>{USER_STATUS.active[lang]}</div></div>
        </div>
        {us.slice(0, 3).map(u => { const r = roleOf(u.role, p.roles); return (
          <div key={u.id} className="list-row" style={{ cursor:'pointer' }} onClick={() => p.navigate({ name:'module', module:'users', sub:'detail', id:u.id })}>
            <Avatar name={u.name} size={22} color={r.color} /><span className="grow truncate">{u.name}</span><UsRoleBadge role={r} />
          </div>
        ); })}
    </WidgetShell>
  );
}

Object.assign(window, { UserModule, InviteUserModal, UserWidget });
