import 'package:decimal/decimal.dart'; /// Weights travel as shares (`"0.60"` = 60 %) and are edited as percents. The conversion is /// exact on both sides: `Decimal`, never `double`, so 33,33 % round-trips unchanged and a /// set that sums to exactly 1 does not fail validation because of binary floating point. final _hundred = Decimal.fromInt(100); /// `"0.605"` → `"60,5"`; empty for anything unparseable. String shareToPercentText(String? share) { final d = share == null ? null : Decimal.tryParse(share); if (d == null) return ''; final p = d * _hundred; final text = p == p.truncate() ? p.truncate().toString() : p.toString(); return text.replaceAll('.', ','); } /// `"60,5"` → `"0.605"`; null when the text is not a number. String? percentTextToShare(String text) { final normalized = text.trim().replaceAll(',', '.').replaceAll(' ', ''); if (normalized.isEmpty) return null; final d = Decimal.tryParse(normalized); if (d == null) return null; return (d / _hundred).toDecimal(scaleOnInfinitePrecision: 10).toString(); } /// `"0.032"` → `"3,20 %"`, signed. Kept local to the rebalance screen because drift is a /// share, not a return, and the portfolio helper would sign it the same way by accident. String formatShareAsPercent(String? share, {bool signed = false, int digits = 2}) { final d = share == null ? null : Decimal.tryParse(share); if (d == null) return '—'; final p = (d * _hundred).toDouble(); final sign = signed && p > 0 ? '+' : ''; return '$sign${p.toStringAsFixed(digits).replaceAll('.', ',')} %'; }