feat: add advanced analytics and territory management system
- Add comprehensive analytics components with export functionality - Implement territory management with manager performance tracking - Add seatmap components for venue layout management - Create customer management features with modal interface - Add advanced hooks for dashboard flags and territory data - Implement seat selection and venue management utilities - Add type definitions for ticketing and seatmap systems 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
153
reactrebuild0825/TERRITORY_FILTERING.md
Normal file
153
reactrebuild0825/TERRITORY_FILTERING.md
Normal file
@@ -0,0 +1,153 @@
|
||||
# Territory Filtering System
|
||||
|
||||
This document describes the territory filtering system implemented for Black Canyon Tickets, which provides role-based access control at the territory level.
|
||||
|
||||
## Overview
|
||||
|
||||
The territory filtering system ensures that users can only see and manage data within their assigned territories, while providing administrators with flexible filtering capabilities.
|
||||
|
||||
## Components
|
||||
|
||||
### Core Components
|
||||
|
||||
1. **TerritoryFilter.tsx** - UI component for territory selection and display
|
||||
2. **useTerritoryFilter.ts** - Hook for managing territory filter state with URL persistence
|
||||
3. **useClaims.ts** - Hook for accessing user role and territory assignments
|
||||
4. **Query hooks** - Territory-aware data fetching hooks
|
||||
|
||||
### Data Layer
|
||||
|
||||
1. **queries/events.ts** - Events filtering with territory restrictions
|
||||
2. **queries/ticketTypes.ts** - Ticket types filtering with territory validation
|
||||
3. **queries/tickets.ts** - Tickets filtering with territory-based access
|
||||
|
||||
## Role-based Access Control
|
||||
|
||||
### Territory Manager
|
||||
- **Access**: Limited to assigned territories only
|
||||
- **Filter Control**: Cannot modify territory selection (read-only)
|
||||
- **Data Visibility**: Only events, tickets, and ticket types in assigned territories
|
||||
- **UI Behavior**: Shows badge indicating territory restriction
|
||||
|
||||
### Organization Admin / Super Admin
|
||||
- **Access**: Can view all territories in organization
|
||||
- **Filter Control**: Full control over territory selection
|
||||
- **Data Visibility**: All data by default, can filter by selected territories
|
||||
- **UI Behavior**: Shows selectable multi-territory filter with URL persistence
|
||||
|
||||
### Staff
|
||||
- **Access**: Full access within organization (can be restricted in future)
|
||||
- **Filter Control**: Full control over territory selection
|
||||
- **Data Visibility**: All organization data, respects territory filters
|
||||
|
||||
## Implementation Details
|
||||
|
||||
### URL Persistence
|
||||
- Territory filters persist in URL parameters (`?territories=AAA,BBB`)
|
||||
- LocalStorage fallback for admin users
|
||||
- Territory managers don't affect URL (their territories are fixed)
|
||||
|
||||
### Query Batching
|
||||
The `applyTerritoryFilter` utility handles Firestore's 10-item limit for `in` queries by automatically batching larger territory lists:
|
||||
|
||||
```typescript
|
||||
// Handles >10 territories by creating multiple query batches
|
||||
const chunks = [];
|
||||
for (let i = 0; i < territoryIds.length; i += 10) {
|
||||
chunks.push(territoryIds.slice(i, i + 10));
|
||||
}
|
||||
```
|
||||
|
||||
### Filter States
|
||||
- **isActive**: Territory filter is currently applied
|
||||
- **isFiltered**: Data is being filtered (either by role or by admin selection)
|
||||
- **canModifySelection**: User can change territory selection
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### EventsIndexPage
|
||||
```tsx
|
||||
import { TerritoryFilter } from '../../features/territory/TerritoryFilter';
|
||||
import { useTerritoryFilter } from '../../features/territory/useTerritoryFilter';
|
||||
import { useEventsQuery } from '../../queries/events';
|
||||
|
||||
function EventsIndexPage() {
|
||||
const { selectedTerritoryIds, setSelectedTerritories, canModifySelection } = useTerritoryFilter();
|
||||
const { events, isFiltered } = useEventsQuery(selectedTerritoryIds);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<TerritoryFilter
|
||||
selectedTerritoryIds={selectedTerritoryIds}
|
||||
onSelectionChange={setSelectedTerritories}
|
||||
selectable={canModifySelection}
|
||||
/>
|
||||
{/* Event list filtered by territories */}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### EventDetailPage
|
||||
```tsx
|
||||
function EventDetailPage() {
|
||||
const { selectedTerritoryIds, isActive, clearAll } = useTerritoryFilter();
|
||||
|
||||
return (
|
||||
<div>
|
||||
{/* Active filter banner */}
|
||||
{isActive && (
|
||||
<div className="filter-banner">
|
||||
Filtered by: {territoryNames}
|
||||
<button onClick={clearAll}>Clear</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
### Unit Tests
|
||||
- `TerritoryFilter.test.tsx` - Component behavior for different roles
|
||||
- `territory-filtering.test.ts` - Query filtering logic and access control
|
||||
|
||||
### Test Coverage
|
||||
- ✅ Territory manager sees only assigned events
|
||||
- ✅ Admin can filter via territory selection
|
||||
- ✅ URL state persistence works correctly
|
||||
- ✅ Query batching handles >10 territories
|
||||
- ✅ Role-based access matrix validation
|
||||
- ✅ Error handling for missing claims
|
||||
|
||||
## Security Considerations
|
||||
|
||||
1. **Server-side Validation**: All territory restrictions must be enforced on the backend
|
||||
2. **Row Level Security**: Database queries should include territory filtering at the RLS level
|
||||
3. **Claims Validation**: Territory assignments are stored in Firebase custom claims
|
||||
4. **Data Isolation**: Each territory's data is completely isolated from others
|
||||
|
||||
## Performance Optimization
|
||||
|
||||
1. **Query Batching**: Automatic handling of Firestore's 10-item `in` limit
|
||||
2. **Memoization**: Territory filtering logic is memoized to prevent unnecessary re-renders
|
||||
3. **Lazy Loading**: Territory data is loaded on-demand
|
||||
4. **URL Persistence**: Reduces unnecessary API calls by preserving filter state
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
1. **Hierarchical Territories**: Support for territory hierarchies and inheritance
|
||||
2. **Territory Permissions**: Fine-grained permissions within territories
|
||||
3. **Multi-organization Support**: Territory filtering across multiple organizations
|
||||
4. **Analytics Integration**: Territory-based analytics and reporting
|
||||
|
||||
## Migration Notes
|
||||
|
||||
When implementing this system:
|
||||
|
||||
1. Update all existing queries to use territory-aware hooks
|
||||
2. Add territory banners to relevant pages
|
||||
3. Test role-based access thoroughly
|
||||
4. Ensure URL state persistence works correctly
|
||||
5. Validate query performance with large territory lists
|
||||
Reference in New Issue
Block a user