feat: add library-page action props to StepCard (edit/delete/save)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,11 +1,15 @@
|
|||||||
import { Star, User, Calendar, TrendingUp, Eye, Plus, HelpCircle, Zap, CheckCircle } from 'lucide-react'
|
import { Star, User, Calendar, TrendingUp, Eye, Plus, HelpCircle, Zap, CheckCircle, Pencil, Trash2, Bookmark } from 'lucide-react'
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
import type { StepListItem } from '@/types/step'
|
import type { StepListItem } from '@/types/step'
|
||||||
|
|
||||||
interface StepCardProps {
|
interface StepCardProps {
|
||||||
step: StepListItem
|
step: StepListItem
|
||||||
onPreview: (step: StepListItem) => void
|
onPreview: (step: StepListItem) => void
|
||||||
onInsert: (step: StepListItem) => void
|
onInsert?: (step: StepListItem) => void // session context (now optional)
|
||||||
|
onEdit?: (step: StepListItem) => void // library page
|
||||||
|
onDelete?: (step: StepListItem) => void // library page — NOTE: pass full StepListItem, not just ID
|
||||||
|
onSave?: (step: StepListItem) => void // library page (save copy to My Steps)
|
||||||
|
currentUserId?: string // to determine ownership
|
||||||
}
|
}
|
||||||
|
|
||||||
const stepTypeIcons = {
|
const stepTypeIcons = {
|
||||||
@@ -20,12 +24,14 @@ const stepTypeColors = {
|
|||||||
solution: 'bg-emerald-400/10 text-emerald-400 border-emerald-400/20'
|
solution: 'bg-emerald-400/10 text-emerald-400 border-emerald-400/20'
|
||||||
}
|
}
|
||||||
|
|
||||||
export function StepCard({ step, onPreview, onInsert }: StepCardProps) {
|
export function StepCard({ step, onPreview, onInsert, onEdit, onDelete, onSave, currentUserId }: StepCardProps) {
|
||||||
const Icon = stepTypeIcons[step.step_type as keyof typeof stepTypeIcons] || HelpCircle
|
const Icon = stepTypeIcons[step.step_type as keyof typeof stepTypeIcons] || HelpCircle
|
||||||
const hasRating = step.rating_count > 0
|
const hasRating = step.rating_count > 0
|
||||||
const visibleTags = step.tags.slice(0, 3)
|
const visibleTags = step.tags.slice(0, 3)
|
||||||
const remainingTags = step.tags.length - 3
|
const remainingTags = step.tags.length - 3
|
||||||
|
|
||||||
|
const isOwn = currentUserId ? step.created_by === currentUserId : false
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="group rounded-lg border border-border bg-card p-4 transition-shadow hover:shadow-md">
|
<div className="group rounded-lg border border-border bg-card p-4 transition-shadow hover:shadow-md">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
@@ -118,26 +124,70 @@ export function StepCard({ step, onPreview, onInsert }: StepCardProps) {
|
|||||||
|
|
||||||
{/* Actions */}
|
{/* Actions */}
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
<button
|
{(onEdit || onDelete || onSave) ? (
|
||||||
onClick={() => onPreview(step)}
|
isOwn ? (
|
||||||
className={cn(
|
// Own step: Preview + Edit + Delete icon
|
||||||
'flex flex-1 items-center justify-center gap-2 rounded-md border border-border px-3 py-2 text-sm font-medium text-muted-foreground',
|
<>
|
||||||
'hover:bg-accent hover:text-foreground transition-colors'
|
<button
|
||||||
)}
|
onClick={() => onPreview(step)}
|
||||||
>
|
className="flex flex-1 items-center justify-center gap-2 rounded-md border border-border px-3 py-2 text-sm font-medium text-muted-foreground hover:bg-accent hover:text-foreground transition-colors"
|
||||||
<Eye className="h-4 w-4" />
|
>
|
||||||
Preview
|
<Eye className="h-4 w-4" />
|
||||||
</button>
|
Preview
|
||||||
<button
|
</button>
|
||||||
onClick={() => onInsert(step)}
|
<button
|
||||||
className={cn(
|
onClick={() => onEdit?.(step)}
|
||||||
'flex flex-1 items-center justify-center gap-2 rounded-md bg-gradient-brand text-white shadow-lg shadow-primary/20 px-3 py-2 text-sm font-medium',
|
className="flex flex-1 items-center justify-center gap-2 rounded-md border border-border px-3 py-2 text-sm font-medium text-muted-foreground hover:bg-accent hover:text-foreground transition-colors"
|
||||||
'hover:opacity-90 transition-colors'
|
>
|
||||||
)}
|
<Pencil className="h-4 w-4" />
|
||||||
>
|
Edit
|
||||||
<Plus className="h-4 w-4" />
|
</button>
|
||||||
Insert
|
<button
|
||||||
</button>
|
onClick={() => onDelete?.(step)}
|
||||||
|
className="flex items-center justify-center rounded-md border border-border px-3 py-2 text-muted-foreground hover:bg-red-400/10 hover:text-red-400 hover:border-red-400/30 transition-colors"
|
||||||
|
aria-label="Delete step"
|
||||||
|
>
|
||||||
|
<Trash2 className="h-4 w-4" />
|
||||||
|
</button>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
// Others' step: Preview + Save
|
||||||
|
<>
|
||||||
|
<button
|
||||||
|
onClick={() => onPreview(step)}
|
||||||
|
className="flex flex-1 items-center justify-center gap-2 rounded-md border border-border px-3 py-2 text-sm font-medium text-muted-foreground hover:bg-accent hover:text-foreground transition-colors"
|
||||||
|
>
|
||||||
|
<Eye className="h-4 w-4" />
|
||||||
|
Preview
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => onSave?.(step)}
|
||||||
|
className="flex flex-1 items-center justify-center gap-2 rounded-md bg-gradient-brand text-white shadow-lg shadow-primary/20 px-3 py-2 text-sm font-medium hover:opacity-90 transition-colors"
|
||||||
|
>
|
||||||
|
<Bookmark className="h-4 w-4" />
|
||||||
|
Save
|
||||||
|
</button>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
) : (
|
||||||
|
// Session context (original): Preview + Insert
|
||||||
|
<>
|
||||||
|
<button
|
||||||
|
onClick={() => onPreview(step)}
|
||||||
|
className="flex flex-1 items-center justify-center gap-2 rounded-md border border-border px-3 py-2 text-sm font-medium text-muted-foreground hover:bg-accent hover:text-foreground transition-colors"
|
||||||
|
>
|
||||||
|
<Eye className="h-4 w-4" />
|
||||||
|
Preview
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => onInsert?.(step)}
|
||||||
|
className="flex flex-1 items-center justify-center gap-2 rounded-md bg-gradient-brand text-white shadow-lg shadow-primary/20 px-3 py-2 text-sm font-medium hover:opacity-90 transition-colors"
|
||||||
|
>
|
||||||
|
<Plus className="h-4 w-4" />
|
||||||
|
Insert
|
||||||
|
</button>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user