TeamBrandingContext.js
1 import { createContext, useContext, useMemo, useState, useCallback } from "react"; 2 import useAuth from "app/hooks/useAuth"; 3 import api from "app/utils/api"; 4 5 const TeamBrandingContext = createContext({ 6 branding: null, 7 teamName: null, 8 activeTeamId: null, 9 brandedTeams: [], 10 setActiveTeamId: () => {}, 11 }); 12 13 function findBrandedTeam(teams, preferredId) { 14 if (!teams || teams.length === 0) return null; 15 16 // If user has a preference, use it 17 if (preferredId) { 18 const preferred = teams.find((t) => t.id === preferredId); 19 if (preferred) return preferred; 20 } 21 22 // Fall back to first team that has branding configured 23 const withBranding = teams.find( 24 (t) => t.branding && (t.branding.primary_color || t.branding.secondary_color || t.branding.logo_url || t.branding.app_name) 25 ); 26 if (withBranding) return withBranding; 27 28 // No team has branding 29 return null; 30 } 31 32 export function TeamBrandingProvider({ children }) { 33 const { user, isAuthenticated } = useAuth(); 34 const [overrideTeamId, setOverrideTeamId] = useState(null); 35 36 const setActiveTeamId = useCallback((teamId) => { 37 setOverrideTeamId(teamId); 38 // Persist preference to backend 39 if (user && user.token) { 40 api.patch("/users/" + user.username, { options: { preferred_team_id: teamId } }, user.token).catch(() => {}); 41 } 42 }, [user]); 43 44 const value = useMemo(() => { 45 if (!isAuthenticated || !user) { 46 return { branding: null, teamName: null, activeTeamId: null, brandedTeams: [], setActiveTeamId }; 47 } 48 49 const allTeams = [...(user.teams || []), ...(user.admin_teams || [])]; 50 // Deduplicate by id 51 const seen = new Set(); 52 const uniqueTeams = allTeams.filter((t) => { 53 if (seen.has(t.id)) return false; 54 seen.add(t.id); 55 return true; 56 }); 57 58 // Teams that have any branding configured 59 const brandedTeams = uniqueTeams.filter( 60 (t) => t.branding && (t.branding.primary_color || t.branding.secondary_color || t.branding.logo_url || t.branding.app_name) 61 ); 62 63 const preferredId = overrideTeamId || user.options?.preferred_team_id; 64 const activeTeam = findBrandedTeam(uniqueTeams, preferredId); 65 66 const branding = activeTeam?.branding || null; 67 const hasAny = branding && (branding.primary_color || branding.secondary_color || branding.logo_url || branding.app_name || branding.welcome_message); 68 69 return { 70 branding: hasAny ? branding : null, 71 teamName: activeTeam?.name || null, 72 activeTeamId: activeTeam?.id || null, 73 brandedTeams, 74 setActiveTeamId, 75 }; 76 }, [isAuthenticated, user, overrideTeamId, setActiveTeamId]); 77 78 return ( 79 <TeamBrandingContext.Provider value={value}> 80 {children} 81 </TeamBrandingContext.Provider> 82 ); 83 } 84 85 export function useTeamBranding() { 86 return useContext(TeamBrandingContext); 87 }