API features (separate files in /api/src/features/): - media-input: upload text/audio/photo/video, transcription - gamification: points, streaks, badges, leaderboard - templates: predefined task sets (sprint, study, moving) - time-tracking: start/stop timer, task/user reports - kanban: board view, drag-and-drop move - ai-briefing: daily AI summary with tasks/goals/reviews - webhooks-outgoing: notify external systems on events UI components (separate files in /components/features/): - IconButton: icon-only buttons with tooltip - CompactHeader, PageActionBar, InlineEditField - TaskDetailActions, GoalActionButtons, CollabActionButtons - DeleteIconButton, CollabBackButton All features modular — registry.js enables/disables each one. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
126 lines
4.8 KiB
TypeScript
126 lines
4.8 KiB
TypeScript
'use client';
|
|
import IconButton from './IconButton';
|
|
|
|
interface Props {
|
|
taskDone: boolean;
|
|
deleting: boolean;
|
|
onBack: () => void;
|
|
onEdit: () => void;
|
|
onDelete: () => void;
|
|
onToggleStatus: () => void;
|
|
onInvite: () => void;
|
|
onCollaborate: () => void;
|
|
t: (key: string) => string;
|
|
}
|
|
|
|
export default function TaskDetailActions({
|
|
taskDone,
|
|
deleting,
|
|
onBack,
|
|
onEdit,
|
|
onDelete,
|
|
onToggleStatus,
|
|
onInvite,
|
|
onCollaborate,
|
|
t,
|
|
}: Props) {
|
|
return (
|
|
<div className="flex items-center gap-2">
|
|
{/* Back */}
|
|
<IconButton
|
|
icon={
|
|
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
|
|
<path strokeLinecap="round" strokeLinejoin="round" d="M15 19l-7-7 7-7" />
|
|
</svg>
|
|
}
|
|
label={t("common.back")}
|
|
onClick={onBack}
|
|
variant="default"
|
|
size="md"
|
|
/>
|
|
|
|
<div className="flex-1" />
|
|
|
|
{/* Toggle done/reopen */}
|
|
{!taskDone ? (
|
|
<IconButton
|
|
icon={
|
|
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
|
|
<path strokeLinecap="round" strokeLinejoin="round" d="M5 13l4 4L19 7" />
|
|
</svg>
|
|
}
|
|
label={t("tasks.markDone")}
|
|
onClick={onToggleStatus}
|
|
variant="success"
|
|
size="md"
|
|
/>
|
|
) : (
|
|
<IconButton
|
|
icon={
|
|
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
|
|
<path strokeLinecap="round" strokeLinejoin="round" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
|
|
</svg>
|
|
}
|
|
label={t("tasks.reopen")}
|
|
onClick={onToggleStatus}
|
|
variant="warning"
|
|
size="md"
|
|
/>
|
|
)}
|
|
|
|
{/* Edit */}
|
|
<IconButton
|
|
icon={
|
|
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
|
|
<path strokeLinecap="round" strokeLinejoin="round" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z" />
|
|
</svg>
|
|
}
|
|
label={t("tasks.edit")}
|
|
onClick={onEdit}
|
|
variant="primary"
|
|
size="md"
|
|
/>
|
|
|
|
{/* Delete */}
|
|
<IconButton
|
|
icon={
|
|
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
|
|
<path strokeLinecap="round" strokeLinejoin="round" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
|
|
</svg>
|
|
}
|
|
label={deleting ? t("tasks.deleting") : t("tasks.delete")}
|
|
onClick={onDelete}
|
|
disabled={deleting}
|
|
variant="danger"
|
|
size="md"
|
|
/>
|
|
|
|
{/* Collaborate */}
|
|
<IconButton
|
|
icon={
|
|
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
|
|
<path strokeLinecap="round" strokeLinejoin="round" d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z" />
|
|
</svg>
|
|
}
|
|
label={t("collab.collaboration")}
|
|
onClick={onCollaborate}
|
|
variant="purple"
|
|
size="md"
|
|
/>
|
|
|
|
{/* Invite */}
|
|
<IconButton
|
|
icon={
|
|
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
|
|
<path strokeLinecap="round" strokeLinejoin="round" d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197M13 7a4 4 0 11-8 0 4 4 0 018 0z" />
|
|
</svg>
|
|
}
|
|
label="Pozvat"
|
|
onClick={onInvite}
|
|
variant="primary"
|
|
size="md"
|
|
/>
|
|
</div>
|
|
);
|
|
}
|