implemented custom subject colors for the timetable and unified the color palette system

This commit is contained in:
2026-07-12 21:30:08 +02:00
parent a7111844b1
commit fe2b3c43b2
23 changed files with 916 additions and 89 deletions
@@ -0,0 +1,65 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:marianum_mobile/api/marianumconnect/queries/timetable_get_subjects/timetable_get_subjects_response.dart';
import 'package:marianum_mobile/view/pages/timetable/subject_colors/subject_color_filter.dart';
McSubject _sub(String short, String long, {String? color}) =>
McSubject(id: short.hashCode, shortName: short, longName: long, color: color);
void main() {
group('filterAndSortSubjects', () {
test('keeps only subjects in the plan or already coloured', () {
final all = [
_sub('M', 'Mathematik'), // im Plan
_sub('D', 'Deutsch'), // nicht im Plan, keine Farbe -> raus
_sub('SP', 'Sport', color: 'teal'), // nicht im Plan, aber gefärbt
];
final result = filterAndSortSubjects(all, {'M'});
expect(result.map((s) => s.shortName), containsAll(['M', 'SP']));
expect(result.map((s) => s.shortName), isNot(contains('D')));
});
test('sorts coloured subjects first, then alphabetically by label', () {
final all = [
_sub('E', 'Englisch'),
_sub('M', 'Mathematik', color: 'amber'),
_sub('BIO', 'Biologie'),
_sub('D', 'Deutsch', color: 'indigo'),
];
final result = filterAndSortSubjects(all, {'E', 'M', 'BIO', 'D'});
// Gefärbte zuerst (Deutsch, Mathematik alphabetisch), dann der Rest.
expect(
result.map((s) => s.shortName).toList(),
['D', 'M', 'BIO', 'E'],
);
});
test('drops subjects without a short name', () {
final all = [_sub('', 'Leer'), _sub('M', 'Mathematik')];
final result = filterAndSortSubjects(all, {'M', ''});
expect(result.map((s) => s.shortName), ['M']);
});
});
group('searchSubjects', () {
final subjects = [
_sub('M', 'Mathematik'),
_sub('D', 'Deutsch'),
_sub('SP', 'Sport'),
];
test('empty query returns everything unchanged', () {
expect(searchSubjects(subjects, ''), subjects);
expect(searchSubjects(subjects, ' '), subjects);
});
test('matches short name or long name, case-insensitively', () {
expect(searchSubjects(subjects, 'mathe').single.shortName, 'M');
expect(searchSubjects(subjects, 'sp').single.shortName, 'SP');
expect(searchSubjects(subjects, 'DEUTSCH').single.shortName, 'D');
});
test('no match returns empty', () {
expect(searchSubjects(subjects, 'chemie'), isEmpty);
});
});
}
@@ -0,0 +1,38 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:marianum_mobile/view/pages/timetable/data/subject_color_palette.dart';
void main() {
group('SubjectColorPalette.colorFromName', () {
test('resolves every palette name to a concrete colour', () {
for (final option in SubjectColor.values) {
expect(
SubjectColorPalette.colorFromName(option.name),
SubjectColorPalette.displayOf(option).color,
reason: '${option.name} should round-trip to its display colour',
);
}
});
test('returns null for null, empty or unknown names', () {
expect(SubjectColorPalette.colorFromName(null), isNull);
expect(SubjectColorPalette.colorFromName(''), isNull);
expect(SubjectColorPalette.colorFromName('not-a-colour'), isNull);
});
});
group('SubjectColorPalette.fromName legacy aliases', () {
test('maps the old 4-colour custom-event names to palette colours', () {
// Bestehende eigene Termine wurden mit diesen Namen gespeichert und
// dürfen nicht ihre Farbe verlieren.
expect(SubjectColorPalette.fromName('orange'), SubjectColor.amber);
expect(SubjectColorPalette.fromName('red'), SubjectColor.deepOrange);
expect(SubjectColorPalette.fromName('green'), SubjectColor.teal);
expect(SubjectColorPalette.fromName('blue'), SubjectColor.indigo);
});
test('new palette names take precedence and resolve directly', () {
expect(SubjectColorPalette.fromName('teal'), SubjectColor.teal);
expect(SubjectColorPalette.fromName('amber'), SubjectColor.amber);
});
});
}