Merge remote-tracking branch 'origin/master'

This commit is contained in:
Mohammed Al-Samarraie
2026-01-13 15:09:41 +03:00
10 changed files with 335 additions and 209 deletions

4
assets/images/edit2.svg Normal file
View File

@@ -0,0 +1,4 @@
<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M42.9098 10.8326C43.0998 11.121 43.1845 11.4662 43.1495 11.8098C43.1145 12.1534 42.962 12.4744 42.7178 12.7186L24.3318 31.1026C24.1437 31.2906 23.909 31.4252 23.6518 31.4926L15.9938 33.4926C15.7406 33.5587 15.4746 33.5573 15.2222 33.4888C14.9697 33.4202 14.7396 33.2868 14.5546 33.1018C14.3696 32.9169 14.2362 32.6867 14.1676 32.4342C14.0991 32.1818 14.0978 31.9158 14.1638 31.6626L16.1638 24.0066C16.2236 23.7774 16.3336 23.5642 16.4858 23.3826L34.9398 4.94063C35.221 4.65973 35.6023 4.50195 35.9998 4.50195C36.3973 4.50195 36.7785 4.65973 37.0598 4.94063L42.7178 10.5966C42.7877 10.6703 42.8519 10.7492 42.9098 10.8326ZM39.5358 11.6566L35.9998 8.12263L18.9638 25.1586L17.7138 29.9446L22.4998 28.6946L39.5358 11.6566Z" fill="#F7F9EC"/>
<path d="M39.282 34.3202C39.8287 29.6481 40.0032 24.9399 39.804 20.2402C39.7993 20.1294 39.8177 20.0189 39.858 19.9156C39.8983 19.8123 39.9596 19.7185 40.038 19.6402L42.006 17.6722C42.0598 17.6181 42.1281 17.5807 42.2026 17.5644C42.2771 17.5482 42.3547 17.5539 42.4261 17.5807C42.4975 17.6075 42.5596 17.6544 42.605 17.7157C42.6504 17.7769 42.6772 17.85 42.682 17.9262C43.0514 23.5086 42.9109 29.1132 42.262 34.6702C41.79 38.7142 38.542 41.8842 34.516 42.3342C27.5267 43.1077 20.4734 43.1077 13.484 42.3342C9.46003 41.8842 6.21003 38.7142 5.73803 34.6702C4.91024 27.5809 4.91024 20.4194 5.73803 13.3302C6.21003 9.28615 9.45803 6.11615 13.484 5.66615C18.7889 5.08025 24.1334 4.93776 29.462 5.24015C29.5383 5.24563 29.6114 5.27284 29.6726 5.31858C29.7339 5.36431 29.7808 5.42664 29.8077 5.49819C29.8347 5.56975 29.8405 5.64752 29.8246 5.7223C29.8087 5.79709 29.7717 5.86575 29.718 5.92015L27.732 7.90415C27.6544 7.98185 27.5616 8.04272 27.4594 8.08298C27.3572 8.12323 27.2478 8.14202 27.138 8.13815C22.6915 7.98585 18.2399 8.1563 13.818 8.64815C12.5259 8.79117 11.3197 9.3656 10.3943 10.2787C9.46894 11.1917 8.87837 12.3901 8.71803 13.6802C7.91574 20.5368 7.91574 27.4635 8.71803 34.3202C8.87837 35.6102 9.46894 36.8086 10.3943 37.7216C11.3197 38.6347 12.5259 39.2091 13.818 39.3522C20.528 40.1022 27.472 40.1022 34.184 39.3522C35.4761 39.2091 36.6823 38.6347 37.6077 37.7216C38.5331 36.8086 39.1217 35.6102 39.282 34.3202Z" fill="#F7F9EC"/>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -0,0 +1,4 @@
<svg width="97" height="97" viewBox="0 0 97 97" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8 33.0891C8.42033 24.6016 9.67729 19.3071 13.4441 15.5483C17.2029 11.7815 22.4975 10.5245 30.985 10.1042M84.7917 33.0891C84.3713 24.6016 83.1144 19.3071 79.3475 15.5483C75.5888 11.7815 70.2942 10.5245 61.8067 10.1042M61.8067 86.8959C70.2942 86.4755 75.5888 85.2186 79.3475 81.4517C83.1144 77.693 84.3713 72.3984 84.7917 63.9109M30.985 86.8959C22.4975 86.4755 17.2029 85.2186 13.4441 81.4517C9.67729 77.693 8.42033 72.3984 8 63.9109M68.625 68.7084L67.8086 65.277C67.4766 63.8846 66.7807 62.6053 65.7923 61.57C64.8038 60.5346 63.5581 59.7803 62.1826 59.3842L52.4583 56.5793V50.6502C56.0797 48.205 58.5208 43.6339 58.5208 38.3959C58.5208 30.5833 53.0888 24.25 46.3958 24.25C39.6988 24.25 34.2708 30.5833 34.2708 38.3959C34.2708 43.6339 36.708 48.205 40.3333 50.6502V56.5793L30.6697 59.4085C29.3354 59.7992 28.1243 60.5274 27.1537 61.5229C26.183 62.5183 25.4855 63.7473 25.1286 65.0911L24.1667 68.7084" stroke="black" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
<line x1="4" y1="50" x2="86" y2="50" stroke="#059C26" stroke-width="4" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1,4 @@
<svg width="97" height="97" viewBox="0 0 97 97" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8 33.0891C8.42033 24.6016 9.67729 19.3071 13.4441 15.5483C17.2029 11.7815 22.4975 10.5245 30.985 10.1042M84.7917 33.0891C84.3713 24.6016 83.1144 19.3071 79.3475 15.5483C75.5888 11.7815 70.2942 10.5245 61.8067 10.1042M61.8067 86.8959C70.2942 86.4755 75.5888 85.2186 79.3475 81.4517C83.1144 77.693 84.3713 72.3984 84.7917 63.9109M30.985 86.8959C22.4975 86.4755 17.2029 85.2186 13.4441 81.4517C9.67729 77.693 8.42033 72.3984 8 63.9109M68.625 68.7084L67.8086 65.277C67.4766 63.8846 66.7807 62.6053 65.7923 61.57C64.8038 60.5346 63.5581 59.7803 62.1826 59.3842L52.4583 56.5793V50.6502C56.0797 48.205 58.5208 43.6339 58.5208 38.3959C58.5208 30.5833 53.0888 24.25 46.3958 24.25C39.6988 24.25 34.2708 30.5833 34.2708 38.3959C34.2708 43.6339 36.708 48.205 40.3333 50.6502V56.5793L30.6697 59.4085C29.3354 59.7992 28.1243 60.5274 27.1537 61.5229C26.183 62.5183 25.4855 63.7473 25.1286 65.0911L24.1667 68.7084" stroke="black" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
<line x1="4" y1="50" x2="86" y2="50" stroke="#B10A0A" stroke-width="4" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1,18 @@
<svg width="96" height="89" viewBox="0 0 96 89" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_1218_149)">
<mask id="mask0_1218_149" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="23" y="14" width="62" height="56">
<path d="M76.4966 14.851L84.4026 20.397L50.1236 69.839H42.2176L23.1016 43.053L31.0076 35.678L46.1706 49.838L76.4966 14.851Z" fill="black"/>
</mask>
<g mask="url(#mask0_1218_149)">
<path d="M18.0923 33.3968C17.6259 33.4009 17.1668 33.2817 16.7614 33.0511C16.464 32.884 16.203 32.6592 15.9936 32.39C15.7842 32.1208 15.6305 31.8125 15.5417 31.4832C15.4528 31.1539 15.4306 30.8101 15.4761 30.4721C15.5217 30.1341 15.6343 29.8085 15.8072 29.5145C19.1398 23.9522 29.2793 10.9693 51.4043 10.9693C60.9923 10.9693 69.4016 13.4877 76.3865 18.452C82.1355 22.5262 85.3575 27.1378 86.8924 29.359C87.0871 29.6389 87.2238 29.955 87.2945 30.2886C87.3651 30.6222 87.3684 30.9666 87.3039 31.3015C87.2395 31.6363 87.1087 31.9549 86.9193 32.2385C86.7299 32.522 86.4857 32.7648 86.201 32.9526C85.6192 33.3371 84.9106 33.48 84.2252 33.351C83.5398 33.2219 82.9317 32.831 82.5296 32.2612C79.7519 28.2666 71.2822 16.1116 51.4043 16.1116C32.0017 16.1116 23.2295 27.2969 20.3722 32.0935C20.1427 32.494 19.8103 32.826 19.4095 33.0551C19.0087 33.2843 18.554 33.4022 18.0923 33.3968Z" fill="white"/>
<path d="M62.5512 84.2151C62.3306 84.2178 62.1105 84.1928 61.8961 84.1408C45.8469 80.1652 39.8541 64.1211 39.6104 63.4539L39.5723 63.307C39.441 62.8438 36.2207 51.8417 41.1643 45.3978C43.4304 42.4594 46.877 40.9521 51.4282 40.9521C55.6596 40.9521 58.7122 42.2675 60.8106 44.9899C62.5391 47.2128 63.2305 49.9542 63.8995 52.5954C65.3048 58.0955 66.3194 60.9839 72.16 61.2812C74.7252 61.4108 76.4105 59.9105 77.3663 58.6331C79.9505 55.1501 80.3999 49.472 78.4518 44.4593C75.949 37.9894 67.0661 25.7913 51.404 25.7913C44.7181 25.7913 38.575 27.9398 33.6487 31.9776C29.5711 35.3223 26.3406 40.0446 24.7849 44.8983C21.9 53.935 25.6837 68.1399 25.72 68.2696C25.8084 68.6002 25.8296 68.9451 25.7825 69.2841C25.7354 69.623 25.621 69.9491 25.4459 70.2431C25.2707 70.5371 25.0385 70.7931 24.7629 70.9959C24.4873 71.1987 24.1739 71.3443 23.8411 71.4241C23.1688 71.6029 22.4533 71.5112 21.8478 71.1687C21.2423 70.8262 20.795 70.2602 20.6019 69.5919C20.429 68.9437 16.3878 53.7932 19.7203 43.3495C23.3502 32.033 34.5527 20.6248 51.4092 20.6248C59.1996 20.6248 66.5597 23.2728 72.7028 28.2734C77.4597 32.1626 81.3454 37.3862 83.3781 42.608C85.9622 49.2749 85.2691 56.7576 81.6168 61.6459C79.183 64.9059 75.7173 66.6102 71.8783 66.4252C61.8771 65.924 60.0794 58.9425 58.7692 53.8503C57.421 48.6267 56.5585 46.1083 51.4092 46.1083C48.5814 46.1083 46.5953 46.8861 45.3594 48.4971C43.6741 50.7009 43.5427 54.1459 43.7294 56.6453C43.8519 58.3867 44.1472 60.1116 44.611 61.7945C45.0223 62.8317 50.379 75.9684 63.2081 79.1471C63.5397 79.2257 63.8523 79.3693 64.1279 79.5698C64.4035 79.7702 64.6365 80.0234 64.8134 80.3146C64.9903 80.6059 65.1076 80.9294 65.1584 81.2663C65.2092 81.6033 65.1926 81.947 65.1094 82.2775C64.9529 82.8353 64.6181 83.3267 64.1562 83.6765C63.6943 84.0264 63.1307 84.2155 62.5512 84.2151Z" fill="white"/>
<path d="M41.9507 83.0294C41.591 83.0301 41.2348 82.9584 40.9034 82.8186C40.572 82.6787 40.2721 82.4735 40.0217 82.2152C33.5985 75.474 29.9652 67.936 28.5979 58.5104V58.4603C27.8305 52.2203 28.954 43.3859 34.4593 37.3119C38.5231 32.8298 44.2358 30.5516 51.4092 30.5516C59.8927 30.5516 66.5596 34.4961 70.7167 41.9408C73.7329 47.3494 74.331 52.7389 74.3466 52.9601C74.3782 53.3012 74.3422 53.6453 74.2407 53.9725C74.1392 54.2997 73.9741 54.6036 73.7549 54.867C73.5358 55.1303 73.2668 55.3478 72.9635 55.507C72.6601 55.6662 72.3283 55.7641 71.9871 55.7949C71.2987 55.8696 70.6085 55.6706 70.0655 55.2408C69.5225 54.811 69.1703 54.1849 69.085 53.4977C68.6297 50.2639 67.5832 47.1415 65.9978 44.2864C62.7759 38.6013 57.8738 35.7113 51.3902 35.7113C45.7898 35.7113 41.408 37.3966 38.3934 40.724C34.048 45.5206 33.2079 52.91 33.8042 57.7982C35.0021 66.1331 38.205 72.7637 43.8607 78.6891C44.0968 78.9346 44.2811 79.2252 44.4026 79.5434C44.5241 79.8616 44.5804 80.201 44.5682 80.5414C44.5559 80.8818 44.4753 81.2162 44.3313 81.5249C44.1872 81.8335 43.9825 82.11 43.7294 82.338C43.242 82.7798 42.6086 83.026 41.9507 83.0294Z" fill="white"/>
<path d="M71.5411 75.6037C65.9234 75.6037 61.1476 74.048 57.3258 70.9557C49.6477 64.7693 48.7869 54.6938 48.7489 54.2686C48.6948 53.5707 48.9202 52.8798 49.3755 52.348C49.8308 51.8162 50.4787 51.4871 51.1766 51.433C51.8746 51.3789 52.5654 51.6043 53.0972 52.0596C53.629 52.5148 53.9581 53.1627 54.0122 53.8607C54.0313 54.0093 54.7987 62.2509 60.7172 66.9974C64.2191 69.7941 68.8999 70.9038 74.668 70.2557C75.3574 70.172 76.0518 70.3647 76.5995 70.7916C77.1473 71.2185 77.5037 71.8449 77.5909 72.5338C77.6287 72.8742 77.5983 73.2186 77.5015 73.5471C77.4047 73.8755 77.2435 74.1814 77.0273 74.4469C76.811 74.7124 76.5441 74.9321 76.242 75.0933C75.9399 75.2546 75.6087 75.354 75.2678 75.3859C74.0308 75.5302 72.7865 75.6029 71.5411 75.6037ZM75.9799 6.9142C73.7882 5.48818 66.0168 1.2464 51.4039 1.2464C36.0651 1.2464 28.2746 5.9324 26.5513 7.12335C26.4375 7.19322 26.331 7.27429 26.2333 7.36534C26.223 7.37532 26.2095 7.38142 26.1952 7.38263C25.9201 7.6229 25.6992 7.91908 25.5475 8.25141C25.3958 8.58374 25.3167 8.9446 25.3154 9.30992C25.3202 9.65238 25.3924 9.99053 25.5281 10.305C25.6637 10.6195 25.8601 10.9041 26.1059 11.1425C26.3517 11.381 26.6422 11.5686 26.9607 11.6946C27.2792 11.8206 27.6194 11.8825 27.9618 11.8768C28.5106 11.8764 29.0463 11.7081 29.4967 11.3945C29.571 11.3392 36.2759 6.41293 51.4091 6.41293C66.5423 6.41293 73.2835 11.3219 73.3561 11.3582C73.8163 11.6995 74.3751 11.8815 74.948 11.8768C75.2907 11.882 75.6311 11.8195 75.9496 11.6929C76.2682 11.5663 76.5585 11.378 76.8041 11.1389C77.0496 10.8997 77.2456 10.6145 77.3806 10.2994C77.5156 9.98436 77.5871 9.64575 77.5909 9.30301C77.5911 8.78962 77.4378 8.2879 77.1507 7.86225C76.8637 7.43661 76.456 7.10646 75.9799 6.9142Z" fill="white"/>
</g>
</g>
<defs>
<clipPath id="clip0_1218_149">
<rect width="96" height="89" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 5.9 KiB

View File

@@ -0,0 +1,3 @@
<svg width="96" height="89" viewBox="0 0 96 89" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M70.395 17L78.301 22.546L44.022 71.988H36.116L17 45.202L24.906 37.827L40.069 51.987L70.395 17Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 223 B

BIN
assets/images/tickmark3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -7,66 +7,75 @@ class AboutScreen extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return SafeArea( return Scaffold(
child: Scaffold( body: AppBackground(
body: AppBackground( child: SafeArea(
child: Column( child: SingleChildScrollView(
children: [ child: Column(
/// -------------------- SETTINGS BAR -------------------- children: [
SettingsBar( /// -------------------- SETTINGS BAR --------------------
selectedIndex: 0, SettingsBar(
onTap: (_) {}, selectedIndex: 0,
showBackButton: true, onTap: (_) {},
onBackTap: () => Navigator.pop(context), showBackButton: true,
iconPaths: const [], onBackTap: () => Navigator.pop(context),
), iconPaths: const [],
),
const SizedBox(height: 12), const SizedBox(height: 12),
/// -------------------- CENTER CONTENT -------------------- /// -------------------- CENTER CONTENT --------------------
/// ///
Expanded( Center(
child: Center( child: Padding(
child: Align( padding: const EdgeInsets.symmetric(
alignment: Alignment.topCenter, horizontal: 24.0,
child: Directionality( vertical: 10,
textDirection: TextDirection.rtl, ),
child: Column( child: Align(
mainAxisSize: MainAxisSize.min, alignment: Alignment.topCenter,
children: [ child: Directionality(
const Text( textDirection: TextDirection.rtl,
"عن الشركة", child: Column(
style: TextStyle( mainAxisSize: MainAxisSize.min,
fontSize: 26, children: [
fontWeight: FontWeight.bold, const Text(
color: Colors.white, "عن الشركة",
style: TextStyle(
fontSize: 26,
fontWeight: FontWeight.bold,
color: Colors.white,
),
), ),
),
const SizedBox(height: 12), const SizedBox(height: 12),
Container( Container(
width: 200, width: 200,
height: 1, height: 1,
color: Color(0x8732C599), color: const Color(0x8732C599),
),
const SizedBox(height: 14),
const Text(
"نص",
style: TextStyle(
fontSize: 18,
color: Colors.white70,
), ),
),
], const SizedBox(height: 14),
const Text(
"شركة كودا ذ.م.م هي شركة عراقية رائدة تقدم حلولاً متميزة في البرمجيات المخصصة والتطبيقات وإدارة الخوادم والمواقع، ومنظومات الاتصال وخدمات الأمن السيبراني. تأسست عام 2008 ولديها عقود واتفاقيات عديدة مع مؤسسات حكومية عراقية والقطاع الخاص.\n\nوسعت الشركة شراكاتها مع وكالات عالمية مثل CODACS الأمريكية و Laipac الكندية و Teltonika اللتوانية وWolf Team الصينية وLibelium الإسبانية وOdoo العالمية وغيرها. مما أتاح لها تقديم أحدث التقنيات والمنتجات المبتكرة لعملائها.\n\nتوفر كودا حلولاً برمجية مخصصة للمؤسسات الكبيرة والدوائر الحكومية، مما يسهم في تبسيط الإجراءات وتقديم الخدمات للمواطنين بشكل إلكتروني وفعال.\n\nكما تقدم كودا مجموعة واسعة من المنتجات والخدمات الحديثة، بما في ذلك الشاشات الإعلانية، والبوابات الذكية، والمواقف الذكية، والأقفال، والمباني الذكية، وأجهزة الكشك (الخدمة الإلكترونية الذاتية)، وأجهزة محمولة تخصصية، وحساسات، وأجهزة نداء واستغاثة.\n\nبفضل هذه المنتجات والخدمات المبتكرة، تعزز كودا مكانتها الرائدة في السوق المحلي والإقليمي، وتساهم في تطوير التكنولوجيا وتعزيز جودة الحياة في العراق .",
style: TextStyle(
fontSize: 18,
color: Colors.white70,
height:
1.5, // Added line height for better readability
),
),
const SizedBox(height: 20), // Bottom padding
],
),
), ),
), ),
), ),
), ),
), ],
], ),
), ),
), ),
), ),

View File

@@ -3,7 +3,6 @@ import 'package:coda_project/screens/notifications_screen.dart';
import 'package:coda_project/screens/user_settings_screen.dart'; import 'package:coda_project/screens/user_settings_screen.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import '../widgets/login_animation.dart';
import '../widgets/settings_bar.dart'; import '../widgets/settings_bar.dart';
class AttendanceScreen extends StatelessWidget { class AttendanceScreen extends StatelessWidget {
@@ -17,45 +16,43 @@ class AttendanceScreen extends StatelessWidget {
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
child: Stack( child: Stack(
children: [ children: [
SizedBox(height: MediaQuery.of(context).size.height SizedBox(height: MediaQuery.of(context).size.height),
),
/// ------------------------------ /// ------------------------------
/// SETTINGS BAR (STATIC) /// SETTINGS BAR (STATIC)
/// ------------------------------ /// ------------------------------
SafeArea( SafeArea(
child:SettingsBar( child: SettingsBar(
selectedIndex: 0, selectedIndex: 0,
showBackButton: false, showBackButton: false,
iconPaths: [ iconPaths: ['assets/images/user.svg', 'assets/images/ball.svg'],
'assets/images/user.svg', onTap: (index) {
'assets/images/ball.svg', if (index == 0) {
], Navigator.push(
onTap: (index) { context,
if (index == 0) { MaterialPageRoute(
Navigator.push( builder: (context) => UserSettingsScreen(),
context, ),
MaterialPageRoute( );
builder: (context) => UserSettingsScreen(), } else if (index == 1) {
), Navigator.push(
); context,
} else if (index == 1) { MaterialPageRoute(
Navigator.push( builder: (context) => NotificationsScreen(),
context, ),
MaterialPageRoute( );
builder: (context) => NotificationsScreen(), }
), },
); ),
}
},
),
), ),
/// ------------------------------ /// ------------------------------
/// GREETING TEXT /// GREETING TEXT
/// ------------------------------ /// ------------------------------
Positioned( Positioned(
top: screenHeight * 0.14, // moved down because settings bar now exists top:
screenHeight *
0.14, // moved down because settings bar now exists
left: 0, left: 0,
right: 0, right: 0,
child: Center( child: Center(
@@ -65,9 +62,7 @@ class AttendanceScreen extends StatelessWidget {
fontSize: 24, fontSize: 24,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: Colors.white, color: Colors.white,
shadows: [ shadows: [Shadow(color: Color(0x42000000), blurRadius: 6)],
Shadow(color: Color(0x42000000), blurRadius: 6),
],
), ),
), ),
), ),
@@ -77,7 +72,9 @@ class AttendanceScreen extends StatelessWidget {
/// MAIN CARD AREA /// MAIN CARD AREA
/// ------------------------------ /// ------------------------------
Positioned( Positioned(
top: screenHeight * 0.2, // pushed down because of settings bar + greeting top:
screenHeight *
0.2, // pushed down because of settings bar + greeting
left: 0, left: 0,
right: 0, right: 0,
child: Center( child: Center(
@@ -110,7 +107,7 @@ class AttendanceScreen extends StatelessWidget {
), ),
), ),
Container( Container(
height: screenHeight * 0.5, height: screenHeight * 0.5,
width: screenWidth * 0.7, width: screenWidth * 0.7,
decoration: BoxDecoration( decoration: BoxDecoration(
color: Color(0x92757575), color: Color(0x92757575),
@@ -139,13 +136,12 @@ class AttendanceScreen extends StatelessWidget {
), ),
], ],
child: _FingerButton( child: _FingerButton(
icon: "assets/images/login.svg", icon: "assets/images/faceLogin.svg",
label: "تسجيل الدخول", label: "تسجيل الدخول",
onTap: () { onTap: () {
Navigator.of(context).push( Navigator.of(context).push(
MaterialPageRoute( MaterialPageRoute(
builder: (_) => OvalCameraCapturePage( builder: (_) => OvalCameraCapturePage(isLogin: true),
),
), ),
); );
}, },
@@ -180,15 +176,12 @@ class AttendanceScreen extends StatelessWidget {
), ),
], ],
child: _FingerButton( child: _FingerButton(
icon: "assets/images/logout.svg", icon: "assets/images/faceLogout.svg",
label: "تسجيل خروج", label: "تسجيل خروج",
onTap: () { onTap: () {
Navigator.of(context).push( Navigator.of(context).push(
MaterialPageRoute( MaterialPageRoute(
builder: (_) => LoginAnimationScreen( builder: (_) => OvalCameraCapturePage(isLogin: false),
isLogin: false,
isSuccess: true,
),
), ),
); );
}, },
@@ -258,7 +251,7 @@ class _FingerButton extends StatelessWidget {
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
SvgPicture.asset(icon, width: 62, height: 62), SvgPicture.asset(icon, width: 75, height: 75),
SizedBox(height: 10), SizedBox(height: 10),
Text( Text(
label, label,

View File

@@ -1,8 +1,11 @@
import 'package:camera/camera.dart'; import 'package:camera/camera.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'dart:async';
class OvalCameraCapturePage extends StatefulWidget { class OvalCameraCapturePage extends StatefulWidget {
const OvalCameraCapturePage({super.key}); final bool isLogin;
const OvalCameraCapturePage({super.key, this.isLogin = true});
@override @override
State<OvalCameraCapturePage> createState() => _OvalCameraCapturePageState(); State<OvalCameraCapturePage> createState() => _OvalCameraCapturePageState();
@@ -12,6 +15,8 @@ class _OvalCameraCapturePageState extends State<OvalCameraCapturePage> {
CameraController? _cameraController; CameraController? _cameraController;
bool _isCameraInitialized = false; bool _isCameraInitialized = false;
String? _errorMessage; String? _errorMessage;
bool _isSuccess = false;
Timer? _timer;
@override @override
void initState() { void initState() {
@@ -27,7 +32,7 @@ class _OvalCameraCapturePageState extends State<OvalCameraCapturePage> {
// Get available cameras // Get available cameras
final cameras = await availableCameras(); final cameras = await availableCameras();
// Check if cameras list is available // Check if cameras list is available
if (cameras.isEmpty) { if (cameras.isEmpty) {
setState(() { setState(() {
@@ -64,16 +69,31 @@ class _OvalCameraCapturePageState extends State<OvalCameraCapturePage> {
); );
await _cameraController!.initialize(); await _cameraController!.initialize();
if (!mounted) return; if (!mounted) return;
setState(() { setState(() {
_isCameraInitialized = true; _isCameraInitialized = true;
_errorMessage = null; _errorMessage = null;
}); });
_timer = Timer(const Duration(seconds: 3), () {
if (mounted) {
setState(() {
_isSuccess = true;
});
// Auto-close after 2 seconds
Future.delayed(const Duration(seconds: 2), () {
if (mounted) {
Navigator.of(context).pop();
}
});
}
});
} catch (e) { } catch (e) {
if (!mounted) return; if (!mounted) return;
setState(() { setState(() {
_errorMessage = "خطأ في تهيئة الكاميرا: $e"; _errorMessage = "خطأ في تهيئة الكاميرا: $e";
_isCameraInitialized = false; _isCameraInitialized = false;
@@ -82,11 +102,10 @@ class _OvalCameraCapturePageState extends State<OvalCameraCapturePage> {
} }
} }
@override @override
void dispose() { void dispose() {
_cameraController?.dispose(); _cameraController?.dispose();
_timer?.cancel();
super.dispose(); super.dispose();
} }
@@ -95,88 +114,151 @@ class _OvalCameraCapturePageState extends State<OvalCameraCapturePage> {
return Scaffold( return Scaffold(
backgroundColor: Color(0xff000000), backgroundColor: Color(0xff000000),
body: _errorMessage != null body:
? Center( _errorMessage != null
child: Padding( ? Center(
padding: const EdgeInsets.all(20.0), child: Padding(
child: Column( padding: const EdgeInsets.all(20.0),
mainAxisAlignment: MainAxisAlignment.center, child: Column(
children: [ mainAxisAlignment: MainAxisAlignment.center,
Icon( children: [
Icons.camera_alt_outlined, Icon(
size: 64, Icons.camera_alt_outlined,
color: Colors.white70, size: 64,
), color: Colors.white70,
SizedBox(height: 16),
Text(
_errorMessage!,
style: TextStyle(
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.bold,
), ),
textAlign: TextAlign.center, SizedBox(height: 16),
), Text(
SizedBox(height: 24), _errorMessage!,
ElevatedButton( style: TextStyle(
onPressed: _initializeCamera, color: Colors.white,
style: ElevatedButton.styleFrom( fontSize: 18,
backgroundColor: Color(0xffE8001A), fontWeight: FontWeight.bold,
foregroundColor: Colors.white, ),
padding: EdgeInsets.symmetric(horizontal: 32, vertical: 12), textAlign: TextAlign.center,
), ),
child: Text("إعادة المحاولة"), SizedBox(height: 24),
), ElevatedButton(
], onPressed: _initializeCamera,
style: ElevatedButton.styleFrom(
backgroundColor: Color(0xffE8001A),
foregroundColor: Colors.white,
padding: EdgeInsets.symmetric(
horizontal: 32,
vertical: 12,
),
),
child: Text("إعادة المحاولة"),
),
],
),
), ),
), )
) : _isCameraInitialized && _cameraController != null
: _isCameraInitialized && _cameraController != null
? Stack( ? Stack(
children: [ children: [
SizedBox(height: MediaQuery.of(context).size.height ), SizedBox(height: MediaQuery.of(context).size.height),
// Camera Preview
Positioned( // Camera Preview
child: Center(child: CameraPreview(_cameraController!)), Positioned(
), child: Center(child: CameraPreview(_cameraController!)),
// Oval overlay with dimmed background ),
Positioned.fill( // Oval overlay with dimmed background
child: CustomPaint( Positioned.fill(
painter: _OvalOverlayPainter(), child: CustomPaint(painter: _OvalOverlayPainter()),
),
// Top Text
Positioned(
top: 100,
left: 0,
right: 0,
child: Center(
child: Text(
widget.isLogin ? "تسجيل الدخول" : "تسجيل خروج",
style: TextStyle(
color: Colors.white,
fontSize: 24,
fontWeight: FontWeight.bold,
fontFamily:
'Cairo', // Assuming Cairo font based on Arabic text
),
), ),
), ),
),
// // Capture button // Bottom Text and Logo
// Positioned( Positioned(
// bottom: 60, bottom: 80,
// left: 0, left: 0,
// right: 0, right: 0,
// child: Center( child: Column(
// child: GestureDetector( mainAxisSize: MainAxisSize.min,
// onTap: (){}, children: [
// child: Container( Text(
// width: 72, _isSuccess
// height: 72, ? (widget.isLogin
// decoration: BoxDecoration( ? "تم تسجيل دخولك بنجاح"
// shape: BoxShape.circle, : "تم تسجيل خروجك بنجاح")
// color: Colors.white, : (widget.isLogin
// boxShadow: [ ? "يتم تسجيل الدخول ..."
// BoxShadow( : "يتم تسجيل الخروج ..."),
// color: Colors.black26, style: const TextStyle(
// blurRadius: 8, color: Colors.white,
// offset: Offset(0, 4), fontSize: 18,
// ), fontWeight: FontWeight.bold,
// ], ),
// ), ),
// child: Icon(Icons.camera_alt, color: Color(0xffE8001A), size: 36), const SizedBox(height: 20),
// ), // Logo
// ), SizedBox(
// ), height: _isSuccess ? 80 : 60,
// ), width: _isSuccess ? 80 : 60,
], child: SvgPicture.asset(
) _isSuccess
: Center(child: CircularProgressIndicator(color: Color(0xffE8001A))), ? 'assets/images/logSuccess.svg'
: 'assets/images/logLoading.svg',
// ignore: deprecated_member_use
color: Colors.white,
fit: BoxFit.contain,
),
),
],
),
),
// // Capture button
// Positioned(
// bottom: 60,
// left: 0,
// right: 0,
// child: Center(
// child: GestureDetector(
// onTap: (){},
// child: Container(
// width: 72,
// height: 72,
// decoration: BoxDecoration(
// shape: BoxShape.circle,
// color: Colors.white,
// boxShadow: [
// BoxShadow(
// color: Colors.black26,
// blurRadius: 8,
// offset: Offset(0, 4),
// ),
// ],
// ),
// child: Icon(Icons.camera_alt, color: Color(0xffE8001A), size: 36),
// ),
// ),
// ),
// ),
],
)
: Center(
child: CircularProgressIndicator(color: Color(0xffE8001A)),
),
); );
} }
} }
@@ -194,11 +276,16 @@ class _OvalOverlayPainter extends CustomPainter {
); );
// Create a path for the whole screen // Create a path for the whole screen
final screenPath = Path()..addRect(Rect.fromLTWH(0, 0, size.width, size.height)); final screenPath =
Path()..addRect(Rect.fromLTWH(0, 0, size.width, size.height));
// Create a path for the oval // Create a path for the oval
final ovalPath = Path()..addOval(ovalRect); final ovalPath = Path()..addOval(ovalRect);
// Subtract the oval from the screen path // Subtract the oval from the screen path
final overlayPath = Path.combine(PathOperation.difference, screenPath, ovalPath); final overlayPath = Path.combine(
PathOperation.difference,
screenPath,
ovalPath,
);
// Draw the dimmed area outside the oval with gradient // Draw the dimmed area outside the oval with gradient
final gradient = LinearGradient( final gradient = LinearGradient(
@@ -209,11 +296,12 @@ class _OvalOverlayPainter extends CustomPainter {
Color.fromARGB(255, 0, 20, 15), // bottom deep green Color.fromARGB(255, 0, 20, 15), // bottom deep green
], ],
); );
final paint = Paint() final paint =
..shader = gradient.createShader( Paint()
Rect.fromLTWH(0, 0, size.width, size.height), ..shader = gradient.createShader(
) Rect.fromLTWH(0, 0, size.width, size.height),
..style = PaintingStyle.fill; )
..style = PaintingStyle.fill;
canvas.drawPath(overlayPath, paint); canvas.drawPath(overlayPath, paint);
// Draw glowing circles effect (like AppBackground) - drawn after overlay // Draw glowing circles effect (like AppBackground) - drawn after overlay
@@ -222,9 +310,10 @@ class _OvalOverlayPainter extends CustomPainter {
final topCircleRadius = 150.0; final topCircleRadius = 150.0;
// Draw multiple circles with different opacities for spread effect (spreadRadius: 160) // Draw multiple circles with different opacities for spread effect (spreadRadius: 160)
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
final spreadPaint = Paint() final spreadPaint =
..color = Color.fromARGB(69 ~/ (i + 1), 62, 254, 190) Paint()
..maskFilter = MaskFilter.blur(BlurStyle.normal, 140 - (i * 20)); ..color = Color.fromARGB(69 ~/ (i + 1), 62, 254, 190)
..maskFilter = MaskFilter.blur(BlurStyle.normal, 140 - (i * 20));
canvas.drawCircle( canvas.drawCircle(
topCircleCenter, topCircleCenter,
topCircleRadius + (i * 30), topCircleRadius + (i * 30),
@@ -237,9 +326,10 @@ class _OvalOverlayPainter extends CustomPainter {
final bottomCircleRadius = 160.0; final bottomCircleRadius = 160.0;
// Draw multiple circles with different opacities for spread effect (spreadRadius: 60) // Draw multiple circles with different opacities for spread effect (spreadRadius: 60)
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
final spreadPaint = Paint() final spreadPaint =
..color = Color.fromARGB(83 ~/ (i + 1), 62, 254, 190) Paint()
..maskFilter = MaskFilter.blur(BlurStyle.normal, 180 - (i * 25)); ..color = Color.fromARGB(83 ~/ (i + 1), 62, 254, 190)
..maskFilter = MaskFilter.blur(BlurStyle.normal, 180 - (i * 25));
canvas.drawCircle( canvas.drawCircle(
bottomCircleCenter, bottomCircleCenter,
bottomCircleRadius + (i * 40), bottomCircleRadius + (i * 40),
@@ -248,13 +338,14 @@ class _OvalOverlayPainter extends CustomPainter {
} }
// Draw oval border // Draw oval border
final borderPaint = Paint() final borderPaint =
..color = Colors.greenAccent Paint()
..style = PaintingStyle.stroke ..color = Colors.greenAccent
..strokeWidth = 4; ..style = PaintingStyle.stroke
..strokeWidth = 4;
canvas.drawOval(ovalRect, borderPaint); canvas.drawOval(ovalRect, borderPaint);
} }
@override @override
bool shouldRepaint(covariant CustomPainter oldDelegate) => false; bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
} }

View File

@@ -29,7 +29,7 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: async name: async
sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.13.0" version: "2.13.0"
@@ -85,10 +85,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: camera_web name: camera_web
sha256: "57f49a635c8bf249d07fb95eb693d7e4dda6796dedb3777f9127fb54847beba7" sha256: "595f28c89d1fb62d77c73c633193755b781c6d2e0ebcd8dc25b763b514e6ba8f"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.3.5+3" version: "0.3.5"
characters: characters:
dependency: transitive dependency: transitive
description: description:
@@ -133,10 +133,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: cross_file name: cross_file
sha256: "701dcfc06da0882883a2657c445103380e53e647060ad8d9dfb710c100996608" sha256: "942a4791cd385a68ccb3b32c71c427aba508a1bb949b86dff2adbe4049f16239"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.3.5+1" version: "0.3.5"
crypto: crypto:
dependency: transitive dependency: transitive
description: description:
@@ -189,10 +189,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: fake_async name: fake_async
sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.3" version: "1.3.2"
ffi: ffi:
dependency: transitive dependency: transitive
description: description:
@@ -289,7 +289,7 @@ packages:
source: hosted source: hosted
version: "0.15.6" version: "0.15.6"
http: http:
dependency: transitive dependency: "direct main"
description: description:
name: http name: http
sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412" sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412"
@@ -324,10 +324,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: leak_tracker name: leak_tracker
sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0" sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "10.0.9" version: "10.0.8"
leak_tracker_flutter_testing: leak_tracker_flutter_testing:
dependency: transitive dependency: transitive
description: description:
@@ -641,10 +641,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: vm_service name: vm_service
sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02 sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "15.0.0" version: "14.3.1"
web: web:
dependency: transitive dependency: transitive
description: description:
@@ -678,5 +678,5 @@ packages:
source: hosted source: hosted
version: "3.1.3" version: "3.1.3"
sdks: sdks:
dart: ">=3.8.0 <4.0.0" dart: ">=3.7.0 <4.0.0"
flutter: ">=3.32.0" flutter: ">=3.29.0"