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>
43 lines
1.7 KiB
TypeScript
43 lines
1.7 KiB
TypeScript
'use client';
|
|
import { ReactNode } from 'react';
|
|
import IconButton from './IconButton';
|
|
|
|
interface Props {
|
|
title: string;
|
|
showAdd?: boolean;
|
|
onToggleAdd?: () => void;
|
|
addOpen?: boolean;
|
|
t: (key: string) => string;
|
|
children?: ReactNode;
|
|
}
|
|
|
|
export default function PageActionBar({ title, showAdd, onToggleAdd, addOpen, t, children }: Props) {
|
|
return (
|
|
<div className="flex items-center justify-between gap-2">
|
|
<h1 className="text-xl font-bold dark:text-white truncate">{title}</h1>
|
|
<div className="flex items-center gap-2 flex-shrink-0">
|
|
{children}
|
|
{showAdd && onToggleAdd && (
|
|
<IconButton
|
|
icon={
|
|
addOpen ? (
|
|
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
|
|
<path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
|
|
</svg>
|
|
) : (
|
|
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
|
|
<path strokeLinecap="round" strokeLinejoin="round" d="M12 4v16m8-8H4" />
|
|
</svg>
|
|
)
|
|
}
|
|
label={addOpen ? t("tasks.form.cancel") : t("tasks.add")}
|
|
onClick={onToggleAdd}
|
|
variant={addOpen ? "danger" : "primary"}
|
|
size="md"
|
|
/>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|