Skip to content

Commit 9e44a52

Browse files
committed
feat(ui): add 'Default Team for New Users' setting in Team Members
Admins can now select which team new users are added to when: - They join via organization code (no invite) - They're invited without specific team assignments The dropdown appears in the Teams tab of the Members settings.
1 parent 616cdf4 commit 9e44a52

File tree

2 files changed

+66
-4
lines changed

2 files changed

+66
-4
lines changed

bluePLM.code-workspace

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@
22
"folders": [
33
{
44
"path": "."
5-
},
6-
{
7-
"path": "../blueplm-site"
85
}
96
],
107
"settings": {}

src/components/settings/TeamMembersSettings.tsx

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ interface PendingMember {
106106
}
107107

108108
export function TeamMembersSettings() {
109-
const { user, organization, addToast, getEffectiveRole, apiServerUrl } = usePDMStore()
109+
const { user, organization, setOrganization, addToast, getEffectiveRole, apiServerUrl } = usePDMStore()
110110

111111
const isAdmin = getEffectiveRole() === 'admin'
112112

@@ -120,6 +120,7 @@ export function TeamMembersSettings() {
120120
const [pendingMembers, setPendingMembers] = useState<PendingMember[]>([])
121121
const [isLoading, setIsLoading] = useState(true)
122122
const [searchQuery, setSearchQuery] = useState('')
123+
const [isSavingDefaultTeam, setIsSavingDefaultTeam] = useState(false)
123124

124125
// Team dialogs
125126
const [selectedTeam, setSelectedTeam] = useState<TeamWithDetails | null>(null)
@@ -754,6 +755,35 @@ export function TeamMembersSettings() {
754755
setCopyFromTeamId(null)
755756
}
756757

758+
// Update the default team for new users (joining without invite or with invite but no teams)
759+
const handleSetDefaultTeam = async (teamId: string | null) => {
760+
if (!organization?.id) return
761+
762+
setIsSavingDefaultTeam(true)
763+
try {
764+
const { error } = await supabase
765+
.from('organizations')
766+
.update({ default_new_user_team_id: teamId })
767+
.eq('id', organization.id)
768+
769+
if (error) throw error
770+
771+
// Update local organization state
772+
setOrganization({
773+
...organization,
774+
default_new_user_team_id: teamId
775+
})
776+
777+
const teamName = teamId ? teams.find(t => t.id === teamId)?.name : 'None'
778+
addToast('success', `Default team set to "${teamName}"`)
779+
} catch (err) {
780+
console.error('Failed to set default team:', err)
781+
addToast('error', 'Failed to update default team')
782+
} finally {
783+
setIsSavingDefaultTeam(false)
784+
}
785+
}
786+
757787
const openEditTeamDialog = (team: TeamWithDetails) => {
758788
setSelectedTeam(team)
759789
setTeamFormData({
@@ -1504,6 +1534,41 @@ export function TeamMembersSettings() {
15041534
{activeTab === 'teams' && (
15051535
<div className="space-y-3">
15061536

1537+
{/* Default Team for New Users Setting */}
1538+
{isAdmin && teams.length > 0 && (
1539+
<div className="p-4 bg-plm-bg rounded-lg border border-plm-border">
1540+
<div className="flex items-center justify-between gap-4">
1541+
<div className="flex items-center gap-3">
1542+
<div className="p-2 rounded-lg bg-plm-accent/10">
1543+
<UserPlus size={18} className="text-plm-accent" />
1544+
</div>
1545+
<div>
1546+
<h4 className="text-sm font-medium text-plm-fg">Default Team for New Users</h4>
1547+
<p className="text-xs text-plm-fg-muted">
1548+
Users joining via org code (or invited without specific teams) will be added here
1549+
</p>
1550+
</div>
1551+
</div>
1552+
<div className="flex items-center gap-2">
1553+
<select
1554+
value={(organization as any)?.default_new_user_team_id || ''}
1555+
onChange={(e) => handleSetDefaultTeam(e.target.value || null)}
1556+
disabled={isSavingDefaultTeam}
1557+
className="px-3 py-1.5 text-sm bg-plm-bg-secondary border border-plm-border rounded-lg text-plm-fg focus:outline-none focus:border-plm-accent disabled:opacity-50"
1558+
>
1559+
<option value="">No default (unassigned)</option>
1560+
{teams.map(team => (
1561+
<option key={team.id} value={team.id}>{team.name}</option>
1562+
))}
1563+
</select>
1564+
{isSavingDefaultTeam && (
1565+
<Loader2 size={14} className="animate-spin text-plm-fg-muted" />
1566+
)}
1567+
</div>
1568+
</div>
1569+
</div>
1570+
)}
1571+
15071572
{filteredTeams.length === 0 ? (
15081573
<div className="text-center py-8 border border-dashed border-plm-border rounded-lg">
15091574
<Users size={36} className="mx-auto text-plm-fg-muted mb-3 opacity-50" />

0 commit comments

Comments
 (0)