diff --git a/android/app/src/main/res/drawable/launcher.png b/android/app/src/main/res/drawable/launcher.png new file mode 100644 index 0000000..f727140 Binary files /dev/null and b/android/app/src/main/res/drawable/launcher.png differ diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png index db77bb4..8908da6 100644 Binary files a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png index 17987b7..a739172 100644 Binary files a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png index 09d4391..e93b8f8 100644 Binary files a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png index d5f1c8d..853af75 100644 Binary files a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png index 4d6372e..f727140 100644 Binary files a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/assets/images/empty_todo.svg b/assets/images/empty_todo.svg new file mode 100644 index 0000000..e6a1900 --- /dev/null +++ b/assets/images/empty_todo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 4d4b1db..91ae0ca 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -688,6 +688,11 @@ PODS: - leveldb-library (~> 1.22) - nanopb (< 2.30910.0, >= 2.30908.0) - Flutter (1.0.0) + - flutter_local_notifications (0.0.1): + - Flutter + - fluttertoast (0.0.2): + - Flutter + - Toast - google_sign_in_ios (0.0.1): - Flutter - GoogleSignIn (~> 6.2) @@ -786,12 +791,15 @@ PODS: - shared_preferences_foundation (0.0.1): - Flutter - FlutterMacOS + - Toast (4.0.0) DEPENDENCIES: - cloud_firestore (from `.symlinks/plugins/cloud_firestore/ios`) - firebase_auth (from `.symlinks/plugins/firebase_auth/ios`) - firebase_core (from `.symlinks/plugins/firebase_core/ios`) - Flutter (from `Flutter`) + - flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`) + - fluttertoast (from `.symlinks/plugins/fluttertoast/ios`) - google_sign_in_ios (from `.symlinks/plugins/google_sign_in_ios/ios`) - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) @@ -816,6 +824,7 @@ SPEC REPOS: - nanopb - PromisesObjC - RecaptchaInterop + - Toast EXTERNAL SOURCES: cloud_firestore: @@ -826,6 +835,10 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/firebase_core/ios" Flutter: :path: Flutter + flutter_local_notifications: + :path: ".symlinks/plugins/flutter_local_notifications/ios" + fluttertoast: + :path: ".symlinks/plugins/fluttertoast/ios" google_sign_in_ios: :path: ".symlinks/plugins/google_sign_in_ios/ios" shared_preferences_foundation: @@ -845,6 +858,8 @@ SPEC CHECKSUMS: FirebaseCoreInternal: 2cf9202e226e3f78d2bf6d56c472686b935bfb7f FirebaseFirestore: 17bd5c8a0ea4be0fcae5a6f95f817983623adb4a Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 + flutter_local_notifications: 0c0b1ae97e741e1521e4c1629a459d04b9aec743 + fluttertoast: 31b00dabfa7fb7bacd9e7dbee580d7a2ff4bf265 google_sign_in_ios: 1256ff9d941db546373826966720b0c24804bcdd GoogleSignIn: 5651ce3a61e56ca864160e79b484cd9ed3f49b7a GoogleUtilities: 202e7a9f5128accd11160fb9c19612de1911aa19 @@ -857,6 +872,7 @@ SPEC CHECKSUMS: PromisesObjC: c50d2056b5253dadbd6c2bea79b0674bd5a52fa4 RecaptchaInterop: 7d1a4a01a6b2cb1610a47ef3f85f0c411434cb21 shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126 + Toast: 91b396c56ee72a5790816f40d3a94dd357abc196 PODFILE CHECKSUM: 6b9eb94e9f98a329f2ef624b852a6e42d090af2b diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/100.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/100.png new file mode 100644 index 0000000..d45ed9e Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/100.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/102.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/102.png new file mode 100644 index 0000000..cf410c5 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/102.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/1024.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/1024.png new file mode 100644 index 0000000..4362eef Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/1024.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/114.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/114.png new file mode 100644 index 0000000..f1b0db2 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/114.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/120.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/120.png new file mode 100644 index 0000000..b4fc8e1 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/120.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/128.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/128.png new file mode 100644 index 0000000..5fdf4fa Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/128.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/144.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/144.png new file mode 100644 index 0000000..52ec69e Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/144.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/152.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/152.png new file mode 100644 index 0000000..bc363c1 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/152.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/16.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/16.png new file mode 100644 index 0000000..af85b41 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/16.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/167.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/167.png new file mode 100644 index 0000000..bbf7a74 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/167.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/172.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/172.png new file mode 100644 index 0000000..5aabe03 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/172.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/180.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/180.png new file mode 100644 index 0000000..03c1791 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/180.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/196.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/196.png new file mode 100644 index 0000000..d033ec2 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/196.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/20.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/20.png new file mode 100644 index 0000000..0545ce3 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/20.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/216.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/216.png new file mode 100644 index 0000000..32a47cf Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/216.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/256.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/256.png new file mode 100644 index 0000000..3106d6b Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/256.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/29.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/29.png new file mode 100644 index 0000000..c2e6d5a Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/29.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/32.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/32.png new file mode 100644 index 0000000..296e38c Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/32.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/40.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/40.png new file mode 100644 index 0000000..5dae20b Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/40.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/48.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/48.png new file mode 100644 index 0000000..6b697d1 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/48.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/50.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/50.png new file mode 100644 index 0000000..fa51f5a Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/50.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/512.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/512.png new file mode 100644 index 0000000..e7ab23b Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/512.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/55.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/55.png new file mode 100644 index 0000000..7e632b1 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/55.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/57.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/57.png new file mode 100644 index 0000000..bbbbcf4 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/57.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/58.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/58.png new file mode 100644 index 0000000..1311643 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/58.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/60.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/60.png new file mode 100644 index 0000000..993220d Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/60.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/64.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/64.png new file mode 100644 index 0000000..bbc0ed9 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/64.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/66.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/66.png new file mode 100644 index 0000000..496ccc6 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/66.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/72.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/72.png new file mode 100644 index 0000000..d948825 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/72.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/76.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/76.png new file mode 100644 index 0000000..1c3ac86 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/76.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/80.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/80.png new file mode 100644 index 0000000..908d25d Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/80.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/87.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/87.png new file mode 100644 index 0000000..6c089df Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/87.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/88.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/88.png new file mode 100644 index 0000000..3e9b14f Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/88.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/92.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/92.png new file mode 100644 index 0000000..223eb60 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/92.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json index d36b1fa..ffab254 100644 --- a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,122 +1 @@ -{ - "images" : [ - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" - }, - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@3x.png", - "scale" : "3x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@3x.png", - "scale" : "3x" - }, - { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" - }, - { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@3x.png", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@2x.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@3x.png", - "scale" : "3x" - }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@1x.png", - "scale" : "1x" - }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" - }, - { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" - }, - { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" - }, - { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@1x.png", - "scale" : "1x" - }, - { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@1x.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@2x.png", - "scale" : "2x" - }, - { - "size" : "83.5x83.5", - "idiom" : "ipad", - "filename" : "Icon-App-83.5x83.5@2x.png", - "scale" : "2x" - }, - { - "size" : "1024x1024", - "idiom" : "ios-marketing", - "filename" : "Icon-App-1024x1024@1x.png", - "scale" : "1x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} +{"images":[{"size":"60x60","expected-size":"180","filename":"180.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"40x40","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"60x60","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"57x57","expected-size":"57","filename":"57.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"87","filename":"87.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"57x57","expected-size":"114","filename":"114.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"60","filename":"60.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"1024x1024","filename":"1024.png","expected-size":"1024","idiom":"ios-marketing","folder":"Assets.xcassets/AppIcon.appiconset/","scale":"1x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"72x72","expected-size":"72","filename":"72.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"76x76","expected-size":"152","filename":"152.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"50x50","expected-size":"100","filename":"100.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"76x76","expected-size":"76","filename":"76.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"50x50","expected-size":"50","filename":"50.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"72x72","expected-size":"144","filename":"144.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"40x40","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"83.5x83.5","expected-size":"167","filename":"167.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"20x20","expected-size":"20","filename":"20.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"idiom":"watch","filename":"172.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"38mm","scale":"2x","size":"86x86","expected-size":"172","role":"quickLook"},{"idiom":"watch","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"38mm","scale":"2x","size":"40x40","expected-size":"80","role":"appLauncher"},{"idiom":"watch","filename":"88.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"40mm","scale":"2x","size":"44x44","expected-size":"88","role":"appLauncher"},{"idiom":"watch","filename":"102.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"41mm","scale":"2x","size":"45x45","expected-size":"102","role":"appLauncher"},{"idiom":"watch","filename":"92.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"41mm","scale":"2x","size":"46x46","expected-size":"92","role":"appLauncher"},{"idiom":"watch","filename":"100.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"44mm","scale":"2x","size":"50x50","expected-size":"100","role":"appLauncher"},{"idiom":"watch","filename":"196.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"42mm","scale":"2x","size":"98x98","expected-size":"196","role":"quickLook"},{"idiom":"watch","filename":"216.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"44mm","scale":"2x","size":"108x108","expected-size":"216","role":"quickLook"},{"idiom":"watch","filename":"48.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"38mm","scale":"2x","size":"24x24","expected-size":"48","role":"notificationCenter"},{"idiom":"watch","filename":"55.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"42mm","scale":"2x","size":"27.5x27.5","expected-size":"55","role":"notificationCenter"},{"idiom":"watch","filename":"66.png","folder":"Assets.xcassets/AppIcon.appiconset/","subtype":"45mm","scale":"2x","size":"33x33","expected-size":"66","role":"notificationCenter"},{"size":"29x29","expected-size":"87","filename":"87.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"watch","role":"companionSettings","scale":"3x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"watch","role":"companionSettings","scale":"2x"},{"size":"1024x1024","expected-size":"1024","filename":"1024.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"watch-marketing","scale":"1x"},{"size":"128x128","expected-size":"128","filename":"128.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"256x256","expected-size":"256","filename":"256.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"128x128","expected-size":"256","filename":"256.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"256x256","expected-size":"512","filename":"512.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"32x32","expected-size":"32","filename":"32.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"512x512","expected-size":"512","filename":"512.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"16x16","expected-size":"16","filename":"16.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"16x16","expected-size":"32","filename":"32.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"32x32","expected-size":"64","filename":"64.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"512x512","expected-size":"1024","filename":"1024.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"}]} \ No newline at end of file diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png deleted file mode 100644 index dc9ada4..0000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png deleted file mode 100644 index 7353c41..0000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png deleted file mode 100644 index 797d452..0000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png deleted file mode 100644 index 6ed2d93..0000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png deleted file mode 100644 index 4cd7b00..0000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png deleted file mode 100644 index fe73094..0000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png deleted file mode 100644 index 321773c..0000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png deleted file mode 100644 index 797d452..0000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png deleted file mode 100644 index 502f463..0000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png deleted file mode 100644 index 0ec3034..0000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png deleted file mode 100644 index 0ec3034..0000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png deleted file mode 100644 index e9f5fea..0000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png deleted file mode 100644 index 84ac32a..0000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png deleted file mode 100644 index 8953cba..0000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png deleted file mode 100644 index 0467bf1..0000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json deleted file mode 100644 index 0bedcf2..0000000 --- a/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "LaunchImage.png", - "scale" : "1x" - }, - { - "idiom" : "universal", - "filename" : "LaunchImage@2x.png", - "scale" : "2x" - }, - { - "idiom" : "universal", - "filename" : "LaunchImage@3x.png", - "scale" : "3x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png deleted file mode 100644 index 9da19ea..0000000 Binary files a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png deleted file mode 100644 index 9da19ea..0000000 Binary files a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png deleted file mode 100644 index 9da19ea..0000000 Binary files a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md deleted file mode 100644 index 89c2725..0000000 --- a/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Launch Screen Assets - -You can customize the launch screen with your own desired assets by replacing the image files in this directory. - -You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/lib/models/model.dart b/lib/models/model.dart index c220d17..7cf08f1 100644 --- a/lib/models/model.dart +++ b/lib/models/model.dart @@ -60,23 +60,25 @@ class Usermodel { } class NoteModel { - String? id; - String? title; - String? note; - String? date; - String? starttime; - String? endtime; - String? reminder; - bool? isCompleted; + String? id; + String? title; + String? note; + String? date; + String? starttime; + String? endtime; + String? reminder; + String? completedTime; + bool? isCompleted; NoteModel({ this.id, - this.title, - this.note, - this.date, - this.starttime, - this.endtime, - this.reminder, + required this.title, + required this.note, + required this.date, + required this.starttime, + required this.endtime, + required this.reminder, + this.completedTime, this.isCompleted = false, }); @@ -88,6 +90,7 @@ class NoteModel { String? starttime, String? endtime, String? reminder, + String? completedTime, bool? isCompleted, }) { return NoteModel( @@ -98,12 +101,13 @@ class NoteModel { starttime: starttime ?? this.starttime, endtime: endtime ?? this.endtime, reminder: reminder ?? this.reminder, + completedTime: completedTime ?? this.completedTime, isCompleted: isCompleted ?? this.isCompleted, ); } Map toMap() { - return { + return { 'id': id, 'title': title, 'note': note, @@ -111,57 +115,60 @@ class NoteModel { 'starttime': starttime, 'endtime': endtime, 'reminder': reminder, + 'completedTime': completedTime, 'isCompleted': isCompleted, }; } factory NoteModel.fromMap(Map map) { return NoteModel( - id: map['id'] as String?, - title: map['title'] as String?, - note: map['note'] as String?, - date: map['date'] as String?, - starttime: map['starttime'] as String?, - endtime: map['endtime'] as String?, - reminder: map['reminder'] as String?, - isCompleted: map['isCompleted'] as bool?, + id: map['id'] != null ? map['id'] as String : null, + title: map['title'] != null ? map['title'] as String : null, + note: map['note'] != null ? map['note'] as String : null, + date: map['date'] != null ? map['date'] as String : null, + starttime: map['starttime'] != null ? map['starttime'] as String : null, + endtime: map['endtime'] != null ? map['endtime'] as String : null, + reminder: map['reminder'] != null ? map['reminder'] as String : null, + completedTime: map['completedTime'] != null ? map['completedTime'] as String : null, + isCompleted: map['isCompleted'] != null ? map['isCompleted'] as bool : null, ); } String toJson() => json.encode(toMap()); - factory NoteModel.fromJson(String source) => - NoteModel.fromMap(json.decode(source)); + factory NoteModel.fromJson(String source) => NoteModel.fromMap(json.decode(source) as Map); @override String toString() { - return 'NoteModel(id: $id, title: $title, note: $note, date: $date, starttime: $starttime, endtime: $endtime, reminder: $reminder, isCompleted: $isCompleted)'; + return 'NoteModel(id: $id, title: $title, note: $note, date: $date, starttime: $starttime, endtime: $endtime, reminder: $reminder, completedTime: $completedTime, isCompleted: $isCompleted)'; } @override - bool operator ==(Object other) { + bool operator ==(covariant NoteModel other) { if (identical(this, other)) return true; - - return other is NoteModel && - other.id == id && - other.title == title && - other.note == note && - other.date == date && - other.starttime == starttime && - other.endtime == endtime && - other.reminder == reminder && - other.isCompleted == isCompleted; + + return + other.id == id && + other.title == title && + other.note == note && + other.date == date && + other.starttime == starttime && + other.endtime == endtime && + other.reminder == reminder && + other.completedTime == completedTime && + other.isCompleted == isCompleted; } @override int get hashCode { return id.hashCode ^ - title.hashCode ^ - note.hashCode ^ - date.hashCode ^ - starttime.hashCode ^ - endtime.hashCode ^ - reminder.hashCode ^ - isCompleted.hashCode; + title.hashCode ^ + note.hashCode ^ + date.hashCode ^ + starttime.hashCode ^ + endtime.hashCode ^ + reminder.hashCode ^ + completedTime.hashCode ^ + isCompleted.hashCode; } } diff --git a/lib/providers/task_provider.dart b/lib/providers/task_provider.dart index 00dc7c5..82b4c04 100644 --- a/lib/providers/task_provider.dart +++ b/lib/providers/task_provider.dart @@ -1,44 +1,34 @@ -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; import 'package:todo/models/model.dart'; import 'package:todo/utilities/firebase_database.dart'; class TaskProvider with ChangeNotifier { - List _tasks = []; + List tasks = []; + List completedtask = []; - List get tasks => _tasks; - - Future fetchTasks(String date) async { + Future> fetchTasks(String date) async { try { - var querySnapshot = await FirebaseFirestore.instance - .collection("User") - .doc(FirebaseAuth.instance.currentUser!.uid) - .collection("Task") - .where('date', isEqualTo: date).where('isComplete', isEqualTo: false) - .get(); - - List notes = []; - print(notes); - if (querySnapshot.docs.isNotEmpty) { - querySnapshot.docs.forEach((doc) { - final info = doc.data() as Map; - NoteModel a = NoteModel.fromMap(info); - notes.add(a); - }); - } - print(notes); + final notes = await FirebaseStore.GetTask(date); + + tasks = notes; + notifyListeners(); + } catch (e) { + print('An error occurred: $e'); + } + return tasks; + } - if (notes.isEmpty) { - print('No documents found for the specified date.'); - } - _tasks = notes; + Future> fetchdoneTasks(String date) async { + try { + final notesdoc = await FirebaseStore.GetDoneTask(date); + + completedtask = notesdoc; + notifyListeners(); } catch (e) { print('An error occurred: $e'); - _tasks = []; } - - notifyListeners(); + return completedtask; } + notifyListeners(); } diff --git a/lib/screens/bottomsheet_addtask.dart b/lib/screens/bottomsheet_addtask.dart index 187cc25..91ce7d7 100644 --- a/lib/screens/bottomsheet_addtask.dart +++ b/lib/screens/bottomsheet_addtask.dart @@ -1,9 +1,12 @@ +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:todo/models/model.dart'; import 'package:todo/providers/selectedbox_provider.dart'; import 'package:todo/providers/theme_provider.dart'; import 'package:todo/providers/time_provider.dart'; +import 'package:todo/screens/home_screen.dart'; import 'package:todo/utilities/features.dart'; import 'package:todo/utilities/firebase_database.dart'; import 'package:todo/widgets/custom_widgets.dart'; // Add this import for the TimePicker @@ -17,7 +20,7 @@ TextEditingController reminder = TextEditingController(); AdditionslFeature feature = AdditionslFeature(); -final _formkey = GlobalKey(); +final _formkey2 = GlobalKey(); List options = [ '5 Minutes early', @@ -25,10 +28,9 @@ List options = [ '15 Minutes early', '30 Minutes early' ]; - Future sendtask(BuildContext context) async { print("running program"); - if (_formkey.currentState != null && _formkey.currentState!.validate()) { + if (_formkey2.currentState != null && _formkey2.currentState!.validate()) { NoteModel n = NoteModel( title: title.text, note: note.text, @@ -38,20 +40,24 @@ Future sendtask(BuildContext context) async { reminder: reminder.text, ); try { - var result = await FirebaseStore.Savetask(n, date.text); - if (result is bool) { - if (result == true) { - title.text = ''; - note.text = ''; - date.text = ''; - starttime.text = ''; - endtime.text = ''; - reminder.text = ''; - print("Done Data Saved"); - aftertrue(context); - } - } else if (result is String) { - print(result); + List result = await FirebaseStore.Savetask(n, date.text); + if (result[0] == true) { + // Extract the document ID from the result + String docId = result[1]; + + // Update the NoteModel with the retrieved document ID + n = n.copyWith(id: docId); + + title.text = ''; + note.text = ''; + date.text = ''; + starttime.text = ''; + endtime.text = ''; + reminder.text = ''; + print("Done Data Saved"); + aftertrue(context); + } else if (result[0] is String) { + print(result[0]); } else { print("Something went wrong "); } @@ -59,22 +65,23 @@ Future sendtask(BuildContext context) async { print("An error occurred: $e"); } } - return Future.value(null); } aftertrue(BuildContext context) { - + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => home_screen(), + )); ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text( "Task Addes !", style: TextStyle( - fontSize: 18, - color: Colors.white, - fontWeight: FontWeight.bold), + fontSize: 18, color: Colors.white, fontWeight: FontWeight.bold), ), backgroundColor: Colors.black, )); - Navigator.of(context).pop(); + // Navigator.of(context).pop(); } gettask(BuildContext context) { @@ -125,7 +132,7 @@ gettask(BuildContext context) { Padding( padding: const EdgeInsets.all(10.0), child: Form( - key: _formkey, + key: _formkey2, child: Column( children: [ CustomTextFormField( @@ -273,7 +280,7 @@ gettask(BuildContext context) { height: 10, ), DropdownButtonFormField( - value: reminder.text, + value: options[0], icon: const Icon(Icons.arrow_downward), iconSize: 24, elevation: 16, @@ -284,9 +291,9 @@ gettask(BuildContext context) { : Colors.white), onChanged: (String? newValue) { // Update the dropdown value when the user selects an option - // setState(() { - // reminder.text = newValue!; - // }); + + reminder.text = newValue!; + }, items: options.map((String value) { return DropdownMenuItem( @@ -308,8 +315,8 @@ gettask(BuildContext context) { CustomElevatedButton( message: "Add Task", function: () async { - if (_formkey.currentState != null && - _formkey.currentState!.validate()) { + if (_formkey2.currentState != null && + _formkey2.currentState!.validate()) { await sendtask(context); } }), diff --git a/lib/screens/bottomsheet_updatetask.dart b/lib/screens/bottomsheet_updatetask.dart new file mode 100644 index 0000000..e6277b7 --- /dev/null +++ b/lib/screens/bottomsheet_updatetask.dart @@ -0,0 +1,381 @@ +// ignore_for_file: use_build_context_synchronously + +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:todo/models/model.dart'; +import 'package:todo/providers/selectedbox_provider.dart'; +import 'package:todo/providers/theme_provider.dart'; +import 'package:todo/providers/time_provider.dart'; +import 'package:todo/screens/home_screen.dart'; +import 'package:todo/utilities/features.dart'; +import 'package:todo/utilities/firebase_database.dart'; +import 'package:todo/widgets/custom_widgets.dart'; // Add this import for the TimePicker + +TextEditingController title = TextEditingController(); +TextEditingController note = TextEditingController(); +TextEditingController date = TextEditingController(); +TextEditingController starttime = TextEditingController(); +TextEditingController endtime = TextEditingController(); +TextEditingController reminder = TextEditingController(); + +AdditionslFeature feature = AdditionslFeature(); + +final _formkey1 = GlobalKey(); + +List options = [ + '5 Minutes early', + '10 Minutes early', + '15 Minutes early', + '30 Minutes early' +]; + +Future Updatetask(String docId, BuildContext context) async { + print("running program"); + if (_formkey1.currentState != null && _formkey1.currentState!.validate()) { + NoteModel n = NoteModel( + id: docId, + title: title.text, + note: note.text, + date: date.text, + starttime: starttime.text, + endtime: endtime.text, + reminder: reminder.text, + ); + try { + bool result = await FirebaseStore.Updatask( + n, docId, FirebaseAuth.instance.currentUser!.uid); + if (result == true) { + // Navigator.of(context).pop(); + aftertrue(context); + } else { + // Navigator.of(context).pop(); + afterfalse(context); + } + } catch (e) { + print("An error occurred: $e"); + } + } +} + +aftertrue(BuildContext context) { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => home_screen(), + )); + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text( + "Task Addes !", + style: TextStyle( + fontSize: 18, color: Colors.white, fontWeight: FontWeight.bold), + ), + backgroundColor: Colors.black, + )); + // Navigator.of(context).pop(); +} + +afterfalse(BuildContext context) { + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text( + "Unable to Add Task !", + style: TextStyle( + fontSize: 18, color: Colors.white, fontWeight: FontWeight.bold), + ), + backgroundColor: Colors.black, + )); + Navigator.of(context).pop(); +} + + +Future GetTaskDetails(String docId) async { + try { + var querySnapshot = await FirebaseFirestore.instance + .collection("User") + .doc(FirebaseAuth.instance.currentUser!.uid) + .collection("Task") + .doc( + docId) // Use doc method instead of get for retrieving a specific document + .get(); + + if (!querySnapshot.exists) { + print('No document found for the specified ID.'); + return null; + } + + Map data = querySnapshot.data() as Map; + NoteModel task = NoteModel( + id: docId, + title: data['title'], + note: data['note'], + date: data['date'], + starttime: data['starttime'], + endtime: data['endtime'], + reminder: data['reminder'], + isCompleted: data['isCompleted'], + ); + + return task; + } catch (e) { + print('An error occurred: $e'); + return null; + } +} + +void updatesheet(BuildContext context, String docId, String uid) async { + GetTaskDetails(docId); + NoteModel? task = await GetTaskDetails(docId); + if (task != null) { + title.text = task.title ?? ''; + note.text = task.note ?? ''; + date.text = task.date ?? ''; + starttime.text = task.starttime ?? ''; + endtime.text = task.endtime ?? ''; + reminder.text = task.reminder ?? ''; + } + + final timeProvider = Provider.of(context, listen: false); + final provider = context.read(); + String datevalue = provider.getFormattedDate().toString(); + + showModalBottomSheet( + isScrollControlled: true, + isDismissible: true, + context: context, + builder: (context) { + return FractionallySizedBox( + heightFactor: 0.9, + child: Container( + height: MediaQuery.of(context).size.height, + width: double.infinity, + child: SingleChildScrollView( + child: Column( + children: [ + const SizedBox( + height: 10, + ), + Container( + height: 6, + width: 120, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: Colors.grey), + ), + const SizedBox( + height: 20, + ), + const Text( + "Update Task", + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.bold, + letterSpacing: 2), + ), + const SizedBox( + height: 20, + ), + Padding( + padding: const EdgeInsets.all(10.0), + child: Form( + key: _formkey1, + child: Column( + children: [ + CustomTextFormField( + controller: title, + sur: const Icon(Icons.note_add_outlined), + labelText: "Note Title", + hintText: "Eat Snacks", + validator: (value) { + if (value == null || value.isEmpty) { + return "Title can not be empty"; + } else if (value.length < 3) { + return "It needs a minimum of 3 letters"; + } + return null; + }, + ), + const SizedBox( + height: 10, + ), + CustomTextFormField( + controller: note, + sur: const Icon( + Icons.abc_outlined, + size: 30, + ), + labelText: "Note Body", + hintText: "I will eat chips with coke!", + validator: (value) { + if (value == null || value.isEmpty) { + return "Body can not be empty"; + } else if (value.length < 3) { + return "It needs a minimum of 3 letters"; + } + return null; + }, + ), + const SizedBox( + height: 10, + ), + TextFormField( + enabled: false, + controller: date, + decoration: InputDecoration( + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(10)), + labelText: 'Date', + suffixIcon: Icon(Icons.date_range), + ), + validator: (value) { + if (value == null || value.isEmpty) { + return "Date can not be empty"; + } + return null; + }, + ), + const SizedBox( + height: 10, + ), + Row( + children: [ + Expanded( + child: Container( + margin: const EdgeInsets.all(5), + child: TextFormField( + controller: starttime, + decoration: InputDecoration( + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + ), + labelText: "Start Time", + hintText: "12:15", + suffixIcon: IconButton( + onPressed: () { + TimePicker timePicker = TimePicker( + labelText: 'Select Time', + selectedTime: TimeOfDay.now(), + onSelectedTime: (TimeOfDay newTime) { + final formattedTime = timeProvider + .formatTime(newTime, context); + timeProvider + .updateStartTime(formattedTime); + starttime.text = + formattedTime; // Add this line + }, + ); + timePicker.selectTime(context); + }, + icon: const Icon( + Icons.watch_later_outlined), + ), + ), + validator: (value) { + if (value == null || value.isEmpty) { + return "Start time can not be empty"; + } + return null; + }, + ), + ), + ), + const SizedBox(width: 5), + Expanded( + child: Container( + margin: const EdgeInsets.all(5), + child: TextFormField( + controller: endtime, + decoration: InputDecoration( + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + ), + labelText: "End Time", + hintText: "12:45", + suffixIcon: IconButton( + onPressed: () { + TimePicker timePicker = TimePicker( + labelText: 'Select Time', + selectedTime: TimeOfDay.now(), + onSelectedTime: (TimeOfDay newTime) { + final formattedTime = timeProvider + .formatTime(newTime, context); + timeProvider + .updateEndTime(formattedTime); + endtime.text = + formattedTime; // Add this line + }, + ); + timePicker.selectTime(context); + }, + icon: const Icon( + Icons.watch_later_outlined), + ), + ), + validator: (value) { + if (value == null || value.isEmpty) { + return "End time can not be empty"; + } + return null; + }, + ), + ), + ), + ], + ), + const SizedBox( + height: 10, + ), + DropdownButtonFormField( + value: reminder.text, + icon: const Icon(Icons.arrow_downward), + iconSize: 24, + elevation: 16, + style: TextStyle( + color: + Provider.of(context).isDarkMode + ? Colors.black + : Colors.white, + ), + onChanged: (String? newValue) { + // Update the dropdown value when the user selects an option + // setState(() { + // reminder.text = newValue!; + // }); + }, + items: options.map((String value) { + return DropdownMenuItem( + value: value, + child: Text(value), + ); + }).toList(), + decoration: InputDecoration( + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + ), + labelText: 'Reminder', + hintText: "5 Minutes early ", + ), + ), + const SizedBox( + height: 15, + ), + CustomElevatedButton( + message: "Update Task", + function: () async { + if (_formkey1.currentState != null && + _formkey1.currentState!.validate()) { + await Updatetask(docId, context); + } + }), + ], + ), + ), + ), + ], + ), + ), + ), + ); + }, + ); +} diff --git a/lib/screens/home_screen.dart b/lib/screens/home_screen.dart index 635f911..10e19d7 100644 --- a/lib/screens/home_screen.dart +++ b/lib/screens/home_screen.dart @@ -1,11 +1,13 @@ import 'dart:async'; - import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:intl/intl.dart'; import 'package:provider/provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:todo/main.dart'; +import 'package:fluttertoast/fluttertoast.dart'; import 'package:todo/models/model.dart'; import 'package:todo/providers/dateTime_provider.dart'; import 'package:todo/providers/selectedbox_provider.dart'; @@ -13,9 +15,9 @@ import 'package:todo/providers/task_provider.dart'; import 'package:todo/providers/theme_provider.dart'; import 'package:todo/screens/bottomsheet_addtask.dart'; import 'package:todo/screens/bottomsheet_addtask.dart'; +import 'package:todo/screens/bottomsheet_updatetask.dart'; import 'package:todo/screens/signin_screen.dart'; import 'package:todo/utilities/firebase_database.dart'; - import 'bottomsheet_addtask.dart'; class home_screen extends StatefulWidget { @@ -26,16 +28,14 @@ class home_screen extends StatefulWidget { } class _home_screenState extends State { + String? id; String? title; String? notebody; String? starttime; String? endtime; -// List of dropdown options - String? name; String? email; - List numbers = List.generate(100, (index) => index + 1); List tasks = []; List boxcolors = [ @@ -96,45 +96,77 @@ class _home_screenState extends State { }); } - getcurrentmonth() {} - String formatDate(Map dateMap) { - String day = dateMap['date'].toString(); - String month = dateMap['month']; - String year = dateMap['year'].toString(); - return "$day $month $year"; + String formatDate(Map? dateMap) { + if (dateMap == null) { + return ""; + } else { + String day = dateMap['date'].toString(); + String month = dateMap['month']; + String year = dateMap['year'].toString(); + return "$day $month $year"; + } + } + + checkmail() { + bool emailverify = false; + + return emailverify = FirebaseAuth.instance.currentUser!.emailVerified; } @override void initState() { super.initState(); userinfo(); - getcurrentmonth(); + // getcurrentmonth(); + WidgetsBinding.instance!.addPostFrameCallback((_) { final selectedBoxProvider = context.read(); final datesProvider = context.read(); final dates = DatesProvider(); List dateList = dates.showDates(); - selectedBoxProvider - .updateSelectedBox(dateList[0]); // Set the initial value - - // print(formatDate(selectedBoxProvider.selectedBox)); - // FirebaseStore.GetTask(formatDate(selectedBoxProvider.selectedBox)); + selectedBoxProvider.updateSelectedBox(dateList[0]); + checkmail(); + todaydate(); }); - // Dates dateTime = Dates(); - // List dates = dateTime.Calender(); - // print(dates); + } + + void todaydate() async { + final taskProvider = Provider.of(context, listen: false); + DateTime now = DateTime.now(); + String formattedDate = DateFormat('d MMM y').format(now); + + tasks = await taskProvider.fetchTasks(formattedDate); } @override Widget build(BuildContext context) { - final selectedBoxProvider = context.read(); - final selectedbox = Provider.of(context); - final taskProvider = Provider.of(context, listen: false); - final dateProvider = Provider.of(context); + // for checking mail is verified or not to change mail icon + + final selectedBoxProvider = + Provider.of(context, listen: true); + final selectedbox = selectedBoxProvider; + final dateProvider = Provider.of(context, listen: true); + final taskProvider = Provider.of(context); final dates = DatesProvider(); List dateList = dates.showDates(); final today = dateList[0]; + Map? selectedBoxValue = selectedBoxProvider.selectedBox; + + List tasks = taskProvider.tasks; + List donetasks = taskProvider.completedtask; + showtask() async { + tasks = + await taskProvider.fetchTasks(formatDate(selectedbox.selectedBox)); + + } + + showdonetask() async { + donetasks = await taskProvider + .fetchdoneTasks(formatDate(selectedbox.selectedBox)); + print(donetasks); + } + Future getcurrentmonth() async { if (today['month'] == "Jan") { return "January"; @@ -170,20 +202,260 @@ class _home_screenState extends State { final themeprovider = Provider.of(context); return Scaffold( body: SafeArea( - child: Column( - children: [ - Container( - height: MediaQuery.of(context).size.height / 12, - width: double.infinity, - child: Padding( - padding: - const EdgeInsets.only(right: 10, left: 10, top: 5, bottom: 5), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - const CircleAvatar( + child: Column(children: [ + Container( + height: MediaQuery.of(context).size.height / 12, + width: double.infinity, + child: Padding( + padding: + const EdgeInsets.only(right: 10, left: 10, top: 5, bottom: 5), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + GestureDetector( + onTap: () { + showCupertinoModalPopup( + context: context, + builder: (context) { + return CupertinoActionSheet( + actions: [ + Container( + width: MediaQuery.of(context).size.width, + height: screenhight / 1.9, + child: Column( + children: [ + const SizedBox( + height: 20, + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + const CircleAvatar( + minRadius: 50, + maxRadius: 50, + backgroundColor: Colors.blue, + child: Icon( + Icons.person_sharp, + size: 40, + color: Colors.white, + ), + ), + Container( + height: 100, + width: 200, + child: Column( + mainAxisAlignment: + MainAxisAlignment.center, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + FittedBox( + child: Text( + "$name", + style: const TextStyle( + fontSize: 20, + fontWeight: + FontWeight.w700, + color: Colors.white, + decoration: + TextDecoration + .none), + )), + const SizedBox( + height: 10, + ), + FittedBox( + child: Text('$email ', + style: const TextStyle( + fontSize: 20, + fontWeight: + FontWeight + .w700, + color: Colors + .white, + decoration: + TextDecoration + .none))) + ], + ), + ) + ], + ), + ), + const SizedBox( + height: 20, + ), + CupertinoActionSheetAction( + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + const Text( + 'Change Theme', + style: TextStyle( + fontSize: 20, + color: Colors.white, + fontWeight: + FontWeight.w400), + ), + Icon( + themeprovider.getThemeIcon(), + size: 25, + color: Colors.white, + ) + ], + ), + onPressed: () { + themeprovider.toggleTheme(); + }, + ), + CupertinoActionSheetAction( + child: const Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Reminder', + style: TextStyle( + fontSize: 20, + color: Colors.white, + fontWeight: + FontWeight.w400), + ), + Icon( + Icons + .notifications_active_outlined, + color: Colors.white, + ) + ], + ), + onPressed: () {}, + ), + CupertinoActionSheetAction( + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + const Text( + 'Email Verification', + style: TextStyle( + fontSize: 20, + color: Colors.white, + fontWeight: + FontWeight.w400), + ), + Icon( + checkmail() + ? Icons + .mark_email_read_outlined + : Icons.email_outlined, + color: Colors.white, + ) + ], + ), + onPressed: () { + Navigator.of(context).pop(); + if (checkmail() == true) { + final scaffoldContext = + ScaffoldMessenger.of(context); + scaffoldContext.showSnackBar( + const SnackBar( + content: Text( + "Your Mail is already Verified !", + style: TextStyle( + fontSize: 15, + color: Colors.white, + fontWeight: + FontWeight.bold, + ), + ), + backgroundColor: Colors.black, + ), + ); + } else { + final scaffoldContext = + ScaffoldMessenger.of(context); + if (scaffoldContext != null) { + FirebaseStore + .SendMailVerification() + .then((value) { + scaffoldContext.showSnackBar( + const SnackBar( + content: Text( + "Mail Sent ! Please Check Your mail !", + style: TextStyle( + fontSize: 15, + color: Colors.white, + fontWeight: + FontWeight.bold, + ), + ), + backgroundColor: + Colors.black, + ), + ); + }); + } + } + }, + ), + CupertinoActionSheetAction( + child: const Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Share App', + style: TextStyle( + fontSize: 20, + color: Colors.white, + fontWeight: + FontWeight.w400), + ), + Icon( + Icons.ios_share_outlined, + color: Colors.white, + ) + ], + ), + onPressed: () {}, + ), + ], + ), + ), + CupertinoActionSheetAction( + child: const Text( + 'Sign Out', + style: TextStyle( + fontSize: 20, + color: Colors.white, + fontWeight: FontWeight.w400), + ), + onPressed: () { + sign_out(); + }, + ), + ], + cancelButton: CupertinoActionSheetAction( + onPressed: () { + Navigator.of(context).pop(); + }, + child: const Text( + "Cancel", + style: TextStyle(color: Colors.red), + )), + ); + }, + ); + }, + child: const CircleAvatar( minRadius: 25, maxRadius: 25, backgroundColor: Colors.blue, @@ -193,265 +465,249 @@ class _home_screenState extends State { color: Colors.white, ), ), - IconButton( - onPressed: () { - sign_out(); - }, - icon: const Icon( - Icons.logout_outlined, - )) - ], - ), - FittedBox( - child: RichText( - text: TextSpan(children: [ - TextSpan( - text: "Hi, ", - style: TextStyle( - color: themeprovider.isDarkMode - ? Colors.black - : Colors.white, - fontSize: 18, - letterSpacing: 2, - )), - TextSpan( - text: "$name", - style: TextStyle( - color: themeprovider.isDarkMode - ? Colors.black - : Colors.white, - fontSize: 25, - fontWeight: FontWeight.w200), - ), - ])), - ), - Align( - alignment: Alignment.topRight, - child: IconButton( - onPressed: () { - themeprovider.toggleTheme(); - }, - icon: Icon( - themeprovider.getThemeIcon(), - size: 25, - )), - ) - ]), - ), - ), - Container( - child: Padding( - padding: const EdgeInsets.all(10.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - GestureDetector( - onTap: () { - // get task bottom model sheet appear heer - gettask(context); - }, + ), + // IconButton( + // onPressed: () { + // sign_out(); + // }, + // icon: const Icon( + // Icons.logout_outlined, + // )) + ], + ), + FittedBox( child: Container( - height: MediaQuery.of(context).size.height / 16, - width: MediaQuery.of(context).size.width / 3, - clipBehavior: Clip.none, - decoration: BoxDecoration( - color: Colors.deepPurple, - borderRadius: BorderRadius.circular(10)), - child: const Padding( - padding: EdgeInsets.only(right: 10, left: 8), - child: FittedBox( - child: Row(children: [ - Text( - "Add Task", - style: - TextStyle(color: Colors.white, fontSize: 20), - ), - Icon( - Icons.add, - size: 25, - color: Colors.white, - ), - ]), + constraints: BoxConstraints( + maxWidth: MediaQuery.of(context).size.width - 130), + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: RichText( + text: TextSpan( + children: [ + TextSpan( + text: "Hi, ", + style: TextStyle( + color: themeprovider.isDarkMode + ? Colors.black + : Colors.white, + fontSize: 18, + letterSpacing: 2, + ), + ), + TextSpan( + text: "$name", + style: TextStyle( + color: themeprovider.isDarkMode + ? Colors.black + : Colors.white, + fontSize: 25, + fontWeight: FontWeight.w200, + ), + ), + ], + ), + overflow: TextOverflow + .ellipsis, // Add this line to handle text overflow ), ), ), ), - Text( - // gettoday, - selectedbox.getFormattedDate(), - // getcurrentmonth() + - // ' ' + - // today['date'].toString() + - // ' , ' + - // today['year'].toString() + - // '\n' + - // "Today", - style: TextStyle( - fontSize: 20, - color: Colors.grey[650], - fontWeight: FontWeight.bold), + Align( + alignment: Alignment.topRight, + child: IconButton( + onPressed: () { + themeprovider.toggleTheme(); + }, + icon: Icon( + themeprovider.getThemeIcon(), + size: 25, + )), + ) + ]), + ), + ), + Container( + child: Padding( + padding: const EdgeInsets.all(10.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + GestureDetector( + onTap: () { + // get task bottom model sheet appear heer + gettask(context); + }, + child: Container( + height: MediaQuery.of(context).size.height / 16, + width: MediaQuery.of(context).size.width / 3, + clipBehavior: Clip.none, + decoration: BoxDecoration( + color: Colors.deepPurple, + borderRadius: BorderRadius.circular(10)), + child: const Padding( + padding: EdgeInsets.only(right: 10, left: 8), + child: FittedBox( + child: Row(children: [ + Text( + "Add Task", + style: TextStyle(color: Colors.white, fontSize: 20), + ), + Icon( + Icons.add, + size: 25, + color: Colors.white, + ), + ]), + ), + ), ), - ], - ), + ), + Text( + // gettoday, + selectedbox.getFormattedDate(), + // getcurrentmonth() + + // ' ' + + // today['date'].toString() + + // ' , ' + + // today['year'].toString() + + // '\n' + + // "Today", + style: TextStyle( + fontSize: 20, + color: Colors.grey[650], + fontWeight: FontWeight.bold), + ), + ], ), ), + ), - // Code Starts From here ------------------------ + // Code Starts From here ------------------------ - Padding( - padding: const EdgeInsets.all(10.0), - child: SizedBox( - width: MediaQuery.of(context).size.width, - height: 110, - child: ListView.builder( - scrollDirection: Axis.horizontal, - itemCount: dateList.length, - itemBuilder: (context, index) { - final item = dateList[index]; - final color = boxcolors[index % boxcolors.length]; - final selectedBoxValue = selectedbox.selectedBox; - - return Padding( - padding: const EdgeInsets.only(right: 5, left: 3), - child: GestureDetector( - onTap: () { - selectedbox.updateSelectedBox(item); - // void showTasks() async { - // await taskProvider - // .fetchTasks(formatDate(selectedbox.selectedBox)); - // } - FirebaseStore.GetTask( - formatDate(selectedbox.selectedBox)) - .then((notes) { - if (notes.isNotEmpty) { - tasks = notes; - for (var note in notes) { - print("Title: ${note.title}"); - print("Note: ${note.note}"); - print("Date: ${note.date}"); - print("Start Time: ${note.starttime}"); - print("End Time: ${note.endtime}"); - print("Reminder: ${note.reminder}"); - print("Is Completed: ${note.isCompleted}"); - // setState(() { - // title = "${note.title}"; - // notebody = "${note.note}"; - // starttime = "${note.starttime}"; - // endtime = "${note.endtime}"; - // }); - } - } else { - print('No documents found for the specified date.'); - } - }); - // print(selectedbox.selectedBox); - // print(formatDate(selectedbox.selectedBox)); - // print(selectedbox); - // print(item); - }, - child: Container( - height: 100, - width: 100, - decoration: BoxDecoration( - border: Border.all( - color: Colors.deepPurple.withOpacity(1)), - boxShadow: [ - BoxShadow( - color: - Colors.grey.withOpacity(0.2), // Shadow color - spreadRadius: 2, // Spread radius - blurRadius: 2, // Blur radius - offset: const Offset(0, 3), // Offset - ), - ], - borderRadius: BorderRadius.circular(10), - // color: Colors.deepPurple - // color: color - color: selectedBoxValue != null && - selectedBoxValue['year'] == item['year'] && - selectedBoxValue['month'] == item['month'] && - selectedBoxValue['date'] == item['date'] && - selectedBoxValue['dayOfWeek'] == - item['dayOfWeek'] - ? Colors.deepPurple - : Colors.deepPurple.withOpacity(0.4), - ), - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - FittedBox( - child: Text( - item['month'] != null ? item['month'] : '', - style: TextStyle( - fontSize: 20, - color: themeprovider.isDarkMode - ? Colors.white - : Colors.white, - // selectedbox == index - // ? Colors.white - // : Colors.white - ), + Padding( + padding: const EdgeInsets.all(10.0), + child: SizedBox( + width: MediaQuery.of(context).size.width, + height: 110, + child: ListView.builder( + scrollDirection: Axis.horizontal, + itemCount: dateList.length, + itemBuilder: (context, index) { + final item = dateList[index]; + final color = boxcolors[index % boxcolors.length]; + final selectedBoxValue = selectedbox.selectedBox; + + return Padding( + padding: const EdgeInsets.only(right: 5, left: 3), + child: GestureDetector( + onTap: () async { + selectedbox.updateSelectedBox(item); + showtask(); + }, + child: Container( + height: 100, + width: 100, + decoration: BoxDecoration( + border: + Border.all(color: Colors.deepPurple.withOpacity(1)), + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.2), // Shadow color + spreadRadius: 2, // Spread radius + blurRadius: 2, // Blur radius + offset: const Offset(0, 3), // Offset + ), + ], + borderRadius: BorderRadius.circular(10), + // color: Colors.deepPurple + // color: color + color: selectedBoxValue != null && + selectedBoxValue['year'] == item['year'] && + selectedBoxValue['month'] == item['month'] && + selectedBoxValue['date'] == item['date'] && + selectedBoxValue['dayOfWeek'] == + item['dayOfWeek'] + ? Colors.deepPurple + : Colors.deepPurple.withOpacity(0.4), + ), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + FittedBox( + child: Text( + item['month'] != null ? item['month'] : '', + style: TextStyle( + fontSize: 20, + color: themeprovider.isDarkMode + ? Colors.white + : Colors.white, + // selectedbox == index + // ? Colors.white + // : Colors.white ), ), - Text( - item['date'] != null - ? item['date'].toString() + ), + Text( + item['date'] != null + ? item['date'].toString() + : '', + style: const TextStyle( + fontSize: 20, + color: Colors.white, + + // selectedbox == index + // ? Colors.white + // : Colors.white + ), + ), + FittedBox( + child: Text( + item['dayOfWeek'] != null + ? item['dayOfWeek'] : '', - style: TextStyle( + style: const TextStyle( fontSize: 20, color: Colors.white, - // selectedbox == index // ? Colors.white // : Colors.white ), ), - FittedBox( - child: Text( - item['dayOfWeek'] != null - ? item['dayOfWeek'] - : '', - style: TextStyle( - fontSize: 20, - color: Colors.white, - // selectedbox == index - // ? Colors.white - // : Colors.white - ), - ), - ), - ], - ), + ), + ], ), ), ), - ); - }, - ), + ), + ); + }, ), ), + ), - // Second Container Starts + // Second Container Starts - Padding( + Padding( padding: const EdgeInsets.only(right: 10, left: 10), child: SizedBox( width: MediaQuery.of(context).size.width, height: screenhight / 1.9, - child: ListView.builder( - itemCount: numbers.last, - itemBuilder: (context, index) { - // final currentTask = tasks[index]; - final color = boxcolors[index % boxcolors.length]; - - return index != null - ? Padding( + child: tasks.isNotEmpty && tasks != 0 + ? ListView.builder( + itemCount: tasks.length, + itemBuilder: (context, index) { + final currentTask = tasks[index]; + // print(currentTask); + final color = boxcolors[index % boxcolors.length]; + + return Padding( padding: const EdgeInsets.only(top: 5, bottom: 5), child: GestureDetector( onTap: () { - // print(taskProvider.tasks); + // print(currentTask); + // print(currentTask) }, onLongPress: () { showCupertinoModalPopup( @@ -459,13 +715,207 @@ class _home_screenState extends State { builder: (context) { return CupertinoActionSheet( actions: [ + Material( + child: Container( + height: MediaQuery.of(context) + .size + .height / + 3, + width: 300, + decoration: BoxDecoration( + borderRadius: + BorderRadius.circular(10), + color: color), + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + children: [ + Padding( + padding: + const EdgeInsets.all(8.0), + child: Column( + crossAxisAlignment: + CrossAxisAlignment + .start, + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + children: [ + FittedBox( + child: Container( + constraints: BoxConstraints( + maxWidth: MediaQuery.of( + context) + .size + .width - + 100, + maxHeight: MediaQuery.of( + context) + .size + .height / + 8), + child: + SingleChildScrollView( + scrollDirection: + Axis.vertical, + child: Text( + // "Title " + index.toString(), + currentTask + .title ?? + "", + style: const TextStyle( + fontSize: 17, + color: Colors + .white, + fontWeight: + FontWeight + .bold), + ), + ), + ), + ), + Row( + mainAxisAlignment: + MainAxisAlignment + .start, + children: [ + const Icon( + Icons.lock_clock, + size: 28, + color: Colors.white, + ), + Text( + // " 02:04 PM - 02:19 PM", + " ${currentTask.starttime} - ${currentTask.endtime}", + + style: + const TextStyle( + color: + Colors.white, + ), + ), + ], + ), + FittedBox( + child: Container( + constraints: BoxConstraints( + maxWidth: MediaQuery.of( + context) + .size + .width - + 100, + maxHeight: MediaQuery.of( + context) + .size + .height / + 10), + child: + SingleChildScrollView( + scrollDirection: + Axis.vertical, + child: Text( + // "Note 1", + currentTask + .note ?? + "", + style: const TextStyle( + fontSize: 18, + color: Colors + .white, + fontWeight: + FontWeight + .w300), + ), + ), + ), + ) + ], + ), + ), + Padding( + padding: const EdgeInsets.all( + 10.0), + child: Container( + child: Row( + children: [ + Container( + height: 1000, + width: 1, + color: Colors.white, + ), + const SizedBox( + width: 8, + ), + const RotatedBox( + quarterTurns: + 3, // Set the number of clockwise quarter turns + child: Text( + 'TODO', + style: TextStyle( + fontSize: 13, + color: + Colors.white, + ), // Define the text style + ), + ) + ], + ), + ), + ) + ], + )), + ), + const SizedBox( + height: 30, + ), CupertinoActionSheetAction( child: Text( "Mark as Done 🙂", style: TextStyle( color: Colors.grey.shade600), ), - onPressed: () {}, + onPressed: () async { + DateTime now = DateTime.now(); + + // Format the time using DateFormat + String formattedTime = + DateFormat('hh:mm a').format(now); + bool rs = + await FirebaseStore.MarkasRead( + currentTask.id.toString(), + FirebaseAuth.instance + .currentUser!.uid, + formattedTime); + if (rs = true) { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + const home_screen(), + )); + final scaffoldContext = + ScaffoldMessenger.of(context); + scaffoldContext.showSnackBar( + const SnackBar( + content: Text( + "Task Done 👍🏻", + style: TextStyle( + fontSize: 15, + color: Colors.white, + fontWeight: FontWeight.bold, + ), + ), + backgroundColor: Colors.black, + ), + ); + } else { + print( + "Something is wrong while deleting the Task"); + } + }, ), CupertinoActionSheetAction( child: Text( @@ -473,7 +923,13 @@ class _home_screenState extends State { style: TextStyle( color: Colors.grey.shade600), ), - onPressed: () {}, + onPressed: () { + updatesheet( + context, + currentTask.id.toString(), + FirebaseAuth + .instance.currentUser!.uid); + }, ), CupertinoActionSheetAction( child: Text( @@ -481,18 +937,51 @@ class _home_screenState extends State { style: TextStyle( color: Colors.grey.shade600), ), - onPressed: () {}, - ), - CupertinoActionSheetAction( - child: Text( - "Cancel", - style: TextStyle(color: Colors.red), - ), - onPressed: () { - Navigator.of(context).pop(); + onPressed: () async { + bool rs = + await FirebaseStore.DeleteTask( + currentTask.id.toString(), + FirebaseAuth.instance + .currentUser!.uid); + if (rs = true) { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + const home_screen(), + )); + final scaffoldContext = + ScaffoldMessenger.of(context); + scaffoldContext.showSnackBar( + const SnackBar( + content: Text( + "Task Deleted Successfully ! ", + style: TextStyle( + fontSize: 15, + color: Colors.white, + fontWeight: FontWeight.bold, + ), + ), + backgroundColor: Colors.black, + ), + ); + } else { + print( + "Something is wrong while deleting the Task"); + } }, ), ], + cancelButton: CupertinoActionSheetAction( + isDefaultAction: true, + onPressed: () { + Navigator.of(context).pop(); + }, + child: const Text( + "Cancel", + style: TextStyle(color: Colors.red), + ), + ), ); }, ); @@ -518,37 +1007,70 @@ class _home_screenState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "Title " + index.toString(), - // currentTask.title, - style: const TextStyle( - fontSize: 17, - color: Colors.white, - fontWeight: FontWeight.bold), + FittedBox( + child: Container( + constraints: BoxConstraints( + maxWidth: + MediaQuery.of(context) + .size + .width - + 100), + child: SingleChildScrollView( + scrollDirection: + Axis.horizontal, + child: Text( + // "Title " + index.toString(), + currentTask.title ?? "", + style: const TextStyle( + fontSize: 17, + color: Colors.white, + fontWeight: + FontWeight.bold), + ), + ), + ), ), Row( mainAxisAlignment: MainAxisAlignment.start, children: [ - Icon( + const Icon( Icons.lock_clock, size: 28, color: Colors.white, ), Text( - " 02:04 PM - 02:19 PM", - style: TextStyle( + // " 02:04 PM - 02:19 PM", + " ${currentTask.starttime} - ${currentTask.endtime}", + + style: const TextStyle( color: Colors.white, ), ), ], ), - Text( - "Note 1", - style: TextStyle( - fontSize: 18, - color: Colors.white, - fontWeight: FontWeight.w300), + FittedBox( + child: Container( + constraints: BoxConstraints( + maxWidth: + MediaQuery.of(context) + .size + .width - + 100), + child: SingleChildScrollView( + scrollDirection: + Axis.horizontal, + child: Text( + // "Note 1", + currentTask.note ?? "", + style: const TextStyle( + fontSize: 18, + color: Colors.white, + fontWeight: + FontWeight.w300), + ), + ), + ), ) ], ), @@ -585,17 +1107,40 @@ class _home_screenState extends State { )), ), ), - ) - : Text("Empty"); - }, - ), + ); + }, + ) + : Container( + width: MediaQuery.of(context).size.width, + height: screenhight / 1.9, + child: Center( + child: FittedBox( + child: GestureDetector( + onTap: () { + gettask(context); + }, + child: Column( + children: [ + SvgPicture.asset( + 'assets/images/empty_todo.svg', + height: 200, + ), + const SizedBox( + height: 5, + ), + const Text( + "Add Some Task To Increase Your Productivity !!", + style: TextStyle(fontSize: 13), + ), + ], + ), + ), + ))), + + // second Container strts from here + ) ), - ), - ], - )), + ])), ); } } - -// showcupotinomodelpopup -// CupertinoActionSheet diff --git a/lib/utilities/firebase_database.dart b/lib/utilities/firebase_database.dart index cdb4ea7..f5b9de1 100644 --- a/lib/utilities/firebase_database.dart +++ b/lib/utilities/firebase_database.dart @@ -1,7 +1,10 @@ import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:firebase_auth/firebase_auth.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; import 'package:todo/models/model.dart'; import 'package:todo/screens/bottomsheet_addtask.dart'; +import 'package:todo/screens/home_screen.dart'; final FirebaseFirestore store = FirebaseFirestore.instance; final CollectionReference reference = store.collection("Users"); @@ -54,21 +57,60 @@ class FirebaseStore { return a; } - static Future Savetask(NoteModel note, String date) async { + static Future> Savetask(NoteModel note, String date) async { try { - await FirebaseFirestore.instance + CollectionReference taskCollection = FirebaseFirestore.instance .collection("User") .doc(FirebaseAuth.instance.currentUser!.uid) - .collection("Task") - // .doc(date) - .add(note.toMap()); - return true; + .collection("Task"); + + DocumentReference docRef = await taskCollection.add(note.toMap()); + + String docId = docRef.id; + print("Document ID: $docId"); + + // Update the document with the document ID + await docRef.update({'id': docId}); + + return [true, docId]; } on FirebaseAuthException catch (e) { - return e.code; + print("Firebase Auth Exception: ${e.code}"); + return [e.code]; } catch (e) { - return e; + print("An error occurred: $e"); + return [e.toString()]; + } + } + + static Future> GetDoneTask(String date) async { + try { + var querySnapshot = await FirebaseFirestore.instance + .collection("User") + .doc(FirebaseAuth.instance.currentUser!.uid) + .collection("Task") + .where('date', isEqualTo: date) + .where('isCompleted', isEqualTo: true) + .get(); + + List notes = []; + + if (querySnapshot.docs.isNotEmpty) { + querySnapshot.docs.forEach((doc) { + final info = doc.data() as Map; + NoteModel a = NoteModel.fromMap(info); + notes.add(a); + }); + } + + if (notes.isEmpty) { + print('No documents found for the specified date.'); + return []; + } + return notes; + } catch (e) { + print('An error occurred: $e'); + return []; // return an empty list or any other suitable action } - return null; } static Future> GetTask(String date) async { @@ -92,6 +134,7 @@ class FirebaseStore { if (notes.isEmpty) { print('No documents found for the specified date.'); + return []; } return notes; } catch (e) { @@ -99,4 +142,72 @@ class FirebaseStore { return []; // return an empty list or any other suitable action } } + + static Future Updatask( + NoteModel task, String docId, String userId) async { + try { + print(docId); + DocumentReference ref = FirebaseFirestore.instance + .collection("User") + .doc(userId) + .collection("Task") + .doc(docId); + + DocumentSnapshot snapshot = await ref.get(); + if (!snapshot.exists) { + throw Exception("Document does not exist"); + } + + await ref.update(task.toMap()); + return true; + } catch (e) { + print('An error occurred: $e'); + return false; + } + } + + static Future DeleteTask(String docId, String userId) async { + try { + DocumentReference ref = FirebaseFirestore.instance + .collection("User") + .doc(userId) + .collection("Task") + .doc(docId); + await ref.delete(); + return true; + } catch (e) { + print('An error occurred: $e'); + } + return false; + } + + static Future MarkasRead(String docId, String userId, String time) async { + try { + DocumentReference ref = FirebaseFirestore.instance + .collection("User") + .doc(userId) + .collection("Task") + .doc(docId); + await ref.update({'isCompleted': true, + 'completedTime': time}); + return true; + } catch (e) { + print('An error occurred: $e'); + } + return false; + } + + static Future SendMailVerification() async { + try { + await FirebaseAuth.instance.currentUser!.sendEmailVerification(); + print("Mail Send"); + return true; + } on FirebaseAuthException catch (e) { + return e.code; + } catch (e) { + return e; + } + } + + // static Future MarkasRead() async {} } diff --git a/lib/utilities/notification_service.dart b/lib/utilities/notification_service.dart new file mode 100644 index 0000000..487da07 --- /dev/null +++ b/lib/utilities/notification_service.dart @@ -0,0 +1,24 @@ +import 'package:flutter_local_notifications/flutter_local_notifications.dart'; + +class NotificationSerice { + final FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin = + FlutterLocalNotificationsPlugin(); + + Future initNotification() async { + AndroidInitializationSettings initializationSettingsAndroid = + AndroidInitializationSettings('launcher.png'); + + var initializationSettingsIOS = DarwinInitializationSettings( + requestAlertPermission: true, + requestBadgePermission: true, + requestSoundPermission: true, + onDidReceiveLocalNotification: (id, title, body, payload) async {}, + ); + + var initializationSettings = InitializationSettings( + android: initializationSettingsAndroid, iOS: initializationSettingsIOS); + await _flutterLocalNotificationsPlugin.initialize(initializationSettings, onDidReceiveNotificationResponse: (NotificationResponse notificationResponse) async {}); + } + + +} diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 3ba4b5e..8e4093b 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -8,11 +8,13 @@ import Foundation import cloud_firestore import firebase_auth import firebase_core +import flutter_local_notifications import shared_preferences_foundation func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { FLTFirebaseFirestorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseFirestorePlugin")) FLTFirebaseAuthPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAuthPlugin")) FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin")) + FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) } diff --git a/pubspec.lock b/pubspec.lock index 8298e1f..1212f44 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -129,6 +129,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.6" + dbus: + dependency: transitive + description: + name: dbus + sha256: "6f07cba3f7b3448d42d015bfd3d53fe12e5b36da2423f23838efc1d5fb31a263" + url: "https://pub.dev" + source: hosted + version: "0.7.8" fake_async: dependency: transitive description: @@ -222,6 +230,30 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.3" + flutter_local_notifications: + dependency: "direct main" + description: + name: flutter_local_notifications + sha256: "6d11ea777496061e583623aaf31923f93a9409ef8fcaeeefdd6cd78bf4fe5bb3" + url: "https://pub.dev" + source: hosted + version: "16.1.0" + flutter_local_notifications_linux: + dependency: transitive + description: + name: flutter_local_notifications_linux + sha256: "33f741ef47b5f63cc7f78fe75eeeac7e19f171ff3c3df054d84c1e38bedb6a03" + url: "https://pub.dev" + source: hosted + version: "4.0.0+1" + flutter_local_notifications_platform_interface: + dependency: transitive + description: + name: flutter_local_notifications_platform_interface + sha256: "7cf643d6d5022f3baed0be777b0662cce5919c0a7b86e700299f22dc4ae660ef" + url: "https://pub.dev" + source: hosted + version: "7.0.0+1" flutter_spinkit: dependency: "direct main" description: @@ -248,6 +280,14 @@ packages: description: flutter source: sdk version: "0.0.0" + fluttertoast: + dependency: "direct main" + description: + name: fluttertoast + sha256: "474f7d506230897a3cd28c965ec21c5328ae5605fc9c400cd330e9e9d6ac175c" + url: "https://pub.dev" + source: hosted + version: "8.2.2" glob: dependency: transitive description: @@ -605,6 +645,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.6.0" + timezone: + dependency: transitive + description: + name: timezone + sha256: "1cfd8ddc2d1cfd836bc93e67b9be88c3adaeca6f40a00ca999104c30693cdca0" + url: "https://pub.dev" + source: hosted + version: "0.9.2" typed_data: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index ec967be..deb5b65 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -47,6 +47,8 @@ dependencies: google_sign_in: ^6.1.5 googleapis: ^11.4.0 googleapis_auth: ^1.4.1 + fluttertoast: ^8.2.2 + flutter_local_notifications: ^16.1.0 dev_dependencies: flutter_test: