Skip to content

Commit 487bf5a

Browse files
Merge pull request #19 from foundersandcoders/feature/ap-29-cohort-overview-stats-panel
feat(attendance): enhance cohort overview with stats panel and search functionality
2 parents 2826fbe + 9aa0e32 commit 487bf5a

37 files changed

Lines changed: 2104 additions & 952 deletions

README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -182,14 +182,14 @@ The generated schema file can be used to update `src/lib/airtable/config.ts` wit
182182

183183
### Event Types
184184

185-
Event types are defined as a single source of truth in `src/lib/types/event.ts`:
185+
Event types are now managed dynamically through Airtable's "Event types - Apprentice Pulse" table. This provides:
186186

187-
```typescript
188-
export const EVENT_TYPES = ['Regular class', 'Workshop', 'Hackathon'] as const;
189-
export type EventType = typeof EVENT_TYPES[number];
190-
```
187+
- **Single source of truth**: Event types defined in Airtable only
188+
- **No code deployments**: Add/remove event types without touching code
189+
- **Flexible management**: Administrators can manage types directly in Airtable
190+
- **Automatic validation**: API endpoints validate against current Airtable data
191191

192-
To add a new event type, update the `EVENT_TYPES` array - all forms and validation will automatically use the new values.
192+
Event types are cached for performance (5-minute cache) and include automatic color assignment for UI consistency.
193193

194194
### Default Values
195195

docs/plan-search-apprentice.md

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
# Search Apprentice Feature - Implementation Plan
2+
3+
## Overview
4+
Add a Search Apprentice card to the admin dashboard that allows users to quickly search for apprentices by name and navigate directly to their detail page.
5+
6+
## User Flow
7+
1. User types in search field on admin dashboard
8+
2. System shows live search results matching the query
9+
3. User clicks on an apprentice from results
10+
4. System navigates to apprentice detail page (`/admin/apprentices/[id]`)
11+
12+
## Technical Architecture
13+
14+
### 1. Search API Endpoint
15+
**File**: `src/routes/api/apprentices/search/+server.ts`
16+
17+
- **Method**: GET
18+
- **Query params**: `q` (search query)
19+
- **Returns**: Array of matching apprentices with id, name, email, cohort
20+
- **Search logic**:
21+
- Case-insensitive search
22+
- Matches against apprentice name
23+
- Returns up to 10 results
24+
- Orders by relevance/alphabetical
25+
26+
### 2. Search Component
27+
**File**: `src/lib/components/SearchApprentice.svelte`
28+
29+
**Features**:
30+
- Text input field with search icon
31+
- Debounced search (300ms) to avoid excessive API calls
32+
- Loading state while searching
33+
- Dropdown results list
34+
- Keyboard navigation (arrow keys + enter)
35+
- Click outside to close
36+
- Empty state when no results
37+
- Error handling
38+
39+
**Props**:
40+
- No props needed (self-contained)
41+
42+
**State**:
43+
- `searchQuery`: Current search text
44+
- `searchResults`: Array of apprentice results
45+
- `isSearching`: Loading state
46+
- `showResults`: Dropdown visibility
47+
- `selectedIndex`: For keyboard navigation
48+
49+
### 3. Dashboard Integration
50+
**File**: `src/routes/admin/+page.svelte`
51+
52+
**Add new card**:
53+
```svelte
54+
<a href="/admin/apprentices" class="group block...">
55+
<SearchApprentice />
56+
</a>
57+
```
58+
59+
**Card design**:
60+
- Title: "Search Apprentice"
61+
- Description: "Find and view apprentice details"
62+
- Icon: 🔍 (magnifying glass)
63+
- Color scheme: Purple (to differentiate from other cards)
64+
65+
### 4. Data Types
66+
**File**: `src/lib/types/apprentice.ts`
67+
68+
```typescript
69+
interface ApprenticeSearchResult {
70+
id: string;
71+
name: string;
72+
email: string;
73+
cohortNumber?: number;
74+
status: 'Active' | 'On Leave' | 'Off-boarded';
75+
}
76+
```
77+
78+
## Implementation Steps
79+
80+
### Phase 1: Backend
81+
1. Create search API endpoint
82+
2. Implement Airtable search logic
83+
3. Add proper error handling
84+
4. Test with various search queries
85+
86+
### Phase 2: Search Component
87+
1. Create SearchApprentice component structure
88+
2. Implement search input with debouncing
89+
3. Add API integration
90+
4. Implement results dropdown
91+
5. Add keyboard navigation
92+
6. Style component to match existing design
93+
94+
### Phase 3: Dashboard Integration
95+
1. Add new card to admin dashboard
96+
2. Integrate SearchApprentice component
97+
3. Style card to match existing cards
98+
4. Test navigation to apprentice details
99+
100+
### Phase 4: Polish & Testing
101+
1. Add loading states
102+
2. Implement error handling
103+
3. Add empty states
104+
4. Test edge cases
105+
5. Ensure mobile responsiveness
106+
107+
## Component Structure
108+
109+
```svelte
110+
<div class="search-apprentice">
111+
<div class="search-input-wrapper">
112+
<input
113+
type="text"
114+
placeholder="Search apprentices..."
115+
bind:value={searchQuery}
116+
on:input={handleSearch}
117+
/>
118+
<svg class="search-icon">...</svg>
119+
</div>
120+
121+
{#if showResults}
122+
<div class="search-results">
123+
{#if isSearching}
124+
<div class="loading">Searching...</div>
125+
{:else if searchResults.length > 0}
126+
<ul>
127+
{#each searchResults as result, index}
128+
<li>
129+
<a href="/admin/apprentices/{result.id}">
130+
<span class="name">{result.name}</span>
131+
<span class="email">{result.email}</span>
132+
{#if result.cohortNumber}
133+
<span class="cohort">Cohort {result.cohortNumber}</span>
134+
{/if}
135+
</a>
136+
</li>
137+
{/each}
138+
</ul>
139+
{:else if searchQuery}
140+
<div class="no-results">No apprentices found</div>
141+
{/if}
142+
</div>
143+
{/if}
144+
</div>
145+
```
146+
147+
## Styling Considerations
148+
- Match existing card styles (rounded corners, shadows, hover effects)
149+
- Use purple color scheme for differentiation
150+
- Dropdown should have z-index to appear above other content
151+
- Mobile-first responsive design
152+
- Smooth transitions for dropdown appearance
153+
154+
## API Response Example
155+
```json
156+
{
157+
"success": true,
158+
"apprentices": [
159+
{
160+
"id": "recXXXXXXXXXXXXX",
161+
"name": "John Doe",
162+
"email": "john.doe@example.com",
163+
"cohortNumber": 12,
164+
"status": "Active"
165+
}
166+
]
167+
}
168+
```
169+
170+
## Error Handling
171+
- Network errors: Show "Failed to search" message
172+
- Empty results: Show "No apprentices found"
173+
- Rate limiting: Implement debouncing
174+
- Invalid input: Minimum 2 characters to search
175+
176+
## Performance Considerations
177+
- Debounce search input (300ms)
178+
- Limit results to 10 items
179+
- Cancel previous search requests if new one initiated
180+
- Cache recent searches (optional enhancement)
181+
182+
## Accessibility
183+
- Proper ARIA labels for search input
184+
- Keyboard navigation support
185+
- Screen reader announcements for results
186+
- Focus management when opening/closing dropdown
187+
188+
## Testing Checklist
189+
- [ ] Search returns correct results
190+
- [ ] Clicking result navigates to apprentice page
191+
- [ ] Keyboard navigation works
192+
- [ ] Click outside closes dropdown
193+
- [ ] Debouncing prevents excessive API calls
194+
- [ ] Error states display correctly
195+
- [ ] Loading state shows during search
196+
- [ ] Mobile responsive design works
197+
- [ ] Accessibility features work
198+
199+
## Future Enhancements
200+
- Search by email as well as name
201+
- Search by cohort number
202+
- Recent searches history
203+
- Advanced filters (status, cohort, etc.)
204+
- Fuzzy matching for typos

0 commit comments

Comments
 (0)