Files

217 lines
13 KiB
TypeScript

import React from 'react';
import { CardHeader, CardTitle, CardDescription } from '@/Components/ui/card';
import { Button } from '@/Components/ui/button';
import { Input } from '@/Components/ui/input';
import { Label } from '@/Components/ui/label';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/Components/ui/select';
import { Plus, Trash2, ChevronLeft, ChevronRight } from 'lucide-react';
interface Step2TasksProps {
localMilestones: any[];
localTasks: any[];
prepopulateMilestones: boolean;
setPrepopulateMilestones: (v: boolean) => void;
addMilestone: () => void;
removeMilestone: (idx: number) => void;
updateMilestone: (idx: number, field: string, val: string) => void;
addTask: () => void;
removeTask: (idx: number) => void;
updateTask: (idx: number, field: string, val: string) => void;
handleBack: () => void;
handleSaveTasks: () => void;
}
export default function Step2Tasks({
localMilestones,
localTasks,
prepopulateMilestones,
setPrepopulateMilestones,
addMilestone,
removeMilestone,
updateMilestone,
addTask,
removeTask,
updateTask,
handleBack,
handleSaveTasks
}: Step2TasksProps) {
return (
<div className="p-6 space-y-6">
<CardHeader className="p-0 pb-4 border-b border-slate-100 flex flex-row items-center justify-between">
<div>
<CardTitle className="text-md font-semibold text-slate-800">Step 2: Project Tasks & Milestones</CardTitle>
<CardDescription className="text-xs">Schedule the project milestones and assign tasks under them.</CardDescription>
</div>
<div className="flex items-center gap-2 bg-slate-50 p-2 rounded-lg border border-slate-150">
<input
id="prepopulate"
type="checkbox"
checked={prepopulateMilestones}
onChange={e => setPrepopulateMilestones(e.target.checked)}
className="rounded border-slate-300 text-emerald-600 focus:ring-emerald-500 h-4 w-4"
/>
<Label htmlFor="prepopulate" className="text-xs font-semibold text-slate-700 cursor-pointer">Pre-populate Defaults</Label>
</div>
</CardHeader>
{/* Milestones Editor */}
<div className="space-y-4">
<div className="flex items-center justify-between">
<h4 className="text-xs font-bold uppercase tracking-wider text-slate-500">1. Milestones</h4>
<Button variant="outline" size="sm" onClick={addMilestone} className="h-8 border-slate-200 text-slate-600 hover:bg-slate-50">
<Plus className="mr-1.5 h-3.5 w-3.5" /> Add Milestone
</Button>
</div>
{localMilestones.length === 0 ? (
<p className="text-xs italic text-slate-400 py-2">No milestones defined yet. Toggle pre-populate defaults or add custom ones.</p>
) : (
<div className="grid grid-cols-1 md:grid-cols-2 gap-3">
{localMilestones.map((m, idx) => (
<div key={idx} className="flex flex-col sm:flex-row gap-2 items-start sm:items-center bg-slate-50/50 p-3 rounded-lg border border-slate-200/60">
<div className="flex-1 space-y-1 w-full sm:w-auto">
<Label className="text-[10px] font-bold text-slate-600">Milestone Name <span className="text-red-500 font-bold">*</span></Label>
<Input
placeholder="Milestone Name"
value={m.name}
onChange={e => updateMilestone(idx, 'name', e.target.value)}
className="h-8 text-xs border-slate-200"
/>
</div>
<div className="w-full sm:w-24">
<Label className="text-[10px] font-bold text-slate-600">Weight % <span className="text-red-500 font-bold">*</span></Label>
<Input
type="number"
placeholder="Weight %"
value={m.weight_percentage}
onChange={e => updateMilestone(idx, 'weight_percentage', e.target.value)}
className="h-8 text-xs border-slate-200 text-right font-medium"
/>
</div>
<div className="w-full sm:w-32">
<Label className="text-[10px] font-bold text-slate-600">Target Date <span className="text-red-500 font-bold">*</span></Label>
<Input
type="date"
value={m.target_date || ''}
onChange={e => updateMilestone(idx, 'target_date', e.target.value)}
className="h-8 text-xs border-slate-200"
/>
</div>
<div className="sm:pt-4">
<Button variant="ghost" size="icon" onClick={() => removeMilestone(idx)} className="h-8 w-8 text-rose-500 hover:text-rose-700 hover:bg-rose-50">
<Trash2 className="h-4 w-4" />
</Button>
</div>
</div>
))}
</div>
)}
</div>
{/* Tasks Editor */}
<div className="space-y-4 pt-4 border-t border-slate-100">
<div className="flex items-center justify-between">
<h4 className="text-xs font-bold uppercase tracking-wider text-slate-500">2. Scheduled Tasks</h4>
<Button variant="outline" size="sm" onClick={addTask} className="h-8 border-slate-200 text-slate-600 hover:bg-slate-50">
<Plus className="mr-1.5 h-3.5 w-3.5" /> Add Task
</Button>
</div>
{localTasks.length === 0 ? (
<p className="text-xs italic text-slate-400 py-2">No tasks defined yet. Add tasks and link them to milestones.</p>
) : (
<div className="space-y-3">
{localTasks.map((t, idx) => (
<div key={idx} className="bg-slate-50/50 p-4 rounded-xl border border-slate-200/60 space-y-3 relative">
<div className="grid grid-cols-1 md:grid-cols-3 gap-3">
<div className="md:col-span-2">
<Label className="text-[10px] font-bold text-slate-600">Task Name <span className="text-red-500 font-bold">*</span></Label>
<Input
placeholder="Task Name"
value={t.name}
onChange={e => updateTask(idx, 'name', e.target.value)}
className="h-8 text-xs border-slate-200 mt-1"
/>
</div>
<div className="flex items-end gap-2">
<div className="min-w-0 flex-1">
<Label className="text-[10px] font-bold text-slate-600">Milestone <span className="text-red-500 font-bold">*</span></Label>
<Select
value={t.milestone_ulid}
onValueChange={val => updateTask(idx, 'milestone_ulid', val || '')}
items={localMilestones.map((m, mIdx) => ({ value: m.ulid || String(mIdx), label: m.name || `Milestone ${mIdx+1}` }))}
>
<SelectTrigger className="h-8 text-xs border-slate-200 mt-1">
<SelectValue placeholder="Select Milestone" />
</SelectTrigger>
<SelectContent>
{localMilestones.map((m, mIdx) => (
<SelectItem key={mIdx} value={m.ulid || String(mIdx)}>
{m.name || `Milestone ${mIdx+1}`}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
<Button
type="button"
variant="ghost"
size="icon"
aria-label={`Delete task ${idx + 1}`}
title="Delete task"
onClick={() => removeTask(idx)}
className="mb-0 h-8 w-8 shrink-0 rounded-lg p-2 text-rose-500 hover:bg-rose-50 hover:text-rose-700"
>
<Trash2 className="h-4 w-4" />
</Button>
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-3">
<div className="md:col-span-2">
<Label className="text-[10px] font-bold text-slate-600">Task Description / Scope <span className="text-red-500 font-bold">*</span></Label>
<Input
placeholder="Enter detailed task description..."
value={t.description}
onChange={e => updateTask(idx, 'description', e.target.value)}
className="h-8 text-xs border-slate-200 mt-1"
/>
</div>
<div className="grid grid-cols-2 gap-2">
<div>
<Label className="text-[10px] text-slate-500">Start Date</Label>
<Input
type="date"
value={t.start_date}
onChange={e => updateTask(idx, 'start_date', e.target.value)}
className="h-8 text-xs border-slate-200 mt-1"
/>
</div>
<div>
<Label className="text-[10px] text-slate-500">Target End</Label>
<Input
type="date"
value={t.end_date}
onChange={e => updateTask(idx, 'end_date', e.target.value)}
className="h-8 text-xs border-slate-200 mt-1"
/>
</div>
</div>
</div>
</div>
))}
</div>
)}
</div>
<div className="flex justify-between pt-6 border-t border-slate-100">
<Button variant="outline" onClick={handleBack}>
<ChevronLeft className="mr-2 h-4 w-4" /> Back
</Button>
<Button onClick={handleSaveTasks} className="bg-emerald-600 hover:bg-emerald-700 text-white font-medium">
Save & Next <ChevronRight className="ml-2 h-4 w-4" />
</Button>
</div>
</div>
);
}