import React,{useState,useMemo,useTransition,useEffect}from'react';interface SObject{id:string;name:string;label:string;fields:number;records:number;customizable:boolean}const useDebounce=<T,>(value:T,delay:number):T=>{const[debouncedValue,setDebouncedValue]=useState(value);useEffect(()=>{const handler=setTimeout(()=>setDebouncedValue(value),delay);return()=>clearTimeout(handler)},[value,delay]);return debouncedValue};const useToast=()=>{const[toasts,setToasts]=useState<Array<{id:number;message:string}>>([]);const show=(message:string)=>{const id=Date.now();setToasts(prev=>[...prev,{id,message}]);setTimeout(()=>setToasts(prev=>prev.filter(t=>t.id!==id)),3000)};return{toasts,show}};const mockObjects:SObject[]=[{id:'o001',name:'Account',label:'Account',fields:45,records:1250,customizable:true},{id:'o002',name:'Contact',label:'Contact',fields:38,records:3420,customizable:true},{id:'o003',name:'Opportunity',label:'Opportunity',fields:52,records:892,customizable:true},{id:'o004',name:'Lead',label:'Lead',fields:40,records:567,customizable:true},{id:'o005',name:'Case',label:'Case',fields:42,records:1890,customizable:true}];const App:React.FC=()=>{const[searchQuery,setSearchQuery]=useState('');const[isPending,startTransition]=useTransition();const{toasts,show}=useToast();const debouncedSearch=useDebounce(searchQuery,300);const filteredObjects=useMemo(()=>{return mockObjects.filter(obj=>obj.name.toLowerCase().includes(debouncedSearch.toLowerCase())||obj.label.toLowerCase().includes(debouncedSearch.toLowerCase()))},[debouncedSearch]);const stats=useMemo(()=>({total:mockObjects.length,customizable:mockObjects.filter(o=>o.customizable).length,totalRecords:mockObjects.reduce((sum,o)=>sum+o.records,0),avgFields:Math.round(mockObjects.reduce((sum,o)=>sum+o.fields,0)/mockObjects.length)}),[]);const handleSearch=(e:React.ChangeEvent<HTMLInputElement>)=>{startTransition(()=>{setSearchQuery(e.target.value)})};const handleExplore=(obj:SObject)=>{show(`Exploring ${obj.label}`)};return(<div className="app-container"><header className="app-header"><h1>Object Explorer</h1><p>Browse SObjects, describe fields, view records</p></header><div className="stats-grid"><div className="stat-card"><div className="stat-label">Total Objects</div><div className="stat-value">{stats.total}</div></div><div className="stat-card"><div className="stat-label">Customizable</div><div className="stat-value">{stats.customizable}</div></div><div className="stat-card"><div className="stat-label">Total Records</div><div className="stat-value">{(stats.totalRecords/1000).toFixed(1)}K</div></div><div className="stat-card"><div className="stat-label">Avg Fields</div><div className="stat-value">{stats.avgFields}</div></div></div><div className="controls"><input type="text" placeholder="Search objects..." value={searchQuery} onChange={handleSearch} className="search-input"/></div>{filteredObjects.length===0?(<div className="empty-state"><div className="empty-icon">🔍</div><h3>No objects found</h3><p>Try adjusting your search</p></div>):(<div className="data-grid"><table><thead><tr><th>Object Name</th><th>Label</th><th>Fields</th><th>Records</th><th>Customizable</th><th>Actions</th></tr></thead><tbody className={isPending?'loading':''}>{filteredObjects.map(obj=>(<tr key={obj.id}><td><strong>{obj.name}</strong></td><td>{obj.label}</td><td>{obj.fields}</td><td>{obj.records.toLocaleString()}</td><td>{obj.customizable?'✓':'✗'}</td><td><button className="btn-primary" onClick={()=>handleExplore(obj)}>Explore</button></td></tr>))}</tbody></table></div>)}<div className="toast-container">{toasts.map(toast=>(<div key={toast.id} className="toast">{toast.message}</div>))}</div></div>)};export default App;
