Context Providers
React context providers for global state management in Lager Guru.
Overview
Lager Guru uses React Context API for global state management. Context providers wrap the application and provide shared state to all child components.
AuthProvider
Provides authentication state and methods throughout the application.
Source: src/contexts/AuthContext.tsx
State
typescript
{
user: User | null; // Current authenticated user
session: Session | null; // Current session
userRole: UserRole | null; // User role (admin, driver, worker)
loading: boolean; // Loading state
}Methods
typescript
{
signIn: (email: string, password: string) => Promise<{ error: any }>;
signUp: (email: string, password: string, fullName: string) => Promise<{ error: any }>;
signOut: () => Promise<void>;
}Usage
Wrap the app:
typescript
import { AuthProvider } from '@/contexts/AuthContext';
function App() {
return (
<AuthProvider>
<Router>
{/* Your app components */}
</Router>
</AuthProvider>
);
}Consume in components:
typescript
import { useAuth } from '@/contexts/AuthContext';
function MyComponent() {
const { user, userRole, signOut } = useAuth();
if (!user) {
return <div>Please log in</div>;
}
return (
<div>
<p>Welcome, {user.email}</p>
<p>Role: {userRole}</p>
<button onClick={signOut}>Sign Out</button>
</div>
);
}Features
- Automatic session management
- User role fetching
- Profile synchronization
- Automatic redirect on auth state change
- Query cache invalidation on sign out
BrandingProvider
Manages application branding (colors, logos, themes).
Source: src/contexts/BrandingContext.tsx
State
typescript
{
branding: Branding; // Current branding configuration
setBranding: (b: Branding) => void; // Update branding
}Branding Interface
typescript
interface Branding {
primaryColor: string;
accentColor: string;
logoUrl?: string;
companyName?: string;
}Usage
Wrap the app:
typescript
import { BrandingProvider } from '@/contexts/BrandingContext';
function App() {
return (
<BrandingProvider>
<AuthProvider>
{/* Rest of app */}
</AuthProvider>
</BrandingProvider>
);
}Consume in components:
typescript
import { useBranding } from '@/contexts/BrandingContext';
function ThemedComponent() {
const { branding } = useBranding();
return (
<div style={{
backgroundColor: branding.primaryColor,
color: branding.accentColor
}}>
<img src={branding.logoUrl} alt="Logo" />
</div>
);
}Features
- Loads branding from configuration
- Applies CSS variables for theming
- Supports dynamic branding updates
- Tenant-specific branding support
LanguageContext
Manages application language and translations.
Source: src/contexts/LanguageContext.tsx
State
typescript
{
language: string; // Current language code (e.g., 'en', 'de', 'bg')
setLanguage: (lang: string) => void; // Change language
t: (key: string) => string; // Translation function
}Usage
Wrap the app:
typescript
import { LanguageProvider } from '@/contexts/LanguageContext';
function App() {
return (
<LanguageProvider>
<BrandingProvider>
{/* Rest of app */}
</BrandingProvider>
</LanguageProvider>
);
}Consume in components:
typescript
import { useLanguage } from '@/contexts/LanguageContext';
function TranslatedComponent() {
const { language, setLanguage, t } = useLanguage();
return (
<div>
<h1>{t('welcome.title')}</h1>
<select value={language} onChange={e => setLanguage(e.target.value)}>
<option value="en">English</option>
<option value="de">Deutsch</option>
<option value="bg">Български</option>
</select>
</div>
);
}Supported Languages
- English (en)
- German (de)
- Bulgarian (bg)
Provider Hierarchy
Context providers should be nested in the following order:
typescript
function App() {
return (
<LanguageProvider>
<BrandingProvider>
<AuthProvider>
<QueryClientProvider client={queryClient}>
<Router>
{/* Your app components */}
</Router>
</QueryClientProvider>
</AuthProvider>
</BrandingProvider>
</LanguageProvider>
);
}Order Matters
- LanguageProvider (outermost) - Language doesn't depend on other contexts
- BrandingProvider - Branding may use language for translations
- AuthProvider - Authentication may use branding for UI
- QueryClientProvider - React Query for data fetching
- Router - Routing depends on auth state
Custom Context Pattern
To create a new context provider:
typescript
import { createContext, useContext, useState, ReactNode } from 'react';
// 1. Define context type
interface MyContextType {
value: string;
setValue: (v: string) => void;
}
// 2. Create context
const MyContext = createContext<MyContextType | undefined>(undefined);
// 3. Create provider component
export const MyProvider = ({ children }: { children: ReactNode }) => {
const [value, setValue] = useState<string>('');
return (
<MyContext.Provider value={{ value, setValue }}>
{children}
</MyContext.Provider>
);
};
// 4. Create hook for consuming context
export const useMyContext = () => {
const context = useContext(MyContext);
if (context === undefined) {
throw new Error('useMyContext must be used within MyProvider');
}
return context;
};Best Practices
- Always check context existence: Throw error if hook used outside provider
- Minimize re-renders: Use
useMemoanduseCallbackfor expensive operations - Separate concerns: Don't mix unrelated state in one context
- Type safety: Always define TypeScript interfaces for context values
- Provider order: Place providers in logical dependency order
Related Documentation
- Hooks - Custom React hooks
- API Reference - Complete API documentation
- React Context - React Context API