Files
timemaster-kiosk/lib/services/kiosk_service.dart
T
patrickandClaude Sonnet 5 d10b5d572d feat: QR-Login mit der Employee-App
Neuer 4. Login-Modus "QR" im LoginScreen: scannt den Token, den die
Employee-App unter "Am Kiosk anmelden" anzeigt (POST /kiosk/my-qr-token im
Haupt-Repo), meldet den Mitarbeiter per POST /kiosk/auth/qr an. Eigener
QrLoginScanScreen (rohe Token-String statt JSON wie beim Geräte-Enrollment-
QR). v0.1.11+12.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dzdm3EWeNdYFUuXFRJryA1
2026-09-10 14:53:54 +02:00

68 lines
2.6 KiB
Dart

import '../models/kiosk_session.dart';
import 'api_client.dart';
/// Bündelt alle /kiosk/*-Aufrufe. Device-Auth (Bearer-Token) hängt der
/// Dio-Interceptor in ApiClient automatisch an; session_token (Mitarbeiter-
/// Login) wird pro Aufruf im Body mitgegeben, siehe
/// backend/app/schemas/kiosk_auth.py.
class KioskService {
final _dio = ApiClient.instance.dio;
Future<KioskSession> loginPin(String personnelNumber, String pin) async {
final r = await _dio.post('/kiosk/auth/pin', data: {
'personnel_number': personnelNumber,
'pin': pin,
});
return KioskSession.fromJson(r.data as Map<String, dynamic>);
}
Future<KioskSession> loginNfc(String nfcUid, String pin) async {
final r = await _dio.post('/kiosk/auth/nfc', data: {
'nfc_uid': nfcUid,
'pin': pin,
});
return KioskSession.fromJson(r.data as Map<String, dynamic>);
}
Future<KioskSession> loginQr(String qrToken) async {
final r = await _dio.post('/kiosk/auth/qr', data: {'qr_token': qrToken});
return KioskSession.fromJson(r.data as Map<String, dynamic>);
}
Future<KioskSession> loginList(String userId) async {
final r = await _dio.post('/kiosk/auth/list', data: {'user_id': userId});
return KioskSession.fromJson(r.data as Map<String, dynamic>);
}
Future<List<KioskEmployee>> listEmployees() async {
final r = await _dio.get('/kiosk/auth/users');
return KioskEmployee.listFromResponse(r.data as Map<String, dynamic>);
}
Future<void> logout(String sessionToken) async {
await _dio.post('/kiosk/auth/logout', data: {'session_token': sessionToken});
}
Future<StampStatus> status(String sessionToken) async {
final r = await _dio.post('/kiosk/stamp/status', data: {'session_token': sessionToken});
return StampStatus.fromJson(r.data as Map<String, dynamic>);
}
Future<StampResult> stampIn(String sessionToken) => _stamp('in', sessionToken);
Future<StampResult> stampOut(String sessionToken) => _stamp('out', sessionToken);
Future<StampResult> breakStart(String sessionToken) => _stamp('break-start', sessionToken);
Future<StampResult> breakEnd(String sessionToken) => _stamp('break-end', sessionToken);
Future<StampResult> _stamp(String action, String sessionToken) async {
final r = await _dio.post('/kiosk/stamp/$action', data: {'session_token': sessionToken});
return StampResult.fromJson(r.data as Map<String, dynamic>);
}
Future<void> heartbeat({int queuedOfflineEntries = 0, required String clientVersion}) async {
await _dio.post('/kiosk/heartbeat', data: {
'queued_offline_entries': queuedOfflineEntries,
'client_version': clientVersion,
});
}
}