tahamajs/IE / Projects /front /src /components /data-hub /ProtocolStepCard.tsx
tahamajs's picture
download
raw
3.4 kB
// src/components/data-hub/ProtocolStepCard.tsx
import { useState } from "react";
import type { ProtocolStep } from "@/types/data-hub";
import { Check, Clock, Lightbulb, ChevronDown, ChevronUp, Edit, X, Save } from "lucide-react";
interface ProtocolStepCardProps {
step: ProtocolStep;
index: number;
runMode: boolean;
editMode: boolean;
onToggleComplete: () => void;
onUpdate: (data: Partial<ProtocolStep>) => void;
}
export function ProtocolStepCard({ step, index, runMode, editMode, onToggleComplete, onUpdate }: ProtocolStepCardProps) {
const [expanded, setExpanded] = useState(false);
const [editingField, setEditingField] = useState<string | null>(null);
const [tempValue, setTempValue] = useState("");
return (
<div className={`rounded-xl border p-4 transition ${
step.completed ? "border-green-300 dark:border-green-700 bg-green-50/20 dark:bg-green-900/10" : "border-white/20 dark:border-white/10"
}`}>
<div className="flex items-start gap-3">
{/* Checkbox (always visible in run mode) */}
<button onClick={onToggleComplete}
className={`w-6 h-6 rounded-full border-2 flex items-center justify-center shrink-0 mt-0.5 transition ${
step.completed ? "bg-green-500 border-green-500 text-white" : "border-gray-300 dark:border-gray-600"
} ${runMode ? "cursor-pointer hover:border-green-400" : "cursor-default"}`}>
{step.completed && <Check className="w-4 h-4"/>}
</button>
<div className="flex-1">
<div className="flex items-center gap-2">
<span className="text-xs font-mono text-gray-400">{index + 1}.</span>
<h4 className="font-semibold text-sm">{step.title}</h4>
{step.duration && <span className="flex items-center gap-1 text-[10px] text-gray-400"><Clock className="w-3 h-3"/>{step.duration}</span>}
</div>
<p className="text-sm text-gray-600 dark:text-gray-400 mt-1">{step.description}</p>
{step.tips && (
<button onClick={() => setExpanded(!expanded)} className="text-xs text-amber-600 flex items-center gap-1 mt-1">
<Lightbulb className="w-3 h-3"/> Tips {expanded ? <ChevronUp className="w-3 h-3"/> : <ChevronDown className="w-3 h-3"/>}
</button>
)}
{expanded && step.tips && <p className="text-xs text-gray-500 mt-1 bg-amber-50/30 dark:bg-amber-900/10 p-2 rounded">{step.tips}</p>}
</div>
{editMode && (
<div className="flex gap-1">
<button onClick={() => { setEditingField("title"); setTempValue(step.title); }} className="p-1 text-gray-400 hover:text-primary"><Edit className="w-3.5 h-3.5"/></button>
</div>
)}
</div>
{/* Inline edit (shown only for title here; can be extended) */}
{editMode && editingField && (
<div className="flex gap-2 mt-2 ml-9">
<input type="text" value={tempValue} onChange={e => setTempValue(e.target.value)} className="flex-1 text-sm px-3 py-1 bg-white/10 rounded" autoFocus />
<button onClick={() => { onUpdate({ [editingField]: tempValue }); setEditingField(null); }} className="btn btn-primary btn-xs"><Save className="w-3 h-3"/></button>
<button onClick={() => setEditingField(null)} className="btn btn-ghost btn-xs"><X className="w-3 h-3"/></button>
</div>
)}
</div>
);
}

Xet Storage Details

Size:
3.4 kB
·
Xet hash:
10ef4edf032a9b278186fe6ab792b1c4417bfdee4354bbfbda5ea1b03cb3662f

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.