101 lines
5.5 KiB
TypeScript
101 lines
5.5 KiB
TypeScript
export const EMPLOYEE_DIRECTORY_APP = {
|
|
id: 'employee-directory',
|
|
name: 'Employee Directory',
|
|
description: 'Searchable directory of all employees with filters and contact information',
|
|
html: `<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<title>Employee Directory - Gusto</title>
|
|
<script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
|
|
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
|
|
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
|
|
<style>
|
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: #f5f5f5; padding: 20px; }
|
|
.container { max-width: 1200px; margin: 0 auto; }
|
|
.header { background: white; padding: 24px; border-radius: 8px; margin-bottom: 24px; box-shadow: 0 1px 3px rgba(0,0,0,0.1); }
|
|
.search-bar { width: 100%; padding: 12px; border: 1px solid #ddd; border-radius: 6px; font-size: 16px; margin-bottom: 16px; }
|
|
.filters { display: flex; gap: 12px; }
|
|
.filter-btn { padding: 8px 16px; background: white; border: 1px solid #ddd; border-radius: 6px; cursor: pointer; }
|
|
.filter-btn.active { background: #ff6b35; color: white; border-color: #ff6b35; }
|
|
.directory-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 20px; }
|
|
.employee-card { background: white; padding: 20px; border-radius: 8px; box-shadow: 0 1px 3px rgba(0,0,0,0.1); }
|
|
.employee-card:hover { box-shadow: 0 4px 12px rgba(0,0,0,0.15); }
|
|
.avatar { width: 60px; height: 60px; border-radius: 50%; background: linear-gradient(135deg, #ff6b35, #f7931e); margin-bottom: 12px; display: flex; align-items: center; justify-content: center; color: white; font-size: 24px; font-weight: bold; }
|
|
.name { font-size: 18px; font-weight: 600; color: #333; margin-bottom: 4px; }
|
|
.role { color: #666; font-size: 14px; margin-bottom: 12px; }
|
|
.contact { font-size: 14px; color: #666; margin-top: 8px; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div id="root"></div>
|
|
<script type="text/babel">
|
|
const { useState } = React;
|
|
|
|
function EmployeeDirectory() {
|
|
const [searchTerm, setSearchTerm] = useState('');
|
|
const [activeFilter, setActiveFilter] = useState('all');
|
|
|
|
const employees = [
|
|
{ id: 1, name: 'Sarah Johnson', role: 'Software Engineer', department: 'Engineering', email: 'sarah@company.com', phone: '(555) 123-4567' },
|
|
{ id: 2, name: 'Michael Chen', role: 'Product Manager', department: 'Product', email: 'michael@company.com', phone: '(555) 234-5678' },
|
|
{ id: 3, name: 'Emily Rodriguez', role: 'Marketing Manager', department: 'Marketing', email: 'emily@company.com', phone: '(555) 345-6789' },
|
|
{ id: 4, name: 'David Kim', role: 'Sales Rep', department: 'Sales', email: 'david@company.com', phone: '(555) 456-7890' },
|
|
{ id: 5, name: 'Lisa Wang', role: 'Designer', department: 'Design', email: 'lisa@company.com', phone: '(555) 567-8901' },
|
|
{ id: 6, name: 'James Brown', role: 'DevOps Engineer', department: 'Engineering', email: 'james@company.com', phone: '(555) 678-9012' },
|
|
];
|
|
|
|
const getInitials = (name) => {
|
|
return name.split(' ').map(n => n[0]).join('');
|
|
};
|
|
|
|
const filteredEmployees = employees.filter(emp => {
|
|
const matchesSearch = emp.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
|
emp.role.toLowerCase().includes(searchTerm.toLowerCase());
|
|
const matchesFilter = activeFilter === 'all' || emp.department === activeFilter;
|
|
return matchesSearch && matchesFilter;
|
|
});
|
|
|
|
return (
|
|
<div className="container">
|
|
<div className="header">
|
|
<h1>📖 Employee Directory</h1>
|
|
<p style={{ marginBottom: 16 }}>Search and filter all employees</p>
|
|
<input
|
|
type="text"
|
|
className="search-bar"
|
|
placeholder="Search by name or role..."
|
|
value={searchTerm}
|
|
onChange={(e) => setSearchTerm(e.target.value)}
|
|
/>
|
|
<div className="filters">
|
|
<button className={\`filter-btn \${activeFilter === 'all' ? 'active' : ''}\`} onClick={() => setActiveFilter('all')}>All</button>
|
|
<button className={\`filter-btn \${activeFilter === 'Engineering' ? 'active' : ''}\`} onClick={() => setActiveFilter('Engineering')}>Engineering</button>
|
|
<button className={\`filter-btn \${activeFilter === 'Product' ? 'active' : ''}\`} onClick={() => setActiveFilter('Product')}>Product</button>
|
|
<button className={\`filter-btn \${activeFilter === 'Marketing' ? 'active' : ''}\`} onClick={() => setActiveFilter('Marketing')}>Marketing</button>
|
|
<button className={\`filter-btn \${activeFilter === 'Sales' ? 'active' : ''}\`} onClick={() => setActiveFilter('Sales')}>Sales</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="directory-grid">
|
|
{filteredEmployees.map(emp => (
|
|
<div key={emp.id} className="employee-card">
|
|
<div className="avatar">{getInitials(emp.name)}</div>
|
|
<div className="name">{emp.name}</div>
|
|
<div className="role">{emp.role}</div>
|
|
<div className="contact">📧 {emp.email}</div>
|
|
<div className="contact">📱 {emp.phone}</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
ReactDOM.render(<EmployeeDirectory />, document.getElementById('root'));
|
|
</script>
|
|
</body>
|
|
</html>`,
|
|
};
|