Skip to content

Commit

Permalink
car expenses list
Browse files Browse the repository at this point in the history
  • Loading branch information
LynxLynxx committed Oct 10, 2024
1 parent 681b34d commit 4696def
Show file tree
Hide file tree
Showing 20 changed files with 2,013 additions and 71 deletions.
1,642 changes: 1,642 additions & 0 deletions ios/Podfile.lock

Large diffs are not rendered by default.

18 changes: 18 additions & 0 deletions ios/Runner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
FB0B05F8A7D4A85B62B4C979 /* [CP] Embed Pods Frameworks */,
767DB55EB60DD2E3A6EC441E /* FlutterFire: "flutterfire upload-crashlytics-symbols" */,
1BA6883E477312D8326A8C83 /* [CP] Copy Pods Resources */,
);
buildRules = (
);
Expand Down Expand Up @@ -274,6 +275,23 @@
/* End PBXResourcesBuildPhase section */

/* Begin PBXShellScriptBuildPhase section */
1BA6883E477312D8326A8C83 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Copy Pods Resources";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
showEnvVarsInLog = 0;
};
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
Expand Down
8 changes: 6 additions & 2 deletions l10n_errors.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
"more",
"expenseByDt",
"statistics",
"noExpenses"
"noExpenses",
"allExpenses",
"editExpense"
],

"pl": [
Expand All @@ -18,6 +20,8 @@
"more",
"expenseByDt",
"statistics",
"noExpenses"
"noExpenses",
"allExpenses",
"editExpense"
]
}
5 changes: 4 additions & 1 deletion lib/core/router/routes/shell_routes.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:carlog/core/router/entities/dialog_route.dart';
import 'package:carlog/core/router/router.dart';
import 'package:carlog/core/router/routes_constants.dart';
import 'package:carlog/features/dashboard_features/analytics/domain/entities/car_expense_entity.dart';
import 'package:carlog/features/dashboard_features/analytics/presentation/pages/analytics_page.dart';
import 'package:carlog/features/dashboard_features/cars/presentation/pages/add_car_page.dart';
import 'package:carlog/features/dashboard_features/cars/presentation/pages/cars_page.dart';
Expand Down Expand Up @@ -104,7 +105,9 @@ final StatefulShellBranch dashboardBranches = StatefulShellBranch(
GoRoute(
path: "addExpense",
builder: (context, state) {
return const ExpensePage();
return ExpensePage(
carExpenseEntity: state.extra as CarExpenseEntity?,
);
},
),
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,14 @@ class ExpenseDatasourceImpl implements ExpenseDatasource {
.doc(carId)
.collection(CollectionsK.expenses)
.path, (doc) {
return doc
final filteredDoc = doc
.map((model) =>
CarExpenseEntity.fromJson(model.data() as Map<String, dynamic>))
.where((element) => !element.isDeleted)
.toList();

filteredDoc.sort((a, b) => b.timestamp!.compareTo(a.timestamp!));
return filteredDoc;
});

@override
Expand Down Expand Up @@ -63,5 +67,7 @@ class ExpenseDatasourceImpl implements ExpenseDatasource {
.doc(carId)
.collection(CollectionsK.expenses)
.doc(carExpenseId),
(doc) => doc.delete());
(doc) => doc.update({
"isDeleted": true,
}));
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class CarExpenseEntity with _$CarExpenseEntity {
@Default(null) String? note,
@Default(null) String? attachmentPath,
@Default(null) CarExpenseEnum? expense,
@Default(false) bool isDeleted,
}) = _CarExpenseEntity;

factory CarExpenseEntity.fromJson(Map<String, dynamic> json) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ enum CarExpenseEnum {
tires,
tuning,
other,
all,
}

extension CarExpenseExtension on CarExpenseEnum {
Expand All @@ -32,6 +33,8 @@ extension CarExpenseExtension on CarExpenseEnum {
return S.current.tuning;
case CarExpenseEnum.other:
return S.current.other;
case CarExpenseEnum.all:
return S.current.allExpenses;
default:
return S.current.other;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:bloc/bloc.dart';
import 'package:carlog/core/error/failures.dart';
import 'package:carlog/features/dashboard_features/analytics/domain/entities/car_expense_entity.dart';
import 'package:carlog/features/dashboard_features/analytics/domain/usecases/delete_expense_usecase.dart';
import 'package:carlog/features/dashboard_features/analytics/domain/usecases/get_expenses_usecase.dart';
import 'package:freezed_annotation/freezed_annotation.dart';

Expand All @@ -10,13 +11,34 @@ part 'analytics_state.dart';

class AnalyticsBloc extends Bloc<AnalyticsEvent, AnalyticsState> {
final GetExpensesUsecase _getExpensesUsecase;
AnalyticsBloc(this._getExpensesUsecase) : super(const _Initial()) {
final DeleteExpenseUsecase _deleteExpenseUsecase;
List<CarExpenseEntity> carExpenseList = [];
AnalyticsBloc(
this._getExpensesUsecase,
this._deleteExpenseUsecase,
) : super(const _Initial()) {
on<_GetExpenses>(_onGetExpenses);
on<_DeleteExpense>(_onDeleteExpense);
}

_onGetExpenses(_GetExpenses event, Emitter<AnalyticsState> emit) async {
emit(const _Loading());
final result = await _getExpensesUsecase.call(event.carId);
result.fold((l) => emit(_Failure(l)), (r) => emit(_Data(r)));
result.fold((l) => emit(_Failure(l)), (r) {
carExpenseList = r;
emit(_Data(r));
});
}

_onDeleteExpense(_DeleteExpense event, Emitter<AnalyticsState> emit) async {
final result =
await _deleteExpenseUsecase.call(event.carId, event.carExpenseId);
if (result.isNone()) {
final carExpense = carExpenseList
.indexWhere((element) => element.carExpenseId == event.carExpenseId);
emit(const _Loading());
carExpenseList = carExpenseList..removeAt(carExpense);
emit(_Data(carExpenseList));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,8 @@ part of 'analytics_bloc.dart';

@freezed
class AnalyticsEvent with _$AnalyticsEvent {
const factory AnalyticsEvent.getExpenses({required String carId}) = _GetExpenses;
const factory AnalyticsEvent.getExpenses({required String carId}) =
_GetExpenses;
const factory AnalyticsEvent.deleteExpense(
{required String carId, required String carExpenseId}) = _DeleteExpense;
}
Original file line number Diff line number Diff line change
@@ -1,36 +1,154 @@
import 'package:carlog/core/extensions/styles_extenstion.dart';
import 'package:carlog/features/dashboard_features/analytics/domain/entities/car_expense_entity.dart';
import 'package:carlog/features/dashboard_features/analytics/domain/entities/car_expense_enum.dart';
import 'package:carlog/features/dashboard_features/analytics/presentation/bloc/analytics_bloc.dart';
import 'package:carlog/features/dashboard_features/analytics/presentation/widgets/expense_card_widget.dart';
import 'package:carlog/features/other_features/user_app/presentation/bloc/user_app_bloc.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

Future<void> allExpenseModal(BuildContext appContext) {
return showModalBottomSheet(
showDragHandle: true,
useRootNavigator: true,
backgroundColor: appContext.surfaceColor,
isScrollControlled: true,
useSafeArea: true,
context: appContext,
builder: (context) => GestureDetector(
onTap: () => FocusScope.of(context).unfocus(),
child: SizedBox(
width: double.infinity,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
child: Column(
children: [
Padding(
padding: const EdgeInsets.only(bottom: 10, top: 4),
child: Container(
width: 40,
height: 5,
decoration: BoxDecoration(
color: context.primaryColor,
borderRadius: BorderRadius.circular(20),
),
constraints:
BoxConstraints(maxHeight: MediaQuery.of(appContext).size.height * 0.85),
builder: (context) => MultiBlocProvider(
providers: [
BlocProvider.value(
value: appContext.read<AnalyticsBloc>(),
),
BlocProvider.value(
value: appContext.read<UserAppBloc>(),
),
],
child: const AllExpenseDialogWidget(),
),
);
}

class AllExpenseDialogWidget extends StatefulWidget {
const AllExpenseDialogWidget({
super.key,
});

@override
State<AllExpenseDialogWidget> createState() => _AllExpenseDialogWidgetState();
}

class _AllExpenseDialogWidgetState extends State<AllExpenseDialogWidget> {
final List<CarExpenseEnum> carExpensesType = [
CarExpenseEnum.all,
CarExpenseEnum.insuranceFee,
CarExpenseEnum.serviceFee,
CarExpenseEnum.roadFee,
CarExpenseEnum.carWash,
CarExpenseEnum.parkingFee,
CarExpenseEnum.tires,
CarExpenseEnum.tuning,
CarExpenseEnum.other,
];
CarExpenseEnum selectedCarExpenseType = CarExpenseEnum.all;

List<Widget> carExpensesTiles(List<CarExpenseEntity> data) {
final filteredData = data
.where((e) => selectedCarExpenseType != CarExpenseEnum.all
? e.expense == selectedCarExpenseType
: true)
.map((e) => ExpenseCardWidget(
carExpenseEntity: e,
))
.toList();

if (filteredData.isEmpty) {
return [
const Center(
child: Text("There are no expenses that we can show"),
)
];
} else {
return filteredData;
}
}

@override
Widget build(BuildContext context) {
return SizedBox(
width: double.infinity,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
child: Column(
children: [
Padding(
padding: const EdgeInsets.only(bottom: 20),
child: SizedBox(
height: 40,
child: ListView(
scrollDirection: Axis.horizontal,
// itemExtent: 150,
children: carExpensesType
.map(
(e) => Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: Container(
clipBehavior: Clip.hardEdge,
decoration: BoxDecoration(
border: Border.all(
color: context.primaryContainer,
width: 2,
),
borderRadius: BorderRadius.circular(20),
color: selectedCarExpenseType == e
? context.primaryContainer
: null,
),
child: GestureDetector(
onTap: () {
if (selectedCarExpenseType != e) {
setState(() {
selectedCarExpenseType = e;
});
}
},
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
CarExpenseExtension.getCustomName(e),
textAlign: TextAlign.center,
style: TextStyle(
fontWeight: selectedCarExpenseType == e
? FontWeight.bold
: null),
),
),
),
),
),
)
.toList(),
),
),
],
),
),
BlocBuilder<AnalyticsBloc, AnalyticsState>(
builder: (context, state) {
return state.maybeWhen(
orElse: () => const SizedBox(),
data: (data) => Expanded(
child: ListView(
physics: const ClampingScrollPhysics(),
children: carExpensesTiles(data),
),
),
);
},
),
],
),
),
),
);
);
}
}
Loading

0 comments on commit 4696def

Please sign in to comment.