Phase 1 scaffold: auth for all apps
- Backend: Fastify with two listeners (public + internal), routes, services, DB migration + seed - client_app: Flutter with BLoC, all auth screens (welcome, display name, register, OTP, force-register) - mitra_app: Flutter with BLoC, OTP-only login - control_center: React + Vite, email/password login, mitra/user management, anonymity settings - Docs: phase1 plan, API contract, client app mockup - CLAUDE.md and shared memory for all subprojects Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
30
mitra_app/lib/core/api/api_client.dart
Normal file
30
mitra_app/lib/core/api/api_client.dart
Normal file
@@ -0,0 +1,30 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:firebase_auth/firebase_auth.dart';
|
||||
|
||||
class ApiClient {
|
||||
static const String _baseUrl = String.fromEnvironment(
|
||||
'API_BASE_URL',
|
||||
defaultValue: 'https://api.halobestie.com',
|
||||
);
|
||||
|
||||
late final Dio _dio;
|
||||
|
||||
ApiClient() {
|
||||
_dio = Dio(BaseOptions(baseUrl: _baseUrl));
|
||||
_dio.interceptors.add(InterceptorsWrapper(
|
||||
onRequest: (options, handler) async {
|
||||
final user = FirebaseAuth.instance.currentUser;
|
||||
if (user != null) {
|
||||
final token = await user.getIdToken();
|
||||
options.headers['Authorization'] = 'Bearer $token';
|
||||
}
|
||||
handler.next(options);
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> post(String path, {Map<String, dynamic>? data}) async {
|
||||
final response = await _dio.post(path, data: data);
|
||||
return response.data as Map<String, dynamic>;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user