Skip to content

Commit 37beed9

Browse files
committed
fix: Improve type safety in task editing and update handling of category selection
1 parent dd9db0e commit 37beed9

File tree

4 files changed

+77
-28
lines changed

4 files changed

+77
-28
lines changed

CLAUDE.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,71 @@ X_INTEGRATION_ID=your_integration_id
113113
- Edge Functions: Deno test framework
114114
- Manual testing guide available for task-management function
115115

116+
## Build Requirements and Quality Gates
117+
118+
**CRITICAL**: Before completing any task, ALL of the following must pass:
119+
120+
### 1. TypeScript Compilation
121+
```bash
122+
cd ui
123+
npm run build
124+
```
125+
- **Must succeed without errors**
126+
- **Must not use `any` types** - Use proper TypeScript interfaces
127+
- **Must not have unsafe type assertions** - Prefer type guards over `as unknown as`
128+
129+
### 2. Code Formatting
130+
```bash
131+
npx prettier --check "ui/**/*.{ts,tsx,js,jsx,json,md,yml}"
132+
```
133+
- **Must pass without formatting issues**
134+
135+
### 3. Tests
136+
```bash
137+
cd ui
138+
npm test
139+
```
140+
- **All tests must pass**
141+
142+
### Common TypeScript Issues to Avoid
143+
144+
1. **Never use `any` types**:
145+
```typescript
146+
// ❌ Bad
147+
editingField: any;
148+
149+
// ✅ Good
150+
editingField: EditingField | null;
151+
```
152+
153+
2. **Use proper type imports**:
154+
```typescript
155+
// ✅ Import types when needed
156+
import { EditingField } from "./types";
157+
```
158+
159+
3. **Avoid unsafe type assertions**:
160+
```typescript
161+
// ❌ Avoid this pattern
162+
(data as unknown as Category[])
163+
164+
// ✅ Prefer type guards or proper types
165+
data as Category[]
166+
```
167+
168+
4. **Ensure prop interfaces match usage**:
169+
- When adding new props, update both interface definitions and component usage
170+
- TaskEditProps should match actual component prop requirements
171+
172+
### Build Failure Recovery
173+
174+
If `npm run build` fails:
175+
1. Read the TypeScript error carefully
176+
2. Fix type issues systematically
177+
3. Never suppress errors with `any` types
178+
4. Update interfaces to match actual usage
179+
5. Test the build again before considering task complete
180+
116181
## Memories
117182

118183
- Be sure to run test as a completion check.

ui/src/components/task/SortableTask.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,13 @@ import { EndTimeField } from "./EndTimeField";
1111
import { TaskCategoryField } from "./TaskCategoryField";
1212
import { TaskMetaInfo } from "./TaskMetaInfo";
1313
import { Task, Category } from "@/types/task";
14+
import { EditingField } from "./types";
1415

1516
interface TaskEditActions {
16-
editingField: any;
17+
editingField: EditingField | null;
1718
editValue: string;
19+
setEditingField: (field: EditingField | null) => void;
20+
setEditValue: (value: string) => void;
1821
handleEditStart: (
1922
taskId: string,
2023
field:
@@ -26,10 +29,8 @@ interface TaskEditActions {
2629
value: string,
2730
) => void;
2831
handleEditChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
29-
handleEditSave: () => void;
32+
handleEditSave: (customValue?: string) => void;
3033
handleKeyDown: (e: React.KeyboardEvent<HTMLInputElement>) => void;
31-
setEditValue: (value: string) => void;
32-
setEditingField: (field: any) => void;
3334
}
3435

3536
interface TaskActions {

ui/src/components/task/TaskCategoryField.tsx

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,9 @@ import {
66
PopoverTrigger,
77
} from "@/components/ui/popover";
88
import { ChevronDown, Tag } from "lucide-react";
9-
import { createClient } from "@/lib/supabase/client";
109
import { TaskEditProps } from "./types";
1110
import { Category } from "@/types/task";
1211

13-
const supabase = createClient();
14-
1512
interface TaskCategoryFieldProps extends TaskEditProps {
1613
categories: Category[];
1714
}
@@ -21,7 +18,8 @@ export const TaskCategoryField = ({
2118
editingField,
2219
onEditStart,
2320
setEditValue,
24-
setEditingField,
21+
setEditingField: _setEditingField,
22+
handleEditSave,
2523
categories,
2624
}: TaskCategoryFieldProps) => {
2725
const [popoverOpen, setPopoverOpen] = useState(false);
@@ -37,26 +35,9 @@ export const TaskCategoryField = ({
3735
const handleCategorySelect = (categoryId: string) => {
3836
setPopoverOpen(false);
3937
setEditValue(categoryId);
40-
41-
if (editingField) {
42-
const { taskId } = editingField;
43-
const updateData = { category_id: categoryId };
44-
45-
const updateTask = async () => {
46-
const { error } = await supabase
47-
.from("tasks")
48-
.update(updateData)
49-
.eq("id", taskId);
50-
51-
if (error) {
52-
console.error("Error updating task category:", error);
53-
} else {
54-
setEditingField(null);
55-
}
56-
};
57-
58-
updateTask();
59-
}
38+
39+
// useTaskEditのhandleEditSaveを使用してグローバル状態も更新
40+
handleEditSave(categoryId);
6041
};
6142

6243
// カテゴリの色を取得

ui/src/hooks/useTaskEdit.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ export const useTaskEdit = (dispatch: React.Dispatch<TaskAction>) => {
5757
updateData[field] = valueToSave
5858
? new Date(valueToSave).toISOString()
5959
: null;
60+
} else if (field === "category_id") {
61+
updateData.category_id = valueToSave || null;
6062
}
6163

6264
const { error } = await supabase

0 commit comments

Comments
 (0)