Plant catalog UI: /plants page + PlantPicker (#13)
Build image / build-and-push (push) Successful in 15s
Build image / build-and-push (push) Successful in 15s
Co-authored-by: Steve Dudenhoeffer <[email protected]>
This commit was merged in pull request #32.
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
import { PlantIcon } from './PlantIcon'
|
||||
import { CATEGORY_LABELS, isBuiltin, type Plant } from '@/lib/plants'
|
||||
import { formatSpacing, type UnitPref } from '@/lib/units'
|
||||
|
||||
const actionClass =
|
||||
'rounded-md px-2.5 py-1 text-sm font-medium text-muted outline-none transition-colors ' +
|
||||
'hover:bg-border/50 hover:text-fg focus-visible:ring-2 focus-visible:ring-accent/40'
|
||||
const dangerClass =
|
||||
'rounded-md px-2.5 py-1 text-sm font-medium text-muted outline-none transition-colors ' +
|
||||
'hover:bg-red-500/10 hover:text-red-600 focus-visible:ring-2 focus-visible:ring-red-500/40 dark:hover:text-red-400'
|
||||
|
||||
/**
|
||||
* One catalog plant as a card: icon tile tinted with the plant's color, name,
|
||||
* category + mature spacing (unit-aware), and actions. Built-ins are badged and
|
||||
* offer only "Duplicate" (they're read-only); own plants add Edit/Delete.
|
||||
*/
|
||||
export function PlantCard({
|
||||
plant,
|
||||
unit,
|
||||
onEdit,
|
||||
onDelete,
|
||||
onDuplicate,
|
||||
}: {
|
||||
plant: Plant
|
||||
unit: UnitPref
|
||||
onEdit: () => void
|
||||
onDelete: () => void
|
||||
onDuplicate: () => void
|
||||
}) {
|
||||
const builtin = isBuiltin(plant)
|
||||
return (
|
||||
<div className="flex flex-col rounded-xl border border-border bg-surface">
|
||||
<div className="flex items-start gap-3 p-4">
|
||||
<PlantIcon color={plant.color} icon={plant.icon} className="h-11 w-11 rounded-lg text-2xl" />
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="flex items-center gap-2">
|
||||
<h3 className="truncate font-semibold text-fg">{plant.name}</h3>
|
||||
{builtin && (
|
||||
<span className="shrink-0 rounded bg-border/60 px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wide text-muted">
|
||||
Built-in
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<p className="mt-0.5 text-sm text-muted">
|
||||
{CATEGORY_LABELS[plant.category]} · {formatSpacing(plant.spacingCm, unit)} spacing
|
||||
</p>
|
||||
{plant.notes && <p className="mt-1 line-clamp-2 text-xs text-muted">{plant.notes}</p>}
|
||||
</div>
|
||||
<span
|
||||
className="mt-1 h-4 w-4 shrink-0 rounded-full border border-black/10 dark:border-white/10"
|
||||
style={{ backgroundColor: plant.color }}
|
||||
title={plant.color}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex justify-end gap-1 border-t border-border px-2 py-1.5">
|
||||
<button type="button" onClick={onDuplicate} className={actionClass}>
|
||||
Duplicate
|
||||
</button>
|
||||
{!builtin && (
|
||||
<button type="button" onClick={onEdit} className={actionClass}>
|
||||
Edit
|
||||
</button>
|
||||
)}
|
||||
{!builtin && (
|
||||
<button type="button" onClick={onDelete} className={dangerClass}>
|
||||
Delete
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user