111 lines
2.9 KiB
TypeScript
111 lines
2.9 KiB
TypeScript
import { createContext, useContext, useState, useEffect, useCallback, ReactNode } from 'react';
|
|
import { TeamDetail } from '../types';
|
|
import { listTeams } from '../api';
|
|
import { useAuth } from './AuthContext';
|
|
|
|
const SELECTED_TEAM_KEY = 'orchard_selected_team';
|
|
|
|
interface TeamContextType {
|
|
teams: TeamDetail[];
|
|
currentTeam: TeamDetail | null;
|
|
loading: boolean;
|
|
error: string | null;
|
|
setCurrentTeam: (team: TeamDetail | null) => void;
|
|
refreshTeams: () => Promise<void>;
|
|
clearError: () => void;
|
|
}
|
|
|
|
const TeamContext = createContext<TeamContextType | undefined>(undefined);
|
|
|
|
interface TeamProviderProps {
|
|
children: ReactNode;
|
|
}
|
|
|
|
export function TeamProvider({ children }: TeamProviderProps) {
|
|
const { user } = useAuth();
|
|
const [teams, setTeams] = useState<TeamDetail[]>([]);
|
|
const [currentTeam, setCurrentTeamState] = useState<TeamDetail | null>(null);
|
|
const [loading, setLoading] = useState(false);
|
|
const [error, setError] = useState<string | null>(null);
|
|
|
|
const loadTeams = useCallback(async () => {
|
|
if (!user) {
|
|
setTeams([]);
|
|
setCurrentTeamState(null);
|
|
return;
|
|
}
|
|
|
|
setLoading(true);
|
|
setError(null);
|
|
try {
|
|
const response = await listTeams({ limit: 100 });
|
|
setTeams(response.items);
|
|
|
|
// Try to restore previously selected team
|
|
const savedSlug = localStorage.getItem(SELECTED_TEAM_KEY);
|
|
if (savedSlug) {
|
|
const savedTeam = response.items.find(t => t.slug === savedSlug);
|
|
if (savedTeam) {
|
|
setCurrentTeamState(savedTeam);
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Auto-select first team if none selected
|
|
if (response.items.length > 0 && !currentTeam) {
|
|
setCurrentTeamState(response.items[0]);
|
|
localStorage.setItem(SELECTED_TEAM_KEY, response.items[0].slug);
|
|
}
|
|
} catch (err) {
|
|
const message = err instanceof Error ? err.message : 'Failed to load teams';
|
|
setError(message);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
}, [user, currentTeam]);
|
|
|
|
// Load teams when user changes
|
|
useEffect(() => {
|
|
loadTeams();
|
|
}, [user]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
|
|
const setCurrentTeam = useCallback((team: TeamDetail | null) => {
|
|
setCurrentTeamState(team);
|
|
if (team) {
|
|
localStorage.setItem(SELECTED_TEAM_KEY, team.slug);
|
|
} else {
|
|
localStorage.removeItem(SELECTED_TEAM_KEY);
|
|
}
|
|
}, []);
|
|
|
|
const refreshTeams = useCallback(async () => {
|
|
await loadTeams();
|
|
}, [loadTeams]);
|
|
|
|
const clearError = useCallback(() => {
|
|
setError(null);
|
|
}, []);
|
|
|
|
return (
|
|
<TeamContext.Provider value={{
|
|
teams,
|
|
currentTeam,
|
|
loading,
|
|
error,
|
|
setCurrentTeam,
|
|
refreshTeams,
|
|
clearError,
|
|
}}>
|
|
{children}
|
|
</TeamContext.Provider>
|
|
);
|
|
}
|
|
|
|
export function useTeam() {
|
|
const context = useContext(TeamContext);
|
|
if (context === undefined) {
|
|
throw new Error('useTeam must be used within a TeamProvider');
|
|
}
|
|
return context;
|
|
}
|