import 'package:flutter/material.dart'; import '../../../../core/theme/app_typography.dart'; import '../../../../core/theme/theme_extensions.dart'; /// Reusable widget rendering a deterministic 1–2 character monogram badge /// derived from a Club's name. Follows automotive cockpit design guidelines. class ClubMonogram extends StatelessWidget { final String name; final double size; final double? fontSize; final Color? backgroundColor; final Color? textColor; const ClubMonogram({ super.key, required this.name, this.size = 44.0, this.fontSize, this.backgroundColor, this.textColor, }); /// Computes a deterministic 1–2 character monogram from a raw club name. /// Unicode-safe using Characters to handle grapheme clusters, emojis, /// leading punctuation, non-Latin scripts, and single characters. static String getMonogram(String rawName) { final trimmed = rawName.trim(); if (trimmed.isEmpty) return 'C'; final words = trimmed .split(RegExp(r'\s+')) .where((w) => w.isNotEmpty) .toList(); if (words.isEmpty) return 'C'; String cleanWord(String word) { final chars = word.characters.toList(); int start = 0; while (start < chars.length) { final ch = chars[start]; if (_isLeadingPunctuation(ch)) { start++; } else { break; } } if (start >= chars.length) { return word; } return chars.sublist(start).join(); } if (words.length == 1) { final cleaned = cleanWord(words.first); final chars = cleaned.characters.take(2).toList(); if (chars.isEmpty) return 'C'; return chars.join().toUpperCase(); } else { final cleanedWords = words.map(cleanWord).toList(); final firstGrapheme = cleanedWords[0].characters.isNotEmpty ? cleanedWords[0].characters.first : ''; final secondGrapheme = cleanedWords[1].characters.isNotEmpty ? cleanedWords[1].characters.first : ''; final combined = '$firstGrapheme$secondGrapheme'.trim(); if (combined.isEmpty) return 'C'; return combined.toUpperCase(); } } static bool _isLeadingPunctuation(String char) { const punct = { '-', '_', '.', ',', '!', '?', '@', '#', r'$', '%', '^', '&', '*', '(', ')', '[', ']', '{', '}', '<', '>', '/', r'\', '|', '~', '`', '+', '=', ':', ';', '"', '\'', '«', '»', '“', '”', '‘', '’', '•', }; return punct.contains(char); } @override Widget build(BuildContext context) { final colors = context.motorColors; final monogram = getMonogram(name); final effectiveFontSize = fontSize ?? (size * 0.40); return Semantics( label: 'Club monogram for $name', child: Container( width: size, height: size, decoration: BoxDecoration( color: backgroundColor ?? colors.surfaceContainerHighest, borderRadius: BorderRadius.circular(size * 0.28), border: Border.all( color: colors.outlineVariant.withValues(alpha: 0.6), width: 1.0, ), ), alignment: Alignment.center, child: Text( monogram, style: TextStyle( fontFamily: AppTypography.fontHeadline, fontSize: effectiveFontSize, fontWeight: FontWeight.w800, letterSpacing: 0.5, color: textColor ?? colors.cyberCyan, ), ), ), ); } }