Add files via upload
This commit is contained in:
@@ -14,12 +14,13 @@ export default function DeliverableCard({ deliverable, isActive, index, projectC
|
|||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
setCtxMenu({
|
setCtxMenu({
|
||||||
x: e.clientX, y: e.clientY,
|
x: e.clientX,
|
||||||
|
y: e.clientY,
|
||||||
items: [
|
items: [
|
||||||
{ icon: '✎', label: 'Edit Deliverable', highlight: true, action: () => onEdit(deliverable) },
|
{ icon: '\u270e', label: 'Edit Deliverable', highlight: true, action: () => onEdit(deliverable) },
|
||||||
{ separator: true },
|
{ separator: true },
|
||||||
...STATUS_OPTIONS.map(s => ({
|
...STATUS_OPTIONS.map(s => ({
|
||||||
icon: s.value === deliverable.status ? '●' : '○',
|
icon: s.value === deliverable.status ? '\u25cf' : '\u25cb',
|
||||||
label: `Mark ${s.label}`,
|
label: `Mark ${s.label}`,
|
||||||
action: async () => {
|
action: async () => {
|
||||||
storeUpdate(await updateDeliverable(deliverable.id, { status: s.value }))
|
storeUpdate(await updateDeliverable(deliverable.id, { status: s.value }))
|
||||||
@@ -27,7 +28,9 @@ export default function DeliverableCard({ deliverable, isActive, index, projectC
|
|||||||
})),
|
})),
|
||||||
{ separator: true },
|
{ separator: true },
|
||||||
{
|
{
|
||||||
icon: '✕', label: 'Delete Deliverable', danger: true,
|
icon: '\u2715',
|
||||||
|
label: 'Delete Deliverable',
|
||||||
|
danger: true,
|
||||||
action: async () => {
|
action: async () => {
|
||||||
if (window.confirm(`Delete "${deliverable.title}"?`)) {
|
if (window.confirm(`Delete "${deliverable.title}"?`)) {
|
||||||
await deleteDeliverable(deliverable.id)
|
await deleteDeliverable(deliverable.id)
|
||||||
@@ -45,40 +48,23 @@ export default function DeliverableCard({ deliverable, isActive, index, projectC
|
|||||||
onClick={() => onSelect(deliverable.id)}
|
onClick={() => onSelect(deliverable.id)}
|
||||||
onDoubleClick={(e) => { e.stopPropagation(); onEdit(deliverable) }}
|
onDoubleClick={(e) => { e.stopPropagation(); onEdit(deliverable) }}
|
||||||
onContextMenu={handleContextMenu}
|
onContextMenu={handleContextMenu}
|
||||||
title="Click: Select · Double-click: Edit · Right-click: Menu"
|
title="Click: Select · Double-click: Edit · Right-click: Menu"
|
||||||
className={`relative flex flex-col gap-2 rounded-xl border p-4 min-w-[190px] max-w-[230px] flex-shrink-0 cursor-pointer
|
className={`relative flex flex-col gap-2 rounded-xl border p-4 min-w-[190px] max-w-[230px] flex-shrink-0 cursor-pointer transition-all duration-200 select-none mt-4 ${
|
||||||
transition-all duration-200 select-none mt-4
|
isActive
|
||||||
${isActive
|
|
||||||
? 'border-gold bg-surface-elevated shadow-gold scale-105 ring-2 ring-gold/30'
|
? 'border-gold bg-surface-elevated shadow-gold scale-105 ring-2 ring-gold/30'
|
||||||
: 'border-surface-border bg-surface hover:border-gold/40 hover:bg-surface-elevated/60'
|
: 'border-surface-border bg-surface hover:border-gold/40 hover:bg-surface-elevated/60'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{isActive && (
|
{isActive && (
|
||||||
<div className="absolute -top-5 left-1/2 -translate-x-1/2 bg-gold text-surface text-[9px] font-black px-2.5 py-0.5 rounded-full tracking-widest uppercase whitespace-nowrap">
|
<div className="absolute -top-5 left-1/2 -translate-x-1/2 text-[9px] font-bold tracking-widest uppercase text-gold/80 whitespace-nowrap">
|
||||||
Selected
|
Selected
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="flex items-center gap-1.5">
|
|
||||||
<div className="w-2 h-2 rounded-full flex-shrink-0" style={{ backgroundColor: projectColor }} />
|
<div className="text-[10px] text-text-muted/50 font-mono">Deliverable {index + 1}</div>
|
||||||
<span className={`text-[10px] font-semibold uppercase tracking-widest ${isActive ? 'text-gold' : 'text-text-muted/60'}`}>
|
<div className="text-sm font-semibold text-text-primary leading-snug line-clamp-3">{deliverable.title}</div>
|
||||||
Deliverable {index + 1}
|
<div className="text-xs text-text-muted/70 mt-auto pt-1">{formatDate(deliverable.due_date)}</div>
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<p className={`text-sm font-semibold leading-snug ${isActive ? 'text-text-primary' : 'text-text-muted'}`}>
|
|
||||||
{deliverable.title}
|
|
||||||
</p>
|
|
||||||
<p className={`text-xs font-mono ${isActive ? 'text-gold' : 'text-text-muted/50'}`}>
|
|
||||||
{formatDate(deliverable.due_date)}
|
|
||||||
</p>
|
|
||||||
<Badge status={deliverable.status} />
|
<Badge status={deliverable.status} />
|
||||||
{isActive && (
|
|
||||||
<button
|
|
||||||
onClick={(e) => { e.stopPropagation(); onEdit(deliverable) }}
|
|
||||||
className="mt-1 text-[10px] text-gold/70 hover:text-gold border border-gold/20 hover:border-gold/50 rounded px-2 py-0.5 transition-all text-center"
|
|
||||||
>
|
|
||||||
Edit
|
|
||||||
</button>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{ctxMenu && (
|
{ctxMenu && (
|
||||||
|
|||||||
Reference in New Issue
Block a user