feat: add line clamp utility and integrate RecentTaskTimeline component
- Added a new CSS utility for line clamping to `globals.css` for better text overflow handling. - Integrated `WelcomeSection` into `HomePageClient` for enhanced user experience. - Replaced `TaskCard` with `RecentTaskTimeline` in `RecentTasks` for improved task visualization. - Updated `ui/index.ts` to export `RecentTaskTimeline` and showcased it in `CardsSection` and `FeedbackSection`.
This commit is contained in:
129
src/components/ui/RecentTaskTimeline.tsx
Normal file
129
src/components/ui/RecentTaskTimeline.tsx
Normal file
@@ -0,0 +1,129 @@
|
||||
import { HTMLAttributes } from 'react';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { StatusBadge } from './StatusBadge';
|
||||
import { TaskStatus } from '@/lib/types';
|
||||
import { PriorityBadge } from './PriorityBadge';
|
||||
import { TagDisplay } from './TagDisplay';
|
||||
import { formatDateForDisplay } from '@/lib/date-utils';
|
||||
|
||||
interface RecentTaskTimelineProps extends HTMLAttributes<HTMLDivElement> {
|
||||
title: string;
|
||||
description?: string;
|
||||
tags?: string[];
|
||||
priority?: 'low' | 'medium' | 'high';
|
||||
status?: TaskStatus;
|
||||
dueDate?: Date;
|
||||
completedAt?: Date;
|
||||
updatedAt?: Date;
|
||||
source?: 'manual' | 'jira' | 'tfs' | 'reminders';
|
||||
jiraKey?: string;
|
||||
tfsPullRequestId?: number;
|
||||
onClick?: () => void;
|
||||
className?: string;
|
||||
availableTags?: Array<{ id: string; name: string; color: string }>;
|
||||
}
|
||||
|
||||
export function RecentTaskTimeline({
|
||||
title,
|
||||
description,
|
||||
tags = [],
|
||||
priority,
|
||||
status = 'todo',
|
||||
dueDate,
|
||||
completedAt,
|
||||
updatedAt,
|
||||
source = 'manual',
|
||||
jiraKey,
|
||||
tfsPullRequestId,
|
||||
onClick,
|
||||
className,
|
||||
availableTags = [],
|
||||
...props
|
||||
}: RecentTaskTimelineProps) {
|
||||
const getSourceIcon = () => {
|
||||
switch (source) {
|
||||
case 'jira':
|
||||
return <div className="w-2 h-2 bg-[var(--primary)] rounded-full" />;
|
||||
case 'tfs':
|
||||
return <div className="w-2 h-2 bg-[var(--blue)] rounded-full" />;
|
||||
case 'reminders':
|
||||
return <div className="w-2 h-2 bg-[var(--accent)] rounded-full" />;
|
||||
default:
|
||||
return <div className="w-2 h-2 bg-[var(--gray)] rounded-full" />;
|
||||
}
|
||||
};
|
||||
|
||||
const getTimeInfo = () => {
|
||||
if (completedAt) {
|
||||
return `Terminé ${formatDateForDisplay(completedAt)}`;
|
||||
}
|
||||
if (dueDate) {
|
||||
return `Échéance ${formatDateForDisplay(dueDate)}`;
|
||||
}
|
||||
if (updatedAt) {
|
||||
return `Modifié ${formatDateForDisplay(updatedAt)}`;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"group relative flex items-start gap-4 p-3 rounded-lg hover:bg-[var(--card-hover)] transition-colors cursor-pointer",
|
||||
className
|
||||
)}
|
||||
onClick={onClick}
|
||||
{...props}
|
||||
>
|
||||
{/* Timeline dot */}
|
||||
<div className="flex-shrink-0 mt-2">
|
||||
{getSourceIcon()}
|
||||
</div>
|
||||
|
||||
{/* Content */}
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="flex items-start justify-between gap-2 mb-1">
|
||||
<h4 className="font-medium text-[var(--foreground)] text-sm group-hover:text-[var(--primary)] transition-colors">
|
||||
{title}
|
||||
</h4>
|
||||
<div className="flex items-center gap-1 flex-shrink-0">
|
||||
{priority && <PriorityBadge priority={priority} />}
|
||||
<StatusBadge status={status} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{description && (
|
||||
<p className="text-xs text-[var(--muted-foreground)] mb-2 line-clamp-1">
|
||||
{description}
|
||||
</p>
|
||||
)}
|
||||
|
||||
{tags.length > 0 && (
|
||||
<div className="mb-2">
|
||||
<TagDisplay
|
||||
tags={tags}
|
||||
availableTags={availableTags}
|
||||
maxTags={2}
|
||||
size="sm"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="flex items-center justify-between text-xs text-[var(--muted-foreground)]">
|
||||
<div className="flex items-center gap-2">
|
||||
{jiraKey && <span className="font-mono text-[var(--primary)]">{jiraKey}</span>}
|
||||
{tfsPullRequestId && <span className="font-mono text-[var(--blue)]">PR #{tfsPullRequestId}</span>}
|
||||
</div>
|
||||
<span>{getTimeInfo()}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Arrow indicator */}
|
||||
<div className="flex-shrink-0 mt-2 opacity-0 group-hover:opacity-100 transition-opacity">
|
||||
<svg className="w-4 h-4 text-[var(--primary)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -10,6 +10,7 @@ export { StatCard } from './StatCard';
|
||||
export { ProgressBar } from './ProgressBar';
|
||||
export { ActionCard } from './ActionCard';
|
||||
export { TaskCard } from './TaskCard';
|
||||
export { RecentTaskTimeline } from './RecentTaskTimeline';
|
||||
export { MetricCard } from './MetricCard';
|
||||
|
||||
// Composants Kanban
|
||||
|
||||
Reference in New Issue
Block a user