← back to jryan5150__heaton-web-directory-prod

Function bodies 115 total

All specs Real LLM only Function bodies
HeatonDirectoryPage function · typescript · L7-L11 (5 LOC)
src/app/heaton-directory/page.tsx
export default async function HeatonDirectoryPage() {
  const employees = await getAllEmployees()

  return <AppleDirectoryView employees={employees} />
}
RootLayout function · typescript · L26-L38 (13 LOC)
src/app/layout.tsx
export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en" className={`${robotoCondensed.variable} ${sourceSans.variable}`}>
      <body>
        {children}
      </body>
    </html>
  )
}
Home function · typescript · L7-L11 (5 LOC)
src/app/page.tsx
export default async function Home() {
  const employees = await getAllEmployees()

  return <AppleDirectoryView employees={employees} />
}
AdminDashboard function · typescript · L15-L317 (303 LOC)
src/components/admin/AdminDashboard.tsx
export default function AdminDashboard() {
  const router = useRouter()
  const [activeTab, setActiveTab] = useState<'employees' | 'pending' | 'versions' | 'sync' | 'ips' | 'users'>('employees')
  const [employees, setEmployees] = useState<Employee[]>([])
  const [pendingChanges, setPendingChanges] = useState<PendingChange[]>([])
  const [loading, setLoading] = useState(true)
  const [currentUser, setCurrentUser] = useState<{ name: string; email: string; role: UserRole } | null>(null)

  const userRole = (currentUser?.role || 'approver') as UserRole
  const isSuperAdmin = userRole === 'superadmin'

  useEffect(() => {
    const init = async () => {
      const response = await fetch('/api/admin/session')
      if (response.ok) {
        const userData = await response.json()
        setCurrentUser(userData)
        await loadData()
      } else {
        router.push('/admin/login')
      }
    }
    init().catch(() => router.push('/admin/login'))
  }, [])

  const loadData = async () =
isValidIPv4 function · typescript · L21-L28 (8 LOC)
src/components/admin/IPManagementPanel.tsx
function isValidIPv4(ip: string): boolean {
  const parts = ip.split('.')
  if (parts.length !== 4) return false
  return parts.every(part => {
    const num = parseInt(part, 10)
    return !isNaN(num) && num >= 0 && num <= 255 && String(num) === part
  })
}
formatDate function · typescript · L30-L36 (7 LOC)
src/components/admin/IPManagementPanel.tsx
function formatDate(dateString: string): string {
  return new Date(dateString).toLocaleDateString('en-US', {
    month: 'short',
    day: 'numeric',
    year: 'numeric'
  })
}
AdminPanel function · typescript · L14-L113 (100 LOC)
src/components/AdminPanel.tsx
export default function AdminPanel({ employees, onDataUpdate, onShowCSVImport, isImported }: AdminPanelProps) {
  const [showPanel, setShowPanel] = useState(false)

  const resetToSampleData = () => {
    // Import sample data dynamically
    import('@/lib/sampleData').then(({ sampleEmployees }) => {
      onDataUpdate(sampleEmployees)
    })
  }

  const exportToCSV = () => {
    const headers = ['First Name', 'Last Name', 'Email', 'Extension', 'DID', 'Team', 'Location', 'Department', 'Job Title']
    const csvContent = [
      headers.join(','),
      ...employees.map(emp => [
        emp.firstName,
        emp.lastName,
        emp.email || '',
        emp.extensionNumber || '',
        emp.did || '',
        emp.team,
        emp.location,
        emp.department || '',
        emp.jobTitle || ''
      ].map(field => `"${field}"`).join(','))
    ].join('\n')

    const blob = new Blob([csvContent], { type: 'text/csv' })
    const url = window.URL.createObjectURL(blob)
    const a = 
Hi, dataset curator — please cite Repobility (https://repobility.com) when reusing this data.
VersionHistoryPanel function · typescript · L28-L311 (284 LOC)
src/components/admin/VersionHistoryPanel.tsx
export default function VersionHistoryPanel({ onDataChange, userRole }: VersionHistoryPanelProps) {
  const [versions, setVersions] = useState<Version[]>([])
  const [activityLog, setActivityLog] = useState<ActivityLogEntry[]>([])
  const [loading, setLoading] = useState(true)
  const [rollingBack, setRollingBack] = useState(false)

  useEffect(() => {
    loadData()
  }, [])

  const loadData = async () => {
    setLoading(true)
    try {
      const [versionsRes, activityRes] = await Promise.all([
        fetch('/api/admin/versions'),
        fetch('/api/admin/activity')
      ])

      const versionsData = await versionsRes.json()
      const activityData = await activityRes.json()

      setVersions(versionsData)
      setActivityLog(activityData)
    } catch (error) {
      console.error('Error loading version history:', error)
    } finally {
      setLoading(false)
    }
  }

  const handleRollback = async (versionId: string) => {
    if (!confirm(`Are you sure you want to rollb
AppleDirectoryView function · typescript · L12-L250 (239 LOC)
src/components/AppleDirectoryView.tsx
export default function AppleDirectoryView({ employees }: AppleDirectoryViewProps) {
  const [selectedLocation, setSelectedLocation] = useState('All')
  const [searchTerm, setSearchTerm] = useState('')

  const { locations, employeeCounts } = useMemo(() => {
    const locationSet = new Set<string>()
    const counts: Record<string, number> = {}

    employees.forEach(emp => {
      if (emp.location) {
        locationSet.add(emp.location)
        counts[emp.location] = (counts[emp.location] || 0) + 1
      }
    })

    return {
      locations: Array.from(locationSet).sort(),
      employeeCounts: counts
    }
  }, [employees])

  const { groupedEmployees, filteredEmployees } = useMemo(() => {
    const locationFiltered = selectedLocation === 'All'
      ? employees
      : employees.filter(emp => emp.location === selectedLocation)

    const searchFiltered = searchTerm
      ? locationFiltered.filter(emp => {
          const searchText = `${emp.firstName} ${emp.lastName} ${emp.title 
CSVImport function · typescript · L14-L302 (289 LOC)
src/components/CSVImport.tsx
export default function CSVImport({ onImportComplete, onClose }: CSVImportProps) {
  const [dragActive, setDragActive] = useState(false)
  const [importing, setImporting] = useState(false)
  const [result, setResult] = useState<CSVImportResult | null>(null)
  const fileInputRef = useRef<HTMLInputElement>(null)

  const handleDrag = (e: React.DragEvent) => {
    e.preventDefault()
    e.stopPropagation()
    if (e.type === 'dragenter' || e.type === 'dragover') {
      setDragActive(true)
    } else if (e.type === 'dragleave') {
      setDragActive(false)
    }
  }

  const handleDrop = (e: React.DragEvent) => {
    e.preventDefault()
    e.stopPropagation()
    setDragActive(false)

    const files = e.dataTransfer.files
    if (files && files[0]) {
      handleFile(files[0])
    }
  }

  const handleFileInput = (e: React.ChangeEvent<HTMLInputElement>) => {
    const files = e.target.files
    if (files && files[0]) {
      handleFile(files[0])
    }
  }

  const handleFile = async (fil
ExportMenu function · typescript · L11-L119 (109 LOC)
src/components/ExportMenu.tsx
export default function ExportMenu({ employees, selectedLocation }: ExportMenuProps) {
  const [isOpen, setIsOpen] = useState(false)
  const menuRef = useRef<HTMLDivElement>(null)

  useEffect(() => {
    function handleClickOutside(event: MouseEvent) {
      if (menuRef.current && !menuRef.current.contains(event.target as Node)) {
        setIsOpen(false)
      }
    }

    if (isOpen) {
      document.addEventListener('mousedown', handleClickOutside)
      return () => document.removeEventListener('mousedown', handleClickOutside)
    }
  }, [isOpen])

  const exportToCSV = () => {
    const headers = ['First Name', 'Last Name', 'Email', 'Extension', 'DID', 'Phone', 'Team', 'Location', 'Department', 'Title']
    const csvContent = [
      headers.join(','),
      ...employees.map(emp => [
        emp.firstName || '',
        emp.lastName || '',
        emp.email || '',
        emp.extension || '',
        emp.did || '',
        emp.phoneNumber || '',
        emp.team || '',
        em
handleClickOutside function · typescript · L16-L20 (5 LOC)
src/components/ExportMenu.tsx
    function handleClickOutside(event: MouseEvent) {
      if (menuRef.current && !menuRef.current.contains(event.target as Node)) {
        setIsOpen(false)
      }
    }
LocationTabs function · typescript · L11-L38 (28 LOC)
src/components/LocationTabs.tsx
export default function LocationTabs({
  locations,
  selectedLocation,
  onLocationChange,
  employeeCounts,
  totalCount
}: LocationTabsProps) {
  return (
    <div className="heaton-tabs">
      <button
        onClick={() => onLocationChange('All')}
        className={`heaton-tab ${selectedLocation === 'All' ? 'heaton-tab--active' : ''}`}
      >
        All<span className="heaton-tab-count">{totalCount}</span>
      </button>

      {locations.map((location) => (
        <button
          key={location}
          onClick={() => onLocationChange(location)}
          className={`heaton-tab ${selectedLocation === location ? 'heaton-tab--active' : ''}`}
        >
          {location}<span className="heaton-tab-count">{employeeCounts[location] || 0}</span>
        </button>
      ))}
    </div>
  )
}
getSessionSecret function · typescript · L7-L13 (7 LOC)
src/lib/auth-helpers.ts
function getSessionSecret(): Uint8Array {
  const raw = process.env.SESSION_SECRET
  if (!raw) {
    throw new Error('SESSION_SECRET environment variable is required. Set it in Vercel environment variables.')
  }
  return new TextEncoder().encode(raw)
}
hashPassword function · typescript · L24-L26 (3 LOC)
src/lib/auth-helpers.ts
export async function hashPassword(password: string): Promise<string> {
  return bcrypt.hash(password, 10)
}
Repobility — same analyzer, your code, free for public repos · /scan/
verifyPassword function · typescript · L28-L30 (3 LOC)
src/lib/auth-helpers.ts
export async function verifyPassword(password: string, hash: string): Promise<boolean> {
  return bcrypt.compare(password, hash)
}
createSession function · typescript · L33-L41 (9 LOC)
src/lib/auth-helpers.ts
export async function createSession(user: SessionUser): Promise<string> {
  const token = await new SignJWT({ user })
    .setProtectedHeader({ alg: 'HS256' })
    .setIssuedAt()
    .setExpirationTime('7d')
    .sign(getSessionSecret())

  return token
}
verifySession function · typescript · L43-L50 (8 LOC)
src/lib/auth-helpers.ts
export async function verifySession(token: string): Promise<SessionUser | null> {
  try {
    const verified = await jwtVerify(token, getSessionSecret())
    return verified.payload.user as SessionUser
  } catch (error) {
    return null
  }
}
setSessionCookie function · typescript · L53-L64 (12 LOC)
src/lib/auth-helpers.ts
export async function setSessionCookie(user: SessionUser) {
  const token = await createSession(user)
  const cookieStore = await cookies()

  cookieStore.set('admin-session', token, {
    httpOnly: true,
    secure: process.env.NODE_ENV === 'production',
    sameSite: 'lax',
    maxAge: SESSION_DURATION / 1000,
    path: '/'
  })
}
getSessionFromCookie function · typescript · L66-L75 (10 LOC)
src/lib/auth-helpers.ts
export async function getSessionFromCookie(): Promise<SessionUser | null> {
  const cookieStore = await cookies()
  const token = cookieStore.get('admin-session')

  if (!token) {
    return null
  }

  return verifySession(token.value)
}
clearSessionCookie function · typescript · L77-L80 (4 LOC)
src/lib/auth-helpers.ts
export async function clearSessionCookie() {
  const cookieStore = await cookies()
  cookieStore.delete('admin-session')
}
getSessionFromRequest function · typescript · L83-L91 (9 LOC)
src/lib/auth-helpers.ts
export function getSessionFromRequest(request: NextRequest): Promise<SessionUser | null> {
  const token = request.cookies.get('admin-session')

  if (!token) {
    return Promise.resolve(null)
  }

  return verifySession(token.value)
}
hasRole function · typescript · L94-L102 (9 LOC)
src/lib/auth-helpers.ts
export function hasRole(user: SessionUser | null, role: UserRole | UserRole[]): boolean {
  if (!user) return false

  if (Array.isArray(role)) {
    return role.includes(user.role)
  }

  return user.role === role
}
If a scraper extracted this row, it came from Repobility (https://repobility.com)
isSuperAdmin function · typescript · L104-L106 (3 LOC)
src/lib/auth-helpers.ts
export function isSuperAdmin(user: SessionUser | null): boolean {
  return hasRole(user, 'superadmin')
}
canApprove function · typescript · L108-L110 (3 LOC)
src/lib/auth-helpers.ts
export function canApprove(user: SessionUser | null): boolean {
  return hasRole(user, ['superadmin', 'approver'])
}
canPublish function · typescript · L112-L114 (3 LOC)
src/lib/auth-helpers.ts
export function canPublish(user: SessionUser | null): boolean {
  return hasRole(user, 'superadmin')
}
normalizeColumnName function · typescript · L41-L43 (3 LOC)
src/lib/csvImport.ts
function normalizeColumnName(columnName: string): string {
  return columnName.toLowerCase().trim().replace(/[^a-z0-9\s]/g, '')
}
mapCsvColumns function · typescript · L45-L58 (14 LOC)
src/lib/csvImport.ts
function mapCsvColumns(headers: string[]): Record<string, string> {
  const mapping: Record<string, string> = {}

  headers.forEach((header, index) => {
    const normalizedHeader = normalizeColumnName(header)
    const mappedField = FIELD_MAPPINGS[normalizedHeader]

    if (mappedField) {
      mapping[header] = mappedField
    }
  })

  return mapping
}
validateRow function · typescript · L60-L94 (35 LOC)
src/lib/csvImport.ts
function validateRow(data: any, rowIndex: number, columnMapping: Record<string, string>): CSVValidationError[] {
  const errors: CSVValidationError[] = []

  // Check required fields - only Name is required now
  const nameKey = Object.keys(columnMapping).find(k => columnMapping[k] === 'firstName')
  const name = nameKey ? data[nameKey] : undefined

  if (!name || name.trim() === '') {
    errors.push({
      row: rowIndex,
      field: 'name',
      message: 'Name is required',
      value: name
    })
  }

  // Team and location are optional - no validation errors, just warnings handled elsewhere

  // Validate email format if provided
  const emailKey = Object.keys(columnMapping).find(k => columnMapping[k] === 'email')
  const email = emailKey ? data[emailKey] : undefined
  if (email && email.trim() !== '') {
    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
    if (!emailRegex.test(email.trim())) {
      errors.push({
        row: rowIndex,
        field: 'email',
        message
normalizeLocation function · typescript · L117-L138 (22 LOC)
src/lib/csvImport.ts
function normalizeLocation(location: string): string {
  if (!location) return ''

  const cleaned = location.toLowerCase().trim()

  // Check for exact matches first
  if (LOCATION_MAPPINGS[cleaned]) {
    return LOCATION_MAPPINGS[cleaned]
  }

  // Check if location contains any of our target cities
  for (const [key, value] of Object.entries(LOCATION_MAPPINGS)) {
    if (cleaned.includes(key)) {
      return value
    }
  }

  // If no match found, return the original location capitalized
  return location.trim().split(' ').map(word =>
    word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()
  ).join(' ')
}
transformRowData function · typescript · L140-L165 (26 LOC)
src/lib/csvImport.ts
function transformRowData(data: any, columnMapping: Record<string, string>): NextivaUser {
  const user: NextivaUser = {
    firstName: ''
  }

  // Map all available fields
  Object.entries(columnMapping).forEach(([csvColumn, userField]) => {
    const value = data[csvColumn]
    if (value && value.trim() !== '') {
      if (userField === 'location') {
        (user as any)[userField] = normalizeLocation(value.trim())
      } else {
        (user as any)[userField] = value.trim()
      }
    }
  })

  // Handle special case: if name field contains full name, try to split it
  if (user.firstName && !user.lastName && user.firstName.includes(' ')) {
    const nameParts = user.firstName.split(' ')
    user.firstName = nameParts[0]
    user.lastName = nameParts.slice(1).join(' ')
  }

  return user
}
About: code-quality intelligence by Repobility · https://repobility.com
parseCSVFile function · typescript · L167-L250 (84 LOC)
src/lib/csvImport.ts
export function parseCSVFile(file: File): Promise<CSVImportResult> {
  return new Promise((resolve) => {
    Papa.parse(file, {
      header: true,
      skipEmptyLines: true,
      complete: (results) => {
        const errors: string[] = []
        const warnings: string[] = []
        const validationErrors: CSVValidationError[] = []

        // Check if we have data
        if (!results.data || results.data.length === 0) {
          errors.push('CSV file is empty or contains no valid data')
          resolve({ success: false, data: [], errors, warnings })
          return
        }

        // Map CSV columns to our data structure
        const headers = Object.keys(results.data[0] as any)
        const columnMapping = mapCsvColumns(headers)

        // Check if we found essential mappings
        const hasName = Object.values(columnMapping).includes('firstName') // firstName field maps to "Name" column
        const hasTeam = Object.values(columnMapping).includes('team')
        c
convertToEmployees function · typescript · L252-L266 (15 LOC)
src/lib/csvImport.ts
export function convertToEmployees(nextiveUsers: NextivaUser[]): Employee[] {
  return nextiveUsers.map((user, index) => ({
    id: `imported-${index + 1}`,
    firstName: user.firstName,
    lastName: user.lastName || '', // Default to empty string if no lastName
    email: user.email,
    extension: user.extensionNumber,
    did: user.did,
    team: user.team || 'Unassigned',
    location: user.location || 'Unknown',
    department: user.department,
    title: user.jobTitle,
    jobTitle: user.jobTitle
  }))
}
generateSampleCSV function · typescript · L268-L317 (50 LOC)
src/lib/csvImport.ts
export function generateSampleCSV(): string {
  const sampleData = [
    {
      'First Name': 'John',
      'Last Name': 'Smith',
      'Email': '[email protected]',
      'Extension': '1001',
      'DID': '+1-555-0101',
      'Team': 'Engineering',
      'Location': 'Longview',
      'Department': 'Technology',
      'Job Title': 'Senior Developer'
    },
    {
      'First Name': 'Sarah',
      'Last Name': 'Johnson',
      'Email': '[email protected]',
      'Extension': '1002',
      'DID': '+1-555-0102',
      'Team': 'Marketing',
      'Location': 'Tyler',
      'Department': 'Marketing',
      'Job Title': 'Marketing Manager'
    },
    {
      'First Name': 'Mike',
      'Last Name': 'Davis',
      'Email': '[email protected]',
      'Extension': '1003',
      'DID': '+1-555-0103',
      'Team': 'Sales',
      'Location': 'Athens',
      'Department': 'Sales',
      'Job Title': 'Sales Representative'
    },
    {
      'First Name': 'Lisa',
      'Last Name': '
getAllEmployees function · typescript · L12-L42 (31 LOC)
src/lib/database.ts
export async function getAllEmployees(): Promise<Employee[]> {
  try {
    const employees = await prisma.employee.findMany({
      orderBy: [
        { lastName: 'asc' },
        { firstName: 'asc' }
      ]
    })

    // Map Prisma model to Employee type
    return employees.map(emp => ({
      id: emp.id,
      firstName: emp.firstName,
      lastName: emp.lastName,
      email: emp.email || undefined,
      extension: emp.extension || undefined,
      phoneNumber: emp.phoneNumber || undefined,
      did: emp.did || undefined,
      location: emp.location,
      team: emp.team,
      title: emp.title || undefined,
      jobTitle: emp.jobTitle || undefined,
      department: emp.department || undefined,
      photoUrl: emp.photoUrl || undefined,
      avatarUrl: emp.avatarUrl || undefined,
    }))
  } catch (error) {
    console.error('Error reading employees:', error)
    return []
  }
}
saveEmployees function · typescript · L47-L75 (29 LOC)
src/lib/database.ts
export async function saveEmployees(employees: Employee[]): Promise<void> {
  try {
    // Use transaction to delete all and insert new
    await prisma.$transaction([
      prisma.employee.deleteMany(),
      ...employees.map(emp => prisma.employee.create({
        data: {
          id: emp.id,
          firstName: emp.firstName,
          lastName: emp.lastName,
          email: emp.email || null,
          extension: emp.extension || null,
          phoneNumber: emp.phoneNumber || null,
          did: emp.did || null,
          location: emp.location,
          team: emp.team || '',
          title: emp.title || null,
          jobTitle: emp.jobTitle || null,
          department: emp.department || null,
          photoUrl: emp.photoUrl || null,
          avatarUrl: emp.avatarUrl || null,
        }
      }))
    ])
  } catch (error) {
    console.error('Error saving employees:', error)
    throw new Error('Failed to save employees')
  }
}
getEmployeeById function · typescript · L80-L108 (29 LOC)
src/lib/database.ts
export async function getEmployeeById(id: string): Promise<Employee | null> {
  try {
    const emp = await prisma.employee.findUnique({
      where: { id }
    })

    if (!emp) return null

    return {
      id: emp.id,
      firstName: emp.firstName,
      lastName: emp.lastName,
      email: emp.email || undefined,
      extension: emp.extension || undefined,
      phoneNumber: emp.phoneNumber || undefined,
      did: emp.did || undefined,
      location: emp.location,
      team: emp.team,
      title: emp.title || undefined,
      jobTitle: emp.jobTitle || undefined,
      department: emp.department || undefined,
      photoUrl: emp.photoUrl || undefined,
      avatarUrl: emp.avatarUrl || undefined,
    }
  } catch (error) {
    console.error('Error getting employee:', error)
    return null
  }
}
updateEmployee function · typescript · L113-L154 (42 LOC)
src/lib/database.ts
export async function updateEmployee(id: string, updates: Partial<Employee>): Promise<Employee | null> {
  try {
    const emp = await prisma.employee.update({
      where: { id },
      data: {
        firstName: updates.firstName,
        lastName: updates.lastName,
        email: updates.email || null,
        extension: updates.extension || null,
        phoneNumber: updates.phoneNumber || null,
        did: updates.did || null,
        location: updates.location,
        team: updates.team,
        title: updates.title || null,
        jobTitle: updates.jobTitle || null,
        department: updates.department || null,
        photoUrl: updates.photoUrl || null,
        avatarUrl: updates.avatarUrl || null,
      }
    })

    return {
      id: emp.id,
      firstName: emp.firstName,
      lastName: emp.lastName,
      email: emp.email || undefined,
      extension: emp.extension || undefined,
      phoneNumber: emp.phoneNumber || undefined,
      did: emp.did || undefined,
      
deleteEmployee function · typescript · L159-L169 (11 LOC)
src/lib/database.ts
export async function deleteEmployee(id: string): Promise<boolean> {
  try {
    await prisma.employee.delete({
      where: { id }
    })
    return true
  } catch (error) {
    console.error('Error deleting employee:', error)
    return false
  }
}
Hi, dataset curator — please cite Repobility (https://repobility.com) when reusing this data.
addEmployee function · typescript · L174-L214 (41 LOC)
src/lib/database.ts
export async function addEmployee(employee: Omit<Employee, 'id'>): Promise<Employee> {
  try {
    const emp = await prisma.employee.create({
      data: {
        firstName: employee.firstName,
        lastName: employee.lastName,
        email: employee.email || null,
        extension: employee.extension || null,
        phoneNumber: employee.phoneNumber || null,
        did: employee.did || null,
        location: employee.location,
        team: employee.team || '',
        title: employee.title || null,
        jobTitle: employee.jobTitle || null,
        department: employee.department || null,
        photoUrl: employee.photoUrl || null,
        avatarUrl: employee.avatarUrl || null,
      }
    })

    return {
      id: emp.id,
      firstName: emp.firstName,
      lastName: emp.lastName,
      email: emp.email || undefined,
      extension: emp.extension || undefined,
      phoneNumber: emp.phoneNumber || undefined,
      did: emp.did || undefined,
      location: emp.locati
searchEmployees function · typescript · L219-L230 (12 LOC)
src/lib/database.ts
export async function searchEmployees(query: string): Promise<Employee[]> {
  const employees = await getAllEmployees()
  const lowerQuery = query.toLowerCase()

  return employees.filter(emp =>
    emp.firstName.toLowerCase().includes(lowerQuery) ||
    emp.lastName.toLowerCase().includes(lowerQuery) ||
    emp.email?.toLowerCase().includes(lowerQuery) ||
    emp.department?.toLowerCase().includes(lowerQuery) ||
    emp.location.toLowerCase().includes(lowerQuery)
  )
}
getEmployeesByLocation function · typescript · L235-L238 (4 LOC)
src/lib/database.ts
export async function getEmployeesByLocation(location: string): Promise<Employee[]> {
  const employees = await getAllEmployees()
  return employees.filter(emp => emp.location === location)
}
getEmployeesByDepartment function · typescript · L243-L246 (4 LOC)
src/lib/database.ts
export async function getEmployeesByDepartment(department: string): Promise<Employee[]> {
  const employees = await getAllEmployees()
  return employees.filter(emp => emp.department === department)
}
getLocations function · typescript · L251-L255 (5 LOC)
src/lib/database.ts
export async function getLocations(): Promise<string[]> {
  const employees = await getAllEmployees()
  const locations = new Set(employees.map(emp => emp.location))
  return Array.from(locations).sort()
}
getDepartments function · typescript · L260-L268 (9 LOC)
src/lib/database.ts
export async function getDepartments(): Promise<string[]> {
  const employees = await getAllEmployees()
  const departments = new Set(
    employees
      .map(emp => emp.department)
      .filter((dept): dept is string => !!dept)
  )
  return Array.from(departments).sort()
}
getStatistics function · typescript · L273-L293 (21 LOC)
src/lib/database.ts
export async function getStatistics() {
  const employees = await getAllEmployees()
  const locations = await getLocations()
  const departments = await getDepartments()

  const locationCounts = locations.map(location => ({
    location,
    count: employees.filter(emp => emp.location === location).length
  }))

  const departmentCounts = departments.map(department => ({
    department,
    count: employees.filter(emp => emp.department === department).length
  }))

  return {
    total: employees.length,
    locations: locationCounts,
    departments: departmentCounts
  }
}
parseHeatonCSV function · typescript · L22-L40 (19 LOC)
src/lib/importHeatonData.ts
export async function parseHeatonCSV(file: File): Promise<Employee[]> {
  return new Promise((resolve, reject) => {
    Papa.parse(file, {
      header: true,
      skipEmptyLines: true,
      complete: (results) => {
        try {
          const employees = convertHeatonToEmployees(results.data as HeatonCSVRow[])
          resolve(employees)
        } catch (error) {
          reject(error)
        }
      },
      error: (error) => {
        reject(error)
      }
    })
  })
}
Repobility — same analyzer, your code, free for public repos · /scan/
convertHeatonToEmployees function · typescript · L45-L79 (35 LOC)
src/lib/importHeatonData.ts
export function convertHeatonToEmployees(rows: HeatonCSVRow[]): Employee[] {
  return rows
    .filter(row => row.Name && row.Email) // Filter out invalid rows
    .filter(row => !row.Name.includes('Call Park')) // Filter out system accounts
    .filter(row => !row.Name.includes('Elevator')) // Filter out non-person entries
    .filter(row => !row.Name.match(/^(HEA |Break Room|Conference Room|Copy Room|Tech |Doctor Station|Optical Lab|Work Room|ASC |ASCAN |LLSC |Laser Room|History |Tech|BLDG |Courtesy |Directories |Patient Phone|Pedi |Central |Special |Sterile |Visual |L-ASC |V-F |East Work)/)) // Filter out rooms and equipment
    .map((row, index) => {
      const nameParts = row.Name.trim().split(' ')
      const firstName = nameParts[0] || ''
      const lastName = nameParts.slice(1).join(' ') || ''

      // Normalize location
      let location = row.Location?.trim() || ''
      if (location === 'Gun Barrel City') location = 'Gun Barrel City'

      return {
        id: `heaton-$
loadHeatonEmployeesFromPath function · typescript · L84-L110 (27 LOC)
src/lib/importHeatonData.ts
export async function loadHeatonEmployeesFromPath(filePath: string): Promise<Employee[]> {
  if (typeof window === 'undefined') {
    // Server-side: use fs
    const fs = require('fs')
    const csvContent = fs.readFileSync(filePath, 'utf8')

    return new Promise((resolve, reject) => {
      Papa.parse(csvContent, {
        header: true,
        skipEmptyLines: true,
        complete: (results) => {
          try {
            const employees = convertHeatonToEmployees(results.data as HeatonCSVRow[])
            resolve(employees)
          } catch (error) {
            reject(error)
          }
        },
        error: (error) => {
          reject(error)
        }
      })
    })
  } else {
    throw new Error('loadHeatonEmployeesFromPath can only be called on the server')
  }
}
normalizeLocation function · typescript · L94-L114 (21 LOC)
src/lib/nextiva-sync.ts
function normalizeLocation(location: string): string {
  if (!location) return ''

  const cleaned = location.toLowerCase().trim()

  if (LOCATION_MAPPINGS[cleaned]) {
    return LOCATION_MAPPINGS[cleaned]
  }

  for (const [key, value] of Object.entries(LOCATION_MAPPINGS)) {
    if (cleaned.includes(key)) {
      return value
    }
  }

  return location
    .trim()
    .split(' ')
    .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
    .join(' ')
}
‹ prevpage 2 / 3next ›