Files
dashboard/components/camera/CameraCard.tsx
T
Alberto-Audrix 32a36cceff
CI / lint-and-test (push) Canceled after 0s
first commit
2026-07-28 08:55:05 +07:00

70 lines
2.9 KiB
TypeScript

import React from 'react';
import { Camera, CameraType } from '../../types.ts';
interface CameraCardProps {
camera: Camera;
onEdit: () => void;
onDelete: () => void;
}
const statusConfig: {
[key in Camera['status']]: { text: string; bg: string; pulseClass: string };
} = {
online: { text: 'Online', bg: 'bg-green-500', pulseClass: 'bg-green-300 animate-pulse' },
offline: { text: 'Offline', bg: 'bg-gray-500', pulseClass: 'bg-gray-300' },
error: { text: 'Error', bg: 'bg-red-500', pulseClass: 'bg-red-300' },
};
const typeConfig: { [key in CameraType]: { icon: string; color: string } } = {
[CameraType.STANDARD]: { icon: 'fa-video', color: 'text-gray-500' },
[CameraType.INFRARED]: { icon: 'fa-moon', color: 'text-purple-500' },
[CameraType.THERMAL]: { icon: 'fa-temperature-high', color: 'text-orange-500' },
[CameraType.THREE_D]: { icon: 'fa-cube', color: 'text-blue-500' },
};
const CameraCard: React.FC<CameraCardProps> = ({ camera, onEdit, onDelete }) => {
const status = statusConfig[camera.status];
const typeInfo = typeConfig[camera.cameraType] || typeConfig[CameraType.STANDARD];
return (
<div className="bg-white rounded-xl shadow-sm transition-all duration-300 hover:shadow-lg flex flex-col border border-gray-200">
<div className="relative aspect-video bg-black rounded-t-xl flex items-center justify-center">
<i className={`fa-solid ${typeInfo.icon} text-5xl ${typeInfo.color}`}></i>
<span
className={`absolute top-2 right-2 flex items-center text-xs font-semibold text-white px-2 py-0.5 rounded-full ${status.bg}`}
>
<span className={`w-2 h-2 rounded-full mr-1.5 ${status.pulseClass}`}></span>
{status.text}
</span>
</div>
<div className="p-4 flex-grow">
<h3 className="font-bold text-lg text-gray-800 truncate" title={camera.name}>
{camera.name}
</h3>
<p className="text-sm font-semibold text-gray-600">{camera.cameraType}</p>
<p className="text-xs text-gray-500 mt-1 truncate" title={camera.model}>
{camera.model}
</p>
</div>
<div className="p-3 bg-gray-50 border-t border-gray-100 rounded-b-xl flex items-center justify-end space-x-2">
<button
onClick={onEdit}
className="text-sm text-gray-600 hover:text-blue-600 font-medium px-3 py-1 rounded-md hover:bg-gray-200 transition-colors"
aria-label={`Edit ${camera.name}`}
>
<i className="fa-solid fa-pencil mr-1"></i> Edit
</button>
<button
onClick={onDelete}
className="text-sm text-gray-600 hover:text-red-600 font-medium px-3 py-1 rounded-md hover:bg-gray-200 transition-colors"
aria-label={`Delete ${camera.name}`}
>
<i className="fa-solid fa-trash mr-1"></i> Hapus
</button>
</div>
</div>
);
};
export default CameraCard;