Function bodies 115 total
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 rollbAppleDirectoryView 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 (filExportMenu 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 || '',
emhandleClickOutside 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',
messagenormalizeLocation 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')
cconvertToEmployees 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.locatisearchEmployees 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(' ')
}