160 lines
5.7 KiB
TypeScript
160 lines
5.7 KiB
TypeScript
import {
|
|
User,
|
|
Mail,
|
|
Phone,
|
|
Briefcase,
|
|
Building2,
|
|
Clock,
|
|
MapPin,
|
|
Calendar,
|
|
BadgeCheck,
|
|
CircleDot,
|
|
} from "lucide-react"
|
|
import {
|
|
Card,
|
|
CardContent,
|
|
CardHeader,
|
|
CardTitle,
|
|
} from "@/shared/components/ui/card"
|
|
import { Badge } from "@/shared/components/ui/badge"
|
|
import { Separator } from "@/shared/components/ui/separator"
|
|
|
|
type EmployeeData = {
|
|
id?: number
|
|
type?: string
|
|
first_name?: string
|
|
last_name?: string
|
|
email?: string
|
|
phone?: string
|
|
position?: string
|
|
designation?: string
|
|
salary?: string
|
|
wage_type?: string
|
|
status?: string
|
|
track_attendance?: boolean
|
|
notify_owner_when_punch_in_out?: boolean
|
|
geo_fence_radius?: string | number | null
|
|
department?: { id?: number; name?: string } | null
|
|
shop_calender?: { id?: number; title?: string } | null
|
|
shop_timing?: { id?: number; title?: string } | null
|
|
created_at?: string
|
|
updated_at?: string
|
|
}
|
|
|
|
type EmployeeGeneralInfoProps = {
|
|
employee: EmployeeData
|
|
}
|
|
|
|
function InfoItem({
|
|
icon: Icon,
|
|
label,
|
|
value,
|
|
}: {
|
|
icon: React.ComponentType<{ className?: string }>
|
|
label: string
|
|
value?: string | null
|
|
}) {
|
|
return (
|
|
<div className="flex items-start gap-3">
|
|
<div className="flex size-9 shrink-0 items-center justify-center rounded-lg bg-muted text-muted-foreground">
|
|
<Icon className="size-4" />
|
|
</div>
|
|
<div className="flex flex-col gap-0.5">
|
|
<span className="text-xs text-muted-foreground">{label}</span>
|
|
<span className="text-sm font-medium">
|
|
{value || <span className="text-muted-foreground">—</span>}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export function EmployeeGeneralInfo({ employee }: EmployeeGeneralInfoProps) {
|
|
const fullName = [employee.first_name, employee.last_name].filter(Boolean).join(" ")
|
|
|
|
return (
|
|
<div className="grid gap-6 md:grid-cols-2">
|
|
{/* Personal Information */}
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle className="flex items-center gap-2">
|
|
<User className="size-4" />
|
|
Personal Information
|
|
</CardTitle>
|
|
</CardHeader>
|
|
<CardContent className="grid gap-4">
|
|
<div className="flex flex-wrap items-center gap-2">
|
|
<Badge variant="secondary">{fullName || "Unknown"}</Badge>
|
|
{employee.type && (
|
|
<Badge variant="outline" className="capitalize">
|
|
{employee.type}
|
|
</Badge>
|
|
)}
|
|
{employee.status && (
|
|
<Badge
|
|
variant={employee.status === "active" ? "default" : "secondary"}
|
|
className="capitalize"
|
|
>
|
|
{employee.status}
|
|
</Badge>
|
|
)}
|
|
</div>
|
|
<Separator />
|
|
<div className="grid gap-4 sm:grid-cols-2">
|
|
<InfoItem icon={Mail} label="Email" value={employee.email} />
|
|
<InfoItem icon={Phone} label="Phone" value={employee.phone} />
|
|
<InfoItem icon={Briefcase} label="Position" value={employee.position} />
|
|
<InfoItem icon={BadgeCheck} label="Designation" value={employee.designation} />
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
{/* Work Details */}
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle className="flex items-center gap-2">
|
|
<Building2 className="size-4" />
|
|
Work Details
|
|
</CardTitle>
|
|
</CardHeader>
|
|
<CardContent className="grid gap-4">
|
|
<div className="grid gap-4 sm:grid-cols-2">
|
|
<InfoItem
|
|
icon={Building2}
|
|
label="Department"
|
|
value={employee.department?.name}
|
|
/>
|
|
<InfoItem
|
|
icon={Calendar}
|
|
label="Shop Calendar"
|
|
value={employee.shop_calender?.title}
|
|
/>
|
|
<InfoItem
|
|
icon={Clock}
|
|
label="Shop Timing"
|
|
value={employee.shop_timing?.title}
|
|
/>
|
|
<InfoItem
|
|
icon={MapPin}
|
|
label="Geo Fence Radius"
|
|
value={employee.geo_fence_radius != null ? String(employee.geo_fence_radius) : null}
|
|
/>
|
|
</div>
|
|
<Separator />
|
|
<div className="flex flex-wrap gap-2">
|
|
<Badge variant={employee.track_attendance ? "default" : "secondary"}>
|
|
<CircleDot className="mr-1 size-3" />
|
|
{employee.track_attendance ? "Attendance Tracked" : "No Attendance Tracking"}
|
|
</Badge>
|
|
{employee.notify_owner_when_punch_in_out && (
|
|
<Badge variant="outline">
|
|
Punch In/Out Notifications
|
|
</Badge>
|
|
)}
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
)
|
|
}
|