{
  "id": "admin-panel-template",
  "name": "Admin Panel Template",
  "category": "software-builder",
  "tags": ["admin", "dashboard", "table", "sidebar", "stats"],
  "description": "Admin dashboard with sidebar navigation, stats cards, and sortable data table.",
  "triggers": ["admin panel", "dashboard", "admin template", "back office", "control panel"],
  "defaultSize": { "w": 6, "h": 5 },
  "source": "const AdminPanelTemplate = () => {\n  const [activeTab, setActiveTab] = React.useState('Dashboard');\n  const [sortCol, setSortCol] = React.useState('date');\n  const [sortAsc, setSortAsc] = React.useState(false);\n\n  const stats = [\n    { label: 'Revenue', value: '$42,350', change: '+12%', up: true },\n    { label: 'Users', value: '8,241', change: '+5%', up: true },\n    { label: 'Orders', value: '1,204', change: '-2%', up: false },\n    { label: 'Bounce', value: '34%', change: '-4%', up: true }\n  ];\n\n  const [rows, setRows] = React.useState([\n    { id: 1, user: 'Alice Chen', email: 'alice@example.com', status: 'Active', role: 'Admin', date: '2025-04-20' },\n    { id: 2, user: 'Bob Smith', email: 'bob@example.com', status: 'Pending', role: 'Editor', date: '2025-04-18' },\n    { id: 3, user: 'Carol Wu', email: 'carol@example.com', status: 'Active', role: 'User', date: '2025-04-22' },\n    { id: 4, user: 'Dan Lopez', email: 'dan@example.com', status: 'Inactive', role: 'User', date: '2025-03-30' },\n    { id: 5, user: 'Eve Park', email: 'eve@example.com', status: 'Active', role: 'Editor', date: '2025-04-21' }\n  ]);\n\n  const navItems = ['Dashboard', 'Users', 'Orders', 'Settings'];\n\n  const handleSort = (col) => {\n    if (sortCol === col) {\n      setSortAsc(!sortAsc);\n    } else {\n      setSortCol(col);\n      setSortAsc(true);\n    }\n  };\n\n  const sortedRows = [...rows].sort((a, b) => {\n    const av = a[sortCol];\n    const bv = b[sortCol];\n    if (av < bv) return sortAsc ? -1 : 1;\n    if (av > bv) return sortAsc ? 1 : -1;\n    return 0;\n  });\n\n  const toggleStatus = (id) => {\n    setRows(prev => prev.map(r => {\n      if (r.id !== id) return r;\n      const next = r.status === 'Active' ? 'Inactive' : r.status === 'Inactive' ? 'Pending' : 'Active';\n      return { ...r, status: next };\n    }));\n  };\n\n  const statusColor = (s) => {\n    if (s === 'Active') return { bg: '#dcfce7', color: '#15803d' };\n    if (s === 'Pending') return { bg: '#fef3c7', color: '#b45309' };\n    return { bg: '#f1f5f9', color: '#64748b' };\n  };\n\n  const styles = {\n    wrapper: {\n      display: 'flex',\n      fontFamily: 'system-ui, -apple-system, sans-serif',\n      minHeight: '100%',\n      background: '#f1f5f9',\n      color: '#1e293b'\n    },\n    sidebar: {\n      width: 200,\n      background: '#0f172a',\n      color: '#e2e8f0',\n      padding: '20px 12px',\n      flexShrink: 0\n    },\n    sidebarTitle: {\n      fontSize: 16,\n      fontWeight: 700,\n      marginBottom: 20,\n      padding: '0 8px'\n    },\n    navItem: (active) => ({\n      padding: '10px 12px',\n      borderRadius: 8,\n      cursor: 'pointer',\n      fontSize: 14,\n      fontWeight: 500,\n      marginBottom: 4,\n      background: active ? '#1e293b' : 'transparent',\n      color: active ? '#fff' : '#94a3b8'\n    }),\n    main: {\n      flex: 1,\n      padding: 24\n    },\n    header: {\n      fontSize: 22,\n      fontWeight: 700,\n      marginBottom: 16\n    },\n    statsGrid: {\n      display: 'grid',\n      gridTemplateColumns: 'repeat(auto-fit, minmax(140px, 1fr))',\n      gap: 16,\n      marginBottom: 20\n    },\n    statCard: {\n      background: '#fff',\n      borderRadius: 12,\n      padding: 16,\n      boxShadow: '0 1px 3px rgba(0,0,0,0.08)',\n      border: '1px solid #e2e8f0'\n    },\n    statValue: {\n      fontSize: 24,\n      fontWeight: 700,\n      color: '#0f172a'\n    },\n    statLabel: {\n      fontSize: 12,\n      color: '#64748b',\n      marginTop: 4,\n      textTransform: 'uppercase',\n      letterSpacing: 0.5\n    },\n    statChange: (up) => ({\n      fontSize: 12,\n      fontWeight: 600,\n      marginTop: 6,\n      color: up ? '#15803d' : '#dc2626'\n    }),\n    card: {\n      background: '#fff',\n      borderRadius: 12,\n      padding: 20,\n      boxShadow: '0 1px 3px rgba(0,0,0,0.08)',\n      border: '1px solid #e2e8f0'\n    },\n    cardTitle: {\n      fontSize: 16,\n      fontWeight: 700,\n      marginBottom: 12\n    },\n    table: {\n      width: '100%',\n      borderCollapse: 'collapse',\n      fontSize: 14\n    },\n    th: {\n      textAlign: 'left',\n      padding: '10px 8px',\n      borderBottom: '2px solid #e2e8f0',\n      color: '#64748b',\n      fontWeight: 600,\n      fontSize: 12,\n      textTransform: 'uppercase',\n      cursor: 'pointer',\n      userSelect: 'none'\n    },\n    td: {\n      padding: '10px 8px',\n      borderBottom: '1px solid #f1f5f9'\n    },\n    badge: (s) => ({\n      display: 'inline-block',\n      padding: '3px 10px',\n      borderRadius: 999,\n      fontSize: 11,\n      fontWeight: 600,\n      background: statusColor(s).bg,\n      color: statusColor(s).color,\n      cursor: 'pointer'\n    })\n  };\n\n  return (\n    <div style={styles.wrapper}>\n      <div style={styles.sidebar}>\n        <div style={styles.sidebarTitle}>\u25C8 Titan Admin</div>\n        {navItems.map(item => (\n          <div\n            key={item}\n            style={styles.navItem(activeTab === item)}\n            onClick={() => setActiveTab(item)}\n          >\n            {item}\n          </div>\n        ))}\n      </div>\n\n      <div style={styles.main}>\n        <div style={styles.header}>{activeTab}</div>\n\n        <div style={styles.statsGrid}>\n          {stats.map(s => (\n            <div key={s.label} style={styles.statCard}>\n              <div style={styles.statLabel}>{s.label}</div>\n              <div style={styles.statValue}>{s.value}</div>\n              <div style={styles.statChange(s.up)}>{s.change} vs last month</div>\n            </div>\n          ))}\n        </div>\n\n        <div style={styles.card}>\n          <div style={styles.cardTitle}>Recent Users</div>\n          <table style={styles.table}>\n            <thead>\n              <tr>\n                <th style={styles.th} onClick={() => handleSort('user')}>User {sortCol === 'user' ? (sortAsc ? '\u2191' : '\u2193') : ''}</th>\n                <th style={styles.th} onClick={() => handleSort('role')}>Role {sortCol === 'role' ? (sortAsc ? '\u2191' : '\u2193') : ''}</th>\n                <th style={styles.th} onClick={() => handleSort('status')}>Status {sortCol === 'status' ? (sortAsc ? '\u2191' : '\u2193') : ''}</th>\n                <th style={styles.th} onClick={() => handleSort('date')}>Joined {sortCol === 'date' ? (sortAsc ? '\u2191' : '\u2193') : ''}</th>\n              </tr>\n            </thead>\n            <tbody>\n              {sortedRows.map(row => (\n                <tr key={row.id}>\n                  <td style={styles.td}>\n                    <div style={{ fontWeight: 600 }}>{row.user}</div>\n                    <div style={{ fontSize: 12, color: '#64748b' }}>{row.email}</div>\n                  </td>\n                  <td style={styles.td}>{row.role}</td>\n                  <td style={styles.td}>\n                    <span style={styles.badge(row.status)} onClick={() => toggleStatus(row.id)}>\n                      {row.status}\n                    </span>\n                  </td>\n                  <td style={styles.td}>{row.date}</td>\n                </tr>\n              ))}\n            </tbody>\n          </table>\n        </div>\n      </div>\n    </div>\n  );\n};\nrender(<AdminPanelTemplate/>);",
  "placeholders": [{ "name": "REPLACE_WITH_COMPANY_NAME", "description": "Company name shown in the sidebar header", "default": "Titan Admin" }]
}
