working on the user setting screen

This commit is contained in:
Daniah Ayad Al-sultani
2025-12-09 17:16:43 +03:00
parent 6ec8a882ef
commit 5931732b41
3 changed files with 420 additions and 210 deletions

View File

@@ -1,5 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import '../screens/request_leave_screen.dart'; import '../screens/request_leave_screen.dart';
import '../screens/request_advance_scrren.dart'; import '../screens/request_advance_scrren.dart';
import '../models/leave_request.dart'; import '../models/leave_request.dart';
@@ -15,23 +17,43 @@ class HolidayScreen extends StatefulWidget {
class _HolidayScreenState extends State<HolidayScreen> { class _HolidayScreenState extends State<HolidayScreen> {
int activeTab = 0; // 0 = السلف | 1 = الأجازات int activeTab = 0; // 0 = السلف | 1 = الأجازات
// Use the singleton instance
final RequestService _requestService = RequestService(); final RequestService _requestService = RequestService();
late List<LeaveRequest> _leaveRequests; late List<LeaveRequest> _leaveRequests;
late List<AdvanceRequest> _advanceRequests; late List<AdvanceRequest> _advanceRequests;
/// ⭐ Telegram-style FAB animation
final ScrollController _scrollController = ScrollController();
bool _showActions = true;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_initializeData(); _initializeData();
// ⭐ Listen to scroll and animate the floating buttons (Telegram style)
_scrollController.addListener(() {
final direction = _scrollController.position.userScrollDirection;
if (direction == ScrollDirection.reverse) {
// scrolling DOWN → hide buttons
if (_showActions) setState(() => _showActions = false);
} else if (direction == ScrollDirection.forward) {
// scrolling UP → show buttons
if (!_showActions) setState(() => _showActions = true);
}
// If user reaches top → force visible
if (_scrollController.position.pixels <= 10) {
if (!_showActions) setState(() => _showActions = true);
}
});
} }
void _initializeData() async { void _initializeData() async {
// Get initial data
_leaveRequests = await _requestService.getLeaveRequests(); _leaveRequests = await _requestService.getLeaveRequests();
_advanceRequests = await _requestService.getAdvanceRequests(); _advanceRequests = await _requestService.getAdvanceRequests();
// Listen for updates
_requestService.leaveRequestsStream.listen((requests) { _requestService.leaveRequestsStream.listen((requests) {
setState(() { setState(() {
_leaveRequests = requests; _leaveRequests = requests;
@@ -55,13 +77,12 @@ class _HolidayScreenState extends State<HolidayScreen> {
return Column( return Column(
children: [ children: [
Container( Container(
width: 36, // Smaller circle width: 36,
height: 36, height: 36,
decoration: BoxDecoration( decoration: BoxDecoration(
shape: BoxShape.circle, shape: BoxShape.circle,
color: active ? activeColor : const Color(0xFFD6D6D6), color: active ? activeColor : const Color(0xFFD6D6D6),
boxShadow: boxShadow: active
active
? [ ? [
BoxShadow( BoxShadow(
color: glowColor.withOpacity(0.6), color: glowColor.withOpacity(0.6),
@@ -71,43 +92,39 @@ class _HolidayScreenState extends State<HolidayScreen> {
] ]
: [], : [],
), ),
child: child: active && svgPath != null
active && svgPath != null
? Center( ? Center(
child: SvgPicture.asset( child: SvgPicture.asset(
svgPath, svgPath,
width: 18, // Smaller icon width: 18,
height: 18, height: 18,
color: Colors.white, color: const Color(0xFFFFFFFF),
), ),
) )
: null, : null,
), ),
const SizedBox(height: 4),
const SizedBox(height: 4), // Space between circles Text(label, style: const TextStyle(fontSize: 10)),
Text(label, style: const TextStyle(fontSize: 10)), // Smaller text
], ],
); );
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Directionality( return Directionality(
textDirection: TextDirection.rtl, textDirection: TextDirection.rtl,
child: Stack( child: Stack(
children: [ children: [
// Tabs // -------------------- TABS --------------------
Positioned( Positioned(
top: 5, top: 0,
left: 0, left: 0,
right: 0, right: 0,
bottom: 5,
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
// الأجازات TAB // الأجازات
GestureDetector( GestureDetector(
onTap: () => setState(() => activeTab = 1), onTap: () => setState(() => activeTab = 1),
child: Column( child: Column(
@@ -117,8 +134,7 @@ class _HolidayScreenState extends State<HolidayScreen> {
style: TextStyle( style: TextStyle(
fontSize: 22, fontSize: 22,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: color: activeTab == 1
activeTab == 1
? const Color(0xFF8EFDC2) ? const Color(0xFF8EFDC2)
: const Color(0x9EFFFFFF), : const Color(0x9EFFFFFF),
), ),
@@ -136,7 +152,7 @@ class _HolidayScreenState extends State<HolidayScreen> {
const SizedBox(width: 70), const SizedBox(width: 70),
// السلف TAB // السلف
GestureDetector( GestureDetector(
onTap: () => setState(() => activeTab = 0), onTap: () => setState(() => activeTab = 0),
child: Column( child: Column(
@@ -146,8 +162,7 @@ class _HolidayScreenState extends State<HolidayScreen> {
style: TextStyle( style: TextStyle(
fontSize: 22, fontSize: 22,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: color: activeTab == 0
activeTab == 0
? const Color(0xFF8EFDC2) ? const Color(0xFF8EFDC2)
: const Color(0x9EFFFFFF), : const Color(0x9EFFFFFF),
), ),
@@ -166,41 +181,52 @@ class _HolidayScreenState extends State<HolidayScreen> {
), ),
), ),
// Content area for requests // ------------- CONTENT AREA (LISTS) -------------
Positioned( Positioned(
top: 30, // Position below the tabs top: 30,
left: 0, left: 0,
right: 0, right: 0,
bottom: 0, // Leave space for action buttons bottom: 0,
child: activeTab == 1 ? _buildLeaveRequestsTab() : _buildAdvanceRequestsTab(), child: activeTab == 1
? _buildLeaveRequestsTab()
: _buildAdvanceRequestsTab(),
), ),
// Action buttons // -------------------------------------------------------------
// ⭐ TELEGRAM STYLE FLOATING ACTION BUTTONS (SLIDE + FADE)
// -------------------------------------------------------------
Positioned( Positioned(
bottom: 30, bottom: 30,
right: 20, right: 20,
child: AnimatedSlide(
offset: _showActions ? const Offset(0, 0) : const Offset(0, 1.4),
duration: const Duration(milliseconds: 350),
curve: Curves.easeOut,
child: AnimatedOpacity(
duration: const Duration(milliseconds: 250),
opacity: _showActions ? 1 : 0,
child: Column( child: Column(
children: [ children: [
// Money icon (custom size)
_HolidayActionButton( _HolidayActionButton(
label: "طلب سلفة", label: "طلب سلفة",
svgPath: "assets/images/money2.svg", svgPath: "assets/images/money2.svg",
iconWidth: 28, iconWidth: 28,
iconHeight: 20, iconHeight: 20,
onTap: () async { onTap: () async {
// Navigate to RequestAdvanceScreen
await Navigator.push( await Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: (context) => const RequestAdvanceScreen(), builder: (context) =>
const RequestAdvanceScreen(),
), ),
); );
// Data will be updated automatically through the stream
}, },
), ),
const SizedBox(height: 18), const SizedBox(height: 18),
// Plus icon (custom size)
_HolidayActionButton( _HolidayActionButton(
label: "طلب إجازة", label: "طلب إجازة",
svgPath: "assets/images/plus.svg", svgPath: "assets/images/plus.svg",
@@ -210,39 +236,40 @@ class _HolidayScreenState extends State<HolidayScreen> {
await Navigator.push( await Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: (context) => const RequestLeaveScreen(), builder: (context) =>
const RequestLeaveScreen(),
), ),
); );
// Data will be updated automatically through the stream
}, },
), ),
], ],
), ),
), ),
),
),
], ],
), ),
); );
} }
// -------------------- LIST BUILDERS --------------------
Widget _buildLeaveRequestsTab() { Widget _buildLeaveRequestsTab() {
if (_leaveRequests.isEmpty) { if (_leaveRequests.isEmpty) {
return const Center( return const Center(
child: Text( child: Text(
'لا توجد طلبات أجازة', 'لا توجد طلبات أجازة',
style: TextStyle( style: TextStyle(color: Colors.white, fontSize: 18),
color: Colors.white,
fontSize: 18,
),
), ),
); );
} }
return ListView.builder( return ListView.builder(
controller: _scrollController,
padding: const EdgeInsets.symmetric(horizontal: 25, vertical: 20), padding: const EdgeInsets.symmetric(horizontal: 25, vertical: 20),
itemCount: _leaveRequests.length, itemCount: _leaveRequests.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
final request = _leaveRequests[index]; return _buildLeaveRequestCard(_leaveRequests[index]);
return _buildLeaveRequestCard(request);
}, },
); );
} }
@@ -252,32 +279,27 @@ class _HolidayScreenState extends State<HolidayScreen> {
return const Center( return const Center(
child: Text( child: Text(
'لا توجد طلبات سلف', 'لا توجد طلبات سلف',
style: TextStyle( style: TextStyle(color: Colors.white, fontSize: 18),
color: Colors.white,
fontSize: 18,
),
), ),
); );
} }
return ListView.builder( return ListView.builder(
controller: _scrollController,
padding: const EdgeInsets.symmetric(horizontal: 25, vertical: 20), padding: const EdgeInsets.symmetric(horizontal: 25, vertical: 20),
itemCount: _advanceRequests.length, itemCount: _advanceRequests.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
final request = _advanceRequests[index]; return _buildAdvanceRequestCard(_advanceRequests[index]);
return _buildAdvanceRequestCard(request);
}, },
); );
} }
Widget _buildLeaveRequestCard(LeaveRequest request) { // -------------------- LEAVE REQUEST CARD --------------------
// Base colors from the design
const bgColor = Color(0xFFEAF8F3); Widget _buildLeaveRequestCard(LeaveRequest request) {
// const activeColor = Color(0xFFFFC940); // yellow active state const bgColor = Color(0xFFEAF8F3);
// const inactiveColor = Color(0xFFD6D6D6); // grey inactive circles const lineColor = Color(0xFF22A685);
const lineColor = Color(0xFF22A685); // green divider
// Status flags
final bool isWaiting = request.status == "waiting"; final bool isWaiting = request.status == "waiting";
final bool isApproved = request.status == "approved"; final bool isApproved = request.status == "approved";
final bool isDenied = request.status == "denied"; final bool isDenied = request.status == "denied";
@@ -288,9 +310,10 @@ class _HolidayScreenState extends State<HolidayScreen> {
return Directionality( return Directionality(
textDirection: TextDirection.rtl, textDirection: TextDirection.rtl,
child: Container( child: Container(
width: MediaQuery.of(context).size.width * 0.8, // 80% of screen width width: MediaQuery.of(context).size.width * 0.8,
margin: const EdgeInsets.only(bottom: 16), margin: const EdgeInsets.only(bottom: 16),
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 14), // Reduced padding padding:
const EdgeInsets.symmetric(horizontal: 12, vertical: 14),
decoration: BoxDecoration( decoration: BoxDecoration(
color: bgColor, color: bgColor,
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
@@ -298,57 +321,55 @@ class _HolidayScreenState extends State<HolidayScreen> {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end,
children: [ children: [
// ───────────────── STATUS ROW (centered) ───────────────── // Status circles
Row( Row(
mainAxisAlignment: MainAxisAlignment.center, // Center the status circles mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
buildStatusCircle( buildStatusCircle(
active: isWaiting, active: isWaiting,
label: "قيد الانتظار", label: "قيد الانتظار",
svgPath: isWaiting ? "assets/images/waiting.svg" : null, svgPath:
isWaiting ? "assets/images/waiting.svg" : null,
activeColor: const Color(0xFFF9C8A01B), activeColor: const Color(0xFFF9C8A01B),
glowColor: const Color(0xB4FFDC69), glowColor: const Color(0xB4FFDC69),
), ),
const SizedBox(width: 12),
const SizedBox(width: 12), // Space between circles
buildStatusCircle( buildStatusCircle(
active: isApproved, active: isApproved,
label: "موافقة", label: "موافقة",
svgPath: isApproved ? "assets/images/yes.svg" : null, svgPath:
isApproved ? "assets/images/yes.svg" : null,
activeColor: const Color(0xFF0A8A60), activeColor: const Color(0xFF0A8A60),
glowColor: const Color(0xFF00D7A3), glowColor: const Color(0xFF00D7A3),
), ),
const SizedBox(width: 12),
const SizedBox(width: 12), // Space between circles
buildStatusCircle( buildStatusCircle(
active: isDenied, active: isDenied,
label: "تم الرفض", label: "تم الرفض",
svgPath: isDenied ? "assets/images/no.svg" : null, svgPath:
isDenied ? "assets/images/no.svg" : null,
activeColor: const Color(0xFFE63946), activeColor: const Color(0xFFE63946),
glowColor: const Color(0xFFE63946), glowColor: const Color(0xFFE63946),
), ),
], ],
), ),
const SizedBox(height: 8), // Reduced height const SizedBox(height: 8),
// ───────────── DATE (LEFT) + TYPE + TREE ICON (RIGHT) ───────────── // Title + date row
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
// Right cluster: tree icon + leave type // icon + leave type
Row( Row(
children: [ children: [
// Tree SVG in rounded square
SizedBox( SizedBox(
width: 32, // Smaller icon width: 32,
height: 32, height: 32,
child: Center( child: Center(
child: SvgPicture.asset( child: SvgPicture.asset(
"assets/images/holiday.svg", "assets/images/holiday.svg",
width: 32, // Smaller icon width: 32,
height: 32, height: 32,
color: const Color(0xFF11663C), color: const Color(0xFF11663C),
), ),
@@ -358,7 +379,7 @@ class _HolidayScreenState extends State<HolidayScreen> {
Text( Text(
request.leaveType, request.leaveType,
style: const TextStyle( style: const TextStyle(
fontSize: 12, // Smaller text fontSize: 12,
color: Colors.black87, color: Colors.black87,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
@@ -366,11 +387,11 @@ class _HolidayScreenState extends State<HolidayScreen> {
], ],
), ),
// Left: date // date
Text( Text(
dateText, dateText,
style: const TextStyle( style: const TextStyle(
fontSize: 14, // Smaller text fontSize: 14,
color: Colors.black87, color: Colors.black87,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
), ),
@@ -378,40 +399,35 @@ class _HolidayScreenState extends State<HolidayScreen> {
], ],
), ),
const SizedBox(height: 10), // Reduced height const SizedBox(height: 10),
// Divider line // divider
Container(width: double.infinity, height: 1.4, color: lineColor), Container(width: double.infinity, height: 1.4, color: lineColor),
const SizedBox(height: 10), // Reduced height const SizedBox(height: 10),
// Reason label // Reason row
// ───────────── Reason Row (inline with label) ─────────────
Padding( Padding(
padding: const EdgeInsets.only(top: 8), // Reduced padding padding: const EdgeInsets.only(top: 8),
child: Row( child: Row(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
children: [ children: [
// Reason text (LEFT)
Expanded( Expanded(
child: Text( child: Text(
request.reason, request.reason,
textAlign: TextAlign.right, textAlign: TextAlign.right,
style: const TextStyle( style: const TextStyle(
fontSize: 13, // Smaller text fontSize: 13,
color: Colors.black87, color: Colors.black87,
), ),
), ),
), ),
const SizedBox(width: 6), const SizedBox(width: 6),
// Label (RIGHT)
const Text( const Text(
"السبب :", "السبب :",
textAlign: TextAlign.right, textAlign: TextAlign.right,
style: TextStyle( style: TextStyle(
fontSize: 14, // Smaller text fontSize: 14,
color: Colors.black87, color: Colors.black87,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
@@ -425,27 +441,26 @@ class _HolidayScreenState extends State<HolidayScreen> {
); );
} }
// -------------------- ADVANCE REQUEST CARD --------------------
Widget _buildAdvanceRequestCard(AdvanceRequest request) { Widget _buildAdvanceRequestCard(AdvanceRequest request) {
// Base colors
const bgColor = Color(0xFFEAF8F3); const bgColor = Color(0xFFEAF8F3);
const lineColor = Color(0xFF22A685); const lineColor = Color(0xFF22A685);
// const inactiveColor = Color(0xFFD6D6D6);
// Status flags
final bool isWaiting = request.status == "waiting"; final bool isWaiting = request.status == "waiting";
final bool isApproved = request.status == "approved"; final bool isApproved = request.status == "approved";
final bool isDenied = request.status == "denied"; final bool isDenied = request.status == "denied";
// You can format a date if needed
final String dateText = final String dateText =
"${DateTime.now().year}.${DateTime.now().month}.${DateTime.now().day}"; "${DateTime.now().year}.${DateTime.now().month}.${DateTime.now().day}";
return Directionality( return Directionality(
textDirection: TextDirection.rtl, textDirection: TextDirection.rtl,
child: Container( child: Container(
width: MediaQuery.of(context).size.width * 0.8, // 80% of screen width width: MediaQuery.of(context).size.width * 0.8,
margin: const EdgeInsets.only(bottom: 16), margin: const EdgeInsets.only(bottom: 16),
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 14), // Reduced padding padding:
const EdgeInsets.symmetric(horizontal: 10, vertical: 14),
decoration: BoxDecoration( decoration: BoxDecoration(
color: bgColor, color: bgColor,
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
@@ -453,56 +468,52 @@ class _HolidayScreenState extends State<HolidayScreen> {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end,
children: [ children: [
// ───────────────── STATUS ROW (centered) ─────────────────
Row( Row(
mainAxisAlignment: MainAxisAlignment.center, // Center the status circles mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
buildStatusCircle( buildStatusCircle(
active: isWaiting, active: isWaiting,
label: "قيد الانتظار", label: "قيد الانتظار",
svgPath: isWaiting ? "assets/images/waiting.svg" : null, svgPath:
isWaiting ? "assets/images/waiting.svg" : null,
activeColor: const Color(0xFFF9C8A01B), activeColor: const Color(0xFFF9C8A01B),
glowColor: const Color(0xB4FFDC69), glowColor: const Color(0xB4FFDC69),
), ),
const SizedBox(width: 12),
const SizedBox(width: 12), // Space between circles
buildStatusCircle( buildStatusCircle(
active: isApproved, active: isApproved,
label: "موافقة", label: "موافقة",
svgPath: isApproved ? "assets/images/yes.svg" : null, svgPath:
isApproved ? "assets/images/yes.svg" : null,
activeColor: const Color(0xFF0A8A60), activeColor: const Color(0xFF0A8A60),
glowColor: const Color(0xFF00D7A3), glowColor: const Color(0xFF00D7A3),
), ),
const SizedBox(width: 12),
const SizedBox(width: 12), // Space between circles
buildStatusCircle( buildStatusCircle(
active: isDenied, active: isDenied,
label: "تم الرفض", label: "تم الرفض",
svgPath: isDenied ? "assets/images/no.svg" : null, svgPath:
isDenied ? "assets/images/no.svg" : null,
activeColor: const Color(0xFFE63946), activeColor: const Color(0xFFE63946),
glowColor: const Color(0xFFE63946), glowColor: const Color(0xFFE63946),
), ),
], ],
), ),
const SizedBox(height: 8), // Reduced height const SizedBox(height: 8),
// ───────────────── TYPE + ICON + AMOUNT (same layout as leave card) ─────────────────
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
// Right: money icon + amount label
Row( Row(
children: [ children: [
SizedBox( SizedBox(
width: 32, // Smaller icon width: 32,
height: 32, height: 32,
child: Center( child: Center(
child: SvgPicture.asset( child: SvgPicture.asset(
"assets/images/money.svg", "assets/images/money.svg",
width: 32, // Smaller icon width: 32,
height: 32, height: 32,
color: const Color(0xFF11663C), color: const Color(0xFF11663C),
), ),
@@ -512,19 +523,17 @@ class _HolidayScreenState extends State<HolidayScreen> {
Text( Text(
"سلفة: ${request.amount.toStringAsFixed(0)} دع", "سلفة: ${request.amount.toStringAsFixed(0)} دع",
style: const TextStyle( style: const TextStyle(
fontSize: 12, // Smaller text fontSize: 12,
color: Colors.black87, color: Colors.black87,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
), ),
], ],
), ),
// Left: dummy date (or request.requestDate)
Text( Text(
dateText, dateText,
style: const TextStyle( style: const TextStyle(
fontSize: 14, // Smaller text fontSize: 14,
color: Colors.black87, color: Colors.black87,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
), ),
@@ -532,39 +541,33 @@ class _HolidayScreenState extends State<HolidayScreen> {
], ],
), ),
const SizedBox(height: 10), // Reduced height const SizedBox(height: 10),
// Divider line
Container(width: double.infinity, height: 1, color: lineColor), Container(width: double.infinity, height: 1, color: lineColor),
const SizedBox(height: 10), // Reduced height const SizedBox(height: 10),
// ───────────────── REASON ROW (identical to leave card) ─────────────────
Padding( Padding(
padding: const EdgeInsets.only(top: 8), // Reduced padding padding: const EdgeInsets.only(top: 8),
child: Row( child: Row(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
children: [ children: [
// Reason text (LEFT)
Expanded( Expanded(
child: Text( child: Text(
request.reason, request.reason,
textAlign: TextAlign.right, textAlign: TextAlign.right,
style: const TextStyle( style: const TextStyle(
fontSize: 13, // Smaller text fontSize: 13,
color: Colors.black87, color: Colors.black87,
), ),
), ),
), ),
const SizedBox(width: 6), const SizedBox(width: 6),
// Label (RIGHT)
const Text( const Text(
"السبب :", "السبب :",
textAlign: TextAlign.right, textAlign: TextAlign.right,
style: TextStyle( style: TextStyle(
fontSize: 14, // Smaller text fontSize: 14,
color: Colors.black87, color: Colors.black87,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
@@ -579,6 +582,8 @@ class _HolidayScreenState extends State<HolidayScreen> {
} }
} }
// -------------------- FLOATING ACTION BUTTON --------------------
class _HolidayActionButton extends StatelessWidget { class _HolidayActionButton extends StatelessWidget {
final String label; final String label;
final String svgPath; final String svgPath;
@@ -620,9 +625,7 @@ class _HolidayActionButton extends StatelessWidget {
height: iconHeight, height: iconHeight,
child: SvgPicture.asset(svgPath, fit: BoxFit.contain), child: SvgPicture.asset(svgPath, fit: BoxFit.contain),
), ),
const SizedBox(height: 6), const SizedBox(height: 6),
Text( Text(
label, label,
style: const TextStyle( style: const TextStyle(

View File

@@ -0,0 +1,190 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
class UserSettingsScreen extends StatelessWidget {
const UserSettingsScreen({super.key});
@override
Widget build(BuildContext context) {
return Directionality(
textDirection: TextDirection.rtl,
child: Stack(
children: [
// ⭐ You already have your app background + settings bar outside this widget
// -------------------- WHITE CARD --------------------
Positioned(
top: 140,
left: 20,
right: 20,
child: Container(
padding: const EdgeInsets.only(top: 70, bottom: 25),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: const [
BoxShadow(
color: Color(0x33000000),
blurRadius: 12,
offset: Offset(0, 5),
),
],
),
child: Column(
children: [
// -------------------- EMPLOYEE NAME --------------------
Text(
"اسم الموظف",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w700,
color: Colors.black,
fontFamily: "AbdEriady",
),
),
const SizedBox(height: 6),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"تغيير كلمة المرور",
style: TextStyle(
fontSize: 12,
color: Colors.grey[700],
),
),
const SizedBox(width: 4),
SvgPicture.asset(
"assets/images/edit.svg",
width: 16,
height: 16,
)
],
),
const SizedBox(height: 25),
// -------------------- NOTIFICATION TOGGLE --------------------
Padding(
padding: const EdgeInsets.symmetric(horizontal: 18),
child: Row(
children: [
Switch(
value: true,
activeColor: const Color(0xFF177046),
inactiveTrackColor: Colors.grey[400],
onChanged: (value) {},
),
const Spacer(),
Text(
"الإشعارات",
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
),
),
const SizedBox(width: 8),
SvgPicture.asset(
"assets/images/bell.svg",
width: 20,
height: 20,
),
],
),
),
_divider(),
// -------------------- ABOUT COMPANY --------------------
_settingsTile(
label: "عن الشركة",
iconPath: "assets/images/info.svg",
),
_divider(),
// -------------------- LOGOUT --------------------
_settingsTile(
label: "تسجيل خروج",
iconPath: "assets/images/logout.svg",
),
_divider(),
// -------------------- EMPLOYEE LEAVES --------------------
_settingsTile(
label: "إجازات الموظفين",
iconPath: "assets/images/leaves.svg",
),
],
),
),
),
// -------------------- PROFILE IMAGE --------------------
Positioned(
top: 90,
left: 0,
right: 0,
child: Center(
child: Container(
width: 120,
height: 120,
padding: const EdgeInsets.all(6),
decoration: BoxDecoration(
color: const Color(0xFF177046),
shape: BoxShape.circle,
),
child: Container(
decoration: const BoxDecoration(
shape: BoxShape.circle,
color: Color(0xFFD9D9D9), // placeholder profile
),
),
),
),
),
],
),
);
}
// Divider line styled like design
Widget _divider() {
return Container(
margin: const EdgeInsets.symmetric(vertical: 12),
height: 1,
width: double.infinity,
color: const Color(0xFFD1D1D1),
);
}
// Settings row tile
Widget _settingsTile({
required String label,
required String iconPath,
}) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 18),
child: Row(
children: [
Text(
label,
style: const TextStyle(
fontSize: 15,
fontWeight: FontWeight.w600,
),
),
const Spacer(),
SvgPicture.asset(
iconPath,
width: 20,
height: 20,
),
],
),
);
}
}

View File

@@ -1,3 +1,4 @@
import 'dart:ui';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
@@ -22,21 +23,33 @@ class Floatingnavbar extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
// Get the bottom padding to account for system navigation bar
final bottomPadding = MediaQuery.of(context).padding.bottom; final bottomPadding = MediaQuery.of(context).padding.bottom;
return Container( return ClipRRect(
borderRadius: BorderRadius.circular(45),
child: BackdropFilter(
filter: ImageFilter.blur(
sigmaX: 100,
sigmaY: 35,
),
child: Container(
height: 70, height: 70,
margin: EdgeInsets.only( margin: EdgeInsets.only(
bottom: 10 + bottomPadding, // Add system padding to our margin bottom: 10 + bottomPadding,
left: 28, left: 28,
right: 28, right: 28,
), ),
decoration: BoxDecoration(
color: (const Color(0xFFE9E9E9)),
borderRadius: BorderRadius.circular(45),
/// ⭐ Restored white container (same as your original design)
decoration: BoxDecoration(
color: const Color(0xFFE9E9E9), // White navbar restored
borderRadius: BorderRadius.circular(45),
), ),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly, mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: items.asMap().entries.map((entry) { children: items.asMap().entries.map((entry) {
@@ -51,6 +64,8 @@ class Floatingnavbar extends StatelessWidget {
); );
}).toList(), }).toList(),
), ),
),
),
); );
} }
} }
@@ -87,14 +102,16 @@ class _NavBarItemTile extends StatelessWidget {
BlendMode.srcIn, BlendMode.srcIn,
), ),
), ),
const SizedBox(height: 6), const SizedBox(height: 6),
Text( Text(
item.label, item.label,
style: TextStyle( style: TextStyle(
color: isSelected ? const Color(0xFF177046) : Colors.black, color: isSelected ? const Color(0xFF177046) : Colors.black,
fontSize: 15, fontSize: 15,
fontFamily: 'AbdEriady', // Using the custom font family fontFamily: 'AbdEriady',
fontWeight: isSelected ? FontWeight.w700 : FontWeight.w400, // Using specific weights fontWeight: isSelected ? FontWeight.w700 : FontWeight.w400,
), ),
), ),
], ],