interactive / components /ActionPlan.tsx
caustino's picture
Upload 20 files
bb8c446 verified
Raw
History Blame Contribute Delete
5.48 kB
import React, { useState, useMemo } from 'react';
import type { ActionPlan, PlanCategory } from '../types';
import { DocumentIcon } from './icons/DocumentIcon';
import { MedicalIcon } from './icons/MedicalIcon';
import { WorkIcon } from './icons/WorkIcon';
import { CheckIcon } from './icons/CheckIcon';
interface ActionPlanProps {
plan: ActionPlan;
onToggleItem: (categoryIndex: number, itemIndex: number) => void;
onReset: () => void;
}
const getCategoryIcon = (categoryName: string): React.ReactNode => {
const lowerCaseName = categoryName.toLowerCase();
if (lowerCaseName.includes('medical')) return <MedicalIcon className="w-6 h-6" />;
if (lowerCaseName.includes('work')) return <WorkIcon className="w-6 h-6" />;
return <DocumentIcon className="w-6 h-6" />;
};
const CategoryCard: React.FC<{ category: PlanCategory, categoryIndex: number, onToggleItem: (catIdx: number, itemIdx: number) => void }> = ({ category, categoryIndex, onToggleItem }) => {
const [isExpanded, setIsExpanded] = useState(true);
const completedItems = useMemo(() => category.items.filter(item => item.status === 'Completed').length, [category.items]);
const totalItems = category.items.length;
const progress = totalItems > 0 ? (completedItems / totalItems) * 100 : 0;
return (
<div className="bg-gray-900 border border-white/10 rounded-xl overflow-hidden">
<button
className="w-full flex justify-between items-center p-4 md:p-6 text-left hover:bg-gray-800 transition-colors"
onClick={() => setIsExpanded(!isExpanded)}
>
<div className="flex items-center space-x-4">
<span className="text-brand-secondary">{getCategoryIcon(category.category)}</span>
<div>
<h3 className="text-lg font-bold text-white">{category.category}</h3>
<p className="text-sm text-gray-400">{category.description}</p>
</div>
</div>
<div className="flex items-center space-x-4">
<span className="text-sm font-mono text-gray-400">{completedItems}/{totalItems}</span>
<svg className={`w-5 h-5 text-gray-400 transform transition-transform ${isExpanded ? 'rotate-180' : ''}`} fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
</svg>
</div>
</button>
{isExpanded && (
<div className="px-4 md:px-6 pb-4">
<div className="w-full bg-gray-700 rounded-full h-1.5 mb-4">
<div className="bg-brand-secondary h-1.5 rounded-full" style={{ width: `${progress}%`, transition: 'width 0.5s ease-in-out' }}></div>
</div>
<ul className="space-y-3">
{category.items.map((item, itemIndex) => (
<li key={itemIndex} className="flex items-start space-x-3 p-3 rounded-lg bg-gray-800/50">
<button onClick={() => onToggleItem(categoryIndex, itemIndex)} className="flex-shrink-0 mt-1">
<div className={`w-6 h-6 rounded-md flex items-center justify-center border-2 transition-all ${item.status === 'Completed' ? 'bg-brand-secondary border-brand-secondary' : 'bg-gray-700 border-gray-600 hover:border-brand-secondary'}`}>
{item.status === 'Completed' && <CheckIcon />}
</div>
</button>
<div>
<p className={`font-semibold text-white ${item.status === 'Completed' ? 'line-through text-gray-500' : ''}`}>{item.item}</p>
<p className="text-sm text-gray-400">{item.description}</p>
</div>
</li>
))}
</ul>
</div>
)}
</div>
);
};
export const ActionPlanComponent: React.FC<ActionPlanProps> = ({ plan, onToggleItem, onReset }) => {
return (
<div className="space-y-8 animate-fade-in">
<div className="text-center p-6 bg-gray-900 border border-white/10 rounded-xl">
<h2 className="text-3xl font-bold text-white">{plan.title}</h2>
<p className="mt-2 text-gray-300 max-w-3xl mx-auto">{plan.summary}</p>
</div>
<div className="space-y-4">
{plan.categories.map((category, index) => (
<CategoryCard key={index} category={category} categoryIndex={index} onToggleItem={onToggleItem} />
))}
</div>
<div className="text-center pt-8">
<button
onClick={onReset}
className="inline-flex items-center px-8 py-3 border border-gray-600 text-base font-medium rounded-md text-gray-300 bg-gray-800 hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-brand-primary focus:ring-offset-gray-950 transition-colors"
>
Start a New Plan
</button>
</div>
</div>
);
};