8.9 KiB
COPILOT_README.md
This file provides guidance to Github Copilot when working with code in this repository.
Development Commands
- Run tests:
flutter test - Run static analysis:
flutter analyze(Must be clean before submission) - Format code:
dart format lib/ test/ - Build Android APK:
flutter build apk --release - Build iOS:
flutter build ios --release - Build Windows:
flutter build windows --release
Development Workflow
- Code: Write feature with implementation in
lib/and tests intest/ - Analyze:
flutter analyze(Must be clean) - Test:
flutter test(Must pass without overflow or rendering exceptions) - Verify: Ensure UI matches the Hybrid M3/M2 guidelines
Architecture Overview
TasQ is a Flutter task management application with Supabase backend. The architecture follows a clean separation:
State Management → Providers (Riverpod) → Repository/Service → Supabase
↓
Widgets (UI)
Core Stack
- Framework: Flutter with Material 3 (
useMaterial3: true) - State Management: Riverpod with
StreamProvider,StateNotifier, andFutureProvider - Routing: Go Router with auth-based redirects and ShellRoute for layout
- Backend: Supabase (PostgreSQL + Auth + Realtime)
UI/UX Design System (M3 Expressive)
Strictly follow the Material 3 Expressive approach:
- Base Theme:
useMaterial3: true. Seed color#4A6FA5drives the entire tonal palette viaColorScheme.fromSeed. - Cards & Surfaces:
- Use tonal elevation (surface tint color overlays) instead of drop-shadows.
- Three M3 card variants: Elevated (tonal tint, minimal shadow), Filled (surfaceContainerHighest, no shadow), Outlined (outline border, transparent fill).
- Card token rules:
- Default
cardTheme.elevation: 1 with transparent shadow (usessurfaceTintColorfor tonal depth). cardTheme.shape.borderRadius: 16 dp.- No hard borders unless using the Outlined variant (which uses
outlineVariant).
- Default
- Status/summary cards use Filled variant with semantic container colors (
errorContainer,tertiaryContainer, etc.). - Use
M3Card.elevated(),M3Card.filled(), orM3Card.outlined()fromlib/widgets/m3_card.dartfor new cards.
- Corner Radii (M3 Expressive):
- Large containers / dialogs / bottom sheets: 28 dp.
- Standard cards: 16 dp.
- Compact list items: 12 dp.
- Chips / badges: 12 dp.
- Buttons (M3 hierarchy):
FilledButton— primary actions.FilledButton.tonal— secondary emphasis.OutlinedButton— tertiary / neutral actions.TextButton— low-emphasis / destructive cancel.- Do NOT use
ElevatedButton— useFilledButtoninstead.
- Motion (M3 Expressive):
- Standard duration: 400 ms with
Curves.easeInOutCubicEmphasized. - Use
M3Motionconstants fromlib/theme/m3_motion.dart. - Container transitions:
AnimatedContainerwith M3 curves. - Page transitions: shared-axis (vertical) using
M3SharedAxisRoute. - List item reveal:
M3FadeSlideInwith staggered delays.
- Standard duration: 400 ms with
- Typography: Strict adherence to
TextThemevariables (e.g.,titleLarge,bodyMedium); NO hardcoded font sizes. - Navigation:
- Mobile:
NavigationBar(bottom) with pill-shaped indicators. - Tablet:
NavigationRail(collapsed) with tonal surface container. - Desktop:
NavigationRail(extended) with branding in the leading area.
- Mobile:
Data Fetching & Search (Critical)
Server-Side Pagination:
- ALWAYS implement server-side pagination using Supabase
.range(start, end). - Do NOT fetch all rows and filter locally.
- Standard page size: 50 items (Desktop), Infinite Scroll chunks (Mobile).
Full Text Search (FTS):
- Use Supabase
.textSearch()or.ilike()on the server side. - Search state must be managed in a Riverpod provider (e.g.,
searchQueryProvider) and passed to the repository stream.
Real-Time Data:
- Use
StreamProviderfor live updates, but ensure streams respect current search/filter parameters.
Data Flow Pattern
- Supabase Queries: Server-side pagination and search via
.range()and.textSearch() - Providers (
lib/providers/) expose data viaStreamProviderfor real-time updates - Providers handle role-based data filtering (admin/dispatcher/it_staff have global access; standard users are filtered by office assignments)
- Widgets consume providers using
ConsumerWidgetorConsumerStatefulWidget - Controllers (
*Controllerclasses) handle mutations (create/update/delete)
Debugging & Troubleshooting Protocol
- RLS vs. Logic:
- If data returns empty or incomplete, DO NOT assume it is a Row Level Security (RLS) issue immediately.
- Step 1: Check the query logic, specifically
.range()offsets and.eq()filters. - Step 2: Verify the user role and search term binding.
- Step 3: Only check RLS if specific error codes (
401,403,PGRST) are returned.
Key Patterns
Role-Based Access Control: User roles (admin, dispatcher, it_staff, standard) determine data visibility and available UI sections. See lib/routing/app_router.dart for routing guards and lib/providers/ for data filters.
TasQAdaptiveList:
- Mobile: Tile-based list with infinite scroll listeners.
- Desktop: Data Table with paginated footer.
- Input: Requires a reactive data source (
Stream<List<T>>) that responds to pagination/search providers.
Responsive Design:
- Support: Mobile (<600px), Tablet (600-1024px), Desktop (>1024px)
- Implementation:
LayoutBuilderorResponsiveWrapper - Mobile: Single-column, Infinite Scroll, Bottom Navigation
- Desktop: Multi-column (Row/Grid), Pagination Controls, Sidebar Navigation
M3 Expressive Theme: See lib/theme/app_theme.dart:
- Pure Material 3 Expressive — no M2 fallbacks
- Tonal elevation (surface tint) instead of drop-shadows
- 28 dp radius for large containers, 16 dp for cards
- See
lib/theme/m3_motion.dartfor animation constants - See
lib/widgets/m3_card.dartfor M3 card variants
Important Providers
| Provider | Purpose |
|---|---|
authStateChangesProvider |
Auth state stream |
sessionProvider |
Current session |
supabaseClientProvider |
Supabase client instance |
currentProfileProvider |
Current user's profile with role |
ticketsProvider |
User's accessible tickets (filtered by office) |
tasksProvider |
User's accessible tasks |
Time Handling
All timestamps use Asia/Manila timezone via the timezone package. Use AppTime.parse() for parsing and AppTime.format() for display. See lib/utils/app_time.dart.
UI Conventions
- Zero Overflow Policy: Wrap all text in
Flexible/ExpandedwithinRow/Flex. UseSingleChildScrollViewfor tall layouts. - Responsive Breakpoints: Mobile (<600px), Tablet (600-1024px), Desktop (>1024px)
- Mono Text: Technical data uses
MonoTextwidget (defined inlib/theme/app_typography.dart) - Status Pills: Use
StatusPillwidget for status display
Project Conventions
- Testing: Layout Smoke Test only, and do not create and run tests unless I say so.
- Documentation: DartDoc (
///) for public APIs. Explain Why, not just How. - Environment:
.envfile managesSUPABASE_URLandSUPABASE_ANON_KEY. - Audio: Notification sounds via
audioplayers. - Key Files:
lib/app.dart: App setup/theme.lib/routing/app_router.dart: Routing & Auth guards.lib/providers/: State management.
Testing Strategy
- Tests located in
test/directory - Use Riverpod's
ProviderScopewithoverrideWithfor mocking - Mock Supabase client using
SupabaseClient('http://localhost', 'test-key') - Layout tests use
tester.pump()with 16ms delay for animations
Project Structure
lib/
├── app.dart # App entrypoint (theme/router)
├── main.dart # Widget initialization
├── models/ # Data models (fromMap/toJson)
├── providers/ # Riverpod providers & controllers
├── routing/
│ └── app_router.dart # Go Router config with auth guards
├── screens/ # Screen widgets
│ ├── admin/ # Admin-only screens
│ ├── auth/ # Login/Signup
│ ├── dashboard/ # Dashboard
│ ├── notifications/ # Notification center
│ ├── tasks/ # Task management
│ ├── tickets/ # Ticket management
│ ├── teams/ # Team management
│ ├── workforce/ # Workforce management
│ └── shared/ # Shared components
├── theme/ # AppTheme, typography
├── utils/ # Utilities (AppTime)
└── widgets/ # Reusable widgets