Replace status_id with in_progress boolean field
- Remove task_statuses lookup table and StatusID foreign key - Add InProgress boolean field to Task model - Add database migration (005_replace_status_with_in_progress) - Update all handlers, services, and repositories - Update admin frontend to display in_progress as checkbox/boolean - Remove Task Statuses tab from admin lookups page - Update tests to use InProgress instead of StatusID - Task categorization now uses InProgress for kanban column assignment 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -38,7 +38,6 @@ import {
|
||||
const lookupTabs = [
|
||||
{ key: 'categories', label: 'Task Categories', api: lookupsApi.categories },
|
||||
{ key: 'priorities', label: 'Task Priorities', api: lookupsApi.priorities },
|
||||
{ key: 'statuses', label: 'Task Statuses', api: lookupsApi.statuses },
|
||||
{ key: 'frequencies', label: 'Task Frequencies', api: lookupsApi.frequencies },
|
||||
{ key: 'residenceTypes', label: 'Residence Types', api: lookupsApi.residenceTypes },
|
||||
{ key: 'specialties', label: 'Contractor Specialties', api: lookupsApi.specialties },
|
||||
@@ -320,12 +319,12 @@ export default function LookupsPage() {
|
||||
<CardHeader>
|
||||
<CardTitle>Reference Data</CardTitle>
|
||||
<CardDescription>
|
||||
Configure task categories, priorities, statuses, frequencies, residence types, and contractor specialties
|
||||
Configure task categories, priorities, frequencies, residence types, and contractor specialties
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<Tabs defaultValue="categories" className="w-full">
|
||||
<TabsList className="grid w-full grid-cols-6">
|
||||
<TabsList className="grid w-full grid-cols-5">
|
||||
{lookupTabs.map((tab) => (
|
||||
<TabsTrigger key={tab.key} value={tab.key} className="text-xs">
|
||||
{tab.label}
|
||||
|
||||
@@ -248,7 +248,7 @@ export function ResidenceDetailClient() {
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead>Title</TableHead>
|
||||
<TableHead>Status</TableHead>
|
||||
<TableHead>In Progress</TableHead>
|
||||
<TableHead>Priority</TableHead>
|
||||
<TableHead>Category</TableHead>
|
||||
<TableHead>Due Date</TableHead>
|
||||
@@ -271,7 +271,7 @@ export function ResidenceDetailClient() {
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Badge variant="outline">{task.status_name || '-'}</Badge>
|
||||
{task.in_progress ? '✓' : '—'}
|
||||
</TableCell>
|
||||
<TableCell>{task.priority_name || '-'}</TableCell>
|
||||
<TableCell>{task.category_name || '-'}</TableCell>
|
||||
|
||||
@@ -108,7 +108,7 @@ export default function SettingsPage() {
|
||||
This will insert or update all lookup tables including:
|
||||
<ul className="list-disc list-inside mt-2 space-y-1">
|
||||
<li>Residence types</li>
|
||||
<li>Task categories, priorities, statuses, frequencies</li>
|
||||
<li>Task categories, priorities, frequencies</li>
|
||||
<li>Contractor specialties</li>
|
||||
<li>Subscription tiers and feature benefits</li>
|
||||
<li><strong>Task templates (60+ predefined tasks)</strong></li>
|
||||
|
||||
@@ -117,8 +117,8 @@ export function TaskDetailClient() {
|
||||
<div>{task.priority_name || '-'}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-sm font-medium text-muted-foreground">Status</div>
|
||||
<div>{task.status_name || '-'}</div>
|
||||
<div className="text-sm font-medium text-muted-foreground">In Progress</div>
|
||||
<div>{task.in_progress ? 'Yes' : 'No'}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-sm font-medium text-muted-foreground">Due Date</div>
|
||||
|
||||
@@ -62,11 +62,6 @@ export default function EditTaskPage() {
|
||||
queryFn: () => lookupsApi.priorities.list(),
|
||||
});
|
||||
|
||||
const { data: statuses, isLoading: statusesLoading } = useQuery({
|
||||
queryKey: ['lookups', 'statuses'],
|
||||
queryFn: () => lookupsApi.statuses.list(),
|
||||
});
|
||||
|
||||
const { data: frequencies, isLoading: frequenciesLoading } = useQuery({
|
||||
queryKey: ['lookups', 'frequencies'],
|
||||
queryFn: () => lookupsApi.frequencies.list(),
|
||||
@@ -85,7 +80,7 @@ export default function EditTaskPage() {
|
||||
const [formInitialized, setFormInitialized] = useState(false);
|
||||
|
||||
// Wait for ALL data including lookups before initializing form
|
||||
const lookupsLoaded = !categoriesLoading && !prioritiesLoading && !statusesLoading && !frequenciesLoading;
|
||||
const lookupsLoaded = !categoriesLoading && !prioritiesLoading && !frequenciesLoading;
|
||||
|
||||
useEffect(() => {
|
||||
if (task && lookupsLoaded && !formInitialized) {
|
||||
@@ -97,7 +92,7 @@ export default function EditTaskPage() {
|
||||
description: task.description,
|
||||
category_id: task.category_id,
|
||||
priority_id: task.priority_id,
|
||||
status_id: task.status_id,
|
||||
in_progress: task.in_progress,
|
||||
frequency_id: task.frequency_id,
|
||||
due_date: task.due_date,
|
||||
next_due_date: task.next_due_date,
|
||||
@@ -323,30 +318,15 @@ export default function EditTaskPage() {
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="status_id">Status</Label>
|
||||
<Select
|
||||
value={formData.status_id !== undefined ? formData.status_id.toString() : 'none'}
|
||||
onValueChange={(value) => {
|
||||
const newValue = value === 'none' ? undefined : Number(value);
|
||||
// Only update if actually different (prevents spurious triggers)
|
||||
if (newValue !== formData.status_id) {
|
||||
updateField('status_id', newValue);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Select status" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="none">None</SelectItem>
|
||||
{statuses?.map((status: { id: number; name: string }) => (
|
||||
<SelectItem key={status.id} value={status.id.toString()}>
|
||||
{status.name}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<div className="flex items-center space-x-2 pt-8">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="in_progress"
|
||||
checked={formData.in_progress ?? false}
|
||||
onChange={(e) => updateField('in_progress', e.target.checked)}
|
||||
className="h-4 w-4 rounded border-gray-300"
|
||||
/>
|
||||
<Label htmlFor="in_progress">In Progress</Label>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="frequency_id">Frequency</Label>
|
||||
|
||||
@@ -58,9 +58,9 @@ const columns: ColumnDef<Task>[] = [
|
||||
cell: ({ row }) => row.original.priority_name || '-',
|
||||
},
|
||||
{
|
||||
accessorKey: 'status_name',
|
||||
header: 'Status',
|
||||
cell: ({ row }) => row.original.status_name || '-',
|
||||
accessorKey: 'in_progress',
|
||||
header: 'In Progress',
|
||||
cell: ({ row }) => row.original.in_progress ? '✓' : '—',
|
||||
},
|
||||
{
|
||||
accessorKey: 'due_date',
|
||||
|
||||
@@ -517,7 +517,6 @@ const createLookupApi = (endpoint: string) => ({
|
||||
export const lookupsApi = {
|
||||
categories: createLookupApi('categories'),
|
||||
priorities: createLookupApi('priorities'),
|
||||
statuses: createLookupApi('statuses'),
|
||||
frequencies: createLookupApi('frequencies'),
|
||||
residenceTypes: createLookupApi('residence-types'),
|
||||
specialties: createLookupApi('specialties'),
|
||||
|
||||
@@ -186,8 +186,7 @@ export interface Task {
|
||||
category_name?: string;
|
||||
priority_id?: number;
|
||||
priority_name?: string;
|
||||
status_id?: number;
|
||||
status_name?: string;
|
||||
in_progress: boolean;
|
||||
frequency_id?: number;
|
||||
frequency_name?: string;
|
||||
due_date?: string;
|
||||
@@ -211,7 +210,7 @@ export interface TaskListParams extends ListParams {
|
||||
residence_id?: number;
|
||||
category_id?: number;
|
||||
priority_id?: number;
|
||||
status_id?: number;
|
||||
in_progress?: boolean;
|
||||
is_cancelled?: boolean;
|
||||
is_archived?: boolean;
|
||||
}
|
||||
@@ -223,7 +222,7 @@ export interface CreateTaskRequest {
|
||||
description?: string;
|
||||
category_id?: number;
|
||||
priority_id?: number;
|
||||
status_id?: number;
|
||||
in_progress?: boolean;
|
||||
frequency_id?: number;
|
||||
assigned_to_id?: number;
|
||||
due_date?: string;
|
||||
@@ -239,7 +238,7 @@ export interface UpdateTaskRequest {
|
||||
description?: string;
|
||||
category_id?: number;
|
||||
priority_id?: number;
|
||||
status_id?: number;
|
||||
in_progress?: boolean;
|
||||
frequency_id?: number;
|
||||
due_date?: string;
|
||||
next_due_date?: string;
|
||||
|
||||
Reference in New Issue
Block a user