attendence records, extra hours , rewards and punishment funnctionality have been added

This commit is contained in:
Daniah Ayad Al-sultani
2026-02-10 16:27:08 +03:00
parent cd7ba8e9d5
commit 1002937045
25 changed files with 1048 additions and 181 deletions

View File

@@ -1,9 +1,14 @@
import 'package:coda_project/presentation/screens/notifications_screen.dart';
import 'package:coda_project/presentation/screens/user_settings_screen.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../widgets/finance_summary_card.dart';
import '../widgets/work_day_card.dart';
import '../widgets/settings_bar.dart';
import '../bloc/finance_bloc.dart';
import '../../core/di/injection_container.dart';
import '../../data/datasources/user_local_data_source.dart';
import '../../domain/models/finance_category.dart';
class FinanceScreen extends StatefulWidget {
final void Function(bool isScrollingDown)? onScrollEvent;
@@ -15,13 +20,15 @@ class FinanceScreen extends StatefulWidget {
}
class _FinanceScreenState extends State<FinanceScreen> {
String dropdownValue = "الكل";
FinanceCategory currentCategory = FinanceCategory.attendance;
late ScrollController scrollController;
String? _employeeId;
@override
void initState() {
super.initState();
scrollController = ScrollController();
_loadInitialData();
}
@override
@@ -30,74 +37,152 @@ class _FinanceScreenState extends State<FinanceScreen> {
super.dispose();
}
void _loadInitialData() async {
_employeeId = await sl<UserLocalDataSource>().getCachedEmployeeId();
if (mounted) {
setState(() {});
}
}
void _triggerLoad(BuildContext context) {
if (_employeeId != null && _employeeId!.isNotEmpty) {
final bloc = context.read<FinanceBloc>();
if (bloc.state is FinanceInitial) {
bloc.add(
LoadFinanceDataEvent(
employeeId: _employeeId!,
category: currentCategory,
),
);
}
}
}
@override
Widget build(BuildContext context) {
return Directionality(
textDirection: TextDirection.ltr,
child: SafeArea(
child: CustomScrollView(
controller: scrollController,
physics: const BouncingScrollPhysics(),
slivers: [
SliverToBoxAdapter(
child: SettingsBar(
selectedIndex: 0,
showBackButton: false,
iconPaths: [
'assets/images/user.svg',
'assets/images/ball.svg',
],
onTap: (index) {
if (index == 0) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => UserSettingsScreen(),
return BlocProvider(
create: (context) => sl<FinanceBloc>(),
child: Directionality(
textDirection: TextDirection.ltr,
child: SafeArea(
child: Builder(
builder: (context) {
// Trigger initial load when bloc is ready
_triggerLoad(context);
return CustomScrollView(
controller: scrollController,
physics: const BouncingScrollPhysics(),
slivers: [
SliverToBoxAdapter(
child: SettingsBar(
selectedIndex: 0,
showBackButton: false,
iconPaths: const [
'assets/images/user.svg',
'assets/images/ball.svg',
],
onTap: (index) {
if (index == 0) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const UserSettingsScreen(),
),
);
} else if (index == 1) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const NotificationsScreen(),
),
);
}
},
),
),
const SliverToBoxAdapter(child: SizedBox(height: 5)),
/// SUMMARY CARD
SliverToBoxAdapter(
child: FinanceSummaryCard(
totalAmount: "333,000",
currentCategory: currentCategory,
onCalendarTap:
() => showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(2020),
lastDate: DateTime(2030),
),
onCategoryChanged: (category) {
if (category != null) {
setState(() => currentCategory = category);
context.read<FinanceBloc>().add(
LoadFinanceDataEvent(
employeeId: _employeeId ?? '',
category: currentCategory,
),
);
}
},
),
),
/// DATA LIST
BlocBuilder<FinanceBloc, FinanceState>(
builder: (context, state) {
if (state is FinanceLoading || state is FinanceInitial) {
return const SliverToBoxAdapter(
child: Center(
child: Padding(
padding: EdgeInsets.all(20.0),
child: CircularProgressIndicator(),
),
),
);
} else if (index == 1) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => NotificationsScreen(),
} else if (state is FinanceLoaded) {
if (state.records.isEmpty) {
return const SliverToBoxAdapter(
child: Center(
child: Padding(
padding: EdgeInsets.all(20.0),
child: Text("لا توجد سجلات"),
),
),
);
}
return SliverList(
delegate: SliverChildBuilderDelegate((
context,
index,
) {
return WorkDayCard(record: state.records[index]);
}, childCount: state.records.length),
);
} else if (state is FinanceError) {
return SliverToBoxAdapter(
child: Center(
child: Padding(
padding: EdgeInsets.all(20.0),
child: Text(
state.message,
style: const TextStyle(color: Colors.red),
textAlign: TextAlign.center,
),
),
),
);
}
return const SliverToBoxAdapter(child: SizedBox());
},
),
),
const SliverToBoxAdapter(child: SizedBox(height: 5)),
/// SUMMARY CARD
SliverToBoxAdapter(
child: FinanceSummaryCard(
totalAmount: "333,000",
dropdownValue: dropdownValue,
onCalendarTap: () => showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(2020),
lastDate: DateTime(2030),
),
onDropdownChanged: (value) {
setState(() => dropdownValue = value!);
},
),
),
/// WORK DAY CARDS
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) {
return const WorkDayCard();
},
childCount: 3,
),
),
const SliverToBoxAdapter(child: SizedBox(height: 120)),
],
const SliverToBoxAdapter(child: SizedBox(height: 120)),
],
);
},
),
),
),
);