Skip to content

Commit

Permalink
Merge pull request #13 from RedCommander735/12-error-in-price-display
Browse files Browse the repository at this point in the history
Fix formatting error in price display
  • Loading branch information
RedCommander735 authored May 18, 2024
2 parents 07f226d + df99d3a commit 6654b5c
Show file tree
Hide file tree
Showing 4 changed files with 160 additions and 9 deletions.
6 changes: 5 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@ name: Build
on:
push:
branches:
- '*'
- 'main'
- 'develop'
tags:
- '*'
pull_request:
branches:
- 'develop'

workflow_dispatch:

Expand Down
14 changes: 8 additions & 6 deletions lib/src/components/sp_price_text.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:spritverbrauch/src/utils/number_formatter.dart';

class SPPriceText extends StatelessWidget {
final double value;
Expand All @@ -15,15 +16,16 @@ class SPPriceText extends StatelessWidget {
Widget build(BuildContext context) {
String locale = Intl.systemLocale;

final formatter =
NumberFormat.decimalPatternDigits(decimalDigits: 2, locale: locale);
final formatter = NumberFormatter(locale: locale);

final String normal = formatter.format(value);
final decimal = value.toString().split('.')[1];
final FormattedDouble formatted = formatter.format(value);

final normal = formatted.toString(roundLastDigit: false, fractionDigits: 2);
final fraction = formatted.fractionalPartAsIntToString(fractionDigits: 3);

var superscript = '';
if (decimal.length > 2) {
superscript = decimal.substring(2, 3);
if (fraction.length > 2) {
superscript = fraction.substring(2, 3);
}

return Text.rich(
Expand Down
2 changes: 0 additions & 2 deletions lib/src/overview.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import 'dart:ffi';

import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
Expand Down
147 changes: 147 additions & 0 deletions lib/src/utils/number_formatter.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
import 'package:intl/intl.dart';

class NumberFormatter {
final String locale;

NumberFormatter({required this.locale});

FormattedDouble format(double value) {
final format = NumberFormat.decimalPattern(locale);
final decimalSeperator = format.symbols.DECIMAL_SEP;

return FormattedDouble(value, decimalSeperator: decimalSeperator);
}
}

class FormattedDouble {
late double _value;
late int _integer;
late double _fractional;
late String _decimalSeperator;

FormattedDouble(this._value, {required String decimalSeperator}) {
_decimalSeperator = decimalSeperator;
_integer = _value.truncate();
_fractional = _value - _integer;
}

set value(double value) {
_value = value;
_integer = _value.truncate();
_fractional = _value - _integer;
}

set decimalSeperator(String decimalSeperator) {
if (decimalSeperator.length > 1) {
throw InvalidDecimalSeperator(
'Decimal seperator \'$decimalSeperator\' is to long. Decimal seperator cannot be longer than one character.');
} else {
_decimalSeperator = decimalSeperator;
}
}

double get value => _value;
int get integerPart => _integer;
double get fractionalPart => _fractional;
String get decimalSeperator => _decimalSeperator;

@override
String toString({bool roundLastDigit = true, int? fractionDigits}) {
return '$_integer$_decimalSeperator${fractionalPartAsInt(roundLastDigit: roundLastDigit, fractionDigits: fractionDigits)}';
}

String integerPartToString() {
return _integer.toString();
}

String fractionalPartToString() {
return '0$decimalSeperator${fractionalPartAsInt()}';
}

String fractionalPartAsIntToString({bool roundLastDigit = true, int? fractionDigits}) {
int? frac = fractionalPartAsInt(roundLastDigit: roundLastDigit, fractionDigits: fractionDigits);
if (frac != null) {
return frac.toString();
}

return '';
}

int? fractionalPartAsInt({bool roundLastDigit = true, int? fractionDigits}) {
late String fractionalString;

if (fractionDigits != null && fractionDigits.isNegative) {
throw const NegativeValue('Fractional digits cannot be negative');
}

if (fractionDigits != null && roundLastDigit) {
fractionalString = _value.toStringAsFixed(fractionDigits).split('.').last.trimCharRight('0');
} else if (fractionDigits != null &&
fractionDigits > 0 &&
!roundLastDigit) {
String fracPart = _value.toString().split('.').last;
fractionalString =
(fracPart.length > fractionDigits) ? fracPart.substring(0, fractionDigits) : fracPart;
} else if (fractionDigits != null &&
fractionDigits == 0 &&
!roundLastDigit) {
return null;
} else {
fractionalString = _value.toString().split('.').last;
}

final int? fractionAsInt = (fractionalString.isNotEmpty) ? int.parse(fractionalString) : null;
return fractionAsInt;
}
}

class InvalidDecimalSeperator implements Exception {
const InvalidDecimalSeperator([this.message]);

final String? message;

@override
String toString() {
String result = 'InvalidDecimalSeperator';
if (message is String) return '$result: $message';
return result;
}
}

class NegativeValue implements Exception {
const NegativeValue([this.message]);

final String? message;

@override
String toString() {
String result = 'NegativeValue';
if (message is String) return '$result: $message';
return result;
}
}


extension StringFuncs on String {
String trimCharLeft(String pattern) {
if (isEmpty || pattern.isEmpty || pattern.length > length) return this;
var tmp = this;
while (tmp.startsWith(pattern)) {
tmp = tmp.substring(pattern.length);
}
return tmp;
}

String trimCharRight(String pattern) {
if (isEmpty || pattern.isEmpty || pattern.length > length) return this;
var tmp = this;
while (tmp.endsWith(pattern)) {
tmp = tmp.substring(0, tmp.length - pattern.length);
}
return tmp;
}

String trimChar(String pattern) {
return trimCharLeft(pattern).trimCharRight(pattern);
}
}

0 comments on commit 6654b5c

Please sign in to comment.