Aging report

This commit is contained in:
Hillel Coren 2020-03-15 21:00:58 +02:00
parent f738814daf
commit 69da36731d
3 changed files with 181 additions and 133 deletions

View File

@ -231,6 +231,20 @@ const String kSettings = 'settings';
const String kDashboard = 'dashboard'; const String kDashboard = 'dashboard';
const String kReports = 'reports'; const String kReports = 'reports';
const String kAgeGroup0 = 'age_group_0';
const String kAgeGroup30 = 'age_group_30';
const String kAgeGroup60 = 'age_group_60';
const String kAgeGroup90 = 'age_group_90';
const String kAgeGroup120 = 'age_group_120';
const kAgeGroups = {
kAgeGroup0: 0,
kAgeGroup30: 30,
kAgeGroup60: 60,
kAgeGroup90: 90,
kAgeGroup120: 120,
};
/* /*
const String kEmailTemplateInvoice = 'invoice_email'; const String kEmailTemplateInvoice = 'invoice_email';
const String kEmailTemplateQuote = 'quote_email'; const String kEmailTemplateQuote = 'quote_email';

View File

@ -783,144 +783,163 @@ class ReportResult {
], ],
)) ))
else else
if (getReportColumnType(column, context) == if (column == 'age')
ReportColumnType.number) DataCell(AppDropdownButton<String>(
DataCell(TextFormField( value: (textEditingControllers[column].text ?? '')
controller: textEditingControllers[column], .isNotEmpty &&
keyboardType: TextInputType.numberWithOptions(decimal: true), textEditingControllers[column].text != 'null'
decoration: InputDecoration( ? localization.lookup(textEditingControllers[column].text)
suffixIcon: textEditingControllers == null : null,
? null onChanged: (dynamic value) {
: (textEditingControllers[column]?.text ?? '').isEmpty print('## onChanged: $value');
? null },
: IconButton( items: kAgeGroups.keys.map((ageGroup) =>
icon: Icon( DropdownMenuItem(
Icons.clear, child: Text(localization.lookup(ageGroup)),
color: Colors.grey, value: ageGroup,
), )).toList(),
onPressed: () {
textEditingControllers[column].text = '';
onFilterChanged(column, '');
},
)),
)) ))
else else
if (getReportColumnType(column, context) == if (getReportColumnType(column, context) ==
ReportColumnType.dateTime || ReportColumnType.number)
getReportColumnType(column, context) == ReportColumnType.date) DataCell(TextFormField(
DataCell(AppDropdownButton<DateRange>( controller: textEditingControllers[column],
labelText: null, keyboardType: TextInputType.numberWithOptions(decimal: true),
showBlank: true, decoration: InputDecoration(
blankValue: null, suffixIcon: textEditingControllers == null
value: (textEditingControllers[column].text ?? '') ? null
.isNotEmpty && : (textEditingControllers[column]?.text ?? '').isEmpty
textEditingControllers[column].text != 'null' ? null
? DateRange.valueOf(textEditingControllers[column].text) : IconButton(
: null, icon: Icon(
onChanged: (dynamic value) { Icons.clear,
if (value == null) { color: Colors.grey,
textEditingControllers[column].text = '';
onFilterChanged(column, '');
} else {
textEditingControllers[column].text = value.toString();
onFilterChanged(column, value.toString());
}
},
items: DateRange.values
.map((dateRange) =>
DropdownMenuItem<DateRange>(
child: Text(localization.lookup(dateRange.toString())),
value: dateRange,
))
.toList(),
))
// TODO remove DEMO_MODE check
else
if (Config.DEMO_MODE)
DataCell(TextFormField(
controller: textEditingControllers != null
? textEditingControllers[column]
: null,
decoration: InputDecoration(
suffixIcon: textEditingControllers == null
? null
: (textEditingControllers[column]?.text ?? '')
.isEmpty
? null
: IconButton(
icon: Icon(
Icons.clear,
color: Colors.grey,
),
onPressed: () {
textEditingControllers[column].text = '';
onFilterChanged(column, '');
},
)),
))
else
DataCell(
TypeAheadFormField(
noItemsFoundBuilder: (context) => SizedBox(),
suggestionsBoxDecoration: SuggestionsBoxDecoration(
constraints: BoxConstraints(
minWidth: 300,
), ),
onPressed: () {
textEditingControllers[column].text = '';
onFilterChanged(column, '');
},
)),
))
else
if (getReportColumnType(column, context) ==
ReportColumnType.dateTime ||
getReportColumnType(column, context) ==
ReportColumnType.date)
DataCell(AppDropdownButton<DateRange>(
labelText: null,
showBlank: true,
blankValue: null,
value: (textEditingControllers[column].text ?? '')
.isNotEmpty &&
textEditingControllers[column].text != 'null'
? DateRange.valueOf(textEditingControllers[column].text)
: null,
onChanged: (dynamic value) {
if (value == null) {
textEditingControllers[column].text = '';
onFilterChanged(column, '');
} else {
textEditingControllers[column].text = value.toString();
onFilterChanged(column, value.toString());
}
},
items: DateRange.values
.map((dateRange) =>
DropdownMenuItem<DateRange>(
child: Text(localization.lookup(dateRange
.toString())),
value: dateRange,
))
.toList(),
))
// TODO remove DEMO_MODE check
else
if (Config.DEMO_MODE)
DataCell(TextFormField(
controller: textEditingControllers != null
? textEditingControllers[column]
: null,
decoration: InputDecoration(
suffixIcon: textEditingControllers == null
? null
: (textEditingControllers[column]?.text ?? '')
.isEmpty
? null
: IconButton(
icon: Icon(
Icons.clear,
color: Colors.grey,
),
onPressed: () {
textEditingControllers[column].text = '';
onFilterChanged(column, '');
},
)),
))
else
DataCell(
TypeAheadFormField(
noItemsFoundBuilder: (context) => SizedBox(),
suggestionsBoxDecoration: SuggestionsBoxDecoration(
constraints: BoxConstraints(
minWidth: 300,
),
),
suggestionsCallback: (filter) {
filter = filter.toLowerCase();
final index = columns.indexOf(column);
return data
.where((row) =>
row[index]
.renderText(context, column)
.toLowerCase()
.contains(filter) &&
row[index]
.renderText(context, column)
.trim()
.isNotEmpty)
.map((row) =>
row[index].renderText(context, column))
.toSet()
.toList();
},
itemBuilder: (context, String entityId) {
return Padding(
padding: const EdgeInsets.all(12),
child: Text('$entityId'),
);
},
onSuggestionSelected: (String value) {
textEditingControllers[column].text = value;
onFilterChanged(column, value);
},
textFieldConfiguration: TextFieldConfiguration<String>(
controller: textEditingControllers != null
? textEditingControllers[column]
: null,
decoration: InputDecoration(
suffixIcon: textEditingControllers == null
? null
: (textEditingControllers[column]?.text ?? '')
.isEmpty
? null
: IconButton(
icon: Icon(
Icons.clear,
color: Colors.grey,
),
onPressed: () {
textEditingControllers[column].text = '';
onFilterChanged(column, '');
},
)),
),
autoFlipDirection: true,
animationStart: 1,
debounceDuration: Duration(seconds: 0),
), ),
suggestionsCallback: (filter) { )
filter = filter.toLowerCase();
final index = columns.indexOf(column);
return data
.where((row) =>
row[index]
.renderText(context, column)
.toLowerCase()
.contains(filter) &&
row[index]
.renderText(context, column)
.trim()
.isNotEmpty)
.map((row) =>
row[index].renderText(context, column))
.toSet()
.toList();
},
itemBuilder: (context, String entityId) {
return Padding(
padding: const EdgeInsets.all(12),
child: Text('$entityId'),
);
},
onSuggestionSelected: (String value) {
textEditingControllers[column].text = value;
onFilterChanged(column, value);
},
textFieldConfiguration: TextFieldConfiguration<String>(
controller: textEditingControllers != null
? textEditingControllers[column]
: null,
decoration: InputDecoration(
suffixIcon: textEditingControllers == null
? null
: (textEditingControllers[column]?.text ?? '')
.isEmpty
? null
: IconButton(
icon: Icon(
Icons.clear,
color: Colors.grey,
),
onPressed: () {
textEditingControllers[column].text = '';
onFilterChanged(column, '');
},
)),
),
autoFlipDirection: true,
animationStart: 1,
debounceDuration: Duration(seconds: 0),
),
)
]); ]);
} }

View File

@ -15,6 +15,11 @@ mixin LocalizationsProvider on LocaleCodeAware {
static final Map<String, Map<String, String>> _localizedValues = { static final Map<String, Map<String, String>> _localizedValues = {
'en': { 'en': {
// STARTER: lang key - do not remove comment // STARTER: lang key - do not remove comment
'age_group_0': '0 - 30 Days',
'age_group_30': '30 - 60 Days',
'age_group_60': '60 - 90 Days',
'age_group_90': '90 - 120 Days',
'age_group_120': '120+ Days',
'refresh': 'Refresh', 'refresh': 'Refresh',
'saved_design': 'Successfully saved design', 'saved_design': 'Successfully saved design',
'client_details': 'Client Details', 'client_details': 'Client Details',
@ -33039,6 +33044,16 @@ mixin LocalizationsProvider on LocaleCodeAware {
String get age => _localizedValues[localeCode]['age']; String get age => _localizedValues[localeCode]['age'];
String get ageGroup0 => _localizedValues[localeCode]['age_group_0'];
String get ageGroup30 => _localizedValues[localeCode]['age_group_30'];
String get ageGroup60 => _localizedValues[localeCode]['age_group_60'];
String get ageGroup90 => _localizedValues[localeCode]['age_group_90'];
String get ageGroup120 => _localizedValues[localeCode]['age_group_120'];
String lookup(String key) { String lookup(String key) {
final lookupKey = toSnakeCase(key); final lookupKey = toSnakeCase(key);
return _localizedValues[localeCode][lookupKey] ?? return _localizedValues[localeCode][lookupKey] ??