ProfileStatsCard constructor

ProfileStatsCard({
  1. Key? key,
  2. required String name,
  3. required Widget avatar,
  4. Color? frameColor,
  5. String? title,
  6. ProfileLevel? level,
  7. List<ProfileStat> stats = const <ProfileStat>[],
  8. VoidCallback? onTap,
  9. VoidCallback? onEditAvatar,
  10. String editAvatarLabel = 'Edit avatar',
  11. String? semanticLabel,
})

Implementation

ProfileStatsCard({
  super.key,
  required this.name,
  required this.avatar,
  this.frameColor,
  this.title,
  this.level,
  this.stats = const <ProfileStat>[],
  this.onTap,
  this.onEditAvatar,
  this.editAvatarLabel = 'Edit avatar',
  this.semanticLabel,
}) {
  if (name.trim().isEmpty) {
    throw ArgumentError.value(name, 'name', 'must not be blank');
  }
  if (stats.length > 4) {
    throw ArgumentError.value(
      stats.length,
      'stats',
      'must contain at most 4',
    );
  }
  final ids = stats.map((s) => s.label).toSet();
  if (ids.length != stats.length) {
    throw ArgumentError.value(stats, 'stats', 'labels must be unique');
  }
  if (editAvatarLabel.trim().isEmpty) {
    throw ArgumentError.value(
      editAvatarLabel,
      'editAvatarLabel',
      'must not be blank',
    );
  }
  for (final (field, value) in [
    ('title', title),
    ('semanticLabel', semanticLabel),
  ]) {
    if (value != null && value.trim().isEmpty) {
      throw ArgumentError.value(value, field, 'must not be blank');
    }
  }
  final currentLevel = level;
  if (currentLevel != null) {
    if (currentLevel.level < 1) {
      throw ArgumentError.value(currentLevel, 'level', 'must be >= 1');
    }
    if (currentLevel.currentXp < 0) {
      throw ArgumentError.value(
        currentLevel.currentXp,
        'level.currentXp',
        'must be >= 0',
      );
    }
    final next = currentLevel.xpForNextLevel;
    if (next != null && (next <= 0 || currentLevel.currentXp > next)) {
      throw ArgumentError.value(
        next,
        'level.xpForNextLevel',
        'must be > 0 and >= currentXp',
      );
    }
  }
}