66 lines
2.0 KiB
TypeScript
66 lines
2.0 KiB
TypeScript
'use client';
|
||
|
||
import { useState } from 'react';
|
||
import type { RecordingCardProps } from '@/types/component-props';
|
||
|
||
export default function RecordingCard({
|
||
recording,
|
||
showActions = true,
|
||
onClick,
|
||
onDelete,
|
||
}: RecordingCardProps) {
|
||
const [isDeleting, setIsDeleting] = useState(false);
|
||
|
||
const handleDelete = async (e: React.MouseEvent) => {
|
||
e.stopPropagation();
|
||
if (!confirm('Delete this recording?')) return;
|
||
|
||
setIsDeleting(true);
|
||
onDelete?.(recording.id ?? '');
|
||
};
|
||
|
||
const formatDuration = (seconds: number) => {
|
||
const mins = Math.floor(seconds / 60);
|
||
const secs = seconds % 60;
|
||
return `${mins}:${secs.toString().padStart(2, '0')}`;
|
||
};
|
||
|
||
return (
|
||
<div
|
||
onClick={() => onClick?.(recording.id ?? '')}
|
||
className="bg-white border rounded-lg p-4 hover:shadow-md transition-shadow cursor-pointer"
|
||
>
|
||
<div className="flex items-start justify-between">
|
||
<div className="flex-1">
|
||
<h3 className="font-semibold text-gray-900 mb-1">{recording.title}</h3>
|
||
<div className="flex items-center gap-3 text-sm text-gray-600">
|
||
<span>⏱️ {formatDuration(recording.duration)}</span>
|
||
{recording.createdAt && (
|
||
<span>{new Date(recording.createdAt).toLocaleDateString()}</span>
|
||
)}
|
||
</div>
|
||
{recording.isTranscribing && (
|
||
<span className="inline-block mt-2 text-xs bg-yellow-100 text-yellow-800 px-2 py-1 rounded">
|
||
Transcribing...
|
||
</span>
|
||
)}
|
||
{recording.summary && (
|
||
<p className="mt-2 text-sm text-gray-600 line-clamp-2">
|
||
{recording.summary}
|
||
</p>
|
||
)}
|
||
</div>
|
||
{showActions && (
|
||
<button
|
||
onClick={handleDelete}
|
||
disabled={isDeleting}
|
||
className="ml-4 text-red-500 hover:text-red-700 disabled:opacity-50"
|
||
>
|
||
{isDeleting ? '⏳' : '🗑️'}
|
||
</button>
|
||
)}
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|