Skip to content

Commit 086551b

Browse files
Merge pull request #49 from ka1ea6/fix/reminders-and-colleagues
feat: applies fixes on colleagues and tasks
2 parents 34aa445 + b371cf8 commit 086551b

7 files changed

Lines changed: 489 additions & 354 deletions

File tree

src/components/DigitalColleagues/Views/ColleaguesView.tsx

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -64,19 +64,27 @@ export default function ColleaguesView({
6464
setColleagues(initialColleagues || [])
6565
}, [initialColleagues])
6666

67+
// Ensure props are arrays to prevent iteration errors
68+
const safeAvailableUsers = Array.isArray(availableUsers) ? availableUsers : []
69+
const safeExistingDigitalColleagues = Array.isArray(existingDigitalColleagues)
70+
? existingDigitalColleagues
71+
: []
72+
6773
// New state for selection flows
6874
const [currentView, setCurrentView] = useState<
6975
'main' | 'typeSelection' | 'userSelection' | 'digitalOptions' | 'digitalClone' | 'form' | 'view'
7076
>('main')
7177

7278
const filteredColleagues = colleagues.filter((colleague) => {
79+
if (!colleague || !colleague.name) return false
80+
7381
const matchesSearch =
7482
colleague.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
7583
(colleague.type === 'human' &&
76-
(colleague.email.toLowerCase().includes(searchTerm.toLowerCase()) ||
77-
colleague.role.toLowerCase().includes(searchTerm.toLowerCase()))) ||
84+
(colleague.email?.toLowerCase().includes(searchTerm.toLowerCase()) ||
85+
colleague.role?.toLowerCase().includes(searchTerm.toLowerCase()))) ||
7886
(colleague.type === 'digital' &&
79-
colleague.jobDescription.toLowerCase().includes(searchTerm.toLowerCase()))
87+
colleague.jobDescription?.toLowerCase().includes(searchTerm.toLowerCase()))
8088

8189
const matchesDepartment =
8290
departmentFilter === 'all' ||
@@ -113,6 +121,8 @@ export default function ColleaguesView({
113121

114122
// New handler functions
115123
const handleUserSelect = (user: UserType) => {
124+
// Validate user object
125+
116126
// Convert User to HumanColleague
117127
const humanColleague: HumanColleague = {
118128
id: `human-${Date.now()}`,
@@ -124,7 +134,7 @@ export default function ColleaguesView({
124134
phone: user.phone,
125135
location: user.location,
126136
timezone: user.timezone,
127-
skills: user.skills,
137+
skills: user.skills || [],
128138
bio: user.bio,
129139
status: 'active',
130140
joinedDate: new Date(),
@@ -137,6 +147,14 @@ export default function ColleaguesView({
137147
}
138148

139149
const handleDigitalColleagueClone = (clonedColleague: DigitalColleague) => {
150+
if (!clonedColleague || !clonedColleague.id) {
151+
console.error(
152+
'Invalid cloned colleague provided to handleDigitalColleagueClone:',
153+
clonedColleague,
154+
)
155+
return
156+
}
157+
140158
setColleagues((prev) => [...prev, clonedColleague])
141159
onColleagueAdd?.(clonedColleague)
142160
setCurrentView('main')
@@ -148,6 +166,11 @@ export default function ColleaguesView({
148166
}
149167

150168
const handleSaveColleague = (colleague: DigitalColleague) => {
169+
if (!colleague || !colleague.id) {
170+
console.error('Invalid colleague provided to handleSaveColleague:', colleague)
171+
return
172+
}
173+
151174
if (editingColleague) {
152175
// Update existing colleague
153176
setColleagues((prev) => prev.map((c) => (c.id === colleague.id ? colleague : c)))
@@ -197,14 +220,24 @@ export default function ColleaguesView({
197220
const allDocuments: KnowledgeDocument[] = []
198221

199222
// Get documents from existing digital colleagues
200-
existingDigitalColleagues.forEach((colleague) => {
201-
allDocuments.push(...colleague.knowledge, ...colleague.coreKnowledge)
223+
safeExistingDigitalColleagues.forEach((colleague) => {
224+
if (colleague.knowledge && Array.isArray(colleague.knowledge)) {
225+
allDocuments.push(...colleague.knowledge)
226+
}
227+
if (colleague.coreKnowledge && Array.isArray(colleague.coreKnowledge)) {
228+
allDocuments.push(...colleague.coreKnowledge)
229+
}
202230
})
203231

204232
// Get documents from current colleagues in state
205233
colleagues.forEach((colleague) => {
206234
if (colleague.type === 'digital') {
207-
allDocuments.push(...colleague.knowledge, ...colleague.coreKnowledge)
235+
if (colleague.knowledge && Array.isArray(colleague.knowledge)) {
236+
allDocuments.push(...colleague.knowledge)
237+
}
238+
if (colleague.coreKnowledge && Array.isArray(colleague.coreKnowledge)) {
239+
allDocuments.push(...colleague.coreKnowledge)
240+
}
208241
}
209242
})
210243

@@ -230,7 +263,7 @@ export default function ColleaguesView({
230263
if (currentView === 'userSelection') {
231264
return (
232265
<UserSelection
233-
users={availableUsers}
266+
users={safeAvailableUsers}
234267
onUserSelect={handleUserSelect}
235268
onCancel={() => setCurrentView('typeSelection')}
236269
/>
@@ -250,7 +283,7 @@ export default function ColleaguesView({
250283
if (currentView === 'digitalClone') {
251284
return (
252285
<DigitalColleagueClone
253-
digitalColleagues={existingDigitalColleagues}
286+
digitalColleagues={safeExistingDigitalColleagues}
254287
onColleagueClone={handleDigitalColleagueClone}
255288
onCancel={() => setCurrentView('digitalOptions')}
256289
/>
@@ -433,7 +466,7 @@ export default function ColleaguesView({
433466
>
434467
{filteredColleagues.map((colleague) => (
435468
<ColleagueCard
436-
key={colleague.id}
469+
key={`${colleague}-${colleague.id}`}
437470
colleague={colleague}
438471
onEdit={handleEditColleague}
439472
onDelete={handleDeleteColleague}

src/components/Projects/AddTaskModal.tsx

Lines changed: 49 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,15 @@ import { Label } from '@/components/ui/label'
2020
import { Badge } from '@/components/ui/badge'
2121
import { ToggleGroup, ToggleGroupItem } from '@/components/ui/toggle-group'
2222
import { BookOpen, Bug, Zap, AlertCircle } from 'lucide-react'
23-
import { Task, Epic, Sprint } from '../DigitalColleagues/types'
23+
import { Task, Epic, Sprint, User, DigitalColleague } from '../DigitalColleagues/types'
2424

2525
interface AddTaskModalProps {
2626
isOpen: boolean
2727
onClose: () => void
2828
onAddTask: (task: Omit<Task, 'id' | 'createdAt'>) => void
2929
epics: Epic[]
3030
sprints: Sprint[]
31+
assignees: (User | DigitalColleague)[]
3132
defaultEpicId?: string
3233
}
3334

@@ -55,6 +56,7 @@ export const AddTaskModal: React.FC<AddTaskModalProps> = ({
5556
onAddTask,
5657
epics,
5758
sprints,
59+
assignees,
5860
defaultEpicId,
5961
}) => {
6062
const [formData, setFormData] = useState({
@@ -86,7 +88,7 @@ export const AddTaskModal: React.FC<AddTaskModalProps> = ({
8688
priority: 'medium',
8789
type: 'story',
8890
points: 1,
89-
epicId: '',
91+
epicId: defaultEpicId || '',
9092
sprintId: 'none',
9193
assignee: '',
9294
})
@@ -114,7 +116,7 @@ export const AddTaskModal: React.FC<AddTaskModalProps> = ({
114116
priority: 'medium',
115117
type: 'story',
116118
points: 1,
117-
epicId: '',
119+
epicId: defaultEpicId || '',
118120
sprintId: 'none',
119121
assignee: '',
120122
})
@@ -216,27 +218,29 @@ export const AddTaskModal: React.FC<AddTaskModalProps> = ({
216218
</div>
217219

218220
{/* Epic Selection */}
219-
<div className="space-y-2">
220-
<Label htmlFor="epic">Epic</Label>
221-
<Select
222-
value={formData.epicId}
223-
onValueChange={(value) => handleChange('epicId', value)}
224-
>
225-
<SelectTrigger>
226-
<SelectValue placeholder="Select an epic" />
227-
</SelectTrigger>
228-
<SelectContent>
229-
{epics.map((epic) => (
230-
<SelectItem key={epic.id} value={epic.id}>
231-
<div className="flex items-center gap-2">
232-
<div className={`w-3 h-3 rounded-full ${epic.color}`}></div>
233-
{epic.name}
234-
</div>
235-
</SelectItem>
236-
))}
237-
</SelectContent>
238-
</Select>
239-
</div>
221+
{!defaultEpicId && (
222+
<div className="space-y-2">
223+
<Label htmlFor="epic">Epic</Label>
224+
<Select
225+
value={formData.epicId}
226+
onValueChange={(value) => handleChange('epicId', value)}
227+
>
228+
<SelectTrigger>
229+
<SelectValue placeholder="Select an epic" />
230+
</SelectTrigger>
231+
<SelectContent>
232+
{epics.map((epic) => (
233+
<SelectItem key={epic.id} value={epic.id}>
234+
<div className="flex items-center gap-2">
235+
<div className={`w-3 h-3 rounded-full ${epic.color}`}></div>
236+
{epic.name}
237+
</div>
238+
</SelectItem>
239+
))}
240+
</SelectContent>
241+
</Select>
242+
</div>
243+
)}
240244

241245
{/* Sprint Selection */}
242246
<div className="space-y-2">
@@ -267,14 +271,34 @@ export const AddTaskModal: React.FC<AddTaskModalProps> = ({
267271
</div>
268272

269273
<div className="space-y-2">
274+
<Label htmlFor="sprint">Assignee</Label>
275+
<Select
276+
value={formData.assignee}
277+
onValueChange={(value) => handleChange('assignee', value)}
278+
>
279+
<SelectTrigger>
280+
<SelectValue placeholder="Select an Assignee" />
281+
</SelectTrigger>
282+
<SelectContent>
283+
<SelectItem value="none">No Assignee</SelectItem>
284+
{assignees.map((user) => (
285+
<SelectItem key={user.id} value={user.id}>
286+
<div className="flex items-center gap-2">{user.name}</div>
287+
</SelectItem>
288+
))}
289+
</SelectContent>
290+
</Select>
291+
</div>
292+
293+
{/* <div className="space-y-2">
270294
<Label htmlFor="assignee">Assignee</Label>
271295
<Input
272296
id="assignee"
273297
value={formData.assignee}
274298
onChange={(e) => handleChange('assignee', e.target.value)}
275299
placeholder="Enter assignee name"
276300
/>
277-
</div>
301+
</div> */}
278302

279303
<DialogFooter>
280304
<Button type="button" variant="outline" onClick={onClose}>

0 commit comments

Comments
 (0)