Skip to content

Commit d30e3fb

Browse files
committed
feat: allow adding digital colleagues
1 parent c051ca8 commit d30e3fb

10 files changed

Lines changed: 605 additions & 5 deletions

src/components/AdvancedComponents/user-selection.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ export function UserSelection({
8989
</Card>
9090

9191
{/* Users Grid */}
92-
<div className="container grid gap-4 md:grid-cols-2 lg:grid-cols-3">
92+
<div className="container grid gap-4 md:grid-cols-2 lg:grid-cols-3 mt-4">
9393
{filteredUsers.map((user) => {
9494
// Safety check - skip rendering if user is invalid
9595
if (!user || !user.id) return null

src/components/Foundry/Views/ColleaguesView.tsx

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ import { ColleagueCard } from '../colleague-card'
1717
import { ColleagueForm } from '../colleague-form'
1818
import { UserSelection } from '../../AdvancedComponents/user-selection'
1919
import { DigitalColleagueClone } from '../foundary-clone'
20+
import { DigitalColleagueSelection } from '../digital-colleague-selection'
21+
import { AddColleagueToTeamForm } from '../add-colleague-to-team-form'
2022
import { ColleagueTypeSelection } from '../colleague-type-selection'
2123
import { DigitalColleagueOptions } from '../foundary-options'
2224
import {
@@ -28,6 +30,7 @@ import {
2830
type DigitalColleague,
2931
// type KnowledgeDocument,
3032
type User as UserType,
33+
type Team,
3134
} from '../types'
3235
import { motion, AnimatePresence } from 'motion/react'
3336
import { DashboardHero } from '../../Heros/DashboardHero'
@@ -37,12 +40,14 @@ interface ColleaguesViewProps {
3740
onColleagueAdd?: (colleague: Colleague) => void
3841
onColleagueEdit?: (colleague: Colleague) => void
3942
onColleagueDelete?: (colleague: string, type: 'human' | 'digital') => void
43+
onColleagueAddToTeam?: (colleague: DigitalColleague, teamId: number) => void
4044
compactView?: boolean
4145
departments?: string[]
4246
className?: string
4347
// New props for user and colleague selection
4448
availableUsers?: UserType[]
4549
existingDigitalColleagues?: DigitalColleague[]
50+
currentTeam?: Team
4651
availableKnowledgeDocuments?: Knowledge[]
4752
availableCapabilities?: Array<{
4853
relationTo: 'mcpTools' | 'capabilities' | 'internalTools' | 'digital-colleagues'
@@ -59,11 +64,13 @@ export default function ColleaguesView({
5964
onColleagueAdd,
6065
onColleagueEdit,
6166
onColleagueDelete,
67+
onColleagueAddToTeam,
6268
compactView = false,
6369
departments = ['Design', 'Engineering', 'Marketing', 'Product', 'Sales', 'Operations'],
6470
className,
6571
availableUsers = [],
6672
existingDigitalColleagues = [],
73+
currentTeam,
6774
availableKnowledgeDocuments = [],
6875
availableCapabilities = [],
6976
availableModels = [],
@@ -75,6 +82,7 @@ export default function ColleaguesView({
7582
const [activeTab, setActiveTab] = useState('all')
7683
const [editingColleague, setEditingColleague] = useState<DigitalColleague | null>(null)
7784
const [viewingColleague, setViewingColleague] = useState<DigitalColleague | null>(null)
85+
const [selectedColleagueForTeam, setSelectedColleagueForTeam] = useState<DigitalColleague | null>(null)
7886

7987
useEffect(() => {
8088
setColleagues(initialColleagues || [])
@@ -88,7 +96,7 @@ export default function ColleaguesView({
8896

8997
// New state for selection flows
9098
const [currentView, setCurrentView] = useState<
91-
'main' | 'typeSelection' | 'userSelection' | 'digitalOptions' | 'digitalClone' | 'form' | 'view'
99+
'main' | 'typeSelection' | 'userSelection' | 'digitalOptions' | 'digitalClone' | 'digitalSelection' | 'addToTeam' | 'form' | 'view'
92100
>('main')
93101

94102
const filteredColleagues = colleagues.filter((colleague) => {
@@ -184,6 +192,31 @@ export default function ColleaguesView({
184192
setCurrentView('main')
185193
}
186194

195+
const handleDigitalColleagueSelect = (selectedColleague: DigitalColleague) => {
196+
if (!selectedColleague || !selectedColleague.id) {
197+
console.error(
198+
'Invalid selected colleague provided to handleDigitalColleagueSelect:',
199+
selectedColleague,
200+
)
201+
return
202+
}
203+
204+
setSelectedColleagueForTeam(selectedColleague)
205+
setCurrentView('addToTeam')
206+
}
207+
208+
const handleAddColleagueToTeam = (colleague: DigitalColleague, teamId: number) => {
209+
onColleagueAddToTeam?.(colleague, teamId)
210+
setColleagues((prev) => [...prev, { ...colleague, type: 'digital' }])
211+
setSelectedColleagueForTeam(null)
212+
setCurrentView('main')
213+
}
214+
215+
const handleCancelAddToTeam = () => {
216+
setSelectedColleagueForTeam(null)
217+
setCurrentView('digitalSelection')
218+
}
219+
187220
const handleCreateNewDigital = () => {
188221
setEditingColleague(null)
189222
setCurrentView('form')
@@ -304,13 +337,39 @@ export default function ColleaguesView({
304337
if (currentView === 'digitalOptions') {
305338
return (
306339
<DigitalColleagueOptions
340+
onAddExisting={() => setCurrentView('digitalSelection')}
307341
onCloneExisting={() => setCurrentView('digitalClone')}
308342
onCreateNew={handleCreateNewDigital}
309343
onCancel={() => setCurrentView('typeSelection')}
310344
/>
311345
)
312346
}
313347

348+
if (currentView === 'digitalSelection') {
349+
return (
350+
<DigitalColleagueSelection
351+
digitalColleagues={safeExistingDigitalColleagues}
352+
onColleagueSelect={handleDigitalColleagueSelect}
353+
onCancel={() => setCurrentView('digitalOptions')}
354+
/>
355+
)
356+
}
357+
358+
if (currentView === 'addToTeam') {
359+
if (!selectedColleagueForTeam || !currentTeam) {
360+
setCurrentView('digitalSelection')
361+
return null
362+
}
363+
return (
364+
<AddColleagueToTeamForm
365+
colleague={selectedColleagueForTeam}
366+
team={currentTeam}
367+
onSave={handleAddColleagueToTeam}
368+
onCancel={handleCancelAddToTeam}
369+
/>
370+
)
371+
}
372+
314373
if (currentView === 'digitalClone') {
315374
return (
316375
<DigitalColleagueClone
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import React from 'react'
2+
import { AddColleagueToTeamForm } from './add-colleague-to-team-form'
3+
import { action } from '@storybook/addon-actions'
4+
import type { Meta, StoryObj } from '@storybook/react'
5+
import { mockDigitalColleagues } from './test-data'
6+
import type { DigitalColleague, Team } from './types'
7+
8+
const meta: Meta<typeof AddColleagueToTeamForm> = {
9+
title: 'Foundry/AddColleagueToTeamForm',
10+
component: AddColleagueToTeamForm,
11+
parameters: {
12+
layout: 'fullscreen',
13+
},
14+
}
15+
16+
export default meta
17+
18+
type Story = StoryObj<typeof AddColleagueToTeamForm>
19+
20+
// Use the first digital colleague from test data
21+
const selectedColleague: DigitalColleague = mockDigitalColleagues[0]
22+
23+
// Mock team data
24+
const mockTeam: Team = {
25+
id: 1,
26+
name: 'Product Development',
27+
description: 'Core product development team responsible for building and maintaining our main platform',
28+
systemMsg: 'Focus on quality, collaboration, and user-centric design.',
29+
members: [
30+
{
31+
relationTo: 'users',
32+
value: 'user-1',
33+
},
34+
],
35+
useProjects: true,
36+
useKnowledge: true,
37+
useFiles: true,
38+
useChat: true,
39+
updatedAt: new Date().toISOString(),
40+
createdAt: new Date().toISOString(),
41+
}
42+
43+
const mockTeamWithColleague: Team = {
44+
...mockTeam,
45+
id: 2,
46+
name: 'Marketing',
47+
description: 'Growth and marketing team driving customer acquisition and retention',
48+
members: [
49+
{
50+
relationTo: 'digital-colleagues',
51+
value: mockDigitalColleagues[0].id,
52+
},
53+
],
54+
}
55+
56+
export const Default: Story = {
57+
args: {
58+
colleague: selectedColleague,
59+
team: mockTeam,
60+
onSave: action('onSave'),
61+
onCancel: action('onCancel'),
62+
},
63+
}
64+
65+
export const ColleagueAlreadyInTeam: Story = {
66+
args: {
67+
colleague: selectedColleague,
68+
team: mockTeamWithColleague,
69+
onSave: action('onSave'),
70+
onCancel: action('onCancel'),
71+
},
72+
}
73+
74+
export const Loading: Story = {
75+
args: {
76+
colleague: selectedColleague,
77+
team: mockTeam,
78+
onSave: action('onSave'),
79+
onCancel: action('onCancel'),
80+
isLoading: true,
81+
},
82+
}

0 commit comments

Comments
 (0)