resolveBookmarkTarget method

Future<({String? domainSlug, String? topicId, String? topicTitle})> resolveBookmarkTarget({
  1. required BookmarkKind kind,
  2. String? topicId,
  3. String? chunkId,
  4. String? sessionId,
})

Resolves a bookmark target to its owning topic (id + title) and that topic's domain slug, so the UI can build a real lesson/tutor route and a readable title. Chunk and session bookmarks resolve their owning topic first. Any field is null when it can't be resolved (e.g. orphaned target).

Implementation

Future<({String? topicId, String? topicTitle, String? domainSlug})>
resolveBookmarkTarget({
  required BookmarkKind kind,
  String? topicId,
  String? chunkId,
  String? sessionId,
}) async {
  var resolvedTopicId = topicId;
  if (kind == BookmarkKind.chunk && chunkId != null) {
    final row = await _client
        .from('content_chunks')
        .select('topic_id')
        .eq('id', chunkId)
        .maybeSingle();
    resolvedTopicId = row?['topic_id'] as String?;
  } else if (kind == BookmarkKind.session && sessionId != null) {
    final row = await _client
        .from('learning_sessions')
        .select('topic_id')
        .eq('id', sessionId)
        .maybeSingle();
    resolvedTopicId = row?['topic_id'] as String?;
  }
  if (resolvedTopicId == null) {
    return (topicId: null, topicTitle: null, domainSlug: null);
  }
  final topic = await _client
      .from('topics')
      .select('title, domain_id')
      .eq('id', resolvedTopicId)
      .maybeSingle();
  final topicTitle = topic?['title'] as String?;
  final domainId = topic?['domain_id'] as String?;
  String? slug;
  if (domainId != null) {
    final domain = await _client
        .from('domains')
        .select('slug')
        .eq('id', domainId)
        .maybeSingle();
    slug = domain?['slug'] as String?;
  }
  return (topicId: resolvedTopicId, topicTitle: topicTitle, domainSlug: slug);
}