Compare commits
No commits in common. "ba78685bfdef811bbd6a7b668c868951efa30443" and "e0fba11f25446bcac85dca6135b2fa14fbff29d5" have entirely different histories.
ba78685bfd
...
e0fba11f25
@ -1,23 +0,0 @@
|
|||||||
import 'package:isar/isar.dart';
|
|
||||||
import 'package:okane/database/collections/account.dart';
|
|
||||||
import 'package:okane/database/collections/beneficiary.dart';
|
|
||||||
|
|
||||||
part 'loan.g.dart';
|
|
||||||
|
|
||||||
@collection
|
|
||||||
class Loan {
|
|
||||||
Id id = Isar.autoIncrement;
|
|
||||||
|
|
||||||
final beneficiary = IsarLink<Beneficiary>();
|
|
||||||
|
|
||||||
final changes = IsarLinks<LoanChange>();
|
|
||||||
}
|
|
||||||
|
|
||||||
@collection
|
|
||||||
class LoanChange {
|
|
||||||
Id id = Isar.autoIncrement;
|
|
||||||
|
|
||||||
late double amount;
|
|
||||||
|
|
||||||
late DateTime date;
|
|
||||||
}
|
|
@ -1,813 +0,0 @@
|
|||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
|
||||||
|
|
||||||
part of 'loan.dart';
|
|
||||||
|
|
||||||
// **************************************************************************
|
|
||||||
// IsarCollectionGenerator
|
|
||||||
// **************************************************************************
|
|
||||||
|
|
||||||
// coverage:ignore-file
|
|
||||||
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
|
|
||||||
|
|
||||||
extension GetLoanCollection on Isar {
|
|
||||||
IsarCollection<Loan> get loans => this.collection();
|
|
||||||
}
|
|
||||||
|
|
||||||
const LoanSchema = CollectionSchema(
|
|
||||||
name: r'Loan',
|
|
||||||
id: 3165146227223573679,
|
|
||||||
properties: {},
|
|
||||||
estimateSize: _loanEstimateSize,
|
|
||||||
serialize: _loanSerialize,
|
|
||||||
deserialize: _loanDeserialize,
|
|
||||||
deserializeProp: _loanDeserializeProp,
|
|
||||||
idName: r'id',
|
|
||||||
indexes: {},
|
|
||||||
links: {
|
|
||||||
r'beneficiary': LinkSchema(
|
|
||||||
id: -4362685136363706814,
|
|
||||||
name: r'beneficiary',
|
|
||||||
target: r'Beneficiary',
|
|
||||||
single: true,
|
|
||||||
),
|
|
||||||
r'changes': LinkSchema(
|
|
||||||
id: -2646664619562347284,
|
|
||||||
name: r'changes',
|
|
||||||
target: r'LoanChange',
|
|
||||||
single: false,
|
|
||||||
),
|
|
||||||
},
|
|
||||||
embeddedSchemas: {},
|
|
||||||
getId: _loanGetId,
|
|
||||||
getLinks: _loanGetLinks,
|
|
||||||
attach: _loanAttach,
|
|
||||||
version: '3.1.0+1',
|
|
||||||
);
|
|
||||||
|
|
||||||
int _loanEstimateSize(
|
|
||||||
Loan object,
|
|
||||||
List<int> offsets,
|
|
||||||
Map<Type, List<int>> allOffsets,
|
|
||||||
) {
|
|
||||||
var bytesCount = offsets.last;
|
|
||||||
return bytesCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _loanSerialize(
|
|
||||||
Loan object,
|
|
||||||
IsarWriter writer,
|
|
||||||
List<int> offsets,
|
|
||||||
Map<Type, List<int>> allOffsets,
|
|
||||||
) {}
|
|
||||||
Loan _loanDeserialize(
|
|
||||||
Id id,
|
|
||||||
IsarReader reader,
|
|
||||||
List<int> offsets,
|
|
||||||
Map<Type, List<int>> allOffsets,
|
|
||||||
) {
|
|
||||||
final object = Loan();
|
|
||||||
object.id = id;
|
|
||||||
return object;
|
|
||||||
}
|
|
||||||
|
|
||||||
P _loanDeserializeProp<P>(
|
|
||||||
IsarReader reader,
|
|
||||||
int propertyId,
|
|
||||||
int offset,
|
|
||||||
Map<Type, List<int>> allOffsets,
|
|
||||||
) {
|
|
||||||
switch (propertyId) {
|
|
||||||
default:
|
|
||||||
throw IsarError('Unknown property with id $propertyId');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Id _loanGetId(Loan object) {
|
|
||||||
return object.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<IsarLinkBase<dynamic>> _loanGetLinks(Loan object) {
|
|
||||||
return [object.beneficiary, object.changes];
|
|
||||||
}
|
|
||||||
|
|
||||||
void _loanAttach(IsarCollection<dynamic> col, Id id, Loan object) {
|
|
||||||
object.id = id;
|
|
||||||
object.beneficiary.attach(
|
|
||||||
col,
|
|
||||||
col.isar.collection<Beneficiary>(),
|
|
||||||
r'beneficiary',
|
|
||||||
id,
|
|
||||||
);
|
|
||||||
object.changes.attach(col, col.isar.collection<LoanChange>(), r'changes', id);
|
|
||||||
}
|
|
||||||
|
|
||||||
extension LoanQueryWhereSort on QueryBuilder<Loan, Loan, QWhere> {
|
|
||||||
QueryBuilder<Loan, Loan, QAfterWhere> anyId() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addWhereClause(const IdWhereClause.any());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension LoanQueryWhere on QueryBuilder<Loan, Loan, QWhereClause> {
|
|
||||||
QueryBuilder<Loan, Loan, QAfterWhereClause> idEqualTo(Id id) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addWhereClause(IdWhereClause.between(lower: id, upper: id));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Loan, Loan, QAfterWhereClause> idNotEqualTo(Id id) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
if (query.whereSort == Sort.asc) {
|
|
||||||
return query
|
|
||||||
.addWhereClause(
|
|
||||||
IdWhereClause.lessThan(upper: id, includeUpper: false),
|
|
||||||
)
|
|
||||||
.addWhereClause(
|
|
||||||
IdWhereClause.greaterThan(lower: id, includeLower: false),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return query
|
|
||||||
.addWhereClause(
|
|
||||||
IdWhereClause.greaterThan(lower: id, includeLower: false),
|
|
||||||
)
|
|
||||||
.addWhereClause(
|
|
||||||
IdWhereClause.lessThan(upper: id, includeUpper: false),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Loan, Loan, QAfterWhereClause> idGreaterThan(
|
|
||||||
Id id, {
|
|
||||||
bool include = false,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addWhereClause(
|
|
||||||
IdWhereClause.greaterThan(lower: id, includeLower: include),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Loan, Loan, QAfterWhereClause> idLessThan(
|
|
||||||
Id id, {
|
|
||||||
bool include = false,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addWhereClause(
|
|
||||||
IdWhereClause.lessThan(upper: id, includeUpper: include),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Loan, Loan, QAfterWhereClause> idBetween(
|
|
||||||
Id lowerId,
|
|
||||||
Id upperId, {
|
|
||||||
bool includeLower = true,
|
|
||||||
bool includeUpper = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addWhereClause(
|
|
||||||
IdWhereClause.between(
|
|
||||||
lower: lowerId,
|
|
||||||
includeLower: includeLower,
|
|
||||||
upper: upperId,
|
|
||||||
includeUpper: includeUpper,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension LoanQueryFilter on QueryBuilder<Loan, Loan, QFilterCondition> {
|
|
||||||
QueryBuilder<Loan, Loan, QAfterFilterCondition> idEqualTo(Id value) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.equalTo(property: r'id', value: value),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Loan, Loan, QAfterFilterCondition> idGreaterThan(
|
|
||||||
Id value, {
|
|
||||||
bool include = false,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.greaterThan(
|
|
||||||
include: include,
|
|
||||||
property: r'id',
|
|
||||||
value: value,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Loan, Loan, QAfterFilterCondition> idLessThan(
|
|
||||||
Id value, {
|
|
||||||
bool include = false,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.lessThan(
|
|
||||||
include: include,
|
|
||||||
property: r'id',
|
|
||||||
value: value,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Loan, Loan, QAfterFilterCondition> idBetween(
|
|
||||||
Id lower,
|
|
||||||
Id upper, {
|
|
||||||
bool includeLower = true,
|
|
||||||
bool includeUpper = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.between(
|
|
||||||
property: r'id',
|
|
||||||
lower: lower,
|
|
||||||
includeLower: includeLower,
|
|
||||||
upper: upper,
|
|
||||||
includeUpper: includeUpper,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension LoanQueryObject on QueryBuilder<Loan, Loan, QFilterCondition> {}
|
|
||||||
|
|
||||||
extension LoanQueryLinks on QueryBuilder<Loan, Loan, QFilterCondition> {
|
|
||||||
QueryBuilder<Loan, Loan, QAfterFilterCondition> beneficiary(
|
|
||||||
FilterQuery<Beneficiary> q,
|
|
||||||
) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.link(q, r'beneficiary');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Loan, Loan, QAfterFilterCondition> beneficiaryIsNull() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.linkLength(r'beneficiary', 0, true, 0, true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Loan, Loan, QAfterFilterCondition> changes(
|
|
||||||
FilterQuery<LoanChange> q,
|
|
||||||
) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.link(q, r'changes');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Loan, Loan, QAfterFilterCondition> changesLengthEqualTo(
|
|
||||||
int length,
|
|
||||||
) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.linkLength(r'changes', length, true, length, true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Loan, Loan, QAfterFilterCondition> changesIsEmpty() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.linkLength(r'changes', 0, true, 0, true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Loan, Loan, QAfterFilterCondition> changesIsNotEmpty() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.linkLength(r'changes', 0, false, 999999, true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Loan, Loan, QAfterFilterCondition> changesLengthLessThan(
|
|
||||||
int length, {
|
|
||||||
bool include = false,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.linkLength(r'changes', 0, true, length, include);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Loan, Loan, QAfterFilterCondition> changesLengthGreaterThan(
|
|
||||||
int length, {
|
|
||||||
bool include = false,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.linkLength(r'changes', length, include, 999999, true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Loan, Loan, QAfterFilterCondition> changesLengthBetween(
|
|
||||||
int lower,
|
|
||||||
int upper, {
|
|
||||||
bool includeLower = true,
|
|
||||||
bool includeUpper = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.linkLength(
|
|
||||||
r'changes',
|
|
||||||
lower,
|
|
||||||
includeLower,
|
|
||||||
upper,
|
|
||||||
includeUpper,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension LoanQuerySortBy on QueryBuilder<Loan, Loan, QSortBy> {}
|
|
||||||
|
|
||||||
extension LoanQuerySortThenBy on QueryBuilder<Loan, Loan, QSortThenBy> {
|
|
||||||
QueryBuilder<Loan, Loan, QAfterSortBy> thenById() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'id', Sort.asc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Loan, Loan, QAfterSortBy> thenByIdDesc() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'id', Sort.desc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension LoanQueryWhereDistinct on QueryBuilder<Loan, Loan, QDistinct> {}
|
|
||||||
|
|
||||||
extension LoanQueryProperty on QueryBuilder<Loan, Loan, QQueryProperty> {
|
|
||||||
QueryBuilder<Loan, int, QQueryOperations> idProperty() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addPropertyName(r'id');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// coverage:ignore-file
|
|
||||||
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
|
|
||||||
|
|
||||||
extension GetLoanChangeCollection on Isar {
|
|
||||||
IsarCollection<LoanChange> get loanChanges => this.collection();
|
|
||||||
}
|
|
||||||
|
|
||||||
const LoanChangeSchema = CollectionSchema(
|
|
||||||
name: r'LoanChange',
|
|
||||||
id: 998721626271124002,
|
|
||||||
properties: {
|
|
||||||
r'amount': PropertySchema(id: 0, name: r'amount', type: IsarType.double),
|
|
||||||
r'date': PropertySchema(id: 1, name: r'date', type: IsarType.dateTime),
|
|
||||||
},
|
|
||||||
estimateSize: _loanChangeEstimateSize,
|
|
||||||
serialize: _loanChangeSerialize,
|
|
||||||
deserialize: _loanChangeDeserialize,
|
|
||||||
deserializeProp: _loanChangeDeserializeProp,
|
|
||||||
idName: r'id',
|
|
||||||
indexes: {},
|
|
||||||
links: {},
|
|
||||||
embeddedSchemas: {},
|
|
||||||
getId: _loanChangeGetId,
|
|
||||||
getLinks: _loanChangeGetLinks,
|
|
||||||
attach: _loanChangeAttach,
|
|
||||||
version: '3.1.0+1',
|
|
||||||
);
|
|
||||||
|
|
||||||
int _loanChangeEstimateSize(
|
|
||||||
LoanChange object,
|
|
||||||
List<int> offsets,
|
|
||||||
Map<Type, List<int>> allOffsets,
|
|
||||||
) {
|
|
||||||
var bytesCount = offsets.last;
|
|
||||||
return bytesCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _loanChangeSerialize(
|
|
||||||
LoanChange object,
|
|
||||||
IsarWriter writer,
|
|
||||||
List<int> offsets,
|
|
||||||
Map<Type, List<int>> allOffsets,
|
|
||||||
) {
|
|
||||||
writer.writeDouble(offsets[0], object.amount);
|
|
||||||
writer.writeDateTime(offsets[1], object.date);
|
|
||||||
}
|
|
||||||
|
|
||||||
LoanChange _loanChangeDeserialize(
|
|
||||||
Id id,
|
|
||||||
IsarReader reader,
|
|
||||||
List<int> offsets,
|
|
||||||
Map<Type, List<int>> allOffsets,
|
|
||||||
) {
|
|
||||||
final object = LoanChange();
|
|
||||||
object.amount = reader.readDouble(offsets[0]);
|
|
||||||
object.date = reader.readDateTime(offsets[1]);
|
|
||||||
object.id = id;
|
|
||||||
return object;
|
|
||||||
}
|
|
||||||
|
|
||||||
P _loanChangeDeserializeProp<P>(
|
|
||||||
IsarReader reader,
|
|
||||||
int propertyId,
|
|
||||||
int offset,
|
|
||||||
Map<Type, List<int>> allOffsets,
|
|
||||||
) {
|
|
||||||
switch (propertyId) {
|
|
||||||
case 0:
|
|
||||||
return (reader.readDouble(offset)) as P;
|
|
||||||
case 1:
|
|
||||||
return (reader.readDateTime(offset)) as P;
|
|
||||||
default:
|
|
||||||
throw IsarError('Unknown property with id $propertyId');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Id _loanChangeGetId(LoanChange object) {
|
|
||||||
return object.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<IsarLinkBase<dynamic>> _loanChangeGetLinks(LoanChange object) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
void _loanChangeAttach(IsarCollection<dynamic> col, Id id, LoanChange object) {
|
|
||||||
object.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
extension LoanChangeQueryWhereSort
|
|
||||||
on QueryBuilder<LoanChange, LoanChange, QWhere> {
|
|
||||||
QueryBuilder<LoanChange, LoanChange, QAfterWhere> anyId() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addWhereClause(const IdWhereClause.any());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension LoanChangeQueryWhere
|
|
||||||
on QueryBuilder<LoanChange, LoanChange, QWhereClause> {
|
|
||||||
QueryBuilder<LoanChange, LoanChange, QAfterWhereClause> idEqualTo(Id id) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addWhereClause(IdWhereClause.between(lower: id, upper: id));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<LoanChange, LoanChange, QAfterWhereClause> idNotEqualTo(Id id) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
if (query.whereSort == Sort.asc) {
|
|
||||||
return query
|
|
||||||
.addWhereClause(
|
|
||||||
IdWhereClause.lessThan(upper: id, includeUpper: false),
|
|
||||||
)
|
|
||||||
.addWhereClause(
|
|
||||||
IdWhereClause.greaterThan(lower: id, includeLower: false),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return query
|
|
||||||
.addWhereClause(
|
|
||||||
IdWhereClause.greaterThan(lower: id, includeLower: false),
|
|
||||||
)
|
|
||||||
.addWhereClause(
|
|
||||||
IdWhereClause.lessThan(upper: id, includeUpper: false),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<LoanChange, LoanChange, QAfterWhereClause> idGreaterThan(
|
|
||||||
Id id, {
|
|
||||||
bool include = false,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addWhereClause(
|
|
||||||
IdWhereClause.greaterThan(lower: id, includeLower: include),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<LoanChange, LoanChange, QAfterWhereClause> idLessThan(
|
|
||||||
Id id, {
|
|
||||||
bool include = false,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addWhereClause(
|
|
||||||
IdWhereClause.lessThan(upper: id, includeUpper: include),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<LoanChange, LoanChange, QAfterWhereClause> idBetween(
|
|
||||||
Id lowerId,
|
|
||||||
Id upperId, {
|
|
||||||
bool includeLower = true,
|
|
||||||
bool includeUpper = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addWhereClause(
|
|
||||||
IdWhereClause.between(
|
|
||||||
lower: lowerId,
|
|
||||||
includeLower: includeLower,
|
|
||||||
upper: upperId,
|
|
||||||
includeUpper: includeUpper,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension LoanChangeQueryFilter
|
|
||||||
on QueryBuilder<LoanChange, LoanChange, QFilterCondition> {
|
|
||||||
QueryBuilder<LoanChange, LoanChange, QAfterFilterCondition> amountEqualTo(
|
|
||||||
double value, {
|
|
||||||
double epsilon = Query.epsilon,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.equalTo(
|
|
||||||
property: r'amount',
|
|
||||||
value: value,
|
|
||||||
epsilon: epsilon,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<LoanChange, LoanChange, QAfterFilterCondition> amountGreaterThan(
|
|
||||||
double value, {
|
|
||||||
bool include = false,
|
|
||||||
double epsilon = Query.epsilon,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.greaterThan(
|
|
||||||
include: include,
|
|
||||||
property: r'amount',
|
|
||||||
value: value,
|
|
||||||
epsilon: epsilon,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<LoanChange, LoanChange, QAfterFilterCondition> amountLessThan(
|
|
||||||
double value, {
|
|
||||||
bool include = false,
|
|
||||||
double epsilon = Query.epsilon,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.lessThan(
|
|
||||||
include: include,
|
|
||||||
property: r'amount',
|
|
||||||
value: value,
|
|
||||||
epsilon: epsilon,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<LoanChange, LoanChange, QAfterFilterCondition> amountBetween(
|
|
||||||
double lower,
|
|
||||||
double upper, {
|
|
||||||
bool includeLower = true,
|
|
||||||
bool includeUpper = true,
|
|
||||||
double epsilon = Query.epsilon,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.between(
|
|
||||||
property: r'amount',
|
|
||||||
lower: lower,
|
|
||||||
includeLower: includeLower,
|
|
||||||
upper: upper,
|
|
||||||
includeUpper: includeUpper,
|
|
||||||
epsilon: epsilon,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<LoanChange, LoanChange, QAfterFilterCondition> dateEqualTo(
|
|
||||||
DateTime value,
|
|
||||||
) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.equalTo(property: r'date', value: value),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<LoanChange, LoanChange, QAfterFilterCondition> dateGreaterThan(
|
|
||||||
DateTime value, {
|
|
||||||
bool include = false,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.greaterThan(
|
|
||||||
include: include,
|
|
||||||
property: r'date',
|
|
||||||
value: value,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<LoanChange, LoanChange, QAfterFilterCondition> dateLessThan(
|
|
||||||
DateTime value, {
|
|
||||||
bool include = false,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.lessThan(
|
|
||||||
include: include,
|
|
||||||
property: r'date',
|
|
||||||
value: value,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<LoanChange, LoanChange, QAfterFilterCondition> dateBetween(
|
|
||||||
DateTime lower,
|
|
||||||
DateTime upper, {
|
|
||||||
bool includeLower = true,
|
|
||||||
bool includeUpper = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.between(
|
|
||||||
property: r'date',
|
|
||||||
lower: lower,
|
|
||||||
includeLower: includeLower,
|
|
||||||
upper: upper,
|
|
||||||
includeUpper: includeUpper,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<LoanChange, LoanChange, QAfterFilterCondition> idEqualTo(
|
|
||||||
Id value,
|
|
||||||
) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.equalTo(property: r'id', value: value),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<LoanChange, LoanChange, QAfterFilterCondition> idGreaterThan(
|
|
||||||
Id value, {
|
|
||||||
bool include = false,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.greaterThan(
|
|
||||||
include: include,
|
|
||||||
property: r'id',
|
|
||||||
value: value,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<LoanChange, LoanChange, QAfterFilterCondition> idLessThan(
|
|
||||||
Id value, {
|
|
||||||
bool include = false,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.lessThan(
|
|
||||||
include: include,
|
|
||||||
property: r'id',
|
|
||||||
value: value,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<LoanChange, LoanChange, QAfterFilterCondition> idBetween(
|
|
||||||
Id lower,
|
|
||||||
Id upper, {
|
|
||||||
bool includeLower = true,
|
|
||||||
bool includeUpper = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.between(
|
|
||||||
property: r'id',
|
|
||||||
lower: lower,
|
|
||||||
includeLower: includeLower,
|
|
||||||
upper: upper,
|
|
||||||
includeUpper: includeUpper,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension LoanChangeQueryObject
|
|
||||||
on QueryBuilder<LoanChange, LoanChange, QFilterCondition> {}
|
|
||||||
|
|
||||||
extension LoanChangeQueryLinks
|
|
||||||
on QueryBuilder<LoanChange, LoanChange, QFilterCondition> {}
|
|
||||||
|
|
||||||
extension LoanChangeQuerySortBy
|
|
||||||
on QueryBuilder<LoanChange, LoanChange, QSortBy> {
|
|
||||||
QueryBuilder<LoanChange, LoanChange, QAfterSortBy> sortByAmount() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'amount', Sort.asc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<LoanChange, LoanChange, QAfterSortBy> sortByAmountDesc() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'amount', Sort.desc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<LoanChange, LoanChange, QAfterSortBy> sortByDate() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'date', Sort.asc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<LoanChange, LoanChange, QAfterSortBy> sortByDateDesc() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'date', Sort.desc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension LoanChangeQuerySortThenBy
|
|
||||||
on QueryBuilder<LoanChange, LoanChange, QSortThenBy> {
|
|
||||||
QueryBuilder<LoanChange, LoanChange, QAfterSortBy> thenByAmount() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'amount', Sort.asc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<LoanChange, LoanChange, QAfterSortBy> thenByAmountDesc() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'amount', Sort.desc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<LoanChange, LoanChange, QAfterSortBy> thenByDate() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'date', Sort.asc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<LoanChange, LoanChange, QAfterSortBy> thenByDateDesc() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'date', Sort.desc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<LoanChange, LoanChange, QAfterSortBy> thenById() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'id', Sort.asc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<LoanChange, LoanChange, QAfterSortBy> thenByIdDesc() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'id', Sort.desc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension LoanChangeQueryWhereDistinct
|
|
||||||
on QueryBuilder<LoanChange, LoanChange, QDistinct> {
|
|
||||||
QueryBuilder<LoanChange, LoanChange, QDistinct> distinctByAmount() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addDistinctBy(r'amount');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<LoanChange, LoanChange, QDistinct> distinctByDate() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addDistinctBy(r'date');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension LoanChangeQueryProperty
|
|
||||||
on QueryBuilder<LoanChange, LoanChange, QQueryProperty> {
|
|
||||||
QueryBuilder<LoanChange, int, QQueryOperations> idProperty() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addPropertyName(r'id');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<LoanChange, double, QQueryOperations> amountProperty() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addPropertyName(r'amount');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<LoanChange, DateTime, QQueryOperations> dateProperty() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addPropertyName(r'date');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
@ -6,7 +6,6 @@ import 'package:more/collection.dart';
|
|||||||
import 'package:okane/database/collections/account.dart';
|
import 'package:okane/database/collections/account.dart';
|
||||||
import 'package:okane/database/collections/beneficiary.dart';
|
import 'package:okane/database/collections/beneficiary.dart';
|
||||||
import 'package:okane/database/collections/expense_category.dart';
|
import 'package:okane/database/collections/expense_category.dart';
|
||||||
import 'package:okane/database/collections/loan.dart';
|
|
||||||
import 'package:okane/database/collections/recurrent.dart';
|
import 'package:okane/database/collections/recurrent.dart';
|
||||||
import 'package:okane/database/collections/template.dart';
|
import 'package:okane/database/collections/template.dart';
|
||||||
import 'package:okane/database/collections/transaction.dart';
|
import 'package:okane/database/collections/transaction.dart';
|
||||||
@ -27,8 +26,6 @@ Future<Isar> openDatabase() async {
|
|||||||
ExpenseCategorySchema,
|
ExpenseCategorySchema,
|
||||||
BudgetSchema,
|
BudgetSchema,
|
||||||
BudgetItemSchema,
|
BudgetItemSchema,
|
||||||
LoanSchema,
|
|
||||||
LoanChangeSchema,
|
|
||||||
], directory: dir.path);
|
], directory: dir.path);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -291,56 +288,6 @@ Future<List<Transaction>> getTransactionsInTimeframe(
|
|||||||
.findAll();
|
.findAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> upsertLoan(Loan loan) {
|
|
||||||
final db = GetIt.I.get<Isar>();
|
|
||||||
return db.writeTxn(() async {
|
|
||||||
await db.loans.put(loan);
|
|
||||||
await loan.beneficiary.save();
|
|
||||||
await loan.changes.save();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<List<Loan>> getLoans() {
|
|
||||||
return GetIt.I.get<Isar>().loans.where().findAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
Stream<void> watchLoans() {
|
|
||||||
return GetIt.I.get<Isar>().loans.where().watchLazy(fireImmediately: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> deleteLoan(Loan loan) async {
|
|
||||||
final db = GetIt.I.get<Isar>();
|
|
||||||
final loanChangeIds = loan.changes.map((c) => c.id).toList();
|
|
||||||
return db.writeTxn(() async {
|
|
||||||
await db.loans.delete(loan.id);
|
|
||||||
await db.loanChanges.deleteAll(loanChangeIds);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> upsertLoanChange(LoanChange loanChange) {
|
|
||||||
final db = GetIt.I.get<Isar>();
|
|
||||||
return db.writeTxn(() async {
|
|
||||||
await db.loanChanges.put(loanChange);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> deleteLoanChange(LoanChange loanChange) {
|
|
||||||
final db = GetIt.I.get<Isar>();
|
|
||||||
return db.writeTxn(() async {
|
|
||||||
await db.loanChanges.delete(loanChange.id);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<double> getTotalLoanSum() async {
|
|
||||||
final loans = await getLoans();
|
|
||||||
return loans
|
|
||||||
.map(
|
|
||||||
(loan) =>
|
|
||||||
loan.changes.map((l) => l.amount).reduce((acc, val) => acc + val),
|
|
||||||
)
|
|
||||||
.reduce((acc, val) => acc + val);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> deleteAccount(Account account) async {
|
Future<void> deleteAccount(Account account) async {
|
||||||
final db = GetIt.I.get<Isar>();
|
final db = GetIt.I.get<Isar>();
|
||||||
final affectedBudgets =
|
final affectedBudgets =
|
||||||
|
@ -14,8 +14,6 @@ import 'package:okane/ui/pages/transaction_details.dart';
|
|||||||
import 'package:okane/ui/state/core.dart';
|
import 'package:okane/ui/state/core.dart';
|
||||||
import 'package:okane/ui/state/settings.dart';
|
import 'package:okane/ui/state/settings.dart';
|
||||||
|
|
||||||
import 'ui/pages/loans/loan_details.dart';
|
|
||||||
|
|
||||||
Future<void> main() async {
|
Future<void> main() async {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
LocaleSettings.useDeviceLocale();
|
LocaleSettings.useDeviceLocale();
|
||||||
@ -68,7 +66,6 @@ class MyApp extends StatelessWidget {
|
|||||||
"/transactions/details" =>
|
"/transactions/details" =>
|
||||||
TransactionDetailsPage.mobileRoute,
|
TransactionDetailsPage.mobileRoute,
|
||||||
"/budgets/details" => BudgetDetailsPage.mobileRoute,
|
"/budgets/details" => BudgetDetailsPage.mobileRoute,
|
||||||
"/loans/details" => LoanDetailsPage.mobileRoute,
|
|
||||||
_ => MaterialPageRoute<void>(
|
_ => MaterialPageRoute<void>(
|
||||||
builder: (_) => Text("Unknown!!"),
|
builder: (_) => Text("Unknown!!"),
|
||||||
),
|
),
|
||||||
|
@ -5,8 +5,6 @@ import 'package:okane/ui/pages/account/account.dart';
|
|||||||
import 'package:okane/ui/pages/beneficiary_list.dart';
|
import 'package:okane/ui/pages/beneficiary_list.dart';
|
||||||
import 'package:okane/ui/pages/budgets/budget_details.dart';
|
import 'package:okane/ui/pages/budgets/budget_details.dart';
|
||||||
import 'package:okane/ui/pages/budgets/budgets.dart';
|
import 'package:okane/ui/pages/budgets/budgets.dart';
|
||||||
import 'package:okane/ui/pages/loans/loan_details.dart';
|
|
||||||
import 'package:okane/ui/pages/loans/loan_list.dart';
|
|
||||||
import 'package:okane/ui/pages/settings.dart';
|
import 'package:okane/ui/pages/settings.dart';
|
||||||
import 'package:okane/ui/pages/template_list.dart';
|
import 'package:okane/ui/pages/template_list.dart';
|
||||||
import 'package:okane/ui/pages/transaction_details.dart';
|
import 'package:okane/ui/pages/transaction_details.dart';
|
||||||
@ -20,7 +18,6 @@ enum OkanePage {
|
|||||||
beneficiaries,
|
beneficiaries,
|
||||||
templates,
|
templates,
|
||||||
budgets,
|
budgets,
|
||||||
loans,
|
|
||||||
settings,
|
settings,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,7 +70,7 @@ final _pages = <OkanePageItem>[
|
|||||||
"Accounts",
|
"Accounts",
|
||||||
AccountListPage(isPage: false),
|
AccountListPage(isPage: false),
|
||||||
null,
|
null,
|
||||||
true,
|
false,
|
||||||
),
|
),
|
||||||
OkanePageItem(
|
OkanePageItem(
|
||||||
OkanePage.transactions,
|
OkanePage.transactions,
|
||||||
@ -107,14 +104,6 @@ final _pages = <OkanePageItem>[
|
|||||||
(_) => BudgetDetailsPage(),
|
(_) => BudgetDetailsPage(),
|
||||||
true,
|
true,
|
||||||
),
|
),
|
||||||
OkanePageItem(
|
|
||||||
OkanePage.loans,
|
|
||||||
Icons.money_outlined,
|
|
||||||
"Loans",
|
|
||||||
LoanListPage(),
|
|
||||||
(_) => LoanDetailsPage(isPage: false),
|
|
||||||
false,
|
|
||||||
),
|
|
||||||
OkanePageItem(
|
OkanePageItem(
|
||||||
OkanePage.settings,
|
OkanePage.settings,
|
||||||
Icons.settings,
|
Icons.settings,
|
||||||
@ -226,10 +215,17 @@ class OkaneNavigationLayout extends StatelessWidget {
|
|||||||
if (p.showAccountName &&
|
if (p.showAccountName &&
|
||||||
state.activeAccountIndex != null)
|
state.activeAccountIndex != null)
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.symmetric(
|
padding: EdgeInsets.only(left: 8),
|
||||||
horizontal: 8,
|
child: Text(
|
||||||
|
state
|
||||||
|
.accounts[state
|
||||||
|
.activeAccountIndex!]
|
||||||
|
.name!,
|
||||||
|
style:
|
||||||
|
Theme.of(
|
||||||
|
context,
|
||||||
|
).textTheme.titleLarge,
|
||||||
),
|
),
|
||||||
child: AccountSwitcher(),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -242,7 +238,12 @@ class OkaneNavigationLayout extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
if (p.showAccountName &&
|
if (p.showAccountName &&
|
||||||
state.activeAccountIndex != null)
|
state.activeAccountIndex != null)
|
||||||
AccountIndicator(),
|
AccountIndicator(
|
||||||
|
accountName:
|
||||||
|
state
|
||||||
|
.accounts[state.activeAccountIndex!]
|
||||||
|
.name!,
|
||||||
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child:
|
child:
|
||||||
p.details != null
|
p.details != null
|
||||||
|
@ -6,7 +6,6 @@ import 'package:okane/database/collections/beneficiary.dart';
|
|||||||
import 'package:okane/database/database.dart';
|
import 'package:okane/database/database.dart';
|
||||||
import 'package:okane/ui/pages/account/breakdown_card.dart';
|
import 'package:okane/ui/pages/account/breakdown_card.dart';
|
||||||
import 'package:okane/ui/pages/account/delete_account.dart';
|
import 'package:okane/ui/pages/account/delete_account.dart';
|
||||||
import 'package:okane/ui/pages/account/loan_card.dart';
|
|
||||||
import 'package:okane/ui/pages/account/total_balance_card.dart';
|
import 'package:okane/ui/pages/account/total_balance_card.dart';
|
||||||
import 'package:okane/ui/pages/account/upcoming_transactions_card.dart';
|
import 'package:okane/ui/pages/account/upcoming_transactions_card.dart';
|
||||||
import 'package:okane/ui/state/core.dart';
|
import 'package:okane/ui/state/core.dart';
|
||||||
@ -32,6 +31,90 @@ class AccountListPageState extends State<AccountListPage> {
|
|||||||
children: [
|
children: [
|
||||||
ListView(
|
ListView(
|
||||||
children: [
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||||
|
child: Text(
|
||||||
|
t.pages.accounts.title,
|
||||||
|
style: Theme.of(context).textTheme.titleLarge,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||||
|
child: BlocBuilder<CoreCubit, CoreState>(
|
||||||
|
builder:
|
||||||
|
(context, state) => Row(
|
||||||
|
children: [
|
||||||
|
OutlinedButton(
|
||||||
|
onPressed:
|
||||||
|
state.accounts.isEmpty
|
||||||
|
? null
|
||||||
|
: () {
|
||||||
|
showDialogOrModal(
|
||||||
|
context: context,
|
||||||
|
builder:
|
||||||
|
(context) => ListView.builder(
|
||||||
|
shrinkWrap: true,
|
||||||
|
itemCount: state.accounts.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final item =
|
||||||
|
state.accounts[index];
|
||||||
|
return ListTile(
|
||||||
|
title: Text(item.name!),
|
||||||
|
trailing: IconButton(
|
||||||
|
icon: Icon(Icons.delete),
|
||||||
|
color: Colors.red,
|
||||||
|
onPressed: () async {
|
||||||
|
await showDialog(
|
||||||
|
context: context,
|
||||||
|
barrierDismissible: false,
|
||||||
|
builder:
|
||||||
|
(context) =>
|
||||||
|
DeleteAccountPopup(
|
||||||
|
account: item,
|
||||||
|
onCancel: () {
|
||||||
|
Navigator.of(
|
||||||
|
context,
|
||||||
|
).pop();
|
||||||
|
Navigator.of(
|
||||||
|
context,
|
||||||
|
).pop();
|
||||||
|
},
|
||||||
|
afterDelete: () {
|
||||||
|
Navigator.of(
|
||||||
|
context,
|
||||||
|
).pop();
|
||||||
|
Navigator.of(
|
||||||
|
context,
|
||||||
|
).pop();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
GetIt.I
|
||||||
|
.get<CoreCubit>()
|
||||||
|
.setActiveAccountIndex(
|
||||||
|
index,
|
||||||
|
);
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
bloc.activeAccount?.name ??
|
||||||
|
t.pages.accounts.accountSelector.none,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||||
child: BlocBuilder<CoreCubit, CoreState>(
|
child: BlocBuilder<CoreCubit, CoreState>(
|
||||||
@ -101,10 +184,7 @@ class AccountListPageState extends State<AccountListPage> {
|
|||||||
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 8),
|
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 8),
|
||||||
child: UpcomingTransactionsCard(),
|
child: UpcomingTransactionsCard(),
|
||||||
),
|
),
|
||||||
|
|
||||||
Padding(padding: EdgeInsets.all(8), child: BreakdownCard()),
|
Padding(padding: EdgeInsets.all(8), child: BreakdownCard()),
|
||||||
|
|
||||||
Padding(padding: EdgeInsets.all(8), child: TotalLoanCard()),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -1,36 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
||||||
import 'package:okane/database/database.dart';
|
|
||||||
import 'package:okane/i18n/strings.g.dart';
|
|
||||||
import 'package:okane/ui/state/core.dart';
|
|
||||||
import 'package:okane/ui/utils.dart';
|
|
||||||
import 'package:okane/ui/widgets/piechart_card.dart';
|
|
||||||
|
|
||||||
class TotalLoanCard extends StatelessWidget {
|
|
||||||
const TotalLoanCard({super.key});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return BlocBuilder<CoreCubit, CoreState>(
|
|
||||||
builder: (context, state) {
|
|
||||||
return ResponsiveCard(
|
|
||||||
titleText: "Loan Sum",
|
|
||||||
child: Padding(
|
|
||||||
padding: EdgeInsets.all(16),
|
|
||||||
child: FutureBuilder(
|
|
||||||
future: getTotalLoanSum(),
|
|
||||||
builder: (context, snapshot) {
|
|
||||||
return Text(
|
|
||||||
snapshot.hasData
|
|
||||||
? formatCurrency(snapshot.data!)
|
|
||||||
: t.pages.accounts.totalBalance.loading,
|
|
||||||
style: Theme.of(context).textTheme.bodyLarge,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -16,9 +16,8 @@ class TotalBalanceCard extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final results = await Future.wait(accounts.map(getTotalBalance).toList());
|
final results = await Future.wait(accounts.map(getTotalBalance).toList());
|
||||||
final loanSum = await getTotalLoanSum();
|
|
||||||
|
|
||||||
return results.reduce((acc, val) => acc + val) + loanSum;
|
return results.reduce((acc, val) => acc + val);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -68,6 +68,7 @@ class BudgetListPage extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
||||||
Positioned(
|
Positioned(
|
||||||
right: 16,
|
right: 16,
|
||||||
bottom: 16,
|
bottom: 16,
|
||||||
|
@ -1,135 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
||||||
import 'package:get_it/get_it.dart';
|
|
||||||
import 'package:okane/database/collections/beneficiary.dart';
|
|
||||||
import 'package:okane/database/collections/budget.dart';
|
|
||||||
import 'package:okane/database/collections/loan.dart';
|
|
||||||
import 'package:okane/database/database.dart';
|
|
||||||
import 'package:okane/i18n/strings.g.dart';
|
|
||||||
import 'package:okane/ui/state/core.dart';
|
|
||||||
import 'package:searchfield/searchfield.dart';
|
|
||||||
|
|
||||||
class AddLoanPopup extends StatefulWidget {
|
|
||||||
final VoidCallback onDone;
|
|
||||||
|
|
||||||
const AddLoanPopup({super.key, required this.onDone});
|
|
||||||
|
|
||||||
@override
|
|
||||||
AddBudgetState createState() => AddBudgetState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class AddBudgetState extends State<AddLoanPopup> {
|
|
||||||
final TextEditingController _beneficiaryTextController =
|
|
||||||
TextEditingController();
|
|
||||||
SearchFieldListItem<Beneficiary>? _selectedBeneficiary;
|
|
||||||
|
|
||||||
String getBeneficiaryName(Beneficiary item) {
|
|
||||||
return switch (item.type) {
|
|
||||||
BeneficiaryType.account => t.common.beneficiary.nameWithAccount(
|
|
||||||
name: item.name,
|
|
||||||
),
|
|
||||||
BeneficiaryType.other => item.name,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
|
||||||
child: BlocBuilder<CoreCubit, CoreState>(
|
|
||||||
builder:
|
|
||||||
(context, state) => SearchField<Beneficiary>(
|
|
||||||
suggestions:
|
|
||||||
state.beneficiaries
|
|
||||||
.where((el) {
|
|
||||||
final bloc = GetIt.I.get<CoreCubit>();
|
|
||||||
if (el.type == BeneficiaryType.account) {
|
|
||||||
return el.account.value?.id.toInt() ==
|
|
||||||
bloc.activeAccount?.id.toInt();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
})
|
|
||||||
.map((el) {
|
|
||||||
return SearchFieldListItem(
|
|
||||||
getBeneficiaryName(el),
|
|
||||||
item: el,
|
|
||||||
);
|
|
||||||
})
|
|
||||||
.toList(),
|
|
||||||
hint: "Beneficiary",
|
|
||||||
controller: _beneficiaryTextController,
|
|
||||||
selectedValue: _selectedBeneficiary,
|
|
||||||
onSuggestionTap: (beneficiary) {
|
|
||||||
setState(() => _selectedBeneficiary = beneficiary);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
|
||||||
children: [
|
|
||||||
OutlinedButton(
|
|
||||||
onPressed: () async {
|
|
||||||
final beneficiaryName = _beneficiaryTextController.text;
|
|
||||||
if (_selectedBeneficiary == null && beneficiaryName.isEmpty) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Beneficiary? beneficiary = _selectedBeneficiary?.item;
|
|
||||||
if (beneficiary == null ||
|
|
||||||
getBeneficiaryName(beneficiary) != beneficiaryName) {
|
|
||||||
// Add a new beneficiary, if none was selected
|
|
||||||
final result = await showDialog<bool>(
|
|
||||||
context: context,
|
|
||||||
builder:
|
|
||||||
(context) => AlertDialog(
|
|
||||||
title: Text(t.common.beneficiary.addBeneficiary.title),
|
|
||||||
content: Text(
|
|
||||||
t.common.beneficiary.addBeneficiary.body(name: beneficiaryName),
|
|
||||||
),
|
|
||||||
actions: [
|
|
||||||
TextButton(
|
|
||||||
style: TextButton.styleFrom(
|
|
||||||
textStyle: Theme.of(context).textTheme.labelLarge,
|
|
||||||
),
|
|
||||||
child: Text(t.modals.add),
|
|
||||||
onPressed: () => Navigator.of(context).pop(true),
|
|
||||||
),
|
|
||||||
TextButton(
|
|
||||||
style: TextButton.styleFrom(
|
|
||||||
textStyle: Theme.of(context).textTheme.labelLarge,
|
|
||||||
),
|
|
||||||
child: Text(t.modals.cancel),
|
|
||||||
onPressed: () => Navigator.of(context).pop(false),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
if (result == null || !result) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
beneficiary =
|
|
||||||
Beneficiary()
|
|
||||||
..name = beneficiaryName
|
|
||||||
..type = BeneficiaryType.other;
|
|
||||||
await upsertBeneficiary(beneficiary);
|
|
||||||
}
|
|
||||||
|
|
||||||
final loan =
|
|
||||||
Loan()..beneficiary.value = beneficiary;
|
|
||||||
await upsertLoan(loan);
|
|
||||||
widget.onDone();
|
|
||||||
},
|
|
||||||
child: Text(t.modals.add),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,102 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:okane/database/collections/loan.dart';
|
|
||||||
import 'package:okane/database/database.dart';
|
|
||||||
import 'package:okane/i18n/strings.g.dart';
|
|
||||||
import 'package:okane/ui/utils.dart';
|
|
||||||
|
|
||||||
enum LoanChangeType { owe, loan }
|
|
||||||
|
|
||||||
class AddLoanChangePopup extends StatefulWidget {
|
|
||||||
final VoidCallback onDone;
|
|
||||||
|
|
||||||
final Loan loan;
|
|
||||||
|
|
||||||
const AddLoanChangePopup({
|
|
||||||
super.key,
|
|
||||||
required this.onDone,
|
|
||||||
required this.loan,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
AddLoanPopupState createState() => AddLoanPopupState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class AddLoanPopupState extends State<AddLoanChangePopup> {
|
|
||||||
LoanChangeType _loanChangeType = LoanChangeType.loan;
|
|
||||||
final TextEditingController _amountController = TextEditingController(
|
|
||||||
text: "0.00",
|
|
||||||
);
|
|
||||||
|
|
||||||
DateTime _selectedDate = DateTime.now();
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
SegmentedButton(
|
|
||||||
segments: [
|
|
||||||
ButtonSegment(value: LoanChangeType.loan, label: Text("Loan")),
|
|
||||||
ButtonSegment(value: LoanChangeType.owe, label: Text("Owe")),
|
|
||||||
],
|
|
||||||
selected: {_loanChangeType},
|
|
||||||
onSelectionChanged: (values) {
|
|
||||||
setState(() {
|
|
||||||
_loanChangeType = values.first;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
TextField(
|
|
||||||
decoration: InputDecoration(
|
|
||||||
icon: Icon(Icons.euro),
|
|
||||||
hintText: "Amount",
|
|
||||||
),
|
|
||||||
controller: _amountController,
|
|
||||||
keyboardType: TextInputType.numberWithOptions(
|
|
||||||
signed: false,
|
|
||||||
decimal: true,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Text("Date"),
|
|
||||||
OutlinedButton(
|
|
||||||
onPressed: () async {
|
|
||||||
final dt = await showDatePicker(
|
|
||||||
context: context,
|
|
||||||
initialDate: _selectedDate,
|
|
||||||
firstDate: DateTime(1),
|
|
||||||
lastDate: DateTime(9999),
|
|
||||||
);
|
|
||||||
if (dt == null) return;
|
|
||||||
|
|
||||||
setState(() => _selectedDate = dt);
|
|
||||||
},
|
|
||||||
child: Text(formatDateTime(_selectedDate)),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Align(
|
|
||||||
alignment: Alignment.centerRight,
|
|
||||||
child: OutlinedButton(
|
|
||||||
onPressed: () async {
|
|
||||||
final sign = switch (_loanChangeType) {
|
|
||||||
LoanChangeType.owe => -1,
|
|
||||||
LoanChangeType.loan => 1,
|
|
||||||
};
|
|
||||||
final loanChange =
|
|
||||||
LoanChange()
|
|
||||||
..amount = sign * double.parse(_amountController.text).abs()
|
|
||||||
..date = DateTime.now();
|
|
||||||
await upsertLoanChange(loanChange);
|
|
||||||
widget.loan.changes.add(loanChange);
|
|
||||||
await upsertLoan(widget.loan);
|
|
||||||
widget.onDone();
|
|
||||||
},
|
|
||||||
child: Text(t.modals.add),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,168 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
||||||
import 'package:grouped_list/grouped_list.dart';
|
|
||||||
import 'package:okane/database/collections/loan.dart';
|
|
||||||
import 'package:okane/database/database.dart';
|
|
||||||
import 'package:okane/ui/pages/loans/add_loan_change.dart';
|
|
||||||
import 'package:okane/ui/state/core.dart';
|
|
||||||
import 'package:okane/ui/utils.dart';
|
|
||||||
import 'package:okane/ui/widgets/image_wrapper.dart';
|
|
||||||
|
|
||||||
class LoanDetailsPage extends StatelessWidget {
|
|
||||||
final bool isPage;
|
|
||||||
|
|
||||||
const LoanDetailsPage({super.key, required this.isPage});
|
|
||||||
|
|
||||||
static MaterialPageRoute<void> get mobileRoute =>
|
|
||||||
MaterialPageRoute(builder: (_) => LoanDetailsPage(isPage: true));
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Scaffold(
|
|
||||||
body: Column(
|
|
||||||
children: [
|
|
||||||
if (isPage)
|
|
||||||
SizedBox(
|
|
||||||
height: 50,
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
IconButton(
|
|
||||||
icon: Icon(Icons.arrow_back),
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: BlocBuilder<CoreCubit, CoreState>(
|
|
||||||
builder: (context, state) {
|
|
||||||
if (state.activeLoan == null) {
|
|
||||||
return Text("No loan selected");
|
|
||||||
}
|
|
||||||
|
|
||||||
final loanChanges = state.activeLoan!.changes.toList();
|
|
||||||
final loanSum =
|
|
||||||
loanChanges.isNotEmpty
|
|
||||||
? loanChanges
|
|
||||||
.map((c) => c.amount)
|
|
||||||
.reduce((acc, val) => acc + val)
|
|
||||||
: 0.0;
|
|
||||||
return CustomScrollView(
|
|
||||||
slivers: [
|
|
||||||
SliverToBoxAdapter(
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
ImageWrapper(
|
|
||||||
title: state.activeLoan!.beneficiary.value!.name,
|
|
||||||
path:
|
|
||||||
state.activeLoan!.beneficiary.value!.imagePath,
|
|
||||||
),
|
|
||||||
Text(state.activeLoan!.beneficiary.value!.name),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
SliverToBoxAdapter(
|
|
||||||
child: Text("Total: ${formatCurrency(loanSum)}"),
|
|
||||||
),
|
|
||||||
|
|
||||||
SliverToBoxAdapter(
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Text("Loan Transactions"),
|
|
||||||
|
|
||||||
IconButton(
|
|
||||||
onPressed: () {
|
|
||||||
showDialogOrModal(
|
|
||||||
context: context,
|
|
||||||
builder:
|
|
||||||
(_) => AddLoanChangePopup(
|
|
||||||
loan: state.activeLoan!,
|
|
||||||
onDone: () {
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
icon: Icon(Icons.add),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
SliverToBoxAdapter(
|
|
||||||
child:
|
|
||||||
loanChanges.isNotEmpty
|
|
||||||
? GroupedListView(
|
|
||||||
elements: loanChanges,
|
|
||||||
shrinkWrap: true,
|
|
||||||
reverse: true,
|
|
||||||
groupBy:
|
|
||||||
(LoanChange loanChange) =>
|
|
||||||
formatDateTime(loanChange.date),
|
|
||||||
groupHeaderBuilder:
|
|
||||||
(item) => Row(
|
|
||||||
mainAxisAlignment:
|
|
||||||
MainAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
DecoratedBox(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.black.withAlpha(170),
|
|
||||||
borderRadius: BorderRadius.circular(
|
|
||||||
8,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: Padding(
|
|
||||||
padding: EdgeInsets.all(4),
|
|
||||||
child: Text(
|
|
||||||
formatDateTime(item.date),
|
|
||||||
style: TextStyle(
|
|
||||||
color: Colors.white,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
indexedItemBuilder:
|
|
||||||
(ctx, item, idx) => ListTile(
|
|
||||||
leading:
|
|
||||||
item.amount > 0
|
|
||||||
? Icon(
|
|
||||||
Icons.add,
|
|
||||||
color: Colors.green,
|
|
||||||
)
|
|
||||||
: Icon(
|
|
||||||
Icons.remove,
|
|
||||||
color: Colors.red,
|
|
||||||
),
|
|
||||||
title: Text(formatCurrency(item.amount)),
|
|
||||||
trailing: IconButton(
|
|
||||||
icon: Icon(
|
|
||||||
Icons.delete,
|
|
||||||
color: Colors.red,
|
|
||||||
),
|
|
||||||
onPressed: () async {
|
|
||||||
state.activeLoan!.changes.remove(
|
|
||||||
item,
|
|
||||||
);
|
|
||||||
await deleteLoanChange(item);
|
|
||||||
await upsertLoan(state.activeLoan!);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: Text("No transactions available"),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,79 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
||||||
import 'package:get_it/get_it.dart';
|
|
||||||
import 'package:okane/database/database.dart';
|
|
||||||
import 'package:okane/screen.dart';
|
|
||||||
import 'package:okane/ui/pages/loans/add_loan.dart';
|
|
||||||
import 'package:okane/ui/state/core.dart';
|
|
||||||
import 'package:okane/ui/utils.dart';
|
|
||||||
import 'package:okane/ui/widgets/image_wrapper.dart';
|
|
||||||
|
|
||||||
class LoanListPage extends StatelessWidget {
|
|
||||||
const LoanListPage({super.key});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return BlocBuilder<CoreCubit, CoreState>(
|
|
||||||
builder: (context, state) {
|
|
||||||
return Stack(
|
|
||||||
children: [
|
|
||||||
ListView.builder(
|
|
||||||
itemCount: state.loans.length,
|
|
||||||
itemBuilder: (context, index) {
|
|
||||||
final item = state.loans[index];
|
|
||||||
final beneficiary = item.beneficiary.value!;
|
|
||||||
return ListTile(
|
|
||||||
leading: ImageWrapper(
|
|
||||||
title: beneficiary.name,
|
|
||||||
path: beneficiary.imagePath,
|
|
||||||
),
|
|
||||||
onTap: () {
|
|
||||||
GetIt.I.get<CoreCubit>().setActiveLoan(item);
|
|
||||||
|
|
||||||
if (getScreenSize(context) == ScreenSize.small) {
|
|
||||||
Navigator.of(context).pushNamed("/loans/details");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
trailing: IconButton(
|
|
||||||
onPressed: () async {
|
|
||||||
final result = await confirm(
|
|
||||||
context,
|
|
||||||
"Delete Loan",
|
|
||||||
"Are you sure you want to delete the loan?",
|
|
||||||
);
|
|
||||||
if (!result) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await deleteLoan(item);
|
|
||||||
},
|
|
||||||
icon: Icon(Icons.delete, color: Colors.red),
|
|
||||||
),
|
|
||||||
title: Text(beneficiary.name),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
Positioned(
|
|
||||||
right: 16,
|
|
||||||
bottom: 16,
|
|
||||||
child: FloatingActionButton(
|
|
||||||
child: Icon(Icons.add),
|
|
||||||
onPressed: () {
|
|
||||||
showDialogOrModal(
|
|
||||||
context: context,
|
|
||||||
builder:
|
|
||||||
(_) => AddLoanPopup(
|
|
||||||
onDone: () {
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -5,7 +5,6 @@ import 'package:okane/database/collections/account.dart';
|
|||||||
import 'package:okane/database/collections/beneficiary.dart';
|
import 'package:okane/database/collections/beneficiary.dart';
|
||||||
import 'package:okane/database/collections/budget.dart';
|
import 'package:okane/database/collections/budget.dart';
|
||||||
import 'package:okane/database/collections/expense_category.dart';
|
import 'package:okane/database/collections/expense_category.dart';
|
||||||
import 'package:okane/database/collections/loan.dart';
|
|
||||||
import 'package:okane/database/collections/recurrent.dart';
|
import 'package:okane/database/collections/recurrent.dart';
|
||||||
import 'package:okane/database/collections/template.dart';
|
import 'package:okane/database/collections/template.dart';
|
||||||
import 'package:okane/database/collections/transaction.dart';
|
import 'package:okane/database/collections/transaction.dart';
|
||||||
@ -28,8 +27,6 @@ abstract class CoreState with _$CoreState {
|
|||||||
@Default([]) List<ExpenseCategory> expenseCategories,
|
@Default([]) List<ExpenseCategory> expenseCategories,
|
||||||
@Default([]) List<Budget> budgets,
|
@Default([]) List<Budget> budgets,
|
||||||
@Default(null) Budget? activeBudget,
|
@Default(null) Budget? activeBudget,
|
||||||
@Default([]) List<Loan> loans,
|
|
||||||
@Default(null) Loan? activeLoan,
|
|
||||||
@Default(false) bool isDeletingAccount,
|
@Default(false) bool isDeletingAccount,
|
||||||
}) = _CoreState;
|
}) = _CoreState;
|
||||||
}
|
}
|
||||||
@ -44,7 +41,6 @@ class CoreCubit extends Cubit<CoreState> {
|
|||||||
StreamSubscription<void>? _beneficiariesStreamSubscription;
|
StreamSubscription<void>? _beneficiariesStreamSubscription;
|
||||||
StreamSubscription<void>? _expenseCategoryStreamSubscription;
|
StreamSubscription<void>? _expenseCategoryStreamSubscription;
|
||||||
StreamSubscription<void>? _budgetsStreamSubscription;
|
StreamSubscription<void>? _budgetsStreamSubscription;
|
||||||
StreamSubscription<void>? _loanStreamSubscription;
|
|
||||||
|
|
||||||
void setupAccountStream() {
|
void setupAccountStream() {
|
||||||
_accountsStreamSubscription?.cancel();
|
_accountsStreamSubscription?.cancel();
|
||||||
@ -119,10 +115,6 @@ class CoreCubit extends Cubit<CoreState> {
|
|||||||
) async {
|
) async {
|
||||||
emit(state.copyWith(budgets: await db.getBudgets(activeAccount!)));
|
emit(state.copyWith(budgets: await db.getBudgets(activeAccount!)));
|
||||||
});
|
});
|
||||||
_loanStreamSubscription?.cancel();
|
|
||||||
_loanStreamSubscription = db.watchLoans().listen((_) async {
|
|
||||||
emit(state.copyWith(loans: await db.getLoans()));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void cancelStreams() {
|
void cancelStreams() {
|
||||||
@ -133,7 +125,6 @@ class CoreCubit extends Cubit<CoreState> {
|
|||||||
_expenseCategoryStreamSubscription?.cancel();
|
_expenseCategoryStreamSubscription?.cancel();
|
||||||
_transactionsStreamSubscription?.cancel();
|
_transactionsStreamSubscription?.cancel();
|
||||||
_transactionTemplatesStreamSubcription?.cancel();
|
_transactionTemplatesStreamSubcription?.cancel();
|
||||||
_loanStreamSubscription?.cancel();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> init() async {
|
Future<void> init() async {
|
||||||
@ -149,7 +140,6 @@ class CoreCubit extends Cubit<CoreState> {
|
|||||||
recurringTransactions: await db.getRecurringTransactions(account),
|
recurringTransactions: await db.getRecurringTransactions(account),
|
||||||
expenseCategories: await db.getExpenseCategories(),
|
expenseCategories: await db.getExpenseCategories(),
|
||||||
budgets: await db.getBudgets(account),
|
budgets: await db.getBudgets(account),
|
||||||
loans: await db.getLoans(),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -177,7 +167,6 @@ class CoreCubit extends Cubit<CoreState> {
|
|||||||
budgets: await db.getBudgets(account),
|
budgets: await db.getBudgets(account),
|
||||||
activeBudget: null,
|
activeBudget: null,
|
||||||
activeTransaction: null,
|
activeTransaction: null,
|
||||||
activeLoan: null,
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
setupStreams(account);
|
setupStreams(account);
|
||||||
@ -210,10 +199,6 @@ class CoreCubit extends Cubit<CoreState> {
|
|||||||
await init();
|
await init();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setActiveLoan(Loan loan) {
|
|
||||||
emit(state.copyWith(activeLoan: loan));
|
|
||||||
}
|
|
||||||
|
|
||||||
Account? get activeAccount =>
|
Account? get activeAccount =>
|
||||||
state.activeAccountIndex == null
|
state.activeAccountIndex == null
|
||||||
? null
|
? null
|
||||||
|
@ -31,8 +31,6 @@ mixin _$CoreState {
|
|||||||
throw _privateConstructorUsedError;
|
throw _privateConstructorUsedError;
|
||||||
List<Budget> get budgets => throw _privateConstructorUsedError;
|
List<Budget> get budgets => throw _privateConstructorUsedError;
|
||||||
Budget? get activeBudget => throw _privateConstructorUsedError;
|
Budget? get activeBudget => throw _privateConstructorUsedError;
|
||||||
List<Loan> get loans => throw _privateConstructorUsedError;
|
|
||||||
Loan? get activeLoan => throw _privateConstructorUsedError;
|
|
||||||
bool get isDeletingAccount => throw _privateConstructorUsedError;
|
bool get isDeletingAccount => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
@JsonKey(ignore: true)
|
@JsonKey(ignore: true)
|
||||||
@ -57,8 +55,6 @@ abstract class $CoreStateCopyWith<$Res> {
|
|||||||
List<ExpenseCategory> expenseCategories,
|
List<ExpenseCategory> expenseCategories,
|
||||||
List<Budget> budgets,
|
List<Budget> budgets,
|
||||||
Budget? activeBudget,
|
Budget? activeBudget,
|
||||||
List<Loan> loans,
|
|
||||||
Loan? activeLoan,
|
|
||||||
bool isDeletingAccount,
|
bool isDeletingAccount,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -87,8 +83,6 @@ class _$CoreStateCopyWithImpl<$Res, $Val extends CoreState>
|
|||||||
Object? expenseCategories = null,
|
Object? expenseCategories = null,
|
||||||
Object? budgets = null,
|
Object? budgets = null,
|
||||||
Object? activeBudget = freezed,
|
Object? activeBudget = freezed,
|
||||||
Object? loans = null,
|
|
||||||
Object? activeLoan = freezed,
|
|
||||||
Object? isDeletingAccount = null,
|
Object? isDeletingAccount = null,
|
||||||
}) {
|
}) {
|
||||||
return _then(
|
return _then(
|
||||||
@ -148,16 +142,6 @@ class _$CoreStateCopyWithImpl<$Res, $Val extends CoreState>
|
|||||||
? _value.activeBudget
|
? _value.activeBudget
|
||||||
: activeBudget // ignore: cast_nullable_to_non_nullable
|
: activeBudget // ignore: cast_nullable_to_non_nullable
|
||||||
as Budget?,
|
as Budget?,
|
||||||
loans:
|
|
||||||
null == loans
|
|
||||||
? _value.loans
|
|
||||||
: loans // ignore: cast_nullable_to_non_nullable
|
|
||||||
as List<Loan>,
|
|
||||||
activeLoan:
|
|
||||||
freezed == activeLoan
|
|
||||||
? _value.activeLoan
|
|
||||||
: activeLoan // ignore: cast_nullable_to_non_nullable
|
|
||||||
as Loan?,
|
|
||||||
isDeletingAccount:
|
isDeletingAccount:
|
||||||
null == isDeletingAccount
|
null == isDeletingAccount
|
||||||
? _value.isDeletingAccount
|
? _value.isDeletingAccount
|
||||||
@ -190,8 +174,6 @@ abstract class _$$CoreStateImplCopyWith<$Res>
|
|||||||
List<ExpenseCategory> expenseCategories,
|
List<ExpenseCategory> expenseCategories,
|
||||||
List<Budget> budgets,
|
List<Budget> budgets,
|
||||||
Budget? activeBudget,
|
Budget? activeBudget,
|
||||||
List<Loan> loans,
|
|
||||||
Loan? activeLoan,
|
|
||||||
bool isDeletingAccount,
|
bool isDeletingAccount,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -219,8 +201,6 @@ class __$$CoreStateImplCopyWithImpl<$Res>
|
|||||||
Object? expenseCategories = null,
|
Object? expenseCategories = null,
|
||||||
Object? budgets = null,
|
Object? budgets = null,
|
||||||
Object? activeBudget = freezed,
|
Object? activeBudget = freezed,
|
||||||
Object? loans = null,
|
|
||||||
Object? activeLoan = freezed,
|
|
||||||
Object? isDeletingAccount = null,
|
Object? isDeletingAccount = null,
|
||||||
}) {
|
}) {
|
||||||
return _then(
|
return _then(
|
||||||
@ -280,16 +260,6 @@ class __$$CoreStateImplCopyWithImpl<$Res>
|
|||||||
? _value.activeBudget
|
? _value.activeBudget
|
||||||
: activeBudget // ignore: cast_nullable_to_non_nullable
|
: activeBudget // ignore: cast_nullable_to_non_nullable
|
||||||
as Budget?,
|
as Budget?,
|
||||||
loans:
|
|
||||||
null == loans
|
|
||||||
? _value._loans
|
|
||||||
: loans // ignore: cast_nullable_to_non_nullable
|
|
||||||
as List<Loan>,
|
|
||||||
activeLoan:
|
|
||||||
freezed == activeLoan
|
|
||||||
? _value.activeLoan
|
|
||||||
: activeLoan // ignore: cast_nullable_to_non_nullable
|
|
||||||
as Loan?,
|
|
||||||
isDeletingAccount:
|
isDeletingAccount:
|
||||||
null == isDeletingAccount
|
null == isDeletingAccount
|
||||||
? _value.isDeletingAccount
|
? _value.isDeletingAccount
|
||||||
@ -315,8 +285,6 @@ class _$CoreStateImpl implements _CoreState {
|
|||||||
final List<ExpenseCategory> expenseCategories = const [],
|
final List<ExpenseCategory> expenseCategories = const [],
|
||||||
final List<Budget> budgets = const [],
|
final List<Budget> budgets = const [],
|
||||||
this.activeBudget = null,
|
this.activeBudget = null,
|
||||||
final List<Loan> loans = const [],
|
|
||||||
this.activeLoan = null,
|
|
||||||
this.isDeletingAccount = false,
|
this.isDeletingAccount = false,
|
||||||
}) : _accounts = accounts,
|
}) : _accounts = accounts,
|
||||||
_recurringTransactions = recurringTransactions,
|
_recurringTransactions = recurringTransactions,
|
||||||
@ -324,8 +292,7 @@ class _$CoreStateImpl implements _CoreState {
|
|||||||
_transactionTemplates = transactionTemplates,
|
_transactionTemplates = transactionTemplates,
|
||||||
_beneficiaries = beneficiaries,
|
_beneficiaries = beneficiaries,
|
||||||
_expenseCategories = expenseCategories,
|
_expenseCategories = expenseCategories,
|
||||||
_budgets = budgets,
|
_budgets = budgets;
|
||||||
_loans = loans;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@JsonKey()
|
@JsonKey()
|
||||||
@ -404,25 +371,13 @@ class _$CoreStateImpl implements _CoreState {
|
|||||||
@override
|
@override
|
||||||
@JsonKey()
|
@JsonKey()
|
||||||
final Budget? activeBudget;
|
final Budget? activeBudget;
|
||||||
final List<Loan> _loans;
|
|
||||||
@override
|
|
||||||
@JsonKey()
|
|
||||||
List<Loan> get loans {
|
|
||||||
if (_loans is EqualUnmodifiableListView) return _loans;
|
|
||||||
// ignore: implicit_dynamic_type
|
|
||||||
return EqualUnmodifiableListView(_loans);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
@JsonKey()
|
|
||||||
final Loan? activeLoan;
|
|
||||||
@override
|
@override
|
||||||
@JsonKey()
|
@JsonKey()
|
||||||
final bool isDeletingAccount;
|
final bool isDeletingAccount;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'CoreState(activePage: $activePage, activeAccountIndex: $activeAccountIndex, activeTransaction: $activeTransaction, accounts: $accounts, recurringTransactions: $recurringTransactions, transactions: $transactions, transactionTemplates: $transactionTemplates, beneficiaries: $beneficiaries, expenseCategories: $expenseCategories, budgets: $budgets, activeBudget: $activeBudget, loans: $loans, activeLoan: $activeLoan, isDeletingAccount: $isDeletingAccount)';
|
return 'CoreState(activePage: $activePage, activeAccountIndex: $activeAccountIndex, activeTransaction: $activeTransaction, accounts: $accounts, recurringTransactions: $recurringTransactions, transactions: $transactions, transactionTemplates: $transactionTemplates, beneficiaries: $beneficiaries, expenseCategories: $expenseCategories, budgets: $budgets, activeBudget: $activeBudget, isDeletingAccount: $isDeletingAccount)';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -460,9 +415,6 @@ class _$CoreStateImpl implements _CoreState {
|
|||||||
const DeepCollectionEquality().equals(other._budgets, _budgets) &&
|
const DeepCollectionEquality().equals(other._budgets, _budgets) &&
|
||||||
(identical(other.activeBudget, activeBudget) ||
|
(identical(other.activeBudget, activeBudget) ||
|
||||||
other.activeBudget == activeBudget) &&
|
other.activeBudget == activeBudget) &&
|
||||||
const DeepCollectionEquality().equals(other._loans, _loans) &&
|
|
||||||
(identical(other.activeLoan, activeLoan) ||
|
|
||||||
other.activeLoan == activeLoan) &&
|
|
||||||
(identical(other.isDeletingAccount, isDeletingAccount) ||
|
(identical(other.isDeletingAccount, isDeletingAccount) ||
|
||||||
other.isDeletingAccount == isDeletingAccount));
|
other.isDeletingAccount == isDeletingAccount));
|
||||||
}
|
}
|
||||||
@ -481,8 +433,6 @@ class _$CoreStateImpl implements _CoreState {
|
|||||||
const DeepCollectionEquality().hash(_expenseCategories),
|
const DeepCollectionEquality().hash(_expenseCategories),
|
||||||
const DeepCollectionEquality().hash(_budgets),
|
const DeepCollectionEquality().hash(_budgets),
|
||||||
activeBudget,
|
activeBudget,
|
||||||
const DeepCollectionEquality().hash(_loans),
|
|
||||||
activeLoan,
|
|
||||||
isDeletingAccount,
|
isDeletingAccount,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -506,8 +456,6 @@ abstract class _CoreState implements CoreState {
|
|||||||
final List<ExpenseCategory> expenseCategories,
|
final List<ExpenseCategory> expenseCategories,
|
||||||
final List<Budget> budgets,
|
final List<Budget> budgets,
|
||||||
final Budget? activeBudget,
|
final Budget? activeBudget,
|
||||||
final List<Loan> loans,
|
|
||||||
final Loan? activeLoan,
|
|
||||||
final bool isDeletingAccount,
|
final bool isDeletingAccount,
|
||||||
}) = _$CoreStateImpl;
|
}) = _$CoreStateImpl;
|
||||||
|
|
||||||
@ -534,10 +482,6 @@ abstract class _CoreState implements CoreState {
|
|||||||
@override
|
@override
|
||||||
Budget? get activeBudget;
|
Budget? get activeBudget;
|
||||||
@override
|
@override
|
||||||
List<Loan> get loans;
|
|
||||||
@override
|
|
||||||
Loan? get activeLoan;
|
|
||||||
@override
|
|
||||||
bool get isDeletingAccount;
|
bool get isDeletingAccount;
|
||||||
@override
|
@override
|
||||||
@JsonKey(ignore: true)
|
@JsonKey(ignore: true)
|
||||||
|
@ -1,86 +1,11 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
||||||
import 'package:get_it/get_it.dart';
|
|
||||||
import 'package:okane/ui/pages/account/delete_account.dart';
|
|
||||||
import 'package:okane/ui/state/core.dart';
|
|
||||||
import 'package:okane/ui/utils.dart';
|
|
||||||
|
|
||||||
class AccountSwitcher extends StatelessWidget {
|
|
||||||
const AccountSwitcher({super.key});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final bloc = GetIt.I.get<CoreCubit>();
|
|
||||||
return BlocBuilder<CoreCubit, CoreState>(
|
|
||||||
builder:
|
|
||||||
(context, state) => InkWell(
|
|
||||||
borderRadius: BorderRadius.circular(8),
|
|
||||||
onTap: () {
|
|
||||||
showDialogOrModal(
|
|
||||||
context: context,
|
|
||||||
builder:
|
|
||||||
(context) => ListView.builder(
|
|
||||||
shrinkWrap: true,
|
|
||||||
itemCount: state.accounts.length,
|
|
||||||
itemBuilder: (context, index) {
|
|
||||||
final item = state.accounts[index];
|
|
||||||
return ListTile(
|
|
||||||
title: Text(item.name!),
|
|
||||||
trailing: IconButton(
|
|
||||||
icon: Icon(Icons.delete),
|
|
||||||
color: Colors.red,
|
|
||||||
onPressed: () async {
|
|
||||||
await showDialog(
|
|
||||||
context: context,
|
|
||||||
barrierDismissible: false,
|
|
||||||
builder:
|
|
||||||
(context) => DeleteAccountPopup(
|
|
||||||
account: item,
|
|
||||||
onCancel: () {
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
|
||||||
afterDelete: () {
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
onTap: () {
|
|
||||||
GetIt.I.get<CoreCubit>().setActiveAccountIndex(
|
|
||||||
index,
|
|
||||||
);
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
child: Padding(
|
|
||||||
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
|
||||||
child: Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
bloc.activeAccount!.name!,
|
|
||||||
style: Theme.of(context).textTheme.titleLarge,
|
|
||||||
),
|
|
||||||
Icon(Icons.arrow_drop_down),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class AccountIndicator extends StatelessWidget {
|
class AccountIndicator extends StatelessWidget {
|
||||||
|
final String accountName;
|
||||||
|
|
||||||
final Widget? trailing;
|
final Widget? trailing;
|
||||||
|
|
||||||
const AccountIndicator({super.key, this.trailing});
|
const AccountIndicator({super.key, this.trailing, required this.accountName});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -90,8 +15,11 @@ class AccountIndicator extends StatelessWidget {
|
|||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
padding: EdgeInsets.all(8),
|
||||||
child: AccountSwitcher(),
|
child: Text(
|
||||||
|
accountName,
|
||||||
|
style: Theme.of(context).textTheme.titleLarge,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
if (trailing != null) trailing!,
|
if (trailing != null) trailing!,
|
||||||
|
@ -2,7 +2,7 @@ name: okane
|
|||||||
description: "A cross-platform finance tracker."
|
description: "A cross-platform finance tracker."
|
||||||
publish_to: 'none'
|
publish_to: 'none'
|
||||||
|
|
||||||
version: 1.0.0+2
|
version: 1.0.0+1
|
||||||
environment:
|
environment:
|
||||||
sdk: ^3.7.0
|
sdk: ^3.7.0
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user