getCourse method

Future<Course> getCourse(
  1. String code, {
  2. bool refresh = false,
})

Gets course catalog information by code.

Returns cached data if fresh (within TTL). Set refresh to true to bypass TTL (pull-to-refresh).

Implementation

Future<Course> getCourse(String code, {bool refresh = false}) async {
  const ttl = Duration(days: 3);

  if (!refresh) {
    final cached = await (_database.select(
      _database.courses,
    )..where((c) => c.code.equals(code))).getSingleOrNull();

    if (cached != null) {
      final age = switch (cached.fetchedAt) {
        final t? => DateTime.now().difference(t),
        null => ttl,
      };
      if (age < ttl) return cached;
    }
  }

  final dto = await _authRepository.withAuth(
    () => _courseService.getCourse(code),
    sso: [.courseService],
  );

  if (dto.nameZh == null || dto.credits == null || dto.hours == null) {
    _firebaseService.recordNonFatal(
      'Incomplete course data for $code: '
      'nameZh=${dto.nameZh}, credits=${dto.credits}, hours=${dto.hours}',
    );
  }

  final courseId = await _database.upsertCourse(
    code: code,
    credits: dto.credits ?? 0,
    hours: dto.hours ?? 0,
    nameZh: dto.nameZh ?? code,
    nameEn: dto.nameEn,
  );

  await (_database.update(
    _database.courses,
  )..where((c) => c.id.equals(courseId))).write(
    CoursesCompanion(
      descriptionZh: Value(dto.descriptionZh),
      descriptionEn: Value(dto.descriptionEn),
      fetchedAt: Value(DateTime.now()),
    ),
  );

  return (_database.select(
    _database.courses,
  )..where((c) => c.id.equals(courseId))).getSingle();
}