implemented foreign timetable support for students, teachers, rooms, and classes, including a searchable element picker with favorites support, introduced a capabilities system for feature gating, refactored the timetable UI into a reusable TimetableCalendarView component, and redesigned the chat input field with a unified emoji picker and integrated attachment actions.
This commit is contained in:
+43
@@ -0,0 +1,43 @@
|
||||
/// A concrete, selectable timetable element: its type, WebUntis element id and
|
||||
/// a human-readable label (room short name, abbreviated student name, …). Used
|
||||
/// to hand a picker selection back to the timetable view and to drive the
|
||||
/// inline foreign-plan rendering.
|
||||
typedef TimetableElementRef = ({TimetableElementType type, int id, String label});
|
||||
|
||||
/// The four kinds of timetable elements whose schedule can be requested via
|
||||
/// `timetable/{type}/{id}`. `schoolClass` is named to avoid the reserved Dart
|
||||
/// keyword `class`; its [pathSegment] maps back to the backend's `class`.
|
||||
enum TimetableElementType {
|
||||
student,
|
||||
teacher,
|
||||
room,
|
||||
schoolClass;
|
||||
|
||||
/// Path segment used in the backend timetable endpoint URL.
|
||||
String get pathSegment {
|
||||
switch (this) {
|
||||
case TimetableElementType.student:
|
||||
return 'student';
|
||||
case TimetableElementType.teacher:
|
||||
return 'teacher';
|
||||
case TimetableElementType.room:
|
||||
return 'room';
|
||||
case TimetableElementType.schoolClass:
|
||||
return 'class';
|
||||
}
|
||||
}
|
||||
|
||||
/// Singular German label for the UI (picker segments, hints).
|
||||
String get label {
|
||||
switch (this) {
|
||||
case TimetableElementType.student:
|
||||
return 'Schüler';
|
||||
case TimetableElementType.teacher:
|
||||
return 'Lehrer';
|
||||
case TimetableElementType.room:
|
||||
return 'Raum';
|
||||
case TimetableElementType.schoolClass:
|
||||
return 'Klasse';
|
||||
}
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
import 'package:dio/dio.dart';
|
||||
|
||||
import '../../errors/marianumconnect_error.dart';
|
||||
import '../../marianumconnect_api.dart';
|
||||
import '../../marianumconnect_endpoint.dart';
|
||||
import '../timetable_get_week/timetable_get_week_response.dart';
|
||||
import 'timetable_element_type.dart';
|
||||
|
||||
/// Fetches a foreign element's weekly timetable from
|
||||
/// `timetable/{student|teacher|room|class}/{id}`. The response shape is
|
||||
/// identical to `timetable/me`, so [TimetableGetWeekResponse] is reused.
|
||||
class TimetableGetElementWeek {
|
||||
final Dio _dio;
|
||||
|
||||
TimetableGetElementWeek({Dio? dio}) : _dio = dio ?? MarianumConnectApi.dio();
|
||||
|
||||
Future<TimetableGetWeekResponse> run({
|
||||
required TimetableElementType type,
|
||||
required int id,
|
||||
required DateTime from,
|
||||
required DateTime until,
|
||||
}) async {
|
||||
try {
|
||||
final response = await _dio.get<Map<String, dynamic>>(
|
||||
MarianumConnectEndpoint.resolve('timetable/${type.pathSegment}/$id'),
|
||||
queryParameters: {'from': _format(from), 'until': _format(until)},
|
||||
);
|
||||
return TimetableGetWeekResponse.fromJson(response.data!);
|
||||
} on DioException catch (e) {
|
||||
throw mapMarianumConnectError(e);
|
||||
}
|
||||
}
|
||||
|
||||
String _format(DateTime d) =>
|
||||
'${d.year.toString().padLeft(4, '0')}-${d.month.toString().padLeft(2, '0')}-${d.day.toString().padLeft(2, '0')}';
|
||||
}
|
||||
Reference in New Issue
Block a user