diff --git a/.vscode/launch.json b/.vscode/launch.json index 01e4634..afddeed 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,6 +1,18 @@ { "version": "0.2.0", "configurations": [ + { + "name": "Prod", + "request": "launch", + "type": "dart", + "program": "lib/main-prod.dart", + "args": [ + "-t", + "lib/main-prod.dart", + "--flavor", + "prod" + ], + }, { "name": "Local Dev", "request": "launch", @@ -12,7 +24,7 @@ "--flavor", "dev" ], - }, + }, { "name": "Dev", "request": "launch", @@ -44,19 +56,16 @@ "-t", "lib/main-dev.dart", ], - }, - + }, { - "name": "Pro", + "name": "Prod iOS", "request": "launch", "type": "dart", "program": "lib/main-prod.dart", "args": [ "-t", "lib/main-prod.dart", - "--flavor", - "prod" ], - }, + }, ] } \ No newline at end of file diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index f617e89..e32dd3b 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -39,14 +39,5 @@ - - - diff --git a/android/settings_aar.gradle b/android/settings_aar.gradle new file mode 100644 index 0000000..e7b4def --- /dev/null +++ b/android/settings_aar.gradle @@ -0,0 +1 @@ +include ':app' diff --git a/assets/FirstName&LastName_.jpeg b/assets/FirstName&LastName_.jpeg deleted file mode 100644 index 8f1c6ae..0000000 Binary files a/assets/FirstName&LastName_.jpeg and /dev/null differ diff --git a/assets/Fullname_.jpeg b/assets/Fullname_.jpeg deleted file mode 100644 index fbaa0e2..0000000 Binary files a/assets/Fullname_.jpeg and /dev/null differ diff --git a/assets/MyMMUnicodeUniversal.ttf b/assets/MyMMUnicodeUniversal.ttf deleted file mode 100644 index 128085b..0000000 Binary files a/assets/MyMMUnicodeUniversal.ttf and /dev/null differ diff --git a/assets/address.png b/assets/address.png deleted file mode 100644 index ae42728..0000000 Binary files a/assets/address.png and /dev/null differ diff --git a/assets/admin.png b/assets/admin.png deleted file mode 100644 index 294efd3..0000000 Binary files a/assets/admin.png and /dev/null differ diff --git a/assets/amazon_ins.png b/assets/amazon_ins.png deleted file mode 100644 index 4281986..0000000 Binary files a/assets/amazon_ins.png and /dev/null differ diff --git a/assets/amount.png b/assets/amount.png deleted file mode 100644 index 5e3f1fc..0000000 Binary files a/assets/amount.png and /dev/null differ diff --git a/assets/approve.png b/assets/approve.png deleted file mode 100644 index a58d32f..0000000 Binary files a/assets/approve.png and /dev/null differ diff --git a/assets/block.png b/assets/block.png deleted file mode 100644 index 9070fd0..0000000 Binary files a/assets/block.png and /dev/null differ diff --git a/assets/buyer.png b/assets/buyer.png deleted file mode 100644 index 881b91d..0000000 Binary files a/assets/buyer.png and /dev/null differ diff --git a/assets/FirstName&LastName.png b/assets/buying_online_with_first_last_name.png similarity index 100% rename from assets/FirstName&LastName.png rename to assets/buying_online_with_first_last_name.png diff --git a/assets/Fullname.png b/assets/buying_online_with_full_name.png similarity index 100% rename from assets/Fullname.png rename to assets/buying_online_with_full_name.png diff --git a/assets/date_filter.png b/assets/date_filter.png deleted file mode 100644 index 537c2e3..0000000 Binary files a/assets/date_filter.png and /dev/null differ diff --git a/assets/demo.pdf b/assets/demo.pdf deleted file mode 100644 index 7d40327..0000000 --- a/assets/demo.pdf +++ /dev/null @@ -1,51897 +0,0 @@ -%PDF-1.3 -% -6 0 obj -<< -/Type /Page -/Parent 1 0 R -/MediaBox [0 0 612 792] -/Contents 4 0 R -/Resources 5 0 R ->> -endobj -5 0 obj -<< -/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] -/Font << -/F2 7 0 R -/F3 9 0 R ->> ->> -endobj -4 0 obj -<< -/Length 186 -/Filter /FlateDecode ->> -stream -x10 E_IH( lHC[ց/m@K,1Y\UuS$g+8rȃZ-Aic! -,8 A:2ƮX*&3A:~ffm=vh)6a5gD*A~vf֗ζ|"e5] ' q]eQMq0X -endstream -endobj -14 0 obj -<< -/S /URI -/URI (false) ->> -endobj -15 0 obj -<< -/Subtype /Link -/A 14 0 R -/Type /Annot -/Rect [72 685.975 366.225 720] -/Border [0 0 0] ->> -endobj -17 0 obj -<< -/S /URI -/URI (false) ->> -endobj -18 0 obj -<< -/Subtype /Link -/A 17 0 R -/Type /Annot -/Rect [72 646.477 159.516 670.975] -/Border [0 0 0] ->> -endobj -19 0 obj -<< -/S /URI -/URI (false) ->> -endobj -20 0 obj -<< -/Subtype /Link -/A 19 0 R -/Type /Annot -/Rect [72 623.977 176.6875 636.477] -/Border [0 0 0] ->> -endobj -21 0 obj -<< -/S /URI -/URI (http://npmjs.org/) ->> -endobj -22 0 obj -<< -/Subtype /Link -/A 21 0 R -/Type /Annot -/Rect [176.6875 623.977 200.076172 636.477] -/Border [0 0 0] ->> -endobj -23 0 obj -<< -/S /URI -/URI (false) ->> -endobj -24 0 obj -<< -/Subtype /Link -/A 23 0 R -/Type /Annot -/Rect [200.076172 623.977 489.832031 636.477] -/Border [0 0 0] ->> -endobj -25 0 obj -<< -/S /URI -/URI (false) ->> -endobj -26 0 obj -<< -/Subtype /Link -/A 25 0 R -/Type /Annot -/Rect [72 611.477 149.299805 623.977] -/Border [0 0 0] ->> -endobj -27 0 obj -<< -/S /URI -/URI (false) ->> -endobj -28 0 obj -<< -/Subtype /Link -/A 27 0 R -/Type /Annot -/Rect [72 590.164 88.2 601.477] -/Border [0 0 0] ->> -endobj -30 0 obj -<< -/S /URI -/URI (false) ->> -endobj -31 0 obj -<< -/Subtype /Link -/A 30 0 R -/Type /Annot -/Rect [88.2 590.164 93.6 601.477] -/Border [0 0 0] ->> -endobj -32 0 obj -<< -/S /URI -/URI (false) ->> -endobj -33 0 obj -<< -/Subtype /Link -/A 32 0 R -/Type /Annot -/Rect [93.6 590.164 131.4 601.477] -/Border [0 0 0] ->> -endobj -34 0 obj -<< -/S /URI -/URI (false) ->> -endobj -35 0 obj -<< -/Subtype /Link -/A 34 0 R -/Type /Annot -/Rect [131.4 590.164 136.8 601.477] -/Border [0 0 0] ->> -endobj -36 0 obj -<< -/S /URI -/URI (false) ->> -endobj -37 0 obj -<< -/Subtype /Link -/A 36 0 R -/Type /Annot -/Rect [136.8 590.164 169.2 601.477] -/Border [0 0 0] ->> -endobj -38 0 obj -<< -/S /URI -/URI (false) ->> -endobj -39 0 obj -<< -/Subtype /Link -/A 38 0 R -/Type /Annot -/Rect [72 555.666 229.122 580.164] -/Border [0 0 0] ->> -endobj -40 0 obj -<< -/S /URI -/URI (false) ->> -endobj -41 0 obj -<< -/Subtype /Link -/A 40 0 R -/Type /Annot -/Rect [72 533.166 374.041016 545.666] -/Border [0 0 0] ->> -endobj -42 0 obj -<< -/S /URI -/URI (false) ->> -endobj -43 0 obj -<< -/Subtype /Link -/A 42 0 R -/Type /Annot -/Rect [374.041016 533.096 410.041016 545.666] -/Border [0 0 0] ->> -endobj -45 0 obj -<< -/S /URI -/URI (false) ->> -endobj -46 0 obj -<< -/Subtype /Link -/A 45 0 R -/Type /Annot -/Rect [410.041016 533.166 490.412109 545.666] -/Border [0 0 0] ->> -endobj -47 0 obj -<< -/S /URI -/URI (false) ->> -endobj -48 0 obj -<< -/Subtype /Link -/A 47 0 R -/Type /Annot -/Rect [72 520.666 324.905273 533.166] -/Border [0 0 0] ->> -endobj -49 0 obj -<< -/S /URI -/URI (false) ->> -endobj -50 0 obj -<< -/Subtype /Link -/A 49 0 R -/Type /Annot -/Rect [324.905273 520.596 390.905273 533.166] -/Border [0 0 0] ->> -endobj -51 0 obj -<< -/S /URI -/URI (false) ->> -endobj -52 0 obj -<< -/Subtype /Link -/A 51 0 R -/Type /Annot -/Rect [390.905273 520.666 421.242188 533.166] -/Border [0 0 0] ->> -endobj -53 0 obj -<< -/S /URI -/URI (false) ->> -endobj -54 0 obj -<< -/Subtype /Link -/A 53 0 R -/Type /Annot -/Rect [72 499.353 99 510.666] -/Border [0 0 0] ->> -endobj -55 0 obj -<< -/S /URI -/URI (false) ->> -endobj -56 0 obj -<< -/Subtype /Link -/A 55 0 R -/Type /Annot -/Rect [99 499.353 104.4 510.666] -/Border [0 0 0] ->> -endobj -57 0 obj -<< -/S /URI -/URI (false) ->> -endobj -58 0 obj -<< -/Subtype /Link -/A 57 0 R -/Type /Annot -/Rect [104.4 499.353 163.8 510.666] -/Border [0 0 0] ->> -endobj -59 0 obj -<< -/S /URI -/URI (false) ->> -endobj -60 0 obj -<< -/Subtype /Link -/A 59 0 R -/Type /Annot -/Rect [163.8 499.353 169.2 510.666] -/Border [0 0 0] ->> -endobj -61 0 obj -<< -/S /URI -/URI (false) ->> -endobj -62 0 obj -<< -/Subtype /Link -/A 61 0 R -/Type /Annot -/Rect [169.2 499.353 174.6 510.666] -/Border [0 0 0] ->> -endobj -63 0 obj -<< -/S /URI -/URI (false) ->> -endobj -64 0 obj -<< -/Subtype /Link -/A 63 0 R -/Type /Annot -/Rect [174.6 499.353 180 510.666] -/Border [0 0 0] ->> -endobj -65 0 obj -<< -/S /URI -/URI (false) ->> -endobj -66 0 obj -<< -/Subtype /Link -/A 65 0 R -/Type /Annot -/Rect [180 499.353 217.8 510.666] -/Border [0 0 0] ->> -endobj -67 0 obj -<< -/S /URI -/URI (false) ->> -endobj -68 0 obj -<< -/Subtype /Link -/A 67 0 R -/Type /Annot -/Rect [217.8 499.353 223.2 510.666] -/Border [0 0 0] ->> -endobj -69 0 obj -<< -/S /URI -/URI (false) ->> -endobj -70 0 obj -<< -/Subtype /Link -/A 69 0 R -/Type /Annot -/Rect [223.2 499.353 266.4 510.666] -/Border [0 0 0] ->> -endobj -71 0 obj -<< -/S /URI -/URI (false) ->> -endobj -72 0 obj -<< -/Subtype /Link -/A 71 0 R -/Type /Annot -/Rect [266.4 499.353 271.8 510.666] -/Border [0 0 0] ->> -endobj -73 0 obj -<< -/S /URI -/URI (false) ->> -endobj -74 0 obj -<< -/Subtype /Link -/A 73 0 R -/Type /Annot -/Rect [271.8 499.353 277.2 510.666] -/Border [0 0 0] ->> -endobj -75 0 obj -<< -/S /URI -/URI (false) ->> -endobj -76 0 obj -<< -/Subtype /Link -/A 75 0 R -/Type /Annot -/Rect [72 488.04 99 499.353] -/Border [0 0 0] ->> -endobj -77 0 obj -<< -/S /URI -/URI (false) ->> -endobj -78 0 obj -<< -/Subtype /Link -/A 77 0 R -/Type /Annot -/Rect [99 488.04 104.4 499.353] -/Border [0 0 0] ->> -endobj -79 0 obj -<< -/S /URI -/URI (false) ->> -endobj -80 0 obj -<< -/Subtype /Link -/A 79 0 R -/Type /Annot -/Rect [104.4 488.04 120.6 499.353] -/Border [0 0 0] ->> -endobj -81 0 obj -<< -/S /URI -/URI (false) ->> -endobj -82 0 obj -<< -/Subtype /Link -/A 81 0 R -/Type /Annot -/Rect [120.6 488.04 126 499.353] -/Border [0 0 0] ->> -endobj -83 0 obj -<< -/S /URI -/URI (false) ->> -endobj -84 0 obj -<< -/Subtype /Link -/A 83 0 R -/Type /Annot -/Rect [126 488.04 131.4 499.353] -/Border [0 0 0] ->> -endobj -85 0 obj -<< -/S /URI -/URI (false) ->> -endobj -86 0 obj -<< -/Subtype /Link -/A 85 0 R -/Type /Annot -/Rect [131.4 488.04 136.8 499.353] -/Border [0 0 0] ->> -endobj -87 0 obj -<< -/S /URI -/URI (false) ->> -endobj -88 0 obj -<< -/Subtype /Link -/A 87 0 R -/Type /Annot -/Rect [136.8 488.04 153 499.353] -/Border [0 0 0] ->> -endobj -89 0 obj -<< -/S /URI -/URI (false) ->> -endobj -90 0 obj -<< -/Subtype /Link -/A 89 0 R -/Type /Annot -/Rect [153 488.04 158.4 499.353] -/Border [0 0 0] ->> -endobj -91 0 obj -<< -/S /URI -/URI (false) ->> -endobj -92 0 obj -<< -/Subtype /Link -/A 91 0 R -/Type /Annot -/Rect [158.4 488.04 217.8 499.353] -/Border [0 0 0] ->> -endobj -93 0 obj -<< -/S /URI -/URI (false) ->> -endobj -94 0 obj -<< -/Subtype /Link -/A 93 0 R -/Type /Annot -/Rect [217.8 488.04 223.2 499.353] -/Border [0 0 0] ->> -endobj -95 0 obj -<< -/S /URI -/URI (false) ->> -endobj -96 0 obj -<< -/Subtype /Link -/A 95 0 R -/Type /Annot -/Rect [72 465.47 138 478.04] -/Border [0 0 0] ->> -endobj -97 0 obj -<< -/S /URI -/URI (false) ->> -endobj -98 0 obj -<< -/Subtype /Link -/A 97 0 R -/Type /Annot -/Rect [138 465.54 485.890625 478.04] -/Border [0 0 0] ->> -endobj -99 0 obj -<< -/S /URI -/URI (false) ->> -endobj -100 0 obj -<< -/Subtype /Link -/A 99 0 R -/Type /Annot -/Rect [72 453.04 245.452148 465.54] -/Border [0 0 0] ->> -endobj -101 0 obj -<< -/S /URI -/URI (false) ->> -endobj -102 0 obj -<< -/Subtype /Link -/A 101 0 R -/Type /Annot -/Rect [245.452148 452.97 269.452148 465.54] -/Border [0 0 0] ->> -endobj -103 0 obj -<< -/S /URI -/URI (false) ->> -endobj -104 0 obj -<< -/Subtype /Link -/A 103 0 R -/Type /Annot -/Rect [269.452148 453.04 528.084961 465.54] -/Border [0 0 0] ->> -endobj -105 0 obj -<< -/S /URI -/URI (false) ->> -endobj -106 0 obj -<< -/Subtype /Link -/A 105 0 R -/Type /Annot -/Rect [72 440.54 531.765625 453.04] -/Border [0 0 0] ->> -endobj -107 0 obj -<< -/S /URI -/URI (false) ->> -endobj -108 0 obj -<< -/Subtype /Link -/A 107 0 R -/Type /Annot -/Rect [72 428.04 111.272461 440.54] -/Border [0 0 0] ->> -endobj -109 0 obj -<< -/S /URI -/URI (false) ->> -endobj -110 0 obj -<< -/Subtype /Link -/A 109 0 R -/Type /Annot -/Rect [111.272461 427.97 129.272461 440.54] -/Border [0 0 0] ->> -endobj -111 0 obj -<< -/S /URI -/URI (false) ->> -endobj -112 0 obj -<< -/Subtype /Link -/A 111 0 R -/Type /Annot -/Rect [129.272461 428.04 510.810547 440.54] -/Border [0 0 0] ->> -endobj -113 0 obj -<< -/S /URI -/URI (false) ->> -endobj -114 0 obj -<< -/Subtype /Link -/A 113 0 R -/Type /Annot -/Rect [72 415.54 150.276367 428.04] -/Border [0 0 0] ->> -endobj -115 0 obj -<< -/S /URI -/URI (false) ->> -endobj -116 0 obj -<< -/Subtype /Link -/A 115 0 R -/Type /Annot -/Rect [72 394.227 88.2 405.54] -/Border [0 0 0] ->> -endobj -117 0 obj -<< -/S /URI -/URI (false) ->> -endobj -118 0 obj -<< -/Subtype /Link -/A 117 0 R -/Type /Annot -/Rect [88.2 394.227 93.6 405.54] -/Border [0 0 0] ->> -endobj -119 0 obj -<< -/S /URI -/URI (false) ->> -endobj -120 0 obj -<< -/Subtype /Link -/A 119 0 R -/Type /Annot -/Rect [93.6 394.227 115.2 405.54] -/Border [0 0 0] ->> -endobj -121 0 obj -<< -/S /URI -/URI (false) ->> -endobj -122 0 obj -<< -/Subtype /Link -/A 121 0 R -/Type /Annot -/Rect [115.2 394.227 120.6 405.54] -/Border [0 0 0] ->> -endobj -123 0 obj -<< -/S /URI -/URI (false) ->> -endobj -124 0 obj -<< -/Subtype /Link -/A 123 0 R -/Type /Annot -/Rect [120.6 394.227 131.4 405.54] -/Border [0 0 0] ->> -endobj -125 0 obj -<< -/S /URI -/URI (false) ->> -endobj -126 0 obj -<< -/Subtype /Link -/A 125 0 R -/Type /Annot -/Rect [131.4 394.227 136.8 405.54] -/Border [0 0 0] ->> -endobj -127 0 obj -<< -/S /URI -/URI (false) ->> -endobj -128 0 obj -<< -/Subtype /Link -/A 127 0 R -/Type /Annot -/Rect [136.8 394.227 228.6 405.54] -/Border [0 0 0] ->> -endobj -129 0 obj -<< -/S /URI -/URI (false) ->> -endobj -130 0 obj -<< -/Subtype /Link -/A 129 0 R -/Type /Annot -/Rect [228.6 394.227 234 405.54] -/Border [0 0 0] ->> -endobj -131 0 obj -<< -/S /URI -/URI (false) ->> -endobj -132 0 obj -<< -/Subtype /Link -/A 131 0 R -/Type /Annot -/Rect [234 394.227 336.6 405.54] -/Border [0 0 0] ->> -endobj -133 0 obj -<< -/S /URI -/URI (false) ->> -endobj -134 0 obj -<< -/Subtype /Link -/A 133 0 R -/Type /Annot -/Rect [336.6 394.227 342 405.54] -/Border [0 0 0] ->> -endobj -135 0 obj -<< -/S /URI -/URI (false) ->> -endobj -136 0 obj -<< -/Subtype /Link -/A 135 0 R -/Type /Annot -/Rect [342 394.227 347.4 405.54] -/Border [0 0 0] ->> -endobj -137 0 obj -<< -/S /URI -/URI (false) ->> -endobj -138 0 obj -<< -/Subtype /Link -/A 137 0 R -/Type /Annot -/Rect [347.4 394.227 352.8 405.54] -/Border [0 0 0] ->> -endobj -139 0 obj -<< -/S /URI -/URI (false) ->> -endobj -140 0 obj -<< -/Subtype /Link -/A 139 0 R -/Type /Annot -/Rect [352.8 394.227 358.2 405.54] -/Border [0 0 0] ->> -endobj -141 0 obj -<< -/S /URI -/URI (false) ->> -endobj -142 0 obj -<< -/Subtype /Link -/A 141 0 R -/Type /Annot -/Rect [358.2 394.227 439.2 405.54] -/Border [0 0 0] ->> -endobj -143 0 obj -<< -/S /URI -/URI (false) ->> -endobj -144 0 obj -<< -/Subtype /Link -/A 143 0 R -/Type /Annot -/Rect [72 382.914 88.2 394.227] -/Border [0 0 0] ->> -endobj -145 0 obj -<< -/S /URI -/URI (false) ->> -endobj -146 0 obj -<< -/Subtype /Link -/A 145 0 R -/Type /Annot -/Rect [88.2 382.914 93.6 394.227] -/Border [0 0 0] ->> -endobj -147 0 obj -<< -/S /URI -/URI (false) ->> -endobj -148 0 obj -<< -/Subtype /Link -/A 147 0 R -/Type /Annot -/Rect [93.6 382.914 115.2 394.227] -/Border [0 0 0] ->> -endobj -149 0 obj -<< -/S /URI -/URI (false) ->> -endobj -150 0 obj -<< -/Subtype /Link -/A 149 0 R -/Type /Annot -/Rect [115.2 382.914 120.6 394.227] -/Border [0 0 0] ->> -endobj -151 0 obj -<< -/S /URI -/URI (false) ->> -endobj -152 0 obj -<< -/Subtype /Link -/A 151 0 R -/Type /Annot -/Rect [120.6 382.914 136.8 394.227] -/Border [0 0 0] ->> -endobj -153 0 obj -<< -/S /URI -/URI (false) ->> -endobj -154 0 obj -<< -/Subtype /Link -/A 153 0 R -/Type /Annot -/Rect [136.8 382.914 142.2 394.227] -/Border [0 0 0] ->> -endobj -155 0 obj -<< -/S /URI -/URI (false) ->> -endobj -156 0 obj -<< -/Subtype /Link -/A 155 0 R -/Type /Annot -/Rect [142.2 382.914 147.6 394.227] -/Border [0 0 0] ->> -endobj -157 0 obj -<< -/S /URI -/URI (false) ->> -endobj -158 0 obj -<< -/Subtype /Link -/A 157 0 R -/Type /Annot -/Rect [147.6 382.914 358.2 394.227] -/Border [0 0 0] ->> -endobj -159 0 obj -<< -/S /URI -/URI (false) ->> -endobj -160 0 obj -<< -/Subtype /Link -/A 159 0 R -/Type /Annot -/Rect [358.2 382.914 444.6 394.227] -/Border [0 0 0] ->> -endobj -161 0 obj -<< -/S /URI -/URI (false) ->> -endobj -162 0 obj -<< -/Subtype /Link -/A 161 0 R -/Type /Annot -/Rect [72 360.288 379.8 371.601] -/Border [0 0 0] ->> -endobj -163 0 obj -<< -/S /URI -/URI (false) ->> -endobj -164 0 obj -<< -/Subtype /Link -/A 163 0 R -/Type /Annot -/Rect [72 337.662 277.2 348.975] -/Border [0 0 0] ->> -endobj -165 0 obj -<< -/S /URI -/URI (false) ->> -endobj -166 0 obj -<< -/Subtype /Link -/A 165 0 R -/Type /Annot -/Rect [72 326.349 88.2 337.662] -/Border [0 0 0] ->> -endobj -167 0 obj -<< -/S /URI -/URI (false) ->> -endobj -168 0 obj -<< -/Subtype /Link -/A 167 0 R -/Type /Annot -/Rect [88.2 326.349 93.6 337.662] -/Border [0 0 0] ->> -endobj -169 0 obj -<< -/S /URI -/URI (false) ->> -endobj -170 0 obj -<< -/Subtype /Link -/A 169 0 R -/Type /Annot -/Rect [93.6 326.349 109.8 337.662] -/Border [0 0 0] ->> -endobj -171 0 obj -<< -/S /URI -/URI (false) ->> -endobj -172 0 obj -<< -/Subtype /Link -/A 171 0 R -/Type /Annot -/Rect [109.8 326.349 115.2 337.662] -/Border [0 0 0] ->> -endobj -173 0 obj -<< -/S /URI -/URI (false) ->> -endobj -174 0 obj -<< -/Subtype /Link -/A 173 0 R -/Type /Annot -/Rect [115.2 326.349 120.6 337.662] -/Border [0 0 0] ->> -endobj -175 0 obj -<< -/S /URI -/URI (false) ->> -endobj -176 0 obj -<< -/Subtype /Link -/A 175 0 R -/Type /Annot -/Rect [120.6 326.349 126 337.662] -/Border [0 0 0] ->> -endobj -177 0 obj -<< -/S /URI -/URI (false) ->> -endobj -178 0 obj -<< -/Subtype /Link -/A 177 0 R -/Type /Annot -/Rect [72 303.849 93.201172 316.349] -/Border [0 0 0] ->> -endobj -179 0 obj -<< -/S /URI -/URI (false) ->> -endobj -180 0 obj -<< -/Subtype /Link -/A 179 0 R -/Type /Annot -/Rect [93.201172 303.779 123.201172 316.349] -/Border [0 0 0] ->> -endobj -181 0 obj -<< -/S /URI -/URI (false) ->> -endobj -182 0 obj -<< -/Subtype /Link -/A 181 0 R -/Type /Annot -/Rect [123.201172 303.849 146.912109 316.349] -/Border [0 0 0] ->> -endobj -183 0 obj -<< -/S /URI -/URI (false) ->> -endobj -184 0 obj -<< -/Subtype /Link -/A 183 0 R -/Type /Annot -/Rect [146.912109 303.779 182.912109 316.349] -/Border [0 0 0] ->> -endobj -185 0 obj -<< -/S /URI -/URI (false) ->> -endobj -186 0 obj -<< -/Subtype /Link -/A 185 0 R -/Type /Annot -/Rect [182.912109 303.849 506.325195 316.349] -/Border [0 0 0] ->> -endobj -12 0 obj -<< -/Type /Page -/Parent 1 0 R -/MediaBox [0 0 612 792] -/Contents 10 0 R -/Resources 11 0 R -/Annots [15 0 R 18 0 R 20 0 R 22 0 R 24 0 R 26 0 R 28 0 R 31 0 R 33 0 R 35 0 R 37 0 R 39 0 R 41 0 R 43 0 R 46 0 R 48 0 R 50 0 R 52 0 R 54 0 R 56 0 R 58 0 R 60 0 R 62 0 R 64 0 R 66 0 R 68 0 R 70 0 R 72 0 R 74 0 R 76 0 R 78 0 R 80 0 R 82 0 R 84 0 R 86 0 R 88 0 R 90 0 R 92 0 R 94 0 R 96 0 R 98 0 R 100 0 R 102 0 R 104 0 R 106 0 R 108 0 R 110 0 R 112 0 R 114 0 R 116 0 R 118 0 R 120 0 R 122 0 R 124 0 R 126 0 R 128 0 R 130 0 R 132 0 R 134 0 R 136 0 R 138 0 R 140 0 R 142 0 R 144 0 R 146 0 R 148 0 R 150 0 R 152 0 R 154 0 R 156 0 R 158 0 R 160 0 R 162 0 R 164 0 R 166 0 R 168 0 R 170 0 R 172 0 R 174 0 R 176 0 R 178 0 R 180 0 R 182 0 R 184 0 R 186 0 R] ->> -endobj -11 0 obj -<< -/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] -/Font << -/F4 16 0 R -/F3 9 0 R -/F5 29 0 R -/F6 44 0 R ->> ->> -endobj -10 0 obj -<< -/Length 1881 -/Filter /FlateDecode ->> -stream -x[Ko6WT b>ZV8C  f"NVf"oSw_8_׃*׿>s7~yy\4#~2'ih& Kç|LHg~/thStO~|:-ػy%x%r#b0(iuWgB݁ C'e܌LUwQA e -v? ,=W*[w&Y:vry԰zMf{`E0%Vq$I1IB -Kn"3=LzئRB EN͐2ɱWI,ƪNVON]ClLaX[ód=09+j\&~GQ'܄e)iŽX y@@>q!g2e{ld>x͊S31~?f,6A6s6ޚ8 W.ݑ4!g2zXf:^#Z # h~dbV$2lvkLF~ F72J> 逓FZTU[̞&goȵ:J7Ȧ*8a+]Z:>,/jZqן;H5Z :Ovɧj? -6<0jl3\>wB~:_obh,z](Ջ*&A:lv:*hQȕcn G|0I)5ڠˆQƆJT2_ޮvx];ƺKI_TYY3"%^D,gݦҀ"XQy9STl1%,vB$$Tneo2MJJ]˙=.uVl;[jB=Y.~]B{'\f~!J[^(IfA(i28Gyłe K!ϢﳋGABw1cM8X{vpފm?zvtqs4@[ks\uuRڍz9}A# e[]RVbGNgXRyt[pLfq> 7YsmI+0z%YLț\o>p4M^:m}DS@dCTr1\"@1%rmz%MTGvz_W'uYy¯6+fG~mOoW&^"n1ڮWR_3|sQ (QJ7+8t ~vХΡK{.-p1|)qB ~ \n&_e֮% -Kzzj|3[ʾa]eosy͉ۊbF;:ݚSEs#K*%qֿ̈́)M&.-CMVC,%itgMRsxrÄW 8wZ"U!C ~/ -!^ ~ҵplգћJhnqH -4ibmˡ/&C̋}&34&\щ |u7[.BKn*;+_hpcR(r3b8­J~sCZΆ" -endstream -endobj -191 0 obj -<< -/S /URI -/URI (false) ->> -endobj -192 0 obj -<< -/Subtype /Link -/A 191 0 R -/Type /Annot -/Rect [72 695.502 285.624 720] -/Border [0 0 0] ->> -endobj -193 0 obj -<< -/S /URI -/URI (false) ->> -endobj -194 0 obj -<< -/Subtype /Link -/A 193 0 R -/Type /Annot -/Rect [72 673.002 538.088867 685.502] -/Border [0 0 0] ->> -endobj -195 0 obj -<< -/S /URI -/URI (false) ->> -endobj -196 0 obj -<< -/Subtype /Link -/A 195 0 R -/Type /Annot -/Rect [72 660.502 297.742188 673.002] -/Border [0 0 0] ->> -endobj -197 0 obj -<< -/S /URI -/URI (http://browserify.org/) ->> -endobj -198 0 obj -<< -/Subtype /Link -/A 197 0 R -/Type /Annot -/Rect [297.742188 660.502 351.702148 673.002] -/Border [0 0 0] ->> -endobj -199 0 obj -<< -/S /URI -/URI (false) ->> -endobj -200 0 obj -<< -/Subtype /Link -/A 199 0 R -/Type /Annot -/Rect [351.702148 660.502 525.852539 673.002] -/Border [0 0 0] ->> -endobj -201 0 obj -<< -/S /URI -/URI (false) ->> -endobj -202 0 obj -<< -/Subtype /Link -/A 201 0 R -/Type /Annot -/Rect [72 648.002 238.025391 660.502] -/Border [0 0 0] ->> -endobj -203 0 obj -<< -/S /URI -/URI (false) ->> -endobj -204 0 obj -<< -/Subtype /Link -/A 203 0 R -/Type /Annot -/Rect [238.025391 647.932 280.025391 660.502] -/Border [0 0 0] ->> -endobj -205 0 obj -<< -/S /URI -/URI (false) ->> -endobj -206 0 obj -<< -/Subtype /Link -/A 205 0 R -/Type /Annot -/Rect [280.025391 648.002 529.200195 660.502] -/Border [0 0 0] ->> -endobj -207 0 obj -<< -/S /URI -/URI (false) ->> -endobj -208 0 obj -<< -/Subtype /Link -/A 207 0 R -/Type /Annot -/Rect [72 635.502 186.038086 648.002] -/Border [0 0 0] ->> -endobj -209 0 obj -<< -/S /URI -/URI (https://github.com/devongovett/pdfkit/releases) ->> -endobj -210 0 obj -<< -/Subtype /Link -/A 209 0 R -/Type /Annot -/Rect [186.038086 635.502 298.728516 648.002] -/Border [0 0 0] ->> -endobj -211 0 obj -<< -/S /URI -/URI (false) ->> -endobj -212 0 obj -<< -/Subtype /Link -/A 211 0 R -/Type /Annot -/Rect [298.728516 635.502 302.175781 648.002] -/Border [0 0 0] ->> -endobj -213 0 obj -<< -/S /URI -/URI (false) ->> -endobj -214 0 obj -<< -/Subtype /Link -/A 213 0 R -/Type /Annot -/Rect [72 613.002 516.760742 625.502] -/Border [0 0 0] ->> -endobj -215 0 obj -<< -/S /URI -/URI (false) ->> -endobj -216 0 obj -<< -/Subtype /Link -/A 215 0 R -/Type /Annot -/Rect [72 600.502 411.125977 613.002] -/Border [0 0 0] ->> -endobj -217 0 obj -<< -/S /URI -/URI (https://developer.mozilla.org/en-US/docs/Web/API/Blob) ->> -endobj -218 0 obj -<< -/Subtype /Link -/A 217 0 R -/Type /Annot -/Rect [411.125977 600.502 433.645508 613.002] -/Border [0 0 0] ->> -endobj -219 0 obj -<< -/S /URI -/URI (false) ->> -endobj -220 0 obj -<< -/Subtype /Link -/A 219 0 R -/Type /Annot -/Rect [433.645508 600.502 529.983398 613.002] -/Border [0 0 0] ->> -endobj -221 0 obj -<< -/S /URI -/URI (false) ->> -endobj -222 0 obj -<< -/Subtype /Link -/A 221 0 R -/Type /Annot -/Rect [72 588.002 483.166992 600.502] -/Border [0 0 0] ->> -endobj -223 0 obj -<< -/S /URI -/URI (false) ->> -endobj -224 0 obj -<< -/Subtype /Link -/A 223 0 R -/Type /Annot -/Rect [483.166992 587.932 519.166992 600.502] -/Border [0 0 0] ->> -endobj -225 0 obj -<< -/S /URI -/URI (false) ->> -endobj -226 0 obj -<< -/Subtype /Link -/A 225 0 R -/Type /Annot -/Rect [519.166992 588.002 538.136719 600.502] -/Border [0 0 0] ->> -endobj -227 0 obj -<< -/S /URI -/URI (false) ->> -endobj -228 0 obj -<< -/Subtype /Link -/A 227 0 R -/Type /Annot -/Rect [72 575.502 523.557617 588.002] -/Border [0 0 0] ->> -endobj -229 0 obj -<< -/S /URI -/URI (false) ->> -endobj -230 0 obj -<< -/Subtype /Link -/A 229 0 R -/Type /Annot -/Rect [72 553.002 173.152344 565.502] -/Border [0 0 0] ->> -endobj -231 0 obj -<< -/S /URI -/URI (false) ->> -endobj -232 0 obj -<< -/Subtype /Link -/A 231 0 R -/Type /Annot -/Rect [173.152344 552.932 239.152344 565.502] -/Border [0 0 0] ->> -endobj -233 0 obj -<< -/S /URI -/URI (false) ->> -endobj -234 0 obj -<< -/Subtype /Link -/A 233 0 R -/Type /Annot -/Rect [239.152344 553.002 357.414063 565.502] -/Border [0 0 0] ->> -endobj -235 0 obj -<< -/S /URI -/URI (https://github.com/devongovett/blob-stream) ->> -endobj -236 0 obj -<< -/Subtype /Link -/A 235 0 R -/Type /Annot -/Rect [357.414063 553.002 420.358398 565.502] -/Border [0 0 0] ->> -endobj -237 0 obj -<< -/S /URI -/URI (false) ->> -endobj -238 0 obj -<< -/Subtype /Link -/A 237 0 R -/Type /Annot -/Rect [420.358398 553.002 518.546875 565.502] -/Border [0 0 0] ->> -endobj -239 0 obj -<< -/S /URI -/URI (false) ->> -endobj -240 0 obj -<< -/Subtype /Link -/A 239 0 R -/Type /Annot -/Rect [72 540.502 527.239258 553.002] -/Border [0 0 0] ->> -endobj -241 0 obj -<< -/S /URI -/URI (false) ->> -endobj -242 0 obj -<< -/Subtype /Link -/A 241 0 R -/Type /Annot -/Rect [72 528.002 108.533203 540.502] -/Border [0 0 0] ->> -endobj -243 0 obj -<< -/S /URI -/URI (false) ->> -endobj -244 0 obj -<< -/Subtype /Link -/A 243 0 R -/Type /Annot -/Rect [108.533203 527.932 144.533203 540.502] -/Border [0 0 0] ->> -endobj -245 0 obj -<< -/S /URI -/URI (false) ->> -endobj -246 0 obj -<< -/Subtype /Link -/A 245 0 R -/Type /Annot -/Rect [144.533203 528.002 168.244141 540.502] -/Border [0 0 0] ->> -endobj -247 0 obj -<< -/S /URI -/URI (false) ->> -endobj -248 0 obj -<< -/Subtype /Link -/A 247 0 R -/Type /Annot -/Rect [168.244141 527.932 234.244141 540.502] -/Border [0 0 0] ->> -endobj -249 0 obj -<< -/S /URI -/URI (false) ->> -endobj -250 0 obj -<< -/Subtype /Link -/A 249 0 R -/Type /Annot -/Rect [234.244141 528.002 519.737305 540.502] -/Border [0 0 0] ->> -endobj -251 0 obj -<< -/S /URI -/URI (false) ->> -endobj -252 0 obj -<< -/Subtype /Link -/A 251 0 R -/Type /Annot -/Rect [72 515.502 279.158203 528.002] -/Border [0 0 0] ->> -endobj -253 0 obj -<< -/S /URI -/URI (false) ->> -endobj -254 0 obj -<< -/Subtype /Link -/A 253 0 R -/Type /Annot -/Rect [72 494.189 196.2 505.502] -/Border [0 0 0] ->> -endobj -255 0 obj -<< -/S /URI -/URI (false) ->> -endobj -256 0 obj -<< -/Subtype /Link -/A 255 0 R -/Type /Annot -/Rect [72 482.876 99 494.189] -/Border [0 0 0] ->> -endobj -257 0 obj -<< -/S /URI -/URI (false) ->> -endobj -258 0 obj -<< -/Subtype /Link -/A 257 0 R -/Type /Annot -/Rect [99 482.876 104.4 494.189] -/Border [0 0 0] ->> -endobj -259 0 obj -<< -/S /URI -/URI (false) ->> -endobj -260 0 obj -<< -/Subtype /Link -/A 259 0 R -/Type /Annot -/Rect [104.4 482.876 163.8 494.189] -/Border [0 0 0] ->> -endobj -261 0 obj -<< -/S /URI -/URI (false) ->> -endobj -262 0 obj -<< -/Subtype /Link -/A 261 0 R -/Type /Annot -/Rect [163.8 482.876 169.2 494.189] -/Border [0 0 0] ->> -endobj -263 0 obj -<< -/S /URI -/URI (false) ->> -endobj -264 0 obj -<< -/Subtype /Link -/A 263 0 R -/Type /Annot -/Rect [169.2 482.876 174.6 494.189] -/Border [0 0 0] ->> -endobj -265 0 obj -<< -/S /URI -/URI (false) ->> -endobj -266 0 obj -<< -/Subtype /Link -/A 265 0 R -/Type /Annot -/Rect [174.6 482.876 180 494.189] -/Border [0 0 0] ->> -endobj -267 0 obj -<< -/S /URI -/URI (false) ->> -endobj -268 0 obj -<< -/Subtype /Link -/A 267 0 R -/Type /Annot -/Rect [180 482.876 217.8 494.189] -/Border [0 0 0] ->> -endobj -269 0 obj -<< -/S /URI -/URI (false) ->> -endobj -270 0 obj -<< -/Subtype /Link -/A 269 0 R -/Type /Annot -/Rect [217.8 482.876 223.2 494.189] -/Border [0 0 0] ->> -endobj -271 0 obj -<< -/S /URI -/URI (false) ->> -endobj -272 0 obj -<< -/Subtype /Link -/A 271 0 R -/Type /Annot -/Rect [223.2 482.876 266.4 494.189] -/Border [0 0 0] ->> -endobj -273 0 obj -<< -/S /URI -/URI (false) ->> -endobj -274 0 obj -<< -/Subtype /Link -/A 273 0 R -/Type /Annot -/Rect [266.4 482.876 271.8 494.189] -/Border [0 0 0] ->> -endobj -275 0 obj -<< -/S /URI -/URI (false) ->> -endobj -276 0 obj -<< -/Subtype /Link -/A 275 0 R -/Type /Annot -/Rect [271.8 482.876 277.2 494.189] -/Border [0 0 0] ->> -endobj -277 0 obj -<< -/S /URI -/URI (false) ->> -endobj -278 0 obj -<< -/Subtype /Link -/A 277 0 R -/Type /Annot -/Rect [72 471.563 99 482.876] -/Border [0 0 0] ->> -endobj -279 0 obj -<< -/S /URI -/URI (false) ->> -endobj -280 0 obj -<< -/Subtype /Link -/A 279 0 R -/Type /Annot -/Rect [99 471.563 104.4 482.876] -/Border [0 0 0] ->> -endobj -281 0 obj -<< -/S /URI -/URI (false) ->> -endobj -282 0 obj -<< -/Subtype /Link -/A 281 0 R -/Type /Annot -/Rect [104.4 471.563 158.4 482.876] -/Border [0 0 0] ->> -endobj -283 0 obj -<< -/S /URI -/URI (false) ->> -endobj -284 0 obj -<< -/Subtype /Link -/A 283 0 R -/Type /Annot -/Rect [158.4 471.563 169.2 482.876] -/Border [0 0 0] ->> -endobj -285 0 obj -<< -/S /URI -/URI (false) ->> -endobj -286 0 obj -<< -/Subtype /Link -/A 285 0 R -/Type /Annot -/Rect [169.2 471.563 174.6 482.876] -/Border [0 0 0] ->> -endobj -287 0 obj -<< -/S /URI -/URI (false) ->> -endobj -288 0 obj -<< -/Subtype /Link -/A 287 0 R -/Type /Annot -/Rect [174.6 471.563 180 482.876] -/Border [0 0 0] ->> -endobj -289 0 obj -<< -/S /URI -/URI (false) ->> -endobj -290 0 obj -<< -/Subtype /Link -/A 289 0 R -/Type /Annot -/Rect [180 471.563 217.8 482.876] -/Border [0 0 0] ->> -endobj -291 0 obj -<< -/S /URI -/URI (false) ->> -endobj -292 0 obj -<< -/Subtype /Link -/A 291 0 R -/Type /Annot -/Rect [217.8 471.563 223.2 482.876] -/Border [0 0 0] ->> -endobj -293 0 obj -<< -/S /URI -/URI (false) ->> -endobj -294 0 obj -<< -/Subtype /Link -/A 293 0 R -/Type /Annot -/Rect [223.2 471.563 293.4 482.876] -/Border [0 0 0] ->> -endobj -295 0 obj -<< -/S /URI -/URI (false) ->> -endobj -296 0 obj -<< -/Subtype /Link -/A 295 0 R -/Type /Annot -/Rect [293.4 471.563 298.8 482.876] -/Border [0 0 0] ->> -endobj -297 0 obj -<< -/S /URI -/URI (false) ->> -endobj -298 0 obj -<< -/Subtype /Link -/A 297 0 R -/Type /Annot -/Rect [298.8 471.563 304.2 482.876] -/Border [0 0 0] ->> -endobj -299 0 obj -<< -/S /URI -/URI (false) ->> -endobj -300 0 obj -<< -/Subtype /Link -/A 299 0 R -/Type /Annot -/Rect [72 448.937 298.8 460.25] -/Border [0 0 0] ->> -endobj -301 0 obj -<< -/S /URI -/URI (false) ->> -endobj -302 0 obj -<< -/Subtype /Link -/A 301 0 R -/Type /Annot -/Rect [72 437.624 99 448.937] -/Border [0 0 0] ->> -endobj -303 0 obj -<< -/S /URI -/URI (false) ->> -endobj -304 0 obj -<< -/Subtype /Link -/A 303 0 R -/Type /Annot -/Rect [99 437.624 104.4 448.937] -/Border [0 0 0] ->> -endobj -305 0 obj -<< -/S /URI -/URI (false) ->> -endobj -306 0 obj -<< -/Subtype /Link -/A 305 0 R -/Type /Annot -/Rect [104.4 437.624 120.6 448.937] -/Border [0 0 0] ->> -endobj -307 0 obj -<< -/S /URI -/URI (false) ->> -endobj -308 0 obj -<< -/Subtype /Link -/A 307 0 R -/Type /Annot -/Rect [120.6 437.624 126 448.937] -/Border [0 0 0] ->> -endobj -309 0 obj -<< -/S /URI -/URI (false) ->> -endobj -310 0 obj -<< -/Subtype /Link -/A 309 0 R -/Type /Annot -/Rect [126 437.624 131.4 448.937] -/Border [0 0 0] ->> -endobj -311 0 obj -<< -/S /URI -/URI (false) ->> -endobj -312 0 obj -<< -/Subtype /Link -/A 311 0 R -/Type /Annot -/Rect [131.4 437.624 136.8 448.937] -/Border [0 0 0] ->> -endobj -313 0 obj -<< -/S /URI -/URI (false) ->> -endobj -314 0 obj -<< -/Subtype /Link -/A 313 0 R -/Type /Annot -/Rect [136.8 437.624 153 448.937] -/Border [0 0 0] ->> -endobj -315 0 obj -<< -/S /URI -/URI (false) ->> -endobj -316 0 obj -<< -/Subtype /Link -/A 315 0 R -/Type /Annot -/Rect [153 437.624 158.4 448.937] -/Border [0 0 0] ->> -endobj -317 0 obj -<< -/S /URI -/URI (false) ->> -endobj -318 0 obj -<< -/Subtype /Link -/A 317 0 R -/Type /Annot -/Rect [158.4 437.624 217.8 448.937] -/Border [0 0 0] ->> -endobj -319 0 obj -<< -/S /URI -/URI (false) ->> -endobj -320 0 obj -<< -/Subtype /Link -/A 319 0 R -/Type /Annot -/Rect [217.8 437.624 223.2 448.937] -/Border [0 0 0] ->> -endobj -321 0 obj -<< -/S /URI -/URI (false) ->> -endobj -322 0 obj -<< -/Subtype /Link -/A 321 0 R -/Type /Annot -/Rect [72 414.998 234 426.311] -/Border [0 0 0] ->> -endobj -323 0 obj -<< -/S /URI -/URI (false) ->> -endobj -324 0 obj -<< -/Subtype /Link -/A 323 0 R -/Type /Annot -/Rect [72 403.685 99 414.998] -/Border [0 0 0] ->> -endobj -325 0 obj -<< -/S /URI -/URI (false) ->> -endobj -326 0 obj -<< -/Subtype /Link -/A 325 0 R -/Type /Annot -/Rect [99 403.685 104.4 414.998] -/Border [0 0 0] ->> -endobj -327 0 obj -<< -/S /URI -/URI (false) ->> -endobj -328 0 obj -<< -/Subtype /Link -/A 327 0 R -/Type /Annot -/Rect [104.4 403.685 136.8 414.998] -/Border [0 0 0] ->> -endobj -329 0 obj -<< -/S /URI -/URI (false) ->> -endobj -330 0 obj -<< -/Subtype /Link -/A 329 0 R -/Type /Annot -/Rect [136.8 403.685 142.2 414.998] -/Border [0 0 0] ->> -endobj -331 0 obj -<< -/S /URI -/URI (false) ->> -endobj -332 0 obj -<< -/Subtype /Link -/A 331 0 R -/Type /Annot -/Rect [142.2 403.685 147.6 414.998] -/Border [0 0 0] ->> -endobj -333 0 obj -<< -/S /URI -/URI (false) ->> -endobj -334 0 obj -<< -/Subtype /Link -/A 333 0 R -/Type /Annot -/Rect [147.6 403.685 153 414.998] -/Border [0 0 0] ->> -endobj -335 0 obj -<< -/S /URI -/URI (false) ->> -endobj -336 0 obj -<< -/Subtype /Link -/A 335 0 R -/Type /Annot -/Rect [153 403.685 169.2 414.998] -/Border [0 0 0] ->> -endobj -337 0 obj -<< -/S /URI -/URI (false) ->> -endobj -338 0 obj -<< -/Subtype /Link -/A 337 0 R -/Type /Annot -/Rect [169.2 403.685 174.6 414.998] -/Border [0 0 0] ->> -endobj -339 0 obj -<< -/S /URI -/URI (false) ->> -endobj -340 0 obj -<< -/Subtype /Link -/A 339 0 R -/Type /Annot -/Rect [174.6 403.685 196.2 414.998] -/Border [0 0 0] ->> -endobj -341 0 obj -<< -/S /URI -/URI (false) ->> -endobj -342 0 obj -<< -/Subtype /Link -/A 341 0 R -/Type /Annot -/Rect [196.2 403.685 201.6 414.998] -/Border [0 0 0] ->> -endobj -343 0 obj -<< -/S /URI -/URI (false) ->> -endobj -344 0 obj -<< -/Subtype /Link -/A 343 0 R -/Type /Annot -/Rect [201.6 403.685 255.6 414.998] -/Border [0 0 0] ->> -endobj -345 0 obj -<< -/S /URI -/URI (false) ->> -endobj -346 0 obj -<< -/Subtype /Link -/A 345 0 R -/Type /Annot -/Rect [255.6 403.685 261 414.998] -/Border [0 0 0] ->> -endobj -347 0 obj -<< -/S /URI -/URI (false) ->> -endobj -348 0 obj -<< -/Subtype /Link -/A 347 0 R -/Type /Annot -/Rect [261 403.685 266.4 414.998] -/Border [0 0 0] ->> -endobj -349 0 obj -<< -/S /URI -/URI (false) ->> -endobj -350 0 obj -<< -/Subtype /Link -/A 349 0 R -/Type /Annot -/Rect [266.4 403.685 271.8 414.998] -/Border [0 0 0] ->> -endobj -351 0 obj -<< -/S /URI -/URI (false) ->> -endobj -352 0 obj -<< -/Subtype /Link -/A 351 0 R -/Type /Annot -/Rect [271.8 403.685 277.2 414.998] -/Border [0 0 0] ->> -endobj -353 0 obj -<< -/S /URI -/URI (false) ->> -endobj -354 0 obj -<< -/Subtype /Link -/A 353 0 R -/Type /Annot -/Rect [72 381.059 342 392.372] -/Border [0 0 0] ->> -endobj -355 0 obj -<< -/S /URI -/URI (false) ->> -endobj -356 0 obj -<< -/Subtype /Link -/A 355 0 R -/Type /Annot -/Rect [72 358.433 234 369.746] -/Border [0 0 0] ->> -endobj -357 0 obj -<< -/S /URI -/URI (false) ->> -endobj -358 0 obj -<< -/Subtype /Link -/A 357 0 R -/Type /Annot -/Rect [72 347.12 88.2 358.433] -/Border [0 0 0] ->> -endobj -359 0 obj -<< -/S /URI -/URI (false) ->> -endobj -360 0 obj -<< -/Subtype /Link -/A 359 0 R -/Type /Annot -/Rect [88.2 347.12 93.6 358.433] -/Border [0 0 0] ->> -endobj -361 0 obj -<< -/S /URI -/URI (false) ->> -endobj -362 0 obj -<< -/Subtype /Link -/A 361 0 R -/Type /Annot -/Rect [93.6 347.12 109.8 358.433] -/Border [0 0 0] ->> -endobj -363 0 obj -<< -/S /URI -/URI (false) ->> -endobj -364 0 obj -<< -/Subtype /Link -/A 363 0 R -/Type /Annot -/Rect [109.8 347.12 115.2 358.433] -/Border [0 0 0] ->> -endobj -365 0 obj -<< -/S /URI -/URI (false) ->> -endobj -366 0 obj -<< -/Subtype /Link -/A 365 0 R -/Type /Annot -/Rect [115.2 347.12 120.6 358.433] -/Border [0 0 0] ->> -endobj -367 0 obj -<< -/S /URI -/URI (false) ->> -endobj -368 0 obj -<< -/Subtype /Link -/A 367 0 R -/Type /Annot -/Rect [120.6 347.12 126 358.433] -/Border [0 0 0] ->> -endobj -369 0 obj -<< -/S /URI -/URI (false) ->> -endobj -370 0 obj -<< -/Subtype /Link -/A 369 0 R -/Type /Annot -/Rect [72 335.807 104.4 347.12] -/Border [0 0 0] ->> -endobj -371 0 obj -<< -/S /URI -/URI (false) ->> -endobj -372 0 obj -<< -/Subtype /Link -/A 371 0 R -/Type /Annot -/Rect [104.4 335.807 109.8 347.12] -/Border [0 0 0] ->> -endobj -373 0 obj -<< -/S /URI -/URI (false) ->> -endobj -374 0 obj -<< -/Subtype /Link -/A 373 0 R -/Type /Annot -/Rect [109.8 335.807 120.6 347.12] -/Border [0 0 0] ->> -endobj -375 0 obj -<< -/S /URI -/URI (false) ->> -endobj -376 0 obj -<< -/Subtype /Link -/A 375 0 R -/Type /Annot -/Rect [120.6 335.807 126 347.12] -/Border [0 0 0] ->> -endobj -377 0 obj -<< -/S /URI -/URI (false) ->> -endobj -378 0 obj -<< -/Subtype /Link -/A 377 0 R -/Type /Annot -/Rect [126 335.807 169.2 347.12] -/Border [0 0 0] ->> -endobj -379 0 obj -<< -/S /URI -/URI (false) ->> -endobj -380 0 obj -<< -/Subtype /Link -/A 379 0 R -/Type /Annot -/Rect [169.2 335.807 174.6 347.12] -/Border [0 0 0] ->> -endobj -381 0 obj -<< -/S /URI -/URI (false) ->> -endobj -382 0 obj -<< -/Subtype /Link -/A 381 0 R -/Type /Annot -/Rect [174.6 335.807 180 347.12] -/Border [0 0 0] ->> -endobj -383 0 obj -<< -/S /URI -/URI (false) ->> -endobj -384 0 obj -<< -/Subtype /Link -/A 383 0 R -/Type /Annot -/Rect [180 335.807 223.2 347.12] -/Border [0 0 0] ->> -endobj -385 0 obj -<< -/S /URI -/URI (false) ->> -endobj -386 0 obj -<< -/Subtype /Link -/A 385 0 R -/Type /Annot -/Rect [223.2 335.807 228.6 347.12] -/Border [0 0 0] ->> -endobj -387 0 obj -<< -/S /URI -/URI (false) ->> -endobj -388 0 obj -<< -/Subtype /Link -/A 387 0 R -/Type /Annot -/Rect [228.6 335.807 234 347.12] -/Border [0 0 0] ->> -endobj -389 0 obj -<< -/S /URI -/URI (false) ->> -endobj -390 0 obj -<< -/Subtype /Link -/A 389 0 R -/Type /Annot -/Rect [234 335.807 239.4 347.12] -/Border [0 0 0] ->> -endobj -391 0 obj -<< -/S /URI -/URI (false) ->> -endobj -392 0 obj -<< -/Subtype /Link -/A 391 0 R -/Type /Annot -/Rect [239.4 335.807 244.8 347.12] -/Border [0 0 0] ->> -endobj -393 0 obj -<< -/S /URI -/URI (false) ->> -endobj -394 0 obj -<< -/Subtype /Link -/A 393 0 R -/Type /Annot -/Rect [72 324.494 82.8 335.807] -/Border [0 0 0] ->> -endobj -395 0 obj -<< -/S /URI -/URI (false) ->> -endobj -396 0 obj -<< -/Subtype /Link -/A 395 0 R -/Type /Annot -/Rect [82.8 324.494 336.6 335.807] -/Border [0 0 0] ->> -endobj -397 0 obj -<< -/S /URI -/URI (false) ->> -endobj -398 0 obj -<< -/Subtype /Link -/A 397 0 R -/Type /Annot -/Rect [72 313.181 82.8 324.494] -/Border [0 0 0] ->> -endobj -399 0 obj -<< -/S /URI -/URI (false) ->> -endobj -400 0 obj -<< -/Subtype /Link -/A 399 0 R -/Type /Annot -/Rect [82.8 313.181 109.8 324.494] -/Border [0 0 0] ->> -endobj -401 0 obj -<< -/S /URI -/URI (false) ->> -endobj -402 0 obj -<< -/Subtype /Link -/A 401 0 R -/Type /Annot -/Rect [109.8 313.181 115.2 324.494] -/Border [0 0 0] ->> -endobj -403 0 obj -<< -/S /URI -/URI (false) ->> -endobj -404 0 obj -<< -/Subtype /Link -/A 403 0 R -/Type /Annot -/Rect [115.2 313.181 136.8 324.494] -/Border [0 0 0] ->> -endobj -405 0 obj -<< -/S /URI -/URI (false) ->> -endobj -406 0 obj -<< -/Subtype /Link -/A 405 0 R -/Type /Annot -/Rect [136.8 313.181 142.2 324.494] -/Border [0 0 0] ->> -endobj -407 0 obj -<< -/S /URI -/URI (false) ->> -endobj -408 0 obj -<< -/Subtype /Link -/A 407 0 R -/Type /Annot -/Rect [142.2 313.181 147.6 324.494] -/Border [0 0 0] ->> -endobj -409 0 obj -<< -/S /URI -/URI (false) ->> -endobj -410 0 obj -<< -/Subtype /Link -/A 409 0 R -/Type /Annot -/Rect [147.6 313.181 153 324.494] -/Border [0 0 0] ->> -endobj -411 0 obj -<< -/S /URI -/URI (false) ->> -endobj -412 0 obj -<< -/Subtype /Link -/A 411 0 R -/Type /Annot -/Rect [153 313.181 185.4 324.494] -/Border [0 0 0] ->> -endobj -413 0 obj -<< -/S /URI -/URI (false) ->> -endobj -414 0 obj -<< -/Subtype /Link -/A 413 0 R -/Type /Annot -/Rect [185.4 313.181 190.8 324.494] -/Border [0 0 0] ->> -endobj -415 0 obj -<< -/S /URI -/URI (false) ->> -endobj -416 0 obj -<< -/Subtype /Link -/A 415 0 R -/Type /Annot -/Rect [190.8 313.181 223.2 324.494] -/Border [0 0 0] ->> -endobj -417 0 obj -<< -/S /URI -/URI (false) ->> -endobj -418 0 obj -<< -/Subtype /Link -/A 417 0 R -/Type /Annot -/Rect [223.2 313.181 228.6 324.494] -/Border [0 0 0] ->> -endobj -419 0 obj -<< -/S /URI -/URI (false) ->> -endobj -420 0 obj -<< -/Subtype /Link -/A 419 0 R -/Type /Annot -/Rect [228.6 313.181 320.4 324.494] -/Border [0 0 0] ->> -endobj -421 0 obj -<< -/S /URI -/URI (false) ->> -endobj -422 0 obj -<< -/Subtype /Link -/A 421 0 R -/Type /Annot -/Rect [320.4 313.181 325.8 324.494] -/Border [0 0 0] ->> -endobj -423 0 obj -<< -/S /URI -/URI (false) ->> -endobj -424 0 obj -<< -/Subtype /Link -/A 423 0 R -/Type /Annot -/Rect [325.8 313.181 331.2 324.494] -/Border [0 0 0] ->> -endobj -425 0 obj -<< -/S /URI -/URI (false) ->> -endobj -426 0 obj -<< -/Subtype /Link -/A 425 0 R -/Type /Annot -/Rect [72 290.555 82.8 301.868] -/Border [0 0 0] ->> -endobj -427 0 obj -<< -/S /URI -/URI (false) ->> -endobj -428 0 obj -<< -/Subtype /Link -/A 427 0 R -/Type /Annot -/Rect [82.8 290.555 336.6 301.868] -/Border [0 0 0] ->> -endobj -429 0 obj -<< -/S /URI -/URI (false) ->> -endobj -430 0 obj -<< -/Subtype /Link -/A 429 0 R -/Type /Annot -/Rect [72 279.242 82.8 290.555] -/Border [0 0 0] ->> -endobj -431 0 obj -<< -/S /URI -/URI (false) ->> -endobj -432 0 obj -<< -/Subtype /Link -/A 431 0 R -/Type /Annot -/Rect [82.8 279.242 109.8 290.555] -/Border [0 0 0] ->> -endobj -433 0 obj -<< -/S /URI -/URI (false) ->> -endobj -434 0 obj -<< -/Subtype /Link -/A 433 0 R -/Type /Annot -/Rect [109.8 279.242 115.2 290.555] -/Border [0 0 0] ->> -endobj -435 0 obj -<< -/S /URI -/URI (false) ->> -endobj -436 0 obj -<< -/Subtype /Link -/A 435 0 R -/Type /Annot -/Rect [115.2 279.242 131.4 290.555] -/Border [0 0 0] ->> -endobj -437 0 obj -<< -/S /URI -/URI (false) ->> -endobj -438 0 obj -<< -/Subtype /Link -/A 437 0 R -/Type /Annot -/Rect [131.4 279.242 136.8 290.555] -/Border [0 0 0] ->> -endobj -439 0 obj -<< -/S /URI -/URI (false) ->> -endobj -440 0 obj -<< -/Subtype /Link -/A 439 0 R -/Type /Annot -/Rect [136.8 279.242 142.2 290.555] -/Border [0 0 0] ->> -endobj -441 0 obj -<< -/S /URI -/URI (false) ->> -endobj -442 0 obj -<< -/Subtype /Link -/A 441 0 R -/Type /Annot -/Rect [142.2 279.242 147.6 290.555] -/Border [0 0 0] ->> -endobj -443 0 obj -<< -/S /URI -/URI (false) ->> -endobj -444 0 obj -<< -/Subtype /Link -/A 443 0 R -/Type /Annot -/Rect [147.6 279.242 180 290.555] -/Border [0 0 0] ->> -endobj -445 0 obj -<< -/S /URI -/URI (false) ->> -endobj -446 0 obj -<< -/Subtype /Link -/A 445 0 R -/Type /Annot -/Rect [180 279.242 185.4 290.555] -/Border [0 0 0] ->> -endobj -447 0 obj -<< -/S /URI -/URI (false) ->> -endobj -448 0 obj -<< -/Subtype /Link -/A 447 0 R -/Type /Annot -/Rect [185.4 279.242 234 290.555] -/Border [0 0 0] ->> -endobj -449 0 obj -<< -/S /URI -/URI (false) ->> -endobj -450 0 obj -<< -/Subtype /Link -/A 449 0 R -/Type /Annot -/Rect [234 279.242 239.4 290.555] -/Border [0 0 0] ->> -endobj -451 0 obj -<< -/S /URI -/URI (false) ->> -endobj -452 0 obj -<< -/Subtype /Link -/A 451 0 R -/Type /Annot -/Rect [239.4 279.242 331.2 290.555] -/Border [0 0 0] ->> -endobj -453 0 obj -<< -/S /URI -/URI (false) ->> -endobj -454 0 obj -<< -/Subtype /Link -/A 453 0 R -/Type /Annot -/Rect [331.2 279.242 336.6 290.555] -/Border [0 0 0] ->> -endobj -455 0 obj -<< -/S /URI -/URI (false) ->> -endobj -456 0 obj -<< -/Subtype /Link -/A 455 0 R -/Type /Annot -/Rect [336.6 279.242 342 290.555] -/Border [0 0 0] ->> -endobj -457 0 obj -<< -/S /URI -/URI (false) ->> -endobj -458 0 obj -<< -/Subtype /Link -/A 457 0 R -/Type /Annot -/Rect [72 267.929 82.8 279.242] -/Border [0 0 0] ->> -endobj -459 0 obj -<< -/S /URI -/URI (false) ->> -endobj -460 0 obj -<< -/Subtype /Link -/A 459 0 R -/Type /Annot -/Rect [82.8 267.929 115.2 279.242] -/Border [0 0 0] ->> -endobj -461 0 obj -<< -/S /URI -/URI (false) ->> -endobj -462 0 obj -<< -/Subtype /Link -/A 461 0 R -/Type /Annot -/Rect [115.2 267.929 120.6 279.242] -/Border [0 0 0] ->> -endobj -463 0 obj -<< -/S /URI -/URI (false) ->> -endobj -464 0 obj -<< -/Subtype /Link -/A 463 0 R -/Type /Annot -/Rect [120.6 267.929 136.8 279.242] -/Border [0 0 0] ->> -endobj -465 0 obj -<< -/S /URI -/URI (false) ->> -endobj -466 0 obj -<< -/Subtype /Link -/A 465 0 R -/Type /Annot -/Rect [136.8 267.929 142.2 279.242] -/Border [0 0 0] ->> -endobj -467 0 obj -<< -/S /URI -/URI (false) ->> -endobj -468 0 obj -<< -/Subtype /Link -/A 467 0 R -/Type /Annot -/Rect [142.2 267.929 147.6 279.242] -/Border [0 0 0] ->> -endobj -469 0 obj -<< -/S /URI -/URI (false) ->> -endobj -470 0 obj -<< -/Subtype /Link -/A 469 0 R -/Type /Annot -/Rect [147.6 267.929 153 279.242] -/Border [0 0 0] ->> -endobj -471 0 obj -<< -/S /URI -/URI (false) ->> -endobj -472 0 obj -<< -/Subtype /Link -/A 471 0 R -/Type /Annot -/Rect [153 267.929 169.2 279.242] -/Border [0 0 0] ->> -endobj -473 0 obj -<< -/S /URI -/URI (false) ->> -endobj -474 0 obj -<< -/Subtype /Link -/A 473 0 R -/Type /Annot -/Rect [169.2 267.929 174.6 279.242] -/Border [0 0 0] ->> -endobj -475 0 obj -<< -/S /URI -/URI (false) ->> -endobj -476 0 obj -<< -/Subtype /Link -/A 475 0 R -/Type /Annot -/Rect [72 256.616 77.4 267.929] -/Border [0 0 0] ->> -endobj -477 0 obj -<< -/S /URI -/URI (false) ->> -endobj -478 0 obj -<< -/Subtype /Link -/A 477 0 R -/Type /Annot -/Rect [77.4 256.616 82.8 267.929] -/Border [0 0 0] ->> -endobj -479 0 obj -<< -/S /URI -/URI (false) ->> -endobj -480 0 obj -<< -/Subtype /Link -/A 479 0 R -/Type /Annot -/Rect [82.8 256.616 88.2 267.929] -/Border [0 0 0] ->> -endobj -481 0 obj -<< -/S /URI -/URI (false) ->> -endobj -482 0 obj -<< -/Subtype /Link -/A 481 0 R -/Type /Annot -/Rect [72 234.116 343.210938 246.616] -/Border [0 0 0] ->> -endobj -483 0 obj -<< -/S /URI -/URI (http://pdfkit.org/demo/browser.html) ->> -endobj -484 0 obj -<< -/Subtype /Link -/A 483 0 R -/Type /Annot -/Rect [343.210938 234.116 365.754883 246.616] -/Border [0 0 0] ->> -endobj -485 0 obj -<< -/S /URI -/URI (false) ->> -endobj -486 0 obj -<< -/Subtype /Link -/A 485 0 R -/Type /Annot -/Rect [365.754883 234.116 369.202148 246.616] -/Border [0 0 0] ->> -endobj -487 0 obj -<< -/S /URI -/URI (false) ->> -endobj -488 0 obj -<< -/Subtype /Link -/A 487 0 R -/Type /Annot -/Rect [72 211.616 463.196289 224.116] -/Border [0 0 0] ->> -endobj -489 0 obj -<< -/S /URI -/URI (false) ->> -endobj -490 0 obj -<< -/Subtype /Link -/A 489 0 R -/Type /Annot -/Rect [463.196289 211.546 487.196289 224.116] -/Border [0 0 0] ->> -endobj -491 0 obj -<< -/S /URI -/URI (false) ->> -endobj -492 0 obj -<< -/Subtype /Link -/A 491 0 R -/Type /Annot -/Rect [487.196289 211.616 529.925781 224.116] -/Border [0 0 0] ->> -endobj -493 0 obj -<< -/S /URI -/URI (false) ->> -endobj -494 0 obj -<< -/Subtype /Link -/A 493 0 R -/Type /Annot -/Rect [72 199.116 484.666016 211.616] -/Border [0 0 0] ->> -endobj -495 0 obj -<< -/S /URI -/URI (false) ->> -endobj -496 0 obj -<< -/Subtype /Link -/A 495 0 R -/Type /Annot -/Rect [72 186.476 150 199.046] -/Border [0 0 0] ->> -endobj -497 0 obj -<< -/S /URI -/URI (false) ->> -endobj -498 0 obj -<< -/Subtype /Link -/A 497 0 R -/Type /Annot -/Rect [150 186.546 211.557617 199.046] -/Border [0 0 0] ->> -endobj -499 0 obj -<< -/S /URI -/URI (false) ->> -endobj -500 0 obj -<< -/Subtype /Link -/A 499 0 R -/Type /Annot -/Rect [211.557617 186.476 283.557617 199.046] -/Border [0 0 0] ->> -endobj -501 0 obj -<< -/S /URI -/URI (false) ->> -endobj -502 0 obj -<< -/Subtype /Link -/A 501 0 R -/Type /Annot -/Rect [283.557617 186.546 526.414063 199.046] -/Border [0 0 0] ->> -endobj -503 0 obj -<< -/S /URI -/URI (false) ->> -endobj -504 0 obj -<< -/Subtype /Link -/A 503 0 R -/Type /Annot -/Rect [72 174.046 380.413086 186.546] -/Border [0 0 0] ->> -endobj -189 0 obj -<< -/Type /Page -/Parent 1 0 R -/MediaBox [0 0 612 792] -/Contents 187 0 R -/Resources 188 0 R -/Annots [192 0 R 194 0 R 196 0 R 198 0 R 200 0 R 202 0 R 204 0 R 206 0 R 208 0 R 210 0 R 212 0 R 214 0 R 216 0 R 218 0 R 220 0 R 222 0 R 224 0 R 226 0 R 228 0 R 230 0 R 232 0 R 234 0 R 236 0 R 238 0 R 240 0 R 242 0 R 244 0 R 246 0 R 248 0 R 250 0 R 252 0 R 254 0 R 256 0 R 258 0 R 260 0 R 262 0 R 264 0 R 266 0 R 268 0 R 270 0 R 272 0 R 274 0 R 276 0 R 278 0 R 280 0 R 282 0 R 284 0 R 286 0 R 288 0 R 290 0 R 292 0 R 294 0 R 296 0 R 298 0 R 300 0 R 302 0 R 304 0 R 306 0 R 308 0 R 310 0 R 312 0 R 314 0 R 316 0 R 318 0 R 320 0 R 322 0 R 324 0 R 326 0 R 328 0 R 330 0 R 332 0 R 334 0 R 336 0 R 338 0 R 340 0 R 342 0 R 344 0 R 346 0 R 348 0 R 350 0 R 352 0 R 354 0 R 356 0 R 358 0 R 360 0 R 362 0 R 364 0 R 366 0 R 368 0 R 370 0 R 372 0 R 374 0 R 376 0 R 378 0 R 380 0 R 382 0 R 384 0 R 386 0 R 388 0 R 390 0 R 392 0 R 394 0 R 396 0 R 398 0 R 400 0 R 402 0 R 404 0 R 406 0 R 408 0 R 410 0 R 412 0 R 414 0 R 416 0 R 418 0 R 420 0 R 422 0 R 424 0 R 426 0 R 428 0 R 430 0 R 432 0 R 434 0 R 436 0 R 438 0 R 440 0 R 442 0 R 444 0 R 446 0 R 448 0 R 450 0 R 452 0 R 454 0 R 456 0 R 458 0 R 460 0 R 462 0 R 464 0 R 466 0 R 468 0 R 470 0 R 472 0 R 474 0 R 476 0 R 478 0 R 480 0 R 482 0 R 484 0 R 486 0 R 488 0 R 490 0 R 492 0 R 494 0 R 496 0 R 498 0 R 500 0 R 502 0 R 504 0 R] ->> -endobj -188 0 obj -<< -/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] -/Font << -/F4 16 0 R -/F3 9 0 R -/F6 44 0 R -/F5 29 0 R ->> ->> -endobj -187 0 obj -<< -/Length 3008 -/Filter /FlateDecode ->> -stream -x]ˎ Wb0I.Ȣ -"#ɢM?h.AMwei y폿rM]L{9'/N@@^M//I%cƏ[W~וc_#ۿ3u-#oo~7cm@v>*V#o>BE^8gc~po/|s\/uoy&ߙ˷n#߇UƳdOnU ޚvs\3/cб&ӻ߰Eep繤`avQڔCH tQxiZ ɿyw|e9YO~R8Y5{^1CGVflL Cd'o"U8[X["BIZdB= E'ٯb]"y]j]^$_@Os=j ͣ4 ߷fo1Qm#.PIl^ڢmЖ(9,r}68 ,P}F(?xgE-bWœߋ[h⧨ A{ͅ}Q.@T%ѽNqݘDph$W=}:q\w)^ ; -.$Mmٝ>DC -&8s>7Zš1bN!I8b9ؖ)h㽟%|,~0@?ʭh|=o'q_f}7|Xr#W XBpv9 ~tFg$.l'$PRg#di%L3$ƿ|AnS1sB } -YT% |&1؟.6ޙTx!&~Arb&EK3Ri`K3q1IVT["h#<.0;sXqklPʊ >X*EWougz@R[#*0{I͏(TTe'֫cVL1 5jMkD5-bFJq- -u?Ry[H= -mQmo?-b:_랢UHۡq6J3cWt|d[5c:oaG-χ:9ff#iͮ@supTu0Z2Xҡ^O4JsJ۲\Bǝ{d W_~ġl1-Q\ڈ -\<&N22<1'\y@9itH=Rcbx{2ʛ&ųP$a\!*zC#,aNh..=B=awS`UwX:B+ԣN^PZ\.h,js_"B19:f7&ՒZ>Du&0u ]p`I+ \Ѣ|tvؚ'+ge;k9$3kx jyRǬө޼Jb;=`1t12Ob`UcXPQV a/Hi[ F[/%9ŠHD\MGw\ k-ѵr KtDX1\,ͽ2Zx1Pu64ZX:x**KY֚'(8GWYzSm0 -MpqZqژ،\$8166{1VQc WK9Ύ]BH=.J P#v HQUNZE.`8TXP1#M+qi亶W[86 y5VĪrJ -Xkeڜ.OEJJ(q>G6*"l]e,/?c{(Br+q0-lӜW@Z` fPPO=1P$^xx䜆;Rm;9D0KҪ"KVϟl*./PdԠ eCWGEp7KV"|<ыm(빔it^ ςp߫S|Ք]Eߧᗌ^xoY鐯m6̭w /SlaޛiЬb2G!&Y A }[\pGzV=B'nu#XT!IeFK#;UK#,UBޤI\(%.qB~atr,;s_>k@@oA|.d5ܫYP\=8>Z,dz|FD)SC5\K ݗ%Yʵr_Ba6CctA*Khg٩h#[WEx2bީ6DAtU/Ӑj,f*?5x,NĬ`m=o/Y7@'姛X6@':psmQU{c^GdYf -m?]?'}h\odꌎ<>T ,=? 5nڊAk1ҹ2ksdaS*H NYtc{xion{`-א[ -.t -ľlWCNj)<*9BNʚG=ݸWgLAGҵN;>]nSר K\'7;b?7 p7WfQ>V51LILcުǡJuͽĕK%o鱺yO6rR]Q>OZ11b=2]*ևe;{w[CČVv=[}ǽ?<*EecTv 8=tCZ{48,lَ W!JqhFO,K.p|lܤ0z|4kf_D \z Dsܙ=%NZ?DFAꑀٹKH( Bcˊ 8~ -endstream -endobj -509 0 obj -<< -/S /URI -/URI (false) ->> -endobj -510 0 obj -<< -/Subtype /Link -/A 509 0 R -/Type /Annot -/Rect [72 695.502 173.682 720] -/Border [0 0 0] ->> -endobj -511 0 obj -<< -/S /URI -/URI (false) ->> -endobj -512 0 obj -<< -/Subtype /Link -/A 511 0 R -/Type /Annot -/Rect [72 673.002 508.889648 685.502] -/Border [0 0 0] ->> -endobj -513 0 obj -<< -/S /URI -/URI (false) ->> -endobj -514 0 obj -<< -/Subtype /Link -/A 513 0 R -/Type /Annot -/Rect [72 660.502 220.754883 673.002] -/Border [0 0 0] ->> -endobj -515 0 obj -<< -/S /URI -/URI (false) ->> -endobj -516 0 obj -<< -/Subtype /Link -/A 515 0 R -/Type /Annot -/Rect [220.754883 660.432 340.754883 673.002] -/Border [0 0 0] ->> -endobj -517 0 obj -<< -/S /URI -/URI (false) ->> -endobj -518 0 obj -<< -/Subtype /Link -/A 517 0 R -/Type /Annot -/Rect [340.754883 660.502 527.957031 673.002] -/Border [0 0 0] ->> -endobj -519 0 obj -<< -/S /URI -/URI (false) ->> -endobj -520 0 obj -<< -/Subtype /Link -/A 519 0 R -/Type /Annot -/Rect [72 648.002 224.53418 660.502] -/Border [0 0 0] ->> -endobj -521 0 obj -<< -/S /URI -/URI (false) ->> -endobj -522 0 obj -<< -/Subtype /Link -/A 521 0 R -/Type /Annot -/Rect [72 626.689 88.2 638.002] -/Border [0 0 0] ->> -endobj -523 0 obj -<< -/S /URI -/URI (false) ->> -endobj -524 0 obj -<< -/Subtype /Link -/A 523 0 R -/Type /Annot -/Rect [88.2 626.689 93.6 638.002] -/Border [0 0 0] ->> -endobj -525 0 obj -<< -/S /URI -/URI (false) ->> -endobj -526 0 obj -<< -/Subtype /Link -/A 525 0 R -/Type /Annot -/Rect [93.6 626.689 131.4 638.002] -/Border [0 0 0] ->> -endobj -527 0 obj -<< -/S /URI -/URI (false) ->> -endobj -528 0 obj -<< -/Subtype /Link -/A 527 0 R -/Type /Annot -/Rect [131.4 626.689 136.8 638.002] -/Border [0 0 0] ->> -endobj -529 0 obj -<< -/S /URI -/URI (false) ->> -endobj -530 0 obj -<< -/Subtype /Link -/A 529 0 R -/Type /Annot -/Rect [136.8 626.689 142.2 638.002] -/Border [0 0 0] ->> -endobj -531 0 obj -<< -/S /URI -/URI (false) ->> -endobj -532 0 obj -<< -/Subtype /Link -/A 531 0 R -/Type /Annot -/Rect [72 604.189 403.958008 616.689] -/Border [0 0 0] ->> -endobj -533 0 obj -<< -/S /URI -/URI (false) ->> -endobj -534 0 obj -<< -/Subtype /Link -/A 533 0 R -/Type /Annot -/Rect [403.958008 604.119 457.958008 616.689] -/Border [0 0 0] ->> -endobj -535 0 obj -<< -/S /URI -/URI (false) ->> -endobj -536 0 obj -<< -/Subtype /Link -/A 535 0 R -/Type /Annot -/Rect [457.958008 604.189 473.583008 616.689] -/Border [0 0 0] ->> -endobj -537 0 obj -<< -/S /URI -/URI (false) ->> -endobj -538 0 obj -<< -/Subtype /Link -/A 537 0 R -/Type /Annot -/Rect [72 591.689 225.71582 604.189] -/Border [0 0 0] ->> -endobj -539 0 obj -<< -/S /URI -/URI (false) ->> -endobj -540 0 obj -<< -/Subtype /Link -/A 539 0 R -/Type /Annot -/Rect [225.71582 591.619 279.71582 604.189] -/Border [0 0 0] ->> -endobj -541 0 obj -<< -/S /URI -/URI (false) ->> -endobj -542 0 obj -<< -/Subtype /Link -/A 541 0 R -/Type /Annot -/Rect [279.71582 591.689 313.724609 604.189] -/Border [0 0 0] ->> -endobj -543 0 obj -<< -/S /URI -/URI (false) ->> -endobj -544 0 obj -<< -/Subtype /Link -/A 543 0 R -/Type /Annot -/Rect [72 570.376 88.2 581.689] -/Border [0 0 0] ->> -endobj -545 0 obj -<< -/S /URI -/URI (false) ->> -endobj -546 0 obj -<< -/Subtype /Link -/A 545 0 R -/Type /Annot -/Rect [88.2 570.376 93.6 581.689] -/Border [0 0 0] ->> -endobj -547 0 obj -<< -/S /URI -/URI (false) ->> -endobj -548 0 obj -<< -/Subtype /Link -/A 547 0 R -/Type /Annot -/Rect [93.6 570.376 104.4 581.689] -/Border [0 0 0] ->> -endobj -549 0 obj -<< -/S /URI -/URI (false) ->> -endobj -550 0 obj -<< -/Subtype /Link -/A 549 0 R -/Type /Annot -/Rect [104.4 570.376 109.8 581.689] -/Border [0 0 0] ->> -endobj -551 0 obj -<< -/S /URI -/URI (false) ->> -endobj -552 0 obj -<< -/Subtype /Link -/A 551 0 R -/Type /Annot -/Rect [109.8 570.376 169.2 581.689] -/Border [0 0 0] ->> -endobj -553 0 obj -<< -/S /URI -/URI (false) ->> -endobj -554 0 obj -<< -/Subtype /Link -/A 553 0 R -/Type /Annot -/Rect [169.2 570.376 174.6 581.689] -/Border [0 0 0] ->> -endobj -555 0 obj -<< -/S /URI -/URI (false) ->> -endobj -556 0 obj -<< -/Subtype /Link -/A 555 0 R -/Type /Annot -/Rect [174.6 570.376 180 581.689] -/Border [0 0 0] ->> -endobj -557 0 obj -<< -/S /URI -/URI (false) ->> -endobj -558 0 obj -<< -/Subtype /Link -/A 557 0 R -/Type /Annot -/Rect [180 570.376 185.4 581.689] -/Border [0 0 0] ->> -endobj -559 0 obj -<< -/S /URI -/URI (false) ->> -endobj -560 0 obj -<< -/Subtype /Link -/A 559 0 R -/Type /Annot -/Rect [185.4 570.376 190.8 581.689] -/Border [0 0 0] ->> -endobj -561 0 obj -<< -/S /URI -/URI (false) ->> -endobj -562 0 obj -<< -/Subtype /Link -/A 561 0 R -/Type /Annot -/Rect [190.8 570.376 196.2 581.689] -/Border [0 0 0] ->> -endobj -563 0 obj -<< -/S /URI -/URI (false) ->> -endobj -564 0 obj -<< -/Subtype /Link -/A 563 0 R -/Type /Annot -/Rect [196.2 570.376 207 581.689] -/Border [0 0 0] ->> -endobj -565 0 obj -<< -/S /URI -/URI (false) ->> -endobj -566 0 obj -<< -/Subtype /Link -/A 565 0 R -/Type /Annot -/Rect [207 570.376 212.4 581.689] -/Border [0 0 0] ->> -endobj -567 0 obj -<< -/S /URI -/URI (false) ->> -endobj -568 0 obj -<< -/Subtype /Link -/A 567 0 R -/Type /Annot -/Rect [212.4 570.376 228.6 581.689] -/Border [0 0 0] ->> -endobj -569 0 obj -<< -/S /URI -/URI (false) ->> -endobj -570 0 obj -<< -/Subtype /Link -/A 569 0 R -/Type /Annot -/Rect [228.6 570.376 234 581.689] -/Border [0 0 0] ->> -endobj -571 0 obj -<< -/S /URI -/URI (false) ->> -endobj -572 0 obj -<< -/Subtype /Link -/A 571 0 R -/Type /Annot -/Rect [234 570.376 255.6 581.689] -/Border [0 0 0] ->> -endobj -573 0 obj -<< -/S /URI -/URI (false) ->> -endobj -574 0 obj -<< -/Subtype /Link -/A 573 0 R -/Type /Annot -/Rect [255.6 570.376 261 581.689] -/Border [0 0 0] ->> -endobj -575 0 obj -<< -/S /URI -/URI (false) ->> -endobj -576 0 obj -<< -/Subtype /Link -/A 575 0 R -/Type /Annot -/Rect [261 570.376 325.8 581.689] -/Border [0 0 0] ->> -endobj -577 0 obj -<< -/S /URI -/URI (false) ->> -endobj -578 0 obj -<< -/Subtype /Link -/A 577 0 R -/Type /Annot -/Rect [325.8 570.376 331.2 581.689] -/Border [0 0 0] ->> -endobj -579 0 obj -<< -/S /URI -/URI (false) ->> -endobj -580 0 obj -<< -/Subtype /Link -/A 579 0 R -/Type /Annot -/Rect [331.2 570.376 336.6 581.689] -/Border [0 0 0] ->> -endobj -581 0 obj -<< -/S /URI -/URI (false) ->> -endobj -582 0 obj -<< -/Subtype /Link -/A 581 0 R -/Type /Annot -/Rect [336.6 570.376 342 581.689] -/Border [0 0 0] ->> -endobj -583 0 obj -<< -/S /URI -/URI (false) ->> -endobj -584 0 obj -<< -/Subtype /Link -/A 583 0 R -/Type /Annot -/Rect [72 547.876 446.682617 560.376] -/Border [0 0 0] ->> -endobj -585 0 obj -<< -/S /URI -/URI (false) ->> -endobj -586 0 obj -<< -/Subtype /Link -/A 585 0 R -/Type /Annot -/Rect [72 525.376 93.201172 537.876] -/Border [0 0 0] ->> -endobj -587 0 obj -<< -/S /URI -/URI (false) ->> -endobj -588 0 obj -<< -/Subtype /Link -/A 587 0 R -/Type /Annot -/Rect [93.201172 525.306 129.201172 537.876] -/Border [0 0 0] ->> -endobj -589 0 obj -<< -/S /URI -/URI (false) ->> -endobj -590 0 obj -<< -/Subtype /Link -/A 589 0 R -/Type /Annot -/Rect [129.201172 525.376 244.699219 537.876] -/Border [0 0 0] ->> -endobj -591 0 obj -<< -/S /URI -/URI (false) ->> -endobj -592 0 obj -<< -/Subtype /Link -/A 591 0 R -/Type /Annot -/Rect [244.699219 525.306 292.699219 537.876] -/Border [0 0 0] ->> -endobj -593 0 obj -<< -/S /URI -/URI (false) ->> -endobj -594 0 obj -<< -/Subtype /Link -/A 593 0 R -/Type /Annot -/Rect [292.699219 525.376 373.416992 537.876] -/Border [0 0 0] ->> -endobj -595 0 obj -<< -/S /URI -/URI (false) ->> -endobj -596 0 obj -<< -/Subtype /Link -/A 595 0 R -/Type /Annot -/Rect [373.416992 525.306 427.416992 537.876] -/Border [0 0 0] ->> -endobj -597 0 obj -<< -/S /URI -/URI (false) ->> -endobj -598 0 obj -<< -/Subtype /Link -/A 597 0 R -/Type /Annot -/Rect [427.416992 525.376 454.619141 537.876] -/Border [0 0 0] ->> -endobj -599 0 obj -<< -/S /URI -/URI (false) ->> -endobj -600 0 obj -<< -/Subtype /Link -/A 599 0 R -/Type /Annot -/Rect [454.619141 525.306 478.619141 537.876] -/Border [0 0 0] ->> -endobj -601 0 obj -<< -/S /URI -/URI (false) ->> -endobj -602 0 obj -<< -/Subtype /Link -/A 601 0 R -/Type /Annot -/Rect [478.619141 525.376 527.095703 537.876] -/Border [0 0 0] ->> -endobj -603 0 obj -<< -/S /URI -/URI (false) ->> -endobj -604 0 obj -<< -/Subtype /Link -/A 603 0 R -/Type /Annot -/Rect [72 512.876 236.238281 525.376] -/Border [0 0 0] ->> -endobj -605 0 obj -<< -/S /URI -/URI (false) ->> -endobj -606 0 obj -<< -/Subtype /Link -/A 605 0 R -/Type /Annot -/Rect [236.238281 512.806 326.238281 525.376] -/Border [0 0 0] ->> -endobj -607 0 obj -<< -/S /URI -/URI (false) ->> -endobj -608 0 obj -<< -/Subtype /Link -/A 607 0 R -/Type /Annot -/Rect [326.238281 512.876 521.951172 525.376] -/Border [0 0 0] ->> -endobj -609 0 obj -<< -/S /URI -/URI (false) ->> -endobj -610 0 obj -<< -/Subtype /Link -/A 609 0 R -/Type /Annot -/Rect [72 500.376 451.726563 512.876] -/Border [0 0 0] ->> -endobj -611 0 obj -<< -/S /URI -/URI (https://github.com/devongovett/pdfkit/blob/b13423bf0a391ed1c33a2e277bc06c00cabd6bf9/lib/page.coffee#L72-L122) ->> -endobj -612 0 obj -<< -/Subtype /Link -/A 611 0 R -/Type /Annot -/Rect [451.726563 500.376 474.270508 512.876] -/Border [0 0 0] ->> -endobj -613 0 obj -<< -/S /URI -/URI (false) ->> -endobj -614 0 obj -<< -/Subtype /Link -/A 613 0 R -/Type /Annot -/Rect [474.270508 500.376 539.416992 512.876] -/Border [0 0 0] ->> -endobj -615 0 obj -<< -/S /URI -/URI (false) ->> -endobj -616 0 obj -<< -/Subtype /Link -/A 615 0 R -/Type /Annot -/Rect [72 487.876 83.005859 500.376] -/Border [0 0 0] ->> -endobj -617 0 obj -<< -/S /URI -/URI (false) ->> -endobj -618 0 obj -<< -/Subtype /Link -/A 617 0 R -/Type /Annot -/Rect [83.005859 487.806 119.005859 500.376] -/Border [0 0 0] ->> -endobj -619 0 obj -<< -/S /URI -/URI (false) ->> -endobj -620 0 obj -<< -/Subtype /Link -/A 619 0 R -/Type /Annot -/Rect [119.005859 487.876 122.453125 500.376] -/Border [0 0 0] ->> -endobj -621 0 obj -<< -/S /URI -/URI (false) ->> -endobj -622 0 obj -<< -/Subtype /Link -/A 621 0 R -/Type /Annot -/Rect [72 465.376 252.263672 477.876] -/Border [0 0 0] ->> -endobj -623 0 obj -<< -/S /URI -/URI (false) ->> -endobj -624 0 obj -<< -/Subtype /Link -/A 623 0 R -/Type /Annot -/Rect [252.263672 465.306 318.263672 477.876] -/Border [0 0 0] ->> -endobj -625 0 obj -<< -/S /URI -/URI (false) ->> -endobj -626 0 obj -<< -/Subtype /Link -/A 625 0 R -/Type /Annot -/Rect [318.263672 465.376 529.894531 477.876] -/Border [0 0 0] ->> -endobj -627 0 obj -<< -/S /URI -/URI (false) ->> -endobj -628 0 obj -<< -/Subtype /Link -/A 627 0 R -/Type /Annot -/Rect [72 452.876 522.732422 465.376] -/Border [0 0 0] ->> -endobj -629 0 obj -<< -/S /URI -/URI (false) ->> -endobj -630 0 obj -<< -/Subtype /Link -/A 629 0 R -/Type /Annot -/Rect [72 440.376 140.613281 452.876] -/Border [0 0 0] ->> -endobj -631 0 obj -<< -/S /URI -/URI (false) ->> -endobj -632 0 obj -<< -/Subtype /Link -/A 631 0 R -/Type /Annot -/Rect [140.613281 440.306 182.613281 452.876] -/Border [0 0 0] ->> -endobj -633 0 obj -<< -/S /URI -/URI (false) ->> -endobj -634 0 obj -<< -/Subtype /Link -/A 633 0 R -/Type /Annot -/Rect [182.613281 440.376 227.583984 452.876] -/Border [0 0 0] ->> -endobj -635 0 obj -<< -/S /URI -/URI (false) ->> -endobj -636 0 obj -<< -/Subtype /Link -/A 635 0 R -/Type /Annot -/Rect [72 417.876 411.790039 430.376] -/Border [0 0 0] ->> -endobj -637 0 obj -<< -/S /URI -/URI (false) ->> -endobj -638 0 obj -<< -/Subtype /Link -/A 637 0 R -/Type /Annot -/Rect [411.790039 417.806 447.790039 430.376] -/Border [0 0 0] ->> -endobj -639 0 obj -<< -/S /URI -/URI (false) ->> -endobj -640 0 obj -<< -/Subtype /Link -/A 639 0 R -/Type /Annot -/Rect [447.790039 417.876 496.266602 430.376] -/Border [0 0 0] ->> -endobj -641 0 obj -<< -/S /URI -/URI (false) ->> -endobj -642 0 obj -<< -/Subtype /Link -/A 641 0 R -/Type /Annot -/Rect [72 405.376 518.972656 417.876] -/Border [0 0 0] ->> -endobj -643 0 obj -<< -/S /URI -/URI (false) ->> -endobj -644 0 obj -<< -/Subtype /Link -/A 643 0 R -/Type /Annot -/Rect [72 392.736 114 405.306] -/Border [0 0 0] ->> -endobj -645 0 obj -<< -/S /URI -/URI (false) ->> -endobj -646 0 obj -<< -/Subtype /Link -/A 645 0 R -/Type /Annot -/Rect [114 392.806 288.360352 405.306] -/Border [0 0 0] ->> -endobj -647 0 obj -<< -/S /URI -/URI (false) ->> -endobj -648 0 obj -<< -/Subtype /Link -/A 647 0 R -/Type /Annot -/Rect [288.360352 392.736 306.360352 405.306] -/Border [0 0 0] ->> -endobj -649 0 obj -<< -/S /URI -/URI (false) ->> -endobj -650 0 obj -<< -/Subtype /Link -/A 649 0 R -/Type /Annot -/Rect [306.360352 392.806 312.258789 405.306] -/Border [0 0 0] ->> -endobj -651 0 obj -<< -/S /URI -/URI (false) ->> -endobj -652 0 obj -<< -/Subtype /Link -/A 651 0 R -/Type /Annot -/Rect [312.258789 392.736 348.258789 405.306] -/Border [0 0 0] ->> -endobj -653 0 obj -<< -/S /URI -/URI (false) ->> -endobj -654 0 obj -<< -/Subtype /Link -/A 653 0 R -/Type /Annot -/Rect [348.258789 392.806 354.157227 405.306] -/Border [0 0 0] ->> -endobj -655 0 obj -<< -/S /URI -/URI (false) ->> -endobj -656 0 obj -<< -/Subtype /Link -/A 655 0 R -/Type /Annot -/Rect [354.157227 392.736 378.157227 405.306] -/Border [0 0 0] ->> -endobj -657 0 obj -<< -/S /URI -/URI (false) ->> -endobj -658 0 obj -<< -/Subtype /Link -/A 657 0 R -/Type /Annot -/Rect [378.157227 392.806 405.212891 405.306] -/Border [0 0 0] ->> -endobj -659 0 obj -<< -/S /URI -/URI (false) ->> -endobj -660 0 obj -<< -/Subtype /Link -/A 659 0 R -/Type /Annot -/Rect [405.212891 392.736 435.212891 405.306] -/Border [0 0 0] ->> -endobj -661 0 obj -<< -/S /URI -/URI (false) ->> -endobj -662 0 obj -<< -/Subtype /Link -/A 661 0 R -/Type /Annot -/Rect [435.212891 392.806 537.283203 405.306] -/Border [0 0 0] ->> -endobj -663 0 obj -<< -/S /URI -/URI (false) ->> -endobj -664 0 obj -<< -/Subtype /Link -/A 663 0 R -/Type /Annot -/Rect [72 380.306 272.732422 392.806] -/Border [0 0 0] ->> -endobj -665 0 obj -<< -/S /URI -/URI (false) ->> -endobj -666 0 obj -<< -/Subtype /Link -/A 665 0 R -/Type /Annot -/Rect [72 357.806 137.019531 370.306] -/Border [0 0 0] ->> -endobj -667 0 obj -<< -/S /URI -/URI (false) ->> -endobj -668 0 obj -<< -/Subtype /Link -/A 667 0 R -/Type /Annot -/Rect [72 336.493 271.8 347.806] -/Border [0 0 0] ->> -endobj -669 0 obj -<< -/S /URI -/URI (false) ->> -endobj -670 0 obj -<< -/Subtype /Link -/A 669 0 R -/Type /Annot -/Rect [72 325.18 88.2 336.493] -/Border [0 0 0] ->> -endobj -671 0 obj -<< -/S /URI -/URI (false) ->> -endobj -672 0 obj -<< -/Subtype /Link -/A 671 0 R -/Type /Annot -/Rect [88.2 325.18 93.6 336.493] -/Border [0 0 0] ->> -endobj -673 0 obj -<< -/S /URI -/URI (false) ->> -endobj -674 0 obj -<< -/Subtype /Link -/A 673 0 R -/Type /Annot -/Rect [93.6 325.18 131.4 336.493] -/Border [0 0 0] ->> -endobj -675 0 obj -<< -/S /URI -/URI (false) ->> -endobj -676 0 obj -<< -/Subtype /Link -/A 675 0 R -/Type /Annot -/Rect [131.4 325.18 136.8 336.493] -/Border [0 0 0] ->> -endobj -677 0 obj -<< -/S /URI -/URI (false) ->> -endobj -678 0 obj -<< -/Subtype /Link -/A 677 0 R -/Type /Annot -/Rect [136.8 325.18 142.2 336.493] -/Border [0 0 0] ->> -endobj -679 0 obj -<< -/S /URI -/URI (false) ->> -endobj -680 0 obj -<< -/Subtype /Link -/A 679 0 R -/Type /Annot -/Rect [72 313.867 82.8 325.18] -/Border [0 0 0] ->> -endobj -681 0 obj -<< -/S /URI -/URI (false) ->> -endobj -682 0 obj -<< -/Subtype /Link -/A 681 0 R -/Type /Annot -/Rect [82.8 313.867 115.2 325.18] -/Border [0 0 0] ->> -endobj -683 0 obj -<< -/S /URI -/URI (false) ->> -endobj -684 0 obj -<< -/Subtype /Link -/A 683 0 R -/Type /Annot -/Rect [115.2 313.867 120.6 325.18] -/Border [0 0 0] ->> -endobj -685 0 obj -<< -/S /URI -/URI (false) ->> -endobj -686 0 obj -<< -/Subtype /Link -/A 685 0 R -/Type /Annot -/Rect [120.6 313.867 126 325.18] -/Border [0 0 0] ->> -endobj -687 0 obj -<< -/S /URI -/URI (false) ->> -endobj -688 0 obj -<< -/Subtype /Link -/A 687 0 R -/Type /Annot -/Rect [126 313.867 136.8 325.18] -/Border [0 0 0] ->> -endobj -689 0 obj -<< -/S /URI -/URI (false) ->> -endobj -690 0 obj -<< -/Subtype /Link -/A 689 0 R -/Type /Annot -/Rect [136.8 313.867 142.2 325.18] -/Border [0 0 0] ->> -endobj -691 0 obj -<< -/S /URI -/URI (false) ->> -endobj -692 0 obj -<< -/Subtype /Link -/A 691 0 R -/Type /Annot -/Rect [142.2 313.867 147.6 325.18] -/Border [0 0 0] ->> -endobj -693 0 obj -<< -/S /URI -/URI (false) ->> -endobj -694 0 obj -<< -/Subtype /Link -/A 693 0 R -/Type /Annot -/Rect [147.6 313.867 153 325.18] -/Border [0 0 0] ->> -endobj -695 0 obj -<< -/S /URI -/URI (false) ->> -endobj -696 0 obj -<< -/Subtype /Link -/A 695 0 R -/Type /Annot -/Rect [72 279.928 271.8 291.241] -/Border [0 0 0] ->> -endobj -697 0 obj -<< -/S /URI -/URI (false) ->> -endobj -698 0 obj -<< -/Subtype /Link -/A 697 0 R -/Type /Annot -/Rect [72 268.615 88.2 279.928] -/Border [0 0 0] ->> -endobj -699 0 obj -<< -/S /URI -/URI (false) ->> -endobj -700 0 obj -<< -/Subtype /Link -/A 699 0 R -/Type /Annot -/Rect [88.2 268.615 93.6 279.928] -/Border [0 0 0] ->> -endobj -701 0 obj -<< -/S /URI -/URI (false) ->> -endobj -702 0 obj -<< -/Subtype /Link -/A 701 0 R -/Type /Annot -/Rect [93.6 268.615 131.4 279.928] -/Border [0 0 0] ->> -endobj -703 0 obj -<< -/S /URI -/URI (false) ->> -endobj -704 0 obj -<< -/Subtype /Link -/A 703 0 R -/Type /Annot -/Rect [131.4 268.615 136.8 279.928] -/Border [0 0 0] ->> -endobj -705 0 obj -<< -/S /URI -/URI (false) ->> -endobj -706 0 obj -<< -/Subtype /Link -/A 705 0 R -/Type /Annot -/Rect [136.8 268.615 142.2 279.928] -/Border [0 0 0] ->> -endobj -707 0 obj -<< -/S /URI -/URI (false) ->> -endobj -708 0 obj -<< -/Subtype /Link -/A 707 0 R -/Type /Annot -/Rect [72 257.302 82.8 268.615] -/Border [0 0 0] ->> -endobj -709 0 obj -<< -/S /URI -/URI (false) ->> -endobj -710 0 obj -<< -/Subtype /Link -/A 709 0 R -/Type /Annot -/Rect [82.8 257.302 120.6 268.615] -/Border [0 0 0] ->> -endobj -711 0 obj -<< -/S /URI -/URI (false) ->> -endobj -712 0 obj -<< -/Subtype /Link -/A 711 0 R -/Type /Annot -/Rect [120.6 257.302 126 268.615] -/Border [0 0 0] ->> -endobj -713 0 obj -<< -/S /URI -/URI (false) ->> -endobj -714 0 obj -<< -/Subtype /Link -/A 713 0 R -/Type /Annot -/Rect [126 257.302 131.4 268.615] -/Border [0 0 0] ->> -endobj -715 0 obj -<< -/S /URI -/URI (false) ->> -endobj -716 0 obj -<< -/Subtype /Link -/A 715 0 R -/Type /Annot -/Rect [131.4 257.302 136.8 268.615] -/Border [0 0 0] ->> -endobj -717 0 obj -<< -/S /URI -/URI (false) ->> -endobj -718 0 obj -<< -/Subtype /Link -/A 717 0 R -/Type /Annot -/Rect [72 245.989 93.6 257.302] -/Border [0 0 0] ->> -endobj -719 0 obj -<< -/S /URI -/URI (false) ->> -endobj -720 0 obj -<< -/Subtype /Link -/A 719 0 R -/Type /Annot -/Rect [93.6 245.989 109.8 257.302] -/Border [0 0 0] ->> -endobj -721 0 obj -<< -/S /URI -/URI (false) ->> -endobj -722 0 obj -<< -/Subtype /Link -/A 721 0 R -/Type /Annot -/Rect [109.8 245.989 115.2 257.302] -/Border [0 0 0] ->> -endobj -723 0 obj -<< -/S /URI -/URI (false) ->> -endobj -724 0 obj -<< -/Subtype /Link -/A 723 0 R -/Type /Annot -/Rect [115.2 245.989 120.6 257.302] -/Border [0 0 0] ->> -endobj -725 0 obj -<< -/S /URI -/URI (false) ->> -endobj -726 0 obj -<< -/Subtype /Link -/A 725 0 R -/Type /Annot -/Rect [120.6 245.989 131.4 257.302] -/Border [0 0 0] ->> -endobj -727 0 obj -<< -/S /URI -/URI (false) ->> -endobj -728 0 obj -<< -/Subtype /Link -/A 727 0 R -/Type /Annot -/Rect [131.4 245.989 136.8 257.302] -/Border [0 0 0] ->> -endobj -729 0 obj -<< -/S /URI -/URI (false) ->> -endobj -730 0 obj -<< -/Subtype /Link -/A 729 0 R -/Type /Annot -/Rect [72 234.676 93.6 245.989] -/Border [0 0 0] ->> -endobj -731 0 obj -<< -/S /URI -/URI (false) ->> -endobj -732 0 obj -<< -/Subtype /Link -/A 731 0 R -/Type /Annot -/Rect [93.6 234.676 126 245.989] -/Border [0 0 0] ->> -endobj -733 0 obj -<< -/S /URI -/URI (false) ->> -endobj -734 0 obj -<< -/Subtype /Link -/A 733 0 R -/Type /Annot -/Rect [126 234.676 131.4 245.989] -/Border [0 0 0] ->> -endobj -735 0 obj -<< -/S /URI -/URI (false) ->> -endobj -736 0 obj -<< -/Subtype /Link -/A 735 0 R -/Type /Annot -/Rect [131.4 234.676 136.8 245.989] -/Border [0 0 0] ->> -endobj -737 0 obj -<< -/S /URI -/URI (false) ->> -endobj -738 0 obj -<< -/Subtype /Link -/A 737 0 R -/Type /Annot -/Rect [136.8 234.676 147.6 245.989] -/Border [0 0 0] ->> -endobj -739 0 obj -<< -/S /URI -/URI (false) ->> -endobj -740 0 obj -<< -/Subtype /Link -/A 739 0 R -/Type /Annot -/Rect [147.6 234.676 153 245.989] -/Border [0 0 0] ->> -endobj -741 0 obj -<< -/S /URI -/URI (false) ->> -endobj -742 0 obj -<< -/Subtype /Link -/A 741 0 R -/Type /Annot -/Rect [72 223.363 93.6 234.676] -/Border [0 0 0] ->> -endobj -743 0 obj -<< -/S /URI -/URI (false) ->> -endobj -744 0 obj -<< -/Subtype /Link -/A 743 0 R -/Type /Annot -/Rect [93.6 223.363 115.2 234.676] -/Border [0 0 0] ->> -endobj -745 0 obj -<< -/S /URI -/URI (false) ->> -endobj -746 0 obj -<< -/Subtype /Link -/A 745 0 R -/Type /Annot -/Rect [115.2 223.363 120.6 234.676] -/Border [0 0 0] ->> -endobj -747 0 obj -<< -/S /URI -/URI (false) ->> -endobj -748 0 obj -<< -/Subtype /Link -/A 747 0 R -/Type /Annot -/Rect [120.6 223.363 126 234.676] -/Border [0 0 0] ->> -endobj -749 0 obj -<< -/S /URI -/URI (false) ->> -endobj -750 0 obj -<< -/Subtype /Link -/A 749 0 R -/Type /Annot -/Rect [126 223.363 136.8 234.676] -/Border [0 0 0] ->> -endobj -751 0 obj -<< -/S /URI -/URI (false) ->> -endobj -752 0 obj -<< -/Subtype /Link -/A 751 0 R -/Type /Annot -/Rect [136.8 223.363 142.2 234.676] -/Border [0 0 0] ->> -endobj -753 0 obj -<< -/S /URI -/URI (false) ->> -endobj -754 0 obj -<< -/Subtype /Link -/A 753 0 R -/Type /Annot -/Rect [72 212.05 93.6 223.363] -/Border [0 0 0] ->> -endobj -755 0 obj -<< -/S /URI -/URI (false) ->> -endobj -756 0 obj -<< -/Subtype /Link -/A 755 0 R -/Type /Annot -/Rect [93.6 212.05 120.6 223.363] -/Border [0 0 0] ->> -endobj -757 0 obj -<< -/S /URI -/URI (false) ->> -endobj -758 0 obj -<< -/Subtype /Link -/A 757 0 R -/Type /Annot -/Rect [120.6 212.05 126 223.363] -/Border [0 0 0] ->> -endobj -759 0 obj -<< -/S /URI -/URI (false) ->> -endobj -760 0 obj -<< -/Subtype /Link -/A 759 0 R -/Type /Annot -/Rect [126 212.05 131.4 223.363] -/Border [0 0 0] ->> -endobj -761 0 obj -<< -/S /URI -/URI (false) ->> -endobj -762 0 obj -<< -/Subtype /Link -/A 761 0 R -/Type /Annot -/Rect [131.4 212.05 142.2 223.363] -/Border [0 0 0] ->> -endobj -763 0 obj -<< -/S /URI -/URI (false) ->> -endobj -764 0 obj -<< -/Subtype /Link -/A 763 0 R -/Type /Annot -/Rect [72 200.737 82.8 212.05] -/Border [0 0 0] ->> -endobj -765 0 obj -<< -/S /URI -/URI (false) ->> -endobj -766 0 obj -<< -/Subtype /Link -/A 765 0 R -/Type /Annot -/Rect [82.8 200.737 88.2 212.05] -/Border [0 0 0] ->> -endobj -767 0 obj -<< -/S /URI -/URI (false) ->> -endobj -768 0 obj -<< -/Subtype /Link -/A 767 0 R -/Type /Annot -/Rect [72 189.424 77.4 200.737] -/Border [0 0 0] ->> -endobj -769 0 obj -<< -/S /URI -/URI (false) ->> -endobj -770 0 obj -<< -/Subtype /Link -/A 769 0 R -/Type /Annot -/Rect [77.4 189.424 82.8 200.737] -/Border [0 0 0] ->> -endobj -771 0 obj -<< -/S /URI -/URI (false) ->> -endobj -772 0 obj -<< -/Subtype /Link -/A 771 0 R -/Type /Annot -/Rect [82.8 189.424 88.2 200.737] -/Border [0 0 0] ->> -endobj -507 0 obj -<< -/Type /Page -/Parent 1 0 R -/MediaBox [0 0 612 792] -/Contents 505 0 R -/Resources 506 0 R -/Annots [510 0 R 512 0 R 514 0 R 516 0 R 518 0 R 520 0 R 522 0 R 524 0 R 526 0 R 528 0 R 530 0 R 532 0 R 534 0 R 536 0 R 538 0 R 540 0 R 542 0 R 544 0 R 546 0 R 548 0 R 550 0 R 552 0 R 554 0 R 556 0 R 558 0 R 560 0 R 562 0 R 564 0 R 566 0 R 568 0 R 570 0 R 572 0 R 574 0 R 576 0 R 578 0 R 580 0 R 582 0 R 584 0 R 586 0 R 588 0 R 590 0 R 592 0 R 594 0 R 596 0 R 598 0 R 600 0 R 602 0 R 604 0 R 606 0 R 608 0 R 610 0 R 612 0 R 614 0 R 616 0 R 618 0 R 620 0 R 622 0 R 624 0 R 626 0 R 628 0 R 630 0 R 632 0 R 634 0 R 636 0 R 638 0 R 640 0 R 642 0 R 644 0 R 646 0 R 648 0 R 650 0 R 652 0 R 654 0 R 656 0 R 658 0 R 660 0 R 662 0 R 664 0 R 666 0 R 668 0 R 670 0 R 672 0 R 674 0 R 676 0 R 678 0 R 680 0 R 682 0 R 684 0 R 686 0 R 688 0 R 690 0 R 692 0 R 694 0 R 696 0 R 698 0 R 700 0 R 702 0 R 704 0 R 706 0 R 708 0 R 710 0 R 712 0 R 714 0 R 716 0 R 718 0 R 720 0 R 722 0 R 724 0 R 726 0 R 728 0 R 730 0 R 732 0 R 734 0 R 736 0 R 738 0 R 740 0 R 742 0 R 744 0 R 746 0 R 748 0 R 750 0 R 752 0 R 754 0 R 756 0 R 758 0 R 760 0 R 762 0 R 764 0 R 766 0 R 768 0 R 770 0 R 772 0 R] ->> -endobj -506 0 obj -<< -/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] -/Font << -/F4 16 0 R -/F3 9 0 R -/F6 44 0 R -/F5 29 0 R ->> ->> -endobj -505 0 obj -<< -/Length 2518 -/Filter /FlateDecode ->> -stream -x\K,ymз   X%(C3[ɏHxo?ΗOyo_E1X, - Wp?s.ΜR˄ }?}3ooc `G4r@Iq6{Ɍ{?f7Lt__mi,#'2e{j3~'}Oh2;bxy.w=Ο~8ΩqLR А4Gj +,AE -5,*-ʬVɴ*arU9^C#dFw*OMT U]$aF<d"x^*xhZBt+ -_$ W]Z9*yKU(ͽ҃iS32gBQ*z U'oW0oh5evqpĹ)#M$F -iA+E7 -?؃W䲠NYyЄLR08|<-BAV?蹎!聘19NZfdy" ̖S6-ƚX@-ʢ]` SVxwlK>S\2TA<88N=Vy+]]h;#!,(;sp*dC]̱0 nd\qb4T&(tb}.ϡ/>1Kj ̅_$KRp>7KBI 53"sf'}|H$07?)ğ ol8j: U_ei5oZ1UyXn3hX 5y#=SN!Lie"$IJ떤>/$,)׵nזUox!dH1ȀZ{Ksv]/$l}A&5)Co\!n ۬ 5s,Tn{P(@,m$wr+B].q/J =oFXazXJ&~Nߋ.{BByvjس2DJDD˵k5K -ϱu*rޏzҾF:%F|s5 •hzVrAkInxħ3ؽ7wǻZSu]a^LWFtJ&Q54kMXUU]+'P`&_JrA;{ă[)IsO @ei]4 w pP"Q LF-ãP@>7QE*4[8quqBrmn}JR棄 feve)Uq"_IBS.2JʸΑvrG͹i:%:b?e5le.ͱmq -4F _x@%S})f\q4?όJ۠Y`2C_FWbN -߇:ǤRGrƪ6T[b%crݒ/J -- -|.""ĊĊehϬ/HHdd;P$W4uA9j1Bht{>hgʡ5ׯ ]_$w#t|6&-Շ^P@;@a7Ic/U|NjU0?8jXaꐎnEԎFC:&Ӽ;:F ,WsÍN:"/> -endobj -778 0 obj -<< -/Subtype /Link -/A 777 0 R -/Type /Annot -/Rect [72 695.502 281.484 720] -/Border [0 0 0] ->> -endobj -779 0 obj -<< -/S /URI -/URI (false) ->> -endobj -780 0 obj -<< -/Subtype /Link -/A 779 0 R -/Type /Annot -/Rect [72 673.002 521.296875 685.502] -/Border [0 0 0] ->> -endobj -781 0 obj -<< -/S /URI -/URI (false) ->> -endobj -782 0 obj -<< -/Subtype /Link -/A 781 0 R -/Type /Annot -/Rect [72 660.502 528.162109 673.002] -/Border [0 0 0] ->> -endobj -783 0 obj -<< -/S /URI -/URI (false) ->> -endobj -784 0 obj -<< -/Subtype /Link -/A 783 0 R -/Type /Annot -/Rect [72 648.002 529.080078 660.502] -/Border [0 0 0] ->> -endobj -785 0 obj -<< -/S /URI -/URI (false) ->> -endobj -786 0 obj -<< -/Subtype /Link -/A 785 0 R -/Type /Annot -/Rect [72 635.502 518.967773 648.002] -/Border [0 0 0] ->> -endobj -787 0 obj -<< -/S /URI -/URI (false) ->> -endobj -788 0 obj -<< -/Subtype /Link -/A 787 0 R -/Type /Annot -/Rect [72 623.002 517.605469 635.502] -/Border [0 0 0] ->> -endobj -789 0 obj -<< -/S /URI -/URI (false) ->> -endobj -790 0 obj -<< -/Subtype /Link -/A 789 0 R -/Type /Annot -/Rect [72 610.502 211.970703 623.002] -/Border [0 0 0] ->> -endobj -791 0 obj -<< -/S /URI -/URI (false) ->> -endobj -792 0 obj -<< -/Subtype /Link -/A 791 0 R -/Type /Annot -/Rect [72 588.002 137.439453 600.502] -/Border [0 0 0] ->> -endobj -793 0 obj -<< -/S /URI -/URI (false) ->> -endobj -794 0 obj -<< -/Subtype /Link -/A 793 0 R -/Type /Annot -/Rect [137.439453 587.932 203.439453 600.502] -/Border [0 0 0] ->> -endobj -795 0 obj -<< -/S /URI -/URI (false) ->> -endobj -796 0 obj -<< -/Subtype /Link -/A 795 0 R -/Type /Annot -/Rect [203.439453 588.002 539.933594 600.502] -/Border [0 0 0] ->> -endobj -797 0 obj -<< -/S /URI -/URI (false) ->> -endobj -798 0 obj -<< -/Subtype /Link -/A 797 0 R -/Type /Annot -/Rect [72 575.502 526.248047 588.002] -/Border [0 0 0] ->> -endobj -799 0 obj -<< -/S /URI -/URI (false) ->> -endobj -800 0 obj -<< -/Subtype /Link -/A 799 0 R -/Type /Annot -/Rect [72 563.002 165.515625 575.502] -/Border [0 0 0] ->> -endobj -801 0 obj -<< -/S /URI -/URI (false) ->> -endobj -802 0 obj -<< -/Subtype /Link -/A 801 0 R -/Type /Annot -/Rect [165.515625 562.932 267.515625 575.502] -/Border [0 0 0] ->> -endobj -803 0 obj -<< -/S /URI -/URI (false) ->> -endobj -804 0 obj -<< -/Subtype /Link -/A 803 0 R -/Type /Annot -/Rect [267.515625 563.002 365.674805 575.502] -/Border [0 0 0] ->> -endobj -805 0 obj -<< -/S /URI -/URI (false) ->> -endobj -806 0 obj -<< -/Subtype /Link -/A 805 0 R -/Type /Annot -/Rect [365.674805 562.932 431.674805 575.502] -/Border [0 0 0] ->> -endobj -807 0 obj -<< -/S /URI -/URI (false) ->> -endobj -808 0 obj -<< -/Subtype /Link -/A 807 0 R -/Type /Annot -/Rect [431.674805 563.002 532.045898 575.502] -/Border [0 0 0] ->> -endobj -809 0 obj -<< -/S /URI -/URI (false) ->> -endobj -810 0 obj -<< -/Subtype /Link -/A 809 0 R -/Type /Annot -/Rect [72 550.502 132.615234 563.002] -/Border [0 0 0] ->> -endobj -811 0 obj -<< -/S /URI -/URI (false) ->> -endobj -812 0 obj -<< -/Subtype /Link -/A 811 0 R -/Type /Annot -/Rect [132.615234 550.432 300.615234 563.002] -/Border [0 0 0] ->> -endobj -813 0 obj -<< -/S /URI -/URI (false) ->> -endobj -814 0 obj -<< -/Subtype /Link -/A 813 0 R -/Type /Annot -/Rect [300.615234 550.502 521.274414 563.002] -/Border [0 0 0] ->> -endobj -815 0 obj -<< -/S /URI -/URI (false) ->> -endobj -816 0 obj -<< -/Subtype /Link -/A 815 0 R -/Type /Annot -/Rect [72 538.002 124.436523 550.502] -/Border [0 0 0] ->> -endobj -817 0 obj -<< -/S /URI -/URI (false) ->> -endobj -818 0 obj -<< -/Subtype /Link -/A 817 0 R -/Type /Annot -/Rect [72 515.502 415.745117 528.002] -/Border [0 0 0] ->> -endobj -819 0 obj -<< -/S /URI -/URI (false) ->> -endobj -820 0 obj -<< -/Subtype /Link -/A 819 0 R -/Type /Annot -/Rect [415.745117 515.432 475.745117 528.002] -/Border [0 0 0] ->> -endobj -821 0 obj -<< -/S /URI -/URI (false) ->> -endobj -822 0 obj -<< -/Subtype /Link -/A 821 0 R -/Type /Annot -/Rect [475.745117 515.502 505.808594 528.002] -/Border [0 0 0] ->> -endobj -823 0 obj -<< -/S /URI -/URI (false) ->> -endobj -824 0 obj -<< -/Subtype /Link -/A 823 0 R -/Type /Annot -/Rect [72 503.002 241.760742 515.502] -/Border [0 0 0] ->> -endobj -825 0 obj -<< -/S /URI -/URI (false) ->> -endobj -826 0 obj -<< -/Subtype /Link -/A 825 0 R -/Type /Annot -/Rect [241.760742 502.932 295.760742 515.502] -/Border [0 0 0] ->> -endobj -827 0 obj -<< -/S /URI -/URI (false) ->> -endobj -828 0 obj -<< -/Subtype /Link -/A 827 0 R -/Type /Annot -/Rect [295.760742 503.002 518.744141 515.502] -/Border [0 0 0] ->> -endobj -829 0 obj -<< -/S /URI -/URI (false) ->> -endobj -830 0 obj -<< -/Subtype /Link -/A 829 0 R -/Type /Annot -/Rect [72 490.502 343.845703 503.002] -/Border [0 0 0] ->> -endobj -831 0 obj -<< -/S /URI -/URI (false) ->> -endobj -832 0 obj -<< -/Subtype /Link -/A 831 0 R -/Type /Annot -/Rect [343.845703 490.432 445.845703 503.002] -/Border [0 0 0] ->> -endobj -833 0 obj -<< -/S /URI -/URI (false) ->> -endobj -834 0 obj -<< -/Subtype /Link -/A 833 0 R -/Type /Annot -/Rect [445.845703 490.502 526.231445 503.002] -/Border [0 0 0] ->> -endobj -835 0 obj -<< -/S /URI -/URI (false) ->> -endobj -836 0 obj -<< -/Subtype /Link -/A 835 0 R -/Type /Annot -/Rect [72 478.002 525.100586 490.502] -/Border [0 0 0] ->> -endobj -837 0 obj -<< -/S /URI -/URI (false) ->> -endobj -838 0 obj -<< -/Subtype /Link -/A 837 0 R -/Type /Annot -/Rect [72 465.502 317.595703 478.002] -/Border [0 0 0] ->> -endobj -839 0 obj -<< -/S /URI -/URI (false) ->> -endobj -840 0 obj -<< -/Subtype /Link -/A 839 0 R -/Type /Annot -/Rect [72 444.189 336.6 455.502] -/Border [0 0 0] ->> -endobj -841 0 obj -<< -/S /URI -/URI (false) ->> -endobj -842 0 obj -<< -/Subtype /Link -/A 841 0 R -/Type /Annot -/Rect [72 432.876 88.2 444.189] -/Border [0 0 0] ->> -endobj -843 0 obj -<< -/S /URI -/URI (false) ->> -endobj -844 0 obj -<< -/Subtype /Link -/A 843 0 R -/Type /Annot -/Rect [88.2 432.876 93.6 444.189] -/Border [0 0 0] ->> -endobj -845 0 obj -<< -/S /URI -/URI (false) ->> -endobj -846 0 obj -<< -/Subtype /Link -/A 845 0 R -/Type /Annot -/Rect [93.6 432.876 99 444.189] -/Border [0 0 0] ->> -endobj -847 0 obj -<< -/S /URI -/URI (false) ->> -endobj -848 0 obj -<< -/Subtype /Link -/A 847 0 R -/Type /Annot -/Rect [99 432.876 104.4 444.189] -/Border [0 0 0] ->> -endobj -849 0 obj -<< -/S /URI -/URI (false) ->> -endobj -850 0 obj -<< -/Subtype /Link -/A 849 0 R -/Type /Annot -/Rect [72 421.563 88.2 432.876] -/Border [0 0 0] ->> -endobj -851 0 obj -<< -/S /URI -/URI (false) ->> -endobj -852 0 obj -<< -/Subtype /Link -/A 851 0 R -/Type /Annot -/Rect [88.2 421.563 93.6 432.876] -/Border [0 0 0] ->> -endobj -853 0 obj -<< -/S /URI -/URI (false) ->> -endobj -854 0 obj -<< -/Subtype /Link -/A 853 0 R -/Type /Annot -/Rect [93.6 421.563 109.8 432.876] -/Border [0 0 0] ->> -endobj -855 0 obj -<< -/S /URI -/URI (false) ->> -endobj -856 0 obj -<< -/Subtype /Link -/A 855 0 R -/Type /Annot -/Rect [109.8 421.563 115.2 432.876] -/Border [0 0 0] ->> -endobj -857 0 obj -<< -/S /URI -/URI (false) ->> -endobj -858 0 obj -<< -/Subtype /Link -/A 857 0 R -/Type /Annot -/Rect [72 410.25 99 421.563] -/Border [0 0 0] ->> -endobj -859 0 obj -<< -/S /URI -/URI (false) ->> -endobj -860 0 obj -<< -/Subtype /Link -/A 859 0 R -/Type /Annot -/Rect [99 410.25 104.4 421.563] -/Border [0 0 0] ->> -endobj -861 0 obj -<< -/S /URI -/URI (false) ->> -endobj -862 0 obj -<< -/Subtype /Link -/A 861 0 R -/Type /Annot -/Rect [104.4 410.25 120.6 421.563] -/Border [0 0 0] ->> -endobj -863 0 obj -<< -/S /URI -/URI (false) ->> -endobj -864 0 obj -<< -/Subtype /Link -/A 863 0 R -/Type /Annot -/Rect [120.6 410.25 126 421.563] -/Border [0 0 0] ->> -endobj -865 0 obj -<< -/S /URI -/URI (false) ->> -endobj -866 0 obj -<< -/Subtype /Link -/A 865 0 R -/Type /Annot -/Rect [126 410.25 131.4 421.563] -/Border [0 0 0] ->> -endobj -867 0 obj -<< -/S /URI -/URI (false) ->> -endobj -868 0 obj -<< -/Subtype /Link -/A 867 0 R -/Type /Annot -/Rect [131.4 410.25 136.8 421.563] -/Border [0 0 0] ->> -endobj -869 0 obj -<< -/S /URI -/URI (false) ->> -endobj -870 0 obj -<< -/Subtype /Link -/A 869 0 R -/Type /Annot -/Rect [136.8 410.25 153 421.563] -/Border [0 0 0] ->> -endobj -871 0 obj -<< -/S /URI -/URI (false) ->> -endobj -872 0 obj -<< -/Subtype /Link -/A 871 0 R -/Type /Annot -/Rect [153 410.25 158.4 421.563] -/Border [0 0 0] ->> -endobj -873 0 obj -<< -/S /URI -/URI (false) ->> -endobj -874 0 obj -<< -/Subtype /Link -/A 873 0 R -/Type /Annot -/Rect [158.4 410.25 217.8 421.563] -/Border [0 0 0] ->> -endobj -875 0 obj -<< -/S /URI -/URI (false) ->> -endobj -876 0 obj -<< -/Subtype /Link -/A 875 0 R -/Type /Annot -/Rect [217.8 410.25 223.2 421.563] -/Border [0 0 0] ->> -endobj -877 0 obj -<< -/S /URI -/URI (false) ->> -endobj -878 0 obj -<< -/Subtype /Link -/A 877 0 R -/Type /Annot -/Rect [223.2 410.25 228.6 421.563] -/Border [0 0 0] ->> -endobj -879 0 obj -<< -/S /URI -/URI (false) ->> -endobj -880 0 obj -<< -/Subtype /Link -/A 879 0 R -/Type /Annot -/Rect [72 398.937 82.8 410.25] -/Border [0 0 0] ->> -endobj -881 0 obj -<< -/S /URI -/URI (false) ->> -endobj -882 0 obj -<< -/Subtype /Link -/A 881 0 R -/Type /Annot -/Rect [82.8 398.937 142.2 410.25] -/Border [0 0 0] ->> -endobj -883 0 obj -<< -/S /URI -/URI (false) ->> -endobj -884 0 obj -<< -/Subtype /Link -/A 883 0 R -/Type /Annot -/Rect [142.2 398.937 147.6 410.25] -/Border [0 0 0] ->> -endobj -885 0 obj -<< -/S /URI -/URI (false) ->> -endobj -886 0 obj -<< -/Subtype /Link -/A 885 0 R -/Type /Annot -/Rect [147.6 398.937 153 410.25] -/Border [0 0 0] ->> -endobj -887 0 obj -<< -/S /URI -/URI (false) ->> -endobj -888 0 obj -<< -/Subtype /Link -/A 887 0 R -/Type /Annot -/Rect [153 398.937 174.6 410.25] -/Border [0 0 0] ->> -endobj -889 0 obj -<< -/S /URI -/URI (false) ->> -endobj -890 0 obj -<< -/Subtype /Link -/A 889 0 R -/Type /Annot -/Rect [174.6 398.937 180 410.25] -/Border [0 0 0] ->> -endobj -891 0 obj -<< -/S /URI -/URI (false) ->> -endobj -892 0 obj -<< -/Subtype /Link -/A 891 0 R -/Type /Annot -/Rect [180 398.937 185.4 410.25] -/Border [0 0 0] ->> -endobj -893 0 obj -<< -/S /URI -/URI (false) ->> -endobj -894 0 obj -<< -/Subtype /Link -/A 893 0 R -/Type /Annot -/Rect [185.4 398.937 190.8 410.25] -/Border [0 0 0] ->> -endobj -895 0 obj -<< -/S /URI -/URI (false) ->> -endobj -896 0 obj -<< -/Subtype /Link -/A 895 0 R -/Type /Annot -/Rect [72 376.311 190.8 387.624] -/Border [0 0 0] ->> -endobj -897 0 obj -<< -/S /URI -/URI (false) ->> -endobj -898 0 obj -<< -/Subtype /Link -/A 897 0 R -/Type /Annot -/Rect [72 364.998 88.2 376.311] -/Border [0 0 0] ->> -endobj -899 0 obj -<< -/S /URI -/URI (false) ->> -endobj -900 0 obj -<< -/Subtype /Link -/A 899 0 R -/Type /Annot -/Rect [88.2 364.998 93.6 376.311] -/Border [0 0 0] ->> -endobj -901 0 obj -<< -/S /URI -/URI (false) ->> -endobj -902 0 obj -<< -/Subtype /Link -/A 901 0 R -/Type /Annot -/Rect [93.6 364.998 131.4 376.311] -/Border [0 0 0] ->> -endobj -903 0 obj -<< -/S /URI -/URI (false) ->> -endobj -904 0 obj -<< -/Subtype /Link -/A 903 0 R -/Type /Annot -/Rect [131.4 364.998 136.8 376.311] -/Border [0 0 0] ->> -endobj -905 0 obj -<< -/S /URI -/URI (false) ->> -endobj -906 0 obj -<< -/Subtype /Link -/A 905 0 R -/Type /Annot -/Rect [136.8 364.998 142.2 376.311] -/Border [0 0 0] ->> -endobj -907 0 obj -<< -/S /URI -/URI (false) ->> -endobj -908 0 obj -<< -/Subtype /Link -/A 907 0 R -/Type /Annot -/Rect [142.2 364.998 147.6 376.311] -/Border [0 0 0] ->> -endobj -909 0 obj -<< -/S /URI -/URI (false) ->> -endobj -910 0 obj -<< -/Subtype /Link -/A 909 0 R -/Type /Annot -/Rect [72 353.685 104.4 364.998] -/Border [0 0 0] ->> -endobj -911 0 obj -<< -/S /URI -/URI (false) ->> -endobj -912 0 obj -<< -/Subtype /Link -/A 911 0 R -/Type /Annot -/Rect [72 342.372 88.2 353.685] -/Border [0 0 0] ->> -endobj -913 0 obj -<< -/S /URI -/URI (false) ->> -endobj -914 0 obj -<< -/Subtype /Link -/A 913 0 R -/Type /Annot -/Rect [88.2 342.372 93.6 353.685] -/Border [0 0 0] ->> -endobj -915 0 obj -<< -/S /URI -/URI (false) ->> -endobj -916 0 obj -<< -/Subtype /Link -/A 915 0 R -/Type /Annot -/Rect [93.6 342.372 131.4 353.685] -/Border [0 0 0] ->> -endobj -917 0 obj -<< -/S /URI -/URI (false) ->> -endobj -918 0 obj -<< -/Subtype /Link -/A 917 0 R -/Type /Annot -/Rect [131.4 342.372 136.8 353.685] -/Border [0 0 0] ->> -endobj -919 0 obj -<< -/S /URI -/URI (false) ->> -endobj -920 0 obj -<< -/Subtype /Link -/A 919 0 R -/Type /Annot -/Rect [136.8 342.372 142.2 353.685] -/Border [0 0 0] ->> -endobj -921 0 obj -<< -/S /URI -/URI (false) ->> -endobj -922 0 obj -<< -/Subtype /Link -/A 921 0 R -/Type /Annot -/Rect [142.2 342.372 147.6 353.685] -/Border [0 0 0] ->> -endobj -923 0 obj -<< -/S /URI -/URI (false) ->> -endobj -924 0 obj -<< -/Subtype /Link -/A 923 0 R -/Type /Annot -/Rect [72 319.746 255.6 331.059] -/Border [0 0 0] ->> -endobj -925 0 obj -<< -/S /URI -/URI (false) ->> -endobj -926 0 obj -<< -/Subtype /Link -/A 925 0 R -/Type /Annot -/Rect [72 308.433 99 319.746] -/Border [0 0 0] ->> -endobj -927 0 obj -<< -/S /URI -/URI (false) ->> -endobj -928 0 obj -<< -/Subtype /Link -/A 927 0 R -/Type /Annot -/Rect [99 308.433 104.4 319.746] -/Border [0 0 0] ->> -endobj -929 0 obj -<< -/S /URI -/URI (false) ->> -endobj -930 0 obj -<< -/Subtype /Link -/A 929 0 R -/Type /Annot -/Rect [104.4 308.433 131.4 319.746] -/Border [0 0 0] ->> -endobj -931 0 obj -<< -/S /URI -/URI (false) ->> -endobj -932 0 obj -<< -/Subtype /Link -/A 931 0 R -/Type /Annot -/Rect [131.4 308.433 136.8 319.746] -/Border [0 0 0] ->> -endobj -933 0 obj -<< -/S /URI -/URI (false) ->> -endobj -934 0 obj -<< -/Subtype /Link -/A 933 0 R -/Type /Annot -/Rect [136.8 308.433 142.2 319.746] -/Border [0 0 0] ->> -endobj -935 0 obj -<< -/S /URI -/URI (false) ->> -endobj -936 0 obj -<< -/Subtype /Link -/A 935 0 R -/Type /Annot -/Rect [142.2 308.433 147.6 319.746] -/Border [0 0 0] ->> -endobj -937 0 obj -<< -/S /URI -/URI (false) ->> -endobj -938 0 obj -<< -/Subtype /Link -/A 937 0 R -/Type /Annot -/Rect [147.6 308.433 163.8 319.746] -/Border [0 0 0] ->> -endobj -939 0 obj -<< -/S /URI -/URI (false) ->> -endobj -940 0 obj -<< -/Subtype /Link -/A 939 0 R -/Type /Annot -/Rect [163.8 308.433 169.2 319.746] -/Border [0 0 0] ->> -endobj -941 0 obj -<< -/S /URI -/URI (false) ->> -endobj -942 0 obj -<< -/Subtype /Link -/A 941 0 R -/Type /Annot -/Rect [169.2 308.433 261 319.746] -/Border [0 0 0] ->> -endobj -943 0 obj -<< -/S /URI -/URI (false) ->> -endobj -944 0 obj -<< -/Subtype /Link -/A 943 0 R -/Type /Annot -/Rect [261 308.433 266.4 319.746] -/Border [0 0 0] ->> -endobj -945 0 obj -<< -/S /URI -/URI (false) ->> -endobj -946 0 obj -<< -/Subtype /Link -/A 945 0 R -/Type /Annot -/Rect [266.4 308.433 271.8 319.746] -/Border [0 0 0] ->> -endobj -947 0 obj -<< -/S /URI -/URI (false) ->> -endobj -948 0 obj -<< -/Subtype /Link -/A 947 0 R -/Type /Annot -/Rect [271.8 308.433 277.2 319.746] -/Border [0 0 0] ->> -endobj -949 0 obj -<< -/S /URI -/URI (false) ->> -endobj -950 0 obj -<< -/Subtype /Link -/A 949 0 R -/Type /Annot -/Rect [277.2 308.433 282.6 319.746] -/Border [0 0 0] ->> -endobj -951 0 obj -<< -/S /URI -/URI (false) ->> -endobj -952 0 obj -<< -/Subtype /Link -/A 951 0 R -/Type /Annot -/Rect [282.6 308.433 433.8 319.746] -/Border [0 0 0] ->> -endobj -953 0 obj -<< -/S /URI -/URI (false) ->> -endobj -954 0 obj -<< -/Subtype /Link -/A 953 0 R -/Type /Annot -/Rect [72 285.807 88.2 297.12] -/Border [0 0 0] ->> -endobj -955 0 obj -<< -/S /URI -/URI (false) ->> -endobj -956 0 obj -<< -/Subtype /Link -/A 955 0 R -/Type /Annot -/Rect [88.2 285.807 93.6 297.12] -/Border [0 0 0] ->> -endobj -957 0 obj -<< -/S /URI -/URI (false) ->> -endobj -958 0 obj -<< -/Subtype /Link -/A 957 0 R -/Type /Annot -/Rect [93.6 285.807 99 297.12] -/Border [0 0 0] ->> -endobj -959 0 obj -<< -/S /URI -/URI (false) ->> -endobj -960 0 obj -<< -/Subtype /Link -/A 959 0 R -/Type /Annot -/Rect [99 285.807 104.4 297.12] -/Border [0 0 0] ->> -endobj -961 0 obj -<< -/S /URI -/URI (false) ->> -endobj -962 0 obj -<< -/Subtype /Link -/A 961 0 R -/Type /Annot -/Rect [104.4 285.807 109.8 297.12] -/Border [0 0 0] ->> -endobj -963 0 obj -<< -/S /URI -/URI (false) ->> -endobj -964 0 obj -<< -/Subtype /Link -/A 963 0 R -/Type /Annot -/Rect [109.8 285.807 115.2 297.12] -/Border [0 0 0] ->> -endobj -965 0 obj -<< -/S /URI -/URI (false) ->> -endobj -966 0 obj -<< -/Subtype /Link -/A 965 0 R -/Type /Annot -/Rect [115.2 285.807 120.6 297.12] -/Border [0 0 0] ->> -endobj -967 0 obj -<< -/S /URI -/URI (false) ->> -endobj -968 0 obj -<< -/Subtype /Link -/A 967 0 R -/Type /Annot -/Rect [120.6 285.807 147.6 297.12] -/Border [0 0 0] ->> -endobj -969 0 obj -<< -/S /URI -/URI (false) ->> -endobj -970 0 obj -<< -/Subtype /Link -/A 969 0 R -/Type /Annot -/Rect [147.6 285.807 153 297.12] -/Border [0 0 0] ->> -endobj -971 0 obj -<< -/S /URI -/URI (false) ->> -endobj -972 0 obj -<< -/Subtype /Link -/A 971 0 R -/Type /Annot -/Rect [153 285.807 180 297.12] -/Border [0 0 0] ->> -endobj -973 0 obj -<< -/S /URI -/URI (false) ->> -endobj -974 0 obj -<< -/Subtype /Link -/A 973 0 R -/Type /Annot -/Rect [180 285.807 185.4 297.12] -/Border [0 0 0] ->> -endobj -975 0 obj -<< -/S /URI -/URI (false) ->> -endobj -976 0 obj -<< -/Subtype /Link -/A 975 0 R -/Type /Annot -/Rect [185.4 285.807 190.8 297.12] -/Border [0 0 0] ->> -endobj -977 0 obj -<< -/S /URI -/URI (false) ->> -endobj -978 0 obj -<< -/Subtype /Link -/A 977 0 R -/Type /Annot -/Rect [190.8 285.807 207 297.12] -/Border [0 0 0] ->> -endobj -979 0 obj -<< -/S /URI -/URI (false) ->> -endobj -980 0 obj -<< -/Subtype /Link -/A 979 0 R -/Type /Annot -/Rect [207 285.807 212.4 297.12] -/Border [0 0 0] ->> -endobj -981 0 obj -<< -/S /URI -/URI (false) ->> -endobj -982 0 obj -<< -/Subtype /Link -/A 981 0 R -/Type /Annot -/Rect [212.4 285.807 217.8 297.12] -/Border [0 0 0] ->> -endobj -983 0 obj -<< -/S /URI -/URI (false) ->> -endobj -984 0 obj -<< -/Subtype /Link -/A 983 0 R -/Type /Annot -/Rect [217.8 285.807 223.2 297.12] -/Border [0 0 0] ->> -endobj -985 0 obj -<< -/S /URI -/URI (false) ->> -endobj -986 0 obj -<< -/Subtype /Link -/A 985 0 R -/Type /Annot -/Rect [223.2 285.807 250.2 297.12] -/Border [0 0 0] ->> -endobj -987 0 obj -<< -/S /URI -/URI (false) ->> -endobj -988 0 obj -<< -/Subtype /Link -/A 987 0 R -/Type /Annot -/Rect [250.2 285.807 255.6 297.12] -/Border [0 0 0] ->> -endobj -989 0 obj -<< -/S /URI -/URI (false) ->> -endobj -990 0 obj -<< -/Subtype /Link -/A 989 0 R -/Type /Annot -/Rect [255.6 285.807 282.6 297.12] -/Border [0 0 0] ->> -endobj -991 0 obj -<< -/S /URI -/URI (false) ->> -endobj -992 0 obj -<< -/Subtype /Link -/A 991 0 R -/Type /Annot -/Rect [282.6 285.807 288 297.12] -/Border [0 0 0] ->> -endobj -993 0 obj -<< -/S /URI -/URI (false) ->> -endobj -994 0 obj -<< -/Subtype /Link -/A 993 0 R -/Type /Annot -/Rect [288 285.807 293.4 297.12] -/Border [0 0 0] ->> -endobj -995 0 obj -<< -/S /URI -/URI (false) ->> -endobj -996 0 obj -<< -/Subtype /Link -/A 995 0 R -/Type /Annot -/Rect [293.4 285.807 298.8 297.12] -/Border [0 0 0] ->> -endobj -997 0 obj -<< -/S /URI -/URI (false) ->> -endobj -998 0 obj -<< -/Subtype /Link -/A 997 0 R -/Type /Annot -/Rect [298.8 285.807 325.8 297.12] -/Border [0 0 0] ->> -endobj -999 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1000 0 obj -<< -/Subtype /Link -/A 999 0 R -/Type /Annot -/Rect [325.8 285.807 331.2 297.12] -/Border [0 0 0] ->> -endobj -1001 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1002 0 obj -<< -/Subtype /Link -/A 1001 0 R -/Type /Annot -/Rect [331.2 285.807 358.2 297.12] -/Border [0 0 0] ->> -endobj -1003 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1004 0 obj -<< -/Subtype /Link -/A 1003 0 R -/Type /Annot -/Rect [358.2 285.807 363.6 297.12] -/Border [0 0 0] ->> -endobj -1005 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1006 0 obj -<< -/Subtype /Link -/A 1005 0 R -/Type /Annot -/Rect [363.6 285.807 369 297.12] -/Border [0 0 0] ->> -endobj -1007 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1008 0 obj -<< -/Subtype /Link -/A 1007 0 R -/Type /Annot -/Rect [369 285.807 396 297.12] -/Border [0 0 0] ->> -endobj -1009 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1010 0 obj -<< -/Subtype /Link -/A 1009 0 R -/Type /Annot -/Rect [396 285.807 401.4 297.12] -/Border [0 0 0] ->> -endobj -1011 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1012 0 obj -<< -/Subtype /Link -/A 1011 0 R -/Type /Annot -/Rect [401.4 285.807 428.4 297.12] -/Border [0 0 0] ->> -endobj -1013 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1014 0 obj -<< -/Subtype /Link -/A 1013 0 R -/Type /Annot -/Rect [428.4 285.807 433.8 297.12] -/Border [0 0 0] ->> -endobj -1015 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1016 0 obj -<< -/Subtype /Link -/A 1015 0 R -/Type /Annot -/Rect [433.8 285.807 444.6 297.12] -/Border [0 0 0] ->> -endobj -1017 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1018 0 obj -<< -/Subtype /Link -/A 1017 0 R -/Type /Annot -/Rect [444.6 285.807 450 297.12] -/Border [0 0 0] ->> -endobj -1019 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1020 0 obj -<< -/Subtype /Link -/A 1019 0 R -/Type /Annot -/Rect [450 285.807 466.2 297.12] -/Border [0 0 0] ->> -endobj -1021 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1022 0 obj -<< -/Subtype /Link -/A 1021 0 R -/Type /Annot -/Rect [466.2 285.807 471.6 297.12] -/Border [0 0 0] ->> -endobj -1023 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1024 0 obj -<< -/Subtype /Link -/A 1023 0 R -/Type /Annot -/Rect [471.6 285.807 477 297.12] -/Border [0 0 0] ->> -endobj -1025 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1026 0 obj -<< -/Subtype /Link -/A 1025 0 R -/Type /Annot -/Rect [477 285.807 482.4 297.12] -/Border [0 0 0] ->> -endobj -1027 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1028 0 obj -<< -/Subtype /Link -/A 1027 0 R -/Type /Annot -/Rect [482.4 285.807 487.8 297.12] -/Border [0 0 0] ->> -endobj -1029 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1030 0 obj -<< -/Subtype /Link -/A 1029 0 R -/Type /Annot -/Rect [487.8 285.807 493.2 297.12] -/Border [0 0 0] ->> -endobj -1031 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1032 0 obj -<< -/Subtype /Link -/A 1031 0 R -/Type /Annot -/Rect [493.2 285.807 498.6 297.12] -/Border [0 0 0] ->> -endobj -1033 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1034 0 obj -<< -/Subtype /Link -/A 1033 0 R -/Type /Annot -/Rect [498.6 285.807 514.8 297.12] -/Border [0 0 0] ->> -endobj -1035 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1036 0 obj -<< -/Subtype /Link -/A 1035 0 R -/Type /Annot -/Rect [514.8 285.807 520.2 297.12] -/Border [0 0 0] ->> -endobj -1037 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1038 0 obj -<< -/Subtype /Link -/A 1037 0 R -/Type /Annot -/Rect [520.2 285.807 525.6 297.12] -/Border [0 0 0] ->> -endobj -1039 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1040 0 obj -<< -/Subtype /Link -/A 1039 0 R -/Type /Annot -/Rect [525.6 285.807 531 297.12] -/Border [0 0 0] ->> -endobj -1041 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1042 0 obj -<< -/Subtype /Link -/A 1041 0 R -/Type /Annot -/Rect [531 285.807 536.4 297.12] -/Border [0 0 0] ->> -endobj -1043 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1044 0 obj -<< -/Subtype /Link -/A 1043 0 R -/Type /Annot -/Rect [72 274.494 77.4 285.807] -/Border [0 0 0] ->> -endobj -1045 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1046 0 obj -<< -/Subtype /Link -/A 1045 0 R -/Type /Annot -/Rect [77.4 274.494 82.8 285.807] -/Border [0 0 0] ->> -endobj -1047 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1048 0 obj -<< -/Subtype /Link -/A 1047 0 R -/Type /Annot -/Rect [82.8 274.494 88.2 285.807] -/Border [0 0 0] ->> -endobj -1049 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1050 0 obj -<< -/Subtype /Link -/A 1049 0 R -/Type /Annot -/Rect [88.2 274.494 93.6 285.807] -/Border [0 0 0] ->> -endobj -1051 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1052 0 obj -<< -/Subtype /Link -/A 1051 0 R -/Type /Annot -/Rect [93.6 274.494 99 285.807] -/Border [0 0 0] ->> -endobj -1053 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1054 0 obj -<< -/Subtype /Link -/A 1053 0 R -/Type /Annot -/Rect [72 263.181 82.8 274.494] -/Border [0 0 0] ->> -endobj -1055 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1056 0 obj -<< -/Subtype /Link -/A 1055 0 R -/Type /Annot -/Rect [82.8 263.181 99 274.494] -/Border [0 0 0] ->> -endobj -1057 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1058 0 obj -<< -/Subtype /Link -/A 1057 0 R -/Type /Annot -/Rect [99 263.181 104.4 274.494] -/Border [0 0 0] ->> -endobj -1059 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1060 0 obj -<< -/Subtype /Link -/A 1059 0 R -/Type /Annot -/Rect [104.4 263.181 169.2 274.494] -/Border [0 0 0] ->> -endobj -1061 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1062 0 obj -<< -/Subtype /Link -/A 1061 0 R -/Type /Annot -/Rect [169.2 263.181 174.6 274.494] -/Border [0 0 0] ->> -endobj -1063 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1064 0 obj -<< -/Subtype /Link -/A 1063 0 R -/Type /Annot -/Rect [174.6 263.181 180 274.494] -/Border [0 0 0] ->> -endobj -1065 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1066 0 obj -<< -/Subtype /Link -/A 1065 0 R -/Type /Annot -/Rect [180 263.181 185.4 274.494] -/Border [0 0 0] ->> -endobj -1067 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1068 0 obj -<< -/Subtype /Link -/A 1067 0 R -/Type /Annot -/Rect [185.4 263.181 190.8 274.494] -/Border [0 0 0] ->> -endobj -1069 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1070 0 obj -<< -/Subtype /Link -/A 1069 0 R -/Type /Annot -/Rect [72 251.868 82.8 263.181] -/Border [0 0 0] ->> -endobj -1071 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1072 0 obj -<< -/Subtype /Link -/A 1071 0 R -/Type /Annot -/Rect [82.8 251.868 99 263.181] -/Border [0 0 0] ->> -endobj -1073 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1074 0 obj -<< -/Subtype /Link -/A 1073 0 R -/Type /Annot -/Rect [99 251.868 104.4 263.181] -/Border [0 0 0] ->> -endobj -1075 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1076 0 obj -<< -/Subtype /Link -/A 1075 0 R -/Type /Annot -/Rect [104.4 251.868 126 263.181] -/Border [0 0 0] ->> -endobj -1077 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1078 0 obj -<< -/Subtype /Link -/A 1077 0 R -/Type /Annot -/Rect [126 251.868 131.4 263.181] -/Border [0 0 0] ->> -endobj -1079 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1080 0 obj -<< -/Subtype /Link -/A 1079 0 R -/Type /Annot -/Rect [131.4 251.868 174.6 263.181] -/Border [0 0 0] ->> -endobj -1081 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1082 0 obj -<< -/Subtype /Link -/A 1081 0 R -/Type /Annot -/Rect [174.6 251.868 180 263.181] -/Border [0 0 0] ->> -endobj -1083 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1084 0 obj -<< -/Subtype /Link -/A 1083 0 R -/Type /Annot -/Rect [180 251.868 185.4 263.181] -/Border [0 0 0] ->> -endobj -1085 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1086 0 obj -<< -/Subtype /Link -/A 1085 0 R -/Type /Annot -/Rect [185.4 251.868 190.8 263.181] -/Border [0 0 0] ->> -endobj -1087 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1088 0 obj -<< -/Subtype /Link -/A 1087 0 R -/Type /Annot -/Rect [190.8 251.868 196.2 263.181] -/Border [0 0 0] ->> -endobj -1089 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1090 0 obj -<< -/Subtype /Link -/A 1089 0 R -/Type /Annot -/Rect [196.2 251.868 201.6 263.181] -/Border [0 0 0] ->> -endobj -1091 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1092 0 obj -<< -/Subtype /Link -/A 1091 0 R -/Type /Annot -/Rect [201.6 251.868 207 263.181] -/Border [0 0 0] ->> -endobj -1093 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1094 0 obj -<< -/Subtype /Link -/A 1093 0 R -/Type /Annot -/Rect [207 251.868 212.4 263.181] -/Border [0 0 0] ->> -endobj -1095 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1096 0 obj -<< -/Subtype /Link -/A 1095 0 R -/Type /Annot -/Rect [212.4 251.868 223.2 263.181] -/Border [0 0 0] ->> -endobj -1097 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1098 0 obj -<< -/Subtype /Link -/A 1097 0 R -/Type /Annot -/Rect [223.2 251.868 228.6 263.181] -/Border [0 0 0] ->> -endobj -1099 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1100 0 obj -<< -/Subtype /Link -/A 1099 0 R -/Type /Annot -/Rect [228.6 251.868 234 263.181] -/Border [0 0 0] ->> -endobj -1101 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1102 0 obj -<< -/Subtype /Link -/A 1101 0 R -/Type /Annot -/Rect [234 251.868 239.4 263.181] -/Border [0 0 0] ->> -endobj -1103 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1104 0 obj -<< -/Subtype /Link -/A 1103 0 R -/Type /Annot -/Rect [239.4 251.868 266.4 263.181] -/Border [0 0 0] ->> -endobj -1105 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1106 0 obj -<< -/Subtype /Link -/A 1105 0 R -/Type /Annot -/Rect [266.4 251.868 271.8 263.181] -/Border [0 0 0] ->> -endobj -1107 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1108 0 obj -<< -/Subtype /Link -/A 1107 0 R -/Type /Annot -/Rect [271.8 251.868 298.8 263.181] -/Border [0 0 0] ->> -endobj -1109 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1110 0 obj -<< -/Subtype /Link -/A 1109 0 R -/Type /Annot -/Rect [298.8 251.868 304.2 263.181] -/Border [0 0 0] ->> -endobj -1111 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1112 0 obj -<< -/Subtype /Link -/A 1111 0 R -/Type /Annot -/Rect [304.2 251.868 320.4 263.181] -/Border [0 0 0] ->> -endobj -1113 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1114 0 obj -<< -/Subtype /Link -/A 1113 0 R -/Type /Annot -/Rect [72 240.555 77.4 251.868] -/Border [0 0 0] ->> -endobj -1115 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1116 0 obj -<< -/Subtype /Link -/A 1115 0 R -/Type /Annot -/Rect [72 217.929 325.8 229.242] -/Border [0 0 0] ->> -endobj -1117 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1118 0 obj -<< -/Subtype /Link -/A 1117 0 R -/Type /Annot -/Rect [72 206.616 163.8 217.929] -/Border [0 0 0] ->> -endobj -1119 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1120 0 obj -<< -/Subtype /Link -/A 1119 0 R -/Type /Annot -/Rect [72 183.99 352.8 195.303] -/Border [0 0 0] ->> -endobj -1121 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1122 0 obj -<< -/Subtype /Link -/A 1121 0 R -/Type /Annot -/Rect [72 172.677 331.2 183.99] -/Border [0 0 0] ->> -endobj -1123 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1124 0 obj -<< -/Subtype /Link -/A 1123 0 R -/Type /Annot -/Rect [72 161.364 126 172.677] -/Border [0 0 0] ->> -endobj -775 0 obj -<< -/Type /Page -/Parent 1 0 R -/MediaBox [0 0 612 792] -/Contents 773 0 R -/Resources 774 0 R -/Annots [778 0 R 780 0 R 782 0 R 784 0 R 786 0 R 788 0 R 790 0 R 792 0 R 794 0 R 796 0 R 798 0 R 800 0 R 802 0 R 804 0 R 806 0 R 808 0 R 810 0 R 812 0 R 814 0 R 816 0 R 818 0 R 820 0 R 822 0 R 824 0 R 826 0 R 828 0 R 830 0 R 832 0 R 834 0 R 836 0 R 838 0 R 840 0 R 842 0 R 844 0 R 846 0 R 848 0 R 850 0 R 852 0 R 854 0 R 856 0 R 858 0 R 860 0 R 862 0 R 864 0 R 866 0 R 868 0 R 870 0 R 872 0 R 874 0 R 876 0 R 878 0 R 880 0 R 882 0 R 884 0 R 886 0 R 888 0 R 890 0 R 892 0 R 894 0 R 896 0 R 898 0 R 900 0 R 902 0 R 904 0 R 906 0 R 908 0 R 910 0 R 912 0 R 914 0 R 916 0 R 918 0 R 920 0 R 922 0 R 924 0 R 926 0 R 928 0 R 930 0 R 932 0 R 934 0 R 936 0 R 938 0 R 940 0 R 942 0 R 944 0 R 946 0 R 948 0 R 950 0 R 952 0 R 954 0 R 956 0 R 958 0 R 960 0 R 962 0 R 964 0 R 966 0 R 968 0 R 970 0 R 972 0 R 974 0 R 976 0 R 978 0 R 980 0 R 982 0 R 984 0 R 986 0 R 988 0 R 990 0 R 992 0 R 994 0 R 996 0 R 998 0 R 1000 0 R 1002 0 R 1004 0 R 1006 0 R 1008 0 R 1010 0 R 1012 0 R 1014 0 R 1016 0 R 1018 0 R 1020 0 R 1022 0 R 1024 0 R 1026 0 R 1028 0 R 1030 0 R 1032 0 R 1034 0 R 1036 0 R 1038 0 R 1040 0 R 1042 0 R 1044 0 R 1046 0 R 1048 0 R 1050 0 R 1052 0 R 1054 0 R 1056 0 R 1058 0 R 1060 0 R 1062 0 R 1064 0 R 1066 0 R 1068 0 R 1070 0 R 1072 0 R 1074 0 R 1076 0 R 1078 0 R 1080 0 R 1082 0 R 1084 0 R 1086 0 R 1088 0 R 1090 0 R 1092 0 R 1094 0 R 1096 0 R 1098 0 R 1100 0 R 1102 0 R 1104 0 R 1106 0 R 1108 0 R 1110 0 R 1112 0 R 1114 0 R 1116 0 R 1118 0 R 1120 0 R 1122 0 R 1124 0 R] ->> -endobj -774 0 obj -<< -/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] -/Font << -/F4 16 0 R -/F3 9 0 R -/F6 44 0 R -/F5 29 0 R ->> ->> -endobj -773 0 obj -<< -/Length 2976 -/Filter /FlateDecode ->> -stream -x]ˎWŗ\"  " CR,$h[ԙglqY;qz?z:&7jtPp/'}!z:/%tKlW8~83ݿg錄T͐~?Xg; n -Ry7pIt J -C9"Hȣ<0'xxe<ۛ_6t,0t+3mr/`xДU-j*i ڔ%.b. H֓u^HhAue/J%)=~A/@;3'I` &ւv"FI2{6g4fdٷPR3D:>F)SGIhY&HOZm/DCZ}Xs|Q0[|[k˚/58s)GdԢ?93NKzC =/SثROW<:I*kX2ۼM` -G>@)SkB+K :f|Y-J&)f %(imOnKbv=RZĚ.b;I#ȄJ@|j -k@g -)Y3;rȳ&fYJ.1M }$ ג%&@$QM骥s &2J 6ABMveçmI`ir[*w*o tϥs2*1bI_2 Z*hYJ擤~LכA9*kSs%δւk"g,EP^Y3L`m'Ya_I0aO<&,ak:#`<1؄2>B|X? -ug$= -?rVrBTUMr!.X&T(F(FLP:"E-¤9yN\e`<yM. H3yMlSګWS M%1ʧ 2e7 ,nTVyd2`ˁ. A,\7졐)F@I\:ķ4FJ5Pmz0?W2 x E\U'ϊ7m 5ϮD>ɲ : -q)q7Y90z zv=eB`f -]J1Jц823 ,y;4;[^UtoJ ]&(s­c/4-G@fRNr0nf-lBɚvVBpfr2ꈾepEL%?U'pxYDڲ! )zmwR'# K(HBA f%p!,j3L_Iʥj6b!r")5 ڡ0!p8Ae)w[yu$gqTΊ<"ZLքg|e="E(z7gS`jr6d-\ejYLDZe+˗f;pD;l0nDCV+UaǺnJĭ'-W)[V5Vv2ʠgܻԵL@>lFGfD#w, lhguq 4y!Fy!Ʒej]F/8hW~6~s'#|,>蒞1g)j\Šrq+vөaNǷa6;`6.ƀٛ8\ -νuEX%P,_W},y<-_:?p)\R@c.4؎g1.{>qo3^!+Vnq\_:7 -p mp@A_ f{8XPMO4W\ZnsiJY|:Q>ǫĉUaxq4P[h {_,Nwͩ&?1봂|w -7d=}~wAc7ժ Wx$}dY5p%{)j,#p.܃Zj+lx]@Z0Z ?%nӵ4 ߙN j20q21C7T.'UBQ/{>WBa/\ϡ -endstream -endobj -1129 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1130 0 obj -<< -/Subtype /Link -/A 1129 0 R -/Type /Annot -/Rect [72 695.502 279.954 720] -/Border [0 0 0] ->> -endobj -1131 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1132 0 obj -<< -/Subtype /Link -/A 1131 0 R -/Type /Annot -/Rect [72 673.002 534.363281 685.502] -/Border [0 0 0] ->> -endobj -1133 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1134 0 obj -<< -/Subtype /Link -/A 1133 0 R -/Type /Annot -/Rect [72 660.502 402.058594 673.002] -/Border [0 0 0] ->> -endobj -1135 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1136 0 obj -<< -/Subtype /Link -/A 1135 0 R -/Type /Annot -/Rect [402.058594 660.432 450.058594 673.002] -/Border [0 0 0] ->> -endobj -1137 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1138 0 obj -<< -/Subtype /Link -/A 1137 0 R -/Type /Annot -/Rect [450.058594 660.502 516.181641 673.002] -/Border [0 0 0] ->> -endobj -1139 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1140 0 obj -<< -/Subtype /Link -/A 1139 0 R -/Type /Annot -/Rect [72 648.002 361.233398 660.502] -/Border [0 0 0] ->> -endobj -1141 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1142 0 obj -<< -/Subtype /Link -/A 1141 0 R -/Type /Annot -/Rect [72 625.502 533.992188 638.002] -/Border [0 0 0] ->> -endobj -1143 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1144 0 obj -<< -/Subtype /Link -/A 1143 0 R -/Type /Annot -/Rect [72 613.002 375.681641 625.502] -/Border [0 0 0] ->> -endobj -1145 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1146 0 obj -<< -/Subtype /Link -/A 1145 0 R -/Type /Annot -/Rect [72 590.432 102 603.002] -/Border [0 0 0] ->> -endobj -1147 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1148 0 obj -<< -/Subtype /Link -/A 1147 0 R -/Type /Annot -/Rect [102 590.502 237.883789 603.002] -/Border [0 0 0] ->> -endobj -1149 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1150 0 obj -<< -/Subtype /Link -/A 1149 0 R -/Type /Annot -/Rect [72 571.932 108 584.502] -/Border [0 0 0] ->> -endobj -1151 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1152 0 obj -<< -/Subtype /Link -/A 1151 0 R -/Type /Annot -/Rect [108 572.002 234.376953 584.502] -/Border [0 0 0] ->> -endobj -1153 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1154 0 obj -<< -/Subtype /Link -/A 1153 0 R -/Type /Annot -/Rect [72 553.432 114 566.002] -/Border [0 0 0] ->> -endobj -1155 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1156 0 obj -<< -/Subtype /Link -/A 1155 0 R -/Type /Annot -/Rect [114 553.502 264.805664 566.002] -/Border [0 0 0] ->> -endobj -1157 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1158 0 obj -<< -/Subtype /Link -/A 1157 0 R -/Type /Annot -/Rect [72 534.932 120 547.502] -/Border [0 0 0] ->> -endobj -1159 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1160 0 obj -<< -/Subtype /Link -/A 1159 0 R -/Type /Annot -/Rect [120 535.002 330.419922 547.502] -/Border [0 0 0] ->> -endobj -1161 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1162 0 obj -<< -/Subtype /Link -/A 1161 0 R -/Type /Annot -/Rect [72 516.432 144 529.002] -/Border [0 0 0] ->> -endobj -1163 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1164 0 obj -<< -/Subtype /Link -/A 1163 0 R -/Type /Annot -/Rect [144 516.502 491.753906 529.002] -/Border [0 0 0] ->> -endobj -1165 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1166 0 obj -<< -/Subtype /Link -/A 1165 0 R -/Type /Annot -/Rect [72 497.932 114 510.502] -/Border [0 0 0] ->> -endobj -1167 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1168 0 obj -<< -/Subtype /Link -/A 1167 0 R -/Type /Annot -/Rect [114 498.002 327.881836 510.502] -/Border [0 0 0] ->> -endobj -1127 0 obj -<< -/Type /Page -/Parent 1 0 R -/MediaBox [0 0 612 792] -/Contents 1125 0 R -/Resources 1126 0 R -/Annots [1130 0 R 1132 0 R 1134 0 R 1136 0 R 1138 0 R 1140 0 R 1142 0 R 1144 0 R 1146 0 R 1148 0 R 1150 0 R 1152 0 R 1154 0 R 1156 0 R 1158 0 R 1160 0 R 1162 0 R 1164 0 R 1166 0 R 1168 0 R] ->> -endobj -1126 0 obj -<< -/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] -/Font << -/F4 16 0 R -/F3 9 0 R -/F6 44 0 R ->> ->> -endobj -1125 0 obj -<< -/Length 817 -/Filter /FlateDecode ->> -stream -xWɎ0 +uIYmà [܊/@-P f2rtXP{_k5޾TA|4~WlQZuZFast~h?~^iX >}Awu\}8T_^k]M4 -=яɏ9yd=zO?bCoFKa0vmQ^qGEohL!:PO߬FFYOwAޑލd\'uҧ;Zgg;xβaN,G>#; vE7CyL^D#Z#a;BL^F}G&E`I L>qB_K$]lo"(ݝD[jځ)"VXVcN, 6GbIXb}/,n e˨I\2rvw0my#ymU$EO~,֪Uo̙wȱ>G<,ej1ќ~)"nrٓbe5,AQf9YC0 ~>FW6Сu5e>,.'3ӱ -endstream -endobj -1173 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1174 0 obj -<< -/Subtype /Link -/A 1173 0 R -/Type /Annot -/Rect [72 695.502 319.086 720] -/Border [0 0 0] ->> -endobj -1175 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1176 0 obj -<< -/Subtype /Link -/A 1175 0 R -/Type /Annot -/Rect [72 673.002 535.925781 685.502] -/Border [0 0 0] ->> -endobj -1177 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1178 0 obj -<< -/Subtype /Link -/A 1177 0 R -/Type /Annot -/Rect [72 660.502 505.691406 673.002] -/Border [0 0 0] ->> -endobj -1179 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1180 0 obj -<< -/Subtype /Link -/A 1179 0 R -/Type /Annot -/Rect [72 648.002 514.001953 660.502] -/Border [0 0 0] ->> -endobj -1181 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1182 0 obj -<< -/Subtype /Link -/A 1181 0 R -/Type /Annot -/Rect [72 635.502 458.625977 648.002] -/Border [0 0 0] ->> -endobj -1183 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1184 0 obj -<< -/Subtype /Link -/A 1183 0 R -/Type /Annot -/Rect [72 613.002 397.751953 625.502] -/Border [0 0 0] ->> -endobj -1185 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1186 0 obj -<< -/Subtype /Link -/A 1185 0 R -/Type /Annot -/Rect [397.751953 612.932 463.751953 625.502] -/Border [0 0 0] ->> -endobj -1187 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1188 0 obj -<< -/Subtype /Link -/A 1187 0 R -/Type /Annot -/Rect [463.751953 613.002 479.010742 625.502] -/Border [0 0 0] ->> -endobj -1189 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1190 0 obj -<< -/Subtype /Link -/A 1189 0 R -/Type /Annot -/Rect [479.010742 612.932 521.010742 625.502] -/Border [0 0 0] ->> -endobj -1191 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1192 0 obj -<< -/Subtype /Link -/A 1191 0 R -/Type /Annot -/Rect [72 600.502 520.383789 613.002] -/Border [0 0 0] ->> -endobj -1193 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1194 0 obj -<< -/Subtype /Link -/A 1193 0 R -/Type /Annot -/Rect [72 588.002 410.901367 600.502] -/Border [0 0 0] ->> -endobj -1195 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1196 0 obj -<< -/Subtype /Link -/A 1195 0 R -/Type /Annot -/Rect [72 565.432 144 578.002] -/Border [0 0 0] ->> -endobj -1197 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1198 0 obj -<< -/Subtype /Link -/A 1197 0 R -/Type /Annot -/Rect [144 565.502 315.323242 578.002] -/Border [0 0 0] ->> -endobj -1199 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1200 0 obj -<< -/Subtype /Link -/A 1199 0 R -/Type /Annot -/Rect [72 537.002 491.057617 549.502] -/Border [0 0 0] ->> -endobj -1201 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1202 0 obj -<< -/Subtype /Link -/A 1201 0 R -/Type /Annot -/Rect [72 524.502 205.691406 537.002] -/Border [0 0 0] ->> -endobj -1203 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1204 0 obj -<< -/Subtype /Link -/A 1203 0 R -/Type /Annot -/Rect [205.691406 524.432 241.691406 537.002] -/Border [0 0 0] ->> -endobj -1205 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1206 0 obj -<< -/Subtype /Link -/A 1205 0 R -/Type /Annot -/Rect [241.691406 524.502 350.714844 537.002] -/Border [0 0 0] ->> -endobj -1207 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1208 0 obj -<< -/Subtype /Link -/A 1207 0 R -/Type /Annot -/Rect [350.714844 524.432 416.714844 537.002] -/Border [0 0 0] ->> -endobj -1209 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1210 0 obj -<< -/Subtype /Link -/A 1209 0 R -/Type /Annot -/Rect [416.714844 524.502 494.063477 537.002] -/Border [0 0 0] ->> -endobj -1211 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1212 0 obj -<< -/Subtype /Link -/A 1211 0 R -/Type /Annot -/Rect [72 512.002 439.324219 524.502] -/Border [0 0 0] ->> -endobj -1213 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1214 0 obj -<< -/Subtype /Link -/A 1213 0 R -/Type /Annot -/Rect [72 489.432 150 502.002] -/Border [0 0 0] ->> -endobj -1215 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1216 0 obj -<< -/Subtype /Link -/A 1215 0 R -/Type /Annot -/Rect [150 489.502 330.986328 502.002] -/Border [0 0 0] ->> -endobj -1217 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1218 0 obj -<< -/Subtype /Link -/A 1217 0 R -/Type /Annot -/Rect [72 470.932 138 483.502] -/Border [0 0 0] ->> -endobj -1219 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1220 0 obj -<< -/Subtype /Link -/A 1219 0 R -/Type /Annot -/Rect [138 471.002 358.27832 483.502] -/Border [0 0 0] ->> -endobj -1221 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1222 0 obj -<< -/Subtype /Link -/A 1221 0 R -/Type /Annot -/Rect [72 442.502 238.513672 455.002] -/Border [0 0 0] ->> -endobj -1223 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1224 0 obj -<< -/Subtype /Link -/A 1223 0 R -/Type /Annot -/Rect [238.513672 442.432 304.513672 455.002] -/Border [0 0 0] ->> -endobj -1225 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1226 0 obj -<< -/Subtype /Link -/A 1225 0 R -/Type /Annot -/Rect [304.513672 442.502 340.773438 455.002] -/Border [0 0 0] ->> -endobj -1227 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1228 0 obj -<< -/Subtype /Link -/A 1227 0 R -/Type /Annot -/Rect [72 419.932 120 432.502] -/Border [0 0 0] ->> -endobj -1229 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1230 0 obj -<< -/Subtype /Link -/A 1229 0 R -/Type /Annot -/Rect [120 420.002 313.725586 432.502] -/Border [0 0 0] ->> -endobj -1231 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1232 0 obj -<< -/Subtype /Link -/A 1231 0 R -/Type /Annot -/Rect [313.725586 419.932 403.725586 432.502] -/Border [0 0 0] ->> -endobj -1233 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1234 0 obj -<< -/Subtype /Link -/A 1233 0 R -/Type /Annot -/Rect [403.725586 420.002 496.582031 432.502] -/Border [0 0 0] ->> -endobj -1235 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1236 0 obj -<< -/Subtype /Link -/A 1235 0 R -/Type /Annot -/Rect [72 407.502 132.327148 420.002] -/Border [0 0 0] ->> -endobj -1237 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1238 0 obj -<< -/Subtype /Link -/A 1237 0 R -/Type /Annot -/Rect [132.327148 407.432 228.327148 420.002] -/Border [0 0 0] ->> -endobj -1239 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1240 0 obj -<< -/Subtype /Link -/A 1239 0 R -/Type /Annot -/Rect [228.327148 407.502 418.800781 420.002] -/Border [0 0 0] ->> -endobj -1241 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1242 0 obj -<< -/Subtype /Link -/A 1241 0 R -/Type /Annot -/Rect [72 388.932 126 401.502] -/Border [0 0 0] ->> -endobj -1243 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1244 0 obj -<< -/Subtype /Link -/A 1243 0 R -/Type /Annot -/Rect [126 389.002 367.928711 401.502] -/Border [0 0 0] ->> -endobj -1245 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1246 0 obj -<< -/Subtype /Link -/A 1245 0 R -/Type /Annot -/Rect [367.928711 388.932 391.928711 401.502] -/Border [0 0 0] ->> -endobj -1247 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1248 0 obj -<< -/Subtype /Link -/A 1247 0 R -/Type /Annot -/Rect [391.928711 389.002 490.419922 401.502] -/Border [0 0 0] ->> -endobj -1249 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1250 0 obj -<< -/Subtype /Link -/A 1249 0 R -/Type /Annot -/Rect [72 376.502 163.650391 389.002] -/Border [0 0 0] ->> -endobj -1251 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1252 0 obj -<< -/Subtype /Link -/A 1251 0 R -/Type /Annot -/Rect [72 357.932 114 370.502] -/Border [0 0 0] ->> -endobj -1253 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1254 0 obj -<< -/Subtype /Link -/A 1253 0 R -/Type /Annot -/Rect [114 358.002 386.324219 370.502] -/Border [0 0 0] ->> -endobj -1255 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1256 0 obj -<< -/Subtype /Link -/A 1255 0 R -/Type /Annot -/Rect [386.324219 357.932 410.324219 370.502] -/Border [0 0 0] ->> -endobj -1257 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1258 0 obj -<< -/Subtype /Link -/A 1257 0 R -/Type /Annot -/Rect [410.324219 358.002 494.103516 370.502] -/Border [0 0 0] ->> -endobj -1259 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1260 0 obj -<< -/Subtype /Link -/A 1259 0 R -/Type /Annot -/Rect [72 339.432 132 352.002] -/Border [0 0 0] ->> -endobj -1261 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1262 0 obj -<< -/Subtype /Link -/A 1261 0 R -/Type /Annot -/Rect [132 339.502 403.064453 352.002] -/Border [0 0 0] ->> -endobj -1263 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1264 0 obj -<< -/Subtype /Link -/A 1263 0 R -/Type /Annot -/Rect [403.064453 339.432 427.064453 352.002] -/Border [0 0 0] ->> -endobj -1265 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1266 0 obj -<< -/Subtype /Link -/A 1265 0 R -/Type /Annot -/Rect [427.064453 339.502 529.447266 352.002] -/Border [0 0 0] ->> -endobj -1267 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1268 0 obj -<< -/Subtype /Link -/A 1267 0 R -/Type /Annot -/Rect [72 327.002 150.686523 339.502] -/Border [0 0 0] ->> -endobj -1269 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1270 0 obj -<< -/Subtype /Link -/A 1269 0 R -/Type /Annot -/Rect [72 308.432 144 321.002] -/Border [0 0 0] ->> -endobj -1271 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1272 0 obj -<< -/Subtype /Link -/A 1271 0 R -/Type /Annot -/Rect [144 308.502 414.776367 321.002] -/Border [0 0 0] ->> -endobj -1273 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1274 0 obj -<< -/Subtype /Link -/A 1273 0 R -/Type /Annot -/Rect [414.776367 308.432 438.776367 321.002] -/Border [0 0 0] ->> -endobj -1275 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1276 0 obj -<< -/Subtype /Link -/A 1275 0 R -/Type /Annot -/Rect [438.776367 308.502 528.859375 321.002] -/Border [0 0 0] ->> -endobj -1277 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1278 0 obj -<< -/Subtype /Link -/A 1277 0 R -/Type /Annot -/Rect [72 296.002 187.878906 308.502] -/Border [0 0 0] ->> -endobj -1279 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1280 0 obj -<< -/Subtype /Link -/A 1279 0 R -/Type /Annot -/Rect [72 277.432 192 290.002] -/Border [0 0 0] ->> -endobj -1281 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1282 0 obj -<< -/Subtype /Link -/A 1281 0 R -/Type /Annot -/Rect [192 277.502 486.594727 290.002] -/Border [0 0 0] ->> -endobj -1283 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1284 0 obj -<< -/Subtype /Link -/A 1283 0 R -/Type /Annot -/Rect [486.594727 277.432 510.594727 290.002] -/Border [0 0 0] ->> -endobj -1285 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1286 0 obj -<< -/Subtype /Link -/A 1285 0 R -/Type /Annot -/Rect [510.594727 277.502 525.921875 290.002] -/Border [0 0 0] ->> -endobj -1287 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1288 0 obj -<< -/Subtype /Link -/A 1287 0 R -/Type /Annot -/Rect [72 265.002 221.194336 277.502] -/Border [0 0 0] ->> -endobj -1289 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1290 0 obj -<< -/Subtype /Link -/A 1289 0 R -/Type /Annot -/Rect [72 246.432 168 259.002] -/Border [0 0 0] ->> -endobj -1291 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1292 0 obj -<< -/Subtype /Link -/A 1291 0 R -/Type /Annot -/Rect [168 246.502 430.392578 259.002] -/Border [0 0 0] ->> -endobj -1293 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1294 0 obj -<< -/Subtype /Link -/A 1293 0 R -/Type /Annot -/Rect [430.392578 246.432 454.392578 259.002] -/Border [0 0 0] ->> -endobj -1295 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1296 0 obj -<< -/Subtype /Link -/A 1295 0 R -/Type /Annot -/Rect [454.392578 246.502 498.953125 259.002] -/Border [0 0 0] ->> -endobj -1297 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1298 0 obj -<< -/Subtype /Link -/A 1297 0 R -/Type /Annot -/Rect [72 234.002 171.614258 246.502] -/Border [0 0 0] ->> -endobj -1299 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1300 0 obj -<< -/Subtype /Link -/A 1299 0 R -/Type /Annot -/Rect [72 205.502 524.62207 218.002] -/Border [0 0 0] ->> -endobj -1301 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1302 0 obj -<< -/Subtype /Link -/A 1301 0 R -/Type /Annot -/Rect [72 193.002 257.756836 205.502] -/Border [0 0 0] ->> -endobj -1303 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1304 0 obj -<< -/Subtype /Link -/A 1303 0 R -/Type /Annot -/Rect [72 170.502 524.441406 183.002] -/Border [0 0 0] ->> -endobj -1305 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1306 0 obj -<< -/Subtype /Link -/A 1305 0 R -/Type /Annot -/Rect [72 158.002 259.133789 170.502] -/Border [0 0 0] ->> -endobj -1307 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1308 0 obj -<< -/Subtype /Link -/A 1307 0 R -/Type /Annot -/Rect [72 139.502 517.507813 152.002] -/Border [0 0 0] ->> -endobj -1309 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1310 0 obj -<< -/Subtype /Link -/A 1309 0 R -/Type /Annot -/Rect [72 127.002 508.787109 139.502] -/Border [0 0 0] ->> -endobj -1311 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1312 0 obj -<< -/Subtype /Link -/A 1311 0 R -/Type /Annot -/Rect [72 114.502 433.542969 127.002] -/Border [0 0 0] ->> -endobj -1313 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1314 0 obj -<< -/Subtype /Link -/A 1313 0 R -/Type /Annot -/Rect [72 96.002 533.357422 108.502] -/Border [0 0 0] ->> -endobj -1315 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1316 0 obj -<< -/Subtype /Link -/A 1315 0 R -/Type /Annot -/Rect [72 83.502 505.15918 96.002] -/Border [0 0 0] ->> -endobj -1171 0 obj -<< -/Type /Page -/Parent 1 0 R -/MediaBox [0 0 612 792] -/Contents 1169 0 R -/Resources 1170 0 R -/Annots [1174 0 R 1176 0 R 1178 0 R 1180 0 R 1182 0 R 1184 0 R 1186 0 R 1188 0 R 1190 0 R 1192 0 R 1194 0 R 1196 0 R 1198 0 R 1200 0 R 1202 0 R 1204 0 R 1206 0 R 1208 0 R 1210 0 R 1212 0 R 1214 0 R 1216 0 R 1218 0 R 1220 0 R 1222 0 R 1224 0 R 1226 0 R 1228 0 R 1230 0 R 1232 0 R 1234 0 R 1236 0 R 1238 0 R 1240 0 R 1242 0 R 1244 0 R 1246 0 R 1248 0 R 1250 0 R 1252 0 R 1254 0 R 1256 0 R 1258 0 R 1260 0 R 1262 0 R 1264 0 R 1266 0 R 1268 0 R 1270 0 R 1272 0 R 1274 0 R 1276 0 R 1278 0 R 1280 0 R 1282 0 R 1284 0 R 1286 0 R 1288 0 R 1290 0 R 1292 0 R 1294 0 R 1296 0 R 1298 0 R 1300 0 R 1302 0 R 1304 0 R 1306 0 R 1308 0 R 1310 0 R 1312 0 R 1314 0 R 1316 0 R] ->> -endobj -1170 0 obj -<< -/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] -/Font << -/F4 16 0 R -/F3 9 0 R -/F6 44 0 R ->> ->> -endobj -1169 0 obj -<< -/Length 2082 -/Filter /FlateDecode ->> -stream -x[Ɏ6+QS> %[ CCRUTeR4 zlk}s?;oqӧ/>ս^",{u:>to1/g{Ǵd1^'ݟr=ߏm/sY _6ָEzϧ^Og]at&{|/p߰ -4ï." |y--rY_G2,Y`5#{iDr1hYFFԳ *"hFc^ 4:j kj@SG,6joKBmy q~У:D9KQj@RF-'Z+ uҤ+Hw]O(ШTSab:bIrrV\Ḕ/R4ZZӸ]9@Z"^&;Sj{c24~a~ ir.rekBՎ3UbG^ndzLǜZ\M}s.Vk`7A5$Fb 5CSڸޮܕCOG8Fl6P_=nTimzDMd^24]G(A nR,\f>D׸P RbU8i/Ybc;˹rCGǤmLe{{ڈBcfQ9@Aq&kքE Cf.\Z`GZ`.SLh u)d|kRi[{bUpm}B#9io1e=puM}LhqEviir) ][C0/(XB yt8LY!=hoR[%u5<ʣ/kXNܕ~Ń ?\oŹv(a*2ҙ^a<-K2zvcW[ȡ\v;+J(GUyh]J5pqPp\;49"~Iaz0y#g8BYL5)pN"W`Ս-+lX6Mn moMaۢB |)hv0p3_ArB( <9LY' $[Z=X nQ2|~|`B0MIE;6*H}*Þc&Fؙr-~ -Ze,ÿrs{5yA [q" 8Bm0.+(6O@튠[+VBr}7ˉcGNgMP3q.:7̸fK\XJn9Ef^VU -zgg($pcqpmյ-9<~,r[k\ec\ScN.1ÿ)8yV*bTt~  dJth 2NKr(Zry$#?c0ϔlo*J]bjms=9mwG]k3;K,|+}7wprSEVwxnlROENNYddIuhQ v[M=Vd0:ҳCprsDeZKûDRԒgp eV$;\SmDwMcA%nirjGn0uoi, cbb -endstream -endobj -1320 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1321 0 obj -<< -/Subtype /Link -/A 1320 0 R -/Type /Annot -/Rect [72 707.5 287.795898 720] -/Border [0 0 0] ->> -endobj -1322 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1323 0 obj -<< -/Subtype /Link -/A 1322 0 R -/Type /Annot -/Rect [72 679 534.207031 691.5] -/Border [0 0 0] ->> -endobj -1324 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1325 0 obj -<< -/Subtype /Link -/A 1324 0 R -/Type /Annot -/Rect [72 666.5 533.723633 679] -/Border [0 0 0] ->> -endobj -1326 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1327 0 obj -<< -/Subtype /Link -/A 1326 0 R -/Type /Annot -/Rect [72 654 174.670898 666.5] -/Border [0 0 0] ->> -endobj -1328 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1329 0 obj -<< -/Subtype /Link -/A 1328 0 R -/Type /Annot -/Rect [72 631.5 508.21582 644] -/Border [0 0 0] ->> -endobj -1330 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1331 0 obj -<< -/Subtype /Link -/A 1330 0 R -/Type /Annot -/Rect [72 619 380.564453 631.5] -/Border [0 0 0] ->> -endobj -1332 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1333 0 obj -<< -/Subtype /Link -/A 1332 0 R -/Type /Annot -/Rect [72 596.43 132 609] -/Border [0 0 0] ->> -endobj -1334 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1335 0 obj -<< -/Subtype /Link -/A 1334 0 R -/Type /Annot -/Rect [132 596.5 345.725586 609] -/Border [0 0 0] ->> -endobj -1336 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1337 0 obj -<< -/Subtype /Link -/A 1336 0 R -/Type /Annot -/Rect [72 568 206.580078 580.5] -/Border [0 0 0] ->> -endobj -1338 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1339 0 obj -<< -/Subtype /Link -/A 1338 0 R -/Type /Annot -/Rect [72 545.43 90 558] -/Border [0 0 0] ->> -endobj -1340 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1341 0 obj -<< -/Subtype /Link -/A 1340 0 R -/Type /Annot -/Rect [90 545.5 320.263672 558] -/Border [0 0 0] ->> -endobj -1342 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1343 0 obj -<< -/Subtype /Link -/A 1342 0 R -/Type /Annot -/Rect [72 526.93 90 539.5] -/Border [0 0 0] ->> -endobj -1344 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1345 0 obj -<< -/Subtype /Link -/A 1344 0 R -/Type /Annot -/Rect [90 527 279.233398 539.5] -/Border [0 0 0] ->> -endobj -1346 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1347 0 obj -<< -/Subtype /Link -/A 1346 0 R -/Type /Annot -/Rect [72 508.43 90 521] -/Border [0 0 0] ->> -endobj -1348 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1349 0 obj -<< -/Subtype /Link -/A 1348 0 R -/Type /Annot -/Rect [90 508.5 278.383789 521] -/Border [0 0 0] ->> -endobj -1350 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1351 0 obj -<< -/Subtype /Link -/A 1350 0 R -/Type /Annot -/Rect [72 489.93 90 502.5] -/Border [0 0 0] ->> -endobj -1352 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1353 0 obj -<< -/Subtype /Link -/A 1352 0 R -/Type /Annot -/Rect [90 490 279.023438 502.5] -/Border [0 0 0] ->> -endobj -1354 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1355 0 obj -<< -/Subtype /Link -/A 1354 0 R -/Type /Annot -/Rect [72 471.43 90 484] -/Border [0 0 0] ->> -endobj -1356 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1357 0 obj -<< -/Subtype /Link -/A 1356 0 R -/Type /Annot -/Rect [90 471.5 278.950195 484] -/Border [0 0 0] ->> -endobj -1358 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1359 0 obj -<< -/Subtype /Link -/A 1358 0 R -/Type /Annot -/Rect [72 452.93 114 465.5] -/Border [0 0 0] ->> -endobj -1360 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1361 0 obj -<< -/Subtype /Link -/A 1360 0 R -/Type /Annot -/Rect [114 453 390.567383 465.5] -/Border [0 0 0] ->> -endobj -1362 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1363 0 obj -<< -/Subtype /Link -/A 1362 0 R -/Type /Annot -/Rect [72 424.5 538.835938 437] -/Border [0 0 0] ->> -endobj -1364 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1365 0 obj -<< -/Subtype /Link -/A 1364 0 R -/Type /Annot -/Rect [72 412 497.712891 424.5] -/Border [0 0 0] ->> -endobj -1366 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1367 0 obj -<< -/Subtype /Link -/A 1366 0 R -/Type /Annot -/Rect [72 399.5 186.882813 412] -/Border [0 0 0] ->> -endobj -1368 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1369 0 obj -<< -/Subtype /Link -/A 1368 0 R -/Type /Annot -/Rect [72 365.002 187.866 389.5] -/Border [0 0 0] ->> -endobj -1370 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1371 0 obj -<< -/Subtype /Link -/A 1370 0 R -/Type /Annot -/Rect [72 342.502 183.020508 355.002] -/Border [0 0 0] ->> -endobj -1372 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1373 0 obj -<< -/Subtype /Link -/A 1372 0 R -/Type /Annot -/Rect [183.020508 342.432 249.020508 355.002] -/Border [0 0 0] ->> -endobj -1374 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1375 0 obj -<< -/Subtype /Link -/A 1374 0 R -/Type /Annot -/Rect [249.020508 342.502 523.981445 355.002] -/Border [0 0 0] ->> -endobj -1376 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1377 0 obj -<< -/Subtype /Link -/A 1376 0 R -/Type /Annot -/Rect [72 330.002 538.625977 342.502] -/Border [0 0 0] ->> -endobj -1378 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1379 0 obj -<< -/Subtype /Link -/A 1378 0 R -/Type /Annot -/Rect [72 317.502 93.430664 330.002] -/Border [0 0 0] ->> -endobj -1380 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1381 0 obj -<< -/Subtype /Link -/A 1380 0 R -/Type /Annot -/Rect [72 295.002 486.423828 307.502] -/Border [0 0 0] ->> -endobj -1319 0 obj -<< -/Type /Page -/Parent 1 0 R -/MediaBox [0 0 612 792] -/Contents 1317 0 R -/Resources 1318 0 R -/Annots [1321 0 R 1323 0 R 1325 0 R 1327 0 R 1329 0 R 1331 0 R 1333 0 R 1335 0 R 1337 0 R 1339 0 R 1341 0 R 1343 0 R 1345 0 R 1347 0 R 1349 0 R 1351 0 R 1353 0 R 1355 0 R 1357 0 R 1359 0 R 1361 0 R 1363 0 R 1365 0 R 1367 0 R 1369 0 R 1371 0 R 1373 0 R 1375 0 R 1377 0 R 1379 0 R 1381 0 R] ->> -endobj -1318 0 obj -<< -/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] -/Font << -/F3 9 0 R -/F6 44 0 R -/F4 16 0 R ->> ->> -endobj -1317 0 obj -<< -/Length 1242 -/Filter /FlateDecode ->> -stream -xYɎ6 WR2a-A݂9dH2).S]QwOmY"{$ -}ῶæ?|j'? =ŦuvhKg݀j.TJ2¥- Kxvՠ!t -jϝԎHm~ ]K]_gsy^N -D0ĦcJN(1^ĭ9Vq}d=V'M :S$ #u²W;M7[Oh(ag,c`yHQ"K/Ŏ#m _};Kl[#@܌WTydvVeB{e/LwXF6HT@ddݪ;-NSNj7WFBwjFՋ6+NY-[5-7 lyF׆wŹް龖m&4ޣj .D!M% K8vz'a:9J(s^d] tҢ"Vj|C2rwWP~.Oİq\BV1 -x/EV]*̹-mG"9=4mglg~YM+Ѷc/k%7gR7rIfNMx l͜mM\u[JP4K˳(*v|tE@^7%6l ^ -endstream -endobj -1386 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1387 0 obj -<< -/Subtype /Link -/A 1386 0 R -/Type /Annot -/Rect [72 685.975 346.525 720] -/Border [0 0 0] ->> -endobj -1389 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1390 0 obj -<< -/Subtype /Link -/A 1389 0 R -/Type /Annot -/Rect [72 646.477 328.356 670.975] -/Border [0 0 0] ->> -endobj -1391 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1392 0 obj -<< -/Subtype /Link -/A 1391 0 R -/Type /Annot -/Rect [72 623.977 520.78418 636.477] -/Border [0 0 0] ->> -endobj -1393 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1394 0 obj -<< -/Subtype /Link -/A 1393 0 R -/Type /Annot -/Rect [72 611.477 525.569336 623.977] -/Border [0 0 0] ->> -endobj -1395 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1396 0 obj -<< -/Subtype /Link -/A 1395 0 R -/Type /Annot -/Rect [72 598.977 538.5625 611.477] -/Border [0 0 0] ->> -endobj -1397 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1398 0 obj -<< -/Subtype /Link -/A 1397 0 R -/Type /Annot -/Rect [72 586.477 527.898438 598.977] -/Border [0 0 0] ->> -endobj -1399 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1400 0 obj -<< -/Subtype /Link -/A 1399 0 R -/Type /Annot -/Rect [72 573.977 536.819336 586.477] -/Border [0 0 0] ->> -endobj -1401 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1402 0 obj -<< -/Subtype /Link -/A 1401 0 R -/Type /Annot -/Rect [72 561.477 111.897461 573.977] -/Border [0 0 0] ->> -endobj -1403 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1404 0 obj -<< -/Subtype /Link -/A 1403 0 R -/Type /Annot -/Rect [72 526.979 233.928 551.477] -/Border [0 0 0] ->> -endobj -1405 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1406 0 obj -<< -/Subtype /Link -/A 1405 0 R -/Type /Annot -/Rect [72 504.479 322.078125 516.979] -/Border [0 0 0] ->> -endobj -1407 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1408 0 obj -<< -/Subtype /Link -/A 1407 0 R -/Type /Annot -/Rect [322.078125 504.409 358.078125 516.979] -/Border [0 0 0] ->> -endobj -1409 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1410 0 obj -<< -/Subtype /Link -/A 1409 0 R -/Type /Annot -/Rect [358.078125 504.479 363.976563 516.979] -/Border [0 0 0] ->> -endobj -1411 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1412 0 obj -<< -/Subtype /Link -/A 1411 0 R -/Type /Annot -/Rect [363.976563 504.409 441.976563 516.979] -/Border [0 0 0] ->> -endobj -1413 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1414 0 obj -<< -/Subtype /Link -/A 1413 0 R -/Type /Annot -/Rect [441.976563 504.479 465.6875 516.979] -/Border [0 0 0] ->> -endobj -1415 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1416 0 obj -<< -/Subtype /Link -/A 1415 0 R -/Type /Annot -/Rect [72 491.839 168 504.409] -/Border [0 0 0] ->> -endobj -1417 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1418 0 obj -<< -/Subtype /Link -/A 1417 0 R -/Type /Annot -/Rect [168 491.909 448.195313 504.409] -/Border [0 0 0] ->> -endobj -1419 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1420 0 obj -<< -/Subtype /Link -/A 1419 0 R -/Type /Annot -/Rect [448.195313 491.839 484.195313 504.409] -/Border [0 0 0] ->> -endobj -1421 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1422 0 obj -<< -/Subtype /Link -/A 1421 0 R -/Type /Annot -/Rect [484.195313 491.909 522.701172 504.409] -/Border [0 0 0] ->> -endobj -1423 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1424 0 obj -<< -/Subtype /Link -/A 1423 0 R -/Type /Annot -/Rect [72 479.409 517.664063 491.909] -/Border [0 0 0] ->> -endobj -1425 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1426 0 obj -<< -/Subtype /Link -/A 1425 0 R -/Type /Annot -/Rect [72 466.909 475.369141 479.409] -/Border [0 0 0] ->> -endobj -1427 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1428 0 obj -<< -/Subtype /Link -/A 1427 0 R -/Type /Annot -/Rect [72 445.596 88.2 456.909] -/Border [0 0 0] ->> -endobj -1429 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1430 0 obj -<< -/Subtype /Link -/A 1429 0 R -/Type /Annot -/Rect [88.2 445.596 93.6 456.909] -/Border [0 0 0] ->> -endobj -1431 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1432 0 obj -<< -/Subtype /Link -/A 1431 0 R -/Type /Annot -/Rect [93.6 445.596 126 456.909] -/Border [0 0 0] ->> -endobj -1433 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1434 0 obj -<< -/Subtype /Link -/A 1433 0 R -/Type /Annot -/Rect [126 445.596 131.4 456.909] -/Border [0 0 0] ->> -endobj -1435 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1436 0 obj -<< -/Subtype /Link -/A 1435 0 R -/Type /Annot -/Rect [131.4 445.596 136.8 456.909] -/Border [0 0 0] ->> -endobj -1437 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1438 0 obj -<< -/Subtype /Link -/A 1437 0 R -/Type /Annot -/Rect [136.8 445.596 142.2 456.909] -/Border [0 0 0] ->> -endobj -1439 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1440 0 obj -<< -/Subtype /Link -/A 1439 0 R -/Type /Annot -/Rect [142.2 445.596 147.6 456.909] -/Border [0 0 0] ->> -endobj -1441 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1442 0 obj -<< -/Subtype /Link -/A 1441 0 R -/Type /Annot -/Rect [147.6 445.596 158.4 456.909] -/Border [0 0 0] ->> -endobj -1443 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1444 0 obj -<< -/Subtype /Link -/A 1443 0 R -/Type /Annot -/Rect [158.4 445.596 163.8 456.909] -/Border [0 0 0] ->> -endobj -1445 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1446 0 obj -<< -/Subtype /Link -/A 1445 0 R -/Type /Annot -/Rect [163.8 445.596 331.2 456.909] -/Border [0 0 0] ->> -endobj -1447 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1448 0 obj -<< -/Subtype /Link -/A 1447 0 R -/Type /Annot -/Rect [331.2 445.596 460.8 456.909] -/Border [0 0 0] ->> -endobj -1449 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1450 0 obj -<< -/Subtype /Link -/A 1449 0 R -/Type /Annot -/Rect [72 434.283 88.2 445.596] -/Border [0 0 0] ->> -endobj -1451 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1452 0 obj -<< -/Subtype /Link -/A 1451 0 R -/Type /Annot -/Rect [88.2 434.283 93.6 445.596] -/Border [0 0 0] ->> -endobj -1453 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1454 0 obj -<< -/Subtype /Link -/A 1453 0 R -/Type /Annot -/Rect [93.6 434.283 126 445.596] -/Border [0 0 0] ->> -endobj -1455 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1456 0 obj -<< -/Subtype /Link -/A 1455 0 R -/Type /Annot -/Rect [126 434.283 131.4 445.596] -/Border [0 0 0] ->> -endobj -1457 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1458 0 obj -<< -/Subtype /Link -/A 1457 0 R -/Type /Annot -/Rect [131.4 434.283 147.6 445.596] -/Border [0 0 0] ->> -endobj -1459 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1460 0 obj -<< -/Subtype /Link -/A 1459 0 R -/Type /Annot -/Rect [147.6 434.283 153 445.596] -/Border [0 0 0] ->> -endobj -1461 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1462 0 obj -<< -/Subtype /Link -/A 1461 0 R -/Type /Annot -/Rect [153 434.283 158.4 445.596] -/Border [0 0 0] ->> -endobj -1463 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1464 0 obj -<< -/Subtype /Link -/A 1463 0 R -/Type /Annot -/Rect [158.4 434.283 174.6 445.596] -/Border [0 0 0] ->> -endobj -1465 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1466 0 obj -<< -/Subtype /Link -/A 1465 0 R -/Type /Annot -/Rect [174.6 434.283 180 445.596] -/Border [0 0 0] ->> -endobj -1467 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1468 0 obj -<< -/Subtype /Link -/A 1467 0 R -/Type /Annot -/Rect [180 434.283 331.2 445.596] -/Border [0 0 0] ->> -endobj -1469 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1470 0 obj -<< -/Subtype /Link -/A 1469 0 R -/Type /Annot -/Rect [331.2 434.283 406.8 445.596] -/Border [0 0 0] ->> -endobj -1471 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1472 0 obj -<< -/Subtype /Link -/A 1471 0 R -/Type /Annot -/Rect [72 422.97 88.2 434.283] -/Border [0 0 0] ->> -endobj -1473 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1474 0 obj -<< -/Subtype /Link -/A 1473 0 R -/Type /Annot -/Rect [88.2 422.97 93.6 434.283] -/Border [0 0 0] ->> -endobj -1475 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1476 0 obj -<< -/Subtype /Link -/A 1475 0 R -/Type /Annot -/Rect [93.6 422.97 180 434.283] -/Border [0 0 0] ->> -endobj -1477 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1478 0 obj -<< -/Subtype /Link -/A 1477 0 R -/Type /Annot -/Rect [180 422.97 185.4 434.283] -/Border [0 0 0] ->> -endobj -1479 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1480 0 obj -<< -/Subtype /Link -/A 1479 0 R -/Type /Annot -/Rect [185.4 422.97 201.6 434.283] -/Border [0 0 0] ->> -endobj -1481 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1482 0 obj -<< -/Subtype /Link -/A 1481 0 R -/Type /Annot -/Rect [201.6 422.97 207 434.283] -/Border [0 0 0] ->> -endobj -1483 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1484 0 obj -<< -/Subtype /Link -/A 1483 0 R -/Type /Annot -/Rect [207 422.97 212.4 434.283] -/Border [0 0 0] ->> -endobj -1485 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1486 0 obj -<< -/Subtype /Link -/A 1485 0 R -/Type /Annot -/Rect [212.4 422.97 228.6 434.283] -/Border [0 0 0] ->> -endobj -1487 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1488 0 obj -<< -/Subtype /Link -/A 1487 0 R -/Type /Annot -/Rect [228.6 422.97 234 434.283] -/Border [0 0 0] ->> -endobj -1489 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1490 0 obj -<< -/Subtype /Link -/A 1489 0 R -/Type /Annot -/Rect [234 422.97 239.4 434.283] -/Border [0 0 0] ->> -endobj -1491 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1492 0 obj -<< -/Subtype /Link -/A 1491 0 R -/Type /Annot -/Rect [239.4 422.97 255.6 434.283] -/Border [0 0 0] ->> -endobj -1493 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1494 0 obj -<< -/Subtype /Link -/A 1493 0 R -/Type /Annot -/Rect [255.6 422.97 261 434.283] -/Border [0 0 0] ->> -endobj -1495 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1496 0 obj -<< -/Subtype /Link -/A 1495 0 R -/Type /Annot -/Rect [261 422.97 266.4 434.283] -/Border [0 0 0] ->> -endobj -1497 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1498 0 obj -<< -/Subtype /Link -/A 1497 0 R -/Type /Annot -/Rect [266.4 422.97 282.6 434.283] -/Border [0 0 0] ->> -endobj -1499 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1500 0 obj -<< -/Subtype /Link -/A 1499 0 R -/Type /Annot -/Rect [282.6 422.97 288 434.283] -/Border [0 0 0] ->> -endobj -1501 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1502 0 obj -<< -/Subtype /Link -/A 1501 0 R -/Type /Annot -/Rect [288 422.97 331.2 434.283] -/Border [0 0 0] ->> -endobj -1503 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1504 0 obj -<< -/Subtype /Link -/A 1503 0 R -/Type /Annot -/Rect [331.2 422.97 466.2 434.283] -/Border [0 0 0] ->> -endobj -1505 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1506 0 obj -<< -/Subtype /Link -/A 1505 0 R -/Type /Annot -/Rect [72 411.657 88.2 422.97] -/Border [0 0 0] ->> -endobj -1507 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1508 0 obj -<< -/Subtype /Link -/A 1507 0 R -/Type /Annot -/Rect [88.2 411.657 93.6 422.97] -/Border [0 0 0] ->> -endobj -1509 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1510 0 obj -<< -/Subtype /Link -/A 1509 0 R -/Type /Annot -/Rect [93.6 411.657 163.8 422.97] -/Border [0 0 0] ->> -endobj -1511 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1512 0 obj -<< -/Subtype /Link -/A 1511 0 R -/Type /Annot -/Rect [163.8 411.657 169.2 422.97] -/Border [0 0 0] ->> -endobj -1513 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1514 0 obj -<< -/Subtype /Link -/A 1513 0 R -/Type /Annot -/Rect [169.2 411.657 185.4 422.97] -/Border [0 0 0] ->> -endobj -1515 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1516 0 obj -<< -/Subtype /Link -/A 1515 0 R -/Type /Annot -/Rect [185.4 411.657 190.8 422.97] -/Border [0 0 0] ->> -endobj -1517 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1518 0 obj -<< -/Subtype /Link -/A 1517 0 R -/Type /Annot -/Rect [190.8 411.657 196.2 422.97] -/Border [0 0 0] ->> -endobj -1519 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1520 0 obj -<< -/Subtype /Link -/A 1519 0 R -/Type /Annot -/Rect [196.2 411.657 201.6 422.97] -/Border [0 0 0] ->> -endobj -1521 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1522 0 obj -<< -/Subtype /Link -/A 1521 0 R -/Type /Annot -/Rect [201.6 411.657 212.4 422.97] -/Border [0 0 0] ->> -endobj -1523 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1524 0 obj -<< -/Subtype /Link -/A 1523 0 R -/Type /Annot -/Rect [212.4 411.657 217.8 422.97] -/Border [0 0 0] ->> -endobj -1525 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1526 0 obj -<< -/Subtype /Link -/A 1525 0 R -/Type /Annot -/Rect [217.8 411.657 223.2 422.97] -/Border [0 0 0] ->> -endobj -1527 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1528 0 obj -<< -/Subtype /Link -/A 1527 0 R -/Type /Annot -/Rect [223.2 411.657 239.4 422.97] -/Border [0 0 0] ->> -endobj -1529 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1530 0 obj -<< -/Subtype /Link -/A 1529 0 R -/Type /Annot -/Rect [239.4 411.657 244.8 422.97] -/Border [0 0 0] ->> -endobj -1531 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1532 0 obj -<< -/Subtype /Link -/A 1531 0 R -/Type /Annot -/Rect [244.8 411.657 250.2 422.97] -/Border [0 0 0] ->> -endobj -1533 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1534 0 obj -<< -/Subtype /Link -/A 1533 0 R -/Type /Annot -/Rect [250.2 411.657 266.4 422.97] -/Border [0 0 0] ->> -endobj -1535 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1536 0 obj -<< -/Subtype /Link -/A 1535 0 R -/Type /Annot -/Rect [266.4 411.657 271.8 422.97] -/Border [0 0 0] ->> -endobj -1537 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1538 0 obj -<< -/Subtype /Link -/A 1537 0 R -/Type /Annot -/Rect [271.8 411.657 277.2 422.97] -/Border [0 0 0] ->> -endobj -1539 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1540 0 obj -<< -/Subtype /Link -/A 1539 0 R -/Type /Annot -/Rect [277.2 411.657 293.4 422.97] -/Border [0 0 0] ->> -endobj -1541 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1542 0 obj -<< -/Subtype /Link -/A 1541 0 R -/Type /Annot -/Rect [293.4 411.657 298.8 422.97] -/Border [0 0 0] ->> -endobj -1543 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1544 0 obj -<< -/Subtype /Link -/A 1543 0 R -/Type /Annot -/Rect [298.8 411.657 304.2 422.97] -/Border [0 0 0] ->> -endobj -1545 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1546 0 obj -<< -/Subtype /Link -/A 1545 0 R -/Type /Annot -/Rect [304.2 411.657 320.4 422.97] -/Border [0 0 0] ->> -endobj -1547 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1548 0 obj -<< -/Subtype /Link -/A 1547 0 R -/Type /Annot -/Rect [320.4 411.657 325.8 422.97] -/Border [0 0 0] ->> -endobj -1549 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1550 0 obj -<< -/Subtype /Link -/A 1549 0 R -/Type /Annot -/Rect [325.8 411.657 331.2 422.97] -/Border [0 0 0] ->> -endobj -1551 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1552 0 obj -<< -/Subtype /Link -/A 1551 0 R -/Type /Annot -/Rect [331.2 411.657 450 422.97] -/Border [0 0 0] ->> -endobj -1553 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1554 0 obj -<< -/Subtype /Link -/A 1553 0 R -/Type /Annot -/Rect [72 400.344 88.2 411.657] -/Border [0 0 0] ->> -endobj -1555 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1556 0 obj -<< -/Subtype /Link -/A 1555 0 R -/Type /Annot -/Rect [88.2 400.344 93.6 411.657] -/Border [0 0 0] ->> -endobj -1557 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1558 0 obj -<< -/Subtype /Link -/A 1557 0 R -/Type /Annot -/Rect [93.6 400.344 126 411.657] -/Border [0 0 0] ->> -endobj -1559 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1560 0 obj -<< -/Subtype /Link -/A 1559 0 R -/Type /Annot -/Rect [126 400.344 131.4 411.657] -/Border [0 0 0] ->> -endobj -1561 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1562 0 obj -<< -/Subtype /Link -/A 1561 0 R -/Type /Annot -/Rect [131.4 400.344 147.6 411.657] -/Border [0 0 0] ->> -endobj -1563 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1564 0 obj -<< -/Subtype /Link -/A 1563 0 R -/Type /Annot -/Rect [147.6 400.344 153 411.657] -/Border [0 0 0] ->> -endobj -1565 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1566 0 obj -<< -/Subtype /Link -/A 1565 0 R -/Type /Annot -/Rect [153 400.344 158.4 411.657] -/Border [0 0 0] ->> -endobj -1567 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1568 0 obj -<< -/Subtype /Link -/A 1567 0 R -/Type /Annot -/Rect [158.4 400.344 169.2 411.657] -/Border [0 0 0] ->> -endobj -1569 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1570 0 obj -<< -/Subtype /Link -/A 1569 0 R -/Type /Annot -/Rect [169.2 400.344 174.6 411.657] -/Border [0 0 0] ->> -endobj -1571 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1572 0 obj -<< -/Subtype /Link -/A 1571 0 R -/Type /Annot -/Rect [174.6 400.344 331.2 411.657] -/Border [0 0 0] ->> -endobj -1573 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1574 0 obj -<< -/Subtype /Link -/A 1573 0 R -/Type /Annot -/Rect [331.2 400.344 439.2 411.657] -/Border [0 0 0] ->> -endobj -1575 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1576 0 obj -<< -/Subtype /Link -/A 1575 0 R -/Type /Annot -/Rect [72 389.031 88.2 400.344] -/Border [0 0 0] ->> -endobj -1577 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1578 0 obj -<< -/Subtype /Link -/A 1577 0 R -/Type /Annot -/Rect [88.2 389.031 93.6 400.344] -/Border [0 0 0] ->> -endobj -1579 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1580 0 obj -<< -/Subtype /Link -/A 1579 0 R -/Type /Annot -/Rect [93.6 389.031 126 400.344] -/Border [0 0 0] ->> -endobj -1581 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1582 0 obj -<< -/Subtype /Link -/A 1581 0 R -/Type /Annot -/Rect [126 389.031 131.4 400.344] -/Border [0 0 0] ->> -endobj -1583 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1584 0 obj -<< -/Subtype /Link -/A 1583 0 R -/Type /Annot -/Rect [131.4 389.031 136.8 400.344] -/Border [0 0 0] ->> -endobj -1585 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1586 0 obj -<< -/Subtype /Link -/A 1585 0 R -/Type /Annot -/Rect [136.8 389.031 142.2 400.344] -/Border [0 0 0] ->> -endobj -1587 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1588 0 obj -<< -/Subtype /Link -/A 1587 0 R -/Type /Annot -/Rect [142.2 389.031 331.2 400.344] -/Border [0 0 0] ->> -endobj -1589 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1590 0 obj -<< -/Subtype /Link -/A 1589 0 R -/Type /Annot -/Rect [331.2 389.031 428.4 400.344] -/Border [0 0 0] ->> -endobj -1591 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1592 0 obj -<< -/Subtype /Link -/A 1591 0 R -/Type /Annot -/Rect [72 366.531 282.390625 379.031] -/Border [0 0 0] ->> -endobj -1593 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1594 0 obj -<< -/Subtype /Link -/A 1593 0 R -/Type /Annot -/Rect [72 143.627 535.378906 156.127] -/Border [0 0 0] ->> -endobj -1595 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1596 0 obj -<< -/Subtype /Link -/A 1595 0 R -/Type /Annot -/Rect [72 131.127 482.366211 143.627] -/Border [0 0 0] ->> -endobj -1597 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1598 0 obj -<< -/Subtype /Link -/A 1597 0 R -/Type /Annot -/Rect [72 118.627 151.580078 131.127] -/Border [0 0 0] ->> -endobj -1599 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1600 0 obj -<< -/Subtype /Link -/A 1599 0 R -/Type /Annot -/Rect [151.580078 118.557 169.580078 131.127] -/Border [0 0 0] ->> -endobj -1601 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1602 0 obj -<< -/Subtype /Link -/A 1601 0 R -/Type /Annot -/Rect [169.580078 118.627 525.3125 131.127] -/Border [0 0 0] ->> -endobj -1603 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1604 0 obj -<< -/Subtype /Link -/A 1603 0 R -/Type /Annot -/Rect [72 106.127 376.443359 118.627] -/Border [0 0 0] ->> -endobj -1384 0 obj -<< -/Type /Page -/Parent 1 0 R -/MediaBox [0 0 612 792] -/Contents 1382 0 R -/Resources 1383 0 R -/Annots [1387 0 R 1390 0 R 1392 0 R 1394 0 R 1396 0 R 1398 0 R 1400 0 R 1402 0 R 1404 0 R 1406 0 R 1408 0 R 1410 0 R 1412 0 R 1414 0 R 1416 0 R 1418 0 R 1420 0 R 1422 0 R 1424 0 R 1426 0 R 1428 0 R 1430 0 R 1432 0 R 1434 0 R 1436 0 R 1438 0 R 1440 0 R 1442 0 R 1444 0 R 1446 0 R 1448 0 R 1450 0 R 1452 0 R 1454 0 R 1456 0 R 1458 0 R 1460 0 R 1462 0 R 1464 0 R 1466 0 R 1468 0 R 1470 0 R 1472 0 R 1474 0 R 1476 0 R 1478 0 R 1480 0 R 1482 0 R 1484 0 R 1486 0 R 1488 0 R 1490 0 R 1492 0 R 1494 0 R 1496 0 R 1498 0 R 1500 0 R 1502 0 R 1504 0 R 1506 0 R 1508 0 R 1510 0 R 1512 0 R 1514 0 R 1516 0 R 1518 0 R 1520 0 R 1522 0 R 1524 0 R 1526 0 R 1528 0 R 1530 0 R 1532 0 R 1534 0 R 1536 0 R 1538 0 R 1540 0 R 1542 0 R 1544 0 R 1546 0 R 1548 0 R 1550 0 R 1552 0 R 1554 0 R 1556 0 R 1558 0 R 1560 0 R 1562 0 R 1564 0 R 1566 0 R 1568 0 R 1570 0 R 1572 0 R 1574 0 R 1576 0 R 1578 0 R 1580 0 R 1582 0 R 1584 0 R 1586 0 R 1588 0 R 1590 0 R 1592 0 R 1594 0 R 1596 0 R 1598 0 R 1600 0 R 1602 0 R 1604 0 R] ->> -endobj -1383 0 obj -<< -/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] -/Font << -/F4 16 0 R -/F3 9 0 R -/F6 44 0 R -/F5 29 0 R ->> ->> -endobj -1382 0 obj -<< -/Length 2257 -/Filter /FlateDecode ->> -stream -x\K6WD%OAA@omV`{m@S_F2)˻ZڛZz3߼% e#2q4/~<}xN_ɋs??N8hl[7j{~m"⚨E+(=㻼-rdDIWyRw@Ns%캹-0";/+58$$uNDzO^!g P7@.$q%(N3 5 % cY }A.w"[hKF1ɣ7ʍR]&3hl>#V6A:03tFըntv \9ħƴtʙ+s|e @+ -enY1hц64e<=/?Vƪ^I'"v8h-9eY.ue#ѡ56 ϔ-JNpxk\< -w$8+,OщYJ2폩k7,NOE'm5쌒,HMqLE؜0=&=z R7r<_ps Ihؐqx^LK<n sbG@Bahmaо MT:4 mJΉ;=RW!lK·ME ,ľ]%łz8\2BIde o ՁV5۵2$J6M7P/6 .) :dek-#l2as`tbCch:N j͂TLB2Paf%[]Gj*"UC --h^*bJz؇"Bk[M-8sK`ƒtL)(ڿPP! P7~婹s*@ԍS*uOӭ؊~4<9CX%E 3?U2#= -@gY0^"V{PT αDO5c({qs;\8.jyӻ<NrAr`d[2*+tUy Яz<,Ōz{"#*A2ZvR}/Iԭs@ΝU>XXBsTv RZƦ԰$zul'gTAvR<Ŕ]¥с؃Z yJQu7OIw-nT? ௄-IE*/ҧҧܾrG@|r@Ν˝H Zk'yR"{Gz*?-EK-%Si[Ҹzȧ'WdEo{.x#%\ȹo*D-_ԶwT+U^[Ίtsb"Wz8~;Y{{c'[Kc'IܿQ -iu\bUߋ˼Z,Օxѩ рh€!?@_~cvN{M.LtEJR֙LF-Λ:x›azZab*Kdϝ7Ӊ2Z -ҋ\ 5̛JcjF+P߾=I*BNj=9fk} ]|\NMZkd(YKRa֍JmHJa5-Ur4@mhXccKel6|i #hI%y\<[:_@CqE;`׃_4꩖gMq^rQZƙ16 -]O ƙKph+fВ_*86u^!&B*KafV -endstream -endobj -1609 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1610 0 obj -<< -/Subtype /Link -/A 1609 0 R -/Type /Annot -/Rect [72 695.502 149.31 720] -/Border [0 0 0] ->> -endobj -1611 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1612 0 obj -<< -/Subtype /Link -/A 1611 0 R -/Type /Annot -/Rect [72 673.002 534.954102 685.502] -/Border [0 0 0] ->> -endobj -1613 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1614 0 obj -<< -/Subtype /Link -/A 1613 0 R -/Type /Annot -/Rect [72 660.502 528.899414 673.002] -/Border [0 0 0] ->> -endobj -1615 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1616 0 obj -<< -/Subtype /Link -/A 1615 0 R -/Type /Annot -/Rect [72 648.002 525.964844 660.502] -/Border [0 0 0] ->> -endobj -1617 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1618 0 obj -<< -/Subtype /Link -/A 1617 0 R -/Type /Annot -/Rect [72 635.502 326.057617 648.002] -/Border [0 0 0] ->> -endobj -1619 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1620 0 obj -<< -/Subtype /Link -/A 1619 0 R -/Type /Annot -/Rect [72 614.189 88.2 625.502] -/Border [0 0 0] ->> -endobj -1621 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1622 0 obj -<< -/Subtype /Link -/A 1621 0 R -/Type /Annot -/Rect [88.2 614.189 93.6 625.502] -/Border [0 0 0] ->> -endobj -1623 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1624 0 obj -<< -/Subtype /Link -/A 1623 0 R -/Type /Annot -/Rect [93.6 614.189 115.2 625.502] -/Border [0 0 0] ->> -endobj -1625 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1626 0 obj -<< -/Subtype /Link -/A 1625 0 R -/Type /Annot -/Rect [115.2 614.189 120.6 625.502] -/Border [0 0 0] ->> -endobj -1627 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1628 0 obj -<< -/Subtype /Link -/A 1627 0 R -/Type /Annot -/Rect [120.6 614.189 504 625.502] -/Border [0 0 0] ->> -endobj -1629 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1630 0 obj -<< -/Subtype /Link -/A 1629 0 R -/Type /Annot -/Rect [504 614.189 509.4 625.502] -/Border [0 0 0] ->> -endobj -1631 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1632 0 obj -<< -/Subtype /Link -/A 1631 0 R -/Type /Annot -/Rect [72 602.876 88.2 614.189] -/Border [0 0 0] ->> -endobj -1633 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1634 0 obj -<< -/Subtype /Link -/A 1633 0 R -/Type /Annot -/Rect [88.2 602.876 93.6 614.189] -/Border [0 0 0] ->> -endobj -1635 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1636 0 obj -<< -/Subtype /Link -/A 1635 0 R -/Type /Annot -/Rect [93.6 602.876 126 614.189] -/Border [0 0 0] ->> -endobj -1637 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1638 0 obj -<< -/Subtype /Link -/A 1637 0 R -/Type /Annot -/Rect [126 602.876 131.4 614.189] -/Border [0 0 0] ->> -endobj -1639 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1640 0 obj -<< -/Subtype /Link -/A 1639 0 R -/Type /Annot -/Rect [131.4 602.876 136.8 614.189] -/Border [0 0 0] ->> -endobj -1641 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1642 0 obj -<< -/Subtype /Link -/A 1641 0 R -/Type /Annot -/Rect [72 379.972 518.59668 392.472] -/Border [0 0 0] ->> -endobj -1643 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1644 0 obj -<< -/Subtype /Link -/A 1643 0 R -/Type /Annot -/Rect [72 367.472 321.18457 379.972] -/Border [0 0 0] ->> -endobj -1607 0 obj -<< -/Type /Page -/Parent 1 0 R -/MediaBox [0 0 612 792] -/Contents 1605 0 R -/Resources 1606 0 R -/Annots [1610 0 R 1612 0 R 1614 0 R 1616 0 R 1618 0 R 1620 0 R 1622 0 R 1624 0 R 1626 0 R 1628 0 R 1630 0 R 1632 0 R 1634 0 R 1636 0 R 1638 0 R 1640 0 R 1642 0 R 1644 0 R] ->> -endobj -1606 0 obj -<< -/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] -/Font << -/F4 16 0 R -/F3 9 0 R -/F5 29 0 R ->> ->> -endobj -1605 0 obj -<< -/Length 907 -/Filter /FlateDecode ->> -stream -xXn@ +9;tzk[у-@@ YHk$KYpɀ /Ptw㏮Ntݯww;ZP8 x-ݩv#R"wz\|;G'A -]>5w ζ P$#H)"L)RJ2NkHPڙ&N. w1]>'Tԩ 5Vt~g‡1KNc_q WC%H K6XBnZ֒lUdXxbedi(zq0iK A8M mK -񳉥Q\3#S~ M("C__N*Zf2o\,|&ᨴšL&yԊRYʥ,\:I)~S> -endobj -1650 0 obj -<< -/Subtype /Link -/A 1649 0 R -/Type /Annot -/Rect [72 695.502 176.994 720] -/Border [0 0 0] ->> -endobj -1651 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1652 0 obj -<< -/Subtype /Link -/A 1651 0 R -/Type /Annot -/Rect [72 673.002 532.078125 685.502] -/Border [0 0 0] ->> -endobj -1653 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1654 0 obj -<< -/Subtype /Link -/A 1653 0 R -/Type /Annot -/Rect [72 660.502 171.609375 673.002] -/Border [0 0 0] ->> -endobj -1655 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1656 0 obj -<< -/Subtype /Link -/A 1655 0 R -/Type /Annot -/Rect [72 637.932 222 650.502] -/Border [0 0 0] ->> -endobj -1657 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1658 0 obj -<< -/Subtype /Link -/A 1657 0 R -/Type /Annot -/Rect [72 619.362 348 631.932] -/Border [0 0 0] ->> -endobj -1659 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1660 0 obj -<< -/Subtype /Link -/A 1659 0 R -/Type /Annot -/Rect [72 600.792 390 613.362] -/Border [0 0 0] ->> -endobj -1661 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1662 0 obj -<< -/Subtype /Link -/A 1661 0 R -/Type /Annot -/Rect [72 582.222 264 594.792] -/Border [0 0 0] ->> -endobj -1663 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1664 0 obj -<< -/Subtype /Link -/A 1663 0 R -/Type /Annot -/Rect [72 563.652 180 576.222] -/Border [0 0 0] ->> -endobj -1665 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1666 0 obj -<< -/Subtype /Link -/A 1665 0 R -/Type /Annot -/Rect [72 535.152 138.396484 547.652] -/Border [0 0 0] ->> -endobj -1667 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1668 0 obj -<< -/Subtype /Link -/A 1667 0 R -/Type /Annot -/Rect [138.396484 535.082 180.396484 547.652] -/Border [0 0 0] ->> -endobj -1669 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1670 0 obj -<< -/Subtype /Link -/A 1669 0 R -/Type /Annot -/Rect [180.396484 535.152 519.805664 547.652] -/Border [0 0 0] ->> -endobj -1671 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1672 0 obj -<< -/Subtype /Link -/A 1671 0 R -/Type /Annot -/Rect [72 522.652 517.03418 535.152] -/Border [0 0 0] ->> -endobj -1673 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1674 0 obj -<< -/Subtype /Link -/A 1673 0 R -/Type /Annot -/Rect [72 510.152 396.96582 522.652] -/Border [0 0 0] ->> -endobj -1675 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1676 0 obj -<< -/Subtype /Link -/A 1675 0 R -/Type /Annot -/Rect [72 488.839 88.2 500.152] -/Border [0 0 0] ->> -endobj -1677 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1678 0 obj -<< -/Subtype /Link -/A 1677 0 R -/Type /Annot -/Rect [88.2 488.839 93.6 500.152] -/Border [0 0 0] ->> -endobj -1679 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1680 0 obj -<< -/Subtype /Link -/A 1679 0 R -/Type /Annot -/Rect [93.6 488.839 131.4 500.152] -/Border [0 0 0] ->> -endobj -1681 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1682 0 obj -<< -/Subtype /Link -/A 1681 0 R -/Type /Annot -/Rect [131.4 488.839 136.8 500.152] -/Border [0 0 0] ->> -endobj -1683 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1684 0 obj -<< -/Subtype /Link -/A 1683 0 R -/Type /Annot -/Rect [136.8 488.839 142.2 500.152] -/Border [0 0 0] ->> -endobj -1685 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1686 0 obj -<< -/Subtype /Link -/A 1685 0 R -/Type /Annot -/Rect [142.2 488.839 158.4 500.152] -/Border [0 0 0] ->> -endobj -1687 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1688 0 obj -<< -/Subtype /Link -/A 1687 0 R -/Type /Annot -/Rect [158.4 488.839 163.8 500.152] -/Border [0 0 0] ->> -endobj -1689 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1690 0 obj -<< -/Subtype /Link -/A 1689 0 R -/Type /Annot -/Rect [163.8 488.839 169.2 500.152] -/Border [0 0 0] ->> -endobj -1691 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1692 0 obj -<< -/Subtype /Link -/A 1691 0 R -/Type /Annot -/Rect [169.2 488.839 174.6 500.152] -/Border [0 0 0] ->> -endobj -1693 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1694 0 obj -<< -/Subtype /Link -/A 1693 0 R -/Type /Annot -/Rect [174.6 488.839 180 500.152] -/Border [0 0 0] ->> -endobj -1695 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1696 0 obj -<< -/Subtype /Link -/A 1695 0 R -/Type /Annot -/Rect [180 488.839 185.4 500.152] -/Border [0 0 0] ->> -endobj -1697 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1698 0 obj -<< -/Subtype /Link -/A 1697 0 R -/Type /Annot -/Rect [185.4 488.839 190.8 500.152] -/Border [0 0 0] ->> -endobj -1699 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1700 0 obj -<< -/Subtype /Link -/A 1699 0 R -/Type /Annot -/Rect [190.8 488.839 196.2 500.152] -/Border [0 0 0] ->> -endobj -1701 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1702 0 obj -<< -/Subtype /Link -/A 1701 0 R -/Type /Annot -/Rect [196.2 488.839 207 500.152] -/Border [0 0 0] ->> -endobj -1703 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1704 0 obj -<< -/Subtype /Link -/A 1703 0 R -/Type /Annot -/Rect [207 488.839 212.4 500.152] -/Border [0 0 0] ->> -endobj -1705 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1706 0 obj -<< -/Subtype /Link -/A 1705 0 R -/Type /Annot -/Rect [212.4 488.839 217.8 500.152] -/Border [0 0 0] ->> -endobj -1707 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1708 0 obj -<< -/Subtype /Link -/A 1707 0 R -/Type /Annot -/Rect [217.8 488.839 234 500.152] -/Border [0 0 0] ->> -endobj -1709 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1710 0 obj -<< -/Subtype /Link -/A 1709 0 R -/Type /Annot -/Rect [234 488.839 239.4 500.152] -/Border [0 0 0] ->> -endobj -1711 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1712 0 obj -<< -/Subtype /Link -/A 1711 0 R -/Type /Annot -/Rect [239.4 488.839 244.8 500.152] -/Border [0 0 0] ->> -endobj -1713 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1714 0 obj -<< -/Subtype /Link -/A 1713 0 R -/Type /Annot -/Rect [244.8 488.839 250.2 500.152] -/Border [0 0 0] ->> -endobj -1715 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1716 0 obj -<< -/Subtype /Link -/A 1715 0 R -/Type /Annot -/Rect [250.2 488.839 255.6 500.152] -/Border [0 0 0] ->> -endobj -1717 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1718 0 obj -<< -/Subtype /Link -/A 1717 0 R -/Type /Annot -/Rect [255.6 488.839 271.8 500.152] -/Border [0 0 0] ->> -endobj -1719 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1720 0 obj -<< -/Subtype /Link -/A 1719 0 R -/Type /Annot -/Rect [271.8 488.839 277.2 500.152] -/Border [0 0 0] ->> -endobj -1721 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1722 0 obj -<< -/Subtype /Link -/A 1721 0 R -/Type /Annot -/Rect [277.2 488.839 282.6 500.152] -/Border [0 0 0] ->> -endobj -1723 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1724 0 obj -<< -/Subtype /Link -/A 1723 0 R -/Type /Annot -/Rect [282.6 488.839 298.8 500.152] -/Border [0 0 0] ->> -endobj -1725 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1726 0 obj -<< -/Subtype /Link -/A 1725 0 R -/Type /Annot -/Rect [298.8 488.839 304.2 500.152] -/Border [0 0 0] ->> -endobj -1727 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1728 0 obj -<< -/Subtype /Link -/A 1727 0 R -/Type /Annot -/Rect [304.2 488.839 309.6 500.152] -/Border [0 0 0] ->> -endobj -1729 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1730 0 obj -<< -/Subtype /Link -/A 1729 0 R -/Type /Annot -/Rect [309.6 488.839 315 500.152] -/Border [0 0 0] ->> -endobj -1731 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1732 0 obj -<< -/Subtype /Link -/A 1731 0 R -/Type /Annot -/Rect [72 477.526 88.2 488.839] -/Border [0 0 0] ->> -endobj -1733 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1734 0 obj -<< -/Subtype /Link -/A 1733 0 R -/Type /Annot -/Rect [88.2 477.526 93.6 488.839] -/Border [0 0 0] ->> -endobj -1735 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1736 0 obj -<< -/Subtype /Link -/A 1735 0 R -/Type /Annot -/Rect [93.6 477.526 126 488.839] -/Border [0 0 0] ->> -endobj -1737 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1738 0 obj -<< -/Subtype /Link -/A 1737 0 R -/Type /Annot -/Rect [126 477.526 131.4 488.839] -/Border [0 0 0] ->> -endobj -1739 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1740 0 obj -<< -/Subtype /Link -/A 1739 0 R -/Type /Annot -/Rect [131.4 477.526 136.8 488.839] -/Border [0 0 0] ->> -endobj -1741 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1742 0 obj -<< -/Subtype /Link -/A 1741 0 R -/Type /Annot -/Rect [136.8 477.526 142.2 488.839] -/Border [0 0 0] ->> -endobj -1743 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1744 0 obj -<< -/Subtype /Link -/A 1743 0 R -/Type /Annot -/Rect [72 455.026 282.390625 467.526] -/Border [0 0 0] ->> -endobj -1647 0 obj -<< -/Type /Page -/Parent 1 0 R -/MediaBox [0 0 612 792] -/Contents 1645 0 R -/Resources 1646 0 R -/Annots [1650 0 R 1652 0 R 1654 0 R 1656 0 R 1658 0 R 1660 0 R 1662 0 R 1664 0 R 1666 0 R 1668 0 R 1670 0 R 1672 0 R 1674 0 R 1676 0 R 1678 0 R 1680 0 R 1682 0 R 1684 0 R 1686 0 R 1688 0 R 1690 0 R 1692 0 R 1694 0 R 1696 0 R 1698 0 R 1700 0 R 1702 0 R 1704 0 R 1706 0 R 1708 0 R 1710 0 R 1712 0 R 1714 0 R 1716 0 R 1718 0 R 1720 0 R 1722 0 R 1724 0 R 1726 0 R 1728 0 R 1730 0 R 1732 0 R 1734 0 R 1736 0 R 1738 0 R 1740 0 R 1742 0 R 1744 0 R] ->> -endobj -1646 0 obj -<< -/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] -/Font << -/F4 16 0 R -/F3 9 0 R -/F6 44 0 R -/F5 29 0 R ->> ->> -endobj -1645 0 obj -<< -/Length 1153 -/Filter /FlateDecode ->> -stream -xYˮ6+efoMxt!6Z)PmKn9_0c=okiko_ws܉ -E._c/Q]hZ=o84^X#HQ\ f4i4a##V<Їq[xyZ?B~2bbXd:#5sy.pw8>*8J2JF -3g5l%l,na˷cM[ٞeZ<߰+i,=??4 4 ᗺ'caznOV@ -M3$-ʱ?c;̄X渂5װ8 oc)cG/m4O;ctsq$8Gwڤa"=ia?=Nɡ"7Xͥi2Iz -p,wA`Bď]?[i LM )w,w#wOI̘Խ0)~J-3J˝_lJαjz.QUh,PE*\O k>cEJl4-`ܔuY{ -]ЏX |Jx%*Xc!3yY>MlY;qLlJ^WkFxU .6m]y`1uB촞*wІ>BFYΑ0.E8دrWaa$JKZ[PpxX&)?x}w?PPˬz8p8~äg:VD:>npC2v5nJ\*S `}WNf UMO$%q/eeUKvphXi $o ,_]luwkO| Aeb|8*YWsf]?YH ̷+DZFVNK8éy ^U8 f7T&.|&A=Ww[,&R[!C6a(4ipl| - -endstream -endobj -1749 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1750 0 obj -<< -/Subtype /Link -/A 1749 0 R -/Type /Annot -/Rect [72 695.502 223.83 720] -/Border [0 0 0] ->> -endobj -1751 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1752 0 obj -<< -/Subtype /Link -/A 1751 0 R -/Type /Annot -/Rect [72 673.002 468.210938 685.502] -/Border [0 0 0] ->> -endobj -1753 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1754 0 obj -<< -/Subtype /Link -/A 1753 0 R -/Type /Annot -/Rect [468.210938 672.932 492.210938 685.502] -/Border [0 0 0] ->> -endobj -1755 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1756 0 obj -<< -/Subtype /Link -/A 1755 0 R -/Type /Annot -/Rect [492.210938 673.002 539.632813 685.502] -/Border [0 0 0] ->> -endobj -1757 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1758 0 obj -<< -/Subtype /Link -/A 1757 0 R -/Type /Annot -/Rect [72 660.502 309.382813 673.002] -/Border [0 0 0] ->> -endobj -1759 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1760 0 obj -<< -/Subtype /Link -/A 1759 0 R -/Type /Annot -/Rect [309.382813 660.432 387.382813 673.002] -/Border [0 0 0] ->> -endobj -1761 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1762 0 obj -<< -/Subtype /Link -/A 1761 0 R -/Type /Annot -/Rect [387.382813 660.502 520.893555 673.002] -/Border [0 0 0] ->> -endobj -1763 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1764 0 obj -<< -/Subtype /Link -/A 1763 0 R -/Type /Annot -/Rect [72 647.862 96 660.432] -/Border [0 0 0] ->> -endobj -1765 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1766 0 obj -<< -/Subtype /Link -/A 1765 0 R -/Type /Annot -/Rect [96 647.932 145.736328 660.432] -/Border [0 0 0] ->> -endobj -1767 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1768 0 obj -<< -/Subtype /Link -/A 1767 0 R -/Type /Annot -/Rect [145.736328 647.862 181.736328 660.432] -/Border [0 0 0] ->> -endobj -1769 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1770 0 obj -<< -/Subtype /Link -/A 1769 0 R -/Type /Annot -/Rect [181.736328 647.932 521.589844 660.432] -/Border [0 0 0] ->> -endobj -1771 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1772 0 obj -<< -/Subtype /Link -/A 1771 0 R -/Type /Annot -/Rect [72 635.432 112.166016 647.932] -/Border [0 0 0] ->> -endobj -1773 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1774 0 obj -<< -/Subtype /Link -/A 1773 0 R -/Type /Annot -/Rect [112.166016 635.362 190.166016 647.932] -/Border [0 0 0] ->> -endobj -1775 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1776 0 obj -<< -/Subtype /Link -/A 1775 0 R -/Type /Annot -/Rect [190.166016 635.432 536.68457 647.932] -/Border [0 0 0] ->> -endobj -1777 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1778 0 obj -<< -/Subtype /Link -/A 1777 0 R -/Type /Annot -/Rect [72 612.932 521.741211 625.432] -/Border [0 0 0] ->> -endobj -1779 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1780 0 obj -<< -/Subtype /Link -/A 1779 0 R -/Type /Annot -/Rect [72 600.432 289.919922 612.932] -/Border [0 0 0] ->> -endobj -1781 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1782 0 obj -<< -/Subtype /Link -/A 1781 0 R -/Type /Annot -/Rect [72 577.862 126 590.432] -/Border [0 0 0] ->> -endobj -1783 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1784 0 obj -<< -/Subtype /Link -/A 1783 0 R -/Type /Annot -/Rect [72 559.292 114 571.862] -/Border [0 0 0] ->> -endobj -1785 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1786 0 obj -<< -/Subtype /Link -/A 1785 0 R -/Type /Annot -/Rect [72 540.722 120 553.292] -/Border [0 0 0] ->> -endobj -1787 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1788 0 obj -<< -/Subtype /Link -/A 1787 0 R -/Type /Annot -/Rect [72 522.152 132 534.722] -/Border [0 0 0] ->> -endobj -1789 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1790 0 obj -<< -/Subtype /Link -/A 1789 0 R -/Type /Annot -/Rect [72 503.582 96 516.152] -/Border [0 0 0] ->> -endobj -1791 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1792 0 obj -<< -/Subtype /Link -/A 1791 0 R -/Type /Annot -/Rect [72 485.012 126 497.582] -/Border [0 0 0] ->> -endobj -1793 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1794 0 obj -<< -/Subtype /Link -/A 1793 0 R -/Type /Annot -/Rect [72 466.442 138 479.012] -/Border [0 0 0] ->> -endobj -1795 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1796 0 obj -<< -/Subtype /Link -/A 1795 0 R -/Type /Annot -/Rect [72 447.872 114 460.442] -/Border [0 0 0] ->> -endobj -1797 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1798 0 obj -<< -/Subtype /Link -/A 1797 0 R -/Type /Annot -/Rect [72 429.302 138 441.872] -/Border [0 0 0] ->> -endobj -1799 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1800 0 obj -<< -/Subtype /Link -/A 1799 0 R -/Type /Annot -/Rect [72 410.732 150 423.302] -/Border [0 0 0] ->> -endobj -1801 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1802 0 obj -<< -/Subtype /Link -/A 1801 0 R -/Type /Annot -/Rect [72 382.232 455.623047 394.732] -/Border [0 0 0] ->> -endobj -1747 0 obj -<< -/Type /Page -/Parent 1 0 R -/MediaBox [0 0 612 792] -/Contents 1745 0 R -/Resources 1746 0 R -/Annots [1750 0 R 1752 0 R 1754 0 R 1756 0 R 1758 0 R 1760 0 R 1762 0 R 1764 0 R 1766 0 R 1768 0 R 1770 0 R 1772 0 R 1774 0 R 1776 0 R 1778 0 R 1780 0 R 1782 0 R 1784 0 R 1786 0 R 1788 0 R 1790 0 R 1792 0 R 1794 0 R 1796 0 R 1798 0 R 1800 0 R 1802 0 R] ->> -endobj -1746 0 obj -<< -/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] -/Font << -/F4 16 0 R -/F3 9 0 R -/F6 44 0 R ->> ->> -endobj -1745 0 obj -<< -/Length 969 -/Filter /FlateDecode ->> -stream -xXn0+e9U@C譅oE,=@_F6(,⼙f ?n{~c~z솧.ϟ_;Z} v;At萎>.L:Ё[)bCwϻݗWan2Ž٪OGL2p˟cŽ΀.#m?qX{'20@e/S&lkD~(2Nvދ-X o$ֱ-$88NVH7W-cyYU~*kU5h(<)T`tLĘ.G WyBG8:wM &sN8EFs3ϫѪX:\*d vqҰVh3Xs-m!X drŗ Ut9GemBoO kۼx0Oq$.esqE|m2^KC&*W15`>eMAϮת`Ad%\%Ym̳(G? y;z6R]Ъ‚A |< -.ߚKyyvQ/xea^)Ee_cQg^ױS <-smM=GNm̔HE};fpĪ:.AThg ~]_8Ҭͬ -GT<(ʲ5ʺ{|ke=d' ^B2PCA9 -!6 1)ⅉ|nŹpTH|u-:֏U[294HXpGdSUsB_CIDtEYTx ;qۣkST4OoԤ iN0W]/9X] -endstream -endobj -1807 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1808 0 obj -<< -/Subtype /Link -/A 1807 0 R -/Type /Annot -/Rect [72 695.502 230.562 720] -/Border [0 0 0] ->> -endobj -1809 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1810 0 obj -<< -/Subtype /Link -/A 1809 0 R -/Type /Annot -/Rect [72 673.002 93.201172 685.502] -/Border [0 0 0] ->> -endobj -1811 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1812 0 obj -<< -/Subtype /Link -/A 1811 0 R -/Type /Annot -/Rect [93.201172 672.932 135.201172 685.502] -/Border [0 0 0] ->> -endobj -1813 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1814 0 obj -<< -/Subtype /Link -/A 1813 0 R -/Type /Annot -/Rect [135.201172 673.002 158.912109 685.502] -/Border [0 0 0] ->> -endobj -1815 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1816 0 obj -<< -/Subtype /Link -/A 1815 0 R -/Type /Annot -/Rect [158.912109 672.932 206.912109 685.502] -/Border [0 0 0] ->> -endobj -1817 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1818 0 obj -<< -/Subtype /Link -/A 1817 0 R -/Type /Annot -/Rect [206.912109 673.002 535.588867 685.502] -/Border [0 0 0] ->> -endobj -1819 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1820 0 obj -<< -/Subtype /Link -/A 1819 0 R -/Type /Annot -/Rect [72 660.502 236.287109 673.002] -/Border [0 0 0] ->> -endobj -1821 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1822 0 obj -<< -/Subtype /Link -/A 1821 0 R -/Type /Annot -/Rect [72 639.189 390.6 650.502] -/Border [0 0 0] ->> -endobj -1823 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1824 0 obj -<< -/Subtype /Link -/A 1823 0 R -/Type /Annot -/Rect [72 627.876 88.2 639.189] -/Border [0 0 0] ->> -endobj -1825 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1826 0 obj -<< -/Subtype /Link -/A 1825 0 R -/Type /Annot -/Rect [88.2 627.876 93.6 639.189] -/Border [0 0 0] ->> -endobj -1827 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1828 0 obj -<< -/Subtype /Link -/A 1827 0 R -/Type /Annot -/Rect [93.6 627.876 142.2 639.189] -/Border [0 0 0] ->> -endobj -1829 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1830 0 obj -<< -/Subtype /Link -/A 1829 0 R -/Type /Annot -/Rect [142.2 627.876 147.6 639.189] -/Border [0 0 0] ->> -endobj -1831 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1832 0 obj -<< -/Subtype /Link -/A 1831 0 R -/Type /Annot -/Rect [147.6 627.876 158.4 639.189] -/Border [0 0 0] ->> -endobj -1833 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1834 0 obj -<< -/Subtype /Link -/A 1833 0 R -/Type /Annot -/Rect [158.4 627.876 163.8 639.189] -/Border [0 0 0] ->> -endobj -1835 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1836 0 obj -<< -/Subtype /Link -/A 1835 0 R -/Type /Annot -/Rect [163.8 627.876 169.2 639.189] -/Border [0 0 0] ->> -endobj -1837 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1838 0 obj -<< -/Subtype /Link -/A 1837 0 R -/Type /Annot -/Rect [72 605.25 180 616.563] -/Border [0 0 0] ->> -endobj -1839 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1840 0 obj -<< -/Subtype /Link -/A 1839 0 R -/Type /Annot -/Rect [72 593.937 88.2 605.25] -/Border [0 0 0] ->> -endobj -1841 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1842 0 obj -<< -/Subtype /Link -/A 1841 0 R -/Type /Annot -/Rect [88.2 593.937 93.6 605.25] -/Border [0 0 0] ->> -endobj -1843 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1844 0 obj -<< -/Subtype /Link -/A 1843 0 R -/Type /Annot -/Rect [93.6 593.937 131.4 605.25] -/Border [0 0 0] ->> -endobj -1845 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1846 0 obj -<< -/Subtype /Link -/A 1845 0 R -/Type /Annot -/Rect [131.4 593.937 136.8 605.25] -/Border [0 0 0] ->> -endobj -1847 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1848 0 obj -<< -/Subtype /Link -/A 1847 0 R -/Type /Annot -/Rect [136.8 593.937 169.2 605.25] -/Border [0 0 0] ->> -endobj -1849 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1850 0 obj -<< -/Subtype /Link -/A 1849 0 R -/Type /Annot -/Rect [169.2 593.937 174.6 605.25] -/Border [0 0 0] ->> -endobj -1851 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1852 0 obj -<< -/Subtype /Link -/A 1851 0 R -/Type /Annot -/Rect [72 582.624 88.2 593.937] -/Border [0 0 0] ->> -endobj -1853 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1854 0 obj -<< -/Subtype /Link -/A 1853 0 R -/Type /Annot -/Rect [88.2 582.624 93.6 593.937] -/Border [0 0 0] ->> -endobj -1855 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1856 0 obj -<< -/Subtype /Link -/A 1855 0 R -/Type /Annot -/Rect [93.6 582.624 126 593.937] -/Border [0 0 0] ->> -endobj -1857 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1858 0 obj -<< -/Subtype /Link -/A 1857 0 R -/Type /Annot -/Rect [126 582.624 131.4 593.937] -/Border [0 0 0] ->> -endobj -1859 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1860 0 obj -<< -/Subtype /Link -/A 1859 0 R -/Type /Annot -/Rect [131.4 582.624 142.2 593.937] -/Border [0 0 0] ->> -endobj -1861 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1862 0 obj -<< -/Subtype /Link -/A 1861 0 R -/Type /Annot -/Rect [142.2 582.624 147.6 593.937] -/Border [0 0 0] ->> -endobj -1863 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1864 0 obj -<< -/Subtype /Link -/A 1863 0 R -/Type /Annot -/Rect [147.6 582.624 153 593.937] -/Border [0 0 0] ->> -endobj -1865 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1866 0 obj -<< -/Subtype /Link -/A 1865 0 R -/Type /Annot -/Rect [153 582.624 163.8 593.937] -/Border [0 0 0] ->> -endobj -1867 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1868 0 obj -<< -/Subtype /Link -/A 1867 0 R -/Type /Annot -/Rect [163.8 582.624 169.2 593.937] -/Border [0 0 0] ->> -endobj -1869 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1870 0 obj -<< -/Subtype /Link -/A 1869 0 R -/Type /Annot -/Rect [72 571.311 88.2 582.624] -/Border [0 0 0] ->> -endobj -1871 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1872 0 obj -<< -/Subtype /Link -/A 1871 0 R -/Type /Annot -/Rect [88.2 571.311 93.6 582.624] -/Border [0 0 0] ->> -endobj -1873 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1874 0 obj -<< -/Subtype /Link -/A 1873 0 R -/Type /Annot -/Rect [93.6 571.311 126 582.624] -/Border [0 0 0] ->> -endobj -1875 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1876 0 obj -<< -/Subtype /Link -/A 1875 0 R -/Type /Annot -/Rect [126 571.311 131.4 582.624] -/Border [0 0 0] ->> -endobj -1877 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1878 0 obj -<< -/Subtype /Link -/A 1877 0 R -/Type /Annot -/Rect [131.4 571.311 147.6 582.624] -/Border [0 0 0] ->> -endobj -1879 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1880 0 obj -<< -/Subtype /Link -/A 1879 0 R -/Type /Annot -/Rect [147.6 571.311 153 582.624] -/Border [0 0 0] ->> -endobj -1881 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1882 0 obj -<< -/Subtype /Link -/A 1881 0 R -/Type /Annot -/Rect [153 571.311 158.4 582.624] -/Border [0 0 0] ->> -endobj -1883 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1884 0 obj -<< -/Subtype /Link -/A 1883 0 R -/Type /Annot -/Rect [158.4 571.311 169.2 582.624] -/Border [0 0 0] ->> -endobj -1885 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1886 0 obj -<< -/Subtype /Link -/A 1885 0 R -/Type /Annot -/Rect [169.2 571.311 174.6 582.624] -/Border [0 0 0] ->> -endobj -1887 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1888 0 obj -<< -/Subtype /Link -/A 1887 0 R -/Type /Annot -/Rect [72 559.998 88.2 571.311] -/Border [0 0 0] ->> -endobj -1889 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1890 0 obj -<< -/Subtype /Link -/A 1889 0 R -/Type /Annot -/Rect [88.2 559.998 93.6 571.311] -/Border [0 0 0] ->> -endobj -1891 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1892 0 obj -<< -/Subtype /Link -/A 1891 0 R -/Type /Annot -/Rect [93.6 559.998 126 571.311] -/Border [0 0 0] ->> -endobj -1893 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1894 0 obj -<< -/Subtype /Link -/A 1893 0 R -/Type /Annot -/Rect [126 559.998 131.4 571.311] -/Border [0 0 0] ->> -endobj -1895 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1896 0 obj -<< -/Subtype /Link -/A 1895 0 R -/Type /Annot -/Rect [131.4 559.998 136.8 571.311] -/Border [0 0 0] ->> -endobj -1897 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1898 0 obj -<< -/Subtype /Link -/A 1897 0 R -/Type /Annot -/Rect [136.8 559.998 142.2 571.311] -/Border [0 0 0] ->> -endobj -1899 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1900 0 obj -<< -/Subtype /Link -/A 1899 0 R -/Type /Annot -/Rect [72 537.372 88.2 548.685] -/Border [0 0 0] ->> -endobj -1901 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1902 0 obj -<< -/Subtype /Link -/A 1901 0 R -/Type /Annot -/Rect [88.2 537.372 93.6 548.685] -/Border [0 0 0] ->> -endobj -1903 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1904 0 obj -<< -/Subtype /Link -/A 1903 0 R -/Type /Annot -/Rect [93.6 537.372 131.4 548.685] -/Border [0 0 0] ->> -endobj -1905 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1906 0 obj -<< -/Subtype /Link -/A 1905 0 R -/Type /Annot -/Rect [131.4 537.372 136.8 548.685] -/Border [0 0 0] ->> -endobj -1907 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1908 0 obj -<< -/Subtype /Link -/A 1907 0 R -/Type /Annot -/Rect [136.8 537.372 174.6 548.685] -/Border [0 0 0] ->> -endobj -1909 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1910 0 obj -<< -/Subtype /Link -/A 1909 0 R -/Type /Annot -/Rect [174.6 537.372 180 548.685] -/Border [0 0 0] ->> -endobj -1911 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1912 0 obj -<< -/Subtype /Link -/A 1911 0 R -/Type /Annot -/Rect [72 526.059 88.2 537.372] -/Border [0 0 0] ->> -endobj -1913 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1914 0 obj -<< -/Subtype /Link -/A 1913 0 R -/Type /Annot -/Rect [88.2 526.059 93.6 537.372] -/Border [0 0 0] ->> -endobj -1915 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1916 0 obj -<< -/Subtype /Link -/A 1915 0 R -/Type /Annot -/Rect [93.6 526.059 126 537.372] -/Border [0 0 0] ->> -endobj -1917 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1918 0 obj -<< -/Subtype /Link -/A 1917 0 R -/Type /Annot -/Rect [126 526.059 131.4 537.372] -/Border [0 0 0] ->> -endobj -1919 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1920 0 obj -<< -/Subtype /Link -/A 1919 0 R -/Type /Annot -/Rect [131.4 526.059 147.6 537.372] -/Border [0 0 0] ->> -endobj -1921 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1922 0 obj -<< -/Subtype /Link -/A 1921 0 R -/Type /Annot -/Rect [147.6 526.059 153 537.372] -/Border [0 0 0] ->> -endobj -1923 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1924 0 obj -<< -/Subtype /Link -/A 1923 0 R -/Type /Annot -/Rect [153 526.059 158.4 537.372] -/Border [0 0 0] ->> -endobj -1925 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1926 0 obj -<< -/Subtype /Link -/A 1925 0 R -/Type /Annot -/Rect [158.4 526.059 169.2 537.372] -/Border [0 0 0] ->> -endobj -1927 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1928 0 obj -<< -/Subtype /Link -/A 1927 0 R -/Type /Annot -/Rect [169.2 526.059 174.6 537.372] -/Border [0 0 0] ->> -endobj -1929 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1930 0 obj -<< -/Subtype /Link -/A 1929 0 R -/Type /Annot -/Rect [72 514.746 88.2 526.059] -/Border [0 0 0] ->> -endobj -1931 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1932 0 obj -<< -/Subtype /Link -/A 1931 0 R -/Type /Annot -/Rect [88.2 514.746 93.6 526.059] -/Border [0 0 0] ->> -endobj -1933 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1934 0 obj -<< -/Subtype /Link -/A 1933 0 R -/Type /Annot -/Rect [93.6 514.746 126 526.059] -/Border [0 0 0] ->> -endobj -1935 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1936 0 obj -<< -/Subtype /Link -/A 1935 0 R -/Type /Annot -/Rect [126 514.746 131.4 526.059] -/Border [0 0 0] ->> -endobj -1937 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1938 0 obj -<< -/Subtype /Link -/A 1937 0 R -/Type /Annot -/Rect [131.4 514.746 147.6 526.059] -/Border [0 0 0] ->> -endobj -1939 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1940 0 obj -<< -/Subtype /Link -/A 1939 0 R -/Type /Annot -/Rect [147.6 514.746 153 526.059] -/Border [0 0 0] ->> -endobj -1941 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1942 0 obj -<< -/Subtype /Link -/A 1941 0 R -/Type /Annot -/Rect [153 514.746 158.4 526.059] -/Border [0 0 0] ->> -endobj -1943 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1944 0 obj -<< -/Subtype /Link -/A 1943 0 R -/Type /Annot -/Rect [158.4 514.746 169.2 526.059] -/Border [0 0 0] ->> -endobj -1945 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1946 0 obj -<< -/Subtype /Link -/A 1945 0 R -/Type /Annot -/Rect [169.2 514.746 174.6 526.059] -/Border [0 0 0] ->> -endobj -1947 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1948 0 obj -<< -/Subtype /Link -/A 1947 0 R -/Type /Annot -/Rect [72 503.433 88.2 514.746] -/Border [0 0 0] ->> -endobj -1949 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1950 0 obj -<< -/Subtype /Link -/A 1949 0 R -/Type /Annot -/Rect [88.2 503.433 93.6 514.746] -/Border [0 0 0] ->> -endobj -1951 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1952 0 obj -<< -/Subtype /Link -/A 1951 0 R -/Type /Annot -/Rect [93.6 503.433 126 514.746] -/Border [0 0 0] ->> -endobj -1953 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1954 0 obj -<< -/Subtype /Link -/A 1953 0 R -/Type /Annot -/Rect [126 503.433 131.4 514.746] -/Border [0 0 0] ->> -endobj -1955 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1956 0 obj -<< -/Subtype /Link -/A 1955 0 R -/Type /Annot -/Rect [131.4 503.433 136.8 514.746] -/Border [0 0 0] ->> -endobj -1957 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1958 0 obj -<< -/Subtype /Link -/A 1957 0 R -/Type /Annot -/Rect [136.8 503.433 142.2 514.746] -/Border [0 0 0] ->> -endobj -1959 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1960 0 obj -<< -/Subtype /Link -/A 1959 0 R -/Type /Annot -/Rect [72 480.807 471.6 492.12] -/Border [0 0 0] ->> -endobj -1961 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1962 0 obj -<< -/Subtype /Link -/A 1961 0 R -/Type /Annot -/Rect [72 469.494 88.2 480.807] -/Border [0 0 0] ->> -endobj -1963 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1964 0 obj -<< -/Subtype /Link -/A 1963 0 R -/Type /Annot -/Rect [88.2 469.494 93.6 480.807] -/Border [0 0 0] ->> -endobj -1965 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1966 0 obj -<< -/Subtype /Link -/A 1965 0 R -/Type /Annot -/Rect [93.6 469.494 131.4 480.807] -/Border [0 0 0] ->> -endobj -1967 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1968 0 obj -<< -/Subtype /Link -/A 1967 0 R -/Type /Annot -/Rect [131.4 469.494 136.8 480.807] -/Border [0 0 0] ->> -endobj -1969 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1970 0 obj -<< -/Subtype /Link -/A 1969 0 R -/Type /Annot -/Rect [136.8 469.494 180 480.807] -/Border [0 0 0] ->> -endobj -1971 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1972 0 obj -<< -/Subtype /Link -/A 1971 0 R -/Type /Annot -/Rect [180 469.494 185.4 480.807] -/Border [0 0 0] ->> -endobj -1973 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1974 0 obj -<< -/Subtype /Link -/A 1973 0 R -/Type /Annot -/Rect [72 458.181 88.2 469.494] -/Border [0 0 0] ->> -endobj -1975 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1976 0 obj -<< -/Subtype /Link -/A 1975 0 R -/Type /Annot -/Rect [88.2 458.181 93.6 469.494] -/Border [0 0 0] ->> -endobj -1977 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1978 0 obj -<< -/Subtype /Link -/A 1977 0 R -/Type /Annot -/Rect [93.6 458.181 126 469.494] -/Border [0 0 0] ->> -endobj -1979 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1980 0 obj -<< -/Subtype /Link -/A 1979 0 R -/Type /Annot -/Rect [126 458.181 131.4 469.494] -/Border [0 0 0] ->> -endobj -1981 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1982 0 obj -<< -/Subtype /Link -/A 1981 0 R -/Type /Annot -/Rect [131.4 458.181 147.6 469.494] -/Border [0 0 0] ->> -endobj -1983 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1984 0 obj -<< -/Subtype /Link -/A 1983 0 R -/Type /Annot -/Rect [147.6 458.181 153 469.494] -/Border [0 0 0] ->> -endobj -1985 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1986 0 obj -<< -/Subtype /Link -/A 1985 0 R -/Type /Annot -/Rect [153 458.181 158.4 469.494] -/Border [0 0 0] ->> -endobj -1987 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1988 0 obj -<< -/Subtype /Link -/A 1987 0 R -/Type /Annot -/Rect [158.4 458.181 169.2 469.494] -/Border [0 0 0] ->> -endobj -1989 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1990 0 obj -<< -/Subtype /Link -/A 1989 0 R -/Type /Annot -/Rect [169.2 458.181 174.6 469.494] -/Border [0 0 0] ->> -endobj -1991 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1992 0 obj -<< -/Subtype /Link -/A 1991 0 R -/Type /Annot -/Rect [72 446.868 88.2 458.181] -/Border [0 0 0] ->> -endobj -1993 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1994 0 obj -<< -/Subtype /Link -/A 1993 0 R -/Type /Annot -/Rect [88.2 446.868 93.6 458.181] -/Border [0 0 0] ->> -endobj -1995 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1996 0 obj -<< -/Subtype /Link -/A 1995 0 R -/Type /Annot -/Rect [93.6 446.868 126 458.181] -/Border [0 0 0] ->> -endobj -1997 0 obj -<< -/S /URI -/URI (false) ->> -endobj -1998 0 obj -<< -/Subtype /Link -/A 1997 0 R -/Type /Annot -/Rect [126 446.868 131.4 458.181] -/Border [0 0 0] ->> -endobj -1999 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2000 0 obj -<< -/Subtype /Link -/A 1999 0 R -/Type /Annot -/Rect [131.4 446.868 147.6 458.181] -/Border [0 0 0] ->> -endobj -2001 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2002 0 obj -<< -/Subtype /Link -/A 2001 0 R -/Type /Annot -/Rect [147.6 446.868 153 458.181] -/Border [0 0 0] ->> -endobj -2003 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2004 0 obj -<< -/Subtype /Link -/A 2003 0 R -/Type /Annot -/Rect [153 446.868 158.4 458.181] -/Border [0 0 0] ->> -endobj -2005 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2006 0 obj -<< -/Subtype /Link -/A 2005 0 R -/Type /Annot -/Rect [158.4 446.868 169.2 458.181] -/Border [0 0 0] ->> -endobj -2007 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2008 0 obj -<< -/Subtype /Link -/A 2007 0 R -/Type /Annot -/Rect [169.2 446.868 174.6 458.181] -/Border [0 0 0] ->> -endobj -2009 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2010 0 obj -<< -/Subtype /Link -/A 2009 0 R -/Type /Annot -/Rect [174.6 446.868 180 458.181] -/Border [0 0 0] ->> -endobj -2011 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2012 0 obj -<< -/Subtype /Link -/A 2011 0 R -/Type /Annot -/Rect [180 446.868 190.8 458.181] -/Border [0 0 0] ->> -endobj -2013 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2014 0 obj -<< -/Subtype /Link -/A 2013 0 R -/Type /Annot -/Rect [190.8 446.868 196.2 458.181] -/Border [0 0 0] ->> -endobj -2015 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2016 0 obj -<< -/Subtype /Link -/A 2015 0 R -/Type /Annot -/Rect [72 435.555 88.2 446.868] -/Border [0 0 0] ->> -endobj -2017 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2018 0 obj -<< -/Subtype /Link -/A 2017 0 R -/Type /Annot -/Rect [88.2 435.555 93.6 446.868] -/Border [0 0 0] ->> -endobj -2019 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2020 0 obj -<< -/Subtype /Link -/A 2019 0 R -/Type /Annot -/Rect [93.6 435.555 126 446.868] -/Border [0 0 0] ->> -endobj -2021 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2022 0 obj -<< -/Subtype /Link -/A 2021 0 R -/Type /Annot -/Rect [126 435.555 131.4 446.868] -/Border [0 0 0] ->> -endobj -2023 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2024 0 obj -<< -/Subtype /Link -/A 2023 0 R -/Type /Annot -/Rect [131.4 435.555 136.8 446.868] -/Border [0 0 0] ->> -endobj -2025 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2026 0 obj -<< -/Subtype /Link -/A 2025 0 R -/Type /Annot -/Rect [136.8 435.555 142.2 446.868] -/Border [0 0 0] ->> -endobj -2027 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2028 0 obj -<< -/Subtype /Link -/A 2027 0 R -/Type /Annot -/Rect [72 412.929 185.4 424.242] -/Border [0 0 0] ->> -endobj -2029 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2030 0 obj -<< -/Subtype /Link -/A 2029 0 R -/Type /Annot -/Rect [72 401.616 88.2 412.929] -/Border [0 0 0] ->> -endobj -2031 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2032 0 obj -<< -/Subtype /Link -/A 2031 0 R -/Type /Annot -/Rect [88.2 401.616 93.6 412.929] -/Border [0 0 0] ->> -endobj -2033 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2034 0 obj -<< -/Subtype /Link -/A 2033 0 R -/Type /Annot -/Rect [93.6 401.616 136.8 412.929] -/Border [0 0 0] ->> -endobj -2035 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2036 0 obj -<< -/Subtype /Link -/A 2035 0 R -/Type /Annot -/Rect [136.8 401.616 142.2 412.929] -/Border [0 0 0] ->> -endobj -2037 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2038 0 obj -<< -/Subtype /Link -/A 2037 0 R -/Type /Annot -/Rect [142.2 401.616 180 412.929] -/Border [0 0 0] ->> -endobj -2039 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2040 0 obj -<< -/Subtype /Link -/A 2039 0 R -/Type /Annot -/Rect [180 401.616 185.4 412.929] -/Border [0 0 0] ->> -endobj -2041 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2042 0 obj -<< -/Subtype /Link -/A 2041 0 R -/Type /Annot -/Rect [72 390.303 88.2 401.616] -/Border [0 0 0] ->> -endobj -2043 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2044 0 obj -<< -/Subtype /Link -/A 2043 0 R -/Type /Annot -/Rect [88.2 390.303 93.6 401.616] -/Border [0 0 0] ->> -endobj -2045 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2046 0 obj -<< -/Subtype /Link -/A 2045 0 R -/Type /Annot -/Rect [93.6 390.303 115.2 401.616] -/Border [0 0 0] ->> -endobj -2047 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2048 0 obj -<< -/Subtype /Link -/A 2047 0 R -/Type /Annot -/Rect [115.2 390.303 120.6 401.616] -/Border [0 0 0] ->> -endobj -2049 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2050 0 obj -<< -/Subtype /Link -/A 2049 0 R -/Type /Annot -/Rect [120.6 390.303 131.4 401.616] -/Border [0 0 0] ->> -endobj -2051 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2052 0 obj -<< -/Subtype /Link -/A 2051 0 R -/Type /Annot -/Rect [131.4 390.303 136.8 401.616] -/Border [0 0 0] ->> -endobj -2053 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2054 0 obj -<< -/Subtype /Link -/A 2053 0 R -/Type /Annot -/Rect [136.8 390.303 142.2 401.616] -/Border [0 0 0] ->> -endobj -2055 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2056 0 obj -<< -/Subtype /Link -/A 2055 0 R -/Type /Annot -/Rect [142.2 390.303 158.4 401.616] -/Border [0 0 0] ->> -endobj -2057 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2058 0 obj -<< -/Subtype /Link -/A 2057 0 R -/Type /Annot -/Rect [158.4 390.303 163.8 401.616] -/Border [0 0 0] ->> -endobj -2059 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2060 0 obj -<< -/Subtype /Link -/A 2059 0 R -/Type /Annot -/Rect [163.8 390.303 169.2 401.616] -/Border [0 0 0] ->> -endobj -2061 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2062 0 obj -<< -/Subtype /Link -/A 2061 0 R -/Type /Annot -/Rect [169.2 390.303 180 401.616] -/Border [0 0 0] ->> -endobj -2063 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2064 0 obj -<< -/Subtype /Link -/A 2063 0 R -/Type /Annot -/Rect [180 390.303 185.4 401.616] -/Border [0 0 0] ->> -endobj -2065 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2066 0 obj -<< -/Subtype /Link -/A 2065 0 R -/Type /Annot -/Rect [185.4 390.303 190.8 401.616] -/Border [0 0 0] ->> -endobj -2067 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2068 0 obj -<< -/Subtype /Link -/A 2067 0 R -/Type /Annot -/Rect [190.8 390.303 201.6 401.616] -/Border [0 0 0] ->> -endobj -2069 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2070 0 obj -<< -/Subtype /Link -/A 2069 0 R -/Type /Annot -/Rect [201.6 390.303 207 401.616] -/Border [0 0 0] ->> -endobj -2071 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2072 0 obj -<< -/Subtype /Link -/A 2071 0 R -/Type /Annot -/Rect [72 378.99 88.2 390.303] -/Border [0 0 0] ->> -endobj -2073 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2074 0 obj -<< -/Subtype /Link -/A 2073 0 R -/Type /Annot -/Rect [88.2 378.99 93.6 390.303] -/Border [0 0 0] ->> -endobj -2075 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2076 0 obj -<< -/Subtype /Link -/A 2075 0 R -/Type /Annot -/Rect [93.6 378.99 126 390.303] -/Border [0 0 0] ->> -endobj -2077 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2078 0 obj -<< -/Subtype /Link -/A 2077 0 R -/Type /Annot -/Rect [126 378.99 131.4 390.303] -/Border [0 0 0] ->> -endobj -2079 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2080 0 obj -<< -/Subtype /Link -/A 2079 0 R -/Type /Annot -/Rect [131.4 378.99 136.8 390.303] -/Border [0 0 0] ->> -endobj -2081 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2082 0 obj -<< -/Subtype /Link -/A 2081 0 R -/Type /Annot -/Rect [136.8 378.99 142.2 390.303] -/Border [0 0 0] ->> -endobj -2083 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2084 0 obj -<< -/Subtype /Link -/A 2083 0 R -/Type /Annot -/Rect [72 356.364 88.2 367.677] -/Border [0 0 0] ->> -endobj -2085 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2086 0 obj -<< -/Subtype /Link -/A 2085 0 R -/Type /Annot -/Rect [88.2 356.364 93.6 367.677] -/Border [0 0 0] ->> -endobj -2087 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2088 0 obj -<< -/Subtype /Link -/A 2087 0 R -/Type /Annot -/Rect [93.6 356.364 136.8 367.677] -/Border [0 0 0] ->> -endobj -2089 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2090 0 obj -<< -/Subtype /Link -/A 2089 0 R -/Type /Annot -/Rect [136.8 356.364 142.2 367.677] -/Border [0 0 0] ->> -endobj -2091 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2092 0 obj -<< -/Subtype /Link -/A 2091 0 R -/Type /Annot -/Rect [142.2 356.364 180 367.677] -/Border [0 0 0] ->> -endobj -2093 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2094 0 obj -<< -/Subtype /Link -/A 2093 0 R -/Type /Annot -/Rect [180 356.364 185.4 367.677] -/Border [0 0 0] ->> -endobj -2095 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2096 0 obj -<< -/Subtype /Link -/A 2095 0 R -/Type /Annot -/Rect [72 345.051 88.2 356.364] -/Border [0 0 0] ->> -endobj -2097 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2098 0 obj -<< -/Subtype /Link -/A 2097 0 R -/Type /Annot -/Rect [88.2 345.051 93.6 356.364] -/Border [0 0 0] ->> -endobj -2099 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2100 0 obj -<< -/Subtype /Link -/A 2099 0 R -/Type /Annot -/Rect [93.6 345.051 115.2 356.364] -/Border [0 0 0] ->> -endobj -2101 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2102 0 obj -<< -/Subtype /Link -/A 2101 0 R -/Type /Annot -/Rect [115.2 345.051 120.6 356.364] -/Border [0 0 0] ->> -endobj -2103 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2104 0 obj -<< -/Subtype /Link -/A 2103 0 R -/Type /Annot -/Rect [120.6 345.051 136.8 356.364] -/Border [0 0 0] ->> -endobj -2105 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2106 0 obj -<< -/Subtype /Link -/A 2105 0 R -/Type /Annot -/Rect [136.8 345.051 142.2 356.364] -/Border [0 0 0] ->> -endobj -2107 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2108 0 obj -<< -/Subtype /Link -/A 2107 0 R -/Type /Annot -/Rect [142.2 345.051 147.6 356.364] -/Border [0 0 0] ->> -endobj -2109 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2110 0 obj -<< -/Subtype /Link -/A 2109 0 R -/Type /Annot -/Rect [147.6 345.051 163.8 356.364] -/Border [0 0 0] ->> -endobj -2111 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2112 0 obj -<< -/Subtype /Link -/A 2111 0 R -/Type /Annot -/Rect [163.8 345.051 169.2 356.364] -/Border [0 0 0] ->> -endobj -2113 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2114 0 obj -<< -/Subtype /Link -/A 2113 0 R -/Type /Annot -/Rect [169.2 345.051 174.6 356.364] -/Border [0 0 0] ->> -endobj -2115 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2116 0 obj -<< -/Subtype /Link -/A 2115 0 R -/Type /Annot -/Rect [174.6 345.051 185.4 356.364] -/Border [0 0 0] ->> -endobj -2117 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2118 0 obj -<< -/Subtype /Link -/A 2117 0 R -/Type /Annot -/Rect [185.4 345.051 190.8 356.364] -/Border [0 0 0] ->> -endobj -2119 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2120 0 obj -<< -/Subtype /Link -/A 2119 0 R -/Type /Annot -/Rect [190.8 345.051 196.2 356.364] -/Border [0 0 0] ->> -endobj -2121 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2122 0 obj -<< -/Subtype /Link -/A 2121 0 R -/Type /Annot -/Rect [196.2 345.051 207 356.364] -/Border [0 0 0] ->> -endobj -2123 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2124 0 obj -<< -/Subtype /Link -/A 2123 0 R -/Type /Annot -/Rect [207 345.051 212.4 356.364] -/Border [0 0 0] ->> -endobj -2125 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2126 0 obj -<< -/Subtype /Link -/A 2125 0 R -/Type /Annot -/Rect [72 333.738 88.2 345.051] -/Border [0 0 0] ->> -endobj -2127 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2128 0 obj -<< -/Subtype /Link -/A 2127 0 R -/Type /Annot -/Rect [88.2 333.738 93.6 345.051] -/Border [0 0 0] ->> -endobj -2129 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2130 0 obj -<< -/Subtype /Link -/A 2129 0 R -/Type /Annot -/Rect [93.6 333.738 126 345.051] -/Border [0 0 0] ->> -endobj -2131 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2132 0 obj -<< -/Subtype /Link -/A 2131 0 R -/Type /Annot -/Rect [126 333.738 131.4 345.051] -/Border [0 0 0] ->> -endobj -2133 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2134 0 obj -<< -/Subtype /Link -/A 2133 0 R -/Type /Annot -/Rect [131.4 333.738 136.8 345.051] -/Border [0 0 0] ->> -endobj -2135 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2136 0 obj -<< -/Subtype /Link -/A 2135 0 R -/Type /Annot -/Rect [136.8 333.738 142.2 345.051] -/Border [0 0 0] ->> -endobj -2137 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2138 0 obj -<< -/Subtype /Link -/A 2137 0 R -/Type /Annot -/Rect [72 311.112 88.2 322.425] -/Border [0 0 0] ->> -endobj -2139 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2140 0 obj -<< -/Subtype /Link -/A 2139 0 R -/Type /Annot -/Rect [88.2 311.112 93.6 322.425] -/Border [0 0 0] ->> -endobj -2141 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2142 0 obj -<< -/Subtype /Link -/A 2141 0 R -/Type /Annot -/Rect [93.6 311.112 136.8 322.425] -/Border [0 0 0] ->> -endobj -2143 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2144 0 obj -<< -/Subtype /Link -/A 2143 0 R -/Type /Annot -/Rect [136.8 311.112 142.2 322.425] -/Border [0 0 0] ->> -endobj -2145 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2146 0 obj -<< -/Subtype /Link -/A 2145 0 R -/Type /Annot -/Rect [142.2 311.112 180 322.425] -/Border [0 0 0] ->> -endobj -2147 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2148 0 obj -<< -/Subtype /Link -/A 2147 0 R -/Type /Annot -/Rect [180 311.112 185.4 322.425] -/Border [0 0 0] ->> -endobj -2149 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2150 0 obj -<< -/Subtype /Link -/A 2149 0 R -/Type /Annot -/Rect [72 299.799 88.2 311.112] -/Border [0 0 0] ->> -endobj -2151 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2152 0 obj -<< -/Subtype /Link -/A 2151 0 R -/Type /Annot -/Rect [88.2 299.799 93.6 311.112] -/Border [0 0 0] ->> -endobj -2153 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2154 0 obj -<< -/Subtype /Link -/A 2153 0 R -/Type /Annot -/Rect [93.6 299.799 115.2 311.112] -/Border [0 0 0] ->> -endobj -2155 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2156 0 obj -<< -/Subtype /Link -/A 2155 0 R -/Type /Annot -/Rect [115.2 299.799 120.6 311.112] -/Border [0 0 0] ->> -endobj -2157 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2158 0 obj -<< -/Subtype /Link -/A 2157 0 R -/Type /Annot -/Rect [120.6 299.799 136.8 311.112] -/Border [0 0 0] ->> -endobj -2159 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2160 0 obj -<< -/Subtype /Link -/A 2159 0 R -/Type /Annot -/Rect [136.8 299.799 142.2 311.112] -/Border [0 0 0] ->> -endobj -2161 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2162 0 obj -<< -/Subtype /Link -/A 2161 0 R -/Type /Annot -/Rect [142.2 299.799 147.6 311.112] -/Border [0 0 0] ->> -endobj -2163 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2164 0 obj -<< -/Subtype /Link -/A 2163 0 R -/Type /Annot -/Rect [147.6 299.799 163.8 311.112] -/Border [0 0 0] ->> -endobj -2165 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2166 0 obj -<< -/Subtype /Link -/A 2165 0 R -/Type /Annot -/Rect [163.8 299.799 169.2 311.112] -/Border [0 0 0] ->> -endobj -2167 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2168 0 obj -<< -/Subtype /Link -/A 2167 0 R -/Type /Annot -/Rect [169.2 299.799 174.6 311.112] -/Border [0 0 0] ->> -endobj -2169 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2170 0 obj -<< -/Subtype /Link -/A 2169 0 R -/Type /Annot -/Rect [174.6 299.799 185.4 311.112] -/Border [0 0 0] ->> -endobj -2171 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2172 0 obj -<< -/Subtype /Link -/A 2171 0 R -/Type /Annot -/Rect [185.4 299.799 190.8 311.112] -/Border [0 0 0] ->> -endobj -2173 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2174 0 obj -<< -/Subtype /Link -/A 2173 0 R -/Type /Annot -/Rect [190.8 299.799 196.2 311.112] -/Border [0 0 0] ->> -endobj -2175 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2176 0 obj -<< -/Subtype /Link -/A 2175 0 R -/Type /Annot -/Rect [196.2 299.799 207 311.112] -/Border [0 0 0] ->> -endobj -2177 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2178 0 obj -<< -/Subtype /Link -/A 2177 0 R -/Type /Annot -/Rect [207 299.799 212.4 311.112] -/Border [0 0 0] ->> -endobj -2179 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2180 0 obj -<< -/Subtype /Link -/A 2179 0 R -/Type /Annot -/Rect [72 288.486 88.2 299.799] -/Border [0 0 0] ->> -endobj -2181 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2182 0 obj -<< -/Subtype /Link -/A 2181 0 R -/Type /Annot -/Rect [88.2 288.486 93.6 299.799] -/Border [0 0 0] ->> -endobj -2183 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2184 0 obj -<< -/Subtype /Link -/A 2183 0 R -/Type /Annot -/Rect [93.6 288.486 126 299.799] -/Border [0 0 0] ->> -endobj -2185 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2186 0 obj -<< -/Subtype /Link -/A 2185 0 R -/Type /Annot -/Rect [126 288.486 131.4 299.799] -/Border [0 0 0] ->> -endobj -2187 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2188 0 obj -<< -/Subtype /Link -/A 2187 0 R -/Type /Annot -/Rect [131.4 288.486 136.8 299.799] -/Border [0 0 0] ->> -endobj -2189 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2190 0 obj -<< -/Subtype /Link -/A 2189 0 R -/Type /Annot -/Rect [136.8 288.486 142.2 299.799] -/Border [0 0 0] ->> -endobj -2191 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2192 0 obj -<< -/Subtype /Link -/A 2191 0 R -/Type /Annot -/Rect [72 265.986 282.390625 278.486] -/Border [0 0 0] ->> -endobj -1805 0 obj -<< -/Type /Page -/Parent 1 0 R -/MediaBox [0 0 612 792] -/Contents 1803 0 R -/Resources 1804 0 R -/Annots [1808 0 R 1810 0 R 1812 0 R 1814 0 R 1816 0 R 1818 0 R 1820 0 R 1822 0 R 1824 0 R 1826 0 R 1828 0 R 1830 0 R 1832 0 R 1834 0 R 1836 0 R 1838 0 R 1840 0 R 1842 0 R 1844 0 R 1846 0 R 1848 0 R 1850 0 R 1852 0 R 1854 0 R 1856 0 R 1858 0 R 1860 0 R 1862 0 R 1864 0 R 1866 0 R 1868 0 R 1870 0 R 1872 0 R 1874 0 R 1876 0 R 1878 0 R 1880 0 R 1882 0 R 1884 0 R 1886 0 R 1888 0 R 1890 0 R 1892 0 R 1894 0 R 1896 0 R 1898 0 R 1900 0 R 1902 0 R 1904 0 R 1906 0 R 1908 0 R 1910 0 R 1912 0 R 1914 0 R 1916 0 R 1918 0 R 1920 0 R 1922 0 R 1924 0 R 1926 0 R 1928 0 R 1930 0 R 1932 0 R 1934 0 R 1936 0 R 1938 0 R 1940 0 R 1942 0 R 1944 0 R 1946 0 R 1948 0 R 1950 0 R 1952 0 R 1954 0 R 1956 0 R 1958 0 R 1960 0 R 1962 0 R 1964 0 R 1966 0 R 1968 0 R 1970 0 R 1972 0 R 1974 0 R 1976 0 R 1978 0 R 1980 0 R 1982 0 R 1984 0 R 1986 0 R 1988 0 R 1990 0 R 1992 0 R 1994 0 R 1996 0 R 1998 0 R 2000 0 R 2002 0 R 2004 0 R 2006 0 R 2008 0 R 2010 0 R 2012 0 R 2014 0 R 2016 0 R 2018 0 R 2020 0 R 2022 0 R 2024 0 R 2026 0 R 2028 0 R 2030 0 R 2032 0 R 2034 0 R 2036 0 R 2038 0 R 2040 0 R 2042 0 R 2044 0 R 2046 0 R 2048 0 R 2050 0 R 2052 0 R 2054 0 R 2056 0 R 2058 0 R 2060 0 R 2062 0 R 2064 0 R 2066 0 R 2068 0 R 2070 0 R 2072 0 R 2074 0 R 2076 0 R 2078 0 R 2080 0 R 2082 0 R 2084 0 R 2086 0 R 2088 0 R 2090 0 R 2092 0 R 2094 0 R 2096 0 R 2098 0 R 2100 0 R 2102 0 R 2104 0 R 2106 0 R 2108 0 R 2110 0 R 2112 0 R 2114 0 R 2116 0 R 2118 0 R 2120 0 R 2122 0 R 2124 0 R 2126 0 R 2128 0 R 2130 0 R 2132 0 R 2134 0 R 2136 0 R 2138 0 R 2140 0 R 2142 0 R 2144 0 R 2146 0 R 2148 0 R 2150 0 R 2152 0 R 2154 0 R 2156 0 R 2158 0 R 2160 0 R 2162 0 R 2164 0 R 2166 0 R 2168 0 R 2170 0 R 2172 0 R 2174 0 R 2176 0 R 2178 0 R 2180 0 R 2182 0 R 2184 0 R 2186 0 R 2188 0 R 2190 0 R 2192 0 R] ->> -endobj -1804 0 obj -<< -/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] -/Font << -/F4 16 0 R -/F3 9 0 R -/F6 44 0 R -/F5 29 0 R ->> ->> -endobj -1803 0 obj -<< -/Length 2045 -/Filter /FlateDecode ->> -stream -x]ˎ6+e&Y}٥]Ō=6h -/_Gv:4Nⱆ{u(Y OҸz*{#e[Zf 6=l޿u 2vU6&JEkb2T5B=hTzmoCY$Q ns[NԪx6 -)x{Ul@!P_!۲]ƚ VwHKy6m:ϥt},f<߫ -_t)}<vW:*f/i^J}\E^ yʤD_I(l!:U?`Vu3{k~ɯ#jSE㻒aIoI5S;=?i%ɧ8#ًPck3>6|\RP&Y^*#G>~tQ8{\X2f{DaPN=r1Z|(m$X*,ZαS;nGn}}1Y}2JU^1ݼ_Wg:*SfRM 2Thy!j*$jKnDڬ2o~"nImlɝĕsN؇0ŹU@]!v]DR WϮ+%>w@5<QDԕL>E;J'uqofwe>Ak[9ŜQ;XI''*jjv>ẄtTDy靟csųicx!J?%Zc.tU<5k"(ǂ2NwNy9.&6"i)iy ԋ1gjq~ jjpDzA|F@;)~q3#98AS#Vx1/\V&R<XIWkd#P6|+Ҋ粺RܰbKNӪQ=wb|餾K8-߯& ?8^tMi'h.\ϥI!8j IZH: FN<)51µliM}1WbF$' _KN^?Dxyچw/ŭFȔ\}XIO*⫵vϹdx:+tƊIw|VeX}\i~CS%3IO]iDs|u9@']c9F*^.f CۈEܐ9-!tc/f CeЍ0A;wexz>8H2v}簗ߟt9O/=98?Qjy> !IA8wpe.u.%p} 1G#`j #ty ,7Ce0A;wdxq ߟ#)pzs~sSv- 7<: !IA8sqt!+Ap;0Qw|In|ٶ^tiC2-|dC៰ۻAPu}S8Fr9P.6DGuC/4NW[73m)^K'RxtȘj -; _;8Dtij ۣCl׀bbLsۇԷbyͿ5z -endstream -endobj -2197 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2198 0 obj -<< -/Subtype /Link -/A 2197 0 R -/Type /Annot -/Rect [72 695.502 167.292 720] -/Border [0 0 0] ->> -endobj -2199 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2200 0 obj -<< -/Subtype /Link -/A 2199 0 R -/Type /Annot -/Rect [72 673.002 93.201172 685.502] -/Border [0 0 0] ->> -endobj -2201 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2202 0 obj -<< -/Subtype /Link -/A 2201 0 R -/Type /Annot -/Rect [93.201172 672.932 117.201172 685.502] -/Border [0 0 0] ->> -endobj -2203 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2204 0 obj -<< -/Subtype /Link -/A 2203 0 R -/Type /Annot -/Rect [117.201172 673.002 497.918945 685.502] -/Border [0 0 0] ->> -endobj -2205 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2206 0 obj -<< -/Subtype /Link -/A 2205 0 R -/Type /Annot -/Rect [72 660.502 490.242188 673.002] -/Border [0 0 0] ->> -endobj -2207 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2208 0 obj -<< -/Subtype /Link -/A 2207 0 R -/Type /Annot -/Rect [72 648.002 179.592773 660.502] -/Border [0 0 0] ->> -endobj -2209 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2210 0 obj -<< -/Subtype /Link -/A 2209 0 R -/Type /Annot -/Rect [179.592773 647.932 209.592773 660.502] -/Border [0 0 0] ->> -endobj -2211 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2212 0 obj -<< -/Subtype /Link -/A 2211 0 R -/Type /Annot -/Rect [209.592773 648.002 233.303711 660.502] -/Border [0 0 0] ->> -endobj -2213 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2214 0 obj -<< -/Subtype /Link -/A 2213 0 R -/Type /Annot -/Rect [233.303711 647.932 263.303711 660.502] -/Border [0 0 0] ->> -endobj -2215 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2216 0 obj -<< -/Subtype /Link -/A 2215 0 R -/Type /Annot -/Rect [263.303711 648.002 266.750977 660.502] -/Border [0 0 0] ->> -endobj -2217 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2218 0 obj -<< -/Subtype /Link -/A 2217 0 R -/Type /Annot -/Rect [72 625.502 93.201172 638.002] -/Border [0 0 0] ->> -endobj -2219 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2220 0 obj -<< -/Subtype /Link -/A 2219 0 R -/Type /Annot -/Rect [93.201172 625.432 123.201172 638.002] -/Border [0 0 0] ->> -endobj -2221 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2222 0 obj -<< -/Subtype /Link -/A 2221 0 R -/Type /Annot -/Rect [123.201172 625.502 457.742188 638.002] -/Border [0 0 0] ->> -endobj -2223 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2224 0 obj -<< -/Subtype /Link -/A 2223 0 R -/Type /Annot -/Rect [457.742188 625.432 487.742188 638.002] -/Border [0 0 0] ->> -endobj -2225 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2226 0 obj -<< -/Subtype /Link -/A 2225 0 R -/Type /Annot -/Rect [487.742188 625.502 525.696289 638.002] -/Border [0 0 0] ->> -endobj -2227 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2228 0 obj -<< -/Subtype /Link -/A 2227 0 R -/Type /Annot -/Rect [72 613.002 408.064453 625.502] -/Border [0 0 0] ->> -endobj -2229 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2230 0 obj -<< -/Subtype /Link -/A 2229 0 R -/Type /Annot -/Rect [408.064453 612.932 438.064453 625.502] -/Border [0 0 0] ->> -endobj -2231 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2232 0 obj -<< -/Subtype /Link -/A 2231 0 R -/Type /Annot -/Rect [438.064453 613.002 527.825195 625.502] -/Border [0 0 0] ->> -endobj -2233 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2234 0 obj -<< -/Subtype /Link -/A 2233 0 R -/Type /Annot -/Rect [72 600.502 103.982422 613.002] -/Border [0 0 0] ->> -endobj -2235 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2236 0 obj -<< -/Subtype /Link -/A 2235 0 R -/Type /Annot -/Rect [103.982422 600.432 139.982422 613.002] -/Border [0 0 0] ->> -endobj -2237 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2238 0 obj -<< -/Subtype /Link -/A 2237 0 R -/Type /Annot -/Rect [139.982422 600.502 182.902344 613.002] -/Border [0 0 0] ->> -endobj -2239 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2240 0 obj -<< -/Subtype /Link -/A 2239 0 R -/Type /Annot -/Rect [182.902344 600.432 212.902344 613.002] -/Border [0 0 0] ->> -endobj -2241 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2242 0 obj -<< -/Subtype /Link -/A 2241 0 R -/Type /Annot -/Rect [212.902344 600.502 303.390625 613.002] -/Border [0 0 0] ->> -endobj -2243 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2244 0 obj -<< -/Subtype /Link -/A 2243 0 R -/Type /Annot -/Rect [303.390625 600.432 309.390625 613.002] -/Border [0 0 0] ->> -endobj -2245 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2246 0 obj -<< -/Subtype /Link -/A 2245 0 R -/Type /Annot -/Rect [309.390625 600.502 395.708984 613.002] -/Border [0 0 0] ->> -endobj -2247 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2248 0 obj -<< -/Subtype /Link -/A 2247 0 R -/Type /Annot -/Rect [395.708984 600.432 431.708984 613.002] -/Border [0 0 0] ->> -endobj -2249 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2250 0 obj -<< -/Subtype /Link -/A 2249 0 R -/Type /Annot -/Rect [431.708984 600.502 537.832031 613.002] -/Border [0 0 0] ->> -endobj -2251 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2252 0 obj -<< -/Subtype /Link -/A 2251 0 R -/Type /Annot -/Rect [72 588.002 150.979492 600.502] -/Border [0 0 0] ->> -endobj -2253 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2254 0 obj -<< -/Subtype /Link -/A 2253 0 R -/Type /Annot -/Rect [72 565.502 535.115234 578.002] -/Border [0 0 0] ->> -endobj -2255 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2256 0 obj -<< -/Subtype /Link -/A 2255 0 R -/Type /Annot -/Rect [72 553.002 239.314453 565.502] -/Border [0 0 0] ->> -endobj -2257 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2258 0 obj -<< -/Subtype /Link -/A 2257 0 R -/Type /Annot -/Rect [72 531.689 88.2 543.002] -/Border [0 0 0] ->> -endobj -2259 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2260 0 obj -<< -/Subtype /Link -/A 2259 0 R -/Type /Annot -/Rect [88.2 531.689 93.6 543.002] -/Border [0 0 0] ->> -endobj -2261 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2262 0 obj -<< -/Subtype /Link -/A 2261 0 R -/Type /Annot -/Rect [93.6 531.689 126 543.002] -/Border [0 0 0] ->> -endobj -2263 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2264 0 obj -<< -/Subtype /Link -/A 2263 0 R -/Type /Annot -/Rect [126 531.689 131.4 543.002] -/Border [0 0 0] ->> -endobj -2265 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2266 0 obj -<< -/Subtype /Link -/A 2265 0 R -/Type /Annot -/Rect [131.4 531.689 147.6 543.002] -/Border [0 0 0] ->> -endobj -2267 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2268 0 obj -<< -/Subtype /Link -/A 2267 0 R -/Type /Annot -/Rect [147.6 531.689 153 543.002] -/Border [0 0 0] ->> -endobj -2269 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2270 0 obj -<< -/Subtype /Link -/A 2269 0 R -/Type /Annot -/Rect [153 531.689 158.4 543.002] -/Border [0 0 0] ->> -endobj -2271 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2272 0 obj -<< -/Subtype /Link -/A 2271 0 R -/Type /Annot -/Rect [158.4 531.689 169.2 543.002] -/Border [0 0 0] ->> -endobj -2273 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2274 0 obj -<< -/Subtype /Link -/A 2273 0 R -/Type /Annot -/Rect [169.2 531.689 174.6 543.002] -/Border [0 0 0] ->> -endobj -2275 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2276 0 obj -<< -/Subtype /Link -/A 2275 0 R -/Type /Annot -/Rect [174.6 531.689 180 543.002] -/Border [0 0 0] ->> -endobj -2277 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2278 0 obj -<< -/Subtype /Link -/A 2277 0 R -/Type /Annot -/Rect [180 531.689 190.8 543.002] -/Border [0 0 0] ->> -endobj -2279 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2280 0 obj -<< -/Subtype /Link -/A 2279 0 R -/Type /Annot -/Rect [190.8 531.689 196.2 543.002] -/Border [0 0 0] ->> -endobj -2281 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2282 0 obj -<< -/Subtype /Link -/A 2281 0 R -/Type /Annot -/Rect [72 520.376 88.2 531.689] -/Border [0 0 0] ->> -endobj -2283 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2284 0 obj -<< -/Subtype /Link -/A 2283 0 R -/Type /Annot -/Rect [88.2 520.376 93.6 531.689] -/Border [0 0 0] ->> -endobj -2285 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2286 0 obj -<< -/Subtype /Link -/A 2285 0 R -/Type /Annot -/Rect [93.6 520.376 115.2 531.689] -/Border [0 0 0] ->> -endobj -2287 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2288 0 obj -<< -/Subtype /Link -/A 2287 0 R -/Type /Annot -/Rect [115.2 520.376 120.6 531.689] -/Border [0 0 0] ->> -endobj -2289 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2290 0 obj -<< -/Subtype /Link -/A 2289 0 R -/Type /Annot -/Rect [120.6 520.376 126 531.689] -/Border [0 0 0] ->> -endobj -2291 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2292 0 obj -<< -/Subtype /Link -/A 2291 0 R -/Type /Annot -/Rect [126 520.376 131.4 531.689] -/Border [0 0 0] ->> -endobj -2293 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2294 0 obj -<< -/Subtype /Link -/A 2293 0 R -/Type /Annot -/Rect [131.4 520.376 136.8 531.689] -/Border [0 0 0] ->> -endobj -2295 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2296 0 obj -<< -/Subtype /Link -/A 2295 0 R -/Type /Annot -/Rect [136.8 520.376 142.2 531.689] -/Border [0 0 0] ->> -endobj -2297 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2298 0 obj -<< -/Subtype /Link -/A 2297 0 R -/Type /Annot -/Rect [142.2 520.376 169.2 531.689] -/Border [0 0 0] ->> -endobj -2299 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2300 0 obj -<< -/Subtype /Link -/A 2299 0 R -/Type /Annot -/Rect [169.2 520.376 174.6 531.689] -/Border [0 0 0] ->> -endobj -2301 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2302 0 obj -<< -/Subtype /Link -/A 2301 0 R -/Type /Annot -/Rect [174.6 520.376 180 531.689] -/Border [0 0 0] ->> -endobj -2303 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2304 0 obj -<< -/Subtype /Link -/A 2303 0 R -/Type /Annot -/Rect [180 520.376 190.8 531.689] -/Border [0 0 0] ->> -endobj -2305 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2306 0 obj -<< -/Subtype /Link -/A 2305 0 R -/Type /Annot -/Rect [190.8 520.376 196.2 531.689] -/Border [0 0 0] ->> -endobj -2307 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2308 0 obj -<< -/Subtype /Link -/A 2307 0 R -/Type /Annot -/Rect [196.2 520.376 201.6 531.689] -/Border [0 0 0] ->> -endobj -2309 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2310 0 obj -<< -/Subtype /Link -/A 2309 0 R -/Type /Annot -/Rect [72 509.063 88.2 520.376] -/Border [0 0 0] ->> -endobj -2311 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2312 0 obj -<< -/Subtype /Link -/A 2311 0 R -/Type /Annot -/Rect [88.2 509.063 93.6 520.376] -/Border [0 0 0] ->> -endobj -2313 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2314 0 obj -<< -/Subtype /Link -/A 2313 0 R -/Type /Annot -/Rect [93.6 509.063 126 520.376] -/Border [0 0 0] ->> -endobj -2315 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2316 0 obj -<< -/Subtype /Link -/A 2315 0 R -/Type /Annot -/Rect [126 509.063 131.4 520.376] -/Border [0 0 0] ->> -endobj -2317 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2318 0 obj -<< -/Subtype /Link -/A 2317 0 R -/Type /Annot -/Rect [131.4 509.063 136.8 520.376] -/Border [0 0 0] ->> -endobj -2319 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2320 0 obj -<< -/Subtype /Link -/A 2319 0 R -/Type /Annot -/Rect [136.8 509.063 142.2 520.376] -/Border [0 0 0] ->> -endobj -2321 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2322 0 obj -<< -/Subtype /Link -/A 2321 0 R -/Type /Annot -/Rect [72 486.563 282.390625 499.063] -/Border [0 0 0] ->> -endobj -2195 0 obj -<< -/Type /Page -/Parent 1 0 R -/MediaBox [0 0 612 792] -/Contents 2193 0 R -/Resources 2194 0 R -/Annots [2198 0 R 2200 0 R 2202 0 R 2204 0 R 2206 0 R 2208 0 R 2210 0 R 2212 0 R 2214 0 R 2216 0 R 2218 0 R 2220 0 R 2222 0 R 2224 0 R 2226 0 R 2228 0 R 2230 0 R 2232 0 R 2234 0 R 2236 0 R 2238 0 R 2240 0 R 2242 0 R 2244 0 R 2246 0 R 2248 0 R 2250 0 R 2252 0 R 2254 0 R 2256 0 R 2258 0 R 2260 0 R 2262 0 R 2264 0 R 2266 0 R 2268 0 R 2270 0 R 2272 0 R 2274 0 R 2276 0 R 2278 0 R 2280 0 R 2282 0 R 2284 0 R 2286 0 R 2288 0 R 2290 0 R 2292 0 R 2294 0 R 2296 0 R 2298 0 R 2300 0 R 2302 0 R 2304 0 R 2306 0 R 2308 0 R 2310 0 R 2312 0 R 2314 0 R 2316 0 R 2318 0 R 2320 0 R 2322 0 R] ->> -endobj -2194 0 obj -<< -/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] -/Font << -/F4 16 0 R -/F3 9 0 R -/F6 44 0 R -/F5 29 0 R ->> ->> -endobj -2193 0 obj -<< -/Length 1339 -/Filter /FlateDecode ->> -stream -xZK6W 9xe!RD٢Vvdm@kY"9|3w4?tswmkwO7c?Cl-PXZt||nÍ@ɟ',?S.?GOC7@2$C-BD`Bᶐ ^2 -˜ă)Vo!R+KSO|T;ҿsPc2gƞ]=FuQ8&M8 YKZO&^ƹQVsLﺴvk.e]:0+p0#e=>6Ĩ.$",cfe)WgV/#{uld֏IFަ{t˖̖=s#+lG=:d]apQD$ (!4%Asd'[/'k%}nB2A![7m"YJ!AZĺA_cHgSH|* OMB,s":M KA> -endobj -2328 0 obj -<< -/Subtype /Link -/A 2327 0 R -/Type /Annot -/Rect [72 695.502 113.148 720] -/Border [0 0 0] ->> -endobj -2329 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2330 0 obj -<< -/Subtype /Link -/A 2329 0 R -/Type /Annot -/Rect [72 673.002 527.424805 685.502] -/Border [0 0 0] ->> -endobj -2331 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2332 0 obj -<< -/Subtype /Link -/A 2331 0 R -/Type /Annot -/Rect [72 660.502 538.845703 673.002] -/Border [0 0 0] ->> -endobj -2333 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2334 0 obj -<< -/Subtype /Link -/A 2333 0 R -/Type /Annot -/Rect [72 648.002 195.759766 660.502] -/Border [0 0 0] ->> -endobj -2335 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2336 0 obj -<< -/Subtype /Link -/A 2335 0 R -/Type /Annot -/Rect [72 625.502 93.201172 638.002] -/Border [0 0 0] ->> -endobj -2337 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2338 0 obj -<< -/Subtype /Link -/A 2337 0 R -/Type /Annot -/Rect [93.201172 625.432 147.201172 638.002] -/Border [0 0 0] ->> -endobj -2339 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2340 0 obj -<< -/Subtype /Link -/A 2339 0 R -/Type /Annot -/Rect [147.201172 625.502 170.912109 638.002] -/Border [0 0 0] ->> -endobj -2341 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2342 0 obj -<< -/Subtype /Link -/A 2341 0 R -/Type /Annot -/Rect [170.912109 625.432 236.912109 638.002] -/Border [0 0 0] ->> -endobj -2343 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2344 0 obj -<< -/Subtype /Link -/A 2343 0 R -/Type /Annot -/Rect [236.912109 625.502 535.305664 638.002] -/Border [0 0 0] ->> -endobj -2345 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2346 0 obj -<< -/Subtype /Link -/A 2345 0 R -/Type /Annot -/Rect [72 613.002 146.072266 625.502] -/Border [0 0 0] ->> -endobj -2347 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2348 0 obj -<< -/Subtype /Link -/A 2347 0 R -/Type /Annot -/Rect [146.072266 612.932 212.072266 625.502] -/Border [0 0 0] ->> -endobj -2349 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2350 0 obj -<< -/Subtype /Link -/A 2349 0 R -/Type /Annot -/Rect [212.072266 613.002 235.783203 625.502] -/Border [0 0 0] ->> -endobj -2351 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2352 0 obj -<< -/Subtype /Link -/A 2351 0 R -/Type /Annot -/Rect [235.783203 612.932 313.783203 625.502] -/Border [0 0 0] ->> -endobj -2353 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2354 0 obj -<< -/Subtype /Link -/A 2353 0 R -/Type /Annot -/Rect [313.783203 613.002 379.110352 625.502] -/Border [0 0 0] ->> -endobj -2355 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2356 0 obj -<< -/Subtype /Link -/A 2355 0 R -/Type /Annot -/Rect [379.110352 612.932 421.110352 625.502] -/Border [0 0 0] ->> -endobj -2357 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2358 0 obj -<< -/Subtype /Link -/A 2357 0 R -/Type /Annot -/Rect [421.110352 613.002 484.337891 625.502] -/Border [0 0 0] ->> -endobj -2359 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2360 0 obj -<< -/Subtype /Link -/A 2359 0 R -/Type /Annot -/Rect [72 600.502 471.794922 613.002] -/Border [0 0 0] ->> -endobj -2361 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2362 0 obj -<< -/Subtype /Link -/A 2361 0 R -/Type /Annot -/Rect [72 578.002 93.201172 590.502] -/Border [0 0 0] ->> -endobj -2363 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2364 0 obj -<< -/Subtype /Link -/A 2363 0 R -/Type /Annot -/Rect [93.201172 577.932 117.201172 590.502] -/Border [0 0 0] ->> -endobj -2365 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2366 0 obj -<< -/Subtype /Link -/A 2365 0 R -/Type /Annot -/Rect [117.201172 578.002 140.912109 590.502] -/Border [0 0 0] ->> -endobj -2367 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2368 0 obj -<< -/Subtype /Link -/A 2367 0 R -/Type /Annot -/Rect [140.912109 577.932 176.912109 590.502] -/Border [0 0 0] ->> -endobj -2369 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2370 0 obj -<< -/Subtype /Link -/A 2369 0 R -/Type /Annot -/Rect [176.912109 578.002 525.334961 590.502] -/Border [0 0 0] ->> -endobj -2371 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2372 0 obj -<< -/Subtype /Link -/A 2371 0 R -/Type /Annot -/Rect [72 565.502 92.063477 578.002] -/Border [0 0 0] ->> -endobj -2373 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2374 0 obj -<< -/Subtype /Link -/A 2373 0 R -/Type /Annot -/Rect [92.063477 565.432 146.063477 578.002] -/Border [0 0 0] ->> -endobj -2375 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2376 0 obj -<< -/Subtype /Link -/A 2375 0 R -/Type /Annot -/Rect [146.063477 565.502 161.688477 578.002] -/Border [0 0 0] ->> -endobj -2377 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2378 0 obj -<< -/Subtype /Link -/A 2377 0 R -/Type /Annot -/Rect [161.688477 565.432 227.688477 578.002] -/Border [0 0 0] ->> -endobj -2379 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2380 0 obj -<< -/Subtype /Link -/A 2379 0 R -/Type /Annot -/Rect [227.688477 565.502 314.861328 578.002] -/Border [0 0 0] ->> -endobj -2381 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2382 0 obj -<< -/Subtype /Link -/A 2381 0 R -/Type /Annot -/Rect [314.861328 565.432 392.861328 578.002] -/Border [0 0 0] ->> -endobj -2383 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2384 0 obj -<< -/Subtype /Link -/A 2383 0 R -/Type /Annot -/Rect [392.861328 565.502 519.262695 578.002] -/Border [0 0 0] ->> -endobj -2385 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2386 0 obj -<< -/Subtype /Link -/A 2385 0 R -/Type /Annot -/Rect [72 553.002 230.90625 565.502] -/Border [0 0 0] ->> -endobj -2387 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2388 0 obj -<< -/Subtype /Link -/A 2387 0 R -/Type /Annot -/Rect [72 531.689 88.2 543.002] -/Border [0 0 0] ->> -endobj -2389 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2390 0 obj -<< -/Subtype /Link -/A 2389 0 R -/Type /Annot -/Rect [88.2 531.689 93.6 543.002] -/Border [0 0 0] ->> -endobj -2391 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2392 0 obj -<< -/Subtype /Link -/A 2391 0 R -/Type /Annot -/Rect [93.6 531.689 126 543.002] -/Border [0 0 0] ->> -endobj -2393 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2394 0 obj -<< -/Subtype /Link -/A 2393 0 R -/Type /Annot -/Rect [126 531.689 131.4 543.002] -/Border [0 0 0] ->> -endobj -2395 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2396 0 obj -<< -/Subtype /Link -/A 2395 0 R -/Type /Annot -/Rect [131.4 531.689 147.6 543.002] -/Border [0 0 0] ->> -endobj -2397 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2398 0 obj -<< -/Subtype /Link -/A 2397 0 R -/Type /Annot -/Rect [147.6 531.689 153 543.002] -/Border [0 0 0] ->> -endobj -2399 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2400 0 obj -<< -/Subtype /Link -/A 2399 0 R -/Type /Annot -/Rect [153 531.689 158.4 543.002] -/Border [0 0 0] ->> -endobj -2401 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2402 0 obj -<< -/Subtype /Link -/A 2401 0 R -/Type /Annot -/Rect [158.4 531.689 169.2 543.002] -/Border [0 0 0] ->> -endobj -2403 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2404 0 obj -<< -/Subtype /Link -/A 2403 0 R -/Type /Annot -/Rect [169.2 531.689 174.6 543.002] -/Border [0 0 0] ->> -endobj -2405 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2406 0 obj -<< -/Subtype /Link -/A 2405 0 R -/Type /Annot -/Rect [174.6 531.689 180 543.002] -/Border [0 0 0] ->> -endobj -2407 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2408 0 obj -<< -/Subtype /Link -/A 2407 0 R -/Type /Annot -/Rect [180 531.689 190.8 543.002] -/Border [0 0 0] ->> -endobj -2409 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2410 0 obj -<< -/Subtype /Link -/A 2409 0 R -/Type /Annot -/Rect [190.8 531.689 196.2 543.002] -/Border [0 0 0] ->> -endobj -2411 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2412 0 obj -<< -/Subtype /Link -/A 2411 0 R -/Type /Annot -/Rect [72 520.376 88.2 531.689] -/Border [0 0 0] ->> -endobj -2413 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2414 0 obj -<< -/Subtype /Link -/A 2413 0 R -/Type /Annot -/Rect [88.2 520.376 93.6 531.689] -/Border [0 0 0] ->> -endobj -2415 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2416 0 obj -<< -/Subtype /Link -/A 2415 0 R -/Type /Annot -/Rect [93.6 520.376 142.2 531.689] -/Border [0 0 0] ->> -endobj -2417 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2418 0 obj -<< -/Subtype /Link -/A 2417 0 R -/Type /Annot -/Rect [142.2 520.376 147.6 531.689] -/Border [0 0 0] ->> -endobj -2419 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2420 0 obj -<< -/Subtype /Link -/A 2419 0 R -/Type /Annot -/Rect [147.6 520.376 153 531.689] -/Border [0 0 0] ->> -endobj -2421 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2422 0 obj -<< -/Subtype /Link -/A 2421 0 R -/Type /Annot -/Rect [153 520.376 158.4 531.689] -/Border [0 0 0] ->> -endobj -2423 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2424 0 obj -<< -/Subtype /Link -/A 2423 0 R -/Type /Annot -/Rect [72 509.063 88.2 520.376] -/Border [0 0 0] ->> -endobj -2425 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2426 0 obj -<< -/Subtype /Link -/A 2425 0 R -/Type /Annot -/Rect [88.2 509.063 93.6 520.376] -/Border [0 0 0] ->> -endobj -2427 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2428 0 obj -<< -/Subtype /Link -/A 2427 0 R -/Type /Annot -/Rect [93.6 509.063 153 520.376] -/Border [0 0 0] ->> -endobj -2429 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2430 0 obj -<< -/Subtype /Link -/A 2429 0 R -/Type /Annot -/Rect [153 509.063 158.4 520.376] -/Border [0 0 0] ->> -endobj -2431 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2432 0 obj -<< -/Subtype /Link -/A 2431 0 R -/Type /Annot -/Rect [158.4 509.063 174.6 520.376] -/Border [0 0 0] ->> -endobj -2433 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2434 0 obj -<< -/Subtype /Link -/A 2433 0 R -/Type /Annot -/Rect [174.6 509.063 180 520.376] -/Border [0 0 0] ->> -endobj -2435 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2436 0 obj -<< -/Subtype /Link -/A 2435 0 R -/Type /Annot -/Rect [72 497.75 88.2 509.063] -/Border [0 0 0] ->> -endobj -2437 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2438 0 obj -<< -/Subtype /Link -/A 2437 0 R -/Type /Annot -/Rect [88.2 497.75 93.6 509.063] -/Border [0 0 0] ->> -endobj -2439 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2440 0 obj -<< -/Subtype /Link -/A 2439 0 R -/Type /Annot -/Rect [93.6 497.75 163.8 509.063] -/Border [0 0 0] ->> -endobj -2441 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2442 0 obj -<< -/Subtype /Link -/A 2441 0 R -/Type /Annot -/Rect [163.8 497.75 169.2 509.063] -/Border [0 0 0] ->> -endobj -2443 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2444 0 obj -<< -/Subtype /Link -/A 2443 0 R -/Type /Annot -/Rect [169.2 497.75 196.2 509.063] -/Border [0 0 0] ->> -endobj -2445 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2446 0 obj -<< -/Subtype /Link -/A 2445 0 R -/Type /Annot -/Rect [196.2 497.75 201.6 509.063] -/Border [0 0 0] ->> -endobj -2447 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2448 0 obj -<< -/Subtype /Link -/A 2447 0 R -/Type /Annot -/Rect [201.6 497.75 207 509.063] -/Border [0 0 0] ->> -endobj -2449 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2450 0 obj -<< -/Subtype /Link -/A 2449 0 R -/Type /Annot -/Rect [207 497.75 239.4 509.063] -/Border [0 0 0] ->> -endobj -2451 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2452 0 obj -<< -/Subtype /Link -/A 2451 0 R -/Type /Annot -/Rect [239.4 497.75 244.8 509.063] -/Border [0 0 0] ->> -endobj -2453 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2454 0 obj -<< -/Subtype /Link -/A 2453 0 R -/Type /Annot -/Rect [72 475.25 294.856445 487.75] -/Border [0 0 0] ->> -endobj -2455 0 obj -<< -/Type /ExtGState -/ca 0.8 ->> -endobj -2325 0 obj -<< -/Type /Page -/Parent 1 0 R -/MediaBox [0 0 612 792] -/Contents 2323 0 R -/Resources 2324 0 R -/Annots [2328 0 R 2330 0 R 2332 0 R 2334 0 R 2336 0 R 2338 0 R 2340 0 R 2342 0 R 2344 0 R 2346 0 R 2348 0 R 2350 0 R 2352 0 R 2354 0 R 2356 0 R 2358 0 R 2360 0 R 2362 0 R 2364 0 R 2366 0 R 2368 0 R 2370 0 R 2372 0 R 2374 0 R 2376 0 R 2378 0 R 2380 0 R 2382 0 R 2384 0 R 2386 0 R 2388 0 R 2390 0 R 2392 0 R 2394 0 R 2396 0 R 2398 0 R 2400 0 R 2402 0 R 2404 0 R 2406 0 R 2408 0 R 2410 0 R 2412 0 R 2414 0 R 2416 0 R 2418 0 R 2420 0 R 2422 0 R 2424 0 R 2426 0 R 2428 0 R 2430 0 R 2432 0 R 2434 0 R 2436 0 R 2438 0 R 2440 0 R 2442 0 R 2444 0 R 2446 0 R 2448 0 R 2450 0 R 2452 0 R 2454 0 R] ->> -endobj -2324 0 obj -<< -/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] -/Font << -/F4 16 0 R -/F3 9 0 R -/F6 44 0 R -/F5 29 0 R ->> -/ExtGState << -/Gs1 2455 0 R ->> ->> -endobj -2323 0 obj -<< -/Length 1450 -/Filter /FlateDecode ->> -stream -xZ͎6 )?Pa=hwnE'뗒)[N,u< ۲$DсVj}wˇǶmD|E'nbkt}I~P-[!K4Cf|e}b2 gGa6.}/|$-˟82& 3МY\e3M$xTjx-3ͻ 8'=H,#OR_Ic$ %iZ=9gsd bE 2r^Df-ݧhPòEe[q(J6MԼ쐦d`8L2V^P\T^?{4p-esNݯ؟Jيe 5`uJsT"lx[Acga i5=4,7e-p1ADGWq=\ )IqkGe:a!.ugx <6 48qT>RwѢ$X<Hg%LxSS^ns;w4X=1R)FtVO-OY5diFԖ'y` 0LVSBP0 -Ĥ<'[# -endstream -endobj -2460 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2461 0 obj -<< -/Subtype /Link -/A 2460 0 R -/Type /Annot -/Rect [72 695.502 146.52 720] -/Border [0 0 0] ->> -endobj -2462 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2463 0 obj -<< -/Subtype /Link -/A 2462 0 R -/Type /Annot -/Rect [72 673.002 537.078125 685.502] -/Border [0 0 0] ->> -endobj -2464 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2465 0 obj -<< -/Subtype /Link -/A 2464 0 R -/Type /Annot -/Rect [72 660.502 216.907227 673.002] -/Border [0 0 0] ->> -endobj -2466 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2467 0 obj -<< -/Subtype /Link -/A 2466 0 R -/Type /Annot -/Rect [216.907227 660.432 270.907227 673.002] -/Border [0 0 0] ->> -endobj -2468 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2469 0 obj -<< -/Subtype /Link -/A 2468 0 R -/Type /Annot -/Rect [270.907227 660.502 311.239258 673.002] -/Border [0 0 0] ->> -endobj -2470 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2471 0 obj -<< -/Subtype /Link -/A 2470 0 R -/Type /Annot -/Rect [311.239258 660.432 335.239258 673.002] -/Border [0 0 0] ->> -endobj -2472 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2473 0 obj -<< -/Subtype /Link -/A 2472 0 R -/Type /Annot -/Rect [335.239258 660.502 531.713867 673.002] -/Border [0 0 0] ->> -endobj -2474 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2475 0 obj -<< -/Subtype /Link -/A 2474 0 R -/Type /Annot -/Rect [72 648.002 368.870117 660.502] -/Border [0 0 0] ->> -endobj -2476 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2477 0 obj -<< -/Subtype /Link -/A 2476 0 R -/Type /Annot -/Rect [72 625.502 443.552734 638.002] -/Border [0 0 0] ->> -endobj -2478 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2479 0 obj -<< -/Subtype /Link -/A 2478 0 R -/Type /Annot -/Rect [443.552734 625.432 527.552734 638.002] -/Border [0 0 0] ->> -endobj -2480 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2481 0 obj -<< -/Subtype /Link -/A 2480 0 R -/Type /Annot -/Rect [72 613.002 95.710938 625.502] -/Border [0 0 0] ->> -endobj -2482 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2483 0 obj -<< -/Subtype /Link -/A 2482 0 R -/Type /Annot -/Rect [95.710938 612.932 179.710938 625.502] -/Border [0 0 0] ->> -endobj -2484 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2485 0 obj -<< -/Subtype /Link -/A 2484 0 R -/Type /Annot -/Rect [179.710938 613.002 445.692383 625.502] -/Border [0 0 0] ->> -endobj -2486 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2487 0 obj -<< -/Subtype /Link -/A 2486 0 R -/Type /Annot -/Rect [72 590.432 252 603.002] -/Border [0 0 0] ->> -endobj -2488 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2489 0 obj -<< -/Subtype /Link -/A 2488 0 R -/Type /Annot -/Rect [252 590.502 263.166992 603.002] -/Border [0 0 0] ->> -endobj -2490 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2491 0 obj -<< -/Subtype /Link -/A 2490 0 R -/Type /Annot -/Rect [263.166992 590.432 293.166992 603.002] -/Border [0 0 0] ->> -endobj -2492 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2493 0 obj -<< -/Subtype /Link -/A 2492 0 R -/Type /Annot -/Rect [293.166992 590.502 384.856445 603.002] -/Border [0 0 0] ->> -endobj -2494 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2495 0 obj -<< -/Subtype /Link -/A 2494 0 R -/Type /Annot -/Rect [384.856445 590.432 414.856445 603.002] -/Border [0 0 0] ->> -endobj -2496 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2497 0 obj -<< -/Subtype /Link -/A 2496 0 R -/Type /Annot -/Rect [414.856445 590.502 495.618164 603.002] -/Border [0 0 0] ->> -endobj -2498 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2499 0 obj -<< -/Subtype /Link -/A 2498 0 R -/Type /Annot -/Rect [72 571.932 300 584.502] -/Border [0 0 0] ->> -endobj -2500 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2501 0 obj -<< -/Subtype /Link -/A 2500 0 R -/Type /Annot -/Rect [300 572.002 311.166992 584.502] -/Border [0 0 0] ->> -endobj -2502 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2503 0 obj -<< -/Subtype /Link -/A 2502 0 R -/Type /Annot -/Rect [311.166992 571.932 323.166992 584.502] -/Border [0 0 0] ->> -endobj -2504 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2505 0 obj -<< -/Subtype /Link -/A 2504 0 R -/Type /Annot -/Rect [323.166992 572.002 422.507813 584.502] -/Border [0 0 0] ->> -endobj -2506 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2507 0 obj -<< -/Subtype /Link -/A 2506 0 R -/Type /Annot -/Rect [422.507813 571.932 434.507813 584.502] -/Border [0 0 0] ->> -endobj -2508 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2509 0 obj -<< -/Subtype /Link -/A 2508 0 R -/Type /Annot -/Rect [434.507813 572.002 527.510742 584.502] -/Border [0 0 0] ->> -endobj -2510 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2511 0 obj -<< -/Subtype /Link -/A 2510 0 R -/Type /Annot -/Rect [72 543.502 534.250977 556.002] -/Border [0 0 0] ->> -endobj -2512 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2513 0 obj -<< -/Subtype /Link -/A 2512 0 R -/Type /Annot -/Rect [72 531.002 508.928711 543.502] -/Border [0 0 0] ->> -endobj -2514 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2515 0 obj -<< -/Subtype /Link -/A 2514 0 R -/Type /Annot -/Rect [72 518.502 284.744141 531.002] -/Border [0 0 0] ->> -endobj -2516 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2517 0 obj -<< -/Subtype /Link -/A 2516 0 R -/Type /Annot -/Rect [72 496.002 419.705078 508.502] -/Border [0 0 0] ->> -endobj -2518 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2519 0 obj -<< -/Subtype /Link -/A 2518 0 R -/Type /Annot -/Rect [72 474.689 217.8 486.002] -/Border [0 0 0] ->> -endobj -2520 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2521 0 obj -<< -/Subtype /Link -/A 2520 0 R -/Type /Annot -/Rect [72 463.376 88.2 474.689] -/Border [0 0 0] ->> -endobj -2522 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2523 0 obj -<< -/Subtype /Link -/A 2522 0 R -/Type /Annot -/Rect [88.2 463.376 93.6 474.689] -/Border [0 0 0] ->> -endobj -2524 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2525 0 obj -<< -/Subtype /Link -/A 2524 0 R -/Type /Annot -/Rect [93.6 463.376 115.2 474.689] -/Border [0 0 0] ->> -endobj -2526 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2527 0 obj -<< -/Subtype /Link -/A 2526 0 R -/Type /Annot -/Rect [115.2 463.376 120.6 474.689] -/Border [0 0 0] ->> -endobj -2528 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2529 0 obj -<< -/Subtype /Link -/A 2528 0 R -/Type /Annot -/Rect [120.6 463.376 126 474.689] -/Border [0 0 0] ->> -endobj -2530 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2531 0 obj -<< -/Subtype /Link -/A 2530 0 R -/Type /Annot -/Rect [126 463.376 131.4 474.689] -/Border [0 0 0] ->> -endobj -2532 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2533 0 obj -<< -/Subtype /Link -/A 2532 0 R -/Type /Annot -/Rect [131.4 463.376 147.6 474.689] -/Border [0 0 0] ->> -endobj -2534 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2535 0 obj -<< -/Subtype /Link -/A 2534 0 R -/Type /Annot -/Rect [147.6 463.376 153 474.689] -/Border [0 0 0] ->> -endobj -2536 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2537 0 obj -<< -/Subtype /Link -/A 2536 0 R -/Type /Annot -/Rect [153 463.376 228.6 474.689] -/Border [0 0 0] ->> -endobj -2538 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2539 0 obj -<< -/Subtype /Link -/A 2538 0 R -/Type /Annot -/Rect [228.6 463.376 234 474.689] -/Border [0 0 0] ->> -endobj -2540 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2541 0 obj -<< -/Subtype /Link -/A 2540 0 R -/Type /Annot -/Rect [234 463.376 244.8 474.689] -/Border [0 0 0] ->> -endobj -2542 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2543 0 obj -<< -/Subtype /Link -/A 2542 0 R -/Type /Annot -/Rect [244.8 463.376 250.2 474.689] -/Border [0 0 0] ->> -endobj -2544 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2545 0 obj -<< -/Subtype /Link -/A 2544 0 R -/Type /Annot -/Rect [250.2 463.376 255.6 474.689] -/Border [0 0 0] ->> -endobj -2546 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2547 0 obj -<< -/Subtype /Link -/A 2546 0 R -/Type /Annot -/Rect [255.6 463.376 261 474.689] -/Border [0 0 0] ->> -endobj -2548 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2549 0 obj -<< -/Subtype /Link -/A 2548 0 R -/Type /Annot -/Rect [261 463.376 266.4 474.689] -/Border [0 0 0] ->> -endobj -2550 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2551 0 obj -<< -/Subtype /Link -/A 2550 0 R -/Type /Annot -/Rect [266.4 463.376 271.8 474.689] -/Border [0 0 0] ->> -endobj -2552 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2553 0 obj -<< -/Subtype /Link -/A 2552 0 R -/Type /Annot -/Rect [271.8 463.376 288 474.689] -/Border [0 0 0] ->> -endobj -2554 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2555 0 obj -<< -/Subtype /Link -/A 2554 0 R -/Type /Annot -/Rect [288 463.376 293.4 474.689] -/Border [0 0 0] ->> -endobj -2556 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2557 0 obj -<< -/Subtype /Link -/A 2556 0 R -/Type /Annot -/Rect [293.4 463.376 298.8 474.689] -/Border [0 0 0] ->> -endobj -2558 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2559 0 obj -<< -/Subtype /Link -/A 2558 0 R -/Type /Annot -/Rect [298.8 463.376 315 474.689] -/Border [0 0 0] ->> -endobj -2560 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2561 0 obj -<< -/Subtype /Link -/A 2560 0 R -/Type /Annot -/Rect [315 463.376 320.4 474.689] -/Border [0 0 0] ->> -endobj -2562 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2563 0 obj -<< -/Subtype /Link -/A 2562 0 R -/Type /Annot -/Rect [320.4 463.376 325.8 474.689] -/Border [0 0 0] ->> -endobj -2564 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2565 0 obj -<< -/Subtype /Link -/A 2564 0 R -/Type /Annot -/Rect [72 452.063 93.6 463.376] -/Border [0 0 0] ->> -endobj -2566 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2567 0 obj -<< -/Subtype /Link -/A 2566 0 R -/Type /Annot -/Rect [93.6 452.063 99 463.376] -/Border [0 0 0] ->> -endobj -2568 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2569 0 obj -<< -/Subtype /Link -/A 2568 0 R -/Type /Annot -/Rect [99 452.063 120.6 463.376] -/Border [0 0 0] ->> -endobj -2570 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2571 0 obj -<< -/Subtype /Link -/A 2570 0 R -/Type /Annot -/Rect [120.6 452.063 126 463.376] -/Border [0 0 0] ->> -endobj -2572 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2573 0 obj -<< -/Subtype /Link -/A 2572 0 R -/Type /Annot -/Rect [126 452.063 131.4 463.376] -/Border [0 0 0] ->> -endobj -2574 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2575 0 obj -<< -/Subtype /Link -/A 2574 0 R -/Type /Annot -/Rect [131.4 452.063 136.8 463.376] -/Border [0 0 0] ->> -endobj -2576 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2577 0 obj -<< -/Subtype /Link -/A 2576 0 R -/Type /Annot -/Rect [136.8 452.063 142.2 463.376] -/Border [0 0 0] ->> -endobj -2578 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2579 0 obj -<< -/Subtype /Link -/A 2578 0 R -/Type /Annot -/Rect [142.2 452.063 180 463.376] -/Border [0 0 0] ->> -endobj -2580 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2581 0 obj -<< -/Subtype /Link -/A 2580 0 R -/Type /Annot -/Rect [180 452.063 185.4 463.376] -/Border [0 0 0] ->> -endobj -2582 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2583 0 obj -<< -/Subtype /Link -/A 2582 0 R -/Type /Annot -/Rect [72 440.75 93.6 452.063] -/Border [0 0 0] ->> -endobj -2584 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2585 0 obj -<< -/Subtype /Link -/A 2584 0 R -/Type /Annot -/Rect [93.6 440.75 99 452.063] -/Border [0 0 0] ->> -endobj -2586 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2587 0 obj -<< -/Subtype /Link -/A 2586 0 R -/Type /Annot -/Rect [99 440.75 120.6 452.063] -/Border [0 0 0] ->> -endobj -2588 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2589 0 obj -<< -/Subtype /Link -/A 2588 0 R -/Type /Annot -/Rect [120.6 440.75 126 452.063] -/Border [0 0 0] ->> -endobj -2590 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2591 0 obj -<< -/Subtype /Link -/A 2590 0 R -/Type /Annot -/Rect [126 440.75 131.4 452.063] -/Border [0 0 0] ->> -endobj -2592 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2593 0 obj -<< -/Subtype /Link -/A 2592 0 R -/Type /Annot -/Rect [131.4 440.75 136.8 452.063] -/Border [0 0 0] ->> -endobj -2594 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2595 0 obj -<< -/Subtype /Link -/A 2594 0 R -/Type /Annot -/Rect [136.8 440.75 142.2 452.063] -/Border [0 0 0] ->> -endobj -2596 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2597 0 obj -<< -/Subtype /Link -/A 2596 0 R -/Type /Annot -/Rect [142.2 440.75 169.2 452.063] -/Border [0 0 0] ->> -endobj -2598 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2599 0 obj -<< -/Subtype /Link -/A 2598 0 R -/Type /Annot -/Rect [169.2 440.75 174.6 452.063] -/Border [0 0 0] ->> -endobj -2600 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2601 0 obj -<< -/Subtype /Link -/A 2600 0 R -/Type /Annot -/Rect [174.6 440.75 180 452.063] -/Border [0 0 0] ->> -endobj -2602 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2603 0 obj -<< -/Subtype /Link -/A 2602 0 R -/Type /Annot -/Rect [72 418.124 88.2 429.437] -/Border [0 0 0] ->> -endobj -2604 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2605 0 obj -<< -/Subtype /Link -/A 2604 0 R -/Type /Annot -/Rect [88.2 418.124 93.6 429.437] -/Border [0 0 0] ->> -endobj -2606 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2607 0 obj -<< -/Subtype /Link -/A 2606 0 R -/Type /Annot -/Rect [93.6 418.124 115.2 429.437] -/Border [0 0 0] ->> -endobj -2608 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2609 0 obj -<< -/Subtype /Link -/A 2608 0 R -/Type /Annot -/Rect [115.2 418.124 120.6 429.437] -/Border [0 0 0] ->> -endobj -2610 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2611 0 obj -<< -/Subtype /Link -/A 2610 0 R -/Type /Annot -/Rect [120.6 418.124 131.4 429.437] -/Border [0 0 0] ->> -endobj -2612 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2613 0 obj -<< -/Subtype /Link -/A 2612 0 R -/Type /Annot -/Rect [131.4 418.124 136.8 429.437] -/Border [0 0 0] ->> -endobj -2614 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2615 0 obj -<< -/Subtype /Link -/A 2614 0 R -/Type /Annot -/Rect [136.8 418.124 142.2 429.437] -/Border [0 0 0] ->> -endobj -2616 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2617 0 obj -<< -/Subtype /Link -/A 2616 0 R -/Type /Annot -/Rect [142.2 418.124 147.6 429.437] -/Border [0 0 0] ->> -endobj -2618 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2619 0 obj -<< -/Subtype /Link -/A 2618 0 R -/Type /Annot -/Rect [147.6 418.124 153 429.437] -/Border [0 0 0] ->> -endobj -2620 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2621 0 obj -<< -/Subtype /Link -/A 2620 0 R -/Type /Annot -/Rect [153 418.124 158.4 429.437] -/Border [0 0 0] ->> -endobj -2622 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2623 0 obj -<< -/Subtype /Link -/A 2622 0 R -/Type /Annot -/Rect [158.4 418.124 174.6 429.437] -/Border [0 0 0] ->> -endobj -2624 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2625 0 obj -<< -/Subtype /Link -/A 2624 0 R -/Type /Annot -/Rect [174.6 418.124 180 429.437] -/Border [0 0 0] ->> -endobj -2626 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2627 0 obj -<< -/Subtype /Link -/A 2626 0 R -/Type /Annot -/Rect [180 418.124 185.4 429.437] -/Border [0 0 0] ->> -endobj -2628 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2629 0 obj -<< -/Subtype /Link -/A 2628 0 R -/Type /Annot -/Rect [185.4 418.124 201.6 429.437] -/Border [0 0 0] ->> -endobj -2630 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2631 0 obj -<< -/Subtype /Link -/A 2630 0 R -/Type /Annot -/Rect [201.6 418.124 207 429.437] -/Border [0 0 0] ->> -endobj -2632 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2633 0 obj -<< -/Subtype /Link -/A 2632 0 R -/Type /Annot -/Rect [207 418.124 212.4 429.437] -/Border [0 0 0] ->> -endobj -2634 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2635 0 obj -<< -/Subtype /Link -/A 2634 0 R -/Type /Annot -/Rect [72 406.811 88.2 418.124] -/Border [0 0 0] ->> -endobj -2636 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2637 0 obj -<< -/Subtype /Link -/A 2636 0 R -/Type /Annot -/Rect [88.2 406.811 93.6 418.124] -/Border [0 0 0] ->> -endobj -2638 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2639 0 obj -<< -/Subtype /Link -/A 2638 0 R -/Type /Annot -/Rect [93.6 406.811 115.2 418.124] -/Border [0 0 0] ->> -endobj -2640 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2641 0 obj -<< -/Subtype /Link -/A 2640 0 R -/Type /Annot -/Rect [115.2 406.811 120.6 418.124] -/Border [0 0 0] ->> -endobj -2642 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2643 0 obj -<< -/Subtype /Link -/A 2642 0 R -/Type /Annot -/Rect [120.6 406.811 142.2 418.124] -/Border [0 0 0] ->> -endobj -2644 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2645 0 obj -<< -/Subtype /Link -/A 2644 0 R -/Type /Annot -/Rect [142.2 406.811 147.6 418.124] -/Border [0 0 0] ->> -endobj -2646 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2647 0 obj -<< -/Subtype /Link -/A 2646 0 R -/Type /Annot -/Rect [147.6 406.811 153 418.124] -/Border [0 0 0] ->> -endobj -2648 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2649 0 obj -<< -/Subtype /Link -/A 2648 0 R -/Type /Annot -/Rect [72 384.185 217.8 395.498] -/Border [0 0 0] ->> -endobj -2650 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2651 0 obj -<< -/Subtype /Link -/A 2650 0 R -/Type /Annot -/Rect [72 372.872 93.6 384.185] -/Border [0 0 0] ->> -endobj -2652 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2653 0 obj -<< -/Subtype /Link -/A 2652 0 R -/Type /Annot -/Rect [93.6 372.872 99 384.185] -/Border [0 0 0] ->> -endobj -2654 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2655 0 obj -<< -/Subtype /Link -/A 2654 0 R -/Type /Annot -/Rect [99 372.872 104.4 384.185] -/Border [0 0 0] ->> -endobj -2656 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2657 0 obj -<< -/Subtype /Link -/A 2656 0 R -/Type /Annot -/Rect [104.4 372.872 109.8 384.185] -/Border [0 0 0] ->> -endobj -2658 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2659 0 obj -<< -/Subtype /Link -/A 2658 0 R -/Type /Annot -/Rect [109.8 372.872 126 384.185] -/Border [0 0 0] ->> -endobj -2660 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2661 0 obj -<< -/Subtype /Link -/A 2660 0 R -/Type /Annot -/Rect [126 372.872 131.4 384.185] -/Border [0 0 0] ->> -endobj -2662 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2663 0 obj -<< -/Subtype /Link -/A 2662 0 R -/Type /Annot -/Rect [131.4 372.872 207 384.185] -/Border [0 0 0] ->> -endobj -2664 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2665 0 obj -<< -/Subtype /Link -/A 2664 0 R -/Type /Annot -/Rect [207 372.872 212.4 384.185] -/Border [0 0 0] ->> -endobj -2666 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2667 0 obj -<< -/Subtype /Link -/A 2666 0 R -/Type /Annot -/Rect [212.4 372.872 228.6 384.185] -/Border [0 0 0] ->> -endobj -2668 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2669 0 obj -<< -/Subtype /Link -/A 2668 0 R -/Type /Annot -/Rect [228.6 372.872 234 384.185] -/Border [0 0 0] ->> -endobj -2670 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2671 0 obj -<< -/Subtype /Link -/A 2670 0 R -/Type /Annot -/Rect [234 372.872 239.4 384.185] -/Border [0 0 0] ->> -endobj -2672 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2673 0 obj -<< -/Subtype /Link -/A 2672 0 R -/Type /Annot -/Rect [239.4 372.872 250.2 384.185] -/Border [0 0 0] ->> -endobj -2674 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2675 0 obj -<< -/Subtype /Link -/A 2674 0 R -/Type /Annot -/Rect [250.2 372.872 255.6 384.185] -/Border [0 0 0] ->> -endobj -2676 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2677 0 obj -<< -/Subtype /Link -/A 2676 0 R -/Type /Annot -/Rect [255.6 372.872 261 384.185] -/Border [0 0 0] ->> -endobj -2678 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2679 0 obj -<< -/Subtype /Link -/A 2678 0 R -/Type /Annot -/Rect [261 372.872 266.4 384.185] -/Border [0 0 0] ->> -endobj -2680 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2681 0 obj -<< -/Subtype /Link -/A 2680 0 R -/Type /Annot -/Rect [266.4 372.872 271.8 384.185] -/Border [0 0 0] ->> -endobj -2682 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2683 0 obj -<< -/Subtype /Link -/A 2682 0 R -/Type /Annot -/Rect [271.8 372.872 277.2 384.185] -/Border [0 0 0] ->> -endobj -2684 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2685 0 obj -<< -/Subtype /Link -/A 2684 0 R -/Type /Annot -/Rect [277.2 372.872 293.4 384.185] -/Border [0 0 0] ->> -endobj -2686 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2687 0 obj -<< -/Subtype /Link -/A 2686 0 R -/Type /Annot -/Rect [293.4 372.872 298.8 384.185] -/Border [0 0 0] ->> -endobj -2688 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2689 0 obj -<< -/Subtype /Link -/A 2688 0 R -/Type /Annot -/Rect [298.8 372.872 304.2 384.185] -/Border [0 0 0] ->> -endobj -2690 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2691 0 obj -<< -/Subtype /Link -/A 2690 0 R -/Type /Annot -/Rect [304.2 372.872 315 384.185] -/Border [0 0 0] ->> -endobj -2692 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2693 0 obj -<< -/Subtype /Link -/A 2692 0 R -/Type /Annot -/Rect [315 372.872 320.4 384.185] -/Border [0 0 0] ->> -endobj -2694 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2695 0 obj -<< -/Subtype /Link -/A 2694 0 R -/Type /Annot -/Rect [320.4 372.872 325.8 384.185] -/Border [0 0 0] ->> -endobj -2696 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2697 0 obj -<< -/Subtype /Link -/A 2696 0 R -/Type /Annot -/Rect [325.8 372.872 336.6 384.185] -/Border [0 0 0] ->> -endobj -2698 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2699 0 obj -<< -/Subtype /Link -/A 2698 0 R -/Type /Annot -/Rect [336.6 372.872 342 384.185] -/Border [0 0 0] ->> -endobj -2700 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2701 0 obj -<< -/Subtype /Link -/A 2700 0 R -/Type /Annot -/Rect [342 372.872 347.4 384.185] -/Border [0 0 0] ->> -endobj -2702 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2703 0 obj -<< -/Subtype /Link -/A 2702 0 R -/Type /Annot -/Rect [72 361.559 93.6 372.872] -/Border [0 0 0] ->> -endobj -2704 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2705 0 obj -<< -/Subtype /Link -/A 2704 0 R -/Type /Annot -/Rect [93.6 361.559 99 372.872] -/Border [0 0 0] ->> -endobj -2706 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2707 0 obj -<< -/Subtype /Link -/A 2706 0 R -/Type /Annot -/Rect [99 361.559 120.6 372.872] -/Border [0 0 0] ->> -endobj -2708 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2709 0 obj -<< -/Subtype /Link -/A 2708 0 R -/Type /Annot -/Rect [120.6 361.559 126 372.872] -/Border [0 0 0] ->> -endobj -2710 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2711 0 obj -<< -/Subtype /Link -/A 2710 0 R -/Type /Annot -/Rect [126 361.559 131.4 372.872] -/Border [0 0 0] ->> -endobj -2712 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2713 0 obj -<< -/Subtype /Link -/A 2712 0 R -/Type /Annot -/Rect [131.4 361.559 136.8 372.872] -/Border [0 0 0] ->> -endobj -2714 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2715 0 obj -<< -/Subtype /Link -/A 2714 0 R -/Type /Annot -/Rect [136.8 361.559 142.2 372.872] -/Border [0 0 0] ->> -endobj -2716 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2717 0 obj -<< -/Subtype /Link -/A 2716 0 R -/Type /Annot -/Rect [142.2 361.559 185.4 372.872] -/Border [0 0 0] ->> -endobj -2718 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2719 0 obj -<< -/Subtype /Link -/A 2718 0 R -/Type /Annot -/Rect [185.4 361.559 190.8 372.872] -/Border [0 0 0] ->> -endobj -2720 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2721 0 obj -<< -/Subtype /Link -/A 2720 0 R -/Type /Annot -/Rect [190.8 361.559 196.2 372.872] -/Border [0 0 0] ->> -endobj -2722 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2723 0 obj -<< -/Subtype /Link -/A 2722 0 R -/Type /Annot -/Rect [196.2 361.559 201.6 372.872] -/Border [0 0 0] ->> -endobj -2724 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2725 0 obj -<< -/Subtype /Link -/A 2724 0 R -/Type /Annot -/Rect [201.6 361.559 207 372.872] -/Border [0 0 0] ->> -endobj -2726 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2727 0 obj -<< -/Subtype /Link -/A 2726 0 R -/Type /Annot -/Rect [72 350.246 93.6 361.559] -/Border [0 0 0] ->> -endobj -2728 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2729 0 obj -<< -/Subtype /Link -/A 2728 0 R -/Type /Annot -/Rect [93.6 350.246 99 361.559] -/Border [0 0 0] ->> -endobj -2730 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2731 0 obj -<< -/Subtype /Link -/A 2730 0 R -/Type /Annot -/Rect [99 350.246 120.6 361.559] -/Border [0 0 0] ->> -endobj -2732 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2733 0 obj -<< -/Subtype /Link -/A 2732 0 R -/Type /Annot -/Rect [120.6 350.246 126 361.559] -/Border [0 0 0] ->> -endobj -2734 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2735 0 obj -<< -/Subtype /Link -/A 2734 0 R -/Type /Annot -/Rect [126 350.246 131.4 361.559] -/Border [0 0 0] ->> -endobj -2736 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2737 0 obj -<< -/Subtype /Link -/A 2736 0 R -/Type /Annot -/Rect [131.4 350.246 136.8 361.559] -/Border [0 0 0] ->> -endobj -2738 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2739 0 obj -<< -/Subtype /Link -/A 2738 0 R -/Type /Annot -/Rect [136.8 350.246 142.2 361.559] -/Border [0 0 0] ->> -endobj -2740 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2741 0 obj -<< -/Subtype /Link -/A 2740 0 R -/Type /Annot -/Rect [142.2 350.246 185.4 361.559] -/Border [0 0 0] ->> -endobj -2742 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2743 0 obj -<< -/Subtype /Link -/A 2742 0 R -/Type /Annot -/Rect [185.4 350.246 190.8 361.559] -/Border [0 0 0] ->> -endobj -2744 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2745 0 obj -<< -/Subtype /Link -/A 2744 0 R -/Type /Annot -/Rect [190.8 350.246 196.2 361.559] -/Border [0 0 0] ->> -endobj -2746 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2747 0 obj -<< -/Subtype /Link -/A 2746 0 R -/Type /Annot -/Rect [196.2 350.246 201.6 361.559] -/Border [0 0 0] ->> -endobj -2748 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2749 0 obj -<< -/Subtype /Link -/A 2748 0 R -/Type /Annot -/Rect [201.6 350.246 207 361.559] -/Border [0 0 0] ->> -endobj -2750 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2751 0 obj -<< -/Subtype /Link -/A 2750 0 R -/Type /Annot -/Rect [207 350.246 212.4 361.559] -/Border [0 0 0] ->> -endobj -2752 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2753 0 obj -<< -/Subtype /Link -/A 2752 0 R -/Type /Annot -/Rect [72 327.62 88.2 338.933] -/Border [0 0 0] ->> -endobj -2754 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2755 0 obj -<< -/Subtype /Link -/A 2754 0 R -/Type /Annot -/Rect [88.2 327.62 93.6 338.933] -/Border [0 0 0] ->> -endobj -2756 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2757 0 obj -<< -/Subtype /Link -/A 2756 0 R -/Type /Annot -/Rect [93.6 327.62 126 338.933] -/Border [0 0 0] ->> -endobj -2758 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2759 0 obj -<< -/Subtype /Link -/A 2758 0 R -/Type /Annot -/Rect [126 327.62 131.4 338.933] -/Border [0 0 0] ->> -endobj -2760 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2761 0 obj -<< -/Subtype /Link -/A 2760 0 R -/Type /Annot -/Rect [131.4 327.62 147.6 338.933] -/Border [0 0 0] ->> -endobj -2762 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2763 0 obj -<< -/Subtype /Link -/A 2762 0 R -/Type /Annot -/Rect [147.6 327.62 153 338.933] -/Border [0 0 0] ->> -endobj -2764 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2765 0 obj -<< -/Subtype /Link -/A 2764 0 R -/Type /Annot -/Rect [153 327.62 158.4 338.933] -/Border [0 0 0] ->> -endobj -2766 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2767 0 obj -<< -/Subtype /Link -/A 2766 0 R -/Type /Annot -/Rect [158.4 327.62 169.2 338.933] -/Border [0 0 0] ->> -endobj -2768 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2769 0 obj -<< -/Subtype /Link -/A 2768 0 R -/Type /Annot -/Rect [169.2 327.62 174.6 338.933] -/Border [0 0 0] ->> -endobj -2770 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2771 0 obj -<< -/Subtype /Link -/A 2770 0 R -/Type /Annot -/Rect [174.6 327.62 180 338.933] -/Border [0 0 0] ->> -endobj -2772 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2773 0 obj -<< -/Subtype /Link -/A 2772 0 R -/Type /Annot -/Rect [180 327.62 190.8 338.933] -/Border [0 0 0] ->> -endobj -2774 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2775 0 obj -<< -/Subtype /Link -/A 2774 0 R -/Type /Annot -/Rect [190.8 327.62 196.2 338.933] -/Border [0 0 0] ->> -endobj -2776 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2777 0 obj -<< -/Subtype /Link -/A 2776 0 R -/Type /Annot -/Rect [196.2 327.62 201.6 338.933] -/Border [0 0 0] ->> -endobj -2778 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2779 0 obj -<< -/Subtype /Link -/A 2778 0 R -/Type /Annot -/Rect [72 316.307 88.2 327.62] -/Border [0 0 0] ->> -endobj -2780 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2781 0 obj -<< -/Subtype /Link -/A 2780 0 R -/Type /Annot -/Rect [88.2 316.307 93.6 327.62] -/Border [0 0 0] ->> -endobj -2782 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2783 0 obj -<< -/Subtype /Link -/A 2782 0 R -/Type /Annot -/Rect [93.6 316.307 115.2 327.62] -/Border [0 0 0] ->> -endobj -2784 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2785 0 obj -<< -/Subtype /Link -/A 2784 0 R -/Type /Annot -/Rect [115.2 316.307 120.6 327.62] -/Border [0 0 0] ->> -endobj -2786 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2787 0 obj -<< -/Subtype /Link -/A 2786 0 R -/Type /Annot -/Rect [120.6 316.307 142.2 327.62] -/Border [0 0 0] ->> -endobj -2788 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2789 0 obj -<< -/Subtype /Link -/A 2788 0 R -/Type /Annot -/Rect [142.2 316.307 147.6 327.62] -/Border [0 0 0] ->> -endobj -2790 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2791 0 obj -<< -/Subtype /Link -/A 2790 0 R -/Type /Annot -/Rect [147.6 316.307 153 327.62] -/Border [0 0 0] ->> -endobj -2792 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2793 0 obj -<< -/Subtype /Link -/A 2792 0 R -/Type /Annot -/Rect [72 293.807 279.299805 306.307] -/Border [0 0 0] ->> -endobj -2794 0 obj -<< -/FunctionType 2 -/Domain [0 1] -/C0 [0 0.501961 0] -/C1 [1 0 0] -/N 1 ->> -endobj -2795 0 obj -<< -/ShadingType 2 -/ColorSpace /DeviceRGB -/Coords [50 0 150 100] -/Function 2794 0 R -/Extend [true true] ->> -endobj -2796 0 obj -<< -/Type /Pattern -/PatternType 2 -/Shading 2795 0 R -/Matrix [1 0 0 -1 72 273.403] ->> -endobj -2797 0 obj -<< -/FunctionType 2 -/Domain [0 1] -/C0 [1 0.647059 0] -/C1 [1 0.647059 0] -/N 1 ->> -endobj -2798 0 obj -<< -/ShadingType 3 -/ColorSpace /DeviceRGB -/Coords [300 50 0 300 50 50] -/Function 2797 0 R -/Extend [true true] ->> -endobj -2799 0 obj -<< -/Type /Pattern -/PatternType 2 -/Shading 2798 0 R -/Matrix [1 0 0 -1 72 273.403] ->> -endobj -2800 0 obj -<< -/FunctionType 2 -/Domain [0 1] -/C0 [0] -/C1 [1] -/N 1 ->> -endobj -2801 0 obj -<< -/ShadingType 3 -/ColorSpace /DeviceGray -/Coords [300 50 0 300 50 50] -/Function 2800 0 R -/Extend [true true] ->> -endobj -2802 0 obj -<< -/Type /Pattern -/PatternType 2 -/Shading 2801 0 R -/Matrix [1 0 0 -1 72 273.403] ->> -endobj -2803 0 obj -<< -/Type /XObject -/Subtype /Form -/FormType 1 -/BBox [0 0 612 792] -/Group << -/Type /Group -/S /Transparency -/CS /DeviceGray ->> -/Resources << -/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] -/Pattern << -/Sh1 2802 0 R ->> ->> -/Length 46 -/Filter /FlateDecode ->> -stream -xH,)I-SH.V0T(N2P0P034R04R(JUH -/ -endstream -endobj -2804 0 obj -<< -/Type /ExtGState -/SMask << -/Type /Mask -/S /Luminosity -/G 2803 0 R ->> ->> -endobj -2805 0 obj -<< -/Type /Pattern -/PatternType 1 -/PaintType 1 -/TilingType 2 -/BBox [0 0 612 792] -/XStep 612 -/YStep 792 -/Resources << -/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] -/Pattern << -/Sh1 2799 0 R ->> -/ExtGState << -/Gs1 2804 0 R ->> ->> -/Length 52 -/Filter /FlateDecode ->> -stream -xw/6TH/VH,)I-SH3    -RҸ9 c -endstream -endobj -2458 0 obj -<< -/Type /Page -/Parent 1 0 R -/MediaBox [0 0 612 792] -/Contents 2456 0 R -/Resources 2457 0 R -/Annots [2461 0 R 2463 0 R 2465 0 R 2467 0 R 2469 0 R 2471 0 R 2473 0 R 2475 0 R 2477 0 R 2479 0 R 2481 0 R 2483 0 R 2485 0 R 2487 0 R 2489 0 R 2491 0 R 2493 0 R 2495 0 R 2497 0 R 2499 0 R 2501 0 R 2503 0 R 2505 0 R 2507 0 R 2509 0 R 2511 0 R 2513 0 R 2515 0 R 2517 0 R 2519 0 R 2521 0 R 2523 0 R 2525 0 R 2527 0 R 2529 0 R 2531 0 R 2533 0 R 2535 0 R 2537 0 R 2539 0 R 2541 0 R 2543 0 R 2545 0 R 2547 0 R 2549 0 R 2551 0 R 2553 0 R 2555 0 R 2557 0 R 2559 0 R 2561 0 R 2563 0 R 2565 0 R 2567 0 R 2569 0 R 2571 0 R 2573 0 R 2575 0 R 2577 0 R 2579 0 R 2581 0 R 2583 0 R 2585 0 R 2587 0 R 2589 0 R 2591 0 R 2593 0 R 2595 0 R 2597 0 R 2599 0 R 2601 0 R 2603 0 R 2605 0 R 2607 0 R 2609 0 R 2611 0 R 2613 0 R 2615 0 R 2617 0 R 2619 0 R 2621 0 R 2623 0 R 2625 0 R 2627 0 R 2629 0 R 2631 0 R 2633 0 R 2635 0 R 2637 0 R 2639 0 R 2641 0 R 2643 0 R 2645 0 R 2647 0 R 2649 0 R 2651 0 R 2653 0 R 2655 0 R 2657 0 R 2659 0 R 2661 0 R 2663 0 R 2665 0 R 2667 0 R 2669 0 R 2671 0 R 2673 0 R 2675 0 R 2677 0 R 2679 0 R 2681 0 R 2683 0 R 2685 0 R 2687 0 R 2689 0 R 2691 0 R 2693 0 R 2695 0 R 2697 0 R 2699 0 R 2701 0 R 2703 0 R 2705 0 R 2707 0 R 2709 0 R 2711 0 R 2713 0 R 2715 0 R 2717 0 R 2719 0 R 2721 0 R 2723 0 R 2725 0 R 2727 0 R 2729 0 R 2731 0 R 2733 0 R 2735 0 R 2737 0 R 2739 0 R 2741 0 R 2743 0 R 2745 0 R 2747 0 R 2749 0 R 2751 0 R 2753 0 R 2755 0 R 2757 0 R 2759 0 R 2761 0 R 2763 0 R 2765 0 R 2767 0 R 2769 0 R 2771 0 R 2773 0 R 2775 0 R 2777 0 R 2779 0 R 2781 0 R 2783 0 R 2785 0 R 2787 0 R 2789 0 R 2791 0 R 2793 0 R] ->> -endobj -2457 0 obj -<< -/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] -/Font << -/F4 16 0 R -/F3 9 0 R -/F6 44 0 R -/F5 29 0 R ->> -/Pattern << -/Sh1 2796 0 R -/Sh3 2802 0 R -/Sh2 2805 0 R ->> ->> -endobj -2456 0 obj -<< -/Length 2354 -/Filter /FlateDecode ->> -stream -x]ɮ6+Ux9(:]ux Fh6AeJ֥&Jl=<ݛ|ֈ:K]uL度pL$*(W%zJ Μ>'$5Mӵ2"L3~>ޠ~P?)Ejܪ@F{٪<"z#D*3ժhHBoʬL䳮rZnyH$\y~V,vi[VorkMrrR!cxˮYng,w3%7,4DZV﯑-}Q7cf݊#KM,Ϳ潗ch>_LgsG$pҘᜍBPŸ̪x#C.Is/d%16#Ybt,-e -tg&',Fe@DK.)sQuĨaJ )f4dniꓔE'Ε"oɸ8e8~?&",kտ,k Ɇ4@ ODlftRak)J) -Wɚ4!9ex̏qFZxMǻ0o1zkgGgnÐ̧Dtcej/)XJR2HRJ\`9 J+sUH(Wi𺅫ZK\sl>ؘtF0.IM*%~([dyS3Ҙ*;u>=Nn/ipU(+,Ѽ'ם~ռr&NjП -4I%a's+A*h-͓&C$#aH'#dtgn( uE%N+6 EL҈F!r~92j1NTqcuŪZaJƯ"֨ lFߊhƜjHkXMR!VQ(5Ab0N^k.`yXTsbtA #^Ȕz1NټD[mՃ(\5edFi4JQٝܞ#JgK8G_\XSLF2_4kr -kSU%n!E?#qW%i8xZ-+:5oOM<ڐ{zGx[a1Ds>jf8y! -nȻ=.eɡc]AA]MDo=EK6cTg~  > -6d눺'`fe8FXsz}v3hDG>0<"_6q:& -]Ɍ})&pYEE4AՓ#g#%jEA"zH.㩮DfaI"8{I`zILtV>6Ҕp{،xZjzaEPGs>a5,Ś8'-LD׏`i1VޟwW:>B}A(ƫbWS%߮jsW[#6%z7ysށ[Cv^ SżOCԷ7U; +lZ>vMdȨى yAjX4(m?12zc8?W~m?~BNl"m3v?{?}f -7n@N;`޷C5^|æ+YЀv+Uв7<|Mgpzt՟tՀy* -n<۰ט#%s/@΁a΁T3=TQ?C5w;_GN ѺY7!?t,Ȥ)T7C{ZC R03La< S,1j0{ -SCB| Lu70hCS'At/@Icn0yHC'm'";y0!p^f Y_mhA&"p:@=(S{1\={Q 8jZ'eXl^16qvsyz=0=0LhF9?IOvw/j?P:2-dUG_KӁQ+1>LY^cTepNl|wiK4? 0g -endstream -endobj -2810 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2811 0 obj -<< -/Subtype /Link -/A 2810 0 R -/Type /Annot -/Rect [72 695.502 180.18 720] -/Border [0 0 0] ->> -endobj -2812 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2813 0 obj -<< -/Subtype /Link -/A 2812 0 R -/Type /Annot -/Rect [72 673.002 535.549805 685.502] -/Border [0 0 0] ->> -endobj -2814 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2815 0 obj -<< -/Subtype /Link -/A 2814 0 R -/Type /Annot -/Rect [72 660.502 243.401367 673.002] -/Border [0 0 0] ->> -endobj -2816 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2817 0 obj -<< -/Subtype /Link -/A 2816 0 R -/Type /Annot -/Rect [243.401367 660.432 267.401367 673.002] -/Border [0 0 0] ->> -endobj -2818 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2819 0 obj -<< -/Subtype /Link -/A 2818 0 R -/Type /Annot -/Rect [267.401367 660.502 291.112305 673.002] -/Border [0 0 0] ->> -endobj -2820 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2821 0 obj -<< -/Subtype /Link -/A 2820 0 R -/Type /Annot -/Rect [291.112305 660.432 369.112305 673.002] -/Border [0 0 0] ->> -endobj -2822 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2823 0 obj -<< -/Subtype /Link -/A 2822 0 R -/Type /Annot -/Rect [369.112305 660.502 511.392578 673.002] -/Border [0 0 0] ->> -endobj -2824 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2825 0 obj -<< -/Subtype /Link -/A 2824 0 R -/Type /Annot -/Rect [72 648.002 187.097656 660.502] -/Border [0 0 0] ->> -endobj -2826 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2827 0 obj -<< -/Subtype /Link -/A 2826 0 R -/Type /Annot -/Rect [187.097656 647.932 235.097656 660.502] -/Border [0 0 0] ->> -endobj -2828 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2829 0 obj -<< -/Subtype /Link -/A 2828 0 R -/Type /Annot -/Rect [235.097656 648.002 258.808594 660.502] -/Border [0 0 0] ->> -endobj -2830 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2831 0 obj -<< -/Subtype /Link -/A 2830 0 R -/Type /Annot -/Rect [258.808594 647.932 306.808594 660.502] -/Border [0 0 0] ->> -endobj -2832 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2833 0 obj -<< -/Subtype /Link -/A 2832 0 R -/Type /Annot -/Rect [306.808594 648.002 310.255859 660.502] -/Border [0 0 0] ->> -endobj -2834 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2835 0 obj -<< -/Subtype /Link -/A 2834 0 R -/Type /Annot -/Rect [72 626.689 158.4 638.002] -/Border [0 0 0] ->> -endobj -2836 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2837 0 obj -<< -/Subtype /Link -/A 2836 0 R -/Type /Annot -/Rect [72 615.376 88.2 626.689] -/Border [0 0 0] ->> -endobj -2838 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2839 0 obj -<< -/Subtype /Link -/A 2838 0 R -/Type /Annot -/Rect [88.2 615.376 93.6 626.689] -/Border [0 0 0] ->> -endobj -2840 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2841 0 obj -<< -/Subtype /Link -/A 2840 0 R -/Type /Annot -/Rect [93.6 615.376 142.2 626.689] -/Border [0 0 0] ->> -endobj -2842 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2843 0 obj -<< -/Subtype /Link -/A 2842 0 R -/Type /Annot -/Rect [142.2 615.376 147.6 626.689] -/Border [0 0 0] ->> -endobj -2844 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2845 0 obj -<< -/Subtype /Link -/A 2844 0 R -/Type /Annot -/Rect [147.6 615.376 174.6 626.689] -/Border [0 0 0] ->> -endobj -2846 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2847 0 obj -<< -/Subtype /Link -/A 2846 0 R -/Type /Annot -/Rect [174.6 615.376 180 626.689] -/Border [0 0 0] ->> -endobj -2848 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2849 0 obj -<< -/Subtype /Link -/A 2848 0 R -/Type /Annot -/Rect [72 604.063 88.2 615.376] -/Border [0 0 0] ->> -endobj -2850 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2851 0 obj -<< -/Subtype /Link -/A 2850 0 R -/Type /Annot -/Rect [88.2 604.063 93.6 615.376] -/Border [0 0 0] ->> -endobj -2852 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2853 0 obj -<< -/Subtype /Link -/A 2852 0 R -/Type /Annot -/Rect [93.6 604.063 142.2 615.376] -/Border [0 0 0] ->> -endobj -2854 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2855 0 obj -<< -/Subtype /Link -/A 2854 0 R -/Type /Annot -/Rect [142.2 604.063 147.6 615.376] -/Border [0 0 0] ->> -endobj -2856 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2857 0 obj -<< -/Subtype /Link -/A 2856 0 R -/Type /Annot -/Rect [147.6 604.063 153 615.376] -/Border [0 0 0] ->> -endobj -2858 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2859 0 obj -<< -/Subtype /Link -/A 2858 0 R -/Type /Annot -/Rect [153 604.063 169.2 615.376] -/Border [0 0 0] ->> -endobj -2860 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2861 0 obj -<< -/Subtype /Link -/A 2860 0 R -/Type /Annot -/Rect [169.2 604.063 174.6 615.376] -/Border [0 0 0] ->> -endobj -2862 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2863 0 obj -<< -/Subtype /Link -/A 2862 0 R -/Type /Annot -/Rect [174.6 604.063 180 615.376] -/Border [0 0 0] ->> -endobj -2864 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2865 0 obj -<< -/Subtype /Link -/A 2864 0 R -/Type /Annot -/Rect [180 604.063 185.4 615.376] -/Border [0 0 0] ->> -endobj -2866 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2867 0 obj -<< -/Subtype /Link -/A 2866 0 R -/Type /Annot -/Rect [185.4 604.063 196.2 615.376] -/Border [0 0 0] ->> -endobj -2868 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2869 0 obj -<< -/Subtype /Link -/A 2868 0 R -/Type /Annot -/Rect [196.2 604.063 201.6 615.376] -/Border [0 0 0] ->> -endobj -2870 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2871 0 obj -<< -/Subtype /Link -/A 2870 0 R -/Type /Annot -/Rect [72 592.75 88.2 604.063] -/Border [0 0 0] ->> -endobj -2872 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2873 0 obj -<< -/Subtype /Link -/A 2872 0 R -/Type /Annot -/Rect [88.2 592.75 93.6 604.063] -/Border [0 0 0] ->> -endobj -2874 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2875 0 obj -<< -/Subtype /Link -/A 2874 0 R -/Type /Annot -/Rect [93.6 592.75 120.6 604.063] -/Border [0 0 0] ->> -endobj -2876 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2877 0 obj -<< -/Subtype /Link -/A 2876 0 R -/Type /Annot -/Rect [120.6 592.75 126 604.063] -/Border [0 0 0] ->> -endobj -2878 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2879 0 obj -<< -/Subtype /Link -/A 2878 0 R -/Type /Annot -/Rect [126 592.75 142.2 604.063] -/Border [0 0 0] ->> -endobj -2880 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2881 0 obj -<< -/Subtype /Link -/A 2880 0 R -/Type /Annot -/Rect [142.2 592.75 147.6 604.063] -/Border [0 0 0] ->> -endobj -2882 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2883 0 obj -<< -/Subtype /Link -/A 2882 0 R -/Type /Annot -/Rect [147.6 592.75 153 604.063] -/Border [0 0 0] ->> -endobj -2884 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2885 0 obj -<< -/Subtype /Link -/A 2884 0 R -/Type /Annot -/Rect [72 570.124 325.8 581.437] -/Border [0 0 0] ->> -endobj -2886 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2887 0 obj -<< -/Subtype /Link -/A 2886 0 R -/Type /Annot -/Rect [72 558.811 88.2 570.124] -/Border [0 0 0] ->> -endobj -2888 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2889 0 obj -<< -/Subtype /Link -/A 2888 0 R -/Type /Annot -/Rect [88.2 558.811 93.6 570.124] -/Border [0 0 0] ->> -endobj -2890 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2891 0 obj -<< -/Subtype /Link -/A 2890 0 R -/Type /Annot -/Rect [93.6 558.811 115.2 570.124] -/Border [0 0 0] ->> -endobj -2892 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2893 0 obj -<< -/Subtype /Link -/A 2892 0 R -/Type /Annot -/Rect [115.2 558.811 120.6 570.124] -/Border [0 0 0] ->> -endobj -2894 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2895 0 obj -<< -/Subtype /Link -/A 2894 0 R -/Type /Annot -/Rect [120.6 558.811 369 570.124] -/Border [0 0 0] ->> -endobj -2896 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2897 0 obj -<< -/Subtype /Link -/A 2896 0 R -/Type /Annot -/Rect [369 558.811 374.4 570.124] -/Border [0 0 0] ->> -endobj -2898 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2899 0 obj -<< -/Subtype /Link -/A 2898 0 R -/Type /Annot -/Rect [72 547.498 88.2 558.811] -/Border [0 0 0] ->> -endobj -2900 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2901 0 obj -<< -/Subtype /Link -/A 2900 0 R -/Type /Annot -/Rect [88.2 547.498 93.6 558.811] -/Border [0 0 0] ->> -endobj -2902 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2903 0 obj -<< -/Subtype /Link -/A 2902 0 R -/Type /Annot -/Rect [93.6 547.498 115.2 558.811] -/Border [0 0 0] ->> -endobj -2904 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2905 0 obj -<< -/Subtype /Link -/A 2904 0 R -/Type /Annot -/Rect [115.2 547.498 120.6 558.811] -/Border [0 0 0] ->> -endobj -2906 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2907 0 obj -<< -/Subtype /Link -/A 2906 0 R -/Type /Annot -/Rect [120.6 547.498 174.6 558.811] -/Border [0 0 0] ->> -endobj -2908 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2909 0 obj -<< -/Subtype /Link -/A 2908 0 R -/Type /Annot -/Rect [174.6 547.498 180 558.811] -/Border [0 0 0] ->> -endobj -2910 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2911 0 obj -<< -/Subtype /Link -/A 2910 0 R -/Type /Annot -/Rect [180 547.498 185.4 558.811] -/Border [0 0 0] ->> -endobj -2912 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2913 0 obj -<< -/Subtype /Link -/A 2912 0 R -/Type /Annot -/Rect [72 524.872 325.8 536.185] -/Border [0 0 0] ->> -endobj -2914 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2915 0 obj -<< -/Subtype /Link -/A 2914 0 R -/Type /Annot -/Rect [72 513.559 88.2 524.872] -/Border [0 0 0] ->> -endobj -2916 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2917 0 obj -<< -/Subtype /Link -/A 2916 0 R -/Type /Annot -/Rect [88.2 513.559 93.6 524.872] -/Border [0 0 0] ->> -endobj -2918 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2919 0 obj -<< -/Subtype /Link -/A 2918 0 R -/Type /Annot -/Rect [93.6 513.559 142.2 524.872] -/Border [0 0 0] ->> -endobj -2920 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2921 0 obj -<< -/Subtype /Link -/A 2920 0 R -/Type /Annot -/Rect [142.2 513.559 147.6 524.872] -/Border [0 0 0] ->> -endobj -2922 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2923 0 obj -<< -/Subtype /Link -/A 2922 0 R -/Type /Annot -/Rect [147.6 513.559 163.8 524.872] -/Border [0 0 0] ->> -endobj -2924 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2925 0 obj -<< -/Subtype /Link -/A 2924 0 R -/Type /Annot -/Rect [163.8 513.559 169.2 524.872] -/Border [0 0 0] ->> -endobj -2926 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2927 0 obj -<< -/Subtype /Link -/A 2926 0 R -/Type /Annot -/Rect [169.2 513.559 174.6 524.872] -/Border [0 0 0] ->> -endobj -2928 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2929 0 obj -<< -/Subtype /Link -/A 2928 0 R -/Type /Annot -/Rect [174.6 513.559 180 524.872] -/Border [0 0 0] ->> -endobj -2930 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2931 0 obj -<< -/Subtype /Link -/A 2930 0 R -/Type /Annot -/Rect [180 513.559 185.4 524.872] -/Border [0 0 0] ->> -endobj -2932 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2933 0 obj -<< -/Subtype /Link -/A 2932 0 R -/Type /Annot -/Rect [72 502.246 88.2 513.559] -/Border [0 0 0] ->> -endobj -2934 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2935 0 obj -<< -/Subtype /Link -/A 2934 0 R -/Type /Annot -/Rect [88.2 502.246 93.6 513.559] -/Border [0 0 0] ->> -endobj -2936 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2937 0 obj -<< -/Subtype /Link -/A 2936 0 R -/Type /Annot -/Rect [93.6 502.246 115.2 513.559] -/Border [0 0 0] ->> -endobj -2938 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2939 0 obj -<< -/Subtype /Link -/A 2938 0 R -/Type /Annot -/Rect [115.2 502.246 120.6 513.559] -/Border [0 0 0] ->> -endobj -2940 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2941 0 obj -<< -/Subtype /Link -/A 2940 0 R -/Type /Annot -/Rect [120.6 502.246 369 513.559] -/Border [0 0 0] ->> -endobj -2942 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2943 0 obj -<< -/Subtype /Link -/A 2942 0 R -/Type /Annot -/Rect [369 502.246 374.4 513.559] -/Border [0 0 0] ->> -endobj -2944 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2945 0 obj -<< -/Subtype /Link -/A 2944 0 R -/Type /Annot -/Rect [72 490.933 88.2 502.246] -/Border [0 0 0] ->> -endobj -2946 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2947 0 obj -<< -/Subtype /Link -/A 2946 0 R -/Type /Annot -/Rect [88.2 490.933 93.6 502.246] -/Border [0 0 0] ->> -endobj -2948 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2949 0 obj -<< -/Subtype /Link -/A 2948 0 R -/Type /Annot -/Rect [93.6 490.933 115.2 502.246] -/Border [0 0 0] ->> -endobj -2950 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2951 0 obj -<< -/Subtype /Link -/A 2950 0 R -/Type /Annot -/Rect [115.2 490.933 120.6 502.246] -/Border [0 0 0] ->> -endobj -2952 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2953 0 obj -<< -/Subtype /Link -/A 2952 0 R -/Type /Annot -/Rect [120.6 490.933 174.6 502.246] -/Border [0 0 0] ->> -endobj -2954 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2955 0 obj -<< -/Subtype /Link -/A 2954 0 R -/Type /Annot -/Rect [174.6 490.933 180 502.246] -/Border [0 0 0] ->> -endobj -2956 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2957 0 obj -<< -/Subtype /Link -/A 2956 0 R -/Type /Annot -/Rect [180 490.933 185.4 502.246] -/Border [0 0 0] ->> -endobj -2958 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2959 0 obj -<< -/Subtype /Link -/A 2958 0 R -/Type /Annot -/Rect [72 468.433 212.585938 480.933] -/Border [0 0 0] ->> -endobj -2960 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2961 0 obj -<< -/Subtype /Link -/A 2960 0 R -/Type /Annot -/Rect [212.585938 468.363 242.585938 480.933] -/Border [0 0 0] ->> -endobj -2962 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2963 0 obj -<< -/Subtype /Link -/A 2962 0 R -/Type /Annot -/Rect [242.585938 468.433 266.296875 480.933] -/Border [0 0 0] ->> -endobj -2964 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2965 0 obj -<< -/Subtype /Link -/A 2964 0 R -/Type /Annot -/Rect [266.296875 468.363 320.296875 480.933] -/Border [0 0 0] ->> -endobj -2966 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2967 0 obj -<< -/Subtype /Link -/A 2966 0 R -/Type /Annot -/Rect [320.296875 468.433 519.891602 480.933] -/Border [0 0 0] ->> -endobj -2968 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2969 0 obj -<< -/Subtype /Link -/A 2968 0 R -/Type /Annot -/Rect [72 455.933 501.462891 468.433] -/Border [0 0 0] ->> -endobj -2808 0 obj -<< -/Type /Page -/Parent 1 0 R -/MediaBox [0 0 612 792] -/Contents 2806 0 R -/Resources 2807 0 R -/Annots [2811 0 R 2813 0 R 2815 0 R 2817 0 R 2819 0 R 2821 0 R 2823 0 R 2825 0 R 2827 0 R 2829 0 R 2831 0 R 2833 0 R 2835 0 R 2837 0 R 2839 0 R 2841 0 R 2843 0 R 2845 0 R 2847 0 R 2849 0 R 2851 0 R 2853 0 R 2855 0 R 2857 0 R 2859 0 R 2861 0 R 2863 0 R 2865 0 R 2867 0 R 2869 0 R 2871 0 R 2873 0 R 2875 0 R 2877 0 R 2879 0 R 2881 0 R 2883 0 R 2885 0 R 2887 0 R 2889 0 R 2891 0 R 2893 0 R 2895 0 R 2897 0 R 2899 0 R 2901 0 R 2903 0 R 2905 0 R 2907 0 R 2909 0 R 2911 0 R 2913 0 R 2915 0 R 2917 0 R 2919 0 R 2921 0 R 2923 0 R 2925 0 R 2927 0 R 2929 0 R 2931 0 R 2933 0 R 2935 0 R 2937 0 R 2939 0 R 2941 0 R 2943 0 R 2945 0 R 2947 0 R 2949 0 R 2951 0 R 2953 0 R 2955 0 R 2957 0 R 2959 0 R 2961 0 R 2963 0 R 2965 0 R 2967 0 R 2969 0 R] ->> -endobj -2807 0 obj -<< -/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] -/Font << -/F4 16 0 R -/F3 9 0 R -/F6 44 0 R -/F5 29 0 R ->> ->> -endobj -2806 0 obj -<< -/Length 1539 -/Filter /FlateDecode ->> -stream -x[Ko6 ϯ@TQoE>ZV0Z[XL=Ʊm'pl˲D~")RG՜>/?~hN2?tFu?2l89vw{9rŘ=vhw% 5h GWl>sn=sDnۃ6 ul/Jeވd Ez=~f·Q).RaswI9$w8*XtWl)P;YXIm27)UJ}ۦz> -endobj -2975 0 obj -<< -/Subtype /Link -/A 2974 0 R -/Type /Annot -/Rect [72 695.502 365.778 720] -/Border [0 0 0] ->> -endobj -2976 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2977 0 obj -<< -/Subtype /Link -/A 2976 0 R -/Type /Annot -/Rect [72 673.002 536.326172 685.502] -/Border [0 0 0] ->> -endobj -2978 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2979 0 obj -<< -/Subtype /Link -/A 2978 0 R -/Type /Annot -/Rect [72 660.502 531.941406 673.002] -/Border [0 0 0] ->> -endobj -2980 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2981 0 obj -<< -/Subtype /Link -/A 2980 0 R -/Type /Annot -/Rect [72 648.002 506.106445 660.502] -/Border [0 0 0] ->> -endobj -2982 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2983 0 obj -<< -/Subtype /Link -/A 2982 0 R -/Type /Annot -/Rect [72 635.502 297.961914 648.002] -/Border [0 0 0] ->> -endobj -2984 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2985 0 obj -<< -/Subtype /Link -/A 2984 0 R -/Type /Annot -/Rect [297.961914 635.432 321.961914 648.002] -/Border [0 0 0] ->> -endobj -2986 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2987 0 obj -<< -/Subtype /Link -/A 2986 0 R -/Type /Annot -/Rect [321.961914 635.502 516.385742 648.002] -/Border [0 0 0] ->> -endobj -2988 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2989 0 obj -<< -/Subtype /Link -/A 2988 0 R -/Type /Annot -/Rect [72 623.002 318.098633 635.502] -/Border [0 0 0] ->> -endobj -2990 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2991 0 obj -<< -/Subtype /Link -/A 2990 0 R -/Type /Annot -/Rect [318.098633 622.932 360.098633 635.502] -/Border [0 0 0] ->> -endobj -2992 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2993 0 obj -<< -/Subtype /Link -/A 2992 0 R -/Type /Annot -/Rect [360.098633 623.002 507.745117 635.502] -/Border [0 0 0] ->> -endobj -2994 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2995 0 obj -<< -/Subtype /Link -/A 2994 0 R -/Type /Annot -/Rect [72 610.502 531.223633 623.002] -/Border [0 0 0] ->> -endobj -2996 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2997 0 obj -<< -/Subtype /Link -/A 2996 0 R -/Type /Annot -/Rect [72 598.002 348.030273 610.502] -/Border [0 0 0] ->> -endobj -2998 0 obj -<< -/S /URI -/URI (false) ->> -endobj -2999 0 obj -<< -/Subtype /Link -/A 2998 0 R -/Type /Annot -/Rect [72 563.504 199.872 588.002] -/Border [0 0 0] ->> -endobj -3000 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3001 0 obj -<< -/Subtype /Link -/A 3000 0 R -/Type /Annot -/Rect [72 541.004 523.987305 553.504] -/Border [0 0 0] ->> -endobj -3002 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3003 0 obj -<< -/Subtype /Link -/A 3002 0 R -/Type /Annot -/Rect [72 528.504 533.12793 541.004] -/Border [0 0 0] ->> -endobj -3004 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3005 0 obj -<< -/Subtype /Link -/A 3004 0 R -/Type /Annot -/Rect [72 516.004 279.119141 528.504] -/Border [0 0 0] ->> -endobj -3006 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3007 0 obj -<< -/Subtype /Link -/A 3006 0 R -/Type /Annot -/Rect [279.119141 515.934 333.119141 528.504] -/Border [0 0 0] ->> -endobj -3008 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3009 0 obj -<< -/Subtype /Link -/A 3008 0 R -/Type /Annot -/Rect [333.119141 516.004 339.017578 528.504] -/Border [0 0 0] ->> -endobj -3010 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3011 0 obj -<< -/Subtype /Link -/A 3010 0 R -/Type /Annot -/Rect [339.017578 515.934 375.017578 528.504] -/Border [0 0 0] ->> -endobj -3012 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3013 0 obj -<< -/Subtype /Link -/A 3012 0 R -/Type /Annot -/Rect [375.017578 516.004 398.728516 528.504] -/Border [0 0 0] ->> -endobj -3014 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3015 0 obj -<< -/Subtype /Link -/A 3014 0 R -/Type /Annot -/Rect [398.728516 515.934 428.728516 528.504] -/Border [0 0 0] ->> -endobj -3016 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3017 0 obj -<< -/Subtype /Link -/A 3016 0 R -/Type /Annot -/Rect [428.728516 516.004 432.175781 528.504] -/Border [0 0 0] ->> -endobj -3018 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3019 0 obj -<< -/Subtype /Link -/A 3018 0 R -/Type /Annot -/Rect [72 493.504 93.201172 506.004] -/Border [0 0 0] ->> -endobj -3020 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3021 0 obj -<< -/Subtype /Link -/A 3020 0 R -/Type /Annot -/Rect [93.201172 493.434 147.201172 506.004] -/Border [0 0 0] ->> -endobj -3022 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3023 0 obj -<< -/Subtype /Link -/A 3022 0 R -/Type /Annot -/Rect [147.201172 493.504 339.55957 506.004] -/Border [0 0 0] ->> -endobj -3024 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3025 0 obj -<< -/Subtype /Link -/A 3024 0 R -/Type /Annot -/Rect [339.55957 493.434 345.55957 506.004] -/Border [0 0 0] ->> -endobj -3026 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3027 0 obj -<< -/Subtype /Link -/A 3026 0 R -/Type /Annot -/Rect [345.55957 493.504 369.270508 506.004] -/Border [0 0 0] ->> -endobj -3028 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3029 0 obj -<< -/Subtype /Link -/A 3028 0 R -/Type /Annot -/Rect [369.270508 493.434 375.270508 506.004] -/Border [0 0 0] ->> -endobj -3030 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3031 0 obj -<< -/Subtype /Link -/A 3030 0 R -/Type /Annot -/Rect [375.270508 493.504 511.686523 506.004] -/Border [0 0 0] ->> -endobj -3032 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3033 0 obj -<< -/Subtype /Link -/A 3032 0 R -/Type /Annot -/Rect [72 481.004 391.638672 493.504] -/Border [0 0 0] ->> -endobj -3034 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3035 0 obj -<< -/Subtype /Link -/A 3034 0 R -/Type /Annot -/Rect [391.638672 480.934 397.638672 493.504] -/Border [0 0 0] ->> -endobj -3036 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3037 0 obj -<< -/Subtype /Link -/A 3036 0 R -/Type /Annot -/Rect [397.638672 481.004 421.349609 493.504] -/Border [0 0 0] ->> -endobj -3038 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3039 0 obj -<< -/Subtype /Link -/A 3038 0 R -/Type /Annot -/Rect [421.349609 480.934 427.349609 493.504] -/Border [0 0 0] ->> -endobj -3040 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3041 0 obj -<< -/Subtype /Link -/A 3040 0 R -/Type /Annot -/Rect [427.349609 481.004 459.136719 493.504] -/Border [0 0 0] ->> -endobj -3042 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3043 0 obj -<< -/Subtype /Link -/A 3042 0 R -/Type /Annot -/Rect [72 458.504 93.201172 471.004] -/Border [0 0 0] ->> -endobj -3044 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3045 0 obj -<< -/Subtype /Link -/A 3044 0 R -/Type /Annot -/Rect [93.201172 458.434 129.201172 471.004] -/Border [0 0 0] ->> -endobj -3046 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3047 0 obj -<< -/Subtype /Link -/A 3046 0 R -/Type /Annot -/Rect [129.201172 458.504 451.173828 471.004] -/Border [0 0 0] ->> -endobj -3048 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3049 0 obj -<< -/Subtype /Link -/A 3048 0 R -/Type /Annot -/Rect [451.173828 458.434 487.173828 471.004] -/Border [0 0 0] ->> -endobj -3050 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3051 0 obj -<< -/Subtype /Link -/A 3050 0 R -/Type /Annot -/Rect [487.173828 458.504 539.097656 471.004] -/Border [0 0 0] ->> -endobj -3052 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3053 0 obj -<< -/Subtype /Link -/A 3052 0 R -/Type /Annot -/Rect [72 446.004 192.380859 458.504] -/Border [0 0 0] ->> -endobj -3054 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3055 0 obj -<< -/Subtype /Link -/A 3054 0 R -/Type /Annot -/Rect [192.380859 445.934 222.380859 458.504] -/Border [0 0 0] ->> -endobj -3056 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3057 0 obj -<< -/Subtype /Link -/A 3056 0 R -/Type /Annot -/Rect [222.380859 446.004 359.77832 458.504] -/Border [0 0 0] ->> -endobj -3058 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3059 0 obj -<< -/Subtype /Link -/A 3058 0 R -/Type /Annot -/Rect [359.77832 445.934 395.77832 458.504] -/Border [0 0 0] ->> -endobj -3060 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3061 0 obj -<< -/Subtype /Link -/A 3060 0 R -/Type /Annot -/Rect [395.77832 446.004 524.225586 458.504] -/Border [0 0 0] ->> -endobj -3062 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3063 0 obj -<< -/Subtype /Link -/A 3062 0 R -/Type /Annot -/Rect [72 433.504 245.374023 446.004] -/Border [0 0 0] ->> -endobj -3064 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3065 0 obj -<< -/Subtype /Link -/A 3064 0 R -/Type /Annot -/Rect [72 411.004 93.201172 423.504] -/Border [0 0 0] ->> -endobj -3066 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3067 0 obj -<< -/Subtype /Link -/A 3066 0 R -/Type /Annot -/Rect [93.201172 410.934 123.201172 423.504] -/Border [0 0 0] ->> -endobj -3068 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3069 0 obj -<< -/Subtype /Link -/A 3068 0 R -/Type /Annot -/Rect [123.201172 411.004 382.59082 423.504] -/Border [0 0 0] ->> -endobj -3070 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3071 0 obj -<< -/Subtype /Link -/A 3070 0 R -/Type /Annot -/Rect [382.59082 410.934 418.59082 423.504] -/Border [0 0 0] ->> -endobj -3072 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3073 0 obj -<< -/Subtype /Link -/A 3072 0 R -/Type /Annot -/Rect [418.59082 411.004 525.958984 423.504] -/Border [0 0 0] ->> -endobj -3074 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3075 0 obj -<< -/Subtype /Link -/A 3074 0 R -/Type /Annot -/Rect [72 398.504 156.658203 411.004] -/Border [0 0 0] ->> -endobj -3076 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3077 0 obj -<< -/Subtype /Link -/A 3076 0 R -/Type /Annot -/Rect [156.658203 398.434 192.658203 411.004] -/Border [0 0 0] ->> -endobj -3078 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3079 0 obj -<< -/Subtype /Link -/A 3078 0 R -/Type /Annot -/Rect [192.658203 398.504 514.206055 411.004] -/Border [0 0 0] ->> -endobj -3080 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3081 0 obj -<< -/Subtype /Link -/A 3080 0 R -/Type /Annot -/Rect [72 386.004 432.463867 398.504] -/Border [0 0 0] ->> -endobj -3082 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3083 0 obj -<< -/Subtype /Link -/A 3082 0 R -/Type /Annot -/Rect [432.463867 385.934 450.463867 398.504] -/Border [0 0 0] ->> -endobj -3084 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3085 0 obj -<< -/Subtype /Link -/A 3084 0 R -/Type /Annot -/Rect [450.463867 386.004 535.029297 398.504] -/Border [0 0 0] ->> -endobj -3086 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3087 0 obj -<< -/Subtype /Link -/A 3086 0 R -/Type /Annot -/Rect [72 373.504 281.267578 386.004] -/Border [0 0 0] ->> -endobj -3088 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3089 0 obj -<< -/Subtype /Link -/A 3088 0 R -/Type /Annot -/Rect [281.267578 373.434 287.267578 386.004] -/Border [0 0 0] ->> -endobj -3090 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3091 0 obj -<< -/Subtype /Link -/A 3090 0 R -/Type /Annot -/Rect [287.267578 373.504 470.216797 386.004] -/Border [0 0 0] ->> -endobj -3092 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3093 0 obj -<< -/Subtype /Link -/A 3092 0 R -/Type /Annot -/Rect [72 351.004 510.662109 363.504] -/Border [0 0 0] ->> -endobj -3094 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3095 0 obj -<< -/Subtype /Link -/A 3094 0 R -/Type /Annot -/Rect [72 338.504 121.213867 351.004] -/Border [0 0 0] ->> -endobj -3096 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3097 0 obj -<< -/Subtype /Link -/A 3096 0 R -/Type /Annot -/Rect [121.213867 338.434 175.213867 351.004] -/Border [0 0 0] ->> -endobj -3098 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3099 0 obj -<< -/Subtype /Link -/A 3098 0 R -/Type /Annot -/Rect [175.213867 338.504 220.18457 351.004] -/Border [0 0 0] ->> -endobj -3100 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3101 0 obj -<< -/Subtype /Link -/A 3100 0 R -/Type /Annot -/Rect [72 316.004 135.378906 328.504] -/Border [0 0 0] ->> -endobj -3102 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3103 0 obj -<< -/Subtype /Link -/A 3102 0 R -/Type /Annot -/Rect [135.378906 315.934 165.378906 328.504] -/Border [0 0 0] ->> -endobj -3104 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3105 0 obj -<< -/Subtype /Link -/A 3104 0 R -/Type /Annot -/Rect [165.378906 316.004 189.089844 328.504] -/Border [0 0 0] ->> -endobj -3106 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3107 0 obj -<< -/Subtype /Link -/A 3106 0 R -/Type /Annot -/Rect [189.089844 315.934 243.089844 328.504] -/Border [0 0 0] ->> -endobj -3108 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3109 0 obj -<< -/Subtype /Link -/A 3108 0 R -/Type /Annot -/Rect [243.089844 316.004 536.913086 328.504] -/Border [0 0 0] ->> -endobj -3110 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3111 0 obj -<< -/Subtype /Link -/A 3110 0 R -/Type /Annot -/Rect [72 303.364 108 315.934] -/Border [0 0 0] ->> -endobj -3112 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3113 0 obj -<< -/Subtype /Link -/A 3112 0 R -/Type /Annot -/Rect [108 303.434 515.255859 315.934] -/Border [0 0 0] ->> -endobj -3114 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3115 0 obj -<< -/Subtype /Link -/A 3114 0 R -/Type /Annot -/Rect [72 282.121 88.2 293.434] -/Border [0 0 0] ->> -endobj -3116 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3117 0 obj -<< -/Subtype /Link -/A 3116 0 R -/Type /Annot -/Rect [88.2 282.121 93.6 293.434] -/Border [0 0 0] ->> -endobj -3118 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3119 0 obj -<< -/Subtype /Link -/A 3118 0 R -/Type /Annot -/Rect [93.6 282.121 126 293.434] -/Border [0 0 0] ->> -endobj -3120 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3121 0 obj -<< -/Subtype /Link -/A 3120 0 R -/Type /Annot -/Rect [126 282.121 131.4 293.434] -/Border [0 0 0] ->> -endobj -3122 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3123 0 obj -<< -/Subtype /Link -/A 3122 0 R -/Type /Annot -/Rect [131.4 282.121 142.2 293.434] -/Border [0 0 0] ->> -endobj -3124 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3125 0 obj -<< -/Subtype /Link -/A 3124 0 R -/Type /Annot -/Rect [142.2 282.121 147.6 293.434] -/Border [0 0 0] ->> -endobj -3126 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3127 0 obj -<< -/Subtype /Link -/A 3126 0 R -/Type /Annot -/Rect [147.6 282.121 153 293.434] -/Border [0 0 0] ->> -endobj -3128 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3129 0 obj -<< -/Subtype /Link -/A 3128 0 R -/Type /Annot -/Rect [153 282.121 158.4 293.434] -/Border [0 0 0] ->> -endobj -3130 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3131 0 obj -<< -/Subtype /Link -/A 3130 0 R -/Type /Annot -/Rect [158.4 282.121 190.8 293.434] -/Border [0 0 0] ->> -endobj -3132 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3133 0 obj -<< -/Subtype /Link -/A 3132 0 R -/Type /Annot -/Rect [190.8 282.121 196.2 293.434] -/Border [0 0 0] ->> -endobj -3134 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3135 0 obj -<< -/Subtype /Link -/A 3134 0 R -/Type /Annot -/Rect [196.2 282.121 201.6 293.434] -/Border [0 0 0] ->> -endobj -3136 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3137 0 obj -<< -/Subtype /Link -/A 3136 0 R -/Type /Annot -/Rect [201.6 282.121 207 293.434] -/Border [0 0 0] ->> -endobj -3138 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3139 0 obj -<< -/Subtype /Link -/A 3138 0 R -/Type /Annot -/Rect [207 282.121 223.2 293.434] -/Border [0 0 0] ->> -endobj -3140 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3141 0 obj -<< -/Subtype /Link -/A 3140 0 R -/Type /Annot -/Rect [223.2 282.121 228.6 293.434] -/Border [0 0 0] ->> -endobj -3142 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3143 0 obj -<< -/Subtype /Link -/A 3142 0 R -/Type /Annot -/Rect [228.6 282.121 234 293.434] -/Border [0 0 0] ->> -endobj -3144 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3145 0 obj -<< -/Subtype /Link -/A 3144 0 R -/Type /Annot -/Rect [234 282.121 244.8 293.434] -/Border [0 0 0] ->> -endobj -3146 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3147 0 obj -<< -/Subtype /Link -/A 3146 0 R -/Type /Annot -/Rect [244.8 282.121 250.2 293.434] -/Border [0 0 0] ->> -endobj -3148 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3149 0 obj -<< -/Subtype /Link -/A 3148 0 R -/Type /Annot -/Rect [250.2 282.121 255.6 293.434] -/Border [0 0 0] ->> -endobj -3150 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3151 0 obj -<< -/Subtype /Link -/A 3150 0 R -/Type /Annot -/Rect [255.6 282.121 261 293.434] -/Border [0 0 0] ->> -endobj -3152 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3153 0 obj -<< -/Subtype /Link -/A 3152 0 R -/Type /Annot -/Rect [72 270.808 88.2 282.121] -/Border [0 0 0] ->> -endobj -3154 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3155 0 obj -<< -/Subtype /Link -/A 3154 0 R -/Type /Annot -/Rect [88.2 270.808 93.6 282.121] -/Border [0 0 0] ->> -endobj -3156 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3157 0 obj -<< -/Subtype /Link -/A 3156 0 R -/Type /Annot -/Rect [93.6 270.808 115.2 282.121] -/Border [0 0 0] ->> -endobj -3158 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3159 0 obj -<< -/Subtype /Link -/A 3158 0 R -/Type /Annot -/Rect [115.2 270.808 120.6 282.121] -/Border [0 0 0] ->> -endobj -3160 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3161 0 obj -<< -/Subtype /Link -/A 3160 0 R -/Type /Annot -/Rect [120.6 270.808 136.8 282.121] -/Border [0 0 0] ->> -endobj -3162 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3163 0 obj -<< -/Subtype /Link -/A 3162 0 R -/Type /Annot -/Rect [136.8 270.808 142.2 282.121] -/Border [0 0 0] ->> -endobj -3164 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3165 0 obj -<< -/Subtype /Link -/A 3164 0 R -/Type /Annot -/Rect [142.2 270.808 147.6 282.121] -/Border [0 0 0] ->> -endobj -3166 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3167 0 obj -<< -/Subtype /Link -/A 3166 0 R -/Type /Annot -/Rect [147.6 270.808 158.4 282.121] -/Border [0 0 0] ->> -endobj -3168 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3169 0 obj -<< -/Subtype /Link -/A 3168 0 R -/Type /Annot -/Rect [158.4 270.808 163.8 282.121] -/Border [0 0 0] ->> -endobj -3170 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3171 0 obj -<< -/Subtype /Link -/A 3170 0 R -/Type /Annot -/Rect [163.8 270.808 169.2 282.121] -/Border [0 0 0] ->> -endobj -3172 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3173 0 obj -<< -/Subtype /Link -/A 3172 0 R -/Type /Annot -/Rect [169.2 270.808 185.4 282.121] -/Border [0 0 0] ->> -endobj -3174 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3175 0 obj -<< -/Subtype /Link -/A 3174 0 R -/Type /Annot -/Rect [185.4 270.808 190.8 282.121] -/Border [0 0 0] ->> -endobj -3176 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3177 0 obj -<< -/Subtype /Link -/A 3176 0 R -/Type /Annot -/Rect [190.8 270.808 196.2 282.121] -/Border [0 0 0] ->> -endobj -3178 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3179 0 obj -<< -/Subtype /Link -/A 3178 0 R -/Type /Annot -/Rect [196.2 270.808 212.4 282.121] -/Border [0 0 0] ->> -endobj -3180 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3181 0 obj -<< -/Subtype /Link -/A 3180 0 R -/Type /Annot -/Rect [212.4 270.808 217.8 282.121] -/Border [0 0 0] ->> -endobj -3182 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3183 0 obj -<< -/Subtype /Link -/A 3182 0 R -/Type /Annot -/Rect [72 259.495 88.2 270.808] -/Border [0 0 0] ->> -endobj -3184 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3185 0 obj -<< -/Subtype /Link -/A 3184 0 R -/Type /Annot -/Rect [88.2 259.495 93.6 270.808] -/Border [0 0 0] ->> -endobj -3186 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3187 0 obj -<< -/Subtype /Link -/A 3186 0 R -/Type /Annot -/Rect [93.6 259.495 115.2 270.808] -/Border [0 0 0] ->> -endobj -3188 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3189 0 obj -<< -/Subtype /Link -/A 3188 0 R -/Type /Annot -/Rect [115.2 259.495 120.6 270.808] -/Border [0 0 0] ->> -endobj -3190 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3191 0 obj -<< -/Subtype /Link -/A 3190 0 R -/Type /Annot -/Rect [120.6 259.495 153 270.808] -/Border [0 0 0] ->> -endobj -3192 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3193 0 obj -<< -/Subtype /Link -/A 3192 0 R -/Type /Annot -/Rect [153 259.495 158.4 270.808] -/Border [0 0 0] ->> -endobj -3194 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3195 0 obj -<< -/Subtype /Link -/A 3194 0 R -/Type /Annot -/Rect [158.4 259.495 163.8 270.808] -/Border [0 0 0] ->> -endobj -3196 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3197 0 obj -<< -/Subtype /Link -/A 3196 0 R -/Type /Annot -/Rect [72 236.995 290.012695 249.495] -/Border [0 0 0] ->> -endobj -2972 0 obj -<< -/Type /Page -/Parent 1 0 R -/MediaBox [0 0 612 792] -/Contents 2970 0 R -/Resources 2971 0 R -/Annots [2975 0 R 2977 0 R 2979 0 R 2981 0 R 2983 0 R 2985 0 R 2987 0 R 2989 0 R 2991 0 R 2993 0 R 2995 0 R 2997 0 R 2999 0 R 3001 0 R 3003 0 R 3005 0 R 3007 0 R 3009 0 R 3011 0 R 3013 0 R 3015 0 R 3017 0 R 3019 0 R 3021 0 R 3023 0 R 3025 0 R 3027 0 R 3029 0 R 3031 0 R 3033 0 R 3035 0 R 3037 0 R 3039 0 R 3041 0 R 3043 0 R 3045 0 R 3047 0 R 3049 0 R 3051 0 R 3053 0 R 3055 0 R 3057 0 R 3059 0 R 3061 0 R 3063 0 R 3065 0 R 3067 0 R 3069 0 R 3071 0 R 3073 0 R 3075 0 R 3077 0 R 3079 0 R 3081 0 R 3083 0 R 3085 0 R 3087 0 R 3089 0 R 3091 0 R 3093 0 R 3095 0 R 3097 0 R 3099 0 R 3101 0 R 3103 0 R 3105 0 R 3107 0 R 3109 0 R 3111 0 R 3113 0 R 3115 0 R 3117 0 R 3119 0 R 3121 0 R 3123 0 R 3125 0 R 3127 0 R 3129 0 R 3131 0 R 3133 0 R 3135 0 R 3137 0 R 3139 0 R 3141 0 R 3143 0 R 3145 0 R 3147 0 R 3149 0 R 3151 0 R 3153 0 R 3155 0 R 3157 0 R 3159 0 R 3161 0 R 3163 0 R 3165 0 R 3167 0 R 3169 0 R 3171 0 R 3173 0 R 3175 0 R 3177 0 R 3179 0 R 3181 0 R 3183 0 R 3185 0 R 3187 0 R 3189 0 R 3191 0 R 3193 0 R 3195 0 R 3197 0 R] ->> -endobj -2971 0 obj -<< -/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] -/Font << -/F4 16 0 R -/F3 9 0 R -/F6 44 0 R -/F5 29 0 R ->> ->> -endobj -2970 0 obj -<< -/Length 2596 -/Filter /FlateDecode ->> -stream -x\n#+Cy%.B$ H.&l%TR]uEOϗ|\_^X<ǿ^wd ?rvzƘ};ҿi2=}>k-,U:S:/w)iNnso^'/x{t9E"pt!e,ֿ Ϝ-| -\s}g]gt]&^itHϹ.c94iB+SE_-G^%)U>^uCF=]aN .  i0nVbsU=X4l`*V^+kc,q%L:uRQL>fƍ2;jVL0NVV/#ẇ,Qd]A͉#QK9i׬Ԍ|%U}\Ω OGS6CIۂְ|HԄ(j~R OjoW.BڠpXVOjnSE[n] h}\->*sE|c$w) LDN#ao4bgKc7oêiv%lkcYV)XwMB^,S E2hndCYosL JV=ؚ㚱T/{!ӭƚ9p l+dUjϠ%hs%C`Jt=ۜW{}qug8x!T~\,y4&N,QJݻ顽ap^bk<9~tG/SRKD9Z?Nd儎_j;ðX"9>:hju}NQ#ʇʹ/:+%-1]b大/J}LPl)w5s -`umBt1=3wll$ԓZn,U>9m[az/@[t5Ai0;˄ߐJlZs.r0ZYM/,vàǀsaZ -|hvGWG|CG&€G3LFw.8>L+<%hm"+q/!%rSc|#@UI>;3}Y4a J_͡zpc5Ճ<2i|@ip:DdIq]ڃ[m\⪧qXGաR萁~ܟ*c @݇_PoO|v -M'՞RR}p4խ՛cP{Pe u9tu8-Ec:[9ƤnyxP5zB}s1E,߮62f'va!]H`0oFyKY*ꅘ?-\vR:IYDM -^, B -endstream -endobj -3202 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3203 0 obj -<< -/Subtype /Link -/A 3202 0 R -/Type /Annot -/Rect [72 695.502 137.268 720] -/Border [0 0 0] ->> -endobj -3204 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3205 0 obj -<< -/Subtype /Link -/A 3204 0 R -/Type /Annot -/Rect [72 673.002 514.949219 685.502] -/Border [0 0 0] ->> -endobj -3206 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3207 0 obj -<< -/Subtype /Link -/A 3206 0 R -/Type /Annot -/Rect [72 660.502 494.114258 673.002] -/Border [0 0 0] ->> -endobj -3208 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3209 0 obj -<< -/Subtype /Link -/A 3208 0 R -/Type /Annot -/Rect [72 648.002 539.724609 660.502] -/Border [0 0 0] ->> -endobj -3210 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3211 0 obj -<< -/Subtype /Link -/A 3210 0 R -/Type /Annot -/Rect [72 635.502 526.785156 648.002] -/Border [0 0 0] ->> -endobj -3212 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3213 0 obj -<< -/Subtype /Link -/A 3212 0 R -/Type /Annot -/Rect [72 623.002 102.493164 635.502] -/Border [0 0 0] ->> -endobj -3214 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3215 0 obj -<< -/Subtype /Link -/A 3214 0 R -/Type /Annot -/Rect [72 601.689 207 613.002] -/Border [0 0 0] ->> -endobj -3216 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3217 0 obj -<< -/Subtype /Link -/A 3216 0 R -/Type /Annot -/Rect [72 590.376 88.2 601.689] -/Border [0 0 0] ->> -endobj -3218 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3219 0 obj -<< -/Subtype /Link -/A 3218 0 R -/Type /Annot -/Rect [88.2 590.376 93.6 601.689] -/Border [0 0 0] ->> -endobj -3220 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3221 0 obj -<< -/Subtype /Link -/A 3220 0 R -/Type /Annot -/Rect [93.6 590.376 126 601.689] -/Border [0 0 0] ->> -endobj -3222 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3223 0 obj -<< -/Subtype /Link -/A 3222 0 R -/Type /Annot -/Rect [126 590.376 131.4 601.689] -/Border [0 0 0] ->> -endobj -3224 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3225 0 obj -<< -/Subtype /Link -/A 3224 0 R -/Type /Annot -/Rect [131.4 590.376 147.6 601.689] -/Border [0 0 0] ->> -endobj -3226 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3227 0 obj -<< -/Subtype /Link -/A 3226 0 R -/Type /Annot -/Rect [147.6 590.376 153 601.689] -/Border [0 0 0] ->> -endobj -3228 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3229 0 obj -<< -/Subtype /Link -/A 3228 0 R -/Type /Annot -/Rect [153 590.376 158.4 601.689] -/Border [0 0 0] ->> -endobj -3230 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3231 0 obj -<< -/Subtype /Link -/A 3230 0 R -/Type /Annot -/Rect [158.4 590.376 174.6 601.689] -/Border [0 0 0] ->> -endobj -3232 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3233 0 obj -<< -/Subtype /Link -/A 3232 0 R -/Type /Annot -/Rect [174.6 590.376 180 601.689] -/Border [0 0 0] ->> -endobj -3234 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3235 0 obj -<< -/Subtype /Link -/A 3234 0 R -/Type /Annot -/Rect [180 590.376 185.4 601.689] -/Border [0 0 0] ->> -endobj -3236 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3237 0 obj -<< -/Subtype /Link -/A 3236 0 R -/Type /Annot -/Rect [185.4 590.376 201.6 601.689] -/Border [0 0 0] ->> -endobj -3238 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3239 0 obj -<< -/Subtype /Link -/A 3238 0 R -/Type /Annot -/Rect [201.6 590.376 207 601.689] -/Border [0 0 0] ->> -endobj -3240 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3241 0 obj -<< -/Subtype /Link -/A 3240 0 R -/Type /Annot -/Rect [72 579.063 88.2 590.376] -/Border [0 0 0] ->> -endobj -3242 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3243 0 obj -<< -/Subtype /Link -/A 3242 0 R -/Type /Annot -/Rect [88.2 579.063 93.6 590.376] -/Border [0 0 0] ->> -endobj -3244 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3245 0 obj -<< -/Subtype /Link -/A 3244 0 R -/Type /Annot -/Rect [93.6 579.063 115.2 590.376] -/Border [0 0 0] ->> -endobj -3246 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3247 0 obj -<< -/Subtype /Link -/A 3246 0 R -/Type /Annot -/Rect [115.2 579.063 120.6 590.376] -/Border [0 0 0] ->> -endobj -3248 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3249 0 obj -<< -/Subtype /Link -/A 3248 0 R -/Type /Annot -/Rect [120.6 579.063 126 590.376] -/Border [0 0 0] ->> -endobj -3250 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3251 0 obj -<< -/Subtype /Link -/A 3250 0 R -/Type /Annot -/Rect [126 579.063 131.4 590.376] -/Border [0 0 0] ->> -endobj -3252 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3253 0 obj -<< -/Subtype /Link -/A 3252 0 R -/Type /Annot -/Rect [72 556.437 234 567.75] -/Border [0 0 0] ->> -endobj -3254 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3255 0 obj -<< -/Subtype /Link -/A 3254 0 R -/Type /Annot -/Rect [72 545.124 88.2 556.437] -/Border [0 0 0] ->> -endobj -3256 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3257 0 obj -<< -/Subtype /Link -/A 3256 0 R -/Type /Annot -/Rect [88.2 545.124 93.6 556.437] -/Border [0 0 0] ->> -endobj -3258 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3259 0 obj -<< -/Subtype /Link -/A 3258 0 R -/Type /Annot -/Rect [93.6 545.124 99 556.437] -/Border [0 0 0] ->> -endobj -3260 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3261 0 obj -<< -/Subtype /Link -/A 3260 0 R -/Type /Annot -/Rect [99 545.124 115.2 556.437] -/Border [0 0 0] ->> -endobj -3262 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3263 0 obj -<< -/Subtype /Link -/A 3262 0 R -/Type /Annot -/Rect [115.2 545.124 120.6 556.437] -/Border [0 0 0] ->> -endobj -3264 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3265 0 obj -<< -/Subtype /Link -/A 3264 0 R -/Type /Annot -/Rect [120.6 545.124 136.8 556.437] -/Border [0 0 0] ->> -endobj -3266 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3267 0 obj -<< -/Subtype /Link -/A 3266 0 R -/Type /Annot -/Rect [136.8 545.124 142.2 556.437] -/Border [0 0 0] ->> -endobj -3268 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3269 0 obj -<< -/Subtype /Link -/A 3268 0 R -/Type /Annot -/Rect [142.2 545.124 147.6 556.437] -/Border [0 0 0] ->> -endobj -3270 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3271 0 obj -<< -/Subtype /Link -/A 3270 0 R -/Type /Annot -/Rect [147.6 545.124 153 556.437] -/Border [0 0 0] ->> -endobj -3272 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3273 0 obj -<< -/Subtype /Link -/A 3272 0 R -/Type /Annot -/Rect [153 545.124 158.4 556.437] -/Border [0 0 0] ->> -endobj -3274 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3275 0 obj -<< -/Subtype /Link -/A 3274 0 R -/Type /Annot -/Rect [158.4 545.124 163.8 556.437] -/Border [0 0 0] ->> -endobj -3276 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3277 0 obj -<< -/Subtype /Link -/A 3276 0 R -/Type /Annot -/Rect [163.8 545.124 169.2 556.437] -/Border [0 0 0] ->> -endobj -3278 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3279 0 obj -<< -/Subtype /Link -/A 3278 0 R -/Type /Annot -/Rect [169.2 545.124 185.4 556.437] -/Border [0 0 0] ->> -endobj -3280 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3281 0 obj -<< -/Subtype /Link -/A 3280 0 R -/Type /Annot -/Rect [185.4 545.124 190.8 556.437] -/Border [0 0 0] ->> -endobj -3282 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3283 0 obj -<< -/Subtype /Link -/A 3282 0 R -/Type /Annot -/Rect [190.8 545.124 196.2 556.437] -/Border [0 0 0] ->> -endobj -3284 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3285 0 obj -<< -/Subtype /Link -/A 3284 0 R -/Type /Annot -/Rect [196.2 545.124 201.6 556.437] -/Border [0 0 0] ->> -endobj -3286 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3287 0 obj -<< -/Subtype /Link -/A 3286 0 R -/Type /Annot -/Rect [201.6 545.124 212.4 556.437] -/Border [0 0 0] ->> -endobj -3288 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3289 0 obj -<< -/Subtype /Link -/A 3288 0 R -/Type /Annot -/Rect [212.4 545.124 217.8 556.437] -/Border [0 0 0] ->> -endobj -3290 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3291 0 obj -<< -/Subtype /Link -/A 3290 0 R -/Type /Annot -/Rect [217.8 545.124 223.2 556.437] -/Border [0 0 0] ->> -endobj -3292 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3293 0 obj -<< -/Subtype /Link -/A 3292 0 R -/Type /Annot -/Rect [223.2 545.124 239.4 556.437] -/Border [0 0 0] ->> -endobj -3294 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3295 0 obj -<< -/Subtype /Link -/A 3294 0 R -/Type /Annot -/Rect [239.4 545.124 250.2 556.437] -/Border [0 0 0] ->> -endobj -3296 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3297 0 obj -<< -/Subtype /Link -/A 3296 0 R -/Type /Annot -/Rect [250.2 545.124 255.6 556.437] -/Border [0 0 0] ->> -endobj -3298 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3299 0 obj -<< -/Subtype /Link -/A 3298 0 R -/Type /Annot -/Rect [255.6 545.124 261 556.437] -/Border [0 0 0] ->> -endobj -3300 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3301 0 obj -<< -/Subtype /Link -/A 3300 0 R -/Type /Annot -/Rect [261 545.124 266.4 556.437] -/Border [0 0 0] ->> -endobj -3302 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3303 0 obj -<< -/Subtype /Link -/A 3302 0 R -/Type /Annot -/Rect [72 533.811 82.8 545.124] -/Border [0 0 0] ->> -endobj -3304 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3305 0 obj -<< -/Subtype /Link -/A 3304 0 R -/Type /Annot -/Rect [82.8 533.811 99 545.124] -/Border [0 0 0] ->> -endobj -3306 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3307 0 obj -<< -/Subtype /Link -/A 3306 0 R -/Type /Annot -/Rect [99 533.811 104.4 545.124] -/Border [0 0 0] ->> -endobj -3308 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3309 0 obj -<< -/Subtype /Link -/A 3308 0 R -/Type /Annot -/Rect [104.4 533.811 109.8 545.124] -/Border [0 0 0] ->> -endobj -3310 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3311 0 obj -<< -/Subtype /Link -/A 3310 0 R -/Type /Annot -/Rect [109.8 533.811 126 545.124] -/Border [0 0 0] ->> -endobj -3312 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3313 0 obj -<< -/Subtype /Link -/A 3312 0 R -/Type /Annot -/Rect [126 533.811 131.4 545.124] -/Border [0 0 0] ->> -endobj -3314 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3315 0 obj -<< -/Subtype /Link -/A 3314 0 R -/Type /Annot -/Rect [131.4 533.811 147.6 545.124] -/Border [0 0 0] ->> -endobj -3316 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3317 0 obj -<< -/Subtype /Link -/A 3316 0 R -/Type /Annot -/Rect [147.6 533.811 153 545.124] -/Border [0 0 0] ->> -endobj -3318 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3319 0 obj -<< -/Subtype /Link -/A 3318 0 R -/Type /Annot -/Rect [153 533.811 158.4 545.124] -/Border [0 0 0] ->> -endobj -3320 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3321 0 obj -<< -/Subtype /Link -/A 3320 0 R -/Type /Annot -/Rect [158.4 533.811 163.8 545.124] -/Border [0 0 0] ->> -endobj -3322 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3323 0 obj -<< -/Subtype /Link -/A 3322 0 R -/Type /Annot -/Rect [163.8 533.811 169.2 545.124] -/Border [0 0 0] ->> -endobj -3324 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3325 0 obj -<< -/Subtype /Link -/A 3324 0 R -/Type /Annot -/Rect [169.2 533.811 174.6 545.124] -/Border [0 0 0] ->> -endobj -3326 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3327 0 obj -<< -/Subtype /Link -/A 3326 0 R -/Type /Annot -/Rect [174.6 533.811 180 545.124] -/Border [0 0 0] ->> -endobj -3328 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3329 0 obj -<< -/Subtype /Link -/A 3328 0 R -/Type /Annot -/Rect [180 533.811 196.2 545.124] -/Border [0 0 0] ->> -endobj -3330 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3331 0 obj -<< -/Subtype /Link -/A 3330 0 R -/Type /Annot -/Rect [196.2 533.811 201.6 545.124] -/Border [0 0 0] ->> -endobj -3332 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3333 0 obj -<< -/Subtype /Link -/A 3332 0 R -/Type /Annot -/Rect [201.6 533.811 207 545.124] -/Border [0 0 0] ->> -endobj -3334 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3335 0 obj -<< -/Subtype /Link -/A 3334 0 R -/Type /Annot -/Rect [207 533.811 212.4 545.124] -/Border [0 0 0] ->> -endobj -3336 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3337 0 obj -<< -/Subtype /Link -/A 3336 0 R -/Type /Annot -/Rect [212.4 533.811 223.2 545.124] -/Border [0 0 0] ->> -endobj -3338 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3339 0 obj -<< -/Subtype /Link -/A 3338 0 R -/Type /Annot -/Rect [223.2 533.811 228.6 545.124] -/Border [0 0 0] ->> -endobj -3340 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3341 0 obj -<< -/Subtype /Link -/A 3340 0 R -/Type /Annot -/Rect [228.6 533.811 234 545.124] -/Border [0 0 0] ->> -endobj -3342 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3343 0 obj -<< -/Subtype /Link -/A 3342 0 R -/Type /Annot -/Rect [234 533.811 250.2 545.124] -/Border [0 0 0] ->> -endobj -3344 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3345 0 obj -<< -/Subtype /Link -/A 3344 0 R -/Type /Annot -/Rect [250.2 533.811 261 545.124] -/Border [0 0 0] ->> -endobj -3346 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3347 0 obj -<< -/Subtype /Link -/A 3346 0 R -/Type /Annot -/Rect [261 533.811 266.4 545.124] -/Border [0 0 0] ->> -endobj -3348 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3349 0 obj -<< -/Subtype /Link -/A 3348 0 R -/Type /Annot -/Rect [266.4 533.811 271.8 545.124] -/Border [0 0 0] ->> -endobj -3350 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3351 0 obj -<< -/Subtype /Link -/A 3350 0 R -/Type /Annot -/Rect [271.8 533.811 277.2 545.124] -/Border [0 0 0] ->> -endobj -3352 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3353 0 obj -<< -/Subtype /Link -/A 3352 0 R -/Type /Annot -/Rect [72 522.498 93.6 533.811] -/Border [0 0 0] ->> -endobj -3354 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3355 0 obj -<< -/Subtype /Link -/A 3354 0 R -/Type /Annot -/Rect [93.6 522.498 120.6 533.811] -/Border [0 0 0] ->> -endobj -3356 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3357 0 obj -<< -/Subtype /Link -/A 3356 0 R -/Type /Annot -/Rect [120.6 522.498 126 533.811] -/Border [0 0 0] ->> -endobj -3358 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3359 0 obj -<< -/Subtype /Link -/A 3358 0 R -/Type /Annot -/Rect [126 522.498 153 533.811] -/Border [0 0 0] ->> -endobj -3360 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3361 0 obj -<< -/Subtype /Link -/A 3360 0 R -/Type /Annot -/Rect [153 522.498 158.4 533.811] -/Border [0 0 0] ->> -endobj -3362 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3363 0 obj -<< -/Subtype /Link -/A 3362 0 R -/Type /Annot -/Rect [158.4 522.498 163.8 533.811] -/Border [0 0 0] ->> -endobj -3364 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3365 0 obj -<< -/Subtype /Link -/A 3364 0 R -/Type /Annot -/Rect [163.8 522.498 169.2 533.811] -/Border [0 0 0] ->> -endobj -3366 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3367 0 obj -<< -/Subtype /Link -/A 3366 0 R -/Type /Annot -/Rect [169.2 522.498 174.6 533.811] -/Border [0 0 0] ->> -endobj -3368 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3369 0 obj -<< -/Subtype /Link -/A 3368 0 R -/Type /Annot -/Rect [174.6 522.498 190.8 533.811] -/Border [0 0 0] ->> -endobj -3370 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3371 0 obj -<< -/Subtype /Link -/A 3370 0 R -/Type /Annot -/Rect [190.8 522.498 196.2 533.811] -/Border [0 0 0] ->> -endobj -3372 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3373 0 obj -<< -/Subtype /Link -/A 3372 0 R -/Type /Annot -/Rect [196.2 522.498 201.6 533.811] -/Border [0 0 0] ->> -endobj -3374 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3375 0 obj -<< -/Subtype /Link -/A 3374 0 R -/Type /Annot -/Rect [201.6 522.498 207 533.811] -/Border [0 0 0] ->> -endobj -3376 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3377 0 obj -<< -/Subtype /Link -/A 3376 0 R -/Type /Annot -/Rect [207 522.498 212.4 533.811] -/Border [0 0 0] ->> -endobj -3378 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3379 0 obj -<< -/Subtype /Link -/A 3378 0 R -/Type /Annot -/Rect [212.4 522.498 217.8 533.811] -/Border [0 0 0] ->> -endobj -3380 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3381 0 obj -<< -/Subtype /Link -/A 3380 0 R -/Type /Annot -/Rect [217.8 522.498 223.2 533.811] -/Border [0 0 0] ->> -endobj -3382 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3383 0 obj -<< -/Subtype /Link -/A 3382 0 R -/Type /Annot -/Rect [223.2 522.498 228.6 533.811] -/Border [0 0 0] ->> -endobj -3384 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3385 0 obj -<< -/Subtype /Link -/A 3384 0 R -/Type /Annot -/Rect [228.6 522.498 234 533.811] -/Border [0 0 0] ->> -endobj -3386 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3387 0 obj -<< -/Subtype /Link -/A 3386 0 R -/Type /Annot -/Rect [234 522.498 239.4 533.811] -/Border [0 0 0] ->> -endobj -3388 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3389 0 obj -<< -/Subtype /Link -/A 3388 0 R -/Type /Annot -/Rect [239.4 522.498 255.6 533.811] -/Border [0 0 0] ->> -endobj -3390 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3391 0 obj -<< -/Subtype /Link -/A 3390 0 R -/Type /Annot -/Rect [255.6 522.498 261 533.811] -/Border [0 0 0] ->> -endobj -3392 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3393 0 obj -<< -/Subtype /Link -/A 3392 0 R -/Type /Annot -/Rect [261 522.498 266.4 533.811] -/Border [0 0 0] ->> -endobj -3394 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3395 0 obj -<< -/Subtype /Link -/A 3394 0 R -/Type /Annot -/Rect [266.4 522.498 271.8 533.811] -/Border [0 0 0] ->> -endobj -3396 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3397 0 obj -<< -/Subtype /Link -/A 3396 0 R -/Type /Annot -/Rect [271.8 522.498 277.2 533.811] -/Border [0 0 0] ->> -endobj -3398 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3399 0 obj -<< -/Subtype /Link -/A 3398 0 R -/Type /Annot -/Rect [277.2 522.498 282.6 533.811] -/Border [0 0 0] ->> -endobj -3400 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3401 0 obj -<< -/Subtype /Link -/A 3400 0 R -/Type /Annot -/Rect [282.6 522.498 288 533.811] -/Border [0 0 0] ->> -endobj -3402 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3403 0 obj -<< -/Subtype /Link -/A 3402 0 R -/Type /Annot -/Rect [288 522.498 293.4 533.811] -/Border [0 0 0] ->> -endobj -3404 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3405 0 obj -<< -/Subtype /Link -/A 3404 0 R -/Type /Annot -/Rect [293.4 522.498 298.8 533.811] -/Border [0 0 0] ->> -endobj -3406 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3407 0 obj -<< -/Subtype /Link -/A 3406 0 R -/Type /Annot -/Rect [298.8 522.498 331.2 533.811] -/Border [0 0 0] ->> -endobj -3408 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3409 0 obj -<< -/Subtype /Link -/A 3408 0 R -/Type /Annot -/Rect [331.2 522.498 336.6 533.811] -/Border [0 0 0] ->> -endobj -3410 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3411 0 obj -<< -/Subtype /Link -/A 3410 0 R -/Type /Annot -/Rect [336.6 522.498 342 533.811] -/Border [0 0 0] ->> -endobj -3412 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3413 0 obj -<< -/Subtype /Link -/A 3412 0 R -/Type /Annot -/Rect [342 522.498 347.4 533.811] -/Border [0 0 0] ->> -endobj -3414 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3415 0 obj -<< -/Subtype /Link -/A 3414 0 R -/Type /Annot -/Rect [347.4 522.498 396 533.811] -/Border [0 0 0] ->> -endobj -3416 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3417 0 obj -<< -/Subtype /Link -/A 3416 0 R -/Type /Annot -/Rect [396 522.498 401.4 533.811] -/Border [0 0 0] ->> -endobj -3418 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3419 0 obj -<< -/Subtype /Link -/A 3418 0 R -/Type /Annot -/Rect [72 511.185 93.6 522.498] -/Border [0 0 0] ->> -endobj -3420 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3421 0 obj -<< -/Subtype /Link -/A 3420 0 R -/Type /Annot -/Rect [93.6 511.185 109.8 522.498] -/Border [0 0 0] ->> -endobj -3422 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3423 0 obj -<< -/Subtype /Link -/A 3422 0 R -/Type /Annot -/Rect [109.8 511.185 115.2 522.498] -/Border [0 0 0] ->> -endobj -3424 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3425 0 obj -<< -/Subtype /Link -/A 3424 0 R -/Type /Annot -/Rect [115.2 511.185 136.8 522.498] -/Border [0 0 0] ->> -endobj -3426 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3427 0 obj -<< -/Subtype /Link -/A 3426 0 R -/Type /Annot -/Rect [136.8 511.185 142.2 522.498] -/Border [0 0 0] ->> -endobj -3428 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3429 0 obj -<< -/Subtype /Link -/A 3428 0 R -/Type /Annot -/Rect [142.2 511.185 158.4 522.498] -/Border [0 0 0] ->> -endobj -3430 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3431 0 obj -<< -/Subtype /Link -/A 3430 0 R -/Type /Annot -/Rect [158.4 511.185 163.8 522.498] -/Border [0 0 0] ->> -endobj -3432 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3433 0 obj -<< -/Subtype /Link -/A 3432 0 R -/Type /Annot -/Rect [163.8 511.185 169.2 522.498] -/Border [0 0 0] ->> -endobj -3434 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3435 0 obj -<< -/Subtype /Link -/A 3434 0 R -/Type /Annot -/Rect [169.2 511.185 174.6 522.498] -/Border [0 0 0] ->> -endobj -3436 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3437 0 obj -<< -/Subtype /Link -/A 3436 0 R -/Type /Annot -/Rect [174.6 511.185 185.4 522.498] -/Border [0 0 0] ->> -endobj -3438 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3439 0 obj -<< -/Subtype /Link -/A 3438 0 R -/Type /Annot -/Rect [185.4 511.185 190.8 522.498] -/Border [0 0 0] ->> -endobj -3440 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3441 0 obj -<< -/Subtype /Link -/A 3440 0 R -/Type /Annot -/Rect [190.8 511.185 196.2 522.498] -/Border [0 0 0] ->> -endobj -3442 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3443 0 obj -<< -/Subtype /Link -/A 3442 0 R -/Type /Annot -/Rect [196.2 511.185 212.4 522.498] -/Border [0 0 0] ->> -endobj -3444 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3445 0 obj -<< -/Subtype /Link -/A 3444 0 R -/Type /Annot -/Rect [212.4 511.185 217.8 522.498] -/Border [0 0 0] ->> -endobj -3446 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3447 0 obj -<< -/Subtype /Link -/A 3446 0 R -/Type /Annot -/Rect [217.8 511.185 223.2 522.498] -/Border [0 0 0] ->> -endobj -3448 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3449 0 obj -<< -/Subtype /Link -/A 3448 0 R -/Type /Annot -/Rect [223.2 511.185 228.6 522.498] -/Border [0 0 0] ->> -endobj -3450 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3451 0 obj -<< -/Subtype /Link -/A 3450 0 R -/Type /Annot -/Rect [228.6 511.185 239.4 522.498] -/Border [0 0 0] ->> -endobj -3452 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3453 0 obj -<< -/Subtype /Link -/A 3452 0 R -/Type /Annot -/Rect [239.4 511.185 244.8 522.498] -/Border [0 0 0] ->> -endobj -3454 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3455 0 obj -<< -/Subtype /Link -/A 3454 0 R -/Type /Annot -/Rect [244.8 511.185 250.2 522.498] -/Border [0 0 0] ->> -endobj -3456 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3457 0 obj -<< -/Subtype /Link -/A 3456 0 R -/Type /Annot -/Rect [250.2 511.185 261 522.498] -/Border [0 0 0] ->> -endobj -3458 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3459 0 obj -<< -/Subtype /Link -/A 3458 0 R -/Type /Annot -/Rect [261 511.185 266.4 522.498] -/Border [0 0 0] ->> -endobj -3460 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3461 0 obj -<< -/Subtype /Link -/A 3460 0 R -/Type /Annot -/Rect [266.4 511.185 271.8 522.498] -/Border [0 0 0] ->> -endobj -3462 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3463 0 obj -<< -/Subtype /Link -/A 3462 0 R -/Type /Annot -/Rect [271.8 511.185 282.6 522.498] -/Border [0 0 0] ->> -endobj -3464 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3465 0 obj -<< -/Subtype /Link -/A 3464 0 R -/Type /Annot -/Rect [282.6 511.185 288 522.498] -/Border [0 0 0] ->> -endobj -3466 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3467 0 obj -<< -/Subtype /Link -/A 3466 0 R -/Type /Annot -/Rect [72 499.872 109.8 511.185] -/Border [0 0 0] ->> -endobj -3468 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3469 0 obj -<< -/Subtype /Link -/A 3468 0 R -/Type /Annot -/Rect [109.8 499.872 115.2 511.185] -/Border [0 0 0] ->> -endobj -3470 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3471 0 obj -<< -/Subtype /Link -/A 3470 0 R -/Type /Annot -/Rect [115.2 499.872 136.8 511.185] -/Border [0 0 0] ->> -endobj -3472 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3473 0 obj -<< -/Subtype /Link -/A 3472 0 R -/Type /Annot -/Rect [136.8 499.872 142.2 511.185] -/Border [0 0 0] ->> -endobj -3474 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3475 0 obj -<< -/Subtype /Link -/A 3474 0 R -/Type /Annot -/Rect [142.2 499.872 169.2 511.185] -/Border [0 0 0] ->> -endobj -3476 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3477 0 obj -<< -/Subtype /Link -/A 3476 0 R -/Type /Annot -/Rect [169.2 499.872 174.6 511.185] -/Border [0 0 0] ->> -endobj -3478 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3479 0 obj -<< -/Subtype /Link -/A 3478 0 R -/Type /Annot -/Rect [174.6 499.872 180 511.185] -/Border [0 0 0] ->> -endobj -3480 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3481 0 obj -<< -/Subtype /Link -/A 3480 0 R -/Type /Annot -/Rect [72 488.559 82.8 499.872] -/Border [0 0 0] ->> -endobj -3482 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3483 0 obj -<< -/Subtype /Link -/A 3482 0 R -/Type /Annot -/Rect [82.8 488.559 88.2 499.872] -/Border [0 0 0] ->> -endobj -3484 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3485 0 obj -<< -/Subtype /Link -/A 3484 0 R -/Type /Annot -/Rect [72 477.246 77.4 488.559] -/Border [0 0 0] ->> -endobj -3486 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3487 0 obj -<< -/Subtype /Link -/A 3486 0 R -/Type /Annot -/Rect [72 454.746 285.500977 467.246] -/Border [0 0 0] ->> -endobj -3488 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3489 0 obj -<< -/Subtype /Link -/A 3488 0 R -/Type /Annot -/Rect [72 201.842 272.029297 214.342] -/Border [0 0 0] ->> -endobj -3490 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3491 0 obj -<< -/Subtype /Link -/A 3490 0 R -/Type /Annot -/Rect [272.029297 201.772 296.029297 214.342] -/Border [0 0 0] ->> -endobj -3492 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3493 0 obj -<< -/Subtype /Link -/A 3492 0 R -/Type /Annot -/Rect [296.029297 201.842 507.279297 214.342] -/Border [0 0 0] ->> -endobj -3494 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3495 0 obj -<< -/Subtype /Link -/A 3494 0 R -/Type /Annot -/Rect [72 189.202 114 201.772] -/Border [0 0 0] ->> -endobj -3496 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3497 0 obj -<< -/Subtype /Link -/A 3496 0 R -/Type /Annot -/Rect [114 189.272 296.817383 201.772] -/Border [0 0 0] ->> -endobj -3498 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3499 0 obj -<< -/Subtype /Link -/A 3498 0 R -/Type /Annot -/Rect [72 166.772 518.235352 179.272] -/Border [0 0 0] ->> -endobj -3500 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3501 0 obj -<< -/Subtype /Link -/A 3500 0 R -/Type /Annot -/Rect [72 154.272 114.529297 166.772] -/Border [0 0 0] ->> -endobj -3200 0 obj -<< -/Type /Page -/Parent 1 0 R -/MediaBox [0 0 612 792] -/Contents 3198 0 R -/Resources 3199 0 R -/Annots [3203 0 R 3205 0 R 3207 0 R 3209 0 R 3211 0 R 3213 0 R 3215 0 R 3217 0 R 3219 0 R 3221 0 R 3223 0 R 3225 0 R 3227 0 R 3229 0 R 3231 0 R 3233 0 R 3235 0 R 3237 0 R 3239 0 R 3241 0 R 3243 0 R 3245 0 R 3247 0 R 3249 0 R 3251 0 R 3253 0 R 3255 0 R 3257 0 R 3259 0 R 3261 0 R 3263 0 R 3265 0 R 3267 0 R 3269 0 R 3271 0 R 3273 0 R 3275 0 R 3277 0 R 3279 0 R 3281 0 R 3283 0 R 3285 0 R 3287 0 R 3289 0 R 3291 0 R 3293 0 R 3295 0 R 3297 0 R 3299 0 R 3301 0 R 3303 0 R 3305 0 R 3307 0 R 3309 0 R 3311 0 R 3313 0 R 3315 0 R 3317 0 R 3319 0 R 3321 0 R 3323 0 R 3325 0 R 3327 0 R 3329 0 R 3331 0 R 3333 0 R 3335 0 R 3337 0 R 3339 0 R 3341 0 R 3343 0 R 3345 0 R 3347 0 R 3349 0 R 3351 0 R 3353 0 R 3355 0 R 3357 0 R 3359 0 R 3361 0 R 3363 0 R 3365 0 R 3367 0 R 3369 0 R 3371 0 R 3373 0 R 3375 0 R 3377 0 R 3379 0 R 3381 0 R 3383 0 R 3385 0 R 3387 0 R 3389 0 R 3391 0 R 3393 0 R 3395 0 R 3397 0 R 3399 0 R 3401 0 R 3403 0 R 3405 0 R 3407 0 R 3409 0 R 3411 0 R 3413 0 R 3415 0 R 3417 0 R 3419 0 R 3421 0 R 3423 0 R 3425 0 R 3427 0 R 3429 0 R 3431 0 R 3433 0 R 3435 0 R 3437 0 R 3439 0 R 3441 0 R 3443 0 R 3445 0 R 3447 0 R 3449 0 R 3451 0 R 3453 0 R 3455 0 R 3457 0 R 3459 0 R 3461 0 R 3463 0 R 3465 0 R 3467 0 R 3469 0 R 3471 0 R 3473 0 R 3475 0 R 3477 0 R 3479 0 R 3481 0 R 3483 0 R 3485 0 R 3487 0 R 3489 0 R 3491 0 R 3493 0 R 3495 0 R 3497 0 R 3499 0 R 3501 0 R] ->> -endobj -3199 0 obj -<< -/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] -/Font << -/F4 16 0 R -/F3 9 0 R -/F5 29 0 R -/F6 44 0 R ->> ->> -endobj -3198 0 obj -<< -/Length 2564 -/Filter /FlateDecode ->> -stream -x]4S q@,7/q@$@q;v d&8Z\2}_Roq7 rugey q'I'%&ݛ{aս=.~`!s?9_wwo*ZRH:0iE*&pGkE5W{0zPI:HmNC;B̗E=OP -9pge oIe|quؾ7pJ^,rV\}Qޫ) P6szP>RiLvs GU۟P^}JG "' \)_ :D -[L,q+cASJWupSzC%e I~ EA*R|l8J`DO(U˺6PzeΜ~ =}rv:ʄ21p<\"R=HL_7u6!Aף69@ 1I{{$cp#4@ɚ?[M,b=f~y8j le#칡!ekHPyc3BT,5L"h:9=Dž^ʔ ECpۭc+`p(5xv Tδp4r',؂J@Ha 1"&ydXz{m^Snff4/l7su.Kv+Ԃĸߏ}6GនţYFsɐh4-ilfivw(Ò(misjnl2UֵqIvcEidn>gˉbO2s r+ʹH\?S̈A/뇹 *Aۍx~}W~csA?щ^@1#~8d?{z'4JCH9gpj%lޫ:^[5*-j,fm c,&Y)uz*%TE=aD8xYLPQހ"vtAkY$Kf -1;dpaKj8K [ǴyWxLNP%yW%NCͻ&9ei]:zGp] LNz9H6*zmnJ:z&uڬ(D}8mJΛ_aA P ׁ:^ ?o?~ޞG9)~*ō痟gp{mf3Eå0xd5ݽA qzr/=ee=GPC9~ 4h7*r)TyG3ƷzU -{%F,$6ժ Fvƣ(S N(Q0eRT(%D{e>a_*3$7D0+ rdHGr!V3x{a%Roޚ~pVbVV 28~oWo lJ >Pi~?nKw:}%ڃp_au6V6:Ά :K{Yg?~))AsParwDzJs ;ȑ#.y#G=[3ϼs8> ӸGxаG䠐hs6+~q3S$3mhgO֭}.-;stekB qj:.1Wf(%'g.XOlŝ XrgGĪ~?h/g<6kvK$qx\bURpjzظZ%N.wUIQ%kc%)+e-n0VZ.e-bV#cɊjV#gdeݬ 4 b2@ m&4 j2H U4vSMh7vS@Mi7TpvSu& -n*@ -n*H >W7?m`VO8jp]`Clu +jp ] U#x-8Tn] c{X"FЕ Q5r@[&7ÍPQup,] U#cJ9-] cyBFrШn81t%pTЖÍkz`co0XR iW'$e I}'HvV/CϔЋoG$DKG n& )}]Z"muir{44Mp6-oZ"Ovڣ56D66~hcf&=&p!;3oq̫c]PהAm1}S.tzr =;5P!38ER{j<$M|ġ$#c\y9;]ș6fc\f4f@m?:~" -endstream -endobj -3506 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3507 0 obj -<< -/Subtype /Link -/A 3506 0 R -/Type /Annot -/Rect [72 685.975 225.95 720] -/Border [0 0 0] ->> -endobj -3509 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3510 0 obj -<< -/Subtype /Link -/A 3509 0 R -/Type /Annot -/Rect [72 646.477 149.22 670.975] -/Border [0 0 0] ->> -endobj -3511 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3512 0 obj -<< -/Subtype /Link -/A 3511 0 R -/Type /Annot -/Rect [72 623.977 491.516602 636.477] -/Border [0 0 0] ->> -endobj -3513 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3514 0 obj -<< -/Subtype /Link -/A 3513 0 R -/Type /Annot -/Rect [72 611.477 518.206055 623.977] -/Border [0 0 0] ->> -endobj -3515 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3516 0 obj -<< -/Subtype /Link -/A 3515 0 R -/Type /Annot -/Rect [72 598.837 96 611.407] -/Border [0 0 0] ->> -endobj -3517 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3518 0 obj -<< -/Subtype /Link -/A 3517 0 R -/Type /Annot -/Rect [96 598.907 140.970703 611.407] -/Border [0 0 0] ->> -endobj -3519 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3520 0 obj -<< -/Subtype /Link -/A 3519 0 R -/Type /Annot -/Rect [72 577.594 88.2 588.907] -/Border [0 0 0] ->> -endobj -3521 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3522 0 obj -<< -/Subtype /Link -/A 3521 0 R -/Type /Annot -/Rect [88.2 577.594 93.6 588.907] -/Border [0 0 0] ->> -endobj -3523 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3524 0 obj -<< -/Subtype /Link -/A 3523 0 R -/Type /Annot -/Rect [93.6 577.594 115.2 588.907] -/Border [0 0 0] ->> -endobj -3525 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3526 0 obj -<< -/Subtype /Link -/A 3525 0 R -/Type /Annot -/Rect [115.2 577.594 120.6 588.907] -/Border [0 0 0] ->> -endobj -3527 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3528 0 obj -<< -/Subtype /Link -/A 3527 0 R -/Type /Annot -/Rect [120.6 577.594 196.2 588.907] -/Border [0 0 0] ->> -endobj -3529 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3530 0 obj -<< -/Subtype /Link -/A 3529 0 R -/Type /Annot -/Rect [196.2 577.594 201.6 588.907] -/Border [0 0 0] ->> -endobj -3531 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3532 0 obj -<< -/Subtype /Link -/A 3531 0 R -/Type /Annot -/Rect [72 555.094 513.123047 567.594] -/Border [0 0 0] ->> -endobj -3533 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3534 0 obj -<< -/Subtype /Link -/A 3533 0 R -/Type /Annot -/Rect [72 542.594 294.783203 555.094] -/Border [0 0 0] ->> -endobj -3535 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3536 0 obj -<< -/Subtype /Link -/A 3535 0 R -/Type /Annot -/Rect [294.783203 542.524 318.783203 555.094] -/Border [0 0 0] ->> -endobj -3537 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3538 0 obj -<< -/Subtype /Link -/A 3537 0 R -/Type /Annot -/Rect [318.783203 542.594 528.114258 555.094] -/Border [0 0 0] ->> -endobj -3539 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3540 0 obj -<< -/Subtype /Link -/A 3539 0 R -/Type /Annot -/Rect [72 530.094 533.147461 542.594] -/Border [0 0 0] ->> -endobj -3541 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3542 0 obj -<< -/Subtype /Link -/A 3541 0 R -/Type /Annot -/Rect [72 517.594 174.177734 530.094] -/Border [0 0 0] ->> -endobj -3543 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3544 0 obj -<< -/Subtype /Link -/A 3543 0 R -/Type /Annot -/Rect [174.177734 517.524 198.177734 530.094] -/Border [0 0 0] ->> -endobj -3545 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3546 0 obj -<< -/Subtype /Link -/A 3545 0 R -/Type /Annot -/Rect [198.177734 517.594 339.461914 530.094] -/Border [0 0 0] ->> -endobj -3547 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3548 0 obj -<< -/Subtype /Link -/A 3547 0 R -/Type /Annot -/Rect [72 496.281 88.2 507.594] -/Border [0 0 0] ->> -endobj -3549 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3550 0 obj -<< -/Subtype /Link -/A 3549 0 R -/Type /Annot -/Rect [88.2 496.281 93.6 507.594] -/Border [0 0 0] ->> -endobj -3551 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3552 0 obj -<< -/Subtype /Link -/A 3551 0 R -/Type /Annot -/Rect [93.6 496.281 115.2 507.594] -/Border [0 0 0] ->> -endobj -3553 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3554 0 obj -<< -/Subtype /Link -/A 3553 0 R -/Type /Annot -/Rect [115.2 496.281 120.6 507.594] -/Border [0 0 0] ->> -endobj -3555 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3556 0 obj -<< -/Subtype /Link -/A 3555 0 R -/Type /Annot -/Rect [120.6 496.281 196.2 507.594] -/Border [0 0 0] ->> -endobj -3557 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3558 0 obj -<< -/Subtype /Link -/A 3557 0 R -/Type /Annot -/Rect [196.2 496.281 201.6 507.594] -/Border [0 0 0] ->> -endobj -3559 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3560 0 obj -<< -/Subtype /Link -/A 3559 0 R -/Type /Annot -/Rect [201.6 496.281 207 507.594] -/Border [0 0 0] ->> -endobj -3561 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3562 0 obj -<< -/Subtype /Link -/A 3561 0 R -/Type /Annot -/Rect [207 496.281 223.2 507.594] -/Border [0 0 0] ->> -endobj -3563 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3564 0 obj -<< -/Subtype /Link -/A 3563 0 R -/Type /Annot -/Rect [223.2 496.281 228.6 507.594] -/Border [0 0 0] ->> -endobj -3565 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3566 0 obj -<< -/Subtype /Link -/A 3565 0 R -/Type /Annot -/Rect [228.6 496.281 234 507.594] -/Border [0 0 0] ->> -endobj -3567 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3568 0 obj -<< -/Subtype /Link -/A 3567 0 R -/Type /Annot -/Rect [234 496.281 250.2 507.594] -/Border [0 0 0] ->> -endobj -3569 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3570 0 obj -<< -/Subtype /Link -/A 3569 0 R -/Type /Annot -/Rect [250.2 496.281 255.6 507.594] -/Border [0 0 0] ->> -endobj -3571 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3572 0 obj -<< -/Subtype /Link -/A 3571 0 R -/Type /Annot -/Rect [72 473.781 336.501953 486.281] -/Border [0 0 0] ->> -endobj -3573 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3574 0 obj -<< -/Subtype /Link -/A 3573 0 R -/Type /Annot -/Rect [336.501953 473.711 384.501953 486.281] -/Border [0 0 0] ->> -endobj -3575 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3576 0 obj -<< -/Subtype /Link -/A 3575 0 R -/Type /Annot -/Rect [384.501953 473.781 400.126953 486.281] -/Border [0 0 0] ->> -endobj -3577 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3578 0 obj -<< -/Subtype /Link -/A 3577 0 R -/Type /Annot -/Rect [400.126953 473.711 436.126953 486.281] -/Border [0 0 0] ->> -endobj -3579 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3580 0 obj -<< -/Subtype /Link -/A 3579 0 R -/Type /Annot -/Rect [436.126953 473.781 524.62793 486.281] -/Border [0 0 0] ->> -endobj -3581 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3582 0 obj -<< -/Subtype /Link -/A 3581 0 R -/Type /Annot -/Rect [72 461.281 316.389648 473.781] -/Border [0 0 0] ->> -endobj -3504 0 obj -<< -/Type /Page -/Parent 1 0 R -/MediaBox [0 0 612 792] -/Contents 3502 0 R -/Resources 3503 0 R -/Annots [3507 0 R 3510 0 R 3512 0 R 3514 0 R 3516 0 R 3518 0 R 3520 0 R 3522 0 R 3524 0 R 3526 0 R 3528 0 R 3530 0 R 3532 0 R 3534 0 R 3536 0 R 3538 0 R 3540 0 R 3542 0 R 3544 0 R 3546 0 R 3548 0 R 3550 0 R 3552 0 R 3554 0 R 3556 0 R 3558 0 R 3560 0 R 3562 0 R 3564 0 R 3566 0 R 3568 0 R 3570 0 R 3572 0 R 3574 0 R 3576 0 R 3578 0 R 3580 0 R 3582 0 R] ->> -endobj -3503 0 obj -<< -/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] -/Font << -/F4 16 0 R -/F3 9 0 R -/F6 44 0 R -/F5 29 0 R ->> ->> -endobj -3502 0 obj -<< -/Length 1126 -/Filter /FlateDecode ->> -stream -xYn8)r@C{ۅo=8E>GPI6:7T+$lΟ||t}svyfs M'|s% t5}oYj/Ԟk`r| ]6t;|-xkp@۷ -4vXL`B0qjXkH &| $byk~| ;^)Á ^s$',J1kvm6SzC;P:UҾ~4-Ԭ+yH'oB4.J'j24y/[;HdWq&3h-T%>An?"Z{H%۬]B7s_ Xo" +`fÜ<;K hBf„ugR0 -endstream -endobj -3587 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3588 0 obj -<< -/Subtype /Link -/A 3587 0 R -/Type /Annot -/Rect [72 695.502 308.07 720] -/Border [0 0 0] ->> -endobj -3589 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3590 0 obj -<< -/Subtype /Link -/A 3589 0 R -/Type /Annot -/Rect [72 673.002 509.895508 685.502] -/Border [0 0 0] ->> -endobj -3591 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3592 0 obj -<< -/Subtype /Link -/A 3591 0 R -/Type /Annot -/Rect [72 660.502 530.989258 673.002] -/Border [0 0 0] ->> -endobj -3593 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3594 0 obj -<< -/Subtype /Link -/A 3593 0 R -/Type /Annot -/Rect [72 648.002 533.293945 660.502] -/Border [0 0 0] ->> -endobj -3595 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3596 0 obj -<< -/Subtype /Link -/A 3595 0 R -/Type /Annot -/Rect [72 635.502 485.364258 648.002] -/Border [0 0 0] ->> -endobj -3597 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3598 0 obj -<< -/Subtype /Link -/A 3597 0 R -/Type /Annot -/Rect [72 623.002 307.3125 635.502] -/Border [0 0 0] ->> -endobj -3599 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3600 0 obj -<< -/Subtype /Link -/A 3599 0 R -/Type /Annot -/Rect [72 600.502 326.931641 613.002] -/Border [0 0 0] ->> -endobj -3601 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3602 0 obj -<< -/Subtype /Link -/A 3601 0 R -/Type /Annot -/Rect [326.931641 600.432 380.931641 613.002] -/Border [0 0 0] ->> -endobj -3603 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3604 0 obj -<< -/Subtype /Link -/A 3603 0 R -/Type /Annot -/Rect [380.931641 600.502 431.65918 613.002] -/Border [0 0 0] ->> -endobj -3605 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3606 0 obj -<< -/Subtype /Link -/A 3605 0 R -/Type /Annot -/Rect [431.65918 600.432 461.65918 613.002] -/Border [0 0 0] ->> -endobj -3607 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3608 0 obj -<< -/Subtype /Link -/A 3607 0 R -/Type /Annot -/Rect [461.65918 600.502 533.353516 613.002] -/Border [0 0 0] ->> -endobj -3609 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3610 0 obj -<< -/Subtype /Link -/A 3609 0 R -/Type /Annot -/Rect [72 588.002 258.982422 600.502] -/Border [0 0 0] ->> -endobj -3611 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3612 0 obj -<< -/Subtype /Link -/A 3611 0 R -/Type /Annot -/Rect [258.982422 587.932 288.982422 600.502] -/Border [0 0 0] ->> -endobj -3613 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3614 0 obj -<< -/Subtype /Link -/A 3613 0 R -/Type /Annot -/Rect [288.982422 588.002 520.310547 600.502] -/Border [0 0 0] ->> -endobj -3615 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3616 0 obj -<< -/Subtype /Link -/A 3615 0 R -/Type /Annot -/Rect [72 575.502 274.416992 588.002] -/Border [0 0 0] ->> -endobj -3617 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3618 0 obj -<< -/Subtype /Link -/A 3617 0 R -/Type /Annot -/Rect [274.416992 575.432 310.416992 588.002] -/Border [0 0 0] ->> -endobj -3619 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3620 0 obj -<< -/Subtype /Link -/A 3619 0 R -/Type /Annot -/Rect [310.416992 575.502 499.572266 588.002] -/Border [0 0 0] ->> -endobj -3621 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3622 0 obj -<< -/Subtype /Link -/A 3621 0 R -/Type /Annot -/Rect [72 563.002 283.484375 575.502] -/Border [0 0 0] ->> -endobj -3623 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3624 0 obj -<< -/Subtype /Link -/A 3623 0 R -/Type /Annot -/Rect [72 540.502 523.665039 553.002] -/Border [0 0 0] ->> -endobj -3625 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3626 0 obj -<< -/Subtype /Link -/A 3625 0 R -/Type /Annot -/Rect [72 527.862 96 540.432] -/Border [0 0 0] ->> -endobj -3627 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3628 0 obj -<< -/Subtype /Link -/A 3627 0 R -/Type /Annot -/Rect [96 527.932 166.991211 540.432] -/Border [0 0 0] ->> -endobj -3629 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3630 0 obj -<< -/Subtype /Link -/A 3629 0 R -/Type /Annot -/Rect [166.991211 527.862 202.991211 540.432] -/Border [0 0 0] ->> -endobj -3631 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3632 0 obj -<< -/Subtype /Link -/A 3631 0 R -/Type /Annot -/Rect [202.991211 527.932 208.889648 540.432] -/Border [0 0 0] ->> -endobj -3633 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3634 0 obj -<< -/Subtype /Link -/A 3633 0 R -/Type /Annot -/Rect [208.889648 527.862 238.889648 540.432] -/Border [0 0 0] ->> -endobj -3635 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3636 0 obj -<< -/Subtype /Link -/A 3635 0 R -/Type /Annot -/Rect [238.889648 527.932 265.945313 540.432] -/Border [0 0 0] ->> -endobj -3637 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3638 0 obj -<< -/Subtype /Link -/A 3637 0 R -/Type /Annot -/Rect [265.945313 527.862 307.945313 540.432] -/Border [0 0 0] ->> -endobj -3639 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3640 0 obj -<< -/Subtype /Link -/A 3639 0 R -/Type /Annot -/Rect [307.945313 527.932 521.724609 540.432] -/Border [0 0 0] ->> -endobj -3641 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3642 0 obj -<< -/Subtype /Link -/A 3641 0 R -/Type /Annot -/Rect [72 515.432 425.066406 527.932] -/Border [0 0 0] ->> -endobj -3643 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3644 0 obj -<< -/Subtype /Link -/A 3643 0 R -/Type /Annot -/Rect [72 494.119 99 505.432] -/Border [0 0 0] ->> -endobj -3645 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3646 0 obj -<< -/Subtype /Link -/A 3645 0 R -/Type /Annot -/Rect [99 494.119 104.4 505.432] -/Border [0 0 0] ->> -endobj -3647 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3648 0 obj -<< -/Subtype /Link -/A 3647 0 R -/Type /Annot -/Rect [104.4 494.119 131.4 505.432] -/Border [0 0 0] ->> -endobj -3649 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3650 0 obj -<< -/Subtype /Link -/A 3649 0 R -/Type /Annot -/Rect [131.4 494.119 136.8 505.432] -/Border [0 0 0] ->> -endobj -3651 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3652 0 obj -<< -/Subtype /Link -/A 3651 0 R -/Type /Annot -/Rect [136.8 494.119 142.2 505.432] -/Border [0 0 0] ->> -endobj -3653 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3654 0 obj -<< -/Subtype /Link -/A 3653 0 R -/Type /Annot -/Rect [142.2 494.119 147.6 505.432] -/Border [0 0 0] ->> -endobj -3655 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3656 0 obj -<< -/Subtype /Link -/A 3655 0 R -/Type /Annot -/Rect [147.6 494.119 509.4 505.432] -/Border [0 0 0] ->> -endobj -3657 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3658 0 obj -<< -/Subtype /Link -/A 3657 0 R -/Type /Annot -/Rect [72 482.806 514.8 494.119] -/Border [0 0 0] ->> -endobj -3659 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3660 0 obj -<< -/Subtype /Link -/A 3659 0 R -/Type /Annot -/Rect [72 471.493 531 482.806] -/Border [0 0 0] ->> -endobj -3661 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3662 0 obj -<< -/Subtype /Link -/A 3661 0 R -/Type /Annot -/Rect [72 460.18 466.2 471.493] -/Border [0 0 0] ->> -endobj -3663 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3664 0 obj -<< -/Subtype /Link -/A 3663 0 R -/Type /Annot -/Rect [466.2 460.18 471.6 471.493] -/Border [0 0 0] ->> -endobj -3665 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3666 0 obj -<< -/Subtype /Link -/A 3665 0 R -/Type /Annot -/Rect [72 437.554 88.2 448.867] -/Border [0 0 0] ->> -endobj -3667 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3668 0 obj -<< -/Subtype /Link -/A 3667 0 R -/Type /Annot -/Rect [88.2 437.554 93.6 448.867] -/Border [0 0 0] ->> -endobj -3669 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3670 0 obj -<< -/Subtype /Link -/A 3669 0 R -/Type /Annot -/Rect [93.6 437.554 136.8 448.867] -/Border [0 0 0] ->> -endobj -3671 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3672 0 obj -<< -/Subtype /Link -/A 3671 0 R -/Type /Annot -/Rect [136.8 437.554 142.2 448.867] -/Border [0 0 0] ->> -endobj -3673 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3674 0 obj -<< -/Subtype /Link -/A 3673 0 R -/Type /Annot -/Rect [142.2 437.554 147.6 448.867] -/Border [0 0 0] ->> -endobj -3675 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3676 0 obj -<< -/Subtype /Link -/A 3675 0 R -/Type /Annot -/Rect [147.6 437.554 153 448.867] -/Border [0 0 0] ->> -endobj -3677 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3678 0 obj -<< -/Subtype /Link -/A 3677 0 R -/Type /Annot -/Rect [153 437.554 158.4 448.867] -/Border [0 0 0] ->> -endobj -3679 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3680 0 obj -<< -/Subtype /Link -/A 3679 0 R -/Type /Annot -/Rect [72 426.241 88.2 437.554] -/Border [0 0 0] ->> -endobj -3681 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3682 0 obj -<< -/Subtype /Link -/A 3681 0 R -/Type /Annot -/Rect [88.2 426.241 93.6 437.554] -/Border [0 0 0] ->> -endobj -3683 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3684 0 obj -<< -/Subtype /Link -/A 3683 0 R -/Type /Annot -/Rect [93.6 426.241 115.2 437.554] -/Border [0 0 0] ->> -endobj -3685 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3686 0 obj -<< -/Subtype /Link -/A 3685 0 R -/Type /Annot -/Rect [115.2 426.241 120.6 437.554] -/Border [0 0 0] ->> -endobj -3687 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3688 0 obj -<< -/Subtype /Link -/A 3687 0 R -/Type /Annot -/Rect [120.6 426.241 282.6 437.554] -/Border [0 0 0] ->> -endobj -3689 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3690 0 obj -<< -/Subtype /Link -/A 3689 0 R -/Type /Annot -/Rect [282.6 426.241 309.6 437.554] -/Border [0 0 0] ->> -endobj -3691 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3692 0 obj -<< -/Subtype /Link -/A 3691 0 R -/Type /Annot -/Rect [309.6 426.241 315 437.554] -/Border [0 0 0] ->> -endobj -3693 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3694 0 obj -<< -/Subtype /Link -/A 3693 0 R -/Type /Annot -/Rect [315 426.241 336.6 437.554] -/Border [0 0 0] ->> -endobj -3695 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3696 0 obj -<< -/Subtype /Link -/A 3695 0 R -/Type /Annot -/Rect [72 414.928 82.8 426.241] -/Border [0 0 0] ->> -endobj -3697 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3698 0 obj -<< -/Subtype /Link -/A 3697 0 R -/Type /Annot -/Rect [82.8 414.928 142.2 426.241] -/Border [0 0 0] ->> -endobj -3699 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3700 0 obj -<< -/Subtype /Link -/A 3699 0 R -/Type /Annot -/Rect [72 403.615 82.8 414.928] -/Border [0 0 0] ->> -endobj -3701 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3702 0 obj -<< -/Subtype /Link -/A 3701 0 R -/Type /Annot -/Rect [82.8 403.615 153 414.928] -/Border [0 0 0] ->> -endobj -3703 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3704 0 obj -<< -/Subtype /Link -/A 3703 0 R -/Type /Annot -/Rect [72 392.302 77.4 403.615] -/Border [0 0 0] ->> -endobj -3705 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3706 0 obj -<< -/Subtype /Link -/A 3705 0 R -/Type /Annot -/Rect [72 380.989 82.8 392.302] -/Border [0 0 0] ->> -endobj -3707 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3708 0 obj -<< -/Subtype /Link -/A 3707 0 R -/Type /Annot -/Rect [72 358.363 153 369.676] -/Border [0 0 0] ->> -endobj -3709 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3710 0 obj -<< -/Subtype /Link -/A 3709 0 R -/Type /Annot -/Rect [72 347.05 126 358.363] -/Border [0 0 0] ->> -endobj -3711 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3712 0 obj -<< -/Subtype /Link -/A 3711 0 R -/Type /Annot -/Rect [126 347.05 147.6 358.363] -/Border [0 0 0] ->> -endobj -3713 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3714 0 obj -<< -/Subtype /Link -/A 3713 0 R -/Type /Annot -/Rect [147.6 347.05 153 358.363] -/Border [0 0 0] ->> -endobj -3715 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3716 0 obj -<< -/Subtype /Link -/A 3715 0 R -/Type /Annot -/Rect [153 347.05 174.6 358.363] -/Border [0 0 0] ->> -endobj -3717 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3718 0 obj -<< -/Subtype /Link -/A 3717 0 R -/Type /Annot -/Rect [174.6 347.05 180 358.363] -/Border [0 0 0] ->> -endobj -3719 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3720 0 obj -<< -/Subtype /Link -/A 3719 0 R -/Type /Annot -/Rect [180 347.05 190.8 358.363] -/Border [0 0 0] ->> -endobj -3721 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3722 0 obj -<< -/Subtype /Link -/A 3721 0 R -/Type /Annot -/Rect [190.8 347.05 196.2 358.363] -/Border [0 0 0] ->> -endobj -3723 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3724 0 obj -<< -/Subtype /Link -/A 3723 0 R -/Type /Annot -/Rect [196.2 347.05 239.4 358.363] -/Border [0 0 0] ->> -endobj -3725 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3726 0 obj -<< -/Subtype /Link -/A 3725 0 R -/Type /Annot -/Rect [239.4 347.05 244.8 358.363] -/Border [0 0 0] ->> -endobj -3727 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3728 0 obj -<< -/Subtype /Link -/A 3727 0 R -/Type /Annot -/Rect [244.8 347.05 250.2 358.363] -/Border [0 0 0] ->> -endobj -3729 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3730 0 obj -<< -/Subtype /Link -/A 3729 0 R -/Type /Annot -/Rect [250.2 347.05 255.6 358.363] -/Border [0 0 0] ->> -endobj -3731 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3732 0 obj -<< -/Subtype /Link -/A 3731 0 R -/Type /Annot -/Rect [255.6 347.05 261 358.363] -/Border [0 0 0] ->> -endobj -3733 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3734 0 obj -<< -/Subtype /Link -/A 3733 0 R -/Type /Annot -/Rect [261 347.05 288 358.363] -/Border [0 0 0] ->> -endobj -3735 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3736 0 obj -<< -/Subtype /Link -/A 3735 0 R -/Type /Annot -/Rect [288 347.05 293.4 358.363] -/Border [0 0 0] ->> -endobj -3737 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3738 0 obj -<< -/Subtype /Link -/A 3737 0 R -/Type /Annot -/Rect [293.4 347.05 315 358.363] -/Border [0 0 0] ->> -endobj -3739 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3740 0 obj -<< -/Subtype /Link -/A 3739 0 R -/Type /Annot -/Rect [72 335.737 82.8 347.05] -/Border [0 0 0] ->> -endobj -3741 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3742 0 obj -<< -/Subtype /Link -/A 3741 0 R -/Type /Annot -/Rect [82.8 335.737 142.2 347.05] -/Border [0 0 0] ->> -endobj -3743 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3744 0 obj -<< -/Subtype /Link -/A 3743 0 R -/Type /Annot -/Rect [72 324.424 82.8 335.737] -/Border [0 0 0] ->> -endobj -3745 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3746 0 obj -<< -/Subtype /Link -/A 3745 0 R -/Type /Annot -/Rect [82.8 324.424 163.8 335.737] -/Border [0 0 0] ->> -endobj -3747 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3748 0 obj -<< -/Subtype /Link -/A 3747 0 R -/Type /Annot -/Rect [72 313.111 77.4 324.424] -/Border [0 0 0] ->> -endobj -3749 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3750 0 obj -<< -/Subtype /Link -/A 3749 0 R -/Type /Annot -/Rect [72 301.798 82.8 313.111] -/Border [0 0 0] ->> -endobj -3751 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3752 0 obj -<< -/Subtype /Link -/A 3751 0 R -/Type /Annot -/Rect [72 279.172 153 290.485] -/Border [0 0 0] ->> -endobj -3753 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3754 0 obj -<< -/Subtype /Link -/A 3753 0 R -/Type /Annot -/Rect [72 267.859 126 279.172] -/Border [0 0 0] ->> -endobj -3755 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3756 0 obj -<< -/Subtype /Link -/A 3755 0 R -/Type /Annot -/Rect [126 267.859 147.6 279.172] -/Border [0 0 0] ->> -endobj -3757 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3758 0 obj -<< -/Subtype /Link -/A 3757 0 R -/Type /Annot -/Rect [147.6 267.859 153 279.172] -/Border [0 0 0] ->> -endobj -3759 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3760 0 obj -<< -/Subtype /Link -/A 3759 0 R -/Type /Annot -/Rect [153 267.859 174.6 279.172] -/Border [0 0 0] ->> -endobj -3761 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3762 0 obj -<< -/Subtype /Link -/A 3761 0 R -/Type /Annot -/Rect [174.6 267.859 180 279.172] -/Border [0 0 0] ->> -endobj -3763 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3764 0 obj -<< -/Subtype /Link -/A 3763 0 R -/Type /Annot -/Rect [180 267.859 190.8 279.172] -/Border [0 0 0] ->> -endobj -3765 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3766 0 obj -<< -/Subtype /Link -/A 3765 0 R -/Type /Annot -/Rect [190.8 267.859 196.2 279.172] -/Border [0 0 0] ->> -endobj -3767 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3768 0 obj -<< -/Subtype /Link -/A 3767 0 R -/Type /Annot -/Rect [196.2 267.859 223.2 279.172] -/Border [0 0 0] ->> -endobj -3769 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3770 0 obj -<< -/Subtype /Link -/A 3769 0 R -/Type /Annot -/Rect [223.2 267.859 228.6 279.172] -/Border [0 0 0] ->> -endobj -3771 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3772 0 obj -<< -/Subtype /Link -/A 3771 0 R -/Type /Annot -/Rect [228.6 267.859 266.4 279.172] -/Border [0 0 0] ->> -endobj -3773 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3774 0 obj -<< -/Subtype /Link -/A 3773 0 R -/Type /Annot -/Rect [266.4 267.859 271.8 279.172] -/Border [0 0 0] ->> -endobj -3775 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3776 0 obj -<< -/Subtype /Link -/A 3775 0 R -/Type /Annot -/Rect [271.8 267.859 277.2 279.172] -/Border [0 0 0] ->> -endobj -3777 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3778 0 obj -<< -/Subtype /Link -/A 3777 0 R -/Type /Annot -/Rect [277.2 267.859 282.6 279.172] -/Border [0 0 0] ->> -endobj -3779 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3780 0 obj -<< -/Subtype /Link -/A 3779 0 R -/Type /Annot -/Rect [282.6 267.859 288 279.172] -/Border [0 0 0] ->> -endobj -3781 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3782 0 obj -<< -/Subtype /Link -/A 3781 0 R -/Type /Annot -/Rect [288 267.859 315 279.172] -/Border [0 0 0] ->> -endobj -3783 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3784 0 obj -<< -/Subtype /Link -/A 3783 0 R -/Type /Annot -/Rect [315 267.859 320.4 279.172] -/Border [0 0 0] ->> -endobj -3785 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3786 0 obj -<< -/Subtype /Link -/A 3785 0 R -/Type /Annot -/Rect [320.4 267.859 347.4 279.172] -/Border [0 0 0] ->> -endobj -3787 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3788 0 obj -<< -/Subtype /Link -/A 3787 0 R -/Type /Annot -/Rect [72 256.546 82.8 267.859] -/Border [0 0 0] ->> -endobj -3789 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3790 0 obj -<< -/Subtype /Link -/A 3789 0 R -/Type /Annot -/Rect [82.8 256.546 142.2 267.859] -/Border [0 0 0] ->> -endobj -3791 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3792 0 obj -<< -/Subtype /Link -/A 3791 0 R -/Type /Annot -/Rect [72 245.233 82.8 256.546] -/Border [0 0 0] ->> -endobj -3793 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3794 0 obj -<< -/Subtype /Link -/A 3793 0 R -/Type /Annot -/Rect [82.8 245.233 158.4 256.546] -/Border [0 0 0] ->> -endobj -3795 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3796 0 obj -<< -/Subtype /Link -/A 3795 0 R -/Type /Annot -/Rect [72 233.92 77.4 245.233] -/Border [0 0 0] ->> -endobj -3797 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3798 0 obj -<< -/Subtype /Link -/A 3797 0 R -/Type /Annot -/Rect [72 222.607 82.8 233.92] -/Border [0 0 0] ->> -endobj -3799 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3800 0 obj -<< -/Subtype /Link -/A 3799 0 R -/Type /Annot -/Rect [72 199.981 153 211.294] -/Border [0 0 0] ->> -endobj -3801 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3802 0 obj -<< -/Subtype /Link -/A 3801 0 R -/Type /Annot -/Rect [72 188.668 126 199.981] -/Border [0 0 0] ->> -endobj -3803 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3804 0 obj -<< -/Subtype /Link -/A 3803 0 R -/Type /Annot -/Rect [126 188.668 147.6 199.981] -/Border [0 0 0] ->> -endobj -3805 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3806 0 obj -<< -/Subtype /Link -/A 3805 0 R -/Type /Annot -/Rect [147.6 188.668 153 199.981] -/Border [0 0 0] ->> -endobj -3807 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3808 0 obj -<< -/Subtype /Link -/A 3807 0 R -/Type /Annot -/Rect [153 188.668 174.6 199.981] -/Border [0 0 0] ->> -endobj -3809 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3810 0 obj -<< -/Subtype /Link -/A 3809 0 R -/Type /Annot -/Rect [174.6 188.668 180 199.981] -/Border [0 0 0] ->> -endobj -3811 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3812 0 obj -<< -/Subtype /Link -/A 3811 0 R -/Type /Annot -/Rect [180 188.668 190.8 199.981] -/Border [0 0 0] ->> -endobj -3813 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3814 0 obj -<< -/Subtype /Link -/A 3813 0 R -/Type /Annot -/Rect [190.8 188.668 196.2 199.981] -/Border [0 0 0] ->> -endobj -3815 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3816 0 obj -<< -/Subtype /Link -/A 3815 0 R -/Type /Annot -/Rect [196.2 188.668 244.8 199.981] -/Border [0 0 0] ->> -endobj -3817 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3818 0 obj -<< -/Subtype /Link -/A 3817 0 R -/Type /Annot -/Rect [244.8 188.668 250.2 199.981] -/Border [0 0 0] ->> -endobj -3819 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3820 0 obj -<< -/Subtype /Link -/A 3819 0 R -/Type /Annot -/Rect [250.2 188.668 255.6 199.981] -/Border [0 0 0] ->> -endobj -3821 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3822 0 obj -<< -/Subtype /Link -/A 3821 0 R -/Type /Annot -/Rect [255.6 188.668 261 199.981] -/Border [0 0 0] ->> -endobj -3823 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3824 0 obj -<< -/Subtype /Link -/A 3823 0 R -/Type /Annot -/Rect [261 188.668 266.4 199.981] -/Border [0 0 0] ->> -endobj -3825 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3826 0 obj -<< -/Subtype /Link -/A 3825 0 R -/Type /Annot -/Rect [266.4 188.668 293.4 199.981] -/Border [0 0 0] ->> -endobj -3827 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3828 0 obj -<< -/Subtype /Link -/A 3827 0 R -/Type /Annot -/Rect [293.4 188.668 298.8 199.981] -/Border [0 0 0] ->> -endobj -3829 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3830 0 obj -<< -/Subtype /Link -/A 3829 0 R -/Type /Annot -/Rect [298.8 188.668 325.8 199.981] -/Border [0 0 0] ->> -endobj -3831 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3832 0 obj -<< -/Subtype /Link -/A 3831 0 R -/Type /Annot -/Rect [72 177.355 82.8 188.668] -/Border [0 0 0] ->> -endobj -3833 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3834 0 obj -<< -/Subtype /Link -/A 3833 0 R -/Type /Annot -/Rect [82.8 177.355 142.2 188.668] -/Border [0 0 0] ->> -endobj -3835 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3836 0 obj -<< -/Subtype /Link -/A 3835 0 R -/Type /Annot -/Rect [72 166.042 82.8 177.355] -/Border [0 0 0] ->> -endobj -3837 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3838 0 obj -<< -/Subtype /Link -/A 3837 0 R -/Type /Annot -/Rect [82.8 166.042 169.2 177.355] -/Border [0 0 0] ->> -endobj -3839 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3840 0 obj -<< -/Subtype /Link -/A 3839 0 R -/Type /Annot -/Rect [72 154.729 77.4 166.042] -/Border [0 0 0] ->> -endobj -3841 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3842 0 obj -<< -/Subtype /Link -/A 3841 0 R -/Type /Annot -/Rect [72 143.416 82.8 154.729] -/Border [0 0 0] ->> -endobj -3843 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3844 0 obj -<< -/Subtype /Link -/A 3843 0 R -/Type /Annot -/Rect [72 120.79 212.4 132.103] -/Border [0 0 0] ->> -endobj -3845 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3846 0 obj -<< -/Subtype /Link -/A 3845 0 R -/Type /Annot -/Rect [72 109.477 288 120.79] -/Border [0 0 0] ->> -endobj -3847 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3848 0 obj -<< -/Subtype /Link -/A 3847 0 R -/Type /Annot -/Rect [72 86.977 285.735352 99.477] -/Border [0 0 0] ->> -endobj -3585 0 obj -<< -/Type /Page -/Parent 1 0 R -/MediaBox [0 0 612 792] -/Contents 3583 0 R -/Resources 3584 0 R -/Annots [3588 0 R 3590 0 R 3592 0 R 3594 0 R 3596 0 R 3598 0 R 3600 0 R 3602 0 R 3604 0 R 3606 0 R 3608 0 R 3610 0 R 3612 0 R 3614 0 R 3616 0 R 3618 0 R 3620 0 R 3622 0 R 3624 0 R 3626 0 R 3628 0 R 3630 0 R 3632 0 R 3634 0 R 3636 0 R 3638 0 R 3640 0 R 3642 0 R 3644 0 R 3646 0 R 3648 0 R 3650 0 R 3652 0 R 3654 0 R 3656 0 R 3658 0 R 3660 0 R 3662 0 R 3664 0 R 3666 0 R 3668 0 R 3670 0 R 3672 0 R 3674 0 R 3676 0 R 3678 0 R 3680 0 R 3682 0 R 3684 0 R 3686 0 R 3688 0 R 3690 0 R 3692 0 R 3694 0 R 3696 0 R 3698 0 R 3700 0 R 3702 0 R 3704 0 R 3706 0 R 3708 0 R 3710 0 R 3712 0 R 3714 0 R 3716 0 R 3718 0 R 3720 0 R 3722 0 R 3724 0 R 3726 0 R 3728 0 R 3730 0 R 3732 0 R 3734 0 R 3736 0 R 3738 0 R 3740 0 R 3742 0 R 3744 0 R 3746 0 R 3748 0 R 3750 0 R 3752 0 R 3754 0 R 3756 0 R 3758 0 R 3760 0 R 3762 0 R 3764 0 R 3766 0 R 3768 0 R 3770 0 R 3772 0 R 3774 0 R 3776 0 R 3778 0 R 3780 0 R 3782 0 R 3784 0 R 3786 0 R 3788 0 R 3790 0 R 3792 0 R 3794 0 R 3796 0 R 3798 0 R 3800 0 R 3802 0 R 3804 0 R 3806 0 R 3808 0 R 3810 0 R 3812 0 R 3814 0 R 3816 0 R 3818 0 R 3820 0 R 3822 0 R 3824 0 R 3826 0 R 3828 0 R 3830 0 R 3832 0 R 3834 0 R 3836 0 R 3838 0 R 3840 0 R 3842 0 R 3844 0 R 3846 0 R 3848 0 R] ->> -endobj -3584 0 obj -<< -/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] -/Font << -/F4 16 0 R -/F3 9 0 R -/F6 44 0 R -/F5 29 0 R -/F1 3849 0 R ->> ->> -endobj -3583 0 obj -<< -/Length 3366 -/Filter /FlateDecode ->> -stream -x]ݎ T`.zI`/Z]_JmZ<Ɍ'Ξ]x'eH~"ث㿞~?'rEߟFupR 9p~~7)AK) q{(:ӕ|W4jFgT>?O;4[0>q&]BrWG$LcJ;G]c8I}^Csrdse0)5pN8Y_dqmG E6Սf0ˑҼ X K^a1kY,DHMìAP>EEehkzFI"PdfZ&#Υ -l -ﱒUo|ȦL~e<1qaj')`lck CZONqa#\0 pjO45Y3膙8MִHffnҤ\n҆-( -܂\dV3Agڊ -W˥t!Z`#Mi, ^ZegנJ 2 yPpmDM-rFeԔ+MU$sde$&%iZZ-$2Z g#]h2AU=odb'n#AK4Z1+IhfG;,xHH(S bI{)\36KXoR@`3wp3MIc-yg`eGREY|"' ->2cR)ݽ"PxcFG4ثMZI> ͋ ›r>ua9yb]֛J*Vm:]OZڲ$rnʚ^f쾣y/}`QLtQ(2.#b9LsK%54u54$`&.RHMx$:M i;}y [H0cTTmIkGM^<{tDљbZͼ#o2";Eqf})݄KXhpɢ,;y;WFѩ1T̩m^㰵C+lkUA$ n碨.}{EC7khy(eoH9)}imHђGP<,O|/}>:ֳڃ5 DwKhkM\ڍ1HA!-&:aeq'h둃R]b_ľPB.!p +YX$&}haK!Ζr8ra@8' !eTm:p}% MZҔfX:DMՕ+Vngo90y(ǡ8ˡcrM: ]A_= ,. +WIAKfa 47 [#5 䘨ydx0Ș?߲'=rt^h/mQ6 GL@uY#ҭFJ7ubmFQw5:31OZ91 C%e2P_jd+66Iwif8Lo/[\ =fe'x(F;r\+ALW̉2ipNAk蕫{-[־ުZnck?3JNkp/ӽ苣)Z̦Ry,Rj0rkdHAKRSAwN -{ȽUQ|\u1Eu9^Ox79Ki\|A:=JZs}7?Tv k_M0 -u~CY#yv^岶*ihy̙ƿb -\p,ʮ{F-v -^T^ШE!U;5 S/{%t"f1NH`ܛ< -la-FxoZËZ}Ta'EhxxmȲuiMR+Z% -I1۝ p]ɗi}ˠ.+> 7T}Kiî+;S}Qr6+Wl+,cTjye#DKQ ޡM -N;`ܛ±v=l{H ,@ppY -Z5~wdO=+.V]v ) RPA> BE?qI+ty^kj-ݴսw7ܜ -kU^=+~uj;w;ި]~icy7iAҲھzjl(`o/WqCJ F}?p ߱`;M_֖ ^U~Fw/_k$߳kݕjZZ+"k\?#Er[C;=9XC;gNiO;֐NY|ik{]>mX_m|Ac_ıݩߨ#{#(“χizKo(EiGunyy/(T]HDTp97Z)쪹XO[|F۬{˧}0mْ!3d^jGTٴ3e3ZOc2ur79e"d F^Ĝ^t煯|t[]e4E(6ǀ*$:G˺䋦x^( -&́~8&eN'*;ːu9p lV؃7QH_O I9Pvo^,^0 -EsZ"94;n^zj _: QjH 盄'[ld^\_dp~[ɗV@M(QQw.{O.C1IƢu",R&rY6ip0 &YjKJZ-fbp@L/15(_0_PU0JcvѦ8.':6̂ѹ>qsXxnsAPQ-VNP/Uy:LA`^l -endstream -endobj -3854 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3855 0 obj -<< -/Subtype /Link -/A 3854 0 R -/Type /Annot -/Rect [72 695.502 159.858 720] -/Border [0 0 0] ->> -endobj -3856 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3857 0 obj -<< -/Subtype /Link -/A 3856 0 R -/Type /Annot -/Rect [72 673.002 536.223633 685.502] -/Border [0 0 0] ->> -endobj -3858 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3859 0 obj -<< -/Subtype /Link -/A 3858 0 R -/Type /Annot -/Rect [72 660.502 154.929688 673.002] -/Border [0 0 0] ->> -endobj -3860 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3861 0 obj -<< -/Subtype /Link -/A 3860 0 R -/Type /Annot -/Rect [154.929688 660.432 178.929688 673.002] -/Border [0 0 0] ->> -endobj -3862 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3863 0 obj -<< -/Subtype /Link -/A 3862 0 R -/Type /Annot -/Rect [178.929688 660.502 367.464844 673.002] -/Border [0 0 0] ->> -endobj -3864 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3865 0 obj -<< -/Subtype /Link -/A 3864 0 R -/Type /Annot -/Rect [72 637.932 126 650.502] -/Border [0 0 0] ->> -endobj -3866 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3867 0 obj -<< -/Subtype /Link -/A 3866 0 R -/Type /Annot -/Rect [126 638.002 167.411133 650.502] -/Border [0 0 0] ->> -endobj -3868 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3869 0 obj -<< -/Subtype /Link -/A 3868 0 R -/Type /Annot -/Rect [167.411133 637.932 197.411133 650.502] -/Border [0 0 0] ->> -endobj -3870 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3871 0 obj -<< -/Subtype /Link -/A 3870 0 R -/Type /Annot -/Rect [197.411133 638.002 380.082031 650.502] -/Border [0 0 0] ->> -endobj -3872 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3873 0 obj -<< -/Subtype /Link -/A 3872 0 R -/Type /Annot -/Rect [72 619.432 102 632.002] -/Border [0 0 0] ->> -endobj -3874 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3875 0 obj -<< -/Subtype /Link -/A 3874 0 R -/Type /Annot -/Rect [102 619.502 528.230469 632.002] -/Border [0 0 0] ->> -endobj -3876 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3877 0 obj -<< -/Subtype /Link -/A 3876 0 R -/Type /Annot -/Rect [72 607.002 160.691406 619.502] -/Border [0 0 0] ->> -endobj -3878 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3879 0 obj -<< -/Subtype /Link -/A 3878 0 R -/Type /Annot -/Rect [72 588.432 108 601.002] -/Border [0 0 0] ->> -endobj -3880 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3881 0 obj -<< -/Subtype /Link -/A 3880 0 R -/Type /Annot -/Rect [108 588.502 373.249023 601.002] -/Border [0 0 0] ->> -endobj -3882 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3883 0 obj -<< -/Subtype /Link -/A 3882 0 R -/Type /Annot -/Rect [72 569.932 120 582.502] -/Border [0 0 0] ->> -endobj -3884 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3885 0 obj -<< -/Subtype /Link -/A 3884 0 R -/Type /Annot -/Rect [120 570.002 487.089844 582.502] -/Border [0 0 0] ->> -endobj -3886 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3887 0 obj -<< -/Subtype /Link -/A 3886 0 R -/Type /Annot -/Rect [487.089844 569.932 511.089844 582.502] -/Border [0 0 0] ->> -endobj -3888 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3889 0 obj -<< -/Subtype /Link -/A 3888 0 R -/Type /Annot -/Rect [511.089844 570.002 526.416992 582.502] -/Border [0 0 0] ->> -endobj -3890 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3891 0 obj -<< -/Subtype /Link -/A 3890 0 R -/Type /Annot -/Rect [72 557.502 199.226563 570.002] -/Border [0 0 0] ->> -endobj -3892 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3893 0 obj -<< -/Subtype /Link -/A 3892 0 R -/Type /Annot -/Rect [72 538.932 114 551.502] -/Border [0 0 0] ->> -endobj -3894 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3895 0 obj -<< -/Subtype /Link -/A 3894 0 R -/Type /Annot -/Rect [114 539.002 343.448242 551.502] -/Border [0 0 0] ->> -endobj -3896 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3897 0 obj -<< -/Subtype /Link -/A 3896 0 R -/Type /Annot -/Rect [72 520.432 126 533.002] -/Border [0 0 0] ->> -endobj -3898 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3899 0 obj -<< -/Subtype /Link -/A 3898 0 R -/Type /Annot -/Rect [126 520.502 451.375977 533.002] -/Border [0 0 0] ->> -endobj -3900 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3901 0 obj -<< -/Subtype /Link -/A 3900 0 R -/Type /Annot -/Rect [72 501.932 108 514.502] -/Border [0 0 0] ->> -endobj -3902 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3903 0 obj -<< -/Subtype /Link -/A 3902 0 R -/Type /Annot -/Rect [108 502.002 476.505859 514.502] -/Border [0 0 0] ->> -endobj -3904 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3905 0 obj -<< -/Subtype /Link -/A 3904 0 R -/Type /Annot -/Rect [72 483.432 144 496.002] -/Border [0 0 0] ->> -endobj -3906 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3907 0 obj -<< -/Subtype /Link -/A 3906 0 R -/Type /Annot -/Rect [144 483.502 415.884766 496.002] -/Border [0 0 0] ->> -endobj -3908 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3909 0 obj -<< -/Subtype /Link -/A 3908 0 R -/Type /Annot -/Rect [72 464.932 114 477.502] -/Border [0 0 0] ->> -endobj -3910 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3911 0 obj -<< -/Subtype /Link -/A 3910 0 R -/Type /Annot -/Rect [114 465.002 353.589844 477.502] -/Border [0 0 0] ->> -endobj -3912 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3913 0 obj -<< -/Subtype /Link -/A 3912 0 R -/Type /Annot -/Rect [72 446.432 138 459.002] -/Border [0 0 0] ->> -endobj -3914 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3915 0 obj -<< -/Subtype /Link -/A 3914 0 R -/Type /Annot -/Rect [138 446.502 402.677734 459.002] -/Border [0 0 0] ->> -endobj -3916 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3917 0 obj -<< -/Subtype /Link -/A 3916 0 R -/Type /Annot -/Rect [72 427.932 168 440.502] -/Border [0 0 0] ->> -endobj -3918 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3919 0 obj -<< -/Subtype /Link -/A 3918 0 R -/Type /Annot -/Rect [168 428.002 454.757813 440.502] -/Border [0 0 0] ->> -endobj -3920 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3921 0 obj -<< -/Subtype /Link -/A 3920 0 R -/Type /Annot -/Rect [72 409.432 96 422.002] -/Border [0 0 0] ->> -endobj -3922 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3923 0 obj -<< -/Subtype /Link -/A 3922 0 R -/Type /Annot -/Rect [96 409.502 226.600586 422.002] -/Border [0 0 0] ->> -endobj -3924 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3925 0 obj -<< -/Subtype /Link -/A 3924 0 R -/Type /Annot -/Rect [226.600586 409.432 250.600586 422.002] -/Border [0 0 0] ->> -endobj -3926 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3927 0 obj -<< -/Subtype /Link -/A 3926 0 R -/Type /Annot -/Rect [250.600586 409.502 306.855469 422.002] -/Border [0 0 0] ->> -endobj -3928 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3929 0 obj -<< -/Subtype /Link -/A 3928 0 R -/Type /Annot -/Rect [72 390.932 108 403.502] -/Border [0 0 0] ->> -endobj -3930 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3931 0 obj -<< -/Subtype /Link -/A 3930 0 R -/Type /Annot -/Rect [108 391.002 249.494141 403.502] -/Border [0 0 0] ->> -endobj -3932 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3933 0 obj -<< -/Subtype /Link -/A 3932 0 R -/Type /Annot -/Rect [72 372.432 96 385.002] -/Border [0 0 0] ->> -endobj -3934 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3935 0 obj -<< -/Subtype /Link -/A 3934 0 R -/Type /Annot -/Rect [96 372.502 399.876953 385.002] -/Border [0 0 0] ->> -endobj -3936 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3937 0 obj -<< -/Subtype /Link -/A 3936 0 R -/Type /Annot -/Rect [72 353.932 126 366.502] -/Border [0 0 0] ->> -endobj -3938 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3939 0 obj -<< -/Subtype /Link -/A 3938 0 R -/Type /Annot -/Rect [126 354.002 284.408203 366.502] -/Border [0 0 0] ->> -endobj -3940 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3941 0 obj -<< -/Subtype /Link -/A 3940 0 R -/Type /Annot -/Rect [72 335.432 108 348.002] -/Border [0 0 0] ->> -endobj -3942 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3943 0 obj -<< -/Subtype /Link -/A 3942 0 R -/Type /Annot -/Rect [108 335.502 265.900391 348.002] -/Border [0 0 0] ->> -endobj -3944 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3945 0 obj -<< -/Subtype /Link -/A 3944 0 R -/Type /Annot -/Rect [72 316.932 114 329.502] -/Border [0 0 0] ->> -endobj -3946 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3947 0 obj -<< -/Subtype /Link -/A 3946 0 R -/Type /Annot -/Rect [114 317.002 352.134766 329.502] -/Border [0 0 0] ->> -endobj -3948 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3949 0 obj -<< -/Subtype /Link -/A 3948 0 R -/Type /Annot -/Rect [352.134766 316.932 376.134766 329.502] -/Border [0 0 0] ->> -endobj -3950 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3951 0 obj -<< -/Subtype /Link -/A 3950 0 R -/Type /Annot -/Rect [376.134766 317.002 380.104492 329.502] -/Border [0 0 0] ->> -endobj -3952 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3953 0 obj -<< -/Subtype /Link -/A 3952 0 R -/Type /Annot -/Rect [72 298.432 120 311.002] -/Border [0 0 0] ->> -endobj -3954 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3955 0 obj -<< -/Subtype /Link -/A 3954 0 R -/Type /Annot -/Rect [120 298.502 520.522461 311.002] -/Border [0 0 0] ->> -endobj -3956 0 obj -<< -/S /URI -/URI (https://www.w3schools.com/tags/canvas_textbaseline.asp) ->> -endobj -3957 0 obj -<< -/Subtype /Link -/A 3956 0 R -/Type /Annot -/Rect [72 286.002 170.662109 298.502] -/Border [0 0 0] ->> -endobj -3958 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3959 0 obj -<< -/Subtype /Link -/A 3958 0 R -/Type /Annot -/Rect [170.662109 286.002 174.631836 298.502] -/Border [0 0 0] ->> -endobj -3960 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3961 0 obj -<< -/Subtype /Link -/A 3960 0 R -/Type /Annot -/Rect [72 267.432 126 280.002] -/Border [0 0 0] ->> -endobj -3962 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3963 0 obj -<< -/Subtype /Link -/A 3962 0 R -/Type /Annot -/Rect [126 267.502 521.15625 280.002] -/Border [0 0 0] ->> -endobj -3964 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3965 0 obj -<< -/Subtype /Link -/A 3964 0 R -/Type /Annot -/Rect [72 255.002 354.65625 267.502] -/Border [0 0 0] ->> -endobj -3966 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3967 0 obj -<< -/Subtype /Link -/A 3966 0 R -/Type /Annot -/Rect [72 236.432 120 249.002] -/Border [0 0 0] ->> -endobj -3968 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3969 0 obj -<< -/Subtype /Link -/A 3968 0 R -/Type /Annot -/Rect [120 236.502 187.143555 249.002] -/Border [0 0 0] ->> -endobj -3970 0 obj -<< -/S /URI -/URI (https://www.microsoft.com/typography/otspec/featuretags.htm) ->> -endobj -3971 0 obj -<< -/Subtype /Link -/A 3970 0 R -/Type /Annot -/Rect [187.143555 236.502 298.730469 249.002] -/Border [0 0 0] ->> -endobj -3972 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3973 0 obj -<< -/Subtype /Link -/A 3972 0 R -/Type /Annot -/Rect [298.730469 236.502 519.892578 249.002] -/Border [0 0 0] ->> -endobj -3974 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3975 0 obj -<< -/Subtype /Link -/A 3974 0 R -/Type /Annot -/Rect [72 224.002 98.660156 236.502] -/Border [0 0 0] ->> -endobj -3976 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3977 0 obj -<< -/Subtype /Link -/A 3976 0 R -/Type /Annot -/Rect [72 195.502 447.224609 208.002] -/Border [0 0 0] ->> -endobj -3978 0 obj -<< -/S /URI -/URI (vector.html) ->> -endobj -3979 0 obj -<< -/Subtype /Link -/A 3978 0 R -/Type /Annot -/Rect [447.224609 195.502 526.399414 208.002] -/Border [0 0 0] ->> -endobj -3980 0 obj -<< -/S /URI -/URI (vector.html) ->> -endobj -3981 0 obj -<< -/Subtype /Link -/A 3980 0 R -/Type /Annot -/Rect [72 183.002 108.181641 195.502] -/Border [0 0 0] ->> -endobj -3982 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3983 0 obj -<< -/Subtype /Link -/A 3982 0 R -/Type /Annot -/Rect [108.181641 183.002 282.307617 195.502] -/Border [0 0 0] ->> -endobj -3852 0 obj -<< -/Type /Page -/Parent 1 0 R -/MediaBox [0 0 612 792] -/Contents 3850 0 R -/Resources 3851 0 R -/Annots [3855 0 R 3857 0 R 3859 0 R 3861 0 R 3863 0 R 3865 0 R 3867 0 R 3869 0 R 3871 0 R 3873 0 R 3875 0 R 3877 0 R 3879 0 R 3881 0 R 3883 0 R 3885 0 R 3887 0 R 3889 0 R 3891 0 R 3893 0 R 3895 0 R 3897 0 R 3899 0 R 3901 0 R 3903 0 R 3905 0 R 3907 0 R 3909 0 R 3911 0 R 3913 0 R 3915 0 R 3917 0 R 3919 0 R 3921 0 R 3923 0 R 3925 0 R 3927 0 R 3929 0 R 3931 0 R 3933 0 R 3935 0 R 3937 0 R 3939 0 R 3941 0 R 3943 0 R 3945 0 R 3947 0 R 3949 0 R 3951 0 R 3953 0 R 3955 0 R 3957 0 R 3959 0 R 3961 0 R 3963 0 R 3965 0 R 3967 0 R 3969 0 R 3971 0 R 3973 0 R 3975 0 R 3977 0 R 3979 0 R 3981 0 R 3983 0 R] ->> -endobj -3851 0 obj -<< -/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] -/Font << -/F4 16 0 R -/F3 9 0 R -/F6 44 0 R ->> ->> -endobj -3850 0 obj -<< -/Length 1892 -/Filter /FlateDecode ->> -stream -x[Ɏ#7 +J}drKз  GR*J.{؍̸mF"}8u˧OxQzx^?&F̟a6I/_iPϿ~z>A37fE%ug+r+rc*4|gc[v7|9|_ox}r}yYG^W:Z吿s#|^f|[`<:ZQ^*Tܡ1o~Mc.Ȓ' j)J8{CȜGKL=rg%8UKlr'$yK5+\jYu&P')ߵ}!ȕՋf̵,:|226@6x`L_ I=iI0YW! -N^P5@n !g>-;;w W&ೱJe̅v"V3ɮwNlt(˂3yn/NXjA^3ʔ4H'Cn]Ek~OFTëq9qH^}F."nu)X*d7]F6G(x`׮Rܼ ܖyK)i,G/D+U$ovVY p.B\2k} -m3R@V׮(䧔 = -TgZ;(b|a<0k7 T$;]tֺؽZLmD)k3l'd71w_ )n<_\Jk==Fη_#/NZ뇼b`I~YMQ"'EY6J?# ַ )ř^y -;y%QfOkPB cLIt&=tL: `%VuБ~r/q]y~xl& ᤰW/<>"$G9]'\pF ţdfrQ js,D:ܲ(@g\ZcX |h0ϯ;TqV-V4BIiI-0v3O:oKū}|g[e]+i 6zK vZ -!2X$ ҔQ_9^EiF7`r^Βѱ Mf0ŋTz -(mWђϤ-4ih49l`@a-+؜VQ>0}) <+l0uj*)KYLz )y 1eeԎMM,?֖u6HxQkcLS̔"!t~[Q(!T!^x{_pmDe>?* -endstream -endobj -3987 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3988 0 obj -<< -/Subtype /Link -/A 3987 0 R -/Type /Annot -/Rect [72 697.5 536.291992 710] -/Border [0 0 0] ->> -endobj -3989 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3990 0 obj -<< -/Subtype /Link -/A 3989 0 R -/Type /Annot -/Rect [72 685 277.727539 697.5] -/Border [0 0 0] ->> -endobj -3991 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3992 0 obj -<< -/Subtype /Link -/A 3991 0 R -/Type /Annot -/Rect [72 663.687 99 675] -/Border [0 0 0] ->> -endobj -3993 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3994 0 obj -<< -/Subtype /Link -/A 3993 0 R -/Type /Annot -/Rect [99 663.687 104.4 675] -/Border [0 0 0] ->> -endobj -3995 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3996 0 obj -<< -/Subtype /Link -/A 3995 0 R -/Type /Annot -/Rect [104.4 663.687 131.4 675] -/Border [0 0 0] ->> -endobj -3997 0 obj -<< -/S /URI -/URI (false) ->> -endobj -3998 0 obj -<< -/Subtype /Link -/A 3997 0 R -/Type /Annot -/Rect [131.4 663.687 136.8 675] -/Border [0 0 0] ->> -endobj -3999 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4000 0 obj -<< -/Subtype /Link -/A 3999 0 R -/Type /Annot -/Rect [136.8 663.687 142.2 675] -/Border [0 0 0] ->> -endobj -4001 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4002 0 obj -<< -/Subtype /Link -/A 4001 0 R -/Type /Annot -/Rect [142.2 663.687 147.6 675] -/Border [0 0 0] ->> -endobj -4003 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4004 0 obj -<< -/Subtype /Link -/A 4003 0 R -/Type /Annot -/Rect [147.6 663.687 509.4 675] -/Border [0 0 0] ->> -endobj -4005 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4006 0 obj -<< -/Subtype /Link -/A 4005 0 R -/Type /Annot -/Rect [72 652.374 509.4 663.687] -/Border [0 0 0] ->> -endobj -4007 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4008 0 obj -<< -/Subtype /Link -/A 4007 0 R -/Type /Annot -/Rect [72 641.061 531 652.374] -/Border [0 0 0] ->> -endobj -4009 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4010 0 obj -<< -/Subtype /Link -/A 4009 0 R -/Type /Annot -/Rect [72 629.748 531 641.061] -/Border [0 0 0] ->> -endobj -4011 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4012 0 obj -<< -/Subtype /Link -/A 4011 0 R -/Type /Annot -/Rect [72 618.435 536.4 629.748] -/Border [0 0 0] ->> -endobj -4013 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4014 0 obj -<< -/Subtype /Link -/A 4013 0 R -/Type /Annot -/Rect [72 607.122 514.8 618.435] -/Border [0 0 0] ->> -endobj -4015 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4016 0 obj -<< -/Subtype /Link -/A 4015 0 R -/Type /Annot -/Rect [72 595.809 520.2 607.122] -/Border [0 0 0] ->> -endobj -4017 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4018 0 obj -<< -/Subtype /Link -/A 4017 0 R -/Type /Annot -/Rect [72 584.496 531 595.809] -/Border [0 0 0] ->> -endobj -4019 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4020 0 obj -<< -/Subtype /Link -/A 4019 0 R -/Type /Annot -/Rect [72 573.183 504 584.496] -/Border [0 0 0] ->> -endobj -4021 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4022 0 obj -<< -/Subtype /Link -/A 4021 0 R -/Type /Annot -/Rect [72 561.87 514.8 573.183] -/Border [0 0 0] ->> -endobj -4023 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4024 0 obj -<< -/Subtype /Link -/A 4023 0 R -/Type /Annot -/Rect [72 550.557 504 561.87] -/Border [0 0 0] ->> -endobj -4025 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4026 0 obj -<< -/Subtype /Link -/A 4025 0 R -/Type /Annot -/Rect [72 539.244 153 550.557] -/Border [0 0 0] ->> -endobj -4027 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4028 0 obj -<< -/Subtype /Link -/A 4027 0 R -/Type /Annot -/Rect [153 539.244 158.4 550.557] -/Border [0 0 0] ->> -endobj -4029 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4030 0 obj -<< -/Subtype /Link -/A 4029 0 R -/Type /Annot -/Rect [158.4 539.244 174.6 550.557] -/Border [0 0 0] ->> -endobj -4031 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4032 0 obj -<< -/Subtype /Link -/A 4031 0 R -/Type /Annot -/Rect [72 516.618 88.2 527.931] -/Border [0 0 0] ->> -endobj -4033 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4034 0 obj -<< -/Subtype /Link -/A 4033 0 R -/Type /Annot -/Rect [88.2 516.618 93.6 527.931] -/Border [0 0 0] ->> -endobj -4035 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4036 0 obj -<< -/Subtype /Link -/A 4035 0 R -/Type /Annot -/Rect [93.6 516.618 115.2 527.931] -/Border [0 0 0] ->> -endobj -4037 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4038 0 obj -<< -/Subtype /Link -/A 4037 0 R -/Type /Annot -/Rect [115.2 516.618 120.6 527.931] -/Border [0 0 0] ->> -endobj -4039 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4040 0 obj -<< -/Subtype /Link -/A 4039 0 R -/Type /Annot -/Rect [120.6 516.618 147.6 527.931] -/Border [0 0 0] ->> -endobj -4041 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4042 0 obj -<< -/Subtype /Link -/A 4041 0 R -/Type /Annot -/Rect [147.6 516.618 153 527.931] -/Border [0 0 0] ->> -endobj -4043 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4044 0 obj -<< -/Subtype /Link -/A 4043 0 R -/Type /Annot -/Rect [153 516.618 158.4 527.931] -/Border [0 0 0] ->> -endobj -4045 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4046 0 obj -<< -/Subtype /Link -/A 4045 0 R -/Type /Annot -/Rect [158.4 516.618 163.8 527.931] -/Border [0 0 0] ->> -endobj -4047 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4048 0 obj -<< -/Subtype /Link -/A 4047 0 R -/Type /Annot -/Rect [72 505.305 82.8 516.618] -/Border [0 0 0] ->> -endobj -4049 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4050 0 obj -<< -/Subtype /Link -/A 4049 0 R -/Type /Annot -/Rect [82.8 505.305 120.6 516.618] -/Border [0 0 0] ->> -endobj -4051 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4052 0 obj -<< -/Subtype /Link -/A 4051 0 R -/Type /Annot -/Rect [120.6 505.305 126 516.618] -/Border [0 0 0] ->> -endobj -4053 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4054 0 obj -<< -/Subtype /Link -/A 4053 0 R -/Type /Annot -/Rect [126 505.305 131.4 516.618] -/Border [0 0 0] ->> -endobj -4055 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4056 0 obj -<< -/Subtype /Link -/A 4055 0 R -/Type /Annot -/Rect [131.4 505.305 136.8 516.618] -/Border [0 0 0] ->> -endobj -4057 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4058 0 obj -<< -/Subtype /Link -/A 4057 0 R -/Type /Annot -/Rect [136.8 505.305 142.2 516.618] -/Border [0 0 0] ->> -endobj -4059 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4060 0 obj -<< -/Subtype /Link -/A 4059 0 R -/Type /Annot -/Rect [72 493.992 82.8 505.305] -/Border [0 0 0] ->> -endobj -4061 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4062 0 obj -<< -/Subtype /Link -/A 4061 0 R -/Type /Annot -/Rect [82.8 493.992 131.4 505.305] -/Border [0 0 0] ->> -endobj -4063 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4064 0 obj -<< -/Subtype /Link -/A 4063 0 R -/Type /Annot -/Rect [131.4 493.992 136.8 505.305] -/Border [0 0 0] ->> -endobj -4065 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4066 0 obj -<< -/Subtype /Link -/A 4065 0 R -/Type /Annot -/Rect [136.8 493.992 142.2 505.305] -/Border [0 0 0] ->> -endobj -4067 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4068 0 obj -<< -/Subtype /Link -/A 4067 0 R -/Type /Annot -/Rect [142.2 493.992 153 505.305] -/Border [0 0 0] ->> -endobj -4069 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4070 0 obj -<< -/Subtype /Link -/A 4069 0 R -/Type /Annot -/Rect [153 493.992 158.4 505.305] -/Border [0 0 0] ->> -endobj -4071 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4072 0 obj -<< -/Subtype /Link -/A 4071 0 R -/Type /Annot -/Rect [72 482.679 82.8 493.992] -/Border [0 0 0] ->> -endobj -4073 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4074 0 obj -<< -/Subtype /Link -/A 4073 0 R -/Type /Annot -/Rect [82.8 482.679 115.2 493.992] -/Border [0 0 0] ->> -endobj -4075 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4076 0 obj -<< -/Subtype /Link -/A 4075 0 R -/Type /Annot -/Rect [115.2 482.679 120.6 493.992] -/Border [0 0 0] ->> -endobj -4077 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4078 0 obj -<< -/Subtype /Link -/A 4077 0 R -/Type /Annot -/Rect [120.6 482.679 126 493.992] -/Border [0 0 0] ->> -endobj -4079 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4080 0 obj -<< -/Subtype /Link -/A 4079 0 R -/Type /Annot -/Rect [126 482.679 142.2 493.992] -/Border [0 0 0] ->> -endobj -4081 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4082 0 obj -<< -/Subtype /Link -/A 4081 0 R -/Type /Annot -/Rect [142.2 482.679 147.6 493.992] -/Border [0 0 0] ->> -endobj -4083 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4084 0 obj -<< -/Subtype /Link -/A 4083 0 R -/Type /Annot -/Rect [72 471.366 82.8 482.679] -/Border [0 0 0] ->> -endobj -4085 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4086 0 obj -<< -/Subtype /Link -/A 4085 0 R -/Type /Annot -/Rect [82.8 471.366 109.8 482.679] -/Border [0 0 0] ->> -endobj -4087 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4088 0 obj -<< -/Subtype /Link -/A 4087 0 R -/Type /Annot -/Rect [109.8 471.366 115.2 482.679] -/Border [0 0 0] ->> -endobj -4089 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4090 0 obj -<< -/Subtype /Link -/A 4089 0 R -/Type /Annot -/Rect [115.2 471.366 120.6 482.679] -/Border [0 0 0] ->> -endobj -4091 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4092 0 obj -<< -/Subtype /Link -/A 4091 0 R -/Type /Annot -/Rect [120.6 471.366 136.8 482.679] -/Border [0 0 0] ->> -endobj -4093 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4094 0 obj -<< -/Subtype /Link -/A 4093 0 R -/Type /Annot -/Rect [136.8 471.366 142.2 482.679] -/Border [0 0 0] ->> -endobj -4095 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4096 0 obj -<< -/Subtype /Link -/A 4095 0 R -/Type /Annot -/Rect [72 460.053 82.8 471.366] -/Border [0 0 0] ->> -endobj -4097 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4098 0 obj -<< -/Subtype /Link -/A 4097 0 R -/Type /Annot -/Rect [82.8 460.053 109.8 471.366] -/Border [0 0 0] ->> -endobj -4099 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4100 0 obj -<< -/Subtype /Link -/A 4099 0 R -/Type /Annot -/Rect [109.8 460.053 115.2 471.366] -/Border [0 0 0] ->> -endobj -4101 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4102 0 obj -<< -/Subtype /Link -/A 4101 0 R -/Type /Annot -/Rect [115.2 460.053 120.6 471.366] -/Border [0 0 0] ->> -endobj -4103 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4104 0 obj -<< -/Subtype /Link -/A 4103 0 R -/Type /Annot -/Rect [120.6 460.053 169.2 471.366] -/Border [0 0 0] ->> -endobj -4105 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4106 0 obj -<< -/Subtype /Link -/A 4105 0 R -/Type /Annot -/Rect [72 448.74 77.4 460.053] -/Border [0 0 0] ->> -endobj -4107 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4108 0 obj -<< -/Subtype /Link -/A 4107 0 R -/Type /Annot -/Rect [77.4 448.74 82.8 460.053] -/Border [0 0 0] ->> -endobj -4109 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4110 0 obj -<< -/Subtype /Link -/A 4109 0 R -/Type /Annot -/Rect [82.8 448.74 88.2 460.053] -/Border [0 0 0] ->> -endobj -4111 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4112 0 obj -<< -/Subtype /Link -/A 4111 0 R -/Type /Annot -/Rect [72 426.24 202.65918 438.74] -/Border [0 0 0] ->> -endobj -3986 0 obj -<< -/Type /Page -/Parent 1 0 R -/MediaBox [0 0 612 792] -/Contents 3984 0 R -/Resources 3985 0 R -/Annots [3988 0 R 3990 0 R 3992 0 R 3994 0 R 3996 0 R 3998 0 R 4000 0 R 4002 0 R 4004 0 R 4006 0 R 4008 0 R 4010 0 R 4012 0 R 4014 0 R 4016 0 R 4018 0 R 4020 0 R 4022 0 R 4024 0 R 4026 0 R 4028 0 R 4030 0 R 4032 0 R 4034 0 R 4036 0 R 4038 0 R 4040 0 R 4042 0 R 4044 0 R 4046 0 R 4048 0 R 4050 0 R 4052 0 R 4054 0 R 4056 0 R 4058 0 R 4060 0 R 4062 0 R 4064 0 R 4066 0 R 4068 0 R 4070 0 R 4072 0 R 4074 0 R 4076 0 R 4078 0 R 4080 0 R 4082 0 R 4084 0 R 4086 0 R 4088 0 R 4090 0 R 4092 0 R 4094 0 R 4096 0 R 4098 0 R 4100 0 R 4102 0 R 4104 0 R 4106 0 R 4108 0 R 4110 0 R 4112 0 R] ->> -endobj -3985 0 obj -<< -/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] -/Font << -/F3 9 0 R -/F5 29 0 R -/F1 3849 0 R ->> ->> -endobj -3984 0 obj -<< -/Length 2791 -/Filter /FlateDecode ->> -stream -x[Ɏ#WLs'am>Tk|cA3$%eC= L5T% V' WX?ϧo=oj"TOAJ;$1'%Oﷷ$*Le+Bye -SimږyW2WLUצe^Q9.8cQt9pϵ6]t`v0{Vr*ΈJ{z).ñR(" CŅ - ̣ 689˝kj'Yzj&K"oJ+`M` x2=A]#ju}ON',Fdy#=0w;T:B(+cdyQԔln, -c: CEtR,mUdQ @`Ga (9GxqhuAϻc,H'eUٻʏDbMrЭh\'[ 'E8qI^uL}ZTK?9AxjݎPqaS \VrEn%Zea=9ꍖS@Оz,0)I>3ӋGثs8=v\ nR;b2GkʆbtA t"/-5Չ]'UT;o3ӦkKaW?5@EQ@*0J:GYQ1=ʜ&_iY#ʺY -3l03Kz_ƽ5C:ƍ -ځlw%'j#[QemÌ䶸Qh^'|: - -@&odor-eA6⥃m -?Lɀc0g>V6Nu1@ P_ed3Odk=8kƮAn :!376`o(:*g?N"7C^۾EvnEKyϼM!tK$x9IS8|Q5)_*|l= x2?7R!-[âY{S<~Vogr(άs™5^ɟC-D˟Ddsda :g1G0<~7[cp~>7ⅵ pSdg:yP{e_́L8o>}*7xxyJ2f%L#I`-&~Q<69rˉ?{3C\-O?%YHMہ\aQMiVuutwq׮”0B 0M#ڣ"Nd "Hʢr~9w
5hyN5ZAI3_{T2U%-`rr敊 k\S+м#ͻ TK׆=Jj#ڐeSD~Ma!W4ӸzѹyMEm=J)-0sՖb?hegyHs5JF7IMHC[czVYV\RaOupI ,Wk*Lو,Pz3*~"ɩا$V-1o BcJ . CJqΛG^Sj{VOa5RPq%1ښ5B6wo9{Z!Q \;4| j G*f#dnխ۬s,MP SܰM$`4m3>%K 9vW̨>uYWE NdՋW*.J!3*ڧԎ͹DLťlTڡbInn b` WJڴOa]3.9y71@ $v"֨mV{ZYge#-Iᄞ U~wM"p.0E}))17_d2m6hT{$ r_66Sڷw%bk}hE3oб5ޭ5'jSn|eHAe=#4κt[;v3>E81XEV ֶ/?>[_rf~jO)Ћ37E;(AEQ?6EMEMS9TV>%v|Ue{ӲrtĮy? -endstream -endobj -4117 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4118 0 obj -<< -/Subtype /Link -/A 4117 0 R -/Type /Annot -/Rect [72 695.502 220.698 720] -/Border [0 0 0] ->> -endobj -4119 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4120 0 obj -<< -/Subtype /Link -/A 4119 0 R -/Type /Annot -/Rect [72 673.002 538.303711 685.502] -/Border [0 0 0] ->> -endobj -4121 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4122 0 obj -<< -/Subtype /Link -/A 4121 0 R -/Type /Annot -/Rect [72 660.502 363.479492 673.002] -/Border [0 0 0] ->> -endobj -4123 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4124 0 obj -<< -/Subtype /Link -/A 4123 0 R -/Type /Annot -/Rect [363.479492 660.432 531.479492 673.002] -/Border [0 0 0] ->> -endobj -4125 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4126 0 obj -<< -/Subtype /Link -/A 4125 0 R -/Type /Annot -/Rect [531.479492 660.502 536.586914 673.002] -/Border [0 0 0] ->> -endobj -4127 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4128 0 obj -<< -/Subtype /Link -/A 4127 0 R -/Type /Annot -/Rect [72 648.002 93.157227 660.502] -/Border [0 0 0] ->> -endobj -4129 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4130 0 obj -<< -/Subtype /Link -/A 4129 0 R -/Type /Annot -/Rect [93.157227 647.932 267.157227 660.502] -/Border [0 0 0] ->> -endobj -4131 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4132 0 obj -<< -/Subtype /Link -/A 4131 0 R -/Type /Annot -/Rect [267.157227 648.002 539.442383 660.502] -/Border [0 0 0] ->> -endobj -4133 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4134 0 obj -<< -/Subtype /Link -/A 4133 0 R -/Type /Annot -/Rect [72 635.502 422.751953 648.002] -/Border [0 0 0] ->> -endobj -4115 0 obj -<< -/Type /Page -/Parent 1 0 R -/MediaBox [0 0 612 792] -/Contents 4113 0 R -/Resources 4114 0 R -/Annots [4118 0 R 4120 0 R 4122 0 R 4124 0 R 4126 0 R 4128 0 R 4130 0 R 4132 0 R 4134 0 R] ->> -endobj -4114 0 obj -<< -/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] -/Font << -/F4 16 0 R -/F3 9 0 R -/F6 44 0 R ->> ->> -endobj -4113 0 obj -<< -/Length 565 -/Filter /FlateDecode ->> -stream -xUn0 +݈,@C@n-|+zA|Ziž$E )w|j?[5>5:Ƈ污FRtĪI>YEAKtMx+6)(b[}m'A謹o>͗@;(҂P5IDL bo(Ud3vF>[r%NaLe(ʟv9ܹ;027Z1xL1_T*Vmʉ*m c'(;)O -,eT3:uŤ#BUYQA*^bq\a*_3j<&Ji}g*9XWTzRXf\afֹdV5օo5T:k酙1ߪ2]F9nZ}rGI-a7f/ɉhI=Bsr}?,\5:sP12yF1ag2G6 ǭ^2ՄaH!{R.&F܌;GxC\^3Ņ+W]x -+Ҭ -endstream -endobj -4139 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4140 0 obj -<< -/Subtype /Link -/A 4139 0 R -/Type /Annot -/Rect [72 695.502 107.532 720] -/Border [0 0 0] ->> -endobj -4141 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4142 0 obj -<< -/Subtype /Link -/A 4141 0 R -/Type /Annot -/Rect [72 673.002 93.201172 685.502] -/Border [0 0 0] ->> -endobj -4143 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4144 0 obj -<< -/Subtype /Link -/A 4143 0 R -/Type /Annot -/Rect [93.201172 672.932 117.201172 685.502] -/Border [0 0 0] ->> -endobj -4145 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4146 0 obj -<< -/Subtype /Link -/A 4145 0 R -/Type /Annot -/Rect [117.201172 673.002 533.119141 685.502] -/Border [0 0 0] ->> -endobj -4147 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4148 0 obj -<< -/Subtype /Link -/A 4147 0 R -/Type /Annot -/Rect [72 660.502 116.399414 673.002] -/Border [0 0 0] ->> -endobj -4149 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4150 0 obj -<< -/Subtype /Link -/A 4149 0 R -/Type /Annot -/Rect [116.399414 660.432 122.399414 673.002] -/Border [0 0 0] ->> -endobj -4151 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4152 0 obj -<< -/Subtype /Link -/A 4151 0 R -/Type /Annot -/Rect [122.399414 660.502 128.297852 673.002] -/Border [0 0 0] ->> -endobj -4153 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4154 0 obj -<< -/Subtype /Link -/A 4153 0 R -/Type /Annot -/Rect [128.297852 660.432 134.297852 673.002] -/Border [0 0 0] ->> -endobj -4155 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4156 0 obj -<< -/Subtype /Link -/A 4155 0 R -/Type /Annot -/Rect [134.297852 660.502 527.544922 673.002] -/Border [0 0 0] ->> -endobj -4157 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4158 0 obj -<< -/Subtype /Link -/A 4157 0 R -/Type /Annot -/Rect [72 648.002 257.751953 660.502] -/Border [0 0 0] ->> -endobj -4159 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4160 0 obj -<< -/Subtype /Link -/A 4159 0 R -/Type /Annot -/Rect [72 625.432 144 638.002] -/Border [0 0 0] ->> -endobj -4161 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4162 0 obj -<< -/Subtype /Link -/A 4161 0 R -/Type /Annot -/Rect [72 606.862 132 619.432] -/Border [0 0 0] ->> -endobj -4163 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4164 0 obj -<< -/Subtype /Link -/A 4163 0 R -/Type /Annot -/Rect [72 588.292 144 600.862] -/Border [0 0 0] ->> -endobj -4137 0 obj -<< -/Type /Page -/Parent 1 0 R -/MediaBox [0 0 612 792] -/Contents 4135 0 R -/Resources 4136 0 R -/Annots [4140 0 R 4142 0 R 4144 0 R 4146 0 R 4148 0 R 4150 0 R 4152 0 R 4154 0 R 4156 0 R 4158 0 R 4160 0 R 4162 0 R 4164 0 R] ->> -endobj -4136 0 obj -<< -/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] -/Font << -/F4 16 0 R -/F3 9 0 R -/F6 44 0 R ->> ->> -endobj -4135 0 obj -<< -/Length 498 -/Filter /FlateDecode ->> -stream -xTˎ0 +dl-!فC,.^Hh~i"ܤy>F{t|]֏> -endobj -4170 0 obj -<< -/Subtype /Link -/A 4169 0 R -/Type /Annot -/Rect [72 695.502 143.046 720] -/Border [0 0 0] ->> -endobj -4171 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4172 0 obj -<< -/Subtype /Link -/A 4171 0 R -/Type /Annot -/Rect [72 673.002 428.928711 685.502] -/Border [0 0 0] ->> -endobj -4173 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4174 0 obj -<< -/Subtype /Link -/A 4173 0 R -/Type /Annot -/Rect [428.928711 672.932 482.928711 685.502] -/Border [0 0 0] ->> -endobj -4175 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4176 0 obj -<< -/Subtype /Link -/A 4175 0 R -/Type /Annot -/Rect [482.928711 673.002 524.330078 685.502] -/Border [0 0 0] ->> -endobj -4177 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4178 0 obj -<< -/Subtype /Link -/A 4177 0 R -/Type /Annot -/Rect [72 660.502 414.978516 673.002] -/Border [0 0 0] ->> -endobj -4179 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4180 0 obj -<< -/Subtype /Link -/A 4179 0 R -/Type /Annot -/Rect [414.978516 660.432 438.978516 673.002] -/Border [0 0 0] ->> -endobj -4181 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4182 0 obj -<< -/Subtype /Link -/A 4181 0 R -/Type /Annot -/Rect [438.978516 660.502 519.588867 673.002] -/Border [0 0 0] ->> -endobj -4183 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4184 0 obj -<< -/Subtype /Link -/A 4183 0 R -/Type /Annot -/Rect [72 648.002 510.564453 660.502] -/Border [0 0 0] ->> -endobj -4185 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4186 0 obj -<< -/Subtype /Link -/A 4185 0 R -/Type /Annot -/Rect [72 635.502 152.9375 648.002] -/Border [0 0 0] ->> -endobj -4187 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4188 0 obj -<< -/Subtype /Link -/A 4187 0 R -/Type /Annot -/Rect [72 613.002 219.480469 625.502] -/Border [0 0 0] ->> -endobj -4189 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4190 0 obj -<< -/Subtype /Link -/A 4189 0 R -/Type /Annot -/Rect [219.480469 612.932 243.480469 625.502] -/Border [0 0 0] ->> -endobj -4191 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4192 0 obj -<< -/Subtype /Link -/A 4191 0 R -/Type /Annot -/Rect [243.480469 613.002 490.833984 625.502] -/Border [0 0 0] ->> -endobj -4193 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4194 0 obj -<< -/Subtype /Link -/A 4193 0 R -/Type /Annot -/Rect [72 600.362 126 612.932] -/Border [0 0 0] ->> -endobj -4195 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4196 0 obj -<< -/Subtype /Link -/A 4195 0 R -/Type /Annot -/Rect [126 600.432 489.491211 612.932] -/Border [0 0 0] ->> -endobj -4197 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4198 0 obj -<< -/Subtype /Link -/A 4197 0 R -/Type /Annot -/Rect [489.491211 600.362 519.491211 612.932] -/Border [0 0 0] ->> -endobj -4199 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4200 0 obj -<< -/Subtype /Link -/A 4199 0 R -/Type /Annot -/Rect [72 587.932 180.237305 600.432] -/Border [0 0 0] ->> -endobj -4201 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4202 0 obj -<< -/Subtype /Link -/A 4201 0 R -/Type /Annot -/Rect [180.237305 587.862 204.237305 600.432] -/Border [0 0 0] ->> -endobj -4203 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4204 0 obj -<< -/Subtype /Link -/A 4203 0 R -/Type /Annot -/Rect [204.237305 587.932 374.144531 600.432] -/Border [0 0 0] ->> -endobj -4205 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4206 0 obj -<< -/Subtype /Link -/A 4205 0 R -/Type /Annot -/Rect [72 566.619 88.2 577.932] -/Border [0 0 0] ->> -endobj -4207 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4208 0 obj -<< -/Subtype /Link -/A 4207 0 R -/Type /Annot -/Rect [88.2 566.619 93.6 577.932] -/Border [0 0 0] ->> -endobj -4209 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4210 0 obj -<< -/Subtype /Link -/A 4209 0 R -/Type /Annot -/Rect [93.6 566.619 142.2 577.932] -/Border [0 0 0] ->> -endobj -4211 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4212 0 obj -<< -/Subtype /Link -/A 4211 0 R -/Type /Annot -/Rect [142.2 566.619 147.6 577.932] -/Border [0 0 0] ->> -endobj -4213 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4214 0 obj -<< -/Subtype /Link -/A 4213 0 R -/Type /Annot -/Rect [147.6 566.619 185.4 577.932] -/Border [0 0 0] ->> -endobj -4215 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4216 0 obj -<< -/Subtype /Link -/A 4215 0 R -/Type /Annot -/Rect [185.4 566.619 190.8 577.932] -/Border [0 0 0] ->> -endobj -4217 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4218 0 obj -<< -/Subtype /Link -/A 4217 0 R -/Type /Annot -/Rect [72 555.306 88.2 566.619] -/Border [0 0 0] ->> -endobj -4219 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4220 0 obj -<< -/Subtype /Link -/A 4219 0 R -/Type /Annot -/Rect [88.2 555.306 93.6 566.619] -/Border [0 0 0] ->> -endobj -4221 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4222 0 obj -<< -/Subtype /Link -/A 4221 0 R -/Type /Annot -/Rect [93.6 555.306 115.2 566.619] -/Border [0 0 0] ->> -endobj -4223 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4224 0 obj -<< -/Subtype /Link -/A 4223 0 R -/Type /Annot -/Rect [115.2 555.306 120.6 566.619] -/Border [0 0 0] ->> -endobj -4225 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4226 0 obj -<< -/Subtype /Link -/A 4225 0 R -/Type /Annot -/Rect [120.6 555.306 147.6 566.619] -/Border [0 0 0] ->> -endobj -4227 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4228 0 obj -<< -/Subtype /Link -/A 4227 0 R -/Type /Annot -/Rect [147.6 555.306 153 566.619] -/Border [0 0 0] ->> -endobj -4229 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4230 0 obj -<< -/Subtype /Link -/A 4229 0 R -/Type /Annot -/Rect [153 555.306 180 566.619] -/Border [0 0 0] ->> -endobj -4231 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4232 0 obj -<< -/Subtype /Link -/A 4231 0 R -/Type /Annot -/Rect [180 555.306 185.4 566.619] -/Border [0 0 0] ->> -endobj -4233 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4234 0 obj -<< -/Subtype /Link -/A 4233 0 R -/Type /Annot -/Rect [185.4 555.306 190.8 566.619] -/Border [0 0 0] ->> -endobj -4235 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4236 0 obj -<< -/Subtype /Link -/A 4235 0 R -/Type /Annot -/Rect [190.8 555.306 196.2 566.619] -/Border [0 0 0] ->> -endobj -4237 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4238 0 obj -<< -/Subtype /Link -/A 4237 0 R -/Type /Annot -/Rect [196.2 555.306 201.6 566.619] -/Border [0 0 0] ->> -endobj -4239 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4240 0 obj -<< -/Subtype /Link -/A 4239 0 R -/Type /Annot -/Rect [201.6 555.306 217.8 566.619] -/Border [0 0 0] ->> -endobj -4241 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4242 0 obj -<< -/Subtype /Link -/A 4241 0 R -/Type /Annot -/Rect [217.8 555.306 223.2 566.619] -/Border [0 0 0] ->> -endobj -4243 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4244 0 obj -<< -/Subtype /Link -/A 4243 0 R -/Type /Annot -/Rect [223.2 555.306 228.6 566.619] -/Border [0 0 0] ->> -endobj -4245 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4246 0 obj -<< -/Subtype /Link -/A 4245 0 R -/Type /Annot -/Rect [228.6 555.306 234 566.619] -/Border [0 0 0] ->> -endobj -4247 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4248 0 obj -<< -/Subtype /Link -/A 4247 0 R -/Type /Annot -/Rect [234 555.306 239.4 566.619] -/Border [0 0 0] ->> -endobj -4249 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4250 0 obj -<< -/Subtype /Link -/A 4249 0 R -/Type /Annot -/Rect [72 543.993 99 555.306] -/Border [0 0 0] ->> -endobj -4251 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4252 0 obj -<< -/Subtype /Link -/A 4251 0 R -/Type /Annot -/Rect [99 543.993 126 555.306] -/Border [0 0 0] ->> -endobj -4253 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4254 0 obj -<< -/Subtype /Link -/A 4253 0 R -/Type /Annot -/Rect [126 543.993 131.4 555.306] -/Border [0 0 0] ->> -endobj -4255 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4256 0 obj -<< -/Subtype /Link -/A 4255 0 R -/Type /Annot -/Rect [131.4 543.993 136.8 555.306] -/Border [0 0 0] ->> -endobj -4257 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4258 0 obj -<< -/Subtype /Link -/A 4257 0 R -/Type /Annot -/Rect [136.8 543.993 153 555.306] -/Border [0 0 0] ->> -endobj -4259 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4260 0 obj -<< -/Subtype /Link -/A 4259 0 R -/Type /Annot -/Rect [153 543.993 158.4 555.306] -/Border [0 0 0] ->> -endobj -4261 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4262 0 obj -<< -/Subtype /Link -/A 4261 0 R -/Type /Annot -/Rect [72 532.68 99 543.993] -/Border [0 0 0] ->> -endobj -4263 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4264 0 obj -<< -/Subtype /Link -/A 4263 0 R -/Type /Annot -/Rect [99 532.68 147.6 543.993] -/Border [0 0 0] ->> -endobj -4265 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4266 0 obj -<< -/Subtype /Link -/A 4265 0 R -/Type /Annot -/Rect [147.6 532.68 153 543.993] -/Border [0 0 0] ->> -endobj -4267 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4268 0 obj -<< -/Subtype /Link -/A 4267 0 R -/Type /Annot -/Rect [153 532.68 158.4 543.993] -/Border [0 0 0] ->> -endobj -4269 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4270 0 obj -<< -/Subtype /Link -/A 4269 0 R -/Type /Annot -/Rect [158.4 532.68 180 543.993] -/Border [0 0 0] ->> -endobj -4271 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4272 0 obj -<< -/Subtype /Link -/A 4271 0 R -/Type /Annot -/Rect [72 521.367 88.2 532.68] -/Border [0 0 0] ->> -endobj -4273 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4274 0 obj -<< -/Subtype /Link -/A 4273 0 R -/Type /Annot -/Rect [88.2 521.367 93.6 532.68] -/Border [0 0 0] ->> -endobj -4275 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4276 0 obj -<< -/Subtype /Link -/A 4275 0 R -/Type /Annot -/Rect [93.6 521.367 99 532.68] -/Border [0 0 0] ->> -endobj -4277 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4278 0 obj -<< -/Subtype /Link -/A 4277 0 R -/Type /Annot -/Rect [99 521.367 104.4 532.68] -/Border [0 0 0] ->> -endobj -4279 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4280 0 obj -<< -/Subtype /Link -/A 4279 0 R -/Type /Annot -/Rect [104.4 521.367 153 532.68] -/Border [0 0 0] ->> -endobj -4281 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4282 0 obj -<< -/Subtype /Link -/A 4281 0 R -/Type /Annot -/Rect [153 521.367 158.4 532.68] -/Border [0 0 0] ->> -endobj -4283 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4284 0 obj -<< -/Subtype /Link -/A 4283 0 R -/Type /Annot -/Rect [158.4 521.367 185.4 532.68] -/Border [0 0 0] ->> -endobj -4285 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4286 0 obj -<< -/Subtype /Link -/A 4285 0 R -/Type /Annot -/Rect [185.4 521.367 190.8 532.68] -/Border [0 0 0] ->> -endobj -4287 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4288 0 obj -<< -/Subtype /Link -/A 4287 0 R -/Type /Annot -/Rect [72 510.054 88.2 521.367] -/Border [0 0 0] ->> -endobj -4289 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4290 0 obj -<< -/Subtype /Link -/A 4289 0 R -/Type /Annot -/Rect [88.2 510.054 93.6 521.367] -/Border [0 0 0] ->> -endobj -4291 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4292 0 obj -<< -/Subtype /Link -/A 4291 0 R -/Type /Annot -/Rect [93.6 510.054 115.2 521.367] -/Border [0 0 0] ->> -endobj -4293 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4294 0 obj -<< -/Subtype /Link -/A 4293 0 R -/Type /Annot -/Rect [115.2 510.054 120.6 521.367] -/Border [0 0 0] ->> -endobj -4295 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4296 0 obj -<< -/Subtype /Link -/A 4295 0 R -/Type /Annot -/Rect [120.6 510.054 147.6 521.367] -/Border [0 0 0] ->> -endobj -4297 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4298 0 obj -<< -/Subtype /Link -/A 4297 0 R -/Type /Annot -/Rect [147.6 510.054 153 521.367] -/Border [0 0 0] ->> -endobj -4299 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4300 0 obj -<< -/Subtype /Link -/A 4299 0 R -/Type /Annot -/Rect [153 510.054 180 521.367] -/Border [0 0 0] ->> -endobj -4301 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4302 0 obj -<< -/Subtype /Link -/A 4301 0 R -/Type /Annot -/Rect [180 510.054 185.4 521.367] -/Border [0 0 0] ->> -endobj -4303 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4304 0 obj -<< -/Subtype /Link -/A 4303 0 R -/Type /Annot -/Rect [185.4 510.054 201.6 521.367] -/Border [0 0 0] ->> -endobj -4305 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4306 0 obj -<< -/Subtype /Link -/A 4305 0 R -/Type /Annot -/Rect [201.6 510.054 207 521.367] -/Border [0 0 0] ->> -endobj -4307 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4308 0 obj -<< -/Subtype /Link -/A 4307 0 R -/Type /Annot -/Rect [207 510.054 212.4 521.367] -/Border [0 0 0] ->> -endobj -4309 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4310 0 obj -<< -/Subtype /Link -/A 4309 0 R -/Type /Annot -/Rect [212.4 510.054 217.8 521.367] -/Border [0 0 0] ->> -endobj -4311 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4312 0 obj -<< -/Subtype /Link -/A 4311 0 R -/Type /Annot -/Rect [72 487.554 165.745117 500.054] -/Border [0 0 0] ->> -endobj -4167 0 obj -<< -/Type /Page -/Parent 1 0 R -/MediaBox [0 0 612 792] -/Contents 4165 0 R -/Resources 4166 0 R -/Annots [4170 0 R 4172 0 R 4174 0 R 4176 0 R 4178 0 R 4180 0 R 4182 0 R 4184 0 R 4186 0 R 4188 0 R 4190 0 R 4192 0 R 4194 0 R 4196 0 R 4198 0 R 4200 0 R 4202 0 R 4204 0 R 4206 0 R 4208 0 R 4210 0 R 4212 0 R 4214 0 R 4216 0 R 4218 0 R 4220 0 R 4222 0 R 4224 0 R 4226 0 R 4228 0 R 4230 0 R 4232 0 R 4234 0 R 4236 0 R 4238 0 R 4240 0 R 4242 0 R 4244 0 R 4246 0 R 4248 0 R 4250 0 R 4252 0 R 4254 0 R 4256 0 R 4258 0 R 4260 0 R 4262 0 R 4264 0 R 4266 0 R 4268 0 R 4270 0 R 4272 0 R 4274 0 R 4276 0 R 4278 0 R 4280 0 R 4282 0 R 4284 0 R 4286 0 R 4288 0 R 4290 0 R 4292 0 R 4294 0 R 4296 0 R 4298 0 R 4300 0 R 4302 0 R 4304 0 R 4306 0 R 4308 0 R 4310 0 R 4312 0 R] ->> -endobj -4166 0 obj -<< -/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] -/Font << -/F4 16 0 R -/F3 9 0 R -/F6 44 0 R -/F5 29 0 R -/F1 3849 0 R ->> ->> -endobj -4165 0 obj -<< -/Length 2118 -/Filter /FlateDecode ->> -stream -xZˎ6+Ql -܂ t7IEYȏJ#dEw9?o?ivJ;g~H -ZN~2 M)WJH:jGGMQ4~?8Z>"ԀGVK?uSFxO-A)v%}S;)@Ǐr[$Ϟ6 -!my?$dz$AH*Zx3_pBu[7`ctsY6\ -e1t߫+FvPq2VS]i;,8af"2dT 娳L$dUEroUysSA־(B5ɏpW LBYe;{3ce EU~xLHF9+Kb``X~uj먛ĬY)ԅŰK}a285A kΡ .IOԐLYK5url sm!:c{ZM kLx6&ii6ۡ[!5cCbaaP_ՙ"rh`r]ag/yަ̣D@sWfӨ̔HV-ia3b~VGei )3۬e9ʅ~0؋hh6VuAaxgJuUEl $:QBp8%w+F;Lm9@@8ښD̑|c j:I_2S"Ku#^b/5= [xޓmH\6q9p[z -ylW<9k$wrrԀt5pGg@H{czWgUK}qąS͛VZ]^ȱ NS|ol佱tfK~F P:&Zq wHJ ϧHgsjtd-zk_*̈́YGa %,Yt QVfM ܐ[5?0D+F@vFFhL[O{&{WlAysyi3<aCGApgZ(x4 \; J4Iw 7J ULzq8 0CC2<:? b ripZly RI|#ִ݄SN%JD`&*y`PfJ bKcC6ljzzny$"X;1$zcϧ5vZ_P{!+;L3N,9 ہջTLh8g]"K̞5fQEwhiR1S `D~䙍xc$D.r -™$uP,ًg1נkaG&RɒI♚rvc6YGẇȯ`tr},Mcɳ"ѶYS8xL2meg1ݥ&W[n$oj._LU?;i -endstream -endobj -4317 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4318 0 obj -<< -/Subtype /Link -/A 4317 0 R -/Type /Annot -/Rect [72 695.502 113.418 720] -/Border [0 0 0] ->> -endobj -4319 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4320 0 obj -<< -/Subtype /Link -/A 4319 0 R -/Type /Annot -/Rect [72 673.002 498.669922 685.502] -/Border [0 0 0] ->> -endobj -4321 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4322 0 obj -<< -/Subtype /Link -/A 4321 0 R -/Type /Annot -/Rect [72 660.502 513.166992 673.002] -/Border [0 0 0] ->> -endobj -4323 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4324 0 obj -<< -/Subtype /Link -/A 4323 0 R -/Type /Annot -/Rect [72 648.002 526.360352 660.502] -/Border [0 0 0] ->> -endobj -4325 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4326 0 obj -<< -/Subtype /Link -/A 4325 0 R -/Type /Annot -/Rect [72 635.502 234.973633 648.002] -/Border [0 0 0] ->> -endobj -4327 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4328 0 obj -<< -/Subtype /Link -/A 4327 0 R -/Type /Annot -/Rect [234.973633 635.432 258.973633 648.002] -/Border [0 0 0] ->> -endobj -4329 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4330 0 obj -<< -/Subtype /Link -/A 4329 0 R -/Type /Annot -/Rect [258.973633 635.502 452.660156 648.002] -/Border [0 0 0] ->> -endobj -4331 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4332 0 obj -<< -/Subtype /Link -/A 4331 0 R -/Type /Annot -/Rect [72 612.932 126 625.502] -/Border [0 0 0] ->> -endobj -4333 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4334 0 obj -<< -/Subtype /Link -/A 4333 0 R -/Type /Annot -/Rect [72 594.362 156 606.932] -/Border [0 0 0] ->> -endobj -4335 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4336 0 obj -<< -/Subtype /Link -/A 4335 0 R -/Type /Annot -/Rect [72 575.792 174 588.362] -/Border [0 0 0] ->> -endobj -4337 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4338 0 obj -<< -/Subtype /Link -/A 4337 0 R -/Type /Annot -/Rect [72 557.222 198 569.792] -/Border [0 0 0] ->> -endobj -4339 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4340 0 obj -<< -/Subtype /Link -/A 4339 0 R -/Type /Annot -/Rect [72 538.652 138 551.222] -/Border [0 0 0] ->> -endobj -4341 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4342 0 obj -<< -/Subtype /Link -/A 4341 0 R -/Type /Annot -/Rect [72 520.082 168 532.652] -/Border [0 0 0] ->> -endobj -4343 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4344 0 obj -<< -/Subtype /Link -/A 4343 0 R -/Type /Annot -/Rect [72 501.512 186 514.082] -/Border [0 0 0] ->> -endobj -4345 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4346 0 obj -<< -/Subtype /Link -/A 4345 0 R -/Type /Annot -/Rect [72 482.942 210 495.512] -/Border [0 0 0] ->> -endobj -4347 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4348 0 obj -<< -/Subtype /Link -/A 4347 0 R -/Type /Annot -/Rect [72 464.372 120 476.942] -/Border [0 0 0] ->> -endobj -4349 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4350 0 obj -<< -/Subtype /Link -/A 4349 0 R -/Type /Annot -/Rect [72 445.802 150 458.372] -/Border [0 0 0] ->> -endobj -4351 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4352 0 obj -<< -/Subtype /Link -/A 4351 0 R -/Type /Annot -/Rect [72 427.232 144 439.802] -/Border [0 0 0] ->> -endobj -4353 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4354 0 obj -<< -/Subtype /Link -/A 4353 0 R -/Type /Annot -/Rect [72 408.662 156 421.232] -/Border [0 0 0] ->> -endobj -4355 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4356 0 obj -<< -/Subtype /Link -/A 4355 0 R -/Type /Annot -/Rect [72 390.092 180 402.662] -/Border [0 0 0] ->> -endobj -4357 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4358 0 obj -<< -/Subtype /Link -/A 4357 0 R -/Type /Annot -/Rect [72 371.522 156 384.092] -/Border [0 0 0] ->> -endobj -4359 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4360 0 obj -<< -/Subtype /Link -/A 4359 0 R -/Type /Annot -/Rect [72 343.022 519.602539 355.522] -/Border [0 0 0] ->> -endobj -4361 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4362 0 obj -<< -/Subtype /Link -/A 4361 0 R -/Type /Annot -/Rect [72 330.522 182.615234 343.022] -/Border [0 0 0] ->> -endobj -4363 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4364 0 obj -<< -/Subtype /Link -/A 4363 0 R -/Type /Annot -/Rect [182.615234 330.452 206.615234 343.022] -/Border [0 0 0] ->> -endobj -4365 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4366 0 obj -<< -/Subtype /Link -/A 4365 0 R -/Type /Annot -/Rect [206.615234 330.522 272.870117 343.022] -/Border [0 0 0] ->> -endobj -4367 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4368 0 obj -<< -/Subtype /Link -/A 4367 0 R -/Type /Annot -/Rect [272.870117 330.452 296.870117 343.022] -/Border [0 0 0] ->> -endobj -4369 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4370 0 obj -<< -/Subtype /Link -/A 4369 0 R -/Type /Annot -/Rect [296.870117 330.522 489.882813 343.022] -/Border [0 0 0] ->> -endobj -4371 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4372 0 obj -<< -/Subtype /Link -/A 4371 0 R -/Type /Annot -/Rect [489.882813 330.452 513.882813 343.022] -/Border [0 0 0] ->> -endobj -4373 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4374 0 obj -<< -/Subtype /Link -/A 4373 0 R -/Type /Annot -/Rect [513.882813 330.522 523.750977 343.022] -/Border [0 0 0] ->> -endobj -4375 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4376 0 obj -<< -/Subtype /Link -/A 4375 0 R -/Type /Annot -/Rect [72 318.022 191.887695 330.522] -/Border [0 0 0] ->> -endobj -4377 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4378 0 obj -<< -/Subtype /Link -/A 4377 0 R -/Type /Annot -/Rect [191.887695 317.952 227.887695 330.522] -/Border [0 0 0] ->> -endobj -4379 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4380 0 obj -<< -/Subtype /Link -/A 4379 0 R -/Type /Annot -/Rect [227.887695 318.022 264.098633 330.522] -/Border [0 0 0] ->> -endobj -4381 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4382 0 obj -<< -/Subtype /Link -/A 4381 0 R -/Type /Annot -/Rect [72 295.522 328.113281 308.022] -/Border [0 0 0] ->> -endobj -4383 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4384 0 obj -<< -/Subtype /Link -/A 4383 0 R -/Type /Annot -/Rect [328.113281 295.452 352.113281 308.022] -/Border [0 0 0] ->> -endobj -4385 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4386 0 obj -<< -/Subtype /Link -/A 4385 0 R -/Type /Annot -/Rect [352.113281 295.522 533.661133 308.022] -/Border [0 0 0] ->> -endobj -4387 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4388 0 obj -<< -/Subtype /Link -/A 4387 0 R -/Type /Annot -/Rect [72 283.022 249.783203 295.522] -/Border [0 0 0] ->> -endobj -4389 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4390 0 obj -<< -/Subtype /Link -/A 4389 0 R -/Type /Annot -/Rect [249.783203 282.952 273.783203 295.522] -/Border [0 0 0] ->> -endobj -4391 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4392 0 obj -<< -/Subtype /Link -/A 4391 0 R -/Type /Annot -/Rect [273.783203 283.022 539.037109 295.522] -/Border [0 0 0] ->> -endobj -4393 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4394 0 obj -<< -/Subtype /Link -/A 4393 0 R -/Type /Annot -/Rect [72 270.522 80.144531 283.022] -/Border [0 0 0] ->> -endobj -4395 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4396 0 obj -<< -/Subtype /Link -/A 4395 0 R -/Type /Annot -/Rect [80.144531 270.452 116.144531 283.022] -/Border [0 0 0] ->> -endobj -4397 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4398 0 obj -<< -/Subtype /Link -/A 4397 0 R -/Type /Annot -/Rect [116.144531 270.522 397.228516 283.022] -/Border [0 0 0] ->> -endobj -4399 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4400 0 obj -<< -/Subtype /Link -/A 4399 0 R -/Type /Annot -/Rect [397.228516 270.452 421.228516 283.022] -/Border [0 0 0] ->> -endobj -4401 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4402 0 obj -<< -/Subtype /Link -/A 4401 0 R -/Type /Annot -/Rect [421.228516 270.522 444.939453 283.022] -/Border [0 0 0] ->> -endobj -4403 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4404 0 obj -<< -/Subtype /Link -/A 4403 0 R -/Type /Annot -/Rect [444.939453 270.452 480.939453 283.022] -/Border [0 0 0] ->> -endobj -4405 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4406 0 obj -<< -/Subtype /Link -/A 4405 0 R -/Type /Annot -/Rect [480.939453 270.522 514.899414 283.022] -/Border [0 0 0] ->> -endobj -4407 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4408 0 obj -<< -/Subtype /Link -/A 4407 0 R -/Type /Annot -/Rect [72 258.022 521.453125 270.522] -/Border [0 0 0] ->> -endobj -4409 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4410 0 obj -<< -/Subtype /Link -/A 4409 0 R -/Type /Annot -/Rect [72 245.522 273.75293 258.022] -/Border [0 0 0] ->> -endobj -4411 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4412 0 obj -<< -/Subtype /Link -/A 4411 0 R -/Type /Annot -/Rect [72 223.022 374.431641 235.522] -/Border [0 0 0] ->> -endobj -4413 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4414 0 obj -<< -/Subtype /Link -/A 4413 0 R -/Type /Annot -/Rect [72 201.709 180 213.022] -/Border [0 0 0] ->> -endobj -4415 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4416 0 obj -<< -/Subtype /Link -/A 4415 0 R -/Type /Annot -/Rect [72 190.396 88.2 201.709] -/Border [0 0 0] ->> -endobj -4417 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4418 0 obj -<< -/Subtype /Link -/A 4417 0 R -/Type /Annot -/Rect [88.2 190.396 93.6 201.709] -/Border [0 0 0] ->> -endobj -4419 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4420 0 obj -<< -/Subtype /Link -/A 4419 0 R -/Type /Annot -/Rect [93.6 190.396 136.8 201.709] -/Border [0 0 0] ->> -endobj -4421 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4422 0 obj -<< -/Subtype /Link -/A 4421 0 R -/Type /Annot -/Rect [136.8 190.396 142.2 201.709] -/Border [0 0 0] ->> -endobj -4423 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4424 0 obj -<< -/Subtype /Link -/A 4423 0 R -/Type /Annot -/Rect [142.2 190.396 153 201.709] -/Border [0 0 0] ->> -endobj -4425 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4426 0 obj -<< -/Subtype /Link -/A 4425 0 R -/Type /Annot -/Rect [153 190.396 158.4 201.709] -/Border [0 0 0] ->> -endobj -4427 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4428 0 obj -<< -/Subtype /Link -/A 4427 0 R -/Type /Annot -/Rect [158.4 190.396 163.8 201.709] -/Border [0 0 0] ->> -endobj -4429 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4430 0 obj -<< -/Subtype /Link -/A 4429 0 R -/Type /Annot -/Rect [72 167.77 223.2 179.083] -/Border [0 0 0] ->> -endobj -4431 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4432 0 obj -<< -/Subtype /Link -/A 4431 0 R -/Type /Annot -/Rect [72 156.457 88.2 167.77] -/Border [0 0 0] ->> -endobj -4433 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4434 0 obj -<< -/Subtype /Link -/A 4433 0 R -/Type /Annot -/Rect [88.2 156.457 93.6 167.77] -/Border [0 0 0] ->> -endobj -4435 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4436 0 obj -<< -/Subtype /Link -/A 4435 0 R -/Type /Annot -/Rect [93.6 156.457 115.2 167.77] -/Border [0 0 0] ->> -endobj -4437 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4438 0 obj -<< -/Subtype /Link -/A 4437 0 R -/Type /Annot -/Rect [115.2 156.457 120.6 167.77] -/Border [0 0 0] ->> -endobj -4439 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4440 0 obj -<< -/Subtype /Link -/A 4439 0 R -/Type /Annot -/Rect [120.6 156.457 190.8 167.77] -/Border [0 0 0] ->> -endobj -4441 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4442 0 obj -<< -/Subtype /Link -/A 4441 0 R -/Type /Annot -/Rect [190.8 156.457 196.2 167.77] -/Border [0 0 0] ->> -endobj -4443 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4444 0 obj -<< -/Subtype /Link -/A 4443 0 R -/Type /Annot -/Rect [72 145.144 88.2 156.457] -/Border [0 0 0] ->> -endobj -4445 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4446 0 obj -<< -/Subtype /Link -/A 4445 0 R -/Type /Annot -/Rect [88.2 145.144 93.6 156.457] -/Border [0 0 0] ->> -endobj -4447 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4448 0 obj -<< -/Subtype /Link -/A 4447 0 R -/Type /Annot -/Rect [93.6 145.144 115.2 156.457] -/Border [0 0 0] ->> -endobj -4449 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4450 0 obj -<< -/Subtype /Link -/A 4449 0 R -/Type /Annot -/Rect [115.2 145.144 120.6 156.457] -/Border [0 0 0] ->> -endobj -4451 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4452 0 obj -<< -/Subtype /Link -/A 4451 0 R -/Type /Annot -/Rect [120.6 145.144 255.6 156.457] -/Border [0 0 0] ->> -endobj -4453 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4454 0 obj -<< -/Subtype /Link -/A 4453 0 R -/Type /Annot -/Rect [255.6 145.144 261 156.457] -/Border [0 0 0] ->> -endobj -4455 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4456 0 obj -<< -/Subtype /Link -/A 4455 0 R -/Type /Annot -/Rect [72 133.831 88.2 145.144] -/Border [0 0 0] ->> -endobj -4457 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4458 0 obj -<< -/Subtype /Link -/A 4457 0 R -/Type /Annot -/Rect [88.2 133.831 93.6 145.144] -/Border [0 0 0] ->> -endobj -4459 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4460 0 obj -<< -/Subtype /Link -/A 4459 0 R -/Type /Annot -/Rect [93.6 133.831 136.8 145.144] -/Border [0 0 0] ->> -endobj -4461 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4462 0 obj -<< -/Subtype /Link -/A 4461 0 R -/Type /Annot -/Rect [136.8 133.831 142.2 145.144] -/Border [0 0 0] ->> -endobj -4463 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4464 0 obj -<< -/Subtype /Link -/A 4463 0 R -/Type /Annot -/Rect [142.2 133.831 158.4 145.144] -/Border [0 0 0] ->> -endobj -4465 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4466 0 obj -<< -/Subtype /Link -/A 4465 0 R -/Type /Annot -/Rect [158.4 133.831 163.8 145.144] -/Border [0 0 0] ->> -endobj -4467 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4468 0 obj -<< -/Subtype /Link -/A 4467 0 R -/Type /Annot -/Rect [163.8 133.831 169.2 145.144] -/Border [0 0 0] ->> -endobj -4469 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4470 0 obj -<< -/Subtype /Link -/A 4469 0 R -/Type /Annot -/Rect [72 111.205 255.6 122.518] -/Border [0 0 0] ->> -endobj -4471 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4472 0 obj -<< -/Subtype /Link -/A 4471 0 R -/Type /Annot -/Rect [72 99.892 88.2 111.205] -/Border [0 0 0] ->> -endobj -4473 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4474 0 obj -<< -/Subtype /Link -/A 4473 0 R -/Type /Annot -/Rect [88.2 99.892 93.6 111.205] -/Border [0 0 0] ->> -endobj -4475 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4476 0 obj -<< -/Subtype /Link -/A 4475 0 R -/Type /Annot -/Rect [93.6 99.892 115.2 111.205] -/Border [0 0 0] ->> -endobj -4477 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4478 0 obj -<< -/Subtype /Link -/A 4477 0 R -/Type /Annot -/Rect [115.2 99.892 120.6 111.205] -/Border [0 0 0] ->> -endobj -4479 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4480 0 obj -<< -/Subtype /Link -/A 4479 0 R -/Type /Annot -/Rect [120.6 99.892 223.2 111.205] -/Border [0 0 0] ->> -endobj -4481 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4482 0 obj -<< -/Subtype /Link -/A 4481 0 R -/Type /Annot -/Rect [223.2 99.892 228.6 111.205] -/Border [0 0 0] ->> -endobj -4483 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4484 0 obj -<< -/Subtype /Link -/A 4483 0 R -/Type /Annot -/Rect [72 88.579 88.2 99.892] -/Border [0 0 0] ->> -endobj -4485 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4486 0 obj -<< -/Subtype /Link -/A 4485 0 R -/Type /Annot -/Rect [88.2 88.579 93.6 99.892] -/Border [0 0 0] ->> -endobj -4487 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4488 0 obj -<< -/Subtype /Link -/A 4487 0 R -/Type /Annot -/Rect [93.6 88.579 115.2 99.892] -/Border [0 0 0] ->> -endobj -4489 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4490 0 obj -<< -/Subtype /Link -/A 4489 0 R -/Type /Annot -/Rect [115.2 88.579 120.6 99.892] -/Border [0 0 0] ->> -endobj -4491 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4492 0 obj -<< -/Subtype /Link -/A 4491 0 R -/Type /Annot -/Rect [120.6 88.579 223.2 99.892] -/Border [0 0 0] ->> -endobj -4493 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4494 0 obj -<< -/Subtype /Link -/A 4493 0 R -/Type /Annot -/Rect [223.2 88.579 228.6 99.892] -/Border [0 0 0] ->> -endobj -4495 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4496 0 obj -<< -/Subtype /Link -/A 4495 0 R -/Type /Annot -/Rect [72 77.266 88.2 88.579] -/Border [0 0 0] ->> -endobj -4497 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4498 0 obj -<< -/Subtype /Link -/A 4497 0 R -/Type /Annot -/Rect [88.2 77.266 93.6 88.579] -/Border [0 0 0] ->> -endobj -4499 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4500 0 obj -<< -/Subtype /Link -/A 4499 0 R -/Type /Annot -/Rect [93.6 77.266 136.8 88.579] -/Border [0 0 0] ->> -endobj -4501 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4502 0 obj -<< -/Subtype /Link -/A 4501 0 R -/Type /Annot -/Rect [136.8 77.266 142.2 88.579] -/Border [0 0 0] ->> -endobj -4503 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4504 0 obj -<< -/Subtype /Link -/A 4503 0 R -/Type /Annot -/Rect [142.2 77.266 158.4 88.579] -/Border [0 0 0] ->> -endobj -4505 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4506 0 obj -<< -/Subtype /Link -/A 4505 0 R -/Type /Annot -/Rect [158.4 77.266 163.8 88.579] -/Border [0 0 0] ->> -endobj -4507 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4508 0 obj -<< -/Subtype /Link -/A 4507 0 R -/Type /Annot -/Rect [163.8 77.266 169.2 88.579] -/Border [0 0 0] ->> -endobj -4315 0 obj -<< -/Type /Page -/Parent 1 0 R -/MediaBox [0 0 612 792] -/Contents 4313 0 R -/Resources 4314 0 R -/Annots [4318 0 R 4320 0 R 4322 0 R 4324 0 R 4326 0 R 4328 0 R 4330 0 R 4332 0 R 4334 0 R 4336 0 R 4338 0 R 4340 0 R 4342 0 R 4344 0 R 4346 0 R 4348 0 R 4350 0 R 4352 0 R 4354 0 R 4356 0 R 4358 0 R 4360 0 R 4362 0 R 4364 0 R 4366 0 R 4368 0 R 4370 0 R 4372 0 R 4374 0 R 4376 0 R 4378 0 R 4380 0 R 4382 0 R 4384 0 R 4386 0 R 4388 0 R 4390 0 R 4392 0 R 4394 0 R 4396 0 R 4398 0 R 4400 0 R 4402 0 R 4404 0 R 4406 0 R 4408 0 R 4410 0 R 4412 0 R 4414 0 R 4416 0 R 4418 0 R 4420 0 R 4422 0 R 4424 0 R 4426 0 R 4428 0 R 4430 0 R 4432 0 R 4434 0 R 4436 0 R 4438 0 R 4440 0 R 4442 0 R 4444 0 R 4446 0 R 4448 0 R 4450 0 R 4452 0 R 4454 0 R 4456 0 R 4458 0 R 4460 0 R 4462 0 R 4464 0 R 4466 0 R 4468 0 R 4470 0 R 4472 0 R 4474 0 R 4476 0 R 4478 0 R 4480 0 R 4482 0 R 4484 0 R 4486 0 R 4488 0 R 4490 0 R 4492 0 R 4494 0 R 4496 0 R 4498 0 R 4500 0 R 4502 0 R 4504 0 R 4506 0 R 4508 0 R] ->> -endobj -4314 0 obj -<< -/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] -/Font << -/F4 16 0 R -/F3 9 0 R -/F6 44 0 R -/F5 29 0 R ->> ->> -endobj -4313 0 obj -<< -/Length 2096 -/Filter /FlateDecode ->> -stream -x[͎6 SJ?â?@o-Vd(WI[v8Q"3l'I{U'ӿT#to?ߞd9?Oگ/8:JxK'өн~"ϝ]>RX?w嗧_~}\P{SKRTkcH7xnW{uexdyEZT6Hƹlrb'؝ߛ/)&+uŊ8-ҊH?Az -"X#h #<Fˊ5<􂼚IsHDy黉hzddi9h`1 -~3zOuZlm{+(SG%p~5;~NM2+oB.8xOc5ځ빳"ب}a+Sgb/_gEU1qZ$ďNUL".ڈӺXBjhg-\6R/TMv -zu>!1e;ҺTRbբ?'ծpK8SqclL# lB7h<2Z ,QUheq54QDhlЁؐG<&"whr_ߓFyvYQ{8>Fs煒\QҮtEsgUVNØ~ŽR#HlFwr- 6d=NfZ%D`k1>/\rpEy-hUʊi\)eV ɡTuN)q+EvnU5 U󫕼:UK+Ģ0SsPP[ uߤ.*#ڷ2@t6iPأդz``2?|rA̮)2RWq}νO а0DU0! (}[HJRWVVIsgn?D.d]5B3R'lq5ک!e/Ym ,ZqW}o7 cYCTWV#+]5 JUq1PK]/u~cS^E6uWuoLf -el޽'/Ym5QHH'2݁2X_E0rb}+VgXfo\|lA50V+H%Z#R.-&rtR 5\PD45]3q)Ҝm > 4)9MܚH6FD+{ʤ(~<#iޑc:.B&GU_6jrP|=[AeY9/=ԸD[!Gg %N G;4Z;T$a#;bP1'J__SK Y6̇a[Fٖ>ZKH]C7JHw>87yr zgc³!Qӻyц 'չR=u(3lHH 2)CYaG]Q*rؗ񅰷 }&S !|g89Cu]>zCuɯ>~`K?+'X9enW]./KZd{sמ\QI:Gu6b-+*0NZ]wz|JZ{\П%݊JH}޾(b696,8oN/ |cTϣHp1U3“mf @[:UY*ScQ - -endstream -endobj -4512 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4513 0 obj -<< -/Subtype /Link -/A 4512 0 R -/Type /Annot -/Rect [72 697.374 320.4 708.687] -/Border [0 0 0] ->> -endobj -4514 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4515 0 obj -<< -/Subtype /Link -/A 4514 0 R -/Type /Annot -/Rect [72 686.061 88.2 697.374] -/Border [0 0 0] ->> -endobj -4516 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4517 0 obj -<< -/Subtype /Link -/A 4516 0 R -/Type /Annot -/Rect [88.2 686.061 93.6 697.374] -/Border [0 0 0] ->> -endobj -4518 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4519 0 obj -<< -/Subtype /Link -/A 4518 0 R -/Type /Annot -/Rect [93.6 686.061 115.2 697.374] -/Border [0 0 0] ->> -endobj -4520 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4521 0 obj -<< -/Subtype /Link -/A 4520 0 R -/Type /Annot -/Rect [115.2 686.061 120.6 697.374] -/Border [0 0 0] ->> -endobj -4522 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4523 0 obj -<< -/Subtype /Link -/A 4522 0 R -/Type /Annot -/Rect [120.6 686.061 239.4 697.374] -/Border [0 0 0] ->> -endobj -4524 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4525 0 obj -<< -/Subtype /Link -/A 4524 0 R -/Type /Annot -/Rect [239.4 686.061 244.8 697.374] -/Border [0 0 0] ->> -endobj -4526 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4527 0 obj -<< -/Subtype /Link -/A 4526 0 R -/Type /Annot -/Rect [244.8 686.061 250.2 697.374] -/Border [0 0 0] ->> -endobj -4528 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4529 0 obj -<< -/Subtype /Link -/A 4528 0 R -/Type /Annot -/Rect [250.2 686.061 342 697.374] -/Border [0 0 0] ->> -endobj -4530 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4531 0 obj -<< -/Subtype /Link -/A 4530 0 R -/Type /Annot -/Rect [342 686.061 347.4 697.374] -/Border [0 0 0] ->> -endobj -4532 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4533 0 obj -<< -/Subtype /Link -/A 4532 0 R -/Type /Annot -/Rect [72 674.748 88.2 686.061] -/Border [0 0 0] ->> -endobj -4534 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4535 0 obj -<< -/Subtype /Link -/A 4534 0 R -/Type /Annot -/Rect [88.2 674.748 93.6 686.061] -/Border [0 0 0] ->> -endobj -4536 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4537 0 obj -<< -/Subtype /Link -/A 4536 0 R -/Type /Annot -/Rect [93.6 674.748 115.2 686.061] -/Border [0 0 0] ->> -endobj -4538 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4539 0 obj -<< -/Subtype /Link -/A 4538 0 R -/Type /Annot -/Rect [115.2 674.748 120.6 686.061] -/Border [0 0 0] ->> -endobj -4540 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4541 0 obj -<< -/Subtype /Link -/A 4540 0 R -/Type /Annot -/Rect [120.6 674.748 320.4 686.061] -/Border [0 0 0] ->> -endobj -4542 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4543 0 obj -<< -/Subtype /Link -/A 4542 0 R -/Type /Annot -/Rect [320.4 674.748 325.8 686.061] -/Border [0 0 0] ->> -endobj -4544 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4545 0 obj -<< -/Subtype /Link -/A 4544 0 R -/Type /Annot -/Rect [325.8 674.748 331.2 686.061] -/Border [0 0 0] ->> -endobj -4546 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4547 0 obj -<< -/Subtype /Link -/A 4546 0 R -/Type /Annot -/Rect [72 652.248 282.390625 664.748] -/Border [0 0 0] ->> -endobj -4551 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4552 0 obj -<< -/Subtype /Link -/A 4551 0 R -/Type /Annot -/Rect [72 518.250855 524.709961 530.750855] -/Border [0 0 0] ->> -endobj -4553 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4554 0 obj -<< -/Subtype /Link -/A 4553 0 R -/Type /Annot -/Rect [72 505.750855 517.629883 518.250855] -/Border [0 0 0] ->> -endobj -4555 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4556 0 obj -<< -/Subtype /Link -/A 4555 0 R -/Type /Annot -/Rect [72 484.437855 169.2 495.750855] -/Border [0 0 0] ->> -endobj -4557 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4558 0 obj -<< -/Subtype /Link -/A 4557 0 R -/Type /Annot -/Rect [72 473.124855 88.2 484.437855] -/Border [0 0 0] ->> -endobj -4559 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4560 0 obj -<< -/Subtype /Link -/A 4559 0 R -/Type /Annot -/Rect [88.2 473.124855 93.6 484.437855] -/Border [0 0 0] ->> -endobj -4561 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4562 0 obj -<< -/Subtype /Link -/A 4561 0 R -/Type /Annot -/Rect [93.6 473.124855 158.4 484.437855] -/Border [0 0 0] ->> -endobj -4563 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4564 0 obj -<< -/Subtype /Link -/A 4563 0 R -/Type /Annot -/Rect [158.4 473.124855 163.8 484.437855] -/Border [0 0 0] ->> -endobj -4565 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4566 0 obj -<< -/Subtype /Link -/A 4565 0 R -/Type /Annot -/Rect [163.8 473.124855 239.4 484.437855] -/Border [0 0 0] ->> -endobj -4567 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4568 0 obj -<< -/Subtype /Link -/A 4567 0 R -/Type /Annot -/Rect [239.4 473.124855 244.8 484.437855] -/Border [0 0 0] ->> -endobj -4569 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4570 0 obj -<< -/Subtype /Link -/A 4569 0 R -/Type /Annot -/Rect [244.8 473.124855 250.2 484.437855] -/Border [0 0 0] ->> -endobj -4571 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4572 0 obj -<< -/Subtype /Link -/A 4571 0 R -/Type /Annot -/Rect [250.2 473.124855 369 484.437855] -/Border [0 0 0] ->> -endobj -4573 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4574 0 obj -<< -/Subtype /Link -/A 4573 0 R -/Type /Annot -/Rect [369 473.124855 374.4 484.437855] -/Border [0 0 0] ->> -endobj -4575 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4576 0 obj -<< -/Subtype /Link -/A 4575 0 R -/Type /Annot -/Rect [374.4 473.124855 379.8 484.437855] -/Border [0 0 0] ->> -endobj -4577 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4578 0 obj -<< -/Subtype /Link -/A 4577 0 R -/Type /Annot -/Rect [379.8 473.124855 471.6 484.437855] -/Border [0 0 0] ->> -endobj -4579 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4580 0 obj -<< -/Subtype /Link -/A 4579 0 R -/Type /Annot -/Rect [471.6 473.124855 477 484.437855] -/Border [0 0 0] ->> -endobj -4581 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4582 0 obj -<< -/Subtype /Link -/A 4581 0 R -/Type /Annot -/Rect [477 473.124855 482.4 484.437855] -/Border [0 0 0] ->> -endobj -4583 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4584 0 obj -<< -/Subtype /Link -/A 4583 0 R -/Type /Annot -/Rect [72 450.498855 185.4 461.811855] -/Border [0 0 0] ->> -endobj -4585 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4586 0 obj -<< -/Subtype /Link -/A 4585 0 R -/Type /Annot -/Rect [72 439.185855 88.2 450.498855] -/Border [0 0 0] ->> -endobj -4587 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4588 0 obj -<< -/Subtype /Link -/A 4587 0 R -/Type /Annot -/Rect [88.2 439.185855 93.6 450.498855] -/Border [0 0 0] ->> -endobj -4589 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4590 0 obj -<< -/Subtype /Link -/A 4589 0 R -/Type /Annot -/Rect [93.6 439.185855 115.2 450.498855] -/Border [0 0 0] ->> -endobj -4591 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4592 0 obj -<< -/Subtype /Link -/A 4591 0 R -/Type /Annot -/Rect [115.2 439.185855 120.6 450.498855] -/Border [0 0 0] ->> -endobj -4593 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4594 0 obj -<< -/Subtype /Link -/A 4593 0 R -/Type /Annot -/Rect [120.6 439.185855 196.2 450.498855] -/Border [0 0 0] ->> -endobj -4595 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4596 0 obj -<< -/Subtype /Link -/A 4595 0 R -/Type /Annot -/Rect [196.2 439.185855 201.6 450.498855] -/Border [0 0 0] ->> -endobj -4597 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4598 0 obj -<< -/Subtype /Link -/A 4597 0 R -/Type /Annot -/Rect [72 427.872855 88.2 439.185855] -/Border [0 0 0] ->> -endobj -4599 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4600 0 obj -<< -/Subtype /Link -/A 4599 0 R -/Type /Annot -/Rect [88.2 427.872855 93.6 439.185855] -/Border [0 0 0] ->> -endobj -4601 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4602 0 obj -<< -/Subtype /Link -/A 4601 0 R -/Type /Annot -/Rect [93.6 427.872855 115.2 439.185855] -/Border [0 0 0] ->> -endobj -4603 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4604 0 obj -<< -/Subtype /Link -/A 4603 0 R -/Type /Annot -/Rect [115.2 427.872855 120.6 439.185855] -/Border [0 0 0] ->> -endobj -4605 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4606 0 obj -<< -/Subtype /Link -/A 4605 0 R -/Type /Annot -/Rect [120.6 427.872855 228.6 439.185855] -/Border [0 0 0] ->> -endobj -4607 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4608 0 obj -<< -/Subtype /Link -/A 4607 0 R -/Type /Annot -/Rect [228.6 427.872855 234 439.185855] -/Border [0 0 0] ->> -endobj -4609 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4610 0 obj -<< -/Subtype /Link -/A 4609 0 R -/Type /Annot -/Rect [234 427.872855 239.4 439.185855] -/Border [0 0 0] ->> -endobj -4611 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4612 0 obj -<< -/Subtype /Link -/A 4611 0 R -/Type /Annot -/Rect [72 405.372855 462.756836 417.872855] -/Border [0 0 0] ->> -endobj -4511 0 obj -<< -/Type /Page -/Parent 1 0 R -/MediaBox [0 0 612 792] -/Contents 4509 0 R -/Resources 4510 0 R -/Annots [4513 0 R 4515 0 R 4517 0 R 4519 0 R 4521 0 R 4523 0 R 4525 0 R 4527 0 R 4529 0 R 4531 0 R 4533 0 R 4535 0 R 4537 0 R 4539 0 R 4541 0 R 4543 0 R 4545 0 R 4547 0 R 4552 0 R 4554 0 R 4556 0 R 4558 0 R 4560 0 R 4562 0 R 4564 0 R 4566 0 R 4568 0 R 4570 0 R 4572 0 R 4574 0 R 4576 0 R 4578 0 R 4580 0 R 4582 0 R 4584 0 R 4586 0 R 4588 0 R 4590 0 R 4592 0 R 4594 0 R 4596 0 R 4598 0 R 4600 0 R 4602 0 R 4604 0 R 4606 0 R 4608 0 R 4610 0 R 4612 0 R] ->> -endobj -4510 0 obj -<< -/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] -/Font << -/F5 29 0 R -/F3 9 0 R -/F7 4548 0 R -/F8 4549 0 R -/F9 4550 0 R ->> ->> -endobj -4509 0 obj -<< -/Length 1332 -/Filter /FlateDecode ->> -stream -xYK&ϯBP*)Dsr퇴DVOm';ktnx} -4|?|8kP izB@0y_EC)L??p5g!qU00<3s)j'. )t%Fh^JS -ITriϿ>ۛrYO9KBA9WB N=na pЃ ƣEڇģ`k=a_eD#bqC|M4.`;̂`TLpA-f̊M -˵B؊hkøkUXWȮG{Z2R`U(LvVvb+H^{-Ǜ -|Gqjw Q fN6ȸIS: -]fKa Kt))M ؗ8$" */c]s͖e*&s3Y.ӫ8 ĂrqCLQyMA~H#1rt$=ҙRnظE:Q. ak #1>S -BO>1Ҍ%Nݴ̴nā$n(֛8*:ws'P(psjuCgYG-~OuD;o:*ǯ=lke5ZQ^qAwXT_xwS572GbNjvݒ|~9EMN^t+1z2 Y^-M| Ӛc^Ro5l=YdJr̮拾RYΓdZQƝ -?9b -endstream -endobj -4617 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4618 0 obj -<< -/Subtype /Link -/A 4617 0 R -/Type /Annot -/Rect [72 685.975 256.1 720] -/Border [0 0 0] ->> -endobj -4619 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4620 0 obj -<< -/Subtype /Link -/A 4619 0 R -/Type /Annot -/Rect [72 658.475 531.40918 670.975] -/Border [0 0 0] ->> -endobj -4621 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4622 0 obj -<< -/Subtype /Link -/A 4621 0 R -/Type /Annot -/Rect [72 645.975 251.291992 658.475] -/Border [0 0 0] ->> -endobj -4623 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4624 0 obj -<< -/Subtype /Link -/A 4623 0 R -/Type /Annot -/Rect [251.291992 645.905 281.291992 658.475] -/Border [0 0 0] ->> -endobj -4625 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4626 0 obj -<< -/Subtype /Link -/A 4625 0 R -/Type /Annot -/Rect [281.291992 645.975 514.739258 658.475] -/Border [0 0 0] ->> -endobj -4627 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4628 0 obj -<< -/Subtype /Link -/A 4627 0 R -/Type /Annot -/Rect [72 633.475 508.782227 645.975] -/Border [0 0 0] ->> -endobj -4629 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4630 0 obj -<< -/Subtype /Link -/A 4629 0 R -/Type /Annot -/Rect [72 620.975 539.641602 633.475] -/Border [0 0 0] ->> -endobj -4631 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4632 0 obj -<< -/Subtype /Link -/A 4631 0 R -/Type /Annot -/Rect [72 608.475 520.666992 620.975] -/Border [0 0 0] ->> -endobj -4633 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4634 0 obj -<< -/Subtype /Link -/A 4633 0 R -/Type /Annot -/Rect [72 595.975 163.176758 608.475] -/Border [0 0 0] ->> -endobj -4635 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4636 0 obj -<< -/Subtype /Link -/A 4635 0 R -/Type /Annot -/Rect [72 573.475 112.756836 585.975] -/Border [0 0 0] ->> -endobj -4637 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4638 0 obj -<< -/Subtype /Link -/A 4637 0 R -/Type /Annot -/Rect [112.756836 573.405 142.756836 585.975] -/Border [0 0 0] ->> -endobj -4639 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4640 0 obj -<< -/Subtype /Link -/A 4639 0 R -/Type /Annot -/Rect [142.756836 573.475 158.381836 585.975] -/Border [0 0 0] ->> -endobj -4641 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4642 0 obj -<< -/Subtype /Link -/A 4641 0 R -/Type /Annot -/Rect [158.381836 573.405 194.381836 585.975] -/Border [0 0 0] ->> -endobj -4643 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4644 0 obj -<< -/Subtype /Link -/A 4643 0 R -/Type /Annot -/Rect [194.381836 573.475 395.236328 585.975] -/Border [0 0 0] ->> -endobj -4645 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4646 0 obj -<< -/Subtype /Link -/A 4645 0 R -/Type /Annot -/Rect [72 554.905 102 567.475] -/Border [0 0 0] ->> -endobj -4647 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4648 0 obj -<< -/Subtype /Link -/A 4647 0 R -/Type /Annot -/Rect [102 554.975 190.041992 567.475] -/Border [0 0 0] ->> -endobj -4649 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4650 0 obj -<< -/Subtype /Link -/A 4649 0 R -/Type /Annot -/Rect [190.041992 554.905 226.041992 567.475] -/Border [0 0 0] ->> -endobj -4651 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4652 0 obj -<< -/Subtype /Link -/A 4651 0 R -/Type /Annot -/Rect [226.041992 554.975 495.265625 567.475] -/Border [0 0 0] ->> -endobj -4653 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4654 0 obj -<< -/Subtype /Link -/A 4653 0 R -/Type /Annot -/Rect [495.265625 554.905 525.265625 567.475] -/Border [0 0 0] ->> -endobj -4655 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4656 0 obj -<< -/Subtype /Link -/A 4655 0 R -/Type /Annot -/Rect [72 536.335 108 548.905] -/Border [0 0 0] ->> -endobj -4657 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4658 0 obj -<< -/Subtype /Link -/A 4657 0 R -/Type /Annot -/Rect [108 536.405 196.041992 548.905] -/Border [0 0 0] ->> -endobj -4659 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4660 0 obj -<< -/Subtype /Link -/A 4659 0 R -/Type /Annot -/Rect [196.041992 536.335 226.041992 548.905] -/Border [0 0 0] ->> -endobj -4661 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4662 0 obj -<< -/Subtype /Link -/A 4661 0 R -/Type /Annot -/Rect [226.041992 536.405 495.265625 548.905] -/Border [0 0 0] ->> -endobj -4663 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4664 0 obj -<< -/Subtype /Link -/A 4663 0 R -/Type /Annot -/Rect [495.265625 536.335 531.265625 548.905] -/Border [0 0 0] ->> -endobj -4665 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4666 0 obj -<< -/Subtype /Link -/A 4665 0 R -/Type /Annot -/Rect [72 517.835 98.557617 530.335] -/Border [0 0 0] ->> -endobj -4667 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4668 0 obj -<< -/Subtype /Link -/A 4667 0 R -/Type /Annot -/Rect [98.557617 517.765 128.557617 530.335] -/Border [0 0 0] ->> -endobj -4669 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4670 0 obj -<< -/Subtype /Link -/A 4669 0 R -/Type /Annot -/Rect [128.557617 517.835 152.268555 530.335] -/Border [0 0 0] ->> -endobj -4671 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4672 0 obj -<< -/Subtype /Link -/A 4671 0 R -/Type /Annot -/Rect [152.268555 517.765 188.268555 530.335] -/Border [0 0 0] ->> -endobj -4673 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4674 0 obj -<< -/Subtype /Link -/A 4673 0 R -/Type /Annot -/Rect [188.268555 517.835 477.160156 530.335] -/Border [0 0 0] ->> -endobj -4675 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4676 0 obj -<< -/Subtype /Link -/A 4675 0 R -/Type /Annot -/Rect [72 499.265 102 511.835] -/Border [0 0 0] ->> -endobj -4677 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4678 0 obj -<< -/Subtype /Link -/A 4677 0 R -/Type /Annot -/Rect [102 499.335 481.487305 511.835] -/Border [0 0 0] ->> -endobj -4679 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4680 0 obj -<< -/Subtype /Link -/A 4679 0 R -/Type /Annot -/Rect [72 480.765 90 493.335] -/Border [0 0 0] ->> -endobj -4681 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4682 0 obj -<< -/Subtype /Link -/A 4681 0 R -/Type /Annot -/Rect [90 480.835 532.167969 493.335] -/Border [0 0 0] ->> -endobj -4683 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4684 0 obj -<< -/Subtype /Link -/A 4683 0 R -/Type /Annot -/Rect [72 462.265 102 474.835] -/Border [0 0 0] ->> -endobj -4685 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4686 0 obj -<< -/Subtype /Link -/A 4685 0 R -/Type /Annot -/Rect [102 462.335 509.568359 474.835] -/Border [0 0 0] ->> -endobj -4687 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4688 0 obj -<< -/Subtype /Link -/A 4687 0 R -/Type /Annot -/Rect [72 449.835 267.834961 462.335] -/Border [0 0 0] ->> -endobj -4689 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4690 0 obj -<< -/Subtype /Link -/A 4689 0 R -/Type /Annot -/Rect [72 421.335 112.219727 433.835] -/Border [0 0 0] ->> -endobj -4691 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4692 0 obj -<< -/Subtype /Link -/A 4691 0 R -/Type /Annot -/Rect [112.219727 421.265 130.219727 433.835] -/Border [0 0 0] ->> -endobj -4693 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4694 0 obj -<< -/Subtype /Link -/A 4693 0 R -/Type /Annot -/Rect [130.219727 421.335 145.844727 433.835] -/Border [0 0 0] ->> -endobj -4695 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4696 0 obj -<< -/Subtype /Link -/A 4695 0 R -/Type /Annot -/Rect [145.844727 421.265 175.844727 433.835] -/Border [0 0 0] ->> -endobj -4697 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4698 0 obj -<< -/Subtype /Link -/A 4697 0 R -/Type /Annot -/Rect [175.844727 421.335 469.248047 433.835] -/Border [0 0 0] ->> -endobj -4699 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4700 0 obj -<< -/Subtype /Link -/A 4699 0 R -/Type /Annot -/Rect [72 398.765 102 411.335] -/Border [0 0 0] ->> -endobj -4701 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4702 0 obj -<< -/Subtype /Link -/A 4701 0 R -/Type /Annot -/Rect [102 398.835 375.525391 411.335] -/Border [0 0 0] ->> -endobj -4703 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4704 0 obj -<< -/Subtype /Link -/A 4703 0 R -/Type /Annot -/Rect [375.525391 398.765 411.525391 411.335] -/Border [0 0 0] ->> -endobj -4705 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4706 0 obj -<< -/Subtype /Link -/A 4705 0 R -/Type /Annot -/Rect [411.525391 398.835 417.423828 411.335] -/Border [0 0 0] ->> -endobj -4707 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4708 0 obj -<< -/Subtype /Link -/A 4707 0 R -/Type /Annot -/Rect [417.423828 398.765 465.423828 411.335] -/Border [0 0 0] ->> -endobj -4709 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4710 0 obj -<< -/Subtype /Link -/A 4709 0 R -/Type /Annot -/Rect [465.423828 398.835 489.134766 411.335] -/Border [0 0 0] ->> -endobj -4711 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4712 0 obj -<< -/Subtype /Link -/A 4711 0 R -/Type /Annot -/Rect [489.134766 398.765 531.134766 411.335] -/Border [0 0 0] ->> -endobj -4713 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4714 0 obj -<< -/Subtype /Link -/A 4713 0 R -/Type /Annot -/Rect [531.134766 398.835 533.688477 411.335] -/Border [0 0 0] ->> -endobj -4715 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4716 0 obj -<< -/Subtype /Link -/A 4715 0 R -/Type /Annot -/Rect [72 380.265 108 392.835] -/Border [0 0 0] ->> -endobj -4717 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4718 0 obj -<< -/Subtype /Link -/A 4717 0 R -/Type /Annot -/Rect [108 380.335 367.0625 392.835] -/Border [0 0 0] ->> -endobj -4719 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4720 0 obj -<< -/Subtype /Link -/A 4719 0 R -/Type /Annot -/Rect [367.0625 380.265 397.0625 392.835] -/Border [0 0 0] ->> -endobj -4721 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4722 0 obj -<< -/Subtype /Link -/A 4721 0 R -/Type /Annot -/Rect [397.0625 380.335 402.960938 392.835] -/Border [0 0 0] ->> -endobj -4723 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4724 0 obj -<< -/Subtype /Link -/A 4723 0 R -/Type /Annot -/Rect [402.960938 380.265 450.960938 392.835] -/Border [0 0 0] ->> -endobj -4725 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4726 0 obj -<< -/Subtype /Link -/A 4725 0 R -/Type /Annot -/Rect [450.960938 380.335 474.671875 392.835] -/Border [0 0 0] ->> -endobj -4727 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4728 0 obj -<< -/Subtype /Link -/A 4727 0 R -/Type /Annot -/Rect [474.671875 380.265 522.671875 392.835] -/Border [0 0 0] ->> -endobj -4729 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4730 0 obj -<< -/Subtype /Link -/A 4729 0 R -/Type /Annot -/Rect [72 351.765 327.732422 364.265] -/Border [0 0 0] ->> -endobj -4731 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4732 0 obj -<< -/Subtype /Link -/A 4731 0 R -/Type /Annot -/Rect [72 330.452 320.4 341.765] -/Border [0 0 0] ->> -endobj -4733 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4734 0 obj -<< -/Subtype /Link -/A 4733 0 R -/Type /Annot -/Rect [72 319.139 88.2 330.452] -/Border [0 0 0] ->> -endobj -4735 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4736 0 obj -<< -/Subtype /Link -/A 4735 0 R -/Type /Annot -/Rect [88.2 319.139 93.6 330.452] -/Border [0 0 0] ->> -endobj -4737 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4738 0 obj -<< -/Subtype /Link -/A 4737 0 R -/Type /Annot -/Rect [93.6 319.139 120.6 330.452] -/Border [0 0 0] ->> -endobj -4739 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4740 0 obj -<< -/Subtype /Link -/A 4739 0 R -/Type /Annot -/Rect [120.6 319.139 126 330.452] -/Border [0 0 0] ->> -endobj -4741 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4742 0 obj -<< -/Subtype /Link -/A 4741 0 R -/Type /Annot -/Rect [126 319.139 223.2 330.452] -/Border [0 0 0] ->> -endobj -4743 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4744 0 obj -<< -/Subtype /Link -/A 4743 0 R -/Type /Annot -/Rect [223.2 319.139 228.6 330.452] -/Border [0 0 0] ->> -endobj -4745 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4746 0 obj -<< -/Subtype /Link -/A 4745 0 R -/Type /Annot -/Rect [228.6 319.139 234 330.452] -/Border [0 0 0] ->> -endobj -4747 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4748 0 obj -<< -/Subtype /Link -/A 4747 0 R -/Type /Annot -/Rect [234 319.139 239.4 330.452] -/Border [0 0 0] ->> -endobj -4749 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4750 0 obj -<< -/Subtype /Link -/A 4749 0 R -/Type /Annot -/Rect [239.4 319.139 244.8 330.452] -/Border [0 0 0] ->> -endobj -4751 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4752 0 obj -<< -/Subtype /Link -/A 4751 0 R -/Type /Annot -/Rect [244.8 319.139 250.2 330.452] -/Border [0 0 0] ->> -endobj -4753 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4754 0 obj -<< -/Subtype /Link -/A 4753 0 R -/Type /Annot -/Rect [250.2 319.139 261 330.452] -/Border [0 0 0] ->> -endobj -4755 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4756 0 obj -<< -/Subtype /Link -/A 4755 0 R -/Type /Annot -/Rect [261 319.139 266.4 330.452] -/Border [0 0 0] ->> -endobj -4757 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4758 0 obj -<< -/Subtype /Link -/A 4757 0 R -/Type /Annot -/Rect [266.4 319.139 271.8 330.452] -/Border [0 0 0] ->> -endobj -4759 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4760 0 obj -<< -/Subtype /Link -/A 4759 0 R -/Type /Annot -/Rect [271.8 319.139 277.2 330.452] -/Border [0 0 0] ->> -endobj -4761 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4762 0 obj -<< -/Subtype /Link -/A 4761 0 R -/Type /Annot -/Rect [277.2 319.139 304.2 330.452] -/Border [0 0 0] ->> -endobj -4763 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4764 0 obj -<< -/Subtype /Link -/A 4763 0 R -/Type /Annot -/Rect [304.2 319.139 309.6 330.452] -/Border [0 0 0] ->> -endobj -4765 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4766 0 obj -<< -/Subtype /Link -/A 4765 0 R -/Type /Annot -/Rect [309.6 319.139 315 330.452] -/Border [0 0 0] ->> -endobj -4767 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4768 0 obj -<< -/Subtype /Link -/A 4767 0 R -/Type /Annot -/Rect [315 319.139 331.2 330.452] -/Border [0 0 0] ->> -endobj -4769 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4770 0 obj -<< -/Subtype /Link -/A 4769 0 R -/Type /Annot -/Rect [331.2 319.139 336.6 330.452] -/Border [0 0 0] ->> -endobj -4771 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4772 0 obj -<< -/Subtype /Link -/A 4771 0 R -/Type /Annot -/Rect [336.6 319.139 342 330.452] -/Border [0 0 0] ->> -endobj -4773 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4774 0 obj -<< -/Subtype /Link -/A 4773 0 R -/Type /Annot -/Rect [72 307.826 88.2 319.139] -/Border [0 0 0] ->> -endobj -4775 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4776 0 obj -<< -/Subtype /Link -/A 4775 0 R -/Type /Annot -/Rect [88.2 307.826 93.6 319.139] -/Border [0 0 0] ->> -endobj -4777 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4778 0 obj -<< -/Subtype /Link -/A 4777 0 R -/Type /Annot -/Rect [93.6 307.826 115.2 319.139] -/Border [0 0 0] ->> -endobj -4779 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4780 0 obj -<< -/Subtype /Link -/A 4779 0 R -/Type /Annot -/Rect [115.2 307.826 120.6 319.139] -/Border [0 0 0] ->> -endobj -4781 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4782 0 obj -<< -/Subtype /Link -/A 4781 0 R -/Type /Annot -/Rect [120.6 307.826 244.8 319.139] -/Border [0 0 0] ->> -endobj -4783 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4784 0 obj -<< -/Subtype /Link -/A 4783 0 R -/Type /Annot -/Rect [244.8 307.826 250.2 319.139] -/Border [0 0 0] ->> -endobj -4785 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4786 0 obj -<< -/Subtype /Link -/A 4785 0 R -/Type /Annot -/Rect [250.2 307.826 255.6 319.139] -/Border [0 0 0] ->> -endobj -4787 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4788 0 obj -<< -/Subtype /Link -/A 4787 0 R -/Type /Annot -/Rect [255.6 307.826 261 319.139] -/Border [0 0 0] ->> -endobj -4789 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4790 0 obj -<< -/Subtype /Link -/A 4789 0 R -/Type /Annot -/Rect [261 307.826 266.4 319.139] -/Border [0 0 0] ->> -endobj -4791 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4792 0 obj -<< -/Subtype /Link -/A 4791 0 R -/Type /Annot -/Rect [266.4 307.826 271.8 319.139] -/Border [0 0 0] ->> -endobj -4793 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4794 0 obj -<< -/Subtype /Link -/A 4793 0 R -/Type /Annot -/Rect [271.8 307.826 277.2 319.139] -/Border [0 0 0] ->> -endobj -4795 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4796 0 obj -<< -/Subtype /Link -/A 4795 0 R -/Type /Annot -/Rect [277.2 307.826 282.6 319.139] -/Border [0 0 0] ->> -endobj -4797 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4798 0 obj -<< -/Subtype /Link -/A 4797 0 R -/Type /Annot -/Rect [282.6 307.826 288 319.139] -/Border [0 0 0] ->> -endobj -4799 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4800 0 obj -<< -/Subtype /Link -/A 4799 0 R -/Type /Annot -/Rect [72 285.2 277.2 296.513] -/Border [0 0 0] ->> -endobj -4801 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4802 0 obj -<< -/Subtype /Link -/A 4801 0 R -/Type /Annot -/Rect [72 273.887 88.2 285.2] -/Border [0 0 0] ->> -endobj -4803 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4804 0 obj -<< -/Subtype /Link -/A 4803 0 R -/Type /Annot -/Rect [88.2 273.887 93.6 285.2] -/Border [0 0 0] ->> -endobj -4805 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4806 0 obj -<< -/Subtype /Link -/A 4805 0 R -/Type /Annot -/Rect [93.6 273.887 120.6 285.2] -/Border [0 0 0] ->> -endobj -4807 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4808 0 obj -<< -/Subtype /Link -/A 4807 0 R -/Type /Annot -/Rect [120.6 273.887 126 285.2] -/Border [0 0 0] ->> -endobj -4809 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4810 0 obj -<< -/Subtype /Link -/A 4809 0 R -/Type /Annot -/Rect [126 273.887 223.2 285.2] -/Border [0 0 0] ->> -endobj -4811 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4812 0 obj -<< -/Subtype /Link -/A 4811 0 R -/Type /Annot -/Rect [223.2 273.887 228.6 285.2] -/Border [0 0 0] ->> -endobj -4813 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4814 0 obj -<< -/Subtype /Link -/A 4813 0 R -/Type /Annot -/Rect [228.6 273.887 234 285.2] -/Border [0 0 0] ->> -endobj -4815 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4816 0 obj -<< -/Subtype /Link -/A 4815 0 R -/Type /Annot -/Rect [234 273.887 250.2 285.2] -/Border [0 0 0] ->> -endobj -4817 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4818 0 obj -<< -/Subtype /Link -/A 4817 0 R -/Type /Annot -/Rect [250.2 273.887 255.6 285.2] -/Border [0 0 0] ->> -endobj -4819 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4820 0 obj -<< -/Subtype /Link -/A 4819 0 R -/Type /Annot -/Rect [255.6 273.887 261 285.2] -/Border [0 0 0] ->> -endobj -4821 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4822 0 obj -<< -/Subtype /Link -/A 4821 0 R -/Type /Annot -/Rect [261 273.887 271.8 285.2] -/Border [0 0 0] ->> -endobj -4823 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4824 0 obj -<< -/Subtype /Link -/A 4823 0 R -/Type /Annot -/Rect [271.8 273.887 277.2 285.2] -/Border [0 0 0] ->> -endobj -4825 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4826 0 obj -<< -/Subtype /Link -/A 4825 0 R -/Type /Annot -/Rect [277.2 273.887 282.6 285.2] -/Border [0 0 0] ->> -endobj -4827 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4828 0 obj -<< -/Subtype /Link -/A 4827 0 R -/Type /Annot -/Rect [282.6 273.887 288 285.2] -/Border [0 0 0] ->> -endobj -4829 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4830 0 obj -<< -/Subtype /Link -/A 4829 0 R -/Type /Annot -/Rect [288 273.887 304.2 285.2] -/Border [0 0 0] ->> -endobj -4831 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4832 0 obj -<< -/Subtype /Link -/A 4831 0 R -/Type /Annot -/Rect [304.2 273.887 309.6 285.2] -/Border [0 0 0] ->> -endobj -4833 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4834 0 obj -<< -/Subtype /Link -/A 4833 0 R -/Type /Annot -/Rect [309.6 273.887 315 285.2] -/Border [0 0 0] ->> -endobj -4835 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4836 0 obj -<< -/Subtype /Link -/A 4835 0 R -/Type /Annot -/Rect [315 273.887 320.4 285.2] -/Border [0 0 0] ->> -endobj -4837 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4838 0 obj -<< -/Subtype /Link -/A 4837 0 R -/Type /Annot -/Rect [320.4 273.887 336.6 285.2] -/Border [0 0 0] ->> -endobj -4839 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4840 0 obj -<< -/Subtype /Link -/A 4839 0 R -/Type /Annot -/Rect [336.6 273.887 342 285.2] -/Border [0 0 0] ->> -endobj -4841 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4842 0 obj -<< -/Subtype /Link -/A 4841 0 R -/Type /Annot -/Rect [342 273.887 347.4 285.2] -/Border [0 0 0] ->> -endobj -4843 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4844 0 obj -<< -/Subtype /Link -/A 4843 0 R -/Type /Annot -/Rect [347.4 273.887 363.6 285.2] -/Border [0 0 0] ->> -endobj -4845 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4846 0 obj -<< -/Subtype /Link -/A 4845 0 R -/Type /Annot -/Rect [363.6 273.887 369 285.2] -/Border [0 0 0] ->> -endobj -4847 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4848 0 obj -<< -/Subtype /Link -/A 4847 0 R -/Type /Annot -/Rect [369 273.887 374.4 285.2] -/Border [0 0 0] ->> -endobj -4849 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4850 0 obj -<< -/Subtype /Link -/A 4849 0 R -/Type /Annot -/Rect [374.4 273.887 379.8 285.2] -/Border [0 0 0] ->> -endobj -4851 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4852 0 obj -<< -/Subtype /Link -/A 4851 0 R -/Type /Annot -/Rect [72 262.574 88.2 273.887] -/Border [0 0 0] ->> -endobj -4853 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4854 0 obj -<< -/Subtype /Link -/A 4853 0 R -/Type /Annot -/Rect [88.2 262.574 93.6 273.887] -/Border [0 0 0] ->> -endobj -4855 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4856 0 obj -<< -/Subtype /Link -/A 4855 0 R -/Type /Annot -/Rect [93.6 262.574 115.2 273.887] -/Border [0 0 0] ->> -endobj -4857 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4858 0 obj -<< -/Subtype /Link -/A 4857 0 R -/Type /Annot -/Rect [115.2 262.574 120.6 273.887] -/Border [0 0 0] ->> -endobj -4859 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4860 0 obj -<< -/Subtype /Link -/A 4859 0 R -/Type /Annot -/Rect [120.6 262.574 136.8 273.887] -/Border [0 0 0] ->> -endobj -4861 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4862 0 obj -<< -/Subtype /Link -/A 4861 0 R -/Type /Annot -/Rect [136.8 262.574 142.2 273.887] -/Border [0 0 0] ->> -endobj -4863 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4864 0 obj -<< -/Subtype /Link -/A 4863 0 R -/Type /Annot -/Rect [142.2 262.574 147.6 273.887] -/Border [0 0 0] ->> -endobj -4865 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4866 0 obj -<< -/Subtype /Link -/A 4865 0 R -/Type /Annot -/Rect [147.6 262.574 158.4 273.887] -/Border [0 0 0] ->> -endobj -4867 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4868 0 obj -<< -/Subtype /Link -/A 4867 0 R -/Type /Annot -/Rect [158.4 262.574 163.8 273.887] -/Border [0 0 0] ->> -endobj -4869 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4870 0 obj -<< -/Subtype /Link -/A 4869 0 R -/Type /Annot -/Rect [163.8 262.574 169.2 273.887] -/Border [0 0 0] ->> -endobj -4871 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4872 0 obj -<< -/Subtype /Link -/A 4871 0 R -/Type /Annot -/Rect [169.2 262.574 185.4 273.887] -/Border [0 0 0] ->> -endobj -4873 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4874 0 obj -<< -/Subtype /Link -/A 4873 0 R -/Type /Annot -/Rect [185.4 262.574 190.8 273.887] -/Border [0 0 0] ->> -endobj -4875 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4876 0 obj -<< -/Subtype /Link -/A 4875 0 R -/Type /Annot -/Rect [190.8 262.574 196.2 273.887] -/Border [0 0 0] ->> -endobj -4877 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4878 0 obj -<< -/Subtype /Link -/A 4877 0 R -/Type /Annot -/Rect [196.2 262.574 212.4 273.887] -/Border [0 0 0] ->> -endobj -4879 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4880 0 obj -<< -/Subtype /Link -/A 4879 0 R -/Type /Annot -/Rect [212.4 262.574 217.8 273.887] -/Border [0 0 0] ->> -endobj -4881 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4882 0 obj -<< -/Subtype /Link -/A 4881 0 R -/Type /Annot -/Rect [72 251.261 88.2 262.574] -/Border [0 0 0] ->> -endobj -4883 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4884 0 obj -<< -/Subtype /Link -/A 4883 0 R -/Type /Annot -/Rect [88.2 251.261 93.6 262.574] -/Border [0 0 0] ->> -endobj -4885 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4886 0 obj -<< -/Subtype /Link -/A 4885 0 R -/Type /Annot -/Rect [93.6 251.261 126 262.574] -/Border [0 0 0] ->> -endobj -4887 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4888 0 obj -<< -/Subtype /Link -/A 4887 0 R -/Type /Annot -/Rect [126 251.261 131.4 262.574] -/Border [0 0 0] ->> -endobj -4889 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4890 0 obj -<< -/Subtype /Link -/A 4889 0 R -/Type /Annot -/Rect [131.4 251.261 136.8 262.574] -/Border [0 0 0] ->> -endobj -4891 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4892 0 obj -<< -/Subtype /Link -/A 4891 0 R -/Type /Annot -/Rect [72 239.948 88.2 251.261] -/Border [0 0 0] ->> -endobj -4893 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4894 0 obj -<< -/Subtype /Link -/A 4893 0 R -/Type /Annot -/Rect [88.2 239.948 93.6 251.261] -/Border [0 0 0] ->> -endobj -4895 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4896 0 obj -<< -/Subtype /Link -/A 4895 0 R -/Type /Annot -/Rect [93.6 239.948 115.2 251.261] -/Border [0 0 0] ->> -endobj -4897 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4898 0 obj -<< -/Subtype /Link -/A 4897 0 R -/Type /Annot -/Rect [115.2 239.948 120.6 251.261] -/Border [0 0 0] ->> -endobj -4899 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4900 0 obj -<< -/Subtype /Link -/A 4899 0 R -/Type /Annot -/Rect [120.6 239.948 147.6 251.261] -/Border [0 0 0] ->> -endobj -4901 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4902 0 obj -<< -/Subtype /Link -/A 4901 0 R -/Type /Annot -/Rect [147.6 239.948 153 251.261] -/Border [0 0 0] ->> -endobj -4903 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4904 0 obj -<< -/Subtype /Link -/A 4903 0 R -/Type /Annot -/Rect [153 239.948 158.4 251.261] -/Border [0 0 0] ->> -endobj -4905 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4906 0 obj -<< -/Subtype /Link -/A 4905 0 R -/Type /Annot -/Rect [158.4 239.948 174.6 251.261] -/Border [0 0 0] ->> -endobj -4907 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4908 0 obj -<< -/Subtype /Link -/A 4907 0 R -/Type /Annot -/Rect [174.6 239.948 180 251.261] -/Border [0 0 0] ->> -endobj -4909 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4910 0 obj -<< -/Subtype /Link -/A 4909 0 R -/Type /Annot -/Rect [180 239.948 185.4 251.261] -/Border [0 0 0] ->> -endobj -4911 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4912 0 obj -<< -/Subtype /Link -/A 4911 0 R -/Type /Annot -/Rect [185.4 239.948 190.8 251.261] -/Border [0 0 0] ->> -endobj -4913 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4914 0 obj -<< -/Subtype /Link -/A 4913 0 R -/Type /Annot -/Rect [190.8 239.948 196.2 251.261] -/Border [0 0 0] ->> -endobj -4915 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4916 0 obj -<< -/Subtype /Link -/A 4915 0 R -/Type /Annot -/Rect [196.2 239.948 201.6 251.261] -/Border [0 0 0] ->> -endobj -4917 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4918 0 obj -<< -/Subtype /Link -/A 4917 0 R -/Type /Annot -/Rect [72 217.322 180 228.635] -/Border [0 0 0] ->> -endobj -4919 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4920 0 obj -<< -/Subtype /Link -/A 4919 0 R -/Type /Annot -/Rect [72 206.009 88.2 217.322] -/Border [0 0 0] ->> -endobj -4921 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4922 0 obj -<< -/Subtype /Link -/A 4921 0 R -/Type /Annot -/Rect [88.2 206.009 93.6 217.322] -/Border [0 0 0] ->> -endobj -4923 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4924 0 obj -<< -/Subtype /Link -/A 4923 0 R -/Type /Annot -/Rect [93.6 206.009 120.6 217.322] -/Border [0 0 0] ->> -endobj -4925 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4926 0 obj -<< -/Subtype /Link -/A 4925 0 R -/Type /Annot -/Rect [120.6 206.009 126 217.322] -/Border [0 0 0] ->> -endobj -4927 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4928 0 obj -<< -/Subtype /Link -/A 4927 0 R -/Type /Annot -/Rect [126 206.009 223.2 217.322] -/Border [0 0 0] ->> -endobj -4929 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4930 0 obj -<< -/Subtype /Link -/A 4929 0 R -/Type /Annot -/Rect [223.2 206.009 228.6 217.322] -/Border [0 0 0] ->> -endobj -4931 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4932 0 obj -<< -/Subtype /Link -/A 4931 0 R -/Type /Annot -/Rect [228.6 206.009 234 217.322] -/Border [0 0 0] ->> -endobj -4933 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4934 0 obj -<< -/Subtype /Link -/A 4933 0 R -/Type /Annot -/Rect [234 206.009 250.2 217.322] -/Border [0 0 0] ->> -endobj -4935 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4936 0 obj -<< -/Subtype /Link -/A 4935 0 R -/Type /Annot -/Rect [250.2 206.009 255.6 217.322] -/Border [0 0 0] ->> -endobj -4937 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4938 0 obj -<< -/Subtype /Link -/A 4937 0 R -/Type /Annot -/Rect [255.6 206.009 261 217.322] -/Border [0 0 0] ->> -endobj -4939 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4940 0 obj -<< -/Subtype /Link -/A 4939 0 R -/Type /Annot -/Rect [261 206.009 277.2 217.322] -/Border [0 0 0] ->> -endobj -4941 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4942 0 obj -<< -/Subtype /Link -/A 4941 0 R -/Type /Annot -/Rect [277.2 206.009 282.6 217.322] -/Border [0 0 0] ->> -endobj -4943 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4944 0 obj -<< -/Subtype /Link -/A 4943 0 R -/Type /Annot -/Rect [282.6 206.009 288 217.322] -/Border [0 0 0] ->> -endobj -4945 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4946 0 obj -<< -/Subtype /Link -/A 4945 0 R -/Type /Annot -/Rect [288 206.009 293.4 217.322] -/Border [0 0 0] ->> -endobj -4947 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4948 0 obj -<< -/Subtype /Link -/A 4947 0 R -/Type /Annot -/Rect [293.4 206.009 320.4 217.322] -/Border [0 0 0] ->> -endobj -4949 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4950 0 obj -<< -/Subtype /Link -/A 4949 0 R -/Type /Annot -/Rect [320.4 206.009 325.8 217.322] -/Border [0 0 0] ->> -endobj -4951 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4952 0 obj -<< -/Subtype /Link -/A 4951 0 R -/Type /Annot -/Rect [325.8 206.009 331.2 217.322] -/Border [0 0 0] ->> -endobj -4953 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4954 0 obj -<< -/Subtype /Link -/A 4953 0 R -/Type /Annot -/Rect [331.2 206.009 347.4 217.322] -/Border [0 0 0] ->> -endobj -4955 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4956 0 obj -<< -/Subtype /Link -/A 4955 0 R -/Type /Annot -/Rect [347.4 206.009 352.8 217.322] -/Border [0 0 0] ->> -endobj -4957 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4958 0 obj -<< -/Subtype /Link -/A 4957 0 R -/Type /Annot -/Rect [352.8 206.009 358.2 217.322] -/Border [0 0 0] ->> -endobj -4959 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4960 0 obj -<< -/Subtype /Link -/A 4959 0 R -/Type /Annot -/Rect [358.2 206.009 390.6 217.322] -/Border [0 0 0] ->> -endobj -4961 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4962 0 obj -<< -/Subtype /Link -/A 4961 0 R -/Type /Annot -/Rect [390.6 206.009 396 217.322] -/Border [0 0 0] ->> -endobj -4963 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4964 0 obj -<< -/Subtype /Link -/A 4963 0 R -/Type /Annot -/Rect [396 206.009 401.4 217.322] -/Border [0 0 0] ->> -endobj -4965 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4966 0 obj -<< -/Subtype /Link -/A 4965 0 R -/Type /Annot -/Rect [401.4 206.009 417.6 217.322] -/Border [0 0 0] ->> -endobj -4967 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4968 0 obj -<< -/Subtype /Link -/A 4967 0 R -/Type /Annot -/Rect [417.6 206.009 423 217.322] -/Border [0 0 0] ->> -endobj -4969 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4970 0 obj -<< -/Subtype /Link -/A 4969 0 R -/Type /Annot -/Rect [423 206.009 428.4 217.322] -/Border [0 0 0] ->> -endobj -4971 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4972 0 obj -<< -/Subtype /Link -/A 4971 0 R -/Type /Annot -/Rect [72 194.696 88.2 206.009] -/Border [0 0 0] ->> -endobj -4973 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4974 0 obj -<< -/Subtype /Link -/A 4973 0 R -/Type /Annot -/Rect [88.2 194.696 93.6 206.009] -/Border [0 0 0] ->> -endobj -4975 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4976 0 obj -<< -/Subtype /Link -/A 4975 0 R -/Type /Annot -/Rect [93.6 194.696 115.2 206.009] -/Border [0 0 0] ->> -endobj -4977 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4978 0 obj -<< -/Subtype /Link -/A 4977 0 R -/Type /Annot -/Rect [115.2 194.696 120.6 206.009] -/Border [0 0 0] ->> -endobj -4979 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4980 0 obj -<< -/Subtype /Link -/A 4979 0 R -/Type /Annot -/Rect [120.6 194.696 169.2 206.009] -/Border [0 0 0] ->> -endobj -4981 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4982 0 obj -<< -/Subtype /Link -/A 4981 0 R -/Type /Annot -/Rect [169.2 194.696 174.6 206.009] -/Border [0 0 0] ->> -endobj -4983 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4984 0 obj -<< -/Subtype /Link -/A 4983 0 R -/Type /Annot -/Rect [174.6 194.696 180 206.009] -/Border [0 0 0] ->> -endobj -4985 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4986 0 obj -<< -/Subtype /Link -/A 4985 0 R -/Type /Annot -/Rect [180 194.696 196.2 206.009] -/Border [0 0 0] ->> -endobj -4987 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4988 0 obj -<< -/Subtype /Link -/A 4987 0 R -/Type /Annot -/Rect [196.2 194.696 201.6 206.009] -/Border [0 0 0] ->> -endobj -4989 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4990 0 obj -<< -/Subtype /Link -/A 4989 0 R -/Type /Annot -/Rect [201.6 194.696 207 206.009] -/Border [0 0 0] ->> -endobj -4991 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4992 0 obj -<< -/Subtype /Link -/A 4991 0 R -/Type /Annot -/Rect [207 194.696 223.2 206.009] -/Border [0 0 0] ->> -endobj -4993 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4994 0 obj -<< -/Subtype /Link -/A 4993 0 R -/Type /Annot -/Rect [223.2 194.696 228.6 206.009] -/Border [0 0 0] ->> -endobj -4995 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4996 0 obj -<< -/Subtype /Link -/A 4995 0 R -/Type /Annot -/Rect [228.6 194.696 234 206.009] -/Border [0 0 0] ->> -endobj -4997 0 obj -<< -/S /URI -/URI (false) ->> -endobj -4998 0 obj -<< -/Subtype /Link -/A 4997 0 R -/Type /Annot -/Rect [72 172.07 169.2 183.383] -/Border [0 0 0] ->> -endobj -4999 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5000 0 obj -<< -/Subtype /Link -/A 4999 0 R -/Type /Annot -/Rect [72 160.757 88.2 172.07] -/Border [0 0 0] ->> -endobj -5001 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5002 0 obj -<< -/Subtype /Link -/A 5001 0 R -/Type /Annot -/Rect [88.2 160.757 93.6 172.07] -/Border [0 0 0] ->> -endobj -5003 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5004 0 obj -<< -/Subtype /Link -/A 5003 0 R -/Type /Annot -/Rect [93.6 160.757 120.6 172.07] -/Border [0 0 0] ->> -endobj -5005 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5006 0 obj -<< -/Subtype /Link -/A 5005 0 R -/Type /Annot -/Rect [120.6 160.757 126 172.07] -/Border [0 0 0] ->> -endobj -5007 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5008 0 obj -<< -/Subtype /Link -/A 5007 0 R -/Type /Annot -/Rect [126 160.757 223.2 172.07] -/Border [0 0 0] ->> -endobj -5009 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5010 0 obj -<< -/Subtype /Link -/A 5009 0 R -/Type /Annot -/Rect [223.2 160.757 228.6 172.07] -/Border [0 0 0] ->> -endobj -5011 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5012 0 obj -<< -/Subtype /Link -/A 5011 0 R -/Type /Annot -/Rect [228.6 160.757 234 172.07] -/Border [0 0 0] ->> -endobj -5013 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5014 0 obj -<< -/Subtype /Link -/A 5013 0 R -/Type /Annot -/Rect [234 160.757 250.2 172.07] -/Border [0 0 0] ->> -endobj -5015 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5016 0 obj -<< -/Subtype /Link -/A 5015 0 R -/Type /Annot -/Rect [250.2 160.757 255.6 172.07] -/Border [0 0 0] ->> -endobj -5017 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5018 0 obj -<< -/Subtype /Link -/A 5017 0 R -/Type /Annot -/Rect [255.6 160.757 261 172.07] -/Border [0 0 0] ->> -endobj -5019 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5020 0 obj -<< -/Subtype /Link -/A 5019 0 R -/Type /Annot -/Rect [261 160.757 277.2 172.07] -/Border [0 0 0] ->> -endobj -5021 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5022 0 obj -<< -/Subtype /Link -/A 5021 0 R -/Type /Annot -/Rect [277.2 160.757 282.6 172.07] -/Border [0 0 0] ->> -endobj -5023 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5024 0 obj -<< -/Subtype /Link -/A 5023 0 R -/Type /Annot -/Rect [282.6 160.757 288 172.07] -/Border [0 0 0] ->> -endobj -5025 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5026 0 obj -<< -/Subtype /Link -/A 5025 0 R -/Type /Annot -/Rect [288 160.757 293.4 172.07] -/Border [0 0 0] ->> -endobj -5027 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5028 0 obj -<< -/Subtype /Link -/A 5027 0 R -/Type /Annot -/Rect [293.4 160.757 320.4 172.07] -/Border [0 0 0] ->> -endobj -5029 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5030 0 obj -<< -/Subtype /Link -/A 5029 0 R -/Type /Annot -/Rect [320.4 160.757 325.8 172.07] -/Border [0 0 0] ->> -endobj -5031 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5032 0 obj -<< -/Subtype /Link -/A 5031 0 R -/Type /Annot -/Rect [325.8 160.757 331.2 172.07] -/Border [0 0 0] ->> -endobj -5033 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5034 0 obj -<< -/Subtype /Link -/A 5033 0 R -/Type /Annot -/Rect [331.2 160.757 352.8 172.07] -/Border [0 0 0] ->> -endobj -5035 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5036 0 obj -<< -/Subtype /Link -/A 5035 0 R -/Type /Annot -/Rect [352.8 160.757 358.2 172.07] -/Border [0 0 0] ->> -endobj -5037 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5038 0 obj -<< -/Subtype /Link -/A 5037 0 R -/Type /Annot -/Rect [358.2 160.757 363.6 172.07] -/Border [0 0 0] ->> -endobj -5039 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5040 0 obj -<< -/Subtype /Link -/A 5039 0 R -/Type /Annot -/Rect [72 149.444 88.2 160.757] -/Border [0 0 0] ->> -endobj -5041 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5042 0 obj -<< -/Subtype /Link -/A 5041 0 R -/Type /Annot -/Rect [88.2 149.444 93.6 160.757] -/Border [0 0 0] ->> -endobj -5043 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5044 0 obj -<< -/Subtype /Link -/A 5043 0 R -/Type /Annot -/Rect [93.6 149.444 115.2 160.757] -/Border [0 0 0] ->> -endobj -5045 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5046 0 obj -<< -/Subtype /Link -/A 5045 0 R -/Type /Annot -/Rect [115.2 149.444 120.6 160.757] -/Border [0 0 0] ->> -endobj -5047 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5048 0 obj -<< -/Subtype /Link -/A 5047 0 R -/Type /Annot -/Rect [120.6 149.444 158.4 160.757] -/Border [0 0 0] ->> -endobj -5049 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5050 0 obj -<< -/Subtype /Link -/A 5049 0 R -/Type /Annot -/Rect [158.4 149.444 163.8 160.757] -/Border [0 0 0] ->> -endobj -5051 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5052 0 obj -<< -/Subtype /Link -/A 5051 0 R -/Type /Annot -/Rect [163.8 149.444 169.2 160.757] -/Border [0 0 0] ->> -endobj -5053 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5054 0 obj -<< -/Subtype /Link -/A 5053 0 R -/Type /Annot -/Rect [169.2 149.444 185.4 160.757] -/Border [0 0 0] ->> -endobj -5055 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5056 0 obj -<< -/Subtype /Link -/A 5055 0 R -/Type /Annot -/Rect [185.4 149.444 190.8 160.757] -/Border [0 0 0] ->> -endobj -5057 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5058 0 obj -<< -/Subtype /Link -/A 5057 0 R -/Type /Annot -/Rect [190.8 149.444 196.2 160.757] -/Border [0 0 0] ->> -endobj -5059 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5060 0 obj -<< -/Subtype /Link -/A 5059 0 R -/Type /Annot -/Rect [196.2 149.444 212.4 160.757] -/Border [0 0 0] ->> -endobj -5061 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5062 0 obj -<< -/Subtype /Link -/A 5061 0 R -/Type /Annot -/Rect [212.4 149.444 217.8 160.757] -/Border [0 0 0] ->> -endobj -5063 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5064 0 obj -<< -/Subtype /Link -/A 5063 0 R -/Type /Annot -/Rect [217.8 149.444 223.2 160.757] -/Border [0 0 0] ->> -endobj -5065 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5066 0 obj -<< -/Subtype /Link -/A 5065 0 R -/Type /Annot -/Rect [72 126.818 514.8 138.131] -/Border [0 0 0] ->> -endobj -5067 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5068 0 obj -<< -/Subtype /Link -/A 5067 0 R -/Type /Annot -/Rect [72 115.505 88.2 126.818] -/Border [0 0 0] ->> -endobj -5069 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5070 0 obj -<< -/Subtype /Link -/A 5069 0 R -/Type /Annot -/Rect [88.2 115.505 93.6 126.818] -/Border [0 0 0] ->> -endobj -5071 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5072 0 obj -<< -/Subtype /Link -/A 5071 0 R -/Type /Annot -/Rect [93.6 115.505 120.6 126.818] -/Border [0 0 0] ->> -endobj -5073 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5074 0 obj -<< -/Subtype /Link -/A 5073 0 R -/Type /Annot -/Rect [120.6 115.505 126 126.818] -/Border [0 0 0] ->> -endobj -5075 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5076 0 obj -<< -/Subtype /Link -/A 5075 0 R -/Type /Annot -/Rect [126 115.505 223.2 126.818] -/Border [0 0 0] ->> -endobj -5077 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5078 0 obj -<< -/Subtype /Link -/A 5077 0 R -/Type /Annot -/Rect [223.2 115.505 228.6 126.818] -/Border [0 0 0] ->> -endobj -5079 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5080 0 obj -<< -/Subtype /Link -/A 5079 0 R -/Type /Annot -/Rect [228.6 115.505 234 126.818] -/Border [0 0 0] ->> -endobj -5081 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5082 0 obj -<< -/Subtype /Link -/A 5081 0 R -/Type /Annot -/Rect [234 115.505 250.2 126.818] -/Border [0 0 0] ->> -endobj -5083 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5084 0 obj -<< -/Subtype /Link -/A 5083 0 R -/Type /Annot -/Rect [250.2 115.505 255.6 126.818] -/Border [0 0 0] ->> -endobj -5085 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5086 0 obj -<< -/Subtype /Link -/A 5085 0 R -/Type /Annot -/Rect [255.6 115.505 261 126.818] -/Border [0 0 0] ->> -endobj -5087 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5088 0 obj -<< -/Subtype /Link -/A 5087 0 R -/Type /Annot -/Rect [261 115.505 271.8 126.818] -/Border [0 0 0] ->> -endobj -5089 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5090 0 obj -<< -/Subtype /Link -/A 5089 0 R -/Type /Annot -/Rect [271.8 115.505 277.2 126.818] -/Border [0 0 0] ->> -endobj -5091 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5092 0 obj -<< -/Subtype /Link -/A 5091 0 R -/Type /Annot -/Rect [277.2 115.505 282.6 126.818] -/Border [0 0 0] ->> -endobj -5093 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5094 0 obj -<< -/Subtype /Link -/A 5093 0 R -/Type /Annot -/Rect [282.6 115.505 288 126.818] -/Border [0 0 0] ->> -endobj -5095 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5096 0 obj -<< -/Subtype /Link -/A 5095 0 R -/Type /Annot -/Rect [288 115.505 304.2 126.818] -/Border [0 0 0] ->> -endobj -5097 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5098 0 obj -<< -/Subtype /Link -/A 5097 0 R -/Type /Annot -/Rect [304.2 115.505 309.6 126.818] -/Border [0 0 0] ->> -endobj -5099 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5100 0 obj -<< -/Subtype /Link -/A 5099 0 R -/Type /Annot -/Rect [309.6 115.505 315 126.818] -/Border [0 0 0] ->> -endobj -5101 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5102 0 obj -<< -/Subtype /Link -/A 5101 0 R -/Type /Annot -/Rect [315 115.505 320.4 126.818] -/Border [0 0 0] ->> -endobj -5103 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5104 0 obj -<< -/Subtype /Link -/A 5103 0 R -/Type /Annot -/Rect [320.4 115.505 336.6 126.818] -/Border [0 0 0] ->> -endobj -5105 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5106 0 obj -<< -/Subtype /Link -/A 5105 0 R -/Type /Annot -/Rect [336.6 115.505 342 126.818] -/Border [0 0 0] ->> -endobj -5107 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5108 0 obj -<< -/Subtype /Link -/A 5107 0 R -/Type /Annot -/Rect [342 115.505 347.4 126.818] -/Border [0 0 0] ->> -endobj -5109 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5110 0 obj -<< -/Subtype /Link -/A 5109 0 R -/Type /Annot -/Rect [347.4 115.505 363.6 126.818] -/Border [0 0 0] ->> -endobj -5111 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5112 0 obj -<< -/Subtype /Link -/A 5111 0 R -/Type /Annot -/Rect [363.6 115.505 369 126.818] -/Border [0 0 0] ->> -endobj -5113 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5114 0 obj -<< -/Subtype /Link -/A 5113 0 R -/Type /Annot -/Rect [369 115.505 374.4 126.818] -/Border [0 0 0] ->> -endobj -5115 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5116 0 obj -<< -/Subtype /Link -/A 5115 0 R -/Type /Annot -/Rect [374.4 115.505 379.8 126.818] -/Border [0 0 0] ->> -endobj -5117 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5118 0 obj -<< -/Subtype /Link -/A 5117 0 R -/Type /Annot -/Rect [379.8 115.505 406.8 126.818] -/Border [0 0 0] ->> -endobj -5119 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5120 0 obj -<< -/Subtype /Link -/A 5119 0 R -/Type /Annot -/Rect [406.8 115.505 412.2 126.818] -/Border [0 0 0] ->> -endobj -5121 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5122 0 obj -<< -/Subtype /Link -/A 5121 0 R -/Type /Annot -/Rect [412.2 115.505 417.6 126.818] -/Border [0 0 0] ->> -endobj -5123 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5124 0 obj -<< -/Subtype /Link -/A 5123 0 R -/Type /Annot -/Rect [417.6 115.505 460.8 126.818] -/Border [0 0 0] ->> -endobj -5125 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5126 0 obj -<< -/Subtype /Link -/A 5125 0 R -/Type /Annot -/Rect [460.8 115.505 466.2 126.818] -/Border [0 0 0] ->> -endobj -5127 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5128 0 obj -<< -/Subtype /Link -/A 5127 0 R -/Type /Annot -/Rect [466.2 115.505 471.6 126.818] -/Border [0 0 0] ->> -endobj -5129 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5130 0 obj -<< -/Subtype /Link -/A 5129 0 R -/Type /Annot -/Rect [471.6 115.505 504 126.818] -/Border [0 0 0] ->> -endobj -5131 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5132 0 obj -<< -/Subtype /Link -/A 5131 0 R -/Type /Annot -/Rect [504 115.505 509.4 126.818] -/Border [0 0 0] ->> -endobj -5133 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5134 0 obj -<< -/Subtype /Link -/A 5133 0 R -/Type /Annot -/Rect [509.4 115.505 514.8 126.818] -/Border [0 0 0] ->> -endobj -5135 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5136 0 obj -<< -/Subtype /Link -/A 5135 0 R -/Type /Annot -/Rect [72 104.192 115.2 115.505] -/Border [0 0 0] ->> -endobj -5137 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5138 0 obj -<< -/Subtype /Link -/A 5137 0 R -/Type /Annot -/Rect [115.2 104.192 120.6 115.505] -/Border [0 0 0] ->> -endobj -5139 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5140 0 obj -<< -/Subtype /Link -/A 5139 0 R -/Type /Annot -/Rect [120.6 104.192 126 115.505] -/Border [0 0 0] ->> -endobj -5141 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5142 0 obj -<< -/Subtype /Link -/A 5141 0 R -/Type /Annot -/Rect [72 92.879 88.2 104.192] -/Border [0 0 0] ->> -endobj -5143 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5144 0 obj -<< -/Subtype /Link -/A 5143 0 R -/Type /Annot -/Rect [88.2 92.879 93.6 104.192] -/Border [0 0 0] ->> -endobj -5145 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5146 0 obj -<< -/Subtype /Link -/A 5145 0 R -/Type /Annot -/Rect [93.6 92.879 115.2 104.192] -/Border [0 0 0] ->> -endobj -5147 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5148 0 obj -<< -/Subtype /Link -/A 5147 0 R -/Type /Annot -/Rect [115.2 92.879 120.6 104.192] -/Border [0 0 0] ->> -endobj -5149 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5150 0 obj -<< -/Subtype /Link -/A 5149 0 R -/Type /Annot -/Rect [120.6 92.879 136.8 104.192] -/Border [0 0 0] ->> -endobj -5151 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5152 0 obj -<< -/Subtype /Link -/A 5151 0 R -/Type /Annot -/Rect [136.8 92.879 142.2 104.192] -/Border [0 0 0] ->> -endobj -5153 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5154 0 obj -<< -/Subtype /Link -/A 5153 0 R -/Type /Annot -/Rect [142.2 92.879 147.6 104.192] -/Border [0 0 0] ->> -endobj -5155 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5156 0 obj -<< -/Subtype /Link -/A 5155 0 R -/Type /Annot -/Rect [147.6 92.879 158.4 104.192] -/Border [0 0 0] ->> -endobj -5157 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5158 0 obj -<< -/Subtype /Link -/A 5157 0 R -/Type /Annot -/Rect [158.4 92.879 163.8 104.192] -/Border [0 0 0] ->> -endobj -5159 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5160 0 obj -<< -/Subtype /Link -/A 5159 0 R -/Type /Annot -/Rect [163.8 92.879 169.2 104.192] -/Border [0 0 0] ->> -endobj -5161 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5162 0 obj -<< -/Subtype /Link -/A 5161 0 R -/Type /Annot -/Rect [169.2 92.879 185.4 104.192] -/Border [0 0 0] ->> -endobj -5163 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5164 0 obj -<< -/Subtype /Link -/A 5163 0 R -/Type /Annot -/Rect [185.4 92.879 190.8 104.192] -/Border [0 0 0] ->> -endobj -5165 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5166 0 obj -<< -/Subtype /Link -/A 5165 0 R -/Type /Annot -/Rect [190.8 92.879 196.2 104.192] -/Border [0 0 0] ->> -endobj -5167 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5168 0 obj -<< -/Subtype /Link -/A 5167 0 R -/Type /Annot -/Rect [196.2 92.879 212.4 104.192] -/Border [0 0 0] ->> -endobj -5169 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5170 0 obj -<< -/Subtype /Link -/A 5169 0 R -/Type /Annot -/Rect [212.4 92.879 217.8 104.192] -/Border [0 0 0] ->> -endobj -5171 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5172 0 obj -<< -/Subtype /Link -/A 5171 0 R -/Type /Annot -/Rect [217.8 92.879 223.2 104.192] -/Border [0 0 0] ->> -endobj -5173 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5174 0 obj -<< -/Subtype /Link -/A 5173 0 R -/Type /Annot -/Rect [223.2 92.879 255.6 104.192] -/Border [0 0 0] ->> -endobj -5175 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5176 0 obj -<< -/Subtype /Link -/A 5175 0 R -/Type /Annot -/Rect [255.6 92.879 261 104.192] -/Border [0 0 0] ->> -endobj -5177 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5178 0 obj -<< -/Subtype /Link -/A 5177 0 R -/Type /Annot -/Rect [261 92.879 266.4 104.192] -/Border [0 0 0] ->> -endobj -5179 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5180 0 obj -<< -/Subtype /Link -/A 5179 0 R -/Type /Annot -/Rect [72 81.566 88.2 92.879] -/Border [0 0 0] ->> -endobj -5181 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5182 0 obj -<< -/Subtype /Link -/A 5181 0 R -/Type /Annot -/Rect [88.2 81.566 93.6 92.879] -/Border [0 0 0] ->> -endobj -5183 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5184 0 obj -<< -/Subtype /Link -/A 5183 0 R -/Type /Annot -/Rect [93.6 81.566 115.2 92.879] -/Border [0 0 0] ->> -endobj -5185 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5186 0 obj -<< -/Subtype /Link -/A 5185 0 R -/Type /Annot -/Rect [115.2 81.566 120.6 92.879] -/Border [0 0 0] ->> -endobj -5187 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5188 0 obj -<< -/Subtype /Link -/A 5187 0 R -/Type /Annot -/Rect [120.6 81.566 174.6 92.879] -/Border [0 0 0] ->> -endobj -5189 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5190 0 obj -<< -/Subtype /Link -/A 5189 0 R -/Type /Annot -/Rect [174.6 81.566 180 92.879] -/Border [0 0 0] ->> -endobj -5191 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5192 0 obj -<< -/Subtype /Link -/A 5191 0 R -/Type /Annot -/Rect [180 81.566 185.4 92.879] -/Border [0 0 0] ->> -endobj -5193 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5194 0 obj -<< -/Subtype /Link -/A 5193 0 R -/Type /Annot -/Rect [185.4 81.566 201.6 92.879] -/Border [0 0 0] ->> -endobj -5195 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5196 0 obj -<< -/Subtype /Link -/A 5195 0 R -/Type /Annot -/Rect [201.6 81.566 207 92.879] -/Border [0 0 0] ->> -endobj -5197 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5198 0 obj -<< -/Subtype /Link -/A 5197 0 R -/Type /Annot -/Rect [207 81.566 212.4 92.879] -/Border [0 0 0] ->> -endobj -5199 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5200 0 obj -<< -/Subtype /Link -/A 5199 0 R -/Type /Annot -/Rect [212.4 81.566 217.8 92.879] -/Border [0 0 0] ->> -endobj -5201 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5202 0 obj -<< -/Subtype /Link -/A 5201 0 R -/Type /Annot -/Rect [217.8 81.566 223.2 92.879] -/Border [0 0 0] ->> -endobj -5203 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5204 0 obj -<< -/Subtype /Link -/A 5203 0 R -/Type /Annot -/Rect [223.2 81.566 228.6 92.879] -/Border [0 0 0] ->> -endobj -4615 0 obj -<< -/Type /Page -/Parent 1 0 R -/MediaBox [0 0 612 792] -/Contents 4613 0 R -/Resources 4614 0 R -/Annots [4618 0 R 4620 0 R 4622 0 R 4624 0 R 4626 0 R 4628 0 R 4630 0 R 4632 0 R 4634 0 R 4636 0 R 4638 0 R 4640 0 R 4642 0 R 4644 0 R 4646 0 R 4648 0 R 4650 0 R 4652 0 R 4654 0 R 4656 0 R 4658 0 R 4660 0 R 4662 0 R 4664 0 R 4666 0 R 4668 0 R 4670 0 R 4672 0 R 4674 0 R 4676 0 R 4678 0 R 4680 0 R 4682 0 R 4684 0 R 4686 0 R 4688 0 R 4690 0 R 4692 0 R 4694 0 R 4696 0 R 4698 0 R 4700 0 R 4702 0 R 4704 0 R 4706 0 R 4708 0 R 4710 0 R 4712 0 R 4714 0 R 4716 0 R 4718 0 R 4720 0 R 4722 0 R 4724 0 R 4726 0 R 4728 0 R 4730 0 R 4732 0 R 4734 0 R 4736 0 R 4738 0 R 4740 0 R 4742 0 R 4744 0 R 4746 0 R 4748 0 R 4750 0 R 4752 0 R 4754 0 R 4756 0 R 4758 0 R 4760 0 R 4762 0 R 4764 0 R 4766 0 R 4768 0 R 4770 0 R 4772 0 R 4774 0 R 4776 0 R 4778 0 R 4780 0 R 4782 0 R 4784 0 R 4786 0 R 4788 0 R 4790 0 R 4792 0 R 4794 0 R 4796 0 R 4798 0 R 4800 0 R 4802 0 R 4804 0 R 4806 0 R 4808 0 R 4810 0 R 4812 0 R 4814 0 R 4816 0 R 4818 0 R 4820 0 R 4822 0 R 4824 0 R 4826 0 R 4828 0 R 4830 0 R 4832 0 R 4834 0 R 4836 0 R 4838 0 R 4840 0 R 4842 0 R 4844 0 R 4846 0 R 4848 0 R 4850 0 R 4852 0 R 4854 0 R 4856 0 R 4858 0 R 4860 0 R 4862 0 R 4864 0 R 4866 0 R 4868 0 R 4870 0 R 4872 0 R 4874 0 R 4876 0 R 4878 0 R 4880 0 R 4882 0 R 4884 0 R 4886 0 R 4888 0 R 4890 0 R 4892 0 R 4894 0 R 4896 0 R 4898 0 R 4900 0 R 4902 0 R 4904 0 R 4906 0 R 4908 0 R 4910 0 R 4912 0 R 4914 0 R 4916 0 R 4918 0 R 4920 0 R 4922 0 R 4924 0 R 4926 0 R 4928 0 R 4930 0 R 4932 0 R 4934 0 R 4936 0 R 4938 0 R 4940 0 R 4942 0 R 4944 0 R 4946 0 R 4948 0 R 4950 0 R 4952 0 R 4954 0 R 4956 0 R 4958 0 R 4960 0 R 4962 0 R 4964 0 R 4966 0 R 4968 0 R 4970 0 R 4972 0 R 4974 0 R 4976 0 R 4978 0 R 4980 0 R 4982 0 R 4984 0 R 4986 0 R 4988 0 R 4990 0 R 4992 0 R 4994 0 R 4996 0 R 4998 0 R 5000 0 R 5002 0 R 5004 0 R 5006 0 R 5008 0 R 5010 0 R 5012 0 R 5014 0 R 5016 0 R 5018 0 R 5020 0 R 5022 0 R 5024 0 R 5026 0 R 5028 0 R 5030 0 R 5032 0 R 5034 0 R 5036 0 R 5038 0 R 5040 0 R 5042 0 R 5044 0 R 5046 0 R 5048 0 R 5050 0 R 5052 0 R 5054 0 R 5056 0 R 5058 0 R 5060 0 R 5062 0 R 5064 0 R 5066 0 R 5068 0 R 5070 0 R 5072 0 R 5074 0 R 5076 0 R 5078 0 R 5080 0 R 5082 0 R 5084 0 R 5086 0 R 5088 0 R 5090 0 R 5092 0 R 5094 0 R 5096 0 R 5098 0 R 5100 0 R 5102 0 R 5104 0 R 5106 0 R 5108 0 R 5110 0 R 5112 0 R 5114 0 R 5116 0 R 5118 0 R 5120 0 R 5122 0 R 5124 0 R 5126 0 R 5128 0 R 5130 0 R 5132 0 R 5134 0 R 5136 0 R 5138 0 R 5140 0 R 5142 0 R 5144 0 R 5146 0 R 5148 0 R 5150 0 R 5152 0 R 5154 0 R 5156 0 R 5158 0 R 5160 0 R 5162 0 R 5164 0 R 5166 0 R 5168 0 R 5170 0 R 5172 0 R 5174 0 R 5176 0 R 5178 0 R 5180 0 R 5182 0 R 5184 0 R 5186 0 R 5188 0 R 5190 0 R 5192 0 R 5194 0 R 5196 0 R 5198 0 R 5200 0 R 5202 0 R 5204 0 R] ->> -endobj -4614 0 obj -<< -/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] -/Font << -/F4 16 0 R -/F3 9 0 R -/F6 44 0 R -/F5 29 0 R ->> ->> -endobj -4613 0 obj -<< -/Length 3409 -/Filter /FlateDecode ->> -stream -x]ˎWd,6EçD,ח*=Oے*V%wO[vp??//_H8F[:HO:}s81yv}OP^_ʽgj%{]9t|"8}GtS4OdݘI?+A&~z^1tΩ-=u奔/ 9s:*RxN׈EΛt%'Y:W_kcs d_Ǘ^RkV}@ ;>瓜\OIL2 %g `:O觏dP}?aw{VZ~3).#@`n!vl -U"قsՂVNI^!|d=4;\֑aAzڸEw ,靭악$/uǸgd味չL.]uVLx0uo/0Iec'MlQ zc+=ѻunmSϟ+YǒٗhcS4cy%K;Dzٺ,%č ^u~ՑygE_nM<)2gs@?gInLU>=7cz%s̛E-yl;i#tW hWC\I],j\qHN)T&>z.JrͻVZLfk2"M= -@Ʃc[+!k&kqy`l^z渓/Ҁ)W)F!!@St2@P"~r ,y{ 8 -+'bȽ[q;؈ b%?o- aO~Հ=o޹letHh⇢:uG+Jr> slpwcƔҡfwd_sΈԊiʳrƲ/O!tUDM"]x6 ,g3< }M';xfĻ%AR3Re2*]a\j){/_o8^D=liXi!Ɨb1ENhײD(PyG:f"!l+v%5GpänC>U+d\.utiFݢ X|gd!k %[ZlKť QN+3:nh˱>/6g inct> -WGꋖd[AVic0}^}~AA27kp8%X,].Z7V'f 3Q[}Zh7N FOKےRz;"00ϵ#rp0h`J2{AHx5W}r1<F# >,ZCbRsM*ܫ>.H1[%ػMae(sTfmy֘j PZQJS.y)$_{5$_eL -.s{Zq._,*o|h9.W΍=ڦ4QeU!2O~jDHc̊-d=l ;d)E'5lCǃϦ%ҕ4Prͤcވ|!;AdfKX(ylC/h 9SAB53 ¡ЋC7F~3,ecX -ҏ7V; ut ][5[Y# T6劉 `hi'K=D yOE JPJxNLbMikڠ"zZyI c|VLw O~fŀ:bƅh׌R#3b+d6Pyͳ6}<9fJ@I/cD̔}6zƣ/țp7U6UBh;II& ˢWt -}O8X/%V( i0!5zABj 6!`WBfu Rizz=| c1hN"svKL7Ot+>NJaT-WA \@x}j0 2hxYfV24st:d4pR'\(ń~V -ArtbL#! _P:³BT7s+%=O?@pGe!7o}Dxdt?"2Dosa(J@hBk0E %t2% ŗ~"Er<}OQRFAv#M,iR{ ڃ 4`=߃ k{~Cv,r>Av{=g{~k])e*&?ݱ^x\_N),BCnB;q?'3$i %h|IwttnM1#|XE~~KV~\@-Ÿd-*:³d?5E0}sC#&79;Jnh367 X,4V˗F]Y%4-*{ק Q'mw>&'c"^FZS33 -endstream -endobj -5208 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5209 0 obj -<< -/Subtype /Link -/A 5208 0 R -/Type /Annot -/Rect [72 697.5 294.856445 710] -/Border [0 0 0] ->> -endobj -5210 0 obj -<< -/Type /XObject -/Subtype /Image -/BitsPerComponent 8 -/Width 400 -/Height 533 -/ColorSpace /DeviceRGB -/Filter /DCTDecode -/Length 61494 ->> -stream -JFIFHH AppleMark - XICC_PROFILE HLinomntrRGB XYZ  1acspMSFTIEC sRGB-HP cprtP3desclwtptbkptrXYZgXYZ,bXYZ@dmndTpdmddvuedLview$lumimeas $tech0 rTRC< gTRC< bTRC< textCopyright (c) 1998 Hewlett-Packard CompanydescsRGB IEC61966-2.1sRGB IEC61966-2.1XYZ QXYZ XYZ o8XYZ bXYZ $descIEC http://www.iec.chIEC http://www.iec.chdesc.IEC 61966-2.1 Default RGB colour space - sRGB.IEC 61966-2.1 Default RGB colour space - sRGBdesc,Reference Viewing Condition in IEC61966-2.1,Reference Viewing Condition in IEC61966-2.1view_. \XYZ L VPWmeassig CRT curv -#(-27;@EJOTY^chmrw| %+28>ELRY`gnu| &/8AKT]gqz !-8COZfr~ -;HUcq~ +:IXgw'7HYj{+=Oat 2FZn  % : O d y - -' -= -T -j - - - - - - " 9 Q i  * C \ u & @ Z t .Id %A^z &Ca~1Om&Ed#Cc'Ij4Vx&IlAe@e Ek*Qw;c*R{Gp@j>i  A l !!H!u!!!"'"U"""# -#8#f###$$M$|$$% %8%h%%%&'&W&&&''I'z''( (?(q(())8)k))**5*h**++6+i++,,9,n,,- -A-v--..L.../$/Z///050l0011J1112*2c223 3F3334+4e4455M555676r667$7`7788P8899B999:6:t::;-;k;;<' >`>>?!?a??@#@d@@A)AjAAB0BrBBC:C}CDDGDDEEUEEF"FgFFG5G{GHHKHHIIcIIJ7J}JK KSKKL*LrLMMJMMN%NnNOOIOOP'PqPQQPQQR1R|RSS_SSTBTTU(UuUVV\VVWDWWX/X}XYYiYZZVZZ[E[[\5\\]']x]^^l^__a_``W``aOaabIbbcCccd@dde=eef=ffg=ggh?hhiCiijHjjkOkklWlmm`mnnknooxop+ppq:qqrKrss]sttptu(uuv>vvwVwxxnxy*yyzFz{{c{|!||}A}~~b~#G -k͂0WGrׇ;iΉ3dʋ0cʍ1fΏ6n֑?zM _ɖ4 -uL$h՛BdҞ@iءG&vVǥ8nRĩ7u\ЭD-u`ֲK³8%yhYѹJº;.! -zpg_XQKFAǿ=ȼ:ɹ8ʷ6˶5̵5͵6ζ7ϸ9к<Ѿ?DINU\dlvۀ܊ݖޢ)߯6DScs 2F[p(@Xr4Pm8Ww)KmC  -   $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222"O !1A"Qaq2#BR$3brCSs%5Dc46Ed1!1A"Qa2q#Bb ?b<7WP !LP1?JJJv)(RP14Jn))]KI@ ]Kh4򍴣3L''4Wb IN%%u-u&+qkQLTwmm8>kNӍVa7 PcDP#jh|\[%$bWR""bؠBbLWbPq]v+@ !&)1@ -RjJv+Lc+ؤ HiؤRP18PqINu6m%: JJu%7ƝLPiTw4dҞ(ɤv(v)(1]ZPkخ)Q͸>ÚeMFclyW'k_.LDAq|t86 qsNI`cڝPI+TE^ydbU~=Gzѡ&80AW1{_U 'Pn[~ϑPXdJ$W![ Gڦfo|tWp;A%MRm29{cњ"`-*(G=uM5H 2*:MZtئ!)qKPWbPq]v+@ 4P &)E-Ju&(RbLR?))RP1RbSIn+Ԙ*\9>ԘWSImu;ؠ )q]jJ@9ڬI˴ c#>p:~4cl QBЈ QA;{r*0HBpW*FGZ' ̇O-Es&1xAugwt|u PWo99-Jŋ*yyKoYq5+cDmVko^;z`h|~KLRÍ,{71#VuI콪iVaRII F h-+o#dp^O֊|j&KXC$HE>w9S)k]/Q 3ӑXN{ruCu6]|42JPd?ڪC(cE e,:Vh5t{Sd7zgJȔ@VMOk2eĠcQFlrO5YuUfF -߄~6fO_s_ң[QͅOpZ,0_I+WuIjLcAU6nkD%*UE6 -\WbDLRؠ5اbWbP"ҝD]ӁN$66))S&)LS(>RS]f+ԘJ7اb E\Y0hԘؙڢ<.+v)1@ LS7"T+;ckg)I3)$E5弊vӥ*:pqJ$=:⁥cUpBҋ[rT9$mxdҍQ|?3u8=1ҨqZ)f} %힚map -*{/ךe:W% |mi;[#+n|FpO\c"'vW=`2>JY1S7 > EG3H #7/FeS ,vRqht6l6oLap3랕D[ׄ]$aA.PB*đ?䞕LJ&fBC3n5ח -'ئ"#'댞{OӢq=WW9>qNJvg}Q O'_ [Z@ 'N<Еd]I-7,I3p#"{vmH($}z+gN5,jNk>OiVb&\;(Q3ztZLrNXۻJ}̲LWb]LWbBb7.(߇X}M; -I>F^D&)ئ!;Wb]v)(;ؠcqIu&(bTJT:Baj,dRLb7اbLRb]@ &)خ$Q͖U#1,ilߙx` >N0ps֟"+v=꜉WܷJv0BoOOjbR4 -2s׷ZumѣV&}8C_J s"I˽uǵtncKG)Ֆ9-6L\"_ Bnlg ciU$hlFv&w)SAx뚳]CCةd1- }p:dPDŧnXA,TrЎr=zTYtMˡ،0g,s.giXV(8ܤ>>Z`v& x'82*Ċr>d&9w=qO&)RbLSRbLP1]v+@bBcMDG -I<94BsM< `b!;ؠbWbLSIn+Nv( -Yv+@b?Nnki\DEy$sRYH2^=WI-'Âcz~{{I4'kJĽisi.!IK9+uZ=1/Yzn=g5_`U%Ν"% *ݞ9TfrJ>;|3 H(cj0$j|^gWW~H蓼ؠO9/`Ef$|>쫱i%Sy;91 ACߑ9Zoj7rB $ X<#㎼J:ۈ]0{7 L{j!h -*Ö dǵK4(.t*jb\ (v s3H9jxp/$(IPQp0$9 TOMGQ77(@MK}Xr[=1+m͢0$@,n;Rx$acev(aZq6v>RȘ{FjN;粁E᳢116)]Xrur1ZhķlHay:dV7ƣ&fߺ),dF!gfl\(q)d 0EWš#S1+lO~1]{KZI&eN·rz,($9B|?>>J_6@'vG[ sQFQ#ϗve9ތ%8T*~OӭQ6^1IOM" fvZ2X=1]P#طA늅, % -Vu>S= -,yS d;.Q(GŇsԆSUWS2d@*x!1]C壊Bŋi Oϵ[qo 9 -Śi^ٍwZ(#@R(\6?1R,^X]]C\rSHsS-hPqޝXOuO|b1aj2{eyNK+R22bp~C$vrD[]# CIJʕ>6#=핚|I>d$PsFsۥS^Hbl߆>3ßj5< :ʱDW*O^Xp{^{`b opd+q8W)[-Qn!;Wǵ]5IEj1Mwt9Cdc|J7Hr7S^zj*PLHdk-㏮>Ž.}9Yf dOߨV~ Yl5x䍏 -?zfgI%nE,ҁĒA,8<QkH810~B/%+?/G @A -s뚧I,TO9 I=InүoLp VeOJNm[eF1Y` 'S$rLBĥd+v8v#pp}s+܇@~~y" -uP b{ի[ȠxI0YAu)ynN88,8=j̍!lor##qI$JG-ͼx2YA>;ZIQ\XƱxp!;} {fJ˶+V'cYq QzZx\32 -9F?jqis,$CvLGkgxx4d#h'zvIq,i b,U<߮Oqrj.U.+ - |I6odpA=1_Z+Oouxs; d1o,h08ȴբ*#[HeKVL+'cO4&nkhUV7o= }yVQ"62Xzr -S"%wGܔAi=vu"5%Ϡrok8uiu,tIKso;~)!e9B=ANxvZ7u,4+;U'T-n}nKS^]o+r;IBfXᶸKF$!?<^:mfܤ/ O sI/YjIÈ08h<v*K:3=>U|3s,|Z4pU\ȨY].oӗC1Z+{y3p7!<|ގDϊ%i&D`@/9ӊka c0=2i[̏᳃f'j =1RCvW2P|zսhIJ=pVH^!(UJyیsu Fi%PpQ Z#%M$˰ q=ƭ>^i…q -ObbF6)_DGLhL1 ~\FDI P]r1A'1ցO=BG\F=~~nS{i#C,H6v($NG{U DKuKne2+fb~^h YB 2pq׃t湽^)ZFjQ-t{9S[;umxL]: t'qa|E[>!28)Y!`@Qߎ繇PNi$#C<{2 R>zڃՖށolULLHIc֏\KnH>V$ -crs45t[[<m HPA*ǂ -ncdfI 7ӯJRբ,!Y`*A>YT@K F$OMmb݆ypy֯}nQ)]CPM mBs#+?E8()@ҝ°NJf\Glة6m5qPG$겳$|e\vwMKmao3\"eqjIU6;nٶ%d`I`8ֲu٧E[$`;32g#ڛ ysq]sp4kH c/%.8F#8j>Y)zr5?똄r -\c݂FrOhEʛu} =sZUE$FI$|30p9P3\X2?mG\ z{{Y] -2;;֖VDټUX#rX53@dh+˰$6⢼EfV]ZEăF߄p:2\~>L$ԓ5ޛ\I\(,x8NN3UuMVy}̗ IcBÌwsӃj -O:Dipʒf9r+]Z8Hp )Q(eėK5̲\I$J&8D -C!iCC:B|?{_*/&. @(ngU%xݐ! J~oОDFǍR?v8\Uƶ?>nwc!WڠJ*Ԝ@v\KjbFpO VИx7;H35 {[xg8ul^|(MF[zU()͕ltPd -xq<9<ֺgnc)Ԉr -*sqשJ%}KCwI09Pch.6PAq"%I'W? e4=%ӖQs6kqm\[,?2PrRPWnI6rxE4jR+u<# (zz.,My2,-NI"6>FA #tælfy<dbBONrKdn>ܞ+6i&+T R 7aFH@䓞;py7Qݵۉvm#yz) e< -8}, qZʹ le  (S͎_*c(OTPXv;zskD;{ !#trGrGKxCH-(l0rA=8K^>&(1qk< +*X=\.sZlv m80Y@?PI', )bRs.y$ryﶠ%MM )&Kg7垕Ĵ{6赪x#Զ5׃d:&`/μ]\n, YB ˜WVLc~J hL".FѤ];DkK3n:4N>jz;IGaY56Aഷf[#ns9^EolQ|opTB.'I-#x8ٞ"^_zQt s8EeNy%6N{3 c 'tZvN^$]U&N=ϵoǚQm&,TOJyeB"X;NNY5b|zt:y{6aν3mv)W da%෺ı̧$+?: V )F>w,rF*rrv,xa#8n'/cӁE?ª,7Cz8惴SM&ۈh =*!cuG1cU=6])^py[ S]*)G"bBn9{WVnIlnc?Lщr= w3}V6QrOP W5ު^-# Ӝj[տ Hϔ2N2Gn7,VZ*' -0I=1gK$T}ƛ*P:>ۆzO /D:dĺ(5'=3Я ~jLH'msŜerq87:LKfc>1 ;2]>a˥%2Hwy cU/X&8˰,qӒ+LF~)X7MnP{d0 X!ASAӊ ,H7_K9;MrYxnd]6VL$t}',ogʺKe&4lLkOeO^(jr[D%ֻ#MnI6k,,wI#e%OL~XDVWz)HeހxayG *0GߥBxkdLjsjQXncF4`k"')F\_ᧈi\0" ѣ3ɐ2à=~64ShCo,)FanM]A -'`mU]rzsaG-QEQλD 0us3r7[!m' &˻ ScPm5Gy;vPNH #z,I 7nLOڛdĥ`3ƓNo˭|5Rp *Wཷ&Ig0|N9Ռncy^)Z(+Nё8N[ ȸX -Xrz^֩n -ɨ˧ot t]HX<#..-tƾQ*8㓃JQ}ݲ_c> ͽvlHo8\@eOkqXŒ̻T:`Ѭt].-*h q8<ϨIo5Λ"A K;#:>XdQ?'tD"8%ڼ?>{)P7d[GeA nϦZu`5$_7QHJ6<1Dp@$L d椔ޖREŸz1fFM̌'ϧn, [`HFv6\`t $r3@%!YAb0NO'5&ʲ71 s}ߔ\HQ L#Zӯ,Rew.,#LF[M%Y O,Ǒt'9V伺6u46ƀ"ߞl$# 68I6#EnI..yovF<\t'/Yo/y+qQ[KlP|HUNA\cAYil+F8L֩풔} e$B9%+9pYʡ$<0H{`9*ʟKM*JH# 9l=zԚlsK REl.rzZ`GRErjI,=L]p3Hϭ%f/PX}==j{$#o)~-\|UJk`H]Qy$Mg{AG]#|`>C=z;i&!HӶ(n‘]4o81uesʶrs(Io6uyaW< -NM-B^k;x q$Dži+f)3 Pӂ{v247UI.;nR^xJtwgy2rc? -ޤFH`^{sVm=-]2`W~\fY E cX\H@Fx.v' +LBj0y+%<5tT !yÐ}֯ifXusᜳnzv8*)]B431XvO|?%X] zbh%K dGAxU5g9UR c޿~)L+7sJm5qKۃPSK|q+H'~v FpM c;᱀ǐ:j<t8rMhtKTtaP22qlOtot -)򇢜y7.ַKlƬa ltRޜW aAV6-Q\|c&ӬnUF 0I!a:YXc #:-Ȉc$d'9ǶߥmKO;[G,}61 w֡Nn<c`ĠxMڔSC`wtH\Y$2!2FU=H-iDž5PL[eNs;9$މZ6Bڃ$Q:0ܕ o/a۵ 6 x3W֢O["6',snASBx& (Rɽx$qډ׃k.Ym[,ÑЌڢrܝgTE,2ycq^/|-uFR[\cO.['IWv8J=VTĖ1[ +aF+:s:Ӵ_[%v$ T^ >_,[o"Im'X110B4RKRFPȻco2 $?Joh,!$; uw.cupPF85i )^~'JjĐ>!$随MfR"7r%A$yC-(#XmEFqFFv L WXH3YK>3z{R#)98Uv,6mNpzSqmc+&X )xsL*ܹNjnL0x`g}pa&OҢfeO=${cҨwkxbcMaR72Ndyzs|F+!>5xc 0 TK;]lX)d I\ႎI5Kigf"xGq.H< J|{j\AO%97WVfkuŔLvhP-'=/w4LGS#a8 㩬h޽ċ7Lmt4x^kHbHwAW;OslTf]k bh` [ Nsׁ5;1 w# ޛ[II2ns!†{v -b̓t=Xd|(ApԂs#:Tڻx7*vC5àePHR@ϦG^mB1lX|A -tl ǧJ_\-i~fXUVbI"p;sɡBYrm4>]xP#uD{ U)XĨ0ܝLMKWeS;p<~8'~^H(*䒛uH,7Һ3(F=:E,D.6q -U<-F$hJ!VQ' ܓOzv4%E*eDA-5;+yVXVKџo 9AVvMSOHw̏N*` sִw:Fngl3;}H>(^dװܩZlAUʃsZ}KNCmFhQ啡*p2[,x9Vrf..*VLaAEa:i%ҕTXC+dsr3LTr=Ł3x',?Ìa}hw+w_ -Z;(#D,0O Ӧ~kOûu e߹E ڢ2 |gў@$ce }jΞq*$@:Pe[trWGd$dKXG2 sz{sBnW%2KܮNI=&NK1bOkcntFBD]tVYA9꭬^Fm0Y1sӱVVKne&S6I<*6Tk֓;PHURHPϷw %[ -X0pѴ Hq3Gi+Hyzg'QӢbi_f7];{:ǖgԸl8[#omD.-RD #!LCRgE0 ex^8?΢:rabC!Q ۃWʓG+픰 +wQǿ^՗}ͪjvlD4K$&#c<{ hgiL͈9 p=%i,WNa987CW%XDQޣB ]8 )8'icwH5@JI+EOym2+#xsDZwTgisLZΘkhc]qb={|Pu V&9Q185T%.E>%MV\E=i]K@A9~@$DX>#[>qdi&e juo69[χxfǝV@XДtSҴ&tirŀ7-[!@-$q֩jsT[f,9'QfC#C!E, ڄ^-Q\4iQб -''ﶪˍ(T,r| vy-ޢlw/m8O&<9s۵h #)L7L?>Ms֗K$mf`PRdp*{߈a&(v1 PO烟JK'/@2~}[e+3F5Z4+%y]و0sZBn.ުXB ͤix#8Ïz*0@ B*%vfBT8\ǐ*|UKfp -sy7* z^p1QǧWC涊.{su4 Aqk4x|IROo+GӵYe1A87)Lg}ϧaɛsM!粃zC8yI)VVw乸 QrZX;BW@aY=6Sn.O #{6BbJ "v3}:U-:eJڰTmݒj;VB"}s/<{oOI/53"m`D(f\n}w>Rs5LhtqD7m-mN왧3qp@QUtƒ/c[VgBp(όu ݡHYe4[A09 W9y5WR&mcTfv,p@{]?7:k$$Vmq5V74[kon#i~RcRљcsN'<߻0i68[B`G.ď+0A''$~+q *)fKA# (dqu"dmb3[i ̨:3\q rx4_V}Gp'~ʃf^Ge_\ռ1}mHq +&Ol1L6z-#.3o`cJ1$a/ ze[rxC9q7֗^:Qxn| 0FG'cVdȧcRM%꼶EeDٵFOԜc}[]NKK[e@1]|s0y"am}wӶ+r(nhڞw%;\If J88UJ87)}iI5 ucB]Pv;I$ҧ_sB0Q6ߚWPfNpL{[K}T4ͥ$Hs ܏J&T1bӜ!>jVbl&Ko b1ˎ(y]0 - q,N9kV6:ޜq N3sa)4 vR0V1 ߙԜ.Oѱiw:ZlhaXCW'c >"HH#+K@g{g4Y_ cq88Jw"]Adϰ\"ePAT@98ŪJwPK[7X#?*qӾ*:|=R,RBn08zezKh&cƥ%s)>UwkWgN0Xʉ0 UL絡Fek8[H@,T2/ -571KJQ190iwźe?.‘G~5,팩i<:Gn0Nֿ5~ cr(+Ϩ^v$[yaWF:~UCO:qs")e:}]~rNp88Ž19$VlnM ʖZ$_|uc랕dMv%Ȏ![$y'kqڲ]&"ͮeLʐ=S ڱ2H6pc#Fy>>QHœ[&Y)ZDl,sNO#y{x;F!pbX.VyF#$(U -1^Fy$/D3sMinfi'NTdX=SViu$U!K6RU*Qn6K]x$Ni ;x;hWUpLl8Hϩ4Jo.2r1`Hh^zl.2Ȳx Œ: ǟj)6R,d"}]0hGw 08qbCؕ\gr9_ .5EeXͶ(FXԮ2zZ Բi[4$|@[qfqUC[%+zFY)G N1(+K%ɿK@ERBqyo#]F([动A ,9wF=΅5"6]P0$ -=x=55LMhnSEnd/!;N1Ӯ #II"T ]Nb{o͕߄NɐJpA=_]\jz kz+0$}]G 7r_x|]u-#ۥkk)ZDO .?5ٞLy&xw2>%#u"VgQ;@ ==l#l,.R'o[˛rm5Hc8l|o<˾A!F >Gz[Mg5YG$r1 A9-Ul"ha#Dd *Wp;O8/tdM!#JXq#i>Ֆ0j%Sit<ZJ]IJ" IG^: -XŷaKv¾@ Qs5uƅ|k$BYE, 85-ntUTx;lzזhk -1}~-d(Ȣ -#%OMNM|iJ*@R1@Q-I+px9'E};Bi/s,%SktmEǸ9ּ-~ .#񢻄m;vr=kqI sUXz`ڼOM7L߫"4,F̑(/ 1ϧzvJ^>6>q-s$qVtm揶I-a3[iSsӭm4ܶEf~,ݴ9d&B@`*u5%ۛÊY2G?nեuy%J= (r63Qxɻ_ÿJ|;7Lpq؏cVK%r$&_Oqg=9I_̓j;;{[,In{vy]"94-D#%|9 ṅZS\vi%x#?΢$-v#,r@YG8k;vuugЙt)⑉VQgӱ#1Ri_LPѺ:xRID%˧|r*Nw }-V+*Où䷿Snoz_k4r-@;9{q-?-7FS0p瑎br-'٧ydu@G>]Fb[Ų5` .s'ܚT ٓOF0!xyo0R11.5[l-ʹ7LpSm?^eup;rr:0yf힥.,Tilo1(q^y3׺u $c&K;tھێvyn4ݖtqN>7i5'fK7=όՃ0qY=?;ey;(3.C6cN=x:[ib QHH5l{~ -܊ST$m_>_BF:w0TwE2׌>%wϵm^k[[bebr,KfEuՙ]an -N7 @5,2¶ _f ԒowM4I=ܖi<[6䡣̵{?6IdL1;:`uۤXn4r8 ugo}erE$w)pHxB:bQD qu# -ѕ8=}TWŶkKHċlAz}Iz 3[xDd"ےB=kb?hCFl.Wppͻ$FqO5sSצW7&yKIqѾp*xc4r-5KFYxBXz-։/M_jI$Hqz9=*kZ}ؿbr2s@5 ocu0]a3Ўzml| N-dG`K/AǠ8 n.B'W;JxdGKi I>6@x=Iϰ*mL¡]CO^ ws_bK{i?{*18 XZ*ç\B e5)Im0Y+`#ӊtܬƥ)P+Hޙ* -fi* hkN-坑$cxB/&hH\@'5T5r}ڭvG"8ܻqzQ? r,mbz8cYkxond"НpIϧֲBeBXw0Iު9=0ژ[,PyOy4/PW[=mUoGTT[ty$a* n`;n;wuT)i"ޯp)%vaVAEl|K/R1Q~h=>GS(*Eapt鶶Ho08?ޥ[Gƙ%1=IJ)}pb'_P{FtυLYnv4(8B28GCϸ :+Eumۢdcw=LW\  ׏_L(VT[xw&uId^#fNH -9j5W>"Fi6zTcKxKQ0+,u=|m.dž;ǨF_,,2#SH tsisAf.QI>=bhߑ r$CYx8=ډ3D[ df )Q~?xzWOD |)ۜ#uE9Knm,&<ep88뺍 @hAy8:cT!CbW!<\ݪAIc{ -q&VtO>$a|N.5 ˛eFp3K}6H&Ukmݸ #KqjeL|&T -XSkj̩Dhm#z܈ndjEki%`S < g#he0drNZ FH!^zsߵ_OtmgΊu﹁,~cڨǮ\Giko4FYrzxE4w6 -G;?+։ѱ,Xӳ<xw^X#@ݞ@+{ ckxCĘAlx8ZUBIuE kXlm!}Dٱ)=8ܷbe’lX-:ǽX:rGڠmfՙm*+.ь(@qI~mwndOINwQ6wzc]o`]E)ZQ!@9jRC}[|T<<BN)Yܱ\qqӎ݈5>y&h%͐OӧJ|:c.% #YbQ?BsSX+lV+[ :ON~z}:74ᙉP9.18^TI)!7= % -p8Yy=CPk7g90Ѹvr}y0jkˍ5v_B|Ee`=䴽BX5"bXoP'9 qy}vD0 [D"Wc"6bOr>=9kW ᢌTQGz?I]EH$7Uo`I 420..#]r#=8޽*\.)%R8NI@>M"k%wǔnWoV;X˦E3Yv1秡WǰO V]?\ -$N4%of>++hL i lwqʎhɪi]˰A6sܞQ~$U-+0VQ׌s2G(}vq>,H.s/sJc~K2.衊&!T #<\)-DK"t^!B.X܋8ⷵ$,.s'$dxsnX X FxH=^AvXob,#yِPr:Jfck&u3qmn-̐YGR:d9gH>4٬˴(ÌKEgO -d$M P `2vt/<jT´g,,M)X2'3Nヒ1֩a5ӱHu12 OiXDRkFg@u5ֵj\9ڠ``3n*W",1AEŒ7Z*K~ոs9捶s3ž xfW {V+RDqpZ&\֔Nm76#l WѬMNi$˧ -GSҁE"ʜjk(gmؙ"ڤ;՜TP>ǩ6qO-rcq< yr_l)/bˌV._g e!;N[ Ӓ'}3CBQGhrj9mavÀX1VR}nxb.((23^:&EvJ9=rH'?fI{yU7KHI -zF jԭU}%^ VE7qB~j7iK|N2F2G棰{u{O6:i.O wW@*8}e|wx1Dd20rNr?M2VS[jF3OO1OYٺ]'wxkڭƫ-ǁ#adᶎ9;o]~=E,1`H M]Šo ЏŲin v$o'qT~/Gՠ 7 G /n8Ӛݶͥ68 8" bK^YfH -Oة3܏o~(ǰ졥5Pi6"oQw|Jߴ&idhYw<`=隍q4 ECQzdu CI 5#d_2bY8)'RR^3ܲqnD|HnvӕmAo @^IA:M5"B81Vj-n 7++@z{Ed c*:{<(8g?AMQޣj#X[11 ^KE+ʠBp'On:i{}VċnTKr\Z;DWY$4 nyZ{J!"}۠0rxԼ [}v\}jPw[{-@Oy;Zj7$ca|?NO﷯#5 -,f|9X -VL 1x846E Ospͻ=}uԗ~'31={}UivW 98mh2ɏz8vUhEm?MC5gk dȧ vatC2@9_sqVn +C#=I.+ :--\[_1lgzw{ hjxQ DE$ zjݭjnFm5ŽWRۆan֣,eJ$>txf%r!@ -їK~|hgTZ5?k[Qη)C~1oMJ#p8"s1ӵP ݉ݐU9dg|T}Ln[DB Fx1'yǯz!UrXGNVJOKYLrneQ=3[->G8'; $jom-lQ4e`C.]Nj=k1[DNpO55I[43(+4Gݸ8;vqGodVݣ|,vFqcڟa㮱o6CBAoQjρΥyeq1m1a8?JZ5\$_p vT!){ZK(#nr 1+S-qed u6rOJiK -(#u^y9=IءN2VDҭ0_i > BF6y7zQ !tTnoE+;PUG#ʒp9g](1[ RGX˶79oRT%Z %* I%GLͯˉ%Cw==*YʊIOaXi7,*O.Rd]4eJ6+G8[Z Y ԓܓv4WViL҂Asaӭ%nhSdW I_1SQ|[JVQt7rN:p=+a:\,Q\‡ŹC&ذ9 'L4\KLhc[$?J9Ssshpy‘?Q@ vG70[chRyykY]Gu> .FHP3GNƛRm|EZFf&23 0~G@ +ep&wcuu!Mpxs.w134QTE' -r~MUYj^mmi%2FAcwѻBDR -nr[ F<~- -^f>^rI<_i4{[:Y|efC”Ǩ=NhI!7HawNֱ\["0Q]} OO œVAkGbUKpMQLqV b>Ra'IVz#<=y3ac?X -?[ | )OM-τBn#,3j3|$ pp}=JQƈ~bKdT2Ld+ z]-@ڱ#4B{ |XszK<3v6>g->-,ծ)8Nx>RH,)&sz=*(5-:)3YGpV{)7^!HUm~WȨF+1zϩ=sH0 -8ւ yذ[G)G5ؙ8;Iݻ8zfXi?4֎Fg`9?J)M@4GHp 9>֥]6}vIYHG^>N7FMv$:6zPKd ͅ׬4z,nO"uM:зV!٘!Uy>\p{u<ת}:<C&v$wM[UBf|Es|L,=G@.S.q24. sqYK6Dfʹc?{ϯ\5IdUyWĺ֋lu. R 4WLȮw 9$yOp k~ -Me>6v#+c=)<13^ qׁSt$~.[:z9Q_].؁HO`]B?{BY"Blj**0_H Ô.I;22͖c>i O -?/Ldmf|]c[ldE`E3;Glw *ih ӈ^ZIQ 0y3|3niEцKUTWcMJш[WS]mث<[pr;±D;gyq(هgi66qԚ|7tzo=t)$;|Z"NLxp9pȫ'Q9wO צhfgĘ{{/?k4E-NbēOOPdxr-ޠ^?4р]n5ZIKrR#[8<o!pX8@ܫ-Z/~MlxK, OްڝX]8$U^ 0vr4ݰ;QuF|7ʀ >c߅EHZMR\H?[g6bȻGiγ -#.4Aac׽R&Eb.mb8ҽ#Uz-^;"eY5.gYjkt%JHR:ԣ1^ZMfҬ€T6>=rZmh|RrPtc]+gpũMyZ?j w=۸x>+ǑQvŧZ$ˁsW[͚=JhԩF<Zĩ)'Þ)=6'q g\qĉW;3zzT1Q q:UğC :tEOm`/qP'.$QXPXv9u#H/Kx`ڣrR{5F~1J(JۃSz~SƑ_»p?|˙M&@Co@o$z@qK29DKCb`qMS$C܃ESVS6HQFpzm/ 9׍Oqs} W,IG]b -I'sɯu/³Ii"Kd=txzGlvLo֝+=gP4č\-|ǭ@iM,n #|c~0_Õ 'su>(EPXsY2?Hfm_SPX'$eҼF>"5-.Bc-y^M1ˎ1dY?+/59ehw j)Bt 3,JFd*2:hg6&ֺ+t 3Fxs Qm9b1Uc#8 V`e!2\2>V7a4Qރ+)#oEu723]-Λ }]*$e_*/NX7G惙?Q??5VeSEZk0i a&C=A+/Y?gPMn?k,Iʹ,ǷWDxmh=F@6){O,[t`pCסKuw\3$X?jх*Oͷvt0Fm,({n瑟J^ġ6Y$sYHI,e>W`F4tWr3ꇢÿM@vRitO!69w,+zTͫLQ xoÎk JIKZVeV`y=8<ӌ?ãZZ=OE76<fGˑg |t3VTҚFaZB=y/;CK"$lLgLN7HOs )5O$}:p9kYa%ΘԔ.ٖT@rqfI0Hε_[ igJ@X~$`Q ަ;iJ$1c_ˁD澱KI|y؁Lsy|_RJ?ggq/+2z亐+‘HfW?Z|6Ė<FҠl"1j/. +}EQW- =iatLq7;4Oa$-\Jp.oA|8龳d| >wfړۓk6?hU6;~Td2φlu"sE~ԍw*gAN\n?4x1+0x۶% c={SXP_Ɠ!f{U9//I|v4* GvߜcIworH==:{}kϓIR%kck֫޵23F#rSڅ^N6ѣG9|3<`7~ZcLڶ@+QFr2jޗZL\eud8t[cL4@ {U]Y6I̬:*` wrAJV ZfZ@^zp:vI7yPsJRPVv X|GDIlR S=(bs2zTZBi)I_XU\ū(TyČ}X3uoE$Z鱈 ,<;(^qAޫ]E4m=E[Ȼ]c;[׶qzCy$2f3nnsZOǗ0B -?h*uDxya^cGlץ|l1F?l)(DZ](eԛVյ7? rng/ƭcjlWjOum8]Q"i>[ǓI@}dDޟ&*0zԖZw2rDbW俸u9ǵr):k]&"c`ȼvVM 5J,~\n>L֯ho+m;ӧlDe> i̜gtUYHj)  O<|+l dK#:2D Z)cYU]=}{TUCoEc ʭA"x՞t.H'qֽ6KZ3fmHێ3C%Kq?8gF=?dyB<=: -h"WXdY1?"g$` }G1D-ȱI8߯F*"[ 9a|b*k H읦hU7 -AqIpo3w?A /_ZHMWf.4*3X~S_ao -N1Q_-dv+r1svL>f ۻ}4)K}W2Ōw?DrFuO(mgdA+^:kk18䙶p:`-2rR?Ʒ<ݨyfx}psʷ|a9LӃEZ2XãLg`},?N.bͩnQK~aٲVIDI,IHǮ*Ö!ҳ Np5[BӒ(NIP_'KE21GHUA==qP:6i$~bI9LiZ 6 OcpA0XFf4J$3ʮxg9(ݢ)&Ǻ=>*\\Ʀ@ [{߅tďI&# `rsߚk^<1\ΙEqQ5E)׎(l-sb ,C\ uw):,P$緭@?y&.ʰ?x3Gt w7H$,pN;ҚAb2rXs۵69cef@6V!=3=_0m (#,9#=qq -? TUX/9O }EV`5SH,c5Ե?ho{v1h"`sprn+?|Es5@e3>q#9t@6nI=M@zҺLq[V9fSx, ?g>wYce"c?5 w!q+`5 RC;kg&|ʃ#ӿ 27r'*ßZ=Zm22i ?9$-dⴖnD1zpl/zu[Ac| #xVWra`r=rj(|r@矾3VbW<`Kz=jKyOp\aW'OS;q1D$|C9n{9$)98 Wj4Z\yllp?ט9iWp$ ]ѻd$c5 dOS[](&('L-ZmήdOڻMZ(Og%ų2忕Y6ݠSc)-5g߯0 Y.EfS([<̜DJkIF~c\7z 5KoBgh@_t~QtYO2D.[39<U -«z}(T1ueiYq3[\ ꮭs/)ܣ1TzNzqt.SnALgsjAp\ȞWG_OLvs._P?< aY#gn #k -m$!wi"3eo9־AТbH?af8d2$w&I>J,'lSVzCh1@'HTGUk""^}gs24RK&Z*Õ=qZ|Ff;kkk -u=Zܵcь[$٥) aTln3^zMR^+s$C;3k9S?҂6f|)ն66 '\N$)DxεBH=]ڍS!\r@}3{{wg'XAl4xJ y3\~ɺKX{oMR0GGօ}>M!=?SǏjrOw$I#2 XX=j[TV?p$ޥե W,ɩ]菕cA9h 7y8M\i/vS$$tQ[_H+/DagzѬo1L*qgv-*s\CI<(u={qE%He lΉ**)98s{{5ψfPBJUϪս@ :H5y>=M+6dxH 9+㷧?k: P}>$|/$i'A&ՒppWGO'_$-(ꮇ8b=~3GrrcpT?I# Ծ =ˈE tϙC3={}\Gs"& -LVXNyU]BI#dP瞸$0q q>Sz+Ȯx8sH#Pqzڴ4q&'ls }D4?dH2;#S5H&mJݧgpNIp89\i_EvaXw$t?Nָt8\u$!"H7p]$~tdMi)#ZعU?٪I[vaNxv7zpu8_~;BDCQ9?t0[@ɧ3Y1z9𮔗 Ԋ1/}*;Aw6ؚ#vRJA둃)]jMfoo,ǭiȑh8ba(ޟ,/s[;GLK=ȫ -.v#T*`\c"6c - -S. rlz=yq5Hdv9[)P}#Bx_2Gq~{槹_{\01` t{ 檎5ݫ4& -<V 㞝yFP798#CI^2Eʗtw4v(r{TWڪK<{hrJ/_Gxbu(η?>_Yc,lc:MhI³;VSn$sMӥ"[EFI1Am.T,u UJsM/]N>juSK$~"#\HPY |K6 O:M(c*HϖX\J> cDS6. (#d7թXJiZr? =q +v j Sp>yĥ-ѢK7 O^-こ(dt{Q Vg9v|ʒv!A]Fy/gY2r@ I(¢Gd~^-r0p;`ΞE]wDBp[weq֡,ԗЍ[LH[DHx)#A85Ȟ&6n4#)A`c#Z:k9,h. ~S]%f8EdT\-3o>WO-V m[ t\ołA?JDz/9 9z3vVWs (<#Z . ggq ŗR r89P'45Su.ۏ --ˏ0`2N;n#{Tz [BFF7iu7le#i+̑ԓT|iew$N0Pc0:z446<.D B'3Um#h 'zLP !b̾Uk$ tRn6si%`qV$Nb*hڱhI I)(=P"' '2rK7XQYeKľ#%Wem3oN)P]$\ɻ=,{[X2rI=8,MAZw6qE2@w-NmB Rs{߁Ҭj)OV'&vWw7eB8'ɢ ELn|O}āVC)608Uhc>h܌`jRii|`2%: E1UJ/muac<~ 8k}f;UsR'I2oFGF1)U|6ѰFJ0Oh!Gs^o]ܭ G`@Nv(G1jFS̄֡f畫n -=FzNMGÂZ0 ÌGTOc T^nv ,KC!ʑч7H[QҤ, D"-n- 9gKbE# xc\qjo;*;dd0:Nh jwB<̾78}(־,@%o.72y6[5v)'l&KnNd䃝#hziWXe>bX`;}*IjrtR ze+8Y¹&6Rgw'lqT\dTچ-E;СȸG9KCKswjعhTx-)s`GOznZ4۱dbhH&d.&+#Oh5׈`qߧZ$߹*E=Sn1Q?"ːA]8s^Ӏ78` K 7_i.T {M`MK_Cɏ|\H$t͖e$r_C&ݬM{Q%oIl&Ǒ mF>g3ȩc`Z91}Ml\gm+VvͭgKb? -xQ2{z׿AS r. -S*>].[ff;d݀TlU r .KEU~#2vuO{'dBHxA] -&|σtTzhnV*C[|+oo/JhPK6<4XH 7|S|qCQm/Ҧ39U<9+IW֫4%[IA#?SPp51q -P1ʭ0NH9W -`!m֨MhUF$}9 =l/{Chj綅B ;qӦ$W|O?\|zފ& 4.K_QwˉM:I2ԶMw8;cҀ_u)Tb gSR3ZoؚջVK-<y?SsI Yͬ& xlem;\Oa.<;pA#wW\jSQBB 'սKo53資+n} o>%ݩ],}=%oc]йXBY򫓟/^{$趍 #gt=G@qKš2: 4lKg4{ČaG_04 5̫=AvGqR*#CPW91j>Y]@T\ ϛ[K>$G<ԠfHTl'g4B[7K,(^alO]_*_4{'>ƭikᥗG]qc8O\oey]|3zH|$NtF#jz J\Kzz,Z674x-NEۓ4q/Ju vʹ(u|FeZ\zr. <$i#}(YYPрw9ڹfX|I$GMzr SW9-.8)O|)J1Aj{֣<hD[wgSzϯϠ4 Ux\۞zEL -x8+G_[0|qn%8#?\qxJQ~rw. OcSIHrzH.<H. gr/ր(4jwF*| nrPQqq'>?h]^tx;)Yf^wE+i?Um.Ăb 8#SjDy:)F$ FB@#'75cTW=14Z$̤߃@"ԋӆƧhGɸrc 2O\tc} [x, hem>4׆ICܩVGPg#3@5?V@, sYKUO(5y-U_`cwrA -8f?S%*6Sz -]Dʞl)x e4$8A -Io7 $c8ֻȬo8pIAp#">nzgz2H8p=<O׵WZC=O:+geAX7AR_4&<,p"Isy$sWttBBUOڇK5Pp~' &&%IqN~$BOD$jO=#xkd!y#œd$ӳހS֚Ы.dZRXS 7 !@ryA> 2oL+wgD -SʒȪO$`(2g?4i=HC^% mNzM8A?@12~Nkyew -۵>GWMPAO&Bq}YV5;rFW*a*HOVvFsឍ"SUPrY;aO=1F:c - 3T06HTOi:y !_!cCj2r}G(HPI/ʁPf,N[/{ -TUgv2@TwL[1i؏i8ӜxǞLAiL8m& -@S(#;~}?KǗG+P3ҡ->2'on1--J{Pn'1}VsslF 1MXaP)GGs@3֛zҕOg"B1 SUdg4 I=2E;rۑ׭;c>Kp°Gs\ KS_*:a|bYe!s=ǵ)V'L`g t1xPz`zkT>GbiSYW9^GZkFG;bsgQ ǞZqظ*\'Rsǘu0F0 v'M92 1?LF$0ڤ&=8Ͻ"a$$X -;ɁMVCKI1o>uCEWY gN $WqNsJdDg<Ԫ0zc5jAtƅ }iNzTʼT')1s^w > -endobj -5212 0 obj -<< -/Subtype /Link -/A 5211 0 R -/Type /Annot -/Rect [72 234.192 521.84375 246.692] -/Border [0 0 0] ->> -endobj -5213 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5214 0 obj -<< -/Subtype /Link -/A 5213 0 R -/Type /Annot -/Rect [72 221.692 152.805664 234.192] -/Border [0 0 0] ->> -endobj -5207 0 obj -<< -/Type /Page -/Parent 1 0 R -/MediaBox [0 0 612 792] -/Contents 5205 0 R -/Resources 5206 0 R -/Annots [5209 0 R 5212 0 R 5214 0 R] ->> -endobj -5206 0 obj -<< -/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] -/Font << -/F3 9 0 R -/F1 3849 0 R ->> -/XObject << -/I1 5210 0 R ->> ->> -endobj -5205 0 obj -<< -/Length 507 -/Filter /FlateDecode ->> -stream -xTn0 )Hl ȡZlm ; Y>v2?}wnxnml ۟hJij4}D`RiT{}j * c'{V=G]"Ub5P*:'%_o0-W36țF$%6FBۺȺ"5"?MAv#ڶT]$ieAPz53t,r4B-jZ貎m2'?[S:fi#IOWBW) -$݇lNoiJCWgŵ6DQ -WB?ˠtpE'}ou ?hTnyǕ2J\)F޲k ڡZ?b̵<&5NfY2Pgc@q3.3W}dw643j?|XxN -endstream -endobj -5219 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5220 0 obj -<< -/Subtype /Link -/A 5219 0 R -/Type /Annot -/Rect [72 685.975 268.25 720] -/Border [0 0 0] ->> -endobj -5221 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5222 0 obj -<< -/Subtype /Link -/A 5221 0 R -/Type /Annot -/Rect [72 658.475 515.051758 670.975] -/Border [0 0 0] ->> -endobj -5223 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5224 0 obj -<< -/Subtype /Link -/A 5223 0 R -/Type /Annot -/Rect [72 645.975 533.928711 658.475] -/Border [0 0 0] ->> -endobj -5225 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5226 0 obj -<< -/Subtype /Link -/A 5225 0 R -/Type /Annot -/Rect [72 633.475 239.275391 645.975] -/Border [0 0 0] ->> -endobj -5227 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5228 0 obj -<< -/Subtype /Link -/A 5227 0 R -/Type /Annot -/Rect [72 610.905 210 623.475] -/Border [0 0 0] ->> -endobj -5229 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5230 0 obj -<< -/Subtype /Link -/A 5229 0 R -/Type /Annot -/Rect [72 582.405 428.09375 594.905] -/Border [0 0 0] ->> -endobj -5231 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5232 0 obj -<< -/Subtype /Link -/A 5231 0 R -/Type /Annot -/Rect [72 561.092 277.2 572.405] -/Border [0 0 0] ->> -endobj -5233 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5234 0 obj -<< -/Subtype /Link -/A 5233 0 R -/Type /Annot -/Rect [72 549.779 99 561.092] -/Border [0 0 0] ->> -endobj -5235 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5236 0 obj -<< -/Subtype /Link -/A 5235 0 R -/Type /Annot -/Rect [99 549.779 104.4 561.092] -/Border [0 0 0] ->> -endobj -5237 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5238 0 obj -<< -/Subtype /Link -/A 5237 0 R -/Type /Annot -/Rect [104.4 549.779 109.8 561.092] -/Border [0 0 0] ->> -endobj -5239 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5240 0 obj -<< -/Subtype /Link -/A 5239 0 R -/Type /Annot -/Rect [109.8 549.779 115.2 561.092] -/Border [0 0 0] ->> -endobj -5241 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5242 0 obj -<< -/Subtype /Link -/A 5241 0 R -/Type /Annot -/Rect [115.2 549.779 153 561.092] -/Border [0 0 0] ->> -endobj -5243 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5244 0 obj -<< -/Subtype /Link -/A 5243 0 R -/Type /Annot -/Rect [153 549.779 158.4 561.092] -/Border [0 0 0] ->> -endobj -5245 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5246 0 obj -<< -/Subtype /Link -/A 5245 0 R -/Type /Annot -/Rect [158.4 549.779 163.8 561.092] -/Border [0 0 0] ->> -endobj -5247 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5248 0 obj -<< -/Subtype /Link -/A 5247 0 R -/Type /Annot -/Rect [163.8 549.779 169.2 561.092] -/Border [0 0 0] ->> -endobj -5249 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5250 0 obj -<< -/Subtype /Link -/A 5249 0 R -/Type /Annot -/Rect [169.2 549.779 174.6 561.092] -/Border [0 0 0] ->> -endobj -5251 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5252 0 obj -<< -/Subtype /Link -/A 5251 0 R -/Type /Annot -/Rect [174.6 549.779 180 561.092] -/Border [0 0 0] ->> -endobj -5253 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5254 0 obj -<< -/Subtype /Link -/A 5253 0 R -/Type /Annot -/Rect [180 549.779 196.2 561.092] -/Border [0 0 0] ->> -endobj -5255 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5256 0 obj -<< -/Subtype /Link -/A 5255 0 R -/Type /Annot -/Rect [196.2 549.779 201.6 561.092] -/Border [0 0 0] ->> -endobj -5257 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5258 0 obj -<< -/Subtype /Link -/A 5257 0 R -/Type /Annot -/Rect [72 527.153 217.8 538.466] -/Border [0 0 0] ->> -endobj -5259 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5260 0 obj -<< -/Subtype /Link -/A 5259 0 R -/Type /Annot -/Rect [72 515.84 99 527.153] -/Border [0 0 0] ->> -endobj -5261 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5262 0 obj -<< -/Subtype /Link -/A 5261 0 R -/Type /Annot -/Rect [99 515.84 104.4 527.153] -/Border [0 0 0] ->> -endobj -5263 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5264 0 obj -<< -/Subtype /Link -/A 5263 0 R -/Type /Annot -/Rect [104.4 515.84 120.6 527.153] -/Border [0 0 0] ->> -endobj -5265 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5266 0 obj -<< -/Subtype /Link -/A 5265 0 R -/Type /Annot -/Rect [120.6 515.84 126 527.153] -/Border [0 0 0] ->> -endobj -5267 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5268 0 obj -<< -/Subtype /Link -/A 5267 0 R -/Type /Annot -/Rect [126 515.84 131.4 527.153] -/Border [0 0 0] ->> -endobj -5269 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5270 0 obj -<< -/Subtype /Link -/A 5269 0 R -/Type /Annot -/Rect [131.4 515.84 136.8 527.153] -/Border [0 0 0] ->> -endobj -5271 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5272 0 obj -<< -/Subtype /Link -/A 5271 0 R -/Type /Annot -/Rect [136.8 515.84 174.6 527.153] -/Border [0 0 0] ->> -endobj -5273 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5274 0 obj -<< -/Subtype /Link -/A 5273 0 R -/Type /Annot -/Rect [174.6 515.84 180 527.153] -/Border [0 0 0] ->> -endobj -5275 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5276 0 obj -<< -/Subtype /Link -/A 5275 0 R -/Type /Annot -/Rect [180 515.84 217.8 527.153] -/Border [0 0 0] ->> -endobj -5277 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5278 0 obj -<< -/Subtype /Link -/A 5277 0 R -/Type /Annot -/Rect [217.8 515.84 223.2 527.153] -/Border [0 0 0] ->> -endobj -5279 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5280 0 obj -<< -/Subtype /Link -/A 5279 0 R -/Type /Annot -/Rect [223.2 515.84 282.6 527.153] -/Border [0 0 0] ->> -endobj -5281 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5282 0 obj -<< -/Subtype /Link -/A 5281 0 R -/Type /Annot -/Rect [282.6 515.84 288 527.153] -/Border [0 0 0] ->> -endobj -5283 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5284 0 obj -<< -/Subtype /Link -/A 5283 0 R -/Type /Annot -/Rect [288 515.84 293.4 527.153] -/Border [0 0 0] ->> -endobj -5285 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5286 0 obj -<< -/Subtype /Link -/A 5285 0 R -/Type /Annot -/Rect [72 493.214 180 504.527] -/Border [0 0 0] ->> -endobj -5287 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5288 0 obj -<< -/Subtype /Link -/A 5287 0 R -/Type /Annot -/Rect [72 481.901 88.2 493.214] -/Border [0 0 0] ->> -endobj -5289 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5290 0 obj -<< -/Subtype /Link -/A 5289 0 R -/Type /Annot -/Rect [88.2 481.901 93.6 493.214] -/Border [0 0 0] ->> -endobj -5291 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5292 0 obj -<< -/Subtype /Link -/A 5291 0 R -/Type /Annot -/Rect [93.6 481.901 131.4 493.214] -/Border [0 0 0] ->> -endobj -5293 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5294 0 obj -<< -/Subtype /Link -/A 5293 0 R -/Type /Annot -/Rect [131.4 481.901 136.8 493.214] -/Border [0 0 0] ->> -endobj -5295 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5296 0 obj -<< -/Subtype /Link -/A 5295 0 R -/Type /Annot -/Rect [136.8 481.901 207 493.214] -/Border [0 0 0] ->> -endobj -5297 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5298 0 obj -<< -/Subtype /Link -/A 5297 0 R -/Type /Annot -/Rect [207 481.901 212.4 493.214] -/Border [0 0 0] ->> -endobj -5299 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5300 0 obj -<< -/Subtype /Link -/A 5299 0 R -/Type /Annot -/Rect [212.4 481.901 217.8 493.214] -/Border [0 0 0] ->> -endobj -5217 0 obj -<< -/Type /Page -/Parent 1 0 R -/MediaBox [0 0 612 792] -/Contents 5215 0 R -/Resources 5216 0 R -/Annots [5220 0 R 5222 0 R 5224 0 R 5226 0 R 5228 0 R 5230 0 R 5232 0 R 5234 0 R 5236 0 R 5238 0 R 5240 0 R 5242 0 R 5244 0 R 5246 0 R 5248 0 R 5250 0 R 5252 0 R 5254 0 R 5256 0 R 5258 0 R 5260 0 R 5262 0 R 5264 0 R 5266 0 R 5268 0 R 5270 0 R 5272 0 R 5274 0 R 5276 0 R 5278 0 R 5280 0 R 5282 0 R 5284 0 R 5286 0 R 5288 0 R 5290 0 R 5292 0 R 5294 0 R 5296 0 R 5298 0 R 5300 0 R] ->> -endobj -5216 0 obj -<< -/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] -/Font << -/F4 16 0 R -/F3 9 0 R -/F6 44 0 R -/F5 29 0 R ->> ->> -endobj -5215 0 obj -<< -/Length 997 -/Filter /FlateDecode ->> -stream -xYn0+e9rVd(eTTG:eq7ÑoUc]{|PO;۟ꟻ_;}S%T+$OAVisBݍm}pfit\_Ms,b1uOaEuf8zR'Y+`ZBWfꠝ"Dv"/Bϡca%*5 I"dl'2껫gnpg.B/G2 mNEg`JUV>'G'UF{$=;9pÔ~Brt;еGy1V;˅C0+kQ(t23f8͍@`u|82KIVP 15\ -pd~] `|( ˶'b3iJ;g3|);f8|$TEp3pv2CN6c9o<-_scfSpGg)GJ`VC \ۥ~qC)Njgn,(OiE WͶ8rO(X0Fp|p]?Ji1ͣ蛃B(埐C -ӴD킸|n+ldV>:EPr@Y;LO:iqN}n;3/%lI!̯eCQ,&bXɄ7p["Eg'$]=<\sJ,j4LsSF]s0L^ -endstream -endobj -5305 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5306 0 obj -<< -/Subtype /Link -/A 5305 0 R -/Type /Annot -/Rect [72 695.502 131.742 720] -/Border [0 0 0] ->> -endobj -5307 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5308 0 obj -<< -/Subtype /Link -/A 5307 0 R -/Type /Annot -/Rect [72 673.002 93.201172 685.502] -/Border [0 0 0] ->> -endobj -5309 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5310 0 obj -<< -/Subtype /Link -/A 5309 0 R -/Type /Annot -/Rect [93.201172 672.932 135.201172 685.502] -/Border [0 0 0] ->> -endobj -5311 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5312 0 obj -<< -/Subtype /Link -/A 5311 0 R -/Type /Annot -/Rect [135.201172 673.002 355.889648 685.502] -/Border [0 0 0] ->> -endobj -5313 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5314 0 obj -<< -/Subtype /Link -/A 5313 0 R -/Type /Annot -/Rect [355.889648 672.932 403.889648 685.502] -/Border [0 0 0] ->> -endobj -5315 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5316 0 obj -<< -/Subtype /Link -/A 5315 0 R -/Type /Annot -/Rect [403.889648 673.002 512.830078 685.502] -/Border [0 0 0] ->> -endobj -5317 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5318 0 obj -<< -/Subtype /Link -/A 5317 0 R -/Type /Annot -/Rect [512.830078 672.932 536.830078 685.502] -/Border [0 0 0] ->> -endobj -5319 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5320 0 obj -<< -/Subtype /Link -/A 5319 0 R -/Type /Annot -/Rect [72 660.502 479.30957 673.002] -/Border [0 0 0] ->> -endobj -5321 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5322 0 obj -<< -/Subtype /Link -/A 5321 0 R -/Type /Annot -/Rect [479.30957 660.432 509.30957 673.002] -/Border [0 0 0] ->> -endobj -5323 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5324 0 obj -<< -/Subtype /Link -/A 5323 0 R -/Type /Annot -/Rect [509.30957 660.502 515.310547 673.002] -/Border [0 0 0] ->> -endobj -5325 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5326 0 obj -<< -/Subtype /Link -/A 5325 0 R -/Type /Annot -/Rect [72 638.002 467.644531 650.502] -/Border [0 0 0] ->> -endobj -5327 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5328 0 obj -<< -/Subtype /Link -/A 5327 0 R -/Type /Annot -/Rect [72 616.689 217.8 628.002] -/Border [0 0 0] ->> -endobj -5329 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5330 0 obj -<< -/Subtype /Link -/A 5329 0 R -/Type /Annot -/Rect [72 605.376 99 616.689] -/Border [0 0 0] ->> -endobj -5331 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5332 0 obj -<< -/Subtype /Link -/A 5331 0 R -/Type /Annot -/Rect [99 605.376 104.4 616.689] -/Border [0 0 0] ->> -endobj -5333 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5334 0 obj -<< -/Subtype /Link -/A 5333 0 R -/Type /Annot -/Rect [104.4 605.376 120.6 616.689] -/Border [0 0 0] ->> -endobj -5335 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5336 0 obj -<< -/Subtype /Link -/A 5335 0 R -/Type /Annot -/Rect [120.6 605.376 126 616.689] -/Border [0 0 0] ->> -endobj -5337 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5338 0 obj -<< -/Subtype /Link -/A 5337 0 R -/Type /Annot -/Rect [126 605.376 131.4 616.689] -/Border [0 0 0] ->> -endobj -5339 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5340 0 obj -<< -/Subtype /Link -/A 5339 0 R -/Type /Annot -/Rect [131.4 605.376 136.8 616.689] -/Border [0 0 0] ->> -endobj -5341 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5342 0 obj -<< -/Subtype /Link -/A 5341 0 R -/Type /Annot -/Rect [136.8 605.376 174.6 616.689] -/Border [0 0 0] ->> -endobj -5343 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5344 0 obj -<< -/Subtype /Link -/A 5343 0 R -/Type /Annot -/Rect [174.6 605.376 180 616.689] -/Border [0 0 0] ->> -endobj -5345 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5346 0 obj -<< -/Subtype /Link -/A 5345 0 R -/Type /Annot -/Rect [180 605.376 217.8 616.689] -/Border [0 0 0] ->> -endobj -5347 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5348 0 obj -<< -/Subtype /Link -/A 5347 0 R -/Type /Annot -/Rect [217.8 605.376 223.2 616.689] -/Border [0 0 0] ->> -endobj -5349 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5350 0 obj -<< -/Subtype /Link -/A 5349 0 R -/Type /Annot -/Rect [223.2 605.376 282.6 616.689] -/Border [0 0 0] ->> -endobj -5351 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5352 0 obj -<< -/Subtype /Link -/A 5351 0 R -/Type /Annot -/Rect [282.6 605.376 288 616.689] -/Border [0 0 0] ->> -endobj -5353 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5354 0 obj -<< -/Subtype /Link -/A 5353 0 R -/Type /Annot -/Rect [288 605.376 293.4 616.689] -/Border [0 0 0] ->> -endobj -5355 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5356 0 obj -<< -/Subtype /Link -/A 5355 0 R -/Type /Annot -/Rect [293.4 605.376 298.8 616.689] -/Border [0 0 0] ->> -endobj -5357 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5358 0 obj -<< -/Subtype /Link -/A 5357 0 R -/Type /Annot -/Rect [298.8 605.376 304.2 616.689] -/Border [0 0 0] ->> -endobj -5359 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5360 0 obj -<< -/Subtype /Link -/A 5359 0 R -/Type /Annot -/Rect [304.2 605.376 347.4 616.689] -/Border [0 0 0] ->> -endobj -5361 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5362 0 obj -<< -/Subtype /Link -/A 5361 0 R -/Type /Annot -/Rect [347.4 605.376 352.8 616.689] -/Border [0 0 0] ->> -endobj -5363 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5364 0 obj -<< -/Subtype /Link -/A 5363 0 R -/Type /Annot -/Rect [352.8 605.376 358.2 616.689] -/Border [0 0 0] ->> -endobj -5365 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5366 0 obj -<< -/Subtype /Link -/A 5365 0 R -/Type /Annot -/Rect [358.2 605.376 379.8 616.689] -/Border [0 0 0] ->> -endobj -5367 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5368 0 obj -<< -/Subtype /Link -/A 5367 0 R -/Type /Annot -/Rect [379.8 605.376 385.2 616.689] -/Border [0 0 0] ->> -endobj -5369 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5370 0 obj -<< -/Subtype /Link -/A 5369 0 R -/Type /Annot -/Rect [385.2 605.376 390.6 616.689] -/Border [0 0 0] ->> -endobj -5371 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5372 0 obj -<< -/Subtype /Link -/A 5371 0 R -/Type /Annot -/Rect [390.6 605.376 396 616.689] -/Border [0 0 0] ->> -endobj -5373 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5374 0 obj -<< -/Subtype /Link -/A 5373 0 R -/Type /Annot -/Rect [396 605.376 401.4 616.689] -/Border [0 0 0] ->> -endobj -5375 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5376 0 obj -<< -/Subtype /Link -/A 5375 0 R -/Type /Annot -/Rect [72 582.75 180 594.063] -/Border [0 0 0] ->> -endobj -5377 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5378 0 obj -<< -/Subtype /Link -/A 5377 0 R -/Type /Annot -/Rect [72 571.437 88.2 582.75] -/Border [0 0 0] ->> -endobj -5379 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5380 0 obj -<< -/Subtype /Link -/A 5379 0 R -/Type /Annot -/Rect [88.2 571.437 93.6 582.75] -/Border [0 0 0] ->> -endobj -5381 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5382 0 obj -<< -/Subtype /Link -/A 5381 0 R -/Type /Annot -/Rect [93.6 571.437 131.4 582.75] -/Border [0 0 0] ->> -endobj -5383 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5384 0 obj -<< -/Subtype /Link -/A 5383 0 R -/Type /Annot -/Rect [131.4 571.437 136.8 582.75] -/Border [0 0 0] ->> -endobj -5385 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5386 0 obj -<< -/Subtype /Link -/A 5385 0 R -/Type /Annot -/Rect [136.8 571.437 207 582.75] -/Border [0 0 0] ->> -endobj -5387 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5388 0 obj -<< -/Subtype /Link -/A 5387 0 R -/Type /Annot -/Rect [207 571.437 212.4 582.75] -/Border [0 0 0] ->> -endobj -5389 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5390 0 obj -<< -/Subtype /Link -/A 5389 0 R -/Type /Annot -/Rect [212.4 571.437 217.8 582.75] -/Border [0 0 0] ->> -endobj -5303 0 obj -<< -/Type /Page -/Parent 1 0 R -/MediaBox [0 0 612 792] -/Contents 5301 0 R -/Resources 5302 0 R -/Annots [5306 0 R 5308 0 R 5310 0 R 5312 0 R 5314 0 R 5316 0 R 5318 0 R 5320 0 R 5322 0 R 5324 0 R 5326 0 R 5328 0 R 5330 0 R 5332 0 R 5334 0 R 5336 0 R 5338 0 R 5340 0 R 5342 0 R 5344 0 R 5346 0 R 5348 0 R 5350 0 R 5352 0 R 5354 0 R 5356 0 R 5358 0 R 5360 0 R 5362 0 R 5364 0 R 5366 0 R 5368 0 R 5370 0 R 5372 0 R 5374 0 R 5376 0 R 5378 0 R 5380 0 R 5382 0 R 5384 0 R 5386 0 R 5388 0 R 5390 0 R] ->> -endobj -5302 0 obj -<< -/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] -/Font << -/F4 16 0 R -/F3 9 0 R -/F6 44 0 R -/F5 29 0 R ->> ->> -endobj -5301 0 obj -<< -/Length 1016 -/Filter /FlateDecode ->> -stream -xXMo0 ẈD}E>66:6 GITl'bjRY)rN/eڽv>?UN}󤨬, -YiO@i(铆 -~T/WX6Bd+Gˆ&i5y%m>F0j1=M@Y G.4y]pg2%1L~\qy_േA7@+VՌFF'~Wi:eШ3ݎty!?d H}Gi+ejǙ:gӐA5k -%H)T=ɞ;P4#Z5%զJCgㄯ2qoO# !4ZfB8|((>,v'O"`:y`R֝tzt>QrXaX=ÕrV9]N@ &b.W- z3Pق lC]覷\8ZP/ ->\+q+.p#pRa)6K (֋5W:(m-,AhQc k8qKͽYet b;/rT> -endobj -5396 0 obj -<< -/Subtype /Link -/A 5395 0 R -/Type /Annot -/Rect [72 685.975 309.075 720] -/Border [0 0 0] ->> -endobj -5397 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5398 0 obj -<< -/Subtype /Link -/A 5397 0 R -/Type /Annot -/Rect [72 658.475 532.126953 670.975] -/Border [0 0 0] ->> -endobj -5399 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5400 0 obj -<< -/Subtype /Link -/A 5399 0 R -/Type /Annot -/Rect [72 645.975 530.007813 658.475] -/Border [0 0 0] ->> -endobj -5401 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5402 0 obj -<< -/Subtype /Link -/A 5401 0 R -/Type /Annot -/Rect [72 633.475 513.635742 645.975] -/Border [0 0 0] ->> -endobj -5403 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5404 0 obj -<< -/Subtype /Link -/A 5403 0 R -/Type /Annot -/Rect [72 620.975 523.235352 633.475] -/Border [0 0 0] ->> -endobj -5405 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5406 0 obj -<< -/Subtype /Link -/A 5405 0 R -/Type /Annot -/Rect [72 608.475 119.53418 620.975] -/Border [0 0 0] ->> -endobj -5407 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5408 0 obj -<< -/Subtype /Link -/A 5407 0 R -/Type /Annot -/Rect [72 585.905 336 598.475] -/Border [0 0 0] ->> -endobj -5409 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5410 0 obj -<< -/Subtype /Link -/A 5409 0 R -/Type /Annot -/Rect [72 567.335 306 579.905] -/Border [0 0 0] ->> -endobj -5411 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5412 0 obj -<< -/Subtype /Link -/A 5411 0 R -/Type /Annot -/Rect [72 548.765 306 561.335] -/Border [0 0 0] ->> -endobj -5413 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5414 0 obj -<< -/Subtype /Link -/A 5413 0 R -/Type /Annot -/Rect [72 530.195 306 542.765] -/Border [0 0 0] ->> -endobj -5415 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5416 0 obj -<< -/Subtype /Link -/A 5415 0 R -/Type /Annot -/Rect [72 511.625 288 524.195] -/Border [0 0 0] ->> -endobj -5417 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5418 0 obj -<< -/Subtype /Link -/A 5417 0 R -/Type /Annot -/Rect [72 493.055 306 505.625] -/Border [0 0 0] ->> -endobj -5419 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5420 0 obj -<< -/Subtype /Link -/A 5419 0 R -/Type /Annot -/Rect [72 474.485 336 487.055] -/Border [0 0 0] ->> -endobj -5421 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5422 0 obj -<< -/Subtype /Link -/A 5421 0 R -/Type /Annot -/Rect [72 455.915 354 468.485] -/Border [0 0 0] ->> -endobj -5423 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5424 0 obj -<< -/Subtype /Link -/A 5423 0 R -/Type /Annot -/Rect [72 437.345 372 449.915] -/Border [0 0 0] ->> -endobj -5425 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5426 0 obj -<< -/Subtype /Link -/A 5425 0 R -/Type /Annot -/Rect [72 408.845 231.575195 421.345] -/Border [0 0 0] ->> -endobj -5427 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5428 0 obj -<< -/Subtype /Link -/A 5427 0 R -/Type /Annot -/Rect [231.575195 408.775 261.575195 421.345] -/Border [0 0 0] ->> -endobj -5429 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5430 0 obj -<< -/Subtype /Link -/A 5429 0 R -/Type /Annot -/Rect [261.575195 408.845 521.897461 421.345] -/Border [0 0 0] ->> -endobj -5431 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5432 0 obj -<< -/Subtype /Link -/A 5431 0 R -/Type /Annot -/Rect [72 396.345 406.638672 408.845] -/Border [0 0 0] ->> -endobj -5433 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5434 0 obj -<< -/Subtype /Link -/A 5433 0 R -/Type /Annot -/Rect [72 373.845 536.589844 386.345] -/Border [0 0 0] ->> -endobj -5435 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5436 0 obj -<< -/Subtype /Link -/A 5435 0 R -/Type /Annot -/Rect [72 361.345 500.500977 373.845] -/Border [0 0 0] ->> -endobj -5437 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5438 0 obj -<< -/Subtype /Link -/A 5437 0 R -/Type /Annot -/Rect [72 348.845 533.572266 361.345] -/Border [0 0 0] ->> -endobj -5439 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5440 0 obj -<< -/Subtype /Link -/A 5439 0 R -/Type /Annot -/Rect [72 336.345 266.023438 348.845] -/Border [0 0 0] ->> -endobj -5441 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5442 0 obj -<< -/Subtype /Link -/A 5441 0 R -/Type /Annot -/Rect [266.023438 336.275 344.023438 348.845] -/Border [0 0 0] ->> -endobj -5443 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5444 0 obj -<< -/Subtype /Link -/A 5443 0 R -/Type /Annot -/Rect [344.023438 336.345 525.629883 348.845] -/Border [0 0 0] ->> -endobj -5445 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5446 0 obj -<< -/Subtype /Link -/A 5445 0 R -/Type /Annot -/Rect [72 323.845 388.572266 336.345] -/Border [0 0 0] ->> -endobj -5447 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5448 0 obj -<< -/Subtype /Link -/A 5447 0 R -/Type /Annot -/Rect [388.572266 323.775 490.572266 336.345] -/Border [0 0 0] ->> -endobj -5449 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5450 0 obj -<< -/Subtype /Link -/A 5449 0 R -/Type /Annot -/Rect [490.572266 323.845 535.542969 336.345] -/Border [0 0 0] ->> -endobj -5451 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5452 0 obj -<< -/Subtype /Link -/A 5451 0 R -/Type /Annot -/Rect [72 301.345 539.666016 313.845] -/Border [0 0 0] ->> -endobj -5453 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5454 0 obj -<< -/Subtype /Link -/A 5453 0 R -/Type /Annot -/Rect [72 288.845 533.083984 301.345] -/Border [0 0 0] ->> -endobj -5455 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5456 0 obj -<< -/Subtype /Link -/A 5455 0 R -/Type /Annot -/Rect [72 276.345 526.926758 288.845] -/Border [0 0 0] ->> -endobj -5457 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5458 0 obj -<< -/Subtype /Link -/A 5457 0 R -/Type /Annot -/Rect [72 263.845 159.119141 276.345] -/Border [0 0 0] ->> -endobj -5393 0 obj -<< -/Type /Page -/Parent 1 0 R -/MediaBox [0 0 612 792] -/Contents 5391 0 R -/Resources 5392 0 R -/Annots [5396 0 R 5398 0 R 5400 0 R 5402 0 R 5404 0 R 5406 0 R 5408 0 R 5410 0 R 5412 0 R 5414 0 R 5416 0 R 5418 0 R 5420 0 R 5422 0 R 5424 0 R 5426 0 R 5428 0 R 5430 0 R 5432 0 R 5434 0 R 5436 0 R 5438 0 R 5440 0 R 5442 0 R 5444 0 R 5446 0 R 5448 0 R 5450 0 R 5452 0 R 5454 0 R 5456 0 R 5458 0 R] ->> -endobj -5392 0 obj -<< -/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] -/Font << -/F4 16 0 R -/F3 9 0 R -/F6 44 0 R ->> ->> -endobj -5391 0 obj -<< -/Length 1482 -/Filter /FlateDecode ->> -stream -xZ͎F)xVD-ܢlRZ)(24U_W -3ÿӏ_v~;?'X_BQ"6ϾxO|2Ƙ0]>p5,Ww4 =Oϧ^Co`^"-5>K['[MskX;χǸ"uh\Olm/;5VO{l8n֌VCr<~0|3^hB77%e - B҃viƋpAeQ59{qdn3M_ߋt #'e̶ K+7nˆp"2Ѩd-[304K4m'IilX/= 5u">=9Ϋq( Sf&;%ܡ?DJCr'wEi֚jy"bnjPjy+_~AC> F FkIW`q&,k {?0T֟In{Xf\J5+8X2)K@"55dq1f1G_W%TaCj\Y7][n)d[T,UQlRv;!5ܑ֮ n6 -O;CY~vM9trLZXϔuC'ޏZNeq#D;MbH-;֒ /JTyX<|k[hRioEAq[.z7Ƭeμ<>5<Лqr5YCjE-]23:(Ud}3EkNg[mb9BeUZVp<#(ssTY\Ǥ'<q}>-Zv#wk0d.(0RSKEJ}c8[uȦE<,4z*FZ9rOK|/~”G'iaұva]2 0xʕ ߱+ӘZ9!yJ.2zN^zwLC.1-PVQ۔&/ܿT.lq,LѪ'RS$sJp[UnLUy^vThQwVhޏb0cB}A -endstream -endobj -5462 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5463 0 obj -<< -/Subtype /Link -/A 5462 0 R -/Type /Annot -/Rect [72 697.5 366.555664 710] -/Border [0 0 0] ->> -endobj -5464 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5465 0 obj -<< -/Subtype /Link -/A 5464 0 R -/Type /Annot -/Rect [72 676.187 180 687.5] -/Border [0 0 0] ->> -endobj -5466 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5467 0 obj -<< -/Subtype /Link -/A 5466 0 R -/Type /Annot -/Rect [72 664.874 88.2 676.187] -/Border [0 0 0] ->> -endobj -5468 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5469 0 obj -<< -/Subtype /Link -/A 5468 0 R -/Type /Annot -/Rect [88.2 664.874 93.6 676.187] -/Border [0 0 0] ->> -endobj -5470 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5471 0 obj -<< -/Subtype /Link -/A 5470 0 R -/Type /Annot -/Rect [93.6 664.874 136.8 676.187] -/Border [0 0 0] ->> -endobj -5472 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5473 0 obj -<< -/Subtype /Link -/A 5472 0 R -/Type /Annot -/Rect [136.8 664.874 142.2 676.187] -/Border [0 0 0] ->> -endobj -5474 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5475 0 obj -<< -/Subtype /Link -/A 5474 0 R -/Type /Annot -/Rect [142.2 664.874 153 676.187] -/Border [0 0 0] ->> -endobj -5476 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5477 0 obj -<< -/Subtype /Link -/A 5476 0 R -/Type /Annot -/Rect [153 664.874 158.4 676.187] -/Border [0 0 0] ->> -endobj -5478 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5479 0 obj -<< -/Subtype /Link -/A 5478 0 R -/Type /Annot -/Rect [72 653.561 88.2 664.874] -/Border [0 0 0] ->> -endobj -5480 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5481 0 obj -<< -/Subtype /Link -/A 5480 0 R -/Type /Annot -/Rect [88.2 653.561 93.6 664.874] -/Border [0 0 0] ->> -endobj -5482 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5483 0 obj -<< -/Subtype /Link -/A 5482 0 R -/Type /Annot -/Rect [93.6 653.561 142.2 664.874] -/Border [0 0 0] ->> -endobj -5484 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5485 0 obj -<< -/Subtype /Link -/A 5484 0 R -/Type /Annot -/Rect [142.2 653.561 147.6 664.874] -/Border [0 0 0] ->> -endobj -5486 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5487 0 obj -<< -/Subtype /Link -/A 5486 0 R -/Type /Annot -/Rect [147.6 653.561 180 664.874] -/Border [0 0 0] ->> -endobj -5488 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5489 0 obj -<< -/Subtype /Link -/A 5488 0 R -/Type /Annot -/Rect [180 653.561 185.4 664.874] -/Border [0 0 0] ->> -endobj -5490 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5491 0 obj -<< -/Subtype /Link -/A 5490 0 R -/Type /Annot -/Rect [72 642.248 88.2 653.561] -/Border [0 0 0] ->> -endobj -5492 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5493 0 obj -<< -/Subtype /Link -/A 5492 0 R -/Type /Annot -/Rect [88.2 642.248 93.6 653.561] -/Border [0 0 0] ->> -endobj -5494 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5495 0 obj -<< -/Subtype /Link -/A 5494 0 R -/Type /Annot -/Rect [93.6 642.248 115.2 653.561] -/Border [0 0 0] ->> -endobj -5496 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5497 0 obj -<< -/Subtype /Link -/A 5496 0 R -/Type /Annot -/Rect [115.2 642.248 120.6 653.561] -/Border [0 0 0] ->> -endobj -5498 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5499 0 obj -<< -/Subtype /Link -/A 5498 0 R -/Type /Annot -/Rect [120.6 642.248 212.4 653.561] -/Border [0 0 0] ->> -endobj -5500 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5501 0 obj -<< -/Subtype /Link -/A 5500 0 R -/Type /Annot -/Rect [212.4 642.248 217.8 653.561] -/Border [0 0 0] ->> -endobj -5502 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5503 0 obj -<< -/Subtype /Link -/A 5502 0 R -/Type /Annot -/Rect [217.8 642.248 223.2 653.561] -/Border [0 0 0] ->> -endobj -5504 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5505 0 obj -<< -/Subtype /Link -/A 5504 0 R -/Type /Annot -/Rect [223.2 642.248 234 653.561] -/Border [0 0 0] ->> -endobj -5506 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5507 0 obj -<< -/Subtype /Link -/A 5506 0 R -/Type /Annot -/Rect [234 642.248 239.4 653.561] -/Border [0 0 0] ->> -endobj -5508 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5509 0 obj -<< -/Subtype /Link -/A 5508 0 R -/Type /Annot -/Rect [239.4 642.248 244.8 653.561] -/Border [0 0 0] ->> -endobj -5510 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5511 0 obj -<< -/Subtype /Link -/A 5510 0 R -/Type /Annot -/Rect [244.8 642.248 250.2 653.561] -/Border [0 0 0] ->> -endobj -5512 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5513 0 obj -<< -/Subtype /Link -/A 5512 0 R -/Type /Annot -/Rect [250.2 642.248 255.6 653.561] -/Border [0 0 0] ->> -endobj -5514 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5515 0 obj -<< -/Subtype /Link -/A 5514 0 R -/Type /Annot -/Rect [255.6 642.248 261 653.561] -/Border [0 0 0] ->> -endobj -5516 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5517 0 obj -<< -/Subtype /Link -/A 5516 0 R -/Type /Annot -/Rect [72 619.622 174.6 630.935] -/Border [0 0 0] ->> -endobj -5518 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5519 0 obj -<< -/Subtype /Link -/A 5518 0 R -/Type /Annot -/Rect [72 608.309 99 619.622] -/Border [0 0 0] ->> -endobj -5520 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5521 0 obj -<< -/Subtype /Link -/A 5520 0 R -/Type /Annot -/Rect [99 608.309 104.4 619.622] -/Border [0 0 0] ->> -endobj -5522 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5523 0 obj -<< -/Subtype /Link -/A 5522 0 R -/Type /Annot -/Rect [104.4 608.309 131.4 619.622] -/Border [0 0 0] ->> -endobj -5524 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5525 0 obj -<< -/Subtype /Link -/A 5524 0 R -/Type /Annot -/Rect [131.4 608.309 136.8 619.622] -/Border [0 0 0] ->> -endobj -5526 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5527 0 obj -<< -/Subtype /Link -/A 5526 0 R -/Type /Annot -/Rect [136.8 608.309 142.2 619.622] -/Border [0 0 0] ->> -endobj -5528 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5529 0 obj -<< -/Subtype /Link -/A 5528 0 R -/Type /Annot -/Rect [142.2 608.309 147.6 619.622] -/Border [0 0 0] ->> -endobj -5530 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5531 0 obj -<< -/Subtype /Link -/A 5530 0 R -/Type /Annot -/Rect [147.6 608.309 163.8 619.622] -/Border [0 0 0] ->> -endobj -5532 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5533 0 obj -<< -/Subtype /Link -/A 5532 0 R -/Type /Annot -/Rect [163.8 608.309 169.2 619.622] -/Border [0 0 0] ->> -endobj -5534 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5535 0 obj -<< -/Subtype /Link -/A 5534 0 R -/Type /Annot -/Rect [169.2 608.309 239.4 619.622] -/Border [0 0 0] ->> -endobj -5536 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5537 0 obj -<< -/Subtype /Link -/A 5536 0 R -/Type /Annot -/Rect [239.4 608.309 244.8 619.622] -/Border [0 0 0] ->> -endobj -5538 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5539 0 obj -<< -/Subtype /Link -/A 5538 0 R -/Type /Annot -/Rect [244.8 608.309 336.6 619.622] -/Border [0 0 0] ->> -endobj -5540 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5541 0 obj -<< -/Subtype /Link -/A 5540 0 R -/Type /Annot -/Rect [336.6 608.309 342 619.622] -/Border [0 0 0] ->> -endobj -5542 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5543 0 obj -<< -/Subtype /Link -/A 5542 0 R -/Type /Annot -/Rect [342 608.309 347.4 619.622] -/Border [0 0 0] ->> -endobj -5544 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5545 0 obj -<< -/Subtype /Link -/A 5544 0 R -/Type /Annot -/Rect [72 596.996 99 608.309] -/Border [0 0 0] ->> -endobj -5546 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5547 0 obj -<< -/Subtype /Link -/A 5546 0 R -/Type /Annot -/Rect [99 596.996 104.4 608.309] -/Border [0 0 0] ->> -endobj -5548 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5549 0 obj -<< -/Subtype /Link -/A 5548 0 R -/Type /Annot -/Rect [104.4 596.996 136.8 608.309] -/Border [0 0 0] ->> -endobj -5550 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5551 0 obj -<< -/Subtype /Link -/A 5550 0 R -/Type /Annot -/Rect [136.8 596.996 142.2 608.309] -/Border [0 0 0] ->> -endobj -5552 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5553 0 obj -<< -/Subtype /Link -/A 5552 0 R -/Type /Annot -/Rect [142.2 596.996 147.6 608.309] -/Border [0 0 0] ->> -endobj -5554 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5555 0 obj -<< -/Subtype /Link -/A 5554 0 R -/Type /Annot -/Rect [147.6 596.996 153 608.309] -/Border [0 0 0] ->> -endobj -5556 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5557 0 obj -<< -/Subtype /Link -/A 5556 0 R -/Type /Annot -/Rect [153 596.996 169.2 608.309] -/Border [0 0 0] ->> -endobj -5558 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5559 0 obj -<< -/Subtype /Link -/A 5558 0 R -/Type /Annot -/Rect [169.2 596.996 174.6 608.309] -/Border [0 0 0] ->> -endobj -5560 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5561 0 obj -<< -/Subtype /Link -/A 5560 0 R -/Type /Annot -/Rect [174.6 596.996 266.4 608.309] -/Border [0 0 0] ->> -endobj -5562 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5563 0 obj -<< -/Subtype /Link -/A 5562 0 R -/Type /Annot -/Rect [266.4 596.996 271.8 608.309] -/Border [0 0 0] ->> -endobj -5564 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5565 0 obj -<< -/Subtype /Link -/A 5564 0 R -/Type /Annot -/Rect [271.8 596.996 277.2 608.309] -/Border [0 0 0] ->> -endobj -5566 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5567 0 obj -<< -/Subtype /Link -/A 5566 0 R -/Type /Annot -/Rect [277.2 596.996 282.6 608.309] -/Border [0 0 0] ->> -endobj -5568 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5569 0 obj -<< -/Subtype /Link -/A 5568 0 R -/Type /Annot -/Rect [72 574.37 293.4 585.683] -/Border [0 0 0] ->> -endobj -5570 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5571 0 obj -<< -/Subtype /Link -/A 5570 0 R -/Type /Annot -/Rect [72 563.057 88.2 574.37] -/Border [0 0 0] ->> -endobj -5572 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5573 0 obj -<< -/Subtype /Link -/A 5572 0 R -/Type /Annot -/Rect [88.2 563.057 93.6 574.37] -/Border [0 0 0] ->> -endobj -5574 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5575 0 obj -<< -/Subtype /Link -/A 5574 0 R -/Type /Annot -/Rect [93.6 563.057 142.2 574.37] -/Border [0 0 0] ->> -endobj -5576 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5577 0 obj -<< -/Subtype /Link -/A 5576 0 R -/Type /Annot -/Rect [142.2 563.057 147.6 574.37] -/Border [0 0 0] ->> -endobj -5578 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5579 0 obj -<< -/Subtype /Link -/A 5578 0 R -/Type /Annot -/Rect [147.6 563.057 158.4 574.37] -/Border [0 0 0] ->> -endobj -5580 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5581 0 obj -<< -/Subtype /Link -/A 5580 0 R -/Type /Annot -/Rect [158.4 563.057 163.8 574.37] -/Border [0 0 0] ->> -endobj -5582 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5583 0 obj -<< -/Subtype /Link -/A 5582 0 R -/Type /Annot -/Rect [163.8 563.057 169.2 574.37] -/Border [0 0 0] ->> -endobj -5584 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5585 0 obj -<< -/Subtype /Link -/A 5584 0 R -/Type /Annot -/Rect [169.2 563.057 174.6 574.37] -/Border [0 0 0] ->> -endobj -5586 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5587 0 obj -<< -/Subtype /Link -/A 5586 0 R -/Type /Annot -/Rect [174.6 563.057 180 574.37] -/Border [0 0 0] ->> -endobj -5588 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5589 0 obj -<< -/Subtype /Link -/A 5588 0 R -/Type /Annot -/Rect [180 563.057 185.4 574.37] -/Border [0 0 0] ->> -endobj -5590 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5591 0 obj -<< -/Subtype /Link -/A 5590 0 R -/Type /Annot -/Rect [185.4 563.057 212.4 574.37] -/Border [0 0 0] ->> -endobj -5592 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5593 0 obj -<< -/Subtype /Link -/A 5592 0 R -/Type /Annot -/Rect [212.4 563.057 217.8 574.37] -/Border [0 0 0] ->> -endobj -5594 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5595 0 obj -<< -/Subtype /Link -/A 5594 0 R -/Type /Annot -/Rect [217.8 563.057 223.2 574.37] -/Border [0 0 0] ->> -endobj -5596 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5597 0 obj -<< -/Subtype /Link -/A 5596 0 R -/Type /Annot -/Rect [223.2 563.057 255.6 574.37] -/Border [0 0 0] ->> -endobj -5598 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5599 0 obj -<< -/Subtype /Link -/A 5598 0 R -/Type /Annot -/Rect [255.6 563.057 261 574.37] -/Border [0 0 0] ->> -endobj -5600 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5601 0 obj -<< -/Subtype /Link -/A 5600 0 R -/Type /Annot -/Rect [261 563.057 266.4 574.37] -/Border [0 0 0] ->> -endobj -5602 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5603 0 obj -<< -/Subtype /Link -/A 5602 0 R -/Type /Annot -/Rect [266.4 563.057 271.8 574.37] -/Border [0 0 0] ->> -endobj -5604 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5605 0 obj -<< -/Subtype /Link -/A 5604 0 R -/Type /Annot -/Rect [271.8 563.057 298.8 574.37] -/Border [0 0 0] ->> -endobj -5606 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5607 0 obj -<< -/Subtype /Link -/A 5606 0 R -/Type /Annot -/Rect [298.8 563.057 304.2 574.37] -/Border [0 0 0] ->> -endobj -5608 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5609 0 obj -<< -/Subtype /Link -/A 5608 0 R -/Type /Annot -/Rect [304.2 563.057 309.6 574.37] -/Border [0 0 0] ->> -endobj -5610 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5611 0 obj -<< -/Subtype /Link -/A 5610 0 R -/Type /Annot -/Rect [309.6 563.057 342 574.37] -/Border [0 0 0] ->> -endobj -5612 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5613 0 obj -<< -/Subtype /Link -/A 5612 0 R -/Type /Annot -/Rect [342 563.057 347.4 574.37] -/Border [0 0 0] ->> -endobj -5614 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5615 0 obj -<< -/Subtype /Link -/A 5614 0 R -/Type /Annot -/Rect [347.4 563.057 352.8 574.37] -/Border [0 0 0] ->> -endobj -5616 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5617 0 obj -<< -/Subtype /Link -/A 5616 0 R -/Type /Annot -/Rect [72 551.744 88.2 563.057] -/Border [0 0 0] ->> -endobj -5618 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5619 0 obj -<< -/Subtype /Link -/A 5618 0 R -/Type /Annot -/Rect [88.2 551.744 93.6 563.057] -/Border [0 0 0] ->> -endobj -5620 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5621 0 obj -<< -/Subtype /Link -/A 5620 0 R -/Type /Annot -/Rect [93.6 551.744 115.2 563.057] -/Border [0 0 0] ->> -endobj -5622 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5623 0 obj -<< -/Subtype /Link -/A 5622 0 R -/Type /Annot -/Rect [115.2 551.744 120.6 563.057] -/Border [0 0 0] ->> -endobj -5624 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5625 0 obj -<< -/Subtype /Link -/A 5624 0 R -/Type /Annot -/Rect [120.6 551.744 131.4 563.057] -/Border [0 0 0] ->> -endobj -5626 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5627 0 obj -<< -/Subtype /Link -/A 5626 0 R -/Type /Annot -/Rect [131.4 551.744 136.8 563.057] -/Border [0 0 0] ->> -endobj -5628 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5629 0 obj -<< -/Subtype /Link -/A 5628 0 R -/Type /Annot -/Rect [136.8 551.744 142.2 563.057] -/Border [0 0 0] ->> -endobj -5630 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5631 0 obj -<< -/Subtype /Link -/A 5630 0 R -/Type /Annot -/Rect [142.2 551.744 147.6 563.057] -/Border [0 0 0] ->> -endobj -5632 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5633 0 obj -<< -/Subtype /Link -/A 5632 0 R -/Type /Annot -/Rect [147.6 551.744 153 563.057] -/Border [0 0 0] ->> -endobj -5634 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5635 0 obj -<< -/Subtype /Link -/A 5634 0 R -/Type /Annot -/Rect [153 551.744 158.4 563.057] -/Border [0 0 0] ->> -endobj -5636 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5637 0 obj -<< -/Subtype /Link -/A 5636 0 R -/Type /Annot -/Rect [158.4 551.744 185.4 563.057] -/Border [0 0 0] ->> -endobj -5638 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5639 0 obj -<< -/Subtype /Link -/A 5638 0 R -/Type /Annot -/Rect [185.4 551.744 190.8 563.057] -/Border [0 0 0] ->> -endobj -5640 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5641 0 obj -<< -/Subtype /Link -/A 5640 0 R -/Type /Annot -/Rect [190.8 551.744 196.2 563.057] -/Border [0 0 0] ->> -endobj -5642 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5643 0 obj -<< -/Subtype /Link -/A 5642 0 R -/Type /Annot -/Rect [196.2 551.744 228.6 563.057] -/Border [0 0 0] ->> -endobj -5644 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5645 0 obj -<< -/Subtype /Link -/A 5644 0 R -/Type /Annot -/Rect [228.6 551.744 234 563.057] -/Border [0 0 0] ->> -endobj -5646 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5647 0 obj -<< -/Subtype /Link -/A 5646 0 R -/Type /Annot -/Rect [234 551.744 239.4 563.057] -/Border [0 0 0] ->> -endobj -5648 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5649 0 obj -<< -/Subtype /Link -/A 5648 0 R -/Type /Annot -/Rect [239.4 551.744 347.4 563.057] -/Border [0 0 0] ->> -endobj -5650 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5651 0 obj -<< -/Subtype /Link -/A 5650 0 R -/Type /Annot -/Rect [347.4 551.744 352.8 563.057] -/Border [0 0 0] ->> -endobj -5652 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5653 0 obj -<< -/Subtype /Link -/A 5652 0 R -/Type /Annot -/Rect [352.8 551.744 358.2 563.057] -/Border [0 0 0] ->> -endobj -5654 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5655 0 obj -<< -/Subtype /Link -/A 5654 0 R -/Type /Annot -/Rect [72 529.118 234 540.431] -/Border [0 0 0] ->> -endobj -5656 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5657 0 obj -<< -/Subtype /Link -/A 5656 0 R -/Type /Annot -/Rect [72 517.805 88.2 529.118] -/Border [0 0 0] ->> -endobj -5658 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5659 0 obj -<< -/Subtype /Link -/A 5658 0 R -/Type /Annot -/Rect [88.2 517.805 93.6 529.118] -/Border [0 0 0] ->> -endobj -5660 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5661 0 obj -<< -/Subtype /Link -/A 5660 0 R -/Type /Annot -/Rect [93.6 517.805 136.8 529.118] -/Border [0 0 0] ->> -endobj -5662 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5663 0 obj -<< -/Subtype /Link -/A 5662 0 R -/Type /Annot -/Rect [136.8 517.805 142.2 529.118] -/Border [0 0 0] ->> -endobj -5664 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5665 0 obj -<< -/Subtype /Link -/A 5664 0 R -/Type /Annot -/Rect [142.2 517.805 147.6 529.118] -/Border [0 0 0] ->> -endobj -5666 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5667 0 obj -<< -/Subtype /Link -/A 5666 0 R -/Type /Annot -/Rect [72 506.492 88.2 517.805] -/Border [0 0 0] ->> -endobj -5668 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5669 0 obj -<< -/Subtype /Link -/A 5668 0 R -/Type /Annot -/Rect [88.2 506.492 93.6 517.805] -/Border [0 0 0] ->> -endobj -5670 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5671 0 obj -<< -/Subtype /Link -/A 5670 0 R -/Type /Annot -/Rect [93.6 506.492 142.2 517.805] -/Border [0 0 0] ->> -endobj -5672 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5673 0 obj -<< -/Subtype /Link -/A 5672 0 R -/Type /Annot -/Rect [142.2 506.492 147.6 517.805] -/Border [0 0 0] ->> -endobj -5674 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5675 0 obj -<< -/Subtype /Link -/A 5674 0 R -/Type /Annot -/Rect [147.6 506.492 185.4 517.805] -/Border [0 0 0] ->> -endobj -5676 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5677 0 obj -<< -/Subtype /Link -/A 5676 0 R -/Type /Annot -/Rect [185.4 506.492 190.8 517.805] -/Border [0 0 0] ->> -endobj -5678 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5679 0 obj -<< -/Subtype /Link -/A 5678 0 R -/Type /Annot -/Rect [72 495.179 88.2 506.492] -/Border [0 0 0] ->> -endobj -5680 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5681 0 obj -<< -/Subtype /Link -/A 5680 0 R -/Type /Annot -/Rect [88.2 495.179 93.6 506.492] -/Border [0 0 0] ->> -endobj -5682 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5683 0 obj -<< -/Subtype /Link -/A 5682 0 R -/Type /Annot -/Rect [93.6 495.179 142.2 506.492] -/Border [0 0 0] ->> -endobj -5684 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5685 0 obj -<< -/Subtype /Link -/A 5684 0 R -/Type /Annot -/Rect [142.2 495.179 147.6 506.492] -/Border [0 0 0] ->> -endobj -5686 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5687 0 obj -<< -/Subtype /Link -/A 5686 0 R -/Type /Annot -/Rect [147.6 495.179 158.4 506.492] -/Border [0 0 0] ->> -endobj -5688 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5689 0 obj -<< -/Subtype /Link -/A 5688 0 R -/Type /Annot -/Rect [158.4 495.179 163.8 506.492] -/Border [0 0 0] ->> -endobj -5690 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5691 0 obj -<< -/Subtype /Link -/A 5690 0 R -/Type /Annot -/Rect [163.8 495.179 169.2 506.492] -/Border [0 0 0] ->> -endobj -5692 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5693 0 obj -<< -/Subtype /Link -/A 5692 0 R -/Type /Annot -/Rect [169.2 495.179 185.4 506.492] -/Border [0 0 0] ->> -endobj -5694 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5695 0 obj -<< -/Subtype /Link -/A 5694 0 R -/Type /Annot -/Rect [185.4 495.179 190.8 506.492] -/Border [0 0 0] ->> -endobj -5696 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5697 0 obj -<< -/Subtype /Link -/A 5696 0 R -/Type /Annot -/Rect [190.8 495.179 196.2 506.492] -/Border [0 0 0] ->> -endobj -5698 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5699 0 obj -<< -/Subtype /Link -/A 5698 0 R -/Type /Annot -/Rect [196.2 495.179 201.6 506.492] -/Border [0 0 0] ->> -endobj -5700 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5701 0 obj -<< -/Subtype /Link -/A 5700 0 R -/Type /Annot -/Rect [201.6 495.179 207 506.492] -/Border [0 0 0] ->> -endobj -5702 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5703 0 obj -<< -/Subtype /Link -/A 5702 0 R -/Type /Annot -/Rect [207 495.179 223.2 506.492] -/Border [0 0 0] ->> -endobj -5704 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5705 0 obj -<< -/Subtype /Link -/A 5704 0 R -/Type /Annot -/Rect [223.2 495.179 228.6 506.492] -/Border [0 0 0] ->> -endobj -5706 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5707 0 obj -<< -/Subtype /Link -/A 5706 0 R -/Type /Annot -/Rect [228.6 495.179 298.8 506.492] -/Border [0 0 0] ->> -endobj -5708 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5709 0 obj -<< -/Subtype /Link -/A 5708 0 R -/Type /Annot -/Rect [298.8 495.179 304.2 506.492] -/Border [0 0 0] ->> -endobj -5710 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5711 0 obj -<< -/Subtype /Link -/A 5710 0 R -/Type /Annot -/Rect [304.2 495.179 450 506.492] -/Border [0 0 0] ->> -endobj -5712 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5713 0 obj -<< -/Subtype /Link -/A 5712 0 R -/Type /Annot -/Rect [450 495.179 455.4 506.492] -/Border [0 0 0] ->> -endobj -5714 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5715 0 obj -<< -/Subtype /Link -/A 5714 0 R -/Type /Annot -/Rect [455.4 495.179 460.8 506.492] -/Border [0 0 0] ->> -endobj -5716 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5717 0 obj -<< -/Subtype /Link -/A 5716 0 R -/Type /Annot -/Rect [460.8 495.179 466.2 506.492] -/Border [0 0 0] ->> -endobj -5718 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5719 0 obj -<< -/Subtype /Link -/A 5718 0 R -/Type /Annot -/Rect [466.2 495.179 498.6 506.492] -/Border [0 0 0] ->> -endobj -5720 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5721 0 obj -<< -/Subtype /Link -/A 5720 0 R -/Type /Annot -/Rect [498.6 495.179 504 506.492] -/Border [0 0 0] ->> -endobj -5722 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5723 0 obj -<< -/Subtype /Link -/A 5722 0 R -/Type /Annot -/Rect [72 483.866 88.2 495.179] -/Border [0 0 0] ->> -endobj -5724 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5725 0 obj -<< -/Subtype /Link -/A 5724 0 R -/Type /Annot -/Rect [88.2 483.866 93.6 495.179] -/Border [0 0 0] ->> -endobj -5726 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5727 0 obj -<< -/Subtype /Link -/A 5726 0 R -/Type /Annot -/Rect [93.6 483.866 115.2 495.179] -/Border [0 0 0] ->> -endobj -5728 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5729 0 obj -<< -/Subtype /Link -/A 5728 0 R -/Type /Annot -/Rect [115.2 483.866 120.6 495.179] -/Border [0 0 0] ->> -endobj -5730 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5731 0 obj -<< -/Subtype /Link -/A 5730 0 R -/Type /Annot -/Rect [120.6 483.866 266.4 495.179] -/Border [0 0 0] ->> -endobj -5732 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5733 0 obj -<< -/Subtype /Link -/A 5732 0 R -/Type /Annot -/Rect [266.4 483.866 271.8 495.179] -/Border [0 0 0] ->> -endobj -5734 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5735 0 obj -<< -/Subtype /Link -/A 5734 0 R -/Type /Annot -/Rect [271.8 483.866 277.2 495.179] -/Border [0 0 0] ->> -endobj -5736 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5737 0 obj -<< -/Subtype /Link -/A 5736 0 R -/Type /Annot -/Rect [72 461.24 234 472.553] -/Border [0 0 0] ->> -endobj -5738 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5739 0 obj -<< -/Subtype /Link -/A 5738 0 R -/Type /Annot -/Rect [72 449.927 88.2 461.24] -/Border [0 0 0] ->> -endobj -5740 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5741 0 obj -<< -/Subtype /Link -/A 5740 0 R -/Type /Annot -/Rect [88.2 449.927 93.6 461.24] -/Border [0 0 0] ->> -endobj -5742 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5743 0 obj -<< -/Subtype /Link -/A 5742 0 R -/Type /Annot -/Rect [93.6 449.927 136.8 461.24] -/Border [0 0 0] ->> -endobj -5744 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5745 0 obj -<< -/Subtype /Link -/A 5744 0 R -/Type /Annot -/Rect [136.8 449.927 142.2 461.24] -/Border [0 0 0] ->> -endobj -5746 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5747 0 obj -<< -/Subtype /Link -/A 5746 0 R -/Type /Annot -/Rect [142.2 449.927 147.6 461.24] -/Border [0 0 0] ->> -endobj -5748 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5749 0 obj -<< -/Subtype /Link -/A 5748 0 R -/Type /Annot -/Rect [72 438.614 88.2 449.927] -/Border [0 0 0] ->> -endobj -5750 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5751 0 obj -<< -/Subtype /Link -/A 5750 0 R -/Type /Annot -/Rect [88.2 438.614 93.6 449.927] -/Border [0 0 0] ->> -endobj -5752 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5753 0 obj -<< -/Subtype /Link -/A 5752 0 R -/Type /Annot -/Rect [93.6 438.614 126 449.927] -/Border [0 0 0] ->> -endobj -5754 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5755 0 obj -<< -/Subtype /Link -/A 5754 0 R -/Type /Annot -/Rect [126 438.614 131.4 449.927] -/Border [0 0 0] ->> -endobj -5756 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5757 0 obj -<< -/Subtype /Link -/A 5756 0 R -/Type /Annot -/Rect [131.4 438.614 142.2 449.927] -/Border [0 0 0] ->> -endobj -5758 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5759 0 obj -<< -/Subtype /Link -/A 5758 0 R -/Type /Annot -/Rect [142.2 438.614 147.6 449.927] -/Border [0 0 0] ->> -endobj -5760 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5761 0 obj -<< -/Subtype /Link -/A 5760 0 R -/Type /Annot -/Rect [147.6 438.614 153 449.927] -/Border [0 0 0] ->> -endobj -5762 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5763 0 obj -<< -/Subtype /Link -/A 5762 0 R -/Type /Annot -/Rect [153 438.614 169.2 449.927] -/Border [0 0 0] ->> -endobj -5764 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5765 0 obj -<< -/Subtype /Link -/A 5764 0 R -/Type /Annot -/Rect [169.2 438.614 174.6 449.927] -/Border [0 0 0] ->> -endobj -5766 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5767 0 obj -<< -/Subtype /Link -/A 5766 0 R -/Type /Annot -/Rect [174.6 438.614 180 449.927] -/Border [0 0 0] ->> -endobj -5768 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5769 0 obj -<< -/Subtype /Link -/A 5768 0 R -/Type /Annot -/Rect [180 438.614 185.4 449.927] -/Border [0 0 0] ->> -endobj -5770 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5771 0 obj -<< -/Subtype /Link -/A 5770 0 R -/Type /Annot -/Rect [185.4 438.614 190.8 449.927] -/Border [0 0 0] ->> -endobj -5772 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5773 0 obj -<< -/Subtype /Link -/A 5772 0 R -/Type /Annot -/Rect [190.8 438.614 207 449.927] -/Border [0 0 0] ->> -endobj -5774 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5775 0 obj -<< -/Subtype /Link -/A 5774 0 R -/Type /Annot -/Rect [207 438.614 212.4 449.927] -/Border [0 0 0] ->> -endobj -5776 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5777 0 obj -<< -/Subtype /Link -/A 5776 0 R -/Type /Annot -/Rect [212.4 438.614 282.6 449.927] -/Border [0 0 0] ->> -endobj -5778 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5779 0 obj -<< -/Subtype /Link -/A 5778 0 R -/Type /Annot -/Rect [282.6 438.614 288 449.927] -/Border [0 0 0] ->> -endobj -5780 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5781 0 obj -<< -/Subtype /Link -/A 5780 0 R -/Type /Annot -/Rect [288 438.614 336.6 449.927] -/Border [0 0 0] ->> -endobj -5782 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5783 0 obj -<< -/Subtype /Link -/A 5782 0 R -/Type /Annot -/Rect [336.6 438.614 342 449.927] -/Border [0 0 0] ->> -endobj -5784 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5785 0 obj -<< -/Subtype /Link -/A 5784 0 R -/Type /Annot -/Rect [342 438.614 347.4 449.927] -/Border [0 0 0] ->> -endobj -5786 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5787 0 obj -<< -/Subtype /Link -/A 5786 0 R -/Type /Annot -/Rect [347.4 438.614 352.8 449.927] -/Border [0 0 0] ->> -endobj -5788 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5789 0 obj -<< -/Subtype /Link -/A 5788 0 R -/Type /Annot -/Rect [352.8 438.614 385.2 449.927] -/Border [0 0 0] ->> -endobj -5790 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5791 0 obj -<< -/Subtype /Link -/A 5790 0 R -/Type /Annot -/Rect [385.2 438.614 390.6 449.927] -/Border [0 0 0] ->> -endobj -5792 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5793 0 obj -<< -/Subtype /Link -/A 5792 0 R -/Type /Annot -/Rect [72 427.301 88.2 438.614] -/Border [0 0 0] ->> -endobj -5794 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5795 0 obj -<< -/Subtype /Link -/A 5794 0 R -/Type /Annot -/Rect [88.2 427.301 93.6 438.614] -/Border [0 0 0] ->> -endobj -5796 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5797 0 obj -<< -/Subtype /Link -/A 5796 0 R -/Type /Annot -/Rect [93.6 427.301 115.2 438.614] -/Border [0 0 0] ->> -endobj -5798 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5799 0 obj -<< -/Subtype /Link -/A 5798 0 R -/Type /Annot -/Rect [115.2 427.301 120.6 438.614] -/Border [0 0 0] ->> -endobj -5800 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5801 0 obj -<< -/Subtype /Link -/A 5800 0 R -/Type /Annot -/Rect [120.6 427.301 169.2 438.614] -/Border [0 0 0] ->> -endobj -5802 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5803 0 obj -<< -/Subtype /Link -/A 5802 0 R -/Type /Annot -/Rect [169.2 427.301 174.6 438.614] -/Border [0 0 0] ->> -endobj -5804 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5805 0 obj -<< -/Subtype /Link -/A 5804 0 R -/Type /Annot -/Rect [174.6 427.301 180 438.614] -/Border [0 0 0] ->> -endobj -5806 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5807 0 obj -<< -/Subtype /Link -/A 5806 0 R -/Type /Annot -/Rect [72 404.801 282.390625 417.301] -/Border [0 0 0] ->> -endobj -5808 0 obj -<< -/Subtype /Underline -/QuadPoints [92 384.397 236.475 384.397 92 361.272 236.475 361.272] -/Contents () -/Type /Annot -/Rect [92 361.272 236.475 384.397] -/Border [0 0 0] -/C [0 0 1] ->> -endobj -5809 0 obj -<< -/S /URI -/URI (http://google.com/) ->> -endobj -5810 0 obj -<< -/Subtype /Link -/A 5809 0 R -/Type /Annot -/Rect [92 361.272 236.475 384.397] -/Border [0 0 0] ->> -endobj -5811 0 obj -<< -/Subtype /Highlight -/QuadPoints [92 326.597 345.525 326.597 92 303.472 345.525 303.472] -/Contents () -/Type /Annot -/Rect [92 303.472 345.525 326.597] -/Border [0 0 0] -/C [0.945098 0.933333 0.580392] ->> -endobj -5812 0 obj -<< -/Subtype /StrikeOut -/QuadPoints [92 268.797 189.25 268.797 92 245.672 189.25 245.672] -/Contents () -/Type /Annot -/Rect [92 245.672 189.25 268.797] -/Border [0 0 0] -/C [0 0 0] ->> -endobj -5813 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5814 0 obj -<< -/Subtype /Link -/A 5813 0 R -/Type /Annot -/Rect [72 207.397 517.263672 219.897] -/Border [0 0 0] ->> -endobj -5815 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5816 0 obj -<< -/Subtype /Link -/A 5815 0 R -/Type /Annot -/Rect [72 194.897 526.013672 207.397] -/Border [0 0 0] ->> -endobj -5817 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5818 0 obj -<< -/Subtype /Link -/A 5817 0 R -/Type /Annot -/Rect [72 182.397 499.138672 194.897] -/Border [0 0 0] ->> -endobj -5819 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5820 0 obj -<< -/Subtype /Link -/A 5819 0 R -/Type /Annot -/Rect [72 169.897 319.036133 182.397] -/Border [0 0 0] ->> -endobj -5821 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5822 0 obj -<< -/Subtype /Link -/A 5821 0 R -/Type /Annot -/Rect [72 148.584 88.2 159.897] -/Border [0 0 0] ->> -endobj -5823 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5824 0 obj -<< -/Subtype /Link -/A 5823 0 R -/Type /Annot -/Rect [88.2 148.584 93.6 159.897] -/Border [0 0 0] ->> -endobj -5825 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5826 0 obj -<< -/Subtype /Link -/A 5825 0 R -/Type /Annot -/Rect [93.6 148.584 136.8 159.897] -/Border [0 0 0] ->> -endobj -5827 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5828 0 obj -<< -/Subtype /Link -/A 5827 0 R -/Type /Annot -/Rect [136.8 148.584 142.2 159.897] -/Border [0 0 0] ->> -endobj -5829 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5830 0 obj -<< -/Subtype /Link -/A 5829 0 R -/Type /Annot -/Rect [142.2 148.584 153 159.897] -/Border [0 0 0] ->> -endobj -5831 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5832 0 obj -<< -/Subtype /Link -/A 5831 0 R -/Type /Annot -/Rect [153 148.584 158.4 159.897] -/Border [0 0 0] ->> -endobj -5833 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5834 0 obj -<< -/Subtype /Link -/A 5833 0 R -/Type /Annot -/Rect [72 137.271 88.2 148.584] -/Border [0 0 0] ->> -endobj -5835 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5836 0 obj -<< -/Subtype /Link -/A 5835 0 R -/Type /Annot -/Rect [88.2 137.271 93.6 148.584] -/Border [0 0 0] ->> -endobj -5837 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5838 0 obj -<< -/Subtype /Link -/A 5837 0 R -/Type /Annot -/Rect [93.6 137.271 142.2 148.584] -/Border [0 0 0] ->> -endobj -5839 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5840 0 obj -<< -/Subtype /Link -/A 5839 0 R -/Type /Annot -/Rect [142.2 137.271 147.6 148.584] -/Border [0 0 0] ->> -endobj -5841 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5842 0 obj -<< -/Subtype /Link -/A 5841 0 R -/Type /Annot -/Rect [147.6 137.271 174.6 148.584] -/Border [0 0 0] ->> -endobj -5843 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5844 0 obj -<< -/Subtype /Link -/A 5843 0 R -/Type /Annot -/Rect [174.6 137.271 180 148.584] -/Border [0 0 0] ->> -endobj -5845 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5846 0 obj -<< -/Subtype /Link -/A 5845 0 R -/Type /Annot -/Rect [72 125.958 88.2 137.271] -/Border [0 0 0] ->> -endobj -5847 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5848 0 obj -<< -/Subtype /Link -/A 5847 0 R -/Type /Annot -/Rect [88.2 125.958 93.6 137.271] -/Border [0 0 0] ->> -endobj -5849 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5850 0 obj -<< -/Subtype /Link -/A 5849 0 R -/Type /Annot -/Rect [93.6 125.958 115.2 137.271] -/Border [0 0 0] ->> -endobj -5851 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5852 0 obj -<< -/Subtype /Link -/A 5851 0 R -/Type /Annot -/Rect [115.2 125.958 120.6 137.271] -/Border [0 0 0] ->> -endobj -5853 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5854 0 obj -<< -/Subtype /Link -/A 5853 0 R -/Type /Annot -/Rect [120.6 125.958 201.6 137.271] -/Border [0 0 0] ->> -endobj -5855 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5856 0 obj -<< -/Subtype /Link -/A 5855 0 R -/Type /Annot -/Rect [201.6 125.958 207 137.271] -/Border [0 0 0] ->> -endobj -5857 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5858 0 obj -<< -/Subtype /Link -/A 5857 0 R -/Type /Annot -/Rect [207 125.958 212.4 137.271] -/Border [0 0 0] ->> -endobj -5859 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5860 0 obj -<< -/Subtype /Link -/A 5859 0 R -/Type /Annot -/Rect [212.4 125.958 223.2 137.271] -/Border [0 0 0] ->> -endobj -5861 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5862 0 obj -<< -/Subtype /Link -/A 5861 0 R -/Type /Annot -/Rect [223.2 125.958 228.6 137.271] -/Border [0 0 0] ->> -endobj -5863 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5864 0 obj -<< -/Subtype /Link -/A 5863 0 R -/Type /Annot -/Rect [228.6 125.958 234 137.271] -/Border [0 0 0] ->> -endobj -5865 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5866 0 obj -<< -/Subtype /Link -/A 5865 0 R -/Type /Annot -/Rect [234 125.958 239.4 137.271] -/Border [0 0 0] ->> -endobj -5867 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5868 0 obj -<< -/Subtype /Link -/A 5867 0 R -/Type /Annot -/Rect [239.4 125.958 244.8 137.271] -/Border [0 0 0] ->> -endobj -5869 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5870 0 obj -<< -/Subtype /Link -/A 5869 0 R -/Type /Annot -/Rect [244.8 125.958 250.2 137.271] -/Border [0 0 0] ->> -endobj -5871 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5872 0 obj -<< -/Subtype /Link -/A 5871 0 R -/Type /Annot -/Rect [250.2 125.958 255.6 137.271] -/Border [0 0 0] ->> -endobj -5873 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5874 0 obj -<< -/Subtype /Link -/A 5873 0 R -/Type /Annot -/Rect [72 114.645 99 125.958] -/Border [0 0 0] ->> -endobj -5875 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5876 0 obj -<< -/Subtype /Link -/A 5875 0 R -/Type /Annot -/Rect [99 114.645 120.6 125.958] -/Border [0 0 0] ->> -endobj -5877 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5878 0 obj -<< -/Subtype /Link -/A 5877 0 R -/Type /Annot -/Rect [120.6 114.645 126 125.958] -/Border [0 0 0] ->> -endobj -5879 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5880 0 obj -<< -/Subtype /Link -/A 5879 0 R -/Type /Annot -/Rect [126 114.645 131.4 125.958] -/Border [0 0 0] ->> -endobj -5881 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5882 0 obj -<< -/Subtype /Link -/A 5881 0 R -/Type /Annot -/Rect [131.4 114.645 234 125.958] -/Border [0 0 0] ->> -endobj -5883 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5884 0 obj -<< -/Subtype /Link -/A 5883 0 R -/Type /Annot -/Rect [234 114.645 239.4 125.958] -/Border [0 0 0] ->> -endobj -5885 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5886 0 obj -<< -/Subtype /Link -/A 5885 0 R -/Type /Annot -/Rect [72 103.332 99 114.645] -/Border [0 0 0] ->> -endobj -5887 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5888 0 obj -<< -/Subtype /Link -/A 5887 0 R -/Type /Annot -/Rect [99 103.332 147.6 114.645] -/Border [0 0 0] ->> -endobj -5889 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5890 0 obj -<< -/Subtype /Link -/A 5889 0 R -/Type /Annot -/Rect [147.6 103.332 153 114.645] -/Border [0 0 0] ->> -endobj -5891 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5892 0 obj -<< -/Subtype /Link -/A 5891 0 R -/Type /Annot -/Rect [153 103.332 158.4 114.645] -/Border [0 0 0] ->> -endobj -5893 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5894 0 obj -<< -/Subtype /Link -/A 5893 0 R -/Type /Annot -/Rect [158.4 103.332 180 114.645] -/Border [0 0 0] ->> -endobj -5895 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5896 0 obj -<< -/Subtype /Link -/A 5895 0 R -/Type /Annot -/Rect [72 92.019 88.2 103.332] -/Border [0 0 0] ->> -endobj -5897 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5898 0 obj -<< -/Subtype /Link -/A 5897 0 R -/Type /Annot -/Rect [88.2 92.019 93.6 103.332] -/Border [0 0 0] ->> -endobj -5899 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5900 0 obj -<< -/Subtype /Link -/A 5899 0 R -/Type /Annot -/Rect [72 80.706 77.4 92.019] -/Border [0 0 0] ->> -endobj -5901 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5902 0 obj -<< -/Subtype /Link -/A 5901 0 R -/Type /Annot -/Rect [77.4 80.706 82.8 92.019] -/Border [0 0 0] ->> -endobj -5461 0 obj -<< -/Type /Page -/Parent 1 0 R -/MediaBox [0 0 612 792] -/Contents 5459 0 R -/Resources 5460 0 R -/Annots [5463 0 R 5465 0 R 5467 0 R 5469 0 R 5471 0 R 5473 0 R 5475 0 R 5477 0 R 5479 0 R 5481 0 R 5483 0 R 5485 0 R 5487 0 R 5489 0 R 5491 0 R 5493 0 R 5495 0 R 5497 0 R 5499 0 R 5501 0 R 5503 0 R 5505 0 R 5507 0 R 5509 0 R 5511 0 R 5513 0 R 5515 0 R 5517 0 R 5519 0 R 5521 0 R 5523 0 R 5525 0 R 5527 0 R 5529 0 R 5531 0 R 5533 0 R 5535 0 R 5537 0 R 5539 0 R 5541 0 R 5543 0 R 5545 0 R 5547 0 R 5549 0 R 5551 0 R 5553 0 R 5555 0 R 5557 0 R 5559 0 R 5561 0 R 5563 0 R 5565 0 R 5567 0 R 5569 0 R 5571 0 R 5573 0 R 5575 0 R 5577 0 R 5579 0 R 5581 0 R 5583 0 R 5585 0 R 5587 0 R 5589 0 R 5591 0 R 5593 0 R 5595 0 R 5597 0 R 5599 0 R 5601 0 R 5603 0 R 5605 0 R 5607 0 R 5609 0 R 5611 0 R 5613 0 R 5615 0 R 5617 0 R 5619 0 R 5621 0 R 5623 0 R 5625 0 R 5627 0 R 5629 0 R 5631 0 R 5633 0 R 5635 0 R 5637 0 R 5639 0 R 5641 0 R 5643 0 R 5645 0 R 5647 0 R 5649 0 R 5651 0 R 5653 0 R 5655 0 R 5657 0 R 5659 0 R 5661 0 R 5663 0 R 5665 0 R 5667 0 R 5669 0 R 5671 0 R 5673 0 R 5675 0 R 5677 0 R 5679 0 R 5681 0 R 5683 0 R 5685 0 R 5687 0 R 5689 0 R 5691 0 R 5693 0 R 5695 0 R 5697 0 R 5699 0 R 5701 0 R 5703 0 R 5705 0 R 5707 0 R 5709 0 R 5711 0 R 5713 0 R 5715 0 R 5717 0 R 5719 0 R 5721 0 R 5723 0 R 5725 0 R 5727 0 R 5729 0 R 5731 0 R 5733 0 R 5735 0 R 5737 0 R 5739 0 R 5741 0 R 5743 0 R 5745 0 R 5747 0 R 5749 0 R 5751 0 R 5753 0 R 5755 0 R 5757 0 R 5759 0 R 5761 0 R 5763 0 R 5765 0 R 5767 0 R 5769 0 R 5771 0 R 5773 0 R 5775 0 R 5777 0 R 5779 0 R 5781 0 R 5783 0 R 5785 0 R 5787 0 R 5789 0 R 5791 0 R 5793 0 R 5795 0 R 5797 0 R 5799 0 R 5801 0 R 5803 0 R 5805 0 R 5807 0 R 5808 0 R 5810 0 R 5811 0 R 5812 0 R 5814 0 R 5816 0 R 5818 0 R 5820 0 R 5822 0 R 5824 0 R 5826 0 R 5828 0 R 5830 0 R 5832 0 R 5834 0 R 5836 0 R 5838 0 R 5840 0 R 5842 0 R 5844 0 R 5846 0 R 5848 0 R 5850 0 R 5852 0 R 5854 0 R 5856 0 R 5858 0 R 5860 0 R 5862 0 R 5864 0 R 5866 0 R 5868 0 R 5870 0 R 5872 0 R 5874 0 R 5876 0 R 5878 0 R 5880 0 R 5882 0 R 5884 0 R 5886 0 R 5888 0 R 5890 0 R 5892 0 R 5894 0 R 5896 0 R 5898 0 R 5900 0 R 5902 0 R] ->> -endobj -5460 0 obj -<< -/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] -/Font << -/F3 9 0 R -/F5 29 0 R -/F1 3849 0 R ->> ->> -endobj -5459 0 obj -<< -/Length 2610 -/Filter /FlateDecode ->> -stream -x]Ɏ6Wp_Y-ȡ Cå(Sr;2I hX$@-|?~2^U/p Q19Jap]]>ܥ{u/ξwt(|?ûWp/[б\xG=}T1˯KJj7Wi3*!"y`u9^'0yKDdBK|29u;UF1-$p˨vZ M1KfEhвd=%'#85l1#BgBq5:UDOA܉Jw i8E)aKF-QFSnK2vR`q\Tkxtqxݓjt}Xt=NcÈ=?.Ze5YzQQQލ - 0h0ՈfiX}F4V`H1*+#bee&,jlmUIk*6lh;~C{н"xAUTm$b s[)j9\꒔ztԃ}j޾=c#Ѷ ~|bxcGfׯxF7_毗VPWy/fh -OkqP>J\4oIJ] >pD?.z*^W+G*[`ߵ9S-;Zh L w;ol x /Գ(,:镼/pMsЩz0G_ GM;ʐCj`YZw\;])іJFB9M C%q&RTR h|f_tV&铩F%#2)#[h(;O %hi;ׂڔʆsd]Gݰ<Əz@i<=nȝTjdA*ۅ>b{ 'Q4uWTS~no?F9q yRpzgn((؆?2ˉ-xM|s=4=K^NJq2 Nc_#;WRj?&aTk$5}Ҿb±.@E]Tl(aJGs͒|]f8y'$P3]p1o_B垝8g !F8hRe&HVPotrR+l&:Δ3uvّ@lWvJ浙u3aiD`D>DC@+eD4n51jNczKz[\\s< ߳|- cpڪ1j(vi r&Hb!sU?2ix bTOCȦ8;ϸ Hc@wck(~ƯOAZ/J5DxkABz}P]_(Tqh=cdڲ6cv4(ZoGZ&{FXK鞰,yQM`E^'t>ӸLjtJڑ9 ӘCDwEi·>T]%pd;FC"VOp9Kpr=4:.xCbHrw#!Jݛ(U(~†TQp \z< wIg!If?(g`1,椢iFq^l Nc#RX.F\ X7?Xzc411cѣe04;+DY=)?"jXs#Ϳw GHrhEuyz:hǠŵt N -'V;꠬:wĻijFVZ %? b*~o_JʕOK!'cflE!`8 -P/sI\ΠKA'OY<{F.u$(Q׻Cp]ƹ`<릹40w2/rǐS%a:, OCp;sJO-9D{=O\&ʀi{:[R8!᣸F}i7bp/FABR(0YgK86j{`X᯹Ir/K(NbT>u0+a!Q+h P$ֳ$}$N0S=R!X^TclbL98ڍ!7[g}Bf^ZNMi'YDpV| -B9ZydլBp̊x̷5@z)IƊQn6~Aci{]˵nga(n-Fz, -endstream -endobj -5906 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5907 0 obj -<< -/Subtype /Link -/A 5906 0 R -/Type /Annot -/Rect [72 707.5 220.330078 720] -/Border [0 0 0] ->> -endobj -5908 0 obj -<< -/S /URI -/URI (http://apple.com/) ->> -endobj -5909 0 obj -<< -/Subtype /Link -/A 5908 0 R -/Type /Annot -/Rect [92 668.596 203.16 687.096] -/Border [0 0 0] ->> -endobj -5905 0 obj -<< -/Type /Page -/Parent 1 0 R -/MediaBox [0 0 612 792] -/Contents 5903 0 R -/Resources 5904 0 R -/Annots [5907 0 R 5909 0 R] ->> -endobj -5904 0 obj -<< -/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] -/Font << -/F3 9 0 R -/F1 3849 0 R ->> ->> -endobj -5903 0 obj -<< -/Length 225 -/Filter /FlateDecode ->> -stream -xPjA +&ą҃ -=έt -Eo]p2y<&<_ =<\>VsG~ozi,21,d´'"Q"fr1=ѷgʵqy2'y3A9ZMyF w 0Qu'fяLx ihqp`^;wQ3 jYn-L[!ye#o5jb -endstream -endobj -5914 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5915 0 obj -<< -/Subtype /Link -/A 5914 0 R -/Type /Annot -/Rect [72 685.975 200.75 720] -/Border [0 0 0] ->> -endobj -5916 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5917 0 obj -<< -/Subtype /Link -/A 5916 0 R -/Type /Annot -/Rect [72 658.475 513.044922 670.975] -/Border [0 0 0] ->> -endobj -5918 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5919 0 obj -<< -/Subtype /Link -/A 5918 0 R -/Type /Annot -/Rect [72 645.975 356.829102 658.475] -/Border [0 0 0] ->> -endobj -5920 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5921 0 obj -<< -/Subtype /Link -/A 5920 0 R -/Type /Annot -/Rect [72 623.475 495.291016 635.975] -/Border [0 0 0] ->> -endobj -5922 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5923 0 obj -<< -/Subtype /Link -/A 5922 0 R -/Type /Annot -/Rect [72 610.975 536.570313 623.475] -/Border [0 0 0] ->> -endobj -5924 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5925 0 obj -<< -/Subtype /Link -/A 5924 0 R -/Type /Annot -/Rect [72 598.475 296.614258 610.975] -/Border [0 0 0] ->> -endobj -5926 0 obj -<< -/S /URI -/URI (http://github.com/devongovett/pdfkit/tree/master/docs/generate.coffee) ->> -endobj -5927 0 obj -<< -/Subtype /Link -/A 5926 0 R -/Type /Annot -/Rect [296.614258 598.475 346.375 610.975] -/Border [0 0 0] ->> -endobj -5928 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5929 0 obj -<< -/Subtype /Link -/A 5928 0 R -/Type /Annot -/Rect [346.375 598.475 519.246094 610.975] -/Border [0 0 0] ->> -endobj -5930 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5931 0 obj -<< -/Subtype /Link -/A 5930 0 R -/Type /Annot -/Rect [72 585.975 526.838867 598.475] -/Border [0 0 0] ->> -endobj -5932 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5933 0 obj -<< -/Subtype /Link -/A 5932 0 R -/Type /Annot -/Rect [72 573.475 132.146484 585.975] -/Border [0 0 0] ->> -endobj -5934 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5935 0 obj -<< -/Subtype /Link -/A 5934 0 R -/Type /Annot -/Rect [72 550.975 523.181641 563.475] -/Border [0 0 0] ->> -endobj -5936 0 obj -<< -/S /URI -/URI (http://twitter.com/devongovett) ->> -endobj -5937 0 obj -<< -/Subtype /Link -/A 5936 0 R -/Type /Annot -/Rect [72 538.475 144.172852 550.975] -/Border [0 0 0] ->> -endobj -5938 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5939 0 obj -<< -/Subtype /Link -/A 5938 0 R -/Type /Annot -/Rect [144.172852 538.475 242.517578 550.975] -/Border [0 0 0] ->> -endobj -5940 0 obj -<< -/S /URI -/URI (http://github.com/devongovett/pdfkit/issues) ->> -endobj -5941 0 obj -<< -/Subtype /Link -/A 5940 0 R -/Type /Annot -/Rect [242.517578 538.475 276.897461 550.975] -/Border [0 0 0] ->> -endobj -5942 0 obj -<< -/S /URI -/URI (false) ->> -endobj -5943 0 obj -<< -/Subtype /Link -/A 5942 0 R -/Type /Annot -/Rect [276.897461 538.475 314.402344 550.975] -/Border [0 0 0] ->> -endobj -5912 0 obj -<< -/Type /Page -/Parent 1 0 R -/MediaBox [0 0 612 792] -/Contents 5910 0 R -/Resources 5911 0 R -/Annots [5915 0 R 5917 0 R 5919 0 R 5921 0 R 5923 0 R 5925 0 R 5927 0 R 5929 0 R 5931 0 R 5933 0 R 5935 0 R 5937 0 R 5939 0 R 5941 0 R 5943 0 R] ->> -endobj -5911 0 obj -<< -/ProcSet [/PDF /Text /ImageB /ImageC /ImageI] -/Font << -/F4 16 0 R -/F3 9 0 R ->> ->> -endobj -5910 0 obj -<< -/Length 835 -/Filter /FlateDecode ->> -stream -xWɎ0 +MEj"A=dB*,hlK=>*t{_P???'5t:dv4 *xG| -oqU \:i<ǁeN8L@(9-s&@kr\ސ3;l3{:;IqM8K#Ix}9L%5?Y]g}5QXG.u))wBɱ{{eC>2g{^`x 8Wϻk6SXQqj1Y85%9HrDv(6Ռ{MF b>+h:Źr!א?)p  ,\Ld-<}7&F`<<dr]a4'aW͆w(AfgDDԒ`h -_X[H/ -FĒɪELYxOBrsnş}?;n.< Vn t#W7Bfe݊YXWJe/J7ә~7",@'n]jQg7.+{KotB`ܔX&9ڲ[[1wfm6i{w޶~^9^`fF"gVXAp?gXp6fԴ̱ R_&p<- -endstream -endobj -5945 0 obj -(PDFKit) -endobj -5946 0 obj -(PDFKit) -endobj -5947 0 obj -(D:20190128044916Z) -endobj -5944 0 obj -<< -/Producer 5945 0 R -/Creator 5946 0 R -/CreationDate 5947 0 R ->> -endobj -3849 0 obj -<< -/Type /Font -/BaseFont /Helvetica -/Subtype /Type1 -/Encoding /WinAnsiEncoding ->> -endobj -5949 0 obj -<< -/Type /FontDescriptor -/FontName /BZZZZZ+AlegreyaSans-Light -/Flags 4 -/FontBBox [-240 -264 1137 967] -/ItalicAngle 0 -/Ascent 900 -/Descent -300 -/CapHeight 639 -/XHeight 495 -/StemV 0 -/FontFile2 5948 0 R ->> -endobj -5950 0 obj -<< -/Type /Font -/Subtype /CIDFontType2 -/BaseFont /BZZZZZ+AlegreyaSans-Light -/CIDSystemInfo << -/Registry (Adobe) -/Ordering (Identity) -/Supplement 0 ->> -/FontDescriptor 5949 0 R -/W [0 [172 503 642 423 528 231 309 172 602 508 512 443 516 416 415 489 509]] ->> -endobj -5951 0 obj -<< -/Length 265 -/Filter /FlateDecode ->> -stream -x]Qj0 +t%MHS!0KƲ-b9g[Y;&{Orvn[ڋaqR[ k(CKo%W~]Z"9č]Gd!DS C-ћi yOeIP 'My$UqU8Dq:\DxMJ -endstream -endobj -7 0 obj -<< -/Type /Font -/Subtype /Type0 -/BaseFont /BZZZZZ+AlegreyaSans-Light -/Encoding /Identity-H -/DescendantFonts [5950 0 R] -/ToUnicode 5951 0 R ->> -endobj -5953 0 obj -<< -/Type /FontDescriptor -/FontName /CZZZZZ+Merriweather -/Flags 6 -/FontBBox [-41.992187 -312.5 1199.707031 937.5] -/ItalicAngle 0 -/Ascent 937.5 -/Descent -312.5 -/CapHeight 758.300781 -/XHeight 546.386719 -/StemV 0 -/FontFile2 5952 0 R ->> -endobj -5954 0 obj -<< -/Type /Font -/Subtype /CIDFontType2 -/BaseFont /CZZZZZ+Merriweather -/CIDSystemInfo << -/Registry (Adobe) -/Ordering (Identity) -/Supplement 0 ->> -/FontDescriptor 5953 0 R -/W [0 [1770 695.800781 559.082031 450.683594 511.71875 333.496094 601.074219 681.640625 255.371094 647.949219 344.726563 615.234375 372.558594 420.898438 559.082031 340.820313 630.859375 685.546875 646.484375 1010.742188 510.253906 622.070313 587.402344 351.5625 561.523438 408.691406 826.171875 619.628906 688.476563 632.8125 777.832031 604.492188 692.871094 606.445313 580.078125 600.097656 617.1875 811.523438 620.117188 400.390625 334.472656 1025.878906 526.367188 833.007813 570.3125 526.855469 729.003906 610.839844 344.726563 692.871094 750 769.53125 692.871094 607.421875 605.957031 396.972656 396.972656 660.15625 317.382813 603.515625 596.191406 455.566406 344.726563 644.042969 398.4375 524.414063 611.816406 605.957031 758.789063 965.332031 494.140625 615.234375 693.359375 660.15625 619.628906]] ->> -endobj -5955 0 obj -<< -/Length 390 -/Filter /FlateDecode ->> -stream -x]Sn0>h%T}dȁIU$2*Kz+/,}uia]oy<;MSogK¯)I=^煆v#+͗ŭl`Ɩn܋3z{bc2yi ۤ,=5s3Ku__uY׎u"C|%=Fk쉒?eLȚHj̃lJy U SrH: GRSr Ąy- : Q0Af1N &r$U5%+89*D9L 4G$4 -*&!ͱ4~*ythr+ )Q$q)(ڮNCڎr윿eNtxqX̐ -endstream -endobj -9 0 obj -<< -/Type /Font -/Subtype /Type0 -/BaseFont /CZZZZZ+Merriweather -/Encoding /Identity-H -/DescendantFonts [5954 0 R] -/ToUnicode 5955 0 R ->> -endobj -5957 0 obj -<< -/Type /FontDescriptor -/FontName /DZZZZZ+Alegreya-Bold -/Flags 6 -/FontBBox [-205 -318 1042 977] -/ItalicAngle 0 -/Ascent 1016 -/Descent -345 -/CapHeight 642 -/XHeight 462 -/StemV 0 -/FontFile2 5956 0 R ->> -endobj -5958 0 obj -<< -/Type /Font -/Subtype /CIDFontType2 -/BaseFont /DZZZZZ+Alegreya-Bold -/CIDSystemInfo << -/Registry (Adobe) -/Ordering (Identity) -/Supplement 0 ->> -/FontDescriptor 5957 0 R -/W [0 [174 654 463 332 293 570 512 174 540 479 413 537 740 544 577 693 532 659 365 409 265 503 617 432 547 839 655 514 625 538 468 597 465 625 519 531 274 964 569 342 497 623 643 674 598 285]] ->> -endobj -5959 0 obj -<< -/Length 329 -/Filter /FlateDecode ->> -stream -x]R=o0 Éi%T]~SsTBr!vF']tgkqB4 (C>BV>EȣQKrV^ NS4 /̤a r,D - Rr"̈E<((VT).& F@PgllM` -)XzQ%_2[pyըy|muW ;G SƊFG -endstream -endobj -16 0 obj -<< -/Type /Font -/Subtype /Type0 -/BaseFont /DZZZZZ+Alegreya-Bold -/Encoding /Identity-H -/DescendantFonts [5958 0 R] -/ToUnicode 5959 0 R ->> -endobj -5961 0 obj -<< -/Type /FontDescriptor -/FontName /EZZZZZ+SourceCodePro-Regular -/Flags 5 -/FontBBox [-39 -400 706 1000] -/ItalicAngle 0 -/Ascent 984 -/Descent -273 -/CapHeight 660 -/XHeight 480 -/StemV 0 -/FontFile2 5960 0 R ->> -endobj -5962 0 obj -<< -/Type /Font -/Subtype /CIDFontType2 -/BaseFont /EZZZZZ+SourceCodePro-Regular -/CIDSystemInfo << -/Registry (Adobe) -/Ordering (Identity) -/Supplement 0 ->> -/FontDescriptor 5961 0 R -/W [0 [600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600]] ->> -endobj -5963 0 obj -<< -/Length 409 -/Filter /FlateDecode ->> -stream -x]Sj0+tLv -PK}д҃m5ۤԐ -tx> -endobj -5965 0 obj -<< -/Type /FontDescriptor -/FontName /FZZZZZ+SourceCodePro-Bold -/Flags 5 -/FontBBox [-69 -400 705 1000] -/ItalicAngle 0 -/Ascent 984 -/Descent -273 -/CapHeight 660 -/XHeight 480 -/StemV 0 -/FontFile2 5964 0 R ->> -endobj -5966 0 obj -<< -/Type /Font -/Subtype /CIDFontType2 -/BaseFont /FZZZZZ+SourceCodePro-Bold -/CIDSystemInfo << -/Registry (Adobe) -/Ordering (Identity) -/Supplement 0 ->> -/FontDescriptor 5965 0 R -/W [0 [600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600]] ->> -endobj -5967 0 obj -<< -/Length 377 -/Filter /FlateDecode ->> -stream -x]Sn0>6JJ/PiOUdȁlHd |,mՍmEzkٵ$:6:Hav*C=Ey(<"~yq=ً3z{cTi"n:/TO@"~{?ue VjGCTj{(Ww*"_/[xi!>eH5 4{PKx^_d6JP`& +B/H=f?6J˰R -1 {;42Pc -%~NR%4{LAp)|MbwP4L(vF!&YkKol=;3·Ůt@qڦp4 -endstream -endobj -44 0 obj -<< -/Type /Font -/Subtype /Type0 -/BaseFont /FZZZZZ+SourceCodePro-Bold -/Encoding /Identity-H -/DescendantFonts [5966 0 R] -/ToUnicode 5967 0 R ->> -endobj -4548 0 obj -<< -/Type /Font -/BaseFont /Times-Roman -/Subtype /Type1 -/Encoding /WinAnsiEncoding ->> -endobj -5969 0 obj -<< -/Type /FontDescriptor -/FontName /HZZZZZ+GoodDog -/Flags 4 -/FontBBox [-107.421875 -174.804687 1034.667969 641.601563] -/ItalicAngle 0 -/Ascent 836.914063 -/Descent -174.804687 -/CapHeight 591.308594 -/XHeight 442.382813 -/StemV 0 -/FontFile2 5968 0 R ->> -endobj -5970 0 obj -<< -/Type /Font -/Subtype /CIDFontType2 -/BaseFont /HZZZZZ+GoodDog -/CIDSystemInfo << -/Registry (Adobe) -/Ordering (Identity) -/Supplement 0 ->> -/FontDescriptor 5969 0 R -/W [0 [378 431.640625 337.890625 184.570313 344.726563 184.570313 393.554688 281.738281 369.628906 379.882813 326.660156 230.957031]] ->> -endobj -5971 0 obj -<< -/Length 255 -/Filter /FlateDecode ->> -stream -x]QMO +6lku5iHzX=/uH/3o{@_=PH]@pԆT5H-SL::,-o_a W)%zmF}qB@*^3h;y}T]*WP*- +qv\fDb4 >/M}u4©ElJM>I;{fpi?p%U? -endstream -endobj -4549 0 obj -<< -/Type /Font -/Subtype /Type0 -/BaseFont /HZZZZZ+GoodDog -/Encoding /Identity-H -/DescendantFonts [5970 0 R] -/ToUnicode 5971 0 R ->> -endobj -5973 0 obj -<< -/Type /FontDescriptor -/FontName /IZZZZZ+Chalkboard-Bold -/Flags 4 -/FontBBox [-163.535912 -615.469613 2017.679558 1358.01105] -/ItalicAngle 0 -/Ascent 980.110497 -/Descent -282.872928 -/CapHeight 712.707182 -/XHeight 525.966851 -/StemV 0 -/FontFile2 5972 0 R ->> -endobj -5974 0 obj -<< -/Type /Font -/Subtype /CIDFontType2 -/BaseFont /IZZZZZ+Chalkboard-Bold -/CIDSystemInfo << -/Registry (Adobe) -/Ordering (Identity) -/Supplement 0 ->> -/FontDescriptor 5973 0 R -/W [0 [540 591.160221 565.745856 271.823204 453.038674 414.364641 608.839779 558.01105 322.651934 550.276243 581.21547 509.392265 459.668508 600 299.447514 532.596685 479.558011 759.116022 514.917127 609.944751 339.226519]] ->> -endobj -5975 0 obj -<< -/Length 275 -/Filter /FlateDecode ->> -stream -x]=o w!r:i+YHUxv2pXH5 LGH=(Sޣp#NJU BqUZ<آ ~]<Νڶ(Cxnͣ0#ĽW')=اl7Ψ= -@ 2en;ʯf|N+q#pG7 vke@-i!j|]I8njJiH*' ɗլs&R,$TsBvom|NlU\RԞJHU@ -endstream -endobj -4550 0 obj -<< -/Type /Font -/Subtype /Type0 -/BaseFont /IZZZZZ+Chalkboard-Bold -/Encoding /Identity-H -/DescendantFonts [5974 0 R] -/ToUnicode 5975 0 R ->> -endobj -8 0 obj -<< -/Dest [6 0 R /Fit] -/Parent 3 0 R -/Title (PDFKit Guide) -/Next 13 0 R ->> -endobj -190 0 obj -<< -/Dest [189 0 R /Fit] -/Parent 13 0 R -/Title (Using PDFKit in the browser) -/Next 508 0 R ->> -endobj -508 0 obj -<< -/Dest [507 0 R /Fit] -/Parent 13 0 R -/Title (Adding pages) -/Prev 190 0 R -/Next 776 0 R ->> -endobj -776 0 obj -<< -/Dest [775 0 R /Fit] -/Parent 13 0 R -/Title (Switching to previous pages) -/Prev 508 0 R -/Next 1128 0 R ->> -endobj -1128 0 obj -<< -/Dest [1127 0 R /Fit] -/Parent 13 0 R -/Title (Setting document metadata) -/Prev 776 0 R -/Next 1172 0 R ->> -endobj -1172 0 obj -<< -/Dest [1171 0 R /Fit] -/Parent 13 0 R -/Title (Encryption and Access Privileges) -/Prev 1128 0 R ->> -endobj -13 0 obj -<< -/Dest [12 0 R /Fit] -/Parent 3 0 R -/Title (Getting Started with PDFKit) -/Prev 8 0 R -/Next 1385 0 R -/First 190 0 R -/Last 1172 0 R ->> -endobj -1388 0 obj -<< -/Dest [1384 0 R /Fit] -/Parent 1385 0 R -/Title (An introduction to vector graphics) -/Next 1608 0 R ->> -endobj -1608 0 obj -<< -/Dest [1607 0 R /Fit] -/Parent 1385 0 R -/Title (SVG paths) -/Prev 1388 0 R -/Next 1648 0 R ->> -endobj -1648 0 obj -<< -/Dest [1647 0 R /Fit] -/Parent 1385 0 R -/Title (Shape helpers) -/Prev 1608 0 R -/Next 1748 0 R ->> -endobj -1748 0 obj -<< -/Dest [1747 0 R /Fit] -/Parent 1385 0 R -/Title (Fill and stroke styles) -/Prev 1648 0 R -/Next 1806 0 R ->> -endobj -1806 0 obj -<< -/Dest [1805 0 R /Fit] -/Parent 1385 0 R -/Title (Line cap and line join) -/Prev 1748 0 R -/Next 2196 0 R ->> -endobj -2196 0 obj -<< -/Dest [2195 0 R /Fit] -/Parent 1385 0 R -/Title (Dashed lines) -/Prev 1806 0 R -/Next 2326 0 R ->> -endobj -2326 0 obj -<< -/Dest [2325 0 R /Fit] -/Parent 1385 0 R -/Title (Color) -/Prev 2196 0 R -/Next 2459 0 R ->> -endobj -2459 0 obj -<< -/Dest [2458 0 R /Fit] -/Parent 1385 0 R -/Title (Gradients) -/Prev 2326 0 R -/Next 2809 0 R ->> -endobj -2809 0 obj -<< -/Dest [2808 0 R /Fit] -/Parent 1385 0 R -/Title (Winding rules) -/Prev 2459 0 R -/Next 2973 0 R ->> -endobj -2973 0 obj -<< -/Dest [2972 0 R /Fit] -/Parent 1385 0 R -/Title (Saving and restoring the graphics stack) -/Prev 2809 0 R -/Next 3201 0 R ->> -endobj -3201 0 obj -<< -/Dest [3200 0 R /Fit] -/Parent 1385 0 R -/Title (Clipping) -/Prev 2973 0 R ->> -endobj -1385 0 obj -<< -/Dest [1384 0 R /Fit] -/Parent 3 0 R -/Title (Vector Graphics in PDFKit) -/Prev 13 0 R -/Next 3505 0 R -/First 1388 0 R -/Last 3201 0 R ->> -endobj -3508 0 obj -<< -/Dest [3504 0 R /Fit] -/Parent 3505 0 R -/Title (The basics) -/Next 3586 0 R ->> -endobj -3586 0 obj -<< -/Dest [3585 0 R /Fit] -/Parent 3505 0 R -/Title (Line wrapping and justification) -/Prev 3508 0 R -/Next 3853 0 R ->> -endobj -3853 0 obj -<< -/Dest [3852 0 R /Fit] -/Parent 3505 0 R -/Title (Text styling) -/Prev 3586 0 R -/Next 4116 0 R ->> -endobj -4116 0 obj -<< -/Dest [4115 0 R /Fit] -/Parent 3505 0 R -/Title (Text measurements) -/Prev 3853 0 R -/Next 4138 0 R ->> -endobj -4138 0 obj -<< -/Dest [4137 0 R /Fit] -/Parent 3505 0 R -/Title (Lists) -/Prev 4116 0 R -/Next 4168 0 R ->> -endobj -4168 0 obj -<< -/Dest [4167 0 R /Fit] -/Parent 3505 0 R -/Title (Rich Text) -/Prev 4138 0 R -/Next 4316 0 R ->> -endobj -4316 0 obj -<< -/Dest [4315 0 R /Fit] -/Parent 3505 0 R -/Title (Fonts) -/Prev 4168 0 R ->> -endobj -3505 0 obj -<< -/Dest [3504 0 R /Fit] -/Parent 3 0 R -/Title (Text in PDFKit) -/Prev 1385 0 R -/Next 4616 0 R -/First 3508 0 R -/Last 4316 0 R ->> -endobj -4616 0 obj -<< -/Dest [4615 0 R /Fit] -/Parent 3 0 R -/Title (Images in PDFKit) -/Prev 3505 0 R -/Next 5218 0 R ->> -endobj -5304 0 obj -<< -/Dest [5303 0 R /Fit] -/Parent 5218 0 R -/Title (Options) ->> -endobj -5218 0 obj -<< -/Dest [5217 0 R /Fit] -/Parent 3 0 R -/Title (Outlines in PDFKit) -/Prev 4616 0 R -/Next 5394 0 R -/First 5304 0 R -/Last 5304 0 R ->> -endobj -5394 0 obj -<< -/Dest [5393 0 R /Fit] -/Parent 3 0 R -/Title (Annotations in PDFKit) -/Prev 5218 0 R -/Next 5913 0 R ->> -endobj -5913 0 obj -<< -/Dest [5912 0 R /Fit] -/Parent 3 0 R -/Title (You made it!) -/Prev 5394 0 R ->> -endobj -3 0 obj -<< -/First 8 0 R -/Last 5913 0 R ->> -endobj -2 0 obj -<< -/Type /Catalog -/Pages 1 0 R -/Outlines 3 0 R -/PageMode /UseOutlines ->> -endobj -1 0 obj -<< -/Type /Pages -/Count 36 -/Kids [6 0 R 12 0 R 189 0 R 507 0 R 775 0 R 1127 0 R 1171 0 R 1319 0 R 1384 0 R 1607 0 R 1647 0 R 1747 0 R 1805 0 R 2195 0 R 2325 0 R 2458 0 R 2808 0 R 2972 0 R 3200 0 R 3504 0 R 3585 0 R 3852 0 R 3986 0 R 4115 0 R 4137 0 R 4167 0 R 4315 0 R 4511 0 R 4615 0 R 5207 0 R 5217 0 R 5303 0 R 5393 0 R 5461 0 R 5905 0 R 5912 0 R] ->> -endobj -5948 0 obj -<< -/Length 3400 -/Filter /FlateDecode ->> -stream -xW}p\Unn&Y>mimH$mCg&iKvv@G0"*Ta?t9o7--0nwϽ9w>mn_`58BqU>O\_ÿҭsPqHe -mMηcȱ;Kw.Vk>pʼ!|?T:/2vx톏3/>}\k(?ጉ0<_WZi#k`a8^\ -.Vjd{c -dQv E˔ ?}/BWkkkY߿_Y{k-Ng+ӹh.HIn))*1[bX7 vW$fIj=ԠPXN;P]RyS9?+JIۏ3P'vϳvT>],n, cǙ5p ]C< gTܙe.gn@X;ٚܤg !`l d>8#K|@onV~+?~S?SWT^~CH 2/;ٯ>Љ(Ɉob],v"J@`/S ID8wvۭ7䳅lD[o_Tׁ8=tuqu <ͯKen+L-$0qAؼ(^M:C1bB? .4V_ixI?oe'1+,;8c5i bl -nn2cQ%L{b@'FsvE`Z,xaOip9OQ.Y Tu=la>wɆ,wp }KS9*ʨ)E9%]>5#Rn,koq?ZY*# &Y`R 3x9ЖTisАͧ; xna\=?{SO>OhۻK_}oS˟.Ep!nĪyP`2.r_ ?n ZyW8 d3Y/4/.6 x,dZ[--JO g3V oKٳV~76ZaT׋>u/ƛ)FsMSiqθ4Ζli VK+V={o]DpG|)f>Sk=Ӏ/+DlV-cCa"0;q,/MlmSR=«]/UVLdj3ZvՇ6 L{/u.1wpxv]߽О[{ë:kՆBDD:xDVO5 p*kϮ@Ky+Bk5ZFg8^76+[;ڣTlc7` 8 f!߹>~#_>O <C+J~m!ɽGp>'*0S3[4P'7@z4%7WZP3Nn3:CC~F˖UçnП:05XNį{ cYxYa fuP:K &îJlo:V<熳 VXL/qvǯHe6g\:;o9zOh~wa#~|٫fm grx`_Z:#dU*Um01|t 4G14" SJC%Ű-˰} 5-{Ke-^{ dNG+E]N -^-I$ r &s |D -Ss"&'sR5R3hx^B!"@/? i)W<ԫvL -t>gq/#~4"USڒUŇS#a F(E sZi3u69t),檭%Ӊ5VN0wQ$-\R3-dmw "fIb*"MuYNo`$Ai9pN|rJGPO.tYT>(l0'r;*{FĜ]әD tK/r):&&V0<;`k벿OPJ=ɢY\=KĘX@RQnRwt =-k)g ʗ^@sճDbPjhߎwY\]ɖuʵm۸+QXVbPnOǥ@7qi=DYH MXu[7']9}Qզ_QS+2}7c#:^Rf=X!)?3%ȫkjqrQfQf2Ga; -@„ -ʵ(X+' " !a0W0Mv!aaP0$aH&,aHMEFpaH()7hG9KڊҼO8ɂ)6Ћ4-,7rxz&K"%)7o@ĂjI=bI=j}A2 -endstream -endobj -5952 0 obj -<< -/Length 7213 -/Filter /FlateDecode ->> -stream -xmY \gڟ$\!w8!$J$\r}FCAADDţ(Z޷UkVݣn/v׶s3#̼?E1.AT_S^mnB̬Ϣo~nAMOm ?EQ00eӂZ%Da]?zns/v<[%Ԡ ZfhA -}b0=1-+Ll' -p܀0.[_q=W 8O|HE hih^%K+h}YAGg:NN;cwGo n묤jdM|]ӫO E`pJR -\pF&{ :à|)}>Ǚ S Av7}Tw/WٛqH -1QkRJ@nպaz$E#/6>)oiaM`2 CrMEȈ!L.a1bV@*%7O|\壇jj5rnEЎC"}8mQ^TY`"2-! -ámwml/@P eVOwX"52]Y,BI- dr Dr(J?']<V)ώɑ1*q&dG{Nbe>6~X#HQ,za Ui mIRR |4c!HUx\MHn)8 UTvI."/^n +Ôhz4b}ee/eeR/P]1#)10!D)AtU(nnd`Q`` &0!cbB>C6amFʥJWIL s̿ORAjS%{z4ҬN*ōiJSR+(Z]ĘY&g,̚HÇRy[.7x/g^k[uiJUFWuiJ&`K6{nu0\wCY2Vs~a DK0 eT2Y\֏{Ou"c@]ďY9N+s^[Fb!bGdCy04B6ѭD5%HbVheD}M]D,Ez1I*LHD2@=B^i @P3X2kI#u6 F)I4ٌj'l̎u"=SUjukg&gS[,T5Tryl^cl -[sJ,g*SABrsf±86\ *t -Tn؅# P{x|%Urs˕v2_K:[Rb97&V)'ݷ8@>DŽ)g椭<;ǂd>ڌ}e :AM~ C` 9W(32T[irt)p4f[heV)}zi4O:17Dy - -, @&c1P\1;4=po_z u)_X?P bi!+&X6Ni)3jώՈƐ``Z`/f{XԣDZO&P&{ضZ;P1svaqxp\iސ 2\,oeAU1Uv -&[A*L۾PrMf@7G4%xmx$uZƤns3csᆌ0wsJez^P-pGM3@"CYdKF儅Et":1.eSDqߐU-[lφfۄ:oaQ2^mbۻ )3ػE}Ce_!jiP57nBWV7GRq=$H{e(0=b+XT2&޼wO[PV07΁_ -_Rc(dFjFz9r&xrzdԘp_N,g4>p-W55_5^?Few?xv9}]7͛GY]ޏ)ރmfNS$zO CX4ʦGSx}BKb6[lLC½饻?5MBcDH-u,Zhmq I;xS peK\7޲泃e|G+qdJ0utCY\݋sv0,ّ㳸#0[,2W۶{5P)h K^/Iyu;urܷg_.zr+W4r.RW2}؈ zH0gYO(c<jl](.z4v]YmܔY `0Fg2OgUp j=6o㢒HO!V+:wRF.^%QLDfБ*L) j4LG%/ -<..Mz4P5sA[HvgF@9)@4߼G;+"g} 'Ap  !,J$jB5"z*tDi:qnt -PRltS'T<#r55K Vsҡ%UWh_!~q -Nb6o,jma2!Z3m4/.5i=^+)*lBU[BHxrW|'+e|dR*B}SE.~qqmvDxpFEm ˃`S ݼB,?"#iiMl{h@18+'-[l&|o5;;KbA昆ə[SjZCȬ"clmQ7!gW3ʥ`ş]uqMڀk -;1Z_D{E"FդET秫;וtk*xn#1W,h>Np'@{|NudRV_/aDeolPƜo(׫Q6C[6`DKC<d38(A-3z|t&6r&le{➰M8FA)1{*P}DwP[.WĹ_2WyFo*,9iwI<oOЁ qS \3^Qg][iФFj9πdz8ɘ -k5 -?/ApNgÜZ!!/Bf&ߦ=KP-Bq/bW%TWT\YiYtJTEqnF73U@?81-d<~1X>yNR_I+:Ram Wl=/Db#SszutJnYu ~vї@*Z^uuV8꼈,-[ZĴe& ĎͤX;e+˘IVJlf=O0Ѻԭ뗖rۇR@ggH۷}!:|W]~#K:W, 人)>Eڪr-ݐ<6t1 B~ƯhSW2zp;~Gp:<:TEȈ -@^ -覾EXʡ10l_=H_M&"1z_Act~CWqoO  M'?zC{1G-}4 윇嚔*iҖ?9!{z5]j4}&&f r_ʴP#hg\c[r*=#sKL΁M6XeVrE8:>RR7Ƽ*-%xp> R27.U,'Rph2UrI̾ywTRs$.e *v!3^Z9olO0Ot]؅Y",ٻM=kj,vr%|@?e@br>ibU&2ʹ.35@fZ`{d~jK֝w'ǯk S?j bP{1ZSW_(Crv|6!g3-pI;}TJsu]ol)sKZOź U t  , ]SRjo"7H@\]|pYV\!~Yˋur1ud/Gx-rEH3Q9}> |H۳CB05I xVZ}^"B -zi+QsHˡU^QYZ*/:ysR1G~7# -?ub SX7+IV}ƆF~S'h -endstream -endobj -5956 0 obj -<< -/Length 12434 -/Filter /FlateDecode ->> -stream -x| u}\=W};;{ H(J,EhM"e)ʩ"]&bW؎+q\]2"*ˑ\v()(6cfpQ.W@w!6y$# Gɧ'ǃ|#%={bQ\_?{#oؓ}_!B~?¯7ކ?W=_>&= }o?ϳsE?v6QY? ђ;;Zo53וVOh/oog~;A`1 /Gѿ})%Oש]󅗊KY~^ז7>ַo %0ϔ2Y'GI&{h= XN?=JB\?G+4gIq&#N0|XEj$M/06MY $#0~riH * 3 y^H6D#Y&c,!0*9 btQ׃1:/"AxK SQ\{\ru ^# EΊQW|qS?^"ڵq~J_7q8?+!xw>.?eq~Uwę(_/EEQ$_/DK;bܬ7+g8/vG| '/y\;"8?gֿ̮ψv5xnYoYKY \!s6.er2} x7s]T^"{`ez^&K)\!zp _pׄ׌B(E;<ߺB*p\B=<>[.nUQ?9^kA8wԃ_wbr`j@e^⯶HNZ (ѐ3)w$B Lk!|~6ʕ#wӻp ax, 1apϬWQY@utf4X>*Oٯĸ62(Tl{f#HJ>(B2,%wIxghٻ*Ʃ9XpJ1U_U=P7URKѠ6kDbXV`r*@6'6'xkfԆUAAqb+&exF| lE <kAlq|6Nqg1@v F -Oez*k< -91 V]iT1 E1L gKJ1sL44ͨdy[ -j/uh3+ ru3o -0\gadRmdnrJI-?R>k\.J`GzY%@pu8Ku]:,I k| -Q%YL$ȴw& ]nqXR3m|$|rYV]#b! AC1D\ {`K,Cp 1b.OY-ED]\- -7 8UR#EUZfN,VC7r^,ЌJTES4V=bFЍ[VPÍF*k'vfmyҗR#)ߒI%O~`ED/.Dq-0]0J% !"`od (Ha#7:LÕB]QY&mF?c -gаpW팈\#]%^ƈX6'ya. #n\AnF&@.@LGn@gn6O-p,^vL2U #_"t iɴ~zl'/"/g<69L79q[d_Q&'އ·N ;;~!F#N. -W]-/:HwRAQ94˵oq*ێe:#jVT%i+VOי=ÍѬOR匁]ݭ!(|/UQUA_f?EVuVVR*qLeS9pvsA/?2U_Щ: yd07y p(g3G: p5 "Meeq:2?5nARTa$`-6&<ץXaa:1FiCM1nVo(%[L4Uǝ@qdWj`2?<[_ҞkdJƋ};|**b6 S}N 0>o h!_2+]9E- EG@{{H .]eF9-+teM)5CQS D48"0*'4tk.2&^!&PtL! -Z!VEAz ^3#6gO 7ug*. cyEh6ns#ܢZ>.M {`ۑF%\a2áp9m[hn/Pyh6ZjBn0p$Oܒ~H'S°1Ιt%G'uZz ikrRZXܠQcan'[l:Md1tLتإčLjz6_`*hZoA/j _#m?AFR2"3ٱx"0RnY2pqhKs0#X -k 0O/d -HUt *_+o8Y&_gf]!.,`횰Mc7ɒ^e^U&rE -]Hh qMh9;|-vG -"1Q3܍хM4 Jh1`Y3:~ &*ܹAW6d0ޏnTJ[Æi`5~g;txdbr0v=g' N_|y{ͽt -4wI|,(ߢN -_ۯi\!ѱG\o3'&^ ='>&fu!!0 {Ҋ| -Sx"e<[}99RhX3bi]s Nq =4Km@&ePd @b="=LGD#(vyr`%aH`\%{z[Z4KASb<1^XjJ˩hR M7!wd4+ ܹprB'@$f;>ٮC麳V \s+>_*UDF\w&Պ&b]NOmc΂_ WwoaqW+8JiT鳪sV:ޟb?%L^Bo:I׷HIWBSe,:q&QYu2Wf0PĂ#_""b`0.Fd|Ihy3I}8%޼ɏO#{LH;BD#ux5Im4ˤBk? tc(0:\喷Tկ2HӍʾ|dꖥ+NQuxR0o~(ZwYҿ.$=5&O>חVos fR^ޙW> V::PF8#ͺᵌ)V UJA 3-nγ fHb2?זAS}q?Ÿ.Č1' - F^02baAlЄ2D:Pt&Ƹvhp˅S |e$-ҠgA}6i*pp4+oO/2C`j b`tdZ}9N:?~(hRMSO+бl9jEXU]5X.78&/M#`"iAiH eҥ vl'W_4L }2h'F -M?}m -aQ3x6 -42f iH !E i& (uC67[-B3/N2o2y aCT:_<{O?wu5𫪢Zq$L*s೿φ|$1jm\bdp#llND?V> -A1F<׹퇏#c>}C5!Y7t|;ˮ`Աk3b+мOdm5\`> -C0W)eW4o! =`\q}M۞N>榽L@LǠiJ٥܃/`@9s4sөфL#xFQXr -r 5 'O/W 2z,3: h+\|I<4ӌd⑀$~/ťq %! :@JQ@?Olw8<$ -naYW!67~W$wZI,K,Kg,ۃb|yxguep{ k2E{/AQ(U#qt7N.2&'`! -*pR0*ѭBt­D:cRV\0\ G)NdBƗNT+h31mY?BnlXdn'21jq%b%7>ڟ+s %*9XPLL=u{P\KM_z |<e[F9y7昔/yüGGۿK"b\XmnܗLԭd]= d -6Y&\9@M_q[^:gSJxN' r?T!NY>zukd sD"%}Ԍ).pɔLisÜT8ˀ-bcruF݁Ic^46j nd/u \1DO Q\ɻ1#1,r-Б',C-8Te#m(/SmaVwL'X:p.DxA]Nޡ<Fݘklv}p8  y-].Tˁb jH* Gb7LN - sGz+_{9sbZ:_e/:W%p^/>+,$ȤtHtQ1hiBcu,u -Pc?Lߏޕ,=UOOOLYgϜ݄`"zcC񋟕 ,J @ /Qo/_^b(Bv]s< ( -27IK %c -H!g&L8&cӅlˍ1 -o* í]O]^f:҆OwҞc'lݰ :3"w"$K\nKLa0Ylҗzdwh!ļPLfze.cpLo޻GV(w[TtcRmDe -11+&*, -QF?1(.n_L#`4ٵFϰ-m!ьiOJcȭ#zǪ/8ңg?xO2(3( ?]"E -!:@d: -8k\7v')r\V鸹6N} 6969@<79)Z"Y{q/<0{8cKan3=_EbWmmG={q#y_^ѽƆgy#{~\ARIY$ßF)YRZپvj -\ -/sAVhxQ4 -nDMEMROQ[T[kT_.9f61Kɴ7W;QIsd|g r -(7c;UHਫ਼R98(\l`6feK6L4ףEʷ@Ā h,Q*º~R{4 LQ0EP3*e48t41F?)V"F Fk/|e'ӉD?Hńw=J/`mE|az'.tgUjٹ}M)T&JQ{cժ6([#ymLm֞&+FDZ&w̚ϲ!@]ߛ6 ei]>fb{Xh6랚r -w,!+P4n[7kk+|Ow(T6skuoۻr`#>(S~uz6#8 }{5Ɛt8ҘvhcVˆL>\c38ذElYӬG0\T[,2:,A" -Kr0 R ܅tճnwOXe mx^l(ũwҠD9 u4X+eMhİtOLYѶ>u Wb9fz[\ICO†MHʈL%ƓA77_qiKz7~g_TsVFkNѭR]9sURJ<_# mk|M* d Eq*YZXq0e7yƳGH&+ipq櫶bw5.b -S0Td0Ō8Ý [Vu!wW-ɶ{f%Mum[/hlDGmWv Qhthd#h?41rZ0-@$PQ&+H]Ms섣/N=ZrT+ !VsW{;ߡ¹6BaOl;.,SauS=(Y*9˶`IGY>ўicPrDR._ њg|RY;o,"=S@͊F̅C;'?aAP +Kļb"3'ZJbUe)*xjY3PR^"Bl̈́2f}rb׆yN."kKbva6wFs[H̫w0! X@XcXAڌ^|oKFҍ@\:GCdAdksC0u}sjT7}|zPGUVjo*y&4z<0KLy շv][$*YV'5Jq'Rǥ@QY`F{Y-z ReMo;̛[m=k^Ԇtm2]X]޻ -(tk(hOxef. GS7'׊4X}|s9i}VlGp;EELh%rIjׄ:0-]iSvq[d(jz=ׁُ-0B[d_,4 g{md,"feT: g_ƪ.̉f`)ѳ-ag ^RgK岆2؎Cf2B\C7+H61ߕUL%U9aͣ53sj'Ϲ{6<:cAKܭŲ?z7<]70qtj LTUR%jg$by[Mb}DXV-~Vbp{e ܶ5Q.'ݱ܎9.']l4cW5g`3\q'"ym-[z׶6c[p]PFZܾc鋩 ~"̫\ݽ7c0r'eL$HvVڽMyy>M\0,tu'R΅tj*Xe(jtKGFhg'v8Sa=C"h掟|]y f/<+ipe7C{]%ȬA5~|A4b}K}X8^u7 #$\N8NvgIfu] f?>dMe ޻T⹰ƨA\h;Ήkb}-3Bk$ȴh]gAwvb3X 9<~YTZ)HP;#(7y`Rv L#Γ,fdX9fMòdAg뺕LǼhA^{^Pӕ[ջg5NKm#l3l̄q<\|d']E)o<Lp0~9qKgH= ~v;mz2j +P%k<Lj}Eԁu`|?WjpgMK:)~]+e85FE 9ؙXڵUmCQ'Y|EcrI&^ \S6`?HgqDy ^-d lì^>W -i M%3@K3,yÜ^0(gnۮ-#( Žo0!f=_l05~o ẍFl7?H_nYd~_0պ2&0oP ƴqGm9Hk E#"$zܴD 8(C.;`/jCfzqC2>1{'8j]$L{66w1 M&fQ @dկ ITMV;b[i?CdgJ qk)@ܱ:Ve~ʿ&5_n`⩤=Wd%f(?|2;^4͟g>~s']wSǚ\w,}gϓS_Cģƫ|. "OI; @W -(@<'3݊"(a ld$1`/0]psQ'27|@&x?; kYqѴNo)rQDAL b;:J]JY_0 + C=x26u>2\>jQnx=*_|F &3iku׭"a͌2YT)e-ײ-.һd6gQ>S%OŝnCT:_rZgdcOg(wyeoSžL-qHP iNʧdHחD1=@~|@~DI"1f ?qwfy90|CH`M5՚jy3ᅥ3PkWDƬ 7@DMFk$̐$ v/Kmd(*ˤGRWb|/J߅v`p{Der$i$ηC$%4BL&:=A;*OAOs-*'vOsd &eэ@KНBVs(83,έ^gB@ u~Yۨ*X|q_,;ÍG^<*^&n7JNe:#N8q^<#> -stream -x{ xՕfZjCR?Uݥ~w!YnI,ɶ$ے8h1|<&8&1,$&FC2'HUY>28Y#$;N&soU?bcvU{y-7zRRPJ{%JE@sMgK,~F|o>Z=ۏ t=~5>ܳtlur PTxMJ)yߌM&2<+)Z$~ ̬ls9fa쥞DN&]?'K&%H/>/{U#PbTq~ӊoV1; 6ҪRϫ>l6>xYmUϫ/!WR>ڿ~Sҏ6X }1k7>oz s|Zyl$QZ4%TĒ÷Z)zRYw%JBgY^{R RPOnjO()y9g -P+Ӕ„VPPFLQڞ"dgFo/Sk9\izΥt.BEۂZ{ ijxrm#k7wKmwKshp瀯t2QGrJQGdJ0a 3(0rʤk1 g8y3E|ɨcu V -;WH}3c㉌;O[k0LgSsBi &05"hƄe-BH"UA%W_gXö4lKz($M&SϧGV>z#w`,=y}}~ƣA_:iU|FJ`kؓ:%)̢A%Bu}>NɊxp&:X-AjMUg`B@[, -˪Z~Z,^6$Yx1+"`2;Qٞ\OaCmVf8U{z,1p{NOLJ+:xkI z,=D9k)Z@sCYt'us $% I$z9ȕMv#Y IjXMN _Zel5ښYwTΑՍBILpԘ̂V3<^Hp54#No Jh$Jb 6].+,cue&Ւ1nԚ0v}~iJ73>Y-#g<*jd_ 5,4aBS2TQm"V=2"JTUÙW3c|񒒂d]p-a9 ;z] 7_\y܎W{Z̑-V[< ֻZfP81.*YܭnC FB_R`qII1Q':^yeSZ8:P+2 -vA',!^٥xvPٖ?BÄrdC: %B/ xF矿vgJND}on:}ڈvh-5i+oC ^Lg~g/PmB Ӻ8Dt鏘)O ycA% -^D Dcwy/,t}/ T8;ϭ}0w3̭vY}vM䢈 -g|#cCGL(*@V "l -o7.1A8s* >;136w _)1x&e'rߎl+*NuAVЛLD-Wȼ(FND!G5vxvyg:],XWfo(l٘2auAN'g@:S爞=55Q;"-`W u啸Kפ? CݔEz+H Aq3lWu-MqG$uG-{KlĄFΨA6yP'A>$c,En\ʌ7fZ(} bJq+r0E+l* G+cC:z_ -`]~EJ |?C_c~ܫ#j wY9=}=%421O[_vQhO[[U \;`K,hq+6ap NJ&U::uT >KU#P~C|̱R-x|Xk k\Q;ǀ/",'E3PM|VWeop$aŊUaSAH; @"@!a'R"i0: JcTR'i9|pE"W *-FQcv;2W=//R|˕*1Lmbbo$Xm"tm \=*mbyKtDǡgFWxЙLf_ - -xÝ1 k14i'j {RnvYyG"׶~}@xW,j5f7U~t:aK>T5la>QMg\mh/=f>F_%Znp"yeK\KIgoY]QYdG&QdWHa^TtUlmu^&(ЕW;6@.TV{[z<ʰթn4r#h:z,)!t[_@P #;(vq-`J`k=RAj$bw#I9\n.=Yon{4oOܦnHmï=m~]w^" {/Kav 5]d^;དBz&LM*$ XBϲ^d(x!,<*r>W|?eJ1 B^+tBdv8"lA*Q Wqe Vl~,Dyz B߉;㩍LHQDtBJi] _V/ N^o]bĤ#fR'&&6xgc6DRd5<փysDL/OTW`uNhTWt(D * ltuH^/6a85ҩkuuu9=8YfDILGQlBF+wp(4 #Fo3vb 1?h0yG#$-x<1QBl%4ncW>)5ZCZՑFN)]B*Ti։W&ܣ}O7oE}ԕ"v{t2۝d%`DVtS8*N.S:ެc_33\PI˩;D%%ΔQlQ /n ]BĤ,;)RvǶE[mK*aD6Cvnұdm0v fH7X-:F+2{?A KK}/0NQ1qNl9Ҹkܕ,^8w`} y%W,} -K?EҗG=V3\KGTbfj -vPqEjzUVLs -@ 5:4Rqp+4.TԌ|OCp?X6Fy{}:?Mjvz.)jckpb+hRְ$Kzbz:O 1X;\pEk=$ YZ!#:QzSgOz#n.7 ?W */6JߓH~Xⷁل6(yKpD'-bu];i*iqiC5'>5|[9^Ⱦ W(vAt (޳Vaat݅N?ܹO}aߣ⤋n ^+k {řa6{}rA6pglH_Jkd!3Tw$W]wFh/i_b9߁ btv0D75uat2&I~Hrtq_q;BݣudMGf*gfjTp|=*bqхwђ*y-^gW>G%ڵ lUWO!rX[\T%r+SXjr" ko9ߤ_9/WLo!L:]Cl}89$ ^! sbw#{RNЙCMqC3@qjv]?r*.דZ{Q@Gj(.21HwP 51I[8ҕ],|,nLߍDvZjcDQjBDd'v6B JkB5[g;FQ&z,`fX<ݓe3sm Y)#M kAS@>jIpODӪR4>bkhk[0JwjkRyB!,['7l8dN'q0ۜ -I9Hyûa[C).2M -/Cf[9H=s35[^Ѱ-SWpn[,yذ*jWb612IWmeD2[ pYk5sne%K?\ŻYW9Fj"w -A,(bt99xHhIpxHR:yז2@5oW G/fc>mn7(ў~_Z,xŵu3}u9N5\e]ʥXou9ƕ 4}M?-G[*mbV*fs] \:0Oq؇O#Α{w쀈I#zt 0Ukq!:pجvOްM,uxOکWw5we x i/jF^9J7"&Pa>ǀ>:f'Os(g \,F2l(qrdž -Ĭܸ j,KlSjj?\ڛ 67إ=N9)~ٳWHNG,6VQnxj/"]=(^!ak%(].//=]4xθj 7 ԰] = oggK4G{JWՏtsk>[T597IZ*LSzsiR6:|[vuNГ{\}?VxI#dᅵxI4UR_ .~#y7M`GPaZ-)SM"J"jL(5<܅00T3#Ó#3mL2ɐm:C/ou#))k{4 g,9qd``~0 -0āI1S01$ޏ_;`|F7`胱(;# Ήaoϊ{`8ƽ0y5> -stream -xZ třLϡ5贬K6>6 Y!$rK!\!C@],dl6 },E"nU}_WnG)3߷{/<a?7xm}G[y`8#?7+=>:?{ZEQ?|$;uG?pB_[w?ؿS'J!oG Wţ+@GOFQL-_\~Smj@GoVz/8GQ&ыb=I9)-YEهrZ~V|_qY٩ߛov#TQ]PߣPӫ_?Vzݣֿc61qEgzCsi T@DpoQMGeJMwBYh/Qy*F=COy:豛Ԕw8 ,9xSd_ȋ{eNS)&"%D "Y:Rr4tG^D8.#IK(mB3&E0;"`v*hxl;,,W6z'OnoduVoecO6i490ZM6`ZL뢆EVCdm`{=,)AH5~ue>kI4M68suꀏ86 P^FX $ Om:>H~[ÑhY賡OMNΌ՞G[GR9,N6D"2p@/R2DFEXs,>V!dW}v澙+R mˉ' -lnږNo-]ㄟ;Yswt쀆LTSY5`XTzQaTӮLw.Wʇ;\ށ(ro c(5!_<`ҀS7SJCƙURLVa;#% ^cb>7pJmjp96vL癤݇zg dPQ+QVkY!0T7!0Pcs7s*s 6i35pD%֦cB7ָLpkͪYt9EjX|ŧxz]1ZtC`ıU-|$(Sh,۞ij򱜿WݟiC%ڼx@a g(Ôv:O:A/]tlڭYj:fP'rc&'瘈'C;FL,>cI>^mV>LUa/|x0AKe -A=8JOĆbx$2H{D*|nB"o˿B uQ0=Lx<5q"+ˢW{hv⟐Q$26A@r"_E7Z\ *VLJ)=Ahw!>C_JBZEgU'}0+c9{s 9ഏ!*iI#8_z| t@混'gr?3%} S/dRInмugC;_l2!R&q'syEVڈNR]'RfjW$DŽ8 po EQ&*N jIDpRTJxd6$-.מ2-We;;}TO9ӶL.j -km1ǔe6ZL1#֐hֿޗƋ0()*O=7*z羅.64~[zt YCm+)#֚5d.$JF.m綛̱Z֗&vXiWmWцM)kHN7فpp fQڔK$V't+(t W bB@ *1 -BZT0 0%j Ta8 Q4逷V^3!@Z$~2[ -t-|a*%@?˻XIr9]!y( Oer1&RƯs}tHWD7D5ni׉Dj[-$2Ql'6Ak#f\6)[F"ha}5gvjf߸"t_0xbNgc(8b.޷G[IcAU%XeKc,W ̗('_5ה,rB21tJ+Wi? PCԳC韁 TQ|&ե%"%'O#3[޹wtlxKˁ]ӱ4eUN<-/)B*;(DcxbӻrF!a9BLPPNЬcD.\uYj@\*Ǖ6p'&Ģ#:S#V;5o~mM[}>{8I/pQTk/ YåJYHv#.FFPp2*(9ıx8Fj^C/~uJa{?oC&{q9!FA^ΧDB^(icNc#!!S벨-[XGiJI%>+YcG*amH 9Rvݎ}=e%Dfb"5,3 Ĵ>/ϡp']J~ tLFq% ³Xe֫-¾R zLa}U)BR Eb_3YBmI߉֖O ͽ[P?v ]~G5ۊ9d 6 -c#AK5!6V!Yߺ*6J)6:zQQwĸOmʶM ;Tkjc_߭t5j7e=v[ɞ/"kMgM=“z_dwV[5j-]ݒ}o15l}l|du}z*1,NwpzߍszWlƅk67/1[X#` K [Q*qX3s,d)zDsV}X*Ȥ"T|3}ݭ[AStL8WqB&jh)G!nC8ԑ󃳠܆<5y|ddKaM+ٵCl} 3S@ xK ,{.O tЉ'Ѝ۔5+EAoLTS$2_{Aϣd/R%=r"ė*r:R+l)Sb~Z*32w e⡂?u0_u_hj\%XM m/qn lB4c#$Pz]BZׯkQ-:ÊwZWM㈅{ ,HU"ZvSH(x\ ٣Cwa'Af*!R -J"kW^|q{]9W;YU9Qfs;N}QPe #lgkzXQg0ˈjEu̜u\vÅp -<@wtTR"A2 …p.pO.O }J3U䈄Gd -F#j6.}}-y̭;q@Lg}\V$c_bݙ+觭Q<>S_2:*q?rU9YIJB^[ ɰ -W2[U_ShJ2~7I֊UvU~D7jY,q-q%fYlھaS/v&uOTK8G.QBq,P|Ty陇UvXmQ5?w.lڵb]U4nq^/gbq'p;B̢T/S=ʰ -ho<ةz7]B_ }G/aK=D:N -]9`U|LS*b,A'Κ0uU{JaD#$OLFF}Ggk'щvnwG}~s&u5iѬ&=͝\f}ѼXou -A3yWB6BpT3HCfgH2W8v#G\FHw0X j{,QBu~+SZb0$jQUas[ ,[ؚ+]KW&cc3ccD&>5663}x>?YD>?6anXo 2g+z&bwu,\N(JfY|<5vs;3fɄZаɯKߡcI9-aRyd_u$uڵaQٯ3ji|!h ±h?e Z}t4ސ F\[03 uL&]dӵWSsrhdDH2Cp@vg+:Uu4q*[R8y ]-| Z3wy"'A. *š9/sLU TQ&PD^E)Q( ZJ_!Dݽ}mٟ}.]nij+gu|ydbMg/eCwĂAO6 'E *9Z)rTT$9 --ϣWϟ/Πs33C30[(>C? Z_ }IJ|p ʷp*Y^K$.,N"oa9ϐ닗aF%uʜ]'ԭQ;z_PhF N7:+o౩U*_/aOS Z -8Ah#u@;$<O Z@BB -p? 44k?³0/4M'` -|$ -s8[-V6)pSO!tZcv/ ܑH!0=.@'3`;22{ArfS<51u>'|iWozqdia0xI`Eѩ3ݮBcz_回e -X 0KБLLcgg;7fv5 | ˫ZM(QY@gFɣ3υ n[h]. -endstream -endobj -5968 0 obj -<< -/Length 3070 -/Filter /FlateDecode ->> -stream -x]{Ggvz^}Ͼ9W/w%$KCӴ)M"-T,%^uTH-Bx"Z(]j3gߌ/|MG#Ig6OBϗ8;oλOĹ>ob - N{n^yNy܅ۡ=}s;.B&t({_xk(sj}K!?9B|Ө{cFȷgY6nUnYܱyП3bE``kGG?EG= --z=F?o 0Զ9l;L9C:XdNT8^+b/Âae yG8nG=?sϼx/=16oEu`:*iI`;uQb"6(I[kc''RIkmfz\AB2g-$v.Pbp6IxSM̼H"a$"\uD0ivb>YJV$cA]Ps l2F}7&[Q -CS'G eXaDↁ}~/fՙNmrhx<q̔ H`'} PHlpdvR2 AiamGU3m噑b.MxBT ڏ܃h^D Wx:\!݋rhE%4էiUzɾZp:$m.!SƠ(DX ŵjS1["#P|<廊=|NDd2c9?_R5/z #$X2$,a2uB#ڳP֮*u֪ǘ+Db1YA3$WkysW*u#Hdk6awLI\]u8A(h67ԛdNj `#!ʏ<|ײ2S=婢&5@JqA,GSy+n@V5xm)r, =>AIטo-|N\طx3_8+D2KZl 껨)$2sCEBn%dt -AۻV{觤FD*G4r0::b3 64 DdkM!A셔F_l ѮxV!?e^ 4Q PC.Rj{+9eayt,ap0x -/m<ϿqxM{9[6qU{Q܊oWܼ.fd:hCkc - ԳAj`x[5}7͸.8 HWZ8 (r;xSwf}b=bJ6GƘW!AX㉜(ǭIS ؽ?'ߜI␑}j" -;w[3UUV;~@}|}-pzGҨu-cE)|kWTn So 6qՍ7 ƃ~ۈTmJҪԾU*evlWo^g h#"ѯ:S7UѤ+QM?zGaD$|95P[FD=}RkN;{imʕFqD&MGm@\{$.^iq&IIVҞ;1AU A ޵ ->߹;)P=! أQ2N&h*Wv4$ƅf9eWrx~ q Bg%mORX&y7 vkчsڀ?Ójd+CV l<,szH 0\m@"y.Tf?՚6G_ң^o!bπX yB -'(އ~*1rSG"q*~%ʎrG$ @yBEذLË©Hk"zPlO]y%pTd*4!95[=p:&_ᄧ7S@jcA/ozДϱ֋WC-;[GILyݾ<d(JTd Y,uݾ?.Zϔ [@$/zp%zk|uu2nX;d{a}BǏ _rX|q [rݮٛ]"JKe 0Iܲe.BС F&nl~.?dH1X2# -Ÿ'\OavS)]\Z> -stream -xX}]~wgvvgvvfgvvvi;glj` 31qHĎC*$ Ȩ  Z -GZ h+U6G*RJ 4of "οywv}~<ޓH@7G/>0| -b(ܘ_\CA!=ԓd|.p̥ O}hehyh=$!jzުB;;7W츺'ky7?K+*c!ѣ$:y %G&L4~t]3C|! oC;ď!G8 -Sv Sj mM1fmm03'Offp[K,ch 8_5 )Rkװ0X({?}&?[ IkR,QGJFT6ͦMQUy:>skv]+-:ih҅JN*OxK;*`!l-V7n32:z:DY84!08v9vh8vh8v9v2L߃Y.>z - ~ -o?fa@ k[w.|')O='I&HJl wSս31)ˈ=,L7d=Q}zx?_J4s{~iMZnTXr Gq.\ >&!*EV4̝mVವ:g[s8ރJDBLR?`ޓ JI5S,^>?[Z@hrej\=,8^AN`$IsBJw6q e#A7_!\ W@C7#-K+*mscwVUd!g(Pfp -aky\;ُW3,O -,g+U-ܚeST3l5;}oW`ze(mܜKDob!$ms!A; -Ţ#j,kaPY^pui'L U3hsvAkQx=XN} -QәNA:jNAڠSmЩ6Tt :jTt +ng:ՆEڰX6FUaz msrouYv01$ClJ*_U]|?h= 9+0).B}H8ߟʱ"p˸ɉnT{8ӂab]}t>(ii2$WZ%h^p"Re޲sOʪ!A_jE|Gh| -Ne4p 4DYv&xf̧9ǔ`?xf`I_ecgF^-q̹MXZ`BL, jΆo\aåfEMf^ -=}@Rk];M|f -BH]*(<# љ͟˹7mZ.rII/__]\-Y -2P4/˕$`rQuϚ='UI5fãhAb9GJ;zt\炬w^Cp/kw܁w8p܁w8p܁w܁w92>nFRNʐ:Jh ] ->> -startxref -684442 -%%EOF diff --git a/assets/device.png b/assets/device.png deleted file mode 100644 index 0d51338..0000000 Binary files a/assets/device.png and /dev/null differ diff --git a/assets/do.png b/assets/do.png deleted file mode 100644 index 7eda7e0..0000000 Binary files a/assets/do.png and /dev/null differ diff --git a/assets/email.png b/assets/email.png deleted file mode 100644 index 6015d56..0000000 Binary files a/assets/email.png and /dev/null differ diff --git a/assets/employee.png b/assets/employee.png deleted file mode 100644 index d77f4c7..0000000 Binary files a/assets/employee.png and /dev/null differ diff --git a/assets/eng_flag.png b/assets/eng_flag.png deleted file mode 100755 index e8049d9..0000000 Binary files a/assets/eng_flag.png and /dev/null differ diff --git a/assets/fonts/MyMMUnicodeUniversal.ttf b/assets/fonts/MyMMUnicodeUniversal.ttf deleted file mode 100644 index 128085b..0000000 Binary files a/assets/fonts/MyMMUnicodeUniversal.ttf and /dev/null differ diff --git a/assets/fonts/OpenSans-Regular.ttf b/assets/fonts/OpenSans-Regular.ttf deleted file mode 100644 index 29bfd35..0000000 Binary files a/assets/fonts/OpenSans-Regular.ttf and /dev/null differ diff --git a/assets/fonts/Work_Sans/WorkSans-Black.ttf b/assets/fonts/Work_Sans/WorkSans-Black.ttf deleted file mode 100755 index 3f972d1..0000000 Binary files a/assets/fonts/Work_Sans/WorkSans-Black.ttf and /dev/null differ diff --git a/assets/fonts/Work_Sans/WorkSans-Bold.ttf b/assets/fonts/Work_Sans/WorkSans-Bold.ttf deleted file mode 100755 index 7718ada..0000000 Binary files a/assets/fonts/Work_Sans/WorkSans-Bold.ttf and /dev/null differ diff --git a/assets/fonts/Work_Sans/WorkSans-ExtraBold.ttf b/assets/fonts/Work_Sans/WorkSans-ExtraBold.ttf deleted file mode 100755 index e571099..0000000 Binary files a/assets/fonts/Work_Sans/WorkSans-ExtraBold.ttf and /dev/null differ diff --git a/assets/fonts/Work_Sans/WorkSans-ExtraLight.ttf b/assets/fonts/Work_Sans/WorkSans-ExtraLight.ttf deleted file mode 100755 index 3798fbe..0000000 Binary files a/assets/fonts/Work_Sans/WorkSans-ExtraLight.ttf and /dev/null differ diff --git a/assets/fonts/Work_Sans/WorkSans-Light.ttf b/assets/fonts/Work_Sans/WorkSans-Light.ttf deleted file mode 100755 index 8b03227..0000000 Binary files a/assets/fonts/Work_Sans/WorkSans-Light.ttf and /dev/null differ diff --git a/assets/fonts/Work_Sans/WorkSans-Medium.ttf b/assets/fonts/Work_Sans/WorkSans-Medium.ttf deleted file mode 100755 index 137cf56..0000000 Binary files a/assets/fonts/Work_Sans/WorkSans-Medium.ttf and /dev/null differ diff --git a/assets/fonts/Work_Sans/WorkSans-Regular.ttf b/assets/fonts/Work_Sans/WorkSans-Regular.ttf deleted file mode 100755 index ba11a2d..0000000 Binary files a/assets/fonts/Work_Sans/WorkSans-Regular.ttf and /dev/null differ diff --git a/assets/fonts/Work_Sans/WorkSans-SemiBold.ttf b/assets/fonts/Work_Sans/WorkSans-SemiBold.ttf deleted file mode 100755 index 5cefd7c..0000000 Binary files a/assets/fonts/Work_Sans/WorkSans-SemiBold.ttf and /dev/null differ diff --git a/assets/fonts/Work_Sans/WorkSans-Thin.ttf b/assets/fonts/Work_Sans/WorkSans-Thin.ttf deleted file mode 100755 index 47a06ef..0000000 Binary files a/assets/fonts/Work_Sans/WorkSans-Thin.ttf and /dev/null differ diff --git a/assets/gender.png b/assets/gender.png deleted file mode 100644 index 44e9de1..0000000 Binary files a/assets/gender.png and /dev/null differ diff --git a/assets/img/bg.jpg b/assets/img/bg.jpg deleted file mode 100644 index 993d5e4..0000000 Binary files a/assets/img/bg.jpg and /dev/null differ diff --git a/assets/img/login_logo.png b/assets/img/login_logo.png deleted file mode 100644 index 0531be9..0000000 Binary files a/assets/img/login_logo.png and /dev/null differ diff --git a/assets/img/logo.png b/assets/img/logo.png deleted file mode 100644 index 6254dd0..0000000 Binary files a/assets/img/logo.png and /dev/null differ diff --git a/assets/inventory.png b/assets/inventory.png deleted file mode 100644 index 5f1a3d1..0000000 Binary files a/assets/inventory.png and /dev/null differ diff --git a/assets/licence.png b/assets/licence.png deleted file mode 100644 index a742f69..0000000 Binary files a/assets/licence.png and /dev/null differ diff --git a/assets/local/localization_en.json b/assets/local/localization_en.json index 09d45e8..adcf3fe 100644 --- a/assets/local/localization_en.json +++ b/assets/local/localization_en.json @@ -1,8 +1,38 @@ { + + "Loading Start ================================================================":"", + "load": "Loading...", + "Loading End ================================================================":"", + + "Buttons Start ================================================================":"", + "btn.save": "Save", + "btn.approve":"Approve", + "btn.delete":"Delete", + "btn.select":"Select", + "btn.cancel":"Cancel", + "btn.ok": "Ok", + "feet":"Feet", + "inch":"Inch", + "Buttons End ================================================================":"", + + "Offline Start ================================================================":"", + "offline.status":"Offline, unable to connect to server!", + "Offline End ================================================================":"", + + "Language Start ================================================================":"", + "language.selection.title":"Please select your language", + "Language End ================================================================":"", + + "Welcome Start ================================================================":"", + "welcome.signin":"Sign In", + "welcome.msg":"Welcome to FCS!", + "Welcome End ================================================================":"", + + "Contact Start ================================================================":"", "contact.btn":"Contact Us", "contact.title":"Contact Us", "contact.phone.title":"Input Phone Number", - "contact.phone":"Phone Number", + "contact.phone":"Phone number", "contact.phone.confim":"Call {0}?", "contact.phone.empty":"Please enter phone number", "contact.email":"Email", @@ -14,27 +44,41 @@ "contact.google.empty":"Please enter website url", "contact.confrim":"Confirm update contact?", "contact.open.confrim":"Open '{0}'?", - "contact.bank.accounts":"Bank Accounts Info", + "contact.bank.accounts":"Bank accounts info", "contact.address":"Address", - "contact.usa.address":"USA Address", - "contact.mm.address":"Myanmar Address", - "contact.delivery.phone":"Delivery Phone", - "contact.fcs.email":"FCS Email", - "contact.callus":"Call Us", - "contact.findus":"Find Us", - "contact.emailus":"Email Us", - "contact.visitus":"Visit Us", - "contact.usa.phone": "USA Phone", - "contact.mm.phone": "Myanmar Phone", - + "contact.usa.address":"USA address", + "contact.mm.address":"Myanmar address", + "contact.delivery.phone":"Delivery phone", + "contact.fcs.email":"FCS email", + "contact.callus":"Call us", + "contact.findus":"Find us", + "contact.emailus":"Email us", + "contact.visitus":"Visit us", + "contact.usa.phone": "USA phone", + "contact.mm.phone": "Myanmar phone", "contact.edit.title":"Edit Contact Us", + "Contact End ================================================================":"", + "Term Start ================================================================":"", "term":"Terms of service", "term.btn":"Terms of service", + "Term End ================================================================":"", + "Login Start ================================================================":"", + "login.title":"Sign in to FCS", + "login.phone":"Enter phone number", + "Login End ================================================================":"", + + "SMS Start ================================================================":"", + "sms.verify.title":"Verify your number", + "sms.six.digit":"Enter 6 digit sms code sent to", + "sms.resend":"Resend", + "sms.resend.seconds":"Resend again in {0} seconds", + "SMS End ================================================================":"", + + "FAQ Start ================================================================":"", "faq.btn":"FAQs", - "faq.title":"Frequently Asked Questions", - + "faq.title":"FAQs", "faq.add.title":"New FAQ", "faq.edit.title":"Edit FAQ", "faq.edit.eng":"English", @@ -43,650 +87,455 @@ "faq.edit.answer":"Answer", "faq.edit.sn":"S/N", "faq.edit.delete.confirm":"Delete this FAQ?", - "faq.edit.page":"Additional Page", - "faq.edit.page.label.eng":"Page label in English", - "faq.edit.page.label.mm":"Page label in Myanmar", - + "faq.edit.page":"Additional page", + "faq.edit.page.label.eng":"Page label in english", + "faq.edit.page.label.mm":"Page label in myanmar", + "FAQ End ================================================================":"", - "language.selection.title":"Please select your language", - - "welcome.signin":"Sign In", - "welcome.msg":"Welcome to FCS!", - + "Home Start ================================================================":"", "home.invitation.request.msg":"We are working on your invitation request!", - - "sms.verify.title":"Verify your number", - "sms.six.digit":"Enter 6 digit sms code sent to", - "sms.resend":"Resend", - "sms.resend.seconds":"Resend again in {0} seconds", - + "home.search":"Enter tracking number", + "home.search.btn":"Search", + "Home End ================================================================":"", + + "Invite Start ================================================================":"", "invite.title":"You need invitation from FCS", "invite.name.enter":"Please enter your name", - "invite.request":"Request Invitation", + "invite.request":"Request invitation", "invite.request.successful":"Successfully requested!", "invite.btn":"Invite", + "Invite End ================================================================":"", - "customer.list.title":"Customers", - "customer.name":"Name", - "customer.phone":"Phone Number", - "customer.status":"Status", - "customer.fcs.id":"FCS ID", - "customer.invitation.request.confirm":"Accept Customer", - - "invitation.list": "Invitations", - "invitation.edit": "Invitation", - "invitation.new": "New Invitation", - "invitation.confirm.delete": "Delete this invitation?", - - "staff.title":"Staffs", - "staff.list.title":"Staffs", - "staff.new":"New Staff", - "staff.form.title":"Staff", - "staff.add":"Add", - "staff.update":"Update", - "staff.phone.search":"Enter phone number", - - "profile.title": "My Profile", - "profile.edit_title": "Edit My Profile", - "profile.name": "Name", - "profile.phone": "Phone", - "profile.language": "Languages", - "profile.logout": "logout", - "profile.usa.shipping.address": "USA Shipping Address", - "profile.logout.confirm":"Are you sure want to logout?", - "profile.devices":"Devices", - "profile.email":"Email", - "profile.privilege":"Privilege", - - "package.btn.name":"Track Packages", - "package.title":"Packages", - "package.create.title":"New Packages", - "package.create.fcs.id":"FCS ID", - "package.create.name":"Customer Name", - "package.create.phone":"Phone Number", - "package.tracking.id":"Tracking ID", - "package.create.packages":"Complete receiving", - "package.create.market":"Market", - "package.delete.confirm":"Delete this package?", - - "package.edit.status":"Status", - "package.edit.title":"Edit Package", - "package.edit.remark":"Remark", - "package.edit.desc":"Description", - "package.edit.complete.process.btn":"Complete processing", - "package.edit.procseeing":"Processing", - - "package.info.title":"Package", - - "package.arrival.date":"Arrival Date", - "package.number":"Box Number", - "package.rate":"Rate", - "package.weight":"Weight", - "package.amount":"Amount", - - "market.edit.title":"Markets", - "market.edit.name":"Market Name", - "market.remove.confirm":"Remove this market?", - - "buy_online.title":"Buying instructions", - "buy_online":"Buying Instructions", - "buy_online.buying_instruction":"See below instructions to add USA shipping address while shoping online", - "buy_online.fullname":"With Full Name", - "buy_online.first.last":"With First Name and Last Name", - - "pm.title":"Payment Methods", - "pm.new":"New Payment Method", - "pm.update":"Update Payment Method", - "pm.btn":"Payment Methods", - "pm.name":"Name", - "pm.account.name":"Account Name", - "pm.account.no":"Account Number", - "pm.phone":"Phone Number", - "pm.email":"Email Address", - "pm.link":"Link", - "pm.add.btn":"Add Payment Method", - "pm.save.btn":"Save Payment Method", - "pm.delete.confirm":"Delete this Payment Method?", - - "message.view.detail":"View Deatil", - "message.hint.input":"Type your message...", - - "btn.save": "Save", - "btn.approve":"Approve", - "btn.delete":"Delete", - "btn.select":"Select", - "btn.cancel":"Cancel", - - "================================================================":"", - - - "product": "Product", - "price": "Price", - "volume": "Quantity", - "amount": "Amount", - "storage" :"Storage", - - "welcome.price.updateinfo":"Last updated on :{0}", - "welcome.price.trend":"Price trend", - "welcome.price.detail":"Details", - - "products.title":"Products", - "prodcuts":"Products", - "prices":"Prices", - "product.confirm":"Confirm to update product price?", - "products.prices":"Prices", - "products.gas":"Products", - "product.item":"Product", - "product.name":"Product Name", - "product.name_empty":"Please enter product name", - "product.new_price":"New Price", - "product.price_empty":"Please enter price", - "product.order":"Display Order", - "product.order_empty":"Please enter display order", - "product.balance_qty":"PO Balance Quantity by Product", - "product.qtys":"Balance Quantities", - "product.update.date":"Date", - "product.close": "Order is closed now.", - "product.open": "Order is opened at {0} to {1}\nOn {2}.", - "product.purchase.order": "Order", - - - "login.btn":"Login", - "login.name":"Name", - "login.password":"Password", - "login.confirm_password":"Confirm Password", - "login.name_empty": "Please enter your name", - "login.phone_empty": "Please enter your phone number", - "login.phone_code": "Only starting '+959'", - "login.password_empty": "Please enter password", - "login.password_size": "At least 6 characters", - "login.password_mismatch": "Confirm password mismatch", - "login.confirm_password_empty": "Please enter confirm password", - "login.sms_empty":"Please enter sms code", - "login.sms_size": "Must be 6 characters", - "login.forgot_password":"Forgot Password?", - "login.email.title":"Recovery Email", - "login.email":"Email", - "login.email.empty":"Please Enter Email", - "login.email.add":"Add", - "login.email.skip":"Skip", - - "sing.up":"SIGN UP", - "sing.title":"Signup", - - "change.password.title":"Change Password", - "change":"CHANGE", - "change.phone":"Change Phone Number", - "change.new.phone":"New Phone Number", - "change.phone_empty": "Please enter new phone number", - "change.email":"Recovery Email", - "change.pin.title":"Add PIN Code", - "change.pin":"PIN Code", - "change.pin_empty":"Please enter PIN Code", - "change.pin_size":"Must be 6 characters", - "pin.add_btn":"UPDATE PIN", - "pin.clear_btn":"CLEAR PIN ", - "pin.switch":"Clear PIN", - - "forget.password":"Forgot Password", - "forget.email":"Email (or) Phone Number", - "forget.email.empty":"Please Enter Email (or) Phone Number", - "forget.enter":"Enter", - - "reset.password.title":"Reset Password", - "reset.sms":"SMS Code", - "reset.new_password":"New Password", - "reset":"RESET", - - "reg.title": "My Registration", - "reg.biz_name": "Business Name", - "reg.biz_address": "Business Address", - "reg.biz_shops": "Number of Shops", - "reg.biz_shop_addresses":"Shop Addresses", - "reg.type_shop": "Shop", - "reg.type_agent": "Agent", - "reg.status": "Status", - "reg.table_product": "Product", - "reg.table_storage_vol": "Storage Quantity", - "reg.table_sale_vol": "Daily Sale Quantity", - "reg.quota": "Daily Quota Quantity", - "reg.max_quota": "Max Quota Quantity", - "reg.quota.used": "Daily Quota Used Quantity", - "reg.max_quota.used": "Max Quota Used Quantity", - "reg.empty_biz_name": "Empty businuee name", - "reg.empty_biz_address":"Empty business address", - "reg.empty_shops":"Empty shops", - "reg_info.title": "My Registration Info", - "reg_info.nric_front": "NRIC Front", - "reg_info.nric_back": "NRIC Back", - "reg.confirm":"Submit Registration?", - "reg.date":"Registeration Date", - - - - "device.confirm":"Confirm this device?", - "device.logout":"Logout this device?", - "device.set_primary":"Set this primary device?", - - "po.title":"POs", - "po":"PO", - "po.approval":"PO Approval", - "po.date": "PO Date", - "po.number": "PO No.", - "po.name":"Buyer Name", - "po.po_num": "PO Number", - "po.biz":"Business name", - "po.status": "PO Status", - "po.receipt":"Receipts", - "po.po_payment":"PO Payment", - "po.po_payment_receipt":"Payment Receipt", - "po.storage_receipt":"Storage Receipt", - "po.no.photo": "No selected photo", - "po.storage_charge" :"Storage Charge", - "po.product": "Product", - "po.price": "Price", - "po.volume": "Volume", - "po.balance.volume":"Balance Volume", - "po.amount": "Amount", - "po.form.volume":"Please enter volume", - "po.comment":"Comment", - "po.confirm":"Submit Purchase Order?", - "po.approve.confirm":"Approve this PO?", - "po.cancel.confirm":"Cancel this PO?", - "po.counts":"PO Counts", - "po.details":"Details", - "po.count":"PO Count", - "po.balances":"PO Balance Quantity", - "po.info":"PO Info", - "po.retrieved.amount":"DO Balance\nQty", - "po.count.status":"PO Status", - "po.avail.qty":"PO Balance\nQty", - "po.total_count":"Total Count", - - "do.title":"DOs", - "do":"DO", - "do.do_date":"DO Date", - "do.date": "Delivery Date", - "do.licence": "Driver Licence", - "do.driver":"Driver Name", - "do.car":"Car No.", - "do.status": "DO Status", - "do.delivery.status": "Delivery Status", - "do.delivery.init.time":"Delivery Initiated At", - "do.do_num": "DO Number", - "do.type": "DO Type", - "do.name":"Buyer Name", - "do.biz":"Business name", - "do.form.date":"Please enter DO date", - "do.form.licence":"Please enter car licence", - "do.form.driver":"Please enter driver name", - "do.form.car":"Please enter car number", - "do.product": "Product", - "do.price": "Price", - "do.volume": "Volume", - "do.amount": "Amount", - "do.storage":"Storage", - "do.quantity":"Quantity", - "do.form.volume":"Please enter volume", - "do.form.amount":"Please enter amount", - "do.po_qty":"PO Qty", - "do.po_balance_qty":"PO Balance\nQty", - "do.do_qty":"DO Qty", - "do.po_num":"PO Number", - "do.driver.image":"Driver Image", - "do.driver.sign":"Driver Signature", - "do.receipt":"Delivery Receipt", - "do.no.photo":"No selected photo", - "do.storage_charge" :"Storage Charge", - "do.storage_receipt":"Storage Receipt", - "do.comment":"Comment", - "do.confirm":"Submit Delivery Order?", - "do.approve.confirm":"Approve this DO?", - "do.cancel.confirm":"Cancel this DO?", - "do.end.confirm":"End delivery?", - "do.receipt.title":"Delivery Receipt", - "do.single":"Single", - "do.multiple": "Multiple", - "do_qty":"DO Qty", - "do.product.title":"DO Product", - "do.cancel":"Cancel", - "do.enter":"Enter", - "do.qtys":"DO Qtys", - "do.details":"Details", - "do.counts":"DO Counts", - "do.count":"DO Count", - "do.products":"DO Products", - "do.count.status":"DO Status", - "do.total_count":"Total Count", - - "storage.name":"Storage Name", - "storage.form.name":"Please enter storage name", - "storage.date":"Date", - "storage.form.date":"Please enter date", - "storge": "Storage", - "storage.product.qty":"Quantity", - "storage.delete_confirm":"Delete storage?", - - "name": "Name", - "form.name":"Please enter name", - - - "input_sms": "Input SMS Code", - "sms.sms": "Enter SMS Code", - "sms.empty":"Please Enter SMS Code", - "sms.enter":"Enter", - "singin": "Sign In", - - "email.input": "Input Email Code", - "email.code":"Enter Email Code", - "email.code_empty":"Please Enter SMS Code", - - - "inventory.takings":"Inventory Takings", - "inventory.take":"Take Inventory", - "inventory.item":"Inventory", - "inventory.product": "Product", - "inventory.storage": "Storage", - "inventory.quantity": "Quantity", - "inventory.old.qty": "Old Quantity", - "inventory.new.qty": "New Quantity", - "inventory.form.qty":"Please enter quantity", - "inventory.confirm":"Submit Inventory Taking?", - - - "pd":"PD", - "pd.product.title":"PD Product", - "pd.date" :"Date", - "pd.product": "Product", - "pd.storage": "Storage", - "pd.quantity": "Quantity", - "pd.form.quan":"Please enter quantity", - "pd.confirm":"Submit Purchase Delivery?", - - "buyer.title":"Buyers", - "buyer.type_biz":"Business Type", - "buyer.account_name":"Account Name", - "buyer.phone_number":"Phone Number", - "buyer.quota":"Daily Quota", - "buyer.max.quota":"Maximum Quota", - "buyer.name":"Buyer", - "buyer.product":"Product", - "buyer.balQty":"Balance Volume", - "buyer.approve.confirm":"Confirm to approve buyer?", - "buyer.delete.confirm":"Delete buyer request?", - "buyer.allocate.quota.confirm":"Allocate Quota?", - - - "noti.title":"Notifications", - "noti.list.title":"NOTIFICATIONS", - "log.title":"Logs", - - "document.log.title":"Document Logs", - "document.date":"Date", - "document.by":"By", - "document.desc":"Description", - - - - "manual.title":"Manual", - "myreg.title":"My\nRegistration", - "storage.title":"Storages", - "storage.item.title":"Storage", - "pd.title":"PDs", - - "employee.title":"Employees", - "employee.item.title":"Employee", - "employee.phone":"Phone Number", - "employee.add":"Add", - "employee.update":"Update", - - "setting.title":"Settings", - "setting.confirm":"Confirm update setting?", - - "users.title":"Users", - "user.title":"User", - "user.save":"Save", - "user.block.confirm":"Confirm to block this user?", - "user.block_list":"Block lists", - "user.unblock.confirm":"Confirm to unblock this user?", - - "banks.title":"Bank Accounts", - "banks.edit.title":"Bank Account", - "banks.name":"Bank Name", - "banks.account.name":"Account Name", - "banks.account.number":"Account Number", - "banks.account.delete.confirmation":"Delete Bank Account?", - - - "delivery.title":"Deliveries", - "delivery":"DELIVERIES", - "delivery.confirm":"End delivery?", - "delivery.detail":"Details", - "delivery.date":"Date", - "delivery.qty":"Quantity", - "delivery.do.title":"Delivery DO", - "delivery.do.details":"Details", - "delivery.do.counts":"Delivery DO Counts", - "delivery.do.count":"Delivery DO Count", - "delivery.do.summary":"Delivery DO Summary ", - "delivery.do.sum.counts":"Delivery DO Summary Counts", - "delivery.days":"Days", - "delivery.summary":"Delivery Summary", - "delivery.sum.amounts":"Delivery Summary Amounts", - - "delivery.data.title":"Deliveries", - - "delivery.detail.title":"{0} Deliveries", - - "chart.daily.title":"Daily Quota ({0} Liters)", - "chart.max.title": "Maximum Quota ({0} Liters)", - "chart.remaining": "remaining", - "chart.used": "used", - "chart.revenue":"Revenue", - "chart.spending":"Spending", - "chart.date":"Date", - "chart.30_days":"(Last 30 days)", - - "revenue.amounts":"Revenue Amounts", - "revenue.date":"Date", - "revenue.amount":"Amount", - "revenue.detail":"Details", - "revenue.detail.title":"{0} Revenue Amounts", - - "spending.amounts":"Spending Amounts", - "spending.detail.title":"{0} Spending Amounts", - - "load": "Loading...", - - "Cancel": "Cancel", - "Ok": "Ok", - - "singup": "Sing Up", - "buyer.reg": "Buyer Registeration", - "po.sub": "PO Submission", - "do.sub": "DO Submission", - "inventory.taking": "Inventory Taking", - "do.approved": "DO approved", - "po.approved": "PO approved", - "buyer.approved": "Buyer approved", - "purchase.delivery": "Purchase Delivery", - "do.delivery": "DO Delivery", - "product.price": "Product Price", - - "Click 'Initiate Delivery' button": "Click 'Initiate Delivery' button", - "Click 'Start Delivery'": "Click 'Start Delivery'", - - "1":"1", - "2":"2", - "3":"3", - - "signup.slide.initial":"1.Click Arrow button", - "signup.slide.s1": "1.Select 'Signup' button \n2.Enter all data info\n3.Click 'SIGNUP' button", - "signup.slide.s2" : "1.Enter SMS code\n2.Click 'Sign In' button", - "signup.slide.s3": "1.Click 'Agree' button", - "signup.slide.s4": "1.Click 'Ok' button", - "signup.slide.s5": "Finish SignUp", - - "login.slide.s1":"1.Select 'Login' button\n2.Enter Phone Number and Password\n3.Click 'LOGIN' button", - - "buyerreg.slide.s1":"1.Click 'My Registration' button", - "buyerreg.slide.s2":"1.Enter all data info\n2.Click Sent button", - "buyerreg.slide.s4":"Finished Registration", - - "posub.slide.s1": "1.Click 'POs'", - "posub.slide.s2": "1.Click '+' button", - "posub.slide.s3":"1.Click '+' button\n2.Click Sent button", - "posub.slide.s4":"1.Enter Volume and select Product\n2.Click 'Save' button", - "posub.slide.s6": "Finished PO Submission", - - "dosub.slide.s1": "1.Click 'More' button", - "dosub.slide.s2": "Click 'Create DO'", - "dosub.slide.s4" : "1.Enter all data info\n2.Click Sent button", - "dosub.slide.s6": "Finished DO Submission", - - "storage.slide.s1": "Click Storages", - "storage.slide.s3" : "1.Enter storage name\n2.Click 'Save' button", - - "inventory.taking.s1": "Click Inventory Takings", - "inventory.taking.s4":"1.Select storage name , product and enter quantity\n2.Click 'Save' button,", - "inventory.taking.s5": "1.Click Sent button", - "inventory.taking.s7": "Finished Inventory Taking", - - "poapproved.slide.s1": "Select you want to approve PO", - "poapproved.slide.s3": "1.Click Approve PO", - "poapproved.slide.s5": "Finished PO Approved", - - "doapproved.slide.s1": "Select you want to approve DO", - "doapproved.slide.s3": "1.Select storage name", - "doapproved.slide.s6": "Finished DO Approved", - "doapproved.slide.s5": "1.Click 'More' button\n2.Click Approve DO", - - "buyerapproved.slide.s1": "1.Select New Buyer Registration", - "buyerapproved.slide.s3": "1.Click 'Approve'", - - "product.slide.s1": "1.Click 'Products'", - "product.slide.s2": "1.Click pencil button", - "product.slide.s3": "1.Enter product info\n2.Click 'Save' button", - - - "pd.slide.s1": "1.Click 'PDs'", - "pd.slide.s5": "1.Click Sent button\n2.Click 'Ok' button", - - "dodelivery.slide.s1": "Select DO, want to delivery", - - "Login": "Login", - "Signup": "Signup", - - "forget.pass" : "Forgot Password?", - "manual.confirm": "Are you sure want to delete?", - - "offline.status":"Offline, unable to connect to server!", - - "report.title":"Reports", - "report.user_delete_confirm":"Delete this report user?", - "report.user.search":"Search", - "report.users.title":"{0} Users", - - "announcement.title":"Announcements", - "announcement.form.title":"Announcement", - "announcement.name":"Subject", - "announcement.name_empty":"Please enter subject", - "announcement.delete_confirm":"Delete announcement?", - "announcement.desc":"Description", - - "login": "SignIn", - "login.title":"Sign in to FCS", - "login.phone":"Enter phone number", - + "User Start ================================================================":"", "user_edit.welcome":"Welcome to FCS", "user_edit.name":"Please enter your name", "user.phone":"MY PHONE NUMBER", "user.fcs_id":"MY FCS_ID", "user.shipping_address":"USA SHIPPING ADDRESS", "user.deliveryAddress":"My delivery address", - "user.form.shipping_address":"ADDRESS", + "User End ================================================================":"", + "Customer Start ================================================================":"", + "customers.btn": "Customers", + "customer.list.title":"Customers", + "customer.name":"Name", + "customer.phone":"Phone number", + "customer.status":"Status", + "customer.fcs.id":"FCS ID", + "customer.invitation.request.confirm":"Accept customer", + "customer.disable.btn":"Disable", + "customer.enable.btn":"Enable", + "Customer End ================================================================":"", - "notifications.title":"Notification", + "Invitation Start ================================================================":"", + "invitation.list": "Invitations", + "invitation.edit": "Invitation", + "invitation.new": "New invitation", + "invitation.form.title":"New Invitation", + "invitation.confirm.delete": "Delete this invitation?", + "Invitation End ================================================================":"", + "Staff Start ================================================================":"", + "staff.title":"Staffs", + "staff.list.title":"Staffs", + "staff.new":"New staff", + "staff.form.title":"Staff", + "staff.add":"Add", + "staff.update":"Update", + "staff.phone.search":"Enter phone number", + "Staff End ================================================================":"", - "shipment.title":"FCS Shipments", - "shipment.list.title":"FCS SHIPMENTS", - "shipment.add":"New FCS shipment", - "shipment.form.title":"FCS SHIPMENT", - "shipment.number":"FCS Shipment Number", - - "pickup": "Shipments", - "pickup.title": "SHIPMENTS", - "pickup.new": "New Shipment", - "pickup.edit.title": "SHIPMENT", + "Profile Start ================================================================":"", + "profile.title": "My Profile", + "profile.edit_title": "Edit My Profile", + "profile.edit.currency.title":"Preferred Currency", + "profile.name": "Name", + "profile.phone": "Phone", + "profile.language": "Languages", + "profile.logout": "logout", + "profile.currency":"Preferred currency", + "profile.usa.shipping.address": "USA shipping address", + "profile.logout.confirm":"Are you sure want to logout?", + "profile.devices":"Devices", + "profile.email":"Email", + "profile.privileges":"Privileges", + "profile.default.delivery.address":"Default delivery address", + "Profile End ================================================================":"", - "rate":"Rates", - "rate.title":"RATES", + "Package Start ================================================================":"", + "package.btn.name":"Track Packages", + "package.title":"Packages", + "package.create.title":"New packages", + "package.create.fcs.id":"FCS ID", + "package.create.name":"Customer name", + "package.create.phone":"Phone number", + "package.tracking.id":"Tracking ID", + "package.create.packages":"Complete receiving", + "package.create.market":"Market", + "package.delete.confirm":"Delete this package?", + "package.edit.status":"Status", + "package.edit.title":"Edit Package", + "package.edit.remark":"Remark", + "package.edit.desc":"Description", + "package.edit.complete.process.btn":"Complete processing", + "package.edit.procseeing":"Processing", + "package.info.title":"Package", + "package.arrival.date":"Arrival date", + "package.number":"Carton number", + "package.rate":"Rate", + "package.weight":"Weight", + "package.amount":"Amount", + "package.delivery.address":"Delivery address", + "package.popupmenu.active":"Active Packages", + "package.popupmenu.delivered":"Delivered Packages", + "Package End ================================================================":"", - "rate.edit.title":"EDIT RATES", + "Market Start ================================================================":"", + "market.edit.title":"Markets", + "market.edit.name":"Market name", + "market.remove.confirm":"Remove this market?", + "Market End ================================================================":"", - "rate.cal.title":"ESTIMATE SHIPPING COST", - - "cargo.form.title":"CARGO", - "cargo.type":"Cargo Type", - "cargo.weight":"Weight", - "cargo.rate":"Rate", - "cargo.amount":"Amount", - - "boxes.name":"Boxes", - "boxes.title":"BOXES", - "boxes.new":"New Box", - "box.edit.title":"BOX", + "Buy_Online Start ================================================================":"", + "buy_online.title":"Buying instructions", + "buy_online":"Buying instructions", + "buy_online.buying_instruction":"See below instructions to add USA shipping address while shoping online", + "buy_online.fullname":"With full name", + "buy_online.first.last":"With first name and last name", + "Buy_Online End ================================================================":"", + + "Payment Start ================================================================":"", + "pm.title":"Payment Methods", + "pm.new":"New payment method", + "pm.form.new":"New Payment Method", + "pm.update":"Update Payment Method", + "pm.btn":"Payment methods", + "pm.name":"Name", + "pm.status":"Status", + "pm.pay":"Pay", + "pm.btn_confirm":"Confirm", + "pm.btn_cancel":"Cancel", + "pm.gallery":"Gallery", + "pm.camera":"Camera", + "pm.remove_photo":"Remove", + "pm.account.name":"Account name", + "pm.account.no":"Account number", + "pm.phone":"Phone number", + "pm.email":"Email address", + "pm.link":"Link", + "pm.add.btn":"Add payment method", + "pm.save.btn":"Save payment method", + "pm.delete.confirm":"Delete this payment method?", + "pm_.title": "PAYMENT", + "pm.date": "Date", + "pm.amount": "Amount", + "pm.receipt":"Payment receipt amount", + "pm.attachment":"Payment attachment", + "pm.remaining_balance":"Remaining balance : ", + "pm.total.amount": "Amount :", + "Payment End ================================================================":"", + + "Message Start ================================================================":"", + "message.btn":"Notifications", + "message.view.detail":"View deatil", + "message.hint.input":"Type your message...", + "Message End ================================================================":"", + + "Boxes Start ================================================================":"", + "boxes.name":"Cartons", + "boxes.title":"Cartons", + "boxes.new":"New carton", + "boxes.create.title":"New Carton", + "box.edit.title":"Edit Carton", "box.package.id":"Package ID", "box.package.desc":"Description", "box.package.market":"Market", - "box.add_package":"Add Package", - "box.number":"Box Number", + "box.add_package":"Add package", + "box.number":"Carton number", "box.length":"Length", "box.width":"Width", "box.height":"Height", + "box.shipment_info":"Shipment information", + "box.cargo.type":"Cargos", + "box.dimension":"Dimension", + "box.delivery_address":"Delivery address", + "box.fcs_shipment_num":"FCS shipment number", + "box.fcs.id":"FCS ID", + "box.name":"Customer name", + "box.phone":"Phone number", + "box.actual_weight":"Actual weight", + "box.add_cargo":"Add cargo", + "box.shipment_weight":"Shipment weight", + "box.change_address":"Change\naddress", + "box.status":"Status", + "box.create.btn":"Create new carton", + "box.complete.btn":"Complete packing", + "box.deliver.btn":"Deliver", + "box.packages":"Packages", + "box.tracking.id":"Tracking ID", + "box.market":"Market", + "box.cargo.save.btn":"Save", + "box.type.title":"Carton types", + "box.shipment.boxes":"Cartons", + "box.shipment_number":"Shipment number", + "box.shipment.desc":"Description", + "box.mix.number":"Carton number", + "box.mix.desc":"Description", + "box.info.title":"Carton", + "box.popupmenu.active":"Active Cartons", + "box.popupmenu.delivered":"Delivered Cartons", + "box.cargo.total":"Total Weight", + "box.delete.confirm":"Delete carton?", + "box.mix.carton":"Go into mix carton", + "Boxes End ================================================================":"", + + "Delivery Start ================================================================":"", + "delivery.title":"Deliveries", + "delivery":"Deliveries", + "delivery.info.title":"Delivery", + "delivery.popupmenu.active":"Active cartons", + "delivery.popupmenu.delivered":"Delivered cartons", + "delivery.deliver.btn":"Complete delivery", + "delivery.deliver.confirm":"Complete delivery?", + "Delivery End ================================================================":"", - "pickup.date": "Pickup Date", - "pickup.location_time": "Pickup Location / Time", - "pickup.information": "Pickup Informations", - "pickup.recipient_information": "Recipient Informations", + "FCS Shipment Start ================================================================":"", + "FCSshipment.title":"FCS Shipments", + "FCSshipment.list.title":"FCS Shipments", + "FCSshipment.add":"New FCS shipment", + "FCSshipment.form.title":"FCS Shipment", + "FCSshipment.number":"FCS shipment number", + "FCSshipment.cutoff_date":"Cutoff date", + "FCSshipment.ETA":"ETA", + "FCSshipment.departure_date":"Departure date", + "FCSshipment.shipment_type":"Shipment type", + "FCSshipment.consignee":"Consignee", + "FCSshipment.port_of_loading":"Port of loading", + "FCSshipment.final_destination":"Final destination", + "FCSshipment.status":"Status", + "FCSshipment.remark":"Remark", + "FCSshipment.commercial_invoice":"Download commercial invoice", + "FCSshipment.packing_list":"Download packing list", + "FCSshipment.dms":"Download DMS", + "FCSshipment.cargo_manifest":"Download cargo manifest", + "FCSshipment.create":"Create FCS shipment", + "FCSshipment.update":"Update FCS shipment", + "FCSshipment.ship.btn":"Ship", + "FCSshipment.ship.confirm":"Confirm ship?", + "FCSshipment.popupmenu.active":"Active FCS shipments", + "FCSshipment.popupmenu.shipped":"Shipped FCS shipments", + "FCS Shipment End ================================================================":"", - "message.btn":"Notifications", - "message.title":"NOTIFICATIONS", + "Shipment Start ================================================================":"", + "shipment": "Shipments", + "shipment.title": "Shipments", + "shipment.number": "Shipment number", + "shipment.new": "New shipment", + "shipment.new.title": "New shipment", + "shipment.edit.title": "Edit shipment", + "shipment.type": "Pickup/drop-off", + "shipment.date": "Pickup date", + "shipment.date.time": "Pickup date/time", + "shipment.time": "Pickup time", + "shipment.location": "Pickup address", + "shipment.location.dropoff": "Local dropoff address", + "shipment.courier.dropoff":"Courier dropoff", + "shipment.location_time": "Pickup location/time", + "shipment.information": "Pickup information", + "shipment.recipient_information": "Recipient informations", + "shipment.from":"Ready time", + "shipment.to":"Latest time available", + "shipment.box.delivery":"Delivery address", + "shipment.handling.fee":"Handling fee/courier fee", + "shipment.box.cargo.type":"Cargo types", + "shipment.box.dimemsion":"Dimension", + "shipment.box.shipment.weight":"Shipment weight", + "shipment.box.length":"Length", + "shipment.box.width":"Width", + "shipment.box.height":"Height", + "shipment.box.add":"Add carton", + "shipment.cargo.total":"Total weight", + "shipment.cargo.count":"Carton count", + "shipment.popupmenu.active":"Active shipments", + "shipment.popupmenu.delivered":"Delivered shipments", + "shipment.popupmenu.mypickup":"My pickups", + "shipment.create":"Create shipment", + "shipment.update":"Update shipment", + "shipment.info":"Shipment info", + "shipment.cancel.confirm":"Cancel this shipment?", + "shipment.assign.title":"Assign shipment", + "shipment.assign.for.pickup":"Assign for pickup", + "shipment.assign.btn":"Assign", + "shipment.assign.complete.btn":"Complete assign pickup", + "shipment.assign.complete.confirm":"Complete assign pickup?", + "shipment.staff":"Staff", + "shipment.pickup.complete.btn":"Complete pickup", + "shipment.pickup.complete.confirm":"Complete pickup?", + "shipment.pack.complete.btn":"Complete pack", + "shipment.pack.complete.confirm":"Complete pack?", + "shipment.pack.menuitem":"Pack shipment", + "shipment.pack.fcs.shipment":"FCS shipment", + "shipment.pack.btn":"Pack", + "shipment.confirm.menuitem":"Confirm shipment", + "shipment.confirm.btn":"Confirm", + "shipment.confirm.complete.btn":"Complete confirm", + "shipment.confirm.complete.confirm":"Complete confirm?", + "shipment.receive.complete.btn":"Complete receive", + "shipment.receive.complete.confirm":"Complete receive?", + "Shipment End ================================================================":"", - "customers.btn": "Customers", - "customers.title": "CUSTOMERS", + "Rate Start ================================================================":"", + "rate":"Rates", + "rate.title":"Rates", + "rate.edit.title":"Edit rates", + "rate.cal.title":"Calculate Shipping Cost", + "rate.min_weight":"Min weight for free delivery within yangon", + "rate.delivery_fee":"Delivery fees", + "rate.total_estimated_amount":"Total estimated amount", + "rate.volumetric_ratio":"Volumetric ratio", + "rate.custom.form.title":"Custom", + "rate.cutom.product_type":"Product type", + "rate.custom.fee":"Fee", + "rate.discount.weight":"Weight", + "rate.discount.rate":"Discount rate", + "rate.custom_duty.title":"Custom Fee", + "rate.custom_duty":"Custom Fee", + "rate.cargo.type":"Cargo Types", + "rate.discount_by_weight":"Discounts by weight", + "rate.discount_by_weight.edit.delete.confirm":"Delete this discount by weight?", + "rate.custom.edit.delete.confirm":"Delete this custom duty?", + "Rate End ================================================================":"", + "Cargo Start ================================================================":"", + "cargo.form.title":"Cargo", + "cargo.type":"Cargo type", + "cargo.weight":"Weight", + "cargo.rate":"Rate", + "cargo.amount":"Amount", + "cargo.edit.delete.confirm":"Delete this cargo type?", + "Cargo End ================================================================":"", + + "Invoices Start ================================================================":"", "invoices.btn": "Invoices", - "invoices.title": "INVOICES", - "invoices.add":"New Invoice", - "invoice.form.title":"INVOICE", - "invoice.payment":"Payment Receipt", - "invoice.add_box":"Add Box", - "invoice.add_package":"Add Package", - - - - "fcs.btn": "FCS Profile", - "fcs.profile": "FCS PROFILE", - - - "payment.title": "PAYMENT", - "payment.date": "Date", - "payment.amount": "Amount", - "payment.receipt":"Payment Receipt Amount", - "payment.attachment":"Payment Attachment", - "pdf_view.title":"Payment File", - "remaining_balance":"Remaining Balance : ", - "total.amount": "Amount :", + "invoices.title": "Invoices", + "invoices.add":"New invoice", + "invoice.form.title":"Invoice", + "invoice.payment":"Payment receipt", + "invoice.add_box":"Add carton", + "invoice.add_package":"Add package", + "invoice.date":"Invoice date", + "invoice.number":"Invoice number", + "invoice.customer_name":"Customer name", + "invoice.status":"Status", + "invoice.amount":"Amount", + "invoice.weight":"Weight(lb)", + "invoice.rate":"Rate(USD)", + "invoice.total":"Total amount", + "invoice.balance":"Balance", + "invoice.handling_fee":"Handling fee", + "invoice.custom_fee":"Custom fee", + "invoice.custom_fee_desc":"Custom fee description", + "invoice.discount":"Discount code", + "invoice.payment_method":"Payment method", + "invoice.delivery_fee":"Delivery fee", + "invoice.payment_attachment":"Payment attachment", + "invoice.box_info":"Cartons", + "invoice.cargo_table":"Cargo table", + "invoice.issue.btn":"Issue invoice", + "invoice.btn_save":"Save invoice", + "invoice.btn_payment_receipt":"Attachment payment receipt", + "invoice.description": "Description", + "invoice.box.cargo_type": "Cargo types", + "invoice.box.desc": "Description", + "invoice.cargo_type":"Cargo types", + "invoice.box.number":"Carton number", + "invoice.box.length":"L", + "invoice.box.width":"W", + "invoice.boc.height":"H", + "invoice.discount_value": "Discount", + "invoice.net_amount":"Net Amount", + "invoice.customer_info":"Customer information", + "invoice.pdf": "Invoice PDF", + "invoice.total_custom_fee":"Total custom fee", + "invoice.shipment_weight":"Shipment weight", + "invoice.popupmenu.issused":"Issused", + "invoice.popupmenu.paid":"Paid", + "invoice.popupmenu.cancel":"Canceled", + "invoice.shipment.title":"Select FCS shipment", + "invoice.customer.title":"Select Customer", + "invoice.add.custom.fee.menu":"Custom fee", + "invoice.add.handling.fee.menu":"Handling fee", + "invoice.add.discount.menu":"Discount", + "invoice.shipment.handling.fee.title":"Select shipment", + "invoice.shipment.number":"Shipment number", + "invoice.shipment.discount.title":"Select discount", + "invoice.cancel.btn":"Cancel", + "invoice.cancel.confirm":"Cancel invoice?", + "Invoices End ================================================================":"", + "Discount Start ================================================================":"", "discount.btn":"Discounts", - "discount.title":"DISCOUNTS", - "discount.new":"New Discount", - "discount.form":"DISCOUNT", + "discount.title":"Discounts", + "discount.new":"New discount", + "discount.form":"Discount", + "discount.code":"Code", + "discount.name":"Customer name", + "discount.amount":"Amount", + "discount.status":"Status", + "discount.edit.delete.confirm":"Delete this discount?", + "discount.popupmenu.available":"Available discounts", + "discount.popupmenu.used":"Used discounts", + "Discount End ================================================================":"", - "custom.form.title":"CUSTOM", - "shipping_addresses": "ADDRESSES" + "delivery_addresses Start ================================================================":"", + "delivery_addresses": "Delivery Addresses", + "delivery_address": "Delivery Address", + "delivery_address.full_name": "Full name", + "delivery_address.address_line1": "Address line 1", + "delivery_address.address_line2": "Address line 2", + "delivery_address.state_region": "State/Region", + "delivery_address.city": "City", + "delivery_address.country": "Country", + "delivery_address.phonenumber": "Phone number", + "delivery_address.create": "Create delivery address", + "delivery_address.update": "Update delivery address", + "delivery_address.new_address":"Add new\naddress", + "delivery_address.change_address": "Change address", + "delivery_address.delete.confirm":"Delete this delivery address?", + "delivery_addresses End ================================================================":"", + "Receiving Start ================================================================":"", + "receiving.title":"Receivings", + "receiving.info":"Receiving", + "receiving.new":"New receiving", + "receiving.create":"New Receiving", + "receiving.update":"Update Reveiving", + "receiving.tracking.id":"Tracking ID", + "receiving.remark":"Remark", + "receiving.fcs.id":"FCS ID", + "receiving.name":"Customer name", + "receiving.phone":"Phone number", + "receiving.create_btn":"Complete receiving", + "receiving.update_btn":"Update reveiving", + "receiving.delete.confirm":"Delete this receiving?", + "receiving.return.btn":"Return package", + "receiving.return.confirm":"Return package?", + "Receiving End ================================================================":"", + + "Processing Start ================================================================":"", + "processing.title":"Processing", + "processing.info.title":"Processing", + "processing.tracking.id":"Tracking ID", + "processing.name":"Customer name", + "processing.phone":"Phone number", + "processing.fcs.id":"FCS ID", + "processing.market":"Market", + "processing.status":"Status", + "processing.desc":"Description", + "processing.remark":"Remark", + "processing.edit.title":"Processing", + "processing.delete.confirm":"Delete this package?", + "processing.edit.sub_title":"Processing", + "processing.edit.complete.btn":"Complete processing", + "Processing End ================================================================":"" } \ No newline at end of file diff --git a/assets/local/localization_mu.json b/assets/local/localization_mu.json index b2b8251..8e064c6 100644 --- a/assets/local/localization_mu.json +++ b/assets/local/localization_mu.json @@ -1,4 +1,33 @@ { + "Loading Start ================================================================":"", + "load": "လုပ်ဆောင်နေပါသည်...", + "Loading End ================================================================":"", + + "Buttons Start ================================================================":"", + "btn.save":"သိမ်းဆည်းရန်", + "btn.approve":"အတည်ပြုရန်", + "btn.delete":"ဖျက်ရန်", + "btn.select":"ရွေးချယ်ပါ", + "btn.cancel":"ဖျက်သိမ်းမည်", + "btn.ok": "အိုကေ", + "feet":"ပေ", + "inch":"လက်မ", + "Buttons End ================================================================":"", + + "Offline Start ================================================================":"", + "offline.status":"အင်တာနက် ပိတ်ထားသည်, ဆာဗာကို ဆက်သွယ်၍ မရပါ!", + "Offline End ================================================================":"", + + "Language Start ================================================================":"", + "language.selection.title":"ဘာသာစကား ရွေးချယ်ပါ", + "Language End ================================================================":"", + + "Welcome Start ================================================================":"", + "welcome.signin":"ဝင်မည်", + "welcome.msg":"FCS က ကြိုဆိုပါတယ်!", + "Welcome End ================================================================":"", + + "Contact Start ================================================================":"", "contact.btn":"ဆက်သွယ်ရန်", "contact.title":"ဆက်သွယ်ရန်", "contact.phone.title":"ဖုန်းနံပါတ်ထည့်သွင်းရန်", @@ -26,15 +55,29 @@ "contact.findus":"တည်နေရာ", "contact.emailus":"အီးမေးလ်", "contact.visitus":"ကြည့်ပါ", - "contact.edit.title":"ဆက်သွယ်ရန် ပြုပြင်ခြင်း", + "Contact End ================================================================":"", + "Term Start ================================================================":"", "term":"စည်းကမ်းချက်များ", "term.btn":"စည်းကမ်းချက်များ", + "Term End ================================================================":"", + "Login Start ================================================================":"", + "login.title":"FCS သို့အကောင့်ဒ်၀င်ပါ", + "login.phone":"ဖုန်းနံပါတ်ထည့်ပါ", + "Login End ================================================================":"", + + "SMS Start ================================================================":"", + "sms.verify.title":"သင့်နံပါတ်ကိုအတည်ပြုပါ", + "sms.six.digit":"SMS ဂဏန်း ခြောက်လုံး ကိုရိုက်ထဲ့ပါ", + "sms.resend":"ပြန်ပို့ရန်", + "sms.resend.seconds":"SMS ပြန်ပို့ရန် {0} စက္ကန့် စောင့်ပါ", + "SMS End ================================================================":"", + + "FAQ Start ================================================================":"", "faq.btn":"မေးလေ့ရှိသောမေးခွန်းများ", "faq.title":"မေးလေ့ရှိသောမေးခွန်းများ", - "faq.add.title":"မေးခွန်း အသစ်", "faq.edit.title":"မေးခွန်း ပြုပြင်ခြင်း", "faq.edit.eng":"အင်္ဂလိပ်", @@ -42,43 +85,57 @@ "faq.edit.question":"မေးခွန်း", "faq.edit.answer":"အဖြေ", "faq.edit.sn":"S/N", - "faq.edit.delete.confirm":"Delete this FAQ?", + "faq.edit.delete.confirm":"မေးခွန်းကို ဖျက်မလား?", "faq.edit.page":"Additional Page", "faq.edit.page.label":"Page label", "faq.edit.page.label.eng":"Page label in English", "faq.edit.page.label.mm":"Page label in Myanmar", + "FAQ End ================================================================":"", - - "language.selection.title":"ဘာသာစကား ရွေးချယ်ပါ", - - "welcome.signin":"ဝင်မည်", - "welcome.msg":"FCS က ကြိုဆိုပါတယ်!", - + "Home Start ================================================================":"", "home.invitation.request.msg":"ဖိတ်ကြားမှု တောင်းဆိုသည်ကို လုပ်ဆောင်နေပါသည်!", + "home.search":"Tracking number ရိုက်ထည့်ပါ", + "home.search.btn":"ရှာမည်", + "Home End ================================================================":"", - "sms.verify.title":"သင့်နံပါတ်ကိုအတည်ပြုပါ", - "sms.six.digit":"SMS ဂဏန်း ခြောက်လုံး ကိုရိုက်ထဲ့ပါ", - "sms.resend":"ပြန်ပို့ရန်", - "sms.resend.seconds":"SMS ပြန်ပို့ရန် {0} စက္ကန့် စောင့်ပါ", - + "Invite Start ================================================================":"", "invite.title":"FCS ဖိတ်ကြားမှု လိုအပ်သည်", "invite.name.enter":"နာမည် ရိုက်ထည့်ပါ", "invite.request":"ဖိတ်ကြားမှု တောင်းဆိုမည်", "invite.request.successful":"တောင်းဆိုမှု အောင်မြင်သည်!", "invite.btn":"ဖိတ်ကြားမည်", + "Invite End ================================================================":"", + + "User Start ================================================================":"", + "user_edit.welcome":"FCS မှကြိုဆိုပါသည်", + "user_edit.name":"ကျေးဇူးပြု၍ နာမည်ထည့်ပေးပါ", + "user.phone":"My phone number", + "user.fcs_id":"My FCS_ID", + "user.shipping_address":"My USA shipping address", + "user.deliveryAddress":"My delivery address", + "User End ================================================================":"", + "Customer Start ================================================================":"", + "customers.btn": "ဝယ်ယူသူများ", "customer.list.title":"ဝယ်ယူသူများ", "customer.name":"နာမည်", "customer.phone":"ဖုန်းနံပါတ်", "customer.status":"အခြေအနေ", "customer.fcs.id":"FCS ID", "customer.invitation.request.confirm":"လက်ခံ လိုက်ပါ", + "customer.disable.btn":"ပိတ်ပါ", + "customer.enable.btn":"ဖွင့်ပါ", + "Customer End ================================================================":"", + "Invitation Start ================================================================":"", "invitation.list": "ဖိတ်ကြားမှုများ", "invitation.edit": "ဖိတ်ကြားမှု", "invitation.new": "ဖိတ်ကြားမှု အသစ်", + "invitation.form.title":"ဖိတ်ကြားမှု အသစ်", "invitation.confirm.delete": "ဖိတ်ကြားမှု ဖျက်မလား?", + "Invitation End ================================================================":"", + "Staff Start ================================================================":"", "staff.title":"ဝန်ထမ်းများ", "staff.list.title":"ဝန်ထမ်းများ", "staff.new":"ဝန်ထမ်း အသစ်", @@ -86,20 +143,26 @@ "staff.add":"အသစ်ထည့်မည်", "staff.update":"ပြုပြင်မည်", "staff.phone.search":"ဖုန်းနံပါတ် ရိုက်ထည့်ပါ", + "Staff End ================================================================":"", + "Profile Start ================================================================":"", "profile.title":"ကျွန်ုပ် ပရိုဖိုင်", "profile.edit_title":"ကျွန်ုပ် ပရိုဖိုင်ကိုပြုပြင်ရန်", + "profile.edit.currency.title":"နှစ်သက်သော ငွေအမျိုးအစား", "profile.name":"နာမည်", "profile.phone": "ဖုန်းနံပါတ်", "profile.language": "ဘာသာစကားများ", "profile.logout": "အကောင့်ထွက်ရန်", - "profile.usa.shipping.address": "အမေရိကား ပစည်းပို့ရန်လိပ်စာ", + "profile.currency":"နှစ်သက်သော ငွေအမျိုးအစား", + "profile.usa.shipping.address": "အမေရိကား ပစ္စည်းပို့ရန်လိပ်စာ", "profile.logout.confirm":"အကောင့်ထွက်ရန်သေချာပြီလား?", "profile.devices":"ဖုန်းမော်ဒယ်အမျိုးအစားများ", "profile.email":"အီးမေးလ်", - "profile.privilege":"လုပ်ပိုင်ခွင့်", - + "profile.privileges":"လုပ်ပိုင်ခွင့်များ", + "profile.default.delivery.address":"အမြဲတမ်း ပို့ဆောင်ရမည့်လိပ်စာ", + "Profile End ================================================================":"", + "Package Start ================================================================":"", "package.btn.name":"အထုပ်များ", "package.title":"အထုပ်များ", "package.create.title":"အထုပ် အသစ်များ", @@ -110,37 +173,51 @@ "package.create.packages":"အထုပ် အသစ်များ လက်ခံမည်", "package.create.market":"အွန်လိုင်စျေးဆိုင်", "package.delete.confirm":"အထုပ်ကို ဖျက်မလား?", - "package.edit.title":"အထုပ် ပြင်ဆင်ခြင်း", "package.edit.remark":"မှတ်ချက်", "package.edit.desc":"ဖော်ပြချက်", "package.edit.complete.process.btn":"မွမ်းမံခြင်း ပြီးဆုံးသည်", "package.edit.status":"အခြေအနေ", "package.edit.procseeing":"မွမ်းမံခြင်း", - "package.info.title":"အထုပ်", - "package.arrival.date":"Arrival Date", "package.number":"Package Number", "package.rate":"Rate", "package.weight":"Weight", "package.amount":"Amount", + "package.delivery.address":"ပို့ဆောင်ရမည့်လိပ်စာ", + "package.popupmenu.active":"လာမည့် အထုပ်များ", + "package.popupmenu.delivered":"ပို့ပြီးသော အထုပ်များ", + "Package End ================================================================":"", + "Market Start ================================================================":"", "market.edit.title":"Markets", "market.edit.name":"Market Name", "market.remove.confirm":"Remove this market?", + "Market End ================================================================":"", + "Buy_Online Start ================================================================":"", "buy_online.title":"ဝယ်ယူရန်ညွှန်ကြားချက်များ", "buy_online":"ဝယ်ယူရန်ညွှန်ကြားချက်များ", "buy_online.buying_instruction":"လိပ်စာထည့်ရန် ညွှန်ကြားချက်များကို အောက်တွင်ကြည့်ပါ", "buy_online.fullname":"နာမည် အပြည့်အစုံ", "buy_online.first.last":"ပထမအမည် နှင့် နောက်ဆုံးအမည်", + "Buy_Online End ================================================================":"", + "Payment Start ================================================================":"", "pm.title":"ငွေပေးချေစနစ်များ", - "pm.new":"ငွေပေးချေစနစ်အသစ်", + "pm.new":"ငွေပေးချေစနစ် အသစ်", + "pm.form.new":"ငွေပေးချေစနစ် အသစ်", "pm.update":"ငွေပေးချေစနစ် ပြင်ဆင်ခြင်း", "pm.btn":"ငွေပေးချေစနစ်များ", "pm.name":"အမည်", + "pm.status":"အခြေအနေ", + "pm.pay":"ပေးဆောင်ရန်", + "pm.btn_confirm":"အတည်ပြုရန်", + "pm.btn_cancel":"ပယ်ဖျက်ရန်", + "pm.gallery":"ပြခန်း", + "pm.camera":"ကင်မရာ", + "pm.remove_photo":"ဖယ်ရှားမည်", "pm.account.name":"အကောင့် အမည်", "pm.account.no":"အကောင့် နံပါတ်", "pm.phone":"ဖုန်း နံပါတ်", @@ -149,556 +226,319 @@ "pm.add.btn":"ပေါင်းထည့်ရန်", "pm.save.btn":"သိမ်းဆည်းရန်", "pm.delete.confirm":"ငွေပေးချေစနစ်ကို ဖျက်မလား?", + "pm_.title": "ငွေပေးချေခြင်း", + "pm.date": "ရက်စွဲ", + "pm.amount": "ပမာဏ", + "pm.receipt":"ပေးချေပြီးပမာဏများ", + "pm.attachment":"ပေးချေပြီးဖိုင်များ", + "pm.remaining_balance":"ပေးချေရန်ကျန်ရှိငွေ : ", + "pm.total.amount": "ပမာဏ :", + "Payment End ================================================================":"", + "Message Start ================================================================":"", + "message.btn":"အသိပေးချက်များ", "message.view.detail":"အသေးစိတ် ကြည့်ရန်", "message.hint.input":"စာကို ဒီမှာ ရိုက်ထည့်ပါ...", + "Message End ================================================================":"", - "btn.save":"သိမ်းဆည်းရန်", - "btn.approve":"အတည်ပြုရန်", - "btn.delete":"ဖျက်ရန်", - "btn.select":"ရွေးချယ်ပါ", - "btn.cancel":"Cancel", - - "================================================================":"", - - - - "product": "ကုန်ပစ္စည်း", - "price": "ဈေးနှုန်း", - "volume": "လီတာ", - "amount": "ပမာဏ", - "storage" :"သိုလှောင်", - - "welcome.price.updateinfo":"နောက်ဆုံး စျေးပြောင်းချိန် : {0}", - "welcome.price.trend":"စျေးလှုပ်ရှားမှု", - "welcome.price.detail":"အသေးစိတ်", - - "products.title":"ဆီအမျိုးအစားများ", - "prodcuts":"ကုန်ပစ္စည်းများ", - "prices":"ဈေးနှုန်းများ", - "product.confirm":"ဆီဈေးနှုန်းပြင်ရန်သေချာပြီလား?", - "products.prices":"ဈေးနှုန်းများ", - "products.gas":"ဆီအမျိုးအစား", - "product.item":"ဆီအမျိုးအစား", - "product.name":"ကုန်ပစ္စည်း အမည်", - "product.name_empty":"ကျေးဇူးပြု၍ ကုန်ပစ္စည်းနာမည်ပေးပါ", - "product.new_price":"စျေးနှုန်းအသစ်", - "product.price_empty":"ကျေးဇူးပြု၍ စျေးနှုန်းကိုထည့်ပါ", - "product.order":"အမှာစာ", - "product.order_empty":"ကျေးဇူးပြု၍ အမှာစာကိုထည့်ပါ", - "product.balance_qty":"ဆီအဝယ်ထုတ်ရန်\nလက်ကျန်အရေအတွက်", - "product.qtys":"လက်ကျန်အရေအတွက်များ", - "product.update.date":"ရက်စွဲ", - "product.close": "ယခု ဆီအဝယ် ပိတ်ပါသည်။", - "product.open": "ဆီအဝယ် ကို {0} မှ {1}\n{2} နေ့များတွင် ဖွင့်ပါသည်။", - "product.purchase.order": "ဝယ်မည်", - - - "login.btn":"ဝင်မည်", - "login.name":"နာမည်", - "login.password":"စကားဝှက်", - "login.confirm_password":"အတည်ပြုစကားဝှက်", - "login.name_empty": "ကျေးဇူးပြု၍ နာမည်ထည့်ပေးပါ", - "login.phone_empty": "ကျေးဇူးပြု၍ သင့်ဖုန်းနံပါတ်ထည့်ပါ", - "login.phone_code": "'+ 959'သာစတင်သည်", - "login.password_empty": "ကျေးဇူးပြု၍ စကားဝှက်ကိုရိုက်ထည့်ပါ", - "login.password_size": "အနည်းဆုံးစာလုံး ၆ လုံး", - "login.confirm_password_empty": "အတည်ပြုစကားဝှက်ကိုရိုက်ထည့်ပါ", - "login.sms_empty":"ကျေးဇူးပြုပြီး sms ကုဒ်ကိုထည့်ပါ", - "login.forgot_password":"စကားဝှက်ကိုမေ့နေပါသလား?", - "login.email.title":"Account ပြန်ယူသော အီးမေးလ်", - "login.email":"အီးမေးလ်", - "login.email.empty":"ကျေးဇူးပြု၍အီးမေးလ်ထည့်ပါ", - "login.email.add":"ထည့်ရန်", - "login.email.skip":"ကျော်ရန်", - - "sing.up":"အသစ်ပြုလုပ်မည်", - "sing.title":"အသစ်ပြုလုပ်ရန်", - - "change.password.title":"စကားဝှက်ကိုပြောင်းရန်", - "change":"ပြောင်းမည်", - "change.phone":"ဖုန်းနံပါတ်ပြောင်းရန်", - "change.new.phone":"ဖုန်းနံပါတ်အသစ်", - "change.phone_empty": "ကျေးဇူးပြု၍ ဖုန်းနံပါတ်အသစ်ထည့်ပါ", - "change.email":"Account ပြန်ယူသော အီးမေးလ်", - "change.pin.title":"ပင်နံပါတ်ထည့်ရန်", - "change.pin":"ပင်နံပါတ်", - "change.pin_empty":"ကျေးဇူးပြု၍ ပင်နံပါတ်ကိုရိုက်ထည့်ပါ", - "change.pin_size":"စာလုံး ၆ လုံးဖြစ်ရမည်", - "pin.add_btn":"ပင်ထည့်မည်", - "pin.clear_btn":"ပင်ရှင်းမည် ", - "pin.switch":"ပင်နံပါတ်ရှင်းရန်", - - "forget.password":"စကားဝှက်ကိုပြင်ရန်", - "forget.email":"အီးမေးလ်(သို့) ဖုန်းနံပါတ်", - "forget.email.empty":"ကျေးဇူးပြု၍အီးမေးလ်(သို့)ဖုန်းနံပါတ်ထည့်ပါ", - "forget.enter":"ဝင်မည်", - - "reset.password.title":"စကားဝှက်ကိုပြန်လုပ်ရန်", - "reset.sms":"SMS ကုဒ်", - "reset.new_password":"စကားဝှကိအသစ်", - "reset":"ပြင်မည်", - - "reg.title":"ကိုယ်ရေးအချက်အလက်", - "reg.biz_name":"လုပ်ငန်း အမည်", - "reg.biz_address":"လုပ်ငန်း လိပ်စာ", - "reg.biz_shops":"ဆိုင်အရေအတွက်", - "reg.biz_shop_addresses":"ဆိုင်လိပ်စာများ", - "reg.type_shop":"ကိုယ်ပိုင်", - "reg.type_agent":"ကိုယ်စားလှယ်", - "reg.status": "အခြေအနေ", - "reg.table_product":"ကုန်ပစ္စည်း", - "reg.table_storage_vol":"သိုလှောင်", - "reg.table_sale_vol":"ရောင်းအား", - "reg.quota": "နေ့စဉ်ခွဲတမ်း", - "reg.max_quota": "အများဆုံးခွဲတမ်း", - "reg.quota.used": "နေ့စဉ်\nအသုံးပြုပြီးခွဲတမ်း", - "reg.max_quota.used": "အများဆုံး\nအသုံးပြုပြီးခွဲတမ်း", - "reg.empty_biz_name": "Empty biz name", - "reg.empty_biz_address":"Empty biz address", - "reg.empty_shops":"Empty shops", - "reg_info.nric_front": "မှတ်ပုံတင် ရှေ့ခြမ်း", - "reg_info.nric_back": "မှတ်ပုံတင် နောက်ခြမ်း", - "reg_info.title": "ကိုယ်ရေးအချက်အလက်", - "reg.confirm":"မှတ်ပုံတင်သွင်းမည်လား?", - "reg.date":"မှတ်ပုံတင်သည့် နေ့စွဲ", - - "device.confirm":"ဒီဖုန်းမော်ဒယ်ကိုအတည်ပြုမည်လား?", - "device.logout":"ဒီဖုန်းမော်ဒယ်ကိုထွက်ရန်သေချာပြီလား?", - "device.set_primary":"ဒီဖုန်းမော်ဒယ်ကိုမူလမော်ဒယ်ထည့်ရန်သေချာပြီလား?", - - "po.title":"ဆီအဝယ်များ", - "po":"ဆီအဝယ်", - "po.approval":"ကုန်ပစ္စည်းအမှာစာအချက်အလက်", - "po.date" :"ဆီအဝယ် ရက်စွဲ", - "po.number":"အဝယ် နံပါတ်", - "po.name":"နာမည်", - "po.po_num": "ဆီအဝယ် နံပါတ်", - "po.biz":"လုပ်ငန်း အမည်", - "po.status":"ဆီအဝယ် အခြေအနေ", - "po.receipt":"လက်ခံဖြတ်ပိုင်းများ", - "po.po_payment":"ဆီအဝယ် ပေးဆောင်ခြင်း", - "po.po_payment_receipt":"ပေးဆောင်ခြင်းလက်ခံဖြတ်ပိုင်း", - "po.storage_receipt":"သိုလှောင် လက်ခံဖြတ်ပိုင်း", - "po.no.photo": "ပုံများရွေးချယ်ထားခြင်းမရှိပါ", - "po.storage_charge" :"သိုလှောင်ခ", - "po.product": "ကုန်ပစ္စည်း", - "po.price": "ဈေးနှုန်း", - "po.volume": "လီတာ", - "po.balance.volume":"လက်ကျန်လီတာ", - "po.amount": "ပမာဏ", - "po.form.volume":"ကျေးဇူးပြု၍ လီတာပမာဏကိုထည့်ပါ", - "po.comment":"မှတ်ချက်", - "po.confirm":"ဆီအဝယ်တင်သွင်းမည်လား?", - "po.approve.confirm":"ဆီဝယ်ခြင်းအတည်ပြုမည်လား?", - "po.cancel.confirm":"ဆီဝယ်ခြင်းပယ်ဖျက်မည်လား?", - "po.counts":"ဆီအဝယ် အရေအတွက်များ", - "po.details":"အသေးစိတ်", - "po.count":"အရေအတွက်", - "po.balances":"ဆီအဝယ်လက်ကျန်အရေအတွက်", - "po.info":"ဆီအဝယ်အချက်အလက်များ", - "po.retrieved.amount":"ဆီထုတ်လက်ကျန်\nအရေအတွက်", - "po.count.status":"ဆီအဝယ်\nအခြေအနေ", - "po.avail.qty":"အဝယ်လက်ကျန်\nအရေအတွက်", - "po.total_count":"စုစုပေါင်းအရေအတွက်", - - "do.title":"ဆီအထုတ်များ", - "do":"ဆီအထုတ်", - "do.do_date":"ဆီအထုတ်\nတင်သွင်းသည့်ရက်စွဲ", - "do.date": "ဆီအထုတ် ရက်စွဲ", - "do.licence": "ယာဉ်မောင်းလိုင်စင်", - "do.driver":"ယာဉ်မောင်း ", - "do.car":"ကားနံပါတ်", - "do.status": "ဆီအထုတ်များ အခြေအနေ", - "do.delivery.status": "ဆီပေးပို့မှု အခြေအနေ", - "do.delivery.init.time":"Delivery Initiated At", - "do.do_num": "ဆီအထုတ် နံပါတ်", - "do.type": "ဆီအထုတ်\nအမျိုးအစား", - "do.name":"နာမည်", - "do.biz":"လုပ်ငန်း အမည်", - "do.form.date":"ကျေးဇူးပြု၍ ဆီအထုတ် နေ့စွဲရိုက်ထည့်ပါ", - "do.form.licence":"ကျေးဇူးပြု၍ ကားလိုင်စင်ထည့်ပါ", - "do.form.driver":"ကျေးဇူးပြု၍ ယာဉ်မောင်းအမည်ထည့်ပါ", - "do.form.car":"ကျေးဇူးပြုပြီးကားနံပါတ်ထည့်ပါ", - "do.product": "ကုန်ပစ္စည်း", - "do.price": "ဈေးနှုန်း", - "do.volume": "လီတာ", - "do.amount": "ပမာဏ", - "do.storage":"သိုလှောင်", - "do.quantity":"အရေအတွက်", - "do.form.volume":"ကျေးဇူးပြု၍ လီတာပမာဏကိုထည့်ပါ", - "do.form.amount":"ကျေးဇူးပြု၍ ငွေပမာဏ ကိုထည့်ပါ", - "do.po_qty":"အဝယ်\nအရေအတွက်", - "do.po_balance_qty":"အဝယ်လက်ကျန်\nအရေအတွက်", - "do.do_qty":"အထုတ်\nအရေအတွက်", - "do.po_num":"အဝယ် နံပါတ်", - "do.driver.image":"Driver Image", - "do.driver.sign":"Driver Signature", - "do.receipt":"ဆီအထုတ် လက်ခံဖြတ်ပိုင်း", - "do.no.photo":"ပုံများရွေးချယ်ထားခြင်းမရှိပါ", - "do.storage_charge" :"သိုလှောင်ခ", - "do.storage_receipt":"သိုလှောင်လက်ခံဖြတ်ပိုင်း", - "do.comment":"မှတ်ချက်", - "do.confirm":"ဆီအထွက်တင်သွင်းမည်လား?", - "do.approve.confirm":"ဆီထုတ်ခြင်းအတည်ပြုမည်လား?", - "do.cancel.confirm":"ဆီဝယ်ခြင်းပယ်ဖျက်မည်လား?", - "do.end.confirm":"ပေးပို့ခြင်းအဆုံးသတ်မည်လား?", - "do.receipt.title":"ဆီအထုတ် လက်ခံဖြတ်ပိုင်း", - "do.single":"အကုန်ထုတ်", - "do.multiple": "ခွဲထုတ်", - "do_qty":"ဆီအထုတ်အရေအတွက်", - "do.product.title":"ဆီအထုတ်ကုန်ပစ္စည်း", - "do.cancel":"ပယ်ဖျက်မည်", - "do.enter":"ဝင်မည်", - "do.qtys":"DO အရေအတွက်များ", - "do.details":"အသေးစိတ်", - "do.counts":"ဆီအထုတ် အရေအတွက်များ", - "do.count":"အရေအတွက်", - "do.products":"ဆီအထုတ် ကုန်ပစ္စည်းများ", - "do.count.status":"ဆီအထုတ်\nအခြေအနေ", - "do.total_count":"စုစုပေါင်းအရေအတွက်", - - "storage.name":"သိုလှောင် အမည်", - "storage.form.name":"ကျေးဇူးပြု၍ သိုလှောင် အမည်ကိုထည့်ပါ", - "storage.date":"ရက်စွဲ", - "storage.form.date":"ကျေးဇူးပြု၍ ရက်စွဲ ကိုထည့်ပါ", - "storge": "သိုလှောင်", - "storage.product.qty":"အရေအတွက်", - "storage.delete_confirm":"သိုလှောင် ကိုဖျက်မည်လား?", - - "name": "နာမည်", - "form.name":"နာမည်ကိုရိုက်ထည့်ပေးပါ", - - "input_sms": "SMS ကုဒ်ကိုရိုက်ထည့်ရန်", - "sms.sms": "SMS ကုဒ်ကိုရိုက်ထည့်ပါ", - "sms.empty":"ကျေးဇူးပြု၍ SMS Code ထည့်ပါ", - "sms.enter":"ဝင်မည်", - "singin": "ဝင်မည်", - - "email.input": "အီးမေးလ် ကုဒ်ကိုရိုက်ထည့်ရန်", - "email.code":"အီးမေးလ် ကုဒ်ကိုရိုက်ထည့်ပါ", - "email.code_empty":"ကျေးဇူးပြု၍ အီးမေးလ်ကုဒ် ထည့်ပါ", - - "inventory.takings":"စာရင်းများ", - "inventory.take":"စာရင်းယူခြင်း", - "inventory.item":"စာရင်း", - "inventory.product": "ကုန်ပစ္စည်း", - "inventory.storage": "သိုလှောင်", - "inventory.quantity": "အရေအတွက်", - "inventory.old.qty": "အဟောင်းအရေအတွက်", - "inventory.new.qty": "အသစ်အရေအတွက်", - "inventory.form.qty":"ကျေးဇူးပြု၍ အရေအတွက် ကိုထည့်ပါ", - "inventory.confirm":"စာရင်းရယူခြင်းတင်သွင်းမည်လား?", - - "pd":"ဆီအဝင်", - "pd.product.title":"ဆီအဝင်ကုန်ပစ္စည်း", - "pd.date" :"ရက်စွဲ", - "pd.product": "ကုန်ပစ္စည်း", - "pd.storage": "သိုလှောင်", - "pd.quantity": "အရေအတွက်", - "pd.form.quan":"ကျေးဇူးပြု၍ အရေအတွက် ကိုထည့်ပါ", - "pd.confirm":"ဆီအဝင်အတည်ပြုမည်လား?", - - "buyer.title":"ဝယ်ယူသူ", - "buyer.type_biz":"လုပ်ငန်း အမျိုးအစား", - "buyer.account_name":"အကောင့်ဒ် နာမည်", - "buyer.phone_number":"ဖုန်းနံပါတ်", - "buyer.quota":"ခွဲတမ်း", - "buyer.max.quota":"အများဆုံးခွဲတမ်း", - "buyer.name":"ဝယ်သူ", - "buyer.product":"ကုန်ပစ္စည်း", - "buyer.balQty":"လက်ကျန်လီတာ", - "buyer.approve.confirm":"ဝယ်ယူသူအတည်ပြုရန်သေချာပြီလား?", - "buyer.delete.confirm":"ဝယ်ယူသူပယ်ဖျက်မည်လား?", - "buyer.allocate.quota.confirm":"ခွဲတမ်းသတ်မှတ်မည်လား?", - - "noti.title":"အသိပေးချက်များ", - "noti.list.title":"NOTIFICATIONS", - "log.title":"မှတ်တမ်းများ", - - "document.log.title":"မှတ်တမ်းများ", - "document.date":"ရက်စွဲ", - "document.by":"အားဖြင့်", - "document.desc":"ဖော်ပြချက်", - - - "manual.title":"လက်စွဲစာအုပ်", - "myreg.title":"ကိုယ်ရေး\nအချက်အလက်", - "storage.title":"သိုလှောင်ကန်များ", - "storage.item.title":"သိုလှောင်ကန်", - "pd.title":"ဆီအဝင်များ", - - "employee.title":"ဝန်ထမ်းများ", - "employee.item.title":"ဝန်ထမ်း", - "employee.phone":"ဖုန်းနံပါတ်", - "employee.add":"ထည့်မည်", - "employee.update":"Update", - - "setting.title":"ချိန်ညှိချက်များ", - "setting.confirm":"ချိန်ညှိချက်များ ကိုပြင်မည်လား?", - - "users.title":"အသုံးပြုသူများ", - "user.title":"အသုံးပြုသူ", - "user.save":"သိမ်းဆည်းမည်", - "user.block.confirm":"ဤအသုံးပြုသူအားတားဆီးရန်အတည်ပြုမည်လား?", - "user.block_list":"တားမြစ်ထားသူများ", - "user.unblock.confirm":"တားမြစ်ထားသူအားပယ်ဖျက်မည်လား?", - - "banks.title":"ဘဏ်အကောင့်များ", - "banks.edit.title":"ဘဏ်အကောင့်", - "banks.name":"ဘဏ် အမည်", - "banks.account.name":"ဘဏ်အကောင့် အမည်", - "banks.account.number":"အကောင့် နံပါတ်", - "banks.account.delete.confirmation":"Delete Bank Account?", + "Boxes Start ================================================================":"", + "boxes.name":"သေတ္တာများ", + "boxes.title":"သေတ္တာများ", + "boxes.new":"သေတ္တာ အသစ်", + "boxes.create.title":"သေတ္တာ အသစ်", + "box.edit.title":"သေတ္တာ ပြင်ဆင်ခြင်း", + "box.package.id":"Package ID", + "box.package.desc":"ဖော်ပြချက်", + "box.package.market":"Market", + "box.add_package":"Add Package", + "box.number":"သေတ္တာ နံပါတ်", + "box.length":"အလျား", + "box.width":"အနံ", + "box.height":"အမြင့်", + "box.shipment_info":"တင်ပို့သတင်းအချက်အလက်", + "box.cargo.type":"ကုန်ပစ္စည်းအမျိုးအစားများ", + "box.dimension":"အရွယ်အစား", + "box.delivery_address":"ပို့ဆောင်ရမည့်လိပ်စာ", + "box.fcs_shipment_num":"FCS တင်ပို့နံပါတ်", + "box.fcs.id":"FCS ID", + "box.name":"နာမည်", + "box.phone":"ဖုန်းနံပါတ်", + "box.actual_weight":"အမှန်အလေးချိန်", + "box.add_cargo":"ကုန်ပစ္စည်း\nထည့်ရန်", + "box.shipment_weight":"တင်ပို့အလေးချိန်", + "box.change_address":"လိပ်စာ\nပြောင်းရန်", + "box.status":"အခြေအနေ", + "box.create.btn":"သေတ္တာအသစ်ပြုလုပ်မည်", + "box.complete.btn":"ထုပ်ပိုးခြင်းပြီးဆုံးမည်", + "box.deliver.btn":"ပေးပို့မည်", + "box.packages":"အထုပ်များ", + "box.tracking.id":"Tracking ID", + "box.market":"အွန်လိုင်စျေးဆိုင်", + "box.cargo.save.btn":"သိမ်းဆည်းမည်", + "box.type.title":"သေတ္တာအမျိုးအစားများ", + "box.shipment.boxes":"သေတ္တာများ", + "box.shipment_number":"ပို့ဆောင်နံပါတ်", + "box.shipment.desc":"ဖော်ပြချက်", + "box.mix.number":"သေတ္တာ နံပါတ်", + "box.mix.desc":"ဖော်ပြချက်", + "box.info.title":"သေတ္တာ", + "box.popupmenu.active":"လာမည့် သေတ္တာများ", + "box.popupmenu.delivered":"ပို့ပြီးသော သေတ္တာများ", + "box.cargo.total":"စုစုပေါင်း အလေးချိန်", + "box.delete.confirm":"Delete carton?", + "box.mix.carton":"Go into mix carton", + "Boxes End ================================================================":"", + "Delivery Start ================================================================":"", "delivery.title":"ပေးပို့ရန်များ", "delivery":"ပေးပို့ရန်များ", - "delivery.confirm":"ပေးပို့ခြင်း အဆုံးသတ်မည်လား?", - "delivery.detail":"အသေးစိတ်", - "delivery.date":"ရက်စွဲ", - "delivery.qty":"ပမာဏ", - "delivery.do.title":"ဆီအထုတ်ပေးပို့ခြင်း", - "delivery.do.details":"အသေးစိတ်", - "delivery.do.counts":"ဆီအထုတ်အရေအတွက်များ", - "delivery.do.count":"အရေအတွက်များ", - "delivery.do.summary":"ဆီအထုတ်ပေးပို့ခြင်း\nအကျဉ်းချုပ်", - "delivery.do.sum.counts":"ဆီအထုတ်ပေးပို့ခြင်း အကျဉ်းချုပ်", - "delivery.days":"ရက်ပေါင်း", - "delivery.summary":"ဆီအထုတ် အကျဉ်းချုပ်", - "delivery.sum.amounts":"ဆီအထုတ် အကျဉ်းချုပ် ပမာဏများ", - - "delivery.data.title":"ပေးပို့ရန်များ", + "delivery.info.title":"ပေးပို့ရန်", + "delivery.popupmenu.active":"လာမည့် သေတ္တာများ", + "delivery.popupmenu.delivered":"ပို့ပြီးသော သေတ္တာများ", + "delivery.deliver.btn":"ပို့ခြင်း ပြီးဆုံးမည်", + "delivery.deliver.confirm":"ပို့ခြင်း ပြီးဆုံးမလား?", + "Delivery End ================================================================":"", - "delivery.detail.title":"{0} ပေးပို့ရန်များ", + "FCS Shipment Start ================================================================":"", + "FCSshipment.title":"FCS တင်ပို့ခြင်းများ", + "FCSshipment.list.title":"FCS တင်ပို့ခြင်းများ", + "FCSshipment.add":"FCS တင်ပို့ခြင်းအသစ်", + "FCSshipment.form.title":"FCS တင်ပို့ခြင်း", + "FCSshipment.number":"FCS တင်ပို့နံပါတ်", + "FCSshipment.cutoff_date":"သတ်မှတ်ရက်", + "FCSshipment.ETA":"ခန့်မှန်းရောက်ချိန်", + "FCSshipment.departure_date":"ထွက်ခွာသည့်ရက်", + "FCSshipment.shipment_type":"တင်ပို့မှုအမျိုးအစား", + "FCSshipment.consignee":"ပစ္စည်းလက်ခံသူ", + "FCSshipment.port_of_loading":"ဆိပ်ကမ်း", + "FCSshipment.final_destination":"ဆိုက်ရောက်နေရာ", + "FCSshipment.status":"အခြေအနေ", + "FCSshipment.remark":"မှတ်ချက်", + "FCSshipment.commercial_invoice":"ငွေတောင်းခံလွှာကိုဒေါင်းမည်", + "FCSshipment.packing_list":"ထုပ်ပိုးစာရင်းကိုဒေါင်းမည်", + "FCSshipment.dms":"DMS ကိုဒေါင်းမည်", + "FCSshipment.cargo_manifest":"ကုန်ပစ္စည်းကိုဒေါင်းမည်", + "FCSshipment.create":"FCS တင်ပို့ခြင်းပြုလုပ်မည်", + "FCSshipment.update":"FCS တင်ပို့ခြင်းပြုပြင်မည်", + "FCSshipment.ship.btn":"Ship", + "FCSshipment.ship.confirm":"Confirm ship?", + "FCSshipment.popupmenu.active":"Active FCS shipments", + "FCSshipment.popupmenu.shipped":"Shipped FCS shipments", + "FCS Shipment End ================================================================":"", - "chart.daily.title":"နေ့စဉ် ခွဲတမ်း ({0} လီတာ)", - "chart.max.title": "အများဆုံး ခွဲတမ်း ({0} လီတာ)", - "chart.remaining": "လက်ကျန်", - "chart.used": "အသုံးပြုပြီး", - "chart.revenue":"ဝင်ငွေ", - "chart.spending":"အသုံးစရိတ်", - "chart.date":"ရက်စွဲ", - "chart.30_days":"(နောက်ဆုံး ၃၀ရက်)", + "Shipment Start ================================================================":"", + "shipment": "ပို့ဆောင်ခြင်းများ", + "shipment.title": "ပို့ဆောင်ခြင်းများ", + "shipment.number": "ပို့ဆောင်ခြင်း နံပါတ်", + "shipment.new": "ပို့ဆောင်ခြင်း အသစ်", + "shipment.new.title": "ပို့ဆောင်ခြင်း အသစ်", + "shipment.edit.title": "ပို့ဆောင်ခြင်း ပြင်ဆင်ခြင်း", + "shipment.type": "Pickup/drop-off", + "shipment.date": "Pickup နေ့စွဲ", + "shipment.date.time": "Pickup နေ့စွဲ/အချိန်", + "shipment.time": "Pickup အချိန်", + "shipment.location_time": "Pickup location/time", + "shipment.location": "Pickup လိပ်စာ", + "shipment.location.dropoff": "Local dropoff လိပ်စာ", + "shipment.courier.dropoff":"Courier dropoff", + "shipment.information": "Pickup informations", + "shipment.recipient_information": "Recipient informations", + "shipment.from":"အချိန်(မှ)", + "shipment.to":"အချိန်(သို့)", + "shipment.box.delivery":"ပို့ဆောင်ရမည့်လိပ်စာ", + "shipment.handling.fee":"Handling fee/courier fee", + "shipment.box.cargo.type":"ကုန်ပစ္စည်းအမျိုးအစားများ", + "shipment.box.dimemsion":"အရွယ်အစား", + "shipment.box.shipment.weight":"တင်ပို့အလေးချိန်", + "shipment.box.length":"အလျား", + "shipment.box.width":"အနံ", + "shipment.box.height":"အမြင့်", + "shipment.box.add":"သေတ္တာထည့်မည်", + "shipment.cargo.total":"စုစုပေါင်း အလေးချိန်", + "shipment.cargo.count":"စုစုပေါင်း ပုံးအရေအတွက်", + "shipment.popupmenu.active":"လာမည့် အထုပ်များ", + "shipment.popupmenu.delivered":"ပို့ပြီးသော အထုပ်များ", + "shipment.popupmenu.mypickup":"ကျွန်ုပ်၏ သယ်ဆောင်ရန် အထုပ်များ", + "shipment.create":"ပို့ဆောင်ခြင်း ပြုလုပ်မည်", + "shipment.update":"ပို့ဆောင်ခြင်းပြုပြင်မည်", + "shipment.info":"ပို့ဆောင်ခြင်း", + "shipment.cancel.confirm":"ပို့ဆောင်ခြင်း ပိတ်သိမ်းမလား?", + "shipment.assign.title":"ပို့ဆောင်ခြင်း တာဝန်ပေးရန်", + "shipment.assign.for.pickup":"သယ်ဆောင်ရန် တာဝန်ပေးမည်", + "shipment.assign.btn":"တာဝန်ပေးမည်", + "shipment.assign.complete.btn":"တာဝန်ပေး ပြီးဆုံးမည်", + "shipment.assign.complete.confirm":"တာဝန်ပေး ပြီးဆုံးမလား?", + "shipment.staff":"ဝန်ထမ်း", + "shipment.pickup.complete.btn":"Complete pickup", + "shipment.pickup.complete.confirm":"Complete pickup?", + "shipment.pack.complete.btn":"Complete pack", + "shipment.pack.complete.confirm":"Complete pack?", + "shipment.pack.menuitem":"Pack shipment", + "shipment.pack.fcs.shipment":"FCS shipment", + "shipment.pack.btn":"Pack", + "shipment.confirm.menuitem":"Confirm shipment", + "shipment.confirm.btn":"Confirm", + "shipment.confirm.complete.btn":"Complete confirm", + "shipment.confirm.complete.confirm":"Complete confirm?", + "shipment.receive.complete.btn":"Complete receive", + "shipment.receive.complete.confirm":"Complete receive?", + "Shipment End ================================================================":"", - "revenue.amounts":"ဝင်ငွေပမာဏများ", - "revenue.date":"ရက်စွဲ", - "revenue.amount":"ပမာဏ", - "revenue.detail":"အသေးစိတ်", - "revenue.detail.title":"{0} ဝင်ငွေပမာဏများ", + "Rate Start ================================================================":"", + "rate":"စျေးနှုန်းများ", + "rate.title":"စျေးနှုန်းများ", + "rate.edit.title":"စျေးနှုန်းများပြုပြင်ရန်", + "rate.cal.title":"စျေးနှုန်းများတွက်ချက်ရန်", + "rate.min_weight":"Min Weight for Free delivery within Yangon", + "rate.delivery_fee":"ပို့ဆောင်ခ", + "rate.total_estimated_amount":"စုစုပေါင်းခန့်မှန်းပမာဏ", + "rate.volumetric_ratio":"Volumetric Ratio", + "rate.custom.form.title":"အကောက်ခွန်", + "rate.cutom.product_type":"ကုန်ပစ္စည်းအမျိုးအစား", + "rate.custom.fee":"အခကြေးငွေ", + "rate.discount.weight":"အလေးချိန်", + "rate.discount.rate":"လျှော့စျေးနှုန်း", + "rate.custom_duty.title":"အကောက်ခွန်များ", + "rate.custom_duty":"အကောက်ခွန်", + "rate.cargo.type":"ကုန်ပစ္စည်းအမျိုးအစား", + "rate.discount_by_weight":"အထူးလျှော့စျေး", + "rate.discount_by_weight.edit.delete.confirm":"လျှော့စျေးနှုန်းကို ဖျက်မလား?", + "rate.custom.edit.delete.confirm":"အကောက်ခွန်ကို ဖျက်မလား?", + "Rate End ================================================================":"", - "spending.amounts":"အသုံးစရိတ် ပမာဏများ", - "spending.detail.title":"{0} အသုံးစရိတ် ပမာဏများ", - - "load": "လုပ်ဆောင်နေပါသည်...", - - "Cancel": "မလုပ်နဲ့", - "Ok": "အိုကေ", - - "singup": "အကောင့်ဒ်အသစ်ပြုလုပ်ခြင်း", - "buyer.reg": "ဝယ်ယူသူမှတ်ပုံတင်ခြင်း", - "po.sub": "ဆီအဝယ် တင်သွင်းခြင်း", - "do.sub": "ဆီအထုတ် တင်သွင်းခြင်း", - "inventory.taking": "စာရင်းယူခြင်း", - "do.approved": "ဆီအထုတ်အတည်ပြုခြင်း", - "po.approved": "ဆီအဝယ်အတည်ပြုခြင်း", - "buyer.approved": "ဝယ်ယူသူအတည်ပြုခြင်း", - "purchase.delivery": "ကုန်ပစ္စည်း​​​​ဝယ်ယူခြင်း", - "do.delivery": "ကုန်ပစ္စည်း​​​​ပို့ခြင်း", - "product.price": "ဆီဈေးနှုန်း", - - - "1.Select 'Signup' button": "၁. 'Signup'ကိုရွေးပါ", - "2.Enter all data info": "၂.အချက်အလက်များကိုထည့်ပါ", - "3.Click 'SIGNUP' button": "၃.'SIGNUP'ခလုတ်ကိုနှိပ်ပါ", - "1.Enter SMS code": "၁.ကုဒ်နံပါတ်ရိုက်ထည့်ပါ", - "2.Click 'Sign In' button": "၁.'ဝင်မည်'ခလုတ်ကိုနှိပ်ပါ", - "Click 'Ok' button": "'အိုကေ'ခလုတ်ကိုနှိပ်ပါ", - "2.Click 'Ok' button": "၂.'အိုကေ'ခလုတ်ကိုနှိပ်ပါ", - "1.Select 'Login' button": "၁.'ဝင်မည်'ခလုတ်ကိုရွေးပါ", - "2.Enter Phone Number and Password": "၂.ဖုန်းနံပါတ်နှင့်လျှို့ဝှက်နံပါတ်ကိုရိုက်ထည့်ပါ", - "3.Click 'LOGIN' button": "၃.'ဝင်မည်' ခလုတ်ကိုနှိပ်ပါ", - "1.Enter all data info": "၁.အချက်အလက်များကိုထည့်ပါ", - "2.Click Sent button": "၂.Sentခလုတ်ကိုနှိပ်ပါ", - "1.Click Sent button": "၁.Sentခလုတ်ကိုနှိပ်ပါ", - "1.Click 'POs'": "၁. 'ဆီအဝယ်များ'ကိုနှိပ်ပါ", - "1.Enter Volume and select Product": "၁.ပမာဏ နှင့် ကုန်ပစ္စည်းကိုရွေးပါ", - "2.Click 'Save' button": "၂. 'သိမ်းဆည်းမည်'ခလုတ်ကိုနှိပ်ပါ", - "Finished DO Submission": "ဆီအထုတ်တင်ပြချက်ပြီးဆုံးသည်", - "Click Storages": "သိုလှောင်ကန်များကို ရွေးပါ", - "1.Enter storage name": "၁.သိုလှောင်ကန်အမည်ကိုရွေးပါ", - "Click Inventory Takings": "စာရင်းယူခြင်းခလုတ်ကိုနှိပ်ပါ", - "1.Select storage name , product and enter quantity": "၁.သိုလှောင်ကန်အမည်, ကုန်ပစ္စည်းနှင့် ပမာဏကိုထည့်ပါ", - "Finished Inventory Taking": "စာရင်းယူခြင်းပြီးဆုံးသည်", - "Select you want to approve PO": "အတည်ပြုမည့်ဆီအဝယ်ကိုရွေးပါ", - "Click Approve PO": "1.Approve POကိုနှိပ်ပါ", - "Finished PO Approved": " ဆီအဝယ်အတည်ပြုခြင်းပြီးဆုံးသည်", - "Select you want to approve DO": "အတည်ပြုမည့်ဆီအထုတ်ကိုရွေးပါ", - "Select storage name": "၁. သိုလှောင်ကန်အမည်ကိုရွေးပါ", - "2.Click Approve DO": "၂.Approve DO ကိုနှိပ်ပါ", - "Finished DO Approved": "ဆီအထုတ် အတည်ပြုခြင်းပြီးဆုံးသည်", - "Select New Buyer Registration": "၁.New Buyer Registrationကိုရွေးပါ", - "Click 'Approve'": "၁.'Approve'ကိုနှိပ်ပါ", - "Click 'Products'": "'ဆီဈေးနှုန်း'ကိုနှိပ်ပါ", - "Click pencil button": "ခဲတံခလုတ်ကိုနှိပ်ပါ", - "1.Enter product info": "၁.ကုန်ပစ္စည်း အချက်အလက်များကိုထည့်ပါ", - "Select DO, want to delivery": "ပို့မည့်ဆီအထုတ်ကိုရွေးပါ", - "Click 'Initiate Delivery' button": "'Initiate Delivery' ခလုတ်ကိုနှိပ်ပါ", - "Click 'Start Delivery'": "'Start Delivery'ကိုနှိပ်ပါ", - "1.Click '+' button": "၁.'+'ခလုတ်ကိုနှိပ်ပါ", - "Click 'PDs'": "'ဆီအဝင်များ'ကိုနှိပ်ပါ" , - "Click 'Sent' button": "Sentခလုတ်ကိုနှိပ်ပါ", - - "1":"၁", - "2":"၂", - "3":"၃", - - "signup.slide.initial":"၁. မြှားခလုတ်ကိုနှိပ်ပါ", - "signup.slide.s1": "၁. 'အသစ်ပြုလုပ်ရန်'ကိုရွေးပါ\n၂. အချက်အလက်များကိုထည့်ပါ\n၃. 'အသစ်ပြုလုပ်မည်'ခလုတ်ကိုနှိပ်ပါ", - "signup.slide.s2" : "၁. ကုဒ်နံပါတ်ရိုက်ထည့်ပါ\n၂. 'ဝင်မည်'ခလုတ်ကိုနှိပ်ပါ", - "signup.slide.s3": "၁.'သဘောတူပါသည်'ခလုတ်ကိုနှိပ်ပါ", - "signup.slide.s4": "၁. 'အိုကေ'ခလုတ်ကိုနှိပ်ပါ", - "signup.slide.s5": "အကောင့်ဒ်အသစ်ပြုလုပ်ခြင်းပြီးဆုံးသည်", - - "login.slide.s1":"၁. 'အကောင့်ဒ်၀င်ရန်'ခလုတ်ကိုရွေးပါ\n၂. ဖုန်းနံပါတ်နှင့်စကားဝှက်ကိုရိုက်ထည့်ပါ\n၃. 'ဝင်မည်' ခလုတ်ကိုနှိပ်ပါ", - - "buyerreg.slide.s1":"၁. 'ကိုယ်ရေးအချက်အလက်'ခလုတ်ကိုနှိပ်ပါ", - "buyerreg.slide.s2":"၁. အချက်အလက်များကိုထည့်ပါ\n၂. Sentခလုတ်ကိုနှိပ်ပါ", - "buyerreg.slide.s4":"ဝယ်သူမှတ်ပုံတင်ခြင်းပြီးဆုံးသည်", - - "posub.slide.s1": "၁. 'ဆီအဝယ်များ'ကိုနှိပ်ပါ", - "posub.slide.s2": "၁. '+'ခလုတ်ကိုနှိပ်ပါ", - "posub.slide.s3":"၁. '+'ခလုတ်ကိုနှိပ်ပါ\n၂. Sentခလုတ်ကိုနှိပ်ပါ", - "posub.slide.s4":"၁. ပမာဏ နှင့် ကုန်ပစ္စည်းကိုရွေးပါ\n၂. 'သိမ်းဆည်းမည်'ခလုတ်ကိုနှိပ်ပါ", - "posub.slide.s6": "ဆီအဝယ်တင်ပြချက်ပြီးဆုံးသည်", - - "dosub.slide.s1": "၁.'More' ခလုတ်ကိုနှိပ်ပါ", - "dosub.slide.s2": "၁.'Create DO'ကိုနှိပ်ပါ'", - "dosub.slide.s4" : "၁. အချက်အလက်များကိုထည့်ပါ\n၂.Sentခလုတ်ကိုနှိပ်ပါ", - "dosub.slide.s6": "ဆီအထုတ်တင်ပြချက်ပြီးဆုံးသည်", - - "storage.slide.s1": "Click Storages", - "storage.slide.s3" : "၁. သိုလှောင်ကန်အမည်ကိုရွေးပါ\n၂. 'သိမ်းဆည်းမည်'ခလုတ်ကိုနှိပ်ပါ", - - "inventory.taking.s1": "Click Inventory Takings", - "inventory.taking.s4":"၁.သိုလှောင်ကန်အမည်, ကုန်ပစ္စည်းနှင့် ပမာဏကိုထည့်ပါ\n၂. 'သိမ်းဆည်းမည်'ခလုတ်ကိုနှိပ်ပါ", - "inventory.taking.s5": "1.Click Sent button", - "inventory.taking.s7": "Finished Inventory Taking", - - "poapproved.slide.s1": "Select you want to approve PO", - "poapproved.slide.s3": "1.Click Approve PO", - "poapproved.slide.s5": "Finished PO Approved", - - "doapproved.slide.s1": "Select you want to approve DO", - "doapproved.slide.s3": "1.Select storage name", - "doapproved.slide.s6": "Finished DO Approved", - "doapproved.slide.s5": "၁.'More' ခလုတ်ကိုနှိပ်ပါ\n၂.Approve DO ကိုနှိပ်ပါ", - - "buyerapproved.slide.s1": "1.Select New Buyer Registration", - "buyerapproved.slide.s3": "1.Click 'Approve'", - - "product.slide.s1": "1.Click 'Products'", - "product.slide.s2": "1.Click pencil button", - "product.slide.s3": "1.Enter product info\n2.Click 'Save' button", - - - "pd.slide.s1": "1.Click 'PDs'", - "pd.slide.s5": "1.Click Sent button\n2.Click 'Ok' button", - - "dodelivery.slide.s1": "Select DO, want to delivery", - - "Signup": "အသစ်ပြုလုပ်ရန်", - "Login": "အကောင့်ဒ်၀င်ရန်", - "forget.pass" : "စကားဝှက်မေ့နေပါသလား?", - "manual.confirm": "Are you sure want to delete?", - - "offline.status":"အင်တာနက် ပိတ်ထားသည်, ဆာဗာကို ဆက်သွယ်၍ မရပါ!", - - "report.title":"Reports", - "report.user_delete_confirm":"ဤအစီရင်ခံစာအသုံးပြုသူအားဖျက်မည်လား?", - "report.user.search":"Search", - "report.users.title":"{0} အသုံးပြုသူများ", - - "announcement.title":"ကြေငြာချက်များ", - "announcement.form.title":"ကြေငြာချက်", - "announcement.name":"အကြောင်းအရာ", - "announcement.name_empty":"ကျေးဇူးပြု၍ အကြောင်းအရာ အမည်ပေးပါ", - "announcement.delete_confirm":"ကြေငြာချက်ကိုဖျက်မည်လား?", - "announcement.desc":"ဖော်ပြချက်", - - "login": "SignIn", - "login.title":"FCS သို့အကောင့်ဒ်၀င်ပါ", - "login.phone":"ဖုန်းနံပါတ်ထည့်ပါ", - - "user_edit.welcome":"FCS မှကြိုဆိုပါသည်", - "user_edit.name":"ကျေးဇူးပြု၍ နာမည်ထည့်ပေးပါ", - "user.phone":"My phone number", - "user.fcs_id":"My FCS_ID", - "user.shipping_address":"My USA shipping address", - "user.deliveryAddress":"My delivery address", - "user.form.shipping_address":"ကုန်ပစ္စည်းပို့ဆောင်ရမည့်လိပ်စာ", - - "notifications.title":"Notifications", - - "shipment.title":"FCS တင်ပို့ခြင်းများ", - "shipment.list.title":"FCS တင်ပို့ခြင်းများ", - "shipment.add":"New FCS shipment", - "shipment.form.title":"FCS SHIPMENT", - "shipment.number":"FCS Shipment Number", - - "pickup": "Shipments", - "pickup.title": "SHIPMENTS", - "pickup.new": "New Shipment", - "pickup.edit.title": "PICKUP", - "pickup.date": "Pickup Date", - "pickup.location_time": "Pickup Location / Time", - "pickup.information": "Pickup Informations", - "pickup.recipient_information": "Recipient Informations", - - "rate":"အဆင့်သတ်မှတ်ချက်များ", - "rate.title":"အဆင့်သတ်မှတ်ချက်များ", - "rate.edit.title":"အဆင့်သတ်မှတ်ချက်များပြုပြင်ရန်", - - "rate.cal.title":"အဆင့်သတ်မှတ်ချက်များတွက်ချက်ရန်", - - "cargo.form.title":"ကုန်ပစ္စည်းအမျိုးအစား", + "Cargo Start ================================================================":"", + "cargo.form.title":"ကုန်ပစ္စည်း", "cargo.type":"ကုန်ပစ္စည်းအမျိုးအစား", "cargo.weight":"အလေးချိန်", - "cargo.rate":"အဆင့်", + "cargo.rate":"စျေးနှုန်း", "cargo.amount":"ပမာဏ", + "cargo.edit.delete.confirm":"ကုန်ပစ္စည်းကို ဖျက်မလား?", + "Cargo End ================================================================":"", - "message.btn":"အသိပေးချက်များ", - "message.title":"အသိပေးချက်များ", - - "customers.btn": "ဝယ်ယူသူများ", - "customers.title": "ဝယ်ယူသူများ", - + "Invoices Start ================================================================":"", "invoices.btn": "ငွေတောင်းခံလွှာများ", "invoices.title": "ငွေတောင်းခံလွှာများ", "invoices.add":"ငွေတောင်းခံလွှာအသစ်", "invoice.form.title":"ငွေတောင်းခံလွှာ", "invoice.payment":"လက်ခံဖြတ်ပိုင်း", "invoice.add_package":"Add Package", - "invoice.add_box":"Add Box", + "invoice.add_box":"Box အသစ်", + "invoice.date":"ငွေတောင်းခံလွှာ ရက်စွဲ", + "invoice.number":"ငွေတောင်းခံလွှာ နံပါတ်", + "invoice.customer_name":"ဝယ်ယူသူနာမည်", + "invoice.status":"အခြေအနေ", + "invoice.amount":"ပမာဏ", + "invoice.weight":"Weight(lb)", + "invoice.rate":"Rate(USD)", + "invoice.total":"စုစုပေါင်းပမာဏ", + "invoice.balance":"ပေးချေရန်ကျန်ရှိငွေ", + "invoice.handling_fee":"ထိန်းသိမ်းခ", + "invoice.custom_fee":"ကုန်သွယ်ခွန်", + "invoice.custom_fee_desc":"ကုန်သွယ်ခွန်အကြောင်းအရာ", + "invoice.discount":"လျှော့စျေးကုဒ်", + "invoice.payment_method":"ငွေပေးချေစနစ်", + "invoice.delivery_fee":"ပို့ဆောင်ခ", + "invoice.payment_attachment":"ပေးချေပြီးဖိုင်များ", + "invoice.box_info":"Cartons", + "invoice.cargo_table":"ကုန်ပစ္စည်းဇယား", + "invoice.issue.btn":"ငွေတောင်းခံလွှာ ထုတ်မည်", + "invoice.btn_save":"ငွေတောင်းခံလွှာ သိမ်းရန်", + "invoice.btn_payment_receipt":"ငွေလက်ခံဖြတ်ပိုင်း ထည့်ရန်", + "invoice.box.cargo_type": "ကုန်ပစ္စည်းအမျိုးအစားများ", + "invoice.description": "ငွေတောင်းခံလွှာအကြောင်းအရာ", + "invoice.cargo_type":"Cargo Types", + "invoice.box.desc": "Description", + "invoice.box.number":"Box နံပါတ်", + "invoice.box.length":"L", + "invoice.box.width":"W", + "invoice.box.height":"H", + "invoice.discount_value": "လျှော့စျေး", + "invoice.net_amount":"Net Amount", + "invoice.customer_info":"Customer information", + "invoice.pdf": "Invoice PDF", + "invoice.total_custom_fee":"အခွန်စုစုပေါင်း", + "invoice.shipment_weight":"Shipment weight", + "invoice.popupmenu.issused":"Issused", + "invoice.popupmenu.paid":"Paid", + "invoice.popupmenu.cancel":"Canceled", + "invoice.shipment.title":"Select FCS shipment", + "invoice.customer.title":"Select Customer", + "invoice.add.custom.fee.menu":"Custom fee", + "invoice.add.handling.fee.menu":"Handling fee", + "invoice.add.discount.menu":"Discount", + "invoice.shipment.number":"Shipment number", + "invoice.shipment.handling.fee.title":"Select shipment", + "invoice.shipment.discount.title":"Select discount", + "invoice.cancel.btn":"Cancel", + "invoice.cancel.confirm":"Cancel invoice?", + "Invoices End ================================================================":"", - - "fcs.profile": "ပရိုဖိုင်", - - - "payment.title": "ငွေပေးချေခြင်း", - "payment.date": "ရက်စွဲ", - "payment.amount": "ပမာဏ", - "payment.receipt":"ပေးချေပြီးပမာဏများ", - "payment.attachment":"ပေးချေပြီးဖိုင်များ", - "pdf_view.title":"ပေးဆောင်ခြင်းဖိုင်", - "remaining_balance":"ပေးချေရန်ကျန်ရှိငွေ : ", - "total.amount": "ပမာဏ :", - + "Discount Start ================================================================":"", "discount.btn":"လျှော့စျေးများ", "discount.title":"လျှော့စျေးများ", "discount.new":"လျှော့စျေး", "discount.form":"လျှော့စျေး", + "discount.code":"ကုဒ်", + "discount.name":"ဝယ်ယူသူအမည်", + "discount.amount":"ပမာဏ", + "discount.status":"အခြေအနေ", + "discount.edit.delete.confirm":"လျှော့စျေးကို ဖျက်မလား?", + "discount.popupmenu.available":"Available discounts", + "discount.popupmenu.used":"Used discounts", + "Discount End ================================================================":"", - "custom.form.title":"အကောက်ခွန်", - "shipping_addresses": "လိပ်စာများ" + "delivery_addresses Start ================================================================":"", + "delivery_addresses": "ပို့ဆောင်ရမည့်လိပ်စာများ", + "delivery_address": "အမြဲတမ်း ပို့ဆောင်ရမည့် လိပ်စာ", + "delivery_address.full_name": "နာမည် အပြည့်အစုံ", + "delivery_address.address_line1": "လိပ်စာ ၁", + "delivery_address.address_line2": "လိပ်စာ ၂", + "delivery_address.state_region": "ပြည်နယ်/တိုင်း", + "delivery_address.city": "မြို့", + "delivery_address.country": "နိုင်ငံ", + "delivery_address.phonenumber": "ဖုန်းနံပါတ်", + "delivery_address.create": "ပြုလုပ်ရန်", + "delivery_address.update": "ပြုပြင်ရန်", + "delivery_address.new_address":"လိပ်စာ အသစ်", + "delivery_address.change_address": "လိပ်စာပြောင်းမည်", + "delivery_address.delete.confirm":"ပို့ဆောင်ရမည့်လိပ်စာကို ဖျက်မလား?", + "delivery_addresses End ================================================================":"", + + "Receiving Start ================================================================":"", + "receiving.title":"လက်ခံခြင်းများ", + "receiving.info":"လက်ခံခြင်း", + "receiving.new":"လက်ခံခြင်း အသစ်", + "receiving.create":"လက်ခံခြင်း အသစ်", + "receiving.update":"လက်ခံခြင်း ပြင်ဆင်ခြင်း", + "receiving.tracking.id":"Tracking ID", + "receiving.remark":"မှတ်ချက်", + "receiving.fcs.id":"FCS ID", + "receiving.name":"နာမည်", + "receiving.phone":"ဖုန်းနံပါတ်", + "receiving.create_btn":"လက်ခံမည်", + "receiving.update_btn":"ပြင်ဆင်မည်", + "receiving.delete.confirm":"လက်ခံခြင်းကို ဖျက်မလား?", + "receiving.return.btn":"ပစ္စည်း ပြန်ပို့မည်", + "receiving.return.confirm":"ပစ္စည်းကို ပြန်ပို့မလား?", + "Receiving End ================================================================":"", + + "Processing Start ================================================================":"", + "processing.title":"လုပ်ဆောင်ခြင်းများ", + "processing.info.title":"လုပ်ဆောင်ခြင်း", + "processing.tracking.id":"Tracking ID", + "processing.name":"နာမည်", + "processing.phone":"ဖုန်းနံပါတ်", + "processing.fcs.id":"FCS ID", + "processing.market":"အွန်လိုင်စျေးဆိုင်", + "processing.status":"အခြေအနေ", + "processing.desc":"ဖော်ပြချက်", + "processing.remark":"မှတ်ချက်", + "processing.edit.title":"လုပ်ဆောင်ခြင်း", + "processing.delete.confirm":"အထုပ်ကို ဖျက်မလား?", + "processing.edit.sub_title":"မွမ်းမံခြင်း", + "processing.edit.complete.btn":"မွမ်းမံခြင်း ပြီးဆုံးသည်", + "Processing End ================================================================":"" + + } \ No newline at end of file diff --git a/assets/logo.png b/assets/logo.png deleted file mode 100644 index 96a4619..0000000 Binary files a/assets/logo.png and /dev/null differ diff --git a/assets/logo1 (copy).png b/assets/logo1 (copy).png deleted file mode 100644 index 6254dd0..0000000 Binary files a/assets/logo1 (copy).png and /dev/null differ diff --git a/assets/logo_btn.jpg b/assets/logo_btn.jpg deleted file mode 100644 index 7368d49..0000000 Binary files a/assets/logo_btn.jpg and /dev/null differ diff --git a/assets/logo_btn.png b/assets/logo_btn.png deleted file mode 100644 index c3e37af..0000000 Binary files a/assets/logo_btn.png and /dev/null differ diff --git a/assets/logo_title.png b/assets/logo_title.png deleted file mode 100644 index 3ad5663..0000000 Binary files a/assets/logo_title.png and /dev/null differ diff --git a/assets/manual.png b/assets/manual.png deleted file mode 100644 index 6b9b54d..0000000 Binary files a/assets/manual.png and /dev/null differ diff --git a/assets/message.png b/assets/message.png deleted file mode 100644 index e8c3a17..0000000 Binary files a/assets/message.png and /dev/null differ diff --git a/assets/my_file.json b/assets/my_file.json deleted file mode 100644 index e69de29..0000000 diff --git a/assets/myan_flag.png b/assets/myan_flag.png deleted file mode 100755 index a3ea115..0000000 Binary files a/assets/myan_flag.png and /dev/null differ diff --git a/assets/page.png b/assets/page.png deleted file mode 100755 index e608240..0000000 Binary files a/assets/page.png and /dev/null differ diff --git a/assets/password.png b/assets/password.png deleted file mode 100644 index d0a7e97..0000000 Binary files a/assets/password.png and /dev/null differ diff --git a/assets/pay.png b/assets/pay.png deleted file mode 100644 index 384d33c..0000000 Binary files a/assets/pay.png and /dev/null differ diff --git a/assets/pdo.png b/assets/pdo.png deleted file mode 100644 index 9203800..0000000 Binary files a/assets/pdo.png and /dev/null differ diff --git a/assets/phone.png b/assets/phone.png deleted file mode 100644 index 5e8b0f5..0000000 Binary files a/assets/phone.png and /dev/null differ diff --git a/assets/photos/1.jpg b/assets/photos/1.jpg deleted file mode 100644 index 3186d79..0000000 Binary files a/assets/photos/1.jpg and /dev/null differ diff --git a/assets/photos/2.jpg b/assets/photos/2.jpg deleted file mode 100644 index 9f0d8de..0000000 Binary files a/assets/photos/2.jpg and /dev/null differ diff --git a/assets/photos/3.jpg b/assets/photos/3.jpg deleted file mode 100644 index 504b6f3..0000000 Binary files a/assets/photos/3.jpg and /dev/null differ diff --git a/assets/pin.png b/assets/pin.png deleted file mode 100644 index 33de204..0000000 Binary files a/assets/pin.png and /dev/null differ diff --git a/assets/product.png b/assets/product.png deleted file mode 100644 index 45e3497..0000000 Binary files a/assets/product.png and /dev/null differ diff --git a/assets/product_icon.png b/assets/product_icon.png deleted file mode 100644 index 356510c..0000000 Binary files a/assets/product_icon.png and /dev/null differ diff --git a/assets/quota.png b/assets/quota.png deleted file mode 100644 index b5d057d..0000000 Binary files a/assets/quota.png and /dev/null differ diff --git a/assets/r.jpg b/assets/r.jpg deleted file mode 100644 index 1ca666a..0000000 Binary files a/assets/r.jpg and /dev/null differ diff --git a/assets/reg.png b/assets/reg.png deleted file mode 100644 index 01a2763..0000000 Binary files a/assets/reg.png and /dev/null differ diff --git a/assets/report.png b/assets/report.png deleted file mode 100644 index f5ea278..0000000 Binary files a/assets/report.png and /dev/null differ diff --git a/assets/sales.png b/assets/sales.png deleted file mode 100644 index e4ab266..0000000 Binary files a/assets/sales.png and /dev/null differ diff --git a/assets/status.png b/assets/status.png deleted file mode 100644 index d038e3f..0000000 Binary files a/assets/status.png and /dev/null differ diff --git a/assets/storage.png b/assets/storage.png deleted file mode 100644 index 686572c..0000000 Binary files a/assets/storage.png and /dev/null differ diff --git a/assets/storage12.png b/assets/storage12.png deleted file mode 100644 index 167f698..0000000 Binary files a/assets/storage12.png and /dev/null differ diff --git a/assets/submission.png b/assets/submission.png deleted file mode 100644 index 8c3a7ea..0000000 Binary files a/assets/submission.png and /dev/null differ diff --git a/assets/term.png b/assets/term.png deleted file mode 100644 index f460533..0000000 Binary files a/assets/term.png and /dev/null differ diff --git a/assets/truck.png b/assets/truck.png deleted file mode 100644 index e750a8e..0000000 Binary files a/assets/truck.png and /dev/null differ diff --git a/assets/volume.png b/assets/volume.png deleted file mode 100644 index 8549179..0000000 Binary files a/assets/volume.png and /dev/null differ diff --git a/assets/whole.png b/assets/whole.png deleted file mode 100644 index 6254dd0..0000000 Binary files a/assets/whole.png and /dev/null differ diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index 41252c0..ac80bbd 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -37,6 +37,8 @@ NSCameraUsageDescription Camera permission is required for barcode scanning. + NSPhotoLibraryUsageDescription + Photo library usage is required for FCS team to upload package photos UIBackgroundModes fetch diff --git a/lib/app.dart b/lib/app.dart index a22e425..ff298d5 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -1,54 +1,33 @@ -import 'package:fcs/fcs/common/localization/app_translations_delegate.dart'; -import 'package:fcs/fcs/common/localization/transalation.dart'; -import 'package:fcs/fcs/common/pages/contact/model/contact_model.dart'; -import 'package:fcs/fcs/common/pages/customer/model/customer_model.dart'; -import 'package:fcs/fcs/common/pages/faq/model/faq_model.dart'; -import 'package:fcs/fcs/common/pages/initial_language_selection.dart'; -import 'package:fcs/fcs/common/pages/market/model/market_model.dart'; -import 'package:fcs/fcs/common/pages/model/language_model.dart'; -import 'package:fcs/fcs/common/pages/model/main_model.dart' as fcs; -import 'package:fcs/fcs/common/pages/package/model/package_model.dart'; -import 'package:fcs/fcs/common/pages/package/model/shipment_model.dart'; -import 'package:fcs/fcs/common/pages/payment_methods/model/payment_method_model.dart'; -import 'package:fcs/fcs/common/pages/staff/model/staff_model.dart'; -import 'package:fcs/fcs/common/pages/term/model/term_model.dart'; -import 'package:fcs/model/buyer_model.dart'; -import 'package:fcs/model/delivery_model.dart'; -import 'package:fcs/model/discount_model.dart'; -import 'package:fcs/model/manual_model.dart'; -import 'package:fcs/model/notification_model.dart'; -import 'package:fcs/model/pd_model.dart'; -import 'package:fcs/model/reg_model.dart'; -import 'package:fcs/model/report_model.dart'; -import 'package:fcs/model/storage_model.dart'; -import 'package:fcs/model/test_model.dart'; -import 'package:fcs/pages/email_page.dart'; -import 'package:fcs/pages/login_page.dart'; +import 'package:fcs/localization/app_translations_delegate.dart'; +import 'package:fcs/localization/transalation.dart'; +import 'package:fcs/pages/carton/model/carton_model.dart'; +import 'package:fcs/pages/chat/model/message_model.dart'; +import 'package:fcs/pages/contact/model/contact_model.dart'; +import 'package:fcs/pages/customer/model/customer_model.dart'; +import 'package:fcs/pages/delivery_address/model/delivery_address_model.dart'; +import 'package:fcs/pages/discount/model/discount_model.dart'; +import 'package:fcs/pages/faq/model/faq_model.dart'; +import 'package:fcs/pages/fcs_shipment/model/fcs_shipment_model.dart'; +import 'package:fcs/pages/main/home_page.dart'; +import 'package:fcs/pages/main/initial_language_selection.dart'; +import 'package:fcs/pages/invoice/model/invoice_model.dart'; +import 'package:fcs/pages/market/model/market_model.dart'; +import 'package:fcs/pages/main/model/language_model.dart'; +import 'package:fcs/pages/main/model/main_model.dart'; +import 'package:fcs/pages/package/model/package_model.dart'; +import 'package:fcs/pages/payment_methods/model/payment_method_model.dart'; +import 'package:fcs/pages/rates/model/shipment_rate_model.dart'; +import 'package:fcs/pages/shipment/model/shipment_model.dart'; +import 'package:fcs/pages/main/splash_page.dart'; +import 'package:fcs/pages/staff/model/staff_model.dart'; +import 'package:fcs/pages/term/model/term_model.dart'; +import 'package:fcs/pages/main/welcome_page.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:provider/provider.dart'; -import 'fcs/common/pages/chat/model/message_model.dart'; -import 'fcs/common/pages/home_page.dart'; -import 'fcs/common/pages/splash_page.dart'; -import 'fcs/common/pages/welcome_page.dart'; -import 'model/announcement_model.dart'; -import 'model/chart_model.dart'; -import 'model/device_model.dart'; -import 'model/do_model.dart'; -import 'model/invoice_model.dart'; -import 'model/log_model.dart'; -import 'model/main_model.dart'; -import 'model/pickup_model.dart'; -import 'model/po_model.dart'; -import 'model/product_model.dart'; -import 'model/report_user_model.dart'; -import 'model/shipment_rate_model.dart'; -import 'model/user_model.dart'; -import 'model_fcs/box_model.dart'; -import 'pages/term.dart'; +import 'pages/delivery/model/delivery_model.dart'; class App extends StatefulWidget { @override @@ -56,89 +35,48 @@ class App extends StatefulWidget { } class _AppState extends State { - final fcs.MainModel mainModel2 = new fcs.MainModel(); + final MainModel mainModel = new MainModel(); final ContactModel contactModel = new ContactModel(); final TermModel termModel = new TermModel(); - final MainModel mainModel = new MainModel(); final FAQModel faqModel = new FAQModel(); final PaymentMethodModel paymentMethodModel = new PaymentMethodModel(); - - final UserModel userModel = new UserModel(); - final ProductModel productModel = new ProductModel(); - final POSubmissionModel poSubmissionModel = new POSubmissionModel(); - final DOModel doModel = new DOModel(); + final FcsShipmentModel fcsShipmentModel = new FcsShipmentModel(); final LanguageModel lanuguageModel = new LanguageModel(); - final StorageModel storageModel = new StorageModel(); - final PDModel pdModel = new PDModel(); - final RegModel regModel = new RegModel(); - final BuyerModel buyerModel = new BuyerModel(); - final NotificationModel notificationModel = new NotificationModel(); - final ChartModel chartModel = new ChartModel(); - final DeliveryModel deliveryModel = new DeliveryModel(); - final ManualModel manualModel = new ManualModel(); - final TestModel testModel = new TestModel(); - final LogModel logModel = new LogModel(); - final PhoneDeviceModel phoneDeviceModel = new PhoneDeviceModel(); - final ReportModel reportModel = new ReportModel(); - final AnnouncementModel announcementModel = new AnnouncementModel(); - final ReportUserModel reportUserModel = new ReportUserModel(); - final PickUpModel pickUpModel = new PickUpModel(); + final ShipmentModel shipmentModel = new ShipmentModel(); final ShipmentRateModel shipmentRateModel = new ShipmentRateModel(); - final BoxModel boxModel = new BoxModel(); + final CartonModel boxModel = new CartonModel(); final MessageModel messageModel = new MessageModel(); final InvoiceModel invoiceModel = new InvoiceModel(); final CustomerModel customerModel = new CustomerModel(); final DiscountModel discountModel = new DiscountModel(); final StaffModel staffModel = new StaffModel(); - final ShipmentModel shipmentModel = new ShipmentModel(); + final DeliveryAddressModel deliveryAddressModel = new DeliveryAddressModel(); final PackageModel packageModel = new PackageModel(); final MarketModel marketModel = new MarketModel(); + final DeliveryModel deliveryModel = new DeliveryModel(); AppTranslationsDelegate _newLocaleDelegate; - static FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin = - FlutterLocalNotificationsPlugin(); @override void initState() { super.initState(); - mainModel2 + mainModel ..addModel(customerModel) ..addModel(staffModel) - ..addModel(shipmentModel) + ..addModel(deliveryAddressModel) ..addModel(packageModel) ..addModel(messageModel) - ..addModel(marketModel); - mainModel2.init(); + ..addModel(fcsShipmentModel) + ..addModel(discountModel) + ..addModel(shipmentRateModel) + ..addModel(boxModel) + ..addModel(shipmentModel) + ..addModel(invoiceModel) + ..addModel(marketModel) + ..addModel(deliveryModel); _newLocaleDelegate = AppTranslationsDelegate(newLocale: null); Translation().onLocaleChanged = onLocaleChange; - mainModel - ..addModel(userModel) - ..addModel(storageModel) - ..addModel(regModel) - ..addModel(poSubmissionModel) - ..addModel(doModel) - ..addModel(productModel) - ..addModel(pdModel) - ..addModel(buyerModel) - ..addModel(notificationModel) - ..addModel(chartModel) - ..addModel(deliveryModel) - ..addModel(logModel) - ..addModel(manualModel) - ..addModel(phoneDeviceModel) - ..addModel(regModel) - ..addModel(announcementModel) - ..addModel(reportModel) - ..addModel(testModel) - ..addModel(reportUserModel) - ..addModel(pickUpModel) - ..addModel(shipmentRateModel) - ..addModel(boxModel) - ..addModel(shipmentRateModel) - ..addModel(invoiceModel) - ..addModel(discountModel); - this.mainModel.init(); } void onLocaleChange(Locale locale) { @@ -152,11 +90,6 @@ class _AppState extends State { '/': (_) => SplashScreen(), '/welcome': (_) => WelcomePage(), '/home': (_) => HomePage(), - '/term': (context) => Term( - agreePage: true, - ), - '/login': (context) => LoginPage(), - '/email': (context) => EmailPage(), '/language_selection': (context) => InitialLanguageSelectionPage(), }; return routes; @@ -167,40 +100,24 @@ class _AppState extends State { return MultiProvider( providers: [ ChangeNotifierProvider.value(value: mainModel), - ChangeNotifierProvider.value(value: userModel), - ChangeNotifierProvider.value(value: productModel), ChangeNotifierProvider.value(value: staffModel), - ChangeNotifierProvider.value(value: poSubmissionModel), - ChangeNotifierProvider.value(value: doModel), - ChangeNotifierProvider.value(value: storageModel), - ChangeNotifierProvider.value(value: pdModel), ChangeNotifierProvider.value(value: lanuguageModel), - ChangeNotifierProvider.value(value: regModel), - ChangeNotifierProvider.value(value: buyerModel), - ChangeNotifierProvider.value(value: notificationModel), - ChangeNotifierProvider.value(value: chartModel), - ChangeNotifierProvider.value(value: deliveryModel), - ChangeNotifierProvider.value(value: logModel), - ChangeNotifierProvider.value(value: phoneDeviceModel), - ChangeNotifierProvider.value(value: reportModel), - ChangeNotifierProvider.value(value: announcementModel), - ChangeNotifierProvider.value(value: reportUserModel), - ChangeNotifierProvider.value(value: pickUpModel), - ChangeNotifierProvider.value(value: shipmentRateModel), ChangeNotifierProvider.value(value: shipmentModel), + ChangeNotifierProvider.value(value: shipmentRateModel), + ChangeNotifierProvider.value(value: deliveryAddressModel), ChangeNotifierProvider.value(value: packageModel), ChangeNotifierProvider.value(value: boxModel), ChangeNotifierProvider.value(value: messageModel), ChangeNotifierProvider.value(value: invoiceModel), ChangeNotifierProvider.value(value: customerModel), ChangeNotifierProvider.value(value: discountModel), - ChangeNotifierProvider.value(value: testModel), - ChangeNotifierProvider.value(value: mainModel2), ChangeNotifierProvider.value(value: contactModel), ChangeNotifierProvider.value(value: termModel), ChangeNotifierProvider.value(value: faqModel), ChangeNotifierProvider.value(value: paymentMethodModel), ChangeNotifierProvider.value(value: marketModel), + ChangeNotifierProvider.value(value: fcsShipmentModel), + ChangeNotifierProvider.value(value: deliveryModel), ], child: Consumer( builder: (context, value, child) { @@ -225,9 +142,7 @@ class _AppState extends State { routes: route(context), localizationsDelegates: [ _newLocaleDelegate, - //provides localised strings GlobalMaterialLocalizations.delegate, - //provides RTL support GlobalWidgetsLocalizations.delegate, ], supportedLocales: Translation().supportedLocales()); diff --git a/lib/charts/bar_chart.dart b/lib/charts/bar_chart.dart deleted file mode 100644 index 19de245..0000000 --- a/lib/charts/bar_chart.dart +++ /dev/null @@ -1,120 +0,0 @@ -import 'package:charts_flutter/flutter.dart' as charts; -import 'package:charts_flutter/flutter.dart'; -import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/charts/qtyby_customer_table.dart'; -import 'package:fcs/model/chart_model.dart'; -import 'package:fcs/model/product_model.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/po.dart'; -import 'package:fcs/widget/local_text.dart'; - -class BarChart extends StatefulWidget { - @override - _BarChartState createState() => _BarChartState(); -} - -class _BarChartState extends State { - static final numberFormatter = new NumberFormat("#,###"); - List chartSummary = new List(); - List> series; - - @override - void initState() { - super.initState(); - var chartModel = Provider.of(context, listen: false); - this.chartSummary = chartModel.chartSummary; - } - - @override - Widget build(BuildContext context) { - var productModel = Provider.of(context); - if (this.chartSummary.isNotEmpty) { - this.chartSummary.forEach((s) { - productModel.products.forEach((p) { - if (p.id == s.productID) { - s.displayOrder = p.displayOrder; - } else { - return; - } - }); - }); - - this - .chartSummary - .sort((s1, s2) => s1.displayOrder.compareTo(s2.displayOrder)); - } - List> series = [ - charts.Series( - id: "Subscribers", - data: this.chartSummary, - domainFn: (POChartData series, _) => series.productName, - measureFn: (POChartData series, _) => series.balanceQty, - colorFn: (POChartData series, _) => - charts.ColorUtil.fromDartColor(series.getColor), - labelAccessorFn: (POChartData series, _) => - '${numberFormatter.format(series.balanceQty)}'), - ]; - - return Container( - height: 200, - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - LocalText(context, 'product.balance_qty', - color: primaryColor, fontSize: 16), - IconButton( - icon: Icon( - Icons.refresh, - color: primaryColor, - ), - onPressed: () { - _load(); - }, - ) - ], - ), - Expanded( - child: charts.BarChart( - series, - animate: true, - vertical: false, - defaultRenderer: new charts.BarRendererConfig( - barRendererDecorator: new charts.BarLabelDecorator( - labelPosition: charts.BarLabelPosition.auto, - ), - ), - selectionModels: [ - SelectionModelConfig(changedListener: (SelectionModel model) { - final selectedDatum = model.selectedDatum; - if (selectedDatum.isNotEmpty) { - selectedDatum.forEach((charts.SeriesDatum datumPair) { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => QtyByCustomerTable( - poChartData: datumPair.datum, - )), - ); - }); - } - }) - ], - ), - ), - ], - ), - ); - } - - Future _load() async { - var chartModel = Provider.of(context); - var _s = await chartModel.loadSummary(); - setState(() { - this.chartSummary = _s ?? []; - }); - } -} diff --git a/lib/charts/delivery_do_line.dart b/lib/charts/delivery_do_line.dart deleted file mode 100644 index 5e6bd38..0000000 --- a/lib/charts/delivery_do_line.dart +++ /dev/null @@ -1,84 +0,0 @@ -import 'package:charts_flutter/flutter.dart' as charts; -import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/chart_model.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/revenue.dart'; -import 'package:fcs/widget/local_text.dart'; - -import 'delivery_do_line_detail.dart'; - -class DODeliveryLineChart extends StatefulWidget { - @override - _DODeliveryLineChartState createState() => _DODeliveryLineChartState(); -} - -class _DODeliveryLineChartState extends State { - static final numberFormatter = new NumberFormat("#,###"); - - @override - void initState() { - super.initState(); - } - - @override - Widget build(BuildContext context) { - var chartModel = Provider.of(context); - - List> series = [ - charts.Series( - id: "Subscribers", - data: chartModel.revenue.getDeliveryDo(), - domainFn: (Data series, _) => series.date, - measureFn: (Data series, _) => series.count, - colorFn: (_, __) => charts.ColorUtil.fromDartColor(primaryColor), - labelAccessorFn: (Data series, _) => - '${numberFormatter.format(series.count)}', - ), - ]; - - return Container( - height: 200, - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - LocalText(context, "delivery.do.title", - color: primaryColor, fontSize: 16), - InkWell( - child: LocalText( - context, - "delivery.do.details", - color: secondaryColor, - fontSize: 14, - ), - onTap: () { - Navigator.of(context).push(MaterialPageRoute( - builder: (_) => DODeliveryLineDetail())); - }, - ), - ], - ), - Expanded( - child: charts.TimeSeriesChart( - series, - animate: true, - defaultRenderer: new charts.LineRendererConfig( - includePoints: true, - ), - primaryMeasureAxis: new charts.NumericAxisSpec( - tickProviderSpec: new charts.BasicNumericTickProviderSpec( - zeroBound: false, desiredTickCount: 10), - renderSpec: new charts.GridlineRendererSpec( - lineStyle: charts.LineStyleSpec( - dashPattern: [4, 4], - ))), - ), - ), - ], - ), - ); - } -} diff --git a/lib/charts/delivery_do_line_detail.dart b/lib/charts/delivery_do_line_detail.dart deleted file mode 100644 index 5ef17d8..0000000 --- a/lib/charts/delivery_do_line_detail.dart +++ /dev/null @@ -1,85 +0,0 @@ -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/chart_model.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/revenue.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/my_data_table.dart'; -import 'package:fcs/widget/progress.dart'; - -class DODeliveryLineDetail extends StatefulWidget { - const DODeliveryLineDetail(); - @override - _DODeliveryLineDetailState createState() => _DODeliveryLineDetailState(); -} - -class _DODeliveryLineDetailState extends State { - final numberFormatter = new NumberFormat("#,###"); - var dateFormatter = new DateFormat('dd MMM yyyy'); - bool _isLoading = false; - - @override - void initState() { - super.initState(); - } - - @override - Widget build(BuildContext context) { - var chartModel = Provider.of(context); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - title: LocalText( - context, - 'delivery.do.counts', - color: Colors.white, - fontSize: 18, - ), - ), - body: Container( - padding: EdgeInsets.only(top: 10), - child: SingleChildScrollView( - scrollDirection: Axis.vertical, - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - padding: EdgeInsets.only(left: 20), - child: MyDataTable( - columnSpacing: 100, - columns: [ - MyDataColumn(label: LocalText(context, "delivery.date")), - MyDataColumn(label: LocalText(context, "delivery.do.count")), - ], - rows: getProductRow(chartModel.revenue.getDeliveryDo()), - ), - ), - ), - ), - ), - ); - } - - List getProductRow(List doList) { - return doList.map((d) { - var r = MyDataRow( - cells: [ - MyDataCell( - new Text(dateFormatter.format(d.date), style: textStyle), - ), - MyDataCell( - new Text( - numberFormatter.format(d.count), - style: textStyle, - ), - ), - ], - ); - - return r; - }).toList(); - } -} diff --git a/lib/charts/delivery_do_summary.dart b/lib/charts/delivery_do_summary.dart deleted file mode 100644 index 251bf6d..0000000 --- a/lib/charts/delivery_do_summary.dart +++ /dev/null @@ -1,79 +0,0 @@ -import 'package:charts_flutter/flutter.dart' as charts; -import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/chart_model.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/revenue.dart'; -import 'package:fcs/widget/local_text.dart'; - -import 'delivery_do_summary_details.dart'; - -class DeliveryDoSummaryChart extends StatefulWidget { - @override - _DeliveryDoSummaryChartState createState() => _DeliveryDoSummaryChartState(); -} - -class _DeliveryDoSummaryChartState extends State { - static final numberFormatter = new NumberFormat("#,###"); - var dateFormatter = new DateFormat('dd MMM yyyy'); - - @override - void initState() { - super.initState(); - } - - @override - Widget build(BuildContext context) { - var chartModel = Provider.of(context); - - List> series = [ - charts.Series( - id: "Subscribers", - data: chartModel.revenue.getDeliveryDoSummary(), - domainFn: (Data series, _) => "${series.totalDay}days", - measureFn: (Data series, _) => series.totalCount, - labelAccessorFn: (Data series, _) => - '${numberFormatter.format(series.totalCount)}'), - ]; - - return Container( - height: 200, - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - LocalText(context, "delivery.do.summary", - color: primaryColor, fontSize: 16), - InkWell( - child: LocalText( - context, - "delivery.do.details", - color: secondaryColor, - fontSize: 14, - ), - onTap: () { - Navigator.of(context).push(MaterialPageRoute( - builder: (_) => DeliveryDoSummaryDetail())); - }, - ), - ], - ), - Expanded( - child: charts.BarChart( - series, - animate: true, - vertical: false, - defaultRenderer: new charts.BarRendererConfig( - barRendererDecorator: new charts.BarLabelDecorator( - labelPosition: charts.BarLabelPosition.auto, - ), - ), - ), - ), - ], - ), - ); - } -} diff --git a/lib/charts/delivery_do_summary_details.dart b/lib/charts/delivery_do_summary_details.dart deleted file mode 100644 index 5fa669a..0000000 --- a/lib/charts/delivery_do_summary_details.dart +++ /dev/null @@ -1,86 +0,0 @@ -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/chart_model.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/revenue.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/my_data_table.dart'; -import 'package:fcs/widget/progress.dart'; - -class DeliveryDoSummaryDetail extends StatefulWidget { - const DeliveryDoSummaryDetail(); - @override - _DeliveryDoSummaryDetailState createState() => - _DeliveryDoSummaryDetailState(); -} - -class _DeliveryDoSummaryDetailState extends State { - final numberFormatter = new NumberFormat("#,###"); - var dateFormatter = new DateFormat('dd MMM yyyy'); - bool _isLoading = false; - - @override - void initState() { - super.initState(); - } - - @override - Widget build(BuildContext context) { - var chartModel = Provider.of(context); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - title: LocalText( - context, - 'delivery.do.sum.counts', - color: Colors.white, - fontSize: 18, - ), - ), - body: Container( - padding: EdgeInsets.only(top: 10), - child: SingleChildScrollView( - scrollDirection: Axis.vertical, - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - padding: EdgeInsets.only(left: 20), - child: MyDataTable( - columnSpacing: 100, - columns: [ - MyDataColumn(label: LocalText(context, "delivery.days")), - MyDataColumn(label: LocalText(context, "delivery.do.count")), - ], - rows: getProductRow(chartModel.revenue.getDeliveryDoSummary()), - ), - ), - ), - ), - ), - ); - } - - List getProductRow(List doList) { - return doList.map((d) { - var r = MyDataRow( - cells: [ - MyDataCell( - new Text(d.totalDay.toString(), style: textStyle), - ), - MyDataCell( - new Text( - numberFormatter.format(d.totalCount), - style: textStyle, - ), - ), - ], - ); - - return r; - }).toList(); - } -} diff --git a/lib/charts/delivery_line.dart b/lib/charts/delivery_line.dart deleted file mode 100644 index 6d8f83d..0000000 --- a/lib/charts/delivery_line.dart +++ /dev/null @@ -1,107 +0,0 @@ -import 'package:charts_flutter/flutter.dart' as charts; -import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/chart_model.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/revenue.dart'; -import 'package:fcs/widget/local_text.dart'; - -import 'delivery_line_data.dart'; - -class DeliveryBarChart extends StatefulWidget { - @override - _DeliveryBarChartState createState() => _DeliveryBarChartState(); -} - -class _DeliveryBarChartState extends State { - static final numberFormatter = new NumberFormat("#,###"); - var dateFormatter = new DateFormat('dd MMM yyyy'); - - @override - void initState() { - super.initState(); - } - - @override - Widget build(BuildContext context) { - var chartModel = Provider.of(context); - - List> series = [ - charts.Series( - id: "Subscribers", - data: chartModel.revenue.getDelivery(), - domainFn: (Data series, _) => - "${series.date.day}-${series.date.month}-${series.date.year}", - measureFn: (Data series, _) => series.amount, - labelAccessorFn: (Data series, _) => - '${numberFormatter.format(series.amount)}'), - ]; - - List> seriesLine = [ - charts.Series( - id: "Subscribers", - data: chartModel.revenue.getDelivery(), - domainFn: (Data series, _) => series.date, - measureFn: (Data series, _) => series.amount, - colorFn: (_, __) => charts.ColorUtil.fromDartColor(primaryColor), - labelAccessorFn: (Data series, _) => - '${numberFormatter.format(series.amount)}', - ), - ]; - - return Container( - height: 200, - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - LocalText(context, "delivery", color: primaryColor, fontSize: 16), - InkWell( - child: LocalText( - context, - "delivery.detail", - color: secondaryColor, - fontSize: 14, - ), - onTap: () { - Navigator.of(context).push( - MaterialPageRoute(builder: (_) => DeliveryBarData())); - }, - ), - ], - ), - Expanded( - child: charts.TimeSeriesChart( - seriesLine, - animate: true, - defaultRenderer: new charts.LineRendererConfig( - includePoints: true, - ), - primaryMeasureAxis: new charts.NumericAxisSpec( - tickProviderSpec: new charts.BasicNumericTickProviderSpec( - zeroBound: false, desiredTickCount: 10), - renderSpec: new charts.GridlineRendererSpec( - lineStyle: charts.LineStyleSpec( - dashPattern: [4, 4], - ))), - ), - ), - // Expanded( - // child: charts.BarChart( - // series, - // animate: true, - // vertical: true, - // defaultRenderer: new charts.BarRendererConfig( - // barRendererDecorator: new charts.BarLabelDecorator( - // labelPosition: charts.BarLabelPosition.auto, - // ), - // ), - // ), - // ), - ], - ), - ); - } -} diff --git a/lib/charts/delivery_line_data.dart b/lib/charts/delivery_line_data.dart deleted file mode 100644 index 634a6a3..0000000 --- a/lib/charts/delivery_line_data.dart +++ /dev/null @@ -1,91 +0,0 @@ -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/chart_model.dart'; -import 'package:fcs/model/main_model.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/revenue.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/my_data_table.dart'; -import 'package:fcs/widget/number_cell.dart'; -import 'package:fcs/widget/progress.dart'; - -import 'delivery_line_detail.dart'; - -class DeliveryBarData extends StatefulWidget { - const DeliveryBarData(); - @override - _DeliveryBarDataState createState() => _DeliveryBarDataState(); -} - -class _DeliveryBarDataState extends State { - final numberFormatter = new NumberFormat("#,###"); - var dateFormatter = new DateFormat('dd MMM yyyy'); - bool _isLoading = false; - - @override - void initState() { - super.initState(); - } - - @override - Widget build(BuildContext context) { - var chartModel = Provider.of(context); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - title: LocalText( - context, - 'delivery.data.title', - color: Colors.white, - fontSize: 18, - ), - ), - body: Container( - padding: EdgeInsets.only(top: 10), - child: SingleChildScrollView( - scrollDirection: Axis.vertical, - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - padding: EdgeInsets.only(left: 20), - child: MyDataTable( - columnSpacing: 100, - columns: [ - MyDataColumn(label: LocalText(context, "delivery.date")), - MyDataColumn( - label: LocalText(context, "delivery.qty"), numeric: true), - ], - rows: getProductRow(chartModel.revenue.getDelivery()), - ), - ), - ), - ), - ), - ); - } - - List getProductRow(List doList) { - return doList.map((d) { - var r = MyDataRow( - onSelectChanged: (bool selected) async { - Navigator.push( - context, - MaterialPageRoute(builder: (context) => DeliveryBarDetail(d.date)), - ); - }, - cells: [ - MyDataCell( - new Text(dateFormatter.format(d.date), style: textStyle), - ), - MyDataCell(NumberCell(d.amount)), - ], - ); - - return r; - }).toList(); - } -} diff --git a/lib/charts/delivery_line_detail.dart b/lib/charts/delivery_line_detail.dart deleted file mode 100644 index 211470b..0000000 --- a/lib/charts/delivery_line_detail.dart +++ /dev/null @@ -1,93 +0,0 @@ -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/do_model.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/do.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/my_data_table.dart'; -import 'package:fcs/widget/number_cell.dart'; -import 'package:fcs/widget/progress.dart'; - -class DeliveryBarDetail extends StatefulWidget { - final DateTime date; - const DeliveryBarDetail(this.date); - @override - _DeliveryBarDetailState createState() => _DeliveryBarDetailState(); -} - -class _DeliveryBarDetailState extends State { - final numberFormatter = new NumberFormat("#,###"); - var dateFormatter = new DateFormat('dd-MMM-yyyy'); - bool _isLoading = false; - List dos = []; - - @override - void initState() { - super.initState(); - DOModel dOModel = Provider.of(context, listen: false); - dOModel.getDOForDelivery(widget.date).then((dos) { - setState(() { - this.dos = dos; - }); - }); - } - - @override - Widget build(BuildContext context) { - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - title: LocalText( - context, - 'delivery.detail.title', - translationVariables: [dateFormatter.format(widget.date)], - color: Colors.white, - fontSize: 18, - ), - ), - body: Container( - padding: EdgeInsets.only(top: 5), - child: SingleChildScrollView( - scrollDirection: Axis.vertical, - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - padding: EdgeInsets.only(left: 3), - child: MyDataTable( - columnSpacing: 20, - columns: [ - MyDataColumn(label: LocalText(context, "do.name")), - MyDataColumn(label: LocalText(context, "do.do_num")), - MyDataColumn( - label: LocalText(context, "do.quantity"), numeric: true), - ], - rows: getProductRow(), - ), - ), - ), - ), - ), - ); - } - - List getProductRow() { - return dos.map((d) { - var r = MyDataRow( - cells: [ - MyDataCell( - new Text(d.userName, style: textStyle), - ), - MyDataCell( - new Text(d.doNumber, style: textStyle), - ), - MyDataCell(NumberCell(d.totalQty)), - ], - ); - - return r; - }).toList(); - } -} diff --git a/lib/charts/delivery_summary.dart b/lib/charts/delivery_summary.dart deleted file mode 100644 index 133563b..0000000 --- a/lib/charts/delivery_summary.dart +++ /dev/null @@ -1,78 +0,0 @@ -import 'package:charts_flutter/flutter.dart' as charts; -import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/chart_model.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/revenue.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'delivery_summary_detail.dart'; - -class DeliverySummary extends StatefulWidget { - @override - _DeliverySummaryState createState() => _DeliverySummaryState(); -} - -class _DeliverySummaryState extends State { - static final numberFormatter = new NumberFormat("#,###"); - var dateFormatter = new DateFormat('dd MMM yyyy'); - - @override - void initState() { - super.initState(); - } - - @override - Widget build(BuildContext context) { - var chartModel = Provider.of(context); - - List> series = [ - charts.Series( - id: "Subscribers", - data: chartModel.revenue.getDeliverySummary(), - domainFn: (Data series, _) => "${series.totalDay}days", - measureFn: (Data series, _) => series.totalAmount, - labelAccessorFn: (Data series, _) => - '${numberFormatter.format(series.totalAmount)}'), - ]; - - return Container( - height: 200, - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - LocalText(context, "delivery.summary", - color: primaryColor, fontSize: 16), - InkWell( - child: LocalText( - context, - "delivery.detail", - color: secondaryColor, - fontSize: 14, - ), - onTap: () { - Navigator.of(context).push(MaterialPageRoute( - builder: (_) => DeliverySummaryDetail())); - }, - ), - ], - ), - Expanded( - child: charts.BarChart( - series, - animate: true, - vertical: false, - defaultRenderer: new charts.BarRendererConfig( - barRendererDecorator: new charts.BarLabelDecorator( - labelPosition: charts.BarLabelPosition.auto, - ), - ), - ), - ), - ], - ), - ); - } -} diff --git a/lib/charts/delivery_summary_detail.dart b/lib/charts/delivery_summary_detail.dart deleted file mode 100644 index 78ccad8..0000000 --- a/lib/charts/delivery_summary_detail.dart +++ /dev/null @@ -1,85 +0,0 @@ -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/chart_model.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/revenue.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/my_data_table.dart'; -import 'package:fcs/widget/progress.dart'; - -class DeliverySummaryDetail extends StatefulWidget { - const DeliverySummaryDetail(); - @override - _DeliverySummaryDetailState createState() => _DeliverySummaryDetailState(); -} - -class _DeliverySummaryDetailState extends State { - final numberFormatter = new NumberFormat("#,###"); - var dateFormatter = new DateFormat('dd MMM yyyy'); - bool _isLoading = false; - - @override - void initState() { - super.initState(); - } - - @override - Widget build(BuildContext context) { - var chartModel = Provider.of(context); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - title: LocalText( - context, - 'delivery.sum.amounts', - color: Colors.white, - fontSize: 18, - ), - ), - body: Container( - padding: EdgeInsets.only(top: 10), - child: SingleChildScrollView( - scrollDirection: Axis.vertical, - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - padding: EdgeInsets.only(left: 20), - child: MyDataTable( - columnSpacing: 100, - columns: [ - MyDataColumn(label: LocalText(context, "delivery.days")), - MyDataColumn(label: LocalText(context, "delivery.amount")), - ], - rows: getProductRow(chartModel.revenue.getDeliverySummary()), - ), - ), - ), - ), - ), - ); - } - - List getProductRow(List doList) { - return doList.map((d) { - var r = MyDataRow( - cells: [ - MyDataCell( - new Text(d.totalDay.toString(), style: textStyle), - ), - MyDataCell( - new Text( - numberFormatter.format(d.totalAmount), - style: textStyle, - ), - ), - ], - ); - - return r; - }).toList(); - } -} diff --git a/lib/charts/do_line.dart b/lib/charts/do_line.dart deleted file mode 100644 index 544ac65..0000000 --- a/lib/charts/do_line.dart +++ /dev/null @@ -1,156 +0,0 @@ -import 'package:charts_flutter/flutter.dart' as charts; -import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/chart_model.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/po_do_count.dart'; -import 'package:fcs/widget/local_text.dart'; - -import 'do_line_detail.dart'; - -class DOLineChart extends StatefulWidget { - @override - _DOLineChartState createState() => _DOLineChartState(); -} - -class _DOLineChartState extends State { - static final numberFormatter = new NumberFormat("#,###"); - - @override - void initState() { - super.initState(); - } - - @override - Widget build(BuildContext context) { - var chartModel = Provider.of(context); - - List> series = [ - charts.Series( - id: "pending", - data: chartModel.podoCount.getDODataCounts("pending"), - domainFn: (CountData series, _) => series.date, - measureFn: (CountData series, _) => - series.count == null ? 0 : series.count, - colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault, - dashPatternFn: (_, __) => [8, 3, 2, 3], - labelAccessorFn: (CountData series, _) => - '${numberFormatter.format(series.count)}', - ), - charts.Series( - id: "approved", - data: chartModel.podoCount.getDODataCounts("approved"), - domainFn: (CountData series, _) => series.date, - measureFn: (CountData series, _) => - series.count == null ? 0 : series.count, - colorFn: (_, __) => charts.MaterialPalette.green.shadeDefault, - labelAccessorFn: (CountData series, _) => - '${numberFormatter.format(series.count)}', - ), - charts.Series( - id: "canceled", - data: chartModel.podoCount.getDODataCounts("canceled"), - domainFn: (CountData series, _) => series.date, - measureFn: (CountData series, _) => - series.count == null ? 0 : series.count, - colorFn: (_, __) => charts.MaterialPalette.gray.shadeDefault, - dashPatternFn: (_, __) => [8, 3, 2, 3], - labelAccessorFn: (CountData series, _) => - '${numberFormatter.format(series.count)}', - ), - charts.Series( - id: "rejected", - data: chartModel.podoCount.getDODataCounts("rejected"), - domainFn: (CountData series, _) => series.date, - measureFn: (CountData series, _) => - series.count == null ? 0 : series.count, - colorFn: (_, __) => charts.MaterialPalette.red.shadeDefault, - dashPatternFn: (_, __) => [8, 3, 2, 3], - labelAccessorFn: (CountData series, _) => - '${numberFormatter.format(series.count)}', - ), - charts.Series( - id: "expired", - data: chartModel.podoCount.getDODataCounts("expired"), - domainFn: (CountData series, _) => series.date, - measureFn: (CountData series, _) => - series.count == null ? 0 : series.count, - colorFn: (_, __) => charts.MaterialPalette.purple.shadeDefault, - dashPatternFn: (_, __) => [8, 5, 2, 5], - labelAccessorFn: (CountData series, _) => - '${numberFormatter.format(series.count)}', - ), - charts.Series( - id: "closed", - data: chartModel.podoCount.getDODataCounts("closed"), - domainFn: (CountData series, _) => series.date, - measureFn: (CountData series, _) => - series.count == null ? 0 : series.count, - colorFn: (_, __) => charts.MaterialPalette.indigo.shadeDefault, - dashPatternFn: (_, __) => [8, 5, 2, 5], - labelAccessorFn: (CountData series, _) => - '${numberFormatter.format(series.count)}', - ), - ]; - - return Container( - height: 200, - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - LocalText(context, "do", color: primaryColor, fontSize: 16), - LocalText(context, 'chart.30_days', - color: primaryColor, fontSize: 14) - ], - ), - InkWell( - child: LocalText( - context, - "do.details", - color: secondaryColor, - fontSize: 14, - ), - onTap: () { - Navigator.of(context) - .push(MaterialPageRoute(builder: (_) => DOLineDetail())); - }, - ), - ], - ), - Expanded( - child: charts.TimeSeriesChart( - series, - animate: true, - defaultRenderer: new charts.LineRendererConfig( - includePoints: true, - ), - behaviors: [ - new charts.SeriesLegend( - position: charts.BehaviorPosition.end, - outsideJustification: - charts.OutsideJustification.middleDrawArea, - entryTextStyle: charts.TextStyleSpec( - color: charts.Color(r: 127, g: 63, b: 191), - fontFamily: 'Georgia', - fontSize: 11), - ) - ], - primaryMeasureAxis: new charts.NumericAxisSpec( - tickProviderSpec: new charts.BasicNumericTickProviderSpec( - zeroBound: false, desiredTickCount: 10), - renderSpec: new charts.GridlineRendererSpec( - lineStyle: charts.LineStyleSpec( - dashPattern: [4, 4], - ))), - ), - ), - ], - ), - ); - } -} diff --git a/lib/charts/do_line_detail.dart b/lib/charts/do_line_detail.dart deleted file mode 100644 index e0c8192..0000000 --- a/lib/charts/do_line_detail.dart +++ /dev/null @@ -1,121 +0,0 @@ -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/chart_model.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/po_do_count.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/my_data_table.dart'; -import 'package:fcs/widget/progress.dart'; - -class DOLineDetail extends StatefulWidget { - const DOLineDetail(); - @override - _DOLineDetailState createState() => _DOLineDetailState(); -} - -class _DOLineDetailState extends State { - final numberFormatter = new NumberFormat("#,###"); - var dateFormatter = new DateFormat('dd MMM yyyy'); - bool _isLoading = false; - - @override - void initState() { - super.initState(); - } - - @override - Widget build(BuildContext context) { - var chartModel = Provider.of(context); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - title: LocalText( - context, - 'do.counts', - color: Colors.white, - fontSize: 18, - ), - ), - body: Container( - child: ListView( - children: [ - Column( - children: [ - Container( - padding: EdgeInsets.only(top: 20, left: 20, right: 20), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - LocalText(context, "chart.date"), - LocalText(context, "do.total_count") - ], - ), - ), - Column( - children: getRowTotalCountWidget( - chartModel.podoCount.getDOTotalCounts()), - ) - ], - ), - ], - ), - ), - ), - ); - } - - List getRowTotalCountWidget(List data) { - return data.map((d) { - return Container( - child: ExpansionTile( - title: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text(dateFormatter.format(d.date), style: textStyle), - Text(numberFormatter.format(d.totalCount), style: textStyle), - ], - ), - children: [ - SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: MyDataTable( - columnSpacing: 100, - columns: [ - MyDataColumn(label: LocalText(context, "do.count.status")), - MyDataColumn(label: LocalText(context, "do.count")), - ], - rows: getStatusRow(d.detailCountsList), - ), - ), - ], - ), - ); - }).toList(); - } - - List getStatusRow(List doList) { - doList.sort((a, b) => a.status.compareTo(b.status)); - return doList.map((d) { - var r = MyDataRow( - cells: [ - MyDataCell( - new Text(d.status, style: textStyle), - ), - MyDataCell( - new Text( - numberFormatter.format(d.count), - style: textStyle, - ), - ), - ], - ); - - return r; - }).toList(); - } -} diff --git a/lib/charts/lines.dart b/lib/charts/lines.dart deleted file mode 100644 index bcd4167..0000000 --- a/lib/charts/lines.dart +++ /dev/null @@ -1,107 +0,0 @@ -import 'package:charts_flutter/flutter.dart' as charts; -import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; - -import '../model/product_model.dart'; - -typedef void ProductClick(DateTime date, Map measures); - -class ProductsChart extends StatelessWidget { - static final numberFormatter = new NumberFormat("#,###"); - final ChartData chartData; - final ProductClick productClick; - const ProductsChart(this.chartData, {Key key, this.productClick}) - : super(key: key); - factory ProductsChart.fromModel(ProductModel productModel, - {ProductClick productClick}) { - return new ProductsChart(_createData(productModel), - productClick: productClick); - } - - static ChartData _createData(ProductModel productModel) { - List> list = []; - var min = 9999, max = 0; - productModel.products.forEach((p) { - List data = []; - if (p.priceHistory != null) { - var dateKeys = {}; - p.priceHistory.entries.forEach((e) { - dateKeys[DateTime.parse(e.key)] = e.value; - }); - - var sortedKeys = dateKeys.keys.toList()..sort((a, b) => b.compareTo(a)); - sortedKeys.forEach((k) { - var v = dateKeys[k]; - data.add(new TimeSeriesSales(k, v)); - if (v < min) min = v; - if (v > max) max = v; - }); - } - - list.add(new charts.Series( - id: p.name, - colorFn: (_, __) => charts.ColorUtil.fromDartColor(Color(p.color)), - domainFn: (TimeSeriesSales sales, _) => sales.time, - measureFn: (TimeSeriesSales sales, _) => sales.sales, - data: data, - labelAccessorFn: (TimeSeriesSales series, _) => - '${numberFormatter.format(series.sales)}', - measureFormatterFn: (TimeSeriesSales series, _) => (n) => "s", - )); - }); - var chartData = ChartData(list, min, max); - return chartData; - } - - @override - Widget build(BuildContext context) { - return charts.TimeSeriesChart( - chartData.seriesList, - animate: true, - defaultRenderer: new charts.LineRendererConfig( - includePoints: true, - ), - primaryMeasureAxis: new charts.NumericAxisSpec( - tickProviderSpec: new charts.BasicNumericTickProviderSpec( - zeroBound: false, desiredTickCount: 10), - renderSpec: new charts.GridlineRendererSpec( - lineStyle: charts.LineStyleSpec( - dashPattern: [4, 4], - ))), - selectionModels: [ - new charts.SelectionModelConfig( - type: charts.SelectionModelType.info, - updatedListener: _onSelectionChanged, - ) - ], - ); - } - - _onSelectionChanged(charts.SelectionModel model) { - final selectedDatum = model.selectedDatum; - if (selectedDatum.isNotEmpty) { - var _time = selectedDatum.first.datum.time; - Map _measures = {}; - - selectedDatum.forEach((charts.SeriesDatum datumPair) { - _measures[datumPair.series.displayName] = datumPair.datum.sales; - }); - if (productClick != null) { - productClick(_time, _measures); - } - } - } -} - -class TimeSeriesSales { - final DateTime time; - final int sales; - - TimeSeriesSales(this.time, this.sales); -} - -class ChartData { - final List seriesList; - final num min, max; - ChartData(this.seriesList, this.min, this.max); -} diff --git a/lib/charts/po_balance_chart.dart b/lib/charts/po_balance_chart.dart deleted file mode 100644 index 2791633..0000000 --- a/lib/charts/po_balance_chart.dart +++ /dev/null @@ -1,134 +0,0 @@ -import 'package:charts_flutter/flutter.dart' as charts; -import 'package:charts_flutter/flutter.dart'; -import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/charts/po_balance_table.dart'; -import 'package:fcs/model/chart_model.dart'; -import 'package:fcs/model/product_model.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/po.dart'; -import 'package:fcs/widget/local_text.dart'; - -class POBalanceChart extends StatefulWidget { - @override - _POBalanceChartState createState() => _POBalanceChartState(); -} - -class _POBalanceChartState extends State { - static final numberFormatter = new NumberFormat("#,###"); - List chartSummary = new List(); - List> series; - - @override - void initState() { - super.initState(); - var chartModel = Provider.of(context, listen: false); - if (mounted) { - load(chartModel); - } - } - - Future load(ChartModel chartModel) async { - var _u = await chartModel.loadPOBalancesForBuyer(); - if (_u == null) return; - if (mounted) { - setState(() { - this.chartSummary = _u; - }); - } - } - - @override - Widget build(BuildContext context) { - var productModel = Provider.of(context); - if (this.chartSummary.isNotEmpty) { - this.chartSummary.forEach((s) { - productModel.products.forEach((p) { - if (p.id == s.productID) { - s.displayOrder = p.displayOrder; - } else { - return; - } - }); - }); - - this - .chartSummary - .sort((s1, s2) => s1.displayOrder.compareTo(s2.displayOrder)); - } - List> series = [ - charts.Series( - id: "Subscribers", - data: this.chartSummary, - domainFn: (POChartData series, _) => series.productName, - measureFn: (POChartData series, _) => series.balanceQty, - colorFn: (POChartData series, _) => - charts.ColorUtil.fromDartColor(series.getColor), - labelAccessorFn: (POChartData series, _) => - '${numberFormatter.format(series.balanceQty)}'), - ]; - - return Container( - height: 200, - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - LocalText(context, 'po.balances', - color: primaryColor, fontSize: 16), - IconButton( - icon: Icon( - Icons.refresh, - color: primaryColor, - ), - onPressed: () { - _load(); - }, - ) - ], - ), - Expanded( - child: charts.BarChart( - series, - animate: true, - vertical: false, - defaultRenderer: new charts.BarRendererConfig( - barRendererDecorator: new charts.BarLabelDecorator( - labelPosition: charts.BarLabelPosition.auto, - ), - ), - selectionModels: [ - SelectionModelConfig(changedListener: (SelectionModel model) { - final selectedDatum = model.selectedDatum; - if (selectedDatum.isNotEmpty) { - selectedDatum.forEach((charts.SeriesDatum datumPair) { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => POBalanceTable( - poChartData: datumPair.datum, - )), - ); - }); - } - }) - ], - ), - ), - ], - ), - ); - } - - Future _load() async { - var chartModel = Provider.of(context); - var _s = await chartModel.loadPOBalancesForBuyer(); - if (mounted) { - setState(() { - this.chartSummary = _s ?? []; - }); - } - } -} diff --git a/lib/charts/po_balance_table.dart b/lib/charts/po_balance_table.dart deleted file mode 100644 index d91280e..0000000 --- a/lib/charts/po_balance_table.dart +++ /dev/null @@ -1,106 +0,0 @@ -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/chart_model.dart'; -import 'package:fcs/model/language_model.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/po.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:fcs/widget/my_data_table.dart'; -import 'package:fcs/widget/number_cell.dart'; -import 'package:fcs/widget/progress.dart'; - -class POBalanceTable extends StatefulWidget { - final POChartData poChartData; - const POBalanceTable({Key key, this.poChartData}) : super(key: key); - @override - _POBalanceTableState createState() => _POBalanceTableState(); -} - -class _POBalanceTableState extends State { - final numberFormatter = new NumberFormat("#,###"); - List chartUser = new List(); - bool _isLoading = false; - - @override - void initState() { - super.initState(); - var chartModel = Provider.of(context, listen: false); - if (mounted) { - load(chartModel); - } - } - - Future load(ChartModel chartModel) async { - var _u = await chartModel.loadPOBalProductsForBuyer(); - setState(() { - this.chartUser = _u; - }); - } - - @override - Widget build(BuildContext context) { - List data = this - .chartUser - .where((u) => u.productName == widget.poChartData.productName) - .toList(); - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - title: Text( - AppTranslations.of(context).text("product.qtys"), - style: Provider.of(context).isEng - ? TextStyle(fontSize: 18) - : TextStyle(fontSize: 18, fontFamily: 'MyanmarUnicode'), - ), - ), - body: Container( - padding: EdgeInsets.only(top: 10), - child: SingleChildScrollView( - scrollDirection: Axis.vertical, - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: MyDataTable( - headingRowHeight: 40, - columnSpacing: 40, - columns: [ - MyDataColumn(label: LocalText(context, "buyer.name")), - MyDataColumn(label: LocalText(context, "buyer.product")), - MyDataColumn( - label: LocalText(context, "buyer.balQty"), numeric: true), - ], - rows: getProductRow(data), - ), - ), - ), - ), - ), - ); - } - - List getProductRow(List poLines) { - return poLines.map((p) { - return MyDataRow( - cells: [ - MyDataCell( - new Text(p.userName, style: textStyle), - ), - MyDataCell( - new Text( - p.productName, - style: textStyle, - ), - ), - MyDataCell( - NumberCell(p.balanceQty), - //new Text(numberFormatter.format(p.balanceQty), style: textStyle), - ), - ], - ); - }).toList(); - } -} diff --git a/lib/charts/po_balanceby_buyer.dart b/lib/charts/po_balanceby_buyer.dart deleted file mode 100644 index 035b092..0000000 --- a/lib/charts/po_balanceby_buyer.dart +++ /dev/null @@ -1,96 +0,0 @@ -import 'package:charts_flutter/flutter.dart' as charts; -import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/chart_model.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/po.dart'; -import 'package:fcs/widget/local_text.dart'; - -class POBalanceChart_ extends StatefulWidget { - @override - _POBalanceChartState createState() => _POBalanceChartState(); -} - -class _POBalanceChartState extends State { - static final numberFormatter = new NumberFormat("#,###"); - List chartSummary = new List(); - List> series; - - @override - void initState() { - super.initState(); - var chartModel = Provider.of(context, listen: false); - if (mounted) { - load(chartModel); - } - } - - Future load(ChartModel chartModel) async { - var _u = await chartModel.loadPOBalancesForBuyer_(); - if (_u == null) return; - setState(() { - this.chartSummary = _u; - }); - } - - @override - Widget build(BuildContext context) { - List> series = [ - charts.Series( - id: "Subscribers", - data: this.chartSummary, - domainFn: (POBuyerData series, _) => series.status, - measureFn: (POBuyerData series, _) => series.amount, - colorFn: (POBuyerData series, _) => - charts.ColorUtil.fromDartColor(series.getColor), - labelAccessorFn: (POBuyerData series, _) => - '${numberFormatter.format(series.amount)}'), - ]; - - return Container( - height: 200, - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - LocalText(context, 'po.balances', - color: primaryColor, fontSize: 16), - IconButton( - icon: Icon( - Icons.refresh, - color: primaryColor, - ), - onPressed: () { - _load(); - }, - ) - ], - ), - Expanded( - child: charts.BarChart( - series, - animate: true, - vertical: false, - defaultRenderer: new charts.BarRendererConfig( - barRendererDecorator: new charts.BarLabelDecorator( - labelPosition: charts.BarLabelPosition.auto, - ), - ), - ), - ), - ], - ), - ); - } - - Future _load() async { - var chartModel = Provider.of(context); - var _s = await chartModel.loadPOBalancesForBuyer_(); - if (_s == null) return; - setState(() { - this.chartSummary = _s; - }); - } -} diff --git a/lib/charts/po_line.dart b/lib/charts/po_line.dart deleted file mode 100644 index a29736b..0000000 --- a/lib/charts/po_line.dart +++ /dev/null @@ -1,155 +0,0 @@ -import 'package:charts_flutter/flutter.dart' as charts; -import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/charts/po_line_detail.dart'; -import 'package:fcs/model/chart_model.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/po_do_count.dart'; -import 'package:fcs/widget/local_text.dart'; - -class POLineChart extends StatefulWidget { - @override - _POLineChartState createState() => _POLineChartState(); -} - -class _POLineChartState extends State { - static final numberFormatter = new NumberFormat("#,###"); - - @override - void initState() { - super.initState(); - } - - @override - Widget build(BuildContext context) { - var chartModel = Provider.of(context); - - List> series = [ - charts.Series( - id: "pending", - data: chartModel.podoCount.getPODataCounts('pending'), - domainFn: (CountData series, _) => series.date, - measureFn: (CountData series, _) => - series.count == null ? 0 : series.count, - colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault, - dashPatternFn: (_, __) => [8, 3, 2, 3], - labelAccessorFn: (CountData series, _) => - '${numberFormatter.format(series.count)}', - ), - charts.Series( - id: "approved", - data: chartModel.podoCount.getPODataCounts("approved"), - domainFn: (CountData series, _) => series.date, - measureFn: (CountData series, _) => - series.count == null ? 0 : series.count, - colorFn: (_, __) => charts.MaterialPalette.green.shadeDefault, - labelAccessorFn: (CountData series, _) => - '${numberFormatter.format(series.count)}', - ), - charts.Series( - id: "canceled", - data: chartModel.podoCount.getPODataCounts("canceled"), - domainFn: (CountData series, _) => series.date, - measureFn: (CountData series, _) => - series.count == null ? 0 : series.count, - colorFn: (_, __) => charts.MaterialPalette.gray.shadeDefault, - dashPatternFn: (_, __) => [8, 3, 2, 3], - labelAccessorFn: (CountData series, _) => - '${numberFormatter.format(series.count)}', - ), - charts.Series( - id: "rejected", - data: chartModel.podoCount.getPODataCounts("rejected"), - domainFn: (CountData series, _) => series.date, - measureFn: (CountData series, _) => - series.count == null ? 0 : series.count, - colorFn: (_, __) => charts.MaterialPalette.red.shadeDefault, - dashPatternFn: (_, __) => [8, 3, 2, 3], - labelAccessorFn: (CountData series, _) => - '${numberFormatter.format(series.count)}', - ), - charts.Series( - id: "expired", - data: chartModel.podoCount.getPODataCounts("expired"), - domainFn: (CountData series, _) => series.date, - measureFn: (CountData series, _) => - series.count == null ? 0 : series.count, - colorFn: (_, __) => charts.MaterialPalette.purple.shadeDefault, - dashPatternFn: (_, __) => [8, 5, 2, 5], - labelAccessorFn: (CountData series, _) => - '${numberFormatter.format(series.count)}', - ), - charts.Series( - id: "closed", - data: chartModel.podoCount.getPODataCounts("closed"), - domainFn: (CountData series, _) => series.date, - measureFn: (CountData series, _) => - series.count == null ? 0 : series.count, - colorFn: (_, __) => charts.MaterialPalette.indigo.shadeDefault, - dashPatternFn: (_, __) => [8, 5, 2, 5], - labelAccessorFn: (CountData series, _) => - '${numberFormatter.format(series.count)}', - ), - ]; - - return Container( - height: 200, - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - LocalText(context, "po", color: primaryColor, fontSize: 16), - LocalText(context, 'chart.30_days', - color: primaryColor, fontSize: 14) - ], - ), - InkWell( - child: LocalText( - context, - "po.details", - color: secondaryColor, - fontSize: 14, - ), - onTap: () { - Navigator.of(context) - .push(MaterialPageRoute(builder: (_) => POLineDetail())); - }, - ), - ], - ), - Expanded( - child: charts.TimeSeriesChart( - series, - animate: true, - defaultRenderer: new charts.LineRendererConfig( - includePoints: true, - ), - behaviors: [ - new charts.SeriesLegend( - position: charts.BehaviorPosition.end, - outsideJustification: - charts.OutsideJustification.middleDrawArea, - entryTextStyle: charts.TextStyleSpec( - color: charts.Color(r: 127, g: 63, b: 191), - fontFamily: 'Georgia', - fontSize: 11), - ) - ], - primaryMeasureAxis: new charts.NumericAxisSpec( - tickProviderSpec: new charts.BasicNumericTickProviderSpec( - zeroBound: false, desiredTickCount: 10), - renderSpec: new charts.GridlineRendererSpec( - lineStyle: charts.LineStyleSpec( - dashPattern: [4, 4], - ))), - ), - ), - ], - ), - ); - } -} diff --git a/lib/charts/po_line_detail.dart b/lib/charts/po_line_detail.dart deleted file mode 100644 index 198be9d..0000000 --- a/lib/charts/po_line_detail.dart +++ /dev/null @@ -1,121 +0,0 @@ -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:http/http.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/chart_model.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/po_do_count.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/my_data_table.dart'; -import 'package:fcs/widget/progress.dart'; - -class POLineDetail extends StatefulWidget { - const POLineDetail(); - @override - _POLineDetailState createState() => _POLineDetailState(); -} - -class _POLineDetailState extends State { - final numberFormatter = new NumberFormat("#,###"); - var dateFormatter = new DateFormat('dd MMM yyyy'); - bool _isLoading = false; - - @override - void initState() { - super.initState(); - } - - @override - Widget build(BuildContext context) { - var chartModel = Provider.of(context); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - title: LocalText( - context, - 'po.counts', - color: Colors.white, - fontSize: 18, - ), - ), - body: Container( - child: ListView( - children: [ - Column( - children: [ - Container( - padding: EdgeInsets.only(top: 20, left: 20, right: 20), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - LocalText(context, "chart.date"), - LocalText(context, "po.total_count") - ], - ), - ), - Column( - children: getRowTotalCountWidget( - chartModel.podoCount.getPOTotalCounts()), - ) - ], - ), - ], - ), - ), - )); - } - - List getRowTotalCountWidget(List data) { - return data.map((d) { - return Container( - child: ExpansionTile( - title: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text(dateFormatter.format(d.date), style: textStyle), - Text(numberFormatter.format(d.totalCount), style: textStyle), - ], - ), - children: [ - SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: MyDataTable( - columnSpacing: 100, - columns: [ - MyDataColumn(label: LocalText(context, "po.count.status")), - MyDataColumn(label: LocalText(context, "po.count")), - ], - rows: getStatusRow(d.detailCountsList), - ), - ), - ], - ), - ); - }).toList(); - } - - List getStatusRow(List po) { - po.sort((a, b) => a.status.compareTo(b.status)); - return po.map((p) { - var r = MyDataRow( - cells: [ - MyDataCell( - new Text(p.status, style: textStyle), - ), - MyDataCell( - new Text( - p.count != null ? numberFormatter.format(p.count) : '0', - style: textStyle, - ), - ), - ], - ); - - return r; - }).toList(); - } -} diff --git a/lib/charts/qtyby_customer_table.dart b/lib/charts/qtyby_customer_table.dart deleted file mode 100644 index b5257c8..0000000 --- a/lib/charts/qtyby_customer_table.dart +++ /dev/null @@ -1,103 +0,0 @@ -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/chart_model.dart'; -import 'package:fcs/model/language_model.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/po.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:fcs/widget/my_data_table.dart'; -import 'package:fcs/widget/number_cell.dart'; -import 'package:fcs/widget/progress.dart'; - -class QtyByCustomerTable extends StatefulWidget { - final POChartData poChartData; - const QtyByCustomerTable({Key key, this.poChartData}) : super(key: key); - @override - _QtyByCustomerTableState createState() => _QtyByCustomerTableState(); -} - -class _QtyByCustomerTableState extends State { - final numberFormatter = new NumberFormat("#,###"); - List chartUser = new List(); - bool _isLoading = false; - - @override - void initState() { - super.initState(); - var chartModel = Provider.of(context, listen: false); - if (mounted) { - load(chartModel); - } - } - - Future load(ChartModel chartModel) async { - var _u = await chartModel.loadUsers(); - setState(() { - this.chartUser = _u; - }); - } - - @override - Widget build(BuildContext context) { - List data = this - .chartUser - .where((u) => u.productName == widget.poChartData.productName) - .toList(); - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - title: Text( - AppTranslations.of(context).text("product.qtys"), - style: Provider.of(context).isEng - ? TextStyle(fontSize: 18) - : TextStyle(fontSize: 18, fontFamily: 'MyanmarUnicode'), - ), - ), - body: Container( - padding: EdgeInsets.only(top: 10), - child: SingleChildScrollView( - scrollDirection: Axis.vertical, - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: MyDataTable( - headingRowHeight: 40, - columnSpacing: 40, - columns: [ - MyDataColumn(label: LocalText(context, "buyer.name")), - MyDataColumn(label: LocalText(context, "buyer.product")), - MyDataColumn( - label: LocalText(context, "buyer.balQty"), numeric: true), - ], - rows: getProductRow(data), - ), - ), - ), - ), - ), - ); - } - - List getProductRow(List poLines) { - return poLines.map((p) { - return MyDataRow( - cells: [ - MyDataCell( - new Text(p.userName, style: textStyle), - ), - MyDataCell( - new Text( - p.productName, - style: textStyle, - ), - ), - MyDataCell(NumberCell(p.balanceQty)), - ], - ); - }).toList(); - } -} diff --git a/lib/charts/quota.dart b/lib/charts/quota.dart deleted file mode 100644 index 285ebb2..0000000 --- a/lib/charts/quota.dart +++ /dev/null @@ -1,118 +0,0 @@ -/// Simple pie chart example. -import 'package:charts_flutter/flutter.dart' as charts; -import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; -import 'package:fcs/vo/buyer.dart'; -import 'package:fcs/vo/product.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; - -class QuotaChart extends StatelessWidget { - static final numberFormatter = new NumberFormat("#,###"); - - final List quotaSeries; - final String title; - - QuotaChart(this.quotaSeries, this.title); - - factory QuotaChart.dailyQuota( - BuildContext context, Buyer buyer, List products) { - List data = []; - products.sort((p1, p2) => p1.displayOrder.compareTo(p2.displayOrder)); - products.forEach((p) { - if (buyer.dailyQuotaUsedProducts.containsKey(p.id)) { - int value = buyer.dailyQuotaUsedProducts[p.id]; - data.add(Quota(p.name, value, p.color)); - } - }); - data.add( - new Quota(AppTranslations.of(context).text("chart.remaining"), - buyer.dailyQuota - buyer.dailyQuotaUsed, Colors.purple.value), - ); - - return new QuotaChart( - _createData(data), - AppTranslations.of(context).text("chart.daily.title", - translationVariables: [numberFormatter.format(buyer.dailyQuota)])); - } - - factory QuotaChart.maxQuota( - BuildContext context, Buyer buyer, List products) { - List data = []; - products.sort((p1, p2) => p1.displayOrder.compareTo(p2.displayOrder)); - products.forEach((p) { - if (buyer.maxQuotaUsedProducts.containsKey(p.id)) { - int value = buyer.maxQuotaUsedProducts[p.id]; - data.add(Quota(p.name, value, p.color)); - } - }); - data.add( - new Quota(AppTranslations.of(context).text("chart.remaining"), - buyer.maxQuota - buyer.maxQuotaUsed, Colors.purple.value), - ); - return new QuotaChart( - _createData(data), - AppTranslations.of(context).text("chart.max.title", - translationVariables: [numberFormatter.format(buyer.maxQuota)])); - } - - @override - Widget build(BuildContext context) { - return Column( - children: [ - Text(title), - Padding( - padding: const EdgeInsets.all(8.0), - child: Container( - height: 200, - child: charts.PieChart( - quotaSeries, - animate: false, - behaviors: [ - new charts.DatumLegend( - position: charts.BehaviorPosition.end, - horizontalFirst: false, - cellPadding: new EdgeInsets.only(right: 4.0, bottom: 4.0), - entryTextStyle: charts.TextStyleSpec( - color: charts.MaterialPalette.purple.shadeDefault, - fontFamily: 'Georgia', - fontSize: 11), - ) - ], - defaultRenderer: new charts.ArcRendererConfig( - arcWidth: 60, - arcRendererDecorators: [ - new charts.ArcLabelDecorator( - labelPosition: charts.ArcLabelPosition.auto, - labelPadding: 0) - ], - ), - ), - ), - ), - ], - ); - } - - static List> _createData(List data) { - return [ - new charts.Series( - id: 'Daily Quota', - domainFn: (Quota quota, _) => "${quota.label}\n", - measureFn: (Quota quota, _) => quota.quota, - data: data, - colorFn: (Quota quota, i) => - charts.ColorUtil.fromDartColor(Color(quota.color)), - labelAccessorFn: (Quota row, _) => - '${numberFormatter.format(row.quota)}', - ) - ]; - } -} - -class Quota { - final String label; - final int quota; - final int color; - - Quota(this.label, this.quota, this.color); -} diff --git a/lib/charts/revenue_line.dart b/lib/charts/revenue_line.dart deleted file mode 100644 index dbfbdac..0000000 --- a/lib/charts/revenue_line.dart +++ /dev/null @@ -1,118 +0,0 @@ -import 'package:charts_flutter/flutter.dart' as charts; -import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/chart_model.dart'; -import 'package:fcs/model/main_model.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/revenue.dart'; -import 'package:fcs/widget/local_text.dart'; - -import 'revenue_line_data.dart'; - -class RevenueLineChart extends StatefulWidget { - @override - _RevenueLineChartState createState() => _RevenueLineChartState(); -} - -class _RevenueLineChartState extends State { - static final numberFormatter = NumberFormat.compact(); - int actualChart = 0; - - @override - void initState() { - super.initState(); - } - - @override - Widget build(BuildContext context) { - var chartModel = Provider.of(context); - var mainModel = Provider.of(context); - - List> series = [ - charts.Series( - id: "Subscribers", - data: chartModel.revenue.getData(), - domainFn: (Data series, _) => series.date, - measureFn: (Data series, _) => series.amount, - colorFn: (_, __) => charts.ColorUtil.fromDartColor(primaryColor), - labelAccessorFn: (Data series, _) => - '${numberFormatter.format(series.amount)}', - ), - ]; - - final moneyFormatter = - new charts.BasicNumericTickFormatterSpec.fromNumberFormat( - new NumberFormat.compact()); - - return Container( - height: 200, - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - mainModel.user.isOwnerAndAbove() - ? Row( - children: [ - LocalText(context, 'chart.revenue', - fontSize: 16, color: primaryColor), - LocalText(context, 'chart.30_days', - color: primaryColor, fontSize: 14), - ], - ) - : Row( - children: [ - LocalText(context, 'chart.spending', - fontSize: 16, color: primaryColor), - LocalText(context, 'chart.30_days', - color: primaryColor, fontSize: 14) - ], - ), - Text( - "${chartModel.revenue.mapData == null ? "" : numberFormatter.format(chartModel.revenue.getTotal(actualChart))}", - style: TextStyle( - color: Colors.black, - fontWeight: FontWeight.w700, - fontSize: 17.0)) - ], - ), - InkWell( - child: LocalText( - context, - "revenue.detail", - color: secondaryColor, - fontSize: 14, - ), - onTap: () { - Navigator.of(context).push( - MaterialPageRoute(builder: (_) => RevenueLineData())); - }, - ), - ], - ), - Expanded( - child: charts.TimeSeriesChart( - series, - animate: true, - defaultRenderer: new charts.LineRendererConfig( - includePoints: true, - ), - primaryMeasureAxis: new charts.NumericAxisSpec( - tickFormatterSpec: moneyFormatter, - tickProviderSpec: new charts.BasicNumericTickProviderSpec( - zeroBound: false, desiredTickCount: 10), - renderSpec: new charts.GridlineRendererSpec( - lineStyle: charts.LineStyleSpec( - dashPattern: [4, 4], - ))), - ), - ), - ], - ), - ); - } -} diff --git a/lib/charts/revenue_line_data.dart b/lib/charts/revenue_line_data.dart deleted file mode 100644 index 146e6dc..0000000 --- a/lib/charts/revenue_line_data.dart +++ /dev/null @@ -1,92 +0,0 @@ -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/chart_model.dart'; -import 'package:fcs/model/main_model.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/revenue.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/my_data_table.dart'; -import 'package:fcs/widget/number_cell.dart'; -import 'package:fcs/widget/progress.dart'; - -import 'revenue_line_detail.dart'; - -class RevenueLineData extends StatefulWidget { - const RevenueLineData(); - @override - _RevenueLineDataState createState() => _RevenueLineDataState(); -} - -class _RevenueLineDataState extends State { - final numberFormatter = new NumberFormat("#,###"); - var dateFormatter = new DateFormat('dd MMM yyyy'); - bool _isLoading = false; - - @override - void initState() { - super.initState(); - } - - @override - Widget build(BuildContext context) { - var chartModel = Provider.of(context); - var mainModel = Provider.of(context); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - title: mainModel.user.isOwnerAndAbove() - ? LocalText(context, 'revenue.amounts', - color: Colors.white, fontSize: 18) - : LocalText(context, 'spending.amounts', - color: Colors.white, fontSize: 18), - ), - body: Container( - padding: EdgeInsets.only(top: 10), - child: SingleChildScrollView( - scrollDirection: Axis.vertical, - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - padding: EdgeInsets.only(left: 20), - child: MyDataTable( - columnSpacing: 100, - columns: [ - MyDataColumn(label: LocalText(context, "revenue.date")), - MyDataColumn( - label: LocalText(context, "revenue.amount"), - numeric: true), - ], - rows: getProductRow(chartModel.revenue.getData()), - ), - ), - ), - ), - ), - ); - } - - List getProductRow(List revs) { - return revs.map((p) { - var r = MyDataRow( - onSelectChanged: (bool selected) async { - Navigator.push( - context, - MaterialPageRoute(builder: (context) => RevenueLineDetail(p.date)), - ); - }, - cells: [ - MyDataCell( - new Text(dateFormatter.format(p.date), style: textStyle), - ), - MyDataCell(NumberCell(p.amount)), - ], - ); - - return r; - }).toList(); - } -} diff --git a/lib/charts/revenue_line_detail.dart b/lib/charts/revenue_line_detail.dart deleted file mode 100644 index 2f879e6..0000000 --- a/lib/charts/revenue_line_detail.dart +++ /dev/null @@ -1,106 +0,0 @@ -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/main_model.dart'; -import 'package:fcs/model/po_model.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/po.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/my_data_table.dart'; -import 'package:fcs/widget/number_cell.dart'; -import 'package:fcs/widget/progress.dart'; - -class RevenueLineDetail extends StatefulWidget { - final DateTime date; - const RevenueLineDetail(this.date); - @override - _RevenueLineDetailState createState() => _RevenueLineDetailState(); -} - -class _RevenueLineDetailState extends State { - final numberFormatter = new NumberFormat("#,###"); - var dateFormatter = new DateFormat('dd-MMM-yyyy'); - bool _isLoading = false; - List pos = []; - - @override - void initState() { - super.initState(); - POSubmissionModel pOModel = - Provider.of(context, listen: false); - pOModel.getPOForRevenue(widget.date).then((pos) { - if (mounted) { - setState(() { - this.pos = pos; - }); - } - }); - } - - @override - Widget build(BuildContext context) { - var mainModel = Provider.of(context); - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - title: mainModel.user.isOwnerAndAbove() - ? LocalText( - context, - 'revenue.detail.title', - translationVariables: [dateFormatter.format(widget.date)], - color: Colors.white, - fontSize: 18, - ) - : LocalText( - context, - 'spending.detail.title', - translationVariables: [dateFormatter.format(widget.date)], - color: Colors.white, - fontSize: 18, - ), - ), - body: Container( - padding: EdgeInsets.only(top: 5), - child: SingleChildScrollView( - scrollDirection: Axis.vertical, - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - padding: EdgeInsets.only(left: 3), - child: MyDataTable( - columnSpacing: 20, - columns: [ - MyDataColumn(label: LocalText(context, "po.name")), - MyDataColumn(label: LocalText(context, "po.po_num")), - MyDataColumn( - label: LocalText(context, "po.amount"), numeric: true), - ], - rows: getProductRow(), - ), - ), - ), - ), - ), - ); - } - - List getProductRow() { - return pos.map((p) { - var r = MyDataRow( - cells: [ - MyDataCell( - new Text(p.userName, style: textStyle), - ), - MyDataCell( - new Text(p.poNumber, style: textStyle), - ), - MyDataCell(NumberCell(p.amount)), - ], - ); - - return r; - }).toList(); - } -} diff --git a/lib/charts/time.dart b/lib/charts/time.dart deleted file mode 100644 index a7f7ef3..0000000 --- a/lib/charts/time.dart +++ /dev/null @@ -1,60 +0,0 @@ -/// Timeseries chart example -import 'package:charts_flutter/flutter.dart' as charts; -import 'package:flutter/material.dart'; - -class SimpleTimeSeriesChart extends StatelessWidget { - final List seriesList; - final bool animate; - - SimpleTimeSeriesChart(this.seriesList, {this.animate}); - - /// Creates a [TimeSeriesChart] with sample data and no transition. - factory SimpleTimeSeriesChart.withSampleData() { - return new SimpleTimeSeriesChart( - _createSampleData(), - // Disable animations for image tests. - animate: false, - ); - } - - - @override - Widget build(BuildContext context) { - return new charts.TimeSeriesChart( - seriesList, - animate: animate, - // Optionally pass in a [DateTimeFactory] used by the chart. The factory - // should create the same type of [DateTime] as the data provided. If none - // specified, the default creates local date time. - dateTimeFactory: const charts.LocalDateTimeFactory(), - ); - } - - /// Create one series with sample hard coded data. - static List> _createSampleData() { - final data = [ - new TimeSeriesSales(new DateTime(2017, 9, 19), 5), - new TimeSeriesSales(new DateTime(2017, 9, 26), 25), - new TimeSeriesSales(new DateTime(2017, 10, 3), 100), - new TimeSeriesSales(new DateTime(2017, 10, 10), 75), - ]; - - return [ - new charts.Series( - id: 'Sales', - colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault, - domainFn: (TimeSeriesSales sales, _) => sales.time, - measureFn: (TimeSeriesSales sales, _) => sales.sales, - data: data, - ) - ]; - } -} - -/// Sample time series data type. -class TimeSeriesSales { - final DateTime time; - final int sales; - - TimeSeriesSales(this.time, this.sales); -} diff --git a/lib/fcs/common/data/providers/auth_fb.dart b/lib/data/provider/auth_fb.dart similarity index 62% rename from lib/fcs/common/data/providers/auth_fb.dart rename to lib/data/provider/auth_fb.dart index f2635fc..1eaa500 100644 --- a/lib/fcs/common/data/providers/auth_fb.dart +++ b/lib/data/provider/auth_fb.dart @@ -1,23 +1,24 @@ import 'dart:async'; import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:fcs/fcs/common/domain/constants.dart'; -import 'package:fcs/fcs/common/domain/entities/auth_result.dart' as fcs; -import 'package:fcs/fcs/common/domain/entities/auth_status.dart'; -import 'package:fcs/fcs/common/domain/entities/setting.dart'; -import 'package:fcs/fcs/common/domain/entities/user.dart'; -import 'package:fcs/fcs/common/domain/exceiptions/signin_exception.dart'; +import 'package:fcs/domain/constants.dart'; +import 'package:fcs/domain/entities/auth_result.dart' as fcs; +import 'package:fcs/domain/entities/auth_status.dart'; +import 'package:fcs/domain/entities/setting.dart'; +import 'package:fcs/domain/entities/user.dart'; +import 'package:fcs/domain/exceiptions/signin_exception.dart'; +import 'package:fcs/helpers/api_helper.dart'; +import 'package:fcs/helpers/firebase_helper.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:logging/logging.dart'; -import '../../helpers/api_helper.dart'; - class AuthFb { final log = Logger('AuthFb'); static final AuthFb instance = AuthFb._(); AuthFb._(); + StreamController controller; static final FirebaseAuth _fb = FirebaseAuth.instance; static String _verificationId; @@ -97,6 +98,7 @@ class AuthFb { if (_authResult == null) { throw SigninException("Sigin error!"); } + await _addUserToStream(refreshIdToken: true); } on Exception catch (e) { return Future.error(SigninException(e.toString())); } @@ -104,49 +106,39 @@ class AuthFb { return Future.value(fcs.AuthResult(authStatus: AuthStatus.AUTH_VERIFIED)); } - Future signout() { + Future signout() async { + if (userListener != null) await userListener.cancel(); return _fb.signOut(); } - Stream get onAuthStatus async* { - await for (FirebaseUser firebaseUser in _fb.onAuthStateChanged) { - if (firebaseUser == null) { - yield null; - } - yield await getUser(); - } - } - - Future getUser({bool refreshIdToken = false}) async { + Future _addUserToStream({bool refreshIdToken = false}) async { FirebaseUser firebaseUser = await _fb.currentUser(); if (firebaseUser == null) return null; - IdTokenResult idToken = - await firebaseUser.getIdToken(refresh: refreshIdToken); + Map claims = await getClaims(refreshIdToken: refreshIdToken); - log.info("Claims:${idToken.claims}"); + log.info("Claims:$claims"); - String cid = idToken.claims["cid"]; + String cid = claims["cid"]; User user; if (cid != null && cid != "") { - user = await getUserFromFirestore(cid); + user = await _getUserFromFirestore(cid); } if (user == null) { - user = User(); - user.id = cid; - user.phoneNumber = firebaseUser.phoneNumber; - user.status = idToken.claims["st"]; + controller.add(null); + return; } // add privileges - String privileges = idToken.claims["pr"]; + String privileges = claims["pr"]; if (privileges != null && privileges != "") { user.privileges = privileges.split(":").toList(); + } else { + user.privileges = []; } - - return user; + controller.add(user); } - Future getUserFromFirestore(String userID) async { + Future _getUserFromFirestore(String userID) async { DocumentSnapshot snap = await Firestore.instance .collection(user_collection) .document(userID) @@ -163,24 +155,27 @@ class AuthFb { return Future.value(firebaseUser != null); } - Future signup(String userName) async { + Future signup(String userName) async { await requestAPI("/signup", "POST", payload: { 'user_name': userName, }, token: await getToken()); - // refresh token once signup - return getUser(refreshIdToken: true); + await _addUserToStream(refreshIdToken: true); + _startUserListener(); + return; } - Future joinInvite(String userName) async { + Future joinInvite(String userName) async { await requestAPI("/join_invite", "POST", payload: { 'user_name': userName, }, token: await getToken()); // refresh token once signup - return getUser(refreshIdToken: true); + await _addUserToStream(refreshIdToken: true); + _startUserListener(); + return; } Future hasInvite() async { @@ -189,27 +184,14 @@ class AuthFb { return invited["invited"]; } - Future updateProfile(String newUserName) async { + Future updateProfileName(String newUserName) async { return await requestAPI("/profile", "PUT", payload: {"user_name": newUserName}, token: await getToken()); } - Future getToken() async { - FirebaseUser firebaseUser = await _fb.currentUser(); - IdTokenResult token = await firebaseUser.getIdToken(); - return token.token; - } - - Future getSetting() async { - var snap = await Firestore.instance - .collection(config_collection) - .document(setting_doc_id) - .get(); - if (!snap.exists) { - return null; - } - // _listSetting(); - return Setting.fromMap(snap.data); + Future updatePreferredCurrency(String currency) async { + return await requestAPI("/currency", "PUT", + payload: {"preferred_currency": currency}, token: await getToken()); } Stream settings() async* { @@ -224,16 +206,75 @@ class AuthFb { } } - Stream user(String userID) async* { + Future _getCurrentUserID() async { + FirebaseUser firebaseUser = await _fb.currentUser(); + if (firebaseUser == null) return null; + Map claims = await getClaims(); + String cid = claims["cid"]; + return cid; + } + + Future _startUserListener() async { + if (userListener != null) userListener.cancel(); + String _userID = await _getCurrentUserID(); + if (_userID == null) { + return; + } + Stream snapshot = Firestore.instance .collection(user_collection) - .document(userID) + .document(_userID) .snapshots(); - - await for (var snap in snapshot) { + userListener = snapshot.listen((snap) async { User user = User.fromMap(snap.data, snap.documentID); - user = await getUser(refreshIdToken: true); - yield user; + + FirebaseUser firebaseUser = await _fb.currentUser(); + if (firebaseUser == null) { + userListener.cancel(); + return; + } + try { + // get privilege from claim + IdTokenResult idToken = await firebaseUser.getIdToken(refresh: true); + String privileges = idToken.claims["pr"]; + if (privileges != null && privileges != "") { + user.privileges = privileges.split(":").toList(); + } + controller.add(user); + } catch (e) { + controller.add(null); + } + }); + } + + StreamSubscription userListener; + Stream user() { + // ignore: close_sinks + StreamSubscription authListener; + + Future _start() async { + authListener = _fb.onAuthStateChanged.listen((firebaseUser) async { + if (firebaseUser == null) { + controller.add(null); + } else { + _addUserToStream(refreshIdToken: true); + _startUserListener(); + } + }); } + + void _stop() { + if (userListener != null) { + userListener.cancel(); + } + if (authListener != null) { + authListener.cancel(); + } + } + + controller = StreamController( + onListen: _start, onPause: _stop, onResume: _start, onCancel: _stop); + + return controller.stream; } } diff --git a/lib/data/provider/carton_data_provider.dart b/lib/data/provider/carton_data_provider.dart new file mode 100644 index 0000000..f2457f5 --- /dev/null +++ b/lib/data/provider/carton_data_provider.dart @@ -0,0 +1,33 @@ +import 'dart:async'; + +import 'package:fcs/domain/entities/carton.dart'; +import 'package:fcs/helpers/api_helper.dart'; +import 'package:fcs/helpers/firebase_helper.dart'; +import 'package:logging/logging.dart'; + +class CartonDataProvider { + final log = Logger('CartonDataProvider'); + + static final CartonDataProvider instance = CartonDataProvider._(); + CartonDataProvider._(); + + Future createCarton(Carton carton) async { + return await requestAPI("/cartons", "POST", + payload: carton.toMap(), token: await getToken()); + } + + Future updateCarton(Carton carton) async { + return await requestAPI("/cartons", "PUT", + payload: carton.toMap(), token: await getToken()); + } + + Future deleteCarton(Carton carton) async { + return await requestAPI("/cartons", "DELETE", + payload: carton.toMap(), token: await getToken()); + } + + Future deliver(Carton carton) async { + return await requestAPI("/cartons/deliver", "PUT", + payload: carton.toMap(), token: await getToken()); + } +} diff --git a/lib/fcs/common/data/providers/common_data_provider.dart b/lib/data/provider/common_data_provider.dart similarity index 58% rename from lib/fcs/common/data/providers/common_data_provider.dart rename to lib/data/provider/common_data_provider.dart index 670ef50..5ca1f08 100644 --- a/lib/fcs/common/data/providers/common_data_provider.dart +++ b/lib/data/provider/common_data_provider.dart @@ -1,7 +1,8 @@ -import 'package:fcs/fcs/common/domain/entities/payment_method.dart'; -import 'package:fcs/fcs/common/domain/vo/message.dart'; -import 'package:fcs/fcs/common/helpers/api_helper.dart'; -import 'package:fcs/fcs/common/helpers/firebase_helper.dart'; +import 'package:fcs/domain/entities/discount.dart'; +import 'package:fcs/domain/entities/payment_method.dart'; +import 'package:fcs/domain/vo/message.dart'; +import 'package:fcs/helpers/api_helper.dart'; +import 'package:fcs/helpers/firebase_helper.dart'; import 'package:logging/logging.dart'; class CommonDataProvider { @@ -32,4 +33,19 @@ class CommonDataProvider { payload: {"owner_id": ownerID, "seen_by_owner": seenByOwner}, token: await getToken()); } + + Future createDiscount(Discount discount) async { + return await requestAPI("/discounts", "POST", + payload: discount.toMap(), token: await getToken()); + } + + Future updateDiscount(Discount discount) async { + return await requestAPI("/discounts", "PUT", + payload: discount.toMap(), token: await getToken()); + } + + Future deleteDiscount(String id) async { + return await requestAPI("/discounts", "DELETE", + payload: {"id": id}, token: await getToken()); + } } diff --git a/lib/data/provider/delivery_address_data_provider.dart b/lib/data/provider/delivery_address_data_provider.dart new file mode 100644 index 0000000..70e620b --- /dev/null +++ b/lib/data/provider/delivery_address_data_provider.dart @@ -0,0 +1,30 @@ +import 'package:fcs/domain/entities/fcs_shipment.dart'; +import 'package:fcs/domain/vo/delivery_address.dart'; +import 'package:fcs/helpers/api_helper.dart'; +import 'package:fcs/helpers/firebase_helper.dart'; +import 'package:logging/logging.dart'; + +class DeliveryAddressDataProvider { + final log = Logger('DeliveryAddressDataProvider'); + + Future createDeliveryAddress(DeliveryAddress deliveryAddress) async { + return await requestAPI("/delivery_address", "POST", + payload: deliveryAddress.toMap(), token: await getToken()); + } + + Future updateDeliveryAddress(DeliveryAddress deliveryAddress) async { + return await requestAPI("/delivery_address", "PUT", + payload: deliveryAddress.toMap(), token: await getToken()); + } + + Future deleteDeliveryAddress(DeliveryAddress deliveryAddress) async { + return await requestAPI("/delivery_address", "DELETE", + payload: deliveryAddress.toMap(), token: await getToken()); + } + + Future selectDefalutDeliveryAddress( + DeliveryAddress deliveryAddress) async { + return await requestAPI("/delivery_address/defalut", "PUT", + payload: deliveryAddress.toMap(), token: await getToken()); + } +} diff --git a/lib/data/provider/fcs_shipment_data_provider.dart b/lib/data/provider/fcs_shipment_data_provider.dart new file mode 100644 index 0000000..530a85d --- /dev/null +++ b/lib/data/provider/fcs_shipment_data_provider.dart @@ -0,0 +1,28 @@ +import 'package:fcs/domain/entities/fcs_shipment.dart'; +import 'package:fcs/helpers/api_helper.dart'; +import 'package:fcs/helpers/firebase_helper.dart'; +import 'package:logging/logging.dart'; + +class FcsShipmentDataProvider { + final log = Logger('FcsShipmentDataProvider'); + + Future createFcsShipment(FcsShipment fcsShipment) async { + return await requestAPI("/fcs_shipments", "POST", + payload: fcsShipment.toMap(), token: await getToken()); + } + + Future updateFcsShipment(FcsShipment fcsShipment) async { + return await requestAPI("/fcs_shipments", "PUT", + payload: fcsShipment.toMap(), token: await getToken()); + } + + Future deleteFcsShipment(FcsShipment fcsShipment) async { + return await requestAPI("/fcs_shipments", "DELETE", + payload: fcsShipment.toMap(), token: await getToken()); + } + + Future ship(FcsShipment fcsShipment) async { + return await requestAPI("/fcs_shipments/ship", "PUT", + payload: fcsShipment.toMap(), token: await getToken()); + } +} diff --git a/lib/data/provider/invoice_data_provider.dart b/lib/data/provider/invoice_data_provider.dart new file mode 100644 index 0000000..1afee73 --- /dev/null +++ b/lib/data/provider/invoice_data_provider.dart @@ -0,0 +1,25 @@ +import 'package:fcs/domain/entities/invoice.dart'; +import 'package:fcs/helpers/api_helper.dart'; +import 'package:fcs/helpers/firebase_helper.dart'; +import 'package:logging/logging.dart'; + +class InvoiceDataProvider { + final log = Logger('InvoiceDataProvider'); + static final InvoiceDataProvider instance = InvoiceDataProvider._(); + InvoiceDataProvider._(); + + Future createInvoice(Invoice invoice) async { + return await requestAPI("/invoices", "POST", + payload: invoice.toMap(), token: await getToken()); + } + + Future updateInvoice(Invoice invoice) async { + return await requestAPI("/invoices", "PUT", + payload: invoice.toMap(), token: await getToken()); + } + + Future cancelInvoice(Invoice invoice) async { + return await requestAPI("/invoices/cancel", "PUT", + payload: {"id": invoice.id}, token: await getToken()); + } +} diff --git a/lib/fcs/common/data/providers/messaging_fcm.dart b/lib/data/provider/messaging_fcm.dart similarity index 97% rename from lib/fcs/common/data/providers/messaging_fcm.dart rename to lib/data/provider/messaging_fcm.dart index 76b1e46..a184004 100644 --- a/lib/fcs/common/data/providers/messaging_fcm.dart +++ b/lib/data/provider/messaging_fcm.dart @@ -1,6 +1,6 @@ import 'dart:io'; -import 'package:fcs/fcs/common/services/messaging_service.dart'; +import 'package:fcs/data/services/messaging_service.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:logging/logging.dart'; diff --git a/lib/data/provider/package_data_provider.dart b/lib/data/provider/package_data_provider.dart new file mode 100644 index 0000000..9ac88fe --- /dev/null +++ b/lib/data/provider/package_data_provider.dart @@ -0,0 +1,87 @@ +import 'dart:convert'; + +import 'package:fcs/config.dart'; +import 'package:fcs/domain/constants.dart'; +import 'package:fcs/domain/entities/package.dart'; +import 'package:fcs/helpers/api_helper.dart'; +import 'package:fcs/helpers/firebase_helper.dart'; +import 'package:logging/logging.dart'; + +class PackageDataProvider { + final log = Logger('PackageDataProvider'); + + Future createPackages(List packages, String fcsID) async { + List> json = packages.map((e) => e.toJson()).toList(); + return await requestAPI("/packages", "POST", + payload: {"packages": json, "fcs_id": fcsID}, token: await getToken()); + } + + Future createReceiving(Package package) async { + return await requestAPI("/receiving", "POST", + payload: package.toJson(), token: await getToken()); + } + + Future updateReceiving(Package package) async { + return await requestAPI("/receiving", "PUT", + payload: package.toJson(), token: await getToken()); + } + + Future deleteReceiving(Package package) async { + return await requestAPI("/receiving", "DELETE", + payload: {"id": package.id}, token: await getToken()); + } + + Future updateProcessing(Package package) async { + return await requestAPI("/processing", "PUT", + payload: package.toJson(), token: await getToken()); + } + + Future deleteProcessing(Package package) async { + return await requestAPI("/processing", "DELETE", + payload: {"id": package.id}, token: await getToken()); + } + + Future changeDeliveryAddress( + String packageID, String deliveryID) async { + return await requestAPI("/packages/change_delivery_address", "PUT", + payload: {"package_id": packageID, "deliver_address_id": deliveryID}, + token: await getToken()); + } + + Future packageReturn(String packageID) async { + return await requestAPI("/packages/return", "PUT", + payload: { + "id": packageID, + }, + token: await getToken()); + } + + Future> searchPackage(String term) async { + if (term == null || term == '') return List(); + + var bytes = utf8.encode(term); + var base64Str = base64.encode(bytes); + HtmlEscape htmlEscape = const HtmlEscape(); + String escapePackage = htmlEscape.convert(base64Str); + + int limit = 20; + List packages = []; + + try { + var data = await requestAPI( + "/api/fts/$packages_collection/$escapePackage/$limit", "GET", + url: Config.instance.reportURL, token: await getToken()); + + if (data == null) return List(); + + data.forEach((p) { + var package = Package.fromJson(p); + packages.add(package); + }); + } catch (e) { + log.warning("buyer error:" + e.toString()); + return null; + } + return packages; + } +} diff --git a/lib/data/provider/rate_data_provider.dart b/lib/data/provider/rate_data_provider.dart new file mode 100644 index 0000000..7d0529d --- /dev/null +++ b/lib/data/provider/rate_data_provider.dart @@ -0,0 +1,181 @@ +import 'dart:async'; + +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:fcs/domain/constants.dart'; +import 'package:fcs/domain/entities/cargo_type.dart'; +import 'package:fcs/domain/entities/custom_duty.dart'; +import 'package:fcs/domain/entities/discount_by_weight.dart'; +import 'package:fcs/domain/entities/rate.dart'; +import 'package:fcs/helpers/api_helper.dart'; +import 'package:fcs/helpers/firebase_helper.dart'; +import 'package:logging/logging.dart'; + +class RateDataProvider { + final log = Logger('RateDataProvider'); + + static final RateDataProvider instance = RateDataProvider._(); + RateDataProvider._(); + + StreamController controller; + static Rate _rate = Rate(); + + Stream _rateStream() async* { + Stream snapshot = Firestore.instance + .collection(config_collection) + .document(rate_doc_id) + .snapshots(); + await for (var snap in snapshot) { + Rate rate = Rate.fromMap(snap.data); + yield rate; + } + } + + Stream> _cargoTypeStream() async* { + List cargoTypes = []; + Stream snapshots = Firestore.instance + .collection(config_collection) + .document(rate_doc_id) + .collection(cargo_types_collection) + .snapshots(); + + await for (var snaps in snapshots) { + cargoTypes = []; + cargoTypes = snaps.documents.map((snap) { + return CargoType.fromMap(snap.data, snap.documentID); + }).toList(); + + yield cargoTypes; + } + } + + Stream> _customDutiesStream() async* { + List customDuries = []; + Stream snapshots = Firestore.instance + .collection(config_collection) + .document(rate_doc_id) + .collection(custom_duties_collection) + .snapshots(); + + await for (var snaps in snapshots) { + customDuries = []; + customDuries = snaps.documents.map((snap) { + return CustomDuty.fromMap(snap.data, snap.documentID); + }).toList(); + yield customDuries; + } + } + + Stream> _discountByWeightStream() async* { + List discountByWeight = []; + Stream snapshots = Firestore.instance + .collection(config_collection) + .document(rate_doc_id) + .collection(discounts_by_weights_collection) + .snapshots(); + + await for (var snaps in snapshots) { + discountByWeight = []; + discountByWeight = snaps.documents.map((snap) { + return DiscountByWeight.fromMap(snap.data, snap.documentID); + }).toList(); + yield discountByWeight; + } + } + + StreamSubscription rateListener; + StreamSubscription> cargoListener; + StreamSubscription> customListener; + StreamSubscription> discountListener; + Stream rate() { + Future _start() async { + rateListener = _rateStream().listen((rate) { + _rate.deliveryFee = rate.deliveryFee; + _rate.freeDeliveryWeight = rate.freeDeliveryWeight; + _rate.volumetricRatio = rate.volumetricRatio; + controller.add(_rate); + }); + cargoListener = _cargoTypeStream().listen((cargoTypes) { + _rate.cargoTypes = cargoTypes; + controller.add(_rate); + }); + customListener = _customDutiesStream().listen((customDuties) { + _rate.customDuties = customDuties; + controller.add(_rate); + }); + discountListener = _discountByWeightStream().listen((discountByWeights) { + _rate.discountByWeights = discountByWeights; + controller.add(_rate); + }); + } + + void _stop() { + if (rateListener != null) { + rateListener.cancel(); + } + if (cargoListener != null) { + cargoListener.cancel(); + } + if (customListener != null) { + customListener.cancel(); + } + if (discountListener != null) { + discountListener.cancel(); + } + } + + controller = StreamController( + onListen: _start, onPause: _stop, onResume: _start, onCancel: _stop); + + return controller.stream; + } + + Future updateRates(Rate rate) async { + return await requestAPI("/rates", "PUT", + payload: rate.toMap(), token: await getToken()); + } + + Future createCargoType(CargoType cargoType) async { + return await requestAPI("/cargo_types", "POST", + payload: cargoType.toMap(), token: await getToken()); + } + + Future updateCargoType(CargoType cargoType) async { + return await requestAPI("/cargo_types", "PUT", + payload: cargoType.toMap(), token: await getToken()); + } + + Future deleteCargoType(String id) async { + return await requestAPI("/cargo_types", "DELETE", + payload: {"id": id}, token: await getToken()); + } + + Future createCustomDuty(CustomDuty customDuty) async { + return await requestAPI("/custom_duties", "POST", + payload: customDuty.toMap(), token: await getToken()); + } + + Future updateCustomDuty(CustomDuty customDuty) async { + return await requestAPI("/custom_duties", "PUT", + payload: customDuty.toMap(), token: await getToken()); + } + + Future deleteCustomDuty(String id) async { + return await requestAPI("/custom_duties", "DELETE", + payload: {"id": id}, token: await getToken()); + } + + Future createDiscountByWeight(DiscountByWeight discountByWeight) async { + return await requestAPI("/discounts_by_weight", "POST", + payload: discountByWeight.toMap(), token: await getToken()); + } + + Future updateDiscountByWeight(DiscountByWeight discountByWeight) async { + return await requestAPI("/discounts_by_weight", "PUT", + payload: discountByWeight.toMap(), token: await getToken()); + } + + Future deleteDiscountByWeight(String id) async { + return await requestAPI("/discounts_by_weight", "DELETE", + payload: {"id": id}, token: await getToken()); + } +} diff --git a/lib/data/provider/shipment_data_provider.dart b/lib/data/provider/shipment_data_provider.dart new file mode 100644 index 0000000..44479e3 --- /dev/null +++ b/lib/data/provider/shipment_data_provider.dart @@ -0,0 +1,78 @@ +import 'dart:async'; + +import 'package:fcs/domain/entities/shipment.dart'; +import 'package:fcs/helpers/api_helper.dart'; +import 'package:fcs/helpers/firebase_helper.dart'; +import 'package:logging/logging.dart'; + +class ShipmentDataProvider { + final log = Logger('ShipmentDataProvider'); + + static final ShipmentDataProvider instance = ShipmentDataProvider._(); + ShipmentDataProvider._(); + + Future createShipment(Shipment shipment) async { + return await requestAPI("/shipments", "POST", + payload: shipment.toMap(), token: await getToken()); + } + + Future updateShipment(Shipment shipment) async { + return await requestAPI("/shipments", "PUT", + payload: shipment.toMap(), token: await getToken()); + } + + Future cancelShipment(Shipment shipment) async { + return await requestAPI("/shipments/cancel", "PUT", + payload: shipment.toMap(), token: await getToken()); + } + + Future assignShipment(Shipment shipment) async { + return await requestAPI("/shipments/assign", "PUT", + payload: shipment.toMap(), token: await getToken()); + } + + Future completeAssignShipment(Shipment shipment) async { + return await requestAPI("/shipments/assign/complete", "PUT", + payload: shipment.toMap(), token: await getToken()); + } + + Future completePickupShipment(Shipment shipment) async { + return await requestAPI("/shipments/pickup/complete", "PUT", + payload: shipment.toMap(), token: await getToken()); + } + + Future packShipment(Shipment shipment) async { + return await requestAPI("/shipments/pack", "PUT", + payload: shipment.toMap(), token: await getToken()); + } + + Future completePackShipment(Shipment shipment) async { + return await requestAPI("/shipments/pack/complete", "PUT", + payload: shipment.toMap(), token: await getToken()); + } + + Future confirmShipment(Shipment shipment) async { + return await requestAPI("/shipments/confirm", "PUT", + payload: shipment.toMap(), token: await getToken()); + } + + Future completeConfirmShipment(Shipment shipment) async { + return await requestAPI("/shipments/confirm/complete", "PUT", + payload: shipment.toMap(), token: await getToken()); + } + + Future completeReceiveShipment(Shipment shipment) async { + return await requestAPI("/shipments/receive/complete", "PUT", + payload: shipment.toMap(), token: await getToken()); + } + + Future pickupShipment(Shipment shipment) async { + return await requestAPI("/shipment_pickup", "PUT", + payload: shipment.toMap(), token: await getToken()); + } + + Future receiveShipment(Shipment shipment) async { + return await requestAPI("/shipment_receive", "PUT", + payload: shipment.toMap(), token: await getToken()); + } +} diff --git a/lib/fcs/common/data/providers/user_data_provider.dart b/lib/data/provider/user_data_provider.dart similarity index 85% rename from lib/fcs/common/data/providers/user_data_provider.dart rename to lib/data/provider/user_data_provider.dart index 78261bc..99ec833 100644 --- a/lib/fcs/common/data/providers/user_data_provider.dart +++ b/lib/data/provider/user_data_provider.dart @@ -2,10 +2,10 @@ import 'dart:convert'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:fcs/config.dart'; -import 'package:fcs/fcs/common/domain/constants.dart'; -import 'package:fcs/fcs/common/domain/entities/user.dart'; -import 'package:fcs/fcs/common/helpers/api_helper.dart'; -import 'package:fcs/fcs/common/helpers/firebase_helper.dart'; +import 'package:fcs/domain/constants.dart'; +import 'package:fcs/domain/entities/user.dart'; +import 'package:fcs/helpers/api_helper.dart'; +import 'package:fcs/helpers/firebase_helper.dart'; import 'package:logging/logging.dart'; class UserDataProvider { @@ -80,4 +80,9 @@ class UserDataProvider { } return users; } + + Future enableUser(String userID, bool enabled) async { + return await requestAPI("/enable_user", "PUT", + payload: {"id": userID, "enabled": enabled}, token: await getToken()); + } } diff --git a/lib/data/services/auth_imp.dart b/lib/data/services/auth_imp.dart new file mode 100644 index 0000000..05b36ec --- /dev/null +++ b/lib/data/services/auth_imp.dart @@ -0,0 +1,68 @@ +import 'package:fcs/data/provider/auth_fb.dart'; +import 'package:fcs/domain/entities/auth_result.dart'; +import 'package:fcs/domain/entities/connectivity.dart'; +import 'package:fcs/domain/entities/setting.dart'; +import 'package:fcs/domain/entities/user.dart'; +import 'package:flutter/material.dart'; + +import 'auth_service.dart'; + +class AuthServiceImp implements AuthService { + AuthServiceImp({ + @required this.authFb, + @required this.connectivity, + }); + + final Connectivity connectivity; + final AuthFb authFb; + + @override + Future sendSmsCodeToPhoneNumber(String phoneNumber) { + return authFb.sendSmsCodeToPhoneNumber(phoneNumber); + } + + @override + Future signInWithSmsCode(String smsCode) { + return authFb.signInWithPhoneNumber(smsCode); + } + + @override + Future signout() { + return authFb.signout(); + } + + @override + Stream getUserStream() { + return authFb.user(); + } + + @override + Stream getSetting() { + return authFb.settings(); + } + + @override + Future signup(String userName) { + return authFb.signup(userName); + } + + @override + Future joinInvite(String userName) { + return authFb.joinInvite(userName); + } + + @override + Future hasInvite() { + return authFb.hasInvite(); + } + + @override + Future updateProfileName(String newUserName) { + return authFb.updateProfileName(newUserName); + } + + @override + Future updatePreferredCurrency(String currency) { + return authFb.updatePreferredCurrency(currency); + } +} diff --git a/lib/data/services/auth_service.dart b/lib/data/services/auth_service.dart new file mode 100644 index 0000000..dad8ce7 --- /dev/null +++ b/lib/data/services/auth_service.dart @@ -0,0 +1,16 @@ +import 'package:fcs/domain/entities/auth_result.dart'; +import 'package:fcs/domain/entities/setting.dart'; +import 'package:fcs/domain/entities/user.dart'; + +abstract class AuthService { + Future sendSmsCodeToPhoneNumber(String phoneNumber); + Future signInWithSmsCode(String smsCode); + Future signout(); + Future signup(String userName); + Future joinInvite(String userName); + Future updateProfileName(String newUserName); + Future updatePreferredCurrency(String currency); + Future hasInvite(); + Stream getUserStream(); + Stream getSetting(); +} diff --git a/lib/data/services/carton_imp.dart b/lib/data/services/carton_imp.dart new file mode 100644 index 0000000..6eef25d --- /dev/null +++ b/lib/data/services/carton_imp.dart @@ -0,0 +1,36 @@ +import 'package:fcs/data/provider/carton_data_provider.dart'; +import 'package:fcs/domain/entities/carton.dart'; +import 'package:fcs/domain/entities/connectivity.dart'; +import 'package:flutter/material.dart'; + +import 'carton_service.dart'; + +class CartonServiceImp implements CartonService { + CartonServiceImp({ + @required this.cartonDataProvider, + @required this.connectivity, + }); + + final Connectivity connectivity; + final CartonDataProvider cartonDataProvider; + + @override + Future createCarton(Carton carton) { + return cartonDataProvider.createCarton(carton); + } + + @override + Future deleteCarton(Carton carton) { + return cartonDataProvider.deleteCarton(carton); + } + + @override + Future updateCarton(Carton carton) { + return cartonDataProvider.updateCarton(carton); + } + + @override + Future deliver(Carton carton) { + return cartonDataProvider.deliver(carton); + } +} diff --git a/lib/data/services/carton_service.dart b/lib/data/services/carton_service.dart new file mode 100644 index 0000000..45dde91 --- /dev/null +++ b/lib/data/services/carton_service.dart @@ -0,0 +1,8 @@ +import 'package:fcs/domain/entities/carton.dart'; + +abstract class CartonService { + Future createCarton(Carton carton); + Future updateCarton(Carton carton); + Future deleteCarton(Carton carton); + Future deliver(Carton carton); +} diff --git a/lib/fcs/common/services/common_imp.dart b/lib/data/services/common_imp.dart similarity index 61% rename from lib/fcs/common/services/common_imp.dart rename to lib/data/services/common_imp.dart index c420f02..74e0654 100644 --- a/lib/fcs/common/services/common_imp.dart +++ b/lib/data/services/common_imp.dart @@ -1,7 +1,7 @@ -import 'package:fcs/fcs/common/data/providers/common_data_provider.dart'; -import 'package:fcs/fcs/common/data/providers/user_data_provider.dart'; -import 'package:fcs/fcs/common/domain/entities/payment_method.dart'; -import 'package:fcs/fcs/common/domain/vo/message.dart'; +import 'package:fcs/data/provider/common_data_provider.dart'; +import 'package:fcs/domain/entities/discount.dart'; +import 'package:fcs/domain/entities/payment_method.dart'; +import 'package:fcs/domain/vo/message.dart'; import 'package:flutter/material.dart'; import 'common_service.dart'; @@ -37,4 +37,19 @@ class CommonServiceImp implements CommonService { Future seenMessage(String ownerID, bool seenByOwner) { return commonDataProvider.seenMessage(ownerID, seenByOwner); } + + @override + Future createDiscount(Discount discount) { + return commonDataProvider.createDiscount(discount); + } + + @override + Future deleteDiscount(String id) { + return commonDataProvider.deleteDiscount(id); + } + + @override + Future updateDiscount(Discount discount) { + return commonDataProvider.updateDiscount(discount); + } } diff --git a/lib/fcs/common/services/common_service.dart b/lib/data/services/common_service.dart similarity index 52% rename from lib/fcs/common/services/common_service.dart rename to lib/data/services/common_service.dart index b321ed7..9fe75e9 100644 --- a/lib/fcs/common/services/common_service.dart +++ b/lib/data/services/common_service.dart @@ -1,5 +1,6 @@ -import 'package:fcs/fcs/common/domain/entities/payment_method.dart'; -import 'package:fcs/fcs/common/domain/vo/message.dart'; +import 'package:fcs/domain/entities/discount.dart'; +import 'package:fcs/domain/entities/payment_method.dart'; +import 'package:fcs/domain/vo/message.dart'; abstract class CommonService { // Payment @@ -10,4 +11,9 @@ abstract class CommonService { // Messaging Future sendMessage(Message message); Future seenMessage(String ownerID, bool seenByOwner); + + // Payment + Future createDiscount(Discount discount); + Future updateDiscount(Discount discount); + Future deleteDiscount(String id); } diff --git a/lib/data/services/delivery_address_imp.dart b/lib/data/services/delivery_address_imp.dart new file mode 100644 index 0000000..96d8a36 --- /dev/null +++ b/lib/data/services/delivery_address_imp.dart @@ -0,0 +1,37 @@ +import 'package:fcs/data/provider/delivery_address_data_provider.dart'; +import 'package:fcs/domain/entities/connectivity.dart'; +import 'package:fcs/domain/vo/delivery_address.dart'; +import 'package:flutter/material.dart'; + +import 'delivery_address_service.dart'; + +class DeliveryAddressImp implements DeliveryAddressService { + DeliveryAddressImp({ + @required this.connectivity, + @required this.deliveryAddressDataProvider, + }); + + final Connectivity connectivity; + final DeliveryAddressDataProvider deliveryAddressDataProvider; + + @override + Future createDeliveryAddress(DeliveryAddress deliveryAddress) { + return deliveryAddressDataProvider.createDeliveryAddress(deliveryAddress); + } + + @override + Future updateDeliveryAddress(DeliveryAddress deliveryAddress) { + return deliveryAddressDataProvider.updateDeliveryAddress(deliveryAddress); + } + + @override + Future deleteDeliveryAddress(DeliveryAddress deliveryAddress) { + return deliveryAddressDataProvider.deleteDeliveryAddress(deliveryAddress); + } + + @override + Future selectDefalutDeliveryAddress(DeliveryAddress deliveryAddress) { + return deliveryAddressDataProvider + .selectDefalutDeliveryAddress(deliveryAddress); + } +} diff --git a/lib/data/services/delivery_address_service.dart b/lib/data/services/delivery_address_service.dart new file mode 100644 index 0000000..e638daf --- /dev/null +++ b/lib/data/services/delivery_address_service.dart @@ -0,0 +1,8 @@ +import 'package:fcs/domain/vo/delivery_address.dart'; + +abstract class DeliveryAddressService { + Future createDeliveryAddress(DeliveryAddress deliveryAddress); + Future updateDeliveryAddress(DeliveryAddress deliveryAddress); + Future deleteDeliveryAddress(DeliveryAddress deliveryAddress); + Future selectDefalutDeliveryAddress(DeliveryAddress deliveryAddress); +} diff --git a/lib/data/services/fcs_shipment_imp.dart b/lib/data/services/fcs_shipment_imp.dart new file mode 100644 index 0000000..4eb5e94 --- /dev/null +++ b/lib/data/services/fcs_shipment_imp.dart @@ -0,0 +1,36 @@ +import 'package:fcs/data/provider/fcs_shipment_data_provider.dart'; +import 'package:fcs/domain/entities/connectivity.dart'; +import 'package:fcs/domain/entities/fcs_shipment.dart'; +import 'package:flutter/material.dart'; + +import 'fcs_shipment_service.dart'; + +class FcsShipmentServiceImp implements FcsShipmentService { + FcsShipmentServiceImp({ + @required this.connectivity, + @required this.shipmentDataProvider, + }); + + final Connectivity connectivity; + final FcsShipmentDataProvider shipmentDataProvider; + + @override + Future createFcsShipment(FcsShipment fcsShipment) { + return shipmentDataProvider.createFcsShipment(fcsShipment); + } + + @override + Future updateFcsShipment(FcsShipment fcsShipment) { + return shipmentDataProvider.updateFcsShipment(fcsShipment); + } + + @override + Future deleteFcsShipment(FcsShipment fcsShipment) { + return shipmentDataProvider.deleteFcsShipment(fcsShipment); + } + + @override + Future ship(FcsShipment fcsShipment) { + return shipmentDataProvider.ship(fcsShipment); + } +} diff --git a/lib/data/services/fcs_shipment_service.dart b/lib/data/services/fcs_shipment_service.dart new file mode 100644 index 0000000..46e4ba8 --- /dev/null +++ b/lib/data/services/fcs_shipment_service.dart @@ -0,0 +1,8 @@ +import 'package:fcs/domain/entities/fcs_shipment.dart'; + +abstract class FcsShipmentService { + Future createFcsShipment(FcsShipment fcsShipment); + Future updateFcsShipment(FcsShipment fcsShipment); + Future deleteFcsShipment(FcsShipment fcsShipment); + Future ship(FcsShipment fcsShipment); +} diff --git a/lib/data/services/invoice_imp.dart b/lib/data/services/invoice_imp.dart new file mode 100644 index 0000000..3fe5df1 --- /dev/null +++ b/lib/data/services/invoice_imp.dart @@ -0,0 +1,34 @@ +import 'package:fcs/data/provider/invoice_data_provider.dart'; +import 'package:fcs/data/provider/shipment_data_provider.dart'; +import 'package:fcs/data/services/shipment_service.dart'; +import 'package:fcs/domain/entities/connectivity.dart'; +import 'package:fcs/domain/entities/invoice.dart'; +import 'package:fcs/domain/entities/shipment.dart'; +import 'package:flutter/material.dart'; + +import 'invoice_service.dart'; + +class InvoiceServiceImp implements InvoiceService { + InvoiceServiceImp({ + @required this.invoiceDataProvider, + @required this.connectivity, + }); + + final Connectivity connectivity; + final InvoiceDataProvider invoiceDataProvider; + + @override + Future cancelInvoice(Invoice invoice) { + return invoiceDataProvider.cancelInvoice(invoice); + } + + @override + Future createInvoice(Invoice invoice) { + return invoiceDataProvider.createInvoice(invoice); + } + + @override + Future updateInvoice(Invoice invoice) { + return invoiceDataProvider.updateInvoice(invoice); + } +} diff --git a/lib/data/services/invoice_service.dart b/lib/data/services/invoice_service.dart new file mode 100644 index 0000000..feed4e2 --- /dev/null +++ b/lib/data/services/invoice_service.dart @@ -0,0 +1,8 @@ +import 'package:fcs/domain/entities/invoice.dart'; +import 'package:fcs/domain/entities/shipment.dart'; + +abstract class InvoiceService { + Future createInvoice(Invoice invoice); + Future updateInvoice(Invoice invoice); + Future cancelInvoice(Invoice invoice); +} diff --git a/lib/fcs/common/services/messaging_imp.dart b/lib/data/services/messaging_imp.dart similarity index 90% rename from lib/fcs/common/services/messaging_imp.dart rename to lib/data/services/messaging_imp.dart index 9951e84..ceb6e57 100644 --- a/lib/fcs/common/services/messaging_imp.dart +++ b/lib/data/services/messaging_imp.dart @@ -1,4 +1,4 @@ -import 'package:fcs/fcs/common/data/providers/messaging_fcm.dart'; +import 'package:fcs/data/provider/messaging_fcm.dart'; import 'messaging_service.dart'; diff --git a/lib/fcs/common/services/messaging_service.dart b/lib/data/services/messaging_service.dart similarity index 100% rename from lib/fcs/common/services/messaging_service.dart rename to lib/data/services/messaging_service.dart diff --git a/lib/data/services/package_imp.dart b/lib/data/services/package_imp.dart new file mode 100644 index 0000000..b18e0ea --- /dev/null +++ b/lib/data/services/package_imp.dart @@ -0,0 +1,61 @@ +import 'package:fcs/data/provider/package_data_provider.dart'; +import 'package:fcs/domain/entities/connectivity.dart'; +import 'package:fcs/domain/entities/package.dart'; +import 'package:flutter/material.dart'; + +import 'package_service.dart'; + +class PackageServiceImp implements PackageService { + PackageServiceImp({ + @required this.connectivity, + @required this.packageDataProvider, + }); + + final Connectivity connectivity; + final PackageDataProvider packageDataProvider; + + @override + Future createPackages(List packages, String fcsID) { + return packageDataProvider.createPackages(packages, fcsID); + } + + @override + Future createReceiving(Package package) { + return packageDataProvider.createReceiving(package); + } + + @override + Future updateReceiving(Package package) { + return packageDataProvider.updateReceiving(package); + } + + @override + Future> searchPackage(String term) { + return packageDataProvider.searchPackage(term); + } + + @override + Future deleteReceiving(Package package) { + return packageDataProvider.deleteReceiving(package); + } + + @override + Future updateProcessing(Package package) { + return packageDataProvider.updateProcessing(package); + } + + @override + Future deleteProcessing(Package package) { + return packageDataProvider.deleteProcessing(package); + } + + @override + Future changeDeliveryAddress(String packageID, String deliveryID) { + return packageDataProvider.changeDeliveryAddress(packageID, deliveryID); + } + + @override + Future packageReturn(String packageID) { + return packageDataProvider.packageReturn(packageID); + } +} diff --git a/lib/data/services/package_service.dart b/lib/data/services/package_service.dart new file mode 100644 index 0000000..85bf6c9 --- /dev/null +++ b/lib/data/services/package_service.dart @@ -0,0 +1,13 @@ +import 'package:fcs/domain/entities/package.dart'; + +abstract class PackageService { + Future createPackages(List packages, String fcsID); + Future createReceiving(Package package); + Future updateReceiving(Package package); + Future deleteReceiving(Package package); + Future updateProcessing(Package package); + Future deleteProcessing(Package package); + Future> searchPackage(String term); + Future changeDeliveryAddress(String packageID, String deliveryID); + Future packageReturn(String packageID); +} diff --git a/lib/data/services/rate_imp.dart b/lib/data/services/rate_imp.dart new file mode 100644 index 0000000..6bea2ee --- /dev/null +++ b/lib/data/services/rate_imp.dart @@ -0,0 +1,74 @@ +import 'package:fcs/data/provider/rate_data_provider.dart'; +import 'package:fcs/domain/entities/cargo_type.dart'; +import 'package:fcs/domain/entities/connectivity.dart'; +import 'package:fcs/domain/entities/discount_by_weight.dart'; +import 'package:fcs/domain/entities/custom_duty.dart'; +import 'package:fcs/domain/entities/rate.dart'; +import 'package:flutter/material.dart'; + +import 'rate_service.dart'; + +class RateServiceImp implements RateService { + RateServiceImp({ + @required this.rateDataProvider, + @required this.connectivity, + }); + + final Connectivity connectivity; + final RateDataProvider rateDataProvider; + + @override + Stream getRateStream() { + return rateDataProvider.rate(); + } + + @override + Future createCargoType(CargoType cargoType) { + return rateDataProvider.createCargoType(cargoType); + } + + @override + Future createCustomDuty(CustomDuty customDuty) { + return rateDataProvider.createCustomDuty(customDuty); + } + + @override + Future createDiscountByWeight(DiscountByWeight discountByWeight) { + return rateDataProvider.createDiscountByWeight(discountByWeight); + } + + @override + Future deleteCargoType(String id) { + return rateDataProvider.deleteCargoType(id); + } + + @override + Future deleteCustomDuty(String id) { + return rateDataProvider.deleteCustomDuty(id); + } + + @override + Future deleteDiscountByWeight(String id) { + return rateDataProvider.deleteDiscountByWeight(id); + } + + @override + Future updateCargoType(CargoType cargoType) { + return rateDataProvider.updateCargoType(cargoType); + } + + @override + Future updateCustomDuty(CustomDuty customDuty) { + return rateDataProvider.updateCustomDuty(customDuty); + } + + @override + Future updateDiscountByWeight(DiscountByWeight discountByWeight) { + return rateDataProvider.updateDiscountByWeight(discountByWeight); + } + + @override + Future updateRate(Rate rate) { + return rateDataProvider.updateRates(rate); + } +} diff --git a/lib/data/services/rate_service.dart b/lib/data/services/rate_service.dart new file mode 100644 index 0000000..98bf602 --- /dev/null +++ b/lib/data/services/rate_service.dart @@ -0,0 +1,22 @@ +import 'package:fcs/domain/entities/cargo_type.dart'; +import 'package:fcs/domain/entities/custom_duty.dart'; +import 'package:fcs/domain/entities/discount_by_weight.dart'; +import 'package:fcs/domain/entities/rate.dart'; + +abstract class RateService { + Stream getRateStream(); + + Future updateRate(Rate rate); + + Future createCargoType(CargoType cargoType); + Future updateCargoType(CargoType cargoType); + Future deleteCargoType(String id); + + Future createCustomDuty(CustomDuty customDuty); + Future updateCustomDuty(CustomDuty customDuty); + Future deleteCustomDuty(String id); + + Future createDiscountByWeight(DiscountByWeight discountByWeight); + Future updateDiscountByWeight(DiscountByWeight discountByWeight); + Future deleteDiscountByWeight(String id); +} diff --git a/lib/data/services/services.dart b/lib/data/services/services.dart new file mode 100644 index 0000000..aee169b --- /dev/null +++ b/lib/data/services/services.dart @@ -0,0 +1,87 @@ +import 'package:fcs/data/provider/auth_fb.dart'; +import 'package:fcs/data/provider/carton_data_provider.dart'; +import 'package:fcs/data/provider/common_data_provider.dart'; +import 'package:fcs/data/provider/delivery_address_data_provider.dart'; +import 'package:fcs/data/provider/fcs_shipment_data_provider.dart'; +import 'package:fcs/data/provider/invoice_data_provider.dart'; +import 'package:fcs/data/provider/package_data_provider.dart'; +import 'package:fcs/data/provider/rate_data_provider.dart'; +import 'package:fcs/data/provider/shipment_data_provider.dart'; +import 'package:fcs/data/provider/user_data_provider.dart'; +import 'package:fcs/data/services/carton_imp.dart'; +import 'package:fcs/data/services/carton_service.dart'; +import 'package:fcs/data/services/delivery_address_imp.dart'; +import 'package:fcs/data/services/delivery_address_service.dart'; +import 'package:fcs/data/services/fcs_shipment_imp.dart'; +import 'package:fcs/data/services/fcs_shipment_service.dart'; +import 'package:fcs/data/services/invoice_imp.dart'; +import 'package:fcs/data/services/invoice_service.dart'; +import 'package:fcs/data/services/rate_imp.dart'; +import 'package:fcs/data/services/rate_service.dart'; +import 'package:fcs/data/services/shipment_imp.dart'; +import 'package:fcs/data/services/shipment_service.dart'; + +import 'auth_imp.dart'; +import 'auth_service.dart'; +import 'common_imp.dart'; +import 'common_service.dart'; +import 'messaging_imp.dart'; +import 'messaging_service.dart'; +import 'package_imp.dart'; +import 'package_service.dart'; +import 'user_imp.dart'; +import 'user_service.dart'; + +class Services { + static final Services instance = Services._(); + + AuthService _authService; + UserService _userService; + PackageService _packageService; + MessagingService _messagingService; + CommonService _commonService; + FcsShipmentService _fcsShipmentService; + DeliveryAddressService _deliveryAddressService; + RateService _rateService; + ShipmentService _shipmentService; + CartonService _cartonService; + InvoiceService _invoiceService; + Services._() { + _authService = AuthServiceImp( + authFb: AuthFb.instance, + connectivity: null, + ); + _userService = UserServiceImp( + connectivity: null, userDataProvider: UserDataProvider()); + _messagingService = MessagingServiceImp(); + _packageService = PackageServiceImp( + connectivity: null, packageDataProvider: PackageDataProvider()); + _commonService = CommonServiceImp(commonDataProvider: CommonDataProvider()); + _fcsShipmentService = FcsShipmentServiceImp( + connectivity: null, shipmentDataProvider: FcsShipmentDataProvider()); + _deliveryAddressService = DeliveryAddressImp( + connectivity: null, + deliveryAddressDataProvider: DeliveryAddressDataProvider()); + _rateService = RateServiceImp( + rateDataProvider: RateDataProvider.instance, connectivity: null); + _shipmentService = ShipmentServiceImp( + shipmentDataProvider: ShipmentDataProvider.instance, + connectivity: null); + _cartonService = CartonServiceImp( + cartonDataProvider: CartonDataProvider.instance, connectivity: null); + _invoiceService = InvoiceServiceImp( + invoiceDataProvider: InvoiceDataProvider.instance, connectivity: null); + } + + AuthService get authService => _authService; + UserService get userService => _userService; + MessagingService get messagingService => _messagingService; + PackageService get packageService => _packageService; + CommonService get commonService => _commonService; + FcsShipmentService get fcsShipmentService => _fcsShipmentService; + DeliveryAddressService get deliveryAddressService => _deliveryAddressService; + RateService get rateService => _rateService; + ShipmentService get shipmentService => _shipmentService; + CartonService get cartonService => _cartonService; + InvoiceService get invoiceService => _invoiceService; +} diff --git a/lib/data/services/shipment_imp.dart b/lib/data/services/shipment_imp.dart new file mode 100644 index 0000000..8aeb11d --- /dev/null +++ b/lib/data/services/shipment_imp.dart @@ -0,0 +1,80 @@ +import 'package:fcs/data/provider/shipment_data_provider.dart'; +import 'package:fcs/data/services/shipment_service.dart'; +import 'package:fcs/domain/entities/connectivity.dart'; +import 'package:fcs/domain/entities/shipment.dart'; +import 'package:flutter/material.dart'; + +class ShipmentServiceImp implements ShipmentService { + ShipmentServiceImp({ + @required this.shipmentDataProvider, + @required this.connectivity, + }); + + final Connectivity connectivity; + final ShipmentDataProvider shipmentDataProvider; + + @override + Future cancelShipment(Shipment shipment) { + return shipmentDataProvider.cancelShipment(shipment); + } + + @override + Future confirmShipment(Shipment shipment) { + return shipmentDataProvider.confirmShipment(shipment); + } + + @override + Future createShipment(Shipment shipment) { + return shipmentDataProvider.createShipment(shipment); + } + + @override + Future pickupShipment(Shipment shipment) { + return shipmentDataProvider.pickupShipment(shipment); + } + + @override + Future receiveShipment(Shipment shipment) { + return shipmentDataProvider.receiveShipment(shipment); + } + + @override + Future updateShipment(Shipment shipment) { + return shipmentDataProvider.updateShipment(shipment); + } + + @override + Future assignShipment(Shipment shipment) { + return shipmentDataProvider.assignShipment(shipment); + } + + @override + Future completeAssignShipment(Shipment shipment) { + return shipmentDataProvider.completeAssignShipment(shipment); + } + + @override + Future completePickupShipment(Shipment shipment) { + return shipmentDataProvider.completePickupShipment(shipment); + } + + @override + Future completePackShipment(Shipment shipment) { + return shipmentDataProvider.completePackShipment(shipment); + } + + @override + Future packShipment(Shipment shipment) { + return shipmentDataProvider.packShipment(shipment); + } + + @override + Future completeConfirmShipment(Shipment shipment) { + return shipmentDataProvider.completeConfirmShipment(shipment); + } + + @override + Future completeReceiveShipment(Shipment shipment) { + return shipmentDataProvider.completeReceiveShipment(shipment); + } +} diff --git a/lib/data/services/shipment_service.dart b/lib/data/services/shipment_service.dart new file mode 100644 index 0000000..7761416 --- /dev/null +++ b/lib/data/services/shipment_service.dart @@ -0,0 +1,17 @@ +import 'package:fcs/domain/entities/shipment.dart'; + +abstract class ShipmentService { + Future createShipment(Shipment shipment); + Future updateShipment(Shipment shipment); + Future cancelShipment(Shipment shipment); + Future confirmShipment(Shipment shipment); + Future completeConfirmShipment(Shipment shipment); + Future completeReceiveShipment(Shipment shipment); + Future pickupShipment(Shipment shipment); + Future receiveShipment(Shipment shipment); + Future assignShipment(Shipment shipment); + Future completeAssignShipment(Shipment shipment); + Future completePickupShipment(Shipment shipment); + Future packShipment(Shipment shipment); + Future completePackShipment(Shipment shipment); +} diff --git a/lib/fcs/common/services/user_imp.dart b/lib/data/services/user_imp.dart similarity index 79% rename from lib/fcs/common/services/user_imp.dart rename to lib/data/services/user_imp.dart index 51d5e8c..d3b7685 100644 --- a/lib/fcs/common/services/user_imp.dart +++ b/lib/data/services/user_imp.dart @@ -1,6 +1,6 @@ -import 'package:fcs/fcs/common/data/providers/user_data_provider.dart'; -import 'package:fcs/fcs/common/domain/entities/connectivity.dart'; -import 'package:fcs/fcs/common/domain/entities/user.dart'; +import 'package:fcs/data/provider/user_data_provider.dart'; +import 'package:fcs/domain/entities/connectivity.dart'; +import 'package:fcs/domain/entities/user.dart'; import 'package:flutter/material.dart'; import 'user_service.dart'; @@ -48,4 +48,9 @@ class UserServiceImp implements UserService { Future uploadMsgToken(String token) { return userDataProvider.uploadMsgToken(token); } + + @override + Future enableUser(String userID, bool enabled) { + return userDataProvider.enableUser(userID, enabled); + } } diff --git a/lib/fcs/common/services/user_service.dart b/lib/data/services/user_service.dart similarity index 78% rename from lib/fcs/common/services/user_service.dart rename to lib/data/services/user_service.dart index 93d8c32..168193d 100644 --- a/lib/fcs/common/services/user_service.dart +++ b/lib/data/services/user_service.dart @@ -1,4 +1,4 @@ -import 'package:fcs/fcs/common/domain/entities/user.dart'; +import 'package:fcs/domain/entities/user.dart'; abstract class UserService { Future inviteUser(String userName, String phoneNumber); @@ -8,4 +8,5 @@ abstract class UserService { Future> searchUser(String term); Future uploadMsgToken(String token); Future removeMsgToken(String token); + Future enableUser(String userID, bool enabled); } diff --git a/lib/domain/constants.dart b/lib/domain/constants.dart new file mode 100644 index 0000000..7243933 --- /dev/null +++ b/lib/domain/constants.dart @@ -0,0 +1,99 @@ +const config_collection = "configs"; +const user_collection = "users"; +const invitations_collection = "invitations"; +const privilege_collection = "privileges"; +const markets_collection = "markets"; +const packages_collection = "packages"; +const messages_collection = "messages"; +const fcs_shipment_collection = "fcs_shipments"; +const invoices_collection = "invoices"; +const delivery_address_collection = "delivery_addresses"; +const cargo_types_collection = "cargo_types"; +const custom_duties_collection = "custom_duties"; +const discounts_by_weights_collection = "discounts_by_weight"; +const shipments_collection = "shipments"; +const cartons_collection = "cartons"; +const discounts_collection = "discounts"; + +// docs +const setting_doc_id = "setting"; +const rate_doc_id = "rate"; + +// user's status +const user_requested_status = "requested"; +const user_invited_status = "invited"; +const user_disabled_status = "disabled"; +const user_joined_status = "joined"; + +const pkg_files_path = "/packages"; +const shipment_labels_files_path = "/shipment_labels"; + +// Link page +const page_payment_methods = "payment_methods"; +const page_buying_instructions = "buying_instructions"; +const page_rates = "rates"; + +// Message type +const message_type_package = "t_p"; +const message_type_profile = "t_profile"; +const message_type_shipment = "t_s"; + +// Fcs shipment status +const fcs_shipment_confirmed_status = "confirmed"; +const fcs_shipment_shipped_status = "shipped"; +const fcs_shipment_delivered_status = "delivered"; + +// Package status +const package_received_status = "received"; +const package_processed_status = "processed"; +const package_packed_status = "packed"; +const package_shipped_status = "shipped"; +const package_delivered_status = "delivered"; + +// Privileges +const privilege_sys_admin = "sa"; +const privilege_admin = "admin"; +const privilege_support = "sp"; +const privilege_package = "pkg"; +const privilege_shipment = "sh"; +const privilege_fcs_shipment = "fsh"; +const privilege_staff = "st"; +const privilege_carton = "ca"; +const privilege_customer = "cu"; +const privilege_delivery = "deli"; +const privilege_invoice = "inv"; +const privilege_processing = "pr"; +const privilege_receiving = "rc"; + +// Pickup types +const shipment_local_pickup = "Local pickup"; +const shipment_courier_pickup = "Courier pickup"; +const shipment_local_dropoff = "Local drop off"; +const shipment_courier_dropoff = "Courier drop off"; + +//Carton types +const carton_from_packages = "From packages"; +const carton_from_shipments = "From shipments"; +const carton_mix_box = "Mix carton"; +const carton_small_bag = "Small bag"; + +//Carton status +const carton_packed_status = "packed"; +const carton_shipped_status = "shipped"; +const carton_delivered_status = "delivered"; + +// shipment status +const shipment_pending_status = "pending"; +const shipment_assigned_status = "assigned"; +const shipment_confirmed_status = "confirmed"; +const shipment_received_status = "received"; +const shipment_pickuped_status = "pickuped"; +const shipment_packed_status = "packed"; +const shipment_shipped_status = "shipped"; +const shipment_delivered_status = "delivered"; + +// invoice status +const invoice_issued_status = "issued"; +const invoice_saved_status = "saved"; +const invoice_cancel_status = "canceled"; +const invoice_paid_status = "paid"; diff --git a/lib/fcs/common/domain/entities/auth_result.dart b/lib/domain/entities/auth_result.dart similarity index 100% rename from lib/fcs/common/domain/entities/auth_result.dart rename to lib/domain/entities/auth_result.dart diff --git a/lib/fcs/common/domain/entities/auth_status.dart b/lib/domain/entities/auth_status.dart similarity index 100% rename from lib/fcs/common/domain/entities/auth_status.dart rename to lib/domain/entities/auth_status.dart diff --git a/lib/domain/entities/cargo_type.dart b/lib/domain/entities/cargo_type.dart new file mode 100644 index 0000000..7247ce0 --- /dev/null +++ b/lib/domain/entities/cargo_type.dart @@ -0,0 +1,55 @@ +class CargoType { + String id; + String name; + double rate; + double weight; + + double get calAmount => (calRate ?? 0) * (calWeight ?? 0); + + double calRate; + double calWeight; + + factory CargoType.fromMap(Map map, String id) { + return CargoType( + id: id, + name: map['name'], + rate: map['rate']?.toDouble() ?? 0, + weight: map['weight']?.toDouble() ?? 0, + calWeight: map['cal_weight']?.toDouble() ?? 0, + calRate: map['cal_rate']?.toDouble() ?? 0, + ); + } + CargoType( + {this.id, + this.name, + this.rate, + this.weight, + this.calWeight, + this.calRate}); + + Map toMap() { + return { + "id": id, + 'name': name, + 'rate': rate, + 'weight': weight, + 'cal_weight': calWeight, + 'cal_rate': calRate, + }; + } + + CargoType clone() { + return CargoType.fromMap(toMap(), this.id); + } + + @override + bool operator ==(Object other) => other is CargoType && other.id == id; + + @override + int get hashCode => id.hashCode; + + @override + String toString() { + return name; + } +} diff --git a/lib/domain/entities/carton.dart b/lib/domain/entities/carton.dart new file mode 100644 index 0000000..cccac21 --- /dev/null +++ b/lib/domain/entities/carton.dart @@ -0,0 +1,219 @@ +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:fcs/domain/entities/discount_by_weight.dart'; +import 'package:fcs/domain/entities/rate.dart'; +import 'package:fcs/domain/entities/shipment.dart'; +import 'package:fcs/domain/vo/shipment_status.dart'; +import 'package:fcs/domain/vo/delivery_address.dart'; + +import 'cargo_type.dart'; +import 'package.dart'; + +class Carton { + String id; + String shipmentID; + String shipmentNumber; + String senderFCSID; + String senderName; + String receiverFCSID; + String receiverName; + String receiverAddress; + String receiverNumber; + String boxNumber; + String status; + String cargoDesc; + String desc; + double width; + double height; + double length; + int shipmentWeight; + bool isChecked; + bool isShipmentCarton; + String cartonType; + String fcsID; + String userName; + String userID; + String fcsShipmentID; + String fcsShipmentNumber; + String mixCartonID; + String mixCartonNumber; + + int rate; + int weight; + String packageType; + String pickUpID; + List photos; + String remark; + DateTime arrivedDate; + String cartonNumber; + + List packageIDs; + List packages; + List cargoTypes; + + DeliveryAddress deliveryAddress; + Shipment shipment; + + int get amount => rate != null && weight != null ? rate * weight : 0; + + String get packageNumber => + shipmentNumber + "-" + receiverNumber + " #" + boxNumber; + double get price => rate.toDouble() * weight; + + double get actualWeight => + cargoTypes == null ? 0 : cargoTypes.fold(0, (p, e) => e.weight + p); + + double getShipmentWeight(double volumetricRatio) { + if (length == null || + length <= 0 || + width == null || + width <= 0 || + height == null || + height <= 0 || + volumetricRatio == null || + volumetricRatio <= 0) return 0; + + return (length * width * height) / volumetricRatio; + } + + /// getCargoTypeForCalWeight returns carton with shipment weight + List getCargoTypeForCalWeight(double volumetricRatio) { + // get shipment weight + double volume = (length ?? 0) * (width ?? 0) * (height ?? 0); + double sw = volume / volumetricRatio ?? 0; + + // get actual weight + double aw = cargoTypes.fold(0.0, (p, c) => p + c.weight); + if (aw == 0 || sw == 0) return []; + + cargoTypes.forEach((e) { + double calWeight = aw > sw ? e.weight : e.weight / aw * sw; + e.calWeight = calWeight; + }); + return cargoTypes; + } + + /// calAmount returns total amount + double calAmount(Rate rate) { + // get shipment weight + double volume = (length ?? 0) * (width ?? 0) * (height ?? 0); + double sw = volume / rate.volumetricRatio ?? 0; + + // get actual weight + double aw = cargoTypes.fold(0.0, (p, c) => p + c.weight); + if (aw == 0 || sw == 0) return 0; + + DiscountByWeight discountByWeight = + rate.getDiscountByWeight(sw > aw ? sw : aw); + + double total = 0; + cargoTypes.forEach((e) { + double cargoWeight = aw > sw ? e.weight : e.weight / aw * sw; + double r = + e.rate - (discountByWeight != null ? discountByWeight.discount : 0); + double amount = cargoWeight * r; + total += amount; + }); + return total; + } + + List shipmentHistory; + + Carton( + {this.id, + this.shipmentID, + this.shipmentNumber, + this.senderFCSID, + this.senderName, + this.receiverFCSID, + this.receiverName, + this.receiverNumber, + this.receiverAddress, + this.boxNumber, + this.desc, + this.width, + this.height, + this.length, + this.shipmentWeight, + this.isChecked = false, + this.cartonType, + this.fcsID, + this.userID, + this.userName, + this.rate = 0, + this.weight = 0, + this.packageType, + this.pickUpID, + this.remark, + this.status, + this.arrivedDate, + this.cargoDesc, + this.shipmentHistory, + this.packages, + this.cargoTypes, + this.cartonNumber, + this.fcsShipmentID, + this.fcsShipmentNumber, + this.packageIDs, + this.mixCartonID, + this.mixCartonNumber, + this.isShipmentCarton = false, + this.deliveryAddress}); + + Map toMap() { + List _cargoTypes = cargoTypes.map((c) => c.toMap()).toList(); + List _packages = packages?.map((c) => c.toJson())?.toList(); + return { + "id": id, + 'fcs_shipment_id': fcsShipmentID, + 'user_id': userID, + 'cargo_types': _cargoTypes, + 'packages': _packages, + 'length': length, + 'width': width, + 'height': height, + 'delivery_address': deliveryAddress?.toMap(), + 'carton_type': cartonType, + 'mix_carton_id': mixCartonID, + }; + } + + factory Carton.fromMap(Map map, String docID) { + var _arrivedDate = (map['arrived_date'] as Timestamp); + var da = map['delivery_address']; + var _da = da != null ? DeliveryAddress.fromMap(da, da["id"]) : null; + var cargoTypesMaps = + List>.from(map['cargo_types'] ?? []); + var cargoTypes = + cargoTypesMaps.map((e) => CargoType.fromMap(e, e["id"])).toList(); + return Carton( + id: docID, + arrivedDate: _arrivedDate != null ? _arrivedDate.toDate() : null, + shipmentID: map['shipment_id'], + shipmentNumber: map['shipment_number'], + receiverNumber: map['receiver_number'], + boxNumber: map['box_number'], + length: map['length'], + width: map['width'], + height: map['height'], + userName: map['user_name'], + fcsID: map['fcs_id'], + cartonType: map['carton_type'], + cartonNumber: map['carton_number'], + userID: map['user_id'], + fcsShipmentID: map['fcs_shipment_id'], + fcsShipmentNumber: map['fcs_shipment_number'], + isShipmentCarton: map['is_shipment_carton'], + mixCartonID: map['mix_carton_id'], + mixCartonNumber: map['mix_carton_number'], + status: map['status'], + packageIDs: List.from(map['package_ids'] ?? []), + deliveryAddress: _da, + cargoTypes: cargoTypes); + } + + @override + bool operator ==(Object other) => other is Carton && other.id == id; + + @override + int get hashCode => id.hashCode; +} diff --git a/lib/fcs/common/domain/entities/connectivity.dart b/lib/domain/entities/connectivity.dart similarity index 100% rename from lib/fcs/common/domain/entities/connectivity.dart rename to lib/domain/entities/connectivity.dart diff --git a/lib/domain/entities/custom_duty.dart b/lib/domain/entities/custom_duty.dart new file mode 100644 index 0000000..d5eba6a --- /dev/null +++ b/lib/domain/entities/custom_duty.dart @@ -0,0 +1,31 @@ +class CustomDuty { + String id; + String productType; + String desc; + double fee; + CustomDuty({this.id, this.productType, this.desc, this.fee}); + + factory CustomDuty.fromMap(Map map, String id) { + return CustomDuty( + id: id, + productType: map['product_type'], + desc: map['desc'], + fee: (map['fee'] ?? 0).toDouble(), + ); + } + + Map toMap() { + return { + "id": id, + 'product_type': productType, + 'desc': desc, + 'fee': fee, + }; + } + + @override + bool operator ==(Object other) => other is CustomDuty && other.id == id; + + @override + int get hashCode => id.hashCode; +} diff --git a/lib/fcs/common/domain/entities/customer.dart b/lib/domain/entities/customer.dart similarity index 100% rename from lib/fcs/common/domain/entities/customer.dart rename to lib/domain/entities/customer.dart diff --git a/lib/domain/entities/discount.dart b/lib/domain/entities/discount.dart new file mode 100644 index 0000000..1815a72 --- /dev/null +++ b/lib/domain/entities/discount.dart @@ -0,0 +1,38 @@ +class Discount { + String id; + String code; + String customerId; + String customerName; + String status; + double amount; + + Discount({ + this.id, + this.code, + this.customerId, + this.customerName, + this.amount, + this.status, + }); + + Map toMap() { + return { + 'id': id, + 'code': code, + "customer_id": customerId, + "customer_name": customerName, + "amount": amount, + }; + } + + factory Discount.fromMap(Map map, String id) { + return Discount( + id: id, + code: map['code'], + customerId: map['customer_id'], + customerName: map['customer_name'], + amount: map['amount'], + status: map['status'], + ); + } +} diff --git a/lib/domain/entities/discount_by_weight.dart b/lib/domain/entities/discount_by_weight.dart new file mode 100644 index 0000000..cc4b179 --- /dev/null +++ b/lib/domain/entities/discount_by_weight.dart @@ -0,0 +1,23 @@ +class DiscountByWeight { + String id; + double weight; + double discount; + + DiscountByWeight({this.id, this.weight, this.discount}); + + factory DiscountByWeight.fromMap(Map map, String id) { + return DiscountByWeight( + id: id, + weight: (map['weight'] ?? 0).toDouble(), + discount: (map['discount'] ?? 0).toDouble(), + ); + } + + Map toMap() { + return { + "id": id, + 'weight': weight, + 'discount': discount, + }; + } +} diff --git a/lib/fcs/common/domain/entities/faq.dart b/lib/domain/entities/faq.dart similarity index 100% rename from lib/fcs/common/domain/entities/faq.dart rename to lib/domain/entities/faq.dart diff --git a/lib/domain/entities/fcs_shipment.dart b/lib/domain/entities/fcs_shipment.dart new file mode 100644 index 0000000..5a6264a --- /dev/null +++ b/lib/domain/entities/fcs_shipment.dart @@ -0,0 +1,66 @@ +import 'package:cloud_firestore/cloud_firestore.dart'; + +import '../constants.dart'; + +class FcsShipment { + String id; + String shipmentNumber; + DateTime cutoffDate; + String shipType; + DateTime arrivalDate; + DateTime departureDate; + String consignee; + String port; + String destination; + String status; + FcsShipment({ + this.id, + this.shipmentNumber, + this.cutoffDate, + this.shipType, + this.status, + this.arrivalDate, + this.departureDate, + this.consignee, + this.port, + this.destination, + }); + + factory FcsShipment.fromMap(Map map, String docID) { + var _cutoffDate = (map['cutoff_date'] as Timestamp); + var _arrivalDate = (map['arrival_date'] as Timestamp); + var _departureDate = (map['departure_date'] as Timestamp); + + return FcsShipment( + id: docID, + cutoffDate: _cutoffDate != null ? _cutoffDate.toDate() : null, + arrivalDate: _arrivalDate != null ? _arrivalDate.toDate() : null, + departureDate: _departureDate != null ? _departureDate.toDate() : null, + shipmentNumber: map['shipment_number'], + shipType: map['shipment_type'], + status: map['status'], + consignee: map['consignee'], + port: map['port'], + destination: map['destination'], + ); + } + + Map toMap() { + return { + "id": id, + 'shipment_number': shipmentNumber, + 'cutoff_date': cutoffDate?.toUtc()?.toIso8601String(), + 'shipment_type': shipType, + 'arrival_date': arrivalDate?.toUtc()?.toIso8601String(), + 'departure_date': departureDate?.toUtc()?.toIso8601String(), + 'consignee': consignee, + 'port': port, + 'destination': destination, + 'status': status, + }; + } + + bool isConfirmed() { + return status == fcs_shipment_confirmed_status; + } +} diff --git a/lib/domain/entities/invoice.dart b/lib/domain/entities/invoice.dart new file mode 100644 index 0000000..b7c3460 --- /dev/null +++ b/lib/domain/entities/invoice.dart @@ -0,0 +1,189 @@ +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:fcs/domain/entities/cargo_type.dart'; +import 'package:fcs/domain/entities/carton.dart'; +import 'package:fcs/domain/entities/custom_duty.dart'; +import 'package:fcs/domain/entities/discount.dart'; +import 'package:fcs/domain/entities/discount_by_weight.dart'; +import 'package:fcs/domain/entities/payment_method.dart'; +import 'package:fcs/domain/entities/rate.dart'; +import 'package:fcs/domain/entities/shipment.dart'; + +class Invoice { + String id; + String invoiceNumber; + DateTime invoiceDate; + String fcsShipmentID; + String userID; + String fcsID; + String userName; + String phoneNumber; + String status; + + double handlingFee; + double deliveryFee; + double paidAmount; + double amount; + + List customDuties; + List cartons; + List cargoTypes; + List shipments; + Discount discount; + PaymentMethod paymentMethod; + String invoiceURL; + + List getCargoTypes(Rate rate) { + if (cargoTypes != null) return cargoTypes; + + List _cargoTypes = []; + double totalCalWeight = 0; + cartons.forEach((carton) { + if (carton.isChecked) { + var _cartonsTypes = + carton.getCargoTypeForCalWeight(rate.volumetricRatio); + _cartonsTypes.forEach((ct) { + if (_cargoTypes.contains(ct)) { + CargoType existing = _cargoTypes.firstWhere((wc) => wc.id == ct.id); + existing.calWeight += ct.calWeight; + } else { + _cargoTypes.add(ct.clone()); + } + totalCalWeight += ct.calWeight; + }); + } + }); + + DiscountByWeight discountByWeight = + rate.getDiscountByWeight(totalCalWeight); + + _cargoTypes.forEach((e) { + double r = + e.rate - (discountByWeight != null ? discountByWeight.discount : 0); + e.calRate = r; + }); + return _cargoTypes; + } + + double getTotal(Rate rate) { + List cargoTypes = getCargoTypes(rate); + var total = cargoTypes.fold(0.0, (p, c) => c.calAmount + p); + return total; + } + + double getNetAmount(Rate rate) { + List cargoTypes = getCargoTypes(rate); + var total = cargoTypes.fold(0.0, (p, c) => c.calAmount + p); + total += getCustomFee(); + total += getDeliveryFee(); + total += getHandlingFee(); + total -= getDiscount(); + return total; + } + + double getHandlingFee() { + return shipments?.where((sh) => sh.isSelected ?? false)?.fold(0, (p, s) { + return p + (s?.handlingFee ?? 0) - (s?.paidHandlingFee ?? 0); + }); + } + + double getTotalBalance(Rate rate) { + return getNetAmount(rate) - (paidAmount ?? 0); + } + + double getCustomFee() { + return customDuties == null ? 0 : customDuties.fold(0, (p, d) => p + d.fee); + } + + double getDeliveryFee() { + return deliveryFee == null ? 0 : deliveryFee; + } + + double getDiscount() => discount == null ? 0 : discount.amount; + + Invoice( + {this.id, + this.invoiceNumber, + this.invoiceDate, + this.fcsID, + this.userName, + this.phoneNumber, + this.amount, + this.discount, + this.status, + this.customDuties, + this.cartons, + this.cargoTypes, + this.handlingFee, + this.deliveryFee, + this.fcsShipmentID, + this.shipments, + this.invoiceURL, + this.paymentMethod}); + + factory Invoice.fromMap(Map map, String docID) { + var invd = (map['invoice_date'] as Timestamp); + var cargoTypesMaps = + List>.from(map['cargo_types'] ?? []); + var cargoTypes = + cargoTypesMaps.map((e) => CargoType.fromMap(e, e["id"])).toList(); + var customDutiesMap = + List>.from(map['custom_duties'] ?? []); + var customDuties = + customDutiesMap.map((e) => CustomDuty.fromMap(e, e["id"])).toList(); + var handlingShipmentsMap = + List>.from(map['handling_fee_shipments'] ?? []); + var handingShipments = + handlingShipmentsMap.map((e) => Shipment.fromMap(e, e["id"])).toList(); + var cartonsMap = List>.from(map['cartons'] ?? []); + var cartons = cartonsMap.map((e) => Carton.fromMap(e, e["id"])).toList(); + var paymentMethodMap = map['payment_method']; + var paymentMethod = paymentMethodMap != null + ? PaymentMethod.fromMap(paymentMethodMap, paymentMethodMap['id']) + : null; + var discountMap = map['discount']; + var discount = Discount.fromMap(discountMap, discountMap['id']); + return Invoice( + id: docID, + invoiceNumber: map['invoice_number'], + invoiceDate: invd?.toDate(), + userName: map['user_name'], + fcsID: map['fcs_id'], + phoneNumber: map['phone_number'], + amount: map['amount'], + status: map['status'], + cartons: cartons, + cargoTypes: cargoTypes, + shipments: handingShipments, + customDuties: customDuties, + deliveryFee: map['delivery_fee'], + invoiceURL: map['invoice_url'], + paymentMethod: paymentMethod, + discount: discount, + ); + } + + Map toMap() { + List _cargoTypes = cargoTypes.map((c) => c.toMap()).toList(); + List _customDuties = customDuties?.map((c) => c.toMap())?.toList(); + List _cartons = cartons?.map((c) => c.toMap())?.toList() ?? []; + List _shipments = shipments?.map((s) => s.toMap())?.toList() ?? []; + return { + "id": id, + "invoice_date": invoiceDate?.toUtc()?.toIso8601String(), + "user_id": userID, + "user_name": userName, + "invoice_number": invoiceNumber, + 'fcs_shipment_id': fcsShipmentID, + 'cargo_types': _cargoTypes, + 'custom_duties': _customDuties, + 'handling_fee_shipments': _shipments, + 'cartons': _cartons, + 'discount': discount?.toMap(), + 'amount': amount, + 'handling_fee': handlingFee, + 'delivery_fee': deliveryFee, + 'invoice_url': invoiceURL, + 'payment_method': paymentMethod?.toMap(), + }; + } +} diff --git a/lib/fcs/common/domain/entities/market.dart b/lib/domain/entities/market.dart similarity index 100% rename from lib/fcs/common/domain/entities/market.dart rename to lib/domain/entities/market.dart diff --git a/lib/fcs/common/domain/entities/package.dart b/lib/domain/entities/package.dart similarity index 61% rename from lib/fcs/common/domain/entities/package.dart rename to lib/domain/entities/package.dart index d5fce23..7a606d6 100644 --- a/lib/fcs/common/domain/entities/package.dart +++ b/lib/domain/entities/package.dart @@ -1,5 +1,6 @@ import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:fcs/fcs/common/domain/vo/shipment_status.dart'; +import 'package:fcs/domain/vo/delivery_address.dart'; +import 'package:fcs/domain/vo/shipment_status.dart'; class Package { String id; @@ -8,7 +9,6 @@ class Package { String fcsID; String userName; String phoneNumber; - String currentStatus; DateTime currentStatusDate; List photoUrls; List shipmentHistory; @@ -25,6 +25,7 @@ class Package { String boxNumber; String cargoDesc; String market; + bool isChecked; int rate; int weight; @@ -33,6 +34,7 @@ class Package { List photos; String remark; DateTime arrivedDate; + DeliveryAddress deliveryAddress; int get amount => rate != null && weight != null ? rate * weight : 0; @@ -40,45 +42,47 @@ class Package { shipmentNumber + "-" + receiverNumber + " #" + boxNumber; double get price => rate.toDouble() * weight; - Package({ - this.id, - this.trackingID, - this.userID, - this.userName, - this.fcsID, - this.phoneNumber, - this.shipmentNumber, - this.senderFCSID, - this.senderName, - this.receiverFCSID, - this.receiverName, - this.receiverNumber, - this.receiverAddress, - this.boxNumber, - this.rate, - this.weight, - this.packageType, - this.pickUpID, - this.remark, - this.status, - this.arrivedDate, - this.cargoDesc, - this.market, - this.shipmentHistory, - this.currentStatus, - this.currentStatusDate, - this.photoUrls, - this.desc, - }); + Package( + {this.id, + this.trackingID, + this.userID, + this.userName, + this.fcsID, + this.phoneNumber, + this.shipmentNumber, + this.senderFCSID, + this.senderName, + this.receiverFCSID, + this.receiverName, + this.receiverNumber, + this.receiverAddress, + this.boxNumber, + this.rate, + this.weight, + this.packageType, + this.pickUpID, + this.remark, + this.status, + this.arrivedDate, + this.cargoDesc, + this.market, + this.shipmentHistory, + this.currentStatusDate, + this.photoUrls, + this.desc, + this.deliveryAddress, + this.isChecked = false}); factory Package.fromMap(Map map, String docID) { - var _currentStatusDate = (map['current_status_date'] as Timestamp); + var _currentStatusDate = (map['status_date'] as Timestamp); List _shipmentStatus = List.from(map['all_status']) .map((e) => ShipmentStatus.fromMap(Map.from(e))) .toList(); List _photoUrls = map['photo_urls'] == null ? [] : List.from(map['photo_urls']); + var da = map['delivery_address']; + var _da = da != null ? DeliveryAddress.fromMap(da, da["id"]) : null; return Package( id: docID, @@ -90,7 +94,8 @@ class Package { phoneNumber: map['phone_number'], remark: map['remark'], desc: map['desc'], - currentStatus: map['current_status'], + status: map['status'], + deliveryAddress: _da, currentStatusDate: _currentStatusDate != null ? _currentStatusDate.toDate() : null, photoUrls: _photoUrls, @@ -114,12 +119,18 @@ class Package { market: json['market'], userName: json['user_name'], phoneNumber: json['phone_number'], - currentStatus: json['current_status'], - currentStatusDate: DateTime.parse(json['current_status_date'])); + status: json['status'], + currentStatusDate: DateTime.parse(json['status_date'])); } + @override + bool operator ==(Object other) => other is Package && other.id == id; + + @override + int get hashCode => id.hashCode; + @override String toString() { - return 'Package{id: $id, currentStatus: $currentStatus, market:$market, trackingID: $trackingID,}'; + return 'Package{id: $id, status: $status, market:$market, trackingID: $trackingID,}'; } } diff --git a/lib/fcs/common/domain/entities/payment_method.dart b/lib/domain/entities/payment_method.dart similarity index 100% rename from lib/fcs/common/domain/entities/payment_method.dart rename to lib/domain/entities/payment_method.dart diff --git a/lib/domain/entities/rate.dart b/lib/domain/entities/rate.dart new file mode 100644 index 0000000..94a1ec4 --- /dev/null +++ b/lib/domain/entities/rate.dart @@ -0,0 +1,51 @@ +import 'package:fcs/domain/entities/custom_duty.dart'; +import 'package:fcs/domain/entities/discount_by_weight.dart'; + +import 'cargo_type.dart'; + +class Rate { + double deliveryFee; + double freeDeliveryWeight; + double volumetricRatio; + + List cargoTypes; + List customDuties; + List discountByWeights; + + DiscountByWeight getDiscountByWeight(double weight) { + discountByWeights.sort((d1, d2) => d2.weight.compareTo(d1.weight)); + return discountByWeights.firstWhere((e) => e.weight < weight, + orElse: () => null); + } + + CargoType get defaultCargoType => cargoTypes == null + ? null + : cargoTypes.firstWhere((e) => e.name == "General"); + + Rate({ + this.deliveryFee, + this.freeDeliveryWeight, + this.volumetricRatio, + }); + + factory Rate.fromMap(Map map) { + return Rate( + deliveryFee: (map['delivery_fee'] ?? 0).toDouble(), + freeDeliveryWeight: (map['free_delivery_weight'] ?? 0).toDouble(), + volumetricRatio: (map['volumetric_ratio'] ?? 0).toDouble(), + ); + } + + Map toMap() { + return { + "delivery_fee": deliveryFee, + 'free_delivery_weight': freeDeliveryWeight, + 'volumetric_ratio': volumetricRatio, + }; + } + + @override + String toString() { + return 'Rate{deliveryFee:$deliveryFee,freeDeliveryWeight:$freeDeliveryWeight,volumetricRatio:$volumetricRatio}'; + } +} diff --git a/lib/domain/entities/receipt.dart b/lib/domain/entities/receipt.dart new file mode 100644 index 0000000..6fffbbe --- /dev/null +++ b/lib/domain/entities/receipt.dart @@ -0,0 +1,9 @@ +class Receipt { + String id; + int amount; + String date; + String status; + String fileUrl; + + Receipt({this.id, this.amount, this.date, this.status, this.fileUrl}); +} diff --git a/lib/domain/entities/setting.dart b/lib/domain/entities/setting.dart new file mode 100644 index 0000000..8f594bb --- /dev/null +++ b/lib/domain/entities/setting.dart @@ -0,0 +1,88 @@ +List dayLists = [ + Day(id: 1, name: 'Sun'), + Day(id: 2, name: 'Mon'), + Day(id: 3, name: 'Tue'), + Day(id: 4, name: 'Wed'), + Day(id: 5, name: 'Thu'), + Day(id: 6, name: 'Fri'), + Day(id: 7, name: 'Sat'), +]; + +class Setting { + final int supportBuildNum; + + // contact page + String usaAddress; + String mmAddress; + String usaContactNumber; + String mmContactNumber; + String emailAddress; + String facebookLink; + bool inviteRequired; + String appUrl; + final String termsEng; + final String termsMm; + String about; + String courierWebsite; + + List shipmentTypes; + + Setting( + {this.supportBuildNum, + this.usaAddress, + this.mmAddress, + this.usaContactNumber, + this.mmContactNumber, + this.emailAddress, + this.facebookLink, + this.inviteRequired, + this.appUrl, + this.termsEng, + this.termsMm, + this.about, + this.shipmentTypes, + this.courierWebsite}); + + factory Setting.fromMap(Map map) { + return Setting( + supportBuildNum: map['support_build_number'], + inviteRequired: map['invite_required'], + appUrl: map['app_url'], + usaAddress: map['usa_address'], + mmAddress: map['mm_address'], + usaContactNumber: map['usa_contact_number'], + mmContactNumber: map['mm_contact_number'], + emailAddress: map['email_address'], + facebookLink: map['facebook_link'], + about: map['about'], + termsEng: map['terms_eng'], + termsMm: map['terms_mm'], + shipmentTypes: List.from(map['shipment_types']), + courierWebsite: map['courier_website'], + ); + } + + Map toMap() { + return { + 'terms_eng': termsEng, + 'terms_mm': termsMm, + }; + } + + @override + String toString() { + return 'Setting{supportBuildNum:$supportBuildNum,about:$about}'; + } +} + +class Day { + int id; + String name; + bool isChecked = false; + Day({this.id, this.name, this.isChecked}); + + @override + String toString() { + return 'Day{id:$id,name:$name,isChecked:$isChecked}'; + } +} diff --git a/lib/domain/entities/shipment.dart b/lib/domain/entities/shipment.dart new file mode 100644 index 0000000..7b837df --- /dev/null +++ b/lib/domain/entities/shipment.dart @@ -0,0 +1,133 @@ +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:fcs/domain/constants.dart'; +import 'package:fcs/domain/entities/carton.dart'; +import 'package:fcs/domain/vo/delivery_address.dart'; + +class Shipment { + String id; + String shipmentNumber; + String shipmentType; + DeliveryAddress pickupAddress; + DateTime pickupDate; + String pickupTimeStart; + String pickupTimeEnd; + + String userName; + String userID; + String phoneNumber; + int numberOfPackage; + int weight; + double handlingFee; + double paidHandlingFee; + String address; + String status; + bool isCourier; + int radioIndex; + List boxes; + + String pickupUserID; + String pickupUserName; + String pickupUserPhoneNumber; + + String fcsShipmentID; + String fcsShipmentNumber; + String shipmentLabelUrl; + bool isSelected; + + Shipment( + {this.id, + this.shipmentNumber, + this.shipmentType, + this.userID, + this.userName, + this.phoneNumber, + this.pickupTimeStart, + this.pickupTimeEnd, + this.numberOfPackage, + this.weight, + this.handlingFee, + this.paidHandlingFee, + this.address, + this.status, + this.pickupDate, + this.isCourier = false, + this.radioIndex = 1, + this.pickupAddress, + this.pickupUserID, + this.pickupUserName, + this.pickupUserPhoneNumber, + this.fcsShipmentID, + this.fcsShipmentNumber, + this.shipmentLabelUrl, + this.boxes}); + + int get last => DateTime.now().difference(pickupDate).inDays; + + double get totalWeight => boxes?.fold(0, (p, e) => p + e.actualWeight); + int get totalCount => boxes?.length; + + bool get isPending => status == shipment_pending_status; + bool get isAssigned => status == shipment_assigned_status; + bool get isPickuped => status == shipment_pickuped_status; + bool get isPacked => status == shipment_packed_status; + bool get isConfirmed => status == shipment_confirmed_status; + bool get isReceived => status == shipment_received_status; + + factory Shipment.fromMap(Map map, String id) { + var pd = (map['pickup_date'] as Timestamp); + var pa = map['pickup_address']; + var _pa = pa != null ? DeliveryAddress.fromMap(pa, pa["id"]) : null; + return Shipment( + id: id, + userName: map['user_name'], + userID: map['user_id'], + shipmentNumber: map['shipment_number'], + phoneNumber: map['phone_number'], + pickupDate: pd == null ? null : pd.toDate(), + pickupTimeStart: map['pickup_time_start'], + pickupTimeEnd: map['pickup_time_end'], + status: map['status'], + shipmentType: map['shipment_type'], + pickupUserID: map['pickup_user_id'], + pickupUserName: map['pickup_user_name'], + pickupUserPhoneNumber: map['pickup_user_phone_number'], + handlingFee: map['handling_fee'], + paidHandlingFee: map['paid_handling_fee'], + fcsShipmentID: map['fcs_shipment_id'], + fcsShipmentNumber: map['fcs_shipment_number'], + shipmentLabelUrl: map['shipment_label_url'], + pickupAddress: _pa); + } + + Map toMap() { + List _boxes = boxes?.map((l) => l.toMap())?.toList() ?? []; + + return { + "id": id, + 'user_id': userID, + 'cartons': _boxes, + 'shipment_type': shipmentType, + 'pickup_address': pickupAddress.toMap(), + "pickup_date": pickupDate?.toUtc()?.toIso8601String(), + 'pickup_time_start': pickupTimeStart, + 'pickup_time_end': pickupTimeEnd, + 'pickup_user_id': pickupUserID, + 'pickup_user_name': pickupUserName, + 'pickup_user_phone_number': pickupUserPhoneNumber, + 'handling_fee': handlingFee, + 'fcs_shipment_id': fcsShipmentID, + 'shipment_label_url': shipmentLabelUrl + }; + } + + @override + bool operator ==(Object other) => other is Shipment && other.id == id; + + @override + int get hashCode => id.hashCode; + + @override + String toString() { + return 'PickUp{id:$id, userName:$userName,phoneNumber:$phoneNumber,numberOfPackage:$numberOfPackage,weight:$weight,status:$status}'; + } +} diff --git a/lib/fcs/common/domain/entities/user.dart b/lib/domain/entities/user.dart similarity index 61% rename from lib/fcs/common/domain/entities/user.dart rename to lib/domain/entities/user.dart index 1fd8bac..6ada508 100644 --- a/lib/fcs/common/domain/entities/user.dart +++ b/lib/domain/entities/user.dart @@ -1,10 +1,12 @@ import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:fcs/fcs/common/helpers/const.dart'; -import 'package:fcs/fcs/common/pages/package/package_info.dart'; +import 'package:flutter/foundation.dart'; import 'package:intl/intl.dart'; +import '../constants.dart'; + DateFormat dayFormat = DateFormat("MMM dd yyyy"); DateFormat timeFormat = DateFormat("HH:mm"); +final DateFormat dateFormat = DateFormat("d MMM yyyy"); class User { String id; @@ -16,6 +18,7 @@ class User { String lastMessage; int userUnseenCount; int fcsUnseenCount; + String preferCurrency; String get initial => name != null && name != "" ? name.substring(0, 1) : "?"; @@ -49,9 +52,11 @@ class User { String get phone => phoneNumber != null && phoneNumber.startsWith("959") ? "0${phoneNumber.substring(2)}" : phoneNumber; - bool get joined => status != null && status == userStatusJoined; - bool get invited => status != null && status == userStatusInvited; - bool get requested => status != null && status == userStatusRequested; + bool get joined => status != null && status == user_joined_status; + bool get invited => status != null && status == user_invited_status; + bool get requested => status != null && status == user_requested_status; + bool get disabled => status != null && status == user_disabled_status; + String get share => "Your phone number:$phoneNumber"; User( {this.id, @@ -63,7 +68,8 @@ class User { this.lastMessage, this.lastMessageTime, this.userUnseenCount, - this.fcsUnseenCount}); + this.fcsUnseenCount, + this.preferCurrency}); factory User.fromJson(Map json) { return User( @@ -105,48 +111,78 @@ class User { lastMessage: map['last_message'], userUnseenCount: map['user_unseen_count'], fcsUnseenCount: map['fcs_unseen_count'], + preferCurrency: map['preferred_currency'], lastMessageTime: _date == null ? null : _date.toDate()); } + bool diffPrivileges(User another) { + another.privileges.sort((a, b) => a.compareTo(b)); + privileges.sort((a, b) => a.compareTo(b)); + return !listEquals(another.privileges, privileges); + } + bool isCustomer() { return privileges == null || privileges.length == 0; } bool hasSysAdmin() { - return privileges != null ? privileges.contains('sa') : false; + return _has(privilege_sys_admin); } bool hasAdmin() { - return privileges != null ? privileges.contains('admin') : false; + return _has(privilege_admin); } bool hasCustomers() { - return hasSysAdmin() || - hasAdmin() || - (privileges != null ? privileges.contains('c') : false); + return hasSysAdmin() || hasAdmin() || _has(privilege_customer); + } + + bool hasFcsShipments() { + return hasSysAdmin() || hasAdmin() || _has(privilege_fcs_shipment); } bool hasStaffs() { - return hasSysAdmin() || - hasAdmin() || - (privileges != null ? privileges.contains('s') : false); + return hasSysAdmin() || hasAdmin() || _has(privilege_staff); } bool hasSupport() { - return hasSysAdmin() || - hasAdmin() || - (privileges != null ? privileges.contains('sp') : false); + return hasSysAdmin() || hasAdmin() || _has(privilege_support); } bool hasPackages() { - return hasSysAdmin() || - hasAdmin() || - status == userStatusJoined || - (privileges != null ? privileges.contains('p') : false); + return hasSysAdmin() || hasAdmin() || _has(privilege_package); + } + + bool hasReceiving() { + return hasSysAdmin() || hasAdmin() || _has(privilege_receiving); + } + + bool hasProcessing() { + return hasSysAdmin() || hasAdmin() || _has(privilege_processing); + } + + bool hasDeliveries() { + return hasSysAdmin() || hasAdmin() || _has(privilege_delivery); + } + + bool hasInvoices() { + return hasSysAdmin() || hasAdmin() || _has(privilege_invoice); + } + + bool hasShipment() { + return hasSysAdmin() || hasAdmin() || _has(privilege_shipment); + } + + bool hasCarton() { + return hasSysAdmin() || hasAdmin() || _has(privilege_carton); + } + + bool _has(String privilege) { + return (privileges != null ? privileges.contains(privilege) : false); } @override String toString() { - return 'User{name: $name, phoneNumber: $phoneNumber,status:$status}'; + return 'User{id:$id, name: $name, phoneNumber: $phoneNumber,status:$status}'; } } diff --git a/lib/fcs/common/domain/exceiptions/server_exceptions.dart b/lib/domain/exceiptions/server_exceptions.dart similarity index 100% rename from lib/fcs/common/domain/exceiptions/server_exceptions.dart rename to lib/domain/exceiptions/server_exceptions.dart diff --git a/lib/fcs/common/domain/exceiptions/signin_exception.dart b/lib/domain/exceiptions/signin_exception.dart similarity index 100% rename from lib/fcs/common/domain/exceiptions/signin_exception.dart rename to lib/domain/exceiptions/signin_exception.dart diff --git a/lib/fcs/common/domain/vo/contact.dart b/lib/domain/vo/contact.dart similarity index 94% rename from lib/fcs/common/domain/vo/contact.dart rename to lib/domain/vo/contact.dart index 1135dcc..5df67a2 100644 --- a/lib/fcs/common/domain/vo/contact.dart +++ b/lib/domain/vo/contact.dart @@ -1,4 +1,4 @@ -import 'package:fcs/fcs/common/domain/entities/setting.dart'; +import 'package:fcs/domain/entities/setting.dart'; class Contact { String usaAddress; diff --git a/lib/domain/vo/delivery_address.dart b/lib/domain/vo/delivery_address.dart new file mode 100644 index 0000000..b7157bb --- /dev/null +++ b/lib/domain/vo/delivery_address.dart @@ -0,0 +1,44 @@ +class DeliveryAddress { + String id; + String fullName; + String addressLine1; + String addressLine2; + String city; + String state; + String phoneNumber; + bool isDefault; + DeliveryAddress( + {this.id, + this.fullName, + this.addressLine1, + this.addressLine2, + this.city, + this.state, + this.phoneNumber, + this.isDefault = false}); + + factory DeliveryAddress.fromMap(Map map, String docID) { + return DeliveryAddress( + id: docID, + fullName: map['full_name'], + addressLine1: map['address_line1'], + addressLine2: map['address_line2'], + city: map['city'], + state: map['state'], + phoneNumber: map['phone_number'], + isDefault: map['is_defalut'] ?? false, + ); + } + + Map toMap() { + return { + "id": id, + 'full_name': fullName, + 'address_line1': addressLine1, + 'address_line2': addressLine2, + 'city': city, + 'state': state, + 'phone_number': phoneNumber, + }; + } +} diff --git a/lib/fcs/common/domain/vo/message.dart b/lib/domain/vo/message.dart similarity index 100% rename from lib/fcs/common/domain/vo/message.dart rename to lib/domain/vo/message.dart diff --git a/lib/domain/vo/privilege.dart b/lib/domain/vo/privilege.dart new file mode 100644 index 0000000..5b913b2 --- /dev/null +++ b/lib/domain/vo/privilege.dart @@ -0,0 +1,54 @@ +import 'package:fcs/domain/constants.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_icons/flutter_icons.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; + +class Privilege { + String id; + String name; + String desc; + bool sysAdminOnly = true; + bool isChecked = false; + + IconData iconData; + + Privilege( + {this.id, this.name, this.desc, this.isChecked, this.sysAdminOnly}) { + if (this.id == privilege_admin) { + iconData = MaterialCommunityIcons.account_tie; + } else if (this.id == privilege_support) { + iconData = SimpleLineIcons.support; + } else if (this.id == privilege_package) { + iconData = Octicons.package; + } else if (this.id == privilege_shipment) { + iconData = SimpleLineIcons.direction; + } else if (this.id == privilege_fcs_shipment) { + iconData = Ionicons.ios_airplane; + } else if (this.id == privilege_staff) { + iconData = MaterialCommunityIcons.worker; + } else if (this.id == privilege_carton) { + iconData = MaterialCommunityIcons.package; + } else if (this.id == privilege_customer) { + iconData = Feather.users; + } else if (this.id == privilege_delivery) { + iconData = MaterialCommunityIcons.truck_fast; + } else if (this.id == privilege_invoice) { + iconData = FontAwesomeIcons.fileInvoice; + } else if (this.id == privilege_processing) { + iconData = FontAwesome.dropbox; + } else if (this.id == privilege_receiving) { + iconData = MaterialCommunityIcons.inbox_arrow_down; + } else { + iconData = MaterialCommunityIcons.account_question; + } + } + + factory Privilege.fromMap(Map map, String docID) { + return Privilege( + id: docID, + name: map['name'], + desc: map['desc'], + sysAdminOnly: map['sys_admin_only']); + } +} diff --git a/lib/vo/radio.dart b/lib/domain/vo/radio.dart similarity index 100% rename from lib/vo/radio.dart rename to lib/domain/vo/radio.dart diff --git a/lib/fcs/common/domain/vo/shipment_status.dart b/lib/domain/vo/shipment_status.dart similarity index 100% rename from lib/fcs/common/domain/vo/shipment_status.dart rename to lib/domain/vo/shipment_status.dart diff --git a/lib/vo/status.dart b/lib/domain/vo/status.dart similarity index 100% rename from lib/vo/status.dart rename to lib/domain/vo/status.dart diff --git a/lib/fcs/common/domain/vo/term.dart b/lib/domain/vo/term.dart similarity index 86% rename from lib/fcs/common/domain/vo/term.dart rename to lib/domain/vo/term.dart index 6f2533c..b9c1086 100644 --- a/lib/fcs/common/domain/vo/term.dart +++ b/lib/domain/vo/term.dart @@ -1,4 +1,4 @@ -import 'package:fcs/fcs/common/domain/entities/setting.dart'; +import 'package:fcs/domain/entities/setting.dart'; class Term { String termEng; diff --git a/lib/fcs/common/data/providers/package_data_provider.dart b/lib/fcs/common/data/providers/package_data_provider.dart deleted file mode 100644 index 768cb14..0000000 --- a/lib/fcs/common/data/providers/package_data_provider.dart +++ /dev/null @@ -1,52 +0,0 @@ -import 'dart:convert'; - -import 'package:fcs/config.dart'; -import 'package:fcs/fcs/common/domain/constants.dart'; -import 'package:fcs/fcs/common/domain/entities/package.dart'; -import 'package:fcs/fcs/common/helpers/api_helper.dart'; -import 'package:fcs/fcs/common/helpers/firebase_helper.dart'; -import 'package:logging/logging.dart'; - -class PackageDataProvider { - final log = Logger('PackageDataProvider'); - - Future createPackages(List packages, String fcsID) async { - List> json = packages.map((e) => e.toJson()).toList(); - return await requestAPI("/packages", "POST", - payload: {"packages": json, "fcs_id": fcsID}, token: await getToken()); - } - - Future deletePackage(Package package) async { - return await requestAPI("/packages", "DELETE", - payload: {"id": package.id}, token: await getToken()); - } - - Future> searchPackage(String term) async { - if (term == null || term == '') return List(); - - var bytes = utf8.encode(term); - var base64Str = base64.encode(bytes); - HtmlEscape htmlEscape = const HtmlEscape(); - String escapePackage = htmlEscape.convert(base64Str); - - int limit = 20; - List packages = []; - - try { - var data = await requestAPI( - "/api/fts/$packages_collection/$escapePackage/$limit", "GET", - url: Config.instance.reportURL, token: await getToken()); - - if (data == null) return List(); - - data.forEach((p) { - var package = Package.fromJson(p); - packages.add(package); - }); - } catch (e) { - log.warning("buyer error:" + e.toString()); - return null; - } - return packages; - } -} diff --git a/lib/fcs/common/domain/constants.dart b/lib/fcs/common/domain/constants.dart deleted file mode 100644 index be1bc62..0000000 --- a/lib/fcs/common/domain/constants.dart +++ /dev/null @@ -1,57 +0,0 @@ -const config_collection = "configs"; -const user_collection = "users"; -const invitations_collection = "invitations"; -const setting_doc_id = "setting"; -const privilege_collection = "privileges"; -const markets_collection = "markets"; -const packages_collection = "packages"; -const messages_collection = "messages"; - -const user_requested_status = "requested"; -const user_invited_status = "invited"; - -const pkg_files_path = "/packages"; - -// Link page -const page_payment_methods = "payment_methods"; -const page_buying_instructions = "buying_instructions"; - -// Message type -const message_type_package = "t_p"; -const message_type_profile = "t_profile"; - -////////////////////////////// - -const ok_doc_id = "ok"; - -const biz_collection = "bizs"; -const product_collection = "products"; -const user_level_collection = "user_levels"; -const storage_collection = "storages"; -const buyer_collection = "buyers"; -const buying_pos = "buying_pos"; -const selling_pos = "selling_pos"; -const inventory_takings = "inventory_takings"; -const inventory_lines = "inventory_lines"; -const pds_collection = "pds"; -const pos_collection = "pos"; -const dos_collection = "dos"; -const notification_collection = "notifications"; -const log_collection = "logs"; -const report_collection = "reports"; -const po_product_collection = "po_products"; -const device_collection = "devices"; -const do_po_lines_collection = "do_po_lines"; -const reports_collection = "reports"; -const announcement_collection = "announcements"; -const report_user_collection = "report_users"; - -const po_files_path = "/ok/po"; -const reg_files_path = "/ok/reg"; -const do_files_path = "/ok/do"; -const sign_files_path = "/ok/sign"; -const bank_images_path = "/ok/banks"; - -const po_approved_status = "approved"; -const po_closed_status = "closed"; -const do_approved_status = "approved"; diff --git a/lib/fcs/common/domain/entities/bank_account.dart b/lib/fcs/common/domain/entities/bank_account.dart deleted file mode 100644 index 98027f0..0000000 --- a/lib/fcs/common/domain/entities/bank_account.dart +++ /dev/null @@ -1,31 +0,0 @@ -class BankAccount { - int index; - String bankName; - String bankLogo; - String accountName; - String accountNumber; - BankAccount( - {this.index, - this.bankName, - this.bankLogo, - this.accountName, - this.accountNumber}); - - BankAccount.fromMap(int index, Map json) { - this.index = index; - bankName = json['bank_name']; - bankLogo = json['bank_logo']; - accountName = json['account_name']; - accountNumber = json['account_number']; - } - - Map toMap() { - return { - "index": index, - 'bank_name': bankName, - 'bank_logo': bankLogo, - 'account_name': accountName, - 'account_number': accountNumber, - }; - } -} diff --git a/lib/fcs/common/domain/entities/role.dart b/lib/fcs/common/domain/entities/role.dart deleted file mode 100644 index d0e5aae..0000000 --- a/lib/fcs/common/domain/entities/role.dart +++ /dev/null @@ -1,67 +0,0 @@ -class Role { - String roleID; - String roleName; - String privileges; - Role({this.roleName, this.roleID, this.privileges}); - - Role.fromJson(Map json) { - roleName = json['role_name']; - roleID = json['role_id']; - privileges = json['privileges']; - } -} - -class Parser { - String status; - String message; - Role data; - Parser({this.status, this.message, this.data}); - - Parser.fromJson(Map json) { - status = json['status']; - message = json['message']; - if (json['status'] == 'Ok') { - data = Role.fromJson(json['data']); - } - } -} - -class StatusParser { - String status; - String message; - StatusParser(this.status, this.message); - - StatusParser.fromJson(Map json) { - status = json['status']; - message = json['message']; - } -} - -class Privilege { - String id; - String name; - String desc; - bool sysAdminOnly = true; - bool isChecked = false; - - Privilege({this.id, this.name, this.desc, this.isChecked, this.sysAdminOnly}); - - factory Privilege.fromMap(Map map, String docID) { - return Privilege( - id: docID, - name: map['name'], - desc: map['desc'], - sysAdminOnly: map['sys_admin_only']); - } -} - -class UserLevel { - String id; - String name; - int level; - UserLevel({this.id, this.name, this.level}); - - factory UserLevel.fromMap(Map map, String docID) { - return UserLevel(id: docID, name: map['name'], level: map['level']); - } -} diff --git a/lib/fcs/common/domain/entities/setting.dart b/lib/fcs/common/domain/entities/setting.dart deleted file mode 100644 index 6234da0..0000000 --- a/lib/fcs/common/domain/entities/setting.dart +++ /dev/null @@ -1,192 +0,0 @@ -import 'package:cloud_firestore/cloud_firestore.dart'; - -import 'bank_account.dart'; - -List dayLists = [ - Day(id: 1, name: 'Sun'), - Day(id: 2, name: 'Mon'), - Day(id: 3, name: 'Tue'), - Day(id: 4, name: 'Wed'), - Day(id: 5, name: 'Thu'), - Day(id: 6, name: 'Fri'), - Day(id: 7, name: 'Sat'), -]; - -class Setting { - final int supportBuildNum; - - // contact page - String usaAddress; - String mmAddress; - String usaContactNumber; - String mmContactNumber; - String emailAddress; - String facebookLink; - bool inviteRequired; - String appUrl; - final String termsEng; - final String termsMm; - - final String okEnergyId; - final String about; - int poExpireInHours; - int doExpireInHours; - int poOpenAt; - int poCloseAt; - List poCloseOn; - int latestDeliveryDay; - int firstStorageChargeIn; - int firstStorageCharge; - int secondStorageChargeIn; - int secondStorageCharge; - int deliveryStartWaitMin; - String reportURL; - String helpVersion; - String helpURL; - - List phones; - String deliveryPhone; - String address; - String website; - DateTime priceLastUpdate; - String bankAccountInfo; - List bankAccounts; - - String get getPoOpenAt => poOpenAt > 12 - ? (poOpenAt - 12).toString() + "PM" - : poOpenAt.toString() + "AM"; - - String get getPoCloseAt => poCloseAt > 12 - ? (poCloseAt - 12).toString() + "PM" - : poCloseAt.toString() + "AM"; - - String get getPoCloseOn => poCloseOn.fold( - "", (p, e) => p + (p == "" ? "" : ", ") + dayLists[e - 1].name); - - String get getPoOpenOn => dayLists.fold( - "", - (p, e) => - p + - (p == "" ? "" : poCloseOn.contains(e.id) ? "" : ", ") + - (poCloseOn.contains(e.id) ? "" : e.name)); - - bool get isPOClose { - DateTime now = DateTime.now(); - // dart starts from monday width starting index one - // server starts from sunday with starting index one - var day = (now.weekday + 1) == 8 ? 1 : now.weekday + 1; - return poCloseOn.contains(day) || - (now.hour < poOpenAt || now.hour >= poCloseAt); - } - - Setting( - {this.supportBuildNum, - this.usaAddress, - this.mmAddress, - this.usaContactNumber, - this.mmContactNumber, - this.emailAddress, - this.facebookLink, - this.inviteRequired, - this.appUrl, - this.termsEng, - this.termsMm, - this.about, - this.okEnergyId, - this.poExpireInHours, - this.doExpireInHours, - this.poOpenAt, - this.poCloseAt, - this.poCloseOn, - this.latestDeliveryDay, - this.firstStorageCharge, - this.firstStorageChargeIn, - this.secondStorageCharge, - this.secondStorageChargeIn, - this.deliveryStartWaitMin, - this.reportURL, - this.helpVersion, - this.helpURL, - this.phones, - this.website, - this.priceLastUpdate, - this.bankAccountInfo, - this.bankAccounts, - this.deliveryPhone, - this.address}); - - factory Setting.fromMap(Map map) { - var ts = (map['price_last_update'] as Timestamp); - var list = (map['bank_accounts'] as List); - - List bankAccounts = []; - if (list != null) { - list.asMap().forEach((index, item) { - bankAccounts - .add(BankAccount.fromMap(index, item.cast())); - }); - } - - return Setting( - supportBuildNum: map['support_build_number'], - inviteRequired: map['invite_required'], - appUrl: map['app_url'], - usaAddress: map['usa_address'], - mmAddress: map['mm_address'], - usaContactNumber: map['usa_contact_number'], - mmContactNumber: map['mm_contact_number'], - emailAddress: map['email_address'], - facebookLink: map['facebook_link'], - about: map['about'], - termsEng: map['terms_eng'], - termsMm: map['terms_mm'], - priceLastUpdate: ts?.toDate(), - okEnergyId: map['ok_energy_id'], - poExpireInHours: map['po_expire_hours'], - doExpireInHours: map['do_expire_hours'], - poOpenAt: map['po_open_at'], - poCloseAt: map['po_close_at'], - latestDeliveryDay: map['latest_delivery_days'], - firstStorageChargeIn: map['first_storage_charge_in'], - firstStorageCharge: map['first_storage_charge'], - secondStorageChargeIn: map['second_storage_charge_in'], - secondStorageCharge: map['second_storage_charge'], - deliveryStartWaitMin: map['delivery_start_wait_min'], - reportURL: map['report_url'], - helpVersion: map['help_version'], - helpURL: map['help_url'], - deliveryPhone: map['delivery_phone'], - address: map['address'], - website: map['website'], - bankAccountInfo: map['bank_account_info'], - bankAccounts: bankAccounts); - } - - Map toMap() { - return { - 'terms_eng': termsEng, - 'terms_mm': termsMm, - }; - } - - String helpFileName() { - return "help-v$helpVersion.zip"; - } - - @override - String toString() { - return 'Setting{supportBuildNum:$supportBuildNum,about:$about,okEnergyId:$okEnergyId}'; - } -} - -class Day { - int id; - String name; - bool isChecked = false; - Day({this.id, this.name, this.isChecked}); - - @override - String toString() { - return 'Day{id:$id,name:$name,isChecked:$isChecked}'; - } -} diff --git a/lib/fcs/common/domain/entities/shipment.dart b/lib/fcs/common/domain/entities/shipment.dart deleted file mode 100644 index 1c3f321..0000000 --- a/lib/fcs/common/domain/entities/shipment.dart +++ /dev/null @@ -1,25 +0,0 @@ -class Shipment { - DateTime shipDate; - String shipmentNumber; - DateTime cutoffDate; - String shipType; - DateTime arrivalDate; - DateTime departureDate; - String consignee; - String port; - String destination; - String status; - String remark; - Shipment( - {this.shipDate, - this.shipmentNumber, - this.cutoffDate, - this.shipType, - this.status, - this.arrivalDate, - this.departureDate, - this.consignee, - this.port, - this.destination, - this.remark}); -} diff --git a/lib/fcs/common/domain/vo/shipping_address.dart b/lib/fcs/common/domain/vo/shipping_address.dart deleted file mode 100644 index 0baba4b..0000000 --- a/lib/fcs/common/domain/vo/shipping_address.dart +++ /dev/null @@ -1,15 +0,0 @@ -class ShippingAddress { - String fullName; - String addressLine1; - String addressLine2; - String city; - String state; - String phoneNumber; - ShippingAddress( - {this.fullName, - this.addressLine1, - this.addressLine2, - this.city, - this.state, - this.phoneNumber}); -} diff --git a/lib/fcs/common/helpers/const.dart b/lib/fcs/common/helpers/const.dart deleted file mode 100644 index f558a5e..0000000 --- a/lib/fcs/common/helpers/const.dart +++ /dev/null @@ -1,3 +0,0 @@ -const userStatusInvited = "invited"; -const userStatusJoined = "joined"; -const userStatusRequested = "requested"; diff --git a/lib/fcs/common/helpers/pagination_model.dart b/lib/fcs/common/helpers/pagination_model.dart deleted file mode 100644 index ce0d192..0000000 --- a/lib/fcs/common/helpers/pagination_model.dart +++ /dev/null @@ -1,152 +0,0 @@ -import 'dart:async'; - -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:logging/logging.dart'; - -/* - * PaginationModel load data in page - * and listen to document change based on 'update_time' and 'delete_time' fields - * of the document - */ -class PaginationModel { - final log = Logger('PaginationModel'); - - List ids = []; - DocumentSnapshot prev; - int rowPerLoad = 10; - bool ended = false; - - StreamSubscription listener; - CollectionReference listeningCol; - Query pageQuery; - - PaginationModel(CollectionReference listeningCol, Query pageQuery, - {this.rowPerLoad = 10}) { - this.listeningCol = listeningCol; - this.pageQuery = pageQuery; - initData(); - } - - void initData() async { - _clearState(); - _initListener(); - load(); - } - - void _clearState() { - prev = null; - ids = []; - ended = false; - if (listener != null) listener.cancel(); - listener = null; - if (controller != null) controller.close(); - } - - StreamController controller; - Stream listen() { - if (controller != null) { - controller.close(); - } - controller = StreamController(onCancel: _clearState); - return controller.stream; - } - - void close() { - _clearState(); - } - - final String updateTimeField = 'update_time'; - final String deleteTimeField = 'delete_time'; - void _initListener() { - Query _query = - listeningCol.orderBy(updateTimeField, descending: true).limit(1); - _query.getDocuments(source: Source.server).then((QuerySnapshot snapshot) { - int count = snapshot.documents.length; - int updateTime = 0; - if (count == 1) { - updateTime = snapshot.documents[0].data[updateTimeField]; - } - - Query _queryListener = listeningCol - .where(updateTimeField, isGreaterThan: updateTime) - .orderBy(updateTimeField, descending: true); - - listener = - _queryListener.snapshots(includeMetadataChanges: true).listen((qs) { - qs.documentChanges.forEach((c) { - switch (c.type) { - case DocumentChangeType.added: - log.info("added!! $c"); - _update(c.document.documentID, c.document.data); - break; - case DocumentChangeType.modified: - log.info("modified!! $c"); - _update(c.document.documentID, c.document.data); - break; - default: - } - }); - }); - }); - } - - void _update(String id, Map data) { - if (ids.contains(id)) { - var deleted = data[deleteTimeField]; - if (deleted > 0) { - ids.remove(id); - controller.add(Result( - id: id, - data: data, - documentChangeType: DocumentChangeType.removed)); - } else { - controller.add(Result( - id: id, - data: data, - documentChangeType: DocumentChangeType.modified)); - } - } else { - ids.add(id); - controller.add(Result( - id: id, data: data, documentChangeType: DocumentChangeType.added)); - } - } - - Future load() async { - Query _query = - prev != null ? pageQuery.startAfterDocument(prev) : pageQuery; - try { - await _query - .where(deleteTimeField, isEqualTo: 0) - .limit(rowPerLoad) - .getDocuments(source: Source.server) - .then((QuerySnapshot snapshot) { - int count = snapshot.documents.length; - ended = count < rowPerLoad; - prev = count > 0 ? snapshot.documents[count - 1] : prev; - snapshot.documents.forEach((e) { - if (!ids.contains(e.documentID)) log.shout("load!! $e"); - ids.add(e.documentID); - controller.add(Result( - id: e.documentID, - data: e.data, - documentChangeType: DocumentChangeType.added)); - }); - if (ended) { - controller.add(Result(isEnded: true)); - } - }); - } catch (e) { - log.warning("Error!! $e"); - } - return ended; - } -} - -class Result { - String id; - Map data; - DocumentChangeType documentChangeType; - bool isEnded; - Result({this.id, this.data, this.documentChangeType, this.isEnded = false}); -} diff --git a/lib/fcs/common/pages/chat/chat_page.dart b/lib/fcs/common/pages/chat/chat_page.dart deleted file mode 100644 index 9393b42..0000000 --- a/lib/fcs/common/pages/chat/chat_page.dart +++ /dev/null @@ -1,576 +0,0 @@ -import 'dart:async'; -import 'dart:io'; - -import 'package:cached_network_image/cached_network_image.dart'; -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:firebase_storage/firebase_storage.dart'; -import 'package:flutter/material.dart'; -import 'package:image_picker/image_picker.dart'; -import 'package:intl/intl.dart'; -import 'package:shared_preferences/shared_preferences.dart'; - -import 'full_photo.dart'; -import 'loading.dart'; - -final themeColor = Color(0xfff5a623); -final primaryColor = Color(0xff203152); -final greyColor = Color(0xffaeaeae); -final greyColor2 = Color(0xffE8E8E8); - -class Chat extends StatelessWidget { - final String peerId; - final String peerAvatar; - - Chat({Key key, @required this.peerId, @required this.peerAvatar}) - : super(key: key); - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: Text( - 'CHAT', - style: TextStyle(color: primaryColor, fontWeight: FontWeight.bold), - ), - centerTitle: true, - ), - body: ChatScreen( - peerId: peerId, - peerAvatar: peerAvatar, - ), - ); - } -} - -class ChatScreen extends StatefulWidget { - final String peerId; - final String peerAvatar; - - ChatScreen({Key key, @required this.peerId, @required this.peerAvatar}) - : super(key: key); - - @override - State createState() => - ChatScreenState(peerId: peerId, peerAvatar: peerAvatar); -} - -class ChatScreenState extends State { - ChatScreenState({Key key, @required this.peerId, @required this.peerAvatar}); - GlobalKey key = GlobalKey(); - - String peerId; - String peerAvatar; - String id; - - List listMessage = new List.from([]); - int _limit = 20; - final int _limitIncrement = 20; - String groupChatId; - SharedPreferences prefs; - - File imageFile; - bool isLoading; - String imageUrl; - - final TextEditingController textEditingController = TextEditingController(); - final ScrollController listScrollController = ScrollController(); - - _scrollListener() { - if (listScrollController.offset >= - listScrollController.position.maxScrollExtent && - !listScrollController.position.outOfRange) { - print("reach the bottom"); - setState(() { - print("reach the bottom"); - _limit += _limitIncrement; - }); - } - if (listScrollController.offset <= - listScrollController.position.minScrollExtent && - !listScrollController.position.outOfRange) { - print("reach the top"); - setState(() { - print("reach the top"); - }); - } - } - - @override - void initState() { - super.initState(); - listScrollController.addListener(_scrollListener); - - groupChatId = ''; - - isLoading = false; - imageUrl = ''; - - readLocal(); - } - - readLocal() async { - prefs = await SharedPreferences.getInstance(); - id = prefs.getString('id') ?? ''; - if (id.hashCode <= peerId.hashCode) { - groupChatId = '$id-$peerId'; - } else { - groupChatId = '$peerId-$id'; - } - - Firestore.instance - .collection('users') - .document(id) - .updateData({'chattingWith': peerId}); - - setState(() {}); - } - - Future getImage() async { - ImagePicker imagePicker = ImagePicker(); - PickedFile pickedFile; - - pickedFile = await imagePicker.getImage(source: ImageSource.gallery); - imageFile = File(pickedFile.path); - - if (imageFile != null) { - setState(() { - isLoading = true; - }); - uploadFile(); - } - } - - Future uploadFile() async { - String fileName = DateTime.now().millisecondsSinceEpoch.toString(); - StorageReference reference = FirebaseStorage.instance.ref().child(fileName); - StorageUploadTask uploadTask = reference.putFile(imageFile); - StorageTaskSnapshot storageTaskSnapshot = await uploadTask.onComplete; - storageTaskSnapshot.ref.getDownloadURL().then((downloadUrl) { - imageUrl = downloadUrl; - setState(() { - isLoading = false; - onSendMessage(imageUrl, 1); - }); - }, onError: (err) { - setState(() { - isLoading = false; - }); - }); - } - - void onSendMessage(String content, int type) { - // type: 0 = text, 1 = image, 2 = sticker - if (content.trim() != '') { - textEditingController.clear(); - - var documentReference = Firestore.instance - .collection('messages') - .document(groupChatId) - .collection(groupChatId) - .document(DateTime.now().millisecondsSinceEpoch.toString()); - - Firestore.instance.runTransaction((transaction) async { - transaction.set( - documentReference, - { - 'idFrom': id, - 'idTo': peerId, - 'timestamp': DateTime.now().millisecondsSinceEpoch.toString(), - 'content': content, - 'type': type - }, - ); - }); - listScrollController.animateTo(0.0, - duration: Duration(milliseconds: 300), curve: Curves.easeOut); - } - } - - Widget buildItem(int index, DocumentSnapshot document) { - if (document.data['idFrom'] == id) { - // Right (my message) - return Row( - children: [ - document.data['type'] == 0 - // Text - ? Container( - child: Text( - document.data['content'], - style: TextStyle(color: primaryColor), - ), - padding: EdgeInsets.fromLTRB(15.0, 10.0, 15.0, 10.0), - width: 200.0, - decoration: BoxDecoration( - color: greyColor2, - borderRadius: BorderRadius.circular(8.0)), - margin: EdgeInsets.only( - bottom: isLastMessageRight(index) ? 20.0 : 10.0, - right: 10.0), - ) - : document.data['type'] == 1 - // Image - ? Container( - child: FlatButton( - child: Material( - child: CachedNetworkImage( - placeholder: (context, url) => Container( - child: CircularProgressIndicator( - valueColor: - AlwaysStoppedAnimation(themeColor), - ), - width: 200.0, - height: 200.0, - padding: EdgeInsets.all(70.0), - decoration: BoxDecoration( - color: greyColor2, - borderRadius: BorderRadius.all( - Radius.circular(8.0), - ), - ), - ), - errorWidget: (context, url, error) => Material( - child: Image.asset( - 'images/img_not_available.jpeg', - width: 200.0, - height: 200.0, - fit: BoxFit.cover, - ), - borderRadius: BorderRadius.all( - Radius.circular(8.0), - ), - clipBehavior: Clip.hardEdge, - ), - imageUrl: document.data['content'], - width: 200.0, - height: 200.0, - fit: BoxFit.cover, - ), - borderRadius: BorderRadius.all(Radius.circular(8.0)), - clipBehavior: Clip.hardEdge, - ), - onPressed: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => FullPhoto( - url: document.data['content']))); - }, - padding: EdgeInsets.all(0), - ), - margin: EdgeInsets.only( - bottom: isLastMessageRight(index) ? 20.0 : 10.0, - right: 10.0), - ) - // Sticker - : Container( - child: Image.asset( - 'images/${document.data['content']}.gif', - width: 100.0, - height: 100.0, - fit: BoxFit.cover, - ), - margin: EdgeInsets.only( - bottom: isLastMessageRight(index) ? 20.0 : 10.0, - right: 10.0), - ), - ], - mainAxisAlignment: MainAxisAlignment.end, - ); - } else { - // Left (peer message) - return Container( - child: Column( - children: [ - Row( - children: [ - isLastMessageLeft(index) - ? Material( - child: CachedNetworkImage( - placeholder: (context, url) => Container( - child: CircularProgressIndicator( - strokeWidth: 1.0, - valueColor: - AlwaysStoppedAnimation(themeColor), - ), - width: 35.0, - height: 35.0, - padding: EdgeInsets.all(10.0), - ), - imageUrl: peerAvatar, - width: 35.0, - height: 35.0, - fit: BoxFit.cover, - ), - borderRadius: BorderRadius.all( - Radius.circular(18.0), - ), - clipBehavior: Clip.hardEdge, - ) - : Container(width: 35.0), - document.data['type'] == 0 - ? Container( - child: Text( - document.data['content'], - style: TextStyle(color: Colors.white), - ), - padding: EdgeInsets.fromLTRB(15.0, 10.0, 15.0, 10.0), - width: 200.0, - decoration: BoxDecoration( - color: primaryColor, - borderRadius: BorderRadius.circular(8.0)), - margin: EdgeInsets.only(left: 10.0), - ) - : document.data['type'] == 1 - ? Container( - child: FlatButton( - child: Material( - child: CachedNetworkImage( - placeholder: (context, url) => Container( - child: CircularProgressIndicator( - valueColor: AlwaysStoppedAnimation( - themeColor), - ), - width: 200.0, - height: 200.0, - padding: EdgeInsets.all(70.0), - decoration: BoxDecoration( - color: greyColor2, - borderRadius: BorderRadius.all( - Radius.circular(8.0), - ), - ), - ), - errorWidget: (context, url, error) => - Material( - child: Image.asset( - 'images/img_not_available.jpeg', - width: 200.0, - height: 200.0, - fit: BoxFit.cover, - ), - borderRadius: BorderRadius.all( - Radius.circular(8.0), - ), - clipBehavior: Clip.hardEdge, - ), - imageUrl: document.data['content'], - width: 200.0, - height: 200.0, - fit: BoxFit.cover, - ), - borderRadius: - BorderRadius.all(Radius.circular(8.0)), - clipBehavior: Clip.hardEdge, - ), - onPressed: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => FullPhoto( - url: document.data['content']))); - }, - padding: EdgeInsets.all(0), - ), - margin: EdgeInsets.only(left: 10.0), - ) - : Container( - child: Image.asset( - 'images/${document.data['content']}.gif', - width: 100.0, - height: 100.0, - fit: BoxFit.cover, - ), - margin: EdgeInsets.only( - bottom: isLastMessageRight(index) ? 20.0 : 10.0, - right: 10.0), - ), - ], - ), - - // Time - isLastMessageLeft(index) - ? Container( - child: Text( - DateFormat('dd MMM kk:mm').format( - DateTime.fromMillisecondsSinceEpoch( - int.parse(document.data['timestamp']))), - style: TextStyle( - color: greyColor, - fontSize: 12.0, - fontStyle: FontStyle.italic), - ), - margin: EdgeInsets.only(left: 50.0, top: 5.0, bottom: 5.0), - ) - : Container() - ], - crossAxisAlignment: CrossAxisAlignment.start, - ), - margin: EdgeInsets.only(bottom: 10.0), - ); - } - } - - bool isLastMessageLeft(int index) { - if ((index > 0 && - listMessage != null && - listMessage[index - 1].data['idFrom'] == id) || - index == 0) { - return true; - } else { - return false; - } - } - - bool isLastMessageRight(int index) { - if ((index > 0 && - listMessage != null && - listMessage[index - 1].data['idFrom'] != id) || - index == 0) { - return true; - } else { - return false; - } - } - - Future onBackPress() { - Firestore.instance - .collection('users') - .document(id) - .updateData({'chattingWith': null}); - Navigator.pop(context); - - return Future.value(false); - } - - @override - Widget build(BuildContext context) { - return WillPopScope( - child: Stack( - children: [ - Column( - children: [ - // List of messages - buildListMessage(), - - // Input content - buildInput(), - ], - ), - - // Loading - buildLoading() - ], - ), - onWillPop: onBackPress, - ); - } - - Widget buildLoading() { - return Positioned( - child: isLoading ? const Loading() : Container(), - ); - } - - Widget buildInput() { - return Container( - child: Row( - children: [ - // Button send image - Material( - child: Container( - margin: EdgeInsets.symmetric(horizontal: 1.0), - child: IconButton( - icon: Icon(Icons.image), - onPressed: getImage, - color: primaryColor, - ), - ), - color: Colors.white, - ), - Material( - child: Container( - margin: EdgeInsets.symmetric(horizontal: 1.0), - child: IconButton( - icon: Icon(Icons.face), - onPressed: () => {}, - color: primaryColor, - ), - ), - color: Colors.white, - ), - - // Edit text - Flexible( - child: Container( - child: TextField( - onSubmitted: (value) { - onSendMessage(textEditingController.text, 0); - }, - style: TextStyle(color: primaryColor, fontSize: 15.0), - controller: textEditingController, - decoration: InputDecoration.collapsed( - hintText: 'Type your message...', - hintStyle: TextStyle(color: greyColor), - ), - ), - ), - ), - - // Button send message - Material( - child: Container( - margin: EdgeInsets.symmetric(horizontal: 8.0), - child: IconButton( - icon: Icon(Icons.send), - onPressed: () => onSendMessage(textEditingController.text, 0), - color: primaryColor, - ), - ), - color: Colors.white, - ), - ], - ), - width: double.infinity, - height: 50.0, - decoration: BoxDecoration( - border: Border(top: BorderSide(color: greyColor2, width: 0.5)), - color: Colors.white), - ); - } - - Widget buildListMessage() { - return Flexible( - child: groupChatId == '' - ? Center( - child: CircularProgressIndicator( - valueColor: AlwaysStoppedAnimation(themeColor))) - : StreamBuilder( - stream: Firestore.instance - .collection('messages') - .document(groupChatId) - .collection(groupChatId) - .orderBy('timestamp', descending: true) - .limit(_limit) - .snapshots(), - builder: (context, snapshot) { - if (!snapshot.hasData) { - return Center( - child: CircularProgressIndicator( - valueColor: - AlwaysStoppedAnimation(themeColor))); - } else { - listMessage.addAll(snapshot.data.documents); - return ListView.builder( - padding: EdgeInsets.all(10.0), - itemBuilder: (context, index) => - buildItem(index, snapshot.data.documents[index]), - itemCount: snapshot.data.documents.length, - reverse: true, - controller: listScrollController, - ); - } - }, - ), - ); - } -} diff --git a/lib/fcs/common/pages/chat/full_photo.dart b/lib/fcs/common/pages/chat/full_photo.dart deleted file mode 100644 index 294b1cb..0000000 --- a/lib/fcs/common/pages/chat/full_photo.dart +++ /dev/null @@ -1,51 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:photo_view/photo_view.dart'; -import 'package:cached_network_image/cached_network_image.dart'; - -import 'chat_page.dart'; - -class FullPhoto extends StatelessWidget { - final String url; - - FullPhoto({Key key, @required this.url}) : super(key: key); - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: Text( - 'FULL PHOTO', - style: TextStyle(color: primaryColor, fontWeight: FontWeight.bold), - ), - centerTitle: true, - ), - body: FullPhotoScreen(url: url), - ); - } -} - -class FullPhotoScreen extends StatefulWidget { - final String url; - - FullPhotoScreen({Key key, @required this.url}) : super(key: key); - - @override - State createState() => FullPhotoScreenState(url: url); -} - -class FullPhotoScreenState extends State { - final String url; - - FullPhotoScreenState({Key key, @required this.url}); - - @override - void initState() { - super.initState(); - } - - @override - Widget build(BuildContext context) { - return Container( - child: PhotoView(imageProvider: CachedNetworkImageProvider(url))); - } -} diff --git a/lib/fcs/common/pages/chat/loading.dart b/lib/fcs/common/pages/chat/loading.dart deleted file mode 100644 index ffbf320..0000000 --- a/lib/fcs/common/pages/chat/loading.dart +++ /dev/null @@ -1,18 +0,0 @@ -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:flutter/material.dart'; - -class Loading extends StatelessWidget { - const Loading(); - - @override - Widget build(BuildContext context) { - return Container( - child: Center( - child: CircularProgressIndicator( - valueColor: AlwaysStoppedAnimation(primaryColor), - ), - ), - color: Colors.white.withOpacity(0.8), - ); - } -} diff --git a/lib/fcs/common/pages/chat/notification_list.dart b/lib/fcs/common/pages/chat/notification_list.dart deleted file mode 100644 index ba2d7dc..0000000 --- a/lib/fcs/common/pages/chat/notification_list.dart +++ /dev/null @@ -1,129 +0,0 @@ -import 'package:fcs/fcs/common/domain/vo/message.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/fcs/common/pages/chat/message_detail.dart'; -import 'package:fcs/fcs/common/pages/chat/model/message_model.dart'; -import 'package:fcs/fcs/common/pages/widgets/bottom_up_page_route.dart'; -import 'package:fcs/fcs/common/pages/widgets/local_text.dart'; -import 'package:fcs/fcs/common/pages/widgets/progress.dart'; -import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; - -class NotificationList extends StatefulWidget { - @override - _NotificationListState createState() => _NotificationListState(); -} - -class _NotificationListState extends State { - var timeFormatter = new DateFormat('KK:mm a'); - var dateFormatter = new DateFormat('dd MMM yyyy'); - final double dotSize = 25.0; - int _selectedIndex = 0; - bool _isLoading = false; - bool _isClicked = false; - - @override - Widget build(BuildContext context) { - MessageModel messageModel = Provider.of(context); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - centerTitle: true, - leading: new IconButton( - icon: new Icon( - Icons.close, - ), - onPressed: () => Navigator.of(context).pop(), - ), - backgroundColor: primaryColor, - title: LocalText( - context, - 'message.title', - fontSize: 20, - color: Colors.white, - ), - ), - body: new ListView.separated( - separatorBuilder: (context, index) => Divider( - color: Colors.black, - ), - scrollDirection: Axis.vertical, - padding: EdgeInsets.only(top: 5), - shrinkWrap: true, - itemCount: messageModel.messages.length, - itemBuilder: (BuildContext context, int index) { - Message msg = messageModel.messages[index]; - return Stack( - children: [ - InkWell( - onTap: () => _display(msg), - child: Row( - children: [ - Expanded( - child: new Padding( - padding: const EdgeInsets.symmetric(vertical: 10.0), - child: new Row( - children: [ - new Padding( - padding: new EdgeInsets.symmetric( - horizontal: 22.0 - dotSize / 2), - child: Icon( - Icons.account_circle, - color: primaryColor, - size: 60, - ), - ), - new Expanded( - child: new Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - new Text( - msg.receiverName, - style: new TextStyle(fontSize: 15.0), - ), - ], - ), - ), - ], - ), - ), - ), - Padding( - padding: const EdgeInsets.only(right: 18.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: Text( - timeFormatter.format(msg.date), - style: TextStyle(color: Colors.grey), - ), - ), - msg.fromToday() - ? Container() - : Text( - dateFormatter.format(msg.date), - style: TextStyle(color: Colors.grey), - ), - ], - ), - ) - ], - ), - ), - ], - ); - }), - ), - ); - } - - _display(Message msg) { - Navigator.push(context, - BottomUpPageRoute(MessageDetail(receiverName: msg.receiverName))); - } -} diff --git a/lib/fcs/common/pages/contact/model/contact_model.dart b/lib/fcs/common/pages/contact/model/contact_model.dart deleted file mode 100644 index 70fbc48..0000000 --- a/lib/fcs/common/pages/contact/model/contact_model.dart +++ /dev/null @@ -1,17 +0,0 @@ -import 'dart:async'; - -import 'package:fcs/fcs/common/domain/vo/contact.dart'; -import 'package:fcs/fcs/common/pages/model/base_model.dart'; -import 'package:fcs/fcs/common/services/services.dart'; -import 'package:logging/logging.dart'; - -class ContactModel extends BaseModel { - final log = Logger('ContactModel'); - - Future saveContact(Contact contact) async { - await request("/contact", "PUT", - payload: contact.toMap(), token: await Services.instance.authService.getToken()); - notifyListeners(); - } - -} diff --git a/lib/fcs/common/pages/contact/widgets.dart b/lib/fcs/common/pages/contact/widgets.dart deleted file mode 100644 index 1c068ca..0000000 --- a/lib/fcs/common/pages/contact/widgets.dart +++ /dev/null @@ -1,97 +0,0 @@ - import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/fcs/common/localization/app_translations.dart'; -import 'package:fcs/fcs/common/pages/widgets/local_text.dart'; -import 'package:flutter/material.dart'; - -Widget itemTitle(BuildContext context, String textKey) { - return Padding( - padding: const EdgeInsets.only(left: 18.0, top: 25, bottom: 5), - child: Text( - AppTranslations.of(context).text(textKey), - style: TextStyle( - fontWeight: FontWeight.bold, fontSize: 18, color: Colors.black), - ), - ); - } - -Widget subItemTitle(BuildContext context, String textKey,{IconData iconData}) { - return Padding( - padding: const EdgeInsets.only(left: 0, top: 0, bottom: 0), - child: Row( - children: [ - Icon(iconData,color: primaryColor,),SizedBox(width:10), - Text( - AppTranslations.of(context).text(textKey), - style: TextStyle( - fontWeight: FontWeight.w700, fontSize: 15, color: primaryColor), - ), - ], - ), - ); - } - - Widget contactItem(BuildContext context, String text, IconData iconData, - {Function() onTap, String labelKey}) { - return Material( - child: Padding( - padding: const EdgeInsets.only(left: 18.0, bottom: 10, right: 18), - child: Container( - decoration: BoxDecoration( - border: Border.all(color: Colors.grey, width: 0.8), - borderRadius: BorderRadius.all( - Radius.circular(5.0) // <--- border radius here - ), - ), - child: InkWell( - onTap: () => onTap != null ? onTap() : null, - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: Row( - children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: Icon( - iconData, - color: primaryColor, - ), - ), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - labelKey == null - ? Container() - : Padding( - padding: EdgeInsets.fromLTRB(10, 10, 10, 0), - child: LocalText(context, labelKey, - color: primaryColor, fontWeight: FontWeight.w500,fontSize: 18), - ), - Padding( - padding: const EdgeInsets.all(8.0), - child: Text( - text == null ? "" : text, - overflow: TextOverflow.ellipsis, - maxLines: 5, - style: TextStyle( - fontSize: 14.0, - ), - ), - ), - ], - ), - SizedBox( - width: 5, - ), - onTap == null - ? Container() - : Icon( - Icons.open_in_new, - color: Colors.grey, - size: 15, - ) - ], - ), - )), - ), - ), - ); - } \ No newline at end of file diff --git a/lib/fcs/common/pages/faq/widgets.dart b/lib/fcs/common/pages/faq/widgets.dart deleted file mode 100644 index 1f7140c..0000000 --- a/lib/fcs/common/pages/faq/widgets.dart +++ /dev/null @@ -1,97 +0,0 @@ - import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/fcs/common/localization/app_translations.dart'; -import 'package:fcs/fcs/common/pages/widgets/local_text.dart'; -import 'package:flutter/material.dart'; - -Widget itemTitle(BuildContext context, String textKey) { - return Padding( - padding: const EdgeInsets.only(left: 18.0, top: 15, bottom: 0), - child: Text( - AppTranslations.of(context).text(textKey), - style: TextStyle( - fontWeight: FontWeight.bold, fontSize: 18, color: Colors.black), - ), - ); - } - -Widget subItemTitle(BuildContext context, String textKey,{IconData iconData}) { - return Padding( - padding: const EdgeInsets.only(left: 0, top: 0, bottom: 0), - child: Row( - children: [ - Icon(iconData,color: primaryColor,),SizedBox(width:10), - Text( - AppTranslations.of(context).text(textKey), - style: TextStyle( - fontWeight: FontWeight.w700, fontSize: 15, color: primaryColor), - ), - ], - ), - ); - } - - Widget contactItem(BuildContext context, String text, IconData iconData, - {Function() onTap, String labelKey}) { - return Material( - child: Padding( - padding: const EdgeInsets.only(left: 18.0, bottom: 10, right: 18), - child: Container( - decoration: BoxDecoration( - border: Border.all(color: Colors.grey, width: 0.8), - borderRadius: BorderRadius.all( - Radius.circular(5.0) // <--- border radius here - ), - ), - child: InkWell( - onTap: () => onTap != null ? onTap() : null, - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: Row( - children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: Icon( - iconData, - color: primaryColor, - ), - ), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - labelKey == null - ? Container() - : Padding( - padding: EdgeInsets.fromLTRB(10, 10, 10, 0), - child: LocalText(context, labelKey, - color: primaryColor, fontWeight: FontWeight.w500,fontSize: 18), - ), - Padding( - padding: const EdgeInsets.all(8.0), - child: Text( - text == null ? "" : text, - overflow: TextOverflow.ellipsis, - maxLines: 5, - style: TextStyle( - fontSize: 14.0, - ), - ), - ), - ], - ), - SizedBox( - width: 5, - ), - onTap == null - ? Container() - : Icon( - Icons.open_in_new, - color: Colors.grey, - size: 15, - ) - ], - ), - )), - ), - ), - ); - } \ No newline at end of file diff --git a/lib/fcs/common/pages/home_page.dart b/lib/fcs/common/pages/home_page.dart deleted file mode 100644 index 9474028..0000000 --- a/lib/fcs/common/pages/home_page.dart +++ /dev/null @@ -1,455 +0,0 @@ -import 'dart:async'; -import 'dart:io'; - -import 'package:fcs/fcs/common/domain/entities/user.dart'; -import 'package:fcs/fcs/common/localization/transalation.dart'; -import 'package:fcs/fcs/common/pages/buying_instruction/buying_online.dart'; -import 'package:fcs/fcs/common/pages/chat/message_detail.dart'; -import 'package:fcs/fcs/common/pages/chat/model/message_model.dart'; -import 'package:fcs/fcs/common/pages/chat/notification_list.dart'; -import 'package:fcs/fcs/common/pages/customer/customer_list.dart'; -import 'package:fcs/fcs/common/pages/customer/model/customer_model.dart'; -import 'package:fcs/fcs/common/pages/faq/faq_list_page.dart'; -import 'package:fcs/fcs/common/pages/model/language_model.dart'; -import 'package:fcs/fcs/common/pages/model/main_model.dart'; -import 'package:fcs/fcs/common/pages/package/package_list.dart'; -import 'package:fcs/fcs/common/pages/payment_methods/payment_method_page.dart'; -import 'package:fcs/fcs/common/pages/staff/staff_list.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/fcs/common/pages/widgets/action_button.dart'; -import 'package:fcs/fcs/common/pages/widgets/badge.dart'; -import 'package:fcs/fcs/common/pages/widgets/bottom_widgets.dart'; -import 'package:fcs/fcs/common/services/services.dart'; -import 'package:fcs/pages/discount_list.dart'; -import 'package:fcs/pages/shipment_list.dart'; -import 'package:fcs/pages/term.dart'; -import 'package:fcs/pages_fcs/box_list.dart'; -import 'package:fcs/pages_fcs/delivery_list.dart'; -import 'package:fcs/widget/banner.dart'; -import 'package:fcs/widget/bottom_up_page_route.dart'; -import 'package:fcs/widget/offline_redirect.dart'; -import 'package:fcs/widget/right_left_page_rout.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_icons/flutter_icons.dart'; -import 'package:flutter_local_notifications/flutter_local_notifications.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -import 'package:intl/intl.dart'; -import 'package:logging/logging.dart'; -import 'package:provider/provider.dart'; - -import '../../../pages/fcs_profile_page.dart'; -import '../../../pages/invoice/invoce_list.dart'; -import '../../../pages/pickup_list.dart'; -import '../../../pages/shipment_rates.dart'; -import '../helpers/theme.dart'; -import 'profile/profile_page.dart'; -import 'signin/signin_page.dart'; - -final msgLog = Logger('backgroundMessageHandler'); - -class HomePage extends StatefulWidget { - @override - _HomePageState createState() => _HomePageState(); -} - -class _HomePageState extends State { - final log = Logger('_HomePageState'); - bool login = false; - bool customer = true; - List isSelected = [true, false]; - static FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin = - FlutterLocalNotificationsPlugin(); - - @override - void initState() { - super.initState(); - MainModel mainModel = Provider.of(context, listen: false); - - Services.instance.messagingService.init( - (message) { - print("Message from FCM:$message"); - _showNotification(message); - }, - onLaunch: (m) => _showNotiContent(m), - onResume: (m) => _showNotiContent(m), - onSetupComplete: (token) { - mainModel.setMessaginToken = token; - }); - _initLocalNotifications(); - } - - String notiUserID, notiUserName; - _showNotiContent(Map message) { - try { - Map map = Map.from(message["data"]); - notiUserID = map['user_id']; - notiUserName = map['user_name']; - _startNotiTimer(); - print("Notification:$map"); - } catch (e) { - print("Error:$e"); - } - } - - _startNotiTimer() async { - var _duration = new Duration(milliseconds: 500); - new Timer.periodic(_duration, (t) => displayNoti(t)); - } - - void displayNoti(Timer timer) async { - MainModel mainModel = Provider.of(context, listen: false); - if (mainModel.isLogin()) { - timer.cancel(); - bool isCustomer = mainModel.isCustomer(); - String receiverID = isCustomer ? mainModel.user.id : notiUserID; - String receiverName = isCustomer ? mainModel.user.name : notiUserName; - MessageModel messageModel = - Provider.of(context, listen: false); - messageModel.initQuery(receiverID); - User user = mainModel.user; - if (!isCustomer) { - CustomerModel customerModel = - Provider.of(context, listen: false); - user = await customerModel.getUser(receiverID); - } - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => MessageDetail( - messageModel: messageModel, - receiverID: receiverID, - receiverName: receiverName, - ))).then((value) { - if (user.userUnseenCount > 0) { - messageModel.seenMessages(user.id, true); - } - }); - if (user.userUnseenCount > 0) { - messageModel.seenMessages(user.id, true); - } - } - } - - _initLocalNotifications() { - var initializationSettingsAndroid = - new AndroidInitializationSettings('@mipmap/ic_launcher'); - var initializationSettingsIOS = new IOSInitializationSettings(); - var initializationSettings = new InitializationSettings( - initializationSettingsAndroid, initializationSettingsIOS); - _flutterLocalNotificationsPlugin.initialize(initializationSettings); - } - - static Future _showNotification(Map message) async { - var pushTitle; - var pushText; - var action; - - if (Platform.isAndroid) { - var nodeData = message['notification']; - pushTitle = nodeData['title']; - pushText = nodeData['body']; - action = nodeData['action']; - } else { - pushTitle = message['title']; - pushText = message['body']; - action = message['action']; - } - print("AppPushs params pushTitle : $pushTitle"); - print("AppPushs params pushText : $pushText"); - print("AppPushs params pushAction : $action"); - - // @formatter:off - var platformChannelSpecificsAndroid = new AndroidNotificationDetails( - 'your channel id', 'your channel name', 'your channel description', - playSound: true, - enableVibration: true, - importance: Importance.Max, - priority: Priority.High); - // @formatter:on - var platformChannelSpecificsIos = - new IOSNotificationDetails(presentSound: true); - var platformChannelSpecifics = new NotificationDetails( - platformChannelSpecificsAndroid, platformChannelSpecificsIos); - - new Future.delayed(Duration.zero, () { - _flutterLocalNotificationsPlugin.show( - 0, - pushTitle, - pushText, - platformChannelSpecifics, - payload: 'No_Sound', - ); - }); - } - - void dispose() { - super.dispose(); - } - - static final List chartDropdownItems = [ - 'Last 7 days', - 'Last month', - 'Last three months' - ]; - String actualDropdown = chartDropdownItems[0]; - int actualChart = 0; - final numberFormatter = new NumberFormat("#,###"); - - String pin; - - @override - Widget build(BuildContext context) { - User user = Provider.of(context).user; - customer = Provider.of(context).isCustomer(); - if (user == null) { - return Container(); - } - - login = Provider.of(context).isLogin(); - LanguageModel languageModel = Provider.of(context); - - final faqBtn = _buildBtn("faq.btn", - icon: MaterialCommunityIcons.frequently_asked_questions, - btnCallback: () => Navigator.of(context).push(CupertinoPageRoute( - builder: (context) => FAQListPage(), - ))); - - final packagesBtn = _buildBtn("package.btn.name", - icon: Octicons.package, - btnCallback: () => Navigator.of(context).push( - CupertinoPageRoute(builder: (context) => PackageList()))); - - final boxesBtn = _buildBtn("boxes.name", - icon: MaterialCommunityIcons.package, - btnCallback: () => - Navigator.of(context).push(BottomUpPageRoute(BoxList()))); - - final pickUpBtn = _buildBtn("pickup", - icon: SimpleLineIcons.direction, - btnCallback: () => - Navigator.of(context).push(BottomUpPageRoute(PickUpList()))); - - final shipmentCostBtn = _buildBtn("rate", - icon: FontAwesomeIcons.calculator, - btnCallback: () => - Navigator.of(context).push(BottomUpPageRoute(ShipmentRates()))); - - final fcsProfileBtn = _buildBtn("fcs.btn", - // imgIcon: Image.asset("assets/logo_btn.png", height: 25,color:Colors.white), - icon: MaterialCommunityIcons.home_city, - btnCallback: () => - Navigator.of(context).push(BottomUpPageRoute(FCSProfilePage()))); - - final shipmentBtn = _buildBtn("shipment.title", - icon: Ionicons.ios_airplane, - imgIcon: Image.asset( - "assets/truck.png", - width: 50, - height: 50, - color: primaryColor, - ), - btnCallback: () => - Navigator.of(context).push(BottomUpPageRoute(ShipmentList()))); - - final buyingBtn = _buildBtn("buy_online", - icon: MaterialCommunityIcons.cart_outline, btnCallback: () { - Navigator.push(context, BottomUpPageRoute(BuyingOnlinePage()) - // MaterialPageRoute(builder: (context) => BuyingOnlinePage()), - ); - }); - - final notiBtnOrg = - _buildBtn("message.btn", icon: Icons.message, btnCallback: () { - MessageModel messageModel = - Provider.of(context, listen: false); - messageModel.initQuery(user.id); - Navigator.push( - context, - BottomUpPageRoute(MessageDetail( - messageModel: messageModel, - )), - ).then((value) { - if (user.userUnseenCount > 0) { - messageModel.seenMessages(user.id, true); - } - }); - if (user.userUnseenCount > 0) { - messageModel.seenMessages(user.id, true); - } - }); - final notiBtn = badgeCounter(notiBtnOrg, user.userUnseenCount); - - final staffBtn = _buildBtn( - "staff.title", - icon: MaterialCommunityIcons.worker, - btnCallback: () => Navigator.of(context).push(CupertinoPageRoute( - builder: (context) => StaffList(), - )), - ); - - final customersBtn = _buildBtn("customers.btn", - icon: Feather.users, - btnCallback: () => Navigator.of(context).push(CupertinoPageRoute( - builder: (context) => CustomerList(), - ))); - - final invoicesBtn = _buildBtn("invoices.btn", - icon: FontAwesomeIcons.fileInvoice, - btnCallback: () => - Navigator.of(context).push(BottomUpPageRoute(InvoiceList()))); - - final paymentMethodBtn = _buildBtn("pm.btn", - icon: FontAwesomeIcons.creditCard, - btnCallback: () => - Navigator.of(context).push(BottomUpPageRoute(PaymentMethodPage()))); - - final discountBtn = _buildBtn("discount.btn", - icon: Entypo.price_ribbon, - btnCallback: () => - Navigator.of(context).push(BottomUpPageRoute(DiscountList()))); - - final termBtn = _buildBtn("term.btn", - icon: FontAwesomeIcons.info, - btnCallback: () => - Navigator.of(context).push(BottomUpPageRoute(Term()))); - final deliveryBtn = _buildBtn("delivery.title", - icon: MaterialCommunityIcons.truck_fast, - btnCallback: () => - Navigator.of(context).push(BottomUpPageRoute(DeliverList()))); - - List widgets = []; - widgets.add(faqBtn); - if (user != null) { - // customer ? widgets.add(buyingBtn) : ""; - // customer || owner ? widgets.add(pickUpBtn) : ""; - // !customer ? widgets.add(shipmentBtn) : ""; - customer ? widgets.add(notiBtn) : ""; - user.hasStaffs() ? widgets.add(staffBtn) : ""; - // owner ? widgets.add(fcsProfileBtn) : ""; - // widgets.add(shipmentCostBtn); - user.hasPackages() ? widgets.add(packagesBtn) : ""; - // owner ? widgets.add(boxesBtn) : ""; - // owner ? widgets.add(deliveryBtn) : ""; - user.hasCustomers() ? widgets.add(customersBtn) : ""; - // customer || owner ? widgets.add(invoicesBtn) : ""; - // widgets.add(paymentMethodBtn); - // owner ? widgets.add(discountBtn) : ""; - // widgets.add(termBtn); - } - return OfflineRedirect( - child: FlavorBanner( - child: Scaffold( - appBar: AppBar( - elevation: 0, - backgroundColor: primaryColor, - title: ClipRRect( - child: Image.asset("assets/logo.jpg", height: 40), - borderRadius: new BorderRadius.circular(30.0), - ), - actions: login - ? [ - ToggleButtons( - children: [ - Image.asset( - 'icons/flags/png/us.png', - package: 'country_icons', - fit: BoxFit.fitWidth, - width: 25, - ), - Image.asset( - 'icons/flags/png/mm.png', - package: 'country_icons', - fit: BoxFit.fitWidth, - width: 25, - ) - ], - onPressed: _langChange, - isSelected: languageModel.currentState, - selectedBorderColor: Colors.white24, - ), - IconButton( - onPressed: () { - Navigator.of(context) - .push(RightLeftPageRoute(Profile())); - }, - iconSize: 30, - icon: Icon(Icons.account_circle), - ), - ] - : [ - ToggleButtons( - children: [ - Image.asset( - 'icons/flags/png/us.png', - package: 'country_icons', - fit: BoxFit.fitWidth, - width: 25, - ), - Image.asset( - 'icons/flags/png/mm.png', - package: 'country_icons', - fit: BoxFit.fitWidth, - width: 25, - ) - ], - onPressed: _langChange, - isSelected: languageModel.currentState, - ), - FlatButton( - onPressed: () { - Navigator.of(context) - .push(BottomUpPageRoute(SigninPage())); - }, - child: Text( - "Sign In", - style: siginButtonStyle, - ), - ), - ]), - body: Container( - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [ - Color(0xd0272262), - Color(0xfa272262), - ], - ), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: ListView(children: [ - Wrap( - alignment: WrapAlignment.start, - children: widgets, - ), - ]), - ), - BottomWidgets(), - ], - ))), - ), - ); - } - - _langChange(index) { - var languageModel = Provider.of(context, listen: false); - languageModel.saveLanguage(Translation().supportedLanguages[index]); - setState(() { - isSelected.asMap().forEach((i, e) { - isSelected[i] = false; - }); - isSelected[index] = !isSelected[index]; - }); - } - - Widget _buildBtn(String title, - {Image imgIcon, IconData icon, BtnCallback btnCallback}) { - return ActionButton( - title: title, imgIcon: imgIcon, icon: icon, btnCallback: btnCallback); - } -} diff --git a/lib/fcs/common/pages/model/base_model.dart b/lib/fcs/common/pages/model/base_model.dart deleted file mode 100644 index 911f5cd..0000000 --- a/lib/fcs/common/pages/model/base_model.dart +++ /dev/null @@ -1,37 +0,0 @@ -import 'package:fcs/fcs/common/domain/entities/setting.dart'; -import 'package:fcs/fcs/common/domain/entities/user.dart'; -import 'package:flutter/foundation.dart'; -import 'package:fcs/fcs/common/helpers/api_helper.dart'; - -import 'main_model.dart'; - -abstract class BaseModel extends ChangeNotifier { - User user; - Setting setting; - MainModel mainModel; - - void initUser(User user) async { - this.user = user; - } - - void initSetting(Setting setting) async { - this.setting = setting; - } - - void logout(){ - - } - -// request makes http request -// if token is null - dynamic request( - String path, - method, { - dynamic payload, - String token, - String url, - }) async { - return await requestAPI(path, method, - payload: payload, token: token, url: url); - } -} diff --git a/lib/fcs/common/pages/package/model/package_model.dart b/lib/fcs/common/pages/package/model/package_model.dart deleted file mode 100644 index f6ab839..0000000 --- a/lib/fcs/common/pages/package/model/package_model.dart +++ /dev/null @@ -1,114 +0,0 @@ -import 'dart:async'; -import 'dart:io'; -import 'package:path/path.dart' as Path; - -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:fcs/fcs/common/domain/constants.dart'; -import 'package:fcs/fcs/common/domain/entities/package.dart'; -import 'package:fcs/fcs/common/domain/entities/user.dart'; -import 'package:fcs/fcs/common/helpers/firebase_helper.dart'; -import 'package:fcs/fcs/common/pages/model/base_model.dart'; -import 'package:fcs/fcs/common/services/services.dart'; -import 'package:logging/logging.dart'; - -class PackageModel extends BaseModel { - final log = Logger('PackageModel'); - - StreamSubscription listener; - List packages = []; - - void initUser(user) { - super.initUser(user); - _loadPackages(); - } - - @override - logout() async { - if (listener != null) await listener.cancel(); - packages = []; - } - - Future _loadPackages() async { - if (user == null) return; - String path = ""; - if (user.isCustomer()) { - path = "/$user_collection/${user.id}/$packages_collection"; - } else { - path = "/$packages_collection"; - } - if (listener != null) listener.cancel(); - packages = []; - - try { - listener = Firestore.instance - .collection("$path") - .where("is_delivered", isEqualTo: false) - .snapshots() - .listen((QuerySnapshot snapshot) { - packages.clear(); - packages = snapshot.documents.map((documentSnapshot) { - var package = Package.fromMap( - documentSnapshot.data, documentSnapshot.documentID); - return package; - }).toList(); - notifyListeners(); - }); - } catch (e) { - log.warning("Error!! $e"); - } - } - - Future getPackage(String id) async { - if (user == null) return null; - String path = ""; - if (user.isCustomer()) { - path = "/$user_collection/${user.id}/$packages_collection"; - } else { - path = "/$packages_collection"; - } - try { - DocumentSnapshot snap = - await Firestore.instance.collection("$path").document(id).get(); - if (snap.exists) { - var package = Package.fromMap(snap.data, snap.documentID); - return package; - } - } catch (e) { - log.warning("Error!! $e"); - } - return null; - } - - Future> searchUser(String term) { - return Services.instance.userService.searchUser(term); - } - - Future> searchPackage(String term) { - return Services.instance.packageService.searchPackage(term); - } - - Future createPackages(User user, List packages) { - return Services.instance.packageService - .createPackages(packages, user.fcsID); - } - - Future completeProcessing( - Package package, List files, List deletedUrls) async { - if (files != null) { - if (files.length > 5) throw Exception("Exceed number of file upload"); - package.photoUrls = package.photoUrls == null ? [] : package.photoUrls; - for (File f in files) { - String path = Path.join(pkg_files_path, package.userID, package.id); - String url = await uploadStorage(path, f); - package.photoUrls.add(url); - } - package.photoUrls.removeWhere((e) => deletedUrls.contains(e)); - } - await request("/packages", "PUT", - payload: package.toJson(), token: await getToken()); - } - - Future deletePackage(Package package) { - return Services.instance.packageService.deletePackage(package); - } -} diff --git a/lib/fcs/common/pages/package/model/shipment_model.dart b/lib/fcs/common/pages/package/model/shipment_model.dart deleted file mode 100644 index 05acdcc..0000000 --- a/lib/fcs/common/pages/package/model/shipment_model.dart +++ /dev/null @@ -1,102 +0,0 @@ -import 'package:fcs/fcs/common/domain/entities/shipment.dart'; -import 'package:fcs/fcs/common/domain/vo/shipping_address.dart'; -import 'package:fcs/fcs/common/pages/model/base_model.dart'; - -class ShipmentModel extends BaseModel { - List shipmentType = ['Air', 'Ship', 'Cargo Truck']; - List shipments = [ - Shipment( - shipDate: DateTime(2020, 4, 23), - shipmentNumber: 'A103B', - status: 'In Progress', - arrivalDate: DateTime(2020, 4, 30), - departureDate: DateTime(2020, 4, 23)), - Shipment( - shipDate: DateTime(2020, 4, 2), - shipmentNumber: 'A100A', - status: 'Ready to ship', - arrivalDate: DateTime(2020, 4, 28), - departureDate: DateTime(2020, 4, 15)), - Shipment( - shipDate: DateTime(2020, 4, 2), - shipmentNumber: 'A100B', - status: 'Arrived', - arrivalDate: DateTime(2020, 4, 28), - departureDate: DateTime(2020, 4, 15)), - Shipment( - shipDate: DateTime(2020, 4, 10), - shipmentNumber: 'A102B', - status: 'Canceled', - arrivalDate: DateTime(2020, 4, 20), - departureDate: DateTime(2020, 4, 10)), - Shipment( - shipDate: DateTime(2020, 4, 2), - shipmentNumber: 'A100B', - status: 'Canceled', - arrivalDate: DateTime(2020, 4, 20), - departureDate: DateTime(2020, 4, 23)), - Shipment( - shipDate: DateTime(2020, 4, 10), - shipmentNumber: 'A102B', - status: 'Arrived', - arrivalDate: DateTime(2020, 4, 30), - departureDate: DateTime(2020, 4, 20), - ) - ]; - - List get canceled { - List _p = shipments.where((e) => e.status == "Canceled").toList() - ..sort((e1, e2) { - return e1.shipDate.compareTo(e2.shipDate); - }); - return _p; - } - - List get completed { - return shipments.where((e) => e.status == "Arrived").toList() - ..sort((e1, e2) { - return e1.shipDate.compareTo(e2.shipDate); - }); - } - - List get upcoming { - List _shipments = shipments - .where((e) => - e.status == "In Progress" || - e.status == "Ready to ship" || - e.status == "Processed" || - e.status == "Rescheduled") - .toList(); - - _shipments.sort((e1, e2) { - return e1.shipDate.compareTo(e2.shipDate); - }); - return _shipments; - } - - List shippingAddresses = [ - ShippingAddress( - fullName: 'U Nyi Nyi', - addressLine1: '154-19 64th Ave.', - addressLine2: 'Flushing', - city: 'NY', - state: 'NY', - phoneNumber: '+1 (292)215-2247'), - ShippingAddress( - fullName: 'Mg Myo', - addressLine1: '153-154 5th Thitsar.', - addressLine2: 'South Okkalapa Township', - city: 'Yangon', - state: 'Myanmar', - phoneNumber: '+09 95724 8750'), - ]; - - void initUser(user) { - super.initUser(user); - } - - @override - logout() async { - shipments = []; - } -} diff --git a/lib/fcs/common/pages/package/package_info.dart b/lib/fcs/common/pages/package/package_info.dart deleted file mode 100644 index 222614c..0000000 --- a/lib/fcs/common/pages/package/package_info.dart +++ /dev/null @@ -1,211 +0,0 @@ -import 'package:fcs/fcs/common/domain/entities/package.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/fcs/common/pages/model/main_model.dart'; -import 'package:fcs/fcs/common/pages/package/package_editor.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/fcs/common/pages/widgets/bottom_up_page_route.dart'; -import 'package:fcs/fcs/common/pages/widgets/display_text.dart'; -import 'package:fcs/fcs/common/pages/widgets/local_text.dart'; -import 'package:fcs/fcs/common/pages/widgets/multi_img_controller.dart'; -import 'package:fcs/fcs/common/pages/widgets/multi_img_file.dart'; -import 'package:fcs/fcs/common/pages/widgets/progress.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_icons/flutter_icons.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; -import 'package:timeline_list/timeline.dart'; -import 'package:timeline_list/timeline_model.dart'; - -import 'model/package_model.dart'; - -final DateFormat dateFormat = DateFormat("d MMM yyyy"); - -class PackageInfo extends StatefulWidget { - final Package package; - PackageInfo({this.package}); - - @override - _PackageInfoState createState() => _PackageInfoState(); -} - -class _PackageInfoState extends State { - var dateFormatter = new DateFormat('dd MMM yyyy'); - Package _package; - bool _isLoading = false; - MultiImgController multiImgController = MultiImgController(); - - @override - void initState() { - super.initState(); - initPackage(widget.package); - } - - initPackage(Package package) { - setState(() { - _package = package; - multiImgController.setImageUrls = package.photoUrls; - }); - } - - @override - void dispose() { - super.dispose(); - } - - @override - Widget build(BuildContext context) { - bool isCustomer = Provider.of(context).isCustomer(); - - final trackingIdBox = DisplayText( - text: _package.trackingID, - labelText: getLocalString(context, "package.tracking.id"), - iconData: MaterialCommunityIcons.barcode_scan, - ); - final customerNameBox = DisplayText( - text: _package.userName, - labelText: getLocalString(context, "package.create.name"), - iconData: Icons.perm_identity, - ); - final statusBox = DisplayText( - text: _package.currentStatus, - labelText: getLocalString(context, "package.edit.status"), - iconData: AntDesign.exclamationcircleo, - ); - final marketBox = DisplayText( - text: _package.market ?? "-", - labelText: getLocalString(context, "package.create.market"), - iconData: Icons.store, - ); - final descBox = DisplayText( - text: _package.desc ?? "-", - labelText: getLocalString(context, "package.edit.desc"), - iconData: MaterialCommunityIcons.message_text_outline, - ); - final remarkBox = DisplayText( - text: _package.remark ?? "-", - labelText: getLocalString(context, "package.edit.remark"), - iconData: Entypo.new_message, - ); - final img = MultiImageFile( - enabled: false, - controller: multiImgController, - title: "Receipt File", - ); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - centerTitle: true, - leading: new IconButton( - icon: new Icon(Icons.close, color: primaryColor, size: 30), - onPressed: () => Navigator.of(context).pop(), - ), - shadowColor: Colors.transparent, - backgroundColor: Colors.white, - title: LocalText( - context, - "package.info.title", - fontSize: 20, - color: primaryColor, - ), - actions: [ - isCustomer - ? Container() - : IconButton( - icon: Icon(Icons.edit, color: primaryColor), - onPressed: _gotoEditor, - ) - ], - ), - body: Card( - child: Column( - children: [ - Expanded( - child: Padding( - padding: const EdgeInsets.all(10.0), - child: ListView(children: [ - trackingIdBox, - customerNameBox, - marketBox, - statusBox, - _package.photoUrls.length == 0 ? Container() : img, - descBox, - remarkBox, - ExpansionTile( - initiallyExpanded: true, - title: Text( - 'Status', - style: TextStyle( - color: primaryColor, fontWeight: FontWeight.bold), - ), - children: [ - Container( - padding: EdgeInsets.only(left: 20), - height: 400, - child: Timeline( - children: _models(), - position: TimelinePosition.Left), - ), - ], - ), - SizedBox( - height: 20, - ) - ]), - )), - ], - ), - ), - ), - ); - } - - List _models() { - if (_package.shipmentHistory == null) return []; - return _package.shipmentHistory - .map((e) => TimelineModel( - Padding( - padding: const EdgeInsets.all(18.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(e.status, - style: TextStyle( - color: e.done ? primaryColor : Colors.grey, - fontSize: 16, - fontWeight: FontWeight.bold)), - Text(dateFormat.format(e.date)), - ], - ), - ), - iconBackground: e.done ? primaryColor : Colors.grey, - icon: Icon( - e.status == "shipped" - ? Ionicons.ios_airplane - : e.status == "delivered" - ? MaterialCommunityIcons.truck_fast - : e.status == "processed" - ? MaterialIcons.check - : Octicons.package, - color: Colors.white, - ))) - .toList(); - } - - _gotoEditor() async { - bool deleted = await Navigator.push( - context, - BottomUpPageRoute(PackageEditorPage( - package: widget.package, - ))); - if (deleted ?? false) { - Navigator.pop(context); - } else { - PackageModel packageModel = - Provider.of(context, listen: false); - Package p = await packageModel.getPackage(_package.id); - initPackage(p); - } - } -} diff --git a/lib/fcs/common/pages/package/shipping_address_editor.dart b/lib/fcs/common/pages/package/shipping_address_editor.dart deleted file mode 100644 index 9846070..0000000 --- a/lib/fcs/common/pages/package/shipping_address_editor.dart +++ /dev/null @@ -1,139 +0,0 @@ -import 'package:fcs/fcs/common/domain/vo/shipping_address.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/fcs/common/pages/widgets/local_text.dart'; -import 'package:fcs/fcs/common/pages/widgets/progress.dart'; -import 'package:flutter_icons/flutter_icons.dart'; -import 'package:flutter/material.dart'; - -class ShippingAddressEditor extends StatefulWidget { - final ShippingAddress shippingAddress; - ShippingAddressEditor({this.shippingAddress}); - - @override - _ShippingAddressEditorState createState() => _ShippingAddressEditorState(); -} - -class _ShippingAddressEditorState extends State { - TextEditingController _nameController = new TextEditingController(); - TextEditingController _address1Controller = new TextEditingController(); - TextEditingController _address2Controller = new TextEditingController(); - TextEditingController _cityController = new TextEditingController(); - TextEditingController _stateController = new TextEditingController(); - TextEditingController _phoneController = new TextEditingController(); - - ShippingAddress _shippingAddress = new ShippingAddress(); - - bool _isLoading = false; - - @override - void initState() { - super.initState(); - if (widget.shippingAddress != null) { - _shippingAddress = widget.shippingAddress; - _nameController.text = _shippingAddress.fullName; - _address1Controller.text = _shippingAddress.addressLine1; - _address2Controller.text = _shippingAddress.addressLine2; - _cityController.text = _shippingAddress.city; - _stateController.text = _shippingAddress.state; - _phoneController.text = _shippingAddress.phoneNumber; - } - } - - @override - void dispose() { - super.dispose(); - } - - @override - Widget build(BuildContext context) { - final usaAddress = - fcsInput('Full Name', Icons.text_format, controller: _nameController); - final mmAddress = fcsInput('Address Line 1', Icons.location_on, - controller: _address1Controller); - - final contactNumber = fcsInput('Address Line 2', Icons.location_on, - controller: _address2Controller); - final mmContactNumber = - fcsInput('City', Icons.location_city, controller: _cityController); - - final mailBox = - fcsInput('State/Region', Entypo.location, controller: _stateController); - final fbLinkBox = - fcsInput('Phone Number', Icons.phone, controller: _phoneController); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - centerTitle: true, - leading: new IconButton( - icon: new Icon(Icons.close), - onPressed: () => Navigator.of(context).pop(), - ), - backgroundColor: primaryColor, - title: LocalText( - context, - 'user.form.shipping_address', - color: Colors.white, - fontSize: 20, - ), - ), - body: Card( - child: Column( - children: [ - Expanded( - child: Padding( - padding: const EdgeInsets.only(left: 10.0, right: 10), - child: ListView(children: [ - usaAddress, - SizedBox(height: 10), - mmAddress, - SizedBox(height: 10), - contactNumber, - SizedBox(height: 10), - mmContactNumber, - SizedBox(height: 10), - mailBox, - SizedBox(height: 10), - fbLinkBox, - SizedBox(height: 10), - ]), - )), - widget.shippingAddress == null - ? Align( - alignment: Alignment.bottomCenter, - child: Center( - child: Container( - width: 250, - child: FlatButton( - child: Text('Create'), - color: primaryColor, - textColor: Colors.white, - onPressed: () { - Navigator.pop(context); - }, - ), - ))) - : Align( - alignment: Alignment.bottomCenter, - child: Center( - child: Container( - width: 250, - child: FlatButton( - child: Text('Update'), - color: primaryColor, - textColor: Colors.white, - onPressed: () { - Navigator.pop(context); - }, - ), - ))), - SizedBox(height: 10) - ], - ), - ), - ), - ); - } -} diff --git a/lib/fcs/common/pages/package/shipping_address_list.dart b/lib/fcs/common/pages/package/shipping_address_list.dart deleted file mode 100644 index 90ff149..0000000 --- a/lib/fcs/common/pages/package/shipping_address_list.dart +++ /dev/null @@ -1,112 +0,0 @@ -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/fcs/common/pages/widgets/local_text.dart'; -import 'package:fcs/model/shipment_model.dart'; - -import 'package:fcs/pages/search_page.dart'; -import 'package:fcs/pages_fcs/shipping_address_row.dart'; -import 'package:fcs/vo/shipping_address.dart'; -import 'package:fcs/widget/bottom_up_page_route.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:fcs/widget/progress.dart'; -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; - -class ShippingAddressList extends StatefulWidget { - @override - _ShippingAddressListState createState() => _ShippingAddressListState(); -} - -class _ShippingAddressListState extends State { - bool _isLoading = false; - - @override - void initState() { - super.initState(); - } - - @override - void dispose() { - super.dispose(); - } - - @override - Widget build(BuildContext context) { - var shipmentModel = Provider.of(context); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - centerTitle: true, - leading: new IconButton( - icon: new Icon(Icons.close), - onPressed: () => Navigator.of(context).pop(), - ), - backgroundColor: primaryColor, - title: LocalText( - context, - "shipping_addresses", - fontSize: 20, - color: Colors.white, - ), - actions: [ - IconButton( - icon: Icon( - Icons.search, - color: Colors.white, - ), - iconSize: 30, - onPressed: () => showPlacesSearch(context), - ), - ], - ), - body: Column( - children: [ - Expanded( - child: Column( - children: - getAddressList(context, shipmentModel.shippingAddresses), - ), - ), - Container( - padding: EdgeInsets.only(top: 20, bottom: 15, right: 15), - child: Align( - alignment: Alignment.bottomRight, - child: Container( - width: 130, - height: 40, - child: FloatingActionButton.extended( - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - onPressed: () { - Navigator.push( - context, - BottomUpPageRoute(ShippingAddressList()), - ); - }, - icon: Icon(Icons.add), - label: Text( - 'Add New\nAddress', - style: TextStyle(fontSize: 12), - ), - backgroundColor: primaryColor, - ), - ), - ), - ), - ], - )), - ); - } - - List getAddressList( - BuildContext context, List addresses) { - return addresses.asMap().entries.map((s) { - return InkWell( - onTap: () { - Navigator.pop(context, s.value); - }, - child: ShippingAddressRow(shippingAddress: s.value, index: s.key), - ); - }).toList(); - } -} diff --git a/lib/fcs/common/pages/package/shipping_address_row.dart b/lib/fcs/common/pages/package/shipping_address_row.dart deleted file mode 100644 index 537272e..0000000 --- a/lib/fcs/common/pages/package/shipping_address_row.dart +++ /dev/null @@ -1,121 +0,0 @@ -import 'package:fcs/fcs/common/domain/vo/shipping_address.dart'; -import 'package:fcs/fcs/common/pages/package/model/shipment_model.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; - -class ShippingAddressRow extends StatelessWidget { - final ShippingAddress shippingAddress; - final int index; - - const ShippingAddressRow({Key key, this.shippingAddress, this.index}) - : super(key: key); - - @override - Widget build(BuildContext context) { - var shipmentModel = Provider.of(context); - return Container( - padding: EdgeInsets.only(left: 10, right: 10), - child: Column( - children: [ - Row( - children: [ - Expanded( - child: new Padding( - padding: const EdgeInsets.symmetric(vertical: 10.0), - child: Row( - children: [ - // Padding( - // padding: EdgeInsets.all(5.0), - // child: Icon( - // SimpleLineIcons.location_pin, - // color: primaryColor, - // )), - new Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.only(left: 8.0), - child: new Text( - shippingAddress.fullName == null - ? '' - : shippingAddress.fullName, - style: new TextStyle( - fontSize: 15.0, - color: Colors.black, - fontWeight: FontWeight.bold), - ), - ), - Padding( - padding: const EdgeInsets.only(left: 8.0), - child: new Text( - shippingAddress.addressLine1 == null - ? '' - : shippingAddress.addressLine1, - style: new TextStyle( - fontSize: 14.0, color: Colors.grey), - ), - ), - Padding( - padding: const EdgeInsets.only(left: 8.0), - child: new Text( - shippingAddress.addressLine2 == null - ? '' - : shippingAddress.addressLine2, - style: new TextStyle( - fontSize: 14.0, color: Colors.grey), - ), - ), - Padding( - padding: const EdgeInsets.only(left: 8.0), - child: new Text( - shippingAddress.city == null - ? '' - : shippingAddress.city, - style: new TextStyle( - fontSize: 14.0, color: Colors.grey), - ), - ), - Padding( - padding: const EdgeInsets.only(left: 8.0), - child: new Text( - shippingAddress.state == null - ? '' - : shippingAddress.state, - style: new TextStyle( - fontSize: 14.0, color: Colors.grey), - ), - ), - Padding( - padding: const EdgeInsets.only(left: 8.0), - child: new Text( - shippingAddress.phoneNumber == null - ? '' - : "Phone:${shippingAddress.phoneNumber}", - style: new TextStyle( - fontSize: 14.0, color: Colors.grey), - ), - ), - ], - ), - ], - ), - ), - ), - // IconButton( - // padding: EdgeInsets.only(right: 30), - // icon: Icon(Icons.delete, color: Colors.black45), - // onPressed: null) - ], - ), - index == null - ? Container() - : index == shipmentModel.shippingAddresses.length - 1 - ? Container() - : Divider(color: Colors.black) - ], - ), - ); - } -} diff --git a/lib/fcs/common/pages/profile/profile_page.dart b/lib/fcs/common/pages/profile/profile_page.dart deleted file mode 100644 index 22eaf59..0000000 --- a/lib/fcs/common/pages/profile/profile_page.dart +++ /dev/null @@ -1,336 +0,0 @@ -import 'package:fcs/fcs/common/localization/app_translations.dart'; -import 'package:fcs/fcs/common/localization/transalation.dart'; -import 'package:fcs/fcs/common/pages/model/language_model.dart'; -import 'package:fcs/fcs/common/pages/model/main_model.dart'; -import 'package:fcs/fcs/common/pages/profile/profile_edit.dart'; -import 'package:fcs/fcs/common/pages/widgets/display_text.dart'; -import 'package:fcs/fcs/common/pages/widgets/fcs_id_icon.dart'; -import 'package:fcs/fcs/common/pages/widgets/local_text.dart'; -import 'package:fcs/fcs/common/pages/widgets/progress.dart'; -import 'package:fcs/model/shipment_model.dart'; -import 'package:fcs/model/user_model.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/pages_fcs/shipping_address_row.dart'; -import 'package:fcs/vo/role.dart'; -import 'package:fcs/vo/shipping_address.dart'; -import 'package:fcs/widget/bottom_up_page_route.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:provider/provider.dart'; - -import '../../../../pages/shipping_address_editor.dart'; -import '../../helpers/theme.dart'; - -typedef void ProfileCallback(); - -class Profile extends StatefulWidget { - @override - _ProfileState createState() => _ProfileState(); -} - -class _ProfileState extends State { - GlobalKey key = GlobalKey(); - bool _isLoading = false; - String selectedLanguage; - TextEditingController bizNameController = new TextEditingController(); - - static final List languagesList = Translation().supportedLanguages; - static final List languageCodesList = - Translation().supportedLanguagesCodes; - - final Map languagesMap = { - languagesList[0]: languageCodesList[0], - languagesList[1]: languageCodesList[1], - }; - - buildLanguage(LanguageModel languageModel) async { - var lan = await languageModel.load(); - if (this.selectedLanguage != lan) { - setState(() { - this.selectedLanguage = lan; - }); - } - } - - @override - Widget build(BuildContext context) { - MainModel mainModel = Provider.of(context); - if (mainModel.user == null) { - return Container(); - } - final namebox = DisplayText( - text: mainModel.user.name, - labelText: getLocalString(context, "profile.name"), - iconData: Icons.person, - ); - - final phonenumberbox = DisplayText( - text: mainModel.user.phone, - labelText: getLocalString(context, "profile.phone"), - iconData: Icons.phone, - ); - final fcsIDBox = Row( - children: [ - Expanded( - child: DisplayText( - text: mainModel.user.fcsID, - labelText: getLocalString(context, "customer.fcs.id"), - icon: FcsIDIcon(), - ), - ), - IconButton( - icon: Icon(Icons.content_copy, color: Colors.grey), - onPressed: () => _copy( - getLocalString(context, "customer.fcs.id"), mainModel.user.fcsID), - ) - ], - ); - final usaShippingAddressBox = Row( - children: [ - Expanded( - child: DisplayText( - text: mainModel.setting.usaAddress, - labelText: getLocalString(context, "profile.usa.shipping.address"), - iconData: Icons.location_on, - ), - ), - IconButton( - icon: Icon(Icons.content_copy, color: Colors.grey), - onPressed: () => _copy( - getLocalString(context, "profile.usa.shipping.address"), - mainModel.setting.usaAddress), - ) - ], - ); - - final logoutbutton = fcsButton( - context, getLocalString(context, "profile.logout"), - callack: _logout, iconData: Icons.exit_to_app); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - key: key, - appBar: AppBar( - centerTitle: true, - leading: IconButton( - icon: Icon( - CupertinoIcons.back, - size: 35, - color: primaryColor, - ), - onPressed: () => Navigator.of(context).pop(), - ), - title: LocalText( - context, - "profile.title", - fontSize: 20, - color: primaryColor, - ), - shadowColor: Colors.transparent, - backgroundColor: Colors.white, - actions: [], - ), - body: Padding( - padding: const EdgeInsets.all(8.0), - child: Column( - children: [ - Expanded( - child: ListView( - shrinkWrap: true, - children: [ - Row( - children: [ - Expanded(child: namebox), - Padding( - padding: const EdgeInsets.only(right: 0), - child: IconButton( - icon: Icon(Icons.edit, color: Colors.grey), - onPressed: _editName), - ) - ], - ), - // mainModel.isCustomer() - // ? Container() - // : getPrivilegeBox(context), - phonenumberbox, - fcsIDBox, - usaShippingAddressBox, - DisplayText( - text: mainModel.user.status, - labelText: getLocalString(context, "customer.status"), - iconData: Icons.add_alarm, - ), - // getShippingAddressList(context), - ], - ), - ), - logoutbutton, - SizedBox(height: 25) - ], - ), - ), - ), - ); - } - - Widget getShippingAddressList(BuildContext context) { - var shipmentModel = Provider.of(context); - return Container( - padding: EdgeInsets.only(top: 5, left: 10), - child: ExpansionTile( - title: Text( - "My Addresses", - style: TextStyle( - fontWeight: FontWeight.bold, fontStyle: FontStyle.normal), - ), - children: [ - Column( - children: getAddressList(context, shipmentModel.shippingAddresses), - ), - Container( - padding: EdgeInsets.only(top: 20, bottom: 15, right: 15), - child: Align( - alignment: Alignment.bottomRight, - child: Container( - width: 130, - height: 40, - child: FloatingActionButton.extended( - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - onPressed: () { - Navigator.push( - context, - BottomUpPageRoute(ShippingAddressEditor()), - ); - }, - icon: Icon(Icons.add), - label: Text( - 'Add New\nAddress', - style: TextStyle(fontSize: 12), - ), - backgroundColor: primaryColor, - ), - ), - ), - ) - ], - ), - ); - } - - List getAddressList( - BuildContext context, List addresses) { - return addresses.asMap().entries.map((s) { - return InkWell( - onTap: () { - Navigator.push( - context, - BottomUpPageRoute(ShippingAddressEditor(shippingAddress: s.value)), - ); - }, - child: ShippingAddressRow(shippingAddress: s.value, index: s.key), - ); - }).toList(); - } - - Widget getPrivilegeBox(BuildContext context) { - var languageModel = Provider.of(context); - var userModel = Provider.of(context); - - return ListTileTheme( - contentPadding: EdgeInsets.all(0), - child: ExpansionTile( - title: Text( - AppTranslations.of(context).text("profile.privilege"), - style: languageModel.isEng - ? TextStyle( - fontSize: 16.0, - fontWeight: FontWeight.bold, - fontStyle: FontStyle.normal, - ) - : TextStyle( - fontSize: 15.0, - fontWeight: FontWeight.bold, - fontStyle: FontStyle.normal, - fontFamily: "MyanmarUnicode"), - ), - children: [ - Align( - alignment: Alignment.topLeft, - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: - getRowPrivilegeWidget(userModel.getUserPrivileges())), - ), - ) - ], - ), - ); - } - - List getRowPrivilegeWidget(List privileges) { - return privileges.map((p) { - return Container( - padding: EdgeInsets.all(8.0), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(p.name, - style: TextStyle(fontSize: 16.0, fontStyle: FontStyle.normal)), - SizedBox( - width: 30, - ), - Container( - child: Text( - "- ${p.desc}", - style: TextStyle(fontSize: 16.0, fontStyle: FontStyle.normal), - ), - ) - ], - ), - ); - }).toList(); - } - - _copy(String title, String data) { - Clipboard.setData(ClipboardData(text: data)); - _showToast(title); - } - - void _showToast(String title) { - final ScaffoldState scaffold = key.currentState; - scaffold.showSnackBar( - SnackBar( - content: Text('copied "$title" data to clipboard'), - backgroundColor: secondaryColor, - duration: Duration(seconds: 1), - ), - ); - } - - _editName() { - Navigator.of(context) - .push(CupertinoPageRoute(builder: (context) => ProfileEdit())); - } - - _logout() { - showConfirmDialog(context, "profile.logout.confirm", () async { - setState(() { - _isLoading = true; - }); - await context.read().signout(); - Navigator.of(context) - .pushNamedAndRemoveUntil("/welcome", ModalRoute.withName('/welcome')); - Future.delayed(Duration(seconds: 1), () { - if (mounted) { - setState(() { - _isLoading = false; - }); - } - }); - }); - } -} diff --git a/lib/fcs/common/pages/signin/signin_logic.dart b/lib/fcs/common/pages/signin/signin_logic.dart deleted file mode 100644 index 6e48b85..0000000 --- a/lib/fcs/common/pages/signin/signin_logic.dart +++ /dev/null @@ -1,31 +0,0 @@ -import 'package:fcs/fcs/common/domain/entities/setting.dart'; -import 'package:fcs/fcs/common/domain/entities/user.dart'; -import 'package:fcs/fcs/common/pages/model/main_model.dart'; -import 'package:fcs/fcs/common/pages/signin/invitation_request_page.dart'; -import 'package:fcs/fcs/common/pages/signin/signup_page.dart'; -import 'package:fcs/fcs/common/pages/widgets/bottom_up_page_route.dart'; -import 'package:flutter/widgets.dart'; -import 'package:provider/provider.dart'; - -navigateAfterAuthVerified(BuildContext context) async { - User user = Provider.of(context, listen: false).user; - Setting setting = Provider.of(context, listen: false).setting; - - if (user == null || setting == null) return; - - if (user.joined || user.requested) { - Navigator.pushNamedAndRemoveUntil(context, "/home", (r) => false); - } else { - if (setting.inviteRequired) { - bool invited = - await Provider.of(context, listen: false).hasInvite(); - if (!invited) { - await Navigator.of(context).pushAndRemoveUntil( - BottomUpPageRoute(RequestInvitationPage()), (r) => false); - return; - } - } - await Navigator.of(context) - .pushAndRemoveUntil(BottomUpPageRoute(SignupPage()), (r) => false); - } -} diff --git a/lib/fcs/common/pages/staff/staff_list.dart b/lib/fcs/common/pages/staff/staff_list.dart deleted file mode 100644 index c67d1ed..0000000 --- a/lib/fcs/common/pages/staff/staff_list.dart +++ /dev/null @@ -1,125 +0,0 @@ -import 'package:fcs/fcs/common/domain/entities/user.dart'; -import 'package:fcs/fcs/common/localization/app_translations.dart'; -import 'package:fcs/fcs/common/pages/staff/model/staff_model.dart'; -import 'package:fcs/fcs/common/pages/widgets/bottom_up_page_route.dart'; -import 'package:fcs/fcs/common/pages/widgets/local_text.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/fcs/common/pages/widgets/progress.dart'; -import 'package:flutter/cupertino.dart'; - -import 'package:flutter/material.dart'; -import 'package:flutter_icons/flutter_icons.dart'; -import 'package:intl/intl.dart'; - -import 'package:provider/provider.dart'; -import 'staff_editor.dart'; - -class StaffList extends StatefulWidget { - @override - _StaffListState createState() => _StaffListState(); -} - -class _StaffListState extends State { - var dateFormatter = new DateFormat('dd MMM yyyy - hh:mm:ss a'); - final double dotSize = 15.0; - bool _isLoading = false; - - @override - Widget build(BuildContext context) { - StaffModel staffModel = Provider.of(context); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - centerTitle: true, - leading: new IconButton( - icon: new Icon(CupertinoIcons.back), - onPressed: () => Navigator.of(context).pop(), - ), - backgroundColor: primaryColor, - title: LocalText( - context, - 'staff.list.title', - color: Colors.white, - fontSize: 20, - ), - ), - floatingActionButton: FloatingActionButton.extended( - onPressed: () { - Navigator.of(context).push(BottomUpPageRoute(StaffEditor())); - }, - icon: Icon(Icons.add), - label: LocalText(context, "staff.new", color: Colors.white), - backgroundColor: primaryColor, - ), - body: new ListView.separated( - separatorBuilder: (context, index) => Divider( - color: Colors.black, - ), - scrollDirection: Axis.vertical, - padding: EdgeInsets.only(left: 5, right: 5, top: 5), - shrinkWrap: true, - itemCount: staffModel.employees.length, - itemBuilder: (BuildContext context, int index) { - User user = staffModel.employees[index]; - return _item(user); - }), - ), - ); - } - - Widget _item(User user) { - return Stack( - children: [ - InkWell( - onTap: () { - Navigator.of(context) - .push(BottomUpPageRoute(StaffEditor(staff: user))); - }, - child: Row( - children: [ - Expanded( - child: new Padding( - padding: const EdgeInsets.symmetric(vertical: 10.0), - child: new Row( - children: [ - new Padding( - padding: new EdgeInsets.symmetric( - horizontal: 32.0 - dotSize / 2), - child: Icon( - MaterialCommunityIcons.worker, - color: primaryColor, - size: 40, - ), - ), - new Expanded( - child: new Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - new Text( - user.name, - style: new TextStyle(fontSize: 15.0), - ), - Padding( - padding: const EdgeInsets.only(top: 8.0), - child: new Text( - user.phoneNumber, - style: new TextStyle( - fontSize: 15.0, color: Colors.grey), - ), - ), - ], - ), - ), - ], - ), - ), - ), - ], - ), - ), - ], - ); - } -} diff --git a/lib/fcs/common/pages/term/model/term_model.dart b/lib/fcs/common/pages/term/model/term_model.dart deleted file mode 100644 index 2fe8ee2..0000000 --- a/lib/fcs/common/pages/term/model/term_model.dart +++ /dev/null @@ -1,16 +0,0 @@ -import 'dart:async'; - -import 'package:fcs/fcs/common/domain/vo/term.dart'; -import 'package:fcs/fcs/common/pages/model/base_model.dart'; -import 'package:fcs/fcs/common/services/services.dart'; -import 'package:logging/logging.dart'; - -class TermModel extends BaseModel { - final log = Logger('TermModel'); - - Future saveTerm(Term term) async { - await request("/terms", "PUT", - payload: term.toMap(), - token: await Services.instance.authService.getToken()); - } -} diff --git a/lib/fcs/common/pages/widgets/show_img.dart b/lib/fcs/common/pages/widgets/show_img.dart deleted file mode 100644 index dc955c0..0000000 --- a/lib/fcs/common/pages/widgets/show_img.dart +++ /dev/null @@ -1,35 +0,0 @@ -import 'dart:io'; - -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:flutter/material.dart'; -import 'package:photo_view/photo_view.dart'; - -class ShowImage extends StatefulWidget { - final String url; - final File imageFile; - final String fileName; - const ShowImage({Key key, this.imageFile, this.fileName, this.url}) - : super(key: key); - @override - _ShowImageState createState() => _ShowImageState(); -} - -class _ShowImageState extends State { - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - title: Text(widget.fileName), - ), - body: Center( - child: widget.url != null || widget.imageFile != null - ? PhotoView( - imageProvider: widget.url != null - ? NetworkImage(widget.url) - : FileImage(widget.imageFile), - minScale: PhotoViewComputedScale.contained * 1) - : Container()), - ); - } -} diff --git a/lib/fcs/common/pages/widgets/show_multiple_img.dart b/lib/fcs/common/pages/widgets/show_multiple_img.dart deleted file mode 100644 index 434ffbd..0000000 --- a/lib/fcs/common/pages/widgets/show_multiple_img.dart +++ /dev/null @@ -1,57 +0,0 @@ -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/fcs/common/pages/widgets/display_image_source.dart'; -import 'package:flutter/material.dart'; -import 'package:photo_view/photo_view.dart'; -import 'package:photo_view/photo_view_gallery.dart'; - -class ShowMultiImage extends StatefulWidget { - final List displayImageSources; - final int initialPage; - const ShowMultiImage( - {Key key, this.displayImageSources, this.initialPage = 0}) - : super(key: key); - @override - _ShowMultiImageState createState() => _ShowMultiImageState(); -} - -class _ShowMultiImageState extends State { - PageController pageController; - @override - void initState() { - pageController = PageController(initialPage: widget.initialPage); - super.initState(); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - body: Container( - child: PhotoViewGallery.builder( - scrollPhysics: const BouncingScrollPhysics(), - builder: (BuildContext context, int index) { - return PhotoViewGalleryPageOptions( - imageProvider: widget.displayImageSources[index].imageProvider, - initialScale: PhotoViewComputedScale.contained * 0.8, - heroAttributes: PhotoViewHeroAttributes( - tag: widget.displayImageSources[index].hashCode), - ); - }, - itemCount: widget.displayImageSources.length, - loadingBuilder: (context, event) => Center( - child: Container( - width: 20.0, - height: 20.0, - child: CircularProgressIndicator( - value: event == null - ? 0 - : event.cumulativeBytesLoaded / event.expectedTotalBytes, - ), - ), - ), - backgroundDecoration: const BoxDecoration( - color: primaryColor, - ), - pageController: pageController, - ))); - } -} diff --git a/lib/fcs/common/services/auth_imp.dart b/lib/fcs/common/services/auth_imp.dart deleted file mode 100644 index 2fff912..0000000 --- a/lib/fcs/common/services/auth_imp.dart +++ /dev/null @@ -1,79 +0,0 @@ -import 'package:fcs/fcs/common/data/providers/auth_fb.dart'; -import 'package:fcs/fcs/common/data/providers/user_data_provider.dart'; -import 'package:fcs/fcs/common/domain/entities/auth_result.dart'; -import 'package:fcs/fcs/common/domain/entities/connectivity.dart'; -import 'package:fcs/fcs/common/domain/entities/setting.dart'; -import 'package:fcs/fcs/common/domain/entities/user.dart'; -import 'package:flutter/material.dart'; - -import 'auth_service.dart'; - -class AuthServiceImp implements AuthService { - AuthServiceImp({ - @required this.authFb, - @required this.connectivity, - }); - - final Connectivity connectivity; - final AuthFb authFb; - - @override - Future sendSmsCodeToPhoneNumber(String phoneNumber) { - return authFb.sendSmsCodeToPhoneNumber(phoneNumber); - } - - @override - Future signInWithSmsCode(String smsCode) { - return authFb.signInWithPhoneNumber(smsCode); - } - - @override - Future signout() { - return authFb.signout(); - } - - @override - Future getUser({bool refreshIdToken = false}) { - return authFb.getUser(refreshIdToken: refreshIdToken); - } - - @override - Stream getUserStream(String userID) { - return authFb.user(userID); - } - - @override - Stream getSetting() { - return authFb.settings(); - } - - @override - Future signup(String userName) { - return authFb.signup(userName); - } - - @override - Future joinInvite(String userName) { - return authFb.joinInvite(userName); - } - - @override - Stream onAuthStatus() { - return authFb.onAuthStatus; - } - - @override - Future getToken() { - return authFb.getToken(); - } - - @override - Future hasInvite() { - return authFb.hasInvite(); - } - - @override - Future updateProfile(String newUserName) { - return authFb.updateProfile(newUserName); - } -} diff --git a/lib/fcs/common/services/auth_service.dart b/lib/fcs/common/services/auth_service.dart deleted file mode 100644 index 1d3ddc9..0000000 --- a/lib/fcs/common/services/auth_service.dart +++ /dev/null @@ -1,18 +0,0 @@ -import 'package:fcs/fcs/common/domain/entities/auth_result.dart'; -import 'package:fcs/fcs/common/domain/entities/setting.dart'; -import 'package:fcs/fcs/common/domain/entities/user.dart'; - -abstract class AuthService { - Future sendSmsCodeToPhoneNumber(String phoneNumber); - Future signInWithSmsCode(String smsCode); - Future signout(); - Future getUser({bool refreshIdToken = false}); - Future signup(String userName); - Future joinInvite(String userName); - Future updateProfile(String newUserName); - Future hasInvite(); - Stream getUserStream(String userID); - Stream getSetting(); - Stream onAuthStatus(); - Future getToken(); -} diff --git a/lib/fcs/common/services/package_imp.dart b/lib/fcs/common/services/package_imp.dart deleted file mode 100644 index 02d9394..0000000 --- a/lib/fcs/common/services/package_imp.dart +++ /dev/null @@ -1,30 +0,0 @@ -import 'package:fcs/fcs/common/data/providers/package_data_provider.dart'; -import 'package:fcs/fcs/common/domain/entities/connectivity.dart'; -import 'package:fcs/fcs/common/domain/entities/package.dart'; -import 'package:fcs/fcs/common/services/package_service.dart'; -import 'package:flutter/material.dart'; - -class PackageServiceImp implements PackageService { - PackageServiceImp({ - @required this.connectivity, - @required this.packageDataProvider, - }); - - final Connectivity connectivity; - final PackageDataProvider packageDataProvider; - - @override - Future createPackages(List packages, String fcsID) { - return packageDataProvider.createPackages(packages, fcsID); - } - - @override - Future> searchPackage(String term) { - return packageDataProvider.searchPackage(term); - } - - @override - Future deletePackage(Package package) { - return packageDataProvider.deletePackage(package); - } -} diff --git a/lib/fcs/common/services/package_service.dart b/lib/fcs/common/services/package_service.dart deleted file mode 100644 index b9498b2..0000000 --- a/lib/fcs/common/services/package_service.dart +++ /dev/null @@ -1,7 +0,0 @@ -import 'package:fcs/fcs/common/domain/entities/package.dart'; - -abstract class PackageService { - Future createPackages(List packages, String fcsID); - Future deletePackage(Package package); - Future> searchPackage(String term); -} diff --git a/lib/fcs/common/services/services.dart b/lib/fcs/common/services/services.dart deleted file mode 100644 index 82c0e4d..0000000 --- a/lib/fcs/common/services/services.dart +++ /dev/null @@ -1,43 +0,0 @@ -import 'package:fcs/fcs/common/data/providers/auth_fb.dart'; -import 'package:fcs/fcs/common/data/providers/common_data_provider.dart'; -import 'package:fcs/fcs/common/data/providers/package_data_provider.dart'; -import 'package:fcs/fcs/common/data/providers/user_data_provider.dart'; -import 'package:fcs/fcs/common/services/auth_imp.dart'; -import 'package:fcs/fcs/common/services/common_imp.dart'; -import 'package:fcs/fcs/common/services/common_service.dart'; -import 'package:fcs/fcs/common/services/messaging_imp.dart'; -import 'package:fcs/fcs/common/services/messaging_service.dart'; -import 'package:fcs/fcs/common/services/package_imp.dart'; -import 'package:fcs/fcs/common/services/package_service.dart'; -import 'package:fcs/fcs/common/services/user_imp.dart'; -import 'package:fcs/fcs/common/services/user_service.dart'; - -import 'auth_service.dart'; - -class Services { - static final Services instance = Services._(); - - AuthService _authService; - UserService _userService; - PackageService _packageService; - MessagingService _messagingService; - CommonService _commonService; - Services._() { - _authService = AuthServiceImp( - authFb: AuthFb.instance, - connectivity: null, - ); - _userService = UserServiceImp( - connectivity: null, userDataProvider: UserDataProvider()); - _messagingService = MessagingServiceImp(); - _packageService = PackageServiceImp( - connectivity: null, packageDataProvider: PackageDataProvider()); - _commonService = CommonServiceImp(commonDataProvider: CommonDataProvider()); - } - - AuthService get authService => _authService; - UserService get userService => _userService; - MessagingService get messagingService => _messagingService; - PackageService get packageService => _packageService; - CommonService get commonService => _commonService; -} diff --git a/lib/fcs/common/helpers/api_helper.dart b/lib/helpers/api_helper.dart similarity index 59% rename from lib/fcs/common/helpers/api_helper.dart rename to lib/helpers/api_helper.dart index c0c8321..38415ef 100644 --- a/lib/fcs/common/helpers/api_helper.dart +++ b/lib/helpers/api_helper.dart @@ -1,13 +1,16 @@ +import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'package:device_info/device_info.dart'; import 'package:dio/dio.dart'; +import 'package:fcs/domain/vo/status.dart'; import 'package:logging/logging.dart'; -import 'package:fcs/vo/status.dart'; +import 'package:path_provider/path_provider.dart'; -import '../../../config.dart'; +import '../config.dart'; import 'dev_info.dart'; +import 'firebase_helper.dart'; final log = Logger('requestAPI'); @@ -146,3 +149,92 @@ Future requestDownloadPDFAPI(String path, method, throw e; } } + +typedef OnDownloadDone(File file); +// request makes http request +// if token is null +Future requestDownload(String path, method, + {dynamic payload, + String token, + String url, + String filePath, + OnDownloadDone onDownloadDone}) async { + DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); + AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo; + String deviceName = "${androidInfo.model}(${androidInfo.id})"; + log.info("device:${androidInfo.androidId},deviceName:$deviceName"); + + var bytes = utf8.encode(payload); + var base64Str = base64.encode(bytes); + String escapePayload = HtmlEscape().convert(base64Str); + + try { + String baseUrl = url == null ? Config.instance.apiURL : url; + log.info("Path:$baseUrl$path"); + HttpClient client = new HttpClient(); + // var _downloadData = StringBuffer(); + var request = await client.postUrl(Uri.parse("$baseUrl$path")); + request.headers.set("Project-ID", Config.instance.reportProjectID); + if (token != null) { + request.headers.set("Token", token); + } + if (androidInfo.androidId != null) { + request.headers.set("Device", androidInfo.androidId + ":" + deviceName); + } + request.headers + .set(HttpHeaders.contentTypeHeader, 'application/json; charset=utf-8'); + request.headers.set("payload", escapePayload); + request.write(payload); + // request.write(escapePayload); + var response = await request.close(); + print("headers:${response.headers}"); + var _downloadData = List(); + var cd = response.headers.value("content-disposition"); + String fileName = "download.csv"; + if (cd != null && cd.contains("filename=")) { + fileName = cd.substring(cd.indexOf("=") + 1); + } + + var file = filePath + "/" + fileName; + var fileSave = new File(filePath + "/" + fileName); + response.listen((d) => _downloadData.addAll(d), onDone: () async { + await fileSave.writeAsBytes(_downloadData); + if (onDownloadDone != null) { + onDownloadDone(fileSave); + } + + // final message = await OpenFile.open(file); + // log.info("Open file result:${message.message}"); + // if (message.message != "done") { + // throw Exception(message.message); + // } + // await Share.file(fileName, fileName, _downloadData, + // downloadType == DownloadType.CSV ? "text/csv" : "application/pdf"); + }); + } catch (e) { + e.toString(); + log.warning("path:$path, api:$e"); + throw e; + } +} + +Future downloadPDF( + String templateName, Map values) async { + final completer = Completer(); + + final directory = await getApplicationSupportDirectory(); + String path = ('${directory.path}'); + log.info("download file path:$path"); + + var data = {"template_name": templateName, "data": values}; + print("payload:$data"); + + await requestDownload("/api/pdf", "POST", + filePath: path, + url: Config.instance.reportURL, + token: await getToken(), + payload: jsonEncode(data), onDownloadDone: (f) async { + completer.complete(f); + }); + return completer.future; +} diff --git a/lib/helpers/cache_mgr.dart b/lib/helpers/cache_mgr.dart new file mode 100644 index 0000000..75c5167 --- /dev/null +++ b/lib/helpers/cache_mgr.dart @@ -0,0 +1,12 @@ +import 'package:flutter_cache_manager/flutter_cache_manager.dart'; + +class PdfCacheMgr { + static const key = 'pdfs'; + static CacheManager pdfs = CacheManager( + Config( + key, + stalePeriod: const Duration(days: 7), + maxNrOfCacheObjects: 20, + ), + ); +} diff --git a/lib/fcs/common/helpers/dev_info.dart b/lib/helpers/dev_info.dart similarity index 100% rename from lib/fcs/common/helpers/dev_info.dart rename to lib/helpers/dev_info.dart diff --git a/lib/fcs/common/helpers/firebase_helper.dart b/lib/helpers/firebase_helper.dart similarity index 60% rename from lib/fcs/common/helpers/firebase_helper.dart rename to lib/helpers/firebase_helper.dart index bf72b7f..2febc03 100644 --- a/lib/fcs/common/helpers/firebase_helper.dart +++ b/lib/helpers/firebase_helper.dart @@ -15,6 +15,14 @@ Future getToken() async { return token.token; } +Future getClaims({bool refreshIdToken = false}) async { + FirebaseUser firebaseUser = await auth.currentUser(); + if (firebaseUser == null) return null; + IdTokenResult idToken = + await firebaseUser.getIdToken(refresh: refreshIdToken); + return idToken.claims; +} + Future uploadStorage(String path, File file, {String fileName}) async { if (fileName == null) { fileName = Uuid().v4(); @@ -30,3 +38,20 @@ Future uploadStorage(String path, File file, {String fileName}) async { print("meta:${await storageReference.getMetadata()}"); return downloadUrl; } + +Future deleteStorageFromUrls(List urls) async { + if (urls == null) return; + for (int i = 0; i < urls.length; i++) { + await deleteStorageFromUrl(urls[i]); + } +} + +Future deleteStorageFromUrl(String url) async { + try { + StorageReference storageReference = + await FirebaseStorage.instance.getReferenceFromUrl(url); + await storageReference.delete(); + } catch (e) { + log.warning("deleteStorage:$e"); + } +} diff --git a/lib/fcs/common/helpers/network_connectivity.dart b/lib/helpers/network_connectivity.dart similarity index 96% rename from lib/fcs/common/helpers/network_connectivity.dart rename to lib/helpers/network_connectivity.dart index d34f593..fe7c21d 100644 --- a/lib/fcs/common/helpers/network_connectivity.dart +++ b/lib/helpers/network_connectivity.dart @@ -3,9 +3,10 @@ import 'dart:io'; import 'package:connectivity/connectivity.dart'; import 'package:fcs/config.dart'; -import 'package:fcs/fcs/common/helpers/api_helper.dart'; import 'package:logging/logging.dart'; +import 'api_helper.dart'; + class NetworkConnectivity { final log = Logger('NetworkConnectivity'); diff --git a/lib/helpers/paginator.dart b/lib/helpers/paginator.dart new file mode 100644 index 0000000..cb89f15 --- /dev/null +++ b/lib/helpers/paginator.dart @@ -0,0 +1,70 @@ +import 'dart:async'; + +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:fcs/pages/widgets/callbacks.dart'; +import 'package:logging/logging.dart'; + +typedef ToObj = Function(Map data, String id); + +/* + * Pagination load data in page + */ +class Paginator { + final log = Logger('Paginator'); + + final int rowPerLoad; + DocumentSnapshot prev; + bool ended = false; + bool isLoading = false; + List values = []; + ToObj toObj; + + Query pageQuery; + + Paginator(this.pageQuery, {this.rowPerLoad = 20, this.toObj}) { + _clearState(); + } + + void _clearState() { + prev = null; + ended = false; + isLoading = false; + values = []; + } + + void close() { + _clearState(); + } + + Future refresh({CallBack onFinished}) async { + _clearState(); + await load(); + if (onFinished != null) onFinished(); + } + + Future load({CallBack onFinished}) async { + if (ended) return null; + isLoading = true; + Query _query = + prev != null ? pageQuery.startAfterDocument(prev) : pageQuery; + try { + await _query + .limit(rowPerLoad) + .getDocuments(source: Source.server) + .then((QuerySnapshot snapshot) { + int count = snapshot.documents.length; + ended = count < rowPerLoad; + prev = count > 0 ? snapshot.documents[count - 1] : prev; + snapshot.documents.forEach((e) { + values.add(toObj(e.data, e.documentID)); + }); + }); + } catch (e) { + log.warning("Error!! $e"); + } finally { + isLoading = false; + if (onFinished != null) onFinished(); + } + return ended; + } +} diff --git a/lib/fcs/common/helpers/shared_pref.dart b/lib/helpers/shared_pref.dart similarity index 83% rename from lib/fcs/common/helpers/shared_pref.dart rename to lib/helpers/shared_pref.dart index 0dafb56..d2f26f8 100644 --- a/lib/fcs/common/helpers/shared_pref.dart +++ b/lib/helpers/shared_pref.dart @@ -1,6 +1,6 @@ import 'dart:convert'; -import 'package:fcs/fcs/common/domain/entities/user.dart'; +import 'package:fcs/domain/entities/user.dart'; import 'package:shared_preferences/shared_preferences.dart'; class SharedPref { @@ -27,6 +27,16 @@ class SharedPref { prefs.setString('language', lang); } + static Future getStaffMode() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + return prefs.getBool('staff_mode_on'); + } + + static Future saveStaffMode(bool staffMode) async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + prefs.setBool('staff_mode_on', staffMode); + } + static Future saveUser(User user) async { await _save("user", user.toJson()); } diff --git a/lib/fcs/common/helpers/theme.dart b/lib/helpers/theme.dart similarity index 100% rename from lib/fcs/common/helpers/theme.dart rename to lib/helpers/theme.dart diff --git a/lib/fcs/common/localization/app_translations.dart b/lib/localization/app_translations.dart similarity index 100% rename from lib/fcs/common/localization/app_translations.dart rename to lib/localization/app_translations.dart diff --git a/lib/fcs/common/localization/app_translations_delegate.dart b/lib/localization/app_translations_delegate.dart similarity index 100% rename from lib/fcs/common/localization/app_translations_delegate.dart rename to lib/localization/app_translations_delegate.dart diff --git a/lib/fcs/common/localization/transalation.dart b/lib/localization/transalation.dart similarity index 100% rename from lib/fcs/common/localization/transalation.dart rename to lib/localization/transalation.dart diff --git a/lib/main-dev.dart b/lib/main-dev.dart index ef4a875..fc234be 100644 --- a/lib/main-dev.dart +++ b/lib/main-dev.dart @@ -1,8 +1,8 @@ -import 'package:fcs/config.dart'; import 'package:flutter/material.dart'; import 'package:logging/logging.dart'; import 'app.dart'; +import 'config.dart'; void main() { WidgetsFlutterBinding.ensureInitialized(); diff --git a/lib/main-local.dart b/lib/main-local.dart index cc46f96..6f30bf4 100644 --- a/lib/main-local.dart +++ b/lib/main-local.dart @@ -1,8 +1,8 @@ -import 'package:fcs/config.dart'; import 'package:flutter/material.dart'; import 'package:logging/logging.dart'; import 'app.dart'; +import 'config.dart'; void main() { WidgetsFlutterBinding.ensureInitialized(); diff --git a/lib/main-prod.dart b/lib/main-prod.dart index fd9fc07..c0c431a 100644 --- a/lib/main-prod.dart +++ b/lib/main-prod.dart @@ -1,8 +1,8 @@ -import 'package:fcs/config.dart'; import 'package:flutter/material.dart'; import 'package:logging/logging.dart'; import 'app.dart'; +import 'config.dart'; void main() { WidgetsFlutterBinding.ensureInitialized(); diff --git a/lib/model/announcement_model.dart b/lib/model/announcement_model.dart deleted file mode 100644 index 88c9c24..0000000 --- a/lib/model/announcement_model.dart +++ /dev/null @@ -1,61 +0,0 @@ -import 'dart:async'; - -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:fcs/vo/announcement.dart'; - -import 'base_model.dart'; -import 'constants.dart'; -import 'firebase_helper.dart'; - -class AnnouncementModel extends BaseModel { - List announcements = []; - - void initUser(user) { - super.initUser(user); - _loadAnnouncements(); - } - - @override - logout() async { - announcements = []; - } - - Future _loadAnnouncements() async { - Stream snapshots = Firestore.instance - .collection( - "/$biz_collection/${setting.okEnergyId}/$announcement_collection") - .snapshots(); - - snapshots.listen((snaps) async { - announcements = snaps.documents.map((documentSnapshot) { - var data = Announcement.fromMap( - documentSnapshot.data, documentSnapshot.documentID); - return data; - }).toList(); - - notifyListeners(); - }); - } - - Future getAnnouncement(String id) async { - String path = - "/$biz_collection/${setting.okEnergyId}/$announcement_collection"; - var snap = await getDocSnap(path, id); - return Announcement.fromMap(snap.data, snap.documentID); - } - - Future createAnnouncement(Announcement announcement) async { - await request("/announcement", "POST", - payload: announcement.toMap(), token: await getToken()); - } - - Future updateAnnouncement(Announcement announcement) async { - await request("/announcement", "PUT", - payload: announcement.toMap(), token: await getToken()); - } - - Future deleteAnnouncement(Announcement announcement) async { - await request("/announcement", "DELETE", - payload: announcement.toMap(), token: await getToken()); - } -} diff --git a/lib/model/buyer_model.dart b/lib/model/buyer_model.dart deleted file mode 100644 index 43fbb3d..0000000 --- a/lib/model/buyer_model.dart +++ /dev/null @@ -1,177 +0,0 @@ -import 'dart:async'; -import 'dart:convert' show HtmlEscape, base64, utf8; - -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:logging/logging.dart'; -import 'package:fcs/config.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/buyer.dart'; -import 'package:fcs/vo/popup_menu.dart'; - -import 'base_model.dart'; -import 'constants.dart'; -import 'firebase_helper.dart'; - -class BuyerModel extends BaseModel { - final log = Logger('BuyerModel'); - - StreamSubscription listener; - - List buyers = []; - PopupMenu popupMenu = new PopupMenu(index: 0); - PopupMenu sortMenu = new PopupMenu(); - Buyer searchBuyer; - void initUser(user) { - super.initUser(user); - _loadBuyers(); - } - - Future _loadBuyers() async { - if (!user.isOwnerAndAbove() && !user.hasBuyer()) { - return; - } - - listener = getQuerySnapshotByOrder( - "/$biz_collection/${setting.okEnergyId}/$buyer_collection", - 'user_name') - .listen((snaps) async { - buyers.clear(); - snaps.documents.forEach((d) { - buyers.add(Buyer.fromMap(d.data, d.documentID)); - }); - notifyListeners(); - }); - } - - @override - logout() async { - if (listener != null) await listener.cancel(); - buyers = []; - } - - Future getBuyer(String buyerID) async { - var snap = await getDocSnap( - "/$biz_collection/${setting.okEnergyId}/$buyer_collection", buyerID); - return Buyer.fromMap(snap.data, snap.documentID); - } - - Future loadBuyerProducts(Buyer buyer, {bool force = false}) async { - if (!force && buyer.buyerProducts != null && buyer.buyerProducts.length > 0) - return buyer; - var snaps = await getSnapshot( - "/$biz_collection/${setting.okEnergyId}/$buyer_collection/${buyer.id}/$product_collection"); - buyer.buyerProducts = snaps.documents - .map((s) => BuyerProduct.fromMap(s.data, s.documentID)) - .toList(); - return buyer; - } - - Future delete(Buyer buyer) async { - await request("/buyer/${buyer.id}", "DELETE", token: await getToken()); - } - - Future approve(Buyer buyer) async { - await request("/buyer/approve", "PUT", - payload: buyer.toMap(), token: await getToken()); - } - - Future reject(Buyer buyer) async { - await request("/buyer/reject", "POST", - payload: buyer.toMap(), token: await getToken()); - } - - Future allocate(Buyer buyer) async { - await request("/buyer/allocate", "POST", - payload: buyer.toMap(), token: await getToken()); - } - - void filterStatus(String status, int _selectedIndex, int _sleectedSortIndex) { - this.sortMenu.index = _sleectedSortIndex; - buyers.clear(); - if (listener != null) { - listener.cancel(); - } - - this.popupMenu.index = _selectedIndex; - String path = "/$biz_collection/${setting.okEnergyId}/$buyer_collection"; - listener = getFilterStatusSnapshot(path, status, 'user_name') - .listen((snaps) async { - buyers.clear(); - snaps.documents.forEach((d) { - buyers.add(Buyer.fromMap(d.data, d.documentID)); - }); - notifyListeners(); - }); - notifyListeners(); - } - - Future> search(String searchBuyer) async { - if (searchBuyer == null || searchBuyer == '') return List(); - - var bytes = utf8.encode(searchBuyer); - var base64Str = base64.encode(bytes); - HtmlEscape htmlEscape = const HtmlEscape(); - String escapeBuyer = htmlEscape.convert(base64Str); - - int limit = 20; - List _buyers = []; - - try { - var data = await request( - "/api/fts/$buyer_collection/$escapeBuyer/$limit", "GET", - token: await getToken(), url: Config.instance.reportURL); - if (data == null) return List(); - - data.forEach((buyer) { - var _buyer = Buyer.fromJson(buyer); - _buyers.add(_buyer); - }); - } catch (e) { - // permission error - log.warning("buyer error:" + e.toString()); - return null; - } - return _buyers; - } - - void filterSorting(int _sleectedSortIndex, int _selectedIndex) { - this.popupMenu.index = _selectedIndex; - buyers.clear(); - if (listener != null) { - listener.cancel(); - } - String _fieldName; - bool descending = false; - - if (_sleectedSortIndex == 0) { - _fieldName = 'user_name'; - descending = false; - } - if (_sleectedSortIndex == 1) { - _fieldName = 'user_name'; - descending = true; - } - if (_sleectedSortIndex == 2) { - _fieldName = 'phone_number'; - descending = false; - } - if (_sleectedSortIndex == 3) { - _fieldName = 'phone_number'; - descending = true; - } - - this.sortMenu.index = _sleectedSortIndex; - String path = "/$biz_collection/${setting.okEnergyId}/$buyer_collection"; - listener = - getFilterSnapshot(path, descending, _fieldName).listen((snaps) async { - buyers.clear(); - snaps.documents.forEach((d) { - buyers.add(Buyer.fromMap(d.data, d.documentID)); - notifyListeners(); - }); - - notifyListeners(); - }); - notifyListeners(); - } -} diff --git a/lib/model/chart_model.dart b/lib/model/chart_model.dart deleted file mode 100644 index 1c08ad9..0000000 --- a/lib/model/chart_model.dart +++ /dev/null @@ -1,243 +0,0 @@ -import 'dart:convert'; - -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:logging/logging.dart'; -import 'package:fcs/config.dart'; -import 'package:fcs/model/firebase_helper.dart'; -import 'package:fcs/vo/po.dart'; -import 'package:fcs/vo/po_do_count.dart'; -import 'package:fcs/vo/revenue.dart'; - -import 'base_model.dart'; -import 'constants.dart'; - -class ChartModel extends BaseModel { - final log = Logger('ChartModel'); - - List chartSummary = []; - - Revenue revenue = new Revenue(); - PODOCount podoCount = new PODOCount(); - void initUser(user) async { - super.initUser(user); - revenue = new Revenue(); - podoCount = new PODOCount(); - - _loadRev(); - _loadPODOCount(); - if (user.hasPO() || user.isOwnerAndAbove()) { - _getSummary(); - } - } - - Future _loadRev() async { - try { - String path = "/$biz_collection/${setting.okEnergyId}/$report_collection"; - String reportID = "revenue"; - - if (user.isBuyer()) { - path = - "/$biz_collection/${setting.okEnergyId}/$buyer_collection/${user.docID}/$report_collection"; - reportID = "spending"; - } - - getDocSnapshot(path, reportID).listen((DocumentSnapshot snapshot) async { - if (snapshot.data == null) { - return; - } - revenue = Revenue.fromMap(snapshot.data, snapshot.documentID); - notifyListeners(); - }).onError((e) { - log.warning("Error! $e"); - }); - } catch (e) { - log.warning("Error!! $e"); - } - } - - Future _loadPODOCount() async { - try { - String path = "/$biz_collection/${setting.okEnergyId}/$report_collection"; - String reportID = "po_do_count"; - - if (user.isBuyer()) { - path = - "/$biz_collection/${setting.okEnergyId}/$buyer_collection/${user.docID}/$report_collection"; - } - - getDocSnapshot(path, reportID).listen((DocumentSnapshot snapshot) async { - if (snapshot.data == null) { - return; - } - podoCount = PODOCount.fromMap(snapshot.data, snapshot.documentID); - notifyListeners(); - }).onError((e) { - log.warning("Error! $e"); - }); - } catch (e) { - log.warning("Error!! $e"); - } - } - - @override - logout() async { - chartSummary = []; - revenue = new Revenue(); - podoCount = new PODOCount(); - } - - _getSummary() async { - chartSummary.clear(); - try { - var data = { - "fields": 'quantity,product_id,product_name,color', - "aggfuns": "sum,,,", - "groupbys": 'product_id', - }; - var result = await request("/api/data/po_product_view", "POST", - token: await getToken(), - url: Config.instance.reportURL, - payload: jsonEncode(data)); - if (result == null) return; - chartSummary.clear(); - result.forEach((chart) { - var _list = POChartData.fromJson(chart, "quantity_sum"); - chartSummary.add(_list); - }); - } catch (e) { - log.warning("Error get Summary>>>>${e.toString()}"); - } - } - - Future> loadSummary() async { - List _list = List(); - try { - var data = { - "fields": 'quantity,product_id,product_name,color', - "aggfuns": "sum,,,", - "groupbys": 'product_id', - }; - var result = await request("/api/data/po_product_view", "POST", - token: await getToken(), - url: Config.instance.reportURL, - payload: jsonEncode(data)); - if (result != null) { - result.forEach((chart) { - var _data = POChartData.fromJson(chart, "quantity_sum"); - _list.add(_data); - }); - } - return _list; - } catch (e) { - log.warning("Error>>>>${e.toString()}"); - return null; - } - } - - Future> loadUsers() async { - List _list = List(); - var data = { - "fields": 'quantity,user_name,product_name', - "aggfuns": "sum,,", - "groupbys": 'product_id,user_id', - }; - try { - var result = await request("/api/data/po_product_view", "POST", - token: await getToken(), - url: Config.instance.reportURL, - payload: jsonEncode(data)); - - result.forEach((chart) { - var _buyer = POChartData.fromJson(chart, "quantity_sum"); - _list.add(_buyer); - }); - return _list; - } catch (e) { - log.warning("Error load>>>>${e.toString()}"); - return null; - } - } - - Future> loadPOBalancesForBuyer_() async { - List _list = List(); - try { - var data = { - "fields": 'amount,status', - "aggfuns": "sum,", - "groupbys": 'status', - "filters": [ - {"field": "user_id", "compare": "==", "value": user.docID} - ] - }; - var result = await request("/api/data/po_buyer_view", "POST", - token: await getToken(), - url: Config.instance.reportURL, - payload: jsonEncode(data)); - - if (result != null) { - result.forEach((chart) { - var _data = POBuyerData.fromJson(chart, "amount_sum"); - _list.add(_data); - }); - } - return _list; - } catch (e) { - log.warning("Error>>>>${e.toString()}"); - return null; - } - } - - Future> loadPOBalancesForBuyer() async { - List _list = List(); - try { - var data = { - "fields": 'quantity,product_id,product_name,user_id,color', - "aggfuns": "sum,,,,", - "groupbys": 'product_id,user_id', - "filters": [ - {"field": "user_id", "compare": "==", "value": user.docID} - ] - }; - var result = await request("/api/data/po_product_view", "POST", - token: await getToken(), - url: Config.instance.reportURL, - payload: jsonEncode(data)); - if (result != null) { - result.forEach((chart) { - var _data = POChartData.fromJson(chart, "quantity_sum"); - _list.add(_data); - }); - } - return _list; - } catch (e) { - log.warning("Error>>>>${e.toString()}"); - return null; - } - } - - Future> loadPOBalProductsForBuyer() async { - List _list = List(); - var data = { - "fields": 'quantity,user_name,user_id,product_name', - "aggfuns": "sum,,,", - "groupbys": 'product_id,user_id', - "filters": [ - {"field": "user_id", "compare": "==", "value": user.docID} - ] - }; - try { - var result = await request("/api/data/po_product_view", "POST", - token: await getToken(), - url: Config.instance.reportURL, - payload: jsonEncode(data)); - result.forEach((chart) { - var _buyer = POChartData.fromJson(chart, "quantity_sum"); - _list.add(_buyer); - }); - return _list; - } catch (e) { - log.warning("Error load>>>>${e.toString()}"); - return null; - } - } -} diff --git a/lib/model/constants.dart b/lib/model/constants.dart deleted file mode 100644 index 2d0c0fc..0000000 --- a/lib/model/constants.dart +++ /dev/null @@ -1,37 +0,0 @@ -const ok_doc_id = "ok"; -const setting_doc_id = "ok_setting"; - -const config_collection = "configs"; -const biz_collection = "bizs"; -const product_collection = "products"; -const user_collection = "users"; -const privilege_collection = "privileges"; -const user_level_collection = "user_levels"; -const storage_collection = "storages"; -const buyer_collection = "buyers"; -const buying_pos = "buying_pos"; -const selling_pos = "selling_pos"; -const inventory_takings = "inventory_takings"; -const inventory_lines = "inventory_lines"; -const pds_collection = "pds"; -const pos_collection = "pos"; -const dos_collection = "dos"; -const notification_collection = "notifications"; -const log_collection = "logs"; -const report_collection = "reports"; -const po_product_collection = "po_products"; -const device_collection = "devices"; -const do_po_lines_collection = "do_po_lines"; -const reports_collection = "reports"; -const announcement_collection = "announcements"; -const report_user_collection = "report_users"; - -const po_files_path = "/ok/po"; -const reg_files_path = "/ok/reg"; -const do_files_path = "/ok/do"; -const sign_files_path = "/ok/sign"; -const bank_images_path = "/ok/banks"; - -const po_approved_status = "approved"; -const po_closed_status = "closed"; -const do_approved_status = "approved"; diff --git a/lib/model/customer_model.dart b/lib/model/customer_model.dart deleted file mode 100644 index 45dc95f..0000000 --- a/lib/model/customer_model.dart +++ /dev/null @@ -1,68 +0,0 @@ -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:logging/logging.dart'; -import 'package:fcs/vo/user.dart'; - -import '../vo/user.dart'; -import 'base_model.dart'; -import 'constants.dart'; -import 'firebase_helper.dart'; - -class CustomerModel extends BaseModel { - final log = Logger('CustomerModel'); - - List customers = [ - User( - name: 'Ko Nyi', - phoneNumber: '+95 9 717273634', - status: 'Invited' - ), - User(name: 'Ko Phyu', phoneNumber: '+1 (939) 382-3844',status: 'Signin'), - User(name: 'Ko Ye', phoneNumber: '+95 9 983734783', status: 'Invited'), - ]; - - void initUser(user) async { - super.initUser(user); - // _loadCustomer(); - } - - @override - logout() async { - customers = []; - } - - // Future _loadCustomer() async { - // if (!user.isOwnerAndAbove() && !user.hasAccount()) { - // return; - // } - - // try { - // Firestore.instance - // .collection("/$biz_collection/${setting.okEnergyId}/$user_collection") - // .where("is_employee", isEqualTo: true) - // .snapshots() - // .listen((QuerySnapshot snapshot) { - // customers.clear(); - // customers = snapshot.documents.map((documentSnapshot) { - // var user = - // User.fromMap(documentSnapshot.data, documentSnapshot.documentID); - // return user; - // }).toList(); - // notifyListeners(); - // }).onError((e) { - // log.warning("Error! $e"); - // }); - // } catch (e) { - // log.warning("Error!! $e"); - // } - // } - - // Future updatePrivileges(String userID, List privileges) async { - // try { - // await request("/employee/privileges", "PUT", - // payload: {"id": userID, "privileges": privileges}, - // token: await getToken()); - // } catch (e) { - // throw Exception(e); - // } - // } -} diff --git a/lib/model/delivery_model.dart b/lib/model/delivery_model.dart deleted file mode 100644 index 506be95..0000000 --- a/lib/model/delivery_model.dart +++ /dev/null @@ -1,140 +0,0 @@ -import 'dart:async'; -import 'dart:typed_data'; - -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:path/path.dart' as Path; -import 'package:fcs/model/constants.dart'; -import 'package:fcs/vo/do.dart'; -import 'package:fcs/vo/popup_menu.dart'; - -import 'base_model.dart'; -import 'firebase_helper.dart'; - -class DeliveryModel extends BaseModel { - StreamSubscription listener; - - List dos = []; - PopupMenu popupMenu = new PopupMenu(index: 0); - int dateIndex = 0; - DateTime selectedDate = DateTime.now(); - int timber = 0; - - void initUser(user) async { - super.initUser(user); - _loadDOs(); - } - - Future _loadDOs() async { - if (!user.isOwnerAndAbove() && !user.hasDelivery()) { - return; - } - - String path = "/$biz_collection/${setting.okEnergyId}/$dos_collection"; - - var startDate = new DateTime( - selectedDate.year, selectedDate.month, selectedDate.day, 0, 0, 0); - var endDate = new DateTime( - selectedDate.year, selectedDate.month, selectedDate.day, 23, 59, 59); - - listener = getDeliverySnapshot( - path, 'delivery_date', startDate, endDate, 'do_number') - .listen((snaps) async { - dos.clear(); - snaps.documents.forEach((d) { - dos.add(DOSubmission.fromMap(d.data, d.documentID)); - }); - notifyListeners(); - }); - } - - @override - logout() async { - if (listener != null) await listener.cancel(); - dos = []; - } - - Future getDO(String id) async { - String path = "/$biz_collection/${setting.okEnergyId}/$dos_collection"; - if (user.isBuyer()) { - path = - "/$biz_collection/${setting.okEnergyId}/$buyer_collection/${user.docID}/$dos_collection"; - } - var doSnap = await getDocSnap(path, id); - return DOSubmission.fromMap(doSnap.data, doSnap.documentID); - } - - Future endDelivery(DOSubmission doObj, Uint8List img) async { - String path = Path.join(do_files_path, user.docID); - String imgUrl = await uploadStorageData(path, img, fileName: doObj.id); - doObj.doReceiptUrl = imgUrl; - await request("/do/ended", "POST", - payload: doObj.toMap(), token: await getToken()); - } - - void filterData( - String status, DateTime dateTime, int _selectedIndex, int _dateIndex) { - dos.clear(); - - var startDate = - new DateTime(dateTime.year, dateTime.month, dateTime.day, 0, 0, 0); - var endDate = - new DateTime(dateTime.year, dateTime.month, dateTime.day, 23, 59, 59); - - if (listener != null) { - listener.cancel(); - } - - this.popupMenu.index = _selectedIndex; - this.dateIndex = _dateIndex; - this.selectedDate = dateTime == null - ? new DateTime( - selectedDate.year, selectedDate.month, selectedDate.day, 0, 0, 0) - : dateTime; - - String path = "/$biz_collection/${setting.okEnergyId}/$dos_collection"; - if (user.isBuyer()) { - path = - "/$biz_collection/${setting.okEnergyId}/$buyer_collection/${user.docID}/$dos_collection"; - } - - if (status != null && dateTime == null) { - listener = getDeliveryStatusSnapshot(path, status, 'do_number') - .listen((snaps) async { - dos.clear(); - snaps.documents.forEach((d) { - dos.add(DOSubmission.fromMap(d.data, d.documentID)); - }); - notifyListeners(); - }); - } else if (dateTime != null && status == null) { - listener = getDeliveryDateSnapshot( - path, 'delivery_date', startDate, endDate, 'do_number') - .listen((snaps) async { - dos.clear(); - snaps.documents.forEach((d) { - dos.add(DOSubmission.fromMap(d.data, d.documentID)); - }); - notifyListeners(); - }); - } else if (status != null && dateTime != null) { - listener = getDeliveryDataSnapshot( - path, status, 'delivery_date', startDate, endDate, 'do_number') - .listen((snaps) async { - dos.clear(); - snaps.documents.forEach((d) { - dos.add(DOSubmission.fromMap(d.data, d.documentID)); - }); - notifyListeners(); - }); - } else { - listener = - getQuerySnapshotByOrder(path, 'do_number').listen((snaps) async { - dos.clear(); - snaps.documents.forEach((d) { - dos.add(DOSubmission.fromMap(d.data, d.documentID)); - }); - notifyListeners(); - }); - } - } -} diff --git a/lib/model/device_model.dart b/lib/model/device_model.dart deleted file mode 100644 index e5e0f0c..0000000 --- a/lib/model/device_model.dart +++ /dev/null @@ -1,76 +0,0 @@ -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:device_info/device_info.dart'; -import 'package:fcs/vo/device.dart'; - -import 'base_model.dart'; -import 'constants.dart'; -import 'firebase_helper.dart'; - -class PhoneDeviceModel extends BaseModel { - List devices = new List(); - - bool isLogout = false; - void initUser(user) { - super.initUser(user); - _loadDevices(); - } - - Future _loadDevices() async { - Stream snapshots = Firestore.instance - .collection( - "/$biz_collection/${setting.okEnergyId}/$user_collection/${user.docID}/$device_collection") - .where("primary_device", isEqualTo: false) - .snapshots(); - - DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); - AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo; - - snapshots.listen((snaps) async { - devices = snaps.documents.map((documentSnapshot) { - var data = PhoneDevice.fromMap( - documentSnapshot.data, documentSnapshot.documentID); - if (!data.deviceOn && - !data.primaryDevice && - data.id == androidInfo.androidId && - !documentSnapshot.metadata.isFromCache) { - this.isLogout = true; - this.mainModel.logout(); - notifyListeners(); - } - return data; - }).toList(); - - notifyListeners(); - }); - } - - - @override - logout() async { - devices = []; - } - - bool isLogoutDevice() { - return this.isLogout; - } - - setDevice(bool status) { - this.isLogout = status; - notifyListeners(); - } - - Future confirmDevice(String id, String deviceID) async { - await request("/dev/on", "POST", - payload: {"id": id, "device_id": deviceID}, token: await getToken()); - } - - Future logoutDevice(String id, String deviceID) async { - await request("/dev/off", "POST", - payload: {"id": id, "device_id": deviceID}, token: await getToken()); - } - - Future setPrimaryDevice(String id, String deviceID) async { - await request("/dev", "PUT", - payload: {"id": id, "device_id": deviceID}, token: await getToken()); - } -} diff --git a/lib/model/discount_model.dart b/lib/model/discount_model.dart deleted file mode 100644 index 830f580..0000000 --- a/lib/model/discount_model.dart +++ /dev/null @@ -1,57 +0,0 @@ -import 'package:fcs/vo/discount.dart'; - -import 'base_model.dart'; - -class DiscountModel extends BaseModel { - List get discounts { - List discountList = [ - Discount( - code: 'XMQY01', - customer: 'Ko Nyi', - amount: 5000, - status: 'Used', - ), - Discount( - code: 'XMQY02', - customer: 'Ko Aung Myo', - amount: 3000, - status: 'Avaliable', - ), - Discount( - code: 'XMQY03', - customer: 'Ko Zaw Thu', - amount: 2000, - status: 'Used', - ), - Discount( - code: 'XMQY04', - customer: 'Ko Myo Min', - amount: 3000, - status: 'Avaliable', - ), - Discount( - code: 'XMQY05', - customer: 'Ko Nyi', - amount: 3000, - status: 'Avaliable', - ), - ]; - return discountList; - } - - // List get discountByCustomer { - // return invoices.where((e) => e.status == "Avaliable").toList() - // ..sort((e1, e2) { - // return e2.invoiceNumber.compareTo(e1.invoiceNumber); - // }); - // } - - void initUser(user) { - super.initUser(user); - } - - @override - logout() async { - // discounts = []; - } -} diff --git a/lib/model/do_model.dart b/lib/model/do_model.dart deleted file mode 100644 index 4b8e0f1..0000000 --- a/lib/model/do_model.dart +++ /dev/null @@ -1,258 +0,0 @@ -import 'dart:async'; -import 'dart:io'; -import 'dart:typed_data'; - -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:path/path.dart' as Path; -import 'package:fcs/fcs/common/helpers/api_helper.dart'; -import 'package:fcs/model/constants.dart'; -import 'package:fcs/pages/do/do_files.dart'; -import 'package:fcs/vo/do.dart'; -import 'package:fcs/vo/popup_menu.dart'; - -import 'base_model.dart'; -import 'firebase_helper.dart'; - -class DOModel extends BaseModel { - StreamSubscription listener; - - List dos = []; - PopupMenu popupMenu = new PopupMenu(index: 0); - int dateIndex = 0; - DateTime selectedDate = DateTime.now(); - int timber = 0; - - void initUser(user) async { - super.initUser(user); - _loadDOs(); - } - - @override - logout() async { - if (listener != null) await listener.cancel(); - dos = []; - } - - Future _loadDOs() async { - String path; - if (user.hasDO() || user.isOwnerAndAbove()) { - path = "/$biz_collection/${setting.okEnergyId}/$dos_collection"; - } - if (user.isBuyer()) { - path = - "/$biz_collection/${setting.okEnergyId}/$buyer_collection/${user.docID}/$dos_collection"; - } - var startDate = new DateTime( - selectedDate.year, selectedDate.month, selectedDate.day, 0, 0, 0); - var endDate = new DateTime( - selectedDate.year, selectedDate.month, selectedDate.day, 23, 59, 59); - - listener = - getFilterDateSnapshot(path, 'do_date', startDate, endDate, 'do_number') - .listen((snaps) async { - dos.clear(); - snaps.documents.forEach((d) { - dos.add(DOSubmission.fromMap(d.data, d.documentID)); - }); - notifyListeners(); - }); - } - - Future loadDOPOLines(DOSubmission doSub) async { - String path = - "/$biz_collection/${setting.okEnergyId}/$dos_collection/${doSub.id}/$do_po_lines_collection"; - if (user.isBuyer()) { - path = - "/$biz_collection/${setting.okEnergyId}/$buyer_collection/${user.docID}/$dos_collection/${doSub.id}/$do_po_lines_collection"; - } - var snaps = await getSnapshot(path); - doSub.dopoLies = - snaps.documents.map((s) => DOPOLine.fromMap(s.data)).toList(); - return doSub; - } - - Future getDO(String id) async { - String path = "/$biz_collection/${setting.okEnergyId}/$dos_collection"; - if (user.isBuyer()) { - path = - "/$biz_collection/${setting.okEnergyId}/$buyer_collection/${user.docID}/$dos_collection"; - } - var doSnap = await getDocSnap(path, id); - return DOSubmission.fromMap(doSnap.data, doSnap.documentID); - } - - Future createDO(DOSubmission doSubmission, DOFiles files) async { - doSubmission.userID = user.docID; - String path = Path.join(do_files_path, user.docID); - - if (files.storageChargeFile != null) { - String url = await uploadStorage(path, files.storageChargeFile); - doSubmission.storageReceiptUrl = url; - } - if (files.licenseFile != null) { - String url = await uploadStorage(path, files.licenseFile); - doSubmission.driverLicenceUrl = url; - } - - await request("/do", "POST", - payload: doSubmission.toMap(), token: await getToken()); - } - - Future updateDO(DOSubmission doSubmission, DOFiles files) async { - String path = Path.join(do_files_path, user.docID); - if (files.storageFileChanged) { - if (doSubmission.storageReceiptUrl != null && - doSubmission.storageReceiptUrl != '') { - await deleteStorageFromUrl(doSubmission.storageReceiptUrl); - } - doSubmission.storageReceiptUrl = null; - String url = await uploadStorage(path, files.storageChargeFile); - doSubmission.storageReceiptUrl = url; - } - - if (files.licenseFileChanged) { - if (doSubmission.driverLicenceUrl != null && - doSubmission.driverLicenceUrl != '') { - await deleteStorageFromUrl(doSubmission.driverLicenceUrl); - } - doSubmission.driverLicenceUrl = null; - String url = await uploadStorage(path, files.licenseFile); - doSubmission.driverLicenceUrl = url; - } - await request("/do", "PUT", - payload: doSubmission.toMap(), token: await getToken()); - } - - Future approveDO(DOSubmission doObj) async { - await request("/do/approved", "POST", - payload: doObj.toMap(), token: await getToken()); - } - - Future rejectDO(DOSubmission doObj) async { - await request("/do/rejected", "POST", - payload: doObj.toMap(), token: await getToken()); - } - - Future cancelDO(DOSubmission doObj) async { - await request("/do/canceled", "POST", - payload: doObj.toMap(), token: await getToken()); - } - - Future initDelivery(DOSubmission doObj) async { - String path = Path.join(do_files_path, user.docID); - String imgUrl = - await uploadStorage(path, doObj.driverImg, fileName: doObj.id); - doObj.driverImgUrl = imgUrl; - await request("/do/initiated", "POST", - payload: doObj.toMap(), token: await getToken()); - } - - Future startDelivery(DOSubmission doObj) async { - await request("/do/started", "POST", - payload: doObj.toMap(), token: await getToken()); - } - - Future endDelivery(DOSubmission doObj, Uint8List img) async { - String path = Path.join(do_files_path, user.docID); - String imgUrl = await uploadStorageData(path, img, fileName: doObj.id); - doObj.doReceiptUrl = imgUrl; - await request("/do/ended", "POST", - payload: doObj.toMap(), token: await getToken()); - } - - void filterData( - String status, DateTime dateTime, int _selectedIndex, int _dateIndex) { - dos.clear(); - if (listener != null) { - listener.cancel(); - } - - this.popupMenu.index = _selectedIndex; - this.dateIndex = _dateIndex; - this.selectedDate = dateTime == null - ? new DateTime( - selectedDate.year, selectedDate.month, selectedDate.day, 0, 0, 0) - : dateTime; - - String path = "/$biz_collection/${setting.okEnergyId}/$dos_collection"; - if (user.isBuyer()) { - path = - "/$biz_collection/${setting.okEnergyId}/$buyer_collection/${user.docID}/$dos_collection"; - } - - if (status != null && dateTime == null) { - listener = getFilterStatusSnapshot(path, status, 'do_number') - .listen((snaps) async { - dos.clear(); - snaps.documents.forEach((d) { - dos.add(DOSubmission.fromMap(d.data, d.documentID)); - }); - notifyListeners(); - }); - } else if (dateTime != null && status == null) { - var endDate = - new DateTime(dateTime.year, dateTime.month, dateTime.day, 23, 59, 59); - listener = - getFilterDateSnapshot(path, 'do_date', dateTime, endDate, 'do_number') - .listen((snaps) async { - dos.clear(); - snaps.documents.forEach((d) { - dos.add(DOSubmission.fromMap(d.data, d.documentID)); - }); - notifyListeners(); - }); - } else if (status != null && dateTime != null) { - var endDate = - new DateTime(dateTime.year, dateTime.month, dateTime.day, 23, 59, 59); - listener = getFilterDataSnapshot( - path, status, 'do_date', dateTime, endDate, 'do_number') - .listen((snaps) async { - dos.clear(); - snaps.documents.forEach((d) { - dos.add(DOSubmission.fromMap(d.data, d.documentID)); - }); - notifyListeners(); - }); - } else { - listener = - getQuerySnapshotByOrder(path, 'do_number').listen((snaps) async { - dos.clear(); - snaps.documents.forEach((d) { - dos.add(DOSubmission.fromMap(d.data, d.documentID)); - }); - notifyListeners(); - }); - } - } - - addTimber(int count) { - timber = count; - notifyListeners(); - } - - Future> getDOForDelivery(DateTime dateTime) async { - List dos = []; - - String path = "/$biz_collection/${setting.okEnergyId}/$dos_collection"; - if (user.isBuyer()) { - path = - "/$biz_collection/${setting.okEnergyId}/$buyer_collection/${user.docID}/$dos_collection"; - } - DateTime date = DateTime(dateTime.year, dateTime.month, dateTime.day); - DateTime dateAddOne = date.add(Duration(days: 1)); - - QuerySnapshot snapshots = await Firestore.instance - .collection(path) - .where("status", isEqualTo: do_approved_status) - .where("delivery_date", isGreaterThanOrEqualTo: date) - .where("delivery_date", isLessThan: dateAddOne) - .orderBy("delivery_date") - .orderBy("user_name") - .limit(100) - .getDocuments(); - snapshots.documents.forEach((d) { - dos.add(DOSubmission.fromMap(d.data, d.documentID)); - }); - return dos; - } -} diff --git a/lib/model/employee_model.dart b/lib/model/employee_model.dart deleted file mode 100644 index 3d3a6fc..0000000 --- a/lib/model/employee_model.dart +++ /dev/null @@ -1,64 +0,0 @@ -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:logging/logging.dart'; -import 'package:fcs/vo/user.dart'; - -import '../vo/user.dart'; -import 'base_model.dart'; -import 'constants.dart'; -import 'firebase_helper.dart'; - -class EmployeeModel extends BaseModel { - final log = Logger('EmployeeModel'); - - List employees = [ - User(name: 'Ko Nyi', phoneNumber: '+95 9 717273634',), - User(name: 'Ko Phyu', phoneNumber: '+1 (939) 382-3844'), - User(name: 'Ko Ye', phoneNumber: '+95 9 983734783',status: "Delivered"), - ]; - - void initUser(user) async { - super.initUser(user); - _loadEmployees(); - } - - @override - logout() async { - employees = []; - } - - Future _loadEmployees() async { - if (!user.isOwnerAndAbove() && !user.hasAccount()) { - return; - } - - try { - Firestore.instance - .collection("/$biz_collection/${setting.okEnergyId}/$user_collection") - .where("is_employee", isEqualTo: true) - .snapshots() - .listen((QuerySnapshot snapshot) { - employees.clear(); - employees = snapshot.documents.map((documentSnapshot) { - var user = - User.fromMap(documentSnapshot.data, documentSnapshot.documentID); - return user; - }).toList(); - notifyListeners(); - }).onError((e) { - log.warning("Error! $e"); - }); - } catch (e) { - log.warning("Error!! $e"); - } - } - - Future updatePrivileges(String userID, List privileges) async { - try { - await request("/employee/privileges", "PUT", - payload: {"id": userID, "privileges": privileges}, - token: await getToken()); - } catch (e) { - throw Exception(e); - } - } -} diff --git a/lib/model/firebase_helper.dart b/lib/model/firebase_helper.dart deleted file mode 100644 index d7e59b3..0000000 --- a/lib/model/firebase_helper.dart +++ /dev/null @@ -1,270 +0,0 @@ -import 'dart:io'; -import 'dart:typed_data'; - -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:firebase_auth/firebase_auth.dart'; -import 'package:firebase_storage/firebase_storage.dart'; -import 'package:logging/logging.dart'; -import 'package:uuid/uuid.dart'; - -final log = Logger('firebaseHelper'); - -final FirebaseAuth auth = FirebaseAuth.instance; - -Future getToken() async { - FirebaseUser firebaseUser = await auth.currentUser(); - // IdTokenResult token = await firebaseUser.getIdToken(); - // return token.token; - return ""; -} - -Stream getQuerySnapshot(String path) { - log.info("getQuerySnapshot Path: $path"); - Stream snapshots = - Firestore.instance.collection(path).snapshots(); - return snapshots; -} - -Stream getQuerySnapshotByOrder(String path, String orderName) { - log.info("getQuerySnapshotByOrder Path: $path"); - Stream snapshots = Firestore.instance - .collection(path) - .orderBy(orderName, descending: true) - .snapshots(); - return snapshots; -} - -Stream getFilterStatusSnapshot( - String path, String searchStatus, String orderName) { - log.info("getFilterStatusSnapshot Path: $path"); - Stream snapshots = Firestore.instance - .collection(path) - .where('status', isEqualTo: searchStatus) - .orderBy(orderName, descending: true) - .snapshots(); - return snapshots; -} - -Stream getFilterSnapshot( - String path, bool descending, String orderName) { - log.info("getFilterSnapshot Path: $path"); - Stream snapshots = Firestore.instance - .collection(path) - .orderBy(orderName, descending: descending) - .snapshots(); - return snapshots; -} - -Stream getDeliveryStatusSnapshot( - String path, String searchStatus, String orderName) { - log.info("getDeliveryStatusSnapshot Path: $path"); - Stream snapshots = Firestore.instance - .collection(path) - .where('status', isEqualTo: searchStatus) - .where("in_delivery", isEqualTo: true) - .orderBy(orderName, descending: true) - .snapshots(); - return snapshots; -} - -Stream getFilterDateSnapshot(String path, String type, - DateTime startDate, DateTime endDate, String orderName) { - log.info("getFilterDateSnapshot Path: $path"); - Firestore.instance - .collection(path) - .where(type, isGreaterThanOrEqualTo: startDate) - .where(type, isLessThanOrEqualTo: endDate) - .orderBy(type, descending: true) - .orderBy(orderName, descending: true) - .limit(1) - .getDocuments() - .then((s) {}); - - Stream snapshots = Firestore.instance - .collection(path) - .where(type, isGreaterThanOrEqualTo: startDate) - .where(type, isLessThanOrEqualTo: endDate) - .orderBy(type, descending: true) - .orderBy(orderName, descending: true) - .snapshots(); - return snapshots; -} - -Stream getDeliveryDateSnapshot(String path, String type, - DateTime startDate, DateTime endDate, String orderName) { - log.info("getDeliveryDateSnapshot Path: $path"); - Firestore.instance - .collection(path) - .where(type, isGreaterThanOrEqualTo: startDate) - .where(type, isLessThanOrEqualTo: endDate) - .where("in_delivery", isEqualTo: true) - .orderBy(type, descending: true) - .orderBy(orderName, descending: true) - .limit(1) - .getDocuments() - .then((s) {}); - - Stream snapshots = Firestore.instance - .collection(path) - .where(type, isGreaterThanOrEqualTo: startDate) - .where(type, isLessThanOrEqualTo: endDate) - .where("in_delivery", isEqualTo: true) - .orderBy(type, descending: true) - .orderBy(orderName, descending: true) - .snapshots(); - return snapshots; -} - -Stream getDeliverySnapshot(String path, String type, - DateTime startDate, DateTime endDate, String orderName) { - log.info("getDeliverySnapshot Path: $path"); - Firestore.instance - .collection(path) - .where(type, isGreaterThanOrEqualTo: startDate) - .where(type, isLessThanOrEqualTo: endDate) - .where("in_delivery", isEqualTo: true) - .orderBy(type, descending: true) - .orderBy(orderName, descending: true) - .limit(1) - .getDocuments() - .then((s) {}); - - Stream snapshots = Firestore.instance - .collection(path) - .where(type, isGreaterThanOrEqualTo: startDate) - .where(type, isLessThanOrEqualTo: endDate) - .where("in_delivery", isEqualTo: true) - .orderBy(type, descending: true) - .orderBy(orderName, descending: true) - .snapshots(); - return snapshots; -} - -Stream getFilterDataSnapshot(String path, String status, - String type, DateTime startDate, DateTime endDate, String orderName) { - log.info("getFilterDateSnapshot Path: $path"); - Stream snapshots = Firestore.instance - .collection(path) - .where('status', isEqualTo: status) - .where(type, isGreaterThanOrEqualTo: startDate) - .where(type, isLessThanOrEqualTo: endDate) - .orderBy(type, descending: true) - .orderBy(orderName, descending: true) - .snapshots(); - return snapshots; -} - -Stream getDeliveryDataSnapshot(String path, String status, - String type, DateTime startDate, DateTime endDate, String orderName) { - log.info("getDeliveryDataSnapshot Path: $path"); - Stream snapshots = Firestore.instance - .collection(path) - .where('status', isEqualTo: status) - .where("in_delivery", isEqualTo: true) - .where(type, isGreaterThanOrEqualTo: startDate) - .where(type, isLessThanOrEqualTo: endDate) - .orderBy(type, descending: true) - .orderBy(orderName, descending: true) - .snapshots(); - return snapshots; -} - -Stream getsearchBuyerSnapshot(String path, String buyer) { - log.info("getFilterDateSnapshot Path: $path"); - Stream snapshots = Firestore.instance - .collection(path) - .where("user_name", isEqualTo: buyer) - .snapshots(); - return snapshots; -} - -Stream getDocSnapshot(String path, String id) { - log.info("getDocSnapshot Path: $path, ID: $id"); - Stream snapshot = - Firestore.instance.collection(path).document(id).snapshots(); - return snapshot; -} - -Stream getQuerySnapshotF(String path, accountID) { - log.info("getQuerySnapshot Path: $path"); - Stream snapshots = Firestore.instance - .collection(path) - .where("account_id", isEqualTo: accountID) - .snapshots(); - return snapshots; -} - -Stream getFilterDateSnapshotF(String path, String accountID, - String type, DateTime startDate, DateTime endDate, String orderName) { - log.info("getFilterDateSnapshot Path: $path"); - Stream snapshots = Firestore.instance - .collection(path) - .where("account_id", isEqualTo: accountID) - .where(type, isGreaterThanOrEqualTo: startDate) - .where(type, isLessThanOrEqualTo: endDate) - .orderBy(orderName, descending: true) - .snapshots(); - return snapshots; -} - -Future getSnapshot(String path) { - log.info("getSnapshot Path: $path"); - Future snapshots = - Firestore.instance.collection(path).getDocuments(); - - return snapshots; -} - -Future getDocSnap(String path, String id) { - log.info("getDocSnap Path: $path"); - return Firestore.instance.collection(path).document(id).get(); -} - -Future uploadStorage(String path, File file, {String fileName}) async { - if (fileName == null) { - fileName = Uuid().v4(); - } - StorageReference storageReference = - FirebaseStorage.instance.ref().child('$path/$fileName'); - StorageUploadTask uploadTask = storageReference.putFile(file); - await uploadTask.onComplete; - String downloadUrl = await storageReference.getDownloadURL(); - print("name:${await storageReference.getName()}"); - print("bucket:${await storageReference.getBucket()}"); - print("path:${await storageReference.getPath()}"); - print("meta:${await storageReference.getMetadata()}"); - return downloadUrl; -} - -Future uploadStorageData(String path, Uint8List data, - {String fileName}) async { - if (fileName == null) { - fileName = Uuid().v4(); - } - StorageReference storageReference = - FirebaseStorage.instance.ref().child('$path/$fileName'); - StorageUploadTask uploadTask = storageReference.putData(data); - await uploadTask.onComplete; - String downloadUrl = await storageReference.getDownloadURL(); - return downloadUrl; -} - -Future deleteStorage(String path, name) async { - try { - StorageReference storageReference = - FirebaseStorage.instance.ref().child('$path/$name'); - await storageReference.delete(); - } catch (e) { - log.warning("deleteStorage:$e"); - } -} - -Future deleteStorageFromUrl(String url) async { - try { - StorageReference storageReference = - await FirebaseStorage.instance.getReferenceFromUrl(url); - await storageReference.delete(); - } catch (e) { - log.warning("deleteStorage:$e"); - } -} diff --git a/lib/model/invoice_model.dart b/lib/model/invoice_model.dart deleted file mode 100644 index b0d2d92..0000000 --- a/lib/model/invoice_model.dart +++ /dev/null @@ -1,163 +0,0 @@ -import 'package:fcs/vo/invoice.dart'; -import 'package:fcs/vo/package.dart'; - -import 'base_model.dart'; - -class InvoiceModel extends BaseModel { - List invoices = [ - Invoice( - invoiceNumber: 'A092(A)-30', - invoiceDate: DateTime(2020, 4, 5, 12, 30), - customerName: 'Ko Nyi', - customerPhoneNumber: '+959 888888888', - amount: 500, - status: 'Pending', - packages: [ - Package( - shipmentNumber: "A202", - receiverNumber: "3", - boxNumber: "1", - rate: 7, - packageType: "General", - weight: 25, - status: "Received", - receiverAddress: '1 Bo Yar Nyunt St.\nDagon Tsp, Yangon', - arrivedDate: DateTime(2020, 6, 1), - ), - Package( - shipmentNumber: "A202", - receiverNumber: "3", - boxNumber: "2", - rate: 7, - packageType: "General", - weight: 20, - status: "Received", - arrivedDate: DateTime(2020, 6, 1), - receiverAddress: '1 Bo Yar Nyunt St.\nDagon Tsp, Yangon'), - ], - receipts: [ - Receipt(amount: 200, date: DateTime(2020, 6, 1)), - Receipt(amount: 100, date: DateTime(2020, 6, 16)), - ]), - Invoice( - invoiceNumber: 'A092(A)-31', - invoiceDate: DateTime(2020, 4, 5, 9, 30), - customerName: 'Ko Aung Myo', - customerPhoneNumber: '+959 444444444', - amount: 300, - status: 'Paid', - packages: [ - Package( - shipmentNumber: "A202", - receiverNumber: "3", - boxNumber: "3", - rate: 7, - packageType: "General", - weight: 15, - status: "Received", - arrivedDate: DateTime(2020, 6, 1), - receiverAddress: '1 Bo Yar Nyunt St.\nDagon Tsp, Yangon'), - Package( - shipmentNumber: "A202", - receiverNumber: "2", - boxNumber: "1", - rate: 8, - packageType: "Medicine", - weight: 15, - status: "Processing", - arrivedDate: DateTime(2020, 6, 1), - receiverAddress: '2 Shwe Taung Kyar St, Bahan Tsp, Yangon'), - ], - receipts: [ - Receipt(amount: 200, date: DateTime(2020, 6, 1)), - ]), - Invoice( - invoiceNumber: 'A092(A)-32', - invoiceDate: DateTime(2020, 4, 6, 10, 10), - customerName: 'Ko Zaw Thu', - customerPhoneNumber: '+959 777777777', - amount: 200, - status: 'Paid', - packages: [ - Package( - shipmentNumber: "A202", - receiverNumber: "2", - boxNumber: "2", - rate: 7, - packageType: "General", - weight: 55, - status: "Ready to ship", - arrivedDate: DateTime(2020, 6, 1), - receiverAddress: '2 Shwe Taung Kyar St, Bahan Tsp, Yangon'), - Package( - shipmentNumber: "A201", - receiverNumber: "1", - boxNumber: "1", - rate: 9, - packageType: "Dangerous", - weight: 25, - status: "Delivered", - arrivedDate: DateTime(2020, 5, 21), - receiverAddress: '3 Kambzwza St, Bahan Tsp, Yangon'), - ], - receipts: [ - Receipt(amount: 200, date: DateTime(2020, 6, 1)), - ]), - Invoice( - invoiceNumber: 'A092(A)-33', - invoiceDate: DateTime(2020, 4, 6, 12, 15), - customerName: 'Ko Myo Min', - customerPhoneNumber: '+959 555555555', - amount: 300, - status: 'Pending', - receipts: [ - Receipt(amount: 200, date: DateTime(2020, 6, 1)), - ], - packages: [ - Package( - shipmentNumber: "A201", - receiverNumber: "1", - boxNumber: "1", - rate: 9, - packageType: "Dangerous", - weight: 25, - status: "Delivered", - arrivedDate: DateTime(2020, 5, 21), - receiverAddress: '3 Kambzwza St, Bahan Tsp, Yangon'), - Package( - shipmentNumber: "A201", - receiverNumber: "1", - boxNumber: "2", - rate: 7, - packageType: "General", - weight: 5, - status: "Delivered", - arrivedDate: DateTime(2020, 5, 21), - receiverAddress: '3 Kambzwza St, Bahan Tsp, Yangon'), - ]) - ]; - - List get pending { - List _i = invoices.where((e) => e.status == "Pending").toList() - ..sort((e1, e2) { - return e2.invoiceNumber.compareTo(e1.invoiceNumber); - }); - return _i; - } - - List get paided { - return invoices.where((e) => e.status == "Paid").toList() - ..sort((e1, e2) { - return e2.invoiceNumber.compareTo(e1.invoiceNumber); - }); - } - - void initUser(user) { - super.initUser(user); - } - - @override - logout() async { - invoices = []; - } -} diff --git a/lib/model/language_model.dart b/lib/model/language_model.dart deleted file mode 100644 index 274122c..0000000 --- a/lib/model/language_model.dart +++ /dev/null @@ -1,43 +0,0 @@ -import 'package:flutter/painting.dart'; -import 'package:fcs/model/base_model.dart'; -import 'package:fcs/model/shared_pref.dart'; -import 'package:fcs/vo/setting.dart'; -import 'package:fcs/widget/localization/transalation.dart'; - -class LanguageModel extends BaseModel { - String language; - bool isEng = true; - static final List languageCodesList = - Translation().supportedLanguagesCodes; - static final List languagesList = Translation().supportedLanguages; - - final Map languagesMap = { - languagesList[0]: languageCodesList[0], - languagesList[1]: languageCodesList[1], - }; - - void initSetting(Setting setting) async { - this.language = await load(); - this.isEng = this.language == "English"; - Translation().onLocaleChanged(Locale(languagesMap[language])); - notifyListeners(); - } - - @override - logout() async {} - - Future load() async { - var data = await SharedPref.getLang(); - if (data == null) return languagesList[1]; - return data; - } - - void saveLanguage(String language) async { - Translation().onLocaleChanged(Locale(languagesMap[language])); - - // SharedPref.saveLang(language); - this.language = language; - this.isEng = this.language == "English"; - notifyListeners(); - } -} diff --git a/lib/model/log_model.dart b/lib/model/log_model.dart deleted file mode 100644 index 9d5b44a..0000000 --- a/lib/model/log_model.dart +++ /dev/null @@ -1,59 +0,0 @@ -import 'dart:async'; - -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:fcs/vo/document_log.dart'; -import 'package:fcs/vo/log.dart'; - -import 'base_model.dart'; -import 'constants.dart'; - -class LogModel extends BaseModel { - List logs = []; - List docLogs = []; - - void initUser(user) { - super.initUser(user); - _loadLogs(); - } - - - @override - logout() async { - logs = []; - docLogs=[]; - } - Future _loadLogs() async { - Stream snapshots = Firestore.instance - .collection( - "/$biz_collection/${setting.okEnergyId}/$user_collection/${user.docID}/$log_collection") - .orderBy("active_time", descending: true) - .limit(30) - .snapshots(); - - snapshots.listen((snaps) async { - logs = snaps.documents - .map((documentSnapshot) => - Log.fromMap(documentSnapshot.data, documentSnapshot.documentID)) - .toList(); - notifyListeners(); - }); - } - - Future loadDocLogs(String docID) async { - Stream snapshots = Firestore.instance - .collection("/$biz_collection/${setting.okEnergyId}/$log_collection") - .where('doc_id', isEqualTo: docID) - .orderBy('date', descending: true) - .limit(30) - .snapshots(); - - snapshots.listen((snaps) async { - docLogs.clear(); - docLogs = snaps.documents - .map((documentSnapshot) => DocLog.fromMap( - documentSnapshot.data, documentSnapshot.documentID)) - .toList(); - notifyListeners(); - }); - } -} diff --git a/lib/model/main_model.dart b/lib/model/main_model.dart deleted file mode 100644 index 49ae5a6..0000000 --- a/lib/model/main_model.dart +++ /dev/null @@ -1,521 +0,0 @@ -import 'dart:async'; -import 'dart:io'; - -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:device_info/device_info.dart'; -import 'package:dio/dio.dart'; -import 'package:fcs/fcs/common/services/services.dart'; -import 'package:fcs/vo/payment_method.dart'; -import 'package:firebase_auth/firebase_auth.dart'; -import 'package:firebase_messaging/firebase_messaging.dart'; -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; -import 'package:logging/logging.dart'; -import 'package:package_info/package_info.dart'; -import 'package:path/path.dart' as Path; -import 'package:fcs/model/shared_pref.dart'; -import 'package:fcs/util.dart'; -import 'package:fcs/vo/bank_account.dart'; -import 'package:fcs/vo/buyer.dart'; -import 'package:fcs/vo/setting.dart'; -import 'package:fcs/widget/NetworkConnectivity.dart'; - -import '../config.dart'; -import '../vo/status.dart'; -import '../vo/user.dart'; -import '../fcs/common/helpers/api_helper.dart'; -import 'base_model.dart'; -import 'constants.dart'; -import 'firebase_helper.dart'; - -class ImplementInterfaceModel { - void initUser(User user) => {}; - void initSetting(Setting setting) => {}; -} - -class MainModel extends ChangeNotifier { - final log = Logger('MainModel'); - - final FirebaseAuth auth = FirebaseAuth.instance; - FirebaseMessaging firebaseMessaging; - - List models = []; - User user; - Buyer buyer; - FirebaseUser firebaseUser; - StreamSubscription userListener; - StreamSubscription buyerListener; - bool pinRequired; - Timer pinTimer; - - User customer = User( - name: "Ko Myo Min", - phoneNumber: '+95 9 444444444', - fcsID: 'FCS-0203-390-2', - shippingAddress: - '154-19 64th Ave.Flushing, \nNY 11367 \nTEL. +1 (929) 215-2247', - deliveryAddress: '39 42th St. Kyaut Ta Thar Township Yangon'); - - User recipient = User( - name: "Ko Myo Min", - phoneNumber: '+95 9 444444444', - shippingAddress: '154-19 64th Ave.Flushing, \nNY 11367', - deliveryAddress: '39 42th St. Kyaut Ta Thar Township Yangon'); - - Setting setting = Setting( - terms: - '[{"insert":"* Minimum shipping weight is 1lbs.\n* Oversized goods, Light weight/Large volume items, laptops, phones, tablets may incur extra charges based on pecifications.Please contact us for pricing.\n* Goods with lithium battary needs extra packaging and declaration. Please inform us ahead of time so that we can process your package accordingly.\n* Loose Batteries, Drones, and Prescription medicines are not allowed on aircraft.\n* Payment: We accept money orders, any US bank transfers via Zelle, AYA, KBZ and CB. No COD except for pick-ups.\n*Payments made in Myanmar will incur 2% tranfer fee\n"}]'); - PackageInfo packageInfo; - bool isLoaded = true; - bool isOnline = true; - - static const PIN_TIME_MIN = 10; - - MainModel() { - // NetworkConnectivity.instance.statusStream.listen((data) { - // bool _isOnline = data["isOnline"]; - // if (_isOnline && !this.isOnline) { - // init(); - // } - // this.isOnline = _isOnline; - // notifyListeners(); - // }); - _loadFcs(); - Services.instance.authService.onAuthStatus().listen((event) {}); - } - - List get paymentMethods { - List methods = [ - PaymentMethod( - name: 'AYA Bank', - accountName: 'FCS', - account: '100 23404320548398', - phone: '+959123456789', - mail: 'aya@gmail.com'), - PaymentMethod( - name: 'KBZ Bank', - accountName: 'FCS', - account: '100 23404320548398', - phone: '+959123456789', - mail: 'kbz@gmail.com'), - PaymentMethod( - name: 'PayPal', - accountName: 'FCS', - link: 'https://www.paypal.com/donate/buttons', - ), - ]; - return methods; - } - - _loadFcs() async { - user = await SharedPref.getUser(); - notifyListeners(); - } - - saveUser(String pin, String phone) { - if (pin == "000000") { - user = User(name: "Owner", phoneNumber: phone); - SharedPref.saveUser(user); - } else { - user = User(name: "Customer", phoneNumber: phone); - SharedPref.saveUser(user); - } - notifyListeners(); - } - - resetPinTimer() { - if (pinTimer != null && pinTimer.isActive) { - pinTimer.cancel(); - } - pinRequired = false; - pinTimer = Timer(Duration(minutes: PIN_TIME_MIN), () { - pinRequired = true; - }); - } - - bool isLogin() { - return this.user != null; - } - - bool isCustomer() { - return user != null && user.name != "Owner"; - } - - bool isOwner() { - return user != null && user.name == "Owner"; - } - - bool hasEmail() { - return this.user != null && this.user.isEmail(); - } - - bool agreedTerm() { - return this.user != null && this.user.agreeTerms; - } - - bool isBuyer() { - return this.user == null || this.user.isBuyer(); - } - - bool isRegBuyer() { - return isBuyer() && buyer != null; - } - - bool isApprovedBuyer() { - return isBuyer() && buyer != null && buyer.isApproved(); - } - - bool isSysAdmin() { - return this.user != null && this.user.isSysAdmin(); - } - - bool isSysSupport() { - return this.user != null && this.user.isSysSupport(); - } - - bool isBizAdmin() { - return this.user != null && this.user.isBizAdmin(); - } - - bool isOwnerAndAbove() { - return this.user != null && this.user.isOwnerAndAbove(); - } - - bool isAdmin() { - return this.user != null && this.user.hasAdmin(); - } - - bool showHistoryBtn() { - return isSysAdmin() || isSysSupport() || isBizAdmin(); - } - - init() async { - // await _loadSetting(); - // _loadUser(); - // resetPinTimer(); - } - - void addModel(BaseModel model) { - models.add(model); - } - - void _initUser(User user) { - models.forEach((m) => m.initUser(user)); - - if (firebaseMessaging != null) { - firebaseMessaging.subscribeToTopic(user.docID); - } - } - - void _initSetting(Setting setting) { - models.forEach((m) => m.initSetting(setting)); - } - - Future _loadSetting() async { - this.setting = await _getSetting(); - this.packageInfo = await PackageInfo.fromPlatform(); - _initSetting(setting); - } - - void _loadUser() async { - this.firebaseUser = await auth.currentUser(); - if (this.firebaseUser == null) { - this.isLoaded = true; - notifyListeners(); - return; - } - - _logUser(this.firebaseUser); - - // load from local, if successful,notify listeners - User _user = await SharedPref.getUser(); - if (_user != null) { - await _user.setFirebaseUser(this.firebaseUser); - _initUser(_user); - this.user = _user; - - if (this.user.isRegisteredBuyer()) { - _loadBuyer(); - } - this.isLoaded = true; - notifyListeners(); - log.info("user loaded from shared pref!"); - } - - _listenUser(); - } - - void _listenUser() { - if (this.userListener != null) { - this.userListener.cancel(); - } - - this.userListener = getDocSnapshot( - "/$biz_collection/${setting.okEnergyId}/$user_collection", - firebaseUser.uid) - .listen((userSnap) async { - if (userSnap.exists) { - User _user = User.fromMap(userSnap.data, userSnap.documentID); - - // load claims - try { - FirebaseUser _firebaseUser = await getProfile(this.firebaseUser); - - await _user.setFirebaseUser(_firebaseUser); - _initUser(_user); - this.user = _user; - this.firebaseUser = _firebaseUser; - await SharedPref.saveUser(this.user); - } catch (e) { - log.warning(e.toString()); - } - - log.info( - "_loadUser => ID: ${this.user.docID}, AccountID: ${this.user.accountID}," - "BizID: ${this.user.accountID}," - ", Privileges: ${this.user.claimPrivileges}, isSysAdmin: ${this.user.isSysAdmin()}"); - - if (this.user.isRegisteredBuyer()) { - _loadBuyer(); - } - this.isLoaded = true; - notifyListeners(); - } - }); - } - - void _loadBuyer() async { - if (this.user == null) return; - if (buyerListener != null) buyerListener.cancel(); - buyerListener = getDocSnapshot( - "/$biz_collection/${setting.okEnergyId}/$buyer_collection", - this.user.docID) - .listen((buyerSnap) async { - if (buyerSnap.exists) { - this.buyer = Buyer.fromMap(buyerSnap.data, buyerSnap.documentID); - } else { - this.buyer = null; - } - notifyListeners(); - }); - } - - @override - void dispose() { - super.dispose(); - // if (this.userListener != null) { - // this.userListener.cancel(); - // } - // SharedPref.removeUser(); - // this.user = User(); - } - - Future login(String phoneNumber, String pass) async { - var id = phoneNumber.replaceFirst("+", ""); - id = updatePhoneNumber(id); - - var data = {"id": id, "password": pass}; - var result = await requestAPI("/login", "POST", payload: data); - - var token = result["Token"]; - - // login with custom token - // AuthResult r = await this.auth.signInWithCustomToken(token: token); - // this.firebaseUser = r.user; - isLoaded = false; - _loadUser(); - _logUser(this.firebaseUser); - } - - Future getProfile(FirebaseUser firebaseUser) async { - // IdTokenResult idtoken = await firebaseUser.getIdToken(); - var data = await requestAPI( - "/profile", - "GET", - token: "", //idtoken.token, - ); - var _token = data["Token"]; - // AuthResult a = await this.auth.signInWithCustomToken(token: _token); - // return a.user; - return null; - } - - Future _logUser(FirebaseUser firebaseUser) async { - // IdTokenResult idtoken = await firebaseUser.getIdToken(); - - await requestAPI( - "/log", - "GET", - token: "", //idtoken.token, - ); - } - - Future logout() async { - this.user = null; - notifyListeners(); - return; - - if (this.userListener != null) { - await this.userListener.cancel(); - } - - await auth.signOut(); - this.user = null; - this.buyer = null; - this.firebaseUser = null; - await SharedPref.removeUser(); - if (firebaseMessaging != null) { - firebaseMessaging.unsubscribeFromTopic(user.docID); - } - - // logout models - models.forEach((m) => m.logout()); - - notifyListeners(); - } - - Future signup( - String name, password, confirmPassword, phoneNumber) async { - if (password == "" || password.length < 6) { - throw Exception("Password must be at least 6 characters"); - } - if (password != confirmPassword) { - throw Exception("Password mismatch"); - } - var id = phoneNumber.replaceFirst("+", ""); - id = updatePhoneNumber(id); - - var inputData = {"id": id, "password": password, "user_name": name}; - DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); - AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo; - String deviceName = "${androidInfo.model}(${androidInfo.id})"; - - var url = "${Config.instance.apiURL}/signup"; - Response response = await Dio().post(url, - data: inputData, - options: Options( - headers: {"Device": androidInfo.androidId + ":" + deviceName})); - - var data = Status.fromJson(response.data); - if (data.status != 'Ok') { - throw Exception("${data.errorCode} : ${data.message}"); - } - } - - Future confirmSignup( - String phoneNumber, password, confirmSMSCode) async { - var id = phoneNumber.replaceFirst("+", ""); - id = updatePhoneNumber(id); - - if (confirmSMSCode == "" || confirmSMSCode.length != 6) { - throw Exception("Password must be 6 characters"); - } - - var inputData = { - "id": id, - "password": password, - "confirmation_code": confirmSMSCode - }; - var url = "${Config.instance.apiURL}/confirm"; - Response response = await Dio().post( - url, - data: inputData, - ); - var data = Status.fromJson(response.data); - if (data.status != 'Ok') { - throw Exception(data.message); - } - } - - bool isSupport() { - if (packageInfo == null || setting == null) return false; - return int.parse(packageInfo.buildNumber) >= setting.supportBuildNum; - } - - Future _getSetting() async { - var snap = await Firestore.instance - .collection(config_collection) - .document(setting_doc_id) - .get(); - if (!snap.exists) { - return null; - } - _listSetting(); - return Setting.fromMap(snap.data); - } - - void _listSetting() { - getDocSnapshot("/configs", setting_doc_id).listen((snap) { - this.setting = Setting.fromMap(snap.data); - notifyListeners(); - }); - } - - Future updateProfile(String name) async { - await requestAPI("/user", "PUT", - payload: {"user_name": name}, token: await getToken()); - } - - Future updateTerms(String terms) async { - await requestAPI("/terms", "PUT", - payload: {"terms": terms}, token: await getToken()); - } - - Future agreeTerms() async { - await requestAPI("/user/agree", "PUT", token: await getToken()); - } - - Future updateContact(Setting setting) async { - await requestAPI("/contact", "PUT", - payload: { - 'email': setting.email, - 'facebook_url': setting.facebook, - 'web_url': setting.website, - 'phones': setting.phones, - 'bank_account_info': setting.bankAccountInfo, - 'delivery_phone': setting.deliveryPhone, - 'address': setting.address, - }, - token: await getToken()); - } - - Future updateSetting(Setting setting) async { - await requestAPI("/setting", "PUT", - payload: { - 'do_expire_hours': setting.doExpireInHours, - 'po_expire_hours': setting.poExpireInHours, - 'po_open_at': setting.poOpenAt, - 'po_close_at': setting.poCloseAt, - 'po_close_on': setting.poCloseOn, - 'first_storage_charge_in': setting.firstStorageChargeIn, - 'first_storage_charge': setting.firstStorageCharge, - 'second_storage_charge_in': setting.secondStorageChargeIn, - 'second_storage_charge': setting.secondStorageCharge, - 'latest_delivery_days': setting.latestDeliveryDay, - }, - token: await getToken()); - } - - Future addBankAccount(BankAccount bankAccount, File image) async { - String url = await uploadStorage(bank_images_path, image); - bankAccount.bankLogo = url; - - await requestAPI("/bank_accounts", "POST", - payload: bankAccount.toMap(), token: await getToken()); - } - - Future updateBankAccount(BankAccount bankAccount, File image) async { - if (image != null) { - String url = await uploadStorage(bank_images_path, image); - bankAccount.bankLogo = url; - } - - await requestAPI("/bank_accounts", "PUT", - payload: bankAccount.toMap(), token: await getToken()); - } - - Future deleteBankAccount(BankAccount bankAccount) async { - await requestAPI("/bank_accounts", "DELETE", - payload: bankAccount.toMap(), token: await getToken()); - } -} diff --git a/lib/model/manual_model.dart b/lib/model/manual_model.dart deleted file mode 100644 index 8a778da..0000000 --- a/lib/model/manual_model.dart +++ /dev/null @@ -1,234 +0,0 @@ -import 'dart:convert'; -import 'dart:io'; -import 'dart:typed_data'; - -import 'package:archive/archive_io.dart'; -import 'package:http/http.dart' as http; -import 'package:logging/logging.dart'; -import 'package:path_provider/path_provider.dart'; -import 'package:fcs/model/firebase_helper.dart'; -import 'package:fcs/vo/manual.dart'; -import 'package:fcs/vo/setting.dart'; -import 'package:path/path.dart' as Path; - -import 'base_model.dart'; - -typedef void SlideDataCallback(); - -class ManualModel extends BaseModel { - final log = Logger('ManualModel'); - - List helps = []; - List manuals = []; - String version; - SlideDataCallback slideDataCallback; - List deleteImage = []; - - String dataDir; - - void initSetting(Setting setting) async { - _download(setting); - super.initSetting(setting); - } - - @override - logout() async {} - - Future _download(Setting setting) async { - this.dataDir = (await getApplicationDocumentsDirectory()).path; - version = setting.helpVersion; - var file = File('$dataDir/${setting.helpFileName()}'); - if (await file.exists()) { - _loadJsonData(); - return; - } - - String url = setting.helpURL; - var req = await http.Client().get(Uri.parse(url)); - - File zippedFile = await file.writeAsBytes(req.bodyBytes); - File prev = File('$dataDir/manual'); - if (await prev.exists()) { - await prev.delete(recursive: true); - } - - var bytes = zippedFile.readAsBytesSync(); - var archive = ZipDecoder().decodeBytes(bytes); - for (var file in archive) { - var fileName = '$dataDir/manual/${file.name}'; - if (file.isFile) { - var outFile = File(fileName); - outFile = await outFile.create(recursive: true); - await outFile.writeAsBytes(file.content); - } - } - _loadJsonData(); - } - - List getHelpList(bool isBuyer) { - return helps.where((h) => isBuyer ? h.isBuyer : true).toList(); - } - - getSlideList(int manIndex) { - var slides = helps[manIndex].slides; - return slides; - } - - getSlideData(int manIndex, int slideIndex) { - var slide; - slide = helps[manIndex].slides[slideIndex]; - return slide; - } - - Future _loadJsonData() async { - try { - final directory = await getApplicationDocumentsDirectory(); - File file = File('${directory.path}/manual/manual.json'); - String contents = await file.readAsString(); - - var convertArray = jsonDecode(contents); - manuals.clear(); - convertArray.forEach((item) { - var _list = ManualItem.fromMap(item); - manuals.add(_list); - }); - } catch (e) { - log.warning("Error:${e.toString()}"); - } - helps.clear(); - helps = manuals.map((e) => ManualItem.clone(e)).toList(); - } - - addManualTitle(ManualItem manualItem) { - helps.add(manualItem); - notifyListeners(); - } - - uploadStorageManualData(String version, String dir) async { - String fileName = 'help-v$version.zip'; - - var converthelps = []; - for (final converthelp in helps) { - converthelps.add(converthelp.toJson()); - } - var json = jsonEncode(converthelps); - - Directory myDir = new Directory('$dir/manual/img'); - List _images; - _images = myDir.listSync(recursive: true, followLinks: false); - - var newImgData = await convertArchiveImgFile(_images, dir, json); - File updateImgFile = File('$dir/manual/update'); - updateImgFile.writeAsBytesSync(newImgData); - - var bytes = updateImgFile.readAsBytesSync(); - uploadDataZip(bytes, fileName); - } - - convertArchiveImgFile(List imgList, String dataDir, json) async { - File file = new File('$dataDir/update'); - if (await file.exists()) { - await file.delete(recursive: true); - } - - Archive zipArchive = new Archive(); - List utf8encoded = utf8.encode(json); - ArchiveFile jsonFile = - new ArchiveFile("manual.json", utf8encoded.length, utf8encoded); - zipArchive.addFile(jsonFile); - - for (var img in imgList) { - String basename = Path.basename(img.path); - if (deleteImage.length != 0) { - for (var dImgName in deleteImage) { - if (dImgName != basename) { - Uint8List bytesPhoto = img.readAsBytesSync() as Uint8List; - ArchiveFile jsonFile = - new ArchiveFile("img/$basename", bytesPhoto.length, bytesPhoto); - zipArchive.addFile(jsonFile); - } - } - } else { - Uint8List bytesPhoto = img.readAsBytesSync() as Uint8List; - ArchiveFile jsonFile = - new ArchiveFile("img/$basename", bytesPhoto.length, bytesPhoto); - zipArchive.addFile(jsonFile); - } - } - List zipInBytes = new ZipEncoder().encode(zipArchive); - file.writeAsBytesSync(zipInBytes); - var bytes = file.readAsBytesSync(); - return bytes; - } - - uploadDataZip(Uint8List data, String fileName) async { - String path = '/ok/img'; - String url = await uploadStorageData(path, data, fileName: fileName); - } - - resetManualItems() { - helps.clear(); - //clone manauals - helps = manuals.map((p) => ManualItem.clone(p)).toList(); - // return helps.where((h) => isBuyer ? h.isBuyer : true).toList(); - } - - saveInstruction(int manIndex, int slideIndex, int instIndex, - Instruction instruction, Instruction oldInst, bool isEng) { - if (isEng) { - var inst = helps[manIndex].slides[slideIndex].instructions.toList(); - instruction.id = oldInst.id; - if (inst.length != 0) { - helps[manIndex].slides[slideIndex].instructions.remove(oldInst); - helps[manIndex] - .slides[slideIndex] - .instructions - .insert(instIndex, instruction); - } else { - helps[manIndex].slides[slideIndex].instructions.add(instruction); - } - } else { - var inst = helps[manIndex].slides[slideIndex].instructionsmm.toList(); - instruction.id = oldInst.id; - if (inst.length != 0) { - helps[manIndex].slides[slideIndex].instructionsmm.remove(oldInst); - helps[manIndex] - .slides[slideIndex] - .instructionsmm - .insert(instIndex, instruction); - } else { - helps[manIndex].slides[slideIndex].instructionsmm.add(instruction); - } - } - notifyListeners(); - } - - saveSlideData(int manIndex, int slideIndex, SlideData slideData) { - helps[manIndex].slides.add(slideData); - notifyListeners(); - } - - changeSlideImage(int manIndex, int slideIndex, SlideData slideData) { - var oldSlide = helps[manIndex].slides[slideIndex]; - helps[manIndex].slides.remove(oldSlide); - helps[manIndex].slides.insert(slideIndex, slideData); - notifyListeners(); - } - - deleteSlideData(int manIndex, SlideData slideData) { - String engImage = slideData.image; - String mmImage = slideData.imagemm; - deleteImage.add(mmImage); - deleteImage.add(engImage); - helps[manIndex].slides.remove(slideData); - notifyListeners(); - } - - deleteManualItem(ManualItem item) { - // if(helps.isEmpty){ - // helps = new List(); - // } - helps.remove(item); - notifyListeners(); - } -} diff --git a/lib/model/messaging.dart b/lib/model/messaging.dart deleted file mode 100644 index c3c8fbf..0000000 --- a/lib/model/messaging.dart +++ /dev/null @@ -1,35 +0,0 @@ -import 'package:firebase_messaging/firebase_messaging.dart'; -import 'package:logging/logging.dart'; -import 'package:fcs/vo/user.dart'; - -class MessagingFCM { - final log = Logger('MessagingFCM'); - - final FirebaseMessaging _firebaseMessaging = FirebaseMessaging(); - - MessagingFCM(User user) { - _firebaseMessaging.configure( - onMessage: (Map message) async { - log.info("onMessage: $message"); - }, - // onBackgroundMessage: backgroundMessageHandler, - onLaunch: (Map message) async { - log.info("onLaunch: $message"); - }, - onResume: (Map message) async { - log.info("onResume: $message"); - }, - ); - _firebaseMessaging.requestNotificationPermissions( - const IosNotificationSettings( - sound: true, badge: true, alert: true, provisional: true)); - _firebaseMessaging.onIosSettingsRegistered - .listen((IosNotificationSettings settings) { - log.info("Settings registered: $settings"); - }); - _firebaseMessaging.getToken().then((String token) { - log.info("Token:$token"); - }); - _firebaseMessaging.subscribeToTopic(user.docID); - } -} diff --git a/lib/model/notification_model.dart b/lib/model/notification_model.dart deleted file mode 100644 index a5ed5b6..0000000 --- a/lib/model/notification_model.dart +++ /dev/null @@ -1,96 +0,0 @@ -import 'dart:async'; - -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:fcs/vo/notification.dart'; - -import 'base_model.dart'; -import 'constants.dart'; -import 'firebase_helper.dart'; - -class NotificationModel extends BaseModel { - int filer = 0; - List notifications = [ - Notification( - desc: 'Package delivered!', - status: 'A102A-34-#23', - time: DateTime(2020, 4, 28, 10, 32)), - Notification( - desc: 'Package in transit!', - status: 'A102A-34-#24', - time: DateTime(2020, 4, 26, 9, 32)), - Notification( - desc: 'Package delivered!', - status: 'A102A-34-#23', - time: DateTime(2020, 4, 24, 10, 32)), - Notification( - marketPlace: "Macy", - desc: "Audited received goods!", - status: 'ORDER # 114-0725982-9074639', - time: DateTime(2020, 4, 22, 12, 30)), - Notification( - marketPlace: "Amazon", - desc: "Receive goods!", - status: 'ORDER # 323-982-2308', - time: DateTime(2020, 4, 22, 12, 22)) - ]; - - var filterValues = {1: "po", 2: "do", 3: "buyer"}; - List get notis { - return notifications - .where((n) => filer == 0 || n.itemType == filterValues[filer]) - .toList(); - } - - int unseen = 0; - - void initUser(user) { - super.initUser(user); - _loadNotifications(); - } - - @override - logout() async { - notifications = []; - } - - Future _loadNotifications() async { - Stream snapshots = Firestore.instance - .collection( - "/$biz_collection/${setting.okEnergyId}/$user_collection/${user.docID}/$notification_collection") - .orderBy("time", descending: true) - .limit(50) - .snapshots(); - - snapshots.listen((snaps) async { - notifications.clear(); - unseen = 0; - // snaps.documentChanges.forEach((c) { - // if (c.type == DocumentChangeType.added) { - // FlutterRingtonePlayer.play( - // android: AndroidSounds.notification, - // ios: IosSounds.glass, - // ); - // } - // }); - snaps.documents.forEach((d) { - var n = Notification.fromMap(d.data, d.documentID); - if (!n.seen) unseen++; - notifications.add(n); - }); - notifyListeners(); - }); - } - - void filter(int filter) { - this.filer = filter; - } - - Future seen() async { - await request("/notification/seen", "POST", token: await getToken()); - } - - Future seenID(String id) async { - await request("/notification/seen/${user.docID}/$id", "POST", - token: await getToken()); - } -} diff --git a/lib/model/pagination/paginator.dart b/lib/model/pagination/paginator.dart deleted file mode 100644 index 60275d2..0000000 --- a/lib/model/pagination/paginator.dart +++ /dev/null @@ -1,4 +0,0 @@ - -class Listener { - -} \ No newline at end of file diff --git a/lib/model/pd_model.dart b/lib/model/pd_model.dart deleted file mode 100644 index 3e50965..0000000 --- a/lib/model/pd_model.dart +++ /dev/null @@ -1,88 +0,0 @@ -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:logging/logging.dart'; -import 'package:fcs/model/constants.dart'; -import 'package:fcs/vo/pd.dart'; -import 'package:fcs/vo/user.dart'; - -import 'base_model.dart'; -import 'firebase_helper.dart'; - -class PDModel extends BaseModel { - final log = Logger('PDModel'); - - List pds = []; - int dateIndex = 0; - DateTime selectedDate = DateTime.now(); - - void initUser(User user) async { - super.initUser(user); - loadPDs(); - } - - - @override - logout() async { - pds = []; - } - - loadPDs() { - if (!user.isOwnerAndAbove() && !user.hasInventory()) { - return; - } - - try { - String path = "/$biz_collection/${setting.okEnergyId}/$pds_collection"; - var startDate = new DateTime( - selectedDate.year, selectedDate.month, selectedDate.day, 0, 0, 0); - var endDate = new DateTime( - selectedDate.year, selectedDate.month, selectedDate.day, 23, 59, 59); - pds.clear(); - getFilterDateSnapshot(path, 'date', startDate, endDate, 'pd_number') - .listen((QuerySnapshot snapshot) { - pds = snapshot.documents.map((documentSnapshot) { - var data = - PD.fromMap(documentSnapshot.data, documentSnapshot.documentID); - return data; - }).toList(); - notifyListeners(); - }).onError((e) { - log.warning("Error! $e"); - }); - } catch (e) { - log.warning("Error!! $e"); - } - } - - Future loadPDLines(PD pd) async { - var snaps = await getSnapshot( - "/$biz_collection/${setting.okEnergyId}/$pds_collection/${pd.id}/$product_collection"); - pd.pdLines = snaps.documents.map((s) => PDLine.fromMap(s.data)).toList(); - return pd; - } - - Future createPD(PD pd) async { - await request("/pd", "POST", - payload: pd.toMap(), token: await getToken()); - } - - void filterDate(DateTime dateTime, int _dateIndex) { - this.selectedDate = dateTime; - this.dateIndex = _dateIndex; - String path = "/$biz_collection/${setting.okEnergyId}/$pds_collection"; - var endDate = - new DateTime(dateTime.year, dateTime.month, dateTime.day, 23, 59, 59); - pds.clear(); - getFilterDateSnapshot(path, 'date', dateTime, endDate, 'pd_number').listen( - (snaps) { - pds = snaps.documents.map((documentSnapshot) { - var data = - PD.fromMap(documentSnapshot.data, documentSnapshot.documentID); - return data; - }).toList(); - notifyListeners(); - }, onError: (error) { - log.warning("FIRESTORE ERROR>>$error"); - }); - } -} - diff --git a/lib/model/pickup_model.dart b/lib/model/pickup_model.dart deleted file mode 100644 index 1ffd1d5..0000000 --- a/lib/model/pickup_model.dart +++ /dev/null @@ -1,392 +0,0 @@ -import 'dart:async'; - -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:fcs/vo/cargo.dart'; -import 'package:fcs/vo/fcs_profile.dart'; -import 'package:fcs/vo/pickup.dart'; -import 'package:fcs/vo/radio.dart'; -import 'package:logging/logging.dart'; - -import 'base_model.dart'; - -class PickUpModel extends BaseModel { - final log = Logger('PickUpModel'); - - StreamSubscription listener; - - var profile = FCSProfile( - id: '1', - usaAddress: '154-19 64th Ave.\nFlushing, NY 11367', - mmAddress: 'FCS Trading Myanmar\nRoom 333, Yangon', - usaContactNumber: '1 (929) 215-2247', - mmContactNumber: '+95 9 700224723', - mail: 'admin@fcs.com', - facebook: 'https://facebook.com/fcs'); - - List radioGroups1 = [ - RadioGroup( - text: "FCS Pickup", - index: 1, - ), - RadioGroup( - text: "Courier Pickup", - index: 2, - ), - RadioGroup( - text: "FCS Drop-off", - index: 3, - ), - RadioGroup( - text: "Courier Drop-off", - index: 4, - ), - ]; - - List get radioGroups { - List radioGroups = [ - RadioGroup( - text: "Local Pickup", - index: 1, - ), - RadioGroup( - text: "Courier Pickup", - index: 2, - ), - RadioGroup( - text: "Local Drop-off", - index: 3, - ), - RadioGroup( - text: "Courier Drop-off", - index: 4, - ), - ]; - return radioGroups; - } - - List get pickups { - - List pickups = [ - PickUp( - id: "S200412 - 12 Apr 2020", - userName: "Ko Kyaw Nyi", - phoneNumber: '+959111111111', - fromTime: '1PM', - toTime: '3PM', - numberOfPackage: 5, - weight: 25, - status: 'Pending', - date: DateTime(2020, 5, 1), - address: '154-19 64th Ave.\nFlushing, NY 11367', - handlingFee: 50, - isCourier: true, - radioIndex: 2, - cargoTypes: [ - Cargo(type: 'General Cargo', weight: 25), - Cargo(type: 'Medicine', weight: 20), - Cargo(type: 'Dangerous Cargo', weight: 30) - ]), - PickUp( - id: "S200125 - 12 May 2020", - userName: "Ko Kyaw Nyi", - phoneNumber: '+959111111111', - fromTime: '1PM', - toTime: '3PM', - numberOfPackage: 5, - weight: 25, - status: 'Confirmed', - date: DateTime(2020, 5, 6), - address: '154-19 64th Ave.\nFlushing, NY 11367', - handlingFee: 50, - cargoTypes: [ - Cargo(type: 'General Cargo', weight: 25), - Cargo(type: 'Medicine', weight: 20), - Cargo(type: 'Dangerous Cargo', weight: 30) - ]), - PickUp( - id: "S200441 - 13 Apr 2020", - userName: "Ko Kyaw Nyi", - phoneNumber: '+959111111111', - fromTime: '1PM', - toTime: '3PM', - numberOfPackage: 5, - weight: 25, - status: "Pickuped", - date: DateTime(2020, 5, 9), - address: '154-19 64th Ave.\nFlushing, NY 11367', - handlingFee: 50, - radioIndex: 3, - cargoTypes: [ - Cargo(type: 'General Cargo', weight: 25), - Cargo(type: 'Medicine', weight: 20), - Cargo(type: 'Dangerous Cargo', weight: 30) - ]), - PickUp( - id: "S200412 - 12 Apr 2020", - userName: "Ko Kyaw Nyi", - phoneNumber: '+959111111111', - fromTime: '1PM', - toTime: '3PM', - numberOfPackage: 5, - weight: 25, - status: 'Pickuped', - date: DateTime(2020, 5, 15), - address: '154-19 64th Ave.\nFlushing, NY 11367', - handlingFee: 50, - cargoTypes: [ - Cargo(type: 'General Cargo', weight: 25), - Cargo(type: 'Medicine', weight: 20), - Cargo(type: 'Dangerous Cargo', weight: 30) - ]), - PickUp( - id: "S200125 - 12 May 2020", - userName: "Ko Kyaw Nyi", - phoneNumber: '+959111111111', - fromTime: '1PM', - toTime: '3PM', - numberOfPackage: 5, - weight: 25, - status: 'Pickuped', - date: DateTime(2020, 5, 20), - address: '154-19 64th Ave.\nFlushing, NY 11367', - handlingFee: 50, - cargoTypes: [ - Cargo(type: 'General Cargo', weight: 25), - Cargo(type: 'Medicine', weight: 20), - Cargo(type: 'Dangerous Cargo', weight: 30) - ]), - PickUp( - id: "S200441 - 13 Apr 2020", - userName: "Ko Kyaw Nyi", - phoneNumber: '+959111111111', - fromTime: '1PM', - toTime: '3PM', - numberOfPackage: 5, - weight: 25, - status: "Pickuped", - date: DateTime(2020, 5, 21), - address: '154-19 64th Ave.\nFlushing, NY 11367', - handlingFee: 50, - cargoTypes: [ - Cargo(type: 'General Cargo', weight: 25), - Cargo(type: 'Medicine', weight: 20), - Cargo(type: 'Dangerous Cargo', weight: 30) - ]), - PickUp( - id: "S200441 - 10 Apr 2020", - userName: "Ko Kyaw Nyi", - phoneNumber: '+959111111111', - fromTime: '1PM', - toTime: '3PM', - numberOfPackage: 5, - weight: 25, - status: "Canceled", - date: DateTime(2020, 5, 25), - address: '154-19 64th Ave.\nFlushing, NY 11367', - handlingFee: 50, - cargoTypes: [ - Cargo(type: 'General Cargo', weight: 25), - Cargo(type: 'Medicine', weight: 20), - Cargo(type: 'Dangerous Cargo', weight: 30) - ]), - PickUp( - id: "S200441 - 6 Apr 2020", - userName: "Ko Kyaw Nyi", - phoneNumber: '+959111111111', - fromTime: '1PM', - toTime: '3PM', - numberOfPackage: 5, - weight: 25, - status: "Canceled", - date: DateTime(2020, 5, 27), - address: '154-19 64th Ave.\nFlushing, NY 11367', - handlingFee: 50, - cargoTypes: [ - Cargo(type: 'General Cargo', weight: 25), - Cargo(type: 'Medicine', weight: 20), - Cargo(type: 'Dangerous Cargo', weight: 30) - ]), - ]; - return pickups; - } - - List pickups1 = [ - PickUp( - id: "S200412 - 12 Apr 2020", - userName: "Ko Kyaw Nyi", - phoneNumber: '+959111111111', - fromTime: '1PM', - toTime: '3PM', - numberOfPackage: 5, - weight: 25, - status: 'Pending', - date: DateTime(2020, 5, 1), - address: '154-19 64th Ave.\nFlushing, NY 11367', - handlingFee: 50, - isCourier: true, - radioIndex: 2, - cargoTypes: [ - Cargo(type: 'General Cargo', weight: 25), - Cargo(type: 'Medicine', weight: 20), - Cargo(type: 'Dangerous Cargo', weight: 30) - ]), - PickUp( - id: "S200125 - 12 May 2020", - userName: "Ko Kyaw Nyi", - phoneNumber: '+959111111111', - fromTime: '1PM', - toTime: '3PM', - numberOfPackage: 5, - weight: 25, - status: 'Confirmed', - date: DateTime(2020, 5, 6), - address: '154-19 64th Ave.\nFlushing, NY 11367', - handlingFee: 50, - cargoTypes: [ - Cargo(type: 'General Cargo', weight: 25), - Cargo(type: 'Medicine', weight: 20), - Cargo(type: 'Dangerous Cargo', weight: 30) - ]), - PickUp( - id: "S200441 - 13 Apr 2020", - userName: "Ko Kyaw Nyi", - phoneNumber: '+959111111111', - fromTime: '1PM', - toTime: '3PM', - numberOfPackage: 5, - weight: 25, - status: "Pickuped", - date: DateTime(2020, 5, 9), - address: '154-19 64th Ave.\nFlushing, NY 11367', - handlingFee: 50, - radioIndex: 3, - cargoTypes: [ - Cargo(type: 'General Cargo', weight: 25), - Cargo(type: 'Medicine', weight: 20), - Cargo(type: 'Dangerous Cargo', weight: 30) - ]), - PickUp( - id: "S200412 - 12 Apr 2020", - userName: "Ko Kyaw Nyi", - phoneNumber: '+959111111111', - fromTime: '1PM', - toTime: '3PM', - numberOfPackage: 5, - weight: 25, - status: 'Pickuped', - date: DateTime(2020, 5, 15), - address: '154-19 64th Ave.\nFlushing, NY 11367', - handlingFee: 50, - cargoTypes: [ - Cargo(type: 'General Cargo', weight: 25), - Cargo(type: 'Medicine', weight: 20), - Cargo(type: 'Dangerous Cargo', weight: 30) - ]), - PickUp( - id: "S200125 - 12 May 2020", - userName: "Ko Kyaw Nyi", - phoneNumber: '+959111111111', - fromTime: '1PM', - toTime: '3PM', - numberOfPackage: 5, - weight: 25, - status: 'Pickuped', - date: DateTime(2020, 5, 20), - address: '154-19 64th Ave.\nFlushing, NY 11367', - handlingFee: 50, - cargoTypes: [ - Cargo(type: 'General Cargo', weight: 25), - Cargo(type: 'Medicine', weight: 20), - Cargo(type: 'Dangerous Cargo', weight: 30) - ]), - PickUp( - id: "S200441 - 13 Apr 2020", - userName: "Ko Kyaw Nyi", - phoneNumber: '+959111111111', - fromTime: '1PM', - toTime: '3PM', - numberOfPackage: 5, - weight: 25, - status: "Pickuped", - date: DateTime(2020, 5, 21), - address: '154-19 64th Ave.\nFlushing, NY 11367', - handlingFee: 50, - cargoTypes: [ - Cargo(type: 'General Cargo', weight: 25), - Cargo(type: 'Medicine', weight: 20), - Cargo(type: 'Dangerous Cargo', weight: 30) - ]), - PickUp( - id: "S200441 - 10 Apr 2020", - userName: "Ko Kyaw Nyi", - phoneNumber: '+959111111111', - fromTime: '1PM', - toTime: '3PM', - numberOfPackage: 5, - weight: 25, - status: "Canceled", - date: DateTime(2020, 5, 25), - address: '154-19 64th Ave.\nFlushing, NY 11367', - handlingFee: 50, - cargoTypes: [ - Cargo(type: 'General Cargo', weight: 25), - Cargo(type: 'Medicine', weight: 20), - Cargo(type: 'Dangerous Cargo', weight: 30) - ]), - PickUp( - id: "S200441 - 6 Apr 2020", - userName: "Ko Kyaw Nyi", - phoneNumber: '+959111111111', - fromTime: '1PM', - toTime: '3PM', - numberOfPackage: 5, - weight: 25, - status: "Canceled", - date: DateTime(2020, 5, 27), - address: '154-19 64th Ave.\nFlushing, NY 11367', - handlingFee: 50, - cargoTypes: [ - Cargo(type: 'General Cargo', weight: 25), - Cargo(type: 'Medicine', weight: 20), - Cargo(type: 'Dangerous Cargo', weight: 30) - ]), - ]; - - List get canceled { - List _p = pickups.where((e) => e.status == "Canceled").toList() - ..sort((e1, e2) { - return e2.date.compareTo(e1.date); - }); - return _p; - } - - List get completed { - return pickups.where((e) => e.status == "Pickuped").toList() - ..sort((e1, e2) { - return e2.date.compareTo(e1.date); - }); - } - - List get upcoming { - return pickups - .where((e) => - e.status == "Pending" || - e.status == "Confirmed" || - e.status == "Processed" || - e.status == "Rescheduled") - .toList() - ..sort((e1, e2) { - return e2.date.compareTo(e1.date); - }); - } - - void initUser(user) { - super.initUser(user); - } - - @override - logout() async { - if (listener != null) await listener.cancel(); - // pickups = []; - } -} diff --git a/lib/model/po_model.dart b/lib/model/po_model.dart deleted file mode 100644 index 2364c1c..0000000 --- a/lib/model/po_model.dart +++ /dev/null @@ -1,293 +0,0 @@ -import 'dart:async'; -import 'dart:io'; - -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:logging/logging.dart'; -import 'package:path/path.dart' as Path; -import 'package:fcs/model/constants.dart'; -import 'package:fcs/pages/po/po_files.dart'; -import 'package:fcs/vo/do.dart'; -import 'package:fcs/vo/po.dart'; -import 'package:fcs/vo/popup_menu.dart'; - -import 'base_model.dart'; -import 'firebase_helper.dart'; - -class POSubmissionModel extends BaseModel { - final log = Logger('POSubmissionModel'); - - StreamSubscription listener; - - List pos = []; - List approvedPOs = []; - PopupMenu popupMenu = new PopupMenu(index: 0); - int dateIndex = 0; - DateTime selectedDate = DateTime.now(); - void initUser(user) async { - super.initUser(user); - _loadPOs(); - _loadApprovedPOs(); - } - - @override - logout() async { - if (listener != null) await listener.cancel(); - pos = []; - approvedPOs = []; - } - - Future _loadPOs() async { - String path; - if (user.hasPO() || user.isOwnerAndAbove()) { - path = "/$biz_collection/${setting.okEnergyId}/$pos_collection"; - } - - if (user.isBuyer()) { - path = - "/$biz_collection/${setting.okEnergyId}/$buyer_collection/${user.docID}/$pos_collection"; - } - var startDate = new DateTime( - selectedDate.year, selectedDate.month, selectedDate.day, 0, 0, 0); - var endDate = new DateTime( - selectedDate.year, selectedDate.month, selectedDate.day, 23, 59, 59); - listener = - getFilterDateSnapshot(path, 'po_date', startDate, endDate, 'po_number') - .listen((snaps) async { - pos.clear(); - snaps.documents.forEach((d) { - pos.add(POSubmission.fromMap(d.data, d.documentID)); - }); - notifyListeners(); - }); - } - - Future _loadApprovedPOs() async { - if (!user.isBuyer()) { - return; - } - approvedPOs.clear(); - - String path = - "/$biz_collection/${setting.okEnergyId}/$buyer_collection/${user.docID}/$pos_collection"; - var docs = await Firestore.instance - .collection(path) - .where("status", isEqualTo: po_approved_status) - .orderBy("po_approved_date", descending: false) - .limit(1) - .getDocuments(); - - Firestore.instance - .collection(path) - .where("status", isEqualTo: po_approved_status) - .orderBy("po_approved_date", descending: false) - .limit(10) - .snapshots(includeMetadataChanges: true) - .listen((snaps) async { - List _approved = []; - for (var d in snaps.documents) { - if (d.metadata.isFromCache) continue; - var po = POSubmission.fromMap(d.data, d.documentID); - po.poLines = await loadPOLines(po.id); - _approved.add(po); - } - approvedPOs.clear(); - approvedPOs.addAll(_approved); - notifyListeners(); - }); - } - - Future getPO(String id) async { - String path = "/$biz_collection/${setting.okEnergyId}/$pos_collection"; - if (user.isBuyer()) { - path = - "/$biz_collection/${setting.okEnergyId}/$buyer_collection/${user.docID}/$pos_collection"; - } - var poSnap = await getDocSnap(path, id); - return POSubmission.fromMap(poSnap.data, poSnap.documentID); - } - - Future> loadPOLines(String poID) async { - String path = - "/$biz_collection/${setting.okEnergyId}/$pos_collection/$poID/$po_product_collection"; - if (user.isBuyer()) { - path = - "/$biz_collection/${setting.okEnergyId}/$buyer_collection/${user.docID}/$pos_collection/$poID/$product_collection"; - } - var snaps = await Firestore.instance.collection(path).getDocuments(); - List poLines = - snaps.documents.map((s) => POLine.fromMap(s.data)).toList(); - return poLines; - } - - Future loadDOs(POSubmission po) async { - String path = "/$biz_collection/${setting.okEnergyId}/$dos_collection"; - if (user.isBuyer()) { - path = - "/$biz_collection/${setting.okEnergyId}/$buyer_collection/${user.docID}/$dos_collection"; - } - var snaps = await Firestore.instance - .collection(path) - .where("po_number", isEqualTo: po.poNumber) - .orderBy('do_number', descending: true) - .getDocuments(); - - po.dos = snaps.documents - .map((s) => DOSubmission.fromMap(s.data, s.documentID)) - .toList(); - return po; - } - - Future loadDOLines(DOSubmission doSub) async { - String path = - "/$biz_collection/${setting.okEnergyId}/$dos_collection/${doSub.id}/$product_collection"; - if (user.isBuyer()) { - path = - "/$biz_collection/${setting.okEnergyId}/$buyer_collection/${user.docID}/$dos_collection/${doSub.id}/$product_collection"; - } - var snaps = await getSnapshot(path); - doSub.doLines = snaps.documents.map((s) => DOLine.fromMap(s.data)).toList(); - return doSub; - } - - Future createPO(POSubmission po, List files) async { - if (files != null) { - if (files.length > 5) throw Exception("Exceed number of file upload"); - po.poReceiptUrls = []; - for (File f in files) { - String path = Path.join(po_files_path, user.docID); - String url = await uploadStorage(path, f); - po.poReceiptUrls.add(url); - } - } - - await request("/po", "POST", payload: po.toMap(), token: await getToken()); - } - - Future updatePO( - POSubmission po, List files, List deletedUrls) async { - if (deletedUrls != null) - for (String url in deletedUrls) { - po.poReceiptUrls.remove(url); - await deleteStorageFromUrl(url); - } - - if (files != null) { - if (files.length + po.poReceiptUrls.length > 5) - throw Exception("Exceed number of file upload"); - po.poReceiptUrls = po.poReceiptUrls == null ? [] : po.poReceiptUrls; - for (File f in files) { - String path = Path.join(po_files_path, user.docID); - String url = await uploadStorage(path, f); - po.poReceiptUrls.add(url); - } - } - await request("/po", "PUT", payload: po.toMap(), token: await getToken()); - } - - Future approvePO(POSubmission po) async { - await request("/po/approved", "POST", - payload: po.toMap(), token: await getToken()); - } - - Future rejectPO(POSubmission po) async { - await request("/po/rejected", "POST", - payload: po.toMap(), token: await getToken()); - } - - Future cancelPO(POSubmission po) async { - await request("/po/canceled", "POST", - payload: po.toMap(), token: await getToken()); - } - - void filterData( - String status, DateTime dateTime, int _selectedStatus, int _dateIndex) { - pos.clear(); - var startDate = - new DateTime(dateTime.year, dateTime.month, dateTime.day, 0, 0, 0); - var endDate = - new DateTime(dateTime.year, dateTime.month, dateTime.day, 23, 59, 59); - - if (this.listener != null) { - this.listener.cancel(); - } - - this.popupMenu.index = _selectedStatus; - this.dateIndex = _dateIndex; - this.selectedDate = dateTime == null - ? new DateTime( - selectedDate.year, selectedDate.month, selectedDate.day, 0, 0, 0) - : dateTime; - - String path = "/$biz_collection/${setting.okEnergyId}/$pos_collection"; - if (user.isBuyer()) { - path = - "/$biz_collection/${setting.okEnergyId}/$buyer_collection/${user.docID}/$pos_collection"; - } - - if (status != null && dateTime == null) { - this.listener = getFilterStatusSnapshot(path, status, 'po_number') - .listen((snaps) async { - pos.clear(); - snaps.documents.forEach((d) { - pos.add(POSubmission.fromMap(d.data, d.documentID)); - }); - notifyListeners(); - }); - } else if (dateTime != null && status == null) { - this.listener = getFilterDateSnapshot( - path, 'po_date', startDate, endDate, 'po_number') - .listen((snaps) async { - pos.clear(); - snaps.documents.forEach((d) { - pos.add(POSubmission.fromMap(d.data, d.documentID)); - }); - notifyListeners(); - }); - } else if (status != null && dateTime != null) { - this.listener = getFilterDataSnapshot( - path, status, 'po_date', startDate, endDate, 'po_number') - .listen((snaps) { - pos.clear(); - snaps.documents.forEach((d) { - pos.add(POSubmission.fromMap(d.data, d.documentID)); - }); - notifyListeners(); - }); - } else { - this.listener = - getQuerySnapshotByOrder(path, 'po_number').listen((snaps) async { - pos.clear(); - snaps.documents.forEach((d) { - pos.add(POSubmission.fromMap(d.data, d.documentID)); - }); - notifyListeners(); - }); - } - } - - Future> getPOForRevenue(DateTime dateTime) async { - List pos = []; - - String path = "/$biz_collection/${setting.okEnergyId}/$pos_collection"; - if (user.isBuyer()) { - path = - "/$biz_collection/${setting.okEnergyId}/$buyer_collection/${user.docID}/$pos_collection"; - } - DateTime date = DateTime(dateTime.year, dateTime.month, dateTime.day); - DateTime dateAddOne = date.add(Duration(days: 1)); - - QuerySnapshot snapshots = await Firestore.instance - .collection(path) - .where('status', whereIn: [po_approved_status, po_closed_status]) - .where("po_approved_date", isGreaterThanOrEqualTo: date) - .where("po_approved_date", isLessThan: dateAddOne) - .orderBy("po_approved_date") - .orderBy("user_name") - .limit(100) - .getDocuments(); - snapshots.documents.forEach((d) { - pos.add(POSubmission.fromMap(d.data, d.documentID)); - }); - return pos; - } -} diff --git a/lib/model/product_model.dart b/lib/model/product_model.dart deleted file mode 100644 index 14e21d4..0000000 --- a/lib/model/product_model.dart +++ /dev/null @@ -1,119 +0,0 @@ -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:logging/logging.dart'; -import 'package:fcs/vo/product.dart'; -import 'package:fcs/vo/setting.dart'; - -import 'base_model.dart'; -import 'constants.dart'; -import 'firebase_helper.dart'; - -class ProductModel extends BaseModel { -final log = Logger('ProductModel'); - - List products = []; - List tempProducts = []; - - List get getPrices { - List productPrices = []; - this.products.forEach((p) => productPrices.addAll(p.getPrices)); - productPrices.sort((p1, p2) => p1.compareTo(p2)); - return productPrices; - } - - String getProductName(String productID) { - return products.firstWhere((p) => p.id == productID).name; - } - - Product getProduct(String productID) { - return products.firstWhere((p) => p.id == productID); - } - - List get productsToEdit { - // clone products - tempProducts = products.map((p) => Product.clone(p)).toList(); - tempProducts.sort((p1, p2) => p1.displayOrder.compareTo(p2.displayOrder)); - // set old price with price - tempProducts.forEach((p) { - p.oldPirce = p.price; - p.action = "update"; - }); - - return tempProducts; - } - - void saveProduct(Product product, String name, price, displayOrder, int color, - bool isDisable) { - if (product == null) { - tempProducts.add(Product( - action: "create", - name: name, - price: int.parse(price), - color: color, - displayOrder: int.parse(displayOrder), - isDisable: isDisable)); - } else { - Product _product = product; - _product.name = name; - _product.price = int.parse(price); - _product.color = color; - _product.displayOrder = int.parse(displayOrder); - _product.isDisable = isDisable; - if (_product.id == null) { - _product.action = "create"; - } else { - _product.action = "update"; - } - } - notifyListeners(); - } - - void deleteProduct(Product product) { - if (product == null) { - return; - } - if (product.id == null) { - tempProducts.remove(product); - } else { - Product _product = tempProducts.firstWhere((p) => p.id == product.id); - _product.action = "delete"; - } - notifyListeners(); - } - - @override - void initSetting(Setting setting) { - super.initSetting(setting); - - try { - getQuerySnapshot( - "/$biz_collection/${setting.okEnergyId}/$product_collection") - .listen((QuerySnapshot snapshot) { - products.clear(); - products = snapshot.documents.map((documentSnapshot) { - var data = Product.fromMap( - documentSnapshot.data, documentSnapshot.documentID); - return data; - }).toList(); - products.sort((p1, p2) => p1.displayOrder.compareTo(p2.displayOrder)); - notifyListeners(); - }).onError((e) { - log.warning("Error! $e"); - }); - } catch (e) { - log.warning("Error!! $e"); - } - } - - @override - logout() async { - tempProducts = []; - } - - updateProducts(List products) async { - var items = []; - products.forEach((p) { - if (p.action != null) items.add(p.toMap()); - }); - await request("/products", "PUT", payload: items, token: await getToken()); - } -} diff --git a/lib/model/reg_model.dart b/lib/model/reg_model.dart deleted file mode 100644 index 9b08d4f..0000000 --- a/lib/model/reg_model.dart +++ /dev/null @@ -1,86 +0,0 @@ -import 'dart:async'; -import 'dart:io'; - -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:path/path.dart' as Path; -import 'package:fcs/vo/buyer.dart'; - -import 'base_model.dart'; -import 'constants.dart'; -import 'firebase_helper.dart'; - -class Attachments { - File nricFront, nricBack; -} - -class RegModel extends BaseModel { - Buyer reg = Buyer(); - bool isLoaded = false; - - StreamSubscription regListener; - - void initUser(user) { - super.initUser(user); - if (user.isRegisteredBuyer()) { - _loadReg(); - } else { - reg = Buyer(); - } - } - - @override - logout() async { - if (regListener != null) await regListener.cancel(); - reg = Buyer(); - } - - Future _loadReg() async { - if (regListener != null) { - regListener.cancel(); - } - regListener = getDocSnapshot( - "/$biz_collection/${setting.okEnergyId}/$buyer_collection", - "${user.docID}") - .listen((snap) async { - if (snap.exists) { - reg = Buyer.fromMap(snap.data, snap.documentID); - QuerySnapshot q = await getSnapshot( - "/$biz_collection/${setting.okEnergyId}/$buyer_collection/${user.docID}/$product_collection"); - reg.buyerProducts.clear(); - q.documents.forEach((d) { - reg.buyerProducts.add(BuyerProduct.fromMap(d.data, d.documentID)); - }); - } else { - reg = Buyer(); - } - isLoaded = true; - notifyListeners(); - }); - } - - Future register(Buyer buyer, Attachments attachments) async { - String path = Path.join(reg_files_path, user.docID); - String urlFront = await uploadStorage(path, attachments.nricFront); - buyer.nricFrontUrl = urlFront; - String urlBack = await uploadStorage(path, attachments.nricBack); - buyer.nricBackUrl = urlBack; - - await request("/reg", "POST", - payload: buyer.toMap(), token: await getToken()); - } - - Future update(Buyer buyer, Attachments attachments) async { - String path = Path.join(reg_files_path, user.docID); - if (attachments.nricFront != null) { - String urlFront = await uploadStorage(path, attachments.nricFront); - buyer.nricFrontUrl = urlFront; - } - if (attachments.nricBack != null) { - String urlBack = await uploadStorage(path, attachments.nricBack); - buyer.nricBackUrl = urlBack; - } - - await request("/buyer/update", "PUT", - payload: buyer.toMap(), token: await getToken()); - } -} diff --git a/lib/model/report_model.dart b/lib/model/report_model.dart deleted file mode 100644 index f683f0c..0000000 --- a/lib/model/report_model.dart +++ /dev/null @@ -1,700 +0,0 @@ -import 'dart:async'; -import 'dart:convert'; - -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:fcs/vo/report.dart'; -import 'package:fcs/vo/report_user.dart'; -import 'package:open_file/open_file.dart'; -import 'package:path_provider/path_provider.dart'; -import 'package:fcs/fcs/common/helpers/api_helper.dart' as api; -import 'package:fcs/vo/report.dart'; - -import '../config.dart'; -import 'base_model.dart'; -import 'constants.dart'; -import 'firebase_helper.dart'; -import 'shared_pref.dart'; - -class ReportModel extends BaseModel { - StreamSubscription listener; - StreamSubscription listenerUser; - - List reports = []; - List userReports = []; - List filterValue = []; - - List get reportList { - List _reports = []; - if (user.isOwnerAndAbove() || user.hasAdmin()) { - _reports = reports; - } else { - _reports.addAll(reports); - userReports.forEach((r) { - if (!_reports.contains(r)) { - _reports.add(r); - } - }); - } - _reports.sort((a, b) => a.display.compareTo(b.display)); - return _reports; - } - - void initUser(user) { - super.initUser(user); - reports = []; - _loadReports(); - } - - Future _loadReports() async { - if (listener != null) listener.cancel(); - if (listenerUser != null) listenerUser.cancel(); - - if (user.isOwnerAndAbove() || user.hasAdmin()) { - listener = Firestore.instance - .collection("/$reports_collection") - .snapshots() - .listen((snaps) async { - reports.clear(); - reports = snaps.documents.map((documentSnapshot) { - var report = Report.fromMap( - documentSnapshot.data, documentSnapshot.documentID); - return report; - }).toList(); - notifyListeners(); - }); - } else { - listener = Firestore.instance - .collection("/$reports_collection") - .where("for_all_users", isEqualTo: true) - .snapshots() - .listen((snaps) async { - reports.clear(); - reports = snaps.documents.map((documentSnapshot) { - var report = Report.fromMap( - documentSnapshot.data, documentSnapshot.documentID); - return report; - }).toList(); - notifyListeners(); - }); - - listenerUser = Firestore.instance - .collection("/$report_user_collection") - .where("user_id", isEqualTo: user.docID) - .snapshots() - .listen((snaps) async { - userReports.clear(); - userReports = snaps.documents.map((documentSnapshot) { - var user = ReportUser.fromMap( - documentSnapshot.data, documentSnapshot.documentID); - var report = Report(id: user.reportID, display: user.reportName); - return report; - }).toList(); - notifyListeners(); - }); - } - notifyListeners(); - } - - @override - void logout() { - reports = []; - if (listener != null) listener.cancel(); - if (listenerUser != null) listenerUser.cancel(); - } - - Future getReport(String repID) async { - String path = "/$reports_collection"; - - var snap = await Firestore.instance.collection(path).document(repID).get(); - Report report = Report.fromMap(snap.data, snap.documentID); - return report; - } - - Future getReportData(Report report, int limit, int offset) async { - List reportDataList = []; - var aggFun = []; - var fields = []; - var groupbys = []; - // print('report => $report'); - try { - report.fields.asMap().forEach((key, value) { - if (value.aggFun == '') { - aggFun.add(''); - } else { - aggFun.add(value.aggFun); - } - }); - report.fields.asMap().forEach((key, value) { - fields.add(value.name); - }); - - String strFields; - fields.forEach((element) { - if (strFields == null) { - strFields = element; - } else { - strFields = strFields + ',' + element; - } - }); - - String strAgg; - aggFun.forEach((element) { - if (strAgg == null) { - strAgg = element; - } else { - strAgg = strAgg + ',' + element; - } - }); - - String strGroup; - groupbys.forEach((element) { - if (strGroup == null) { - strGroup = element; - } else { - strGroup = strGroup + ',' + element; - } - }); - - var data = { - "fields": strFields == null ? '' : strFields, - "aggfuns": strAgg == null ? '' : strAgg, - // "groupbys": strGroup == null ? '' : strGroup, - "limit": limit, - "offset": offset - }; - print("payload:$data"); - - var rdata = { - "fields": 'quantity,product_id,product_name', - "aggfuns": ",,", - "groupbys": 'product_id', - "limit": limit, - "offset": offset - }; - var result = await request("/api/data/${report.object}", "POST", - token: await getToken(), - url: Config.instance.reportURL, - payload: jsonEncode(data)); - - if (result == null) return []; - result.forEach((rdata) { - reportDataList.add(rdata); - }); - // print('reportDataList => $reportDataList'); - notifyListeners(); - return reportDataList; - } catch (e) { - log.warning("Error get Summary>>>>${e.toString()}"); - } - } - - Future downloadReportData(Report report) async { - var aggFun = []; - var fields = []; - report.fields.asMap().forEach((key, value) { - if (value.aggFun == '') { - aggFun.add(''); - } else { - aggFun.add(value.aggFun); - } - }); - report.fields.asMap().forEach((key, value) { - fields.add(value.name); - }); - - String strFields; - fields.forEach((element) { - if (strFields == null) { - strFields = element; - } else { - strFields = strFields + ',' + element; - } - }); - - String strAgg; - aggFun.forEach((element) { - if (strAgg == null) { - strAgg = element; - } else { - strAgg = strAgg + ',' + element; - } - }); - - // final directory = await getApplicationDocumentsDirectory(); - final directory = await getExternalStorageDirectory(); - String path = ('${directory.path}/${report.id}.pdf'); - log.info("download file path:$path"); - - var data = { - "fields": strFields == null ? '' : strFields, - "aggfuns": strAgg == null ? '' : strAgg, - "greoupbys": '', - "limit": 0, - "offset": 0 - }; - - await api.requestDownloadPDFAPI("/api/report-pdf/${report.object}", "GET", - filePath: path, - url: Config.instance.reportURL, - token: await getToken(), - payload: jsonEncode(data)); - - final message = await OpenFile.open(path); - log.info("Open file result:$message"); - } - - Future getJson(Report report) async { - var aggFun = []; - var fields = []; - report.fields.asMap().forEach((key, value) { - if (value.aggFun == '') { - aggFun.add(''); - } else { - aggFun.add(value.aggFun); - } - }); - report.fields.asMap().forEach((key, value) { - fields.add(value.name); - }); - - String strFields; - fields.forEach((element) { - if (strFields == null) { - strFields = element; - } else { - strFields = strFields + ',' + element; - } - }); - - String strAgg; - aggFun.forEach((element) { - if (strAgg == null) { - strAgg = element; - } else { - strAgg = strAgg + ',' + element; - } - }); - - var data = { - "fields": strFields == null ? '' : strFields, - "aggfuns": strAgg == null ? '' : strAgg, - "greoupbys": '', - "limit": 0, - "offset": 0 - }; - return jsonEncode(data); - } - - Future getEscapeJson(Report report) async { - var bytes = utf8.encode(await getJson(report)); - var base64Str = base64.encode(bytes); - return HtmlEscape().convert(base64Str); - } - - Future getReportDataWithFilters(Report report, List filters) async { - List reportDataList = []; - var aggFun = []; - var fields = []; - var groupbys = []; - - try { - var data = report.convertArrayToString(report, filters); - print('data=> $data'); - - var result = await request("/api/data/${report.object}", "POST", - token: await getToken(), - url: Config.instance.reportURL, - payload: jsonEncode(data)); - - if (result == null) return []; - result.forEach((rdata) { - reportDataList.add(rdata); - }); - - notifyListeners(); - return reportDataList; - } catch (e) { - log.warning("Error get Summary>>>>${e.toString()}"); - } - } - - Future addreport() async { - var data = [ - { - "display": "Buyer Rpt", - "object": "buyer_rpt", - "display_filters": [ - { - "name": "user_name", - "display_name": "User Name", - "compare": "==", - "data_type": "string", - }, - ], - "fields": [ - { - "name": "user_name", - "display_name": "User Name", - "to_fixed": 0, - "type": "string", - "agg_fun": "", - }, - { - "name": "reg_date", - "display_name": "Registered Date", - "to_fixed": 0, - "type": "intdate", - "agg_fun": "", - }, - { - "name": "biz_name", - "display_name": "Business Name", - "to_fixed": 0, - "type": "string", - "agg_fun": "", - }, - { - "name": "biz_address", - "display_name": "Business Address", - "to_fixed": 0, - "type": "float", - "agg_fun": "", - }, - ], - "display_fields": ['biz_name', 'biz_name', 'reg_date', 'user_name'], - "sorts": [], - "groupbys": [] - }, - { - "display": "Delivery Rpt", - "object": "delivery_rpt", - "display_filters": [ - { - "name": "user_name", - "display_name": "User Name", - "compare": "==", - "data_type": "string", - }, - ], - "fields": [ - { - "name": "user_name", - "display_name": "User Name", - "to_fixed": 0, - "type": "string", - "agg_fun": "", - }, - { - "name": "delivery_ended_date", - "display_name": "Delivery Ended Date", - "to_fixed": 0, - "type": "intdate", - "agg_fun": "", - }, - { - "name": "qty_92", - "display_name": "Qty 92", - "to_fixed": 0, - "type": "float", - "agg_fun": "", - }, - { - "name": "qty_95", - "display_name": "Qty 95", - "to_fixed": 0, - "type": "float", - "agg_fun": "", - }, - { - "name": "qty_d", - "display_name": "Qty D", - "to_fixed": 0, - "type": "float", - "agg_fun": "", - }, - { - "name": "qty_p", - "display_name": "Qty P", - "to_fixed": 0, - "type": "float", - "agg_fun": "", - }, - ], - "display_fields": [ - 'qty_p', - 'qty_d', - 'qty_95', - 'qty_92', - 'delivery_ended_date', - 'user_name', - ], - "sorts": [], - "groupbys": [] - }, - { - "display": "DOs Rpt", - "object": "dos_rpt", - "display_filters": [ - { - "name": "user_name", - "display_name": "User Name", - "compare": "==", - "data_type": "string", - }, - ], - "fields": [ - { - "name": "user_name", - "display_name": "User Name", - "to_fixed": 0, - "type": "string", - "agg_fun": "", - }, - { - "name": "doc_date", - "display_name": "DO Date", - "to_fixed": 0, - "type": "intdate", - "agg_fun": "", - }, - { - "name": "doc_number", - "display_name": "PO/DO Number", - "to_fixed": 0, - "type": "string", - "agg_fun": "", - }, - { - "name": "qty_92", - "display_name": "Qty 92", - "to_fixed": 0, - "type": "float", - "agg_fun": "", - }, - { - "name": "qty_95", - "display_name": "Qty 95", - "to_fixed": 0, - "type": "float", - "agg_fun": "", - }, - { - "name": "qty_d", - "display_name": "Qty D", - "to_fixed": 0, - "type": "float", - "agg_fun": "", - }, - { - "name": "qty_p", - "display_name": "Qty P", - "to_fixed": 0, - "type": "float", - "agg_fun": "", - }, - ], - "display_fields": [ - 'qty_p', - 'qty_d', - 'qty_95', - 'qty_92', - 'doc_date', - 'user_name', - 'doc_number' - ], - "sorts": [], - "groupbys": [] - }, - { - "display": "POs Rpt", - "object": "pos_rpt", - "display_filters": [ - { - "name": "user_name", - "display_name": "User Name", - "compare": "==", - "data_type": "string", - }, - { - "name": "po_number", - "display_name": "PO Number", - "compare": "==", - "data_type": "string", - } - ], - "fields": [ - { - "name": "user_name", - "display_name": "User Name", - "to_fixed": 0, - "type": "string", - "agg_fun": "", - }, - { - "name": "po_date", - "display_name": "PO Date", - "to_fixed": 0, - "type": "intdate", - "agg_fun": "", - }, - { - "name": "po_number", - "display_name": "PO Number", - "to_fixed": 0, - "type": "string", - "agg_fun": "", - }, - { - "name": "qty_92", - "display_name": "Qty 92", - "to_fixed": 0, - "type": "float", - "agg_fun": "", - }, - { - "name": "qty_95", - "display_name": "Qty 95", - "to_fixed": 0, - "type": "float", - "agg_fun": "", - }, - { - "name": "qty_d", - "display_name": "Qty D", - "to_fixed": 0, - "type": "float", - "agg_fun": "", - }, - { - "name": "qty_p", - "display_name": "Qty P", - "to_fixed": 0, - "type": "float", - "agg_fun": "", - }, - { - "name": "price_92", - "display_name": "Price 92", - "to_fixed": 0, - "type": "integer", - "agg_fun": "", - }, - { - "name": "price_95", - "display_name": "Price 95", - "to_fixed": 0, - "type": "integer", - "agg_fun": "", - }, - { - "name": "price_d", - "display_name": "Price D", - "to_fixed": 0, - "type": "integer", - "agg_fun": "", - }, - { - "name": "price_p", - "display_name": "Price P", - "to_fixed": 0, - "type": "integer", - "agg_fun": "", - } - ], - "display_fields": [ - 'qty_p', - 'qty_d', - 'qty_95', - 'qty_92', - 'price_p', - 'price_d', - 'price_95', - 'price_92', - 'po_date', - 'user_name', - 'po_number' - ], - "sorts": [], - "groupbys": [] - }, - { - "display": "Storage Charge Rpt", - "object": "storage_charge_rpt", - "display_filters": [ - { - "name": "user_name", - "display_name": "User Name", - "compare": "==", - "data_type": "string", - }, - ], - "fields": [ - { - "name": "user_name", - "display_name": "User Name", - "to_fixed": 0, - "type": "string", - "agg_fun": "", - }, - { - "name": "total_qty", - "display_name": "Quantity", - "to_fixed": 3, - "type": "float", - "agg_fun": "", - }, - { - "name": "rate", - "display_name": "Rate", - "to_fixed": 0, - "type": "string", - "agg_fun": "", - }, - { - "name": "storage_charge", - "display_name": "Amount", - "to_fixed": 3, - "type": "integer", - "agg_fun": "", - }, - ], - "display_fields": [ - 'qty_p', - 'qty_d', - 'qty_95', - 'qty_92', - 'price_p', - 'price_d', - 'price_95', - 'price_92', - 'po_date', - 'user_name', - 'po_number' - ], - "sorts": [], - "groupbys": [] - } - ]; - - data.asMap().forEach((key, value) { - Firestore.instance - .collection("/$reports_collection") - .document() - .setData(value); - }); - } - - Future saveSelectedFieldsAndPosition( - String id, List positonFields, List selectedFields) async { - // positonFields.toJson - ReportFieldPositionSelection report = ReportFieldPositionSelection( - fieldPosition: positonFields, fieldSelection: selectedFields); - await SharedPref.saveReport(report); - } - - Future loadSelectedFieldsAndPosition( - String id) async { - var data = await SharedPref.getReport(id); - return data; - } -} diff --git a/lib/model/report_user_model.dart b/lib/model/report_user_model.dart deleted file mode 100644 index e97d150..0000000 --- a/lib/model/report_user_model.dart +++ /dev/null @@ -1,83 +0,0 @@ -import 'dart:convert'; - -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:fcs/model/constants.dart'; -import 'package:fcs/vo/report.dart'; -import 'package:fcs/vo/report_user.dart'; -import 'package:fcs/vo/user.dart'; - -import '../config.dart'; -import 'base_model.dart'; -import 'firebase_helper.dart'; - -class ReportUserModel extends BaseModel { - List reportUsers = []; - void initUser(user) { - super.initUser(user); - } - - @override - logout() async {} - - Future> getUsersForReport(String reportID) async { - List users = []; - String path = "/$report_user_collection"; - - QuerySnapshot snapshots = await Firestore.instance - .collection(path) - .where('report_id', isEqualTo: reportID) - .getDocuments(); - snapshots.documents.forEach((d) { - users.add(ReportUser.fromMap(d.data, d.documentID)); - }); - return users; - } - - Future> findUser(String searchUser) async { - if (searchUser == null || searchUser == '') return List(); - - var bytes = utf8.encode(searchUser); - var base64Str = base64.encode(bytes); - HtmlEscape htmlEscape = const HtmlEscape(); - String escapeUser = htmlEscape.convert(base64Str); - - int limit = 20; - List _users = []; - - try { - var data = await request( - "/api/fts/$user_collection/$escapeUser/$limit", "GET", - token: await getToken(), url: Config.instance.reportURL); - if (data == null) return List(); - - data.forEach((user) { - var _user = User.fromUserJson(user); - _users.add(_user); - }); - } catch (e) { - // permission error - log.warning("user error:" + e.toString()); - return null; - } - return _users; - } - - Future updateReportForAllUsers(Report report) async { - await request("/report", "PUT", - payload: {'id': report.id, 'for_all_users': report.forAllUser}, - token: await getToken()); - notifyListeners(); - } - - Future assignUser(ReportUser reportUser) async { - await request("/report_user", "POST", - payload: reportUser.toMap(), token: await getToken()); - notifyListeners(); - } - - Future deleteReportUser(ReportUser reportUser) async { - await request("/report_user", "DELETE", - payload: reportUser.toMap(), token: await getToken()); - notifyListeners(); - } -} diff --git a/lib/model/shared_pref.dart b/lib/model/shared_pref.dart deleted file mode 100644 index bc160a1..0000000 --- a/lib/model/shared_pref.dart +++ /dev/null @@ -1,84 +0,0 @@ -import 'package:shared_preferences/shared_preferences.dart'; -import 'package:fcs/vo/report.dart'; -import 'dart:convert'; - -import 'package:fcs/vo/user.dart'; - -class SharedPref { - static final SharedPref instance = SharedPref._(); - SharedPref._(); - - static Future getLang() async { - SharedPreferences prefs = await SharedPreferences.getInstance(); - return prefs.getString('language'); - } - - static Future saveLang(String lang) async { - SharedPreferences prefs = await SharedPreferences.getInstance(); - prefs.setString('language', lang); - } - - static Future saveUser(User user) async { - await _save("user", user.toJson()); - } - - static Future saveReport(ReportFieldPositionSelection report) async { - await _save('report-${report.id}', report.toJson()); - } - - static Future getReport(String id) async { - try { - return ReportFieldPositionSelection.fromJson(await _read("report-$id")); - } catch (e) { - return null; - } - } - - static Future getUser() async { - try { - return User.fromJson(await _read("user")); - } catch (e) { - return null; - } - } - - static Future removeUser() async { - return await _remove("user"); - } - - static Future saveSkippedRecoverEmail(bool skipped) async { - await _save("skipped_recovery_email", skipped); - } - - static Future getSkippedRecoverEmail() async { - try { - bool _skipped = await _read("skipped_recovery_email"); - return _skipped; - } catch (e) { - return null; - } - } - - static _read(String key) async { - try { - final prefs = await SharedPreferences.getInstance(); - return json.decode(prefs.getString(key)); - } catch (e) { - print("Error:$e"); - } - } - - static _save(String key, value) async { - try { - final prefs = await SharedPreferences.getInstance(); - prefs.setString(key, json.encode(value)); - } catch (e) { - print("Error:$e"); - } - } - - static _remove(String key) async { - final prefs = await SharedPreferences.getInstance(); - prefs.remove(key); - } -} diff --git a/lib/model/shipment_model.dart b/lib/model/shipment_model.dart deleted file mode 100644 index bf8d954..0000000 --- a/lib/model/shipment_model.dart +++ /dev/null @@ -1,103 +0,0 @@ -import 'package:fcs/vo/shipment.dart'; -import 'package:fcs/vo/shipping_address.dart'; - -import 'base_model.dart'; - -class ShipmentModel extends BaseModel { - List shipmentType = ['Air', 'Ship', 'Cargo Truck']; - List shipments = [ - Shipment( - shipDate: DateTime(2020, 4, 23), - shipmentNumber: 'A103B', - status: 'In Progress', - arrivalDate: DateTime(2020, 4, 30), - departureDate: DateTime(2020, 4, 23)), - Shipment( - shipDate: DateTime(2020, 4, 2), - shipmentNumber: 'A100A', - status: 'Ready to ship', - arrivalDate: DateTime(2020, 4, 28), - departureDate: DateTime(2020, 4, 15)), - Shipment( - shipDate: DateTime(2020, 4, 2), - shipmentNumber: 'A100B', - status: 'Arrived', - arrivalDate: DateTime(2020, 4, 28), - departureDate: DateTime(2020, 4, 15)), - Shipment( - shipDate: DateTime(2020, 4, 10), - shipmentNumber: 'A102B', - status: 'Canceled', - arrivalDate: DateTime(2020, 4, 20), - departureDate: DateTime(2020, 4, 10)), - Shipment( - shipDate: DateTime(2020, 4, 2), - shipmentNumber: 'A100B', - status: 'Canceled', - arrivalDate: DateTime(2020, 4, 20), - departureDate: DateTime(2020, 4, 23)), - Shipment( - shipDate: DateTime(2020, 4, 10), - shipmentNumber: 'A102B', - status: 'Arrived', - arrivalDate: DateTime(2020, 4, 30), - departureDate: DateTime(2020, 4, 20), - ) - ]; - - List get canceled { - List _p = shipments.where((e) => e.status == "Canceled").toList() - ..sort((e1, e2) { - return e1.shipDate.compareTo(e2.shipDate); - }); - return _p; - } - - List get completed { - return shipments.where((e) => e.status == "Arrived").toList() - ..sort((e1, e2) { - return e1.shipDate.compareTo(e2.shipDate); - }); - } - - List get upcoming { - List _shipments = shipments - .where((e) => - e.status == "In Progress" || - e.status == "Ready to ship" || - e.status == "Processed" || - e.status == "Rescheduled") - .toList(); - - _shipments.sort((e1, e2) { - return e1.shipDate.compareTo(e2.shipDate); - }); - return _shipments; - } - - List shippingAddresses = [ - ShippingAddress( - fullName: 'U Nyi Nyi', - addressLine1: '154-19 64th Ave.', - addressLine2: 'Flushing', - city: 'NY', - state: 'NY', - phoneNumber: '+1 (292)215-2247'), - ShippingAddress( - fullName: 'Mg Myo', - addressLine1: '153-154 5th Thitsar.', - addressLine2: 'South Okkalapa Township', - city: 'Yangon', - state: 'Myanmar', - phoneNumber: '+09 95724 8750'), - ]; - - void initUser(user) { - super.initUser(user); - } - - @override - logout() async { - shipments = []; - } -} diff --git a/lib/model/shipment_rate_model.dart b/lib/model/shipment_rate_model.dart deleted file mode 100644 index 43e0c25..0000000 --- a/lib/model/shipment_rate_model.dart +++ /dev/null @@ -1,48 +0,0 @@ -import 'dart:async'; - -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:fcs/vo/custom.dart'; -import 'package:fcs/vo/discount.dart'; -import 'package:fcs/vo/rate.dart'; -import 'package:logging/logging.dart'; - -import 'base_model.dart'; - -class ShipmentRateModel extends BaseModel { - final log = Logger('ShipmentRateModel'); - - StreamSubscription listener; - - List rates = [ - Rate( - id: '1', name: 'general_cargo', description: 'General Cargo', price: 6), - Rate(id: '2', name: 'medicine', description: 'Medicine', price: 7), - Rate( - id: '3', - name: 'dangerous_cargo', - description: 'Dangerous Cargo', - price: 8), - ]; - - List customs = [ - Custom(productType: 'Phone', fee: 40), - Custom(productType: 'Max Book', fee: 40) - ]; - - List discountsByWeight = [ - Discount(weight: 50, discountRate: 0.25), - Discount(weight: 100, discountRate: 0.50) - ]; - - int freeDeliveryWeight = 10; - - void initUser(user) { - super.initUser(user); - } - - @override - logout() async { - if (listener != null) await listener.cancel(); - rates = []; - } -} diff --git a/lib/model/storage_model.dart b/lib/model/storage_model.dart deleted file mode 100644 index 4356b8f..0000000 --- a/lib/model/storage_model.dart +++ /dev/null @@ -1,155 +0,0 @@ -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:logging/logging.dart'; -import 'package:fcs/vo/inventory_line.dart'; -import 'package:fcs/vo/inventory_taking.dart'; -import 'package:fcs/vo/product.dart'; -import 'package:fcs/vo/storage.dart'; - -import 'base_model.dart'; -import 'constants.dart'; -import 'firebase_helper.dart'; - -class StorageModel extends BaseModel { - final log = Logger('StorageModel'); - - List storages = []; - List inventoryTakings = []; - int selectedIndex = 0; - DateTime selectedDate = DateTime.now(); - - List getStorage(String productID) { - return storages - .where((s) => s.products.any((p) => p.id == productID)) - .toList(); - } - - void initUser(user) async { - super.initUser(user); - if (!user.isOwnerAndAbove() && !user.hasInventory()) { - return; - } - _loadStorages(); - _loadInventoryTakings(); - } - - @override - logout() async { - storages = []; - inventoryTakings = []; - } - - String getStorageName(String storageID) { - return storages.firstWhere((s) => s.id == storageID).name; - } - - void _loadStorages() async { - try { - getQuerySnapshotF( - "/$biz_collection/${setting.okEnergyId}/$storage_collection", - user.accountID) - .listen((QuerySnapshot snapshot) { - storages.clear(); - storages = snapshot.documents.map((documentSnapshot) { - var storage = Storage.fromMap( - documentSnapshot.data, documentSnapshot.documentID); - loadProducts(storage); - return storage; - }).toList(); - notifyListeners(); - }).onError((e) { - log.warning("Error! $e"); - }); - } catch (e) { - log.warning("Error!! $e"); - } - } - - void _loadInventoryTakings() async { - try { - String path = "/$biz_collection/${setting.okEnergyId}/$inventory_takings"; - var startDate = new DateTime( - selectedDate.year, selectedDate.month, selectedDate.day, 0, 0, 0); - var endDate = new DateTime( - selectedDate.year, selectedDate.month, selectedDate.day, 23, 59, 59); - - inventoryTakings.clear(); - getFilterDateSnapshotF(path, user.accountID, 'date_time', startDate, - endDate, 'date_time') - .listen((QuerySnapshot snapshot) { - inventoryTakings = snapshot.documents.map((documentSnapshot) { - var data = InventoryTaking.fromMap( - documentSnapshot.data, documentSnapshot.documentID); - - return data; - }).toList(); - notifyListeners(); - }).onError((e) { - log.warning("Error! $e"); - }); - } catch (e) { - log.warning("Error!! $e"); - } - } - - loadInventoryLines(InventoryTaking inventoryTaking) async { - if (inventoryTaking.linesLoaded) return; - var snaps = await getSnapshot( - "/$biz_collection/${setting.okEnergyId}/$inventory_takings/${inventoryTaking.id}/$inventory_lines"); - inventoryTaking.inventoryLines = - snaps.documents.map((s) => InventoryLine.fromMap(s.data)).toList(); - inventoryTaking.linesLoaded = true; - notifyListeners(); - } - - loadProducts(Storage storage) async { - if (storage.productsLoaded) return; - var snaps = await getSnapshot( - "/$biz_collection/${setting.okEnergyId}/$storage_collection/${storage.id}/$product_collection"); - storage.products = snaps.documents - .map((s) => Product.fromMap(s.data, s.documentID)) - .toList(); - storage.productsLoaded = true; - notifyListeners(); - } - - Future createStorage(Storage storage) async { - await request("/storage", "POST", - payload: storage.toMap(), token: await getToken()); - } - - Future updateStorage(Storage storage) async { - await request("/storage", "PUT", - payload: storage.toMap(), token: await getToken()); - } - - Future deleteStorage(String storageID) async { - await request("/storage/" + storageID, "DELETE", token: await getToken()); - } - - Future createInventoryTaking(InventoryTaking inventoryTaking) async { - await request("/inventory", "POST", - payload: inventoryTaking.toMap(), token: await getToken()); - } - - void filterDate(DateTime dateTime, int _selectedIndex) async { - this.selectedIndex = _selectedIndex; - this.selectedDate = dateTime; - - String path = "/$biz_collection/${setting.okEnergyId}/$inventory_takings"; - var endDate = - new DateTime(dateTime.year, dateTime.month, dateTime.day, 23, 59, 59); - inventoryTakings.clear(); - getFilterDateSnapshotF( - path, user.accountID, 'date_time', dateTime, endDate, 'date_time') - .listen((snapshot) { - inventoryTakings = snapshot.documents.map((documentSnapshot) { - var data = InventoryTaking.fromMap( - documentSnapshot.data, documentSnapshot.documentID); - - return data; - }).toList(); - notifyListeners(); - }); - notifyListeners(); - } -} diff --git a/lib/model/test_model.dart b/lib/model/test_model.dart deleted file mode 100644 index 123d0b6..0000000 --- a/lib/model/test_model.dart +++ /dev/null @@ -1,177 +0,0 @@ -import 'dart:async'; - -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:faker/faker.dart'; -import 'package:logging/logging.dart'; - -import 'base_model.dart'; - -class TestModel extends BaseModel { - final log = Logger('TestModel'); - - List tests = []; - DocumentSnapshot prev; - static const int row_count = 10; - bool ended = false; - - StreamSubscription listener; - final Query queryBase = Firestore.instance.collection("/tests"); - final Query query = Firestore.instance - .collection("/tests") - // .orderBy("deleted") - .orderBy("age", descending: false); - - void initData() async { - _clearState(); - _initListener(); - load(); - } - - void _clearState() { - prev = null; - tests = []; - ended = false; - if (listener != null) listener.cancel(); - listener = null; - } - - void _initListener() { - Query _query = queryBase.orderBy("update_time", descending: true).limit(1); - _query.getDocuments(source: Source.server).then((QuerySnapshot snapshot) { - int count = snapshot.documents.length; - if (count == 1) { - var test = Test.fromMap( - snapshot.documents[0].data, snapshot.documents[0].documentID); - - Query _queryListener = queryBase - .where("update_time", isGreaterThan: test.updateTime) - .orderBy("update_time", descending: true); - - listener = - _queryListener.snapshots(includeMetadataChanges: true).listen((qs) { - qs.documentChanges.forEach((c) { - switch (c.type) { - case DocumentChangeType.added: - var test = Test.fromMap(c.document.data, c.document.documentID); - if (tests.contains(test)) { - tests[tests.indexOf(test)].name = test.name; - notifyListeners(); - } - if (!tests.contains(test)) { - tests.add(test); - notifyListeners(); - } - break; - case DocumentChangeType.modified: - var test = Test.fromMap(c.document.data, c.document.documentID); - if (tests.contains(test)) { - bool deleted = c.document.data["deleted"]; - if (deleted != null && deleted) { - tests.remove(test); - } else { - tests[tests.indexOf(test)].name = test.name; - } - notifyListeners(); - } - break; - default: - } - }); - }); - notifyListeners(); - } - }); - } - - Future load() async { - Query _query = prev != null ? query.startAfterDocument(prev) : query; - try { - _query - // .where("deleted", isNull: null) - .limit(row_count) - .getDocuments(source: Source.server) - .then((QuerySnapshot snapshot) { - int count = snapshot.documents.length; - ended = count < row_count; - prev = count > 0 ? snapshot.documents[count - 1] : prev; - snapshot.documents.forEach((e) { - var test = Test.fromMap(e.data, e.documentID); - if (!tests.contains(test)) tests.add(test); - }); - notifyListeners(); - }); - } catch (e) { - log.warning("Error!! $e"); - } - } - - void populate() { - for (var i = 0; i < 30; i++) { - Firestore.instance - .collection('tests') - .document(faker.person.name()) - .setData({ - 'name': faker.person.name(), - 'age': random.decimal(), - 'update_time': DateTime.now().microsecondsSinceEpoch - }); - } - } - - void add() { - Firestore.instance - .collection('tests') - .document(faker.person.name()) - .setData({ - 'name': faker.person.name(), - 'age': random.decimal(), - 'update_time': DateTime.now().microsecondsSinceEpoch - }); - } - - void update() { - Firestore.instance.collection('tests').document(tests[0].id).setData({ - 'name': faker.person.name(), - 'update_time': DateTime.now().microsecondsSinceEpoch - }, merge: true); - } - - void remove() { - Firestore.instance.collection('tests').document(tests[0].id).setData( - {'deleted': 1, 'update_time': DateTime.now().microsecondsSinceEpoch}, - merge: true); - } - - @override - void logout() { - _clearState(); - } -} - -class Test { - String id; - String name; - double age; - int updateTime; - Test(this.id, {this.name, this.age, this.updateTime}); - - factory Test.fromMap(Map map, String id) { - return Test(id, - name: map['name'], age: map['age'], updateTime: map['update_time']); - } - - @override - bool operator ==(other) { - if (identical(this, other)) { - return true; - } - return other.id == this.id; - } - - @override - int get hashCode { - int result = 17; - result = 37 * result + id.hashCode; - return result; - } -} diff --git a/lib/model/user_model.dart b/lib/model/user_model.dart deleted file mode 100644 index 48e1f66..0000000 --- a/lib/model/user_model.dart +++ /dev/null @@ -1,375 +0,0 @@ -import 'dart:async'; -import 'dart:convert'; - -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:logging/logging.dart'; -import 'package:fcs/util.dart'; -import 'package:fcs/vo/popup_menu.dart'; -import 'package:fcs/vo/role.dart'; - -import '../config.dart'; -import '../vo/role.dart'; -import '../vo/user.dart'; -import 'base_model.dart'; -import 'constants.dart'; -import 'firebase_helper.dart'; - -class UserModel extends BaseModel { - final log = Logger('UserModel'); - StreamSubscription listener; - PopupMenu popupMenu = new PopupMenu(); - - List users = []; - List privileges = [ - Privilege(name: 'Manage shipment'), - Privilege(name: 'Manage pickups'), - Privilege(name: 'Manage packages'), - Privilege(name: 'Manage deliveries'), - Privilege(name: 'Admin') - ]; - List userLevels = []; - User user = new User(); - - List get getPrivileges { - return privileges - .where((p) => !p.sysAdminOnly || user.isSysAdmin()) - .toList(); - } - - List cont = []; - - void initUser(user) async { - super.initUser(user); - this.user = user; - if (user.isBuyer()) return; - _loadUsers(user); - _loadPrivileges(); - _loadUserLevels(user); - } - - @override - logout() async { - users = []; - userLevels = []; - } - - List getUserPrivileges() { - List result = new List(); - if (user.privilegeIds.isNotEmpty) { - user.privilegeIds.forEach((pID) { - privileges.forEach((p) { - if (p.id == pID) { - var _priv = Privilege(id: p.id, name: p.name, desc: p.desc); - result.add(_priv); - } - }); - }); - } - - return result; - } - - List getBlockListUsers() { - return users.where((u) => u.isBlock == true).toList(); - } - - List getUserList() { - return users.where((u) => u.docID != this.user.docID).toList(); - } - - Future _loadUsers(User user) async { - try { - String path = "/$biz_collection/${setting.okEnergyId}/$user_collection"; - var snaps = await Firestore.instance - .collection(path) - .where('user_level', isLessThanOrEqualTo: user.userLevel) - .limit(1) - .getDocuments(); - - Stream snapshots = Firestore.instance - .collection(path) - .where('user_level', isLessThanOrEqualTo: user.userLevel) - .snapshots(); - - snapshots.listen((snaps) async { - users = snaps.documents.map((documentSnapshot) { - var data = - User.fromMap(documentSnapshot.data, documentSnapshot.documentID); - if (data.docID == user.docID && data.isBlock) { - this.mainModel.logout(); - notifyListeners(); - } - return data; - }).toList(); - notifyListeners(); - }); - } catch (e) { - log.warning("Error!! $e"); - } - } - - Future findUser(String phoneNumber) async { - var _phoneNumber = updatePhoneNumber(phoneNumber); - try { - var data = await request("/user/find/$_phoneNumber", "GET", - token: await getToken()); - return User.fromJson(data); - } catch (e) { - throw Exception(e); - } - } - - Future _loadPrivileges() async { - // if (!user.isOwner() && !user.hasAccount()) { - // return; - // } - - try { - getQuerySnapshot("/$privilege_collection") - .listen((QuerySnapshot snapshot) { - privileges.clear(); - privileges = snapshot.documents.map((documentSnapshot) { - var privilege = Privilege.fromMap( - documentSnapshot.data, documentSnapshot.documentID); - return privilege; - }).toList(); - notifyListeners(); - }).onError((e) { - log.warning("Error! $e"); - }); - } catch (e) { - log.warning("Error!! $e"); - } - } - - Future _loadUserLevels(User user) async { - try { - Stream snapshots = Firestore.instance - .collection("/$user_level_collection") - .where('level', isLessThan: user.userLevel) - .snapshots(); - - snapshots.listen((snaps) async { - userLevels = snaps.documents - .map((documentSnapshot) => UserLevel.fromMap( - documentSnapshot.data, documentSnapshot.documentID)) - .toList(); - notifyListeners(); - }); - } catch (e) { - log.warning("Error!! $e"); - } - } - - Future getUser(String id) async { - String path = "/$biz_collection/${setting.okEnergyId}/$user_collection"; - print("id=> $id"); - var snap = await getDocSnap(path, id); - print("snap=> $snap"); - return User.fromMap(snap.data, snap.documentID); - } - - Future addUserToOk(String userID, List privileges) async { - await addUserToBiz(userID, setting.okEnergyId, privileges); - } - - Future addUserToBiz( - String userID, bizID, List privileges) async { - try { - await request("/user/add-biz", "POST", - payload: { - "user_id": userID, - "biz_id": bizID, - "privileges": privileges - }, - token: await getToken()); - } catch (e) { - throw Exception(e); - } - } - - Future forgetPassword(String id) async { - var _id = updatePhoneNumber(id); - await request("/forget", "POST", payload: {"id": _id}); - } - - Future resetPassword( - String id, String newPassword, String confirmationCode) async { - var _id = updatePhoneNumber(id); - await request( - "/reset", - "POST", - payload: { - "id": _id, - "password": newPassword, - "confirmation_code": confirmationCode - }, - ); - } - - Future changePassword(String id, String newPassword) async { - await request( - "/change/password", - "POST", - payload: { - "id": id, - "password": newPassword, - }, - ); - } - - Future changePhone(String id, String newPhone) async { - var _newPhone = updatePhoneNumber(newPhone); - await request( - "/change/phone", - "POST", - payload: { - "id": id, - "phone_number": _newPhone, - }, - ); - } - - Future addEmail(String id, String email) async { - await request( - "/email", - "PUT", - payload: { - "id": id, - "email": email, - }, - ); - } - - Future confirmEmail( - String id, String email, String phone, String confirmCode) async { - var _id = updatePhoneNumber(id); - var _phone = updatePhoneNumber(phone); - await request( - "/econfirm", - "POST", - payload: { - "id": _id, - "email": email == null ? '' : email, - "phone_number": _phone == null ? '' : _phone, - "confirmation_code": confirmCode - }, - ); - } - - Future deleteStorage(String storageID) async { - await request("/storage/" + storageID, "DELETE", token: await getToken()); - } - - Future blockPhone(String phone) async { - var _phone = updatePhoneNumber(phone); - await request("/blist", "PUT", - payload: {"phone_number": _phone}, token: await getToken()); - } - - Future unblockPhone(String phone) async { - var _phone = updatePhoneNumber(phone); - await request("/wlist", "PUT", - payload: {"phone_number": _phone}, token: await getToken()); - } - - Future addLevel( - String phone, String levelId, List privs) async { - var _phone = updatePhoneNumber(phone); - await request("/lvl", "PUT", - payload: { - "phone_number": _phone, - "user_level_id": levelId, - "privileges": privs - }, - token: await getToken()); - } - - Future updatePin(String pin, String password) async { - await request("/pin", "POST", - payload: { - "id": user.docID, - "pin": pin, - "password": password, - }, - token: await getToken()); - } - - Future clearPin(String password) async { - await request("/pin/clear", "POST", - payload: { - "id": user.docID, - "password": password, - }, - token: await getToken()); - } - - Future> searchUser(String searchUser) async { - if (searchUser == null || searchUser == '') return List(); - - var bytes = utf8.encode(searchUser); - var base64Str = base64.encode(bytes); - HtmlEscape htmlEscape = const HtmlEscape(); - String escapeUser = htmlEscape.convert(base64Str); - - int limit = 20; - List _users = []; - - try { - var data = await request( - "/api/fts/$user_collection/$escapeUser/$limit", "GET", - token: await getToken(), url: Config.instance.reportURL); - if (data == null) return List(); - - data.forEach((user) { - var _user = User.fromUserJson(user); - _users.add(_user); - }); - } catch (e) { - // permission error - log.warning("user error:" + e.toString()); - return null; - } - return _users; - } - - void filterSorting(int _selectedIndex) { - users.clear(); - if (listener != null) { - listener.cancel(); - } - String _fieldName; - bool descending = false; - - if (_selectedIndex == 0) { - _fieldName = 'user_name'; - descending = false; - } - if (_selectedIndex == 1) { - _fieldName = 'user_name'; - descending = true; - } - if (_selectedIndex == 2) { - _fieldName = 'phone_number'; - descending = false; - } - if (_selectedIndex == 3) { - _fieldName = 'phone_number'; - descending = true; - } - - this.popupMenu.index = _selectedIndex; - String path = "/$biz_collection/${setting.okEnergyId}/$user_collection"; - listener = - getFilterSnapshot(path, descending, _fieldName).listen((snaps) async { - users.clear(); - snaps.documents.forEach((d) { - users.add(User.fromMap(d.data, d.documentID)); - notifyListeners(); - }); - users.where((user) => user.userLevel <= this.user.userLevel); - - notifyListeners(); - }); - } -} diff --git a/lib/model_fcs/box_model.dart b/lib/model_fcs/box_model.dart deleted file mode 100644 index c1ea999..0000000 --- a/lib/model_fcs/box_model.dart +++ /dev/null @@ -1,306 +0,0 @@ -import 'dart:async'; - -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:fcs/model/base_model.dart'; -import 'package:fcs/model_fcs/package_model.dart'; -import 'package:fcs/vo/box.dart'; -import 'package:fcs/vo/cargo.dart'; -import 'package:fcs/vo/package.dart'; -import 'package:fcs/vo/shipping_address.dart'; -import 'package:logging/logging.dart'; - -class BoxModel extends BaseModel { - final log = Logger('BoxModel'); - - StreamSubscription listener; - static List statusHistory = [ - Status(status: "Packed", date: DateTime(2020, 6, 1), done: true), - Status(status: "Shipped", date: DateTime(2020, 6, 5), done: false), - Status(status: "Delivered", date: DateTime(2020, 6, 15), done: false) - ]; - static List packages = [ - PackageModel.packages[0], - PackageModel.packages[1], - PackageModel.packages[2] - ]; - - List boxes = [ - Box( - shipmentNumber: "A202", - receiverNumber: "3", - receiverName: "Ko Myo Min", - boxNumber: "1", - rate: 7, - packageType: "General", - weight: 75, - status: "Packed", - receiverAddress: '1 Bo Yar Nyunt St.\nDagon Tsp, Yangon', - cargoDesc: "Clothes", - arrivedDate: DateTime(2020, 6, 1), - width: 10, - height: 10, - length: 10, - shipmentWeight: 6, - packages: packages, - statusHistory: statusHistory, - shippingAddress: ShippingAddress( - fullName: 'U Nyi Nyi', - addressLine1: '154-19 64th Ave.', - addressLine2: 'Flushing', - city: 'NY', - state: 'NY', - phoneNumber: '+1 (292)215-2247'), - cargoTypes: [ - Cargo(type: 'General Cargo', weight: 25), - Cargo(type: 'Medicine', weight: 20), - Cargo(type: 'Dangerous Cargo', weight: 30) - ]), - Box( - shipmentNumber: "A202", - receiverNumber: "3", - receiverName: "Ko Myo Min", - boxNumber: "2", - rate: 7, - packageType: "General", - weight: 75, - status: "Packed", - cargoDesc: "Clothes", - arrivedDate: DateTime(2020, 6, 1), - width: 10, - height: 20, - length: 30, - shipmentWeight: 36, - statusHistory: statusHistory, - packages: packages, - receiverAddress: '1 Bo Yar Nyunt St.\nDagon Tsp, Yangon', - shippingAddress: ShippingAddress( - fullName: 'Mg Myo', - addressLine1: '153-154 5th Thitsar.', - addressLine2: 'South Okkalapa Township', - city: 'Yangon', - state: 'Myanmar', - phoneNumber: '+09 95724 8750'), - cargoTypes: [ - Cargo(type: 'General Cargo', weight: 25), - Cargo(type: 'Medicine', weight: 20), - Cargo(type: 'Dangerous Cargo', weight: 30) - ]), - Box( - shipmentNumber: "A202", - receiverNumber: "3", - receiverName: "Ko Myo Min", - boxNumber: "3", - rate: 7, - packageType: "General", - weight: 75, - cargoDesc: "Shoes", - status: "Packed", - arrivedDate: DateTime(2020, 6, 1), - width: 10, - height: 10, - length: 10, - shipmentWeight: 6, - statusHistory: statusHistory, - packages: packages, - receiverAddress: '1 Bo Yar Nyunt St.\nDagon Tsp, Yangon', - shippingAddress: ShippingAddress( - fullName: 'Mg Myo', - addressLine1: '153-154 5th Thitsar.', - addressLine2: 'South Okkalapa Township', - city: 'Yangon', - state: 'Myanmar', - phoneNumber: '+09 95724 8750'), - cargoTypes: [ - Cargo(type: 'General Cargo', weight: 25), - Cargo(type: 'Medicine', weight: 20), - Cargo(type: 'Dangerous Cargo', weight: 30) - ]), - Box( - shipmentNumber: "A202", - receiverNumber: "2", - receiverName: "Ma Aye", - boxNumber: "1", - rate: 8, - packageType: "Medicine", - weight: 75, - status: "Packed", - cargoDesc: "Dietary supplement", - arrivedDate: DateTime(2020, 6, 1), - width: 10, - height: 10, - length: 10, - shipmentWeight: 6, - statusHistory: statusHistory, - packages: packages, - receiverAddress: '2 Shwe Taung Kyar St, Bahan Tsp, Yangon', - shippingAddress: ShippingAddress( - fullName: 'U Nyi Nyi', - addressLine1: '154-19 64th Ave.', - addressLine2: 'Flushing', - city: 'NY', - state: 'NY', - phoneNumber: '+1 (292)215-2247'), - cargoTypes: [ - Cargo(type: 'General Cargo', weight: 25), - Cargo(type: 'Medicine', weight: 20), - Cargo(type: 'Dangerous Cargo', weight: 30) - ]), - Box( - shipmentNumber: "A202", - receiverNumber: "2", - receiverName: "Ma Aye", - boxNumber: "3", - rate: 7, - packageType: "General", - cargoDesc: "Handbags", - weight: 75, - status: "Arrived", - arrivedDate: DateTime(2020, 6, 1), - width: 10, - height: 10, - length: 10, - shipmentWeight: 6, - statusHistory: statusHistory, - packages: packages, - receiverAddress: '2 Shwe Taung Kyar St, Bahan Tsp, Yangon', - shippingAddress: ShippingAddress( - fullName: 'U Nyi Nyi', - addressLine1: '154-19 64th Ave.', - addressLine2: 'Flushing', - city: 'NY', - state: 'NY', - phoneNumber: '+1 (292)215-2247'), - cargoTypes: [ - Cargo(type: 'General Cargo', weight: 25), - Cargo(type: 'Medicine', weight: 20), - Cargo(type: 'Dangerous Cargo', weight: 30) - ]), - Box( - shipmentNumber: "A202", - receiverNumber: "2", - receiverName: "Ma Aye", - boxNumber: "2", - rate: 7, - packageType: "General", - cargoDesc: "Handbags", - weight: 75, - status: "Shipped", - arrivedDate: DateTime(2020, 6, 1), - width: 10, - height: 10, - length: 10, - shipmentWeight: 6, - statusHistory: statusHistory, - packages: packages, - receiverAddress: '2 Shwe Taung Kyar St, Bahan Tsp, Yangon', - shippingAddress: ShippingAddress( - fullName: 'U Nyi Nyi', - addressLine1: '154-19 64th Ave.', - addressLine2: 'Flushing', - city: 'NY', - state: 'NY', - phoneNumber: '+1 (292)215-2247'), - cargoTypes: [ - Cargo(type: 'General Cargo', weight: 25), - Cargo(type: 'Medicine', weight: 20), - Cargo(type: 'Dangerous Cargo', weight: 30) - ]), - Box( - shipmentNumber: "A201", - receiverNumber: "1", - receiverName: "Ko Wai", - boxNumber: "1", - rate: 9, - packageType: "Dangerous", - cargoDesc: "Phones and Scooters", - weight: 75, - status: "Delivered", - arrivedDate: DateTime(2020, 5, 21), - width: 10, - height: 10, - length: 10, - shipmentWeight: 6, - statusHistory: statusHistory, - packages: packages, - receiverAddress: '3 Kambzwza St, Bahan Tsp, Yangon', - shippingAddress: ShippingAddress( - fullName: 'U Nyi Nyi', - addressLine1: '154-19 64th Ave.', - addressLine2: 'Flushing', - city: 'NY', - state: 'NY', - phoneNumber: '+1 (292)215-2247'), - cargoTypes: [ - Cargo(type: 'General Cargo', weight: 25), - Cargo(type: 'Medicine', weight: 20), - Cargo(type: 'Dangerous Cargo', weight: 30) - ]), - Box( - shipmentNumber: "A201", - receiverNumber: "1", - receiverName: "Ko Wai", - boxNumber: "2", - rate: 7, - packageType: "General", - cargoDesc: "Construction tools", - weight: 75, - status: "Delivered", - arrivedDate: DateTime(2020, 5, 21), - width: 10, - height: 10, - length: 10, - shipmentWeight: 6, - statusHistory: statusHistory, - packages: packages, - receiverAddress: '3 Kambzwza St, Bahan Tsp, Yangon', - shippingAddress: ShippingAddress( - fullName: 'U Nyi Nyi', - addressLine1: '154-19 64th Ave.', - addressLine2: 'Flushing', - city: 'NY', - state: 'NY', - phoneNumber: '+1 (292)215-2247'), - cargoTypes: [ - Cargo(type: 'General Cargo', weight: 25), - Cargo(type: 'Medicine', weight: 20), - Cargo(type: 'Dangerous Cargo', weight: 30) - ]), - ]; - - List get completed { - return boxes.where((e) => e.status == "Delivered").toList() - ..sort((e1, e2) { - return e2.packageNumber.compareTo(e1.packageNumber); - }); - } - - List get processed { - return boxes.where((e) => e.status == "Packed").toList() - ..sort((e1, e2) { - return e2.packageNumber.compareTo(e1.packageNumber); - }); - } - - List get upcoming { - return boxes - .where((e) => - e.status == "Packed" || - // e.status == "Received" || - e.status == "Shipped" || - e.status == "Arrived") - .toList() - ..sort((e1, e2) { - return e2.packageNumber.compareTo(e1.packageNumber); - }); - } - - void initUser(user) { - super.initUser(user); - } - - @override - logout() async { - if (listener != null) await listener.cancel(); - boxes = []; - } -} diff --git a/lib/model_fcs/message_model.dart b/lib/model_fcs/message_model.dart deleted file mode 100644 index 99798db..0000000 --- a/lib/model_fcs/message_model.dart +++ /dev/null @@ -1,133 +0,0 @@ -import 'dart:async'; - -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:fcs/fcs/common/domain/constants.dart'; -import 'package:fcs/model/base_model.dart'; -import 'package:fcs/vo/message.dart'; -import 'package:fcs/vo/package.dart'; -import 'package:logging/logging.dart'; - -class MessageModel extends BaseModel { - final log = Logger('MessageModel'); - - StreamSubscription listener; - - List messages = [ - Message( - senderName: "FCS System", - receiverName: "Ko Myo Min", - date: DateTime(2020, 6, 1, 1, 1, 1), - message: - "Hi Ko Myo Min, we received your goods. Please see the following link", - ), - Message( - senderName: "FCS System", - receiverName: "Ko Myo Min", - date: DateTime(2020, 6, 1, 1, 1, 1), - message: "'A202-3 #1'", - ), - Message( - senderName: "FCS System", - receiverName: "Ko Myo Min", - date: DateTime(2020, 6, 1, 1, 5, 1), - message: "Thank you. Will check the photos.", - isMe: false), - Message( - senderName: "FCS System", - receiverName: "Ko Myo Min", - date: DateTime(2020, 6, 1, 2, 1, 1), - message: - "Hi Ko Myo Min, we successfully processed your goods and ready for payment. Please see in the following link.", - ), - Message( - senderName: "FCS System", - receiverName: "Ko Myo Min", - date: DateTime(2020, 6, 1, 2, 1, 1), - message: "'INV202005010387'", - ), - Message( - senderName: "FCS System", - receiverName: "Ko Myo Min", - date: DateTime(2020, 6, 1, 2, 10, 1), - message: - "Hi Ko Myo Min, we have confirmed your payment and ready to ship your packages.", - ), - Message( - senderName: "FCS System", - receiverName: "Shipper", - date: DateTime(2020, 6, 1, 1, 1, 1), - message: - "Hi Ko Myo Min, we received your goods. Please see in the following link.", - ), - Message( - senderName: "FCS System", - receiverName: "Shipper", - date: DateTime(2020, 6, 1, 1, 1, 1), - message: "'A202-3 #1'", - ), - Message( - senderName: "FCS System", - receiverName: "Shipper", - date: DateTime(2020, 6, 1, 2, 1, 1), - message: - "Hi FCS Team, we successfully processed your goods and ready for payment. Please see in the following link.", - ), - Message( - senderName: "FCS System", - receiverName: "Shipper", - date: DateTime(2020, 6, 1, 2, 1, 1), - message: "'INV202005010387'", - ), - Message( - senderName: "FCS System", - receiverName: "Shipper", - date: DateTime(2020, 6, 1, 2, 10, 1), - message: - "Hi FCS Team, we have confirmed your payment and ready to ship your packages.", - ), - Message( - senderName: "Ko Myo Min", - receiverName: "FCS Team", - date: DateTime(2020, 6, 1, 2, 10, 1), - message: - "Hi Ko Myo Min, we have recevied your pickup request. We will arrange the pickup soon. Thank you.", - ), - ]; - - List get lastMessage { - return [messages[2], messages[6]]; - } - - List getMessage(String receiver) { - return messages.where((e) => e.receiverName == receiver).toList(); - } - - // List get completed { - // return packages.where((e) => e.status == "Delivered").toList() - // ..sort((e1, e2) { - // return e2.packageNumber.compareTo(e1.packageNumber); - // }); - // } - - // List get upcoming { - // return packages - // .where((e) => - // e.status == "Processing" || - // e.status == "Received" || - // e.status == "Ready to ship") - // .toList() - // ..sort((e1, e2) { - // return e2.packageNumber.compareTo(e1.packageNumber); - // }); - // } - - void initUser(user) { - super.initUser(user); - } - - @override - logout() async { - if (listener != null) await listener.cancel(); - messages = []; - } -} diff --git a/lib/model_fcs/package_model.dart b/lib/model_fcs/package_model.dart deleted file mode 100644 index 4fb2cd0..0000000 --- a/lib/model_fcs/package_model.dart +++ /dev/null @@ -1,187 +0,0 @@ -import 'dart:async'; - -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:fcs/model/base_model.dart'; -import 'package:fcs/vo/box.dart'; -import 'package:fcs/vo/package.dart'; -import 'package:logging/logging.dart'; - -class PackageModel extends BaseModel { - final log = Logger('PackageModel'); - - StreamSubscription listener; - static List statusHistory = [ - Status(status: "Received", date: DateTime(2020, 6, 1), done: true), - Status(status: "Processed", date: DateTime(2020, 6, 1), done: true), - Status(status: "Shipped", date: DateTime(2020, 6, 5), done: false), - Status(status: "Arrived", date: DateTime(2020, 6, 7), done: false), - Status(status: "Delivered", date: DateTime(2020, 6, 15), done: false) - ]; - - static List packages = [ - Package( - shipmentNumber: "A202", - receiverNumber: "3", - receiverName: "Ko Myo Min", - boxNumber: "1", - rate: 7, - packageType: "General", - weight: 25, - status: "Received", - receiverAddress: '1 Bo Yar Nyunt St.\nDagon Tsp, Yangon', - cargoDesc: "Computers", - arrivedDate: DateTime(2020, 6, 1), - market: "Amazon", - id: "PKG2039", - trackingID: "23-234s-asdfl", - statusHistory: statusHistory), - Package( - shipmentNumber: "A202", - receiverNumber: "3", - receiverName: "Ko Myo Min", - boxNumber: "2", - rate: 7, - packageType: "General", - weight: 20, - status: "Received", - cargoDesc: "Clothes", - arrivedDate: DateTime(2020, 6, 1), - market: "Macy", - trackingID: "asd-sdf-23498", - id: "PKG2040", - receiverAddress: '1 Bo Yar Nyunt St.\nDagon Tsp, Yangon', - statusHistory: statusHistory), - Package( - shipmentNumber: "A202", - receiverNumber: "3", - receiverName: "Ko Myo Min", - boxNumber: "3", - rate: 7, - packageType: "General", - weight: 15, - cargoDesc: "Shoes", - status: "Processed", - market: "Macy", - trackingID: "8923-234-sd", - id: "PKG2041", - arrivedDate: DateTime(2020, 6, 1), - receiverAddress: '1 Bo Yar Nyunt St.\nDagon Tsp, Yangon', - statusHistory: statusHistory), - Package( - shipmentNumber: "A202", - receiverNumber: "2", - receiverName: "Ma Aye", - boxNumber: "1", - rate: 8, - packageType: "Medicine", - weight: 15, - status: "Processed", - market: "Macy", - trackingID: "lsdf-sd09sdf", - cargoDesc: "Dietary supplement", - id: "PKG2042", - arrivedDate: DateTime(2020, 6, 1), - receiverAddress: '2 Shwe Taung Kyar St, Bahan Tsp, Yangon', - statusHistory: statusHistory), - Package( - shipmentNumber: "A202", - receiverNumber: "2", - receiverName: "Ma Aye", - boxNumber: "2", - rate: 7, - packageType: "General", - cargoDesc: "Handbags", - weight: 55, - market: "Macy", - trackingID: "234-sdflsdf-213", - status: "Shipped", - id: "PKG2043", - arrivedDate: DateTime(2020, 6, 1), - receiverAddress: '2 Shwe Taung Kyar St, Bahan Tsp, Yangon', - statusHistory: statusHistory), - Package( - shipmentNumber: "A201", - receiverNumber: "1", - receiverName: "Ko Wai", - boxNumber: "1", - rate: 9, - packageType: "Dangerous", - cargoDesc: "Phones and Scooters", - weight: 25, - status: "Arrived", - market: "Amazon", - trackingID: "sdf-asdf-23489", - id: "PKG2044", - arrivedDate: DateTime(2020, 5, 21), - receiverAddress: '3 Kambzwza St, Bahan Tsp, Yangon', - statusHistory: statusHistory), - Package( - shipmentNumber: "A201", - receiverNumber: "1", - receiverName: "Ko Wai", - boxNumber: "2", - rate: 7, - packageType: "General", - cargoDesc: "Construction tools", - weight: 5, - status: "Processed", - market: "Amazon", - id: "PKG2045", - trackingID: "oiuw-sdfpo-234", - arrivedDate: DateTime(2020, 5, 21), - receiverAddress: '3 Kambzwza St, Bahan Tsp, Yangon', - statusHistory: statusHistory), - ]; - - List get getPackages { - return packages - ..sort((e1, e2) { - return e2.packageNumber.compareTo(e1.packageNumber); - }); - } - - List get completed { - return packages.where((e) => e.status == "Processed").toList() - ..sort((e1, e2) { - return e2.packageNumber.compareTo(e1.packageNumber); - }); - } - - List get shipped { - return packages.where((e) => e.status == "Shipped").toList() - ..sort((e1, e2) { - return e2.packageNumber.compareTo(e1.packageNumber); - }); - } - - List get arrived { - return packages.where((e) => e.status == "Arrived").toList() - ..sort((e1, e2) { - return e2.packageNumber.compareTo(e1.packageNumber); - }); - } - - List get delivered { - return packages.where((e) => e.status == "Delivered").toList() - ..sort((e1, e2) { - return e2.packageNumber.compareTo(e1.packageNumber); - }); - } - - List get upcoming { - return packages.where((e) => e.status == "Received").toList() - ..sort((e1, e2) { - return e2.packageNumber.compareTo(e1.packageNumber); - }); - } - - void initUser(user) { - super.initUser(user); - } - - @override - logout() async { - if (listener != null) await listener.cancel(); - packages = []; - } -} diff --git a/lib/model_page/user_list_model.dart b/lib/model_page/user_list_model.dart deleted file mode 100644 index 1924b9c..0000000 --- a/lib/model_page/user_list_model.dart +++ /dev/null @@ -1,81 +0,0 @@ -import 'dart:async'; - -import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:logging/logging.dart'; -import 'package:fcs/model/base_model.dart'; -import 'package:fcs/model/constants.dart'; -import 'package:fcs/model/firebase_helper.dart'; -import 'package:fcs/util.dart'; - -import '../vo/user.dart'; - -class UserModel extends BaseModel { - final log = Logger('UserListModel'); - StreamSubscription listener; - List users = []; - - void initUser(user) async { - super.initUser(user); - _loadUsers(user); - } - - Future _loadUsers(User user) async { - try { - String path = "/$biz_collection/${setting.okEnergyId}/$user_collection"; - var snaps = await Firestore.instance - .collection(path) - .where('user_level', isLessThanOrEqualTo: user.userLevel) - .limit(1) - .getDocuments(); - - Stream snapshots = Firestore.instance - .collection(path) - .where('user_level', isLessThanOrEqualTo: user.userLevel) - .snapshots(); - - snapshots.listen((snaps) async { - users = snaps.documents.map((documentSnapshot) { - var data = - User.fromMap(documentSnapshot.data, documentSnapshot.documentID); - if (data.docID == user.docID && data.isBlock) { - this.mainModel.logout(); - notifyListeners(); - } - return data; - }).toList(); - notifyListeners(); - }); - } catch (e) { - log.warning("Error!! $e"); - } - } - - @override - logout() async { - users = []; - if (listener != null) listener.cancel(); - } - - List getUserList() { - return users.where((u) => u.docID != this.user.docID).toList(); - } - - Future findUser(String phoneNumber) async { - var _phoneNumber = updatePhoneNumber(phoneNumber); - try { - var data = await request("/user/find/$_phoneNumber", "GET", - token: await getToken()); - return User.fromJson(data); - } catch (e) { - throw Exception(e); - } - } - - Future getUser(String id) async { - String path = "/$biz_collection/${setting.okEnergyId}/$user_collection"; - print("id=> $id"); - var snap = await getDocSnap(path, id); - print("snap=> $snap"); - return User.fromMap(snap.data, snap.documentID); - } -} diff --git a/lib/pages/add_pin_editor.dart b/lib/pages/add_pin_editor.dart deleted file mode 100644 index 8259afa..0000000 --- a/lib/pages/add_pin_editor.dart +++ /dev/null @@ -1,363 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/language_model.dart'; -import 'package:fcs/model/user_model.dart'; -import 'package:fcs/vo/user.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:fcs/widget/progress.dart'; - -import '../fcs/common/helpers/theme.dart' as Theme; -import '../fcs/common/pages/util.dart'; - -class AddPINEditor extends StatefulWidget { - final User user; - AddPINEditor( - this.user, { - Key key, - }) : super(key: key); - - @override - _AddPINEditorState createState() => new _AddPINEditorState(); -} - -class _AddPINEditorState extends State - with SingleTickerProviderStateMixin { - final GlobalKey _scaffoldKey = new GlobalKey(); - - final FocusNode myFocusNodePassword = FocusNode(); - final FocusNode myFocusNodeEmail = FocusNode(); - - bool _obscureTextLogin = true; - bool _obscureTextSignup = true; - bool _obscureTextSignupConfirm = true; - - TextEditingController _passwordController = new TextEditingController(); - TextEditingController _pinController = new TextEditingController(); - final formKey = GlobalKey(); - bool _isLoading = false; - bool isSwitched = false; - - @override - Widget build(BuildContext context) { - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - key: _scaffoldKey, - body: SingleChildScrollView( - child: Container( - width: MediaQuery.of(context).size.width, - height: MediaQuery.of(context).size.height >= 775.0 - ? MediaQuery.of(context).size.height - : 580.0, - child: Column( - mainAxisSize: MainAxisSize.max, - children: [ - Padding( - padding: EdgeInsets.only(top: 35.0, bottom: 10), - child: ListTile( - leading: IconButton( - icon: Icon(Icons.arrow_back), - onPressed: () { - Navigator.of(context).pop(); - }, - ), - title: LocalText( - context, - 'change.pin.title', - color: Colors.black87, - fontSize: 17, - ), - ), - ), - Expanded( - flex: 2, - child: PageView( - children: [ - new ConstrainedBox( - constraints: const BoxConstraints.expand(), - child: _buildReset(context), - ), - ], - ), - ), - ], - ), - ), - ), - ), - ); - } - - @override - void dispose() { - myFocusNodePassword.dispose(); - myFocusNodeEmail.dispose(); - super.dispose(); - } - - @override - void initState() { - super.initState(); - - // SystemChrome.setPreferredOrientations([ - // DeviceOrientation.portraitUp, - // DeviceOrientation.portraitDown, - // ]); - } - - Widget _buildReset(BuildContext context) { - final switchBtnBox = Row( - children: [ - Container( - padding: EdgeInsets.only(left: 20), - child: LocalText( - context, - 'pin.switch', - fontSize: 15, - )), - Switch( - value: isSwitched, - onChanged: (value) { - setState(() { - isSwitched = value; - if (!isSwitched) { - _pinController.clear(); - } - }); - }, - activeColor: Theme.secondaryColor, - ), - ], - ); - - final pinInputBox = Padding( - padding: EdgeInsets.only(left: 25.0, right: 25.0), - child: TextFormField( - controller: _pinController, - keyboardType: TextInputType.number, - style: TextStyle( - fontFamily: "WorkSansSemiBold", - fontSize: 16.0, - color: Colors.black), - decoration: InputDecoration( - border: InputBorder.none, - icon: Image.asset( - 'assets/pin.png', - width: 30, - height: 30, - ), - labelText: AppTranslations.of(context).text("change.pin"), - labelStyle: Provider.of(context).isEng - ? TextStyle(fontFamily: "WorkSansSemiBold", color: Colors.grey) - : TextStyle(fontFamily: "MyanmarUnicode", color: Colors.grey), - ), - validator: _validatePinCode, - ), - ); - - final passwordInputBox = Padding( - padding: EdgeInsets.only(left: 25.0, right: 25.0), - child: TextFormField( - focusNode: myFocusNodePassword, - controller: _passwordController, - obscureText: _obscureTextSignup, - style: TextStyle( - fontFamily: "WorkSansSemiBold", - fontSize: 16.0, - color: Colors.black), - decoration: InputDecoration( - border: InputBorder.none, - icon: Icon( - FontAwesomeIcons.lock, - color: Colors.black, - ), - labelText: AppTranslations.of(context).text("login.password"), - labelStyle: Provider.of(context).isEng - ? TextStyle(fontFamily: "WorkSansSemiBold", color: Colors.grey) - : TextStyle(fontFamily: "MyanmarUnicode", color: Colors.grey), - suffixIcon: GestureDetector( - onTap: _toggleSignup, - child: Icon( - _obscureTextSignup - ? FontAwesomeIcons.eye - : FontAwesomeIcons.eyeSlash, - size: 15.0, - color: Colors.black, - ), - ), - ), - validator: _validatePassword, - ), - ); - - final updatePinBtn = Container( - decoration: new BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(5.0)), - color: Theme.primaryColor, - ), - child: MaterialButton( - highlightColor: Colors.transparent, - splashColor: Theme.LoginColors.loginGradientEnd, - child: Padding( - padding: - const EdgeInsets.symmetric(vertical: 10.0, horizontal: 42.0), - child: LocalText( - context, - 'pin.add_btn', - color: Colors.white, - fontSize: 18.0, - ), - ), - onPressed: () => _change(context)), - ); - - final clearPinBtn = Container( - // margin: EdgeInsets.only(top: 320.0), - decoration: new BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(5.0)), - color: Theme.primaryColor, - ), - child: MaterialButton( - highlightColor: Colors.transparent, - splashColor: Theme.LoginColors.loginGradientEnd, - //shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(5.0))), - child: Padding( - padding: - const EdgeInsets.symmetric(vertical: 10.0, horizontal: 42.0), - child: LocalText( - context, - 'pin.clear_btn', - color: Colors.white, - fontSize: 18.0, - ), - ), - onPressed: () => _clear(context)), - ); - return Container( - child: ListView( - children: [ - Column( - children: [ - Form( - key: formKey, - child: Card( - elevation: 2.0, - color: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - child: Container( - width: 300.0, - child: Column( - children: [ - switchBtnBox, - isSwitched ? Container() : pinInputBox, - Container( - width: 250.0, - height: 1.0, - color: Colors.grey[400], - ), - passwordInputBox - ], - ), - ), - ), - ), - SizedBox( - height: 15, - ), - isSwitched ? Container() : updatePinBtn, - SizedBox( - height: 15, - ), - !isSwitched ? Container() : clearPinBtn - ], - ), - ], - ), - ); - } - - void _toggleSignup() { - setState(() { - _obscureTextSignup = !_obscureTextSignup; - }); - } - - void _change(BuildContext context) async { - if (!formKey.currentState.validate()) { - return; - } - - setState(() { - _isLoading = true; - }); - - UserModel userModel = Provider.of(context); - try { - await userModel.updatePin(_pinController.text, _passwordController.text); - Navigator.pop(context); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - Future.delayed(Duration(seconds: 1), () { - if (mounted) { - setState(() { - _isLoading = false; - }); - } - }); - } - } - - void _clear(BuildContext context) async { - if (!formKey.currentState.validate()) { - return; - } - - setState(() { - _isLoading = true; - }); - - UserModel userModel = Provider.of(context); - try { - await userModel.clearPin(_passwordController.text); - Navigator.pop(context); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - Future.delayed(Duration(seconds: 1), () { - if (mounted) { - setState(() { - _isLoading = false; - }); - } - }); - } - } - - String _validatePassword(value) { - if (value.isEmpty) { - return AppTranslations.of(context).text("login.password_empty"); - } - if (value.length < 6) { - return AppTranslations.of(context).text("login.password_size"); - } - return null; - } - - String _validatePinCode(value) { - if (!isSwitched) { - if (value.isEmpty) { - return AppTranslations.of(context).text("change.pin_empty"); - } - if (value.length < 6 || value.length > 6) { - return AppTranslations.of(context).text("change.pin_size"); - } - } - - return null; - } -} diff --git a/lib/pages/announcement.dart b/lib/pages/announcement.dart deleted file mode 100644 index af88b1a..0000000 --- a/lib/pages/announcement.dart +++ /dev/null @@ -1,184 +0,0 @@ -import 'dart:convert'; - -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/announcement_model.dart'; -import 'package:fcs/model/main_model.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/vo/announcement.dart'; -import 'package:fcs/vo/popup_menu.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/popupmenu.dart'; -import 'package:fcs/widget/progress.dart'; -import 'package:zefyr/zefyr.dart'; - -import '../fcs/common/helpers/theme.dart'; -import 'announcement_editor.dart'; - -class AnnouncementPage extends StatefulWidget { - final Announcement announcement; - - const AnnouncementPage({Key key, this.announcement}) : super(key: key); - @override - _AnnouncementState createState() => _AnnouncementState(); -} - -class _AnnouncementState extends State { - ZefyrController _textController; - - TextEditingController nameController = new TextEditingController(); - FocusNode _focusNode; - NotusDocument document = new NotusDocument(); - bool isLoading = false; - - Announcement _announcement = new Announcement(); - - @override - void initState() { - super.initState(); - if (widget.announcement != null) { - _announcement = widget.announcement; - nameController.text = _announcement.name; - _textController = ZefyrController(_loadDocument(_announcement)); - _focusNode = FocusNode(); - } - } - - NotusDocument _loadDocument(Announcement announcement) { - NotusDocument doc; - try { - doc = NotusDocument.fromJson(jsonDecode(announcement.text)); - } catch (e) {} - if (doc == null) { - doc = NotusDocument(); - } - return doc; - } - - @override - Widget build(BuildContext context) { - MainModel mainModel = Provider.of(context); - - bool isOwnerAndAbove = - mainModel.user != null && mainModel.user.isOwnerAndAbove(); - bool hasAdmin = mainModel.user != null && mainModel.user.hasAdmin(); - - final nameBox = Container( - padding: EdgeInsets.only(top: 20, left: 20, right: 20), - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - LocalText(context, 'announcement.name'), - SizedBox( - height: 15, - ), - Text( - nameController.text, - style: textStyle, - ) - ], - ), - ); - - final textBox = Expanded( - child: Container( - padding: EdgeInsets.only(left: 5, right: 20), - child: ZefyrTheme( - data: ZefyrThemeData().copyWith(), - child: ZefyrScaffold( - child: ZefyrEditor( - mode: ZefyrMode.view, - padding: EdgeInsets.all(16), - controller: _textController, - focusNode: _focusNode, - ), - )), - )); - - return LocalProgress( - inAsyncCall: isLoading, - child: Scaffold( - appBar: AppBar( - title: LocalText(context, 'announcement.form.title', - color: Colors.white, fontSize: 20), - backgroundColor: primaryColor, - actions: [ - isOwnerAndAbove || hasAdmin - ? PopupMenuButton( - elevation: 3.2, - tooltip: 'This is tooltip', - onSelected: _select, - itemBuilder: (BuildContext context) { - return announcementMenu.map((PopupMenu choice) { - return PopupMenuItem( - value: choice, - child: Text(choice.status), - ); - }).toList(); - }) - : Container() - ], - ), - body: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - nameBox, - Container( - padding: EdgeInsets.only(left: 10, right: 10), - child: Divider( - color: Colors.grey, - )), - Container( - padding: EdgeInsets.only(left: 20, right: 20), - child: LocalText(context, 'announcement.desc')), - textBox, - SizedBox(height: 10) - ], - ), - ), - ); - } - - void _select(PopupMenu choice) async { - if (choice.index == 1) { - Announcement _anno = await Navigator.push( - context, - MaterialPageRoute( - builder: (context) => - AnnouncementEditor(announcement: _announcement)), - ); - if (_anno == null) return; - - setState(() { - _announcement = _anno; - nameController.text = _announcement.name; - _textController = ZefyrController(_loadDocument(_announcement)); - _focusNode = FocusNode(); - }); - } else if (choice.index == 2) { - showConfirmDialog(context, "announcement.delete_confirm", () { - _delete(context); - }); - } - } - - void _delete(BuildContext context) async { - setState(() { - isLoading = true; - }); - try { - if (widget.announcement != null) { - await Provider.of(context) - .deleteAnnouncement(widget.announcement); - } - Navigator.pop(context); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - setState(() { - isLoading = false; - }); - } - } -} diff --git a/lib/pages/announcement_editor.dart b/lib/pages/announcement_editor.dart deleted file mode 100644 index b37a332..0000000 --- a/lib/pages/announcement_editor.dart +++ /dev/null @@ -1,152 +0,0 @@ -import 'dart:convert'; - -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/announcement_model.dart'; -import 'package:fcs/model/language_model.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/announcement.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:fcs/widget/progress.dart'; -import 'package:zefyr/zefyr.dart'; - -class AnnouncementEditor extends StatefulWidget { - final Announcement announcement; - - const AnnouncementEditor({Key key, this.announcement}) : super(key: key); - @override - _AnnouncementEditorState createState() => _AnnouncementEditorState(); -} - -class _AnnouncementEditorState extends State { - final _formKey = GlobalKey(); - static final _scafoldKey = new GlobalKey(); - TextEditingController nameController = new TextEditingController(); - bool _isLoading = false; - FocusNode _focusNode; - ZefyrController _textController; - Announcement _announcement = new Announcement(); - - @override - void initState() { - super.initState(); - if (widget.announcement != null) { - _announcement = widget.announcement; - nameController.text = _announcement.name; - NotusDocument doc = - NotusDocument.fromJson(jsonDecode(widget.announcement.text)); - _textController = ZefyrController(doc); - _focusNode = FocusNode(); - } else { - _textController = ZefyrController(NotusDocument()); - _focusNode = FocusNode(); - } - } - - @override - Widget build(BuildContext context) { - var languageModel = Provider.of(context); - - final nameBox = Container( - padding: EdgeInsets.only(top: 10), - child: TextFormField( - controller: nameController, - autofocus: false, - decoration: new InputDecoration( - labelText: AppTranslations.of(context).text("announcement.name"), - labelStyle: languageModel.isEng ? labelStyle : labelStyleMM, - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - ), - validator: (value) { - if (value.isEmpty) { - return AppTranslations.of(context).text("announcement.name_empty"); - } - return null; - }, - ), - ); - - final textEditor = ZefyrField( - height: 200.0, - decoration: InputDecoration( - labelText: AppTranslations.of(context).text('announcement.desc'), - labelStyle: languageModel.isEng ? labelStyle : labelStyleMM, - ), - controller: _textController, - focusNode: _focusNode, - autofocus: false, - physics: ClampingScrollPhysics(), - ); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - title: LocalText( - context, - "announcement.form.title", - color: Colors.white, - fontSize: 20, - ), - actions: [ - IconButton( - icon: Icon(Icons.save), - onPressed: () { - _save(context); - }, - ) - ], - ), - body: ZefyrScaffold( - key: _scafoldKey, - child: Padding( - padding: EdgeInsets.only(left: 20.0, right: 20.0), - child: Form( - key: _formKey, - child: ListView( - children: [ - nameBox, - SizedBox(height: 10), - textEditor, - ], - )), - ), - ), - ), - ); - } - - void _save(BuildContext context) { - if (!_formKey.currentState.validate()) return; - - setState(() { - _isLoading = true; - }); - try { - _announcement.name = nameController.text; - final contents = jsonEncode(_textController.document); - _announcement.text = contents; - - if (widget.announcement != null) { - Provider.of(context, listen: false) - .updateAnnouncement(_announcement); - } else { - Provider.of(context, listen: false) - .createAnnouncement(_announcement); - } - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - Future.delayed(const Duration(milliseconds: 3000), () { - _isLoading = false; - Navigator.pop(context, this._announcement); - }); - } - } -} diff --git a/lib/pages/announcement_list.dart b/lib/pages/announcement_list.dart deleted file mode 100644 index 0c57365..0000000 --- a/lib/pages/announcement_list.dart +++ /dev/null @@ -1,146 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/announcement_model.dart'; -import 'package:fcs/model/main_model.dart'; -import 'package:fcs/vo/announcement.dart' as Announce; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:fcs/widget/progress.dart'; - -import '../fcs/common/helpers/theme.dart'; -import 'announcement.dart'; -import 'announcement_editor.dart'; - -class AnnouncementList extends StatefulWidget { - @override - _AnnouncementListState createState() => _AnnouncementListState(); -} - -class _AnnouncementListState extends State { - var timeFormatter = new DateFormat('KK:mm a'); - var dateFormatter = new DateFormat('dd MMM'); - - final double dotSize = 15.0; - bool _isLoading = false; - - @override - void initState() { - super.initState(); - } - - @override - Widget build(BuildContext context) { - AnnouncementModel announcementModel = - Provider.of(context); - - MainModel mainModel = Provider.of(context); - bool isOwnerAndAbove = - mainModel.user != null && mainModel.user.isOwnerAndAbove(); - bool hasAdmin = mainModel.user != null && mainModel.user.hasAdmin(); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - title: LocalText( - context, - "announcement.title", - color: Colors.white, - fontSize: 20, - )), - floatingActionButton: isOwnerAndAbove || hasAdmin - ? FloatingActionButton( - backgroundColor: primaryColor, - child: Icon(Icons.add), - onPressed: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => AnnouncementEditor()), - ); - }, - ) - : Container(), - body: new ListView.separated( - separatorBuilder: (context, index) => Divider( - color: Colors.black, - ), - scrollDirection: Axis.vertical, - padding: EdgeInsets.only(left: 15, right: 15, top: 15), - shrinkWrap: true, - itemCount: announcementModel.announcements.length, - itemBuilder: (BuildContext context, int index) { - Announce.Announcement announce = - announcementModel.announcements[index]; - return InkWell( - onTap: () { - setState(() { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => - AnnouncementPage(announcement: announce)), - ); - }); - }, - child: Row( - children: [ - Expanded( - child: new Padding( - padding: const EdgeInsets.symmetric(vertical: 10.0), - child: new Row( - children: [ - new Padding( - padding: new EdgeInsets.symmetric( - horizontal: 32.0 - dotSize / 2), - child: Icon( - Icons.announcement, - color: primaryColor, - size: 30, - ), - ), - new Expanded( - child: new Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - announce.name == null - ? Container() - : new Text( - announce.name, - style: new TextStyle( - fontSize: 15.0, - color: Colors.black), - ), - ], - ), - ), - Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: Text(announce.time == null - ? "" - : timeFormatter.format(announce.time)), - ), - announce.fromToday() - ? Container() - : Text(announce.time == null - ? "" - : dateFormatter.format(announce.time)), - ], - ) - ], - ), - ), - ), - ], - ), - ); - }), - ), - ); - } -} diff --git a/lib/pages/banks/bank_edit.dart b/lib/pages/banks/bank_edit.dart deleted file mode 100644 index e99f1c0..0000000 --- a/lib/pages/banks/bank_edit.dart +++ /dev/null @@ -1,195 +0,0 @@ -import 'dart:io'; - -import 'package:flutter/material.dart'; -import 'package:image_picker/image_picker.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/main_model.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/bank_account.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/local_text_field.dart'; -import 'package:fcs/widget/progress.dart'; - -class BankEdit extends StatefulWidget { - final BankAccount bankAccount; - - const BankEdit({Key key, this.bankAccount}) : super(key: key); - - @override - _BankEditState createState() => _BankEditState(); -} - -class _BankEditState extends State { - TextEditingController bankNameController = new TextEditingController(); - TextEditingController accountNameController = new TextEditingController(); - TextEditingController accountNumberController = new TextEditingController(); - - bool _isLoading; - bool _isEdit; - File image; - BankAccount bankAccount; - - @override - void initState() { - super.initState(); - _isLoading = false; - _isEdit = widget.bankAccount != null; - bankAccount = BankAccount(); - if (_isEdit) { - bankAccount = widget.bankAccount; - bankNameController.text = bankAccount.bankName; - accountNameController.text = bankAccount.accountName; - accountNumberController.text = bankAccount.accountNumber; - } - } - - @override - Widget build(BuildContext context) { - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - title: LocalText(context, 'banks.edit.title', - color: Colors.white, fontSize: 20), - backgroundColor: primaryColor, - actions: [ - IconButton( - icon: Icon(Icons.save), - onPressed: () { - _save(); - }, - ), - IconButton( - icon: Icon(Icons.delete), - onPressed: () { - _delete(); - }, - ) - ], - ), - body: Column( - children: [ - Expanded( - child: ListView( - shrinkWrap: true, - padding: EdgeInsets.only(left: 24.0, right: 24.0), - children: [ - LocalTextField( - labelKey: "banks.name", - textEditingController: bankNameController), - LocalTextField( - labelKey: "banks.account.name", - textEditingController: accountNameController), - LocalTextField( - labelKey: "banks.account.number", - textEditingController: accountNumberController, - textInputType: TextInputType.number, - ), - Padding( - padding: const EdgeInsets.all(18.0), - child: Center( - child: Stack( - children: [ - Container( - width: 80, - height: 80, - padding: const EdgeInsets.all(2.0), - decoration: BoxDecoration( - border: Border.all( - color: primaryColor, - width: 1.0, - ), - ), - child: image == null - ? Image.network( - _isEdit ? widget.bankAccount.bankLogo : "", - height: 80, - width: 80, - ) - : Image.file(image), - ), - Positioned( - bottom: -10, - right: -10, - child: IconButton( - color: primaryColor, - icon: const Icon( - Icons.edit, - color: Colors.grey, - ), - onPressed: () async { - File _image = await ImagePicker.pickImage( - source: ImageSource.gallery, - maxWidth: 300, - maxHeight: 300, - imageQuality: 80); - if (_image != null) { - setState(() { - this.image = _image; - }); - } - })) - ], - ), - ), - ) - ], - ), - ), - ], - ), - ), - ); - } - - _save() async { - if (!_isEdit && image == null) { - showMsgDialog(context, "Error", "Need bank logo!"); - return; - } - setState(() { - _isLoading = true; - }); - try { - bankAccount.bankName = bankNameController.text; - bankAccount.accountName = accountNameController.text; - bankAccount.accountNumber = accountNumberController.text; - MainModel mainModel = Provider.of(context, listen: false); - if (_isEdit) { - await mainModel.updateBankAccount(bankAccount, image); - } else { - await mainModel.addBankAccount(bankAccount, image); - } - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - return; - } finally { - setState(() { - _isLoading = false; - }); - } - Navigator.pop(context); - } - - _delete() async { - showConfirmDialog(context, "banks.account.delete.confirmation", () async { - setState(() { - _isLoading = true; - }); - try { - MainModel mainModel = Provider.of(context, listen: false); - if (_isEdit) { - await mainModel.deleteBankAccount(bankAccount); - } - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - setState(() { - _isLoading = false; - }); - Navigator.pop(context); - } - }); - } -} diff --git a/lib/pages/banks/banks.dart b/lib/pages/banks/banks.dart deleted file mode 100644 index e1000ec..0000000 --- a/lib/pages/banks/banks.dart +++ /dev/null @@ -1,259 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/main_model.dart'; -import 'package:fcs/pages/banks/bank_edit.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/bank_account.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/progress.dart'; - -class BankAccounts extends StatefulWidget { - const BankAccounts({Key key}) : super(key: key); - @override - _BankAccountsState createState() => _BankAccountsState(); -} - -class _BankAccountsState extends State { - bool isLoading = false; - bool isEdit = false; - - final TextEditingController bankNameCtl = TextEditingController(); - final TextEditingController accountNameCtl = TextEditingController(); - final TextEditingController accountNumberCtl = TextEditingController(); - - @override - void initState() { - super.initState(); - } - - @override - Widget build(BuildContext context) { - MainModel mainModel = Provider.of(context); - List bankAccounts = mainModel.setting.bankAccounts; - - bool isOwnerAndAbove = - mainModel.user != null && mainModel.user.isOwnerAndAbove(); - bool hasAdmin = mainModel.user != null && mainModel.user.hasAdmin(); - - return WillPopScope( - onWillPop: () { - if (isEdit) { - setState(() { - isEdit = false; - }); - return Future.value(false); - } - return Future.value(true); - }, - child: LocalProgress( - inAsyncCall: isLoading, - child: Scaffold( - appBar: AppBar( - centerTitle: true, - automaticallyImplyLeading: !isEdit, - title: LocalText(context, 'banks.title', - color: Colors.white, fontSize: 20), - backgroundColor: primaryColor, - actions: [ - (isOwnerAndAbove || hasAdmin) - ? isEdit - ? IconButton( - icon: Icon(Icons.done), - onPressed: () { - setState(() { - isEdit = false; - }); - }, - ) - : IconButton( - icon: Icon(Icons.edit), - onPressed: () { - _edit(); - }, - ) - : Container() - ], - ), - floatingActionButton: isEdit - ? FloatingActionButton( - backgroundColor: primaryColor, - onPressed: () { - Navigator.push( - context, - MaterialPageRoute(builder: (context) => BankEdit()), - ); - }, - child: const Icon( - Icons.add, - color: Colors.white, - ), - ) - : null, - body: new ListView.builder( - scrollDirection: Axis.vertical, - padding: EdgeInsets.only(top: 15), - shrinkWrap: true, - itemCount: bankAccounts.length, - itemBuilder: (BuildContext context, int index) { - return _item(context, bankAccounts[index]); - }), - ), - ), - ); - } - - _item(BuildContext context, BankAccount bankAccount) { - return InkWell( - onTap: isEdit - ? () => Navigator.push( - context, - MaterialPageRoute( - builder: (context) => BankEdit( - bankAccount: bankAccount, - )), - ) - : null, - child: Row( - children: [ - Row( - children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: Container( - padding: const EdgeInsets.all(2.0), - decoration: BoxDecoration( - border: Border.all( - color: primaryColor, - width: 1.0, - ), - ), - child: Image.network( - bankAccount.bankLogo, - height: 80, - width: 80, - ), - ), - ), - ], - ), - Expanded( - child: new Row( - children: [ - new Expanded( - child: new Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.all(3.0), - child: new Text( - bankAccount.bankName, - style: new TextStyle( - fontSize: 20.0, color: Colors.black), - ), - ), - Padding( - padding: const EdgeInsets.all(3.0), - child: new Text( - bankAccount.accountName, - style: - new TextStyle(fontSize: 16.0, color: Colors.grey), - ), - ), - Padding( - padding: const EdgeInsets.all(3.0), - child: Row( - children: [ - Text( - bankAccount.accountNumber, - style: new TextStyle( - fontSize: 16.0, color: Colors.grey), - ), - InkWell( - onTap: () { - Clipboard.setData(ClipboardData( - text: bankAccount.accountNumber)); - _showToast(context, bankAccount.bankName); - }, - child: Padding( - padding: const EdgeInsets.only(left: 7.0), - child: Icon( - Icons.content_copy, - color: Colors.grey, - ), - ), - ), - ], - ), - ), - ], - ), - ), - ], - ), - ), - ], - ), - ); - } - - Future _displayEditDialog(BuildContext context) async { - return showDialog( - context: context, - builder: (context) { - return AlertDialog( - title: Text('Edit'), - content: Column( - children: [ - TextField( - controller: bankNameCtl, - keyboardType: TextInputType.numberWithOptions(decimal: true), - decoration: InputDecoration(hintText: "Enter Bank Name"), - ), - TextField( - controller: accountNameCtl, - keyboardType: TextInputType.numberWithOptions(decimal: true), - decoration: InputDecoration(hintText: "Enter Account Name"), - ), - TextField( - controller: accountNumberCtl, - keyboardType: TextInputType.number, - decoration: InputDecoration(hintText: "Enter Account Number"), - ), - IconButton(icon: Icon(Icons.photo_library), onPressed: null) - ], - ), - actions: [ - FlatButton( - child: const Text('Cancel'), - onPressed: () { - Navigator.of(context).pop(); - }, - ), - FlatButton( - child: const Text('Ok'), - onPressed: () { - Navigator.of(context).pop(); - }), - ], - ); - }); - } - - void _edit() { - setState(() { - isEdit = true; - }); - } - - void _showToast(BuildContext context, String bankName) { - final scaffold = Scaffold.of(context); - scaffold.showSnackBar( - SnackBar( - content: Text('copied "$bankName" account number to clipboard'), - backgroundColor: primaryColor, - duration: Duration(seconds: 1), - ), - ); - } -} diff --git a/lib/pages/barcode_screen_page.dart b/lib/pages/barcode_screen_page.dart deleted file mode 100644 index fee7bea..0000000 --- a/lib/pages/barcode_screen_page.dart +++ /dev/null @@ -1,73 +0,0 @@ -import 'package:barcode_scan/barcode_scan.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_icons/flutter_icons.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/product_model.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/buyer.dart'; -import 'package:fcs/vo/product.dart'; -import 'package:fcs/widget/progress.dart'; - -class BarcodeScreenPage extends StatefulWidget { - final BuyerProduct buyerProduct; - const BarcodeScreenPage({Key key, this.buyerProduct}) : super(key: key); - @override - _BarcodeScreenPageState createState() => _BarcodeScreenPageState(); -} - -class _BarcodeScreenPageState extends State { - final _formKey = GlobalKey(); - bool _isLoading = false; - String scanResult; - - @override - void initState() { - super.initState(); - } - - @override - Widget build(BuildContext context) { - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - title: Text("Bar Code Scranner"), - ), - body: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - InkWell( - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - "Scan : ", - style: TextStyle( - color: primaryColor, - fontWeight: FontWeight.bold, - fontSize: 20), - ), - Icon( - Ionicons.ios_qr_scanner, - size: 50, - ), - ], - ), - onTap: () async { - await scan(); - }, - ) - ], - )), - ); - } - - Future scan() async { - var result = await BarcodeScanner.scan(); - print("ScanResult => $result"); - setState(() => scanResult = result); - } -} diff --git a/lib/pages/block_list.dart b/lib/pages/block_list.dart deleted file mode 100644 index 68314c9..0000000 --- a/lib/pages/block_list.dart +++ /dev/null @@ -1,120 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/user_model.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/popup_menu.dart'; -import 'package:fcs/vo/user.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/popupmenu.dart'; -import 'package:fcs/widget/progress.dart'; - -class BlockList extends StatefulWidget { - @override - _BlockListState createState() => _BlockListState(); -} - -class _BlockListState extends State { - final double dotSize = 15.0; - bool _isLoading = false; - PopupMenu selectedChoices = blocklistpopup[0]; - User user = new User(); - - @override - Widget build(BuildContext context) { - var userModel = Provider.of(context); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - title: LocalText(context, 'user.block_list', - color: Colors.white, fontSize: 20), - ), - body: new ListView.builder( - padding: EdgeInsets.only(left: 15, right: 15, top: 15, bottom: 10), - shrinkWrap: true, - itemCount: userModel.getBlockListUsers().length, - itemBuilder: (BuildContext context, int index) { - return Card( - elevation: 10, - color: Colors.white, - child: Row( - children: [ - Expanded( - child: InkWell( - onTap: () {}, - child: new Padding( - padding: const EdgeInsets.symmetric(vertical: 7.0), - child: new Row( - children: [ - new Padding( - padding: new EdgeInsets.symmetric( - horizontal: 32.0 - dotSize / 2), - child: Image.asset( - 'assets/block.png', - width: 50, - height: 50, - color: primaryColor, - )), - new Text( - userModel.getBlockListUsers()[index].name == - null - ? "" - : userModel.getBlockListUsers()[index].name, - style: new TextStyle( - fontSize: 17.0, color: Colors.black), - ), - ], - ), - ), - ), - ), - PopupMenuButton( - elevation: 3.2, - tooltip: 'This is tooltip', - onSelected: _select, - itemBuilder: (BuildContext context) { - this.user = userModel.getBlockListUsers()[index]; - return blocklistpopup.map((PopupMenu choice) { - return PopupMenuItem( - value: choice, - child: Text(choice.status), - ); - }).toList(); - }) - ], - ), - ); - }), - ), - ); - } - - void _select(PopupMenu choice) async { - selectedChoices = choice; - if (choice.index == 1) { - showConfirmDialog(context, "user.unblock.confirm", () { - _unblock(); - }); - } - } - - _unblock() async { - setState(() { - _isLoading = true; - }); - - try { - var userModel = Provider.of(context); - await userModel.unblockPhone(this.user.phoneNumber); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - setState(() { - _isLoading = false; - }); - } - } -} diff --git a/lib/pages/buyer_info.dart b/lib/pages/buyer_info.dart deleted file mode 100644 index 33654b7..0000000 --- a/lib/pages/buyer_info.dart +++ /dev/null @@ -1,281 +0,0 @@ -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/buyer_model.dart'; -import 'package:fcs/model/main_model.dart'; -import 'package:fcs/pages/quota_page.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/util.dart'; -import 'package:fcs/vo/buyer.dart'; -import 'package:fcs/widget/label_widgets.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:fcs/widget/progress.dart'; - -import '../fcs/common/helpers/theme.dart'; -import 'document_log_page.dart'; - -class BuyerInfo extends StatefulWidget { - final Buyer buyer; - const BuyerInfo({this.buyer}); - @override - _BuyerInfoState createState() => _BuyerInfoState(); -} - -class _BuyerInfoState extends State { - var dateFormatter = new DateFormat('dd MMM yyyy - hh:mm a'); - TextEditingController _companyName = new TextEditingController(); - TextEditingController _comAddress = new TextEditingController(); - TextEditingController _numOfShops = new TextEditingController(); - TextEditingController _bizType = new TextEditingController(); - TextEditingController _accountName = new TextEditingController(); - TextEditingController _accountNumber = new TextEditingController(); - - bool _isLoading = false; - Buyer buyer; - - @override - void initState() { - super.initState(); - if (widget.buyer != null) { - buyer = widget.buyer; - Provider.of(context, listen: false) - .loadBuyerProducts(buyer) - .then((b) { - if (mounted) { - setState(() { - buyer = b; - }); - } - }); - } - } - - @override - Widget build(BuildContext context) { - var mainModel = Provider.of(context); - - _companyName.text = buyer.bizName; - _comAddress.text = buyer.bizAddress; - _numOfShops.text = buyer.numOfShops.toString(); - _bizType.text = buyer.bizType; - _accountName.text = buyer.userName; - _accountNumber.text = buyer.userID; - - final dateBox = - labeledText(context, dateFormatter.format(buyer.regDate), "reg.date"); - final accountBox = - labeledText(context, buyer.userName, "buyer.account_name"); - final phoneBox = labeledText(context, buyer.phone, "buyer.phone_number"); - final statusBox = labeledText(context, buyer.status, "reg.status"); - final bizNameBox = labeledText(context, _companyName.text, "reg.biz_name"); - final bizAddressBox = - labeledText(context, _comAddress.text, "reg.biz_address"); - final shopNumberBox = - labeledText(context, _numOfShops.text, "reg.biz_shops"); - final typeBox = labeledText(context, _bizType.text, "buyer.type_biz"); - final dailyQuotaBox = labeledText( - context, formatNumber(buyer.dailyQuota), "reg.quota", - number: true); - final dailyQuotaUsedBox = labeledText( - context, formatNumber(buyer.dailyQuotaUsed), "reg.quota.used", - number: true); - final maxQuotaBox = labeledText( - context, formatNumber(buyer.maxQuota), "reg.max_quota", - number: true); - final maxQuotaUsedBox = labeledText( - context, formatNumber(buyer.maxQuotaUsed), "reg.max_quota.used", - number: true); - final nricFrontBox = - labeledImg(context, buyer.nricFrontUrl, "reg_info.nric_front"); - final nricBackBox = - labeledImg(context, buyer.nricBackUrl, "reg_info.nric_back"); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - title: Text(AppTranslations.of(context).text("buyer.title")), - actions: [ - mainModel.showHistoryBtn() - ? IconButton( - icon: Icon(Icons.history), - onPressed: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => - DocumentLogPage(docID: buyer.id)), - ); - }, - ) - : Container(), - PopupMenuButton( - onSelected: (s) { - if (s == 1) { - showConfirmDialog(context, "buyer.delete.confirm", () { - _delete(); - }); - } else if (s == 2) { - showConfirmDialog(context, "buyer.approve.confirm", () { - _approve(); - }); - } else if (s == 3) { - showCommentDialog(context, (comment) { - _reject(comment); - }); - } else if (s == 4) { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => QuotaPage( - buyer: this.buyer, - isApproved: true, - )), - ); - } - }, - itemBuilder: (context) => [ - PopupMenuItem( - value: 1, - child: Text("Delete"), - ), - PopupMenuItem( - enabled: buyer.isPending(), - value: 2, - child: Text("Approve"), - ), - PopupMenuItem( - enabled: buyer.isPending(), - value: 3, - child: Text("Reject"), - ), - PopupMenuItem( - enabled: buyer.isApproved(), - value: 4, - child: Text("Allocate Quota"), - ), - ], - ), - ], - ), - body: Container( - padding: EdgeInsets.only(left: 10, right: 10, top: 10, bottom: 10), - child: ListView( - children: [ - dateBox, - Divider(), - accountBox, - Divider(), - Row( - children: [ - Padding( - padding: const EdgeInsets.only(right: 8.0), - child: phoneBox, - ), - InkWell( - onTap: () => call(context, buyer.phone), - child: Icon( - Icons.open_in_new, - color: Colors.grey, - size: 15, - ), - ), - ], - ), - Divider(), - statusBox, - Divider(), - bizNameBox, - Divider(), - bizAddressBox, - Divider(), - typeBox, - Divider(), - dailyQuotaBox, - Divider(), - dailyQuotaUsedBox, - Divider(), - maxQuotaBox, - Divider(), - maxQuotaUsedBox, - Divider(), - nricFrontBox, - Divider(), - nricBackBox - ], - ), - ), - ), - ); - } - - _delete() async { - setState(() { - _isLoading = true; - }); - - try { - await Provider.of(context).delete(buyer); - Navigator.pop(context, true); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - setState(() { - _isLoading = false; - }); - } - } - - _approve() async { - var _buyer = await Navigator.push( - context, - MaterialPageRoute( - builder: (context) => QuotaPage( - buyer: this.buyer, - isApproved: false, - )), - ); - if (_buyer == null) return; - - setState(() { - _isLoading = true; - }); - - try { - this.buyer.dailyQuota = _buyer.dailyQuota; - this.buyer.maxQuota = _buyer.maxQuota; - await Provider.of(context).approve(this.buyer); - Navigator.pop(context, true); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - setState(() { - _isLoading = false; - }); - } - } - - _reject(comment) async { - if (comment == null || comment == "") { - showMsgDialog(context, "Error", "Please enter comment!"); - return; - } - buyer.comment = comment; - setState(() { - _isLoading = true; - }); - - try { - await Provider.of(context).reject(buyer); - Navigator.pop(context, true); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - setState(() { - _isLoading = false; - }); - } - } -} diff --git a/lib/pages/buyer_list.dart b/lib/pages/buyer_list.dart deleted file mode 100644 index 9e85e5c..0000000 --- a/lib/pages/buyer_list.dart +++ /dev/null @@ -1,208 +0,0 @@ -import 'package:provider/provider.dart'; -import 'package:fcs/model/buyer_model.dart'; -import 'package:fcs/pages/search_page.dart'; -import 'package:fcs/vo/buyer.dart'; -import 'package:fcs/vo/popup_menu.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:fcs/widget/popupmenu.dart'; - -import 'package:flutter/material.dart'; -import 'package:fcs/widget/progress.dart'; - -import '../fcs/common/helpers/theme.dart'; -import 'buyer_list_row.dart'; - -class BuyerList extends StatefulWidget { - @override - _BuyerListState createState() => _BuyerListState(); -} - -class _BuyerListState extends State { - Buyer buyer; - int _selectedIndex = 0; - bool _isLoading = false; - int _selectedSortIndex; - - @override - void initState() { - super.initState(); - var buyerModel = Provider.of(context, listen: false); - var index = buyerModel.popupMenu.index; - _selectedIndex = index; - var sortIndexndex = buyerModel.sortMenu.index; - _selectedSortIndex = sortIndexndex; - } - - @override - void dispose() { - super.dispose(); - } - - @override - Widget build(BuildContext context) { - BuyerModel buyerModel = Provider.of(context); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - title: Text(AppTranslations.of(context).text("buyer.title")), - actions: [ - IconButton( - icon: Icon( - Icons.search, - color: Colors.white, - ), - iconSize: 30, - onPressed: () => showPlacesSearch(context), - ), - PopupMenuButton( - elevation: 3.2, - onSelected: (selected) { - setState(() { - this._selectedSortIndex = selected.index; - this._selectedIndex = 0; - buyerModel.filterSorting( - _selectedSortIndex, this._selectedIndex); - }); - }, - icon: Container( - width: 30, - height: 30, - decoration: new BoxDecoration( - shape: BoxShape.circle, - color: Colors.white, - ), - child: Stack( - fit: StackFit.expand, - children: [ - Icon( - Icons.sort, - color: primaryColor, - ), - _selectedSortIndex != null - ? Positioned( - bottom: 0, - right: 0, - child: Container( - width: 10, - height: 10, - decoration: new BoxDecoration( - shape: BoxShape.circle, - color: secondaryColor, - ), - ), - ) - : Container() - ], - )), - itemBuilder: (BuildContext context) { - return userMenu.map((PopupMenu choice) { - return PopupMenuItem( - value: choice, - child: Container( - padding: EdgeInsets.only(left: 8), - child: Row( - children: [ - Text(choice.status), - SizedBox( - width: 10, - ), - _selectedSortIndex != null && - _selectedSortIndex == choice.index - ? Icon( - Icons.check, - color: Colors.grey, - ) - : Container(), - ], - ), - ), - ); - }).toList(); - }), - PopupMenuButton( - elevation: 3.2, - onSelected: (selected) { - String status; - setState(() { - this._selectedIndex = selected.index; - this._selectedSortIndex = null; - if (selected.status == 'All') { - status = null; - } else { - status = selected.status; - } - buyerModel.filterStatus( - status, _selectedIndex, this._selectedSortIndex); - }); - }, - icon: Container( - width: 30, - height: 30, - decoration: new BoxDecoration( - shape: BoxShape.circle, - color: Colors.white, - ), - child: Stack( - fit: StackFit.expand, - children: [ - Icon( - Icons.filter_list, - color: primaryColor, - ), - _selectedIndex != 0 - ? Positioned( - bottom: 0, - right: 0, - child: Container( - width: 10, - height: 10, - decoration: new BoxDecoration( - shape: BoxShape.circle, - color: secondaryColor, - ), - ), - ) - : Container() - ], - )), - itemBuilder: (BuildContext context) { - return buyerStatusMenu.map((PopupMenu choice) { - return PopupMenuItem( - value: choice, - child: Row( - children: [ - Text(choice.status), - SizedBox( - width: 10, - ), - _selectedIndex != null && - _selectedIndex == choice.index - ? Icon( - Icons.check, - color: Colors.grey, - ) - : Container(), - ], - ), - ); - }).toList(); - }), - ], - ), - body: new ListView.builder( - scrollDirection: Axis.vertical, - padding: EdgeInsets.only(top: 15), - shrinkWrap: true, - itemCount: buyerModel.buyers.length, - itemBuilder: (BuildContext context, int index) { - return BuyerListRow( - buyer: buyerModel.buyers[index], - ); - }), - ), - ); - } -} diff --git a/lib/pages/buyer_list_row.dart b/lib/pages/buyer_list_row.dart deleted file mode 100644 index a8cbbf3..0000000 --- a/lib/pages/buyer_list_row.dart +++ /dev/null @@ -1,106 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/buyer_model.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/buyer.dart'; - -import 'buyer_info.dart'; - -class BuyerListRow extends StatefulWidget { - final Buyer buyer; - const BuyerListRow({this.buyer}); - - @override - _BuyerListRowState createState() => _BuyerListRowState(); -} - -class _BuyerListRowState extends State { - final double dotSize = 15.0; - Buyer _buyer = new Buyer(); - - @override - void initState() { - super.initState(); - BuyerModel buyerModel = Provider.of(context, listen: false); - if (widget.buyer != null) { - buyerModel.buyers.forEach((b) { - if (widget.buyer.id == b.id) { - _buyer = b; - } - }); - } - } - - @override - Widget build(BuildContext context) { - return Container( - padding: EdgeInsets.only(left: 15, right: 15), - child: Card( - elevation: 10, - color: Colors.white, - child: InkWell( - onTap: () { - Navigator.push( - context, - MaterialPageRoute(builder: (context) => BuyerInfo(buyer: _buyer)), - ); - }, - child: Row( - children: [ - Expanded( - child: new Padding( - padding: const EdgeInsets.symmetric(vertical: 16.0), - child: new Row( - children: [ - new Padding( - padding: new EdgeInsets.symmetric( - horizontal: 32.0 - dotSize / 2), - child: Image.asset( - "assets/buyer.png", - width: 40, - height: 40, - color: primaryColor, - ), - ), - new Expanded( - child: new Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - new Text( - _buyer.userName == null ? '' : _buyer.userName, - style: new TextStyle( - fontSize: 15.0, color: Colors.black), - ), - new Text( - _buyer.bizName == null ? "" : _buyer.bizName, - style: new TextStyle( - fontSize: 13.0, color: Colors.grey), - ), - new Text( - _buyer.phone == null ? "" : _buyer.phone, - style: new TextStyle( - fontSize: 13.0, color: Colors.grey), - ), - ], - ), - ), - ], - ), - ), - ), - Row( - children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: getStatus(_buyer.status), - ), - ], - ) - ], - ), - ), - ), - ); - } -} diff --git a/lib/fcs/common/pages/buying_instruction/buying_online.dart b/lib/pages/buying_instruction/buying_online.dart similarity index 81% rename from lib/fcs/common/pages/buying_instruction/buying_online.dart rename to lib/pages/buying_instruction/buying_online.dart index 3dee003..fc7efce 100644 --- a/lib/fcs/common/pages/buying_instruction/buying_online.dart +++ b/lib/pages/buying_instruction/buying_online.dart @@ -1,9 +1,10 @@ -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/fcs/common/pages/model/main_model.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/fcs/common/pages/widgets/display_text.dart'; -import 'package:fcs/fcs/common/pages/widgets/fcs_id_icon.dart'; -import 'package:fcs/fcs/common/pages/widgets/local_text.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/main/model/main_model.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/widgets/display_text.dart'; +import 'package:fcs/pages/widgets/fcs_id_icon.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; @@ -28,7 +29,7 @@ class _BuyingOnlinePagetate extends State final phoneNumberBox = DisplayText( text: mainModel.user.phone, - labelText: getLocalString(context, "contact.phone"), + labelTextKey: "contact.phone", iconData: Icons.location_on, ); final nameBox = Center( @@ -38,12 +39,12 @@ class _BuyingOnlinePagetate extends State )); final fcsIdBox = DisplayText( text: mainModel.user.fcsID, - labelText: getLocalString(context, "customer.fcs.id"), + labelTextKey: "customer.fcs.id", icon: FcsIDIcon(), ); final shippingAddressBox = DisplayText( text: mainModel.setting.usaAddress, - labelText: getLocalString(context, "profile.usa.shipping.address"), + labelTextKey: "profile.usa.shipping.address", iconData: Icons.location_on, ); final instructionBox = Container( @@ -67,7 +68,7 @@ class _BuyingOnlinePagetate extends State centerTitle: true, leading: new IconButton( icon: new Icon( - Icons.close, + CupertinoIcons.back, color: primaryColor, ), onPressed: () => Navigator.of(context).pop(), @@ -113,11 +114,12 @@ class _BuyingOnlinePagetate extends State controller: _tabController, children: [ Container( - child: - Image.asset('assets/Fullname.png', fit: BoxFit.contain), + child: Image.asset('assets/buying_online_with_full_name.png', + fit: BoxFit.contain), ), Container( - child: Image.asset('assets/FirstName&LastName.png', + child: Image.asset( + 'assets/buying_online_with_first_last_name.png', fit: BoxFit.contain), ), ], diff --git a/lib/pages/buying_online.dart b/lib/pages/buying_online.dart deleted file mode 100644 index b02f050..0000000 --- a/lib/pages/buying_online.dart +++ /dev/null @@ -1,216 +0,0 @@ -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/vo/manual.dart'; -import 'package:fcs/widget/bottom_up_page_route.dart'; -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/main_model.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/progress.dart'; - -import '../fcs/common/helpers/theme.dart'; -import '../widget/label_widgets.dart'; -import '../widget/local_text.dart'; -import 'instruction.dart'; -import 'manual/manual_page.dart'; - -class BuyingOnlinePage extends StatefulWidget { - @override - _BuyingOnlinePagetate createState() => _BuyingOnlinePagetate(); -} - -class _BuyingOnlinePagetate extends State - with SingleTickerProviderStateMixin { - bool _isLoading = false; - List images = [ - 'assets/Fullname.jpeg', - 'assets/FirstName&LastName.jpeg' - ]; - TabController _tabController; - - @override - void initState() { - _tabController = TabController(vsync: this, length: 2); - super.initState(); - } - - @override - Widget build(BuildContext context) { - MainModel mainModel = Provider.of(context); - - final phoneBox = - labeledText(context, mainModel.customer.phoneNumber, "user.phone"); - final fcsIdBox = Container( - padding: EdgeInsets.only(top: 15), - child: labeledText(context, mainModel.customer.fcsID, "user.fcs_id")); - final shippingAddressBox = Container( - padding: EdgeInsets.only(top: 15), - child: labeledText(context, mainModel.customer.shippingAddress, - "user.shipping_address")); - final deliveryAddressBox = Container( - padding: EdgeInsets.only(top: 15), - child: labeledText(context, mainModel.customer.deliveryAddress, - "user.deliveryAddress")); - - final instructionBox = Container( - padding: EdgeInsets.only(left: 10, top: 30, bottom: 10), - child: Center( - child: Wrap( - children: [ - LocalText( - context, - 'user.buying_instruction', - color: labelColor, - fontSize: 15, - ) - ], - ), - ), - ); - - final amazonbutton = Container( - padding: EdgeInsets.only(left: 10, right: 10, top: 10), - child: Container( - height: 45.0, - decoration: BoxDecoration( - color: primaryColor, - shape: BoxShape.rectangle, - // borderRadius: BorderRadius.all(Radius.circular(10.0)) - ), - child: ButtonTheme( - minWidth: 900.0, - height: 100.0, - child: FlatButton( - onPressed: () { - Navigator.of(context).push(BottomUpPageRoute(InstructionPage( - name: 'Amazon', - image: "assets/amazon_ins.png", - ))); - }, - child: LocalText( - context, - 'buy.amazon', - color: Colors.white, - fontSize: 16, - fontWeight: FontWeight.bold, - ), - ), - ), - ), - ); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - centerTitle: true, - leading: new IconButton( - icon: new Icon(Icons.close), - onPressed: () => Navigator.of(context).pop(), - ), - title: LocalText( - context, - "buy_online.title", - fontSize: 20, - color: Colors.white, - ), - backgroundColor: primaryColor, - ), - body: ListView( - shrinkWrap: true, - padding: EdgeInsets.only(top: 10, left: 10, right: 10), - children: [ - nameWidget(mainModel.customer.name), - phoneWidget(context, mainModel.customer.phoneNumber), - Row( - children: [ - SizedBox( - width: 25, - height: 25, - child: FittedBox( - child: Image.asset("assets/logo.jpg"), - fit: BoxFit.fill, - ), - ), - fcsIdBox, - Padding( - padding: const EdgeInsets.only(left: 7.0, top: 50), - child: Icon( - Icons.content_copy, - color: Colors.grey, - ), - ) - ], - ), - Row( - children: [ - Icon(Icons.location_on), - shippingAddressBox, - Padding( - padding: const EdgeInsets.only(left: 7.0, top: 50), - child: Icon( - Icons.content_copy, - color: Colors.grey, - ), - ) - ], - ), - - // deliveryAddressBox, - instructionBox, - new Container( - decoration: new BoxDecoration(color: Colors.white), - child: new TabBar( - // indicatorColor: primaryColor, - labelColor: primaryColor, - labelStyle: TextStyle(fontWeight: FontWeight.bold), - unselectedLabelColor: Colors.grey, - controller: _tabController, - tabs: [ - new Tab( - text: 'With FULL NAME', - ), - new Tab( - text: 'With FIRST NAME&\nLAST NAME', - ), - ], - ), - ), - new Container( - padding: EdgeInsets.only(top: 10), - height: 500, - width: 500, - child: new TabBarView( - controller: _tabController, - children: [ - Container( - child: - Image.asset('assets/Fullname.png', fit: BoxFit.contain), - ), - Container( - child: Image.asset('assets/FirstName&LastName.png', - fit: BoxFit.contain), - ), - ], - ), - ), - // Container( - // height: 500, - // width: 500, - // child: ListView.builder( - // itemCount: images.length, - // scrollDirection: Axis.horizontal, - // itemBuilder: (context, index) { - // return Container( - // padding: EdgeInsets.only(left: 0, right: 5, top: 5), - // child: Image.asset(images[index], fit: BoxFit.contain), - // ); - // }), - // ), - - SizedBox(height: 10) - ], - ), - ), - ); - } -} diff --git a/lib/pages/calculate_shipment_cost_editor.dart b/lib/pages/calculate_shipment_cost_editor.dart deleted file mode 100644 index a78d088..0000000 --- a/lib/pages/calculate_shipment_cost_editor.dart +++ /dev/null @@ -1,257 +0,0 @@ -import 'package:fcs/model/pickup_model.dart'; -import 'package:fcs/vo/pickup.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; - -import 'package:flutter/material.dart'; -import 'package:fcs/widget/progress.dart'; - -import '../fcs/common/helpers/theme.dart'; - -class CalculateShipmentCostEditor extends StatefulWidget { - final PickUp pickUp; - CalculateShipmentCostEditor({this.pickUp}); - - @override - _CalculateShipmentCostEditorState createState() => - _CalculateShipmentCostEditorState(); -} - -class _CalculateShipmentCostEditorState - extends State { - TextEditingController _addressEditingController = new TextEditingController(); - TextEditingController _fromTimeEditingController = - new TextEditingController(); - TextEditingController _toTimeEditingController = new TextEditingController(); - TextEditingController _noOfPackageEditingController = - new TextEditingController(); - TextEditingController _weightEditingController = new TextEditingController(); - - PickUp _pickUp; - bool _isLoading = false; - - @override - void initState() { - super.initState(); - if (widget.pickUp != null) { - _pickUp = widget.pickUp; - _addressEditingController.text = _pickUp.address; - _fromTimeEditingController.text = _pickUp.fromTime; - _toTimeEditingController.text = _pickUp.toTime; - _noOfPackageEditingController.text = _pickUp.numberOfPackage.toString(); - _weightEditingController.text = _pickUp.weight.toString(); - } - } - - @override - void dispose() { - super.dispose(); - } - - @override - Widget build(BuildContext context) { - var pickupModel = Provider.of(context); - - final pickUpAddress = Container( - child: TextFormField( - maxLines: null, - controller: _addressEditingController, - cursorColor: primaryColor, - style: textStyle, - decoration: new InputDecoration( - labelText: 'Pickup Address', - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - ), - )); - - final pickupTime = Container( - height: 50.0, - child: Row(children: [ - Container( - width: 70.0, - child: TextFormField( - controller: _fromTimeEditingController, - cursorColor: primaryColor, - textAlign: TextAlign.left, - decoration: InputDecoration( - contentPadding: EdgeInsets.all(10.0), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide(color: Colors.grey[300], width: 2), - ), - focusedBorder: OutlineInputBorder( - borderSide: const BorderSide(color: primaryColor, width: 2.0), - ), - ), - )), - Padding( - padding: const EdgeInsets.all(8.0), - child: Text(' to '), - ), - Container( - width: 70.0, - child: TextFormField( - controller: _toTimeEditingController, - cursorColor: primaryColor, - textAlign: TextAlign.left, - decoration: InputDecoration( - contentPadding: EdgeInsets.all(10.0), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide(color: Colors.grey[300], width: 2), - ), - focusedBorder: OutlineInputBorder( - borderSide: const BorderSide(color: primaryColor, width: 2.0), - ), - ), - )), - ]), - ); - - final noOfPackageBox = Container( - height: 50.0, - child: Row(children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: Text('Number of Packages '), - ), - Expanded( - child: TextFormField( - controller: _noOfPackageEditingController, - cursorColor: primaryColor, - textAlign: TextAlign.left, - decoration: InputDecoration( - contentPadding: EdgeInsets.all(10.0), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide(color: Colors.grey[300], width: 2), - ), - focusedBorder: OutlineInputBorder( - borderSide: const BorderSide(color: primaryColor, width: 2.0), - ), - ), - )), - ]), - ); - - final weightBox = Container( - height: 50.0, - child: Row(children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: Text('Total Weight (lb) '), - ), - Expanded( - child: TextFormField( - controller: _weightEditingController, - cursorColor: primaryColor, - textAlign: TextAlign.left, - decoration: InputDecoration( - contentPadding: EdgeInsets.all(10.0), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide(color: Colors.grey[300], width: 2), - ), - focusedBorder: OutlineInputBorder( - borderSide: const BorderSide(color: primaryColor, width: 2.0), - ), - ), - )), - ]), - ); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - title: Text(AppTranslations.of(context).text("pickup.edit.title")), - ), - body: Card( - child: Column( - children: [ - Expanded( - child: Padding( - padding: const EdgeInsets.all(20.0), - child: ListView(children: [ - Text( - "U Aung Zaw", - style: TextStyle(fontSize: 15.0), - ), - Text( - "+82054857695", - style: TextStyle(fontSize: 15.0), - ), - pickUpAddress, - SizedBox(height: 15), - Text('Pickup Time'), - SizedBox(height: 15), - pickupTime, - SizedBox(height: 15), - noOfPackageBox, - SizedBox(height: 15), - weightBox - ]), - )), - widget.pickUp == null - ? Align( - alignment: Alignment.bottomCenter, - child: Center( - child: Container( - width: 250, - child: FlatButton( - shape: new RoundedRectangleBorder( - borderRadius: new BorderRadius.circular(10)), - child: Text('Request'), - color: primaryColor, - textColor: Colors.white, - onPressed: () { - Navigator.pop(context); - }, - ), - ))) - : Container( - child: Column( - children: [ - Align( - alignment: Alignment.bottomCenter, - child: Center( - child: Container( - width: 250, - child: FlatButton( - shape: new RoundedRectangleBorder( - borderRadius: - new BorderRadius.circular(10)), - child: Text('Pickuped'), - color: primaryColor, - textColor: Colors.white, - onPressed: () { - Navigator.pop(context); - }, - ), - ))), - Align( - alignment: Alignment.bottomCenter, - child: Center( - child: Container( - width: 250, - child: FlatButton( - shape: new RoundedRectangleBorder( - borderRadius: - new BorderRadius.circular(10)), - child: Text('Cancel'), - color: primaryColor, - textColor: Colors.white, - onPressed: () { - Navigator.pop(context); - }, - ), - ))) - ], - )) - ], - ), - ), - ), - ); - } -} diff --git a/lib/pages/carton/cargo_type_editor.dart b/lib/pages/carton/cargo_type_editor.dart new file mode 100644 index 0000000..b73f73b --- /dev/null +++ b/lib/pages/carton/cargo_type_editor.dart @@ -0,0 +1,117 @@ +import 'package:fcs/domain/entities/cargo_type.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/main/model/main_model.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/rates/model/shipment_rate_model.dart'; +import 'package:fcs/pages/widgets/input_text.dart'; +import 'package:fcs/pages/widgets/local_dropdown.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:provider/provider.dart'; + +class CargoTypeEditor extends StatefulWidget { + final CargoType cargo; + CargoTypeEditor({this.cargo}); + + @override + _CargoTypeEditorState createState() => _CargoTypeEditorState(); +} + +class _CargoTypeEditorState extends State { + TextEditingController _weightController = new TextEditingController(); + + bool _isLoading = false; + CargoType _cargo; + + @override + void initState() { + super.initState(); + if (widget.cargo != null) { + _cargo = widget.cargo; + _weightController.text = _cargo.weight.toString(); + } else { + _loadDefalut(); + } + } + + _loadDefalut() { + ShipmentRateModel shipmentRateModel = + Provider.of(context, listen: false); + _cargo = shipmentRateModel.rate.defaultCargoType.clone(); + } + + @override + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + ShipmentRateModel shipmentRateModel = + Provider.of(context); + List cargos = shipmentRateModel.rate.cargoTypes; + + final rateBox = InputText( + labelTextKey: 'cargo.weight', + iconData: FontAwesomeIcons.weightHanging, + textInputType: TextInputType.number, + controller: _weightController); + + var cargoTypeBox = LocalDropdown( + callback: (v) { + setState(() { + _cargo = v; + }); + }, + labelKey: "cargo.type", + iconData: Icons.text_format, + selectedValue: _cargo, + values: cargos, + ); + + final saveBtn = fcsButton( + context, + getLocalString(context, 'box.cargo.save.btn'), + callack: () { + _cargo.weight = double.tryParse(_weightController.text) ?? 0; + Navigator.pop(context, _cargo); + }, + ); + return LocalProgress( + inAsyncCall: _isLoading, + child: Scaffold( + appBar: AppBar( + centerTitle: true, + leading: new IconButton( + icon: + new Icon(CupertinoIcons.back, color: primaryColor, size: 30), + onPressed: () => Navigator.of(context).pop(), + ), + shadowColor: Colors.transparent, + backgroundColor: Colors.white, + title: LocalText( + context, + "cargo.form.title", + fontSize: 20, + color: primaryColor, + )), + body: Container( + padding: EdgeInsets.all(18), + child: ListView( + shrinkWrap: true, + children: [ + cargoTypeBox, + rateBox, + SizedBox(height: 40), + saveBtn, + SizedBox(height: 20), + ], + ), + ), + ), + ); + } +} diff --git a/lib/pages/carton/carton_cargo_table.dart b/lib/pages/carton/carton_cargo_table.dart new file mode 100644 index 0000000..3b49332 --- /dev/null +++ b/lib/pages/carton/carton_cargo_table.dart @@ -0,0 +1,118 @@ +import 'package:fcs/domain/entities/cargo_type.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/my_data_table.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +import 'cargo_type_editor.dart'; + +typedef OnAdd(CargoType cargoType); +typedef OnRemove(CargoType cargoType); + +class CargoTable extends StatelessWidget { + final List cargoTypes; + final OnAdd onAdd; + final OnRemove onRemove; + + const CargoTable({Key key, this.cargoTypes, this.onAdd, this.onRemove}) + : super(key: key); + + @override + Widget build(BuildContext context) { + return MyDataTable( + headingRowHeight: 40, + columns: [ + MyDataColumn( + label: LocalText( + context, + "cargo.type", + color: Colors.grey, + ), + ), + MyDataColumn( + label: LocalText( + context, + "cargo.weight", + color: Colors.grey, + ), + ), + ], + rows: getCargoRows(context), + ); + } + + List getCargoRows(BuildContext context) { + if (cargoTypes == null) { + return []; + } + double total = 0; + var rows = cargoTypes.map((c) { + total += c.weight; + return MyDataRow( + onSelectChanged: (bool selected) async { + CargoType cargo = await Navigator.push( + context, + CupertinoPageRoute( + builder: (context) => CargoTypeEditor( + cargo: c, + ))); + if (onAdd != null) onAdd(cargo); + }, + cells: [ + MyDataCell(new Text( + c.name == null ? "" : c.name, + style: textStyle, + )), + MyDataCell( + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text(c.weight == null ? "0" : c.weight.toString(), + style: textStyle), + onRemove == null + ? SizedBox( + width: 50, + ) + : IconButton( + icon: Icon( + Icons.remove_circle, + color: primaryColor, + ), + onPressed: () { + if (onRemove != null) onRemove(c); + }) + ], + ), + ), + ], + ); + }).toList(); + + var totalRow = MyDataRow( + onSelectChanged: (bool selected) {}, + cells: [ + MyDataCell(Align( + alignment: Alignment.centerRight, + child: LocalText( + context, + "shipment.cargo.total", + color: Colors.black87, + fontWeight: FontWeight.bold, + ), + )), + MyDataCell( + Padding( + padding: const EdgeInsets.only(right: 48.0), + child: Align( + alignment: Alignment.centerRight, + child: Text(total.toString(), + style: TextStyle(fontWeight: FontWeight.bold))), + ), + ), + ], + ); + rows.add(totalRow); + return rows; + } +} diff --git a/lib/pages/carton/carton_editor.dart b/lib/pages/carton/carton_editor.dart new file mode 100644 index 0000000..a2746dc --- /dev/null +++ b/lib/pages/carton/carton_editor.dart @@ -0,0 +1,512 @@ +import 'package:fcs/domain/constants.dart'; +import 'package:fcs/domain/entities/carton.dart'; +import 'package:fcs/domain/entities/cargo_type.dart'; +import 'package:fcs/domain/entities/fcs_shipment.dart'; +import 'package:fcs/domain/entities/package.dart'; +import 'package:fcs/domain/entities/user.dart'; +import 'package:fcs/domain/vo/delivery_address.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/localization/app_translations.dart'; +import 'package:fcs/pages/carton/carton_cargo_table.dart'; +import 'package:fcs/pages/carton/carton_mix_table.dart'; +import 'package:fcs/pages/carton/carton_package_table.dart'; +import 'package:fcs/pages/delivery_address/delivery_address_row.dart'; +import 'package:fcs/pages/delivery_address/model/delivery_address_model.dart'; +import 'package:fcs/pages/fcs_shipment/model/fcs_shipment_model.dart'; +import 'package:fcs/pages/main/model/language_model.dart'; +import 'package:fcs/pages/main/model/main_model.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/package/model/package_model.dart'; +import 'package:fcs/pages/rates/model/shipment_rate_model.dart'; +import 'package:fcs/pages/user_search/user_serach.dart'; +import 'package:fcs/pages/widgets/bottom_up_page_route.dart'; +import 'package:fcs/pages/widgets/defalut_delivery_address.dart'; +import 'package:fcs/pages/widgets/delivery_address_selection.dart'; +import 'package:fcs/pages/widgets/display_text.dart'; +import 'package:fcs/pages/widgets/fcs_id_icon.dart'; +import 'package:fcs/pages/widgets/length_picker.dart'; +import 'package:fcs/pages/widgets/local_button.dart'; +import 'package:fcs/pages/widgets/local_dropdown.dart'; +import 'package:fcs/pages/widgets/local_radio_buttons.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/local_title.dart'; +import 'package:fcs/pages/widgets/my_data_table.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_icons/flutter_icons.dart'; +import 'package:provider/provider.dart'; +import 'cargo_type_editor.dart'; +import 'model/carton_model.dart'; +import 'widgets.dart'; + +class CartonEditor extends StatefulWidget { + final Carton box; + CartonEditor({this.box}); + + @override + _CartonEditorState createState() => _CartonEditorState(); +} + +class _CartonEditorState extends State { + TextEditingController _widthController = new TextEditingController(); + TextEditingController _heightController = new TextEditingController(); + TextEditingController _lengthController = new TextEditingController(); + + Carton _carton; + bool _isLoading = false; + bool _isNew; + DeliveryAddress _deliveryAddress = new DeliveryAddress(); + User _user; + String _selectedCartonType; + double volumetricRatio = 0; + double shipmentWeight = 0; + FcsShipment _fcsShipment; + List _fcsShipments; + Carton _mixCarton; + List _mixCartons; + + @override + void initState() { + super.initState(); + + //for shipment weight + volumetricRatio = Provider.of(context, listen: false) + .rate + .volumetricRatio; + _lengthController.addListener(_calShipmentWeight); + _widthController.addListener(_calShipmentWeight); + _heightController.addListener(_calShipmentWeight); + + if (widget.box != null) { + _carton = widget.box; + _deliveryAddress = _carton.deliveryAddress; + _widthController.text = _carton.width.toString(); + _heightController.text = _carton.height.toString(); + _lengthController.text = _carton.length.toString(); + _selectedCartonType = _carton.cartonType; + _isNew = false; + _user = User(fcsID: _carton.fcsID, name: _carton.userName); + _loadPackages(); + } else { + _carton = Carton( + cargoTypes: [], + packages: [], + ); + _lengthController.text = "12"; + _widthController.text = "12"; + _heightController.text = "12"; + _isNew = true; + _selectedCartonType = carton_from_packages; + _loadFcsShipments(); + } + } + + _loadFcsShipments() async { + FcsShipmentModel fcsShipmentModel = + Provider.of(context, listen: false); + var fcsShipments = await fcsShipmentModel.getActiveFcsShipments(); + var fcsShipment = fcsShipments + .firstWhere((e) => e.id == _carton.fcsShipmentID, orElse: () => null); + setState(() { + _fcsShipments = fcsShipments; + _fcsShipment = fcsShipment; + }); + } + + _loadPackages() async { + if (_user == null) return; + PackageModel packageModel = + Provider.of(context, listen: false); + List packages = await packageModel.getPackages( + _user.id, [package_processed_status, package_packed_status]); + if (_isNew) { + String prevCompare; + packages.forEach((p) { + String compare = (p.deliveryAddress?.fullName ?? "") + + (p.deliveryAddress?.phoneNumber ?? ""); + if (prevCompare != null && compare == prevCompare) { + p.isChecked = true; + } else { + p.isChecked = false; + } + if (prevCompare == null) { + p.isChecked = true; + prevCompare = compare; + } + }); + } else { + packages.forEach((p) { + if (_carton.packages.contains(p)) { + p.isChecked = _carton.packages.firstWhere((cp) => cp == p).isChecked; + } else { + p.isChecked = false; + } + }); + } + + setState(() { + _carton.packages = packages; + }); + _populateDeliveryAddress(); + } + + _populateDeliveryAddress() { + if (_carton.packages == null) return; + var d = _carton.packages + .firstWhere((p) => p.isChecked && p.deliveryAddress != null, + orElse: () => null) + ?.deliveryAddress; + setState(() { + _deliveryAddress = d; + }); + } + + _loadMixCartons() async { + if (_fcsShipment == null || _fcsShipment.id == null) return; + if (_selectedCartonType != carton_small_bag) return; + + CartonModel cartonModel = Provider.of(context, listen: false); + List cartons = + await cartonModel.getMixCartonsByFcsShipment(_fcsShipment.id); + setState(() { + _mixCartons = cartons; + }); + } + + _calShipmentWeight() { + double l = double.parse(_lengthController.text, (s) => 0); + double w = double.parse(_widthController.text, (s) => 0); + double h = double.parse(_heightController.text, (s) => 0); + setState(() { + shipmentWeight = l * w * h / volumetricRatio; + }); + } + + @override + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + var boxModel = Provider.of(context); + bool isMixBox = _selectedCartonType == carton_mix_box; + bool isSmallBag = _selectedCartonType == carton_small_bag; + final shipmentBox = DisplayText( + text: _carton.fcsShipmentNumber, + labelTextKey: "box.fcs_shipment_num", + iconData: Ionicons.ios_airplane, + ); + final mixCartonNumberBox = DisplayText( + text: _carton.mixCartonNumber, + labelTextKey: "box.mix.carton", + iconData: MaterialCommunityIcons.package, + ); + var fcsShipmentsBox = LocalDropdown( + callback: (v) { + setState(() { + _fcsShipment = v; + }); + _loadMixCartons(); + }, + labelKey: "shipment.pack.fcs.shipment", + iconData: Ionicons.ios_airplane, + display: (u) => u.shipmentNumber, + selectedValue: _fcsShipment, + values: _fcsShipments, + ); + + var mixCartonsBox = LocalDropdown( + callback: (v) { + setState(() { + _mixCarton = v; + }); + }, + labelKey: "box.mix.carton", + iconData: MaterialCommunityIcons.package, + display: (u) => u.cartonNumber, + selectedValue: _mixCarton, + values: _mixCartons, + ); + + final fcsIDBox = Row( + children: [ + Expanded( + child: DisplayText( + text: _user?.fcsID ?? "", + labelTextKey: "box.fcs.id", + icon: FcsIDIcon(), + )), + _isNew + ? IconButton( + icon: Icon(Icons.search, color: primaryColor), + onPressed: () => searchUser(context, callbackUserSelect: (u) { + setState(() { + this._user = u; + _loadPackages(); + }); + })) + : Container(), + ], + ); + + final namebox = DisplayText( + text: _user?.name ?? "", + labelTextKey: "box.name", + iconData: Icons.person, + ); + + final lengthBox = LengthPicker( + controller: _lengthController, + lableKey: "box.length", + ); + final widthBox = LengthPicker( + controller: _widthController, + lableKey: "box.width", + ); + final heightBox = LengthPicker( + controller: _heightController, + lableKey: "box.height", + ); + + final dimBox = Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(right: 8.0), + child: Icon(FontAwesome.arrow_circle_right, color: primaryColor), + ), + SizedBox(child: lengthBox, width: 80), + SizedBox(child: widthBox, width: 80), + SizedBox(child: heightBox, width: 80), + ], + ); + + final shipmentWeightBox = DisplayText( + text: shipmentWeight != null ? shipmentWeight.toStringAsFixed(0) : "", + labelTextKey: "box.shipment_weight", + iconData: MaterialCommunityIcons.weight, + ); + + final createBtn = LocalButton( + textKey: "box.create.btn", + callBack: _save, + ); + + final saveBtn = LocalButton( + textKey: "box.cargo.save.btn", + callBack: _save, + ); + + final cartonTypeBox = LocalRadioButtons( + readOnly: !_isNew, + values: boxModel.cartonTypes, + selectedValue: _selectedCartonType, + callback: (v) { + setState(() { + _selectedCartonType = v; + }); + }); + + final cargoTableTitleBox = LocalTitle( + textKey: "box.cargo.type", + trailing: IconButton( + icon: Icon( + Icons.add_circle, + color: primaryColor, + ), + onPressed: () async { + CargoType cargo = await Navigator.push(context, + CupertinoPageRoute(builder: (context) => CargoTypeEditor())); + _addCargo(cargo); + }), + ); + + final cargoTableBox = CargoTable( + cargoTypes: _carton.cargoTypes, + onAdd: (c) => _addCargo(c), + onRemove: (c) => _removeCargo(c), + ); + + return LocalProgress( + inAsyncCall: _isLoading, + child: Scaffold( + appBar: AppBar( + centerTitle: true, + leading: new IconButton( + icon: new Icon(CupertinoIcons.back, color: primaryColor, size: 30), + onPressed: () => Navigator.of(context).pop(), + ), + shadowColor: Colors.transparent, + backgroundColor: Colors.white, + title: _isNew + ? LocalText( + context, + "boxes.create.title", + fontSize: 20, + color: primaryColor, + ) + : LocalText( + context, + "box.edit.title", + fontSize: 20, + color: primaryColor, + ), + ), + body: Padding( + padding: const EdgeInsets.all(8.0), + child: ListView( + shrinkWrap: true, + children: [ + _isNew + ? Container() + : Center(child: getCartonNumberStatus(context, _carton)), + LocalTitle(textKey: "box.type.title"), + cartonTypeBox, + LocalTitle(textKey: "box.shipment_info"), + _isNew ? fcsShipmentsBox : shipmentBox, + isSmallBag + ? _isNew ? mixCartonsBox : mixCartonNumberBox + : Container(), + ...(isMixBox + ? [ + // CartonMixTable( + // cartons: _carton.cartons, + // onSelect: (c, check) { + // setState(() { + // c.isChecked = check; + // }); + // }, + // ) + ] + : [ + fcsIDBox, + namebox, + CartonPackageTable( + packages: _carton.packages, + onSelect: (p, checked) { + if (checked && + _deliveryAddress != null && + p.deliveryAddress?.id != _deliveryAddress.id) { + return; + } + setState(() { + p.isChecked = checked; + }); + _populateDeliveryAddress(); + }, + ), + cargoTableTitleBox, + cargoTableBox, + isSmallBag + ? Container() + : LocalTitle(textKey: "box.dimension"), + isSmallBag ? Container() : dimBox, + isSmallBag ? Container() : shipmentWeightBox, + LocalTitle(textKey: "box.delivery_address"), + DefaultDeliveryAddress( + deliveryAddress: _deliveryAddress, + labelKey: "box.delivery_address", + ), + ]), + _isNew ? createBtn : saveBtn, + SizedBox( + height: 20, + ), + ], + ), + ), + ), + ); + } + + List getAddressList( + BuildContext context, List addresses) { + return addresses.asMap().entries.map((s) { + return InkWell( + onTap: () {}, + child: DeliveryAddressRow(deliveryAddress: s.value), + ); + }).toList(); + } + + _addCargo(CargoType cargo) { + if (cargo == null) return; + setState(() { + _carton.cargoTypes.remove(cargo); + _carton.cargoTypes.add(cargo); + }); + } + + _removeCargo(CargoType cargo) { + setState(() { + _carton.cargoTypes.remove(cargo); + }); + } + + _save() async { + bool isFromShipment = _selectedCartonType == carton_from_shipments; + bool isSmallBag = _selectedCartonType == carton_small_bag; + if (_user == null && (isFromShipment || isSmallBag)) { + showMsgDialog(context, "Error", "Please select customer"); + return; + } + if (_fcsShipment == null && _isNew) { + showMsgDialog(context, "Error", "Please select FCS shipment"); + return; + } + if ((_carton.cargoTypes?.length ?? 0) == 0 && + (isFromShipment || isSmallBag)) { + showMsgDialog(context, "Error", "Expect at least one cargo type"); + return; + } + double l = double.parse(_lengthController.text, (s) => 0); + double w = double.parse(_widthController.text, (s) => 0); + double h = double.parse(_heightController.text, (s) => 0); + if ((l <= 0 || w <= 0 || h <= 0) && isFromShipment) { + showMsgDialog(context, "Error", "Invalid dimension"); + return; + } + if (_deliveryAddress == null && (isFromShipment || isSmallBag)) { + showMsgDialog(context, "Error", "Invalid delivery address"); + return; + } + if (isSmallBag && _mixCarton == null && _isNew) { + showMsgDialog(context, "Error", "Invalid mix carton"); + return; + } + + Carton carton = Carton(); + carton.id = _carton.id; + carton.cartonType = _selectedCartonType; + carton.fcsShipmentID = _isNew ? _fcsShipment.id : _carton.fcsShipmentID; + carton.userID = _user?.id; + carton.cargoTypes = _carton.cargoTypes; + carton.packages = _carton.packages.where((e) => e.isChecked).toList(); + carton.mixCartonID = _mixCarton?.id; + carton.length = l; + carton.width = w; + carton.height = h; + carton.deliveryAddress = _deliveryAddress; + setState(() { + _isLoading = true; + }); + try { + CartonModel cartonModel = + Provider.of(context, listen: false); + if (_isNew) { + await cartonModel.createCarton(carton); + } else { + await cartonModel.updateCarton(carton); + } + Navigator.pop(context, true); + } catch (e) { + showMsgDialog(context, "Error", e.toString()); + } finally { + setState(() { + _isLoading = false; + }); + } + } +} diff --git a/lib/pages/carton/carton_info.dart b/lib/pages/carton/carton_info.dart new file mode 100644 index 0000000..37daf5c --- /dev/null +++ b/lib/pages/carton/carton_info.dart @@ -0,0 +1,304 @@ +import 'package:fcs/domain/constants.dart'; +import 'package:fcs/domain/entities/carton.dart'; +import 'package:fcs/domain/entities/package.dart'; +import 'package:fcs/domain/vo/delivery_address.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/package/model/package_model.dart'; +import 'package:fcs/pages/rates/model/shipment_rate_model.dart'; +import 'package:fcs/pages/widgets/defalut_delivery_address.dart'; +import 'package:fcs/pages/widgets/display_text.dart'; +import 'package:fcs/pages/widgets/fcs_id_icon.dart'; +import 'package:fcs/pages/widgets/length_picker.dart'; +import 'package:fcs/pages/widgets/local_radio_buttons.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/local_title.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_icons/flutter_icons.dart'; +import 'package:intl/intl.dart'; +import 'package:provider/provider.dart'; + +import 'carton_cargo_table.dart'; +import 'carton_editor.dart'; +import 'carton_package_table.dart'; +import 'model/carton_model.dart'; +import 'widgets.dart'; + +final DateFormat dateFormat = DateFormat("d MMM yyyy"); + +class CartonInfo extends StatefulWidget { + final Carton box; + CartonInfo({this.box}); + + @override + _CartonInfoState createState() => _CartonInfoState(); +} + +class _CartonInfoState extends State { + bool _isLoading = false; + Carton _box; + DeliveryAddress _deliveryAddress = new DeliveryAddress(); + TextEditingController _widthController = new TextEditingController(); + TextEditingController _heightController = new TextEditingController(); + TextEditingController _lengthController = new TextEditingController(); + double volumetricRatio = 0; + double shipmentWeight = 0; + + bool isMixBox; + bool isFromShipments; + bool isFromPackages; + bool isSmallBag; + bool isEdiable; + + @override + void initState() { + super.initState(); + _box = widget.box; + + //for shipment weight + volumetricRatio = Provider.of(context, listen: false) + .rate + .volumetricRatio; + _lengthController.addListener(_calShipmentWeight); + _widthController.addListener(_calShipmentWeight); + _heightController.addListener(_calShipmentWeight); + + _updateBoxData(); + _loadPackages(); + } + + _updateBoxData() { + _widthController.text = _box.width.toString(); + _heightController.text = _box.height.toString(); + _lengthController.text = _box.length.toString(); + _deliveryAddress = _box.deliveryAddress; + isMixBox = _box.cartonType == carton_mix_box; + isFromShipments = _box.cartonType == carton_from_shipments; + isFromPackages = _box.cartonType == carton_from_packages; + isSmallBag = _box.cartonType == carton_small_bag; + isEdiable = !isMixBox && + (isFromPackages || isSmallBag) && + _box.status == carton_packed_status; + } + + _loadPackages() async { + if (!isFromPackages && !isSmallBag) return; + + if (_box.cartonType == carton_from_packages && _box.userID == null) return; + PackageModel packageModel = + Provider.of(context, listen: false); + List packages = await packageModel.getPackages(_box.userID, [ + package_processed_status, + package_packed_status, + package_shipped_status, + package_delivered_status + ]); + packages = packages.where((p) => _box.packageIDs.contains(p.id)).toList(); + packages.forEach((p) { + p.isChecked = true; + }); + + setState(() { + _box.packages = packages; + }); + } + + _calShipmentWeight() { + double l = double.parse(_lengthController.text, (s) => 0); + double w = double.parse(_widthController.text, (s) => 0); + double h = double.parse(_heightController.text, (s) => 0); + setState(() { + shipmentWeight = l * w * h / volumetricRatio; + }); + } + + @override + void dispose() { + super.dispose(); + } + + final DateFormat dateFormat = DateFormat("d MMM yyyy"); + + @override + Widget build(BuildContext context) { + var cartonModel = Provider.of(context); + + final cartonTypeBox = LocalRadioButtons( + readOnly: true, + values: cartonModel.cartonTypesInfo, + selectedValue: + _box.isShipmentCarton ? carton_from_shipments : _box.cartonType); + final shipmentBox = DisplayText( + text: _box.fcsShipmentNumber, + labelTextKey: "box.fcs_shipment_num", + iconData: Ionicons.ios_airplane, + ); + final fcsIDBox = DisplayText( + text: _box.fcsID == null ? "" : _box.fcsID, + labelTextKey: "box.fcs.id", + icon: FcsIDIcon(), + ); + + final customerNameBox = DisplayText( + text: _box.userName == null ? "" : _box.userName, + labelTextKey: "box.name", + iconData: Icons.person, + ); + + final lengthBox = LengthPicker( + controller: _lengthController, + lableKey: "box.length", + isReadOnly: true, + ); + final widthBox = LengthPicker( + controller: _widthController, + lableKey: "box.width", + isReadOnly: true, + ); + final heightBox = LengthPicker( + controller: _heightController, + lableKey: "box.height", + isReadOnly: true, + ); + + final dimBox = Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(right: 8.0), + child: Icon(FontAwesome.arrow_circle_right, color: primaryColor), + ), + SizedBox(child: lengthBox, width: 80), + SizedBox(child: widthBox, width: 80), + SizedBox(child: heightBox, width: 80), + ], + ); + + final shipmentWeightBox = DisplayText( + text: shipmentWeight != null ? shipmentWeight.toStringAsFixed(0) : "", + labelTextKey: "box.shipment_weight", + iconData: MaterialCommunityIcons.weight, + ); + final cargoTableBox = CargoTable( + cargoTypes: _box.cargoTypes, + ); + final mixCartonNumberBox = DisplayText( + text: _box.mixCartonNumber, + labelTextKey: "box.mix.carton", + iconData: MaterialCommunityIcons.package, + ); + + return LocalProgress( + inAsyncCall: _isLoading, + child: Scaffold( + appBar: AppBar( + centerTitle: true, + leading: new IconButton( + icon: new Icon(CupertinoIcons.back, color: primaryColor, size: 30), + onPressed: () => Navigator.of(context).pop(), + ), + shadowColor: Colors.transparent, + backgroundColor: Colors.white, + title: LocalText( + context, + "box.info.title", + fontSize: 20, + color: primaryColor, + ), + actions: isEdiable + ? [ + IconButton( + icon: Icon(Icons.edit, color: primaryColor), + onPressed: _gotoEditor, + ), + IconButton( + icon: Icon(Icons.delete, color: primaryColor), + onPressed: _delete, + ), + ] + : [], + ), + body: Padding( + padding: const EdgeInsets.all(10.0), + child: ListView(children: [ + Center(child: getCartonNumberStatus(context, _box)), + LocalTitle(textKey: "box.type.title"), + cartonTypeBox, + LocalTitle(textKey: "box.shipment_info"), + shipmentBox, + isSmallBag ? mixCartonNumberBox : Container(), + isMixBox ? Container() : fcsIDBox, + isMixBox ? Container() : customerNameBox, + isFromPackages || isSmallBag + ? CartonPackageTable( + packages: _box.packages, + ) + : Container(), + isMixBox ? Container() : LocalTitle(textKey: "box.cargo.type"), + isMixBox ? Container() : cargoTableBox, + ...(isFromPackages + ? [ + LocalTitle(textKey: "box.dimension"), + dimBox, + shipmentWeightBox, + ] + : []), + isMixBox + ? Container() + : LocalTitle(textKey: "box.delivery_address"), + isMixBox + ? Container() + : DefaultDeliveryAddress( + deliveryAddress: _deliveryAddress, + labelKey: "box.delivery_address", + ), + SizedBox( + height: 20, + ) + ]), + ), + ), + ); + } + + _gotoEditor() async { + bool updated = await Navigator.push( + context, + CupertinoPageRoute(builder: (context) => CartonEditor(box: widget.box)), + ); + if (updated ?? false) { + var cartonModel = Provider.of(context, listen: false); + var c = await cartonModel.getCarton(widget.box.id); + setState(() { + _box = c; + _updateBoxData(); + }); + _loadPackages(); + } + } + + _delete() { + showConfirmDialog(context, "box.delete.confirm", () { + _deleteCarton(); + }); + } + + _deleteCarton() async { + setState(() { + _isLoading = true; + }); + try { + var cartonModel = Provider.of(context, listen: false); + await cartonModel.deleteCarton(widget.box); + Navigator.pop(context, true); + } catch (e) { + showMsgDialog(context, "Error", e.toString()); + } finally { + setState(() { + _isLoading = false; + }); + } + } +} diff --git a/lib/pages/carton/carton_list.dart b/lib/pages/carton/carton_list.dart new file mode 100644 index 0000000..544dba6 --- /dev/null +++ b/lib/pages/carton/carton_list.dart @@ -0,0 +1,129 @@ +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/carton/model/carton_model.dart'; +import 'package:fcs/pages/widgets/local_popup_menu_button.dart'; +import 'package:fcs/pages/widgets/local_popupmenu.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import 'carton_editor.dart'; +import 'carton_list_row.dart'; + +class CartonList extends StatefulWidget { + @override + _CartonListState createState() => _CartonListState(); +} + +class _CartonListState extends State { + bool _isLoading = false; + var _controller = ScrollController(); + + @override + void initState() { + super.initState(); + _controller.addListener(() async { + if (_controller.position.pixels == _controller.position.maxScrollExtent) { + Provider.of(context, listen: false).loadMore(); + } + }); + Provider.of(context, listen: false).initData(); + } + + @override + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + var boxModel = Provider.of(context); + final popupMenu = LocalPopupMenuButton( + popmenus: [ + LocalPopupMenu( + id: 1, + textKey: "box.popupmenu.active", + selected: boxModel.selectedIndex == 1), + LocalPopupMenu( + id: 2, + textKey: "box.popupmenu.delivered", + selected: boxModel.selectedIndex == 2) + ], + popupMenuCallback: (p) => this.setState(() { + boxModel.selectedIndex = p.id; + }), + ); + return LocalProgress( + inAsyncCall: _isLoading, + child: DefaultTabController( + length: 2, + child: Scaffold( + appBar: AppBar( + centerTitle: true, + leading: new IconButton( + icon: new Icon(CupertinoIcons.back), + onPressed: () => Navigator.of(context).pop(), + ), + backgroundColor: primaryColor, + title: LocalText(context, "boxes.name", + color: Colors.white, fontSize: 20), + actions: [popupMenu], + ), + floatingActionButton: FloatingActionButton.extended( + onPressed: () { + _newBox(); + }, + icon: Icon(Icons.add), + label: LocalText(context, "boxes.new", color: Colors.white), + backgroundColor: primaryColor, + ), + body: Column( + children: [ + Expanded( + child: RefreshIndicator( + child: new ListView.separated( + physics: AlwaysScrollableScrollPhysics(), + controller: _controller, + separatorBuilder: (context, index) => Divider( + color: Colors.black, + height: 1, + ), + scrollDirection: Axis.vertical, + shrinkWrap: true, + itemCount: boxModel.boxes.length, + itemBuilder: (BuildContext context, int index) { + return CartonListRow( + key: ValueKey(boxModel.boxes[index].id), + box: boxModel.boxes[index]); + }), + onRefresh: () => boxModel.refresh(), + ), + ), + boxModel.isLoading + ? Container( + padding: EdgeInsets.all(8), + color: primaryColor, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("Loading...", + style: TextStyle(color: Colors.white)), + ], + ), + ) + : Container(), + ], + ), + ), + ), + ); + } + + _newBox() { + Navigator.push( + context, + CupertinoPageRoute(builder: (context) => CartonEditor()), + ); + } +} diff --git a/lib/pages_fcs/delivery_list_row.dart b/lib/pages/carton/carton_list_row.dart similarity index 56% rename from lib/pages_fcs/delivery_list_row.dart rename to lib/pages/carton/carton_list_row.dart index f08a564..54c4a7e 100644 --- a/lib/pages_fcs/delivery_list_row.dart +++ b/lib/pages/carton/carton_list_row.dart @@ -1,48 +1,30 @@ -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/pages_fcs/box_editor.dart'; -import 'package:fcs/vo/box.dart'; -import 'package:fcs/widget/bottom_up_page_route.dart'; +import 'package:fcs/domain/entities/carton.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_icons/flutter_icons.dart'; import 'package:intl/intl.dart'; +import 'carton_info.dart'; -class DeliveryListRow extends StatefulWidget { - final bool isReadOnly; - final Box box; - const DeliveryListRow({this.box, this.isReadOnly}); +class CartonListRow extends StatelessWidget { + final Carton box; + CartonListRow({Key key, this.box}) : super(key: key); - @override - _DeliveryListRowState createState() => _DeliveryListRowState(); -} - -class _DeliveryListRowState extends State { final double dotSize = 15.0; - Box _box = new Box(); final DateFormat dateFormat = new DateFormat("dd MMM yyyy"); - @override - void initState() { - super.initState(); - _box = widget.box; - } - @override Widget build(BuildContext context) { - return Container( - padding: EdgeInsets.only(left: 15, right: 15), - child: InkWell( - onTap: () { - if (widget.isReadOnly) { - // Navigator.push( - // context, - // BottomUpPageRoute(PackageInfo(package: _box)), - // ); - } else { - Navigator.push( - context, - BottomUpPageRoute(BoxEditor(box: _box)), - ); - } - }, + return InkWell( + onTap: () { + Navigator.push( + context, + CupertinoPageRoute(builder: (context) => CartonInfo(box: box)), + ); + }, + child: Container( + padding: EdgeInsets.only(left: 15, right: 15), child: Row( children: [ Expanded( @@ -50,6 +32,14 @@ class _DeliveryListRowState extends State { padding: const EdgeInsets.symmetric(vertical: 16.0), child: new Row( children: [ + Container( + padding: EdgeInsets.only(left: 5, right: 10), + child: Icon( + MaterialCommunityIcons.package, + color: primaryColor, + size: 30, + ), + ), new Expanded( child: new Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -57,9 +47,7 @@ class _DeliveryListRowState extends State { Padding( padding: const EdgeInsets.only(left: 8.0), child: new Text( - _box.packageNumber == null - ? '' - : _box.packageNumber, + box.cartonNumber ?? "", style: new TextStyle( fontSize: 15.0, color: Colors.black), ), @@ -67,7 +55,7 @@ class _DeliveryListRowState extends State { Padding( padding: const EdgeInsets.only(left: 10.0, top: 10), child: new Text( - dateFormat.format(_box.arrivedDate), + box.userName ?? "", style: new TextStyle( fontSize: 15.0, color: Colors.grey), ), @@ -83,21 +71,14 @@ class _DeliveryListRowState extends State { children: [ Padding( padding: const EdgeInsets.all(0), - child: getStatus(_box.status), + child: getStatus(box.status == null ? "" : box.status), ), Padding( padding: const EdgeInsets.only(left: 8.0, top: 5, bottom: 5), child: Row( children: [ new Text( - _box.weight == null - ? '' - : _box.weight.toString() + 'lb - ', - style: - new TextStyle(fontSize: 15.0, color: Colors.grey), - ), - new Text( - _box.price == null ? "" : "\$ " + _box.price.toString(), + "${box.actualWeight?.toString() ?? ''} lb", style: new TextStyle(fontSize: 15.0, color: Colors.grey), ), diff --git a/lib/pages/carton/carton_mix_table.dart b/lib/pages/carton/carton_mix_table.dart new file mode 100644 index 0000000..86daa49 --- /dev/null +++ b/lib/pages/carton/carton_mix_table.dart @@ -0,0 +1,89 @@ +import 'package:fcs/domain/entities/carton.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/local_title.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +typedef OnSelect = Function(Carton carton, bool checked); + +class CartonMixTable extends StatelessWidget { + final List cartons; + final OnSelect onSelect; + + const CartonMixTable({Key key, this.cartons, this.onSelect}) + : super(key: key); + + @override + Widget build(BuildContext context) { + final tableTitle = Container( + padding: EdgeInsets.only(right: 10.0, top: 20), + child: Row( + children: [ + Container( + width: 30, + ), + Expanded( + child: LocalText(context, 'box.mix.number', color: Colors.grey), + ), + LocalText(context, 'box.cargo.total', color: Colors.grey), + ], + ), + ); + + final rows = cartons == null + ? [] + : cartons.asMap().entries.map((p) { + return Container( + color: p.value.isChecked + ? Colors.grey.withOpacity(0.2) + : Colors.grey[50].withOpacity(0.2), + child: Container( + padding: EdgeInsets.only( + left: 0.0, right: 10.0, top: 3.0, bottom: 3.0), + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: p.key == cartons.length - 1 + ? Colors.white + : Colors.grey[350], + width: 1), + ), + ), + child: Row( + children: [ + Checkbox( + value: p.value.isChecked, + activeColor: primaryColor, + onChanged: (bool check) { + if (onSelect != null) onSelect(p.value, check); + }), + Expanded( + child: new Text( + p.value.cartonNumber ?? "", + style: textStyle, + )), + new Text( + p.value?.actualWeight?.toString() ?? "", + style: textStyle, + ), + ], + ), + ), + ); + }).toList(); + + return Column( + children: [ + LocalTitle(textKey: "box.shipment.boxes"), + tableTitle, + Divider( + color: Colors.grey[400], + ), + Column( + children: rows, + ), + ], + ); + } +} diff --git a/lib/pages/carton/carton_package_table.dart b/lib/pages/carton/carton_package_table.dart new file mode 100644 index 0000000..07eb9f3 --- /dev/null +++ b/lib/pages/carton/carton_package_table.dart @@ -0,0 +1,120 @@ +import 'package:fcs/domain/entities/package.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/local_title.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +typedef OnSelect = Function(Package package, bool checked); + +class CartonPackageTable extends StatelessWidget { + final List packages; + final OnSelect onSelect; + + const CartonPackageTable({Key key, this.packages, this.onSelect}) + : super(key: key); + + @override + Widget build(BuildContext context) { + final tableTitle = Container( + padding: EdgeInsets.only(right: 10.0, top: 20), + child: Row( + children: [ + SizedBox( + width: 50, + ), + SizedBox( + width: 150, + child: LocalText(context, 'box.tracking.id', color: Colors.grey), + ), + LocalText(context, 'box.package.desc', color: Colors.grey), + ], + ), + ); + + final rows = packages == null + ? [Container()] + : packages.asMap().entries.map((p) { + return Container( + color: p.value.isChecked + ? Colors.grey.withOpacity(0.2) + : Colors.grey[50].withOpacity(0.2), + child: Container( + padding: EdgeInsets.only( + left: 0.0, right: 10.0, top: 3.0, bottom: 3.0), + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: p.key == packages.length - 1 + ? Colors.white + : Colors.grey[350], + width: 1), + ), + ), + child: Row( + children: [ + onSelect == null + ? p.value.isChecked + ? SizedBox( + child: Icon(Icons.check, color: primaryColor), + width: 30) + : SizedBox(width: 30) + : Checkbox( + value: p.value.isChecked, + activeColor: primaryColor, + onChanged: (bool check) { + if (onSelect != null) onSelect(p.value, check); + }), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + p.value.trackingID, + style: textStyle, + ), + Text( + p.value.deliveryAddress?.fullName ?? "", + style: textStyle, + ), + Text( + p.value.deliveryAddress?.phoneNumber ?? "", + style: textStyle, + ), + ], + )), + Flexible( + child: new Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + new Text( + p.value?.desc ?? "", + style: textStyle, + ), + new Text( + "(${p.value?.market ?? ""})", + style: textStyle, + ) + ], + ), + ) + ], + ), + ), + ); + }).toList(); + + return Column( + children: [ + LocalTitle(textKey: "box.packages"), + tableTitle, + Divider( + color: Colors.grey[400], + ), + Column( + children: rows, + ), + ], + ); + } +} diff --git a/lib/pages/carton/model/carton_model.dart b/lib/pages/carton/model/carton_model.dart new file mode 100644 index 0000000..c503249 --- /dev/null +++ b/lib/pages/carton/model/carton_model.dart @@ -0,0 +1,223 @@ +import 'dart:async'; + +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:fcs/data/services/services.dart'; +import 'package:fcs/domain/constants.dart'; +import 'package:fcs/domain/entities/carton.dart'; +import 'package:fcs/domain/vo/message.dart'; +import 'package:fcs/domain/vo/shipment_status.dart'; +import 'package:fcs/helpers/paginator.dart'; +import 'package:fcs/pages/main/model/base_model.dart'; +import 'package:logging/logging.dart'; + +class CartonModel extends BaseModel { + List _boxes = []; + final log = Logger('CartonModel'); + List get boxes => + _selectedIndex == 1 ? _boxes : List.from(_delivered.values); + + Paginator _delivered; + int _selectedIndex = 1; + bool isLoading = false; + + StreamSubscription listener; + static List statusHistory = [ + ShipmentStatus(status: "Packed", date: DateTime(2020, 6, 1), done: true), + ShipmentStatus(status: "Shipped", date: DateTime(2020, 6, 5), done: false), + ShipmentStatus( + status: "Delivered", date: DateTime(2020, 6, 15), done: false) + ]; + + List get completed { + return boxes.where((e) => e.status == "Delivered").toList() + ..sort((e1, e2) { + return e2.packageNumber.compareTo(e1.packageNumber); + }); + } + + List get processed { + return boxes.where((e) => e.status == "Packed").toList() + ..sort((e1, e2) { + return e2.packageNumber.compareTo(e1.packageNumber); + }); + } + + List get upcoming { + return boxes + .where((e) => + e.status == "Packed" || + // e.status == "Received" || + e.status == "Shipped" || + e.status == "Arrived") + .toList() + ..sort((e1, e2) { + return e2.packageNumber.compareTo(e1.packageNumber); + }); + } + + List cartonTypes = [ + carton_from_packages, + carton_mix_box, + carton_small_bag + ]; + List cartonTypesInfo = [ + carton_from_packages, + carton_mix_box, + carton_from_shipments, + carton_small_bag + ]; + + set selectedIndex(int index) { + _selectedIndex = index; + notifyListeners(); + } + + get selectedIndex => _selectedIndex; + + initData() { + _selectedIndex = 1; + _loadBoxes(); + + if (_delivered != null) _delivered.close(); + _delivered = _getDelivered(); + _delivered.load(); + } + + Future _loadBoxes() async { + if (user == null || !user.hasCarton()) return; + String path = "/$cartons_collection/"; + if (listener != null) listener.cancel(); + _boxes = []; + try { + listener = Firestore.instance + .collection("$path") + .where("status", + whereIn: [carton_packed_status, carton_shipped_status]) + .where("is_deleted", isEqualTo: false) + .orderBy("created_at", descending: true) + .snapshots() + .listen((QuerySnapshot snapshot) { + _boxes.clear(); + _boxes = snapshot.documents.map((documentSnapshot) { + var s = Carton.fromMap( + documentSnapshot.data, documentSnapshot.documentID); + return s; + }).toList(); + notifyListeners(); + }); + } catch (e) { + log.warning("Error!! $e"); + } + } + + Paginator _getDelivered() { + if (user == null || !user.hasCarton()) return null; + + var pageQuery = Firestore.instance + .collection("/$cartons_collection") + .where("is_delivered", isEqualTo: true) + .where("is_deleted", isEqualTo: false); + var paginator = new Paginator(pageQuery, rowPerLoad: 20, toObj: (data, id) { + return Carton.fromMap(data, id); + }); + return paginator; + } + + Future loadMore() async { + if (_delivered.ended || selectedIndex == 1) return; + isLoading = true; + notifyListeners(); + await _delivered.load(onFinished: () { + isLoading = false; + notifyListeners(); + }); + } + + Future refresh() async { + if (selectedIndex == 1) return; + await _delivered.refresh(onFinished: () { + notifyListeners(); + }); + } + + void initUser(user) { + super.initUser(user); + } + + @override + logout() async { + if (listener != null) await listener.cancel(); + if (_delivered != null) _delivered.close(); + _boxes = []; + } + + Future> getCartons(String shipmentID) async { + String path = "/$cartons_collection"; + var querySnap = await Firestore.instance + .collection(path) + .where("shipment_id", isEqualTo: shipmentID) + .getDocuments(); + return querySnap.documents + .map((e) => Carton.fromMap(e.data, e.documentID)) + .toList(); + } + + Future> getCartonsByFcsShipment(String fcsShipmentID) async { + String path = "/$cartons_collection"; + var querySnap = await Firestore.instance + .collection(path) + .where("fcs_shipment_id", isEqualTo: fcsShipmentID) + .where("is_deleted", isEqualTo: false) + .getDocuments(); + return querySnap.documents + .map((e) => Carton.fromMap(e.data, e.documentID)) + .toList(); + } + + Future> getCartonsForInvoice( + String fcsShipmentID, String userID) async { + String path = "/$cartons_collection"; + var querySnap = await Firestore.instance + .collection(path) + .where("fcs_shipment_id", isEqualTo: fcsShipmentID) + .where("user_id", isEqualTo: userID) + .where("is_deleted", isEqualTo: false) + .where("is_invoiced", isEqualTo: false) + .getDocuments(); + List cartons = querySnap.documents + .map((e) => Carton.fromMap(e.data, e.documentID)) + .toList(); + return cartons; + } + + Future> getMixCartonsByFcsShipment(String fcsShipmentID) async { + String path = "/$cartons_collection"; + var querySnap = await Firestore.instance + .collection(path) + .where("fcs_shipment_id", isEqualTo: fcsShipmentID) + .where("carton_type", isEqualTo: carton_mix_box) + .where("is_deleted", isEqualTo: false) + .getDocuments(); + return querySnap.documents + .map((e) => Carton.fromMap(e.data, e.documentID)) + .toList(); + } + + Future getCarton(String id) async { + String path = "/$cartons_collection"; + var snap = await Firestore.instance.collection(path).document(id).get(); + return Carton.fromMap(snap.data, snap.documentID); + } + + Future createCarton(Carton carton) { + return Services.instance.cartonService.createCarton(carton); + } + + Future updateCarton(Carton carton) { + return Services.instance.cartonService.updateCarton(carton); + } + + Future deleteCarton(Carton carton) { + return Services.instance.cartonService.deleteCarton(carton); + } +} diff --git a/lib/pages/carton/widgets.dart b/lib/pages/carton/widgets.dart new file mode 100644 index 0000000..3e9a50c --- /dev/null +++ b/lib/pages/carton/widgets.dart @@ -0,0 +1,24 @@ +import 'package:fcs/domain/entities/carton.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:flutter/material.dart'; + +Widget getCartonNumberStatus(BuildContext context, Carton carton) { + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + LocalText( + context, + '', + text: carton.cartonNumber ?? "", + color: primaryColor, + fontSize: 18, + fontWeight: FontWeight.bold, + ), + Padding( + padding: const EdgeInsets.only(left: 8.0), + child: Chip(label: Text(carton.status ?? "")), + ), + ], + ); +} diff --git a/lib/pages/chage_phone_number.dart b/lib/pages/chage_phone_number.dart deleted file mode 100644 index 8910567..0000000 --- a/lib/pages/chage_phone_number.dart +++ /dev/null @@ -1,272 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/language_model.dart'; -import 'package:fcs/model/user_model.dart'; -import 'package:fcs/vo/user.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:fcs/widget/progress.dart'; - -import '../fcs/common/helpers/theme.dart' as Theme; -import 'confirm_email.dart'; -import '../fcs/common/pages/util.dart'; - -class ChangePhoneNumber extends StatefulWidget { - final User user; - ChangePhoneNumber( - this.user, { - Key key, - }) : super(key: key); - - @override - _ChangePhoneNumberState createState() => new _ChangePhoneNumberState(); -} - -class _ChangePhoneNumberState extends State - with SingleTickerProviderStateMixin { - final GlobalKey _scaffoldKey = new GlobalKey(); - - final FocusNode myFocusNodePhone = FocusNode(); - final FocusNode myFocusNodenewPhone = FocusNode(); - - TextEditingController _phoneController = new TextEditingController(); - TextEditingController _newPhoneController = new TextEditingController(); - final formKey = GlobalKey(); - bool _isLoading = false; - - @override - Widget build(BuildContext context) { - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - key: _scaffoldKey, - body: SingleChildScrollView( - child: Container( - width: MediaQuery.of(context).size.width, - height: MediaQuery.of(context).size.height >= 775.0 - ? MediaQuery.of(context).size.height - : 580.0, - child: Column( - mainAxisSize: MainAxisSize.max, - children: [ - Padding( - padding: EdgeInsets.only(top: 35.0, bottom: 10), - child: ListTile( - leading: IconButton( - icon: Icon(Icons.arrow_back), - onPressed: () { - Navigator.of(context).pop(); - }, - ), - title: LocalText( - context, - 'change.phone', - color: Colors.black87, - fontSize: 17, - ), - ), - ), - Expanded( - flex: 2, - child: PageView( - children: [ - new ConstrainedBox( - constraints: const BoxConstraints.expand(), - child: _buildReset(context), - ), - ], - ), - ), - ], - ), - ), - ), - ), - ); - } - - @override - void dispose() { - myFocusNodenewPhone.dispose(); - myFocusNodePhone.dispose(); - super.dispose(); - } - - @override - void initState() { - super.initState(); - _phoneController.text = widget.user.phone; - _newPhoneController.text = "09"; - - // SystemChrome.setPreferredOrientations([ - // DeviceOrientation.portraitUp, - // DeviceOrientation.portraitDown, - // ]); - } - - Widget _buildReset(BuildContext context) { - return Container( - child: ListView( - children: [ - Column( - children: [ - Form( - key: formKey, - child: Card( - elevation: 2.0, - color: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - child: Container( - width: 300.0, - child: Column( - children: [ - Padding( - padding: EdgeInsets.only(left: 25.0, right: 25.0), - child: TextFormField( - focusNode: myFocusNodePhone, - controller: _phoneController, - readOnly: true, - style: TextStyle( - fontFamily: "WorkSansSemiBold", - fontSize: 16.0, - color: Colors.black), - decoration: InputDecoration( - border: InputBorder.none, - icon: Icon( - FontAwesomeIcons.phone, - color: Colors.black, - size: 22.0, - ), - labelText: AppTranslations.of(context) - .text("login.phone"), - labelStyle: - Provider.of(context).isEng - ? TextStyle( - fontFamily: "WorkSansSemiBold", - color: Colors.grey) - : TextStyle( - fontFamily: "MyanmarUnicode", - color: Colors.grey), - ), - ), - ), - Container( - width: 250.0, - height: 1.0, - color: Colors.grey[400], - ), - Padding( - padding: EdgeInsets.only(left: 25.0, right: 25.0), - child: TextFormField( - focusNode: myFocusNodenewPhone, - controller: _newPhoneController, - keyboardType: TextInputType.phone, - style: TextStyle( - fontFamily: "WorkSansSemiBold", - fontSize: 16.0, - color: Colors.black), - decoration: InputDecoration( - border: InputBorder.none, - icon: Icon( - FontAwesomeIcons.phone, - color: Colors.black, - size: 22.0, - ), - labelText: AppTranslations.of(context) - .text("change.new.phone"), - labelStyle: - Provider.of(context).isEng - ? TextStyle( - fontFamily: "WorkSansSemiBold", - color: Colors.grey) - : TextStyle( - fontFamily: "MyanmarUnicode", - color: Colors.grey), - ), - validator: _validatePhone, - ), - ), - ], - ), - ), - ), - ), - SizedBox( - height: 15, - ), - Container( - // margin: EdgeInsets.only(top: 320.0), - decoration: new BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(5.0)), - color: Theme.primaryColor, - ), - child: MaterialButton( - highlightColor: Colors.transparent, - splashColor: Theme.LoginColors.loginGradientEnd, - //shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(5.0))), - child: Padding( - padding: const EdgeInsets.symmetric( - vertical: 10.0, horizontal: 42.0), - child: LocalText( - context, - 'change', - color: Colors.white, - fontSize: 18.0, - ), - ), - onPressed: () => _change(context)), - ), - ], - ), - ], - ), - ); - } - - void _change(BuildContext context) async { - if (!formKey.currentState.validate()) { - return; - } - var _phone = _newPhoneController.text; - - setState(() { - _isLoading = true; - }); - - UserModel userModel = Provider.of(context); - try { - await userModel.changePhone(widget.user.phoneNumber, _phone); - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => ConfirmEmail( - id: widget.user.phoneNumber, - phoneNumber: _phone, - ))); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - Future.delayed(Duration(seconds: 1), () { - if (mounted) { - setState(() { - _isLoading = false; - }); - } - }); - } - } - - String _validatePhone(value) { - if (value.isEmpty) { - return AppTranslations.of(context).text("change.phone_empty"); - } - if (!value.startsWith("09")) { - return 'Only "09".'; - } - return null; - } -} diff --git a/lib/pages/change_password.dart b/lib/pages/change_password.dart deleted file mode 100644 index 7cac95b..0000000 --- a/lib/pages/change_password.dart +++ /dev/null @@ -1,320 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/language_model.dart'; -import 'package:fcs/model/user_model.dart'; -import 'package:fcs/vo/user.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:fcs/widget/progress.dart'; - -import '../fcs/common/helpers/theme.dart' as Theme; -import '../fcs/common/pages/util.dart'; - -class ChangePassword extends StatefulWidget { - final User user; - ChangePassword( - this.user, { - Key key, - }) : super(key: key); - - @override - _ChangePasswordState createState() => new _ChangePasswordState(); -} - -class _ChangePasswordState extends State - with SingleTickerProviderStateMixin { - final GlobalKey _scaffoldKey = new GlobalKey(); - - final FocusNode myFocusNodePassword = FocusNode(); - final FocusNode myFocusNodeEmail = FocusNode(); - - bool _obscureTextLogin = true; - bool _obscureTextSignup = true; - bool _obscureTextSignupConfirm = true; - - TextEditingController _smsController = new TextEditingController(); - TextEditingController _passwordController = new TextEditingController(); - TextEditingController _confirmPasswordController = - new TextEditingController(); - final formKey = GlobalKey(); - bool _isLoading = false; - - @override - Widget build(BuildContext context) { - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - key: _scaffoldKey, - body: SingleChildScrollView( - child: Container( - width: MediaQuery.of(context).size.width, - height: MediaQuery.of(context).size.height >= 775.0 - ? MediaQuery.of(context).size.height - : 580.0, - child: Column( - mainAxisSize: MainAxisSize.max, - children: [ - Padding( - padding: EdgeInsets.only(top: 35.0, bottom: 10), - child: ListTile( - leading: IconButton( - icon: Icon(Icons.arrow_back), - onPressed: () { - Navigator.of(context).pop(); - }, - ), - title: LocalText( - context, - 'change.password.title', - color: Colors.black87, - fontSize: 17, - ), - ), - ), - Expanded( - flex: 2, - child: PageView( - children: [ - new ConstrainedBox( - constraints: const BoxConstraints.expand(), - child: _buildReset(context), - ), - ], - ), - ), - ], - ), - ), - ), - ), - ); - } - - @override - void dispose() { - myFocusNodePassword.dispose(); - myFocusNodeEmail.dispose(); - super.dispose(); - } - - @override - void initState() { - super.initState(); - - // SystemChrome.setPreferredOrientations([ - // DeviceOrientation.portraitUp, - // DeviceOrientation.portraitDown, - // ]); - - _smsController.text = ""; - } - - Widget _buildReset(BuildContext context) { - return Container( - child: ListView( - children: [ - Column( - children: [ - Form( - key: formKey, - child: Card( - elevation: 2.0, - color: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - child: Container( - width: 300.0, - child: Column( - children: [ - Padding( - padding: EdgeInsets.only(left: 25.0, right: 25.0), - child: TextFormField( - focusNode: myFocusNodePassword, - controller: _passwordController, - obscureText: _obscureTextSignup, - style: TextStyle( - fontFamily: "WorkSansSemiBold", - fontSize: 16.0, - color: Colors.black), - decoration: InputDecoration( - border: InputBorder.none, - icon: Icon( - FontAwesomeIcons.lock, - color: Colors.black, - ), - labelText: AppTranslations.of(context) - .text("login.password"), - labelStyle: - Provider.of(context).isEng - ? TextStyle( - fontFamily: "WorkSansSemiBold", - color: Colors.grey) - : TextStyle( - fontFamily: "MyanmarUnicode", - color: Colors.grey), - suffixIcon: GestureDetector( - onTap: _toggleSignup, - child: Icon( - _obscureTextSignup - ? FontAwesomeIcons.eye - : FontAwesomeIcons.eyeSlash, - size: 15.0, - color: Colors.black, - ), - ), - ), - validator: _validatePassword, - ), - ), - Container( - width: 250.0, - height: 1.0, - color: Colors.grey[400], - ), - Padding( - padding: EdgeInsets.only(left: 25.0, right: 25.0), - child: TextFormField( - controller: _confirmPasswordController, - obscureText: _obscureTextSignupConfirm, - style: TextStyle( - fontFamily: "WorkSansSemiBold", - fontSize: 16.0, - color: Colors.black), - decoration: InputDecoration( - border: InputBorder.none, - icon: Icon( - FontAwesomeIcons.lock, - color: Colors.black, - ), - labelText: AppTranslations.of(context) - .text("login.confirm_password"), - labelStyle: - Provider.of(context).isEng - ? TextStyle( - fontFamily: "WorkSansSemiBold", - color: Colors.grey) - : TextStyle( - fontFamily: "MyanmarUnicode", - color: Colors.grey), - suffixIcon: GestureDetector( - onTap: _toggleSignupConfirm, - child: Icon( - _obscureTextSignupConfirm - ? FontAwesomeIcons.eye - : FontAwesomeIcons.eyeSlash, - size: 15.0, - color: Colors.black, - ), - ), - ), - validator: _validateConfirmPassword, - ), - ), - ], - ), - ), - ), - ), - SizedBox( - height: 15, - ), - Container( - // margin: EdgeInsets.only(top: 320.0), - decoration: new BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(5.0)), - color: Theme.primaryColor, - ), - child: MaterialButton( - highlightColor: Colors.transparent, - splashColor: Theme.LoginColors.loginGradientEnd, - //shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(5.0))), - child: Padding( - padding: const EdgeInsets.symmetric( - vertical: 10.0, horizontal: 42.0), - child: LocalText( - context, - 'change', - color: Colors.white, - fontSize: 18.0, - ), - ), - onPressed: () => _change(context)), - ), - ], - ), - ], - ), - ); - } - - void _toggleLogin() { - setState(() { - _obscureTextLogin = !_obscureTextLogin; - }); - } - - void _toggleSignup() { - setState(() { - _obscureTextSignup = !_obscureTextSignup; - }); - } - - void _toggleSignupConfirm() { - setState(() { - _obscureTextSignupConfirm = !_obscureTextSignupConfirm; - }); - } - - void _change(BuildContext context) async { - if (!formKey.currentState.validate()) { - return; - } - var password = _passwordController.text; - - setState(() { - _isLoading = true; - }); - - UserModel userModel = Provider.of(context); - try { - await userModel.changePassword(widget.user.phoneNumber, password); - Navigator.pop(context); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - Future.delayed(Duration(seconds: 1), () { - if (mounted) { - setState(() { - _isLoading = false; - }); - } - }); - } - } - - String _validatePassword(value) { - if (value.isEmpty) { - return AppTranslations.of(context).text("login.password_empty"); - } - if (value.length < 6) { - return AppTranslations.of(context).text("login.password_size"); - } - return null; - } - - String _validateConfirmPassword(value) { - if (value.isEmpty) { - return AppTranslations.of(context).text("login.password_empty"); - } - if (value.length < 6) { - return AppTranslations.of(context).text("login.password_size"); - } - if (value != _passwordController.text) { - return AppTranslations.of(context).text("login.password_mismatch"); - } - return null; - } -} diff --git a/lib/fcs/common/pages/chat/bubble.dart b/lib/pages/chat/bubble.dart similarity index 93% rename from lib/fcs/common/pages/chat/bubble.dart rename to lib/pages/chat/bubble.dart index c6f8a05..9a99de3 100644 --- a/lib/fcs/common/pages/chat/bubble.dart +++ b/lib/pages/chat/bubble.dart @@ -1,8 +1,8 @@ -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/fcs/common/pages/package/package_info.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/fcs/common/pages/widgets/fcs_id_icon.dart'; -import 'package:fcs/fcs/common/pages/widgets/local_text.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/package/package_info.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/widgets/fcs_id_icon.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; diff --git a/lib/fcs/common/pages/chat/message_detail.dart b/lib/pages/chat/message_detail.dart similarity index 74% rename from lib/fcs/common/pages/chat/message_detail.dart rename to lib/pages/chat/message_detail.dart index 74e9c76..c1209e7 100644 --- a/lib/fcs/common/pages/chat/message_detail.dart +++ b/lib/pages/chat/message_detail.dart @@ -1,19 +1,21 @@ -import 'package:fcs/fcs/common/domain/constants.dart'; -import 'package:fcs/fcs/common/domain/entities/package.dart'; -import 'package:fcs/fcs/common/domain/entities/user.dart'; -import 'package:fcs/fcs/common/domain/vo/message.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/fcs/common/pages/chat/model/message_model.dart'; -import 'package:fcs/fcs/common/pages/customer/customer_editor.dart'; -import 'package:fcs/fcs/common/pages/customer/model/customer_model.dart'; -import 'package:fcs/fcs/common/pages/model/main_model.dart'; -import 'package:fcs/fcs/common/pages/package/model/package_model.dart'; -import 'package:fcs/fcs/common/pages/package/package_info.dart'; -import 'package:fcs/fcs/common/pages/profile/profile_page.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/fcs/common/pages/widgets/bottom_up_page_route.dart'; +import 'package:fcs/domain/constants.dart'; +import 'package:fcs/domain/entities/package.dart'; +import 'package:fcs/domain/entities/shipment.dart'; +import 'package:fcs/domain/entities/user.dart'; +import 'package:fcs/domain/vo/message.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/chat/model/message_model.dart'; +import 'package:fcs/pages/customer/customer_editor.dart'; +import 'package:fcs/pages/customer/model/customer_model.dart'; +import 'package:fcs/pages/main/model/main_model.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/package/model/package_model.dart'; +import 'package:fcs/pages/package/package_info.dart'; +import 'package:fcs/pages/profile/profile_page.dart'; +import 'package:fcs/pages/shipment/model/shipment_model.dart'; +import 'package:fcs/pages/shipment/shipment_info.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; import 'package:provider/provider.dart'; import 'bubble.dart'; @@ -46,6 +48,10 @@ class MessageDetail extends StatelessWidget { return Scaffold( appBar: AppBar( + leading: new IconButton( + icon: new Icon(CupertinoIcons.back), + onPressed: () => Navigator.of(context).pop(), + ), backgroundColor: primaryColor, elevation: .9, title: Text( @@ -171,7 +177,9 @@ class MessageDetail extends StatelessWidget { PackageModel packageModel = Provider.of(context, listen: false); Package p = await packageModel.getPackage(message.messageID); - Navigator.push(context, BottomUpPageRoute(PackageInfo(package: p))); + if (p == null) return; + Navigator.push(context, + CupertinoPageRoute(builder: (context) => PackageInfo(package: p))); } if (message.messageType == message_type_profile && message.messageID != null && @@ -179,14 +187,30 @@ class MessageDetail extends StatelessWidget { MainModel mainModel = Provider.of(context, listen: false); if (mainModel.user.isCustomer()) { - Navigator.push(context, BottomUpPageRoute(Profile())); + Navigator.push( + context, CupertinoPageRoute(builder: (context) => Profile())); } else { CustomerModel customerModel = Provider.of(context, listen: false); User user = await customerModel.getUser(message.messageID); - Navigator.of(context) - .push(BottomUpPageRoute(CustomerEditor(customer: user))); + Navigator.of(context).push(CupertinoPageRoute( + builder: (context) => CustomerEditor(customer: user))); } } + if (message.messageType == message_type_shipment && + message.messageID != null && + message.messageID != "") { + ShipmentModel shipmentModel = + Provider.of(context, listen: false); + Shipment s = await shipmentModel.getShipment(message.messageID); + if (s == null) return; + await Navigator.push( + context, + CupertinoPageRoute( + builder: (context) => ShipmentInfo( + shipment: s, + isCustomer: true, + ))); + } } } diff --git a/lib/fcs/common/pages/chat/model/message_model.dart b/lib/pages/chat/model/message_model.dart similarity index 89% rename from lib/fcs/common/pages/chat/model/message_model.dart rename to lib/pages/chat/model/message_model.dart index ba7c268..447a325 100644 --- a/lib/fcs/common/pages/chat/model/message_model.dart +++ b/lib/pages/chat/model/message_model.dart @@ -1,10 +1,10 @@ import 'dart:async'; import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:fcs/fcs/common/domain/constants.dart'; -import 'package:fcs/fcs/common/domain/vo/message.dart'; -import 'package:fcs/fcs/common/pages/model/base_model.dart'; -import 'package:fcs/fcs/common/services/services.dart'; +import 'package:fcs/data/services/services.dart'; +import 'package:fcs/domain/constants.dart'; +import 'package:fcs/domain/vo/message.dart'; +import 'package:fcs/pages/main/model/base_model.dart'; import 'package:logging/logging.dart'; class MessageModel extends BaseModel { @@ -12,10 +12,6 @@ class MessageModel extends BaseModel { List messages; - void initUser(user) { - super.initUser(user); - } - @override logout() async { if (listener != null) await listener.cancel(); diff --git a/lib/pages/confirm_email.dart b/lib/pages/confirm_email.dart deleted file mode 100644 index ed82bba..0000000 --- a/lib/pages/confirm_email.dart +++ /dev/null @@ -1,114 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/user_model.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:fcs/widget/progress.dart'; - -import '../fcs/common/pages/util.dart'; - -class ConfirmEmail extends StatefulWidget { - final String id, email, phoneNumber; - - const ConfirmEmail({Key key, this.id, this.email, this.phoneNumber}) - : super(key: key); - @override - _ConfirmEmailState createState() => _ConfirmEmailState(); -} - -class _ConfirmEmailState extends State { - final TextEditingController _sms = new TextEditingController(); - bool _isLoading = false; - final _formKey = GlobalKey(); - - @override - void initState() { - super.initState(); - } - - _confimEmail() async { - UserModel userModel = Provider.of(context); - if (!_formKey.currentState.validate()) { - return; - } - - setState(() { - _isLoading = true; - }); - try { - await userModel.confirmEmail( - widget.id, widget.email, widget.phoneNumber, _sms.text); - Navigator.pushNamedAndRemoveUntil(context, "/welcome", (r) => false); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } - - Future.delayed(Duration(seconds: 1), () { - if (mounted) { - setState(() { - _isLoading = false; - }); - } - }); - } - - @override - Widget build(BuildContext context) { - final smsInput = TextFormField( - controller: _sms, - keyboardType: TextInputType.number, - autofocus: false, - decoration: new InputDecoration( - labelText: widget.email == null - ? AppTranslations.of(context).text("sms.sms") - : AppTranslations.of(context).text("email.code"), - labelStyle: labelStyle, - hintText: 'eg. 123456', - icon: Icon( - Icons.lock, - color: primaryColor, - )), - validator: (value) { - if (value.isEmpty) { - return widget.email == null - ? AppTranslations.of(context).text("sms.empty") - : AppTranslations.of(context).text("email.code_empty"); - } - return null; - }, - ); - - final enterButton = Padding( - padding: EdgeInsets.symmetric(vertical: 16.0), - child: RaisedButton( - onPressed: () => _confimEmail(), - padding: EdgeInsets.all(12), - color: primaryColor, - child: Text(AppTranslations.of(context).text("sms.enter"), - style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold)), - ), - ); - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - title: Text(widget.email == null - ? AppTranslations.of(context).text("input_sms") - : AppTranslations.of(context).text("email.input")), - backgroundColor: primaryColor, - ), - body: Center( - child: ListView( - shrinkWrap: true, - padding: EdgeInsets.only(left: 24.0, right: 24.0), - children: [ - Form(key: _formKey, child: smsInput), - SizedBox(height: 8.0), - enterButton, - ], - ), - ), - ), - ); - } -} diff --git a/lib/pages/contact.dart b/lib/pages/contact.dart deleted file mode 100644 index abbdefd..0000000 --- a/lib/pages/contact.dart +++ /dev/null @@ -1,154 +0,0 @@ -import 'package:fcs/model/pickup_model.dart'; -import 'package:fcs/widget/label_widgets.dart'; -import 'package:flutter/material.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -import 'package:package_info/package_info.dart'; -import 'package:provider/provider.dart'; -import 'package:url_launcher/url_launcher.dart'; -import 'package:fcs/model/main_model.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/progress.dart'; - -class Contact extends StatefulWidget { - @override - _ContactState createState() => _ContactState(); -} - -class _ContactState extends State { - bool _isLoading = false; - - @override - Widget build(BuildContext context) { - var pickupModel = Provider.of(context, listen: false); - - // MainModel mainModel = Provider.of(context); - // bool isOwner = mainModel.user != null && mainModel.user.isOwner(); - // bool hasAdmin = mainModel.user != null && mainModel.user.hasAdmin(); - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - elevation: 0, - centerTitle: true, - leading: new IconButton( - icon: new Icon(Icons.close), - onPressed: () => Navigator.of(context).pop(), - ), - title: LocalText( - context, - "contact", - fontSize: 25, - color: Colors.white, - ), - ), - body: ListView( - children: [ - link(pickupModel.profile.usaContactNumber, Icons.phone_forwarded, - onTap: () => _call(pickupModel.profile.usaContactNumber), - label: LocalText( - context, - "contact.usa.phone", - color: primaryColor, - )), - link(pickupModel.profile.mmContactNumber, Icons.phone_forwarded, - onTap: () => _call( - pickupModel.profile.mmContactNumber, - ), - label: LocalText( - context, - "contact.mm.phone", - color: primaryColor, - )), - link( - pickupModel.profile.usaAddress, - Icons.location_on, - ), - link(pickupModel.profile.mmAddress, Icons.location_on), - link(pickupModel.profile.mail, Icons.email, - onTap: () => _email(pickupModel.profile.mail)), - link(pickupModel.profile.facebook, FontAwesomeIcons.facebook, - onTap: () => _openLink(pickupModel.profile.facebook)), - ], - ), - ), - ); - } - - Widget link(String text, IconData iconData, - {Function() onTap, Widget label}) { - return Padding( - padding: const EdgeInsets.only(left: 18.0, bottom: 5), - child: InkWell( - onTap: () => onTap != null ? onTap() : null, - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: Row( - children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: Icon( - iconData, - ), - ), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - label == null - ? Container() - : Padding( - padding: EdgeInsets.fromLTRB(10, 10, 10, 0), - child: label, - ), - Padding( - padding: const EdgeInsets.all(8.0), - child: Text( - text == null ? "" : text, - overflow: TextOverflow.ellipsis, - maxLines: 5, - style: TextStyle(fontSize: 14.0), - ), - ), - ], - ), - SizedBox( - width: 5, - ), - onTap == null - ? Container() - : Icon( - Icons.open_in_new, - color: Colors.grey, - size: 15, - ) - ], - ), - )), - ); - } - - Future getVersionNumber() async { - PackageInfo packageInfo = await PackageInfo.fromPlatform(); - String version = packageInfo.version + "+" + packageInfo.buildNumber; - return version; - } - - _call(String phone) { - showConfirmDialog( - context, "contact.phone.confim", () => launch("tel:$phone"), - translationVariables: ["$phone"]); - } - - _email(String email) { - showConfirmDialog( - context, "contact.email.configm", () => launch("mailto:$email"), - translationVariables: ["$email"]); - } - - _openLink(String link) { - showConfirmDialog(context, "contact.open.confrim", () => launch("$link"), - translationVariables: ["$link"]); - } -} diff --git a/lib/fcs/common/pages/contact/contact_editor.dart b/lib/pages/contact/contact_editor.dart similarity index 90% rename from lib/fcs/common/pages/contact/contact_editor.dart rename to lib/pages/contact/contact_editor.dart index f2965cd..e91085a 100644 --- a/lib/fcs/common/pages/contact/contact_editor.dart +++ b/lib/pages/contact/contact_editor.dart @@ -1,11 +1,11 @@ -import 'package:fcs/fcs/common/domain/vo/contact.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/fcs/common/localization/app_translations.dart'; -import 'package:fcs/fcs/common/pages/contact/model/contact_model.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/fcs/common/pages/widgets/input_text.dart'; -import 'package:fcs/fcs/common/pages/widgets/local_text.dart'; -import 'package:fcs/fcs/common/pages/widgets/progress.dart'; +import 'package:fcs/domain/vo/contact.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/localization/app_translations.dart'; +import 'package:fcs/pages/contact/model/contact_model.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/widgets/input_text.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/progress.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; diff --git a/lib/fcs/common/pages/contact/contact_page.dart b/lib/pages/contact/contact_page.dart similarity index 88% rename from lib/fcs/common/pages/contact/contact_page.dart rename to lib/pages/contact/contact_page.dart index c3d988a..404b2ac 100644 --- a/lib/fcs/common/pages/contact/contact_page.dart +++ b/lib/pages/contact/contact_page.dart @@ -1,10 +1,10 @@ -import 'package:fcs/fcs/common/domain/entities/setting.dart'; -import 'package:fcs/fcs/common/domain/vo/contact.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/fcs/common/localization/app_translations.dart'; -import 'package:fcs/fcs/common/pages/contact/contact_editor.dart'; -import 'package:fcs/fcs/common/pages/model/main_model.dart'; -import 'package:fcs/fcs/common/pages/widgets/local_text.dart'; +import 'package:fcs/domain/entities/setting.dart'; +import 'package:fcs/domain/vo/contact.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/localization/app_translations.dart'; +import 'package:fcs/pages/contact/contact_editor.dart'; +import 'package:fcs/pages/main/model/main_model.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; @@ -30,7 +30,7 @@ class _ContactPageState extends State { centerTitle: true, leading: new IconButton( icon: new Icon( - Icons.close, + CupertinoIcons.back, color: primaryColor, ), onPressed: () => Navigator.of(context).pop(), @@ -114,7 +114,7 @@ class _ContactPageState extends State { } _call(String phone) { - launch("tel:$phone"); + launch("tel:${phone.trim().replaceAll(' ', '')}"); } _email(String email) { diff --git a/lib/pages/contact/model/contact_model.dart b/lib/pages/contact/model/contact_model.dart new file mode 100644 index 0000000..25e2c54 --- /dev/null +++ b/lib/pages/contact/model/contact_model.dart @@ -0,0 +1,16 @@ +import 'dart:async'; + +import 'package:fcs/domain/vo/contact.dart'; +import 'package:fcs/helpers/firebase_helper.dart'; +import 'package:fcs/pages/main/model/base_model.dart'; +import 'package:logging/logging.dart'; + +class ContactModel extends BaseModel { + final log = Logger('ContactModel'); + + Future saveContact(Contact contact) async { + await request("/contact", "PUT", + payload: contact.toMap(), token: await getToken()); + notifyListeners(); + } +} diff --git a/lib/pages/contact/widgets.dart b/lib/pages/contact/widgets.dart new file mode 100644 index 0000000..40a78f6 --- /dev/null +++ b/lib/pages/contact/widgets.dart @@ -0,0 +1,103 @@ +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/localization/app_translations.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:flutter/material.dart'; + +Widget itemTitle(BuildContext context, String textKey) { + return Padding( + padding: const EdgeInsets.only(left: 18.0, top: 25, bottom: 5), + child: Text( + AppTranslations.of(context).text(textKey), + style: TextStyle( + fontWeight: FontWeight.bold, fontSize: 18, color: Colors.black), + ), + ); +} + +Widget subItemTitle(BuildContext context, String textKey, {IconData iconData}) { + return Padding( + padding: const EdgeInsets.only(left: 0, top: 0, bottom: 0), + child: Row( + children: [ + Icon( + iconData, + color: primaryColor, + ), + SizedBox(width: 10), + Text( + AppTranslations.of(context).text(textKey), + style: TextStyle( + fontWeight: FontWeight.w700, fontSize: 15, color: primaryColor), + ), + ], + ), + ); +} + +Widget contactItem(BuildContext context, String text, IconData iconData, + {Function() onTap, String labelKey}) { + return Material( + child: Padding( + padding: const EdgeInsets.only(left: 18.0, bottom: 10, right: 18), + child: Container( + decoration: BoxDecoration( + border: Border.all(color: Colors.grey, width: 0.8), + borderRadius: BorderRadius.all( + Radius.circular(5.0) // <--- border radius here + ), + ), + child: InkWell( + onTap: () => onTap != null ? onTap() : null, + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Row( + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Icon( + iconData, + color: primaryColor, + ), + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + labelKey == null + ? Container() + : Padding( + padding: EdgeInsets.fromLTRB(10, 10, 10, 0), + child: LocalText(context, labelKey, + color: primaryColor, + fontWeight: FontWeight.w500, + fontSize: 18), + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + text == null ? "" : text, + overflow: TextOverflow.ellipsis, + maxLines: 5, + style: TextStyle( + fontSize: 14.0, + ), + ), + ), + ], + ), + SizedBox( + width: 5, + ), + onTap == null + ? Container() + : Icon( + Icons.open_in_new, + color: Colors.grey, + size: 15, + ) + ], + ), + )), + ), + ), + ); +} diff --git a/lib/pages/contact_editor.dart b/lib/pages/contact_editor.dart deleted file mode 100644 index 22db660..0000000 --- a/lib/pages/contact_editor.dart +++ /dev/null @@ -1,274 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/language_model.dart'; -import 'package:fcs/model/main_model.dart'; -import 'package:fcs/pages/phone_input.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/setting.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/local_text_field.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:fcs/widget/progress.dart'; - -class ContactEditor extends StatefulWidget { - final Setting setting; - const ContactEditor({this.setting}); - @override - _ContactEditorState createState() => _ContactEditorState(); -} - -class _ContactEditorState extends State { - TextEditingController _email = new TextEditingController(); - TextEditingController _facebook = new TextEditingController(); - TextEditingController _website = new TextEditingController(); - TextEditingController _address = new TextEditingController(); - TextEditingController _deliveryPhone = new TextEditingController(); - - final _formKey = GlobalKey(); - bool _isLoading = false; - - List phones = new List(); - List _initPhones = new List(); - - @override - void initState() { - super.initState(); - if (widget.setting != null) { - this._initPhones = widget.setting.phones; - _email.text = widget.setting.email; - _facebook.text = widget.setting.facebook; - _website.text = widget.setting.website; - _deliveryPhone.text = widget.setting.deliveryPhone; - _address.text = widget.setting.address; - - phones.clear(); - _initPhones.forEach((p) { - phones.add(p); - }); - } - } - - @override - Widget build(BuildContext context) { - var languageModel = Provider.of(context); - - final emailBox = TextFormField( - controller: _email, - autofocus: false, - cursorColor: primaryColor, - style: textStyle, - decoration: new InputDecoration( - labelText: AppTranslations.of(context).text('contact.email'), - labelStyle: languageModel.isEng ? labelStyle : labelStyleMM, - icon: Icon( - Icons.email, - color: primaryColor, - ), - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - ), - validator: (value) { - if (value.isEmpty) { - return AppTranslations.of(context).text('contact.email.empty'); - } - return null; - }, - ); - - final faceBookBox = TextFormField( - controller: _facebook, - autofocus: false, - cursorColor: primaryColor, - style: textStyle, - decoration: new InputDecoration( - labelText: AppTranslations.of(context).text('contact.facebook'), - labelStyle: languageModel.isEng ? labelStyle : labelStyleMM, - icon: Icon( - FontAwesomeIcons.facebook, - color: primaryColor, - ), - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - ), - validator: (value) { - if (value.isEmpty) { - return AppTranslations.of(context).text('contact.facebook.empty'); - } - return null; - }, - ); - - final googleBox = TextFormField( - controller: _website, - autofocus: false, - cursorColor: primaryColor, - style: textStyle, - decoration: new InputDecoration( - labelText: AppTranslations.of(context).text('contact.google'), - labelStyle: languageModel.isEng ? labelStyle : labelStyleMM, - icon: Icon( - FontAwesomeIcons.chrome, - color: primaryColor, - ), - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - ), - validator: (value) { - if (value.isEmpty) { - return AppTranslations.of(context).text('contact.google.empty'); - } - return null; - }, - ); - - final addPhoneNumber = ListTile( - contentPadding: EdgeInsets.only(top: 15), - title: ButtonTheme( - height: 45, - child: RaisedButton( - color: Colors.white, - onPressed: () async { - var phone = await showDialog( - context: context, builder: (_) => PhoneEditor()); - _save(phone); - }, - child: Text("Add Phone", - style: TextStyle( - fontSize: 18, - )), - ), - )); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - title: LocalText( - context, - "contact.title", - fontSize: 20, - color: Colors.white, - ), - actions: [ - IconButton( - icon: Icon(Icons.send), - onPressed: () { - if (!_formKey.currentState.validate()) return; - showConfirmDialog(context, "contact.confrim", () { - _submit(); - }); - }) - ], - ), - body: Form( - key: _formKey, - child: ListView( - shrinkWrap: true, - padding: EdgeInsets.only(left: 24.0, right: 24.0), - children: [ - this.phones.isNotEmpty - ? ConstrainedBox( - constraints: BoxConstraints(maxHeight: 1000), - child: ListView.builder( - shrinkWrap: true, - itemBuilder: (context, index) { - return Stack( - alignment: const Alignment(1.0, 1.0), - children: [ - new TextField( - controller: new TextEditingController( - text: this.phones[index]), - cursorColor: primaryColor, - readOnly: true, - decoration: new InputDecoration( - border: InputBorder.none, - focusedBorder: InputBorder.none, - icon: Icon( - Icons.phone, - color: primaryColor, - ), - ), - ), - new FlatButton( - onPressed: () { - setState(() { - this.phones.remove(this.phones[index]); - }); - }, - child: new Icon( - Icons.cancel, - size: 25, - )) - ], - ); - }, - itemCount: this.phones.length, - ), - ) - : Container(), - addPhoneNumber, - LocalTextField( - textEditingController: _deliveryPhone, - icon: Icon( - Icons.phone_forwarded, - color: primaryColor, - ), - labelKey: "contact.delivery.phone", - ), - emailBox, - faceBookBox, - googleBox, - LocalTextField( - textEditingController: _address, - icon: Icon( - Icons.location_on, - color: primaryColor, - ), - labelKey: "contact.address", - maxLines: 3, - ), - ], - ), - ), - )); - } - - _save(String phone) { - if (phone == null) return; - setState(() { - this.phones.add(phone); - }); - } - - _submit() async { - setState(() { - _isLoading = true; - }); - try { - widget.setting.email = _email.text; - widget.setting.facebook = _facebook.text; - widget.setting.website = _website.text; - widget.setting.phones = this.phones; - widget.setting.address = _address.text; - widget.setting.deliveryPhone = _deliveryPhone.text; - var mainModel = Provider.of(context); - await mainModel.updateContact(widget.setting); - Navigator.pop(context); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - setState(() { - _isLoading = false; - }); - } - } -} diff --git a/lib/pages/custom_editor.dart b/lib/pages/custom_editor.dart deleted file mode 100644 index 69b5bad..0000000 --- a/lib/pages/custom_editor.dart +++ /dev/null @@ -1,80 +0,0 @@ -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/vo/custom.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:flutter/material.dart'; -import 'package:fcs/widget/progress.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -import '../fcs/common/helpers/theme.dart'; - -class CustomEditor extends StatefulWidget { - final Custom custom; - CustomEditor({this.custom}); - - @override - _CustomEditorState createState() => _CustomEditorState(); -} - -class _CustomEditorState extends State { - TextEditingController _productController = new TextEditingController(); - TextEditingController _feeController = new TextEditingController(); - - bool _isLoading = false; - Custom _custom = new Custom(); - - @override - void initState() { - super.initState(); - if (widget.custom != null) { - _custom = widget.custom; - _productController.text = _custom.productType; - _feeController.text = _custom.fee.toString(); - } - } - - @override - void dispose() { - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - centerTitle: true, - leading: new IconButton( - icon: new Icon( - Icons.close, - ), - onPressed: () => Navigator.of(context).pop(), - ), - backgroundColor: primaryColor, - title: Text(AppTranslations.of(context).text("custom.form.title")), - ), - body: Container( - padding: EdgeInsets.all(18), - child: Column( - children: [ - Expanded( - child: ListView( - children: [ - fcsInput("Procut Type", FontAwesomeIcons.weightHanging, - controller: _productController), - fcsInput("Fee", Icons.attach_money, - controller: _feeController), - SizedBox(height: 30), - ], - ), - ), - widget.custom == null - ? fcsButton(context, "Create", callack: () {}) - : fcsButton(context, "Save", callack: () {}), - SizedBox(height: 10) - ], - ), - ), - ), - ); - } -} diff --git a/lib/fcs/common/pages/customer/customer_editor.dart b/lib/pages/customer/customer_editor.dart similarity index 65% rename from lib/fcs/common/pages/customer/customer_editor.dart rename to lib/pages/customer/customer_editor.dart index 3e7d271..e3df283 100644 --- a/lib/fcs/common/pages/customer/customer_editor.dart +++ b/lib/pages/customer/customer_editor.dart @@ -1,10 +1,13 @@ -import 'package:fcs/fcs/common/domain/entities/user.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/fcs/common/pages/customer/model/customer_model.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/fcs/common/pages/widgets/display_text.dart'; -import 'package:fcs/fcs/common/pages/widgets/fcs_id_icon.dart'; -import 'package:fcs/fcs/common/pages/widgets/progress.dart'; +import 'package:fcs/domain/constants.dart'; +import 'package:fcs/domain/entities/user.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/customer/model/customer_model.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/widgets/display_text.dart'; +import 'package:fcs/pages/widgets/fcs_id_icon.dart'; +import 'package:fcs/pages/widgets/local_button.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; @@ -32,7 +35,7 @@ class _CustomerEditorState extends State { Expanded( child: DisplayText( text: widget.customer.phoneNumber, - labelText: getLocalString(context, "customer.phone"), + labelTextKey: "customer.phone", iconData: Icons.phone, )), IconButton( @@ -41,6 +44,13 @@ class _CustomerEditorState extends State { ], ); + final enabled = widget.customer.status != user_disabled_status; + final enableBox = LocalButton( + textKey: enabled ? "customer.disable.btn" : "customer.enable.btn", + iconData: enabled ? Icons.lock : Icons.lock_open, + color: enabled ? primaryColor : Colors.grey, + callBack: () => _enable(!enabled), + ); return LocalProgress( inAsyncCall: _isLoading, child: SafeArea( @@ -51,7 +61,7 @@ class _CustomerEditorState extends State { centerTitle: true, leading: new IconButton( icon: new Icon( - Icons.close, + CupertinoIcons.back, color: primaryColor, size: 30, ), @@ -72,12 +82,12 @@ class _CustomerEditorState extends State { phoneNumberBox, DisplayText( text: widget.customer.fcsID, - labelText: getLocalString(context, "customer.fcs.id"), + labelTextKey: "customer.fcs.id", icon: FcsIDIcon(), ), DisplayText( text: widget.customer.status, - labelText: getLocalString(context, "customer.status"), + labelTextKey: "customer.status", iconData: Icons.add_alarm, ), SizedBox( @@ -89,6 +99,9 @@ class _CustomerEditorState extends State { getLocalString( context, "customer.invitation.request.confirm"), callack: _add) + : Container(), + widget.customer.joined || widget.customer.disabled + ? enableBox : Container() ], ), @@ -117,4 +130,23 @@ class _CustomerEditorState extends State { } }); } + + _enable(bool enabled) async { + setState(() { + _isLoading = true; + }); + if (widget.customer == null) return; + CustomerModel customerModel = + Provider.of(context, listen: false); + try { + await customerModel.enableUser(widget.customer, enabled); + Navigator.pop(context); + } catch (e) { + showMsgDialog(context, "Error", e.toString()); + } finally { + setState(() { + _isLoading = false; + }); + } + } } diff --git a/lib/fcs/common/pages/customer/customer_list.dart b/lib/pages/customer/customer_list.dart similarity index 77% rename from lib/fcs/common/pages/customer/customer_list.dart rename to lib/pages/customer/customer_list.dart index b0164a5..4e706df 100644 --- a/lib/fcs/common/pages/customer/customer_list.dart +++ b/lib/pages/customer/customer_list.dart @@ -1,18 +1,16 @@ -import 'package:fcs/fcs/common/domain/constants.dart'; -import 'package:fcs/fcs/common/domain/entities/user.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/fcs/common/pages/chat/message_detail.dart'; -import 'package:fcs/fcs/common/pages/chat/model/message_model.dart'; -import 'package:fcs/fcs/common/pages/customer/customer_editor.dart'; -import 'package:fcs/fcs/common/pages/customer/model/customer_model.dart'; -import 'package:fcs/fcs/common/pages/model/main_model.dart'; -import 'package:fcs/fcs/common/pages/user_search/user_serach.dart'; -import 'package:fcs/fcs/common/pages/widgets/bottom_up_page_route.dart'; -import 'package:fcs/fcs/common/pages/widgets/local_text.dart'; -import 'package:fcs/fcs/common/pages/widgets/progress.dart'; +import 'package:fcs/domain/constants.dart'; +import 'package:fcs/domain/entities/user.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/chat/message_detail.dart'; +import 'package:fcs/pages/chat/model/message_model.dart'; +import 'package:fcs/pages/customer/customer_editor.dart'; +import 'package:fcs/pages/customer/model/customer_model.dart'; +import 'package:fcs/pages/main/model/main_model.dart'; +import 'package:fcs/pages/user_search/user_serach.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/progress.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_icons/flutter_icons.dart'; import 'package:intl/intl.dart'; import 'package:provider/provider.dart'; import 'package:share/share.dart'; @@ -59,7 +57,8 @@ class _CustomerListState extends State { ), floatingActionButton: FloatingActionButton.extended( onPressed: () { - Navigator.of(context).push(BottomUpPageRoute(InvitationCreate())); + Navigator.of(context).push( + CupertinoPageRoute(builder: (context) => InvitationCreate())); }, icon: Icon(Icons.add), label: LocalText(context, "invitation.new", color: Colors.white), @@ -147,6 +146,26 @@ class _CustomerListState extends State { ), ), ), + customer.status == user_invited_status + ? Padding( + padding: const EdgeInsets.only(right: 8.0), + child: FlatButton( + onPressed: () => _share(customer), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(18.0), + side: BorderSide(color: primaryColor)), + child: Row( + children: [ + Text( + "Share", + style: TextStyle(fontSize: 12), + ), + Icon(Icons.share, color: primaryColor), + ], + ), + ), + ) + : Container(), Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ @@ -159,23 +178,6 @@ class _CustomerListState extends State { child: Text(customer.getLastMessageTime), ), getCount(customer), - customer.status == user_invited_status - ? FlatButton( - onPressed: () => _share(customer), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(18.0), - side: BorderSide(color: primaryColor)), - child: Row( - children: [ - Text( - "Share", - style: TextStyle(fontSize: 12), - ), - Icon(Icons.share, color: primaryColor), - ], - ), - ) - : Container(), ], ), ], @@ -197,14 +199,14 @@ class _CustomerListState extends State { } Widget _status(String status) { - return user_requested_status == status + return user_requested_status == status || user_disabled_status == status ? Text(status, style: TextStyle(color: primaryColor, fontSize: 14)) : Container(); } _select(User customer) { - Navigator.of(context) - .push(BottomUpPageRoute(CustomerEditor(customer: customer))); + Navigator.of(context).push(CupertinoPageRoute( + builder: (context) => CustomerEditor(customer: customer))); } _gotoMsg(User customer) { @@ -212,11 +214,12 @@ class _CustomerListState extends State { Provider.of(context, listen: false); messageModel.initQuery(customer.id); Navigator.of(context) - .push(BottomUpPageRoute(MessageDetail( - receiverID: customer.id, - receiverName: customer.name, - messageModel: messageModel, - ))) + .push(CupertinoPageRoute( + builder: (context) => MessageDetail( + receiverID: customer.id, + receiverName: customer.name, + messageModel: messageModel, + ))) .then((value) { if (customer.fcsUnseenCount > 0) { messageModel.seenMessages(customer.id, false); diff --git a/lib/fcs/common/pages/customer/invitation_create.dart b/lib/pages/customer/invitation_create.dart similarity index 88% rename from lib/fcs/common/pages/customer/invitation_create.dart rename to lib/pages/customer/invitation_create.dart index fea749a..1d3c1fc 100644 --- a/lib/fcs/common/pages/customer/invitation_create.dart +++ b/lib/pages/customer/invitation_create.dart @@ -1,10 +1,11 @@ import 'package:country_code_picker/country_code_picker.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/fcs/common/localization/app_translations.dart'; -import 'package:fcs/fcs/common/pages/customer/model/customer_model.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/fcs/common/pages/widgets/local_text.dart'; -import 'package:fcs/widget/progress.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/customer/model/customer_model.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/widgets/input_text.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; @@ -33,6 +34,11 @@ class _InvitationCreateState extends State { @override Widget build(BuildContext context) { + final nameBox = InputText( + labelTextKey: 'customer.name', + iconData: Icons.person, + controller: _nameController); + return LocalProgress( inAsyncCall: _isLoading, child: Scaffold( @@ -42,14 +48,14 @@ class _InvitationCreateState extends State { centerTitle: true, leading: new IconButton( icon: new Icon( - Icons.close, + CupertinoIcons.back, color: primaryColor, ), onPressed: () => Navigator.of(context).pop(), ), title: LocalText( context, - "invitation.new", + "invitation.form.title", fontSize: 20, color: primaryColor, ), @@ -58,8 +64,7 @@ class _InvitationCreateState extends State { padding: EdgeInsets.all(18), child: ListView( children: [ - fcsInput(getLocalString(context, "customer.name"), Icons.person, - controller: _nameController, autoFocus: false), + nameBox, SizedBox(height: 10), Row( children: [ @@ -77,7 +82,7 @@ class _InvitationCreateState extends State { child: CountryCodePicker( onChanged: _countryChange, initialSelection: dialCode, - countryFilter: ['+95', '+1'], + countryFilter: ['mm', 'us'], showCountryOnly: false, showOnlyCountryWhenClosed: false, alignLeft: false, diff --git a/lib/fcs/common/pages/customer/invitation_editor.dart b/lib/pages/customer/invitation_editor.dart similarity index 84% rename from lib/fcs/common/pages/customer/invitation_editor.dart rename to lib/pages/customer/invitation_editor.dart index fef5933..837f704 100644 --- a/lib/fcs/common/pages/customer/invitation_editor.dart +++ b/lib/pages/customer/invitation_editor.dart @@ -1,9 +1,10 @@ -import 'package:fcs/fcs/common/domain/entities/user.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/fcs/common/pages/customer/model/customer_model.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/fcs/common/pages/widgets/display_text.dart'; -import 'package:fcs/fcs/common/pages/widgets/progress.dart'; +import 'package:fcs/domain/entities/user.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/customer/model/customer_model.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/widgets/display_text.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; @@ -31,7 +32,7 @@ class _InvitationEditorState extends State { Expanded( child: DisplayText( text: widget.customer.phoneNumber, - labelText: getLocalString(context, "customer.phone"), + labelTextKey: getLocalString(context, "customer.phone"), iconData: Icons.phone, )), IconButton( @@ -49,7 +50,7 @@ class _InvitationEditorState extends State { centerTitle: true, leading: new IconButton( icon: new Icon( - Icons.close, + CupertinoIcons.back, color: primaryColor, size: 30, ), diff --git a/lib/fcs/common/pages/customer/model/customer_model.dart b/lib/pages/customer/model/customer_model.dart similarity index 72% rename from lib/fcs/common/pages/customer/model/customer_model.dart rename to lib/pages/customer/model/customer_model.dart index 7e9d524..1413f3a 100644 --- a/lib/fcs/common/pages/customer/model/customer_model.dart +++ b/lib/pages/customer/model/customer_model.dart @@ -1,10 +1,10 @@ import 'dart:async'; import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:fcs/fcs/common/domain/constants.dart'; -import 'package:fcs/fcs/common/domain/entities/user.dart'; -import 'package:fcs/fcs/common/pages/model/base_model.dart'; -import 'package:fcs/fcs/common/services/services.dart'; +import 'package:fcs/data/services/services.dart'; +import 'package:fcs/domain/constants.dart'; +import 'package:fcs/domain/entities/user.dart'; +import 'package:fcs/pages/main/model/base_model.dart'; import 'package:logging/logging.dart'; class CustomerModel extends BaseModel { @@ -15,8 +15,9 @@ class CustomerModel extends BaseModel { StreamSubscription customerListener; StreamSubscription invitationListener; - void initUser(user) async { - super.initUser(user); + @override + void privilegeChanged() { + super.privilegeChanged(); _loadCustomer(); _loadInvitations(); } @@ -94,4 +95,27 @@ class CustomerModel extends BaseModel { var snap = await Firestore.instance.collection(path).document(id).get(); return User.fromMap(snap.data, snap.documentID); } + + Future> getInvoiceUsers(String fcsShipmentID) async { + List users = []; + try { + var snaps = await Firestore.instance + .collection( + "/$fcs_shipment_collection/$fcsShipmentID/$user_collection") + .where("pending_invoice_carton_count", isGreaterThan: 0) + .getDocuments(source: Source.server); + users = snaps.documents.map((documentSnapshot) { + var user = + User.fromMap(documentSnapshot.data, documentSnapshot.documentID); + return user; + }).toList(); + } catch (e) { + log.warning("Error!! $e"); + } + return users; + } + + Future enableUser(User user, bool enabled) { + return Services.instance.userService.enableUser(user.id, enabled); + } } diff --git a/lib/pages/customer_editor.dart b/lib/pages/customer_editor.dart deleted file mode 100644 index 004dbdd..0000000 --- a/lib/pages/customer_editor.dart +++ /dev/null @@ -1,362 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/employee_model.dart'; -import 'package:fcs/model/language_model.dart'; -import 'package:fcs/model/main_model.dart'; -import 'package:fcs/model/user_model.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/role.dart'; -import 'package:fcs/vo/user.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:fcs/widget/progress.dart'; -import '../fcs/common/pages/util.dart'; - -typedef void FindCallBack(); - -class CustomerEditor extends StatefulWidget { - final User customer; - const CustomerEditor({this.customer}); - @override - _CustomerEditorState createState() => _CustomerEditorState(); -} - -class _CustomerEditorState extends State { - TextEditingController _name = new TextEditingController(); - TextEditingController _phone = new TextEditingController(); - TextEditingController _phoneInput = new TextEditingController(); - TextEditingController _status = new TextEditingController(); - - final _formKey = GlobalKey(); - bool _isLoading = false; - String currentBizId; - bool isSend = false; - User user; - User selectedUser; - List privileges = []; - - @override - void initState() { - super.initState(); - // privileges = Provider.of(context, listen: false).privileges; - if (widget.customer != null) { - _name.text = widget.customer.name; - _phone.text = widget.customer.phone; - _status.text = widget.customer.status; - // privileges.forEach((p) => widget.employee.privilegeIds.contains(p.id) - // ? p.isChecked = true - // : p.isChecked = false); - } - } - - List showprivilegeList(BuildContext context, UserModel userModel) { - return privileges.map((p) { - return new ListTile( - title: new Row( - children: [ - new Checkbox( - value: p.isChecked == null ? false : p.isChecked, - activeColor: primaryColor, - onChanged: (bool value) { - setState(() { - p.isChecked = value; - }); - }), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - new Text( - p.name, - style: TextStyle( - fontSize: 15.0, - ), - ), - // Container( - // width: MediaQuery.of(context).size.width * 0.5, - // child: new Text( - // userModel.getPrivileges[index].desc, - // style: - // TextStyle(fontSize: 12.0, color: Colors.grey[600]), - // ), - // ), - ], - ), - ], - )); - }).toList(); - } - - Widget phoneInputbox(BuildContext context, FindCallBack findCallBack) { - var languageModel = Provider.of(context); - return Container( - padding: EdgeInsets.only(top: 10), - child: Stack( - alignment: const Alignment(1.2, 1.0), - children: [ - TextFormField( - controller: _phoneInput, - autofocus: false, - cursorColor: primaryColor, - keyboardType: TextInputType.phone, - style: textStyle, - decoration: new InputDecoration( - labelText: AppTranslations.of(context).text('employee.phone'), - labelStyle: languageModel.isEng ? labelStyle : labelStyleMM, - icon: Icon( - Icons.phone, - color: primaryColor, - ), - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - ), - ), - new FlatButton( - onPressed: () { - this.isSend = true; - findCallBack(); - }, - child: new Icon( - Icons.search, - size: 25, - )) - ], - )); - } - - @override - Widget build(BuildContext context) { - var userModel = Provider.of(context); - MainModel mainModel = Provider.of(context); - - final namebox = TextFormField( - controller: _name, - autofocus: false, - readOnly: true, - cursorColor: primaryColor, - decoration: new InputDecoration( - border: InputBorder.none, - focusedBorder: InputBorder.none, - icon: Icon( - Icons.person, - color: primaryColor, - ), - ), - ); - - final displayPhoneNo = TextFormField( - controller: _phone, - autofocus: false, - readOnly: true, - cursorColor: primaryColor, - decoration: new InputDecoration( - border: InputBorder.none, - focusedBorder: InputBorder.none, - icon: Icon( - Icons.phone, - color: primaryColor, - ), - ), - ); - - var phoneNumberBox = Row( - children: [ - Expanded(child: displayPhoneNo), - Expanded( - child: InkWell( - onTap: () => call(context, _phone.text), - child: Icon( - Icons.open_in_new, - color: Colors.grey, - size: 15, - ), - ), - ), - ], - ); - - final statusbox = TextFormField( - controller: _status, - autofocus: false, - readOnly: true, - cursorColor: primaryColor, - decoration: new InputDecoration( - border: InputBorder.none, - focusedBorder: InputBorder.none, - icon: Icon( - Icons.av_timer, - color: primaryColor, - ), - ), - ); - - final updateButton = Container( - padding: EdgeInsets.only(top: 40), - child: Container( - height: 45.0, - decoration: BoxDecoration( - color: primaryColor, - shape: BoxShape.rectangle, - ), - child: ButtonTheme( - minWidth: 900.0, - height: 100.0, - child: FlatButton( - onPressed: () {}, - child: LocalText( - context, - 'customer.update', - color: Colors.white, - fontSize: 16, - fontWeight: FontWeight.bold, - ), - ), - ), - ), - ); - - final addButton = Container( - padding: EdgeInsets.only(top: 40), - child: Container( - height: 45.0, - decoration: BoxDecoration( - color: primaryColor, - shape: BoxShape.rectangle, - ), - child: ButtonTheme( - minWidth: 900.0, - height: 100.0, - child: FlatButton( - onPressed: () {}, - child: LocalText( - context, - 'customer.add', - color: Colors.white, - fontSize: 16, - fontWeight: FontWeight.bold, - ), - ), - ), - ), - ); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - centerTitle: true, - leading: new IconButton( - icon: new Icon(Icons.close), - onPressed: () => Navigator.of(context).pop(), - ), - backgroundColor: primaryColor, - title: LocalText( - context, - "customer.form.title", - fontSize: 20, - color: Colors.white, - ), - // actions: [ - // widget.customer == null || !mainModel.showHistoryBtn() - // ? Container() - // : IconButton( - // icon: Icon(Icons.history), - // onPressed: () { - // Navigator.push( - // context, - // MaterialPageRoute( - // builder: (context) => DocumentLogPage( - // docID: widget.customer.docID)), - // ); - // }, - // ), - // ], - ), - body: ListView( - shrinkWrap: true, - padding: EdgeInsets.only(left: 24.0, right: 24.0), - children: [ - widget.customer == null - ? phoneInputbox(context, () => _findUser(context)) - : phoneNumberBox, - widget.customer == null - ? this.isSend ? namebox : Container() - : namebox, - statusbox, - // widget.customer == null ? addButton : updateButton, - SizedBox( - height: 20, - ) - ], - ), - )); - } - - _add(BuildContext context) async { - if (selectedUser == null) return; - setState(() { - _isLoading = true; - }); - var employeeModel = Provider.of(context); - try { - await employeeModel.updatePrivileges( - this.selectedUser.docID, privilegesIDs()); - Navigator.pop(context); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - setState(() { - _isLoading = false; - }); - } - } - - List privilegesIDs() { - return this.privileges.where((p) => p.isChecked).map((p) => p.id).toList(); - } - - _save() async { - setState(() { - _isLoading = true; - }); - if (widget.customer == null) return; - var employeeModel = Provider.of(context); - try { - await employeeModel.updatePrivileges( - widget.customer.docID, privilegesIDs()); - Navigator.pop(context); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - setState(() { - _isLoading = false; - }); - } - } - - _findUser(BuildContext context) async { - var userModel = Provider.of(context); - setState(() { - _isLoading = true; - }); - try { - selectedUser = await userModel.findUser(_phoneInput.text); - setState(() { - isSend = true; - _name.text = selectedUser.name; - if (selectedUser.privilegeIds != null) { - privileges.forEach((p) => selectedUser.privilegeIds.contains(p.id) - ? p.isChecked = true - : p.isChecked = false); - } - }); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - setState(() { - _isLoading = false; - }); - } - } -} diff --git a/lib/pages/customer_list.dart b/lib/pages/customer_list.dart deleted file mode 100644 index d61f64c..0000000 --- a/lib/pages/customer_list.dart +++ /dev/null @@ -1,143 +0,0 @@ -import 'package:fcs/model/customer_model.dart'; -import 'package:fcs/pages/search_page.dart'; -import 'package:fcs/widget/bottom_up_page_route.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_icons/flutter_icons.dart'; -import 'package:intl/intl.dart'; - -import 'package:provider/provider.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/widget/progress.dart'; - -import '../fcs/common/helpers/theme.dart'; -import '../vo/user.dart'; -import '../widget/local_text.dart'; -import 'customer_editor.dart'; -import 'invitation_page.dart'; -import '../fcs/common/pages/util.dart'; - -class CustomerList extends StatefulWidget { - @override - _CustomerListState createState() => _CustomerListState(); -} - -class _CustomerListState extends State { - var dateFormatter = new DateFormat('dd MMM yyyy - hh:mm:ss a'); - final double dotSize = 15.0; - bool _isLoading = false; - - @override - Widget build(BuildContext context) { - var customerModel = Provider.of(context); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - centerTitle: true, - leading: new IconButton( - icon: new Icon(Icons.close), - onPressed: () => Navigator.of(context).pop(), - ), - actions: [ - IconButton( - icon: Icon( - Icons.search, - color: Colors.white, - ), - iconSize: 30, - onPressed: () => showPlacesSearch(context), - ), - ], - backgroundColor: primaryColor, - title: LocalText( - context, - 'customer.list.title', - color: Colors.white, - fontSize: 20, - ), - ), - floatingActionButton: FloatingActionButton.extended( - onPressed: () { - Navigator.of(context).push(BottomUpPageRoute(InvitationPage())); - }, - icon: Icon(Icons.add), - label: Text(AppTranslations.of(context).text("customer.invite")), - backgroundColor: primaryColor, - ), - body: new ListView.separated( - separatorBuilder: (context, index) => Divider( - color: Colors.black, - ), - scrollDirection: Axis.vertical, - padding: EdgeInsets.only(left: 15, right: 15, top: 15), - shrinkWrap: true, - itemCount: customerModel.customers.length, - itemBuilder: (BuildContext context, int index) { - User user = customerModel.customers[index]; - return Stack( - children: [ - InkWell( - onTap: () { - Navigator.of(context).push( - BottomUpPageRoute(CustomerEditor(customer: user))); - }, - child: Row( - children: [ - Expanded( - child: new Padding( - padding: const EdgeInsets.symmetric(vertical: 10.0), - child: new Row( - children: [ - new Padding( - padding: new EdgeInsets.symmetric( - horizontal: 32.0 - dotSize / 2), - child: Icon( - Feather.user, - color: primaryColor, - size: 40, - ), - ), - new Expanded( - child: new Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - new Text( - user.name, - style: new TextStyle( - fontSize: 15.0, - color: primaryColor), - ), - Padding( - padding: - const EdgeInsets.only(top: 8.0), - child: new Text( - user.phoneNumber, - style: new TextStyle( - fontSize: 15.0, - color: Colors.grey), - ), - ), - ], - ), - ), - ], - ), - ), - ), - Padding( - padding: const EdgeInsets.only(right: 10), - child: getStatus(user.status), - ), - ], - ), - ), - ], - ); - }), - ), - ); - } -} diff --git a/lib/pages/delivery/delivery_info.dart b/lib/pages/delivery/delivery_info.dart new file mode 100644 index 0000000..dc0a5c4 --- /dev/null +++ b/lib/pages/delivery/delivery_info.dart @@ -0,0 +1,313 @@ +import 'package:fcs/domain/constants.dart'; +import 'package:fcs/domain/entities/cargo_type.dart'; +import 'package:fcs/domain/entities/carton.dart'; +import 'package:fcs/domain/entities/package.dart'; +import 'package:fcs/domain/vo/delivery_address.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/carton/carton_package_table.dart'; +import 'package:fcs/pages/carton/model/carton_model.dart'; +import 'package:fcs/pages/carton/widgets.dart'; +import 'package:fcs/pages/delivery/model/delivery_model.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/package/model/package_model.dart'; +import 'package:fcs/pages/rates/model/shipment_rate_model.dart'; +import 'package:fcs/pages/widgets/defalut_delivery_address.dart'; +import 'package:fcs/pages/widgets/display_text.dart'; +import 'package:fcs/pages/widgets/fcs_id_icon.dart'; +import 'package:fcs/pages/widgets/length_picker.dart'; +import 'package:fcs/pages/widgets/local_button.dart'; +import 'package:fcs/pages/widgets/local_radio_buttons.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/local_title.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_icons/flutter_icons.dart'; +import 'package:intl/intl.dart'; +import 'package:provider/provider.dart'; + +final DateFormat dateFormat = DateFormat("d MMM yyyy"); + +class DeliveryInfo extends StatefulWidget { + final Carton box; + DeliveryInfo({this.box}); + + @override + _DeliveryInfoState createState() => _DeliveryInfoState(); +} + +class _DeliveryInfoState extends State { + bool _isLoading = false; + Carton _box; + String _selectedCartonType; + List _packages = []; + List _mixBoxes = []; + Carton _selectedShipmentBox = new Carton(); + List _cargoTypes = []; + DeliveryAddress _deliveryAddress = new DeliveryAddress(); + TextEditingController _widthController = new TextEditingController(); + TextEditingController _heightController = new TextEditingController(); + TextEditingController _lengthController = new TextEditingController(); + double volumetricRatio = 0; + double shipmentWeight = 0; + + bool isMixBox; + bool isFromShipments; + bool isFromPackages; + bool isSmallBag; + bool isEdiable; + + @override + void initState() { + super.initState(); + _box = widget.box; + _selectedCartonType = _box.cartonType; + + //for shipment weight + volumetricRatio = Provider.of(context, listen: false) + .rate + .volumetricRatio; + _lengthController.addListener(_calShipmentWeight); + _widthController.addListener(_calShipmentWeight); + _heightController.addListener(_calShipmentWeight); + + _updateBoxData(); + _loadPackages(); + } + + _updateBoxData() { + _widthController.text = _box.width.toString(); + _heightController.text = _box.height.toString(); + _lengthController.text = _box.length.toString(); + _cargoTypes = _box.cargoTypes; + _deliveryAddress = _box.deliveryAddress; + isMixBox = _box.cartonType == carton_mix_box; + isFromShipments = _box.cartonType == carton_from_shipments; + isFromPackages = _box.cartonType == carton_from_packages; + isSmallBag = _box.cartonType == carton_small_bag; + isEdiable = !isMixBox && + (isFromPackages || isSmallBag) && + _box.status == carton_packed_status; + } + + _loadPackages() async { + if (!isFromPackages && !isSmallBag) return; + + if (_box.cartonType == carton_from_packages && _box.userID == null) return; + PackageModel packageModel = + Provider.of(context, listen: false); + List packages = await packageModel.getPackages(_box.userID, [ + package_processed_status, + package_packed_status, + package_shipped_status, + package_delivered_status + ]); + packages = packages.where((p) => _box.packageIDs.contains(p.id)).toList(); + packages.forEach((p) { + p.isChecked = true; + }); + + setState(() { + _box.packages = packages; + }); + } + + _calShipmentWeight() { + double l = double.parse(_lengthController.text, (s) => 0); + double w = double.parse(_widthController.text, (s) => 0); + double h = double.parse(_heightController.text, (s) => 0); + setState(() { + shipmentWeight = l * w * h / volumetricRatio; + }); + } + + @override + void dispose() { + super.dispose(); + } + + final DateFormat dateFormat = DateFormat("d MMM yyyy"); + + @override + Widget build(BuildContext context) { + var cartonModel = Provider.of(context); + + final cartonTypeBox = LocalRadioButtons( + readOnly: true, + values: cartonModel.cartonTypesInfo, + selectedValue: + _box.isShipmentCarton ? carton_from_shipments : _box.cartonType); + final shipmentBox = DisplayText( + text: _box.fcsShipmentNumber, + labelTextKey: "box.fcs_shipment_num", + iconData: Ionicons.ios_airplane, + ); + final fcsIDBox = DisplayText( + text: _box.fcsID == null ? "" : _box.fcsID, + labelTextKey: "box.fcs.id", + icon: FcsIDIcon(), + ); + + final customerNameBox = DisplayText( + text: _box.userName == null ? "" : _box.userName, + labelTextKey: "box.name", + iconData: Icons.person, + ); + + final shipmentBoxTitle = Container( + padding: EdgeInsets.only(left: 15, right: 10.0, top: 20), + child: Row( + children: [ + Expanded( + child: + LocalText(context, 'box.shipment_number', color: Colors.grey), + ), + LocalText(context, 'box.shipment.desc', color: Colors.grey), + ], + ), + ); + + final shipmentBoxRow = Container( + padding: EdgeInsets.only(left: 15.0, right: 10.0, top: 5.0, bottom: 5.0), + child: Row( + children: [ + Expanded( + child: new Text( + _selectedShipmentBox.shipmentNumber == null + ? "" + : _selectedShipmentBox.shipmentNumber, + style: textStyle, + )), + new Text( + _selectedShipmentBox.desc == null ? "" : _selectedShipmentBox.desc, + style: textStyle, + ), + ], + ), + ); + + final lengthBox = LengthPicker( + controller: _lengthController, + lableKey: "box.length", + isReadOnly: true, + ); + final widthBox = LengthPicker( + controller: _widthController, + lableKey: "box.width", + isReadOnly: true, + ); + final heightBox = LengthPicker( + controller: _heightController, + lableKey: "box.height", + isReadOnly: true, + ); + + final dimBox = Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(right: 8.0), + child: Icon(FontAwesome.arrow_circle_right, color: primaryColor), + ), + SizedBox(child: lengthBox, width: 80), + SizedBox(child: widthBox, width: 80), + SizedBox(child: heightBox, width: 80), + ], + ); + + final shipmentWeightBox = DisplayText( + text: shipmentWeight != null ? shipmentWeight.toStringAsFixed(0) : "", + labelTextKey: "box.shipment_weight", + iconData: MaterialCommunityIcons.weight, + ); + final mixCartonNumberBox = DisplayText( + text: _box.mixCartonNumber, + labelTextKey: "box.mix.carton", + iconData: MaterialCommunityIcons.package, + ); + final deliverBtn = LocalButton( + textKey: "delivery.deliver.btn", + callBack: _deliver, + ); + + return LocalProgress( + inAsyncCall: _isLoading, + child: Scaffold( + appBar: AppBar( + centerTitle: true, + leading: new IconButton( + icon: new Icon(CupertinoIcons.back, color: primaryColor, size: 30), + onPressed: () => Navigator.of(context).pop(), + ), + shadowColor: Colors.transparent, + backgroundColor: Colors.white, + title: LocalText( + context, + "delivery.info.title", + fontSize: 20, + color: primaryColor, + ), + ), + body: Padding( + padding: const EdgeInsets.all(10.0), + child: ListView(children: [ + Center(child: getCartonNumberStatus(context, _box)), + LocalTitle(textKey: "box.type.title"), + cartonTypeBox, + LocalTitle(textKey: "box.shipment_info"), + shipmentBox, + isSmallBag ? mixCartonNumberBox : Container(), + isMixBox ? Container() : fcsIDBox, + isMixBox ? Container() : customerNameBox, + isFromPackages || isSmallBag + ? CartonPackageTable( + packages: _box.packages, + ) + : Container(), + isMixBox + ? Container() + : LocalTitle(textKey: "box.delivery_address"), + isMixBox + ? Container() + : DefaultDeliveryAddress( + deliveryAddress: _deliveryAddress, + labelKey: "box.delivery_address", + ), + SizedBox( + height: 20, + ), + !isMixBox && _box.status == carton_shipped_status + ? deliverBtn + : Container(), + SizedBox( + height: 20, + ) + ]), + ), + ), + ); + } + + _deliver() { + showConfirmDialog(context, "delivery.deliver.confirm", () { + _deliverCarton(); + }); + } + + _deliverCarton() async { + setState(() { + _isLoading = true; + }); + try { + var deliveryModel = Provider.of(context, listen: false); + await deliveryModel.deliver(widget.box); + Navigator.pop(context, true); + } catch (e) { + showMsgDialog(context, "Error", e.toString()); + } finally { + setState(() { + _isLoading = false; + }); + } + } +} diff --git a/lib/pages/delivery/delivery_item.dart b/lib/pages/delivery/delivery_item.dart deleted file mode 100644 index c02418f..0000000 --- a/lib/pages/delivery/delivery_item.dart +++ /dev/null @@ -1,519 +0,0 @@ -import 'dart:io'; -import 'dart:typed_data'; - -import 'package:flutter/material.dart'; -import 'package:flutter/widgets.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; -import 'package:quiver/async.dart'; -import 'package:fcs/model/do_model.dart'; -import 'package:fcs/model/language_model.dart'; -import 'package:fcs/model/main_model.dart'; -import 'package:fcs/model/po_model.dart'; -import 'package:fcs/model/product_model.dart'; -import 'package:fcs/pages/do/photo_page.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/do.dart'; -import 'package:fcs/widget/img_file.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:fcs/widget/my_data_table.dart'; -import 'package:fcs/widget/number_cell.dart'; -import 'package:fcs/widget/progress.dart'; - -import '../../fcs/common/pages/util.dart'; - -class DeliveryItem extends StatefulWidget { - final DOSubmission doSubmission; - const DeliveryItem({this.doSubmission}); - @override - _DeliveryItemState createState() => _DeliveryItemState(); -} - -class _DeliveryItemState extends State { - var dateFormatter = new DateFormat('dd MMM yyyy'); - final numberFormatter = new NumberFormat("#,###"); - - bool _isLoading = false; - TextEditingController _date = new TextEditingController(); - TextEditingController _number = new TextEditingController(); - TextEditingController _licence = new TextEditingController(); - TextEditingController _driver = new TextEditingController(); - TextEditingController _carNo = new TextEditingController(); - TextEditingController _type = new TextEditingController(); - TextEditingController _name = new TextEditingController(); - TextEditingController _bizName = new TextEditingController(); - TextEditingController _storage = new TextEditingController(); - TextEditingController _comment = new TextEditingController(); - DOSubmission doObj = DOSubmission(); - int _count; - DateTime _result; - File storageChargeFile; - File receiptImageFile; - - @override - void initState() { - super.initState(); - - var mainModel = Provider.of(context, listen: false); - var doModel = Provider.of(context, listen: false); - - doObj = widget.doSubmission; - _date.text = doObj.deliveryDate != null - ? dateFormatter.format(doObj.deliveryDate) - : ""; - _number.text = doObj.doNumber.toString(); - _licence.text = doObj.driverLicenseNumber; - _driver.text = doObj.driverName; - _carNo.text = doObj.carNo; - _type.text = doObj.type; - _name.text = doObj.userName; - _bizName.text = doObj.bizName; - _storage.text = doObj.storageCharge == null - ? "" - : numberFormatter.format(doObj.storageCharge); - _comment.text = doObj.comment; - - if (doObj.deliveryStatus == 'initiated') { - _count = doModel.timber; - Duration diff = DateTime.now().difference(doObj.deliveryInitiatedTime); - - if (diff.inMinutes < mainModel.setting.deliveryStartWaitMin) { - var time = mainModel.setting.deliveryStartWaitMin - diff.inMinutes; - new CountdownTimer( - new Duration(minutes: time), new Duration(seconds: 1)) - .listen((data) { - if (mounted) { - setState(() { - _count = data.remaining.inSeconds; - doModel.addTimber(_count); - }); - } - }); - } - } else { - _count = 0; - } - _load(); - } - - @override - void dispose() { - super.dispose(); - } - - @override - Widget build(BuildContext context) { - MainModel mainModel = Provider.of(context); - bool isBuyer = mainModel.user.isBuyer(); - String formattedTime; - if (doObj.deliveryStatus == 'initiated') { - _result = DateTime( - doObj.deliveryInitiatedTime.year, - doObj.deliveryInitiatedTime.month, - doObj.deliveryInitiatedTime.day, - doObj.deliveryInitiatedTime.hour, - doObj.deliveryInitiatedTime.minute, - _count); - formattedTime = DateFormat.ms().format(_result); - } - - final dateBox = Container( - padding: EdgeInsets.only(left: 20, top: 15), - child: Row( - children: [ - LocalText(context, "do.date"), - Container( - padding: EdgeInsets.only(left: 10), - child: Text( - _date.text, - style: textStyle, - ), - ) - ], - ), - ); - - final numberBox = Container( - padding: EdgeInsets.only(left: 20, top: 5), - child: Row( - children: [ - LocalText(context, "do.do_num"), - Container( - padding: EdgeInsets.only(left: 10), - child: Text( - _number.text, - style: textStyle, - ), - ) - ], - ), - ); - final driverBox = Container( - padding: EdgeInsets.only(left: 20, top: 5), - child: Row( - children: [ - LocalText(context, "do.driver"), - Container( - padding: EdgeInsets.only(left: 10), - child: Text( - _driver.text, - style: textStyle, - ), - ) - ], - ), - ); - final carNoBox = Container( - padding: EdgeInsets.only(left: 20, top: 5), - child: Row( - children: [ - LocalText(context, "do.car"), - Container( - padding: EdgeInsets.only(left: 10), - child: Text( - _carNo.text, - style: textStyle, - ), - ) - ], - ), - ); - final licenceBox = Container( - padding: EdgeInsets.only(left: 20, top: 5), - child: Row( - children: [ - LocalText(context, "do.licence"), - ImageFile( - enabled: false, - title: "Image", - initialImgUrl: doObj.driverLicenceUrl, - onFile: (file) {}), - ], - ), - ); - final statusBox = Container( - padding: EdgeInsets.only(left: 20, top: 5), - child: Row( - children: [ - LocalText(context, "do.status"), - Container( - padding: EdgeInsets.only(left: 10), - child: Text( - doObj.status, - style: doObj.isPending - ? textHighlightBlueStyle - : doObj.isApproved - ? textHighlightGreenStyle - : textHighlightRedStyle, - ), - ), - ], - ), - ); - final deliveryStatusBox = Container( - padding: EdgeInsets.only(left: 20, top: 5), - child: Row( - children: [ - LocalText(context, "do.delivery.status"), - Container( - padding: EdgeInsets.only(left: 10, right: 15), - child: Text( - doObj.getDeliveryStatus, - style: textStyle, - ), - ), - doObj.deliveryStatus == 'initiated' - ? Text( - "(can start in $formattedTime)", - style: TextStyle(fontSize: 15, fontWeight: FontWeight.bold), - ) - : Container() - ], - ), - ); - - final typeBox = Container( - padding: EdgeInsets.only(left: 20, top: 5), - child: Row( - children: [ - LocalText(context, "do.type"), - Container( - padding: EdgeInsets.only(left: 20), - child: Text( - _type.text, - style: textStyle, - ), - ) - ], - ), - ); - - final userNameBox = Container( - padding: EdgeInsets.only(top: 5, left: 20), - child: Row( - children: [ - LocalText(context, "do.name"), - Container( - padding: EdgeInsets.only(left: 20), - child: Text( - _name.text, - style: textStyle, - ), - ) - ], - ), - ); - - final bizNameBox = Container( - padding: EdgeInsets.only(left: 20, top: 5), - child: Row( - children: [ - LocalText(context, "do.biz"), - Container( - padding: EdgeInsets.only(left: 20), - child: Text( - _bizName.text, - style: textStyle, - ), - ) - ], - ), - ); - - final receiptImagebox = Container( - padding: EdgeInsets.only(left: 20, top: 0), - child: Row(children: [ - LocalText(context, "do.receipt"), - Container( - padding: EdgeInsets.only(left: 10), - child: ImageFile( - enabled: true, - initialImgUrl: doObj.doReceiptUrl, - title: "Receipt File", - onFile: (file) { - this.receiptImageFile = file; - }, - ), - ), - ])); - - final storageBox = Container( - padding: EdgeInsets.only(left: 20), - child: Row( - children: [ - LocalText(context, "do.storage_charge"), - Container( - padding: EdgeInsets.only(left: 10), - child: Text( - _storage.text, - style: textStyle, - ), - ) - ], - ), - ); - final storagePaymentBox = Container( - padding: EdgeInsets.only(left: 20), - child: Row(children: [ - LocalText(context, "do.storage_receipt"), - ImageFile( - enabled: false, - title: "Receipt File", - initialImgUrl: this.doObj.storageReceiptUrl, - onFile: (file) { - this.storageChargeFile = file; - }), - ])); - - final commentBox = Container( - padding: EdgeInsets.only(top: 5, left: 20), - child: Row( - children: [ - LocalText(context, "do.comment"), - Container( - padding: EdgeInsets.only(left: 10), - child: Text( - _comment.text, - style: textStyle, - ), - ) - ], - ), - ); - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - title: Text(AppTranslations.of(context).text("delivery"), - style: Provider.of(context).isEng - ? TextStyle(fontSize: 18) - : TextStyle(fontSize: 18, fontFamily: 'MyanmarUnicode')), - actions: [ - isBuyer - ? Container() - : PopupMenuButton( - onSelected: _select, - itemBuilder: (context) => List.from([ - PopupMenuItem( - enabled: this.doObj.isApproved, - value: 5, - child: Text("End Delivery"), - ), - ]), - ), - ], - ), - body: Container( - padding: EdgeInsets.only(left: 10, right: 10, top: 10, bottom: 10), - child: Card( - elevation: 23, - child: ListView( - children: [ - Column( - children: [ - dateBox, - Divider(), - numberBox, - Divider(), - userNameBox, - Divider(), - bizNameBox, - Divider(), - typeBox, - Divider(), - statusBox, - Divider(), - doObj.comment == null || doObj.comment == '' - ? Container() - : commentBox, - doObj.comment == null || doObj.comment == '' - ? Container() - : Divider(), - driverBox, - Divider(), - carNoBox, - Divider(), - licenceBox, - Divider(), - receiptImagebox, - Divider(), - doObj.hasStorageCharge() ? storageBox : Container(), - doObj.hasStorageCharge() ? Divider() : Container(), - doObj.hasStorageCharge() - ? storagePaymentBox - : Container(), - doObj.isApproved || doObj.isClosed - ? deliveryStatusBox - : Container(), - doObj.isApproved || doObj.isClosed - ? Divider() - : Container(), - Container( - padding: EdgeInsets.only(top: 10), - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: MyDataTable( - headingRowHeight: 40, - columnSpacing: 40, - columns: [ - MyDataColumn( - label: LocalText(context, "do.product"), - ), - MyDataColumn( - label: LocalText(context, "do.storage"), - ), - MyDataColumn( - label: LocalText(context, "do.quantity"), - numeric: true), - ], - rows: getProductRow(doObj.doLines), - ), - ), - ), - SizedBox( - height: 15, - ) - ], - ), - ], - ), - ), - )), - ); - } - - List getProductRow(List doLines) { - ProductModel productModel = Provider.of(context); - if (doLines.isNotEmpty) { - doLines.forEach((d) { - productModel.products.forEach((p) { - if (p.id == d.productID) { - d.displayOrder = p.displayOrder; - } else { - return; - } - }); - }); - - doLines.sort((p1, p2) => p1.displayOrder.compareTo(p2.displayOrder)); - } - return doLines.map((d) { - return MyDataRow( - cells: [ - MyDataCell( - new Text( - d.productName, - style: textStyle, - ), - ), - MyDataCell( - new Text(d.storageName, style: textStyle), - ), - MyDataCell(NumberCell(d.qty)), - ], - ); - }).toList(); - } - - _select(s) { - if (s == 5) { - if (receiptImageFile == null) { - showMsgDialog(context, "Error", "Please insert delivery receipt file"); - return; - } - showConfirmDialog(context, "delivery.confirm", () { - _endDelivery(receiptImageFile); - }); - } - } - - Future _load() async { - POSubmissionModel poModel = - Provider.of(context, listen: false); - var _doSub = await poModel.loadDOLines(doObj); - setState(() { - doObj.doLines = _doSub.doLines; - }); - } - - _endDelivery(dynamic receiptFile) async { - Uint8List bytesPhoto = receiptFile.readAsBytesSync() as Uint8List; - - setState(() { - _isLoading = true; - }); - try { - DOModel doModel = Provider.of(context); - await doModel.endDelivery(doObj, bytesPhoto); - Navigator.pop(context); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - setState(() { - _isLoading = false; - }); - } - } -} diff --git a/lib/pages/delivery/delivery_list.dart b/lib/pages/delivery/delivery_list.dart index 52163de..2e148b7 100644 --- a/lib/pages/delivery/delivery_list.dart +++ b/lib/pages/delivery/delivery_list.dart @@ -1,40 +1,33 @@ +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/widgets/local_popup_menu_button.dart'; +import 'package:fcs/pages/widgets/local_popupmenu.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -import 'package:intl/intl.dart'; import 'package:provider/provider.dart'; -import 'package:fcs/model/delivery_model.dart'; -import 'package:fcs/model/language_model.dart'; -import 'package:fcs/model/main_model.dart'; -import 'package:fcs/pages/delivery/delivery_item.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/popup_menu.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:fcs/widget/popupmenu.dart'; -import 'package:fcs/widget/progress.dart'; -class DeliveryList extends StatefulWidget { +import 'delivery_list_row.dart'; +import 'model/delivery_model.dart'; + +class DeliverList extends StatefulWidget { @override - _DeliveryListState createState() => _DeliveryListState(); + _DeliverListState createState() => _DeliverListState(); } -class _DeliveryListState extends State { - var dateFormatter = new DateFormat('dd MMM yyyy'); - final double dotSize = 10.0; - DateTime _selectedDate = DateTime.now(); - String status; - int _selectedIndex = 0; - int _dateIndex = 0; +class _DeliverListState extends State { bool _isLoading = false; + var _controller = ScrollController(); @override void initState() { super.initState(); - - var doModel = Provider.of(context, listen: false); - _selectedIndex = doModel.popupMenu.index; - _dateIndex = doModel.dateIndex; - _selectedDate = doModel.selectedDate; + _controller.addListener(() async { + if (_controller.position.pixels == _controller.position.maxScrollExtent) { + Provider.of(context, listen: false).loadMore(); + } + }); + Provider.of(context, listen: false).initData(); } @override @@ -42,232 +35,78 @@ class _DeliveryListState extends State { super.dispose(); } - Future _selectDate(BuildContext context) async { - var deliveryModel = Provider.of(context); - - final DateTime picked = await showDatePicker( - context: context, - initialDate: _selectedDate, - firstDate: DateTime(2015, 8), - lastDate: DateTime(2101), - builder: (BuildContext context, Widget child) { - return Theme( - data: ThemeData.light().copyWith( - primaryColor: primaryColor, //Head background - accentColor: secondaryColor, //selection color - dialogBackgroundColor: Colors.white, //Background color - ), - child: child, - ); - }, - ); - - if (picked != null) { - var pickedDate = new DateTime(picked.year, picked.month, picked.day); - var currentDate = new DateTime( - DateTime.now().year, DateTime.now().month, DateTime.now().day); - this._dateIndex = pickedDate == currentDate ? 0 : 1; - setState(() { - _selectedDate = picked; - deliveryModel.filterData( - status, _selectedDate, _selectedIndex, _dateIndex); - }); - } - } - @override Widget build(BuildContext context) { var deliveryModel = Provider.of(context); - MainModel mainModel = Provider.of(context); - bool isBuyer = mainModel.user.isBuyer(); - var languageModle = Provider.of(context); - - return Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - title: Text( - AppTranslations.of(context).text("delivery.title"), - style: languageModle.isEng - ? TextStyle() - : TextStyle(fontFamily: 'MyanmarUnicode'), - ), - actions: [ - InkWell( - child: Container( - padding: EdgeInsets.only(top: 15), - child: Stack( - children: [ - Image.asset( - "assets/date_filter.png", - color: Colors.white, - width: 25, - ), - _dateIndex == 0 - ? Container() - : Positioned( - bottom: 15, - right: 10, - child: Container( - width: 10, - height: 10, - decoration: new BoxDecoration( - shape: BoxShape.circle, - color: secondaryColor, - ), - ), - ) - ], - ), + final popupMenu = LocalPopupMenuButton( + popmenus: [ + LocalPopupMenu( + id: 1, + textKey: "delivery.popupmenu.active", + selected: deliveryModel.selectedIndex == 1), + LocalPopupMenu( + id: 2, + textKey: "delivery.popupmenu.delivered", + selected: deliveryModel.selectedIndex == 2) + ], + popupMenuCallback: (p) => this.setState(() { + deliveryModel.selectedIndex = p.id; + }), + ); + return LocalProgress( + inAsyncCall: _isLoading, + child: DefaultTabController( + length: 2, + child: Scaffold( + appBar: AppBar( + centerTitle: true, + leading: new IconButton( + icon: new Icon(CupertinoIcons.back), + onPressed: () => Navigator.of(context).pop(), ), - onTap: () => _selectDate(context), + backgroundColor: primaryColor, + title: LocalText(context, "delivery", + color: Colors.white, fontSize: 20), + actions: [popupMenu], ), - PopupMenuButton( - elevation: 3.2, - onSelected: (selected) { - setState(() { - _selectedIndex = selected.index; - }); - if (selected.status == 'All') { - status = null; - } else { - status = selected.status; - } - deliveryModel.filterData( - status, _selectedDate, _selectedIndex, _dateIndex); - }, - icon: Container( - width: 30, - height: 30, - decoration: new BoxDecoration( - shape: BoxShape.circle, - color: Colors.white, - ), - child: Stack( - fit: StackFit.expand, - children: [ - Icon( - Icons.filter_list, - color: primaryColor, - ), - _selectedIndex != 0 - ? Positioned( - bottom: 0, - right: 0, - child: Container( - width: 10, - height: 10, - decoration: new BoxDecoration( - shape: BoxShape.circle, - color: secondaryColor, - ), - ), - ) - : Container() - ], - )), - itemBuilder: (BuildContext context) { - return deliveryStatusMenu.map((PopupMenu choice) { - return PopupMenuItem( - value: choice, - child: Row( - children: [ - Text(choice.status), - SizedBox( - width: 10, - ), - _selectedIndex != null && _selectedIndex == choice.index - ? Icon( - Icons.check, - color: Colors.grey, - ) - : Container(), - ], - ), - ); - }).toList(); - }), - ], - ), - body: LocalProgress( - inAsyncCall: _isLoading, - child: new ListView.builder( - scrollDirection: Axis.vertical, - padding: EdgeInsets.only(left: 15, right: 15, top: 15), - shrinkWrap: true, - itemCount: deliveryModel.dos.length, - itemBuilder: (BuildContext context, int index) { - return Card( - elevation: 10, - color: Colors.white, - child: Row( - children: [ - Expanded( - child: InkWell( - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => DeliveryItem( - doSubmission: deliveryModel.dos[index])), - ); - }, - child: new Padding( - padding: const EdgeInsets.symmetric(vertical: 16.0), - child: new Row( - children: [ - new Padding( - padding: new EdgeInsets.symmetric( - horizontal: 32.0 - dotSize / 2), - child: Image.asset( - "assets/truck.png", - width: 50, - height: 50, - color: primaryColor, - ), - ), - new Expanded( - child: new Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - new Text( - deliveryModel.dos[index].doNumber, - style: new TextStyle( - fontSize: 12.0, color: Colors.black), - ), - new Text( - deliveryModel.dos[index].deliveryDate == - null - ? "" - : dateFormatter.format(deliveryModel - .dos[index].deliveryDate), - style: new TextStyle( - fontSize: 14.0, color: Colors.grey), - ), - !isBuyer - ? new Text( - deliveryModel.dos[index].userName, - style: new TextStyle( - fontSize: 12.0, - color: Colors.grey), - ) - : Container() - ], - ), - ), - Container( - padding: EdgeInsets.only(right: 15), - child: - getStatus(deliveryModel.dos[index].status), - ), - ], + body: Column( + children: [ + Expanded( + child: RefreshIndicator( + child: new ListView.separated( + physics: AlwaysScrollableScrollPhysics(), + controller: _controller, + separatorBuilder: (context, index) => Divider( + color: Colors.black, + height: 1, ), - ), - ), - ), - ], + scrollDirection: Axis.vertical, + shrinkWrap: true, + itemCount: deliveryModel.cartons.length, + itemBuilder: (BuildContext context, int index) { + return DeliveryListRow( + key: ValueKey(deliveryModel.cartons[index].id), + box: deliveryModel.cartons[index]); + }), + onRefresh: () => deliveryModel.refresh(), ), - ); - }), + ), + deliveryModel.isLoading + ? Container( + padding: EdgeInsets.all(8), + color: primaryColor, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("Loading...", + style: TextStyle(color: Colors.white)), + ], + ), + ) + : Container(), + ], + ), + ), ), ); } diff --git a/lib/pages/delivery/delivery_list_row.dart b/lib/pages/delivery/delivery_list_row.dart new file mode 100644 index 0000000..16bdcac --- /dev/null +++ b/lib/pages/delivery/delivery_list_row.dart @@ -0,0 +1,96 @@ +import 'package:fcs/domain/entities/carton.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_icons/flutter_icons.dart'; +import 'package:intl/intl.dart'; + +import 'delivery_info.dart'; + +class DeliveryListRow extends StatelessWidget { + final Carton box; + DeliveryListRow({Key key, this.box}) : super(key: key); + + final double dotSize = 15.0; + final DateFormat dateFormat = new DateFormat("dd MMM yyyy"); + + @override + Widget build(BuildContext context) { + return InkWell( + onTap: () { + Navigator.push( + context, + CupertinoPageRoute(builder: (context) => DeliveryInfo(box: box)), + ); + }, + child: Container( + padding: EdgeInsets.only(left: 15, right: 15), + child: Row( + children: [ + Expanded( + child: new Padding( + padding: const EdgeInsets.symmetric(vertical: 10.0), + child: new Row( + children: [ + Container( + padding: EdgeInsets.only(left: 5, right: 10), + child: Icon( + MaterialCommunityIcons.truck_fast, + color: primaryColor, + size: 30, + ), + ), + new Expanded( + child: new Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(left: 8.0), + child: new Text( + box.cartonNumber ?? "", + style: new TextStyle( + fontSize: 15.0, color: Colors.black), + ), + ), + Padding( + padding: const EdgeInsets.only(left: 10.0, top: 10), + child: new Text( + box.userName ?? "", + style: new TextStyle( + fontSize: 15.0, color: Colors.grey), + ), + ) + ], + ), + ), + ], + ), + ), + ), + Column( + children: [ + Padding( + padding: const EdgeInsets.all(0), + child: getStatus(box.status == null ? "" : box.status), + ), + Padding( + padding: const EdgeInsets.only(left: 8.0, top: 5, bottom: 5), + child: Row( + children: [ + new Text( + "${box.actualWeight?.toString() ?? ''} lb", + style: + new TextStyle(fontSize: 15.0, color: Colors.grey), + ), + ], + ), + ), + ], + ) + ], + ), + ), + ); + } +} diff --git a/lib/pages/delivery/model/delivery_model.dart b/lib/pages/delivery/model/delivery_model.dart new file mode 100644 index 0000000..b200684 --- /dev/null +++ b/lib/pages/delivery/model/delivery_model.dart @@ -0,0 +1,116 @@ +import 'dart:async'; + +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:fcs/data/services/services.dart'; +import 'package:fcs/domain/constants.dart'; +import 'package:fcs/domain/entities/carton.dart'; +import 'package:fcs/domain/vo/message.dart'; +import 'package:fcs/helpers/paginator.dart'; +import 'package:fcs/pages/main/model/base_model.dart'; +import 'package:logging/logging.dart'; + +class DeliveryModel extends BaseModel { + final log = Logger('DeliveryModel'); + List get cartons => + _selectedIndex == 1 ? _cartons : List.from(_delivered.values); + + Paginator _delivered; + int _selectedIndex = 1; + bool isLoading = false; + List _cartons = []; + StreamSubscription listener; + + set selectedIndex(int index) { + _selectedIndex = index; + notifyListeners(); + } + + get selectedIndex => _selectedIndex; + + initData() { + _selectedIndex = 1; + _loadCartons(); + + if (_delivered != null) _delivered.close(); + _delivered = _getDelivered(); + _delivered.load(); + } + + Future _loadCartons() async { + if (user == null || !user.hasDeliveries()) return; + String path = "/$cartons_collection/"; + if (listener != null) listener.cancel(); + _cartons = []; + try { + listener = Firestore.instance + .collection("$path") + .where("status", isEqualTo: carton_shipped_status) + .where("carton_type", whereIn: [ + carton_from_packages, + carton_from_shipments, + carton_small_bag + ]) + .where("is_deleted", isEqualTo: false) + .orderBy("carton_number", descending: false) + .snapshots() + .listen((QuerySnapshot snapshot) { + _cartons.clear(); + _cartons = snapshot.documents.map((documentSnapshot) { + var s = Carton.fromMap( + documentSnapshot.data, documentSnapshot.documentID); + return s; + }).toList(); + notifyListeners(); + }); + } catch (e) { + log.warning("Error!! $e"); + } + } + + Paginator _getDelivered() { + if (user == null || !user.hasDeliveries()) return null; + + var pageQuery = Firestore.instance + .collection("/$cartons_collection") + .where("is_delivered", isEqualTo: true) + .where("status", whereIn: [carton_delivered_status]).where("is_deleted", + isEqualTo: false); + var paginator = new Paginator(pageQuery, rowPerLoad: 20, toObj: (data, id) { + return Carton.fromMap(data, id); + }); + return paginator; + } + + Future loadMore() async { + if (_delivered.ended || _selectedIndex == 1) return; + isLoading = true; + notifyListeners(); + await _delivered.load(onFinished: () { + isLoading = false; + notifyListeners(); + }); + } + + Future refresh() async { + if (_selectedIndex == 1) return; + + await _delivered.refresh(onFinished: () { + notifyListeners(); + }); + } + + void initUser(user) { + super.initUser(user); + } + + @override + logout() async { + if (listener != null) await listener.cancel(); + if (_delivered != null) _delivered.close(); + _cartons = []; + } + + Future deliver(Carton carton) { + return Services.instance.cartonService.deliver(carton); + } +} diff --git a/lib/pages/delivery_address/delivery_address_editor.dart b/lib/pages/delivery_address/delivery_address_editor.dart new file mode 100644 index 0000000..f25fce8 --- /dev/null +++ b/lib/pages/delivery_address/delivery_address_editor.dart @@ -0,0 +1,251 @@ +import 'package:fcs/domain/vo/delivery_address.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/delivery_address/model/delivery_address_model.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/widgets/input_text.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter_icons/flutter_icons.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class DeliveryAddressEditor extends StatefulWidget { + final DeliveryAddress deliveryAddress; + DeliveryAddressEditor({this.deliveryAddress}); + + @override + _DeliveryAddressEditorState createState() => _DeliveryAddressEditorState(); +} + +class _DeliveryAddressEditorState extends State { + TextEditingController _nameController = new TextEditingController(); + TextEditingController _address1Controller = new TextEditingController(); + TextEditingController _address2Controller = new TextEditingController(); + TextEditingController _cityController = new TextEditingController(); + TextEditingController _stateController = new TextEditingController(); + TextEditingController _phoneController = new TextEditingController(); + + DeliveryAddress _deliveryAddress = new DeliveryAddress(); + + bool _isLoading = false; + bool _isNew = true; + + @override + void initState() { + super.initState(); + if (widget.deliveryAddress != null) { + _isNew = false; + _deliveryAddress = widget.deliveryAddress; + _nameController.text = _deliveryAddress.fullName; + _address1Controller.text = _deliveryAddress.addressLine1; + _address2Controller.text = _deliveryAddress.addressLine2; + _cityController.text = _deliveryAddress.city; + _stateController.text = _deliveryAddress.state; + _phoneController.text = _deliveryAddress.phoneNumber; + } else { + _cityController.text = "Yangon"; + _stateController.text = "Yangon"; + } + } + + @override + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final fullName = InputText( + labelTextKey: 'delivery_address.full_name', + iconData: MaterialCommunityIcons.account_arrow_left, + controller: _nameController); + + final addressLine1 = InputText( + labelTextKey: 'delivery_address.address_line1', + iconData: Icons.location_on, + controller: _address1Controller); + + final addressLine2 = InputText( + labelTextKey: 'delivery_address.address_line2', + iconData: Icons.location_on, + controller: _address2Controller); + + final cityBox = InputText( + labelTextKey: 'delivery_address.city', + iconData: Icons.location_city, + controller: _cityController); + + final regionBox = InputText( + labelTextKey: 'delivery_address.state_region', + iconData: Entypo.location, + controller: _stateController); + + final phoneNumberBox = InputText( + labelTextKey: 'delivery_address.phonenumber', + iconData: Icons.phone, + textInputType: TextInputType.phone, + controller: _phoneController); + + final createBtn = fcsButton( + context, + getLocalString(context, "delivery_address.create"), + callack: _create, + ); + + final updateBtn = fcsButton( + context, + getLocalString(context, "delivery_address.update"), + callack: _update, + ); + + return LocalProgress( + inAsyncCall: _isLoading, + child: Scaffold( + appBar: AppBar( + centerTitle: true, + leading: new IconButton( + icon: new Icon(CupertinoIcons.back, color: primaryColor), + onPressed: () => Navigator.of(context).pop(), + ), + backgroundColor: Colors.white, + shadowColor: Colors.transparent, + title: LocalText(context, 'delivery_address', + color: primaryColor, fontSize: 18), + actions: [ + IconButton( + icon: Icon( + Icons.delete, + color: primaryColor, + ), + onPressed: _delete) + ], + ), + body: Padding( + padding: const EdgeInsets.only(left: 10.0, right: 10), + child: ListView(children: [ + fullName, + SizedBox(height: 5), + phoneNumberBox, + SizedBox(height: 10), + addressLine1, + SizedBox(height: 5), + addressLine2, + SizedBox(height: 5), + cityBox, + SizedBox(height: 5), + regionBox, + SizedBox(height: 5), + _isNew ? createBtn : updateBtn, + SizedBox(height: 10) + ]), + ), + )); + } + + DeliveryAddress _getPayload() { + DeliveryAddress deliveryAddress = DeliveryAddress(); + deliveryAddress.id = _deliveryAddress.id; + + try { + deliveryAddress.fullName = _nameController.text; + deliveryAddress.addressLine1 = _address1Controller.text; + deliveryAddress.addressLine2 = _address2Controller.text; + deliveryAddress.city = _cityController.text; + deliveryAddress.state = _stateController.text; + deliveryAddress.phoneNumber = _phoneController.text; + } catch (e) { + showMsgDialog(context, "Error", e.toString()); // shold never happen + } + return deliveryAddress; + } + + Future _validate(DeliveryAddress deliveryAddress) async { + if (deliveryAddress.addressLine1 == "") { + await showMsgDialog(context, "Error", "Invalid address line 1!"); + return false; + } + + if (deliveryAddress.city == null) { + await showMsgDialog(context, "Error", "Invalid city!"); + return false; + } + if (deliveryAddress.state == null) { + await showMsgDialog(context, "Error", "Invalid state!"); + return false; + } + if (deliveryAddress.phoneNumber == null) { + await showMsgDialog(context, "Error", "Invalid phone number!"); + return false; + } + return true; + } + + Future _create() async { + DeliveryAddress deliveryAddress = _getPayload(); + bool valid = await _validate(deliveryAddress); + if (!valid) { + return; + } + setState(() { + _isLoading = true; + }); + var deliveryAddressModel = + Provider.of(context, listen: false); + try { + await deliveryAddressModel.createDeliveryAddress(deliveryAddress); + Navigator.pop(context); + } catch (e) { + showMsgDialog(context, "Error", e.toString()); + } finally { + setState(() { + _isLoading = false; + }); + } + } + + Future _update() async { + DeliveryAddress deliveryAddress = _getPayload(); + bool valid = await _validate(deliveryAddress); + if (!valid) { + return; + } + setState(() { + _isLoading = true; + }); + var deliveryAddressModel = + Provider.of(context, listen: false); + try { + await deliveryAddressModel.updateDeliveryAddress(deliveryAddress); + Navigator.pop(context); + } catch (e) { + showMsgDialog(context, "Error", e.toString()); + } finally { + setState(() { + _isLoading = false; + }); + } + } + + _delete() { + showConfirmDialog(context, "delivery_address.delete.confirm", _deleteDA); + } + + _deleteDA() async { + setState(() { + _isLoading = true; + }); + try { + DeliveryAddressModel deliveryAddressModel = + Provider.of(context, listen: false); + await deliveryAddressModel.deleteDeliveryAddress(_deliveryAddress); + Navigator.pop(context); + } catch (e) { + showMsgDialog(context, "Error", e.toString()); + } finally { + setState(() { + _isLoading = false; + }); + } + } +} diff --git a/lib/pages/delivery_address/delivery_address_list.dart b/lib/pages/delivery_address/delivery_address_list.dart new file mode 100644 index 0000000..b096bef --- /dev/null +++ b/lib/pages/delivery_address/delivery_address_list.dart @@ -0,0 +1,127 @@ +import 'package:fcs/domain/vo/delivery_address.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/delivery_address/delivery_address_editor.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import 'delivery_address_row.dart'; +import 'model/delivery_address_model.dart'; + +class DeliveryAddressList extends StatefulWidget { + const DeliveryAddressList({Key key}) : super(key: key); + @override + _DeliveryAddressListState createState() => _DeliveryAddressListState(); +} + +class _DeliveryAddressListState extends State { + bool _isLoading = false; + + @override + void initState() { + super.initState(); + } + + @override + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + var shipmentModel = Provider.of(context); + + return LocalProgress( + inAsyncCall: _isLoading, + child: Scaffold( + appBar: AppBar( + centerTitle: true, + leading: new IconButton( + icon: new Icon(CupertinoIcons.back, color: primaryColor), + onPressed: () => Navigator.of(context).pop(), + ), + backgroundColor: Colors.white, + shadowColor: Colors.transparent, + title: LocalText(context, 'delivery_addresses', + color: primaryColor, fontSize: 20), + ), + floatingActionButton: FloatingActionButton.extended( + onPressed: () { + Navigator.of(context).push(CupertinoPageRoute( + builder: (context) => DeliveryAddressEditor())); + }, + icon: Icon(Icons.add), + label: LocalText(context, "delivery_address.new_address", + color: Colors.white), + backgroundColor: primaryColor, + ), + body: Padding( + padding: const EdgeInsets.all(8.0), + child: ListView.separated( + separatorBuilder: (c, i) => Divider( + color: primaryColor, + ), + itemCount: shipmentModel.deliveryAddresses.length, + itemBuilder: (context, index) { + return _row(context, shipmentModel.deliveryAddresses[index]); + }), + )), + ); + } + + _row(BuildContext context, DeliveryAddress deliveryAddress) { + return Row( + children: [ + InkWell( + onTap: () => _select(deliveryAddress), + child: Padding( + padding: const EdgeInsets.all(10.0), + child: Icon(Icons.check, + color: + deliveryAddress.isDefault ? primaryColor : Colors.black26), + ), + ), + Expanded( + child: DeliveryAddressRow( + key: ValueKey(deliveryAddress.id), + deliveryAddress: deliveryAddress, + selectionCallback: (d) => _edit(context, deliveryAddress)), + ), + ], + ); + } + + _edit(BuildContext context, DeliveryAddress deliveryAddress) { + Navigator.push( + context, + CupertinoPageRoute( + builder: (context) => + DeliveryAddressEditor(deliveryAddress: deliveryAddress)), + ); + } + + Future _select(DeliveryAddress deliveryAddress) async { + if (deliveryAddress.isDefault) { + Navigator.pop(context); + return; + } + setState(() { + _isLoading = true; + }); + var deliveryAddressModel = + Provider.of(context, listen: false); + try { + await deliveryAddressModel.selectDefalutDeliveryAddress(deliveryAddress); + Navigator.pop(context); + } catch (e) { + showMsgDialog(context, "Error", e.toString()); + } finally { + setState(() { + _isLoading = false; + }); + } + } +} diff --git a/lib/pages/delivery_address/delivery_address_row.dart b/lib/pages/delivery_address/delivery_address_row.dart new file mode 100644 index 0000000..e596213 --- /dev/null +++ b/lib/pages/delivery_address/delivery_address_row.dart @@ -0,0 +1,78 @@ +import 'package:fcs/domain/vo/delivery_address.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_icons/flutter_icons.dart'; + +typedef SelectionCallback(DeliveryAddress deliveryAddress); + +class DeliveryAddressRow extends StatelessWidget { + final DeliveryAddress deliveryAddress; + final SelectionCallback selectionCallback; + const DeliveryAddressRow( + {Key key, this.deliveryAddress, this.selectionCallback}) + : super(key: key); + + @override + Widget build(BuildContext context) { + return InkWell( + onTap: selectionCallback == null + ? null + : () => this.selectionCallback(deliveryAddress), + child: Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + line(context, deliveryAddress.fullName, + iconData: MaterialCommunityIcons.account, + color: primaryColor, + fontSize: 16), + line(context, deliveryAddress.phoneNumber, + iconData: Icons.phone, color: primaryColor, fontSize: 16), + SizedBox( + height: 5, + ), + line(context, deliveryAddress.addressLine1, + iconData: Icons.location_on), + line( + context, + deliveryAddress.addressLine2, + ), + line( + context, + deliveryAddress.city, + ), + line(context, deliveryAddress.state), + ], + ), + ), + ], + ), + ); + } + + Widget line(BuildContext context, String text, + {IconData iconData, Color color, double fontSize}) { + return Row( + children: [ + iconData == null + ? SizedBox(width: 40) + : Padding( + padding: const EdgeInsets.only(left: 8.0, right: 8), + child: Icon(iconData, color: Colors.black38), + ), + Flexible( + child: TextLocalStyle( + context, + text ?? "", + fontSize: fontSize ?? 14, + color: color, + ), + ), + ], + ); + } +} diff --git a/lib/pages/delivery_address/model/delivery_address_model.dart b/lib/pages/delivery_address/model/delivery_address_model.dart new file mode 100644 index 0000000..550d6af --- /dev/null +++ b/lib/pages/delivery_address/model/delivery_address_model.dart @@ -0,0 +1,87 @@ +import 'dart:async'; +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:fcs/data/services/services.dart'; +import 'package:fcs/domain/vo/delivery_address.dart'; +import 'package:fcs/pages/main/model/base_model.dart'; +import 'package:fcs/domain/constants.dart'; +import 'package:logging/logging.dart'; + +class DeliveryAddressModel extends BaseModel { + final log = Logger('FcsShipmentModel'); + List deliveryAddresses = []; + + StreamSubscription listener; + + DeliveryAddress get defalutAddress => + deliveryAddresses.firstWhere((e) => e.isDefault, orElse: () => null); + + DeliveryAddress getLocalDeliveryAddress(String id) => + deliveryAddresses.firstWhere((e) => e.id == id, orElse: () => null); + + @override + void privilegeChanged() { + super.privilegeChanged(); + _loadDeliveryAddresses(); + } + + @override + logout() async { + if (listener != null) await listener.cancel(); + deliveryAddresses = []; + } + + Future _loadDeliveryAddresses() async { + if (user == null) return; + String path = "$delivery_address_collection/"; + if (listener != null) listener.cancel(); + deliveryAddresses = []; + try { + listener = Firestore.instance + .collection('users') + .document("${user.id}") + .collection("$path") + .snapshots() + .listen((QuerySnapshot snapshot) { + deliveryAddresses.clear(); + deliveryAddresses = snapshot.documents.map((documentSnapshot) { + var s = DeliveryAddress.fromMap( + documentSnapshot.data, documentSnapshot.documentID); + return s; + }).toList(); + notifyListeners(); + }); + } catch (e) { + log.warning("Error!! $e"); + } + } + + Future getDeliveryAddress(String id) async { + String path = "/$user_collection/${user.id}/$delivery_address_collection"; + var snap = await Firestore.instance.collection(path).document(id).get(); + return DeliveryAddress.fromMap(snap.data, snap.documentID); + } + + void initUser(user) { + super.initUser(user); + } + + Future createDeliveryAddress(DeliveryAddress deliveryAddress) { + return Services.instance.deliveryAddressService + .createDeliveryAddress(deliveryAddress); + } + + Future updateDeliveryAddress(DeliveryAddress deliveryAddress) { + return Services.instance.deliveryAddressService + .updateDeliveryAddress(deliveryAddress); + } + + Future deleteDeliveryAddress(DeliveryAddress deliveryAddress) { + return Services.instance.deliveryAddressService + .deleteDeliveryAddress(deliveryAddress); + } + + Future selectDefalutDeliveryAddress(DeliveryAddress deliveryAddress) { + return Services.instance.deliveryAddressService + .selectDefalutDeliveryAddress(deliveryAddress); + } +} diff --git a/lib/pages/device_list.dart b/lib/pages/device_list.dart deleted file mode 100644 index c51ddf3..0000000 --- a/lib/pages/device_list.dart +++ /dev/null @@ -1,194 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/device_model.dart'; -import 'package:fcs/model/main_model.dart'; -import 'package:fcs/vo/device.dart'; -import 'package:fcs/vo/popup_menu.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/popupmenu.dart'; -import 'package:fcs/widget/progress.dart'; - -import '../fcs/common/helpers/theme.dart'; -import '../fcs/common/pages/util.dart'; - -class PhoneDeviceList extends StatefulWidget { - @override - _PhoneDeviceListState createState() => _PhoneDeviceListState(); -} - -class _PhoneDeviceListState extends State { - final double dotSize = 15.0; - PopupMenu selectedChoices = deviceMenu[0]; - bool _isLoading = false; - PhoneDevice phoneDevice = new PhoneDevice(); - - @override - Widget build(BuildContext context) { - var deviceModel = Provider.of(context); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - title: LocalText( - context, - 'profile.devices', - color: Colors.white, - fontSize: 20, - ), - ), - body: new ListView.builder( - scrollDirection: Axis.vertical, - padding: EdgeInsets.only(left: 15, right: 15, top: 15), - shrinkWrap: true, - itemCount: deviceModel.devices.length, - itemBuilder: (BuildContext context, int index) { - return Card( - elevation: 10, - color: Colors.white, - child: InkWell( - onTap: () {}, - child: Row( - children: [ - Expanded( - child: new Padding( - padding: const EdgeInsets.symmetric(vertical: 7.0), - child: new Row( - children: [ - new Padding( - padding: new EdgeInsets.symmetric( - horizontal: 15.0 - dotSize / 2), - child: Padding( - padding: EdgeInsets.all(5.0), - child: Image.asset( - "assets/device.png", - width: 40, - height: 40, - color: primaryColor, - ), - ), - ), - new Expanded( - child: new Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - new Text( - deviceModel.devices[index].name, - style: new TextStyle( - fontSize: 13.0, color: Colors.black), - ), - ], - ), - ), - ], - ), - ), - ), - PopupMenuButton( - elevation: 3.2, - onSelected: _select, - itemBuilder: (BuildContext context) { - this.phoneDevice = deviceModel.devices[index]; - return deviceMenu.map((PopupMenu choice) { - return PopupMenuItem( - enabled: choice.index == 0 - ? deviceModel.devices[index].isDeviceOn() - ? false - : true - : choice.index == 1 - ? deviceModel.devices[index] - .isDeviceOn() - ? true - : false - : true, - value: choice, - child: Text(choice.status), - ); - }).toList(); - }), - ], - ), - ), - ); - }), - ), - ); - } - - void _select(PopupMenu choice) async { - selectedChoices = choice; - if (choice.index == 0) { - showConfirmDialog(context, "device.confirm", () { - _confirm(); - }); - } else if (choice.index == 1) { - showConfirmDialog(context, "device.logout", () { - _logout(); - }); - } else if (choice.index == 2) { - showConfirmDialog(context, "device.set_primary", () { - _setPrimaryDevice(); - }); - } - } - - _confirm() async { - setState(() { - _isLoading = true; - }); - - try { - var deviceModel = Provider.of(context); - var mainModel = Provider.of(context); - - await deviceModel.confirmDevice( - mainModel.user.phoneNumber, this.phoneDevice.id); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - setState(() { - _isLoading = false; - }); - } - } - - _logout() async { - setState(() { - _isLoading = true; - }); - - try { - var deviceModel = Provider.of(context); - var mainModel = Provider.of(context); - - await deviceModel.logoutDevice( - mainModel.user.phoneNumber, this.phoneDevice.id); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - setState(() { - _isLoading = false; - }); - } - } - - _setPrimaryDevice() async { - setState(() { - _isLoading = true; - }); - - try { - var deviceModel = Provider.of(context); - var mainModel = Provider.of(context); - await deviceModel.setPrimaryDevice( - mainModel.user.phoneNumber, this.phoneDevice.id); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - setState(() { - _isLoading = false; - }); - } - } -} diff --git a/lib/pages/discount/discount_editor.dart b/lib/pages/discount/discount_editor.dart new file mode 100644 index 0000000..e8d0a15 --- /dev/null +++ b/lib/pages/discount/discount_editor.dart @@ -0,0 +1,191 @@ +import 'package:fcs/domain/entities/discount.dart'; +import 'package:fcs/domain/entities/user.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/localization/app_translations.dart'; +import 'package:fcs/pages/discount/model/discount_model.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/rates/model/shipment_rate_model.dart'; +import 'package:fcs/pages/user_search/user_serach.dart'; +import 'package:fcs/pages/widgets/display_text.dart'; +import 'package:fcs/pages/widgets/input_text.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_icons/flutter_icons.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:provider/provider.dart'; + +class DiscountEditor extends StatefulWidget { + final Discount discount; + + const DiscountEditor({Key key, this.discount}) : super(key: key); + @override + _DiscountEditorState createState() => _DiscountEditorState(); +} + +class _DiscountEditorState extends State { + bool _isLoading = false; + Discount _discount = new Discount(); + TextEditingController _codeController = new TextEditingController(); + TextEditingController _amountController = new TextEditingController(); + TextEditingController _statusController = new TextEditingController(); + + bool _isNew = false; + String customerName = ''; + String customerId = ''; + + @override + void initState() { + super.initState(); + if (widget.discount != null) { + _discount = widget.discount; + _codeController.text = _discount.code; + _amountController.text = _discount.amount.toString(); + _statusController.text = _discount.status; + customerName = widget.discount.customerName; + customerId = widget.discount.customerId; + } else { + _isNew = true; + } + } + + @override + Widget build(BuildContext context) { + final codeBox = InputText( + labelTextKey: 'discount.code', + iconData: FontAwesomeIcons.algolia, + controller: _codeController); + + final amountBox = InputText( + labelTextKey: 'discount.amount', + iconData: FontAwesomeIcons.moneyBill, + controller: _amountController); + + final statusBox = DisplayText( + text: _statusController.text, + labelTextKey: "discount.status", + iconData: Icons.av_timer, + ); + + final customerBox = Row( + children: [ + Expanded( + child: DisplayText( + text: customerName != null ? customerName : "", + labelTextKey: "discount.name", + iconData: Feather.user, + )), + IconButton( + icon: Icon(Icons.search, color: primaryColor), + onPressed: () => searchUser(context, callbackUserSelect: (u) { + setState(() { + customerId = u.id; + customerName = u.name; + }); + })), + ], + ); + + return LocalProgress( + inAsyncCall: _isLoading, + child: Scaffold( + backgroundColor: Colors.white, + appBar: AppBar( + centerTitle: true, + title: Text( + AppTranslations.of(context).text("discount.form"), + ), + leading: new IconButton( + icon: new Icon(CupertinoIcons.back), + onPressed: () => Navigator.of(context).pop(), + ), + backgroundColor: primaryColor, + actions: [ + IconButton( + icon: Icon(Icons.delete), + onPressed: _delete, + ) + ], + ), + body: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + Expanded( + child: ListView( + children: [ + codeBox, + amountBox, + SizedBox(height: 7), + customerBox, + SizedBox(height: 7), + widget.discount == null + ? Container() + : Container( + padding: EdgeInsets.only(top: 5), + child: statusBox, + ), + ], + ), + ), + fcsButton(context, getLocalString(context, "btn.save"), + callack: _save), + SizedBox( + height: 30, + ) + ], + ), + )), + ); + } + + _save() async { + setState(() { + _isLoading = true; + }); + try { + DiscountModel discountModel = + Provider.of(context, listen: false); + Discount _discount = Discount( + code: _codeController.text, + customerName: customerName, + customerId: customerId, + amount: double.parse(_amountController.text)); + if (_isNew) { + await discountModel.addDiscount(_discount); + } else { + _discount.id = widget.discount.id; + await discountModel.updateDiscount(_discount); + } + Navigator.pop(context); + } catch (e) { + showMsgDialog(context, "Error", e.toString()); + } finally { + setState(() { + _isLoading = false; + }); + } + } + + _delete() { + showConfirmDialog( + context, "discount.edit.delete.confirm", _deleteCargoType); + } + + _deleteCargoType() async { + setState(() { + _isLoading = true; + }); + try { + var discountModel = Provider.of(context, listen: false); + await discountModel.deleteDiscount(widget.discount); + Navigator.pop(context); + } catch (e) { + showMsgDialog(context, "Error", e.toString()); + } finally { + setState(() { + _isLoading = false; + }); + } + } +} diff --git a/lib/pages/discount/discount_list.dart b/lib/pages/discount/discount_list.dart new file mode 100644 index 0000000..ca2845a --- /dev/null +++ b/lib/pages/discount/discount_list.dart @@ -0,0 +1,138 @@ +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/localization/app_translations.dart'; +import 'package:fcs/pages/discount/discount_list_row.dart'; +import 'package:fcs/pages/discount/model/discount_model.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/widgets/local_popup_menu_button.dart'; +import 'package:fcs/pages/widgets/local_popupmenu.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import 'discount_editor.dart'; + +class DiscountList extends StatefulWidget { + final bool selectionMode; + + const DiscountList({Key key, this.selectionMode = false}) : super(key: key); + @override + _DiscountListState createState() => _DiscountListState(); +} + +class _DiscountListState extends State { + bool _isLoading = false; + var _controller = ScrollController(); + + @override + void initState() { + super.initState(); + _controller.addListener(() async { + if (_controller.position.pixels == _controller.position.maxScrollExtent) { + Provider.of(context, listen: false).loadMore(); + } + }); + Provider.of(context, listen: false).initData(); + } + + @override + Widget build(BuildContext context) { + var discountModel = Provider.of(context); + + final popupMenu = LocalPopupMenuButton( + popmenus: [ + LocalPopupMenu( + id: 1, + textKey: "discount.popupmenu.available", + selected: discountModel.selectedIndex == 1), + LocalPopupMenu( + id: 2, + textKey: "discount.popupmenu.used", + selected: discountModel.selectedIndex == 2) + ], + popupMenuCallback: (p) => this.setState(() { + discountModel.selectedIndex = p.id; + }), + ); + + return LocalProgress( + inAsyncCall: _isLoading, + child: Scaffold( + appBar: AppBar( + centerTitle: true, + title: Text( + AppTranslations.of(context).text("discount.title"), + ), + leading: new IconButton( + icon: new Icon(CupertinoIcons.back), + onPressed: () => Navigator.of(context).pop(), + ), + backgroundColor: primaryColor, + actions: [popupMenu], + ), + body: Column( + children: [ + Expanded( + child: ListView.separated( + separatorBuilder: (context, index) => Divider( + color: Colors.black, + height: 1, + ), + controller: _controller, + itemCount: discountModel.discounts.length, + itemBuilder: (BuildContext context, int index) { + var discount = discountModel.discounts[index]; + return DiscountListRow( + key: ValueKey(discount.id), + discount: discount, + onSelect: (d) { + if (widget.selectionMode) { + Navigator.pop(context, discount); + return; + } + Navigator.push( + context, + CupertinoPageRoute( + builder: (context) => + DiscountEditor(discount: discount)), + ); + }, + ); + }, + ), + ), + discountModel.isLoading + ? Container( + padding: EdgeInsets.all(8), + color: primaryColor, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("Loading...", + style: TextStyle(color: Colors.white)), + ], + ), + ) + : Container(), + ], + ), + floatingActionButton: FloatingActionButton.extended( + onPressed: () { + Navigator.push( + context, + CupertinoPageRoute(builder: (context) => DiscountEditor()), + ); + }, + icon: Icon(Icons.add), + label: LocalText( + context, + 'discount.new', + color: Colors.white, + ), + backgroundColor: primaryColor, + ), + ), + ); + } +} diff --git a/lib/pages_fcs/box_list_row.dart b/lib/pages/discount/discount_list_row.dart similarity index 53% rename from lib/pages_fcs/box_list_row.dart rename to lib/pages/discount/discount_list_row.dart index af14bb6..9047f3b 100644 --- a/lib/pages_fcs/box_list_row.dart +++ b/lib/pages/discount/discount_list_row.dart @@ -1,51 +1,32 @@ -import 'package:fcs/pages/invoice/package_info.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/pages_fcs/box_editor.dart'; -import 'package:fcs/pages_fcs/package_editor.dart'; -import 'package:fcs/vo/box.dart'; -import 'package:fcs/vo/package.dart'; -import 'package:fcs/widget/bottom_up_page_route.dart'; +import 'package:fcs/domain/entities/carton.dart'; +import 'package:fcs/domain/entities/discount.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/discount/discount_editor.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_icons/flutter_icons.dart'; import 'package:intl/intl.dart'; -class BoxListRow extends StatefulWidget { - final bool isReadOnly; - final Box box; - const BoxListRow({this.box, this.isReadOnly}); +typedef OnSelect(Discount discount); - @override - _BoxListRowState createState() => _BoxListRowState(); -} +class DiscountListRow extends StatelessWidget { + final OnSelect onSelect; + final Discount discount; + DiscountListRow({Key key, this.discount, this.onSelect}) : super(key: key); -class _BoxListRowState extends State { - final double dotSize = 15.0; - Box _box = new Box(); final DateFormat dateFormat = new DateFormat("dd MMM yyyy"); - @override - void initState() { - super.initState(); - _box = widget.box; - } - @override Widget build(BuildContext context) { - return Container( - padding: EdgeInsets.only(left: 15, right: 15), - child: InkWell( - onTap: () { - if (widget.isReadOnly) { - // Navigator.push( - // context, - // BottomUpPageRoute(PackageInfo(package: _box)), - // ); - } else { - Navigator.push( - context, - BottomUpPageRoute(BoxEditor(box: _box)), - ); - } - }, + return InkWell( + onTap: () { + if (onSelect != null) { + onSelect(discount); + } + }, + child: Container( + padding: EdgeInsets.only(left: 15, right: 15), child: Row( children: [ Expanded( @@ -53,6 +34,14 @@ class _BoxListRowState extends State { padding: const EdgeInsets.symmetric(vertical: 16.0), child: new Row( children: [ + Container( + padding: EdgeInsets.only(left: 5, right: 10), + child: Icon( + Entypo.price_ribbon, + color: primaryColor, + size: 30, + ), + ), new Expanded( child: new Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -60,9 +49,7 @@ class _BoxListRowState extends State { Padding( padding: const EdgeInsets.only(left: 8.0), child: new Text( - _box.packageNumber == null - ? '' - : _box.packageNumber, + discount.code ?? "", style: new TextStyle( fontSize: 15.0, color: Colors.black), ), @@ -70,7 +57,7 @@ class _BoxListRowState extends State { Padding( padding: const EdgeInsets.only(left: 10.0, top: 10), child: new Text( - dateFormat.format(_box.arrivedDate), + discount.customerName ?? "", style: new TextStyle( fontSize: 15.0, color: Colors.grey), ), @@ -86,23 +73,14 @@ class _BoxListRowState extends State { children: [ Padding( padding: const EdgeInsets.all(0), - child: getStatus(_box.status), + child: Text(discount.status), ), Padding( padding: const EdgeInsets.only(left: 8.0, top: 5, bottom: 5), child: Row( children: [ new Text( - _box.weight == null - ? '' - : _box.weight.toString() + 'lb - ', - style: - new TextStyle(fontSize: 15.0, color: Colors.grey), - ), - new Text( - _box.price == null - ? "" - : "\$ " + _box.price.toString(), + "${discount.amount ?? ''}", style: new TextStyle(fontSize: 15.0, color: Colors.grey), ), diff --git a/lib/pages/discount/model/discount_model.dart b/lib/pages/discount/model/discount_model.dart new file mode 100644 index 0000000..5a25660 --- /dev/null +++ b/lib/pages/discount/model/discount_model.dart @@ -0,0 +1,133 @@ +import 'dart:async'; + +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:fcs/data/services/services.dart'; +import 'package:fcs/domain/constants.dart'; +import 'package:fcs/domain/entities/discount.dart'; +import 'package:fcs/helpers/paginator.dart'; +import 'package:fcs/pages/main/model/base_model.dart'; +import 'package:logging/logging.dart'; + +class DiscountModel extends BaseModel { + final log = Logger('DiscountModel'); + + StreamSubscription listener; + + List _discounts = []; + List get discounts => + _selectedIndex == 1 ? _discounts : List.from(_used.values); + + Paginator _used; + bool isLoading = false; + int _selectedIndex = 1; + set selectedIndex(int index) { + _selectedIndex = index; + notifyListeners(); + } + + get selectedIndex => _selectedIndex; + + initData() { + _selectedIndex = 1; + _load(); + + if (_used != null) _used.close(); + _used = _getUsed(); + _used.load(); + } + + void initUser(user) { + super.initUser(user); + _load(); + } + + _load() { + if (listener != null) listener.cancel(); + try { + listener = Firestore.instance + .collection("/$discounts_collection") + .orderBy("code", descending: false) + .snapshots() + .listen((snaps) { + _discounts.clear(); + snaps.documents.forEach((d) { + _discounts.add(Discount.fromMap(d.data, d.documentID)); + }); + notifyListeners(); + }); + } catch (e) { + log.warning("error:$e"); + } + } + + Paginator _getUsed() { + if (user == null || !user.hasFcsShipments()) return null; + + var pageQuery = Firestore.instance + .collection("/$discounts_collection") + .where("status", isEqualTo: fcs_shipment_shipped_status) + .orderBy("code", descending: false); + var paginator = new Paginator(pageQuery, rowPerLoad: 20, toObj: (data, id) { + return Discount.fromMap(data, id); + }); + return paginator; + } + + Future> getDiscount(String userID) async { + String path = "/$discounts_collection"; + try { + var q = Firestore.instance + .collection("$path") + .where("customer_id", isEqualTo: userID) + .where("status", isEqualTo: "available"); + var snaps = await q.getDocuments(source: Source.server); + List discounts = snaps.documents.map((snap) { + if (snap.exists) { + var s = Discount.fromMap(snap.data, snap.documentID); + return s; + } + }).toList(); + return discounts; + } catch (e) { + log.warning("Error!! $e"); + } + return null; + } + + Future loadMore() async { + if (_used.ended || _selectedIndex == 1) return; + isLoading = true; + notifyListeners(); + await _used.load(onFinished: () { + isLoading = false; + notifyListeners(); + }); + } + + Future refresh() async { + if (_selectedIndex == 1) return; + await _used.refresh(onFinished: () { + notifyListeners(); + }); + } + + @override + logout() async { + if (listener != null) await listener.cancel(); + if (_used != null) _used.close(); + + _discounts = []; + } + + Future addDiscount(Discount discount) async { + return Services.instance.commonService.createDiscount(discount); + } + + Future updateDiscount(Discount discount) async { + return Services.instance.commonService.updateDiscount(discount); + } + + Future deleteDiscount(Discount discount) async { + return Services.instance.commonService.deleteDiscount(discount.id); + } +} diff --git a/lib/pages/discount_by_weight_editor.dart b/lib/pages/discount_by_weight_editor.dart deleted file mode 100644 index f8d0605..0000000 --- a/lib/pages/discount_by_weight_editor.dart +++ /dev/null @@ -1,81 +0,0 @@ -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/vo/custom.dart'; -import 'package:fcs/vo/discount.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:flutter/material.dart'; -import 'package:fcs/widget/progress.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -import '../fcs/common/helpers/theme.dart'; - -class DiscountByWeightEditor extends StatefulWidget { - final Discount discount; - DiscountByWeightEditor({this.discount}); - - @override - _DiscountByWeightEditorState createState() => _DiscountByWeightEditorState(); -} - -class _DiscountByWeightEditorState extends State { - TextEditingController _weightController = new TextEditingController(); - TextEditingController _rateController = new TextEditingController(); - - bool _isLoading = false; - Discount _discount = new Discount(); - - @override - void initState() { - super.initState(); - if (widget.discount != null) { - _discount = widget.discount; - _weightController.text = _discount.weight.toString(); - _rateController.text = _discount.discountRate.toString(); - } - } - - @override - void dispose() { - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - centerTitle: true, - leading: new IconButton( - icon: new Icon( - Icons.close, - ), - onPressed: () => Navigator.of(context).pop(), - ), - backgroundColor: primaryColor, - title: Text(AppTranslations.of(context).text("discount.new")), - ), - body: Container( - padding: EdgeInsets.all(18), - child: Column( - children: [ - Expanded( - child: ListView( - children: [ - fcsInput("Weight", FontAwesomeIcons.weightHanging, - controller: _weightController), - fcsInput("Discount Rate", Icons.attach_money, - controller: _rateController), - SizedBox(height: 30), - ], - ), - ), - widget.discount == null - ? fcsButton(context, "Create", callack: () {}) - : fcsButton(context, "Save", callack: () {}), - SizedBox(height: 10) - ], - ), - ), - ), - ); - } -} diff --git a/lib/pages/discount_editor.dart b/lib/pages/discount_editor.dart deleted file mode 100644 index a3c3b59..0000000 --- a/lib/pages/discount_editor.dart +++ /dev/null @@ -1,138 +0,0 @@ -import 'package:fcs/model/discount_model.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/vo/discount.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_icons/flutter_icons.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:fcs/widget/progress.dart'; - -import '../fcs/common/helpers/theme.dart'; - -class DiscountEditor extends StatefulWidget { - final Discount discount; - - const DiscountEditor({Key key, this.discount}) : super(key: key); - @override - _DiscountEditorState createState() => _DiscountEditorState(); -} - -class _DiscountEditorState extends State { - bool _isLoading = false; - Discount _discount = new Discount(); - TextEditingController _codeController = new TextEditingController(); - TextEditingController _amountController = new TextEditingController(); - TextEditingController _statusController = new TextEditingController(); - TextEditingController _customerController = new TextEditingController(); - - bool isNew = false; - - @override - void initState() { - super.initState(); - if (widget.discount != null) { - _discount = widget.discount; - _codeController.text = _discount.code; - _amountController.text = _discount.amount.toString(); - _statusController.text = _discount.status; - _customerController.text = 'Ko Nyi'; - } else { - isNew = true; - _customerController.text = ''; - } - } - - @override - Widget build(BuildContext context) { - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - backgroundColor: Colors.white, - appBar: AppBar( - centerTitle: true, - title: Text( - AppTranslations.of(context).text("discount.form"), - ), - leading: new IconButton( - icon: new Icon(Icons.close), - onPressed: () => Navigator.of(context).pop(), - ), - backgroundColor: primaryColor, - actions: [], - ), - body: Padding( - padding: const EdgeInsets.only(left: 20.0), - child: Column( - children: [ - Expanded( - child: ListView( - children: [ - fcsInput('Code', FontAwesomeIcons.algolia, - controller: _codeController), - fcsInput('Customer Name', Feather.user, - controller: _customerController), - fcsInput('Amount', FontAwesomeIcons.moneyBill, - controller: _amountController), - widget.discount == null - ? Container() - : Container( - padding: EdgeInsets.only(top: 5), - child: TextFormField( - controller: _statusController, - readOnly: true, - decoration: InputDecoration( - fillColor: Colors.white, - labelText: 'Status', - labelStyle: TextStyle( - fontSize: 16, color: primaryColor), - filled: true, - enabledBorder: InputBorder.none, - focusedBorder: InputBorder.none, - icon: Icon( - Icons.av_timer, - color: primaryColor, - ), - )), - ), - ], - ), - ), - widget.discount == null - ? Align( - alignment: Alignment.bottomCenter, - child: Center( - child: Container( - width: 250, - child: FlatButton( - child: Text('Add Discount'), - color: primaryColor, - textColor: Colors.white, - onPressed: () { - Navigator.pop(context); - }, - ), - ))) - : Align( - alignment: Alignment.bottomCenter, - child: Center( - child: Container( - width: 250, - child: FlatButton( - child: Text('Save box'), - color: primaryColor, - textColor: Colors.white, - onPressed: () { - Navigator.pop(context); - }, - ), - ))), - SizedBox( - height: 30, - ) - ], - ), - )), - ); - } -} diff --git a/lib/pages/discount_list.dart b/lib/pages/discount_list.dart deleted file mode 100644 index b22a149..0000000 --- a/lib/pages/discount_list.dart +++ /dev/null @@ -1,131 +0,0 @@ -import 'package:fcs/model/discount_model.dart'; -import 'package:fcs/pages/discount_editor.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/widget/bottom_up_page_route.dart'; -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:fcs/widget/progress.dart'; - -import '../fcs/common/helpers/theme.dart'; - -class DiscountList extends StatefulWidget { - @override - _DiscountListState createState() => _DiscountListState(); -} - -class _DiscountListState extends State { - bool _isLoading = false; - @override - Widget build(BuildContext context) { - var discountModel = Provider.of(context); - print('discounts => ${discountModel.discounts}'); - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - centerTitle: true, - title: Text( - AppTranslations.of(context).text("discount.title"), - ), - leading: new IconButton( - icon: new Icon(Icons.close), - onPressed: () => Navigator.of(context).pop(), - ), - backgroundColor: primaryColor, - actions: [ - IconButton( - icon: Icon(Icons.search), - onPressed: () {}, - ) - ], - ), - body: ListView.separated( - separatorBuilder: (context, index) => Divider( - color: Colors.black, - ), - itemCount: discountModel.discounts.length, - itemBuilder: (BuildContext context, int index) { - var discount = discountModel.discounts[index]; - return InkWell( - onTap: () { - Navigator.push( - context, - BottomUpPageRoute(DiscountEditor( - discount: discount, - )), - ); - }, - child: Padding( - padding: const EdgeInsets.all(10.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.only(bottom: 8.0), - child: Text( - discount.code, - style: TextStyle( - color: primaryColor, - fontSize: 16, - fontWeight: FontWeight.bold, - ), - ), - ), - Row( - children: [ - Text( - discount.customer, - style: TextStyle( - color: Colors.black, - fontWeight: FontWeight.normal, - fontSize: 15), - ), - ], - ), - ], - ), - ), - Column( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Padding( - padding: - const EdgeInsets.only(left: 10.0, bottom: 5.0), - child: Text( - '\$ ${discount.amount.toString()}', - style: TextStyle( - color: Colors.black, - fontWeight: FontWeight.bold, - fontSize: 16), - ), - ), - getStatus(discount.status), - ], - ), - ], - ), - ), - ); - }, - ), - floatingActionButton: FloatingActionButton.extended( - onPressed: () { - Navigator.push( - context, - BottomUpPageRoute(DiscountEditor()), - ); - }, - icon: Icon(Icons.add), - label: Text(AppTranslations.of(context).text("discount.new")), - backgroundColor: primaryColor, - ), - ), - ); - } -} diff --git a/lib/pages/do/do_approve.dart b/lib/pages/do/do_approve.dart deleted file mode 100644 index 863830c..0000000 --- a/lib/pages/do/do_approve.dart +++ /dev/null @@ -1,909 +0,0 @@ -import 'dart:typed_data'; - -import 'package:flutter/material.dart'; -import 'package:flutter/widgets.dart'; -import 'package:image_picker/image_picker.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; -import 'package:quiver/async.dart'; -import 'package:fcs/model/do_model.dart'; -import 'package:fcs/model/language_model.dart'; -import 'package:fcs/model/log_model.dart'; -import 'package:fcs/model/main_model.dart'; -import 'package:fcs/model/po_model.dart'; -import 'package:fcs/model/product_model.dart'; -import 'package:fcs/pages/do/photo_page.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/do.dart'; -import 'package:fcs/vo/po.dart'; -import 'package:fcs/widget/img_file.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:fcs/widget/my_data_table.dart'; -import 'package:fcs/widget/number_cell.dart'; -import 'package:fcs/widget/progress.dart'; - -import '../document_log_page.dart'; -import '../../fcs/common/pages/util.dart'; -import 'do_files.dart'; -import 'do_storage_item.dart'; - -class DOApproval extends StatefulWidget { - final DOSubmission doSubmission; - const DOApproval({this.doSubmission}); - @override - _DOApprovalState createState() => _DOApprovalState(); -} - -class _DOApprovalState extends State { - var dateFormatter = new DateFormat('dd MMM yyyy'); - final numberFormatter = new NumberFormat("#,###"); - var doDateFormatter = new DateFormat('dd MMM yyyy - hh:mm a'); - - bool _isLoading = false; - TextEditingController _date = new TextEditingController(); - TextEditingController _doDate = new TextEditingController(); - TextEditingController _number = new TextEditingController(); - TextEditingController _licence = new TextEditingController(); - TextEditingController _driver = new TextEditingController(); - TextEditingController _carNo = new TextEditingController(); - TextEditingController _type = new TextEditingController(); - TextEditingController _name = new TextEditingController(); - TextEditingController _bizName = new TextEditingController(); - TextEditingController _storage = new TextEditingController(); - TextEditingController _comment = new TextEditingController(); - DOSubmission doObj = DOSubmission(); - int _count; - DateTime _result; - DOFiles files = DOFiles(); - List doLines = new List(); - - @override - void initState() { - super.initState(); - - var mainModel = Provider.of(context, listen: false); - var doModel = Provider.of(context, listen: false); - - doObj = widget.doSubmission; - _date.text = doObj.deliveryDate != null - ? dateFormatter.format(doObj.deliveryDate) - : ""; - _doDate.text = - doObj.doDate != null ? doDateFormatter.format(doObj.doDate) : ""; - _number.text = doObj.doNumber.toString(); - _licence.text = doObj.driverLicenseNumber; - _driver.text = doObj.driverName; - _carNo.text = doObj.carNo; - _type.text = doObj.type; - _name.text = doObj.userName; - _bizName.text = doObj.bizName; - _storage.text = doObj.storageCharge == null - ? "" - : numberFormatter.format(doObj.storageCharge); - _comment.text = doObj.comment; - - if (doObj.deliveryStatus == 'initiated') { - _count = doModel.timber; - - Duration diff = DateTime.now().difference(doObj.deliveryInitiatedTime); - - if (diff.inMinutes < mainModel.setting.deliveryStartWaitMin) { - var time = mainModel.setting.deliveryStartWaitMin - diff.inMinutes; - new CountdownTimer( - new Duration(minutes: time), new Duration(seconds: 1)) - .listen((data) { - if (mounted) { - setState(() { - _count = data.remaining.inSeconds; - doModel.addTimber(_count); - }); - } - }); - } - } else { - _count = 0; - } - - _load(); - } - - @override - void dispose() { - super.dispose(); - } - - @override - Widget build(BuildContext context) { - MainModel mainModel = Provider.of(context); - bool isBuyer = mainModel.user.isBuyer(); - var logModel = Provider.of(context); - String formattedTime; - if (doObj.deliveryStatus == 'initiated') { - _result = DateTime( - doObj.deliveryInitiatedTime.year, - doObj.deliveryInitiatedTime.month, - doObj.deliveryInitiatedTime.day, - doObj.deliveryInitiatedTime.hour, - doObj.deliveryInitiatedTime.minute, - _count); - formattedTime = DateFormat.ms().format(_result); - } - - final doDateBox = Container( - padding: EdgeInsets.only(left: 20, top: 15), - child: Row( - children: [ - LocalText(context, "do.do_date"), - Container( - padding: EdgeInsets.only(left: 10), - child: Text( - _doDate.text, - style: textStyle, - ), - ) - ], - ), - ); - - final dateBox = Container( - padding: EdgeInsets.only(left: 20, top: 8), - child: Row( - children: [ - LocalText(context, "do.date"), - Container( - padding: EdgeInsets.only(left: 10), - child: Text( - _date.text, - style: textStyle, - ), - ) - ], - ), - ); - - final numberBox = Container( - padding: EdgeInsets.only(left: 20, top: 5), - child: Row( - children: [ - LocalText(context, "do.do_num"), - Container( - padding: EdgeInsets.only(left: 10), - child: Text( - _number.text, - style: textStyle, - ), - ) - ], - ), - ); - final driverBox = Container( - padding: EdgeInsets.only(left: 20, top: 5), - child: Row( - children: [ - LocalText(context, "do.driver"), - Container( - padding: EdgeInsets.only(left: 10), - child: Text( - _driver.text, - style: textStyle, - ), - ) - ], - ), - ); - final carNoBox = Container( - padding: EdgeInsets.only(left: 20, top: 5), - child: Row( - children: [ - LocalText(context, "do.car"), - Container( - padding: EdgeInsets.only(left: 10), - child: Text( - _carNo.text, - style: textStyle, - ), - ) - ], - ), - ); - final licenceBox = Container( - padding: EdgeInsets.only(left: 20, top: 5), - child: Row( - children: [ - LocalText(context, "do.licence"), - ImageFile( - enabled: false, - title: "Image", - initialImgUrl: doObj.driverLicenceUrl, - onFile: (file) {}), - ], - ), - ); - final statusBox = Container( - padding: EdgeInsets.only(left: 20, top: 5), - child: Row( - children: [ - LocalText(context, "do.status"), - Container( - padding: EdgeInsets.only(left: 10), - child: Text( - doObj.status, - style: doObj.isPending - ? textHighlightBlueStyle - : doObj.isApproved - ? textHighlightGreenStyle - : textHighlightRedStyle, - ), - ), - ], - ), - ); - final deliveryStatusBox = Container( - padding: EdgeInsets.only(left: 20, top: 5), - child: Row( - children: [ - LocalText(context, "do.delivery.status"), - Container( - padding: EdgeInsets.only(left: 10, right: 15), - child: Text( - doObj.getDeliveryStatus, - style: textStyle, - ), - ), - doObj.deliveryStatus == 'initiated' - ? Text( - "(can start in $formattedTime)", - style: TextStyle(fontSize: 15, fontWeight: FontWeight.bold), - ) - : Container() - ], - ), - ); - - final typeBox = Container( - padding: EdgeInsets.only(left: 20, top: 5), - child: Row( - children: [ - LocalText(context, "do.type"), - Container( - padding: EdgeInsets.only(left: 20), - child: Text( - _type.text, - style: textStyle, - ), - ) - ], - ), - ); - - final userNameBox = Container( - padding: EdgeInsets.only(top: 5, left: 20), - child: Row( - children: [ - LocalText(context, "do.name"), - Container( - padding: EdgeInsets.only(left: 20), - child: Text( - _name.text, - style: textStyle, - ), - ) - ], - ), - ); - - final bizNameBox = Container( - padding: EdgeInsets.only(left: 20, top: 5), - child: Row( - children: [ - LocalText(context, "do.biz"), - Container( - padding: EdgeInsets.only(left: 20), - child: Text( - _bizName.text, - style: textStyle, - ), - ) - ], - ), - ); - - final driverImgUrlBox = Container( - padding: EdgeInsets.only(left: 20), - child: Row(children: [ - LocalText(context, "do.driver.image"), - Container( - padding: EdgeInsets.only(left: 10), - child: ImageFile( - enabled: !isBuyer && doObj.deliveryStatus == null, - initialImgUrl: doObj.driverImgUrl, - title: "Image", - imageSource: ImageSource.camera, - onFile: (file) { - doObj.driverImg = file; - }), - ), - ])); - - final receiptImagebox = Container( - padding: EdgeInsets.only(left: 20, top: 0), - child: Row(children: [ - LocalText(context, "do.receipt"), - Container( - padding: EdgeInsets.only(left: 10), - child: ImageFile( - enabled: false, - initialImgUrl: doObj.doReceiptUrl, - title: "Receipt", - ), - ), - ])); - - final deliveryInitTimeBox = Container( - padding: EdgeInsets.only(left: 20, top: 5), - child: Row( - children: [ - LocalText(context, "do.delivery.init.time"), - Container( - padding: EdgeInsets.only(left: 10), - child: Text( - doObj.deliveryInitTime, - style: textStyle, - ), - ) - ], - ), - ); - - final storageBox = Container( - padding: EdgeInsets.only(left: 20), - child: Row( - children: [ - LocalText(context, "do.storage_charge"), - Container( - padding: EdgeInsets.only(left: 10), - child: Text( - _storage.text, - style: textStyle, - ), - ) - ], - ), - ); - final storagePaymentBox = Container( - padding: EdgeInsets.only(left: 20), - child: Row(children: [ - LocalText(context, "do.storage_receipt"), - ImageFile( - enabled: mainModel.user.isBuyer() ? true : false, - title: "Receipt File", - initialImgUrl: this.doObj.storageReceiptUrl, - onFile: (file) { - this.files.setStorageChargeFile = file; - }), - ])); - - final commentBox = Container( - padding: EdgeInsets.only(top: 5, left: 20), - child: Row( - children: [ - LocalText(context, "do.comment"), - Container( - padding: EdgeInsets.only(left: 10), - child: Text( - _comment.text, - style: textStyle, - ), - ) - ], - ), - ); - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - title: Text(AppTranslations.of(context).text("do"), - style: Provider.of(context).isEng - ? TextStyle(fontSize: 18) - : TextStyle(fontSize: 18, fontFamily: 'MyanmarUnicode')), - actions: [ - mainModel.showHistoryBtn() - ? IconButton( - icon: Icon(Icons.history), - onPressed: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => - DocumentLogPage(docID: doObj.id)), - ); - }, - ) - : Container(), - isBuyer - ? doObj.isPending - ? PopupMenuButton( - onSelected: _selectBuyer, - itemBuilder: (context) => List.from([ - PopupMenuItem( - enabled: this.doObj.isPending && - this.doObj.storageCharge > 0, - value: 1, - child: Text("Update DO"), - ), - PopupMenuItem( - enabled: this.doObj.isPending, - value: 2, - child: Text("Cancel DO"), - ), - ])) - : Container() - : PopupMenuButton( - onSelected: _select, - itemBuilder: (context) => List.from([ - PopupMenuItem( - enabled: this.doObj.isPending, - value: 1, - child: Text("Approve DO"), - ), - PopupMenuItem( - enabled: this.doObj.isPending, - value: 2, - child: Text("Reject DO"), - ), - PopupMenuItem( - enabled: - this.doObj.isApproved && mainModel.user.isOwner(), - value: 6, - child: Text("Cancel DO"), - ) - ]), - ), - ], - ), - body: Container( - padding: - EdgeInsets.only(left: 10, right: 10, top: 10, bottom: 10), - child: Card( - elevation: 23, - child: ListView( - children: [ - Column( - children: [ - doDateBox, - Divider(), - dateBox, - Divider(), - numberBox, - Divider(), - userNameBox, - Divider(), - bizNameBox, - Divider(), - typeBox, - Divider(), - statusBox, - Divider(), - doObj.comment == null || doObj.comment == '' - ? Container() - : commentBox, - doObj.comment == null || doObj.comment == '' - ? Container() - : Divider(), - driverBox, - Divider(), - carNoBox, - Divider(), - licenceBox, - Divider(), - receiptImagebox, - Divider(), - doObj.hasStorageCharge() ? storageBox : Container(), - doObj.hasStorageCharge() ? Divider() : Container(), - doObj.hasStorageCharge() - ? storagePaymentBox - : Container(), - doObj.isApproved || doObj.isClosed - ? deliveryStatusBox - : Container(), - doObj.isApproved || doObj.isClosed - ? Divider() - : Container(), - Container( - padding: EdgeInsets.only(top: 10), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Center( - child: LocalText( - context, - 'do.products', - fontSize: 14, - fontWeight: FontWeight.bold, - underline: true, - color: secondaryColor, - ), - ), - SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: MyDataTable( - headingRowHeight: 40, - columnSpacing: 40, - columns: [ - MyDataColumn( - label: LocalText(context, "do.product"), - ), - MyDataColumn( - label: LocalText(context, "do.storage"), - ), - MyDataColumn( - label: - LocalText(context, "do.quantity"), - numeric: true), - ], - rows: getProductRow(doObj.doLines), - ), - ), - ], - ), - ), - SizedBox( - height: 15, - ), - getPOProductTable() - ], - ), - ], - ), - )), - )); - } - - List getProductRow(List doLines) { - MainModel mainModel = Provider.of(context); - ProductModel productModel = Provider.of(context); - bool isBuyer = mainModel.user.isBuyer(); - - if (doLines.isNotEmpty) { - doLines.forEach((d) { - productModel.products.forEach((p) { - if (p.id == d.productID) { - d.displayOrder = p.displayOrder; - } else { - return; - } - }); - }); - - doLines.sort((p1, p2) => p1.displayOrder.compareTo(p2.displayOrder)); - } - return doLines.map((d) { - return MyDataRow( - onSelectChanged: (bool selected) async { - if (isBuyer) return; - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => DOStorageItem( - doLine: d, - onSave: (storageID, storageName) { - setState(() { - d.storageID = storageID; - d.storageName = storageName; - }); - }, - )), - ); - }, - cells: [ - MyDataCell( - new Text( - d.productName, - style: textStyle, - ), - ), - MyDataCell( - new Text(d.storageName, style: textStyle), - ), - MyDataCell(NumberCell(d.qty)), - ], - ); - }).toList(); - } - - Widget getPOProductTable() { - return Container( - padding: EdgeInsets.only(top: 10), - child: Column( - children: [ - Center( - child: LocalText(context, 'po.info', - fontSize: 14, - fontWeight: FontWeight.bold, - underline: true, - color: secondaryColor), - ), - SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: MyDataTable( - headingRowHeight: 40, - columnSpacing: 20, - columns: [ - MyDataColumn(label: LocalText(context, "po.number")), - MyDataColumn(label: LocalText(context, "po.product")), - MyDataColumn( - label: LocalText(context, "do.po_qty"), - numeric: true, - ), - MyDataColumn( - label: LocalText(context, "do.po_balance_qty"), - numeric: true, - ), - MyDataColumn( - label: LocalText(context, "po.retrieved.amount"), - numeric: true, - ), - MyDataColumn( - label: LocalText(context, "do.do_qty"), - numeric: true, - ), - ], - rows: getPOProductRow(), - ), - ), - ], - ), - ); - } - - List getPOProductRow() { - ProductModel productModel = Provider.of(context); - if (doObj.dopoLies.isNotEmpty) { - doObj.dopoLies.sort((p1, p2) => p1.poNumber.compareTo(p2.poNumber)); - - doObj.dopoLies.forEach((d) { - productModel.products.forEach((p) { - if (p.id == d.productID) { - d.displayOrder = p.displayOrder; - } else { - return; - } - }); - }); - - doObj.dopoLies.sort((p1, p2) { - if (p1.displayOrder != p2.displayOrder) - return p1.displayOrder.compareTo(p2.displayOrder); - return p1.poNumber.compareTo(p2.poNumber); - }); - } - return doObj.dopoLies.map((d) { - return MyDataRow( - cells: [ - MyDataCell( - new Text( - d.poNumber, - style: textStyle, - ), - ), - MyDataCell( - new Text( - d.productName, - style: textStyle, - ), - ), - MyDataCell(NumberCell(d.poQty)), - MyDataCell(NumberCell(d.poBalAtCreate)), - MyDataCell(NumberCell(d.getPoBalanceQtyAtCreate)), - MyDataCell(NumberCell(d.doQty)), - ], - ); - }).toList(); - } - - _select(s) { - if (s == 1) { - showConfirmDialog(context, "do.approve.confirm", () { - _approve(); - }); - } else if (s == 2) { - showCommentDialog(context, (comment) { - doObj.comment = comment; - _reject(); - }); - } else if (s == 5) { - showConfirmDialog(context, "do.end.confirm", () { - _endDelivery(); - }); - } else if (s == 6) { - showConfirmDialog(context, "do.cancel.confirm", () { - _cancelDelivery(); - }); - } - } - - _selectBuyer(s) { - if (s == 1) { - showConfirmDialog(context, "do.confirm", () { - _submit(); - }); - } else if (s == 2) { - showConfirmDialog(context, "do.cancel.confirm", () { - _cancelDelivery(); - }); - } - } - - Future _load() async { - POSubmissionModel poModel = - Provider.of(context, listen: false); - DOModel doModel = Provider.of(context, listen: false); - - var _doSub = await poModel.loadDOLines(doObj); - _doSub = await doModel.loadDOPOLines(_doSub); - // set po balance - List pos = _doSub.getPOs(); - for (var po in pos) { - List poLines = await poModel.loadPOLines(po); - _doSub.setDOPOLineBalance(po, poLines); - } - if (mounted) { - setState(() { - doObj.doLines = _doSub.doLines; - doObj.dopoLies = _doSub.dopoLies; - }); - } - } - - _approve() async { - if (doObj.doLines.any((l) => l.storageID.isEmpty)) { - showMsgDialog(context, "Error", "Storage required for every product"); - return; - } - setState(() { - _isLoading = true; - }); - try { - DOModel doModel = Provider.of(context); - await doModel.approveDO(doObj); - Navigator.pop(context); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - setState(() { - _isLoading = false; - }); - } - } - - _reject() async { - setState(() { - _isLoading = true; - }); - try { - DOModel doModel = Provider.of(context); - await doModel.rejectDO(doObj); - Navigator.pop(context); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - setState(() { - _isLoading = false; - }); - } - } - - _initDelivery() async { - if (doObj.driverImg == null) { - showMsgDialog(context, "Error", "Please attach driver image"); - return; - } - setState(() { - _isLoading = true; - }); - try { - DOModel doModel = Provider.of(context); - await doModel.initDelivery(doObj); - Navigator.pop(context); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - setState(() { - _isLoading = false; - }); - } - } - - _startDelivery() async { - MainModel mainModel = Provider.of(context); - Duration diff = DateTime.now().difference(doObj.deliveryInitiatedTime); - if (diff.inMinutes < mainModel.setting.deliveryStartWaitMin) { - showMsgDialog(context, "Waiting...", - "Can not start delivery, wait for ${mainModel.setting.deliveryStartWaitMin} minutes"); - return; - } - setState(() { - _isLoading = true; - }); - try { - DOModel doModel = Provider.of(context); - await doModel.startDelivery(doObj); - Navigator.pop(context); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - setState(() { - _isLoading = false; - }); - } - } - - _endDelivery() async { - var photo = await Navigator.push( - context, - MaterialPageRoute(builder: (context) => PhotoPage()), - ); - if (photo == null) { - return; - } - Uint8List bytesPhoto = photo.readAsBytesSync() as Uint8List; - - setState(() { - _isLoading = true; - }); - try { - DOModel doModel = Provider.of(context); - await doModel.endDelivery(doObj, bytesPhoto); - Navigator.pop(context); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - setState(() { - _isLoading = false; - }); - } - } - - _cancelDelivery() async { - setState(() { - _isLoading = true; - }); - try { - DOModel doModel = Provider.of(context); - await doModel.cancelDO(doObj); - Navigator.pop(context); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - setState(() { - _isLoading = false; - }); - } - } - - _submit() async { - if (doObj.hasStorageCharge()) { - if (files.storageChargeFile == null && doObj.storageReceiptUrl == '') { - showMsgDialog(context, "Error", "Please insert storage receipt"); - return; - } - } - - setState(() { - _isLoading = true; - }); - try { - DOModel doModel = Provider.of(context); - await doModel.updateDO(doObj, files); - Navigator.pop(context, true); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - setState(() { - _isLoading = false; - }); - } - } -} diff --git a/lib/pages/do/do_creation_form.dart b/lib/pages/do/do_creation_form.dart deleted file mode 100644 index 843bba4..0000000 --- a/lib/pages/do/do_creation_form.dart +++ /dev/null @@ -1,644 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_datetime_picker/flutter_datetime_picker.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/do_model.dart'; -import 'package:fcs/model/language_model.dart'; -import 'package:fcs/model/main_model.dart'; -import 'package:fcs/model/po_model.dart'; -import 'package:fcs/model/product_model.dart'; -import 'package:fcs/pages/do/do_product_item.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/do.dart'; -import 'package:fcs/vo/po.dart'; -import 'package:fcs/widget/img_file.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:fcs/widget/my_data_table.dart'; -import 'package:fcs/widget/number_cell.dart'; -import 'package:fcs/widget/progress.dart'; - -import 'do_files.dart'; -import 'po_selection.dart'; - -class DOForm extends StatefulWidget { - final DOSubmission doSubmission; - const DOForm({this.doSubmission}); - @override - _DOFormState createState() => _DOFormState(); -} - -class _DOFormState extends State { - var dateFormatter = new DateFormat('dd MMM yyyy'); - final numberFormatter = new NumberFormat("#,###"); - - TextEditingController _deliveryDate = new TextEditingController(); - TextEditingController _licence = new TextEditingController(); - TextEditingController _driver = new TextEditingController(); - TextEditingController _carNo = new TextEditingController(); - TextEditingController _doStatus = new TextEditingController(); - TextEditingController _storage = new TextEditingController(); - TextEditingController _doNumber = new TextEditingController(); - DOSubmission doSubmission = DOSubmission(); - - bool _isLoading = false; - bool _isNew = true; - final _formKey = GlobalKey(); - int doTypeValue = 0; - DOLine doLine = new DOLine(); - DOFiles files = DOFiles(); - - @override - void initState() { - super.initState(); - - if (widget.doSubmission != null) { - this.doSubmission = widget.doSubmission; - this._isNew = false; - _deliveryDate.text = - dateFormatter.format(widget.doSubmission.deliveryDate); - _licence.text = widget.doSubmission.driverLicenseNumber; - _driver.text = widget.doSubmission.driverName; - _carNo.text = widget.doSubmission.carNo; - _doStatus.text = widget.doSubmission.status; - _storage.text = widget.doSubmission.storageCharge == null - ? "" - : numberFormatter.format(widget.doSubmission.storageCharge); - _doNumber.text = widget.doSubmission.doNumber; - - if (widget.doSubmission.type == 'multiple') { - doTypeValue = 1; - } else { - doTypeValue = 0; - } - this.doLine.action = 'update'; - } else { - this.doLine.action = 'create'; - doSubmission.type = 'single'; - _storage.text = "0"; - } - } - - @override - Widget build(BuildContext context) { - var languageModel = Provider.of(context); - var mainModel = Provider.of(context); - var poModel = Provider.of(context); - - bool isBuyer = mainModel.user.isBuyer(); - - final doNumberBox = Container( - padding: EdgeInsets.only(left: 20, top: 10), - child: Row( - children: [ - LocalText(context, "do.do_num"), - Container( - padding: EdgeInsets.only(left: 10), - child: Text( - _doNumber.text, - style: textStyle, - ), - ) - ], - ), - ); - final _doTypeValueBox = Container( - padding: EdgeInsets.only(left: 20, top: 0), - child: Row( - children: [ - LocalText(context, "do.type"), - Container( - width: 130, - child: RadioListTile( - dense: true, - title: LocalText(context, "do.single"), - value: 0, - groupValue: doTypeValue, - onChanged: handleRadioValueChanged, - activeColor: primaryColor, - ), - ), - Container( - width: 136, - child: RadioListTile( - dense: true, - title: LocalText(context, 'do.multiple'), - value: 1, - groupValue: doTypeValue, - onChanged: handleRadioValueChanged, - activeColor: primaryColor, - )) - ], - ), - ); - - final deliveryDateBox = Container( - padding: EdgeInsets.only(left: 20, right: 15), - child: InkWell( - onTap: () { - DatePicker.showDatePicker(context, - showTitleActions: true, - currentTime: _deliveryDate.text == "" - ? null - : dateFormatter.parse(_deliveryDate.text), - minTime: DateTime.now(), - maxTime: DateTime(2030, 12, 31), onConfirm: (date) { - setState(() { - _deliveryDate.text = dateFormatter.format(date); - doSubmission.deliveryDate = - dateFormatter.parse(_deliveryDate.text); - doSubmission.updateStorageCharge(mainModel.setting); - }); - }, locale: LocaleType.en); - }, - child: TextFormField( - controller: _deliveryDate, - autofocus: false, - cursorColor: primaryColor, - style: textStyle, - enabled: false, - keyboardType: TextInputType.datetime, - decoration: new InputDecoration( - border: InputBorder.none, - focusedBorder: InputBorder.none, - labelText: AppTranslations.of(context).text("do.date"), - labelStyle: languageModel.isEng ? labelStyle : labelStyleMM, - contentPadding: - EdgeInsets.symmetric(vertical: 10.0, horizontal: 0.0), - icon: Icon( - Icons.date_range, - color: primaryColor, - )), - validator: (value) { - if (value.isEmpty) { - return AppTranslations.of(context).text("do.form.date"); - } - return null; - }, - ), - )); - - final driverBox = Container( - padding: EdgeInsets.only(left: 20, right: 15), - child: TextFormField( - controller: _driver, - autofocus: false, - style: textStyle, - cursorColor: primaryColor, - decoration: new InputDecoration( - labelText: AppTranslations.of(context).text("do.driver"), - labelStyle: languageModel.isEng ? labelStyle : labelStyleMM, - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide(color: Colors.grey, width: 1.0)), - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide(color: Colors.grey, width: 1.0)), - icon: Icon( - Icons.account_box, - color: primaryColor, - )), - validator: (value) { - if (value.isEmpty) { - return AppTranslations.of(context).text("do.form.driver"); - } - return null; - }, - )); - - final carNoBox = Container( - padding: EdgeInsets.only(left: 20, right: 15), - child: TextFormField( - controller: _carNo, - autofocus: false, - style: textStyle, - cursorColor: primaryColor, - decoration: new InputDecoration( - labelText: AppTranslations.of(context).text("do.car"), - labelStyle: languageModel.isEng ? labelStyle : labelStyleMM, - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide(color: Colors.grey, width: 1.0)), - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide(color: Colors.grey, width: 1.0)), - icon: Icon( - Icons.directions_car, - color: primaryColor, - )), - validator: (value) { - if (value.isEmpty) { - return AppTranslations.of(context).text("do.form.car"); - } - return null; - }, - )); - - final doStatusBox = Container( - padding: EdgeInsets.only(left: 20, right: 15), - child: TextFormField( - controller: _doStatus, - autofocus: false, - style: textStyle, - readOnly: true, - decoration: new InputDecoration( - border: InputBorder.none, - focusedBorder: InputBorder.none, - icon: Image.asset("assets/status.png", - width: 25, color: primaryColor)), - validator: (value) { - if (value.isEmpty) { - return "Please enter DO Status"; - } - return null; - }, - )); - - final storageBox = Container( - padding: EdgeInsets.only(left: 20, top: 10), - child: Row( - children: [ - LocalText(context, "do.storage_charge"), - Container( - padding: EdgeInsets.only(left: 10), - child: Text( - doSubmission.storageCharge == null - ? "" - : numberFormatter.format(doSubmission.storageCharge), - style: textStyle, - ), - ) - ], - ), - ); - final storagePaymentBox = Container( - padding: EdgeInsets.only(left: 20, top: 5), - child: Row(children: [ - LocalText(context, "do.storage_receipt"), - ImageFile( - enabled: isBuyer, - title: "Receipt File", - initialImgUrl: this.doSubmission.storageReceiptUrl, - onFile: (file) { - this.files.setStorageChargeFile = file; - }), - ])); - final licesebox = Container( - padding: EdgeInsets.only(left: 20, top: 5), - child: Row(children: [ - LocalText(context, "do.licence"), - ImageFile( - enabled: isBuyer, - title: "Image", - initialImgUrl: this.doSubmission.driverLicenceUrl, - onFile: (file) { - this.files.setlicenseFile = file; - }), - ])); - - final poButtun = Container( - padding: EdgeInsets.only(left: 20, top: 5), - child: Row(children: [ - LocalText(context, "po.title"), - IconButton( - onPressed: () async { - POSelection.showPOSelection( - context, poModel.approvedPOs, doSubmission.pos, - ok: (List pos) async { - for (var po in pos) { - po.poLines = await poModel.loadPOLines(po.id); - } - setState(() { - doSubmission.pos = pos; - doSubmission.loadPOs(); - doSubmission.updateStorageCharge(mainModel.setting); - }); - }); - }, - icon: Icon(Icons.edit)), - ])); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - title: Text(AppTranslations.of(context).text("do"), - style: Provider.of(context).isEng - ? TextStyle(fontSize: 18) - : TextStyle(fontSize: 18, fontFamily: 'MyanmarUnicode')), - actions: [ - IconButton( - icon: Icon(Icons.send), - onPressed: () { - if (!_formKey.currentState.validate()) return; - showConfirmDialog(context, "do.confirm", () { - _submit(mainModel); - }); - }, - ) - ], - ), - body: Form( - key: _formKey, - child: Container( - child: ListView( - children: [ - Container( - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - this.doSubmission.doNumber != null - ? doNumberBox - : Container(), - this.doSubmission.hasStorageCharge() - ? storageBox - : Container(), - this.doSubmission.hasStorageCharge() - ? storagePaymentBox - : Container(), - _doTypeValueBox, - deliveryDateBox, - driverBox, - licesebox, - carNoBox, - poButtun, - widget.doSubmission == null ? Container() : doStatusBox, - getProductTable(), - getPOProductTable(), - ], - ), - ), - ], - ), - ), - )), - ); - } - - void handleRadioValueChanged(int value) { - var mainModel = Provider.of(context, listen: false); - setState(() { - doSubmission.type = value == 0 ? 'single' : 'multiple'; - doTypeValue = value; - doSubmission.loadPOs(); - doSubmission.updateStorageCharge(mainModel.setting); - switch (doTypeValue) { - case 0: - break; - case 1: - break; - } - }); - } - - Widget getProductTable() { - return Container( - padding: EdgeInsets.only(top: 10), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Center( - child: LocalText( - context, - 'do.products', - fontSize: 14, - fontWeight: FontWeight.bold, - underline: true, - color: secondaryColor, - ), - ), - SingleChildScrollView( - scrollDirection: Axis.horizontal, - padding: EdgeInsets.only(top: 10), - child: MyDataTable( - headingRowHeight: 40, - columnSpacing: 20, - columns: [ - MyDataColumn(label: LocalText(context, "do.product")), - MyDataColumn( - label: LocalText(context, "po.avail.qty"), numeric: true), - MyDataColumn( - label: LocalText(context, "do.do_qty"), - numeric: true, - ), - ], - rows: getProductRow(doSubmission.doLines), - ), - ), - ], - ), - ); - } - - List getProductRow(List doLines) { - ProductModel productModel = Provider.of(context); - if (doLines.isNotEmpty) { - doLines.forEach((d) { - productModel.products.forEach((p) { - if (p.id == d.productID) { - d.displayOrder = p.displayOrder; - } else { - return; - } - }); - }); - - doLines.sort((p1, p2) => p1.displayOrder.compareTo(p2.displayOrder)); - } - return doLines.map((d) { - return MyDataRow( - onSelectChanged: (bool selected) async { - if (doTypeValue == 0) return; - var doLine = await showDialog( - context: context, - builder: (_) => DOProductItem( - doLine: DOLine(productID: d.productID, qty: d.qty), - )); - _updateQty(doLine); - }, - cells: [ - MyDataCell( - new Text( - d.productName, - style: textStyle, - ), - ), - MyDataCell(NumberCell(d.poBalQty)), - MyDataCell( - Container( - color: Colors.cyan, - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - new Text(d.qty == null ? "0" : d.qty.toString(), - style: textStyle), - ], - )), - ), - ], - ); - }).toList(); - } - - Widget getPOProductTable() { - return Container( - padding: EdgeInsets.only(top: 10), - child: Column( - children: [ - Center( - child: LocalText(context, 'po.info', - fontSize: 14, - fontWeight: FontWeight.bold, - underline: true, - color: secondaryColor), - ), - SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: MyDataTable( - headingRowHeight: 40, - columnSpacing: 20, - columns: [ - MyDataColumn(label: LocalText(context, "po.number")), - MyDataColumn(label: LocalText(context, "po.product")), - MyDataColumn( - label: LocalText(context, "do.po_qty"), - numeric: true, - ), - MyDataColumn( - label: LocalText(context, "po.avail.qty"), - numeric: true, - ), - MyDataColumn( - label: LocalText(context, "po.retrieved.amount"), - numeric: true, - ), - MyDataColumn( - label: LocalText(context, "do.do_qty"), - numeric: true, - ), - ], - rows: getPOProductRow(), - ), - ), - ], - ), - ); - } - - List getPOProductRow() { - ProductModel productModel = Provider.of(context); - if (doSubmission.dopoLies.isNotEmpty) { - doSubmission.dopoLies - .sort((p1, p2) => p1.poNumber.compareTo(p2.poNumber)); - doSubmission.dopoLies.forEach((d) { - productModel.products.forEach((p) { - if (p.id == d.productID) { - d.displayOrder = p.displayOrder; - } else { - return; - } - }); - }); - - doSubmission.dopoLies.sort((p1, p2) { - if (p1.displayOrder != p2.displayOrder) - return p1.displayOrder.compareTo(p2.displayOrder); - return p1.poNumber.compareTo(p2.poNumber); - }); - } - return doSubmission.dopoLies.map((d) { - return MyDataRow( - cells: [ - MyDataCell( - new Text( - d.poNumber, - style: textStyle, - ), - ), - MyDataCell( - new Text( - d.productName, - style: textStyle, - ), - ), - MyDataCell(NumberCell(d.poQty)), - MyDataCell(NumberCell(d.poBalQty)), - MyDataCell(NumberCell(d.getPoBalanceQty)), - MyDataCell( - Container( - color: Colors.grey, - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - new Text(d.doQty == null ? "0" : d.doQty.toString(), - style: textStyle), - ], - )), - ), - ], - ); - }).toList(); - } - - _updateQty(DOLine doLine) { - if (doLine == null) return; - - try { - var mainModel = Provider.of(context); - setState(() { - doSubmission.updateDoline(doLine.productID, doLine.qty); - doSubmission.updateStorageCharge(mainModel.setting); - }); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } - } - - _submit(MainModel mainModel) async { - if (doSubmission.doLines.length == 0) { - showMsgDialog(context, "Error", "No product line"); - return; - } - if (files.licenseFile == null) { - showMsgDialog(context, "Error", "Please insert driver licence"); - return; - } - - int total = 0; - doSubmission.doLines.forEach((doLine) { - total += doLine.qty; - }); - - if (total <= 0) { - showMsgDialog(context, "Error", "must be greater than zero"); - return; - } - - doSubmission.carNo = _carNo.text; - doSubmission.driverName = _driver.text; - doSubmission.driverLicenseNumber = _licence.text; - doSubmission.deliveryDate = dateFormatter.parse(_deliveryDate.text); - doSubmission.type = doTypeValue == 0 ? 'single' : 'multiple'; - doSubmission.doLines.removeWhere((d) => d.qty == 0); - doSubmission.dopoLies.removeWhere((d) => d.doQty == 0); - - setState(() { - _isLoading = true; - }); - try { - DOModel doModel = Provider.of(context); - - if (_isNew) { - await doModel.createDO(doSubmission, files); - } else { - await doModel.updateDO(doSubmission, files); - } - Navigator.pop(context, true); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - setState(() { - _isLoading = false; - }); - } - } -} diff --git a/lib/pages/do/do_creation_todelete.dart b/lib/pages/do/do_creation_todelete.dart deleted file mode 100644 index 6215b66..0000000 --- a/lib/pages/do/do_creation_todelete.dart +++ /dev/null @@ -1,423 +0,0 @@ -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/language_model.dart'; -import 'package:fcs/model/po_model.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/do.dart'; -import 'package:fcs/vo/po.dart'; -import 'package:fcs/widget/img_file.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; - -import 'package:flutter/material.dart'; -import 'package:flutter/widgets.dart'; -import 'package:progress/progress.dart'; -import 'package:fcs/widget/my_data_table.dart'; -import 'package:fcs/widget/progress.dart'; - -import 'do_creation_form.dart'; - -class DoCreation extends StatefulWidget { - final POSubmission poSubmission; - const DoCreation({this.poSubmission}); - @override - _DoCreationState createState() => _DoCreationState(); -} - -class _DoCreationState extends State { - var dateFormatter = new DateFormat('dd MMM yyyy'); - bool _isLoading = false; - TextEditingController _podate = new TextEditingController(); - TextEditingController _ponumber = new TextEditingController(); - TextEditingController _postatus = new TextEditingController(); - POSubmission poSubmission = POSubmission(); - - @override - void initState() { - super.initState(); - this.poSubmission = widget.poSubmission; - _podate.text = dateFormatter.format(this.poSubmission.poDate); - _ponumber.text = this.poSubmission.poNumber.toString(); - _postatus.text = this.poSubmission.status; - _isLoading = true; - _load(); - } - - Future _load() async { - List poLines = - await Provider.of(context, listen: false) - .loadPOLines(poSubmission.id); - var _poDos = await Provider.of(context, listen: false) - .loadDOs(poSubmission); - setState(() { - this.poSubmission.poLines = poLines; - this.poSubmission.dos = _poDos.dos; - _isLoading = false; - }); - } - - Widget doDateBox(BuildContext context, DOSubmission doSubmission) { - return Container( - padding: EdgeInsets.only(left: 20, top: 0), - child: Row( - children: [ - LocalText(context, "do.date"), - Container( - padding: EdgeInsets.only(left: 10), - child: Text( - dateFormatter.format(doSubmission.deliveryDate), - style: textStyle, - ), - ) - ], - ), - ); - } - - Widget doNumberBox(BuildContext context, DOSubmission doSubmission) { - return Container( - padding: EdgeInsets.only(left: 20, top: 5), - child: Row( - children: [ - LocalText(context, "do.do_num"), - Container( - padding: EdgeInsets.only(left: 10), - child: Text( - doSubmission.doNumber, - style: textStyle, - ), - ) - ], - ), - ); - } - - Widget driverBox(BuildContext context, DOSubmission doSubmission) { - return Container( - padding: EdgeInsets.only(left: 20, top: 5), - child: Row( - children: [ - LocalText(context, "do.driver"), - Container( - padding: EdgeInsets.only(left: 10), - child: Text( - doSubmission.driverName, - style: textStyle, - ), - ) - ], - ), - ); - } - - Widget carNoBox(BuildContext context, DOSubmission doSubmission) { - return Container( - padding: EdgeInsets.only(left: 20, top: 5), - child: Row( - children: [ - LocalText(context, "do.car"), - Container( - padding: EdgeInsets.only(left: 10), - child: Text( - doSubmission.carNo, - style: textStyle, - ), - ) - ], - ), - ); - } - - Widget doStatusBox(BuildContext context, DOSubmission doSubmission) { - return Container( - padding: EdgeInsets.only(left: 20, top: 5), - child: Row( - children: [ - LocalText(context, "do.status"), - Container( - padding: EdgeInsets.only(left: 10), - child: Text( - doSubmission.status, - style: textStyle, - ), - ) - ], - ), - ); - } - - Widget driverLicence(BuildContext context, DOSubmission doSubmission) { - return Container( - padding: EdgeInsets.only(left: 20, top: 5), - child: Row( - children: [ - LocalText(context, "do.licence"), - ImageFile( - enabled: false, - title: "Receipt File", - initialImgUrl: doSubmission.driverLicenceUrl, - onFile: (file) {}), - ], - ), - ); - } - - @override - Widget build(BuildContext context) { - var languageModle = Provider.of(context); - - final poDateBox = Container( - padding: EdgeInsets.only(left: 20, top: 15), - child: Row( - children: [ - LocalText(context, "po.date"), - Container( - padding: EdgeInsets.only(left: 10), - child: Text( - _podate.text, - style: textStyle, - ), - ) - ], - ), - ); - - final poNumberBox = Container( - padding: EdgeInsets.only(left: 20, top: 5), - child: Row( - children: [ - LocalText(context, "do.po_num"), - Container( - padding: EdgeInsets.only(left: 10), - child: Text( - _ponumber.text, - style: textStyle, - ), - ) - ], - ), - ); - - final poStatusBox = Container( - padding: EdgeInsets.only(left: 20, top: 5), - child: Row( - children: [ - LocalText(context, "po.status"), - Container( - padding: EdgeInsets.only(left: 10), - child: Text( - _postatus.text, - style: textStyle, - ), - ) - ], - ), - ); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - title: Text(AppTranslations.of(context).text("do.title"), - style: languageModle.isEng - ? TextStyle(fontSize: 18) - : TextStyle(fontSize: 18, fontFamily: 'MyanmarUnicode')), - ), - floatingActionButton: FloatingActionButton( - backgroundColor: primaryColor, - heroTag: "btn2", - onPressed: () async { - if (poSubmission.poLines - .fold(0, (p, e) => p + e.balanceQty) == - 0) { - showMsgDialog(context, "Error", "Zero PO balance qty"); - return; - } - - final bool successful = await Navigator.push( - context, MaterialPageRoute(builder: (context) => DOForm())); - if (successful != null && successful) _load(); - }, - child: Icon(Icons.add), - ), - body: Container( - padding: EdgeInsets.only(top: 5), - child: ListView( - children: [ - Container( - padding: EdgeInsets.only(left: 10, right: 10), - child: Card( - elevation: 23, - child: Column( - children: [ - poDateBox, - poNumberBox, - poStatusBox, - Container( - padding: EdgeInsets.only(top: 10), - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: MyDataTable( - headingRowHeight: 40, - columnSpacing: 15, - columns: [ - MyDataColumn( - label: LocalText(context, "po.product"), - ), - MyDataColumn( - label: LocalText(context, "do.po_qty"), - ), - MyDataColumn( - label: - LocalText(context, "do.po_balance_qty"), - ), - ], - rows: - getPoProductRow(widget.poSubmission.poLines), - ), - ), - ), - SizedBox( - height: 15, - ) - ], - ), - ), - ), - Column( - children: getDos(poSubmission.dos), - ), - SizedBox( - height: 10, - ) - ], - ), - ), - )); - } - - List getPoProductRow(List poLines) { - return poLines.map((p) { - return MyDataRow( - cells: [ - MyDataCell( - new Text( - p.productName, - style: textStyle, - ), - ), - MyDataCell( - new Text(p.qty.toString(), style: textStyle), - ), - MyDataCell( - new Text(p.balanceQty.toString(), style: textStyle), - ), - ], - ); - }).toList(); - } - - List getDos(List dos) { - return dos.map((d) { - return Container( - padding: EdgeInsets.only(left: 10, right: 10), - child: Card( - child: Theme( - data: ThemeData(accentColor: Colors.grey), - child: ExpansionTile( - onExpansionChanged: (e) => _onExpend(context, e, d), - title: ListTile( - title: Text(dateFormatter.format(d.deliveryDate)), - subtitle: Text(d.doNumber), - ), - children: [ - Container( - child: Column( - children: [ - Align( - alignment: Alignment.topRight, - child: Container( - padding: EdgeInsets.only(right: 20), - child: InkWell( - child: Icon(Icons.edit), - onTap: () async { - final bool successful = - await Navigator.push( - context, - MaterialPageRoute( - builder: (context) => DOForm( - doSubmission: d, - ))); - if (successful != null && successful) _load(); - }, - )), - ), - doDateBox(context, d), - doNumberBox(context, d), - doStatusBox(context, d), - driverBox(context, d), - carNoBox(context, d), - driverLicence(context, d), - Container( - alignment: AlignmentDirectional.centerStart, - padding: EdgeInsets.only(top: 10), - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: MyDataTable( - headingRowHeight: 40, - columnSpacing: 15, - columns: [ - MyDataColumn( - label: LocalText(context, "do.product"), - ), - MyDataColumn( - label: LocalText(context, "do.do_qty"), - ), - ], - rows: getdoProductRow(d.doLines), - ), - ), - ), - SizedBox( - height: 15, - ) - ], - ), - ), - ], - ), - ), - ), - ); - }).toList(); - } - - List getdoProductRow(List doLines) { - return doLines.map((p) { - return MyDataRow( - cells: [ - MyDataCell( - new Text( - p.productName, - style: textStyle, - ), - ), - MyDataCell( - new Text(p.qty.toString(), style: textStyle), - ), - ], - ); - }).toList(); - } - - _onExpend(BuildContext context, expended, DOSubmission doSub) async { - if (!expended) return; - POSubmissionModel poModel = Provider.of(context); - var _doSub = await poModel.loadDOLines(doSub); - setState(() { - doSub = _doSub; - }); - } -} diff --git a/lib/pages/do/do_files.dart b/lib/pages/do/do_files.dart deleted file mode 100644 index 70bbdaa..0000000 --- a/lib/pages/do/do_files.dart +++ /dev/null @@ -1,26 +0,0 @@ -import 'dart:io'; - -class DOFiles { - File doPaymentFile, storageChargeFile, licenseFile; - bool doFileChanged = false, - storageFileChanged = false, - licenseFileChanged = false; - - set setDoPaymentFile(File file) { - doPaymentFile = file; - doFileChanged = true; - } - - set setStorageChargeFile(File file) { - storageChargeFile = file; - storageFileChanged = true; - } - - set setlicenseFile(File file) { - licenseFile = file; - licenseFileChanged = true; - } - - bool get anyChanged => - doFileChanged || storageFileChanged || licenseFileChanged; -} diff --git a/lib/pages/do/do_list.dart b/lib/pages/do/do_list.dart deleted file mode 100644 index b435c55..0000000 --- a/lib/pages/do/do_list.dart +++ /dev/null @@ -1,286 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/do_model.dart'; -import 'package:fcs/model/language_model.dart'; -import 'package:fcs/model/main_model.dart'; -import 'package:fcs/pages/do/do_creation_form.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/popup_menu.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:fcs/widget/popupmenu.dart'; -import 'package:fcs/widget/progress.dart'; - -import 'do_approve.dart'; - -class DOList extends StatefulWidget { - @override - _DOListState createState() => _DOListState(); -} - -class _DOListState extends State { - var dateFormatter = new DateFormat('dd MMM yyyy'); - final double dotSize = 10.0; - DateTime _selectedDate = DateTime.now(); - String status; - int _selectedIndex = 0; - int _dateIndex = 0; - bool _isLoading = false; - - @override - void initState() { - super.initState(); - - var doModel = Provider.of(context, listen: false); - _selectedIndex = doModel.popupMenu.index; - _dateIndex = doModel.dateIndex; - _selectedDate = doModel.selectedDate; - } - - @override - void dispose() { - super.dispose(); - } - - Future _selectDate(BuildContext context) async { - var doModel = Provider.of(context); - - final DateTime picked = await showDatePicker( - context: context, - initialDate: _selectedDate, - firstDate: DateTime(2015, 8), - lastDate: DateTime(2101), - builder: (BuildContext context, Widget child) { - return Theme( - data: ThemeData.light().copyWith( - primaryColor: primaryColor, //Head background - accentColor: secondaryColor, //selection color - dialogBackgroundColor: Colors.white, //Background color - ), - child: child, - ); - }, - ); - - if (picked != null) { - var pickedDate = new DateTime(picked.year, picked.month, picked.day); - var currentDate = new DateTime( - DateTime.now().year, DateTime.now().month, DateTime.now().day); - this._dateIndex = pickedDate == currentDate ? 0 : 1; - setState(() { - _selectedDate = picked; - doModel.filterData(status, _selectedDate, _selectedIndex, _dateIndex); - }); - } - } - - @override - Widget build(BuildContext context) { - var doModel = Provider.of(context); - MainModel mainModel = Provider.of(context); - bool isBuyer = mainModel.user.isBuyer(); - var languageModle = Provider.of(context); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - title: Text( - AppTranslations.of(context).text("do.title"), - style: languageModle.isEng - ? TextStyle() - : TextStyle(fontFamily: 'MyanmarUnicode'), - ), - actions: [ - InkWell( - child: Container( - padding: EdgeInsets.only(top: 15), - child: Stack( - children: [ - Image.asset( - "assets/date_filter.png", - color: Colors.white, - width: 25, - ), - _dateIndex == 0 - ? Container() - : Positioned( - bottom: 15, - right: 10, - child: Container( - width: 10, - height: 10, - decoration: new BoxDecoration( - shape: BoxShape.circle, - color: secondaryColor, - ), - ), - ) - ], - ), - ), - onTap: () => _selectDate(context), - ), - PopupMenuButton( - elevation: 3.2, - onSelected: (selected) { - setState(() { - _selectedIndex = selected.index; - }); - if (selected.status == 'All') { - status = null; - } else { - status = selected.status; - } - doModel.filterData( - status, _selectedDate, _selectedIndex, _dateIndex); - }, - icon: Container( - width: 30, - height: 30, - decoration: new BoxDecoration( - shape: BoxShape.circle, - color: Colors.white, - ), - child: Stack( - fit: StackFit.expand, - children: [ - Icon( - Icons.filter_list, - color: primaryColor, - ), - _selectedIndex != 0 - ? Positioned( - bottom: 0, - right: 0, - child: Container( - width: 10, - height: 10, - decoration: new BoxDecoration( - shape: BoxShape.circle, - color: secondaryColor, - ), - ), - ) - : Container() - ], - )), - itemBuilder: (BuildContext context) { - return statusMenu.map((PopupMenu choice) { - return PopupMenuItem( - value: choice, - child: Row( - children: [ - Text(choice.status), - SizedBox( - width: 10, - ), - _selectedIndex != null && - _selectedIndex == choice.index - ? Icon( - Icons.check, - color: Colors.grey, - ) - : Container(), - ], - ), - ); - }).toList(); - }), - ], - ), - floatingActionButton: mainModel.isBuyer() - ? FloatingActionButton( - backgroundColor: primaryColor, - onPressed: () => Navigator.push( - context, - MaterialPageRoute(builder: (context) => DOForm()), - ), - child: Icon(Icons.add), - ) - : null, - body: new ListView.builder( - scrollDirection: Axis.vertical, - padding: EdgeInsets.only(left: 15, right: 15, top: 15), - shrinkWrap: true, - itemCount: doModel.dos.length, - itemBuilder: (BuildContext context, int index) { - return Card( - elevation: 10, - color: Colors.white, - child: Row( - children: [ - Expanded( - child: InkWell( - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => DOApproval( - doSubmission: doModel.dos[index])), - ); - }, - child: new Padding( - padding: const EdgeInsets.symmetric(vertical: 16.0), - child: new Row( - children: [ - new Padding( - padding: new EdgeInsets.symmetric( - horizontal: 32.0 - dotSize / 2), - child: Padding( - padding: EdgeInsets.all(5.0), - child: Image.asset( - "assets/do.png", - width: 40, - height: 40, - color: primaryColor, - ), - ), - ), - new Expanded( - child: new Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - new Text( - doModel.dos[index].doNumber, - style: new TextStyle( - fontSize: 12.0, color: Colors.black), - ), - new Text( - doModel.dos[index].deliveryDate == null - ? "" - : dateFormatter.format( - doModel.dos[index].deliveryDate), - style: new TextStyle( - fontSize: 14.0, color: Colors.grey), - ), - !isBuyer - ? new Text( - doModel.dos[index].userName, - style: new TextStyle( - fontSize: 12.0, - color: Colors.grey), - ) - : Container() - ], - ), - ), - Container( - padding: EdgeInsets.only(right: 15), - child: getStatus(doModel.dos[index].status), - ), - ], - ), - ), - ), - ), - ], - ), - ); - }), - ), - ); - } -} diff --git a/lib/pages/do/do_product_item.dart b/lib/pages/do/do_product_item.dart deleted file mode 100644 index 186da53..0000000 --- a/lib/pages/do/do_product_item.dart +++ /dev/null @@ -1,134 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/language_model.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/do.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:fcs/widget/progress.dart'; - -class DOProductItem extends StatefulWidget { - final DOLine doLine; - const DOProductItem({Key key, this.doLine}) : super(key: key); - @override - _DOProductItemState createState() => _DOProductItemState(); -} - -class _DOProductItemState extends State { - final _formKey = GlobalKey(); - TextEditingController _doQty = new TextEditingController(); - DOLine doLine; - bool _isLoading = false; - - @override - void initState() { - super.initState(); - if (widget.doLine != null) { - doLine = widget.doLine; - _doQty.text = widget.doLine.qty.toString(); - } - } - - @override - Widget build(BuildContext context) { - var languageModel = Provider.of(context); - - return LocalProgress( - inAsyncCall: _isLoading, - child: AlertDialog( - title: Center( - child: Text( - AppTranslations.of(context).text("do_qty"), - style: TextStyle( - color: primaryColor, fontWeight: FontWeight.bold, fontSize: 20), - )), - content: Form( - key: _formKey, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - new Expanded( - child: new TextFormField( - keyboardType: TextInputType.number, - autofocus: true, - controller: _doQty, - style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20), - cursorColor: primaryColor, - decoration: new InputDecoration( - fillColor: primaryColor, - icon: Icon( - FontAwesomeIcons.sortNumericUpAlt, - color: primaryColor, - ), - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide(color: Colors.grey, width: 1.0)), - ), - validator: (value) { - if (value.isEmpty) { - return AppTranslations.of(context).text("do.form.volume"); - } - return null; - }, - )) - ], - ), - ), - actions: [ - FlatButton( - child: LocalText( - context, - 'do.cancel', - color: secondaryColor, - ), - onPressed: () { - _doQty.clear(); - Navigator.of(context).pop(); - }), - FlatButton( - color: primaryColor, - child: LocalText( - context, - 'do.enter', - color: Colors.white, - fontWeight: FontWeight.bold, - ), - onPressed: () async { - if (!_formKey.currentState.validate()) return; - _save(); - }) - ], - ), - ); - } - - _save() { - setState(() { - _isLoading = true; - }); - try { - var qty = int.parse(_doQty.text); - if (qty < 0) - throw Exception("invalid number, must be zero or greater than zero"); - // if (qty > doLine.poLine.balanceQty) - // throw Exception( - // "invalid number, must be less than or equal to PO balance qty"); - this.doLine.qty = qty; - Navigator.pop(context, this.doLine); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - setState(() { - _isLoading = false; - }); - } - } - - _delete() { - this.doLine.action = "delete"; - this.doLine.qty = 0; - Navigator.pop(context, this.doLine); - } -} diff --git a/lib/pages/do/do_storage_item.dart b/lib/pages/do/do_storage_item.dart deleted file mode 100644 index 1e3447e..0000000 --- a/lib/pages/do/do_storage_item.dart +++ /dev/null @@ -1,209 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/storage_model.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/util.dart'; -import 'package:fcs/vo/do.dart'; -import 'package:fcs/vo/storage.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/my_data_table.dart'; -import 'package:fcs/widget/number_cell.dart'; -import 'package:fcs/widget/progress.dart'; - -typedef OnSave = void Function(String storageID, String storageName); - -class DOStorageItem extends StatefulWidget { - final DOLine doLine; - final OnSave onSave; - const DOStorageItem({Key key, this.doLine, this.onSave}) : super(key: key); - @override - _DOStorageItemState createState() => _DOStorageItemState(); -} - -class _DOStorageItemState extends State { - final _formKey = GlobalKey(); - bool _isLoading = false; - String currentStorageID; - TextEditingController _product = new TextEditingController(); - TextEditingController _quantity = new TextEditingController(); - DOLine doLine = DOLine(); - - @override - void initState() { - super.initState(); - this.doLine = widget.doLine; - - if (doLine.storageID != null && doLine.storageID.isNotEmpty) { - this.currentStorageID = doLine.storageID; - } - _product.text = this.doLine.productName; - _quantity.text = this.doLine.qty.toString(); - } - - Widget showStorages(BuildContext context, StorageModel storageModel) { - return Container( - padding: EdgeInsets.only(top: 10), - child: Row( - mainAxisSize: MainAxisSize.max, - children: [ - Image.asset( - "assets/inventory.png", - width: 30, - height: 30, - color: primaryColor, - ), - SizedBox( - width: 20, - ), - new Flexible( - child: Container( - width: 170.0, - child: DropdownButton( - value: currentStorageID, - isExpanded: true, - hint: Text( - 'Select Storage', - style: labelStyle, - ), - onChanged: changedStorage, - items: storageModel - .getStorage(doLine.productID) - .map>((Storage storage) { - return new DropdownMenuItem( - value: storage.id, - child: new Text(storage.name, style: textStyle), - ); - }).toList(), - ), - ), - ), - ], - ), - ); - } - - void changedStorage(selected) { - setState(() { - currentStorageID = selected; - }); - } - - Widget showStorgeTable(BuildContext context, StorageModel storageModel) { - return Container( - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: MyDataTable( - headingRowHeight: 40, - columnSpacing: 100, - columns: [ - MyDataColumn( - label: LocalText(context, "storge"), - ), - MyDataColumn( - label: LocalText(context, "storage.product.qty"), - ), - ], - rows: getProductRow(storageModel.getStorage(doLine.productID)), - ), - ), - ); - } - - List getProductRow(List storages) { - return storages.map((s) { - return MyDataRow( - onSelectChanged: (bool selected) { - setState(() { - currentStorageID = s.id; - }); - }, - cells: [ - MyDataCell( - new Text(s.name, style: textStyle), - ), - MyDataCell( - NumberCell(s.products - .firstWhere((p) => p.id == doLine.productID) - .quantity), - ), - ], - ); - }).toList(); - } - - @override - Widget build(BuildContext context) { - var storgeModel = Provider.of(context); - - final productbox = Container( - padding: EdgeInsets.only(top: 10), - child: Row( - children: [ - LocalText(context, "do.product"), - SizedBox( - width: 20, - ), - Text(_product.text, style: textStyle) - ], - )); - - final quantitybox = Container( - padding: EdgeInsets.only(top: 15), - child: Row( - children: [ - LocalText(context, "do.quantity"), - SizedBox( - width: 20, - ), - Text(formatNumber(this.doLine.qty), style: textStyle) - ], - ), - ); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - title: Text("DO"), - actions: [ - IconButton( - icon: Icon(Icons.save), - onPressed: () { - _save(); - }, - ) - ], - ), - body: Form( - key: _formKey, - child: Column( - children: [ - Expanded( - child: ListView( - shrinkWrap: true, - padding: EdgeInsets.only(left: 24.0, right: 24.0, top: 10), - children: [ - productbox, - quantitybox, - showStorages(context, storgeModel), - showStorgeTable(context, storgeModel) - ], - ), - ), - ], - ), - )), - ); - } - - _save() { - this.doLine.storageID = currentStorageID; - var storageName = - Provider.of(context).getStorageName(currentStorageID); - this.doLine.storageName = storageName; - if (widget.onSave != null) - widget.onSave(this.doLine.storageID, storageName); - Navigator.pop(context, this.doLine); - } -} diff --git a/lib/pages/do/photo_page.dart b/lib/pages/do/photo_page.dart deleted file mode 100644 index 6c0e710..0000000 --- a/lib/pages/do/photo_page.dart +++ /dev/null @@ -1,165 +0,0 @@ -import 'dart:io'; -import 'package:flutter/material.dart'; -import 'package:image_picker/image_picker.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/language_model.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; - -import '../../fcs/common/pages/util.dart'; - -class PhotoPage extends StatefulWidget { - PhotoPage({Key key}) : super(key: key); - - @override - _PhotoPageState createState() => _PhotoPageState(); -} - -class _PhotoPageState extends State { - File receiptImageFile; - - @override - Widget build(BuildContext context) { - var languageModel = Provider.of(context); - - final receiptImageBox = Padding( - padding: EdgeInsets.symmetric(vertical: 5.0), - child: Container( - color: Colors.grey[400], - child: Column( - children: [ - Container( - padding: EdgeInsets.only(top: 15), - child: Text( - AppTranslations.of(context).text('do.receipt'), - style: - languageModel.isEng ? photoLabelStyle : photoLabelStyleMM, - ), - ), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - ButtonTheme.bar( - child: new ButtonBar( - alignment: MainAxisAlignment.start, - children: [ - new FlatButton( - child: Icon( - Icons.add_photo_alternate, - size: 60.0, - color: Colors.black, - ), - onPressed: () { - pickImageFromGallery(ImageSource.gallery); - }, - ), - ], - )), - ButtonTheme.bar( - child: new ButtonBar( - alignment: MainAxisAlignment.start, - children: [ - new FlatButton( - child: Icon( - Icons.add_a_photo, - size: 50.0, - color: Colors.black, - ), - onPressed: () { - pickImageFromCamera(ImageSource.camera); - }, - ), - ], - )), - ], - ), - receiptShowImage(), - SizedBox( - height: 10, - ) - ], - ), - ), - ); - - return Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - title: Text(AppTranslations.of(context).text("do.receipt.title"), - style: Provider.of(context).isEng - ? TextStyle(fontSize: 18) - : TextStyle(fontSize: 18, fontFamily: 'MyanmarUnicode')), - actions: [ - IconButton( - icon: Icon(Icons.send), - onPressed: () { - if (receiptImageFile == null) { - showMsgDialog( - context, "Error", "Please insert delivery receipt file"); - return; - } - Navigator.pop(context, receiptImageFile); - }, - ) - ], - ), - body: Column( - children: [ - Expanded( - child: ListView( - shrinkWrap: true, - padding: EdgeInsets.only(left: 24.0, right: 24.0, top: 20), - children: [ - receiptImageBox, - ], - ), - ), - SizedBox( - height: 20, - ) - ], - ), - ); - } - - Widget receiptShowImage() { - return Container( - child: receiptImageFile == null ? initialImage() : receiptEnableImage(), - ); - } - - Widget initialImage() { - var languageModel = Provider.of(context); - - return Center( - child: Text( - AppTranslations.of(context).text('do.no.photo'), - style: languageModel.isEng ? photoLabelStyle : photoLabelStyleMM, - ), - ); - } - - Widget receiptEnableImage() { - return Center( - child: Image.file( - receiptImageFile, - ), - ); - } - - pickImageFromGallery(ImageSource source) async { - var tempImage = await ImagePicker.pickImage( - source: source, imageQuality: 80, maxWidth: 300); - setState(() { - receiptImageFile = tempImage; - }); - } - - pickImageFromCamera(ImageSource source) async { - var tempImage = await ImagePicker.pickImage( - source: source, imageQuality: 80, maxWidth: 300); - setState(() { - receiptImageFile = tempImage; - }); - } -} diff --git a/lib/pages/do/po_selection.dart b/lib/pages/do/po_selection.dart deleted file mode 100644 index 80b8601..0000000 --- a/lib/pages/do/po_selection.dart +++ /dev/null @@ -1,158 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/po.dart'; -import 'package:fcs/widget/local_text.dart'; - -class POSelection extends StatefulWidget { - final List pos; - final List selectedPOs; - - POSelection({Key key, this.pos, this.selectedPOs}) : super(key: key); - - @override - _POSelectionState createState() => new _POSelectionState(); - - static Future showPOSelection(BuildContext context, - List pos, List selectedPOs, - {ok(List pos)}) async { - List _selectedPOs = []; - selectedPOs.forEach((i) => _selectedPOs.add(i)); - - final poselection = POSelection( - pos: pos, - selectedPOs: _selectedPOs, - ); - - await showDialog( - context: context, - builder: (_) { - return AlertDialog( - title: Center( - child: LocalText(context, "po.title"), - ), - content: Container( - width: double.maxFinite, - child: ListView( - shrinkWrap: true, - children: [ - poselection, - Container( - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - FlatButton( - child: LocalText(context, "Cancel"), - onPressed: () { - Navigator.of(context).pop(); - }), - FlatButton( - color: primaryColor, - child: LocalText(context, "Ok"), - onPressed: () async { - if (ok != null) ok(_selectedPOs); - Navigator.of(context).pop(); - }) - ], - ), - ), - ], - ), - ), - ); - }); - } -} - -class _POSelectionState extends State { - List pos; - - @override - void initState() { - super.initState(); - pos = widget.pos; - pos.sort((p1, p2) => p1.poNumber.compareTo(p2.poNumber)); - } - - @override - Widget build(BuildContext context) { - var width = MediaQuery.of(context).size.width * 0.8; - var height = MediaQuery.of(context).size.height * 0.5; - - return Column( - children: [ - FlatButton( - child: Text("Select All"), - onPressed: () { - setState(() { - widget.selectedPOs.clear(); - widget.selectedPOs.addAll(pos); - }); - }), - Container( - width: width, - height: height, - child: Column( - children: pos.asMap().entries.map((p) { - return InkWell( - onTap: () { - setState(() { - if (widget.selectedPOs.contains(p.value)) { - widget.selectedPOs.remove(p.value); - } else { - widget.selectedPOs.add(p.value); - } - }); - }, - child: Row( - children: [ - Checkbox( - onChanged: (v) => {_update(p.key)}, - value: widget.selectedPOs.contains(p.value), - ), - Text(p.value.poNumber), - ], - ), - ); - }).toList(), - ), - // child: ListView.builder( - // itemCount: pos.length, - // scrollDirection: Axis.vertical, - // itemBuilder: (BuildContext ctxt, int index) { - // return InkWell( - // onTap: () { - // setState(() { - // if (widget.selectedPOs.contains(pos[index])) { - // widget.selectedPOs.remove(pos[index]); - // } else { - // widget.selectedPOs.add(pos[index]); - // } - // }); - // }, - // child: Row( - // children: [ - // Checkbox( - // onChanged: (v) => {_update(index)}, - // value: widget.selectedPOs.contains(pos[index]), - // ), - // Text(pos[index].poNumber), - // ], - // ), - // ); - // }), - ), - ], - ); - } - - _update(int index) { - setState(() { - if (widget.selectedPOs.contains(pos[index])) { - widget.selectedPOs.remove(pos[index]); - } else { - widget.selectedPOs.add(pos[index]); - } - }); - } -} diff --git a/lib/pages/document_log_page.dart b/lib/pages/document_log_page.dart deleted file mode 100644 index 2518eb9..0000000 --- a/lib/pages/document_log_page.dart +++ /dev/null @@ -1,87 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/log_model.dart'; -import 'package:fcs/model/user_model.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/document_log.dart'; -import 'package:fcs/vo/role.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/my_data_table.dart'; - -class DocumentLogPage extends StatefulWidget { - final String docID; - - const DocumentLogPage({Key key, this.docID}) : super(key: key); - @override - _DocumentLogPageState createState() => _DocumentLogPageState(); -} - -class _DocumentLogPageState extends State { - var dateFormatter = new DateFormat('dd MMM yyyy\nhh:mm:ss a'); - - @override - void initState() { - super.initState(); - if (widget.docID != null) { - Provider.of(context, listen: false).loadDocLogs(widget.docID); - } - } - - @override - void dispose() { - super.dispose(); - } - - @override - Widget build(BuildContext context) { - var logModel = Provider.of(context); - var userModel = Provider.of(context); - return Scaffold( - appBar: AppBar( - title: LocalText(context, 'document.log.title', - fontSize: 20, color: Colors.white), - backgroundColor: primaryColor, - ), - body: Container( - padding: EdgeInsets.only(top: 10), - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: MyDataTable( - headingRowHeight: 40, - columnSpacing: 40, - columns: [ - MyDataColumn(label: LocalText(context, "document.date")), - MyDataColumn(label: LocalText(context, "document.by")), - MyDataColumn(label: LocalText(context, "document.desc")), - ], - rows: getProductRow(logModel.docLogs, userModel.privileges), - ), - ), - ), - ); - } - - List getProductRow( - List docLogs, List privileges) { - return docLogs.map((d) { - return MyDataRow( - cells: [ - MyDataCell( - new Text(dateFormatter.format(d.date), style: textStyle), - ), - MyDataCell( - new Text( - d.actionerName == null ? '' : d.actionerName, - style: textStyle, - ), - ), - MyDataCell( - new Text(d.getDesc(privileges) == null ? '' : d.getDesc(privileges), - style: textStyle), - ), - ], - ); - }).toList(); - } -} diff --git a/lib/pages/email_page.dart b/lib/pages/email_page.dart deleted file mode 100644 index 7165247..0000000 --- a/lib/pages/email_page.dart +++ /dev/null @@ -1,159 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/language_model.dart'; -import 'package:fcs/model/main_model.dart'; -import 'package:fcs/model/shared_pref.dart'; -import 'package:fcs/model/user_model.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/user.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:fcs/widget/progress.dart'; - -import 'confirm_email.dart'; -import '../fcs/common/pages/util.dart'; - -class EmailPage extends StatefulWidget { - final User user; - EmailPage({this.user}); - @override - _EmailPageState createState() => _EmailPageState(); -} - -class _EmailPageState extends State { - final TextEditingController _email = new TextEditingController(); - bool _isLoading = false; - final _formKey = GlobalKey(); - - @override - void initState() { - super.initState(); - if (widget.user != null) { - _email.text = widget.user.email; - } - } - - @override - void dispose() { - super.dispose(); - } - - @override - Widget build(BuildContext context) { - MainModel mainModel = Provider.of(context); - var languageModel = Provider.of(context); - final emailInput = TextFormField( - controller: _email, - autofocus: false, - decoration: new InputDecoration( - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide(color: Colors.grey, width: 1.0)), - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide(color: Colors.grey, width: 1.0)), - labelText: AppTranslations.of(context).text("login.email"), - labelStyle: labelStyle, - icon: Icon( - Icons.email, - color: primaryColor, - )), - validator: (value) { - if (value.isEmpty) { - return AppTranslations.of(context).text("login.email.empty"); - } - return null; - }, - ); - - final enterButton = Padding( - padding: EdgeInsets.symmetric(vertical: 16.0), - child: RaisedButton( - onPressed: () => _add(mainModel), - padding: EdgeInsets.all(10), - color: primaryColor, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(7), - ), - child: Text(AppTranslations.of(context).text("login.email.add"), - style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold)), - ), - ); - - final skipButton = Container( - child: InkWell( - onTap: () { - SharedPref.saveSkippedRecoverEmail(true); - Navigator.pushNamedAndRemoveUntil( - context, "/welcome", (r) => false); - }, - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Text( - AppTranslations.of(context).text("login.email.skip"), - style: languageModel.isEng - ? TextStyle(fontSize: 18, fontFamily: 'WorkSansMedium') - : TextStyle(fontSize: 18, fontFamily: 'MyanmarUnicode'), - ), - Container( - padding: EdgeInsets.only(top: 4), - child: Icon( - Icons.skip_next, - size: 30, - )), - ], - )), - ); - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - title: LocalText( - context, - 'login.email.title', - fontSize: 20, - color: Colors.white, - ), - backgroundColor: primaryColor, - ), - body: Center( - child: ListView( - shrinkWrap: true, - padding: EdgeInsets.only(left: 24.0, right: 24.0), - children: [ - Form(key: _formKey, child: emailInput), - SizedBox(height: 8.0), - enterButton, - widget.user != null ? Container() : skipButton - ], - ), - ), - ), - ); - } - - Future _add(MainModel mainModel) async { - if (!_formKey.currentState.validate()) { - return; - } - setState(() { - _isLoading = true; - }); - try { - UserModel userModel = Provider.of(context); - await userModel.addEmail(mainModel.user.phoneNumber, _email.text); - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => ConfirmEmail( - id: mainModel.user.phoneNumber, - email: _email.text, - ))); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - setState(() { - _isLoading = false; - }); - } - } -} diff --git a/lib/fcs/common/pages/faq/faq_detail_page.dart b/lib/pages/faq/faq_detail_page.dart similarity index 87% rename from lib/fcs/common/pages/faq/faq_detail_page.dart rename to lib/pages/faq/faq_detail_page.dart index 753fc8e..8a4124f 100644 --- a/lib/fcs/common/pages/faq/faq_detail_page.dart +++ b/lib/pages/faq/faq_detail_page.dart @@ -1,12 +1,12 @@ -import 'package:fcs/fcs/common/domain/entities/faq.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/fcs/common/pages/faq/faq_edit_page.dart'; -import 'package:fcs/fcs/common/pages/faq/model/faq_model.dart'; -import 'package:fcs/fcs/common/pages/model/language_model.dart'; -import 'package:fcs/fcs/common/pages/model/main_model.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/fcs/common/pages/widgets/local_text.dart'; -import 'package:fcs/fcs/common/pages/widgets/progress.dart'; +import 'package:fcs/domain/entities/faq.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/faq/faq_edit_page.dart'; +import 'package:fcs/pages/faq/model/faq_model.dart'; +import 'package:fcs/pages/main/model/language_model.dart'; +import 'package:fcs/pages/main/model/main_model.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/progress.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; diff --git a/lib/fcs/common/pages/faq/faq_edit_page.dart b/lib/pages/faq/faq_edit_page.dart similarity index 76% rename from lib/fcs/common/pages/faq/faq_edit_page.dart rename to lib/pages/faq/faq_edit_page.dart index 738e28a..69eb9be 100644 --- a/lib/fcs/common/pages/faq/faq_edit_page.dart +++ b/lib/pages/faq/faq_edit_page.dart @@ -1,13 +1,13 @@ -import 'package:fcs/fcs/common/domain/constants.dart'; -import 'package:fcs/fcs/common/domain/entities/faq.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/fcs/common/localization/app_translations.dart'; -import 'package:fcs/fcs/common/pages/faq/model/faq_model.dart'; -import 'package:fcs/fcs/common/pages/faq/widgets.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/fcs/common/pages/widgets/input_text.dart'; -import 'package:fcs/fcs/common/pages/widgets/local_text.dart'; -import 'package:fcs/fcs/common/pages/widgets/progress.dart'; +import 'package:fcs/domain/constants.dart'; +import 'package:fcs/domain/entities/faq.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/localization/app_translations.dart'; +import 'package:fcs/pages/faq/model/faq_model.dart'; +import 'package:fcs/pages/faq/widgets.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/widgets/input_text.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/progress.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_icons/flutter_icons.dart'; @@ -94,8 +94,12 @@ class _FAQEditorState extends State { _pageLink = newValue; }); }, - items: [info, page_buying_instructions, page_payment_methods] - .map>((String value) { + items: [ + info, + page_buying_instructions, + page_payment_methods, + page_rates + ].map>((String value) { return DropdownMenuItem( value: value, child: Text( @@ -118,43 +122,32 @@ class _FAQEditorState extends State { return LocalProgress( inAsyncCall: _isLoading, child: Scaffold( - body: CustomScrollView(slivers: [ - SliverAppBar( - leading: IconButton( - icon: Icon( - CupertinoIcons.back, - size: 30, + appBar: AppBar( + centerTitle: true, + leading: new IconButton( + icon: new Icon(CupertinoIcons.back, color: primaryColor), + onPressed: () => Navigator.of(context).pop(), ), - onPressed: () => Navigator.of(context).pop(), + backgroundColor: Colors.white, + shadowColor: Colors.transparent, + title: LocalText( + context, _isNew ? 'faq.add.title' : 'faq.edit.title', + color: primaryColor, fontSize: 20), + actions: [ + IconButton( + icon: Icon( + Icons.delete, + color: primaryColor, + ), + onPressed: _delete, + ) + ], ), - backgroundColor: primaryColor, - expandedHeight: 150.0, - floating: true, - pinned: true, - flexibleSpace: FlexibleSpaceBar( - centerTitle: true, - titlePadding: EdgeInsets.symmetric(vertical: 10), - title: LocalText( - context, - _isNew ? 'faq.add.title' : 'faq.edit.title', - fontSize: 20, - color: Colors.white, - )), - actions: [ - IconButton( - icon: Icon(Icons.delete), - onPressed: _delete, - ) - ], - ), - SliverList( - delegate: SliverChildListDelegate([ - Form( + body: Form( key: _formKey, child: Padding( padding: EdgeInsets.only(left: 24.0, right: 24.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + child: ListView( children: [ snBox, Center(child: itemTitle(context, "faq.edit.eng")), @@ -185,9 +178,7 @@ class _FAQEditorState extends State { ], ), ), - ), - ])) - ]))); + ))); } _save() async { diff --git a/lib/fcs/common/pages/faq/faq_list_page.dart b/lib/pages/faq/faq_list_page.dart similarity index 55% rename from lib/fcs/common/pages/faq/faq_list_page.dart rename to lib/pages/faq/faq_list_page.dart index 1b9e4f3..2c5ae2d 100644 --- a/lib/fcs/common/pages/faq/faq_list_page.dart +++ b/lib/pages/faq/faq_list_page.dart @@ -1,15 +1,16 @@ -import 'package:fcs/fcs/common/domain/constants.dart'; -import 'package:fcs/fcs/common/domain/entities/faq.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/fcs/common/localization/app_translations.dart'; -import 'package:fcs/fcs/common/pages/buying_instruction/buying_online.dart'; -import 'package:fcs/fcs/common/pages/faq/faq_edit_page.dart'; -import 'package:fcs/fcs/common/pages/model/language_model.dart'; -import 'package:fcs/fcs/common/pages/model/main_model.dart'; -import 'package:fcs/fcs/common/pages/payment_methods/payment_method_page.dart'; -import 'package:fcs/fcs/common/pages/widgets/bottom_up_page_route.dart'; -import 'package:fcs/fcs/common/pages/widgets/fcs_expansion_tile.dart'; -import 'package:fcs/fcs/common/pages/widgets/local_text.dart'; +import 'package:fcs/domain/constants.dart'; +import 'package:fcs/domain/entities/faq.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/localization/app_translations.dart'; +import 'package:fcs/pages/buying_instruction/buying_online.dart'; +import 'package:fcs/pages/faq/faq_edit_page.dart'; +import 'package:fcs/pages/main/model/language_model.dart'; +import 'package:fcs/pages/main/model/main_model.dart'; +import 'package:fcs/pages/payment_methods/payment_method_page.dart'; +import 'package:fcs/pages/rates/shipment_rates.dart'; +import 'package:fcs/pages/widgets/bottom_up_page_route.dart'; +import 'package:fcs/pages/widgets/fcs_expansion_tile.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; @@ -43,64 +44,48 @@ class _FAQListPageState extends State bool isEditable = context.select((MainModel m) => m.faqEditable()); return Scaffold( + appBar: AppBar( + centerTitle: true, + title: LocalText( + context, + "faq.title", + color: Colors.white, + fontSize: 20, + ), + leading: new IconButton( + icon: new Icon(CupertinoIcons.back), + onPressed: () => Navigator.of(context).pop(), + ), + backgroundColor: primaryColor, + actions: isEditable + ? [ + IconButton( + onPressed: () => setState(() { + isEditMode = !isEditMode; + }), + icon: Icon( + Icons.edit, + color: Colors.white, + )) + ] + : [], + ), floatingActionButton: isEditable ? FloatingActionButton.extended( onPressed: () { - Navigator.of(context).push(BottomUpPageRoute(FAQEditor())); + Navigator.of(context).push( + CupertinoPageRoute(builder: (context) => FAQEditor())); }, icon: Icon(Icons.add), label: LocalText(context, "faq.add.title", color: Colors.white), backgroundColor: primaryColor, ) : Container(), - body: CustomScrollView( - slivers: [ - SliverAppBar( - leading: IconButton( - icon: Icon( - CupertinoIcons.back, - size: 30, - ), - onPressed: () => Navigator.of(context).pop(), - ), - backgroundColor: primaryColor, - expandedHeight: 150.0, - floating: false, - pinned: true, - flexibleSpace: FlexibleSpaceBar( - centerTitle: true, - titlePadding: - EdgeInsets.symmetric(vertical: 10, horizontal: 45), - title: LocalText( - context, - "faq.title", - fontSize: 20, - color: Colors.white, - ), - ), - actions: isEditable - ? [ - IconButton( - onPressed: () => setState(() { - isEditMode = !isEditMode; - }), - icon: Icon( - Icons.edit, - color: Colors.white, - )) - ] - : [], - ), - SliverList( - delegate: SliverChildBuilderDelegate( - (context, index) { - return _faqItem(context, faqModel.faqs[index]); - }, - childCount: faqModel.faqs.length, - ), - ) - ], - )); + body: ListView.builder( + itemCount: faqModel.faqs.length, + itemBuilder: (BuildContext context, int index) { + return _faqItem(context, faqModel.faqs[index]); + })); } bool isEditMode = false; @@ -144,7 +129,7 @@ class _FAQListPageState extends State context, faq.answer(isEng), fontSize: 16, - fontWeight: FontWeight.w200, + fontWeight: FontWeight.w400, ), _pageLink( faq.pageLink, @@ -171,9 +156,14 @@ class _FAQListPageState extends State _selectLinkPage(String linkPage) { if (linkPage == page_payment_methods) { - Navigator.of(context).push(BottomUpPageRoute(PaymentMethodPage())); + Navigator.of(context) + .push(CupertinoPageRoute(builder: (context) => PaymentMethodPage())); } else if (linkPage == page_buying_instructions) { - Navigator.of(context).push(BottomUpPageRoute(BuyingOnlinePage())); + Navigator.of(context) + .push(CupertinoPageRoute(builder: (context) => BuyingOnlinePage())); + } else if (linkPage == page_rates) { + Navigator.of(context) + .push(CupertinoPageRoute(builder: (context) => ShipmentRates())); } } } diff --git a/lib/fcs/common/pages/faq/model/faq_model.dart b/lib/pages/faq/model/faq_model.dart similarity index 68% rename from lib/fcs/common/pages/faq/model/faq_model.dart rename to lib/pages/faq/model/faq_model.dart index d2c811e..ece61b7 100644 --- a/lib/fcs/common/pages/faq/model/faq_model.dart +++ b/lib/pages/faq/model/faq_model.dart @@ -1,9 +1,9 @@ import 'dart:async'; import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:fcs/fcs/common/domain/entities/faq.dart'; -import 'package:fcs/fcs/common/pages/model/base_model.dart'; -import 'package:fcs/fcs/common/services/services.dart'; +import 'package:fcs/domain/entities/faq.dart'; +import 'package:fcs/helpers/firebase_helper.dart'; +import 'package:fcs/pages/main/model/base_model.dart'; import 'package:logging/logging.dart'; class FAQModel extends BaseModel { @@ -29,7 +29,6 @@ class FAQModel extends BaseModel { snaps.documents.forEach((d) { faqs.add(FAQ.fromMap(d.data, d.documentID)); }); - print("in listener"); notifyListeners(); }); } catch (e) { @@ -39,19 +38,16 @@ class FAQModel extends BaseModel { Future addFAQ(FAQ faq) async { await request("/faqs", "POST", - payload: faq.toMap(), - token: await Services.instance.authService.getToken()); + payload: faq.toMap(), token: await getToken()); } Future updateFAQ(FAQ faq) async { await request("/faqs", "PUT", - payload: faq.toMap(), - token: await Services.instance.authService.getToken()); + payload: faq.toMap(), token: await getToken()); } Future deleteFAQ(FAQ faq) async { await request("/faqs", "DELETE", - payload: faq.toMap(), - token: await Services.instance.authService.getToken()); + payload: faq.toMap(), token: await getToken()); } } diff --git a/lib/pages/faq/widgets.dart b/lib/pages/faq/widgets.dart new file mode 100644 index 0000000..ba1c60a --- /dev/null +++ b/lib/pages/faq/widgets.dart @@ -0,0 +1,103 @@ +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/localization/app_translations.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:flutter/material.dart'; + +Widget itemTitle(BuildContext context, String textKey) { + return Padding( + padding: const EdgeInsets.only(left: 18.0, top: 15, bottom: 0), + child: Text( + AppTranslations.of(context).text(textKey), + style: TextStyle( + fontWeight: FontWeight.bold, fontSize: 18, color: Colors.black), + ), + ); +} + +Widget subItemTitle(BuildContext context, String textKey, {IconData iconData}) { + return Padding( + padding: const EdgeInsets.only(left: 0, top: 0, bottom: 0), + child: Row( + children: [ + Icon( + iconData, + color: primaryColor, + ), + SizedBox(width: 10), + Text( + AppTranslations.of(context).text(textKey), + style: TextStyle( + fontWeight: FontWeight.w700, fontSize: 15, color: primaryColor), + ), + ], + ), + ); +} + +Widget contactItem(BuildContext context, String text, IconData iconData, + {Function() onTap, String labelKey}) { + return Material( + child: Padding( + padding: const EdgeInsets.only(left: 18.0, bottom: 10, right: 18), + child: Container( + decoration: BoxDecoration( + border: Border.all(color: Colors.grey, width: 0.8), + borderRadius: BorderRadius.all( + Radius.circular(5.0) // <--- border radius here + ), + ), + child: InkWell( + onTap: () => onTap != null ? onTap() : null, + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Row( + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Icon( + iconData, + color: primaryColor, + ), + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + labelKey == null + ? Container() + : Padding( + padding: EdgeInsets.fromLTRB(10, 10, 10, 0), + child: LocalText(context, labelKey, + color: primaryColor, + fontWeight: FontWeight.w500, + fontSize: 18), + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + text == null ? "" : text, + overflow: TextOverflow.ellipsis, + maxLines: 5, + style: TextStyle( + fontSize: 14.0, + ), + ), + ), + ], + ), + SizedBox( + width: 5, + ), + onTap == null + ? Container() + : Icon( + Icons.open_in_new, + color: Colors.grey, + size: 15, + ) + ], + ), + )), + ), + ), + ); +} diff --git a/lib/pages/fcs_profile_page.dart b/lib/pages/fcs_profile_page.dart deleted file mode 100644 index 807b106..0000000 --- a/lib/pages/fcs_profile_page.dart +++ /dev/null @@ -1,168 +0,0 @@ -import 'package:fcs/model/pickup_model.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/vo/pickup.dart'; -import 'package:fcs/widget/fcs_text_field.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -import 'package:provider/provider.dart'; - -import 'package:flutter/material.dart'; -import 'package:fcs/widget/progress.dart'; - -import '../fcs/common/helpers/theme.dart'; - -class FCSProfilePage extends StatefulWidget { - final PickUp pickUp; - FCSProfilePage({this.pickUp}); - - @override - _FCSProfilePageState createState() => _FCSProfilePageState(); -} - -class _FCSProfilePageState extends State { - TextEditingController _usaAddressEditingController = - new TextEditingController(); - TextEditingController _mmAddressEditingController = - new TextEditingController(); - TextEditingController _contactEditingController = new TextEditingController(); - TextEditingController _mmContactEditingController = - new TextEditingController(); - TextEditingController _mailEditingController = new TextEditingController(); - TextEditingController _fbLinkEditingController = new TextEditingController(); - - PickUp _pickUp; - bool _isLoading = false; - - @override - void initState() { - super.initState(); - var pickupModel = Provider.of(context, listen: false); - _usaAddressEditingController.text = pickupModel.profile.usaAddress; - _mmAddressEditingController.text = pickupModel.profile.mmAddress; - _contactEditingController.text = pickupModel.profile.usaContactNumber; - _mmContactEditingController.text = pickupModel.profile.mmContactNumber; - _mailEditingController.text = pickupModel.profile.mail; - _fbLinkEditingController.text = pickupModel.profile.facebook; - } - - @override - void dispose() { - super.dispose(); - } - - @override - Widget build(BuildContext context) { - final usaAddress = fcsInput('USA Delivery Address', Icons.location_on, - controller: _usaAddressEditingController); - final mmAddress = fcsInput('Yangon, Myanmar Office', Icons.location_on, - controller: _mmAddressEditingController); - - final contactNumber = fcsInput('USA contact number', Icons.phone, - controller: _contactEditingController); - final mmContactNumber = fcsInput('Myanmar contact number', Icons.phone, - controller: _mmContactEditingController); - - final mailBox = fcsInput('Email Address', Icons.mail, - controller: _mailEditingController); - final fbLinkBox = fcsInput('Facebook Link', FontAwesomeIcons.facebook, - controller: _fbLinkEditingController); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - centerTitle: true, - leading: new IconButton( - icon: new Icon(Icons.close), - onPressed: () => Navigator.of(context).pop(), - ), - backgroundColor: primaryColor, - title: LocalText( - context, - 'fcs.profile', - color: Colors.white, - fontSize: 20, - ), - ), - body: Card( - child: Column( - children: [ - Expanded( - child: Padding( - padding: const EdgeInsets.only(left: 20.0), - child: ListView(children: [ - usaAddress, - SizedBox(height: 10), - mmAddress, - SizedBox(height: 10), - contactNumber, - SizedBox(height: 10), - mmContactNumber, - SizedBox(height: 10), - mailBox, - SizedBox(height: 10), - fbLinkBox, - SizedBox(height: 10), - ]), - )), - widget.pickUp == null - ? Align( - alignment: Alignment.bottomCenter, - child: Center( - child: Container( - width: 250, - child: FlatButton( - child: Text('Update'), - color: primaryColor, - textColor: Colors.white, - onPressed: () { - Navigator.pop(context); - }, - ), - ))) - : Container( - child: Column( - children: [ - Align( - alignment: Alignment.bottomCenter, - child: Center( - child: Container( - width: 250, - child: FlatButton( - shape: new RoundedRectangleBorder( - borderRadius: - new BorderRadius.circular(10)), - child: Text('Pickuped'), - color: primaryColor, - textColor: Colors.white, - onPressed: () { - Navigator.pop(context); - }, - ), - ))), - Align( - alignment: Alignment.bottomCenter, - child: Center( - child: Container( - width: 250, - child: FlatButton( - shape: new RoundedRectangleBorder( - borderRadius: - new BorderRadius.circular(10)), - child: Text('Cancel'), - color: primaryColor, - textColor: Colors.white, - onPressed: () { - Navigator.pop(context); - }, - ), - ))) - ], - )) - ], - ), - ), - ), - ); - } -} diff --git a/lib/pages/fcs_shipment/fcs_shipment_editor.dart b/lib/pages/fcs_shipment/fcs_shipment_editor.dart new file mode 100644 index 0000000..11bffd3 --- /dev/null +++ b/lib/pages/fcs_shipment/fcs_shipment_editor.dart @@ -0,0 +1,267 @@ +import 'package:fcs/domain/entities/fcs_shipment.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/localization/app_translations.dart'; +import 'package:fcs/pages/fcs_shipment/model/fcs_shipment_model.dart'; +import 'package:fcs/pages/main/model/language_model.dart'; +import 'package:fcs/pages/main/model/main_model.dart'; +import 'package:fcs/pages/widgets/display_text.dart'; +import 'package:fcs/pages/widgets/input_date.dart'; +import 'package:fcs/pages/widgets/input_text.dart'; +import 'package:fcs/pages/widgets/local_button.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_icons/flutter_icons.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:intl/intl.dart'; +import 'package:provider/provider.dart'; + +import '../main/util.dart'; + +class FcsShipmentEditor extends StatefulWidget { + final FcsShipment shipment; + FcsShipmentEditor({this.shipment}); + + @override + _FcsShipmentEditorState createState() => _FcsShipmentEditorState(); +} + +class _FcsShipmentEditorState extends State { + var dateFormatter = new DateFormat('dd MMM yyyy'); + TextEditingController _shipmentNumberController = new TextEditingController(); + TextEditingController _cutoffDateController = new TextEditingController(); + TextEditingController _arrivalDateController = new TextEditingController(); + TextEditingController _departureDateControler = new TextEditingController(); + TextEditingController _consigneeController = new TextEditingController(); + TextEditingController _portController = new TextEditingController(); + TextEditingController _destinationController = new TextEditingController(); + TextEditingController _statusController = new TextEditingController(); + + FcsShipment _shipment = new FcsShipment(); + bool _isLoading = false; + String _currentShipmentType; + bool _isNew = false; + + @override + void initState() { + super.initState(); + _isNew = widget.shipment == null; + if (widget.shipment != null) { + _shipment = widget.shipment; + _shipmentNumberController.text = _shipment.shipmentNumber; + _cutoffDateController.text = dateFormatter.format(_shipment.cutoffDate); + _arrivalDateController.text = dateFormatter.format(_shipment.arrivalDate); + _departureDateControler.text = + dateFormatter.format(_shipment.departureDate); + _statusController.text = _shipment.status; + _currentShipmentType = _shipment.shipType; + _consigneeController.text = _shipment.consignee; + _portController.text = _shipment.port; + _destinationController.text = _shipment.destination; + } + } + + @override + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + var languageModel = Provider.of(context); + var mainModel = Provider.of(context); + + final createBtn = LocalButton( + textKey: "FCSshipment.create", + callBack: _create, + ); + + final updateBtn = LocalButton( + textKey: "FCSshipment.update", + callBack: _update, + ); + + return LocalProgress( + inAsyncCall: _isLoading, + child: Scaffold( + appBar: AppBar( + centerTitle: true, + shadowColor: Colors.transparent, + leading: new IconButton( + icon: new Icon(CupertinoIcons.back, color: primaryColor), + onPressed: () => Navigator.of(context).pop(), + ), + backgroundColor: Colors.white, + title: LocalText( + context, + "FCSshipment.form.title", + color: primaryColor, + fontSize: 18, + ), + ), + body: Padding( + padding: const EdgeInsets.all(10.0), + child: ListView(children: [ + InputText( + labelTextKey: "FCSshipment.number", + iconData: Ionicons.ios_airplane, + controller: _shipmentNumberController, + ), + InputDate( + labelTextKey: "FCSshipment.cutoff_date", + iconData: Icons.date_range, + controller: _cutoffDateController, + ), + InputDate( + labelTextKey: "FCSshipment.departure_date", + iconData: Icons.date_range, + controller: _departureDateControler, + ), + InputDate( + labelTextKey: "FCSshipment.ETA", + iconData: Icons.date_range, + controller: _arrivalDateController, + ), + DropdownButtonFormField( + value: _currentShipmentType == "" ? null : _currentShipmentType, + decoration: InputDecoration( + enabledBorder: UnderlineInputBorder( + borderSide: BorderSide(color: primaryColor)), + fillColor: Colors.white, + labelStyle: languageModel.isEng + ? newLabelStyle(color: Colors.black54, fontSize: 20) + : newLabelStyleMM(color: Colors.black54, fontSize: 20), + labelText: AppTranslations.of(context) + .text('FCSshipment.shipment_type'), + icon: Icon(Ionicons.ios_airplane, color: primaryColor)), + items: mainModel.setting.shipmentTypes + .map((e) => DropdownMenuItem(child: Text(e), value: e)) + .toList(), + onChanged: (selected) => { + setState(() { + _currentShipmentType = selected; + }) + }, + ), + InputText( + labelTextKey: 'FCSshipment.consignee', + iconData: Icons.work, + controller: _consigneeController), + InputText( + labelTextKey: 'FCSshipment.port_of_loading', + iconData: FontAwesomeIcons.ship, + controller: _portController), + InputText( + labelTextKey: 'FCSshipment.final_destination', + iconData: MaterialCommunityIcons.location_enter, + controller: _destinationController), + _isNew + ? Container() + : Container( + padding: EdgeInsets.only(top: 5), + child: DisplayText( + text: _statusController.text, + iconData: Icons.av_timer, + labelTextKey: 'FCSshipment.status', + )), + _isNew ? createBtn : updateBtn, + SizedBox(height: 15) + ]), + ), + ), + ); + } + + FcsShipment _getPayload() { + FcsShipment fcsShipment = FcsShipment(); + fcsShipment.id = _shipment.id; + fcsShipment.shipmentNumber = _shipmentNumberController.text; + fcsShipment.shipType = _currentShipmentType; + fcsShipment.consignee = _consigneeController.text; + fcsShipment.port = _portController.text; + fcsShipment.destination = _destinationController.text; + try { + var cutoffDate = _cutoffDateController.text; + var arrivalDate = _arrivalDateController.text; + var depDate = _departureDateControler.text; + fcsShipment.cutoffDate = + cutoffDate == "" ? null : dateFormatter.parse(cutoffDate); + fcsShipment.arrivalDate = + arrivalDate == "" ? null : dateFormatter.parse(arrivalDate); + fcsShipment.departureDate = + depDate == "" ? null : dateFormatter.parse(depDate); + } catch (e) { + showMsgDialog(context, "Error", e.toString()); // shold never happen + } + return fcsShipment; + } + + Future _validate(FcsShipment fcsShipment) async { + if (fcsShipment.shipmentNumber == "") { + await showMsgDialog(context, "Error", "Invalid shipment number!"); + return false; + } + if (fcsShipment.shipType == null) { + await showMsgDialog(context, "Error", "Invalid shipment type!"); + return false; + } + if (fcsShipment.cutoffDate == null) { + await showMsgDialog(context, "Error", "Invalid cutoff date!"); + return false; + } + if (fcsShipment.arrivalDate == null) { + await showMsgDialog(context, "Error", "Invalid ETA date!"); + return false; + } + if (fcsShipment.departureDate == null) { + await showMsgDialog(context, "Error", "Invalid departure date!"); + return false; + } + return true; + } + + Future _create() async { + FcsShipment fcsShipment = _getPayload(); + bool valid = await _validate(fcsShipment); + if (!valid) { + return; + } + setState(() { + _isLoading = true; + }); + var shipmentModel = Provider.of(context, listen: false); + try { + await shipmentModel.create(fcsShipment); + Navigator.pop(context); + } catch (e) { + showMsgDialog(context, "Error", e.toString()); + } finally { + setState(() { + _isLoading = false; + }); + } + } + + Future _update() async { + FcsShipment fcsShipment = _getPayload(); + bool valid = await _validate(fcsShipment); + if (!valid) { + return; + } + setState(() { + _isLoading = true; + }); + var shipmentModel = Provider.of(context, listen: false); + try { + await shipmentModel.update(fcsShipment); + Navigator.pop(context, true); + } catch (e) { + showMsgDialog(context, "Error", e.toString()); + } finally { + setState(() { + _isLoading = false; + }); + } + } +} diff --git a/lib/pages/fcs_shipment/fcs_shipment_info.dart b/lib/pages/fcs_shipment/fcs_shipment_info.dart new file mode 100644 index 0000000..81c2fa8 --- /dev/null +++ b/lib/pages/fcs_shipment/fcs_shipment_info.dart @@ -0,0 +1,255 @@ +import 'package:fcs/domain/constants.dart'; +import 'package:fcs/domain/entities/fcs_shipment.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/fcs_shipment/model/fcs_shipment_model.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/widgets/display_text.dart'; +import 'package:fcs/pages/widgets/local_button.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/popupmenu.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_icons/flutter_icons.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:intl/intl.dart'; +import 'package:provider/provider.dart'; + +import 'fcs_shipment_editor.dart'; + +class FcsShipmentInfo extends StatefulWidget { + final FcsShipment fcsShipment; + FcsShipmentInfo({this.fcsShipment}); + + @override + _FcsShipmentInfoState createState() => _FcsShipmentInfoState(); +} + +class _FcsShipmentInfoState extends State { + var dateFormatter = new DateFormat('dd MMM yyyy'); + FcsShipment _fcsShipment; + bool _isLoading = false; + TextEditingController _shipmentNumberController = new TextEditingController(); + TextEditingController _cutoffDateController = new TextEditingController(); + TextEditingController _arrivalDateController = new TextEditingController(); + TextEditingController _departureDateControler = new TextEditingController(); + TextEditingController _shipmentTypeControler = new TextEditingController(); + TextEditingController _consigneeController = new TextEditingController(); + TextEditingController _portController = new TextEditingController(); + TextEditingController _destinationController = new TextEditingController(); + TextEditingController _statusController = new TextEditingController(); + + @override + void initState() { + super.initState(); + _fcsShipment = widget.fcsShipment; + _load(); + } + + _load() { + _shipmentNumberController.text = _fcsShipment.shipmentNumber; + _cutoffDateController.text = dateFormatter.format(_fcsShipment.cutoffDate); + _arrivalDateController.text = + dateFormatter.format(_fcsShipment.arrivalDate); + _departureDateControler.text = + dateFormatter.format(_fcsShipment.departureDate); + _shipmentTypeControler.text = _fcsShipment.shipType; + _consigneeController.text = _fcsShipment.consignee; + _portController.text = _fcsShipment.port; + _destinationController.text = _fcsShipment.destination; + _statusController.text = _fcsShipment.status; + } + + @override + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final shipmentNumberBox = DisplayText( + text: _shipmentNumberController.text, + labelTextKey: "FCSshipment.number", + iconData: Ionicons.ios_airplane, + ); + final cutoffDateDBox = DisplayText( + text: _cutoffDateController.text, + labelTextKey: "FCSshipment.cutoff_date", + iconData: Icons.date_range, + ); + final etaBox = DisplayText( + text: _arrivalDateController.text, + labelTextKey: "FCSshipment.ETA", + iconData: Icons.date_range, + ); + + final departureDateBox = DisplayText( + text: _departureDateControler.text, + labelTextKey: "FCSshipment.departure_date", + iconData: Icons.date_range, + ); + + final shipTypeBox = DisplayText( + text: _shipmentTypeControler.text, + labelTextKey: "FCSshipment.shipment_type", + iconData: Ionicons.ios_airplane, + ); + + final consigneeBox = DisplayText( + text: _consigneeController.text, + labelTextKey: "FCSshipment.consignee", + iconData: Icons.work, + ); + + final portBox = DisplayText( + text: _portController.text, + labelTextKey: "FCSshipment.port_of_loading", + iconData: FontAwesomeIcons.ship, + ); + + final destinationBox = DisplayText( + text: _destinationController.text, + labelTextKey: "FCSshipment.final_destination", + iconData: MaterialCommunityIcons.location_enter, + ); + + final statusBox = DisplayText( + text: _statusController.text, + labelTextKey: "FCSshipment.status", + iconData: Icons.av_timer, + ); + + final shipBtn = LocalButton( + textKey: "FCSshipment.ship.btn", + callBack: _ship, + ); + + return LocalProgress( + inAsyncCall: _isLoading, + child: Scaffold( + appBar: AppBar( + centerTitle: true, + leading: new IconButton( + icon: new Icon(CupertinoIcons.back, color: primaryColor, size: 30), + onPressed: () => Navigator.of(context).pop(), + ), + shadowColor: Colors.transparent, + backgroundColor: Colors.white, + title: LocalText( + context, + "FCSshipment.form.title", + fontSize: 20, + color: primaryColor, + ), + actions: [ + IconButton( + icon: Icon(Icons.edit, color: primaryColor), + onPressed: _edit, + ), + menuPopWidget(context) + ], + ), + body: Card( + child: Column( + children: [ + Expanded( + child: Padding( + padding: const EdgeInsets.all(10.0), + child: ListView(children: [ + shipmentNumberBox, + cutoffDateDBox, + departureDateBox, + etaBox, + shipTypeBox, + consigneeBox, + portBox, + destinationBox, + statusBox, + _fcsShipment.status == fcs_shipment_confirmed_status + ? shipBtn + : Container(), + SizedBox( + height: 20, + ) + ]), + )), + ], + ), + ), + ), + ); + } + + _edit() async { + bool updated = await Navigator.push( + context, + CupertinoPageRoute( + builder: (context) => FcsShipmentEditor(shipment: _fcsShipment)), + ); + if (updated ?? false) { + var shipmentModel = Provider.of(context, listen: false); + var f = await shipmentModel.getFcsShipment(_fcsShipment.id); + setState(() { + _fcsShipment = f; + }); + _load(); + } + } + + Widget menuPopWidget(BuildContext context) { + return PopupMenuButton( + elevation: 3.2, + icon: Icon(Icons.more_vert, color: primaryColor), + tooltip: 'This is tooltip', + onSelected: (choice) { + print(choice.id); + if (choice.id == 1) { + } else if (choice.id == 2) { + } else if (choice.id == 3) { + } else if (choice.id == 4) {} + }, + itemBuilder: (BuildContext context) { + return menuPopup.map((PopupMenu choice) { + return PopupMenuItem( + value: choice, + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + padding: EdgeInsets.only(left: 15), + child: LocalText( + context, + choice.status, + color: primaryColor, + )), + ], + ), + ); + }).toList(); + }); + } + + _ship() { + showConfirmDialog(context, "FCSshipment.ship.confirm", () { + _shipFcsShipment(); + }); + } + + _shipFcsShipment() async { + setState(() { + _isLoading = true; + }); + try { + FcsShipmentModel fcsShipmentModel = + Provider.of(context, listen: false); + await fcsShipmentModel.ship(_fcsShipment); + Navigator.pop(context, true); + } catch (e) { + showMsgDialog(context, "Error", e.toString()); + } finally { + setState(() { + _isLoading = false; + }); + } + } +} diff --git a/lib/pages/fcs_shipment/fcs_shipment_list.dart b/lib/pages/fcs_shipment/fcs_shipment_list.dart new file mode 100644 index 0000000..a4a632c --- /dev/null +++ b/lib/pages/fcs_shipment/fcs_shipment_list.dart @@ -0,0 +1,121 @@ +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/fcs_shipment/model/fcs_shipment_model.dart'; +import 'package:fcs/pages/widgets/local_popup_menu_button.dart'; +import 'package:fcs/pages/widgets/local_popupmenu.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import 'fcs_shipment_editor.dart'; +import 'fcs_shipment_list_row.dart'; + +class FcsShipmentList extends StatefulWidget { + @override + _FcsShipmentListState createState() => _FcsShipmentListState(); +} + +class _FcsShipmentListState extends State { + bool _isLoading = false; + var _controller = ScrollController(); + + @override + void initState() { + super.initState(); + + _controller.addListener(() async { + if (_controller.position.pixels == _controller.position.maxScrollExtent) { + Provider.of(context, listen: false).loadMore(); + } + }); + Provider.of(context, listen: false).initData(); + } + + @override + Widget build(BuildContext context) { + var shipmentModel = Provider.of(context); + + final popupMenu = LocalPopupMenuButton( + popmenus: [ + LocalPopupMenu( + id: 1, + textKey: "FCSshipment.popupmenu.active", + selected: shipmentModel.selectedIndex == 1), + LocalPopupMenu( + id: 2, + textKey: "FCSshipment.popupmenu.shipped", + selected: shipmentModel.selectedIndex == 2) + ], + popupMenuCallback: (p) => this.setState(() { + shipmentModel.selectedIndex = p.id; + }), + ); + + return LocalProgress( + inAsyncCall: _isLoading, + child: Scaffold( + appBar: AppBar( + centerTitle: true, + leading: new IconButton( + icon: new Icon(CupertinoIcons.back), + onPressed: () => Navigator.of(context).pop(), + ), + backgroundColor: primaryColor, + title: LocalText(context, 'FCSshipment.list.title', + color: Colors.white, fontSize: 20), + actions: [popupMenu], + ), + floatingActionButton: FloatingActionButton.extended( + onPressed: () { + _newShipment(); + }, + icon: Icon(Icons.add), + label: LocalText(context, "FCSshipment.add", color: Colors.white), + backgroundColor: primaryColor, + ), + body: Column( + children: [ + Expanded( + child: RefreshIndicator( + child: ListView.separated( + physics: AlwaysScrollableScrollPhysics(), + controller: _controller, + separatorBuilder: (context, index) => Divider( + color: Colors.black, + height: 1, + ), + scrollDirection: Axis.vertical, + shrinkWrap: true, + itemCount: shipmentModel.fcsShipments.length, + itemBuilder: (BuildContext context, int index) { + return FcsShipmentListRow( + key: ValueKey( + shipmentModel.fcsShipments[index].id), + shipment: shipmentModel.fcsShipments[index]); + }), + onRefresh: () => shipmentModel.refresh(), + ), + ), + shipmentModel.isLoading + ? Container( + padding: EdgeInsets.all(8), + color: primaryColor, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("Loading...", + style: TextStyle(color: Colors.white)), + ], + ), + ) + : Container(), + ], + ))); + } + + _newShipment() { + Navigator.of(context) + .push(CupertinoPageRoute(builder: (context) => FcsShipmentEditor())); + } +} diff --git a/lib/pages/fcs_shipment/fcs_shipment_list_row.dart b/lib/pages/fcs_shipment/fcs_shipment_list_row.dart new file mode 100644 index 0000000..020b304 --- /dev/null +++ b/lib/pages/fcs_shipment/fcs_shipment_list_row.dart @@ -0,0 +1,77 @@ +import 'package:fcs/domain/entities/fcs_shipment.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_icons/flutter_icons.dart'; +import 'package:intl/intl.dart'; +import 'fcs_shipment_info.dart'; + +class FcsShipmentListRow extends StatelessWidget { + final FcsShipment shipment; + final dateFormatter = new DateFormat('dd MMM yyyy'); + FcsShipmentListRow({Key key, this.shipment}) : super(key: key); + + @override + Widget build(BuildContext context) { + return InkWell( + onTap: () { + Navigator.of(context).push(CupertinoPageRoute( + builder: (context) => FcsShipmentInfo(fcsShipment: shipment))); + }, + child: Container( + padding: EdgeInsets.only(left: 15, right: 15), + child: Row( + children: [ + Expanded( + child: new Padding( + padding: const EdgeInsets.symmetric(vertical: 10.0), + child: new Row( + children: [ + Container( + padding: EdgeInsets.only(left: 5, right: 10), + child: Icon( + Ionicons.ios_airplane, + color: primaryColor, + size: 30, + ), + ), + new Expanded( + child: new Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(left: 8.0), + child: new Text( + shipment.shipmentNumber == null + ? '' + : shipment.shipmentNumber, + style: new TextStyle( + fontSize: 15.0, color: Colors.black), + ), + ), + Padding( + padding: const EdgeInsets.only(left: 10.0, top: 10), + child: new Text( + dateFormatter.format(shipment.cutoffDate), + style: new TextStyle( + fontSize: 15.0, color: Colors.grey), + ), + ) + ], + ), + ), + ], + ), + ), + ), + Padding( + padding: const EdgeInsets.all(0), + child: getStatus(shipment.status), + ), + ], + ), + ), + ); + } +} diff --git a/lib/pages/fcs_shipment/model/fcs_shipment_model.dart b/lib/pages/fcs_shipment/model/fcs_shipment_model.dart new file mode 100644 index 0000000..6d60365 --- /dev/null +++ b/lib/pages/fcs_shipment/model/fcs_shipment_model.dart @@ -0,0 +1,175 @@ +import 'dart:async'; + +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:fcs/data/services/services.dart'; +import 'package:fcs/domain/constants.dart'; +import 'package:fcs/domain/entities/fcs_shipment.dart'; +import 'package:fcs/helpers/paginator.dart'; +import 'package:fcs/pages/main/model/base_model.dart'; +import 'package:logging/logging.dart'; + +class FcsShipmentModel extends BaseModel { + final log = Logger('FcsShipmentModel'); + + StreamSubscription listener; + List _fcsShipments = []; + List get fcsShipments => _selectedIndex == 1 + ? _fcsShipments + : List.from(_shipped.values); + + Paginator _shipped; + bool isLoading = false; + int _selectedIndex = 1; + set selectedIndex(int index) { + _selectedIndex = index; + notifyListeners(); + } + + get selectedIndex => _selectedIndex; + + @override + void privilegeChanged() { + super.privilegeChanged(); + _loadFcsShipments(); + } + + initData() { + _selectedIndex = 1; + _loadFcsShipments(); + + if (_shipped != null) _shipped.close(); + _shipped = _getShipped(); + _shipped.load(); + } + + Future _loadFcsShipments() async { + if (user == null || !user.hasFcsShipments()) return; + String path = "/$fcs_shipment_collection/"; + if (listener != null) listener.cancel(); + _fcsShipments = []; + try { + listener = Firestore.instance + .collection("$path") + .where("status", isEqualTo: fcs_shipment_confirmed_status) + .where("is_deleted", isEqualTo: false) + .orderBy("shipment_number", descending: true) + .snapshots() + .listen((QuerySnapshot snapshot) { + _fcsShipments.clear(); + _fcsShipments = snapshot.documents.map((documentSnapshot) { + var s = FcsShipment.fromMap( + documentSnapshot.data, documentSnapshot.documentID); + return s; + }).toList(); + notifyListeners(); + }); + } catch (e) { + log.warning("Error!! $e"); + } + } + + Paginator _getShipped() { + if (user == null || !user.hasFcsShipments()) return null; + + var pageQuery = Firestore.instance + .collection("/$fcs_shipment_collection") + .where("status", isEqualTo: fcs_shipment_shipped_status) + .where("is_deleted", isEqualTo: false) + .orderBy("shipment_number", descending: true); + var paginator = new Paginator(pageQuery, rowPerLoad: 20, toObj: (data, id) { + return FcsShipment.fromMap(data, id); + }); + return paginator; + } + + Future loadMore() async { + if (_shipped.ended || _selectedIndex == 1) return; + isLoading = true; + notifyListeners(); + await _shipped.load(onFinished: () { + isLoading = false; + notifyListeners(); + }); + } + + Future refresh() async { + if (_selectedIndex == 1) return; + await _shipped.refresh(onFinished: () { + notifyListeners(); + }); + } + + Future> getActiveFcsShipments() async { + List fcsShipments = []; + try { + var snaps = await Firestore.instance + .collection("/$fcs_shipment_collection") + .where("status", isEqualTo: fcs_shipment_confirmed_status) + .getDocuments(source: Source.server); + fcsShipments = snaps.documents.map((documentSnapshot) { + var fcs = FcsShipment.fromMap( + documentSnapshot.data, documentSnapshot.documentID); + return fcs; + }).toList(); + } catch (e) { + log.warning("Error!! $e"); + } + return fcsShipments; + } + + Future getFcsShipment(String id) async { + try { + var snap = await Firestore.instance + .collection("/$fcs_shipment_collection") + .document(id) + .get(source: Source.server); + var fcs = FcsShipment.fromMap(snap.data, snap.documentID); + + return fcs; + } catch (e) { + log.warning("Error!! $e"); + } + return null; + } + + Future> getInvoiceFcsShipments() async { + List fcsShipments = []; + try { + var snaps = await Firestore.instance + .collection("/$fcs_shipment_collection") + .where("pending_invoice_user_count", isGreaterThan: 0) + .getDocuments(source: Source.server); + fcsShipments = snaps.documents.map((documentSnapshot) { + var fcs = FcsShipment.fromMap( + documentSnapshot.data, documentSnapshot.documentID); + return fcs; + }).toList(); + } catch (e) { + log.warning("Error!! $e"); + } + return fcsShipments; + } + + void initUser(user) { + super.initUser(user); + } + + @override + logout() async { + if (listener != null) await listener.cancel(); + if (_shipped != null) _shipped.close(); + _fcsShipments = []; + } + + Future create(FcsShipment fcsShipment) { + return Services.instance.fcsShipmentService.createFcsShipment(fcsShipment); + } + + Future update(FcsShipment fcsShipment) { + return Services.instance.fcsShipmentService.updateFcsShipment(fcsShipment); + } + + Future ship(FcsShipment fcsShipment) { + return Services.instance.fcsShipmentService.ship(fcsShipment); + } +} diff --git a/lib/pages/forget_password.dart b/lib/pages/forget_password.dart deleted file mode 100644 index 8b14953..0000000 --- a/lib/pages/forget_password.dart +++ /dev/null @@ -1,126 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:progress/progress.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/main_model.dart'; -import 'package:fcs/model/user_model.dart'; -import 'package:fcs/pages/reset_password.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:fcs/widget/progress.dart'; - -import '../fcs/common/pages/util.dart'; - -class ForgetPassword extends StatefulWidget { - final phoneNumber; - - const ForgetPassword({Key key, this.phoneNumber}) : super(key: key); - @override - _ForgetPasswordState createState() => _ForgetPasswordState(); -} - -class _ForgetPasswordState extends State { - final TextEditingController _email = new TextEditingController(); - bool _isLoading = false; - final _formKey = GlobalKey(); - - @override - void initState() { - super.initState(); - _email.text = widget.phoneNumber; - } - - @override - void dispose() { - super.dispose(); - } - - @override - Widget build(BuildContext context) { - final emailInput = TextFormField( - controller: _email, - autofocus: false, - decoration: new InputDecoration( - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide(color: Colors.grey, width: 1.0)), - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide(color: Colors.grey, width: 1.0)), - labelText: AppTranslations.of(context).text("forget.email"), - labelStyle: labelStyle, - icon: Icon( - Icons.email, - color: primaryColor, - )), - validator: (value) { - if (value.isEmpty) { - return AppTranslations.of(context).text("forget.email.empty"); - } - return null; - }, - ); - - final enterButton = Padding( - padding: EdgeInsets.symmetric(vertical: 16.0), - child: RaisedButton( - onPressed: () => _forgetPassword(), - padding: EdgeInsets.all(10), - color: primaryColor, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(7), - ), - child: Text(AppTranslations.of(context).text("forget.enter"), - style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold)), - ), - ); - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - title: LocalText( - context, - 'forget.password', - fontSize: 20, - color: Colors.white, - ), - backgroundColor: primaryColor, - ), - body: Center( - child: ListView( - shrinkWrap: true, - padding: EdgeInsets.only(left: 24.0, right: 24.0), - children: [ - Form(key: _formKey, child: emailInput), - SizedBox(height: 8.0), - enterButton, - ], - ), - ), - ), - ); - } - - Future _forgetPassword() async { - var phoneNumber = _email.text; - if (phoneNumber.isEmpty) { - showMsgDialog(context, "Error", "Please input email(or)phone number"); - return; - } - setState(() { - _isLoading = true; - }); - try { - UserModel userModel = Provider.of(context); - await userModel.forgetPassword(phoneNumber); - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => ResetPasswordPage(phoneNumber))); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - setState(() { - _isLoading = false; - }); - } - } -} diff --git a/lib/pages/help.dart b/lib/pages/help.dart deleted file mode 100644 index 1b361c0..0000000 --- a/lib/pages/help.dart +++ /dev/null @@ -1,119 +0,0 @@ -import 'dart:async'; -import 'dart:io'; - -import 'package:archive/archive.dart'; -import 'package:flutter/material.dart'; -import 'package:http/http.dart' as http; -import 'package:http_server/http_server.dart'; -import 'package:logging/logging.dart'; -import 'package:path_provider/path_provider.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/main_model.dart'; -import 'package:fcs/vo/setting.dart'; -import 'package:fcs/widget/progress.dart'; - -typedef void ProfileCallback(); - -class Help extends StatefulWidget { - - const Help({Key key}) : super(key: key); - @override - _HelpState createState() => _HelpState(); -} - -class _HelpState extends State { - final log = Logger('Help'); - - bool isLoading = false; - HttpServer httpServer; - // WebViewController _controller; - String url = ""; - - @override - void initState() { - super.initState(); - MainModel mainModel = Provider.of(context, listen: false); - var isBuyer = mainModel.isBuyer(); - this.url = "http://localhost:7777/web/index.html" + - (isBuyer ? "?is_buyer=true" : "?is_buyer=false"); - _run(mainModel.setting); - } - - void _run(Setting setting) async { - await _download(setting); - final directory = await getApplicationDocumentsDirectory(); - var staticFiles = new VirtualDirectory('${directory.path}') - ..allowDirectoryListing = true; - - HttpServer.bind('0.0.0.0', 7777).then((server) async { - httpServer = server; - log.info('Server running'); - server.listen(staticFiles.serveRequest); - // _controller.loadUrl(url); - log.info("locad url:$url"); - }, onError: (e) { - log.warning("Error===>:$e"); - }); - } - - Future dispose() async { - super.dispose(); - if (httpServer != null) await httpServer.close(force: true); - } - - Future _download(Setting setting) async { - final directory = (await getApplicationDocumentsDirectory()).path; - - var file = File('$directory/${setting.helpFileName()}'); - if (await file.exists()) { - return; - } - - String url = setting.helpURL; - var req = await http.Client().get(Uri.parse(url)); - File zippedFile = await file.writeAsBytes(req.bodyBytes); - - File prev = File('$directory/web'); - if (await prev.exists()) { - await prev.delete(recursive: true); - } - - var bytes = zippedFile.readAsBytesSync(); - var archive = ZipDecoder().decodeBytes(bytes); - for (var file in archive) { - var fileName = '$directory/web/${file.name}'; - if (file.isFile) { - var outFile = File(fileName); - outFile = await outFile.create(recursive: true); - await outFile.writeAsBytes(file.content); - } - } - } - - @override - Widget build(BuildContext context) { - return LocalProgress( - inAsyncCall: isLoading, - child: Scaffold( - appBar: AppBar( - iconTheme: IconThemeData( - color: Colors.black, //change your color here - ), - centerTitle: true, - backgroundColor: Colors.white, - title: ClipRRect( - child: Image.asset("assets/logo.png", height: 40), - borderRadius: new BorderRadius.circular(15.0), - )), - body:Text("abc"), - // body: WebView( - // initialUrl: url, - // javascriptMode: JavascriptMode.unrestricted, - // onWebViewCreated: (WebViewController webViewController) { - // _controller = webViewController; - // }, - // ), - ), - ); - } -} diff --git a/lib/pages/instruction.dart b/lib/pages/instruction.dart deleted file mode 100644 index d1129f1..0000000 --- a/lib/pages/instruction.dart +++ /dev/null @@ -1,66 +0,0 @@ -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/language_model.dart'; -import 'package:fcs/model/main_model.dart'; -import 'package:fcs/model/manual_model.dart'; -import 'package:fcs/pages/manual/manual_item_title_dialog.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/vo/manual.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/progress.dart'; - -class InstructionPage extends StatefulWidget { - final String image; - final String name; - - const InstructionPage({Key key, this.image, this.name}) : super(key: key); - @override - _InstructionPageState createState() => _InstructionPageState(); -} - -class _InstructionPageState extends State { - TextEditingController _manualVersionController = TextEditingController(); - final double dotSize = 10.0; - List helpList = new List(); - bool isEng; - String versionName; - bool _isLoading = false; - - @override - void initState() { - helpList.clear(); - var manualModel = Provider.of(context, listen: false); - var mainModel = Provider.of(context, listen: false); - versionName = manualModel.version; - helpList = manualModel.getHelpList(mainModel.isBuyer()); - super.initState(); - } - - @override - Widget build(BuildContext context) { - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - centerTitle: true, - leading: new IconButton( - icon: new Icon(Icons.close, color: Colors.white), - onPressed: () => Navigator.of(context).pop(), - ), - title: Text(widget.name), - backgroundColor: primaryColor, - ), - body: Container( - padding: EdgeInsets.only(left: 5, right: 5, top: 5), - child: Card( - elevation: 0, - child: Expanded( - child: FittedBox( - child: Image.asset(widget.image), fit: BoxFit.contain), - )), - ), - ), - ); - } -} diff --git a/lib/pages/invitation_page.dart b/lib/pages/invitation_page.dart deleted file mode 100644 index b3173f9..0000000 --- a/lib/pages/invitation_page.dart +++ /dev/null @@ -1,67 +0,0 @@ -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:flutter/material.dart'; -import 'package:fcs/widget/progress.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -import '../fcs/common/helpers/theme.dart'; - -class InvitationPage extends StatefulWidget { - @override - _InvitationPageState createState() => _InvitationPageState(); -} - -class _InvitationPageState extends State { - TextEditingController _nameController = new TextEditingController(); - TextEditingController _phoneController = new TextEditingController(); - - bool _isLoading = false; - - @override - void initState() { - super.initState(); - } - - @override - void dispose() { - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - centerTitle: true, - leading: new IconButton( - icon: new Icon( - Icons.close, - ), - onPressed: () => Navigator.of(context).pop(), - ), - backgroundColor: primaryColor, - title: Text(AppTranslations.of(context).text("customer.form.title")), - ), - body: Container( - padding: EdgeInsets.all(18), - child: Column( - children: [ - Expanded( - child: ListView( - children: [ - fcsInput("Name", Icons.person, controller: _nameController), - fcsInput("Phone Number", Icons.phone, - controller: _phoneController), - SizedBox(height: 30), - ], - ), - ), - fcsButton(context, "Invite", callack: () {}), - SizedBox(height: 10) - ], - ), - ), - ), - ); - } -} diff --git a/lib/pages/invoice/box_addition.dart b/lib/pages/invoice/box_addition.dart index 4fea0f2..882529d 100644 --- a/lib/pages/invoice/box_addition.dart +++ b/lib/pages/invoice/box_addition.dart @@ -1,14 +1,14 @@ -import 'package:fcs/model_fcs/box_model.dart'; -import 'package:fcs/model_fcs/package_model.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/box.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:fcs/widget/progress.dart'; +import 'package:fcs/domain/entities/carton.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/localization/app_translations.dart'; +import 'package:fcs/pages/carton/model/carton_model.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; class BoxAddition extends StatefulWidget { - final Box box; + final Carton box; BoxAddition({this.box}); @override @@ -16,7 +16,7 @@ class BoxAddition extends StatefulWidget { } class _BoxAdditionState extends State { - Box _box = new Box(); + Carton _box = new Carton(); bool _isLoading = false; @override @@ -34,14 +34,14 @@ class _BoxAdditionState extends State { @override Widget build(BuildContext context) { - var boxModel = Provider.of(context); + var boxModel = Provider.of(context); return LocalProgress( inAsyncCall: _isLoading, child: Scaffold( appBar: AppBar( centerTitle: true, leading: new IconButton( - icon: new Icon(Icons.close), + icon: new Icon(CupertinoIcons.back), onPressed: () => Navigator.of(context).pop(), ), backgroundColor: primaryColor, diff --git a/lib/pages/invoice/editor/invoice_carton_table.dart b/lib/pages/invoice/editor/invoice_carton_table.dart new file mode 100644 index 0000000..77f05ec --- /dev/null +++ b/lib/pages/invoice/editor/invoice_carton_table.dart @@ -0,0 +1,118 @@ +import 'package:fcs/domain/entities/carton.dart'; +import 'package:fcs/domain/entities/rate.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/local_title.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +typedef OnSelect = Function(Carton carton, bool checked); + +class InvoiceCartonTable extends StatelessWidget { + final List cartons; + final OnSelect onSelect; + final Rate rate; + + const InvoiceCartonTable({Key key, this.cartons, this.onSelect, this.rate}) + : super(key: key); + + @override + Widget build(BuildContext context) { + final tableTitle = Container( + padding: EdgeInsets.only(right: 10.0, top: 5), + child: Row( + children: [ + SizedBox( + width: 50, + ), + SizedBox( + width: 150, + child: LocalText(context, 'invoice.box.number', color: Colors.grey), + ), + LocalText(context, 'invoice.shipment_weight', color: Colors.grey), + ], + ), + ); + + final rows = cartons == null + ? [Container()] + : cartons.asMap().entries.map((p) { + return Container( + color: p.value.isChecked + ? Colors.grey.withOpacity(0.2) + : Colors.grey[50].withOpacity(0.2), + child: Container( + padding: EdgeInsets.only( + left: 0.0, right: 10.0, top: 3.0, bottom: 3.0), + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: p.key == cartons.length - 1 + ? Colors.white + : Colors.grey[350], + width: 1), + ), + ), + child: Row( + children: [ + onSelect == null + ? p.value.isChecked + ? SizedBox( + child: Icon(Icons.check, color: primaryColor), + width: 30) + : SizedBox(width: 30) + : Checkbox( + value: p.value.isChecked, + activeColor: primaryColor, + onChanged: (bool check) { + if (onSelect != null) onSelect(p.value, check); + }), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + p.value.cartonNumber, + style: textStyle, + ), + ], + )), + Flexible( + child: new Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + new Text( + "${p.value?.length ?? ""} x ${p.value?.width ?? ""} x ${p.value?.height ?? ""}", + style: textStyle, + ), + new Text( + "${p.value?.getShipmentWeight(rate.volumetricRatio)?.toStringAsFixed(2) ?? "0"} lb", + style: textStyle, + ), + new Text( + "${p.value?.actualWeight?.toStringAsFixed(2) ?? "0"} lb (Actual)", + style: textStyle, + ), + ], + ), + ) + ], + ), + ), + ); + }).toList(); + + return Column( + children: [ + LocalTitle(textKey: "invoice.box_info"), + tableTitle, + Divider( + color: Colors.grey[400], + ), + Column( + children: rows, + ), + ], + ); + } +} diff --git a/lib/pages/invoice/editor/invoice_discount_list.dart b/lib/pages/invoice/editor/invoice_discount_list.dart new file mode 100644 index 0000000..13ad897 --- /dev/null +++ b/lib/pages/invoice/editor/invoice_discount_list.dart @@ -0,0 +1,88 @@ +import 'package:fcs/domain/entities/discount.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/my_data_table.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +class InvoiceDiscountList extends StatelessWidget { + final List discounts; + + const InvoiceDiscountList({ + Key key, + this.discounts, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + centerTitle: true, + leading: new IconButton( + icon: new Icon(CupertinoIcons.back), + onPressed: () => Navigator.pop(context), + ), + backgroundColor: primaryColor, + title: LocalText( + context, + "invoice.shipment.discount.title", + fontSize: 20, + color: Colors.white, + ), + ), + body: Padding( + padding: const EdgeInsets.all(8.0), + child: table(context), + )); + } + + Widget table(BuildContext context) { + return MyDataTable( + headingRowHeight: 40, + columns: [ + MyDataColumn( + label: LocalText( + context, + "discount.code", + color: Colors.grey, + ), + ), + MyDataColumn( + label: LocalText( + context, + "discount.amount", + color: Colors.grey, + ), + ), + ], + rows: getRows(context), + ); + } + + List getRows(BuildContext context) { + if (discounts == null) { + return []; + } + var rows = discounts.map((c) { + return MyDataRow( + onSelectChanged: (value) => Navigator.pop(context, c), + cells: [ + MyDataCell(new Text( + c.code ?? "", + style: textStyle, + )), + MyDataCell( + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text(c.amount?.toStringAsFixed(2) ?? "0", style: textStyle), + ], + ), + ), + ], + ); + }).toList(); + + return rows; + } +} diff --git a/lib/pages/invoice/editor/invoice_editor.dart b/lib/pages/invoice/editor/invoice_editor.dart new file mode 100644 index 0000000..a56c531 --- /dev/null +++ b/lib/pages/invoice/editor/invoice_editor.dart @@ -0,0 +1,451 @@ +import 'package:fcs/domain/entities/cargo_type.dart'; +import 'package:fcs/domain/entities/carton.dart'; +import 'package:fcs/domain/entities/custom_duty.dart'; +import 'package:fcs/domain/entities/discount.dart'; +import 'package:fcs/domain/entities/fcs_shipment.dart'; +import 'package:fcs/domain/entities/invoice.dart'; +import 'package:fcs/domain/entities/payment_method.dart'; +import 'package:fcs/domain/entities/shipment.dart'; +import 'package:fcs/domain/entities/user.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/carton/model/carton_model.dart'; +import 'package:fcs/pages/discount/model/discount_model.dart'; +import 'package:fcs/pages/invoice/editor/invoice_carton_table.dart'; +import 'package:fcs/pages/invoice/editor/invoice_discount_list.dart'; +import 'package:fcs/pages/invoice/editor/invoice_handling_fee_list.dart'; +import 'package:fcs/pages/invoice/invoice_table.dart'; +import 'package:fcs/pages/invoice/model/invoice_model.dart'; +import 'package:fcs/pages/main/model/main_model.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/payment_methods/model/payment_method_model.dart'; +import 'package:fcs/pages/rates/custom_list.dart'; +import 'package:fcs/pages/rates/model/shipment_rate_model.dart'; +import 'package:fcs/pages/shipment/model/shipment_model.dart'; +import 'package:fcs/pages/widgets/display_text.dart'; +import 'package:fcs/pages/widgets/fcs_icons.dart'; +import 'package:fcs/pages/widgets/local_button.dart'; +import 'package:fcs/pages/widgets/local_dropdown.dart'; +import 'package:fcs/pages/widgets/local_popup_menu_button.dart'; +import 'package:fcs/pages/widgets/local_popupmenu.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_icons/flutter_icons.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:intl/intl.dart'; +import 'package:provider/provider.dart'; + +class InvoiceEditor extends StatefulWidget { + final Invoice invoice; + final User customer; + final FcsShipment fcsShipment; + InvoiceEditor({this.invoice, this.customer, this.fcsShipment}); + + @override + _InvoiceEditorState createState() => _InvoiceEditorState(); +} + +class _InvoiceEditorState extends State { + var dateFormatter = new DateFormat('dd MMM yyyy'); + + Invoice _invoice; + bool _isLoading = false; + bool _isNew; + User _user; + + bool _showCartons = false; + @override + void initState() { + super.initState(); + _isNew = widget.invoice == null; + + if (widget.invoice != null) { + _invoice = widget.invoice; + } else { + _invoice = Invoice( + customDuties: [], + cartons: [], + shipments: [], + invoiceDate: DateTime.now()); + } + _user = widget.customer; + _loadAll(); + } + + _loadAll() async { + setState(() { + _isLoading = true; + }); + try { + await _loadCartons(); + await _loadShipments(); + await _loadDiscount(); + } catch (e) {} finally { + setState(() { + _isLoading = false; + }); + } + } + + _loadCartons() async { + CartonModel cartonModel = Provider.of(context, listen: false); + List cartons = await cartonModel.getCartonsForInvoice( + widget.fcsShipment.id, widget.customer.id); + cartons.forEach((c) { + c.isChecked = true; + }); + setState(() { + _invoice.cartons = cartons; + }); + } + + _loadShipments() async { + ShipmentModel shipmentModel = + Provider.of(context, listen: false); + List shipments = await shipmentModel.getShipmentWithHandlingFee( + widget.fcsShipment.id, widget.customer.id); + shipments.forEach((s) { + s.isSelected = true; + }); + setState(() { + _invoice.shipments = shipments; + }); + } + + List discounts = []; + _loadDiscount() async { + DiscountModel discountModel = + Provider.of(context, listen: false); + discounts = await discountModel.getDiscount(widget.customer.id); + if (discounts != null && discounts.length > 0) { + setState(() { + _invoice.discount = discounts.first; + }); + } + } + + @override + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + var mainModel = Provider.of(context); + var paymentMethodModel = Provider.of(context); + var rateModel = Provider.of(context); + var rate = rateModel.rate; + + final invoiceNumberBox = DisplayText( + labelTextKey: 'invoice.number', + iconData: FontAwesomeIcons.fileInvoice, + text: _invoice?.invoiceNumber ?? ""); + final statusBox = DisplayText( + text: _invoice?.status ?? "", + iconData: Icons.av_timer, + labelTextKey: 'invoice.status'); + final cartonTable = InvoiceCartonTable( + cartons: _invoice.cartons, + rate: rate, + onSelect: (c, checked) { + setState(() { + c.isChecked = checked; + }); + }, + ); + final paymentTypesBox = LocalDropdown( + callback: (v) { + setState(() { + _invoice.paymentMethod = v; + }); + }, + labelKey: "invoice.payment_method", + iconData: FontAwesome.money, + display: (u) => u.name, + selectedValue: _invoice.paymentMethod, + values: paymentMethodModel.paymentMethods, + ); + final invoiceTableBox = InvoiceTable( + invoice: _invoice, + rate: rate, + deliveryFeeSelected: (selected) { + setState(() { + if (selected) { + _invoice.deliveryFee = rate.deliveryFee; + } else { + _invoice.deliveryFee = 0; + } + }); + }, + discountSelected: (discount) { + setState(() { + _invoice.discount = discount; + }); + }, + onRemove: (i) { + if (i.invoiceDataType == InvoiceDataType.CustomFeeDataType) { + _removeCustom(i.data); + } + if (i.invoiceDataType == InvoiceDataType.DiscountDataType) { + setState(() { + _invoice.discount = null; + }); + } + if (i.invoiceDataType == InvoiceDataType.DeliveryFeeType) { + setState(() { + _invoice.deliveryFee = 0; + }); + } + if (i.invoiceDataType == InvoiceDataType.HandlingFeeType) { + setState(() { + _removeShipment(i.data); + }); + } + }, + ); + final toggleButtonsBox = ToggleButtons( + color: Colors.black45, + selectedColor: Colors.black45, + disabledColor: Colors.grey, + selectedBorderColor: primaryColor, + borderColor: Colors.transparent, + fillColor: Colors.transparent, + highlightColor: Colors.black45, + children: [ + Icon(cartonIconData), + ], + onPressed: (int index) { + setState(() { + _showCartons = !_showCartons; + }); + }, + isSelected: [_showCartons], + ); + final popupMenu = LocalPopupMenuButton( + buttonIcon: Icons.add_circle, + selectable: false, + buttonColor: Colors.black45, + popmenus: [ + LocalPopupMenu( + id: 1, + textKey: "invoice.add.custom.fee.menu", + ), + LocalPopupMenu( + id: 2, + textKey: "invoice.add.handling.fee.menu", + ), + LocalPopupMenu( + id: 3, + textKey: "invoice.add.discount.menu", + ), + LocalPopupMenu( + id: 4, + textKey: "invoice.delivery_fee", + ) + ], + popupMenuCallback: (p) async { + if (p.id == 1) { + CustomDuty customDuty = await Navigator.of(context).push( + CupertinoPageRoute( + builder: (context) => CustomList(selected: true))); + _addCustom(customDuty); + } else if (p.id == 2) { + Shipment shipment = await Navigator.of(context).push( + CupertinoPageRoute( + builder: (context) => + InvoiceHandlingFeeList(shipments: _invoice.shipments))); + _addShipment(shipment); + } else if (p.id == 3) { + Discount discount = + await Navigator.of(context).push(CupertinoPageRoute( + builder: (context) => InvoiceDiscountList( + discounts: discounts, + ))); + if (discount != null) { + setState(() { + _invoice.discount = discount; + }); + } + } else if (p.id == 4) { + setState(() { + _invoice.deliveryFee = rate.deliveryFee; + }); + } + }, + ); + + final headerBox = Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(dateFormatter.format(_invoice.invoiceDate)), + SizedBox( + height: 10, + ), + Text(_user?.name ?? ""), + Text( + _user?.fcsID ?? "", + style: TextStyle(fontSize: 12), + ) + ], + ), + Spacer(), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + toggleButtonsBox, + popupMenu, + ], + ), + ], + ); + + final createBtn = LocalButton( + textKey: "invoice.issue.btn", + callBack: _save, + ); + + return LocalProgress( + inAsyncCall: _isLoading, + child: Scaffold( + appBar: AppBar( + centerTitle: true, + leading: new IconButton( + icon: new Icon(CupertinoIcons.back, color: primaryColor), + onPressed: () => Navigator.of(context).pop(), + ), + backgroundColor: Colors.white, + shadowColor: Colors.transparent, + title: LocalText(context, 'invoice.form.title', + color: primaryColor, fontSize: 20), + ), + body: Padding( + padding: const EdgeInsets.all(8.0), + child: ListView( + children: [ + headerBox, + _isNew ? Container() : invoiceNumberBox, + _isNew ? Container() : statusBox, + _showCartons ? cartonTable : Container(), + _showCartons + ? Divider( + color: primaryColor, + thickness: 2, + ) + : Container(), + invoiceTableBox, + SizedBox( + height: 10, + ), + paymentTypesBox, + SizedBox( + height: 10, + ), + _isNew + ? createBtn + : mainModel.isCustomer() + ? Container() + : Container( + child: Column( + children: [ + fcsButton(context, + getLocalString(context, 'invoice.btn_save')) + ], + )), + _isNew + ? Container() + : fcsButton(context, + getLocalString(context, 'invoice.btn_payment_receipt')) + ], + ), + ), + ), + ); + } + + _addCustom(CustomDuty customDuty) { + if (customDuty == null) return; + setState(() { + _invoice.customDuties.remove(customDuty); + _invoice.customDuties.add(customDuty); + }); + } + + _addShipment(Shipment shipment) { + if (shipment == null) return; + shipment.isSelected = true; + setState(() { + _invoice.shipments.remove(shipment); + _invoice.shipments.add(shipment); + }); + } + + _removeShipment(Shipment shipment) { + if (shipment == null) return; + shipment.isSelected = false; + setState(() { + _invoice.shipments.remove(shipment); + _invoice.shipments.add(shipment); + }); + } + + _removeCustom(CustomDuty customDuty) { + setState(() { + _invoice.customDuties.remove(customDuty); + }); + } + + _save() async { + var rateModel = Provider.of(context, listen: false); + double amount = _invoice.getNetAmount(rateModel.rate); + if (_invoice.paymentMethod == null) { + showMsgDialog(context, "Error", "Payment method required"); + return; + } + List cargoTypes = _invoice.getCargoTypes(rateModel.rate); + if (cargoTypes == null || cargoTypes.length == 0) { + showMsgDialog(context, "Error", "Expected at least one cargo type"); + return; + } + if ((amount ?? 0) <= 0) { + showMsgDialog(context, "Error", "Expected positive amount"); + return; + } + + setState(() { + _isLoading = true; + }); + + try { + InvoiceModel invoiceModel = + Provider.of(context, listen: false); + + Invoice invoice = Invoice(); + invoice.cargoTypes = cargoTypes; + invoice.amount = amount; + invoice.handlingFee = _invoice.getHandlingFee(); + invoice.cartons = _invoice.cartons.where((c) => c.isChecked).toList(); + invoice.shipments = + _invoice.shipments.where((s) => s.isSelected).toList(); + invoice.discount = _invoice.discount; + invoice.deliveryFee = _invoice.deliveryFee; + + invoice.userID = widget.customer.id; + invoice.fcsShipmentID = widget.fcsShipment.id; + invoice.invoiceDate = _invoice.invoiceDate; + invoice.paymentMethod = _invoice.paymentMethod; + + await invoiceModel.createInvoice(invoice); + Navigator.pop(context, true); + } catch (e) { + showMsgDialog(context, "Error", e.toString()); + } finally { + setState(() { + _isLoading = false; + }); + } + } +} diff --git a/lib/pages/invoice/editor/invoice_handling_fee_list.dart b/lib/pages/invoice/editor/invoice_handling_fee_list.dart new file mode 100644 index 0000000..9e1af8b --- /dev/null +++ b/lib/pages/invoice/editor/invoice_handling_fee_list.dart @@ -0,0 +1,105 @@ +import 'package:fcs/domain/entities/shipment.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/my_data_table.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +typedef OnAdd(Shipment shipment); +typedef OnRemove(Shipment shipment); + +class InvoiceHandlingFeeList extends StatelessWidget { + final List shipments; + final OnAdd onAdd; + final OnRemove onRemove; + + const InvoiceHandlingFeeList( + {Key key, this.shipments, this.onAdd, this.onRemove}) + : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + centerTitle: true, + leading: new IconButton( + icon: new Icon(CupertinoIcons.back), + onPressed: () => Navigator.pop(context), + ), + backgroundColor: primaryColor, + title: LocalText( + context, + "invoice.shipment.handling.fee.title", + fontSize: 20, + color: Colors.white, + ), + ), + body: Padding( + padding: const EdgeInsets.all(8.0), + child: table(context), + )); + } + + Widget table(BuildContext context) { + return MyDataTable( + headingRowHeight: 40, + columns: [ + MyDataColumn( + label: LocalText( + context, + "invoice.shipment.number", + color: Colors.grey, + ), + ), + MyDataColumn( + label: LocalText( + context, + "invoice.add.handling.fee.menu", + color: Colors.grey, + ), + ), + ], + rows: getRows(context), + ); + } + + List getRows(BuildContext context) { + if (shipments == null) { + return []; + } + var rows = shipments.map((c) { + return MyDataRow( + onSelectChanged: (value) => Navigator.pop(context, c), + cells: [ + MyDataCell(new Text( + c.shipmentNumber ?? "", + style: textStyle, + )), + MyDataCell( + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text(c.handlingFee?.toStringAsFixed(2) ?? "0", + style: textStyle), + onRemove == null + ? SizedBox( + width: 50, + ) + : IconButton( + icon: Icon( + Icons.remove_circle, + color: primaryColor, + ), + onPressed: () { + if (onRemove != null) onRemove(c); + }) + ], + ), + ), + ], + ); + }).toList(); + + return rows; + } +} diff --git a/lib/pages/invoice/invoce_list.dart b/lib/pages/invoice/invoce_list.dart deleted file mode 100644 index 5374e9a..0000000 --- a/lib/pages/invoice/invoce_list.dart +++ /dev/null @@ -1,163 +0,0 @@ -import 'package:fcs/model/invoice_model.dart'; -import 'package:fcs/model/main_model.dart'; -import 'package:fcs/model/shipment_model.dart'; -import 'package:fcs/model_fcs/package_model.dart'; -import 'package:fcs/pages_fcs/package_list_row.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/widget/bottom_up_page_route.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/pages/search_page.dart'; -import 'package:fcs/vo/buyer.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; - -import 'package:flutter/material.dart'; -import 'package:fcs/widget/progress.dart'; - -import '../shipment_editor.dart'; -import '../shipment_list_row.dart'; -import 'invoice_editor.dart'; -import 'invoice_list_row.dart'; - -class InvoiceList extends StatefulWidget { - @override - _InvoiceListState createState() => _InvoiceListState(); -} - -class _InvoiceListState extends State { - bool _isLoading = false; - - @override - void initState() { - super.initState(); - } - - @override - void dispose() { - super.dispose(); - } - - @override - Widget build(BuildContext context) { - var owner = Provider.of(context).isOwner(); - - return LocalProgress( - inAsyncCall: _isLoading, - child: DefaultTabController( - length: 2, - child: Scaffold( - appBar: AppBar( - centerTitle: true, - leading: new IconButton( - icon: new Icon(Icons.close), - onPressed: () => Navigator.of(context).pop(), - ), - backgroundColor: primaryColor, - title: LocalText(context, 'invoices.title', - color: Colors.white, fontSize: 20), - actions: [ - IconButton( - icon: Icon( - Icons.search, - color: Colors.white, - ), - iconSize: 30, - onPressed: () => showPlacesSearch(context), - ), - ], - bottom: TabBar( - unselectedLabelColor: Colors.grey, - tabs: [ - Tab(text: "Pending"), - Tab(text: "Paid"), - ], - ), - ), - floatingActionButton: owner - ? FloatingActionButton.extended( - onPressed: () { - _newInvoice(); - }, - icon: Icon(Icons.add), - label: - Text(AppTranslations.of(context).text("invoices.add")), - backgroundColor: primaryColor, - ) - : null, - body: TabBarView( - children: [_pending(), _paided()], - )), - ), - ); - } - - _newInvoice() { - Navigator.of(context).push(BottomUpPageRoute(InvoiceEditor())); - } - - Widget _packages() { - var packageModel = Provider.of(context); - return Column( - children: [ - Expanded( - child: new ListView.separated( - separatorBuilder: (context, index) => Divider( - color: Colors.black, - ), - scrollDirection: Axis.vertical, - padding: EdgeInsets.only(top: 15), - shrinkWrap: true, - itemCount: packageModel.completed.length, - itemBuilder: (BuildContext context, int index) { - return PackageListRow( - package: packageModel.completed[index], - isReadOnly: true, - ); - }), - ), - ], - ); - } - - Widget _pending() { - var invoiceModel = Provider.of(context); - return Column( - children: [ - Expanded( - child: new ListView.separated( - separatorBuilder: (context, index) => Divider( - color: Colors.black, - ), - scrollDirection: Axis.vertical, - padding: EdgeInsets.only(top: 15), - shrinkWrap: true, - itemCount: invoiceModel.pending.length, - itemBuilder: (BuildContext context, int index) { - return InvoiceListRow(invoice: invoiceModel.pending[index]); - }), - ), - ], - ); - } - - Widget _paided() { - var invoiceModel = Provider.of(context); - return Column( - children: [ - Expanded( - child: new ListView.separated( - separatorBuilder: (context, index) => Divider( - color: Colors.black, - ), - scrollDirection: Axis.vertical, - padding: EdgeInsets.only(top: 15), - shrinkWrap: true, - itemCount: invoiceModel.paided.length, - itemBuilder: (BuildContext context, int index) { - return InvoiceListRow(invoice: invoiceModel.paided[index]); - }), - ), - ], - ); - } -} diff --git a/lib/pages/invoice/invoice_customer_list.dart b/lib/pages/invoice/invoice_customer_list.dart new file mode 100644 index 0000000..dfa7a61 --- /dev/null +++ b/lib/pages/invoice/invoice_customer_list.dart @@ -0,0 +1,163 @@ +import 'package:fcs/domain/entities/fcs_shipment.dart'; +import 'package:fcs/domain/entities/user.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/customer/model/customer_model.dart'; +import 'package:fcs/pages/invoice/editor/invoice_editor.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; +import 'package:provider/provider.dart'; + +class InvoiceCustomerList extends StatefulWidget { + final FcsShipment fcsShipment; + + const InvoiceCustomerList({Key key, this.fcsShipment}) : super(key: key); + + @override + _InvoiceCustomerListState createState() => _InvoiceCustomerListState(); +} + +class _InvoiceCustomerListState extends State { + var dateFormatter = new DateFormat('dd MMM yyyy - hh:mm:ss a'); + final double dotSize = 15.0; + bool _isLoading = false; + List _users = []; + @override + void initState() { + super.initState(); + _load(); + } + + _load() async { + CustomerModel customerModel = + Provider.of(context, listen: false); + var users = await customerModel.getInvoiceUsers(widget.fcsShipment.id); + setState(() { + _users = users; + }); + } + + @override + Widget build(BuildContext context) { + return LocalProgress( + inAsyncCall: _isLoading, + child: Scaffold( + appBar: AppBar( + centerTitle: true, + leading: new IconButton( + icon: new Icon(CupertinoIcons.back), + onPressed: () => Navigator.of(context).pop(), + ), + backgroundColor: primaryColor, + title: LocalText( + context, + "customer.list.title", + fontSize: 20, + color: Colors.white, + ), + ), + body: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Expanded( + child: ListView.separated( + separatorBuilder: (context, index) => Divider( + color: Colors.grey, + ), + scrollDirection: Axis.vertical, + shrinkWrap: true, + itemCount: _users.length, + itemBuilder: (BuildContext context, int index) { + User customer = _users[index]; + return _item(customer); + }), + ), + ], + ), + ), + ); + } + + Widget _item(User customer) { + return InkWell( + onTap: () async { + bool created = await Navigator.of(context).push(CupertinoPageRoute( + builder: (context) => InvoiceEditor( + customer: customer, + fcsShipment: widget.fcsShipment, + ))); + if (created ?? false) { + _load(); + } + }, + child: Padding( + padding: const EdgeInsets.only(left: 12.0, right: 12), + child: Row( + children: [ + Expanded( + child: new Padding( + padding: const EdgeInsets.symmetric(vertical: 2.0), + child: new Row( + children: [ + Padding( + padding: const EdgeInsets.all(5.0), + child: Container( + padding: const EdgeInsets.only( + left: 10.0, right: 10, top: 6, bottom: 6), + decoration: BoxDecoration( + color: primaryColor, + borderRadius: + BorderRadius.all(Radius.circular(35.0))), + child: Text( + customer.initial, + style: TextStyle(fontSize: 30, color: Colors.white), + ), + ), + ), + new Expanded( + child: Padding( + padding: const EdgeInsets.only(left: 8.0), + child: new Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(top: 2.0), + child: new Text( + customer.name, + style: new TextStyle( + fontSize: 20.0, color: primaryColor), + ), + ), + Padding( + padding: const EdgeInsets.only(top: 2.0), + child: new Text( + customer.phoneNumber, + style: new TextStyle( + fontSize: 15.0, color: Colors.grey), + ), + ), + ], + ), + ), + ), + ], + ), + ), + ), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Padding( + padding: const EdgeInsets.only(right: 5), + child: Text(customer.getLastMessageTime), + ), + ], + ), + ], + ), + ), + ); + } +} diff --git a/lib/pages/invoice/invoice_editor.dart b/lib/pages/invoice/invoice_editor.dart deleted file mode 100644 index 66f5810..0000000 --- a/lib/pages/invoice/invoice_editor.dart +++ /dev/null @@ -1,856 +0,0 @@ -import 'package:fcs/model/discount_model.dart'; -import 'package:fcs/model/main_model.dart'; -import 'package:fcs/model_fcs/box_model.dart'; -import 'package:fcs/pages/invoice/package_addition.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/box.dart'; -import 'package:fcs/vo/cargo.dart'; -import 'package:fcs/vo/invoice.dart'; -import 'package:fcs/vo/package.dart'; -import 'package:fcs/widget/bottom_up_page_route.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:fcs/widget/multi_img_controller.dart'; -import 'package:fcs/widget/multi_img_file.dart'; -import 'package:fcs/widget/my_data_table.dart'; -import 'package:fcs/widget/progress.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_icons/flutter_icons.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; - -import '../../fcs/common/pages/util.dart'; -import 'box_addition.dart'; - -class InvoiceEditor extends StatefulWidget { - final Invoice invoice; - InvoiceEditor({this.invoice}); - - @override - _InvoiceEditorState createState() => _InvoiceEditorState(); -} - -class _InvoiceEditorState extends State { - var dateFormatter = new DateFormat('dd MMM yyyy'); - TextEditingController _invoiceNumberController = new TextEditingController(); - TextEditingController _dateController = new TextEditingController(); - TextEditingController _nameController = new TextEditingController(); - TextEditingController _phoneController = new TextEditingController(); - TextEditingController _discountController = new TextEditingController(); - TextEditingController _amountController = new TextEditingController(); - TextEditingController _statusController = new TextEditingController(); - TextEditingController _handlingFeeController = new TextEditingController(); - TextEditingController _customFeeController = new TextEditingController(); - MultiImgController multiImgController = MultiImgController(); - TextEditingController _descriptionController = new TextEditingController(); - TextEditingController _balanceController = new TextEditingController(); - - Invoice _invoice; - bool _isLoading = false; - List _boxes = []; - bool isSwitched = false; - String deliveryfee = '\$0'; - List _cargoTypes = [ - Cargo(type: 'General Cargo', weight: 33, price: 6), - Cargo(type: 'Medicine', weight: 33, price: 7), - Cargo(type: 'Dangerous Cargo', weight: 33, price: 8) - ]; - - List _receipts = [ - "assets/photos/amazon_ins.png", - ]; - - @override - void initState() { - super.initState(); - if (widget.invoice != null) { - _invoice = widget.invoice; - _invoiceNumberController.text = _invoice.invoiceNumber; - _dateController.text = dateFormatter.format(_invoice.invoiceDate); - _nameController.text = _invoice.customerName; - _phoneController.text = _invoice.customerPhoneNumber; - // _amountController.text = _invoice.getAmount.toString(); - _amountController.text = _invoice.amount.toString(); - _statusController.text = _invoice.status.toString(); - _handlingFeeController.text = '0'; - _customFeeController.text = '0'; - multiImgController.setImageUrls = _receipts; - _descriptionController.text = 'For Electronics goods'; - _balanceController.text = - (_invoice.amount - _invoice.receipts[0].amount).toString(); - // _boxes = _invoice.packages; - } else { - _dateController.text = dateFormatter.format(DateTime.now()); - _amountController.text = '0'; - _handlingFeeController.text = '0'; - _customFeeController.text = '0'; - _descriptionController.text = ''; - _balanceController.text = '0'; - } - - _boxes = [ - Box( - shipmentNumber: "A202", - receiverNumber: "3", - receiverName: "Ko Myo Min", - boxNumber: "1", - rate: 7, - packageType: "General", - weight: 75, - status: "Packed", - receiverAddress: '1 Bo Yar Nyunt St.\nDagon Tsp, Yangon', - cargoDesc: "Clothes", - arrivedDate: DateTime(2020, 6, 1), - width: 10, - height: 10, - length: 10, - // packages: packages, - // statusHistory: statusHistory, - cargoTypes: [ - Cargo(type: 'General Cargo', weight: 25), - Cargo(type: 'Medicine', weight: 20), - Cargo(type: 'Dangerous Cargo', weight: 30) - ]), - Box( - shipmentNumber: "A202", - receiverNumber: "3", - receiverName: "Ko Myo Min", - boxNumber: "2", - rate: 7, - packageType: "General", - weight: 75, - status: "Packed", - cargoDesc: "Clothes", - arrivedDate: DateTime(2020, 6, 1), - width: 10, - height: 10, - length: 10, - // statusHistory: statusHistory, - // packages: packages, - receiverAddress: '1 Bo Yar Nyunt St.\nDagon Tsp, Yangon', - cargoTypes: [ - Cargo(type: 'General Cargo', weight: 25), - Cargo(type: 'Medicine', weight: 20), - Cargo(type: 'Dangerous Cargo', weight: 30) - ]) - ]; - } - - @override - void dispose() { - super.dispose(); - } - - @override - Widget build(BuildContext context) { - var mainModel = Provider.of(context); - var discountModel = Provider.of(context); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - centerTitle: true, - leading: new IconButton( - icon: new Icon(Icons.close), - onPressed: () => Navigator.of(context).pop(), - ), - backgroundColor: primaryColor, - title: LocalText(context, 'invoice.form.title', - color: Colors.white, fontSize: 20), - ), - body: Card( - child: Column( - children: [ - Expanded( - child: Padding( - padding: const EdgeInsets.all(10.0), - child: ListView(children: [ - TextFormField( - controller: _dateController, - readOnly: true, - decoration: InputDecoration( - fillColor: Colors.white, - labelText: 'Invoice Date', - labelStyle: TextStyle( - fontSize: 16, - ), - filled: true, - enabledBorder: InputBorder.none, - focusedBorder: InputBorder.none, - icon: Icon( - Icons.date_range, - color: primaryColor, - ), - )), - widget.invoice == null - ? Container() - : Container( - padding: EdgeInsets.only(top: 5), - child: TextFormField( - controller: _invoiceNumberController, - readOnly: true, - decoration: InputDecoration( - fillColor: Colors.white, - labelText: 'Invoice Number', - labelStyle: TextStyle( - fontSize: 16, - ), - filled: true, - enabledBorder: InputBorder.none, - focusedBorder: InputBorder.none, - icon: Icon( - FontAwesomeIcons.fileInvoice, - color: primaryColor, - ), - )), - ), - widget.invoice == null - ? Container( - padding: EdgeInsets.only(top: 5), - child: TextFormField( - initialValue: "Ko Myo Min", - cursorColor: primaryColor, - decoration: InputDecoration( - fillColor: Colors.white, - labelText: 'Customer Name', - labelStyle: TextStyle( - fontSize: 16, - ), - filled: true, - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide( - color: Colors.grey, width: 1.0)), - icon: Icon( - FontAwesomeIcons.fileInvoice, - color: primaryColor, - ), - suffixIcon: IconButton( - icon: Icon( - Icons.search, - color: Colors.grey, - ), - onPressed: () {})), - ), - ) - : Container(), - widget.invoice == null - ? Container() - : Container( - padding: EdgeInsets.only(top: 0), - child: TextFormField( - controller: _nameController, - readOnly: true, - decoration: InputDecoration( - fillColor: Colors.white, - labelText: 'Customer Name', - labelStyle: TextStyle( - fontSize: 16, - ), - filled: true, - enabledBorder: InputBorder.none, - focusedBorder: InputBorder.none, - icon: Icon( - Feather.user, - color: primaryColor, - ), - )), - ), - // widget.invoice == null - // ? Container() - // : TextFormField( - // controller: _phoneController, - // readOnly: true, - // decoration: InputDecoration( - // fillColor: Colors.white, - // labelText: 'Customer Phone Number', - // labelStyle: - // TextStyle(fontSize: 16, color: Colors.grey), - // filled: true, - // enabledBorder: InputBorder.none, - // focusedBorder: InputBorder.none, - // icon: Icon( - // Icons.phone, - // color: Colors.grey, - // ), - // )), - // Container( - // padding: EdgeInsets.only(top: 0), - // child: fcsInput('Amount', FontAwesomeIcons.moneyBill, - // controller: _amountController), - // ), - - widget.invoice == null - ? Container() - : Container( - padding: EdgeInsets.only(top: 5), - child: TextFormField( - controller: _statusController, - readOnly: true, - decoration: InputDecoration( - fillColor: Colors.white, - labelText: 'Status', - labelStyle: TextStyle( - fontSize: 16, - ), - filled: true, - enabledBorder: InputBorder.none, - focusedBorder: InputBorder.none, - icon: Icon( - Icons.av_timer, - color: primaryColor, - ), - )), - ), - - Container( - padding: EdgeInsets.only(top: 0), - child: TextFormField( - controller: _amountController, - readOnly: true, - decoration: InputDecoration( - fillColor: Colors.white, - labelText: 'Amount', - labelStyle: TextStyle( - fontSize: 16, - ), - filled: true, - enabledBorder: InputBorder.none, - focusedBorder: InputBorder.none, - icon: Icon( - FontAwesomeIcons.moneyBill, - color: primaryColor, - ), - )), - ), - - Container( - padding: EdgeInsets.only(top: 5), - child: TextFormField( - controller: _balanceController, - readOnly: true, - decoration: InputDecoration( - fillColor: Colors.white, - labelText: 'Balance', - labelStyle: TextStyle( - fontSize: 16, - ), - filled: true, - enabledBorder: InputBorder.none, - focusedBorder: InputBorder.none, - icon: Icon( - FontAwesomeIcons.moneyBill, - color: primaryColor, - ), - )), - ), - - Container( - padding: EdgeInsets.only(top: 5), - child: TextFormField( - controller: _handlingFeeController, - readOnly: true, - decoration: InputDecoration( - fillColor: Colors.white, - labelText: 'Handling Fee', - labelStyle: TextStyle( - fontSize: 16, - ), - filled: true, - enabledBorder: InputBorder.none, - focusedBorder: InputBorder.none, - icon: Icon( - FontAwesomeIcons.moneyBill, - color: primaryColor, - ), - )), - ), - - Container( - padding: EdgeInsets.only(top: 5), - child: TextFormField( - controller: _customFeeController, - readOnly: false, - decoration: InputDecoration( - fillColor: Colors.white, - labelText: 'Customs Fee', - labelStyle: TextStyle( - fontSize: 16, - ), - filled: true, - icon: Icon( - FontAwesomeIcons.moneyBill, - color: primaryColor, - ), - focusedBorder: UnderlineInputBorder( - borderSide: - BorderSide(color: Colors.grey, width: 1.0)), - )), - ), - - Container( - padding: EdgeInsets.only(top: 5), - child: TextFormField( - controller: _descriptionController, - readOnly: false, - decoration: InputDecoration( - fillColor: Colors.white, - labelText: 'Customs Fee Description', - labelStyle: TextStyle( - fontSize: 16, - ), - filled: true, - icon: Icon( - Icons.comment, - color: primaryColor, - ), - focusedBorder: UnderlineInputBorder( - borderSide: - BorderSide(color: Colors.grey, width: 1.0)), - )), - ), - - Container( - padding: EdgeInsets.only(top: 20, left: 18), - child: Row( - children: [ - Expanded( - child: Text( - 'Discounts', - style: TextStyle( - fontSize: 16, - color: primaryColor, - fontWeight: FontWeight.bold), - )), - Container( - width: 150.0, - child: DropdownButtonFormField( - items: discountModel.discounts - .map((e) => DropdownMenuItem( - child: Text(e.code), value: e.code)) - .toList(), - onChanged: (selected) => {}, - ), - ), - ], - ), - ), - - Container( - padding: EdgeInsets.only(top: 5, left: 18), - child: Row( - children: [ - Expanded( - child: Text( - 'Payment Method', - style: TextStyle( - fontSize: 16, - color: primaryColor, - fontWeight: FontWeight.bold), - )), - Container( - width: 150.0, - child: DropdownButtonFormField( - items: mainModel.paymentMethods - .map((e) => DropdownMenuItem( - child: Text(e.name), value: e.name)) - .toList(), - onChanged: (selected) => {}, - ), - ), - ], - ), - ), - Container( - padding: EdgeInsets.only(top: 5), - child: Row( - children: [ - Expanded( - child: Padding( - padding: const EdgeInsets.only(left: 18.0), - child: Text( - 'Delivery fee:', - style: TextStyle( - fontSize: 16, - color: primaryColor, - fontWeight: FontWeight.bold), - ), - )), - Switch( - value: isSwitched, - onChanged: (value) { - setState(() { - isSwitched = value; - if (value) { - deliveryfee = '\$5'; - } else { - deliveryfee = '\$0'; - } - print(isSwitched); - }); - }, - activeTrackColor: primaryColor.withOpacity(0.8), - activeColor: primaryColor, - ), - Text( - '(Delivery fee : $deliveryfee)', - style: TextStyle( - color: primaryColor, fontWeight: FontWeight.bold), - ), - ], - ), - ), - SizedBox( - height: 10, - ), - - ExpansionTile( - title: Text( - 'Payment Attachment', - style: TextStyle( - color: primaryColor, fontWeight: FontWeight.bold), - ), - children: [ - widget.invoice != null - ? Padding( - padding: EdgeInsets.only(left: 20), - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - padding: EdgeInsets.only(top: 10), - child: Text( - '${dateFormatter.format(_invoice.receipts[0].date)} ', - style: TextStyle( - color: Colors.black, fontSize: 16), - ), - ), - Container( - padding: EdgeInsets.only(left: 10), - child: MultiImageFile( - enabled: false, - controller: multiImgController, - title: "Receipt", - )), - Container( - padding: EdgeInsets.only(top: 10, left: 10), - child: Text( - '\$${_invoice.receipts[0].amount} ', - style: TextStyle( - color: Colors.black, fontSize: 16), - ), - ), - ], - ), - ) - : Container(), - SizedBox( - height: 25, - ), - ], - ), - ExpansionTile( - title: Text( - 'Box Information', - style: TextStyle( - color: primaryColor, fontWeight: FontWeight.bold), - ), - children: [ - Container( - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: MyDataTable( - headingRowHeight: 40, - columnSpacing: 20, - columns: [ - MyDataColumn( - label: LocalText( - context, - "box.number", - color: Colors.grey, - ), - ), - MyDataColumn( - label: LocalText( - context, - "box.length", - color: Colors.grey, - ), - ), - MyDataColumn( - label: LocalText( - context, - "box.width", - color: Colors.grey, - ), - ), - MyDataColumn( - label: LocalText( - context, - "box.height", - color: Colors.grey, - ), - ), - ], - rows: getBoxRow(context), - ), - ), - ), - mainModel.isOwner() - ? Container( - padding: EdgeInsets.only(top: 20), - child: Align( - alignment: Alignment.bottomRight, - child: FloatingActionButton.extended( - icon: Icon(Icons.add), - label: Text(AppTranslations.of(context) - .text("invoice.add_box")), - backgroundColor: primaryColor, - onPressed: () { - Navigator.of(context) - .push(BottomUpPageRoute(BoxAddition())); - }, - ), - ), - ) - : Container(), - SizedBox(height: 25), - ], - ), - - //Cargo Table - ExpansionTile( - title: Text( - 'Cargo Table', - style: TextStyle( - color: primaryColor, fontWeight: FontWeight.bold), - ), - children: [ - Container( - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: MyDataTable( - headingRowHeight: 40, - columnSpacing: 20, - columns: [ - MyDataColumn( - label: LocalText( - context, - "cargo.type", - color: Colors.grey, - ), - ), - MyDataColumn( - label: LocalText( - context, - "cargo.weight", - color: Colors.grey, - ), - ), - MyDataColumn( - label: LocalText( - context, - "cargo.rate", - color: Colors.grey, - ), - ), - MyDataColumn( - label: LocalText( - context, - "cargo.amount", - color: Colors.grey, - ), - ), - ], - rows: getCargoDataRow(context)), - ), - ), - ]), - ]), - )), - widget.invoice == null - ? Align( - alignment: Alignment.bottomCenter, - child: Center( - child: Container( - width: 250, - child: FlatButton( - child: Text('Create invoice'), - color: primaryColor, - textColor: Colors.white, - onPressed: () { - Navigator.pop(context); - }, - ), - ))) - : mainModel.isCustomer() - ? Container() - : Container( - child: Column( - children: [ - Align( - alignment: Alignment.bottomCenter, - child: Center( - child: Container( - width: 250, - child: FlatButton( - child: Text('Save invoice'), - color: primaryColor, - textColor: Colors.white, - onPressed: () { - Navigator.pop(context); - }, - ), - ))), - ], - )), - widget.invoice == null - ? Container() - : Align( - alignment: Alignment.bottomCenter, - child: Center( - child: Container( - width: 250, - child: FlatButton( - child: Text('Attach Payment Receipt'), - color: primaryColor, - textColor: Colors.white, - onPressed: () { - Navigator.pop(context); - }, - ), - ))) - ], - ), - ), - ), - ); - } - - getCargoTableByBox(BuildContext context) { - return Padding( - padding: const EdgeInsets.all(5.0), - child: Container( - decoration: BoxDecoration( - border: Border.all( - color: Colors.grey[100], - width: 1, - ), - ), - child: Row( - children: [ - Expanded( - child: Container( - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: MyDataTable( - headingRowHeight: 40, - columnSpacing: 20, - columns: [ - MyDataColumn( - label: LocalText( - context, - "cargo.type", - color: Colors.grey, - ), - ), - MyDataColumn( - label: LocalText( - context, - "cargo.weight", - color: Colors.grey, - ), - ), - MyDataColumn( - label: LocalText( - context, - "cargo.rate", - color: Colors.grey, - ), - ), - MyDataColumn( - label: LocalText( - context, - "cargo.amount", - color: Colors.grey, - ), - ), - ], - rows: getCargoDataRow(context)), - ), - ), - ) - ], - ), - ), - ); - } - - List getBoxRow(BuildContext context) { - return _boxes.map((p) { - p.cargoTypes.map((cargo) { - print('cargo => $cargo'); - _cargoTypes.asMap().map((index, _cargo) { - if (_cargo.type == cargo.type) { - setState(() { - _cargoTypes[index].weight += cargo.weight; - }); - print('${_cargoTypes[index].type} =>${_cargoTypes[index]}'); - } - }); - }); - return MyDataRow( - onSelectChanged: (bool selected) {}, - cells: [ - MyDataCell(new Text( - p.boxNumber == null - ? "" - : '${p.shipmentNumber}-${p.receiverNumber} #${p.boxNumber}', - style: textStyle, - )), - MyDataCell(new Text( - p.length == null ? "" : p.length.toString(), - style: textStyle, - )), - MyDataCell(new Text( - p.width == null ? "" : p.width.toString(), - style: textStyle, - )), - MyDataCell(new Text( - p.height == null ? "" : p.height.toString(), - style: textStyle, - )), - ], - ); - }).toList(); - } - - List getCargoDataRow(BuildContext context) { - return _cargoTypes.map((cargo) { - var amt = cargo.weight * cargo.price; - return MyDataRow( - onSelectChanged: (bool selected) {}, - cells: [ - MyDataCell(new Text( - cargo.type, - style: textStyle, - )), - MyDataCell(new Text( - cargo.weight.toString(), - style: textStyle, - )), - MyDataCell(new Text( - '\$${cargo.price}', - style: textStyle, - )), - MyDataCell(new Text( - "\$$amt", - style: textStyle, - )), - ], - ); - }).toList(); - } -} diff --git a/lib/pages/invoice/invoice_info.dart b/lib/pages/invoice/invoice_info.dart new file mode 100644 index 0000000..66acd78 --- /dev/null +++ b/lib/pages/invoice/invoice_info.dart @@ -0,0 +1,220 @@ +import 'package:fcs/domain/constants.dart'; +import 'package:fcs/domain/entities/carton.dart'; +import 'package:fcs/domain/entities/invoice.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/carton/model/carton_model.dart'; +import 'package:fcs/pages/invoice/editor/invoice_carton_table.dart'; +import 'package:fcs/pages/invoice/invoice_table.dart'; +import 'package:fcs/pages/invoice/model/invoice_model.dart'; +import 'package:fcs/pages/invoice/widgets.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/rates/model/shipment_rate_model.dart'; +import 'package:fcs/pages/widgets/display_text.dart'; +import 'package:fcs/pages/widgets/fcs_icons.dart'; +import 'package:fcs/pages/widgets/local_button.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; +import 'package:provider/provider.dart'; + +class InvoiceInfo extends StatefulWidget { + final Invoice invoice; + InvoiceInfo({this.invoice}); + + @override + _InvoiceInfoState createState() => _InvoiceInfoState(); +} + +class _InvoiceInfoState extends State { + var dateFormatter = new DateFormat('dd MMM yyyy'); + + Invoice _invoice; + bool _isLoading = false; + + bool _showCartons = false; + @override + void initState() { + super.initState(); + _invoice = widget.invoice; + _invoice.shipments?.forEach((s) { + s.isSelected = true; + }); + _loadCartons(); + } + + _loadCartons() async { + CartonModel cartonModel = Provider.of(context, listen: false); + List cartons = []; + for (var c in _invoice?.cartons ?? []) { + var _carton = await cartonModel.getCarton(c.id); + _carton.isChecked = true; + cartons.add(_carton); + } + setState(() { + _invoice.cartons = cartons; + }); + } + + @override + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + bool isCanceled = _invoice.status == invoice_cancel_status; + var rateModel = Provider.of(context); + var rate = rateModel.rate; + + final cartonTable = InvoiceCartonTable( + cartons: _invoice.cartons, + rate: rate, + ); + + final invoiceTableBox = InvoiceTable( + invoice: _invoice, + rate: rate, + deliveryFeeSelected: (selected) { + setState(() { + if (selected) { + _invoice.deliveryFee = rate.deliveryFee; + } else { + _invoice.deliveryFee = 0; + } + }); + }, + discountSelected: (discount) { + setState(() { + _invoice.discount = discount; + }); + }, + ); + final toggleButtonsBox = ToggleButtons( + color: Colors.black45, + selectedColor: Colors.black45, + disabledColor: Colors.grey, + selectedBorderColor: primaryColor, + borderColor: Colors.transparent, + fillColor: Colors.transparent, + highlightColor: Colors.black45, + children: [ + Icon(cartonIconData), + ], + onPressed: (int index) { + setState(() { + _showCartons = !_showCartons; + }); + }, + isSelected: [_showCartons], + ); + + final headerBox = Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(dateFormatter.format(_invoice.invoiceDate)), + SizedBox( + height: 5, + ), + Text(_invoice?.userName ?? ""), + Text( + _invoice?.fcsID ?? "", + style: TextStyle(fontSize: 12), + ) + ], + ), + Spacer(), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + toggleButtonsBox, + ], + ), + ], + ); + final paymentMethodBox = DisplayText( + labelTextKey: "invoice.payment_method", + text: _invoice.paymentMethod.name, + ); + + final receiptsBtn = LocalButton( + textKey: "invoice.btn_payment_receipt", + callBack: _cancel, + ); + final cancelBtn = LocalButton( + textKey: "invoice.cancel.btn", + callBack: _cancel, + ); + + return LocalProgress( + inAsyncCall: _isLoading, + child: Scaffold( + appBar: AppBar( + centerTitle: true, + leading: new IconButton( + icon: new Icon(CupertinoIcons.back, color: primaryColor), + onPressed: () => Navigator.of(context).pop(), + ), + backgroundColor: Colors.white, + shadowColor: Colors.transparent, + title: LocalText(context, 'invoice.form.title', + color: primaryColor, fontSize: 20), + ), + body: Padding( + padding: const EdgeInsets.all(8.0), + child: ListView( + children: [ + getInvoiceStatus(context, _invoice), + headerBox, + _showCartons ? cartonTable : Container(), + _showCartons + ? Divider( + color: primaryColor, + thickness: 2, + ) + : Container(), + invoiceTableBox, + SizedBox( + height: 10, + ), + paymentMethodBox, + SizedBox( + height: 10, + ), + isCanceled ? Container() : receiptsBtn, + isCanceled ? Container() : cancelBtn, + ], + ), + ), + ), + ); + } + + _cancel() { + showConfirmDialog(context, "invoice.cancel.confirm", _cancelInvoice); + } + + _cancelInvoice() async { + setState(() { + _isLoading = true; + }); + + try { + InvoiceModel invoiceModel = + Provider.of(context, listen: false); + + await invoiceModel.cancelInvoice(_invoice); + Navigator.pop(context, true); + } catch (e) { + showMsgDialog(context, "Error", e.toString()); + } finally { + setState(() { + _isLoading = false; + }); + } + } +} diff --git a/lib/pages/invoice/invoice_list.dart b/lib/pages/invoice/invoice_list.dart new file mode 100644 index 0000000..14b1012 --- /dev/null +++ b/lib/pages/invoice/invoice_list.dart @@ -0,0 +1,157 @@ +import 'dart:io'; + +import 'package:fcs/helpers/api_helper.dart'; +import 'package:fcs/helpers/firebase_helper.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/invoice/invoice_shipment_list.dart'; +import 'package:fcs/pages/invoice/model/invoice_model.dart'; +import 'package:fcs/pages/invoice/payment_pdf_screen.dart'; +import 'package:fcs/pages/widgets/local_popup_menu_button.dart'; +import 'package:fcs/pages/widgets/local_popupmenu.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import 'invoice_list_row.dart'; + +class InvoiceList extends StatefulWidget { + final bool forCustomer; + + const InvoiceList({Key key, this.forCustomer}) : super(key: key); + @override + _InvoiceListState createState() => _InvoiceListState(); +} + +class _InvoiceListState extends State { + bool _isLoading = false; + var _controller = ScrollController(); + + @override + void initState() { + super.initState(); + _controller.addListener(() async { + if (_controller.position.pixels == _controller.position.maxScrollExtent) { + Provider.of(context, listen: false) + .loadMore(isCustomer: widget.forCustomer); + } + }); + + Provider.of(context, listen: false) + .initData(widget.forCustomer, true, false); + } + + @override + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + var owner = true; + var invoiceModel = Provider.of(context); + + final popupMenu = LocalPopupMenuButton( + popmenus: [ + LocalPopupMenu( + id: 1, + textKey: "invoice.popupmenu.issused", + selected: invoiceModel.selectedIndex == 1), + LocalPopupMenu( + id: 2, + textKey: "invoice.popupmenu.paid", + selected: invoiceModel.selectedIndex == 2), + LocalPopupMenu( + id: 3, + textKey: "invoice.popupmenu.cancel", + selected: invoiceModel.selectedIndex == 3) + ], + popupMenuCallback: (p) => this.setState(() { + invoiceModel.selectedIndex = p.id; + if (p.id == 2) { + Provider.of(context, listen: false) + .initData(widget.forCustomer, false, true); + } else if (p.id == 3) { + Provider.of(context, listen: false) + .initData(widget.forCustomer, true, false); + } else { + Provider.of(context, listen: false) + .initData(widget.forCustomer, true, false); + } + }), + ); + + return LocalProgress( + inAsyncCall: _isLoading, + child: DefaultTabController( + length: 2, + child: Scaffold( + appBar: AppBar( + centerTitle: true, + leading: new IconButton( + icon: new Icon(CupertinoIcons.back), + onPressed: () => Navigator.of(context).pop(), + ), + backgroundColor: primaryColor, + title: LocalText(context, 'invoices.title', + color: Colors.white, fontSize: 20), + actions: [popupMenu], + ), + floatingActionButton: owner + ? FloatingActionButton.extended( + onPressed: () { + _newInvoice(); + }, + icon: Icon(Icons.add), + label: + LocalText(context, 'invoices.add', color: Colors.white), + backgroundColor: primaryColor, + ) + : null, + body: Column( + children: [ + Expanded( + child: RefreshIndicator( + child: ListView.separated( + physics: AlwaysScrollableScrollPhysics(), + controller: _controller, + separatorBuilder: (context, index) => Divider( + color: Colors.black, + ), + scrollDirection: Axis.vertical, + padding: EdgeInsets.only(top: 15), + shrinkWrap: true, + itemCount: invoiceModel.invoices.length, + itemBuilder: (BuildContext context, int index) { + return InvoiceListRow( + key: ValueKey(invoiceModel.invoices[index].id), + invoice: invoiceModel.invoices[index]); + }), + onRefresh: () => invoiceModel.refresh(), + ), + ), + invoiceModel.isLoading + ? Container( + padding: EdgeInsets.all(8), + color: primaryColor, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("Loading...", + style: TextStyle(color: Colors.white)), + ], + ), + ) + : Container(), + ], + )), + ), + ); + } + + _newInvoice() async { + Navigator.of(context) + .push(CupertinoPageRoute(builder: (context) => InvoiceShipmentList())); + } +} diff --git a/lib/pages/invoice/invoice_list_row.dart b/lib/pages/invoice/invoice_list_row.dart index fffaf2c..384f3af 100644 --- a/lib/pages/invoice/invoice_list_row.dart +++ b/lib/pages/invoice/invoice_list_row.dart @@ -1,26 +1,23 @@ import 'dart:async'; import 'dart:io'; -import 'package:fcs/model/main_model.dart'; -import 'package:fcs/pages/invoice/payment_pdf_screen.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/invoice.dart'; -import 'package:fcs/widget/bottom_up_page_route.dart'; +import 'package:fcs/domain/constants.dart'; +import 'package:fcs/domain/entities/invoice.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/invoice/invoice_info.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:intl/intl.dart'; import 'package:path_provider/path_provider.dart'; -import 'package:provider/provider.dart'; -import '../../fcs/common/pages/util.dart'; -import 'invoice_editor.dart'; import 'payment_page.dart'; +import 'payment_pdf_screen.dart'; class InvoiceListRow extends StatefulWidget { final Invoice invoice; - const InvoiceListRow({this.invoice}); + InvoiceListRow({Key key, this.invoice}) : super(key: key); @override _InvoiceListRowState createState() => _InvoiceListRowState(); @@ -70,7 +67,7 @@ class _InvoiceListRowState extends State { @override Widget build(BuildContext context) { - var owner = Provider.of(context).isOwner(); + var owner = true; return Container( padding: EdgeInsets.only(left: 15, right: 15), child: Row( @@ -81,12 +78,14 @@ class _InvoiceListRowState extends State { child: InkWell( onTap: () { owner - ? Navigator.of(context).push( - BottomUpPageRoute(InvoiceEditor(invoice: _invoice))) - : Navigator.of(context) - .push(BottomUpPageRoute(PaymentPDFScreen( - path: pdfPath, - ))); + ? Navigator.of(context).push(CupertinoPageRoute( + builder: (context) => PaymentPDFScreen( + url: _invoice.invoiceURL, + ))) + : Navigator.of(context).push(CupertinoPageRoute( + builder: (context) => PaymentPDFScreen( + url: _invoice.invoiceURL, + ))); }, child: new Row( children: [ @@ -132,7 +131,7 @@ class _InvoiceListRowState extends State { // padding: const EdgeInsets.all(0), // child: getStatus(_invoice.status), // ), - _invoice.status == "Pending" + _invoice.status == invoice_issued_status ? Padding( padding: const EdgeInsets.only(left: 10.0), child: InkWell( @@ -150,8 +149,9 @@ class _InvoiceListRowState extends State { ], ), onPressed: () { - Navigator.of(context).push( - BottomUpPageRoute(PaymentPage(invoice: _invoice))); + Navigator.of(context).push(CupertinoPageRoute( + builder: (context) => + PaymentPage(invoice: _invoice))); }, )), ) @@ -181,18 +181,20 @@ class _InvoiceListRowState extends State { CupertinoActionSheetAction( child: Row( children: [ - Icon(Icons.file_download), Padding( padding: const EdgeInsets.only(left: 8.0), child: Text( - 'Download', + 'See detail', style: TextStyle(fontSize: 16, color: Colors.black), ), ), ], ), - onPressed: () { + onPressed: () async { + //to go invoice info page Navigator.pop(context); + Navigator.of(context).push(CupertinoPageRoute( + builder: (context) => InvoiceInfo(invoice: _invoice))); }, ) ], diff --git a/lib/pages/invoice/invoice_shipment_list.dart b/lib/pages/invoice/invoice_shipment_list.dart new file mode 100644 index 0000000..44b9726 --- /dev/null +++ b/lib/pages/invoice/invoice_shipment_list.dart @@ -0,0 +1,81 @@ +import 'package:fcs/domain/entities/fcs_shipment.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/fcs_shipment/model/fcs_shipment_model.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import 'invoice_customer_list.dart'; +import 'invoice_shipment_list_row.dart'; + +class InvoiceShipmentList extends StatefulWidget { + @override + _InvoiceShipmentListState createState() => _InvoiceShipmentListState(); +} + +class _InvoiceShipmentListState extends State { + bool _isLoading = false; + List _fcsShipments = []; + @override + void initState() { + super.initState(); + _load(); + } + + _load() async { + FcsShipmentModel fcsShipmentModel = + Provider.of(context, listen: false); + var fcsShipments = await fcsShipmentModel.getInvoiceFcsShipments(); + setState(() { + _fcsShipments = fcsShipments; + }); + } + + @override + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return LocalProgress( + inAsyncCall: _isLoading, + child: DefaultTabController( + length: 3, + child: Scaffold( + appBar: AppBar( + centerTitle: true, + leading: new IconButton( + icon: new Icon(CupertinoIcons.back), + onPressed: () => Navigator.of(context).pop(), + ), + backgroundColor: primaryColor, + title: LocalText(context, "invoice.shipment.title", + fontSize: 18, color: Colors.white), + ), + body: new ListView.separated( + separatorBuilder: (context, index) => Divider( + color: Colors.black, + ), + scrollDirection: Axis.vertical, + padding: EdgeInsets.only(top: 15), + shrinkWrap: true, + itemCount: _fcsShipments.length, + itemBuilder: (BuildContext context, int index) { + return InvoiceShipmentListRow( + fcsShipment: _fcsShipments[index], + onSelect: (f) { + Navigator.of(context).push(CupertinoPageRoute( + builder: (context) => InvoiceCustomerList( + fcsShipment: f, + ))); + }, + ); + }), + ), + ), + ); + } +} diff --git a/lib/pages/shipment_list_row.dart b/lib/pages/invoice/invoice_shipment_list_row.dart similarity index 66% rename from lib/pages/shipment_list_row.dart rename to lib/pages/invoice/invoice_shipment_list_row.dart index 88d1a7d..eb66ce6 100644 --- a/lib/pages/shipment_list_row.dart +++ b/lib/pages/invoice/invoice_shipment_list_row.dart @@ -1,32 +1,34 @@ -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/shipment.dart'; -import 'package:fcs/widget/bottom_up_page_route.dart'; +import 'package:fcs/domain/entities/fcs_shipment.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_icons/flutter_icons.dart'; import 'package:intl/intl.dart'; -import 'shipment_editor.dart'; -import '../fcs/common/pages/util.dart'; +import '../main/util.dart'; +import 'invoice_customer_list.dart'; -class ShipmentListRow extends StatefulWidget { - final Shipment shipment; - const ShipmentListRow({this.shipment}); +typedef OnSelect(FcsShipment fcsShipment); + +class InvoiceShipmentListRow extends StatefulWidget { + final OnSelect onSelect; + final FcsShipment fcsShipment; + const InvoiceShipmentListRow({this.fcsShipment, this.onSelect}); @override - _ShipmentListRowState createState() => _ShipmentListRowState(); + _InvoiceShipmentListRowState createState() => _InvoiceShipmentListRowState(); } -class _ShipmentListRowState extends State { - var dateFormatter = new DateFormat('dd MMM yyyy'); +class _InvoiceShipmentListRowState extends State { final double dotSize = 15.0; - Shipment _shipment = new Shipment(); + final dateFormatter = new DateFormat('dd MMM yyyy'); + FcsShipment _fcsShipment = new FcsShipment(); @override void initState() { super.initState(); - - if (widget.shipment != null) { - _shipment = widget.shipment; + if (widget.fcsShipment != null) { + _fcsShipment = widget.fcsShipment; } } @@ -36,8 +38,7 @@ class _ShipmentListRowState extends State { padding: EdgeInsets.only(left: 15, right: 15), child: InkWell( onTap: () { - Navigator.of(context) - .push(BottomUpPageRoute(ShipmentEditor(shipment: _shipment))); + if (widget.onSelect != null) widget.onSelect(widget.fcsShipment); }, child: Row( children: [ @@ -61,9 +62,9 @@ class _ShipmentListRowState extends State { Padding( padding: const EdgeInsets.only(left: 8.0), child: new Text( - _shipment.shipmentNumber == null + _fcsShipment.shipmentNumber == null ? '' - : _shipment.shipmentNumber, + : _fcsShipment.shipmentNumber, style: new TextStyle( fontSize: 15.0, color: Colors.black), ), @@ -71,7 +72,7 @@ class _ShipmentListRowState extends State { Padding( padding: const EdgeInsets.only(left: 10.0, top: 10), child: new Text( - dateFormatter.format(_shipment.shipDate), + dateFormatter.format(_fcsShipment.cutoffDate), style: new TextStyle( fontSize: 15.0, color: Colors.grey), ), @@ -85,7 +86,7 @@ class _ShipmentListRowState extends State { ), Padding( padding: const EdgeInsets.all(0), - child: getStatus(_shipment.status), + child: getStatus(_fcsShipment.status), ), ], ), diff --git a/lib/pages/invoice/invoice_table.dart b/lib/pages/invoice/invoice_table.dart new file mode 100644 index 0000000..a1a5ee3 --- /dev/null +++ b/lib/pages/invoice/invoice_table.dart @@ -0,0 +1,377 @@ +import 'package:fcs/domain/entities/cargo_type.dart'; +import 'package:fcs/domain/entities/discount.dart'; +import 'package:fcs/domain/entities/invoice.dart'; +import 'package:fcs/domain/entities/rate.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/discount/discount_list.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; + +typedef OnDiscountSelected(Discount discount); +typedef OnDeliveryFeeSelected(bool selected); +typedef OnRemove(InvoiceTableRow row); +final formatter = new NumberFormat("#,###.00"); + +enum InvoiceDataType { + CargoDataType, + DiscountDataType, + CustomFeeDataType, + HandlingFeeType, + DeliveryFeeType, +} + +class InvoiceTableRow { + final dynamic data; + final String id; + final InvoiceDataType invoiceDataType; + final String desc; + final String rate; + final String amount; + + InvoiceTableRow( + {this.id, + this.data, + this.invoiceDataType, + this.desc, + this.rate, + this.amount}); +} + +class InvoiceTable extends StatelessWidget { + final Invoice invoice; + final Rate rate; + final OnDiscountSelected discountSelected; + final OnDeliveryFeeSelected deliveryFeeSelected; + final OnRemove onRemove; + + const InvoiceTable( + {Key key, + this.invoice, + this.discountSelected, + this.deliveryFeeSelected, + this.onRemove, + this.rate}) + : super(key: key); + @override + Widget build(BuildContext context) { + return Column(children: getRows(context)); + } + + List getTableRows() { + List tableRows = []; + // add cargo types + List _cargoTypes = invoice.getCargoTypes(rate) ?? []; + _cargoTypes.forEach((c) { + tableRows.add(InvoiceTableRow( + invoiceDataType: InvoiceDataType.CargoDataType, + desc: c.name, + rate: + "${c.calWeight.toStringAsFixed(2)} x ${c.calRate.toStringAsFixed(2)}", + amount: "${c.calAmount.toStringAsFixed(2)}")); + }); + invoice.shipments.where((ss) => (ss.isSelected ?? false)).forEach((s) { + tableRows.add(InvoiceTableRow( + data: s, + invoiceDataType: InvoiceDataType.HandlingFeeType, + desc: "Handling fee\n${s.shipmentNumber}", + rate: "", + amount: "${s.handlingFee.toStringAsFixed(2)}")); + }); + // // add custom fee + invoice.customDuties.forEach((c) { + tableRows.add(InvoiceTableRow( + data: c, + invoiceDataType: InvoiceDataType.CustomFeeDataType, + desc: "${c.productType} custom fee", + rate: "", + amount: "${c.fee.toStringAsFixed(2)}")); + }); + // // add delivery fee + tableRows.add(InvoiceTableRow( + data: invoice.deliveryFee == null || invoice.deliveryFee == 0 + ? null + : invoice.deliveryFee, + invoiceDataType: InvoiceDataType.DeliveryFeeType, + desc: "Delivery fee", + rate: "", + amount: "${invoice?.deliveryFee?.toStringAsFixed(2) ?? '0'}")); + + // // add discounts + if (invoice.discount != null) { + tableRows.add(InvoiceTableRow( + data: invoice.discount, + invoiceDataType: InvoiceDataType.DiscountDataType, + desc: "Discount\n${invoice?.discount?.code ?? ""}", + rate: "", + amount: "(${invoice?.discount?.amount?.toStringAsFixed(2) ?? ''})")); + } + + return tableRows; + } + + getRows(BuildContext context) { + List tableRows = getTableRows(); + + List dataRow = tableRows.map((r) { + return Container( + decoration: BoxDecoration( + border: Border(bottom: BorderSide(color: Colors.grey))), + padding: const EdgeInsets.only( + left: 5.0, right: 5.0, top: 10.0, bottom: 10.0), + child: Row( + children: [ + Expanded( + flex: 2, + child: Row( + children: [ + Flexible(child: Text('${r.desc}')), + SizedBox( + width: 5, + ), + r.data == null || onRemove == null + ? Container() + : InkWell( + onTap: () => onRemove(r), + child: Icon( + Icons.remove_circle, + color: Colors.black45, + ), + ) + ], + )), + Expanded( + flex: 1, + child: Text( + '${r.rate}', + textAlign: TextAlign.end, + style: TextStyle(fontSize: 12), + )), + Expanded( + flex: 1, + child: Text('\$ ${r.amount}', + textAlign: TextAlign.end, + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.bold, + ))) + ], + ), + ); + }).toList(); + dataRow.insert( + 0, + Container( + padding: const EdgeInsets.only( + left: 5.0, right: 5.0, top: 15.0, bottom: 15.0), + decoration: BoxDecoration( + border: Border(bottom: BorderSide(color: Colors.grey))), + child: Row( + children: [ + Expanded( + flex: 2, + child: Text(getLocalString(context, 'invoice.box.desc'), + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.bold, + color: Colors.grey))), + Expanded( + flex: 2, + child: Text( + getLocalString(context, 'invoice.weight') + + ' x ' + + getLocalString(context, 'invoice.rate'), + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.bold, + color: Colors.grey))), + Expanded( + child: Text(getLocalString(context, 'invoice.amount'), + textAlign: TextAlign.end, + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.bold, + color: Colors.grey))) + ], + ), + )); + + dataRow.insert( + dataRow.length, + Container( + padding: const EdgeInsets.only( + left: 5.0, right: 5.0, top: 10.0, bottom: 10.0), + child: Row( + children: [ + Expanded( + flex: 1, + child: Container( + alignment: Alignment.centerRight, + child: LocalText( + context, + 'invoice.total', + color: Colors.black, + ), + ), + ), + SizedBox(width: 20), + Text( + '\$ ${invoice.getNetAmount(rate).toStringAsFixed(2)}', + style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold), + textAlign: TextAlign.end, + ) + ], + ), + )); + + // dataRow.insert( + // dataRow.length, + // Container( + // padding: const EdgeInsets.only(left: 5.0, right: 5.0, top: 20.0), + // child: Row( + // children: [ + // Expanded( + // flex: 1, + // child: Container( + // alignment: Alignment.centerRight, + // child: LocalText( + // context, + // 'invoice.handling_fee', + // color: Colors.black, + // ), + // ), + // ), + // SizedBox(width: 50), + // Expanded( + // child: Text( + // '\$ ${invoice.getHandlingFee().toStringAsFixed(2) ?? ""}', + // textAlign: TextAlign.end, + // style: TextStyle( + // fontSize: 15, + // fontWeight: FontWeight.bold, + // ))) + // ], + // ), + // )); + + // dataRow.insert( + // dataRow.length, + // Container( + // padding: const EdgeInsets.only( + // left: 5.0, right: 5.0, top: 10.0, bottom: 10.0), + // child: Row( + // children: [ + // Expanded( + // flex: 1, + // child: Container( + // alignment: Alignment.centerRight, + // child: LocalText( + // context, + // 'invoice.delivery_fee', + // color: Colors.black, + // ), + // )), + // Switch( + // value: (invoice.deliveryFee ?? 0) > 0, + // onChanged: (value) { + // if (deliveryFeeSelected != null) { + // deliveryFeeSelected(value); + // } + // }, + // activeTrackColor: primaryColor.withOpacity(0.8), + // activeColor: primaryColor, + // ), + // Expanded( + // child: + // Text('\$ ${invoice.getDeliveryFee().toStringAsFixed(2)}', + // textAlign: TextAlign.end, + // style: TextStyle( + // fontSize: 15, + // fontWeight: FontWeight.bold, + // ))) + // ], + // ), + // )); + + // dataRow.insert( + // dataRow.length, + // Container( + // child: Row( + // children: [ + // Expanded(child: Text('')), + // Expanded( + // flex: 2, + // child: Divider( + // thickness: 3, + // )), + // ], + // ))); + + // dataRow.insert( + // dataRow.length, + // Container( + // padding: const EdgeInsets.only( + // left: 5.0, right: 5.0, top: 10.0, bottom: 10.0), + // child: Row( + // children: [ + // Expanded( + // flex: 2, + // child: Center( + // child: LocalText( + // context, + // 'invoice.net_amount', + // color: Colors.black, + // fontSize: 15, + // fontWeight: FontWeight.bold, + // ), + // ), + // ), + // Expanded( + // child: Text( + // '\$ ${invoice.getNetAmount(rate).toStringAsFixed(2)}', + // textAlign: TextAlign.end, + // style: TextStyle( + // fontSize: 18, + // fontWeight: FontWeight.bold, + // color: primaryColor))) + // ], + // ), + // )); + + // dataRow.insert( + // dataRow.length, + // Container( + // padding: const EdgeInsets.only( + // left: 5.0, right: 5.0, top: 10.0, bottom: 10.0), + // child: Row( + // children: [ + // Expanded( + // flex: 2, + // child: Center( + // child: LocalText( + // context, + // 'invoice.balance', + // color: Colors.black, + // fontSize: 15, + // fontWeight: FontWeight.bold, + // ), + // ), + // ), + // Expanded( + // child: Text( + // '\$ ${invoice.getTotalBalance(rate).toStringAsFixed(2)}', + // textAlign: TextAlign.end, + // style: TextStyle( + // fontSize: 18, + // fontWeight: FontWeight.bold, + // color: primaryColor))) + // ], + // ), + // )); + + return dataRow; + } +} diff --git a/lib/pages/invoice/model/invoice_model.dart b/lib/pages/invoice/model/invoice_model.dart new file mode 100644 index 0000000..2a6b007 --- /dev/null +++ b/lib/pages/invoice/model/invoice_model.dart @@ -0,0 +1,153 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; + +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:fcs/config.dart'; +import 'package:fcs/data/services/services.dart'; +import 'package:fcs/domain/constants.dart'; +import 'package:fcs/domain/entities/invoice.dart'; +import 'package:fcs/helpers/api_helper.dart'; +import 'package:fcs/helpers/firebase_helper.dart'; +import 'package:fcs/helpers/paginator.dart'; +import 'package:fcs/pages/main/model/base_model.dart'; +import 'package:logging/logging.dart'; +import 'package:path_provider/path_provider.dart'; + +class InvoiceModel extends BaseModel { + final log = Logger('InvoiceModel'); + + StreamSubscription listener; + + List _invoices = []; + + List get invoices => + _selectedIndex == 1 ? _invoices : List.from(_paginator.values); + + Paginator _paginator; + + bool endOfPaidInvoices = false; + bool isLoading = false; + int _selectedIndex = 1; + + set selectedIndex(int index) { + _selectedIndex = index; + notifyListeners(); + } + + get selectedIndex => _selectedIndex; + + @override + void privilegeChanged() { + super.privilegeChanged(); + } + + initData(bool forCustomer, bool isCanceled, bool isPaid) { + _loadInvoices(forCustomer); + + if (_paginator != null) _paginator.close(); + _paginator = _getPaginator(forCustomer, isCanceled, isPaid); + _paginator.load(onFinished: () { + notifyListeners(); + }); + } + + Future _loadInvoices(bool forCustomer) async { + if (user == null) return; + if (!forCustomer && !user.hasInvoices()) return; + String path = "/$invoices_collection"; + if (listener != null) listener.cancel(); + _invoices = []; + + try { + var q = Firestore.instance + .collection("$path") + .where("status", isEqualTo: invoice_issued_status) + .where("is_deleted", isEqualTo: false); + + if (forCustomer) { + q = q.where("user_id", isEqualTo: user.id); + } + + listener = q.snapshots().listen((QuerySnapshot snapshot) { + _invoices.clear(); + _invoices = snapshot.documents.map((documentSnapshot) { + var s = Invoice.fromMap( + documentSnapshot.data, documentSnapshot.documentID); + return s; + }).toList(); + notifyListeners(); + }); + } catch (e) { + log.warning("Error!! $e"); + } + } + + Paginator _getPaginator(bool isCustomer, bool isCanceled, bool isPaid) { + if (!isCustomer) { + if (user == null || !(user.hasInvoices())) throw "No privilege"; + } + var pageQuery = Firestore.instance + .collection("/$invoices_collection") + .where("is_deleted", isEqualTo: false); + if (isCustomer) { + pageQuery = pageQuery.where("user_id", isEqualTo: user.id); + } + if (isCanceled) { + pageQuery = pageQuery.where("status", isEqualTo: invoice_cancel_status); + } + if (isPaid) { + pageQuery = pageQuery.where("status", isEqualTo: invoice_paid_status); + } + + pageQuery = pageQuery.orderBy("created_at", descending: true); + var paginator = new Paginator(pageQuery, rowPerLoad: 20, toObj: (data, id) { + return Invoice.fromMap(data, id); + }); + return paginator; + } + + Future loadMore({bool isCustomer}) async { + if (_paginator.ended || _selectedIndex == 1) + return; // when paid menu is not selected return + isLoading = true; + notifyListeners(); + await _paginator.load(onFinished: () { + isLoading = false; + notifyListeners(); + }); + } + + Future refresh({bool isCustomer}) async { + if (_selectedIndex == 1) return; // when paid menu is not selected return + await _paginator.refresh(onFinished: () { + notifyListeners(); + }); + } + + void initUser(user) { + super.initUser(user); + } + + logout() async { + if (_paginator != null) _paginator.close(); + if (listener != null) await listener.cancel(); + _invoices = []; + } + + Future createInvoice(Invoice invoice) async { + File file = await downloadPDF("invoice", invoice.toMap()); + String url = await uploadStorage("pdfs", file); + print("uploaded url: $url"); + invoice.invoiceURL = url; + return Services.instance.invoiceService.createInvoice(invoice); + } + + Future updateInvoice(Invoice invoice) { + return Services.instance.invoiceService.updateInvoice(invoice); + } + + Future cancelInvoice(Invoice invoice) { + return Services.instance.invoiceService.cancelInvoice(invoice); + } +} diff --git a/lib/pages/invoice/package_addition.dart b/lib/pages/invoice/package_addition.dart deleted file mode 100644 index 72055d4..0000000 --- a/lib/pages/invoice/package_addition.dart +++ /dev/null @@ -1,107 +0,0 @@ -import 'package:fcs/model_fcs/package_model.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/package.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:fcs/widget/progress.dart'; -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; - -class PackageAddition extends StatefulWidget { - final Package package; - PackageAddition({this.package}); - - @override - _PackageAdditionState createState() => _PackageAdditionState(); -} - -class _PackageAdditionState extends State { - Package _package = new Package(); - bool _isLoading = false; - - @override - void initState() { - super.initState(); - if (widget.package != null) { - _package = widget.package; - } - } - - @override - void dispose() { - super.dispose(); - } - - @override - Widget build(BuildContext context) { - var packageModel = Provider.of(context); - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - centerTitle: true, - leading: new IconButton( - icon: new Icon(Icons.close), - onPressed: () => Navigator.of(context).pop(), - ), - backgroundColor: primaryColor, - title: Text(AppTranslations.of(context).text("package.edit.title")), - ), - body: Card( - child: Column( - children: [ - Expanded( - child: Padding( - padding: const EdgeInsets.all(10.0), - child: ListView(children: [ - DropdownButtonFormField( - decoration: InputDecoration( - fillColor: Colors.white, - labelText: 'Package Number', - icon: Icon(Icons.pages)), - items: packageModel.completed - .map((e) => DropdownMenuItem( - child: Text(e.packageNumber), value: e)) - .toList(), - onChanged: (map) => {}, - ), - ]), - )), - widget.package == null - ? Align( - alignment: Alignment.bottomCenter, - child: Center( - child: Container( - width: 250, - child: FlatButton( - child: Text('Add package'), - color: primaryColor, - textColor: Colors.white, - onPressed: () { - Navigator.pop(context); - }, - ), - ))) - : Align( - alignment: Alignment.bottomCenter, - child: Center( - child: Container( - width: 250, - child: FlatButton( - child: Text('Save package'), - color: primaryColor, - textColor: Colors.white, - onPressed: () { - Navigator.pop(context); - }, - ), - ))), - SizedBox( - height: 30, - ) - ], - ), - ), - ), - ); - } -} diff --git a/lib/pages/invoice/package_info.dart b/lib/pages/invoice/package_info.dart deleted file mode 100644 index 239af8f..0000000 --- a/lib/pages/invoice/package_info.dart +++ /dev/null @@ -1,143 +0,0 @@ -import 'package:fcs/model/main_model.dart'; -import 'package:fcs/model/pickup_model.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/package.dart'; -import 'package:fcs/widget/label_widgets.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:fcs/widget/progress.dart'; -import 'package:flutter/material.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; - -class PackageInfo extends StatefulWidget { - final Package package; - PackageInfo({this.package}); - - @override - _PackageInfoState createState() => _PackageInfoState(); -} - -class _PackageInfoState extends State { - var dateFormatter = new DateFormat('dd MMM yyyy'); - Package _package; - bool _isLoading = false; - - @override - void initState() { - super.initState(); - if (widget.package != null) { - _package = widget.package; - } - } - - @override - void dispose() { - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - centerTitle: true, - leading: new IconButton( - icon: new Icon(Icons.close), - onPressed: () => Navigator.of(context).pop(), - ), - backgroundColor: primaryColor, - title: Text(AppTranslations.of(context).text("package.edit.title")), - ), - body: Card( - child: Column( - children: [ - Expanded( - child: Padding( - padding: const EdgeInsets.all(10.0), - child: ListView(children: [ - Container( - padding: EdgeInsets.only(top: 10), - child: Row( - children: [ - Icon( - Icons.calendar_today, - ), - Padding( - padding: const EdgeInsets.only(right: 8.0, left: 15), - child: labeledText( - context, - dateFormatter.format(_package.arrivedDate), - "package.arrival.date"), - ), - ], - ), - ), - Container( - padding: EdgeInsets.only(top: 10), - child: Row( - children: [ - Icon(Icons.pages), - Padding( - padding: const EdgeInsets.only(right: 8.0, left: 15), - child: labeledText(context, _package.packageNumber, - "package.number"), - ), - ], - ), - ), - Container( - padding: EdgeInsets.only(top: 10), - child: Row( - children: [ - Icon(FontAwesomeIcons.weightHanging), - Padding( - padding: const EdgeInsets.only(right: 8.0, left: 15), - child: labeledText( - context, - "${_package.weight.toString()} lb", - "package.weight"), - ), - ], - ), - ), - Container( - padding: EdgeInsets.only(top: 10), - child: Row( - children: [ - Icon(FontAwesomeIcons.tag), - Padding( - padding: const EdgeInsets.only(right: 8.0, left: 15), - child: labeledText(context, _package.rate.toString(), - "package.rate"), - ), - ], - ), - ), - Container( - padding: EdgeInsets.only(top: 10), - child: Row( - children: [ - Icon(FontAwesomeIcons.moneyBill), - Padding( - padding: const EdgeInsets.only(right: 8.0, left: 15), - child: labeledText( - context, - _package.price == null - ? "" - : "\$ " + _package.price.toString(), - "package.amount"), - ), - ], - ), - ) - ]), - )), - ], - ), - ), - ), - ); - } -} diff --git a/lib/pages/invoice/payment_page.dart b/lib/pages/invoice/payment_page.dart index f95e7dc..52ff087 100644 --- a/lib/pages/invoice/payment_page.dart +++ b/lib/pages/invoice/payment_page.dart @@ -1,20 +1,20 @@ -import 'package:fcs/model/main_model.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/invoice.dart'; -import 'package:fcs/vo/package.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:fcs/widget/multi_img_controller.dart'; -import 'package:fcs/widget/multi_img_file.dart'; -import 'package:fcs/widget/my_data_table.dart'; -import 'package:fcs/widget/number_cell.dart'; -import 'package:fcs/widget/progress.dart'; +import 'dart:io'; + +import 'package:fcs/domain/entities/invoice.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/localization/app_translations.dart'; +import 'package:fcs/pages/invoice/payment_page_edit.dart'; +import 'package:fcs/pages/widgets/image_file_picker.dart'; +import 'package:fcs/pages/widgets/input_text.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/local_title.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:fcs/pages/widgets/show_img.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_icons/flutter_icons.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:image_picker/image_picker.dart'; import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; class PaymentPage extends StatefulWidget { final Invoice invoice; @@ -25,28 +25,19 @@ class PaymentPage extends StatefulWidget { } class _PaymentPageState extends State { - TextEditingController _addressEditingController = new TextEditingController(); - TextEditingController _fromTimeEditingController = - new TextEditingController(); - TextEditingController _toTimeEditingController = new TextEditingController(); - TextEditingController _noOfPackageEditingController = - new TextEditingController(); - TextEditingController _weightEditingController = new TextEditingController(); - MultiImgController multiImgController = MultiImgController(); + TextEditingController _amountController = new TextEditingController(); var dateFormatter = new DateFormat('dd MMM yyyy'); Invoice _invoice = new Invoice(); bool _isLoading = false; - List _receipts = [ - "assets/photos/amazon_ins.png", - ]; + bool isNew; + File _file; @override void initState() { if (widget.invoice != null) { _invoice = widget.invoice; - multiImgController.setImageUrls = _receipts; } super.initState(); } @@ -60,146 +51,251 @@ class _PaymentPageState extends State { @override Widget build(BuildContext context) { - // var images = isNew ? [] : _images; + final amountBox = InputText( + labelTextKey: 'pm.amount', + controller: _amountController, + iconData: FontAwesomeIcons.moneyBill); + + final receiptFileBox = Row(children: [ + LocalText(context, 'pm.attachment', fontSize: 16, color: Colors.grey), + _file != null + ? InkWell( + onTap: () async { + await _dialog(context); + }, + child: Chip( + label: Icon(Icons.image, color: primaryColor), + ), + ) + : IconButton( + icon: Icon(Icons.attachment, color: primaryColor), + onPressed: () async { + await _dialog(context); + }), + ]); + + final payBox = Row(mainAxisAlignment: MainAxisAlignment.center, children: [ + Container( + height: 50, + width: 100, + alignment: Alignment.center, + child: Text(AppTranslations.of(context).text("pm.pay"), + textAlign: TextAlign.center, + style: TextStyle(color: Colors.white, fontSize: 14)), + color: primaryColor) + ]); + return LocalProgress( inAsyncCall: _isLoading, child: Scaffold( appBar: AppBar( centerTitle: true, leading: new IconButton( - icon: new Icon(Icons.close), + icon: new Icon(CupertinoIcons.back), onPressed: () => Navigator.of(context).pop(), ), backgroundColor: primaryColor, - title: Text(AppTranslations.of(context).text("payment.title")), + title: Text(AppTranslations.of(context).text("pm_.title")), ), - body: Card( - child: Column( - children: [ - Padding( - padding: const EdgeInsets.all(15.0), - child: Container( - child: Row( - children: [ - LocalText(context, 'total.amount', - color: Colors.black, fontSize: 16), - Text( - ' \$ ${_invoice.amount}', - style: TextStyle( - color: primaryColor, - fontSize: 16, - fontWeight: FontWeight.bold), - ) - ], - )), - ), - Padding( - padding: const EdgeInsets.all(15.0), - child: Container( - child: Row( - children: [ - LocalText(context, 'remaining_balance', - color: Colors.black, fontSize: 16), - Text( - ' \$ ${_invoice.amount - _invoice.receipts[0].amount}', - style: TextStyle( - color: primaryColor, - fontSize: 16, - fontWeight: FontWeight.bold), - ) - ], - )), - ), - Expanded( - child: ListView( - children: [ - ExpansionTile( - title: LocalText(context, 'payment.attachment', - color: Colors.black, fontSize: 16), - children: [ - Padding( - padding: EdgeInsets.only(left: 20), - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - padding: EdgeInsets.only(top: 8), - child: Text( - '${dateFormatter.format(_invoice.receipts[0].date)} ', - style: TextStyle( - color: Colors.black, fontSize: 16), - ), - ), - Container( - padding: EdgeInsets.only(left: 10), - child: MultiImageFile( - enabled: true, - controller: multiImgController, - title: "Receipt File", - )), - ], - ), - ), - SizedBox( - height: 25, - ), - ], - ), - ExpansionTile( - title: LocalText(context, 'payment.receipt', - color: Colors.black, fontSize: 16), - children: [ - Container( - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: MyDataTable( - headingRowHeight: 40, - columnSpacing: 20, - columns: [ - MyDataColumn( - label: LocalText( - context, - "payment.date", - color: Colors.grey, - ), - ), - MyDataColumn( - label: LocalText( - context, - "payment.amount", - color: Colors.grey, - ), - ), - ], - rows: getPackageRow(context), - ), - ), - ), - SizedBox(height: 25), - ], - ), - ], - ), - ), - ], - ), + body: ListView( + padding: const EdgeInsets.all(10.0), + children: [ + amountBox, + SizedBox(height: 10), + receiptFileBox, + SizedBox(height: 10), + payBox, + Divider(), + SizedBox(height: 10), + LocalTitle(textKey: "pm.receipt"), + Column( + children: getCustomFeeRows(context), + ), + SizedBox(height: 25), + ], ), ), ); } - List getPackageRow(BuildContext context) { - return _invoice.receipts.map((r) { - return MyDataRow( - onSelectChanged: (bool selected) {}, - cells: [ - MyDataCell( - new Text(dateFormatter.format(r.date), style: textStyle), + getCustomFeeRows(BuildContext context) { + List dataRow = []; + + dataRow = [].asMap().entries.map((receipt) { + var r = receipt.value; + var k = receipt.key + 1; + return Container( + height: 50, + decoration: BoxDecoration( + border: Border(bottom: BorderSide(color: Colors.grey))), + padding: + const EdgeInsets.only(left: 5.0, right: 5.0, top: 5.0, bottom: 5.0), + child: InkWell( + onTap: () { + Navigator.of(context).push(CupertinoPageRoute( + builder: (context) => PaymentPageEdit(receipt: r))); + }, + child: Row( + children: [ + Expanded(flex: 2, child: Text('${r.date}')), + Expanded( + flex: 2, + child: InkWell( + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => ShowImage( + // localImage: attachment.value.fileUrl, + localImage: 'assets/logo.jpg', + url: null, + fileName: 'image'))); + }, + child: Chip( + label: Icon(Icons.image, color: primaryColor), + ), + ), + ), + Expanded(flex: 1, child: Center(child: Text('pending'))), + Expanded(flex: 1, child: Center(child: Text('\$ ${r.amount}'))), + ], ), - MyDataCell(NumberCell(r.amount)) - ], + ), ); }).toList(); + + dataRow.insert( + 0, + Container( + decoration: BoxDecoration( + border: Border(bottom: BorderSide(color: Colors.grey))), + padding: const EdgeInsets.only( + left: 5.0, right: 5.0, top: 10.0, bottom: 15.0), + child: Row( + children: [ + Expanded( + flex: 2, + child: Text('Date', style: TextStyle(color: Colors.grey))), + Expanded( + flex: 2, + child: Text('File', + textAlign: TextAlign.center, + style: TextStyle(color: Colors.grey))), + Expanded( + flex: 1, + child: Text('Status', + textAlign: TextAlign.center, + style: TextStyle(color: Colors.grey))), + Expanded( + flex: 1, + child: Text('Fee', + textAlign: TextAlign.center, + style: TextStyle(color: Colors.grey))), + ], + ), + )); + + dataRow.insert( + dataRow.length, + Container( + padding: const EdgeInsets.only( + left: 5.0, right: 5.0, top: 15.0, bottom: 15.0), + child: Row( + children: [ + Expanded( + flex: 2, + child: Center( + child: LocalText( + context, + 'pm.remaining_balance', + color: Colors.black, + fontWeight: FontWeight.bold, + ), + ), + ), + Expanded( + flex: 2, + child: Container(), + ), + Expanded( + flex: 1, + child: Center( + child: Text('\$ 300', + textAlign: TextAlign.center, + style: TextStyle( + fontWeight: FontWeight.bold, fontSize: 16.0)))), + ], + ), + )); + return dataRow; + } + + Future _dialog(BuildContext context) { + return showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + content: Container( + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Column( + mainAxisSize: MainAxisSize.min, + children: [ + IconButton( + icon: Icon( + FontAwesomeIcons.camera, + size: 30, + color: primaryColor, + ), + onPressed: () async { + // Navigator.pop(context); + // cameraPress(); + var selectedFile = + await pickImage(ImageSource.camera); + setState(() { + _file = selectedFile; + }); + Navigator.pop(context); + }), + Text("Camera") + ], + ), + Column( + mainAxisSize: MainAxisSize.min, + children: [ + IconButton( + icon: Icon( + Icons.photo_library, + size: 30, + color: primaryColor, + ), + onPressed: () async { + // Navigator.pop(context); + // photoPress(); + var selectedFile = + await pickImage(ImageSource.gallery); + setState(() { + _file = selectedFile; + }); + Navigator.pop(context); + }), + Text("Gallery") + ], + ), + ], + ), + ), + ), + ); + }, + ); + } + + pickImage(ImageSource source) async { + var tempImage = await ImagePicker.pickImage(source: source); + return tempImage; } } diff --git a/lib/pages/invoice/payment_page_edit.dart b/lib/pages/invoice/payment_page_edit.dart new file mode 100644 index 0000000..f751dc3 --- /dev/null +++ b/lib/pages/invoice/payment_page_edit.dart @@ -0,0 +1,222 @@ +import 'dart:io'; + +import 'package:fcs/domain/entities/invoice.dart'; +import 'package:fcs/domain/entities/receipt.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/localization/app_translations.dart'; +import 'package:fcs/pages/main/model/main_model.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/widgets/display_text.dart'; +import 'package:fcs/pages/widgets/image_file_picker.dart'; +import 'package:fcs/pages/widgets/input_text.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/local_title.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:fcs/pages/widgets/show_img.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:intl/intl.dart'; +import 'package:provider/provider.dart'; + +class PaymentPageEdit extends StatefulWidget { + final Receipt receipt; + PaymentPageEdit({this.receipt}); + + @override + _PaymentPageEditState createState() => _PaymentPageEditState(); +} + +class _PaymentPageEditState extends State { + TextEditingController _amountController = new TextEditingController(); + var dateFormatter = new DateFormat('dd MMM yyyy'); + + Receipt _receipt = new Receipt(); + bool _isLoading = false; + File _file; + + bool isNew; + + @override + void initState() { + if (widget.receipt != null) { + _receipt = widget.receipt; + } + super.initState(); + } + + @override + void dispose() { + super.dispose(); + } + + final DateFormat dateFormat = DateFormat("d MMM yyyy"); + + @override + Widget build(BuildContext context) { + var mainModel = Provider.of(context, listen: false); + bool customer = mainModel.isCustomer(); + + final amountBox = DisplayText( + labelTextKey: 'pm.amount', + iconData: FontAwesomeIcons.moneyBill, + text: _receipt.amount.toString()); + + final dateBox = DisplayText( + labelTextKey: 'pm.date', + iconData: Icons.date_range, + text: _receipt.date); + + final statusBox = DisplayText( + labelTextKey: 'pm.status', + iconData: Icons.av_timer, + text: _receipt.status); + + final receiptFileBox = Row(children: [ + LocalText(context, 'pm.attachment', fontSize: 16, color: Colors.grey), + IconButton( + icon: Icon(Icons.attachment, color: primaryColor), onPressed: () {}) + ]); + + final comfirmBox = + fcsButton(context, getLocalString(context, 'pm.btn_confirm')); + + final cancelBox = + fcsButton(context, getLocalString(context, 'pm.btn_cancel')); + + final fileBox = Container( + // padding: EdgeInsets.only(top: 20, left: 20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + LocalText( + context, + "pm.attachment", + fontSize: 16, + color: labelColor, + ), + Container( + padding: EdgeInsets.only(top: 15), + child: Stack( + children: [ + Container( + width: 200, + height: 200, + padding: const EdgeInsets.all(2.0), + decoration: BoxDecoration( + color: Colors.grey[300], + border: Border.all( + color: primaryColor, + width: 1.0, + ), + ), + child: _file == null + ? checkImage(context) + : enableUpload(context), + ), + customer + ? Positioned( + bottom: -8, + right: -10, + child: IconButton( + color: primaryColor, + icon: CircleAvatar( + backgroundColor: primaryColor, + radius: 20, + child: Icon( + FontAwesomeIcons.camera, + size: 20, + color: Colors.white, + ), + ), + onPressed: () => + modelBottomSheet(context, onFile: (file) { + setState(() { + _file = file; + }); + }), + )) + : Container() + ], + ), + ), + ], + ), + ); + + return LocalProgress( + inAsyncCall: _isLoading, + child: Scaffold( + appBar: AppBar( + centerTitle: true, + leading: new IconButton( + icon: new Icon(CupertinoIcons.back), + onPressed: () => Navigator.of(context).pop(), + ), + backgroundColor: primaryColor, + title: Text(AppTranslations.of(context).text("pm_.title")), + ), + body: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + dateBox, + SizedBox(height: 10), + amountBox, + SizedBox(height: 10), + statusBox, + SizedBox(height: 10), + fileBox, + SizedBox(height: 5), + Spacer(), + customer ? Container() : comfirmBox, + SizedBox(height: 5), + customer ? cancelBox : Container(), + SizedBox(height: 5), + ], + ), + ), + ), + ); + } + + Widget checkImage(BuildContext context) { + if (widget.receipt == null) { + return initialImage(); + } else { + Widget _widget; + if (widget.receipt.fileUrl == null) { + _widget = initialImage(); + } else { + _widget = InkWell( + child: Image.asset(widget.receipt.fileUrl, fit: BoxFit.cover), + onTap: () {}, + ); + } + return _widget; + } + } + + Widget initialImage() { + return Center( + child: Icon( + Icons.insert_photo, + size: 45, + color: labelColor, + ), + ); + } + + Widget enableUpload(BuildContext context) { + return InkWell( + child: Image.file(_file, fit: BoxFit.cover), + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + ShowImage(imageFile: _file, url: null, fileName: 'image'))); + }, + ); + } +} diff --git a/lib/pages/invoice/payment_pdf_screen.dart b/lib/pages/invoice/payment_pdf_screen.dart index f3dbc4b..7f6ddf9 100644 --- a/lib/pages/invoice/payment_pdf_screen.dart +++ b/lib/pages/invoice/payment_pdf_screen.dart @@ -1,15 +1,20 @@ import 'dart:async'; +import 'dart:io'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/widget/local_text.dart'; +import 'package:fcs/helpers/cache_mgr.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/progress.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_pdfview/flutter_pdfview.dart'; +import 'package:share/share.dart'; class PaymentPDFScreen extends StatefulWidget { - final String path; + final String url; - PaymentPDFScreen({Key key, this.path}) : super(key: key); + PaymentPDFScreen({Key key, this.url}) : super(key: key); _PaymentPDFScreenState createState() => _PaymentPDFScreenState(); } @@ -22,93 +27,100 @@ class _PaymentPDFScreenState extends State int currentPage = 0; bool isReady = false; String errorMessage = ''; + bool _isLoading = true; + + void initState() { + super.initState(); + download(); + } + + File file; + Future download() async { + try { + File f = await PdfCacheMgr.pdfs.getSingleFile(widget.url); + setState(() { + file = f; + }); + } catch (e) { + showMsgDialog(context, "Error", e.toString()); + } finally { + setState(() { + _isLoading = false; + }); + } + } @override Widget build(BuildContext context) { - print(' widget.path => ${widget.path}'); - print(' pages => ${pages}'); - return Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - title: Text("Invoice File"), - actions: [ - IconButton( - icon: Icon(Icons.share), - onPressed: () {}, + return LocalProgress( + inAsyncCall: _isLoading, + child: Scaffold( + appBar: AppBar( + centerTitle: true, + backgroundColor: Colors.white, + shadowColor: Colors.transparent, + title: LocalText(context, 'invoice.pdf', + color: Colors.white, fontSize: 20), + leading: new IconButton( + icon: new Icon(CupertinoIcons.back, color: primaryColor), + onPressed: () => Navigator.of(context).pop(), ), - ], + actions: [ + IconButton( + icon: Icon( + Icons.share, + color: primaryColor, + ), + onPressed: _share, + ), + ], + ), + body: Stack( + children: [ + _isLoading + ? Container() + : PDFView( + filePath: file?.path ?? "", + enableSwipe: true, + swipeHorizontal: true, + autoSpacing: false, + pageFling: true, + pageSnap: true, + defaultPage: currentPage, + fitPolicy: FitPolicy.BOTH, + preventLinkNavigation: + false, // if set to true the link is handled in flutter + onRender: (_pages) { + print(('pages => $pages')); + setState(() { + pages = _pages; + isReady = true; + }); + }, + onViewCreated: (PDFViewController pdfViewController) { + _controller.complete(pdfViewController); + }, + onLinkHandler: (String uri) { + print('goto uri: $uri'); + }, + onPageChanged: (int page, int total) { + print('page change: $page/$total'); + setState(() { + currentPage = page; + }); + }, + ), + ], + ), ), - body: Stack( - children: [ - PDFView( - filePath: widget.path, - enableSwipe: true, - swipeHorizontal: true, - autoSpacing: false, - pageFling: true, - pageSnap: true, - defaultPage: currentPage, - fitPolicy: FitPolicy.BOTH, - preventLinkNavigation: - false, // if set to true the link is handled in flutter - onRender: (_pages) { - print(('pages => $pages')); - setState(() { - pages = _pages; - isReady = true; - }); - }, - // onError: (error) { - // setState(() { - // errorMessage = error.toString(); - // }); - // print(error.toString()); - // }, - // onPageError: (page, error) { - // setState(() { - // errorMessage = '$page: ${error.toString()}'; - // }); - // print('$page: ${error.toString()}'); - // }, - onViewCreated: (PDFViewController pdfViewController) { - _controller.complete(pdfViewController); - }, - onLinkHandler: (String uri) { - print('goto uri: $uri'); - }, - onPageChanged: (int page, int total) { - print('page change: $page/$total'); - setState(() { - currentPage = page; - }); - }, - ), - // errorMessage.isEmpty - // ? !isReady - // ? Center( - // child: CircularProgressIndicator(), - // ) - // : Container() - // : Center( - // child: Text(errorMessage), - // ) - ], - ), - // floatingActionButton: FutureBuilder( - // future: _controller.future, - // builder: (context, AsyncSnapshot snapshot) { - // if (snapshot.hasData) { - // return FloatingActionButton.extended( - // label: Text("Go to ${pages ~/ 2}"), - // onPressed: () async { - // await snapshot.data.setPage(pages ~/ 2); - // }, - // ); - // } - - // return Container(); - // }, - // ), ); } + + _share() async { + final RenderBox box = context.findRenderObject(); + await Share.shareFiles([file.path], + mimeTypes: ["application/pdf"], + subject: "Invoice", + sharePositionOrigin: box.localToGlobal(Offset.zero) & box.size); + } } diff --git a/lib/pages/invoice/widgets.dart b/lib/pages/invoice/widgets.dart new file mode 100644 index 0000000..d631d46 --- /dev/null +++ b/lib/pages/invoice/widgets.dart @@ -0,0 +1,24 @@ +import 'package:fcs/domain/entities/invoice.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:flutter/material.dart'; + +Widget getInvoiceStatus(BuildContext context, Invoice invoice) { + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + LocalText( + context, + '', + text: invoice.invoiceNumber ?? "", + color: primaryColor, + fontSize: 18, + fontWeight: FontWeight.bold, + ), + Padding( + padding: const EdgeInsets.only(left: 8.0), + child: Chip(label: Text(invoice.status ?? "")), + ), + ], + ); +} diff --git a/lib/pages/log_list.dart b/lib/pages/log_list.dart deleted file mode 100644 index 3f1847a..0000000 --- a/lib/pages/log_list.dart +++ /dev/null @@ -1,97 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/log_model.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:fcs/widget/progress.dart'; - -import '../fcs/common/helpers/theme.dart'; - -class LogList extends StatefulWidget { - @override - _LogListState createState() => _LogListState(); -} - -class _LogListState extends State { - final double dotSize = 15.0; - var dateFormatter = new DateFormat('dd MMM yyyy - hh:mm:ss a'); - bool _isLoading = false; - - @override - Widget build(BuildContext context) { - LogModel logModel = Provider.of(context); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - title: LocalText( - context, - 'log.title', - color: Colors.white, - fontSize: 20, - ), - ), - body: new ListView.separated( - separatorBuilder: (context, index) => Divider( - color: Colors.black, - ), - scrollDirection: Axis.vertical, - padding: EdgeInsets.only(left: 15, right: 15, top: 15), - shrinkWrap: true, - itemCount: logModel.logs.length, - itemBuilder: (BuildContext context, int index) { - return Stack( - children: [ - InkWell( - onTap: () {}, - child: Row( - children: [ - Expanded( - child: new Padding( - padding: const EdgeInsets.symmetric(vertical: 0.0), - child: new Row( - children: [ - new Padding( - padding: new EdgeInsets.symmetric( - horizontal: 32.0 - dotSize / 2), - child: Icon( - Icons.message, - color: primaryColor, - ), - ), - new Expanded( - child: new Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - new Text( - logModel.logs[index].deviceName, - style: new TextStyle( - fontSize: 15.0, - color: Colors.black), - ), - new Text( - "Last login at : ${logModel.logs[index].activeTime == null ? "" : dateFormatter.format(logModel.logs[index].activeTime)}", - style: new TextStyle( - fontSize: 13.0, color: Colors.grey), - ), - ], - ), - ), - ], - ), - ), - ), - ], - ), - ), - ], - ); - }), - ), - ); - } -} diff --git a/lib/pages/login_page.dart b/lib/pages/login_page.dart deleted file mode 100644 index 260f11f..0000000 --- a/lib/pages/login_page.dart +++ /dev/null @@ -1,757 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/language_model.dart'; -import 'package:fcs/model/main_model.dart'; -import 'package:fcs/model/user_model.dart'; -import 'package:fcs/pages/reset_password.dart'; -import 'package:fcs/widget/bubble_indication_painter.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:fcs/widget/progress.dart'; - -import '../fcs/common/helpers/theme.dart' as Theme; -import 'forget_password.dart'; -import 'sms_page.dart'; -import '../fcs/common/pages/util.dart'; - -class LoginPage extends StatefulWidget { - LoginPage({Key key}) : super(key: key); - - @override - _LoginPageState createState() => new _LoginPageState(); -} - -class _LoginPageState extends State - with SingleTickerProviderStateMixin { - final GlobalKey _scaffoldKey = new GlobalKey(); - - final FocusNode myFocusNodeEmailLogin = FocusNode(); - final FocusNode myFocusNodePasswordLogin = FocusNode(); - - final FocusNode myFocusNodePassword = FocusNode(); - final FocusNode myFocusNodeEmail = FocusNode(); - final FocusNode myFocusNodeName = FocusNode(); - - TextEditingController loginPhoneController = new TextEditingController(); - TextEditingController loginPasswordController = new TextEditingController(); - - bool _obscureTextLogin = true; - bool _obscureTextSignup = true; - bool _obscureTextSignupConfirm = true; - - TextEditingController signupPhoneNumberController = - new TextEditingController(); - TextEditingController signupNameController = new TextEditingController(); - TextEditingController signupPasswordController = new TextEditingController(); - TextEditingController signupConfirmPasswordController = - new TextEditingController(); - - PageController _pageController; - - Color left = Colors.black; - Color right = Colors.white; - final loginFormKey = GlobalKey(); - final signupFormKey = GlobalKey(); - - bool _isLoading = false; - - @override - Widget build(BuildContext context) { - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - key: _scaffoldKey, - appBar: AppBar( - backgroundColor: Colors.white, - iconTheme: IconThemeData( - color: Colors.grey, - ), - elevation: 0, - centerTitle: true, - title: new Image( - height: 30, - fit: BoxFit.scaleDown, - image: new AssetImage('assets/img/logo.png')), - ), - body: SingleChildScrollView( - child: Container( - width: MediaQuery.of(context).size.width, - height: MediaQuery.of(context).size.height >= 775.0 - ? MediaQuery.of(context).size.height - : 580.0, - child: Column( - mainAxisSize: MainAxisSize.max, - children: [ - Padding( - padding: EdgeInsets.only(top: 50.0), - child: _buildMenuBar(context), - ), - Expanded( - flex: 2, - child: PageView( - controller: _pageController, - onPageChanged: (i) { - if (i == 0) { - setState(() { - right = Colors.white; - left = Colors.black; - }); - } else if (i == 1) { - setState(() { - right = Colors.black; - left = Colors.white; - }); - } - }, - children: [ - new ConstrainedBox( - constraints: const BoxConstraints.expand(), - child: _buildLogin(context), - ), - new ConstrainedBox( - constraints: const BoxConstraints.expand(), - child: _buildSignUp(context), - ), - ], - ), - ), - ], - ), - ), - ), - ), - ); - } - - @override - void dispose() { - myFocusNodePassword.dispose(); - myFocusNodeEmail.dispose(); - myFocusNodeName.dispose(); - _pageController?.dispose(); - super.dispose(); - } - - @override - void initState() { - super.initState(); - - // SystemChrome.setPreferredOrientations([ - // DeviceOrientation.portraitUp, - // DeviceOrientation.portraitDown, - // ]); - - _pageController = PageController(); - loginPhoneController.text = "09"; - signupPhoneNumberController.text = "09"; - } - - Widget _buildMenuBar(BuildContext context) { - return Container( - width: 300.0, - height: 40.0, - decoration: BoxDecoration( - color: Color(0x552B2B2B), - borderRadius: BorderRadius.all(Radius.circular(25.0)), - ), - child: CustomPaint( - painter: TabIndicationPainter(pageController: _pageController), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - Expanded( - child: FlatButton( - onPressed: _onSignInButtonPress, - child: Text( - AppTranslations.of(context).text("login.title"), - style: Provider.of(context).isEng - ? TextStyle( - color: left, - fontSize: 14.0, - fontFamily: "WorkSansSemiBold") - : TextStyle( - color: left, - fontSize: 15.0, - fontFamily: "MyanmarUnicode"), - ), - ), - ), - //Container(height: 33.0, width: 1.0, color: Colors.white), - Expanded( - child: FlatButton( - onPressed: _onSignUpButtonPress, - child: Text( - AppTranslations.of(context).text("sing.title"), - style: Provider.of(context).isEng - ? TextStyle( - color: right, - fontSize: 14.0, - fontFamily: "WorkSansSemiBold") - : TextStyle( - color: right, - fontSize: 15.0, - fontFamily: "MyanmarUnicode"), - ), - ), - ), - ], - ), - ), - ); - } - - Widget _buildLogin(BuildContext context) { - return Container( - child: ListView( - children: [ - Column( - children: [ - Form( - key: loginFormKey, - child: Card( - elevation: 2.0, - color: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - child: Container( - width: 300.0, - child: Column( - children: [ - Padding( - padding: EdgeInsets.only(left: 25.0, right: 25.0), - child: TextFormField( - focusNode: myFocusNodeEmailLogin, - controller: loginPhoneController, - keyboardType: TextInputType.phone, - style: TextStyle( - fontFamily: "WorkSansSemiBold", - fontSize: 16.0, - color: Colors.black), - decoration: InputDecoration( - border: InputBorder.none, - icon: Icon( - FontAwesomeIcons.phone, - color: Colors.black, - size: 22.0, - ), - labelText: AppTranslations.of(context) - .text("login.phone"), - labelStyle: - Provider.of(context).isEng - ? TextStyle( - fontFamily: "WorkSansSemiBold", - color: Colors.grey) - : TextStyle( - fontFamily: "MyanmarUnicode", - color: Colors.grey), - ), - validator: _validatePhone, - ), - ), - Container( - width: 250.0, - height: 1.0, - color: Colors.grey[400], - ), - Padding( - padding: EdgeInsets.only(left: 25.0, right: 25.0), - child: TextFormField( - focusNode: myFocusNodePasswordLogin, - controller: loginPasswordController, - obscureText: _obscureTextLogin, - style: TextStyle( - fontFamily: "WorkSansSemiBold", - fontSize: 16.0, - color: Colors.black), - decoration: InputDecoration( - border: InputBorder.none, - icon: Icon( - FontAwesomeIcons.lock, - size: 22.0, - color: Colors.black, - ), - labelText: AppTranslations.of(context) - .text("login.password"), - labelStyle: - Provider.of(context).isEng - ? TextStyle( - fontFamily: "WorkSansSemiBold", - color: Colors.grey) - : TextStyle( - fontFamily: "MyanmarUnicode", - color: Colors.grey), - suffixIcon: GestureDetector( - onTap: _toggleLogin, - child: Icon( - _obscureTextLogin - ? FontAwesomeIcons.eye - : FontAwesomeIcons.eyeSlash, - size: 15.0, - color: Colors.black, - ), - ), - ), - validator: _validatePassword, - ), - ), - ], - ), - ), - ), - ), - Container( - decoration: new BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(5.0)), - color: Theme.primaryColor, - ), - child: MaterialButton( - child: Padding( - padding: const EdgeInsets.symmetric( - vertical: 10.0, horizontal: 42.0), - child: Text( - AppTranslations.of(context).text("login.btn"), - style: Provider.of(context).isEng - ? TextStyle( - color: Colors.white, - fontSize: 18.0, - fontWeight: FontWeight.bold, - fontFamily: "WorkSansBold") - : TextStyle( - color: Colors.white, - fontSize: 16.0, - fontWeight: FontWeight.bold, - fontFamily: "MyanmarUnicode"), - ), - ), - onPressed: () => _login(context)), - ), - ], - ), - Padding( - padding: EdgeInsets.only(top: 10.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - decoration: BoxDecoration( - gradient: new LinearGradient( - colors: [ - Colors.white10, - Colors.white, - ], - begin: const FractionalOffset(0.0, 0.0), - end: const FractionalOffset(1.0, 1.0), - stops: [0.0, 1.0], - tileMode: TileMode.clamp), - ), - width: 100.0, - height: 1.0, - ), - Container( - decoration: BoxDecoration( - gradient: new LinearGradient( - colors: [ - Colors.white, - Colors.white10, - ], - begin: const FractionalOffset(0.0, 0.0), - end: const FractionalOffset(1.0, 1.0), - stops: [0.0, 1.0], - tileMode: TileMode.clamp), - ), - width: 100.0, - height: 1.0, - ), - ], - ), - ), - Padding( - padding: EdgeInsets.only(top: 10.0), - child: FlatButton( - onPressed: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => ForgetPassword( - phoneNumber: loginPhoneController.text, - ))); - }, - child: Text( - AppTranslations.of(context).text("login.forgot_password"), - style: Provider.of(context).isEng - ? TextStyle( - decoration: TextDecoration.underline, - color: Colors.black, - fontSize: 16.0, - fontFamily: "WorkSansMedium") - : TextStyle( - decoration: TextDecoration.underline, - color: Colors.black, - fontSize: 16.0, - fontFamily: "MyanmarUnicode"), - )), - ), - ], - ), - ); - } - - Widget _buildSignUp(BuildContext context) { - return Container( - child: ListView( - children: [ - Column( - children: [ - Form( - key: signupFormKey, - child: Card( - elevation: 2.0, - color: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - child: Container( - width: 300.0, - child: Column( - children: [ - Padding( - padding: EdgeInsets.only(left: 25.0, right: 25.0), - child: TextFormField( - focusNode: myFocusNodeName, - controller: signupNameController, - keyboardType: TextInputType.text, - textCapitalization: TextCapitalization.words, - style: TextStyle( - fontFamily: "WorkSansSemiBold", - fontSize: 16.0, - color: Colors.black), - decoration: InputDecoration( - border: InputBorder.none, - icon: Icon( - FontAwesomeIcons.user, - color: Colors.black, - ), - labelText: AppTranslations.of(context) - .text("login.name"), - labelStyle: - Provider.of(context).isEng - ? TextStyle( - fontFamily: "WorkSansSemiBold", - color: Colors.grey) - : TextStyle( - fontFamily: "MyanmarUnicode", - color: Colors.grey), - hintStyle: TextStyle( - fontFamily: "WorkSansSemiBold", - fontSize: 16.0), - ), - validator: (value) { - if (value.isEmpty) { - return AppTranslations.of(context) - .text("login.name_empty"); - } - return null; - }), - ), - Container( - width: 250.0, - height: 1.0, - color: Colors.grey[400], - ), - Padding( - padding: EdgeInsets.only(left: 25.0, right: 25.0), - child: TextFormField( - focusNode: myFocusNodeEmail, - controller: signupPhoneNumberController, - keyboardType: TextInputType.phone, - style: TextStyle( - fontFamily: "WorkSansSemiBold", - fontSize: 16.0, - color: Colors.black), - decoration: InputDecoration( - border: InputBorder.none, - icon: Icon( - FontAwesomeIcons.phone, - color: Colors.black, - ), - labelText: AppTranslations.of(context) - .text("login.phone"), - labelStyle: - Provider.of(context).isEng - ? TextStyle( - fontFamily: "WorkSansSemiBold", - color: Colors.grey) - : TextStyle( - fontFamily: "MyanmarUnicode", - color: Colors.grey), - ), - validator: _validatePhone), - ), - Container( - width: 250.0, - height: 1.0, - color: Colors.grey[400], - ), - Padding( - padding: EdgeInsets.only(left: 25.0, right: 25.0), - child: TextFormField( - focusNode: myFocusNodePassword, - controller: signupPasswordController, - obscureText: _obscureTextSignup, - style: TextStyle( - fontFamily: "WorkSansSemiBold", - fontSize: 16.0, - color: Colors.black), - decoration: InputDecoration( - border: InputBorder.none, - icon: Icon( - FontAwesomeIcons.lock, - color: Colors.black, - ), - labelText: AppTranslations.of(context) - .text("login.password"), - labelStyle: - Provider.of(context).isEng - ? TextStyle( - fontFamily: "WorkSansSemiBold", - color: Colors.grey) - : TextStyle( - fontFamily: "MyanmarUnicode", - color: Colors.grey), - suffixIcon: GestureDetector( - onTap: _toggleSignup, - child: Icon( - _obscureTextSignup - ? FontAwesomeIcons.eye - : FontAwesomeIcons.eyeSlash, - size: 15.0, - color: Colors.black, - ), - ), - ), - validator: _validatePassword, - ), - ), - Container( - width: 250.0, - height: 1.0, - color: Colors.grey[400], - ), - Padding( - padding: EdgeInsets.only(left: 25.0, right: 25.0), - child: TextFormField( - controller: signupConfirmPasswordController, - obscureText: _obscureTextSignupConfirm, - style: TextStyle( - fontFamily: "WorkSansSemiBold", - fontSize: 16.0, - color: Colors.black), - decoration: InputDecoration( - border: InputBorder.none, - icon: Icon( - FontAwesomeIcons.lock, - color: Colors.black, - ), - labelText: AppTranslations.of(context) - .text("login.confirm_password"), - labelStyle: - Provider.of(context).isEng - ? TextStyle( - fontFamily: "WorkSansSemiBold", - color: Colors.grey) - : TextStyle( - fontFamily: "MyanmarUnicode", - color: Colors.grey), - suffixIcon: GestureDetector( - onTap: _toggleSignupConfirm, - child: Icon( - _obscureTextSignupConfirm - ? FontAwesomeIcons.eye - : FontAwesomeIcons.eyeSlash, - size: 15.0, - color: Colors.black, - ), - ), - ), - validator: _validatePassword, - ), - ), - ], - ), - ), - ), - ), - Container( - // margin: EdgeInsets.only(top: 320.0), - decoration: new BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(5.0)), - color: Theme.primaryColor, - ), - child: MaterialButton( - highlightColor: Colors.transparent, - splashColor: Theme.LoginColors.loginGradientEnd, - //shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(5.0))), - child: Padding( - padding: const EdgeInsets.symmetric( - vertical: 10.0, horizontal: 42.0), - child: Text( - AppTranslations.of(context).text("sing.up"), - style: Provider.of(context).isEng - ? TextStyle( - color: Colors.white, - fontSize: 18.0, - fontFamily: "WorkSansBold") - : TextStyle( - color: Colors.white, - fontSize: 16.0, - fontFamily: "MyanmarUnicode"), - ), - ), - onPressed: () => _signup(context)), - ), - ], - ), - ], - ), - ); - } - - void _onSignInButtonPress() { - _pageController.animateToPage(0, - duration: Duration(milliseconds: 500), curve: Curves.decelerate); - } - - void _onSignUpButtonPress() { - _pageController?.animateToPage(1, - duration: Duration(milliseconds: 500), curve: Curves.decelerate); - } - - void _toggleLogin() { - setState(() { - _obscureTextLogin = !_obscureTextLogin; - }); - } - - void _toggleSignup() { - setState(() { - _obscureTextSignup = !_obscureTextSignup; - }); - } - - void _toggleSignupConfirm() { - setState(() { - _obscureTextSignupConfirm = !_obscureTextSignupConfirm; - }); - } - - void _signup(BuildContext context) async { - if (!signupFormKey.currentState.validate()) { - return; - } - setState(() { - _isLoading = true; - }); - - MainModel authModel = Provider.of(context); - - var name = signupNameController.text; - var password = signupPasswordController.text; - var confirmPassword = signupConfirmPasswordController.text; - var phoneNumber = signupPhoneNumberController.text; - try { - await authModel.signup(name, password, confirmPassword, phoneNumber); - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => - SmsCodePage(id: phoneNumber, password: password), - ), - ); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - Future.delayed(Duration(seconds: 1), () { - if (mounted) { - setState(() { - _isLoading = false; - }); - } - }); - } - } - - void _login(BuildContext context) async { - if (!loginFormKey.currentState.validate()) { - return; - } - - setState(() { - _isLoading = true; - }); - MainModel mainModel = Provider.of(context); - var phoneNumber = loginPhoneController.text; - var password = loginPasswordController.text; - - try { - await mainModel.login(phoneNumber, password); - Navigator.pushNamedAndRemoveUntil(context, "/", (r) => false); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } - - Future.delayed(Duration(seconds: 1), () { - if (mounted) { - setState(() { - _isLoading = false; - }); - } - }); - } - - String _validatePassword(value) { - if (value.isEmpty) { - return AppTranslations.of(context).text("login.password_empty"); - } - if (value.length < 6) { - return AppTranslations.of(context).text("login.password_size"); - } - return null; - } - - String _validatePhone(value) { - if (value.isEmpty) { - return AppTranslations.of(context).text("login.phone_empty"); - } - if (!value.startsWith("09") && !value.startsWith("959")) { - return 'Only "09 or 959".'; - } - return null; - } - - Future _forgetPassword() async { - var phoneNumber = loginPhoneController.text; - if (phoneNumber.isEmpty) { - showMsgDialog(context, "Error", "Please input phone number"); - return; - } - setState(() { - _isLoading = true; - }); - try { - UserModel userModel = Provider.of(context); - await userModel.forgetPassword(phoneNumber); - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => ResetPasswordPage(phoneNumber))); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - setState(() { - _isLoading = false; - }); - } - } -} diff --git a/lib/pages/main/home_page.dart b/lib/pages/main/home_page.dart new file mode 100644 index 0000000..13529e7 --- /dev/null +++ b/lib/pages/main/home_page.dart @@ -0,0 +1,546 @@ +import 'dart:async'; +import 'dart:io'; + +import 'package:fcs/data/services/services.dart'; +import 'package:fcs/domain/entities/package.dart'; +import 'package:fcs/domain/entities/user.dart'; +import 'package:fcs/helpers/shared_pref.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/localization/transalation.dart'; +import 'package:fcs/pages/carton/carton_list.dart'; +import 'package:fcs/pages/chat/message_detail.dart'; +import 'package:fcs/pages/chat/model/message_model.dart'; +import 'package:fcs/pages/customer/customer_list.dart'; +import 'package:fcs/pages/customer/model/customer_model.dart'; +import 'package:fcs/pages/delivery/delivery_list.dart'; +import 'package:fcs/pages/discount/discount_list.dart'; +import 'package:fcs/pages/faq/faq_list_page.dart'; +import 'package:fcs/pages/fcs_shipment/fcs_shipment_list.dart'; +import 'package:fcs/pages/invoice/invoice_list.dart'; +import 'package:fcs/pages/main/model/language_model.dart'; +import 'package:fcs/pages/main/model/main_model.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/package/model/package_model.dart'; +import 'package:fcs/pages/package/package_info.dart'; +import 'package:fcs/pages/package/package_list.dart'; +import 'package:fcs/pages/processing/processing_list.dart'; +import 'package:fcs/pages/receiving/receiving_list.dart'; +import 'package:fcs/pages/shipment/shipment_list.dart'; +import 'package:fcs/pages/staff/staff_list.dart'; +import 'package:fcs/pages/widgets/badge.dart'; +import 'package:fcs/pages/widgets/bottom_widgets.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:fcs/pages/widgets/right_left_page_rout.dart'; +import 'package:fcs/pages/widgets/task_button.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_icons/flutter_icons.dart'; +import 'package:flutter_local_notifications/flutter_local_notifications.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:logging/logging.dart'; +import 'package:provider/provider.dart'; + +import '../profile/profile_page.dart'; +import '../signin/signin_page.dart'; +import '../widgets/banner.dart'; +import '../widgets/offline_redirect.dart'; + +final msgLog = Logger('backgroundMessageHandler'); + +class HomePage extends StatefulWidget { + @override + _HomePageState createState() => _HomePageState(); +} + +class _HomePageState extends State { + final log = Logger('_HomePageState'); + bool login = false; + bool _isLoading = false; + List isSelected = [true, false]; + static FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin = + FlutterLocalNotificationsPlugin(); + TextEditingController _searchCtl = TextEditingController(); + List isFcs = [false]; + + @override + void initState() { + super.initState(); + MainModel mainModel = Provider.of(context, listen: false); + + Services.instance.messagingService.init( + (message) { + print("Message from FCM:$message"); + _showNotification(message); + }, + onLaunch: (m) => _showNotiContent(m), + onResume: (m) => _showNotiContent(m), + onSetupComplete: (token) { + mainModel.setMessaginToken = token; + }); + _initLocalNotifications(); + _loadStaffMode(mainModel.isCustomer()); + } + + _loadStaffMode(bool isCustomer) async { + bool staffMode = await SharedPref.getStaffMode(); + setState(() { + if (isCustomer) { + isFcs[0] = false; + } else { + isFcs[0] = staffMode ?? false; + } + }); + } + + String notiUserID, notiUserName; + _showNotiContent(Map message) { + try { + Map map = Map.from(message["data"]); + notiUserID = map['user_id']; + notiUserName = map['user_name']; + _startNotiTimer(); + print("Notification:$map"); + } catch (e) { + print("Error:$e"); + } + } + + _startNotiTimer() async { + var _duration = new Duration(milliseconds: 500); + new Timer.periodic(_duration, (t) => displayNoti(t)); + } + + void displayNoti(Timer timer) async { + MainModel mainModel = Provider.of(context, listen: false); + if (mainModel.isLogin()) { + timer.cancel(); + bool isCustomer = mainModel.isCustomer(); + String receiverID = isCustomer ? mainModel.user.id : notiUserID; + String receiverName = isCustomer ? mainModel.user.name : notiUserName; + MessageModel messageModel = + Provider.of(context, listen: false); + messageModel.initQuery(receiverID); + User user = mainModel.user; + if (!isCustomer) { + CustomerModel customerModel = + Provider.of(context, listen: false); + user = await customerModel.getUser(receiverID); + } + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => MessageDetail( + messageModel: messageModel, + receiverID: receiverID, + receiverName: receiverName, + ))).then((value) { + if (user.userUnseenCount > 0) { + messageModel.seenMessages(user.id, true); + } + }); + if (user.userUnseenCount > 0) { + messageModel.seenMessages(user.id, true); + } + } + } + + _initLocalNotifications() { + var initializationSettingsAndroid = + new AndroidInitializationSettings('@mipmap/ic_launcher'); + var initializationSettingsIOS = new IOSInitializationSettings(); + var initializationSettings = new InitializationSettings( + initializationSettingsAndroid, initializationSettingsIOS); + _flutterLocalNotificationsPlugin.initialize(initializationSettings); + } + + static Future _showNotification(Map message) async { + var pushTitle; + var pushText; + var action; + + if (Platform.isAndroid) { + var nodeData = message['notification']; + pushTitle = nodeData['title']; + pushText = nodeData['body']; + action = nodeData['action']; + } else { + pushTitle = message['title']; + pushText = message['body']; + action = message['action']; + } + print("AppPushs params pushTitle : $pushTitle"); + print("AppPushs params pushText : $pushText"); + print("AppPushs params pushAction : $action"); + + // @formatter:off + var platformChannelSpecificsAndroid = new AndroidNotificationDetails( + 'your channel id', 'your channel name', 'your channel description', + playSound: true, + enableVibration: true, + importance: Importance.Max, + priority: Priority.High); + // @formatter:on + var platformChannelSpecificsIos = + new IOSNotificationDetails(presentSound: true); + var platformChannelSpecifics = new NotificationDetails( + platformChannelSpecificsAndroid, platformChannelSpecificsIos); + + new Future.delayed(Duration.zero, () { + _flutterLocalNotificationsPlugin.show( + 0, + pushTitle, + pushText, + platformChannelSpecifics, + payload: 'No_Sound', + ); + }); + } + + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + User user = Provider.of(context).user; + if (user == null) { + Future.microtask( + () => Navigator.pushNamedAndRemoveUntil(context, "/", (r) => false)); + return Container(); + } + + login = Provider.of(context).isLogin(); + LanguageModel languageModel = Provider.of(context); + + final faqBtn = TaskButton("faq.btn", + icon: MaterialCommunityIcons.frequently_asked_questions, + btnCallback: () => Navigator.of(context).push(CupertinoPageRoute( + builder: (context) => FAQListPage(), + ))); + + final packagesBtn = TaskButton("package.btn.name", + icon: Octicons.package, + btnCallback: () => Navigator.of(context).push( + CupertinoPageRoute(builder: (context) => PackageList()))); + final packagesBtnFcs = TaskButton("package.btn.name", + icon: Octicons.package, + btnCallback: () => Navigator.of(context).push(CupertinoPageRoute( + builder: (context) => PackageList( + forCustomer: false, + )))); + + final receivingBtn = TaskButton("receiving.title", + icon: MaterialCommunityIcons.inbox_arrow_down, + btnCallback: () => Navigator.of(context).push( + CupertinoPageRoute(builder: (context) => ReceivingList()))); + + final processingBtn = TaskButton("processing.title", + icon: FontAwesome.dropbox, + btnCallback: () => Navigator.of(context).push( + CupertinoPageRoute(builder: (context) => ProcessingList()))); + final cartonBtn = TaskButton("boxes.name", + icon: MaterialCommunityIcons.package, + btnCallback: () => Navigator.of(context).push( + CupertinoPageRoute(builder: (context) => CartonList()))); + + final shipmentBtn = TaskButton("shipment", + icon: SimpleLineIcons.direction, + btnCallback: () => Navigator.of(context) + .push(CupertinoPageRoute(builder: (context) => ShipmentList()))); + + final shipmentBtnFcs = TaskButton("shipment", + icon: SimpleLineIcons.direction, + btnCallback: () => Navigator.of(context).push(CupertinoPageRoute( + builder: (context) => ShipmentList( + forCustomer: false, + )))); + + final fcsShipmentBtn = TaskButton("FCSshipment.title", + icon: Ionicons.ios_airplane, + btnCallback: () => Navigator.of(context).push(CupertinoPageRoute( + builder: (context) => FcsShipmentList(), + ))); + final notiBtnOrg = + TaskButton("message.btn", icon: Icons.message, btnCallback: () { + MessageModel messageModel = + Provider.of(context, listen: false); + messageModel.initQuery(user.id); + Navigator.of(context) + .push(CupertinoPageRoute( + builder: (context) => MessageDetail(messageModel: messageModel), + )) + .then((value) { + if (user.userUnseenCount > 0) { + messageModel.seenMessages(user.id, true); + } + }); + if (user.userUnseenCount > 0) { + messageModel.seenMessages(user.id, true); + } + }); + final notiBtn = badgeCounter(notiBtnOrg, user.userUnseenCount); + + final staffBtn = TaskButton( + "staff.title", + icon: MaterialCommunityIcons.worker, + btnCallback: () => Navigator.of(context).push(CupertinoPageRoute( + builder: (context) => StaffList(), + )), + ); + + final customersBtn = TaskButton("customers.btn", + icon: Feather.users, + btnCallback: () => Navigator.of(context).push(CupertinoPageRoute( + builder: (context) => CustomerList(), + ))); + + final invoicesBtn = TaskButton("invoices.btn", + icon: FontAwesomeIcons.fileInvoice, + btnCallback: () => Navigator.of(context).push(CupertinoPageRoute( + builder: (context) => InvoiceList(forCustomer: true)))); + final invoicesBtnFcs = TaskButton("invoices.btn", + icon: FontAwesomeIcons.fileInvoice, + btnCallback: () => Navigator.of(context).push(CupertinoPageRoute( + builder: (context) => InvoiceList(forCustomer: false)))); + + final discountBtn = TaskButton("discount.btn", + icon: Entypo.price_ribbon, + btnCallback: () => Navigator.of(context).push( + CupertinoPageRoute(builder: (context) => DiscountList()))); + + final deliveryBtn = TaskButton("delivery.title", + icon: MaterialCommunityIcons.truck_fast, + btnCallback: () => Navigator.of(context).push( + CupertinoPageRoute(builder: (context) => DeliverList()))); + + List widgets = []; + List widgetsFcs = []; + widgets.add(notiBtn); + if (user.joined) { + widgets.add(packagesBtn); + widgets.add(shipmentBtn); + widgets.add(invoicesBtn); + + if (user.hasPackages()) widgetsFcs.add(packagesBtnFcs); + if (user.hasShipment()) widgetsFcs.add(shipmentBtnFcs); + if (user.hasInvoices()) widgetsFcs.add(invoicesBtnFcs); + + if (user.hasFcsShipments()) widgetsFcs.add(fcsShipmentBtn); + if (user.hasReceiving()) widgetsFcs.add(receivingBtn); + if (user.hasProcessing()) widgetsFcs.add(processingBtn); + if (user.hasCarton()) widgetsFcs.add(cartonBtn); + if (user.hasDeliveries()) widgetsFcs.add(deliveryBtn); + if (user.hasCustomers()) widgetsFcs.add(customersBtn); + if (user.hasAdmin()) widgetsFcs.add(discountBtn); + if (user.hasStaffs()) widgetsFcs.add(staffBtn); + } + widgets.add(faqBtn); + + final fcsToggle = ToggleButtons( + selectedColor: Colors.white, + color: Colors.blue, + children: [ + Icon(MaterialCommunityIcons.worker), + ], + onPressed: (i) => this.setState(() { + isFcs[0] = !isFcs[0]; + SharedPref.saveStaffMode(isFcs[0]); + }), + isSelected: isFcs, + selectedBorderColor: Colors.white24, + ); + final langToggle = ToggleButtons( + children: [ + Image.asset( + 'icons/flags/png/us.png', + package: 'country_icons', + fit: BoxFit.fitWidth, + width: 25, + ), + Image.asset( + 'icons/flags/png/mm.png', + package: 'country_icons', + fit: BoxFit.fitWidth, + width: 25, + ) + ], + onPressed: _langChange, + isSelected: languageModel.currentState, + selectedBorderColor: Colors.white24, + ); + final signinBtn = FlatButton( + onPressed: () { + Navigator.of(context) + .push(CupertinoPageRoute(builder: (context) => SigninPage())); + }, + child: Text( + "Sign In", + style: siginButtonStyle, + ), + ); + final profileBtn = IconButton( + onPressed: () { + Navigator.of(context).push(RightLeftPageRoute(Profile())); + }, + iconSize: 30, + icon: Icon(Icons.account_circle), + ); + + var searchInput = Row(children: [ + Expanded( + child: Padding( + padding: const EdgeInsets.only(bottom: 3, left: 5, right: 5, top: 3), + child: Theme( + data: new ThemeData( + primaryColor: primaryColor, + primaryColorDark: primaryColor, + ), + child: TextField( + style: TextStyle(color: Colors.white), + controller: _searchCtl, + scrollPadding: EdgeInsets.all(0), + decoration: new InputDecoration( + enabledBorder: const OutlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(30)), + borderSide: + const BorderSide(color: Colors.white, width: 1.5), + ), + focusedBorder: const OutlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(30)), + borderSide: + const BorderSide(color: Colors.white, width: 1.5), + ), + contentPadding: EdgeInsets.only(top: 1, bottom: 1), + isDense: true, + hintText: getLocalString(context, "home.search"), + hintStyle: languageModel.isEng + ? newLabelStyle(color: Colors.white60) + : newLabelStyleMM(color: Colors.white60), + prefixIcon: const Icon( + Icons.search, + color: Colors.grey, + ), + suffixIcon: InkWell( + onTap: () => {_searchCtl.clear()}, + child: const Icon( + Icons.close, + color: Colors.grey, + ), + ), + suffixStyle: const TextStyle(color: primaryColor)), + ), + ), + ), + ), + InkWell( + child: Padding( + padding: const EdgeInsets.all(10.0), + child: LocalText( + context, + "home.search.btn", + color: Colors.white, + ), + ), + onTap: _lookup, + ) + ]); + widgets.insert(0, searchInput); + + return LocalProgress( + inAsyncCall: _isLoading, + child: OfflineRedirect( + child: FlavorBanner( + child: Scaffold( + appBar: AppBar( + elevation: 0, + backgroundColor: primaryColor, + title: ClipRRect( + child: Image.asset("assets/logo.jpg", height: 40), + borderRadius: new BorderRadius.circular(30.0), + ), + actions: login + ? user.isCustomer() + ? [ + langToggle, + profileBtn, + ] + : [ + fcsToggle, + langToggle, + profileBtn, + ] + : [ + langToggle, + signinBtn, + ]), + body: Container( + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + Color(0xd0272262), + Color(0xfa272262), + ], + ), + ), + child: ListView( + children: [ + Column(children: [ + Wrap( + alignment: WrapAlignment.center, + children: isFcs[0] ? widgetsFcs : widgets, + ), + ]), + SizedBox(height: 50), + BottomWidgets(), + ], + ))), + ), + ), + ); + } + + _langChange(index) { + var languageModel = Provider.of(context, listen: false); + languageModel.saveLanguage(Translation().supportedLanguages[index]); + setState(() { + isSelected.asMap().forEach((i, e) { + isSelected[i] = false; + }); + isSelected[index] = !isSelected[index]; + }); + } + + _lookup() async { + setState(() { + _isLoading = true; + }); + + try { + String term = _searchCtl.text; + if (term == null || term.trim() == "") return; + var packageModel = Provider.of(context, listen: false); + Package package = await packageModel.lookupPackage(term); + if (package == null) { + showMsgDialog(context, "Not found", "Tracking ID - '$term' not found!"); + return; + } + Navigator.push( + context, + CupertinoPageRoute( + builder: (context) => PackageInfo( + package: package, + isSearchResult: true, + )), + ); + } catch (e) { + showMsgDialog(context, "Error", e.toString()); + } finally { + setState(() { + _isLoading = false; + }); + } + } +} diff --git a/lib/fcs/common/pages/initial_language_selection.dart b/lib/pages/main/initial_language_selection.dart similarity index 93% rename from lib/fcs/common/pages/initial_language_selection.dart rename to lib/pages/main/initial_language_selection.dart index 9ec4240..7d6a018 100644 --- a/lib/fcs/common/pages/initial_language_selection.dart +++ b/lib/pages/main/initial_language_selection.dart @@ -1,11 +1,11 @@ -import 'package:fcs/fcs/common/helpers/shared_pref.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/fcs/common/localization/transalation.dart'; -import 'package:fcs/fcs/common/pages/model/language_model.dart'; -import 'package:fcs/fcs/common/pages/model/main_model.dart'; -import 'package:fcs/fcs/common/pages/signin/signin_page.dart'; -import 'package:fcs/fcs/common/pages/widgets/local_text.dart'; -import 'package:fcs/fcs/common/pages/widgets/progress.dart'; +import 'package:fcs/helpers/shared_pref.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/localization/transalation.dart'; +import 'package:fcs/pages/main/model/language_model.dart'; +import 'package:fcs/pages/main/model/main_model.dart'; +import 'package:fcs/pages/signin/signin_page.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/progress.dart'; import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:provider/provider.dart'; diff --git a/lib/model/base_model.dart b/lib/pages/main/model/base_model.dart similarity index 75% rename from lib/model/base_model.dart rename to lib/pages/main/model/base_model.dart index 2a39149..ac8b8b5 100644 --- a/lib/model/base_model.dart +++ b/lib/pages/main/model/base_model.dart @@ -1,8 +1,8 @@ +import 'package:fcs/domain/entities/setting.dart'; +import 'package:fcs/domain/entities/user.dart'; import 'package:flutter/foundation.dart'; -import 'package:fcs/fcs/common/helpers/api_helper.dart'; +import 'package:fcs/helpers/api_helper.dart'; -import '../vo/setting.dart'; -import '../vo/user.dart'; import 'main_model.dart'; abstract class BaseModel extends ChangeNotifier { @@ -14,11 +14,13 @@ abstract class BaseModel extends ChangeNotifier { this.user = user; } + void privilegeChanged() {} + void initSetting(Setting setting) async { this.setting = setting; } - void logout(); + void logout() {} // request makes http request // if token is null @@ -29,7 +31,6 @@ abstract class BaseModel extends ChangeNotifier { String token, String url, }) async { - mainModel.resetPinTimer(); return await requestAPI(path, method, payload: payload, token: token, url: url); } diff --git a/lib/fcs/common/pages/model/language_model.dart b/lib/pages/main/model/language_model.dart similarity index 90% rename from lib/fcs/common/pages/model/language_model.dart rename to lib/pages/main/model/language_model.dart index 47c9186..b6bd04c 100644 --- a/lib/fcs/common/pages/model/language_model.dart +++ b/lib/pages/main/model/language_model.dart @@ -1,5 +1,5 @@ -import 'package:fcs/fcs/common/localization/transalation.dart'; -import 'package:fcs/fcs/common/helpers/shared_pref.dart'; +import 'package:fcs/localization/transalation.dart'; +import 'package:fcs/helpers/shared_pref.dart'; import 'package:flutter/painting.dart'; import 'base_model.dart'; diff --git a/lib/fcs/common/pages/model/main_model.dart b/lib/pages/main/model/main_model.dart similarity index 53% rename from lib/fcs/common/pages/model/main_model.dart rename to lib/pages/main/model/main_model.dart index 2e9a30d..5f2180e 100644 --- a/lib/fcs/common/pages/model/main_model.dart +++ b/lib/pages/main/model/main_model.dart @@ -1,14 +1,12 @@ import 'dart:async'; -import 'dart:developer'; -import 'package:fcs/fcs/common/domain/entities/auth_result.dart'; -import 'package:fcs/fcs/common/domain/entities/auth_status.dart'; -import 'package:fcs/fcs/common/domain/entities/setting.dart'; -import 'package:fcs/fcs/common/domain/entities/user.dart'; -import 'package:fcs/fcs/common/helpers/network_connectivity.dart'; -import 'package:fcs/fcs/common/helpers/shared_pref.dart'; -import 'package:fcs/fcs/common/pages/model/base_model.dart'; -import 'package:fcs/fcs/common/services/services.dart'; +import 'package:fcs/data/services/services.dart'; +import 'package:fcs/domain/entities/auth_result.dart'; +import 'package:fcs/domain/entities/setting.dart'; +import 'package:fcs/domain/entities/user.dart'; +import 'package:fcs/helpers/network_connectivity.dart'; +import 'package:fcs/helpers/shared_pref.dart'; +import 'package:fcs/pages/main/model/base_model.dart'; import 'package:flutter/foundation.dart'; import 'package:logging/logging.dart'; import 'package:package_info/package_info.dart'; @@ -36,26 +34,21 @@ class MainModel extends ChangeNotifier { NetworkConnectivity.instance.statusStream.listen((data) { bool _isOnline = data["isOnline"]; if (_isOnline && !this.isOnline) { - init(); + _init(); } this.isOnline = _isOnline; notifyListeners(); }); - Services.instance.authService.onAuthStatus().listen((event) async { - this.user = - await Services.instance.authService.getUser(refreshIdToken: true); - _initUser(user); - if (user != null) { - uploadMsgToken(); - } - notifyListeners(); - }); } bool faqEditable() { return this.user != null && this.user.hasSupport(); } + bool rateEditable() { + return this.user != null && this.user.hasSupport(); + } + bool paymentMethodsEditable() { return this.user != null && this.user.hasSupport(); } @@ -84,78 +77,51 @@ class MainModel extends ChangeNotifier { return this.user != null && this.user.hasAdmin(); } - init() async { - await _loadSetting(); + // userListener should never be closed + StreamSubscription userListener; + _init() async { + await _listenSetting(); this.isFirstLaunch = await SharedPref.isFirstLaunch(); this.isFirstLaunch = this.isFirstLaunch ?? true; - - // _loadUser(); this.packageInfo = await PackageInfo.fromPlatform(); + + if (userListener != null) userListener.cancel(); + userListener = + Services.instance.authService.getUserStream().listen((_user) { + if (_user != null) { + models.forEach((m) => m.initUser(_user)); + // call diffPrivileges if privilege changed or first time login + if (this.user == null || _user.diffPrivileges(this.user)) { + models.forEach((m) => m.privilegeChanged()); + } + if (this.user == null) { + uploadMsgToken(); + } + } else { + if (this.user != null) { + models.forEach((m) => m.logout()); + } + } + this.user = _user; + isLoaded = true; + notifyListeners(); + }); } void addModel(BaseModel model) { models.add(model); } - StreamSubscription userListener; - - void _initUser(User user) { - if (user != null) { - if (user.id != null && user.id != "") { - if (userListener != null) userListener.cancel(); - userListener = Services.instance.authService - .getUserStream(user.id) - .listen((event) { - this.user = event; - - models.forEach((m) => m.initUser(user)); - notifyListeners(); - }); - } - models.forEach((m) => m.initUser(user)); - } else { - models.forEach((m) => m.logout()); - } - isLoaded = true; - // if (firebaseMessaging != null) { - // firebaseMessaging.subscribeToTopic(user.docID); - // } - } - - void _initSetting(Setting setting) { - models.forEach((m) => m.initSetting(setting)); - } - - Future _loadSetting() async { + Future _listenSetting() async { try { Services.instance.authService.getSetting().listen((event) { this.setting = event; - _initSetting(setting); + models.forEach((m) => m.initSetting(setting)); notifyListeners(); }); } finally {} } - // void _loadUser() async { - // try { - // this.user = await Services.instance.authService.getUser(); - // _initUser(user); - // } finally { - // this.isLoaded = true; - // notifyListeners(); - // } - // } - - @override - void dispose() { - super.dispose(); - // if (this.userListener != null) { - // this.userListener.cancel(); - // } - // SharedPref.removeUser(); - // this.user = User(); - } - bool isSupport() { if (packageInfo == null || setting == null) return false; return int.parse(packageInfo.buildNumber) >= setting.supportBuildNum; @@ -168,11 +134,6 @@ class MainModel extends ChangeNotifier { Future signin(String smsCode) async { AuthResult authResult = await Services.instance.authService.signInWithSmsCode(smsCode); - if (authResult != null && - authResult.authStatus == AuthStatus.AUTH_VERIFIED) { - this.user = await Services.instance.authService.getUser(); - uploadMsgToken(); - } return authResult; } @@ -187,13 +148,11 @@ class MainModel extends ChangeNotifier { } Future signout() async { - // logout models + try { + await removeMsgToken(); + } catch (e) {} + await Services.instance.authService.signout(); models.forEach((m) => m.logout()); - await removeMsgToken(); - this.user = null; - notifyListeners(); - - return Services.instance.authService.signout(); } Future hasInvite() async { @@ -202,22 +161,20 @@ class MainModel extends ChangeNotifier { Future signup(String userName) async { await Services.instance.authService.signup(userName); - this.user = - await Services.instance.authService.getUser(refreshIdToken: true); - notifyListeners(); } Future joinInvite(String userName) async { await Services.instance.authService.joinInvite(userName); - this.user = - await Services.instance.authService.getUser(refreshIdToken: true); notifyListeners(); } - Future updateProfile(String newUserName) async { - await Services.instance.authService.updateProfile(newUserName); - this.user = - await Services.instance.authService.getUser(refreshIdToken: true); + Future updateProfileName(String newUserName) async { + await Services.instance.authService.updateProfileName(newUserName); + notifyListeners(); + } + + Future updatePreferredCurrency(String currency) async { + await Services.instance.authService.updatePreferredCurrency(currency); notifyListeners(); } } diff --git a/lib/fcs/common/pages/splash_page.dart b/lib/pages/main/splash_page.dart similarity index 93% rename from lib/fcs/common/pages/splash_page.dart rename to lib/pages/main/splash_page.dart index 6658f11..4651fc0 100644 --- a/lib/fcs/common/pages/splash_page.dart +++ b/lib/pages/main/splash_page.dart @@ -1,8 +1,8 @@ import 'dart:async'; -import 'package:fcs/fcs/common/pages/model/main_model.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/fcs/common/pages/widgets/local_text.dart'; +import 'package:fcs/pages/main/model/main_model.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; import 'package:flutter/material.dart'; import 'package:logging/logging.dart'; import 'package:provider/provider.dart'; diff --git a/lib/fcs/common/pages/util.dart b/lib/pages/main/util.dart similarity index 57% rename from lib/fcs/common/pages/util.dart rename to lib/pages/main/util.dart index 537e014..a6ccd3f 100644 --- a/lib/fcs/common/pages/util.dart +++ b/lib/pages/main/util.dart @@ -1,34 +1,13 @@ -import 'package:fcs/fcs/common/localization/app_translations.dart'; -import 'package:fcs/fcs/common/pages/chat/message_detail.dart'; -import 'package:fcs/fcs/common/pages/chat/model/message_model.dart'; -import 'package:fcs/fcs/common/pages/model/language_model.dart'; -import 'package:fcs/fcs/common/pages/model/main_model.dart'; -import 'package:fcs/fcs/common/pages/widgets/local_text.dart'; -import 'package:fcs/fcs/common/services/services.dart'; -import 'package:fcs/widget/label_widgets.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/localization/app_translations.dart'; +import 'package:fcs/pages/main/model/language_model.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_colorpicker/flutter_colorpicker.dart'; import 'package:logging/logging.dart'; import 'package:provider/provider.dart'; import 'package:url_launcher/url_launcher.dart'; -import 'package:fcs/model/announcement_model.dart'; -import 'package:fcs/model/buyer_model.dart'; -import 'package:fcs/model/do_model.dart'; -import 'package:fcs/model/notification_model.dart'; -import 'package:fcs/model/po_model.dart'; -import 'package:fcs/model/user_model.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/buyer.dart'; -import 'package:fcs/vo/notification.dart' as Noti; -import '../../../pages/announcement.dart'; -import '../../../pages/buyer_info.dart'; -import '../../../pages/do/do_approve.dart'; -import '../../../pages/log_list.dart'; -import '../../../pages/my_registeration_info.dart'; -import '../../../pages/po/po_submission_form.dart'; -import '../../../pages/products_list.dart'; -import '../../../pages/user_editor.dart'; +import '../widgets/label_widgets.dart'; final log = Logger('Util'); @@ -52,42 +31,6 @@ Future showMsgDialog(BuildContext context, String title, String msg) { ); } -var selectedColor; -void showColorPicker(BuildContext context, Color color, callback(Color color)) { - showDialog( - context: context, - child: AlertDialog( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.all(Radius.circular(32.0))), - title: const Text('Pick product color'), - content: SingleChildScrollView( - child: ColorPicker( - pickerColor: color.value == 0 ? Colors.red : color, - pickerAreaHeightPercent: 0.6, - onColorChanged: (Color value) { - selectedColor = value; - }, - ), - ), - actions: [ - FlatButton( - child: const Text('Choose'), - onPressed: () { - callback(selectedColor == null ? Colors.red : selectedColor); - Navigator.of(context).pop(); - }, - ), - FlatButton( - child: const Text('Cancel'), - onPressed: () { - Navigator.of(context).pop(); - }, - ), - ], - ), - ); -} - Future showConfirmDialog( BuildContext context, String translationKey, ok(), {List translationVariables}) async { @@ -111,10 +54,10 @@ Future showConfirmDialog( FlatButton( color: Colors.grey[300], child: Text( - AppTranslations.of(context).text('Cancel'), + AppTranslations.of(context).text('btn.cancel'), style: Provider.of(context).isEng ? TextStyle() - : TextStyle(fontFamily: 'MyanmarUnicode'), + : TextStyle(fontFamily: 'Myanmar3'), ), onPressed: () { Navigator.of(context).pop(); @@ -124,7 +67,7 @@ Future showConfirmDialog( ), FlatButton( color: primaryColor, - child: Text(AppTranslations.of(context).text('Ok'), + child: Text(AppTranslations.of(context).text('btn.ok'), style: Provider.of(context).isEng ? TextStyle( color: Colors.white, @@ -132,7 +75,7 @@ Future showConfirmDialog( : TextStyle( color: Colors.white, fontWeight: FontWeight.bold, - fontFamily: 'MyanmarUnicode')), + fontFamily: 'Myanmar3')), onPressed: () async { Navigator.of(context).pop(); await ok(); @@ -144,69 +87,6 @@ Future showConfirmDialog( }); } -void showCommentDialog(BuildContext context, commentCallback(comment)) { - TextEditingController _comment = new TextEditingController(); - showDialog( - context: context, - builder: (_) { - return AlertDialog( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.all(Radius.circular(32.0))), - content: Container( - width: 300.0, - height: 80.0, - child: Container( - child: TextFormField( - controller: _comment, - autofocus: false, - cursorColor: primaryColor, - maxLines: 3, - style: textStyle, - decoration: new InputDecoration( - labelText: "Comment", - labelStyle: labelStyle, - icon: Icon( - Icons.add_comment, - color: primaryColor, - ), - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - ), - validator: (value) { - if (value.isEmpty) { - return "Please enter comment"; - } - return null; - }, - ), - ), - ), - actions: [ - FlatButton( - child: Text( - "Cancel", - style: labelStyle, - ), - onPressed: () { - _comment.clear(); - Navigator.of(context).pop(); - }), - FlatButton( - color: primaryColor, - child: Text("Submit", - style: TextStyle( - color: Colors.white, fontWeight: FontWeight.bold)), - onPressed: () { - commentCallback(_comment.text); - Navigator.of(context).pop(); - }) - ], - ); - }); -} - Widget getStatus(String status) { return status == "Delivered" ? Text(status, @@ -308,7 +188,7 @@ Widget getStatus(String status) { ], ) : Text( - status, + status ?? "", style: TextStyle( color: primaryColor, fontSize: 18, @@ -321,75 +201,6 @@ call(BuildContext context, String phone) { translationVariables: ["$phone"]); } -Future displayNotiContent( - BuildContext context, Noti.Notification noti) async { - if (!noti.seen) { - Provider.of(context, listen: false).seenID(noti.id); - } - - try { - if (noti.itemType == "buyer") { - BuyerModel buyerModel = Provider.of(context, listen: false); - Buyer buyer = await buyerModel.getBuyer(noti.itemID); - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => BuyerInfo( - buyer: buyer, - )), - ); - } else if (noti.itemType == "announcement") { - AnnouncementModel announcementModel = - Provider.of(context, listen: false); - var announce = await announcementModel.getAnnouncement(noti.itemID); - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => AnnouncementPage(announcement: announce)), - ); - } else if (noti.itemType == "reg") { - Navigator.push( - context, - MaterialPageRoute(builder: (context) => MyRegisterationInfo()), - ); - } else if (noti.itemType == "po") { - POSubmissionModel poModel = - Provider.of(context, listen: false); - var po = await poModel.getPO(noti.itemID); - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => POSubmissionForm( - poSubmission: po, - )), - ); - } else if (noti.itemType == "do") { - DOModel doModel = Provider.of(context, listen: false); - var _do = await doModel.getDO(noti.itemID); - Navigator.push( - context, - MaterialPageRoute(builder: (context) => DOApproval(doSubmission: _do)), - ); - } else if (noti.itemType == "price") { - Navigator.of(context) - .push(MaterialPageRoute(builder: (_) => ProductsList())); - } else if (noti.itemType == 'new_device_login') { - Navigator.of(context).push(MaterialPageRoute(builder: (_) => LogList())); - } else if (noti.itemType == 'user') { - UserModel userModel = Provider.of(context, listen: false); - var user = await userModel.getUser(noti.itemID); - Navigator.of(context).push(MaterialPageRoute( - builder: (_) => UserEditor( - user: user, - viewOnly: true, - ))); - } - } catch (e) { - log.warning("Error:$e \n ${noti.toString()}"); - showMsgDialog(context, "Error", "Notification item not found!"); - } finally {} -} - Widget nameWidget(String name) { return Center( child: Padding( @@ -443,37 +254,6 @@ Widget fcsInput(String label, IconData iconData, focusedBorder: UnderlineInputBorder( borderSide: BorderSide(color: Colors.grey, width: 1.0)), )); - // return Row( - // children: [ - // Padding( - // padding: const EdgeInsets.only(right: 8.0), - // child: Icon(iconData), - // ), - // Expanded( - // child: Container( - // child: Row(children: [ - // Expanded( - // child: TextFormField( - // initialValue: value, - // controller: controller, - // cursorColor: primaryColor, - // maxLines: null, - // minLines: 1, - // textAlign: TextAlign.left, - // decoration: new InputDecoration( - // contentPadding: EdgeInsets.only(top: 8), - // labelText: label, - // labelStyle: TextStyle(fontSize: 14, color: Colors.grey), - // enabledBorder: UnderlineInputBorder( - // borderSide: BorderSide(color: primaryColor, width: 1.0)), - // focusedBorder: UnderlineInputBorder( - // borderSide: BorderSide(color: primaryColor, width: 1.0)), - // ), - // )), - // ]), - // )), - // ], - // ); } Widget fcsInputReadOnly(String label, IconData iconData, @@ -496,34 +276,6 @@ Widget fcsInputReadOnly(String label, IconData iconData, color: primaryColor, ), )); - // return Row( - // children: [ - // Padding( - // padding: const EdgeInsets.only(right: 8.0), - // child: Icon(iconData), - // ), - // Expanded( - // child: Container( - // child: Row(children: [ - // Expanded( - // child: TextFormField( - // initialValue: value, - // controller: controller, - // cursorColor: primaryColor, - // maxLines: null, - // minLines: 1, - // readOnly: true, - // textAlign: TextAlign.left, - // decoration: new InputDecoration( - // border: InputBorder.none, - // contentPadding: EdgeInsets.only(top: 8), - // labelText: label, - // ), - // )), - // ]), - // )), - // ], - // ); } Widget fcsDropDown(String label, IconData iconData, diff --git a/lib/fcs/common/pages/welcome_page.dart b/lib/pages/main/welcome_page.dart similarity index 89% rename from lib/fcs/common/pages/welcome_page.dart rename to lib/pages/main/welcome_page.dart index 03bb677..df39162 100644 --- a/lib/fcs/common/pages/welcome_page.dart +++ b/lib/pages/main/welcome_page.dart @@ -1,17 +1,16 @@ -import 'package:fcs/fcs/common/pages/model/language_model.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/fcs/common/pages/widgets/bottom_widgets.dart'; -import 'package:fcs/widget/banner.dart'; -import 'package:fcs/widget/bottom_up_page_route.dart'; -import 'package:fcs/widget/localization/transalation.dart'; -import 'package:fcs/widget/offline_redirect.dart'; +import 'package:fcs/localization/transalation.dart'; +import 'package:fcs/pages/main/model/language_model.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/widgets/bottom_widgets.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:logging/logging.dart'; import 'package:provider/provider.dart'; -import '../helpers/theme.dart'; -import 'signin/signin_page.dart'; +import '../../helpers/theme.dart'; +import '../signin/signin_page.dart'; +import '../widgets/banner.dart'; +import '../widgets/offline_redirect.dart'; final msgLog = Logger('backgroundMessageHandler'); @@ -86,8 +85,8 @@ class _WelcomePageState extends State { ), FlatButton( onPressed: () { - Navigator.of(context) - .push(BottomUpPageRoute(SigninPage())); + Navigator.of(context).push(CupertinoPageRoute( + builder: (context) => SigninPage())); }, child: Text( getLocalString(context, "welcome.signin"), diff --git a/lib/pages/manual/instruction_data_page.dart b/lib/pages/manual/instruction_data_page.dart deleted file mode 100644 index 669b9a4..0000000 --- a/lib/pages/manual/instruction_data_page.dart +++ /dev/null @@ -1,227 +0,0 @@ -import 'dart:io'; - -import 'package:flutter/material.dart'; -import 'package:image_picker/image_picker.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/language_model.dart'; -import 'package:fcs/model/main_model.dart'; -import 'package:fcs/model/manual_model.dart'; -import 'package:fcs/pages/manual/moveable_stack_item.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/manual.dart'; -import 'package:path/path.dart' as Path; -import 'package:fcs/widget/progress.dart'; - -class InstructionDataPage extends StatefulWidget { - final SlideData slideData; - final String path; - final int slideIndex; - final int manIndex; - - InstructionDataPage( - {this.slideData, this.path, this.slideIndex, this.manIndex}); - @override - _InstructionDataPageState createState() => _InstructionDataPageState(); -} - -class _InstructionDataPageState extends State { - String selectedLanguage; - File slideImageFile; - bool isEng; - List _selection = List.generate(2, (_) => false); - String imgName; - bool _isLoading = false; - - @override - void initState() { - super.initState(); - isEng = true; - } - - @override - Widget build(BuildContext context) { - var manualModel = Provider.of(context); - if (isEng) { - imgName = widget.slideData.image; - } else { - imgName = widget.slideData.imagemm; - } - - var screenSize = MediaQuery.of(context).size; - var width = screenSize.width; - var imgWidth = width - (width * 0.15); - var height = screenSize.height; - var imgHeight = height - (height * 0.29); - - var toggleButtons = Container( - child: ToggleButtons( - children: [ - Row( - children: [ - Image.asset( - "assets/eng_flag.png", - width: 25, - ), - Text( - "English", - style: - TextStyle(color: this.isEng ? secondaryColor : Colors.black), - ) - ], - ), - Container( - padding: EdgeInsets.only(left: 10, right: 10), - child: Row( - children: [ - Image.asset( - "assets/myan_flag.png", - width: 25, - ), - Container( - padding: EdgeInsets.only(left: 10), - child: Text( - "မြန်မာ", - style: TextStyle( - color: !this.isEng ? secondaryColor : Colors.black, - fontFamily: "MyanmarUnicode"), - ), - ) - ], - ), - ) - ], - renderBorder: false, - isSelected: _selection, - selectedColor: secondaryColor, - onPressed: (int index) { - setState(() { - _selection[index] = !_selection[index]; - if (index == 0) { - this.isEng = true; - } else { - this.isEng = false; - } - }); - }, - )); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - title: Text('Instruction Data'), - actions: [toggleButtons], - ), - body: Container( - alignment: Alignment.topCenter, - child: Stack( - children: [ - Container( - child: Stack( - children: instructionData( - context, imgWidth, imgHeight, manualModel), - ), - ), - Positioned( - top: 0, - right: 0, - child: IconButton( - icon: Icon(Icons.image), - onPressed: () { - pickImageFromGallery(ImageSource.gallery, manualModel); - }), - ) - ], - ), - ), - floatingActionButton: FloatingActionButton( - onPressed: () { - addInstructionData(); - }, - tooltip: 'Pick Image', - child: Icon(Icons.add), - ), - ), - ); - } - - addInstructionData() { - var instructionList = - isEng ? widget.slideData.instructions : widget.slideData.instructionsmm; - Instruction inst; - if (instructionList.toList().length == 0) { - inst = Instruction( - id: 1, - text: '', - left: 0.0, - top: 0.0, - ); - } else { - dynamic max = instructionList.first; - instructionList.forEach((e) { - if (e.id > max.id) max = e; - }); - inst = Instruction( - id: max.id + 1, - text: '', - left: 0.0, - top: 0.0, - ); - } - - setState(() { - if (isEng) { - widget.slideData.instructions.add(inst); - } else { - widget.slideData.instructionsmm.add(inst); - } - }); - } - - instructionData( - BuildContext context, double imgW, double imgH, ManualModel manualModel) { - List textFields = []; - textFields.add( - Image.file( - File('${widget.path}/manual/img/' + imgName), - alignment: AlignmentDirectional.topCenter, - height: imgH, - width: imgW, - ), - ); - var instructionList = - isEng ? widget.slideData.instructions : widget.slideData.instructionsmm; - if (instructionList.length != 0) { - instructionList.asMap().forEach((k, instruction) { - MoveableStackItem mitem = MoveableStackItem( - instruction: instruction, - manIndex: widget.manIndex, - slideIndex: widget.slideIndex, - instIndex: k, - isEng: this.isEng, - key: Key(this.isEng.toString() + k.toString()), - ); - - textFields.add(mitem); - }); - } - return textFields; - } - - pickImageFromGallery(ImageSource source, ManualModel manualModel) async { - File tempImage = await ImagePicker.pickImage( - source: source, imageQuality: 80, maxWidth: 300); - - var fileName = Path.basename(tempImage.path); - var path = '${manualModel.dataDir}'; - File newImage = await tempImage.copy('$path/manual/img/$fileName'); - var slideData = widget.slideData; - if (this.isEng) { - slideData.image = fileName; - } else { - slideData.imagemm = fileName; - } - - manualModel.changeSlideImage(widget.manIndex, widget.slideIndex, slideData); - } -} diff --git a/lib/pages/manual/manual_item_title_dialog.dart b/lib/pages/manual/manual_item_title_dialog.dart deleted file mode 100644 index 93121a4..0000000 --- a/lib/pages/manual/manual_item_title_dialog.dart +++ /dev/null @@ -1,78 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/manual_model.dart'; -import 'package:fcs/vo/manual.dart'; - -class ManualItemTitleDialog extends StatefulWidget { - @override - State createState() { - return _ManualItemTitleDialogState(); - } -} - -class _ManualItemTitleDialogState extends State { - TextEditingController _engTextFieldController = TextEditingController(); - TextEditingController _mmTextFieldController = TextEditingController(); - ManualItem item; - bool buyer = false; - @override - void initState() { - super.initState(); - } - - @override - Widget build(BuildContext context) { - return AlertDialog( - title: new Text('Enter Title'), - content: Container( - height: 200, - child: Column( - children: [ - TextField( - controller: _engTextFieldController, - decoration: InputDecoration(hintText: "Enter English"), - maxLines: null, - style: TextStyle(fontSize: 13.0), - ), - TextField( - controller: _mmTextFieldController, - decoration: InputDecoration(hintText: "Enter Myanmar"), - maxLines: null, - style: TextStyle(fontSize: 13.0), - ), - CheckboxListTile( - title: Text("For Buyer"), - value: buyer, - onChanged: (val) { - setState(() { - buyer = val; - }); - }, - ), - ], - ), - ), - actions: [ - new FlatButton( - onPressed: () { - _save(); - }, - child: new Text('Save')) - ], - ); - } - - _save() { - try { - String eng = _engTextFieldController.text; - String mm = _mmTextFieldController.text; - - ManualItem item = - ManualItem(title: eng, titlemm: mm, isBuyer: buyer, slides: []); - - Navigator.pop(context, item); - } catch (e) { - // showMsgDialog(context, "Error", e.toString()); - } - } -} diff --git a/lib/pages/manual/manual_page.dart b/lib/pages/manual/manual_page.dart deleted file mode 100644 index 3a63621..0000000 --- a/lib/pages/manual/manual_page.dart +++ /dev/null @@ -1,201 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/language_model.dart'; -import 'package:fcs/model/main_model.dart'; -import 'package:fcs/model/manual_model.dart'; -import 'package:fcs/pages/manual/manual_item_title_dialog.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/vo/manual.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/progress.dart'; - -import '../../fcs/common/helpers/theme.dart'; -import 'slide_page.dart'; - -class ManualPage extends StatefulWidget { - final String marketplace; - - const ManualPage({Key key, this.marketplace}) : super(key: key); - @override - _ManualPageState createState() => _ManualPageState(); -} - -class _ManualPageState extends State { - TextEditingController _manualVersionController = TextEditingController(); - final double dotSize = 10.0; - List helpList = new List(); - bool isEng; - String versionName; - bool _isLoading = false; - - @override - void initState() { - helpList.clear(); - var manualModel = Provider.of(context, listen: false); - var mainModel = Provider.of(context, listen: false); - versionName = manualModel.version; - helpList = manualModel.getHelpList(mainModel.isBuyer()); - super.initState(); - } - - @override - Widget build(BuildContext context) { - var manualModel = Provider.of(context); - var mainModel = Provider.of(context); - var languageModel = Provider.of(context); - isEng = languageModel.isEng; - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - leading: new IconButton( - icon: new Icon(Icons.close, color: Colors.white), - onPressed: () => Navigator.of(context).pop(), - ), - title: Text(widget.marketplace == null ? '' : widget.marketplace), - backgroundColor: primaryColor, - ), - body: Column( - children: [ - new Expanded( - child: new ListView.builder( - scrollDirection: Axis.vertical, - padding: EdgeInsets.only(left: 15, right: 15, top: 5), - shrinkWrap: true, - itemCount: helpList.length, - itemBuilder: (BuildContext context, int index) { - return Card( - elevation: 10, - color: Colors.white, - child: InkWell( - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => SlidePage( - helpDetail: helpList[index], - index: index, - )), - ); - }, - child: Row(children: [ - Expanded( - child: new Padding( - padding: - const EdgeInsets.symmetric(vertical: 5.0), - child: new Row( - children: [ - new Padding( - padding: new EdgeInsets.symmetric( - horizontal: 15.0 - dotSize / 2), - child: Container( - child: Image.asset( - "assets/page.png", - width: 50, - height: 50, - )), - ), - new Expanded( - child: new Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - isEng - ? helpList[index].title - : helpList[index].titlemm, - style: TextStyle( - fontSize: 15, - color: Colors.grey), - ) - ], - ), - ), - ], - ), - ), - ), - mainModel.isSysAdmin() - ? Container( - padding: EdgeInsets.only(right: 20), - child: InkWell( - onTap: () { - showConfirmDialog( - context, "manual.confirm", () { - setState(() { - manualModel.deleteManualItem( - helpList[index]); - helpList = manualModel.getHelpList( - mainModel.isBuyer()); - }); - }); - }, - child: Icon(Icons.delete), - )) - : Container() - ])), - ); - }), - ), - ], - ), - floatingActionButton: mainModel.isSysAdmin() - ? FloatingActionButton( - onPressed: () async { - ManualItem newItem = await showDialog( - context: context, - builder: (_) => ManualItemTitleDialog()); - if (helpList.toList().length == 0) { - newItem.id = 1; - } else { - dynamic max = helpList.first; - helpList.forEach((e) { - if (e.id > max.id) max = e; - }); - newItem.id = max.id + 1; - } - setState(() { - helpList.add(newItem); - }); - manualModel.addManualTitle(newItem); - }, - child: Icon(Icons.add), - ) - : null, - ), - ); - } - - _deleteManualItem(ManualItem item, ManualModel manualModel) { - return showConfirmDialog(context, "manual.confirm", () { - setState(() { - manualModel.deleteManualItem(item); - }); - }); - } - - _inputManualVersion(BuildContext context, ManualModel manModel) async { - return showDialog( - context: context, - builder: (context) { - return AlertDialog( - title: new Text('Version'), - content: TextField( - controller: _manualVersionController, - decoration: InputDecoration(hintText: "Enter manual version"), - ), - actions: [ - new FlatButton( - onPressed: () { - String version = _manualVersionController.text; - String dir = manModel.dataDir; - manModel.uploadStorageManualData(version, dir); - Navigator.of(context).pop(); - }, - child: new Text('Save')) - ], - ); - }); - } -} diff --git a/lib/pages/manual/moveable_stack_item.dart b/lib/pages/manual/moveable_stack_item.dart deleted file mode 100644 index fedb0a0..0000000 --- a/lib/pages/manual/moveable_stack_item.dart +++ /dev/null @@ -1,123 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/manual_model.dart'; -import 'package:fcs/vo/manual.dart'; - -class MoveableStackItem extends StatefulWidget { - Instruction instruction; - final int instIndex; - final int slideIndex; - final int manIndex; - final bool isEng; - - MoveableStackItem( - {this.instIndex, - this.slideIndex, - this.manIndex, - this.instruction, - this.isEng, - Key key}) - : super(key: key); - - @override - State createState() { - return _MoveableStackItemState(); - } -} - -class _MoveableStackItemState extends State { - TextEditingController _textFieldController = TextEditingController(); - double xPosition = 0; - double yPosition = 0; - - @override - void initState() { - super.initState(); - _textFieldController.text = widget.instruction.text; - yPosition = - widget.instruction.top != null ? widget.instruction.top : yPosition; - xPosition = - widget.instruction.left != null ? widget.instruction.left : xPosition; - } - - @override - Widget build(BuildContext context) { - var manualModel = Provider.of(context); - return Positioned( - top: yPosition, - left: xPosition, - child: GestureDetector( - onPanUpdate: (tapInfo) { - setState(() { - xPosition += tapInfo.delta.dx; - yPosition += tapInfo.delta.dy; - }); - var data = Instruction( - id: widget.instruction.id, - top: yPosition, - left: xPosition, - text: _textFieldController.text, - ); - manualModel.saveInstruction(widget.manIndex, widget.slideIndex, - widget.instIndex, data, widget.instruction, widget.isEng); - }, - child: Container( - width: 250, - color: Colors.grey, - child: InkWell( - onTap: () { - _displayDialog(context, manualModel); - }, - child: Container( - child: Text( - _textFieldController.text, - maxLines: null, - style: - TextStyle(fontSize: 15.0, fontWeight: FontWeight.w700), - ))))), - ); - } - - _displayDialog(BuildContext context, ManualModel manualModel) async { - return showDialog( - context: context, - builder: (context) { - return AlertDialog( - title: new Text('Instruction'), - content: Container( - height: 100, - child: Column( - children: [ - TextField( - controller: _textFieldController, - decoration: InputDecoration(hintText: "Enter Instruction"), - maxLines: null, - style: TextStyle(fontSize: 13.0), - ), - ], - ), - ), - actions: [ - new FlatButton( - onPressed: () { - var data = Instruction( - id: widget.instruction.id, - top: yPosition, - left: xPosition, - text: _textFieldController.text, - ); - manualModel.saveInstruction( - widget.manIndex, - widget.slideIndex, - widget.instIndex, - data, - widget.instruction, - widget.isEng); - Navigator.pop(context); - }, - child: new Text('Save')) - ], - ); - }); - } -} diff --git a/lib/pages/manual/slide_data_page.dart b/lib/pages/manual/slide_data_page.dart deleted file mode 100644 index 4325f25..0000000 --- a/lib/pages/manual/slide_data_page.dart +++ /dev/null @@ -1,210 +0,0 @@ -import 'dart:io'; -import 'dart:typed_data'; - -import 'package:flutter/material.dart'; -import 'package:image_picker/image_picker.dart'; -import 'package:path/path.dart' as Path; -import 'package:provider/provider.dart'; -import 'package:fcs/model/manual_model.dart'; -import 'package:fcs/pages/manual/instruction_data_page.dart'; -import 'package:fcs/vo/manual.dart'; -import 'package:fcs/widget/img_file.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/progress.dart'; - -class SlideDataPage extends StatefulWidget { - final ManualItem manItem; - final int manIndex; - - SlideDataPage({this.manItem, this.manIndex}); - @override - _SlideDataPageState createState() => _SlideDataPageState(); -} - -class _SlideDataPageState extends State { - File slideImageFile; - List slideList = []; - List _initSlideList = []; - File imageFile; - File engImgFile; - File mmImgFile; - bool _isLoading = false; - - @override - void initState() { - super.initState(); - } - - pickImageFromGallery(ImageSource source, ManualModel manualModel) async { - File tempImage = await ImagePicker.pickImage( - source: source, imageQuality: 80, maxWidth: 300); - - var fileName = Path.basename(tempImage.path); - var path = '${manualModel.dataDir}'; - File newImage = await tempImage.copy('$path/manual/img/$fileName'); - var slideData = - SlideData(id: slideList.length, image: fileName, instructions: []); - setState(() { - slideList.add(slideData); - }); - // manualModel.saveSlideData(widget.manIndex, slideList.length, slideData); - } - - @override - Widget build(BuildContext context) { - var manualModel = Provider.of(context); - slideList = manualModel.getSlideList(widget.manIndex); - - final engImgBox = Container( - padding: EdgeInsets.only(left: 20), - child: Column(children: [ - Text('English image'), - ImageFile( - imageSource: ImageSource.gallery, - enabled: true, - title: "Image", - onFile: (file) { - engImgFile = file; - }) - ])); - - final mmImgBox = Container( - padding: EdgeInsets.only(left: 20, top: 20), - child: Column(children: [ - Text('Myanmar image'), - ImageFile( - imageSource: ImageSource.gallery, - enabled: true, - title: "Image", - onFile: (file) { - mmImgFile = file; - }), - ])); - - final saveImages = Container( - padding: EdgeInsets.only(left: 20, top: 20), - child: FlatButton( - onPressed: () { - saveSlideImages(context, manualModel, widget.manIndex); - }, - child: Text('Save'))); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - title: Text('Slide Data'), - ), - body: Container( - child: GridView.builder( - itemCount: slideList.length, - itemBuilder: (BuildContext context, int index) { - return Card( - child: InkWell( - onTap: () => { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => InstructionDataPage( - slideData: slideList[index], - path: manualModel.dataDir, - slideIndex: index, - manIndex: widget.manIndex, - ))) - }, - child: Container( - child: Stack( - fit: StackFit.expand, - children: [ - Image.file(File('${manualModel.dataDir}/manual/img/' + - slideList[index].image)), - Positioned( - top: 0, - right: 0, - child: IconButton( - icon: Icon(Icons.delete), - onPressed: () { - setState(() { - manualModel.deleteSlideData( - widget.manIndex, slideList[index]); - }); - }), - ) - ], - ), - ), - ), - ); - }, - gridDelegate: - SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2), - ), - ), - floatingActionButton: FloatingActionButton( - onPressed: () async => await _dialog( - context, manualModel, engImgBox, mmImgBox, saveImages), - tooltip: 'Pick Image', - child: Icon(Icons.add), - ), - ), - ); - } - - Future _dialog(BuildContext context, ManualModel manualModel, - Widget engImg, Widget mmImg, Widget saveImgs) { - return showDialog( - context: context, - builder: (BuildContext context) { - return AlertDialog( - content: Container( - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - Column( - mainAxisSize: MainAxisSize.min, - children: [engImg, mmImg, saveImgs], - ), - ], - ), - ), - ), - ); - }, - ); - } - - saveSlideImages( - BuildContext context, ManualModel manualModel, int manIndex) async { - var engFileName = Path.basename(engImgFile.path); - var mmFileName = Path.basename(mmImgFile.path); - var path = '${manualModel.dataDir}'; - File engImage = await engImgFile.copy('$path/manual/img/$engFileName'); - File mmImage = await mmImgFile.copy('$path/manual/img/$mmFileName'); - var length = slideList.toList().length; - - var slideData; - if (length == 0) { - slideData = SlideData( - id: 1, - image: engFileName, - imagemm: mmFileName, - instructions: [], - instructionsmm: []); - } else { - dynamic max = slideList.first; - slideList.forEach((e) { - if (e.id > max.id) max = e; - }); - slideData = SlideData( - id: max.id + 1, - image: engFileName, - imagemm: mmFileName, - instructions: [], - instructionsmm: []); - } - manualModel.saveSlideData(manIndex, length, slideData); - Navigator.pop(context); - } -} diff --git a/lib/pages/manual/slide_page.dart b/lib/pages/manual/slide_page.dart deleted file mode 100644 index 484337f..0000000 --- a/lib/pages/manual/slide_page.dart +++ /dev/null @@ -1,249 +0,0 @@ -import 'dart:io'; - -import 'package:flutter/material.dart'; -import 'package:flutter/widgets.dart'; -import 'package:introduction_screen/introduction_screen.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/language_model.dart'; -import 'package:fcs/model/main_model.dart'; -import 'package:fcs/model/manual_model.dart'; -import 'package:fcs/pages/manual/slide_data_page.dart'; -import 'package:fcs/vo/manual.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/progress.dart'; - -class SlidePage extends StatefulWidget { - final ManualItem helpDetail; - final int index; - - SlidePage({this.helpDetail, this.index}); - @override - _SlidePageState createState() => _SlidePageState(); -} - -class _SlidePageState extends State { - bool isEng; - bool _isLoading = false; - - void _onIntroEnd(context) { - Navigator.pop(context); - } - - List instructionText(BuildContext context, isEng, image, imgHeight, - width, List instructions) { - List list = new List(); - var imgWidth = width - (width * 0.25); - File imgFile = File(image); - - list.add( - Card( - color: const Color(0x7f7c94b6), - child: Opacity( - opacity: 0.6, - child: Image.file( - imgFile, - alignment: AlignmentDirectional.topCenter, - height: imgHeight, - width: imgWidth, - )), - ), - ); - - for (var i = 0; i < instructions.length; i++) { - var instruction = instructions[i]; - var textPositionTop = (imgHeight / 480) * instruction.top; - var textPositionLeft = (imgWidth / 360) * instruction.left; - - list.add(Positioned( - top: double.parse(textPositionTop.toString()), - left: double.parse(textPositionLeft.toString()), - child: instruction.text.length > 1 - ? Container( - constraints: BoxConstraints(maxWidth: 300), - child: Card( - color: Colors.blue, - child: Padding( - padding: const EdgeInsets.all(3.0), - child: Text( - instruction.text, - style: TextStyle(color: Colors.white), - ), - ), - )) - : Container( - constraints: BoxConstraints(maxWidth: 200), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Container( - alignment: Alignment.topCenter, - width: 30, - height: 30, - decoration: BoxDecoration( - shape: BoxShape.circle, color: Colors.blue), - child: isEng - ? Container( - padding: EdgeInsets.only(top: 5), - child: Text( - instruction.text, - textAlign: TextAlign.center, - style: TextStyle( - color: Colors.white, fontSize: 14.0), - ), - ) - : Text( - instruction.text, - textAlign: TextAlign.center, - style: TextStyle( - color: Colors.white, fontSize: 14.0), - ), - ), - ], - ), - ), - )); - } - return list; - } - - @override - Widget build(BuildContext context) { - var mainModel = Provider.of(context); - var languageModel = Provider.of(context); - var manualModel = Provider.of(context); - isEng = languageModel.isEng; - - List pageViews = new List(); - var screenSize = MediaQuery.of(context).size; - var width = screenSize.width; - var height = screenSize.height; - var imgHeight = height - (height * 0.25); - const bodyStyle = TextStyle(fontSize: 19.0); - const pageDecoration = const PageDecoration( - titleTextStyle: TextStyle(fontSize: 28.0, fontWeight: FontWeight.w700), - bodyTextStyle: bodyStyle, - descriptionPadding: EdgeInsets.fromLTRB(16.0, 0.0, 16.0, 16.0), - pageColor: Colors.white, - imagePadding: EdgeInsets.zero, - ); - - var pageSlides = widget.helpDetail.slides; - - if (pageSlides.length == 0) { - pageViews.add( - PageViewModel( - titleWidget: Row( - children: [ - Text( - isEng ? widget.helpDetail.title : widget.helpDetail.titlemm, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 20, - color: Colors.black, - ), - ), - mainModel.isSysAdmin() - ? FlatButton( - textColor: Colors.blue, - onPressed: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => SlideDataPage( - manItem: widget.helpDetail, - manIndex: widget.index)), - ); - }, - child: Icon(Icons.edit), - shape: CircleBorder( - side: BorderSide(color: Colors.transparent)), - ) - : Container(), - ], - ), - bodyWidget: Container( - width: width, - alignment: Alignment.center, - ), - decoration: pageDecoration), - ); - } - - for (var i = 0; i < pageSlides.length; i++) { - var instructions; - if (isEng) { - instructions = pageSlides[i].instructions; - } else { - instructions = pageSlides[i].instructionsmm; - } - - var imageName; - if (isEng) { - imageName = '${manualModel.dataDir}/manual/img/' + pageSlides[i].image; - } else { - imageName = - '${manualModel.dataDir}/manual/img/' + pageSlides[i].imagemm; - } - - pageViews.add( - PageViewModel( - titleWidget: Row( - children: [ - Text( - isEng ? widget.helpDetail.title : widget.helpDetail.titlemm, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 20, - color: Colors.black, - ), - ), - mainModel.isSysAdmin() - ? FlatButton( - textColor: Colors.blue, - onPressed: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => SlideDataPage( - manItem: widget.helpDetail, - manIndex: widget.index)), - ); - }, - child: Icon(Icons.edit), - shape: CircleBorder( - side: BorderSide(color: Colors.transparent)), - ) - : Container(), - ], - ), - bodyWidget: Container( - width: width, - alignment: Alignment.center, - child: Stack( - alignment: AlignmentDirectional.topStart, - children: instructionText( - context, isEng, imageName, imgHeight, width, instructions), - ), - ), - decoration: pageDecoration), - ); - } - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - body: IntroductionScreen( - pages: pageViews, - onDone: () => _onIntroEnd(context), - showSkipButton: true, - skipFlex: 0, - nextFlex: 0, - skip: const Text('Skip'), - next: const Icon(Icons.arrow_forward), - done: const Text('Done', style: TextStyle(fontWeight: FontWeight.w600)), - dotsDecorator: DotsDecorator(spacing: EdgeInsets.all(1.0)), - )), - ); - } -} diff --git a/lib/fcs/common/pages/market/market_editor.dart b/lib/pages/market/market_editor.dart similarity index 90% rename from lib/fcs/common/pages/market/market_editor.dart rename to lib/pages/market/market_editor.dart index 0cf6618..9ab9717 100644 --- a/lib/fcs/common/pages/market/market_editor.dart +++ b/lib/pages/market/market_editor.dart @@ -1,10 +1,11 @@ -import 'package:fcs/fcs/common/domain/entities/market.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/fcs/common/pages/market/model/market_model.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/fcs/common/pages/widgets/input_text.dart'; -import 'package:fcs/fcs/common/pages/widgets/local_text.dart'; -import 'package:fcs/fcs/common/pages/widgets/progress.dart'; +import 'package:fcs/domain/entities/market.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/market/model/market_model.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/widgets/input_text.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; @@ -60,7 +61,7 @@ class _MarketEditorState extends State { appBar: AppBar( centerTitle: true, leading: new IconButton( - icon: new Icon(Icons.close, color: primaryColor, size: 30), + icon: new Icon(CupertinoIcons.back, color: primaryColor, size: 30), onPressed: () => Navigator.of(context).pop(), ), shadowColor: Colors.transparent, diff --git a/lib/fcs/common/pages/market/model/market_model.dart b/lib/pages/market/model/market_model.dart similarity index 75% rename from lib/fcs/common/pages/market/model/market_model.dart rename to lib/pages/market/model/market_model.dart index 4aa0d9d..c97cbdb 100644 --- a/lib/fcs/common/pages/market/model/market_model.dart +++ b/lib/pages/market/model/market_model.dart @@ -1,10 +1,10 @@ import 'dart:async'; import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:fcs/fcs/common/domain/constants.dart'; -import 'package:fcs/fcs/common/domain/entities/market.dart'; -import 'package:fcs/fcs/common/helpers/firebase_helper.dart'; -import 'package:fcs/fcs/common/pages/model/base_model.dart'; +import 'package:fcs/domain/constants.dart'; +import 'package:fcs/domain/entities/market.dart'; +import 'package:fcs/helpers/firebase_helper.dart'; +import 'package:fcs/pages/main/model/base_model.dart'; import 'package:logging/logging.dart'; class MarketModel extends BaseModel { @@ -12,19 +12,11 @@ class MarketModel extends BaseModel { StreamSubscription listener; List markets = []; - void initUser(user) async { - super.initUser(user); + MarketModel() { _loadMarkets(); } - @override - logout() async { - markets = []; - } - Future _loadMarkets() async { - if (user == null || !user.hasStaffs()) return; - try { if (listener != null) listener.cancel(); diff --git a/lib/pages/message_detail.dart b/lib/pages/message_detail.dart deleted file mode 100644 index 5598fb0..0000000 --- a/lib/pages/message_detail.dart +++ /dev/null @@ -1,140 +0,0 @@ -import 'package:fcs/model_fcs/message_model.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/message.dart'; -import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; - -class Bubble extends StatelessWidget { - Bubble({this.message, this.time, this.delivered, this.isMe}); - - final String message, time; - final delivered, isMe; - - @override - Widget build(BuildContext context) { - final bg = isMe ? Colors.white : Colors.greenAccent.shade100; - final align = isMe ? CrossAxisAlignment.start : CrossAxisAlignment.end; - final icon = delivered ? Icons.done_all : Icons.done; - final radius = isMe - ? BorderRadius.only( - topRight: Radius.circular(5.0), - bottomLeft: Radius.circular(10.0), - bottomRight: Radius.circular(5.0), - ) - : BorderRadius.only( - topLeft: Radius.circular(5.0), - bottomLeft: Radius.circular(5.0), - bottomRight: Radius.circular(10.0), - ); - return Column( - crossAxisAlignment: align, - children: [ - Container( - margin: const EdgeInsets.all(3.0), - padding: const EdgeInsets.all(8.0), - decoration: BoxDecoration( - boxShadow: [ - BoxShadow( - blurRadius: .5, - spreadRadius: 1.0, - color: Colors.black.withOpacity(.12)) - ], - color: bg, - borderRadius: radius, - ), - child: Stack( - children: [ - Padding( - padding: EdgeInsets.only(right: 48.0), - child: Text(message), - ), - Positioned( - bottom: 0.0, - right: 0.0, - child: Row( - children: [ - Text(time, - style: TextStyle( - color: Colors.black38, - fontSize: 10.0, - )), - SizedBox(width: 3.0), - Icon( - icon, - size: 12.0, - color: Colors.black38, - ) - ], - ), - ) - ], - ), - ) - ], - ); - } -} - -class MessageDetail extends StatelessWidget { - final Message msg; - const MessageDetail({Key key, this.msg}) : super(key: key); - - @override - Widget build(BuildContext context) { - DateFormat dateFormat = DateFormat("HH:mm"); - MessageModel messageModel = Provider.of(context); - List messages = messageModel.getMessage(msg.receiverName); - List bubbles = messages - .map((e) => Bubble( - message: e.message, - time: dateFormat.format(e.date), - delivered: true, - isMe: !(e.isMe != null ? e.isMe : true))) - .toList(); - - return Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - elevation: .9, - title: Text( - msg.receiverName, - ), - actions: [], - ), - body: Padding( - padding: EdgeInsets.all(16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: bubbles, - // children: [ - // Bubble( - // message: 'Hi there, this is a message', - // time: '12:00', - // delivered: true, - // isMe: false, - // ), - // Bubble( - // message: 'Whatsapp like bubble talk', - // time: '12:01', - // delivered: true, - // isMe: true, - // ), - // Bubble( - // message: 'Nice one, Flutter is awesome', - // time: '12:00', - // delivered: true, - // isMe: true, - // ), - // Bubble( - // message: 'I\'ve told you so dude!', - // time: '12:00', - // delivered: true, - // isMe: false, - // ), - // ], - ), - ), - ); - } -} diff --git a/lib/pages/my_registeration.dart b/lib/pages/my_registeration.dart deleted file mode 100644 index da886aa..0000000 --- a/lib/pages/my_registeration.dart +++ /dev/null @@ -1,316 +0,0 @@ -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/language_model.dart'; -import 'package:fcs/model/reg_model.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/vo/buyer.dart'; -import 'package:fcs/widget/img_file.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/my_data_table.dart'; -import 'package:fcs/widget/progress.dart'; - -import '../fcs/common/helpers/theme.dart'; -import '../widget/localization/app_translations.dart'; -import 'my_registeration_item.dart'; - -enum BuyerType { shop, agent } - -class MyRegisteration extends StatefulWidget { - final Buyer buyer; - const MyRegisteration({this.buyer}); - @override - _MyRegisterationState createState() => _MyRegisterationState(); -} - -class _MyRegisterationState extends State { - TextEditingController _bizName = new TextEditingController(); - TextEditingController _bizAddress = new TextEditingController(); - BuyerType buyerType; - Buyer buyer = Buyer(); - final formKey = GlobalKey(); - bool _isLoading = false; - Attachments attachments = Attachments(); - bool _isNew = true; - - @override - void initState() { - if (widget.buyer != null) { - _isNew = false; - buyerType = - widget.buyer.bizType == "shop" ? BuyerType.shop : BuyerType.agent; - buyer = widget.buyer; - _bizName.text = buyer.bizName; - _bizAddress.text = buyer.bizAddress; - } else { - buyerType = BuyerType.shop; - } - super.initState(); - } - - @override - void dispose() { - super.dispose(); - } - - @override - Widget build(BuildContext context) { - var languageModel = Provider.of(context); - - final companyName = Container( - padding: EdgeInsets.only(top: 0, left: 20, right: 15), - child: TextFormField( - controller: _bizName, - autofocus: false, - cursorColor: primaryColor, - style: textStyle, - decoration: new InputDecoration( - labelText: AppTranslations.of(context).text("reg.biz_name"), - labelStyle: languageModel.isEng ? labelStyle : labelStyleMM, - icon: Icon( - Icons.business, - color: primaryColor, - ), - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - ), - validator: _validateBizName, - )); - - final companyAddress = Container( - padding: EdgeInsets.only(top: 0, left: 20, right: 15), - child: TextFormField( - minLines: 2, - maxLines: 3, - controller: _bizAddress, - autofocus: false, - cursorColor: primaryColor, - style: textStyle, - decoration: new InputDecoration( - labelText: AppTranslations.of(context).text("reg.biz_address"), - labelStyle: languageModel.isEng ? labelStyle : labelStyleMM, - icon: Image.asset( - "assets/address.png", - height: 25, - color: primaryColor, - ), - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - ), - validator: _validateBizAddress, - )); - - final nricFrontBox = Container( - padding: EdgeInsets.only(left: 20), - child: Row(children: [ - LocalText(context, 'reg_info.nric_front'), - ImageFile( - enabled: true, - initialImgUrl: - widget.buyer == null ? "" : widget.buyer.nricFrontUrl, - title: "Image", - onFile: (file) { - attachments.nricFront = file; - }) - ])); - - final nricBackBox = Container( - padding: EdgeInsets.only(left: 20, top: 20), - child: Row(children: [ - LocalText(context, 'reg_info.nric_back'), - ImageFile( - enabled: true, - initialImgUrl: - widget.buyer == null ? '' : widget.buyer.nricBackUrl, - title: "Image", - onFile: (file) { - attachments.nricBack = file; - }), - ])); - final nric = Container( - padding: EdgeInsets.only(top: 20, left: 20, right: 15), - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - children: [nricFrontBox, nricBackBox], - )); - - final buyerTypeWidget = Row(children: [ - Flexible( - child: ListTile( - onTap: () => setState(() { - buyerType = BuyerType.shop; - }), - title: Text(AppTranslations.of(context).text("reg.type_shop")), - leading: Radio( - activeColor: primaryColor, - value: BuyerType.shop, - groupValue: buyerType, - onChanged: (BuyerType value) { - setState(() { - buyerType = value; - }); - }, - ), - ), - ), - Flexible( - child: ListTile( - onTap: () => setState(() { - buyerType = BuyerType.agent; - }), - title: Text(AppTranslations.of(context).text("reg.type_agent")), - leading: Radio( - activeColor: primaryColor, - value: BuyerType.agent, - groupValue: buyerType, - onChanged: (BuyerType value) { - setState(() { - buyerType = value; - }); - }, - ), - ), - ), - ]); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - title: Text(AppTranslations.of(context).text("reg.title")), - actions: [ - IconButton( - icon: Icon(Icons.send), - onPressed: () { - showConfirmDialog(context, "reg.confirm", () { - _submit(); - }); - }, - ) - ], - ), - body: Container( - child: Form( - key: formKey, - child: ListView( - children: [ - companyName, - companyAddress, - buyerTypeWidget, - nric, - ], - ), - ), - ), - ), - ); - } - - List getProductRow(Buyer buyer) { - return buyer.buyerProducts.map((b) { - return MyDataRow( - onSelectChanged: (bool selected) async { - final BuyerProduct buyerProduct = await Navigator.push( - context, - MaterialPageRoute( - builder: (context) => MyRegisterationItem( - buyerProduct: b, - )), - ); - _save(buyerProduct); - }, - cells: [ - MyDataCell( - new Text( - b.productName, - style: textStyle, - ), - ), - MyDataCell( - new Text(b.storageCapacityQty.toString(), style: textStyle), - ), - MyDataCell( - new Text(b.dailySaleQty.toString(), style: textStyle), - ), - ], - ); - }).toList(); - } - - String _validateBizName(value) { - if (value.isEmpty) { - return AppTranslations.of(context).text("reg.empty_biz_name"); - } - return null; - } - - String _validateBizAddress(value) { - if (value.isEmpty) { - return AppTranslations.of(context).text("reg.empty_biz_address"); - } - return null; - } - - String _validateShops(value) { - if (value.isEmpty) { - return AppTranslations.of(context).text("reg.empty_shops"); - } - return null; - } - - _save(BuyerProduct buyerProduct) { - if (buyerProduct == null) return; - if (buyerProduct.action == "create") { - if (buyer.buyerProducts.contains(buyerProduct)) { - showMsgDialog(context, "Error", "Duplicate line"); - return; - } - buyer.buyerProducts.add(buyerProduct); - } else if (buyerProduct.action == "delete") { - buyer.buyerProducts.remove(buyerProduct); - } - } - - _submit() async { - if (!formKey.currentState.validate()) { - return; - } - - if (_isNew) { - if (attachments.nricFront == null || attachments.nricBack == null) { - showMsgDialog( - context, "Error", "Required NRIC front and back attachments"); - return; - } - } - - setState(() { - _isLoading = true; - }); - try { - String type = buyerType == BuyerType.agent ? "agent" : "shop"; - - buyer.bizName = _bizName.text; - buyer.bizAddress = _bizAddress.text; - buyer.bizType = type; - - if (_isNew) { - await Provider.of(context).register(buyer, attachments); - } else { - await Provider.of(context).update(buyer, attachments); - } - Navigator.pop(context, true); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - setState(() { - _isLoading = false; - }); - } - } -} diff --git a/lib/pages/my_registeration_info.dart b/lib/pages/my_registeration_info.dart deleted file mode 100644 index 9152366..0000000 --- a/lib/pages/my_registeration_info.dart +++ /dev/null @@ -1,121 +0,0 @@ -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/main_model.dart'; -import 'package:fcs/model/reg_model.dart'; -import 'package:fcs/widget/label_widgets.dart'; -import 'package:fcs/widget/progress.dart'; - -import '../fcs/common/helpers/theme.dart'; -import '../util.dart'; -import '../widget/localization/app_translations.dart'; -import 'my_registeration.dart'; - -enum BuyerType { shop, agent } - -class MyRegisterationInfo extends StatefulWidget { - @override - _MyRegisterationInfoState createState() => _MyRegisterationInfoState(); -} - -class _MyRegisterationInfoState extends State { - bool inProgress = true; - - BuyerType buyerType = BuyerType.shop; - TextEditingController _bizName = new TextEditingController(); - TextEditingController _bizAddress = new TextEditingController(); - TextEditingController _status = new TextEditingController(); - - @override - Widget build(BuildContext context) { - RegModel regModel = Provider.of(context); - MainModel mainModel = Provider.of(context); - buyerType = - regModel.reg.bizType == "shop" ? BuyerType.shop : BuyerType.agent; - _bizName.text = regModel.reg.bizName; - _bizAddress.text = regModel.reg.bizAddress; - _status.text = regModel.reg.status; - bool isRegBuyer = mainModel.isRegBuyer(); - if (regModel.isLoaded) { - setState(() { - this.inProgress = false; - }); - } - - final bizNameBox = - labeledText(context, regModel.reg.bizName, "reg.biz_name"); - final bizAddressBox = - labeledText(context, regModel.reg.bizAddress, "reg.biz_address"); - final typeBox = - labeledText(context, regModel.reg.bizType, "buyer.type_biz"); - final statusBox = labeledText(context, regModel.reg.status, "reg.status"); - final dailyQuotaBox = labeledText( - context, formatNumber(regModel.reg.dailyQuota), "reg.quota", - number: true); - final dailyQuotaUsedBox = labeledText( - context, formatNumber(regModel.reg.dailyQuotaUsed), "reg.quota.used", - number: true); - final maxQuotaBox = labeledText( - context, formatNumber(regModel.reg.maxQuota), "reg.max_quota", - number: true); - final maxQuotaUsedBox = labeledText( - context, formatNumber(regModel.reg.maxQuotaUsed), "reg.max_quota.used", - number: true); - final nricFrontBox = - labeledImg(context, regModel.reg.nricFrontUrl, "reg_info.nric_front"); - final nricBackBox = - labeledImg(context, regModel.reg.nricBackUrl, "reg_info.nric_back"); - - return LocalProgress( - inAsyncCall: inProgress, - child: Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - title: Text(AppTranslations.of(context).text("reg_info.title")), - actions: [ - !isRegBuyer - ? Container() - : regModel.reg.isApproved() - ? Container() - : IconButton( - icon: Icon(Icons.edit), - onPressed: () { - Navigator.of(context).push(MaterialPageRoute( - builder: (_) => MyRegisteration( - buyer: regModel.reg, - ))); - }, - ), - ], - ), - body: Container( - padding: EdgeInsets.only(left: 10, right: 10, top: 10, bottom: 10), - child: ListView( - children: [ - bizNameBox, - Divider(), - bizAddressBox, - Divider(), - typeBox, - Divider(), - statusBox, - Divider(), - dailyQuotaBox, - Divider(), - dailyQuotaUsedBox, - Divider(), - maxQuotaBox, - Divider(), - maxQuotaUsedBox, - Divider(), - nricFrontBox, - Divider(), - nricBackBox, - Divider() - ], - ), - ), - ), - ); - } -} diff --git a/lib/pages/my_registeration_item.dart b/lib/pages/my_registeration_item.dart deleted file mode 100644 index c7f76fd..0000000 --- a/lib/pages/my_registeration_item.dart +++ /dev/null @@ -1,194 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/product_model.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/buyer.dart'; -import 'package:fcs/vo/product.dart'; -import 'package:fcs/widget/progress.dart'; - -class MyRegisterationItem extends StatefulWidget { - final BuyerProduct buyerProduct; - const MyRegisterationItem({Key key, this.buyerProduct}) : super(key: key); - @override - _MyRegisterationItemState createState() => _MyRegisterationItemState(); -} - -class _MyRegisterationItemState extends State { - final _formKey = GlobalKey(); - bool _isLoading = false; - TextEditingController _storage = new TextEditingController(); - TextEditingController _sales = new TextEditingController(); - String currentProductID; - BuyerProduct buyerProduct = BuyerProduct(action: "create"); - - @override - void initState() { - super.initState(); - if (widget.buyerProduct != null) { - buyerProduct = widget.buyerProduct; - buyerProduct.action = "update"; - currentProductID = buyerProduct.productID; - _sales.text = buyerProduct.dailySaleQty.toString(); - _storage.text = buyerProduct.storageCapacityQty.toString(); - } - } - - Widget showProducts(BuildContext context, ProductModel productModel) { - return Row( - mainAxisSize: MainAxisSize.max, - children: [ - Icon( - FontAwesomeIcons.tag, - color: primaryColor, - size: 20, - ), - SizedBox( - width: 20, - ), - new Flexible( - child: Container( - width: 170.0, - child: DropdownButton( - value: currentProductID, - isExpanded: true, - hint: Text( - 'Select Product', - style: labelStyle, - ), - onChanged: changedProduct, - items: productModel.products - .map>((Product product) { - return new DropdownMenuItem( - value: product.id, - child: new Text(product.name, style: textStyle), - ); - }).toList(), - ), - ), - ), - ], - ); - } - - void changedProduct(selected) { - setState(() { - currentProductID = selected; - }); - } - - @override - Widget build(BuildContext context) { - ProductModel productModel = Provider.of(context); - - final volumeBox = Container( - padding: EdgeInsets.only(top: 10), - child: TextFormField( - controller: _storage, - autofocus: false, - cursorColor: primaryColor, - keyboardType: TextInputType.number, - decoration: new InputDecoration( - labelText: "Enter total storage capacity", - labelStyle: labelStyle, - icon: Image.asset( - "assets/volume.png", - width: 23, - color: primaryColor, - ), - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - ), - validator: (value) { - if (value.isEmpty) { - return "Please total storage capacity"; - } - return null; - }, - ), - ); - final amountBox = Container( - child: TextFormField( - controller: _sales, - autofocus: false, - cursorColor: primaryColor, - keyboardType: TextInputType.number, - decoration: new InputDecoration( - labelText: "Enter daily sale quantity", - labelStyle: labelStyle, - icon: Image.asset( - "assets/sales.png", - width: 23, - color: primaryColor, - ), - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - ), - validator: (value) { - if (value.isEmpty) { - return "Please enter daily sale quantity"; - } - return null; - }, - ), - ); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - title: Text("Product registration"), - actions: [ - IconButton( - icon: Icon(Icons.delete), - onPressed: () { - buyerProduct.action = "delete"; - Navigator.pop(context, buyerProduct); - }, - ), - IconButton( - icon: Icon(Icons.save), - onPressed: () { - if (!_formKey.currentState.validate()) return; - _save(); - }, - ) - ], - ), - body: Form( - key: _formKey, - child: Column( - children: [ - Expanded( - child: ListView( - shrinkWrap: true, - padding: EdgeInsets.only(left: 24.0, right: 24.0), - children: [ - showProducts(context, productModel), - volumeBox, - amountBox, - ], - ), - ), - ], - ), - )), - ); - } - - _save() { - if (currentProductID == null) return; - this.buyerProduct.productID = currentProductID; - var productName = - Provider.of(context).getProductName(currentProductID); - this.buyerProduct.productName = productName; - this.buyerProduct.storageCapacityQty = int.parse(_storage.text); - this.buyerProduct.dailySaleQty = int.parse(_sales.text); - Navigator.pop(context, this.buyerProduct); - } -} diff --git a/lib/pages/notification_list.dart b/lib/pages/notification_list.dart deleted file mode 100644 index fe4c8b9..0000000 --- a/lib/pages/notification_list.dart +++ /dev/null @@ -1,131 +0,0 @@ -import 'package:fcs/model_fcs/message_model.dart'; -import 'package:fcs/pages/message_detail.dart'; -import 'package:fcs/vo/message.dart'; -import 'package:fcs/widget/bottom_up_page_route.dart'; -import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/notification_model.dart'; -import 'package:fcs/vo/notification.dart' as Noti; -import 'package:fcs/widget/progress.dart'; - -import '../fcs/common/helpers/theme.dart'; -import '../widget/local_text.dart'; - -class NotificationList extends StatefulWidget { - @override - _NotificationListState createState() => _NotificationListState(); -} - -class _NotificationListState extends State { - var timeFormatter = new DateFormat('KK:mm a'); - var dateFormatter = new DateFormat('dd MMM yyyy'); - final double dotSize = 25.0; - int _selectedIndex = 0; - bool _isLoading = false; - bool _isClicked = false; - - @override - Widget build(BuildContext context) { - MessageModel messageModel = Provider.of(context); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - centerTitle: true, - leading: new IconButton( - icon: new Icon( - Icons.close, - ), - onPressed: () => Navigator.of(context).pop(), - ), - backgroundColor: primaryColor, - title: LocalText( - context, - 'message.title', - fontSize: 20, - color: Colors.white, - ), - ), - body: new ListView.separated( - separatorBuilder: (context, index) => Divider( - color: Colors.black, - ), - scrollDirection: Axis.vertical, - padding: EdgeInsets.only(top: 5), - shrinkWrap: true, - itemCount: messageModel.lastMessage.length, - itemBuilder: (BuildContext context, int index) { - Message msg = messageModel.lastMessage[index]; - return Stack( - children: [ - InkWell( - onTap: () => _display(msg), - child: Row( - children: [ - Expanded( - child: new Padding( - padding: const EdgeInsets.symmetric(vertical: 10.0), - child: new Row( - children: [ - new Padding( - padding: new EdgeInsets.symmetric( - horizontal: 22.0 - dotSize / 2), - child: Icon( - Icons.account_circle, - color: primaryColor, - size: 60, - ), - ), - new Expanded( - child: new Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - new Text( - msg.receiverName, - style: new TextStyle(fontSize: 15.0), - ), - ], - ), - ), - ], - ), - ), - ), - Padding( - padding: const EdgeInsets.only(right: 18.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: Text( - timeFormatter.format(msg.date), - style: TextStyle(color: Colors.grey), - ), - ), - msg.fromToday() - ? Container() - : Text( - dateFormatter.format(msg.date), - style: TextStyle(color: Colors.grey), - ), - ], - ), - ) - ], - ), - ), - ], - ); - }), - ), - ); - } - - _display(Message msg) { - Navigator.push(context, BottomUpPageRoute(MessageDetail(msg: msg))); - } -} diff --git a/lib/pages/offline.dart b/lib/pages/offline.dart deleted file mode 100644 index 69d0ae6..0000000 --- a/lib/pages/offline.dart +++ /dev/null @@ -1,33 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:fcs/widget/local_text.dart'; - - -class Offline extends StatefulWidget { - @override - _OfflineState createState() => _OfflineState(); -} - -class _OfflineState extends State { - - @override - Widget build(BuildContext context) { - final retryButton = Card( - elevation: 23, - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon(Icons.offline_bolt), - LocalText(context, "offline.status"), - ], - ), - ), - ); - - return Scaffold( - body: Center(child: retryButton), - ); - } -} diff --git a/lib/pages/package/model/package_model.dart b/lib/pages/package/model/package_model.dart new file mode 100644 index 0000000..f1608d6 --- /dev/null +++ b/lib/pages/package/model/package_model.dart @@ -0,0 +1,294 @@ +import 'dart:async'; +import 'dart:io'; + +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:fcs/data/services/services.dart'; +import 'package:fcs/domain/constants.dart'; +import 'package:fcs/domain/entities/package.dart'; +import 'package:fcs/domain/entities/user.dart'; +import 'package:fcs/domain/vo/delivery_address.dart'; +import 'package:fcs/domain/vo/message.dart'; +import 'package:fcs/helpers/firebase_helper.dart'; +import 'package:fcs/helpers/paginator.dart'; +import 'package:fcs/pages/main/model/base_model.dart'; +import 'package:logging/logging.dart'; +import 'package:path/path.dart' as Path; + +class PackageModel extends BaseModel { + final log = Logger('PackageModel'); + + StreamSubscription listener; + + List get packages => _menuSelectedIndex == 1 + ? _packages + : List.from(_delivered.values); + + List _packages = []; + + Paginator _delivered; + bool isLoading = false; + int _menuSelectedIndex = 1; + + set menuSelectedIndex(int index) { + _menuSelectedIndex = index; + notifyListeners(); + } + + get menuSelectedIndex => _menuSelectedIndex; + + initData(bool forCustomer) { + logout(); + _menuSelectedIndex = 1; + _loadPackages(forCustomer); + _delivered = _getDelivered(forCustomer); + _delivered.load(); + } + + @override + logout() async { + if (_delivered != null) _delivered.close(); + if (listener != null) await listener.cancel(); + _packages = []; + } + + Future loadMore({bool isCustomer}) async { + if (_delivered.ended || menuSelectedIndex == 1) + return; // when delivered menu is not selected return + isLoading = true; + notifyListeners(); + await _delivered.load(onFinished: () { + isLoading = false; + notifyListeners(); + }); + } + + Future refresh({bool isCustomer}) async { + if (menuSelectedIndex == 1) + return; // when delivered menu is not selected return + await _delivered.refresh(onFinished: () { + notifyListeners(); + }); + } + + Paginator _getDelivered(bool isCustomer) { + if (!isCustomer) { + if (user == null || + !((user.hasPackages() || + user.hasReceiving() || + user.hasProcessing()))) throw "No privilege"; + } + var pageQuery = Firestore.instance + .collection("/$packages_collection") + .where("is_delivered", isEqualTo: true) + .where("is_deleted", isEqualTo: false); + if (isCustomer) { + pageQuery = pageQuery.where("user_id", isEqualTo: user.id); + } + pageQuery = pageQuery.orderBy("status_date", descending: true); + var paginator = new Paginator(pageQuery, rowPerLoad: 20, toObj: (data, id) { + return Package.fromMap(data, id); + }); + return paginator; + } + + Future _loadPackages(bool forCustomer) async { + if (user == null) return; + if (!forCustomer && + !((user.hasPackages() || user.hasReceiving() || user.hasProcessing()))) + return; + String path = "/$packages_collection"; + if (listener != null) listener.cancel(); + _packages = []; + + try { + var q = Firestore.instance + .collection("$path") + .where("is_delivered", isEqualTo: false) + .where("is_deleted", isEqualTo: false); + + if (forCustomer) { + q = q.where("user_id", isEqualTo: user.id); + } + q = q.orderBy("tracking_id", descending: false); + listener = q.snapshots().listen((QuerySnapshot snapshot) { + _packages.clear(); + _packages = snapshot.documents.map((documentSnapshot) { + var package = Package.fromMap( + documentSnapshot.data, documentSnapshot.documentID); + return package; + }).toList(); + notifyListeners(); + }); + } catch (e) { + log.warning("Error!! $e"); + } + } + + Future getPackage(String id) async { + if (user == null) return null; + String path = "/$packages_collection"; + try { + DocumentSnapshot snap = + await Firestore.instance.collection("$path").document(id).get(); + if (snap.exists) { + var package = Package.fromMap(snap.data, snap.documentID); + return package; + } + } catch (e) { + log.warning("Error!! $e"); + } + return null; + } + + Future lookupPackage(String trackingID) async { + if (user == null) return null; + String path = "/$packages_collection"; + + try { + var qsnap = await Firestore.instance + .collection("$path") + .where("tracking_id", isEqualTo: trackingID) + .where("has_user_id", isEqualTo: false) + .where("is_deleted", isEqualTo: false) + .getDocuments(source: Source.server); + if (qsnap.documents.length > 0) { + var snap = qsnap.documents[0]; + if (snap.exists) { + var package = Package.fromMap(snap.data, snap.documentID); + return package; + } + } + + qsnap = await Firestore.instance + .collection("$path") + .where("tracking_id", isEqualTo: trackingID) + .where("user_id", isEqualTo: user.id) + .where("is_deleted", isEqualTo: false) + .getDocuments(source: Source.server); + if (qsnap.documents.length > 0) { + var snap = qsnap.documents[0]; + if (snap.exists) { + var package = Package.fromMap(snap.data, snap.documentID); + return package; + } + } + } catch (e) { + log.warning("Error!! $e"); + } + return null; + } + + Future> getPackages(String userID, List status) async { + List packages = []; + try { + var snaps = await Firestore.instance + .collection("/$packages_collection") + .where("status", whereIn: status) + .where("user_id", isEqualTo: userID) + .where("is_deleted", isEqualTo: false) + .getDocuments(source: Source.server); + packages = snaps.documents.map((documentSnapshot) { + var p = + Package.fromMap(documentSnapshot.data, documentSnapshot.documentID); + return p; + }).toList(); + } catch (e) { + log.warning("Error!! $e"); + } + return packages; + } + + Future> searchUser(String term) { + return Services.instance.userService.searchUser(term); + } + + Future> searchPackage(String term) { + return Services.instance.packageService.searchPackage(term); + } + + Future createPackages(User user, List packages) { + return Services.instance.packageService + .createPackages(packages, user.fcsID); + } + + Future createReceiving( + User user, Package package, List files) async { + if (user != null) { + package.fcsID = user.fcsID; + } + if (files != null) { + if (files.length > 5) throw Exception("Exceed number of file upload"); + package.photoUrls = package.photoUrls == null ? [] : package.photoUrls; + for (File f in files) { + String path = Path.join(pkg_files_path); + String url = await uploadStorage(path, f); + package.photoUrls.add(url); + } + } + return Services.instance.packageService.createReceiving(package); + } + + Future updateReceiving(User user, Package package, List files, + List deletedUrls) async { + if (user != null) { + package.fcsID = user.fcsID; + } + if (deletedUrls != null) { + for (String url in deletedUrls) { + package.photoUrls.remove(url); + } + await deleteStorageFromUrls(deletedUrls); + } + + if (files != null) { + if (files.length > 5) throw Exception("Exceed number of file upload"); + package.photoUrls = package.photoUrls == null ? [] : package.photoUrls; + for (File f in files) { + String path = Path.join(pkg_files_path); + String url = await uploadStorage(path, f); + package.photoUrls.add(url); + } + } + await Services.instance.packageService.updateReceiving(package); + } + + Future deleteReceiving(Package package) { + return Services.instance.packageService.deleteReceiving(package); + } + + Future updateProcessing( + Package package, List files, List deletedUrls) async { + if (deletedUrls != null) { + for (String url in deletedUrls) { + package.photoUrls.remove(url); + } + await deleteStorageFromUrls(deletedUrls); + } + + if (files != null) { + if (files.length > 5) throw Exception("Exceed number of file upload"); + package.photoUrls = package.photoUrls == null ? [] : package.photoUrls; + for (File f in files) { + String path = Path.join(pkg_files_path); + String url = await uploadStorage(path, f); + package.photoUrls.add(url); + } + package.photoUrls.removeWhere((e) => deletedUrls.contains(e)); + } + await Services.instance.packageService.updateProcessing(package); + } + + Future deleteProcessing(Package package) { + return Services.instance.packageService.deleteProcessing(package); + } + + Future changeDeliveryAddress( + Package package, DeliveryAddress deliveryAddress) { + return Services.instance.packageService + .changeDeliveryAddress(package.id, deliveryAddress.id); + } + + Future packageReturn(Package package) { + return Services.instance.packageService.packageReturn(package.id); + } +} diff --git a/lib/fcs/common/pages/package/package_editor.dart b/lib/pages/package/package_editor.dart similarity index 77% rename from lib/fcs/common/pages/package/package_editor.dart rename to lib/pages/package/package_editor.dart index 2b02700..7216f63 100644 --- a/lib/fcs/common/pages/package/package_editor.dart +++ b/lib/pages/package/package_editor.dart @@ -1,17 +1,18 @@ -import 'package:fcs/fcs/common/domain/entities/market.dart'; -import 'package:fcs/fcs/common/domain/entities/package.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/fcs/common/pages/market/market_editor.dart'; -import 'package:fcs/fcs/common/pages/market/model/market_model.dart'; -import 'package:fcs/fcs/common/pages/package/model/package_model.dart'; -import 'package:fcs/fcs/common/pages/package/tracking_id_page.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/fcs/common/pages/widgets/bottom_up_page_route.dart'; -import 'package:fcs/fcs/common/pages/widgets/display_text.dart'; -import 'package:fcs/fcs/common/pages/widgets/local_text.dart'; -import 'package:fcs/fcs/common/pages/widgets/multi_img_controller.dart'; -import 'package:fcs/fcs/common/pages/widgets/multi_img_file.dart'; -import 'package:fcs/fcs/common/pages/widgets/progress.dart'; +import 'package:fcs/domain/entities/market.dart'; +import 'package:fcs/domain/entities/package.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/market/market_editor.dart'; +import 'package:fcs/pages/market/model/market_model.dart'; +import 'package:fcs/pages/package/model/package_model.dart'; +import 'package:fcs/pages/package/tracking_id_page.dart'; +import 'package:fcs/pages/widgets/display_text.dart'; +import 'package:fcs/pages/widgets/input_text.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/multi_img_controller.dart'; +import 'package:fcs/pages/widgets/multi_img_file.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_icons/flutter_icons.dart'; import 'package:intl/intl.dart'; @@ -51,17 +52,17 @@ class _PackageEditorPageState extends State { Widget build(BuildContext context) { final trackingIdBox = DisplayText( text: _package.trackingID, - labelText: getLocalString(context, "package.tracking.id"), + labelTextKey: "package.tracking.id", iconData: MaterialCommunityIcons.barcode_scan, ); final statusBox = DisplayText( - text: _package.currentStatus, - labelText: getLocalString(context, "package.edit.status"), + text: _package.status, + labelTextKey: "package.edit.status", iconData: AntDesign.exclamationcircleo, ); final customerNameBox = DisplayText( text: _package.userName, - labelText: getLocalString(context, "package.create.name"), + labelTextKey: "package.create.name", iconData: Icons.perm_identity, ); final completeProcessingBtn = fcsButton( @@ -69,12 +70,15 @@ class _PackageEditorPageState extends State { getLocalString(context, 'package.edit.complete.process.btn'), callack: _completeProcessing, ); - final descBox = fcsInput(getLocalString(context, "package.edit.desc"), - MaterialCommunityIcons.message_text_outline, - controller: _descCtl, autoFocus: false); - final remarkBox = fcsInput( - getLocalString(context, "package.edit.remark"), Entypo.new_message, - controller: _remarkCtl, autoFocus: false); + final descBox = InputText( + labelTextKey: 'package.edit.desc', + iconData: MaterialCommunityIcons.message_text_outline, + controller: _descCtl); + final remarkBox = InputText( + labelTextKey: 'package.edit.remark', + iconData: Entypo.new_message, + controller: _remarkCtl); + final img = MultiImageFile( enabled: true, controller: multiImgController, @@ -86,7 +90,7 @@ class _PackageEditorPageState extends State { appBar: AppBar( centerTitle: true, leading: new IconButton( - icon: new Icon(Icons.close, color: primaryColor, size: 30), + icon: new Icon(CupertinoIcons.back, color: primaryColor, size: 30), onPressed: () => Navigator.of(context).pop(), ), shadowColor: Colors.transparent, @@ -189,7 +193,7 @@ class _PackageEditorPageState extends State { items: markets.map>((String value) { return DropdownMenuItem( value: value, - child: Text(value, + child: Text(value ?? "", overflow: TextOverflow.ellipsis, style: TextStyle( color: value == MANAGE_MARKET @@ -206,7 +210,7 @@ class _PackageEditorPageState extends State { _manageMarket() { Navigator.push( context, - BottomUpPageRoute(MarketEditor()), + CupertinoPageRoute(builder: (context) => MarketEditor()), ); } @@ -224,8 +228,8 @@ class _PackageEditorPageState extends State { _package.desc = _descCtl.text; _package.remark = _remarkCtl.text; _package.market = selectedMarket; - await packageModel.completeProcessing(_package, - multiImgController.getAddedFile, multiImgController.getDeletedUrl); + // await packageModel.completeProcessing(_package, + // multiImgController.getAddedFile, multiImgController.getDeletedUrl); Navigator.pop(context); } catch (e) { showMsgDialog(context, "Error", e.toString()); @@ -247,7 +251,7 @@ class _PackageEditorPageState extends State { PackageModel packageModel = Provider.of(context, listen: false); try { - await packageModel.deletePackage(_package); + // await packageModel.deletePackage(_package); Navigator.pop(context, true); } catch (e) { showMsgDialog(context, "Error", e.toString()); diff --git a/lib/pages/package/package_info.dart b/lib/pages/package/package_info.dart new file mode 100644 index 0000000..7380cd8 --- /dev/null +++ b/lib/pages/package/package_info.dart @@ -0,0 +1,230 @@ +import 'package:fcs/domain/constants.dart'; +import 'package:fcs/domain/entities/package.dart'; +import 'package:fcs/domain/vo/delivery_address.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/delivery_address/model/delivery_address_model.dart'; +import 'package:fcs/pages/main/model/main_model.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/package/model/package_model.dart'; +import 'package:fcs/pages/widgets/defalut_delivery_address.dart'; +import 'package:fcs/pages/widgets/delivery_address_selection.dart'; +import 'package:fcs/pages/widgets/display_text.dart'; +import 'package:fcs/pages/widgets/fcs_id_icon.dart'; +import 'package:fcs/pages/widgets/local_button.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/multi_img_controller.dart'; +import 'package:fcs/pages/widgets/multi_img_file.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:fcs/pages/widgets/status_tree.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_icons/flutter_icons.dart'; +import 'package:intl/intl.dart'; +import 'package:provider/provider.dart'; + +final DateFormat dateFormat = DateFormat("d MMM yyyy"); + +class PackageInfo extends StatefulWidget { + final isCustomer; + final isSearchResult; + final Package package; + + PackageInfo( + {this.package, this.isSearchResult = false, this.isCustomer = false}); + + @override + _PackageInfoState createState() => _PackageInfoState(); +} + +class _PackageInfoState extends State { + var dateFormatter = new DateFormat('dd MMM yyyy'); + Package _package; + bool _isLoading = false; + MultiImgController multiImgController = MultiImgController(); + + @override + void initState() { + super.initState(); + initPackage(widget.package); + } + + initPackage(Package package) { + setState(() { + _package = package; + multiImgController.setImageUrls = package.photoUrls; + }); + } + + @override + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + String id = Provider.of(context).user.id; + bool owner = _package.userID == id; + bool canChangeDeliveryAddress = + _package.status == package_received_status || + _package.status == package_processed_status; + + final trackingIdBox = DisplayText( + text: _package.trackingID, + labelTextKey: "package.tracking.id", + iconData: MaterialCommunityIcons.barcode_scan, + ); + var fcsIDBox = DisplayText( + text: _package.fcsID, + labelTextKey: "processing.fcs.id", + icon: FcsIDIcon(), + ); + final customerNameBox = DisplayText( + text: _package.userName, + labelTextKey: "package.create.name", + iconData: Icons.perm_identity, + ); + final marketBox = DisplayText( + text: _package.market ?? "-", + labelTextKey: "package.create.market", + iconData: Icons.store, + ); + final descBox = DisplayText( + text: _package.desc ?? "-", + labelTextKey: "package.edit.desc", + iconData: MaterialCommunityIcons.message_text_outline, + ); + final remarkBox = DisplayText( + text: _package.remark ?? "-", + labelTextKey: "package.edit.remark", + iconData: Entypo.new_message, + ); + final img = MultiImageFile( + enabled: false, + controller: multiImgController, + title: "Receipt File", + ); + + final returnButton = LocalButton( + textKey: "receiving.return.btn", + callBack: _return, + ); + final deliveryAddressBox = DefaultDeliveryAddress( + deliveryAddress: _package.deliveryAddress, + labelKey: "package.delivery.address", + onTap: owner && canChangeDeliveryAddress + ? () async { + DeliveryAddress d = await Navigator.push( + context, + CupertinoPageRoute( + builder: (context) => DeliveryAddressSelection( + deliveryAddress: _package.deliveryAddress, + )), + ); + if (d == null) return; + _changeDeliverayAddress(d); + } + : null, + ); + + return LocalProgress( + inAsyncCall: _isLoading, + child: Scaffold( + appBar: AppBar( + centerTitle: true, + leading: new IconButton( + icon: new Icon(CupertinoIcons.back, color: primaryColor, size: 30), + onPressed: () => Navigator.of(context).pop(), + ), + shadowColor: Colors.transparent, + backgroundColor: Colors.white, + title: LocalText( + context, + "package.info.title", + fontSize: 20, + color: primaryColor, + ), + ), + body: Card( + child: Column( + children: [ + Expanded( + child: Padding( + padding: const EdgeInsets.all(10.0), + child: ListView(children: [ + trackingIdBox, + widget.isSearchResult ? Container() : fcsIDBox, + widget.isSearchResult ? Container() : customerNameBox, + widget.isSearchResult ? Container() : marketBox, + _package.photoUrls.length == 0 ? Container() : img, + widget.isSearchResult ? Container() : descBox, + remarkBox, + _package.status == package_received_status && + widget.isCustomer + ? returnButton + : Container(), + widget.isSearchResult ? Container() : deliveryAddressBox, + widget.isSearchResult + ? Container() + : StatusTree( + shipmentHistory: _package.shipmentHistory, + currentStatus: _package.status), + SizedBox( + height: 20, + ) + ]), + )), + ], + ), + ), + ), + ); + } + + _changeDeliverayAddress(DeliveryAddress deliveryAddress) async { + if (deliveryAddress == null) return; + setState(() { + _isLoading = true; + }); + PackageModel packageModel = + Provider.of(context, listen: false); + DeliveryAddressModel deliveryAddressModel = + Provider.of(context, listen: false); + + try { + await packageModel.changeDeliveryAddress(_package, deliveryAddress); + var da = + await deliveryAddressModel.getDeliveryAddress(deliveryAddress.id); + setState(() { + _package.deliveryAddress = da; + }); + } catch (e) { + showMsgDialog(context, "Error", e.toString()); + } finally { + setState(() { + _isLoading = false; + }); + } + } + + _return() { + showConfirmDialog(context, "receiving.return.confirm", _returnReceiving); + } + + _returnReceiving() async { + setState(() { + _isLoading = true; + }); + try { + PackageModel packageModel = + Provider.of(context, listen: false); + await packageModel.packageReturn(_package); + Navigator.pop(context); + } catch (e) { + showMsgDialog(context, "Error", e.toString()); + } finally { + setState(() { + _isLoading = false; + }); + } + } +} diff --git a/lib/pages/package/package_list.dart b/lib/pages/package/package_list.dart new file mode 100644 index 0000000..6d3c3f6 --- /dev/null +++ b/lib/pages/package/package_list.dart @@ -0,0 +1,143 @@ +import 'package:fcs/domain/entities/package.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/package/model/package_model.dart'; +import 'package:fcs/pages/package/package_info.dart'; +import 'package:fcs/pages/package/package_list_row.dart'; +import 'package:fcs/pages/package_search/package_serach.dart'; +import 'package:fcs/pages/widgets/local_popup_menu_button.dart'; +import 'package:fcs/pages/widgets/local_popupmenu.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class PackageList extends StatefulWidget { + final bool forCustomer; + + const PackageList({Key key, this.forCustomer = true}) : super(key: key); + @override + _PackageListState createState() => _PackageListState(); +} + +class _PackageListState extends State { + bool _isLoading = false; + var _controller = ScrollController(); + + @override + void initState() { + super.initState(); + + _controller.addListener(() async { + if (_controller.position.pixels == _controller.position.maxScrollExtent) { + Provider.of(context, listen: false) + .loadMore(isCustomer: widget.forCustomer); + } + }); + Provider.of(context, listen: false) + .initData(widget.forCustomer); + } + + @override + Widget build(BuildContext context) { + var packageModel = Provider.of(context); + var packages = packageModel.packages; + + final popupMenu = LocalPopupMenuButton( + popmenus: [ + LocalPopupMenu( + id: 1, + textKey: "package.popupmenu.active", + selected: packageModel.menuSelectedIndex == 1), + LocalPopupMenu( + id: 2, + textKey: "package.popupmenu.delivered", + selected: packageModel.menuSelectedIndex == 2) + ], + popupMenuCallback: (p) => this.setState(() { + packageModel.menuSelectedIndex = p.id; + }), + ); + + return LocalProgress( + inAsyncCall: _isLoading, + child: Scaffold( + appBar: AppBar( + centerTitle: true, + leading: new IconButton( + icon: new Icon(CupertinoIcons.back), + onPressed: () => Navigator.of(context).pop(), + ), + backgroundColor: primaryColor, + title: LocalText( + context, + "package.title", + fontSize: 20, + color: Colors.white, + ), + actions: [ + widget.forCustomer + ? Container() + : IconButton( + icon: Icon( + Icons.search, + color: Colors.white, + ), + iconSize: 30, + onPressed: () => searchPackage(context, + callbackPackageSelect: _searchCallback), + ), + popupMenu + ], + ), + body: Column( + children: [ + Expanded( + child: RefreshIndicator( + child: ListView.separated( + controller: _controller, + separatorBuilder: (context, index) => Divider( + color: Colors.grey, + height: 1, + ), + scrollDirection: Axis.vertical, + itemCount: packages.length, + itemBuilder: (BuildContext context, int index) { + return PackageListRow( + key: ValueKey(packages[index].id), + package: packages[index], + isCustomer: widget.forCustomer, + ); + }), + onRefresh: () => + packageModel.refresh(isCustomer: widget.forCustomer), + ), + ), + packageModel.isLoading + ? Container( + padding: EdgeInsets.all(8), + color: primaryColor, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("Loading...", + style: TextStyle(color: Colors.white)), + ], + ), + ) + : Container(), + ], + )), + ); + } + + _searchCallback(Package package) async { + var packageModel = Provider.of(context, listen: false); + Package _package = await packageModel.getPackage(package.id); + if (_package == null) return; + Navigator.push( + context, + CupertinoPageRoute(builder: (context) => PackageInfo(package: _package)), + ); + } +} diff --git a/lib/pages/package/package_list_row.dart b/lib/pages/package/package_list_row.dart new file mode 100644 index 0000000..ea6052c --- /dev/null +++ b/lib/pages/package/package_list_row.dart @@ -0,0 +1,103 @@ +import 'package:fcs/domain/entities/package.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/package/package_info.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_icons/flutter_icons.dart'; +import 'package:intl/intl.dart'; + +typedef CallbackPackageSelect(Package package); + +class PackageListRow extends StatelessWidget { + final bool isCustomer; + final Package package; + final CallbackPackageSelect callbackPackageSelect; + final double dotSize = 15.0; + final DateFormat dateFormat = new DateFormat("dd MMM yyyy"); + + PackageListRow( + {Key key, this.package, this.callbackPackageSelect, this.isCustomer}) + : super(key: key); + + @override + Widget build(BuildContext context) { + return InkWell( + onTap: () { + if (callbackPackageSelect != null) { + callbackPackageSelect(package); + return; + } + Navigator.push( + context, + CupertinoPageRoute( + builder: (context) => PackageInfo( + package: package, + isCustomer: isCustomer, + )), + ); + }, + child: Container( + padding: EdgeInsets.only(left: 15, right: 15), + child: Column( + children: [ + Row( + children: [ + Expanded( + child: new Padding( + padding: const EdgeInsets.symmetric(vertical: 16.0), + child: new Row( + children: [ + Icon(Octicons.package, color: primaryColor), + SizedBox(width: 8), + new Expanded( + child: new Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(left: 8.0), + child: new Text( + package.id == null ? '' : package.trackingID, + style: new TextStyle( + fontSize: 15.0, color: Colors.black), + ), + ), + Padding( + padding: const EdgeInsets.only(left: 8.0), + child: new Text( + package.market == null ? '' : package.market, + style: new TextStyle( + fontSize: 15.0, color: Colors.black), + ), + ), + ], + ), + ), + ], + ), + ), + ), + Column( + children: [ + Padding( + padding: const EdgeInsets.all(3.0), + child: getStatus(package.status), + ), + Padding( + padding: const EdgeInsets.all(0), + child: new Text( + dateFormat.format(package.currentStatusDate), + style: + new TextStyle(fontSize: 15.0, color: Colors.grey), + ), + ), + ], + ) + ], + ), + ], + ), + ), + ); + } +} diff --git a/lib/fcs/common/pages/package/package_new.dart b/lib/pages/package/package_new.dart similarity index 82% rename from lib/fcs/common/pages/package/package_new.dart rename to lib/pages/package/package_new.dart index ff44211..8bda98b 100644 --- a/lib/fcs/common/pages/package/package_new.dart +++ b/lib/pages/package/package_new.dart @@ -1,15 +1,16 @@ -import 'package:fcs/fcs/common/domain/entities/package.dart'; -import 'package:fcs/fcs/common/domain/entities/user.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/fcs/common/pages/package/tracking_id_page.dart'; -import 'package:fcs/fcs/common/pages/user_search/user_serach.dart'; -import 'package:fcs/fcs/common/pages/staff/model/staff_model.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/fcs/common/pages/widgets/bottom_up_page_route.dart'; -import 'package:fcs/fcs/common/pages/widgets/display_text.dart'; -import 'package:fcs/fcs/common/pages/widgets/fcs_id_icon.dart'; -import 'package:fcs/fcs/common/pages/widgets/local_text.dart'; -import 'package:fcs/fcs/common/pages/widgets/progress.dart'; +import 'package:fcs/domain/entities/package.dart'; +import 'package:fcs/domain/entities/user.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/package/tracking_id_page.dart'; +import 'package:fcs/pages/user_search/user_serach.dart'; +import 'package:fcs/pages/staff/model/staff_model.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/widgets/bottom_up_page_route.dart'; +import 'package:fcs/pages/widgets/display_text.dart'; +import 'package:fcs/pages/widgets/fcs_id_icon.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; @@ -41,7 +42,7 @@ class _PackageNewState extends State { Expanded( child: DisplayText( text: user != null ? user.fcsID : "", - labelText: getLocalString(context, "package.create.fcs.id"), + labelTextKey: "package.create.fcs.id", icon: FcsIDIcon(), )), IconButton( @@ -55,12 +56,12 @@ class _PackageNewState extends State { ); final namebox = DisplayText( text: user != null ? user.name : "", - labelText: getLocalString(context, "package.create.name"), + labelTextKey: "package.create.name", iconData: Icons.person, ); final phoneNumberBox = DisplayText( text: user != null ? user.phoneNumber : "", - labelText: getLocalString(context, "package.create.phone"), + labelTextKey: "package.create.phone", iconData: Icons.phone, ); final createButton = fcsButton( @@ -81,7 +82,7 @@ class _PackageNewState extends State { appBar: AppBar( centerTitle: true, leading: new IconButton( - icon: new Icon(Icons.close, color: primaryColor, size: 30), + icon: new Icon(CupertinoIcons.back, color: primaryColor, size: 30), onPressed: () => Navigator.of(context).pop(), ), shadowColor: Colors.transparent, @@ -171,7 +172,7 @@ class _PackageNewState extends State { _addPackage() async { Package package = await Navigator.push( context, - BottomUpPageRoute(TrackingIDPage()), + CupertinoPageRoute(builder: (context) => TrackingIDPage()), ); if (package != null) { diff --git a/lib/fcs/common/pages/package/tracking_id_page.dart b/lib/pages/package/tracking_id_page.dart similarity index 83% rename from lib/fcs/common/pages/package/tracking_id_page.dart rename to lib/pages/package/tracking_id_page.dart index cc19ca2..26db8ae 100644 --- a/lib/fcs/common/pages/package/tracking_id_page.dart +++ b/lib/pages/package/tracking_id_page.dart @@ -1,20 +1,23 @@ import 'package:barcode_scan/barcode_scan.dart'; -import 'package:fcs/fcs/common/domain/entities/market.dart'; -import 'package:fcs/fcs/common/domain/entities/package.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/fcs/common/pages/market/market_editor.dart'; -import 'package:fcs/fcs/common/pages/market/model/market_model.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/fcs/common/pages/widgets/bottom_up_page_route.dart'; -import 'package:fcs/fcs/common/pages/widgets/input_text.dart'; -import 'package:fcs/fcs/common/pages/widgets/local_text.dart'; -import 'package:fcs/fcs/common/pages/widgets/progress.dart'; +import 'package:fcs/domain/entities/market.dart'; +import 'package:fcs/domain/entities/package.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/market/market_editor.dart'; +import 'package:fcs/pages/market/model/market_model.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/widgets/barcode_scanner.dart'; +import 'package:fcs/pages/widgets/bottom_up_page_route.dart'; +import 'package:fcs/pages/widgets/input_text.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_icons/flutter_icons.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:provider/provider.dart'; const MANAGE_MARKET = "Manage Market"; +const SELECT_MARKET = "Select Market"; class TrackingIDPage extends StatefulWidget { const TrackingIDPage({Key key}) : super(key: key); @@ -29,6 +32,7 @@ class _TrackingIDPageState extends State { @override void initState() { super.initState(); + selectedMarket = SELECT_MARKET; } @override @@ -86,6 +90,7 @@ class _TrackingIDPageState extends State { List _markets = Provider.of(context).markets; List markets = _markets.map((e) => e.name).toList(); markets.insert(0, MANAGE_MARKET); + markets.insert(0, SELECT_MARKET); return Row( children: [ @@ -114,6 +119,10 @@ class _TrackingIDPageState extends State { _manageMarket(); return; } + if (newValue == SELECT_MARKET) { + selectedMarket = null; + return; + } selectedMarket = newValue; }); }, @@ -138,7 +147,7 @@ class _TrackingIDPageState extends State { _manageMarket() { Navigator.push( context, - BottomUpPageRoute(MarketEditor()), + CupertinoPageRoute(builder: (context) => MarketEditor()), ); } @@ -156,7 +165,7 @@ class _TrackingIDPageState extends State { } try { - String barcode = await BarcodeScanner.scan(); + String barcode = await scanBarcode(); if (barcode != null) { setState(() { _transcationIDCtl.text = barcode; diff --git a/lib/fcs/common/pages/package_search/package_serach.dart b/lib/pages/package_search/package_serach.dart similarity index 82% rename from lib/fcs/common/pages/package_search/package_serach.dart rename to lib/pages/package_search/package_serach.dart index 4740a42..2ee5ccf 100644 --- a/lib/fcs/common/pages/package_search/package_serach.dart +++ b/lib/pages/package_search/package_serach.dart @@ -1,9 +1,10 @@ import 'package:barcode_scan/barcode_scan.dart'; -import 'package:fcs/fcs/common/domain/entities/package.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/fcs/common/pages/package/model/package_model.dart'; -import 'package:fcs/fcs/common/pages/package/package_list_row.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; +import 'package:fcs/domain/entities/package.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/package/model/package_model.dart'; +import 'package:fcs/pages/package/package_list_row.dart'; +import 'package:fcs/pages/widgets/barcode_scanner.dart'; import 'package:flutter/material.dart'; import 'package:flutter_icons/flutter_icons.dart'; import 'package:permission_handler/permission_handler.dart'; @@ -136,7 +137,18 @@ class PackageSearchDelegate extends SearchDelegate { } try { - String barcode = await BarcodeScanner.scan(); + // PickedFile pickedFile = + // await ImagePicker().getImage(source: ImageSource.camera); + // FirebaseVisionImage visionImage = + // FirebaseVisionImage.fromFile(File(pickedFile.path)); + // final BarcodeDetector barcodeDetector = + // FirebaseVision.instance.barcodeDetector(); + // final List barcodes = + // await barcodeDetector.detectInImage(visionImage); + // Barcode bc = barcodes.firstWhere((element) => true); + // String barcode; + // if (bc != null) barcode = bc.rawValue; + String barcode = await scanBarcode(); if (barcode != null) { query = barcode; showResults(context); diff --git a/lib/pages/payment_editor.dart b/lib/pages/payment_editor.dart deleted file mode 100644 index 275764c..0000000 --- a/lib/pages/payment_editor.dart +++ /dev/null @@ -1,128 +0,0 @@ -import 'package:fcs/model/discount_model.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/vo/discount.dart'; -import 'package:fcs/vo/payment_method.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_icons/flutter_icons.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:fcs/widget/progress.dart'; - -import '../fcs/common/helpers/theme.dart'; - -class PaymentMethodEditor extends StatefulWidget { - final PaymentMethod paymentMethod; - - const PaymentMethodEditor({Key key, this.paymentMethod}) : super(key: key); - @override - _PaymentMethodEditorState createState() => _PaymentMethodEditorState(); -} - -class _PaymentMethodEditorState extends State { - bool _isLoading = false; - PaymentMethod _paymentMethod = new PaymentMethod(); - TextEditingController _nameController = new TextEditingController(); - TextEditingController _accountNameController = new TextEditingController(); - TextEditingController _accountNumberController = new TextEditingController(); - TextEditingController _mailController = new TextEditingController(); - TextEditingController _phoneController = new TextEditingController(); - TextEditingController _linkController = new TextEditingController(); - - bool isNew = false; - - @override - void initState() { - super.initState(); - if (widget.paymentMethod != null) { - _paymentMethod = widget.paymentMethod; - _nameController.text = _paymentMethod.name; - _accountNameController.text = _paymentMethod.accountName; - _accountNumberController.text = _paymentMethod.account; - _mailController.text = _paymentMethod.mail; - _phoneController.text = _paymentMethod.phone; - _linkController.text = _paymentMethod.link; - } else { - isNew = true; - _nameController.text = ''; - } - } - - @override - Widget build(BuildContext context) { - var discountModel = Provider.of(context); - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - backgroundColor: Colors.white, - appBar: AppBar( - centerTitle: true, - leading: new IconButton( - icon: new Icon(Icons.close), - onPressed: () => Navigator.of(context).pop(), - ), - title: Text( - AppTranslations.of(context).text("payment.method.form"), - ), - backgroundColor: primaryColor, - actions: [], - ), - body: Padding( - padding: const EdgeInsets.only(left: 20.0), - child: Column( - children: [ - Expanded( - child: ListView( - children: [ - fcsInput('Name', FontAwesomeIcons.algolia, - controller: _nameController), - fcsInput('Account Name', Feather.user, - controller: _accountNameController), - fcsInput('Account Number', FontAwesomeIcons.moneyBill, - controller: _accountNumberController), - // fcsInput('E-mail', Icons.mail, - // controller: _mailController), - // fcsInput('Phone', Icons.phone, - // controller: _phoneController), - fcsInput('Phone', Icons.link, controller: _linkController) - ], - ), - ), - widget.paymentMethod == null - ? Align( - alignment: Alignment.bottomCenter, - child: Center( - child: Container( - width: 250, - child: FlatButton( - child: Text('Add Payment Method'), - color: primaryColor, - textColor: Colors.white, - onPressed: () { - Navigator.pop(context); - }, - ), - ))) - : Align( - alignment: Alignment.bottomCenter, - child: Center( - child: Container( - width: 250, - child: FlatButton( - child: Text('Save Payment Method'), - color: primaryColor, - textColor: Colors.white, - onPressed: () { - Navigator.pop(context); - }, - ), - ))), - SizedBox( - height: 30, - ) - ], - ), - )), - ); - } -} diff --git a/lib/pages/payment_method_page.dart b/lib/pages/payment_method_page.dart deleted file mode 100644 index 86597ca..0000000 --- a/lib/pages/payment_method_page.dart +++ /dev/null @@ -1,132 +0,0 @@ -import 'package:fcs/pages/payment_editor.dart'; -import 'package:fcs/widget/bottom_up_page_route.dart'; -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/main_model.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:fcs/widget/progress.dart'; - -import '../fcs/common/helpers/theme.dart'; - -class PaymentMethodPage extends StatefulWidget { - @override - _PaymentMethodPageState createState() => _PaymentMethodPageState(); -} - -class _PaymentMethodPageState extends State { - bool _isLoading = false; - @override - Widget build(BuildContext context) { - MainModel mainModel = Provider.of(context); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - leading: new IconButton( - icon: new Icon(Icons.close), - onPressed: () => Navigator.of(context).pop(), - ), - centerTitle: true, - title: Text( - AppTranslations.of(context).text("payment.method.title"), - ), - backgroundColor: primaryColor, - actions: [], - ), - body: ListView.separated( - separatorBuilder: (context, index) => Divider( - color: Colors.black, - ), - itemCount: mainModel.paymentMethods.length, - itemBuilder: (BuildContext context, int index) { - var method = mainModel.paymentMethods[index]; - return InkWell( - onTap: () { - Navigator.push( - context, - BottomUpPageRoute(PaymentMethodEditor( - paymentMethod: method, - )), - ); - }, - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - method.name, - style: TextStyle( - color: primaryColor, - fontWeight: FontWeight.bold, - fontSize: 18), - ), - Padding( - padding: const EdgeInsets.only(left: 8.0, top: 8.0), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - method.accountName, - style: TextStyle( - color: Colors.black, - fontWeight: FontWeight.normal, - fontSize: 15), - ), - ], - ), - ), - method.account != null - ? Padding( - padding: const EdgeInsets.only(left: 8.0, top: 8.0), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - method.account, - style: TextStyle( - color: Colors.black, - fontWeight: FontWeight.normal, - fontSize: 15), - ), - ], - ), - ) - : Padding( - padding: const EdgeInsets.only(left: 8.0, top: 8.0), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - method.link, - style: TextStyle( - color: Colors.black, - fontWeight: FontWeight.normal, - fontSize: 15), - ), - ], - ), - ) - ], - ), - ), - ); - }, - ), - floatingActionButton: FloatingActionButton.extended( - onPressed: () { - Navigator.push( - context, - BottomUpPageRoute(PaymentMethodEditor()), - ); - }, - icon: Icon(Icons.add), - label: Text(AppTranslations.of(context).text("payment.method.new")), - backgroundColor: primaryColor, - ), - ), - ); - } -} diff --git a/lib/fcs/common/pages/payment_methods/model/payment_method_model.dart b/lib/pages/payment_methods/model/payment_method_model.dart similarity index 87% rename from lib/fcs/common/pages/payment_methods/model/payment_method_model.dart rename to lib/pages/payment_methods/model/payment_method_model.dart index 544d699..25d9f11 100644 --- a/lib/fcs/common/pages/payment_methods/model/payment_method_model.dart +++ b/lib/pages/payment_methods/model/payment_method_model.dart @@ -1,9 +1,9 @@ import 'dart:async'; import 'package:cloud_firestore/cloud_firestore.dart'; -import 'package:fcs/fcs/common/domain/entities/payment_method.dart'; -import 'package:fcs/fcs/common/pages/model/base_model.dart'; -import 'package:fcs/fcs/common/services/services.dart'; +import 'package:fcs/data/services/services.dart'; +import 'package:fcs/domain/entities/payment_method.dart'; +import 'package:fcs/pages/main/model/base_model.dart'; import 'package:logging/logging.dart'; class PaymentMethodModel extends BaseModel { diff --git a/lib/fcs/common/pages/payment_methods/payment_method_editor.dart b/lib/pages/payment_methods/payment_method_editor.dart similarity index 91% rename from lib/fcs/common/pages/payment_methods/payment_method_editor.dart rename to lib/pages/payment_methods/payment_method_editor.dart index c681d16..ec9be49 100644 --- a/lib/fcs/common/pages/payment_methods/payment_method_editor.dart +++ b/lib/pages/payment_methods/payment_method_editor.dart @@ -1,11 +1,12 @@ -import 'package:fcs/fcs/common/domain/entities/payment_method.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/fcs/common/pages/model/main_model.dart'; -import 'package:fcs/fcs/common/pages/payment_methods/model/payment_method_model.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/fcs/common/pages/widgets/input_text.dart'; -import 'package:fcs/fcs/common/pages/widgets/local_text.dart'; -import 'package:fcs/fcs/common/pages/widgets/progress.dart'; +import 'package:fcs/domain/entities/payment_method.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/main/model/main_model.dart'; +import 'package:fcs/pages/payment_methods/model/payment_method_model.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/widgets/input_text.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_icons/flutter_icons.dart'; import 'package:provider/provider.dart'; @@ -58,12 +59,12 @@ class _PaymentMethodEditorState extends State { appBar: AppBar( centerTitle: true, leading: new IconButton( - icon: new Icon(Icons.close, color: primaryColor), + icon: new Icon(CupertinoIcons.back, color: primaryColor), onPressed: () => Navigator.of(context).pop(), ), title: LocalText( context, - isNew ? "pm.new" : "pm.update", + isNew ? "pm.form.new" : "pm.update", fontSize: 20, color: primaryColor, ), diff --git a/lib/fcs/common/pages/payment_methods/payment_method_page.dart b/lib/pages/payment_methods/payment_method_page.dart similarity index 80% rename from lib/fcs/common/pages/payment_methods/payment_method_page.dart rename to lib/pages/payment_methods/payment_method_page.dart index b281297..b03e94a 100644 --- a/lib/fcs/common/pages/payment_methods/payment_method_page.dart +++ b/lib/pages/payment_methods/payment_method_page.dart @@ -1,14 +1,15 @@ -import 'package:fcs/fcs/common/domain/entities/payment_method.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/fcs/common/localization/app_translations.dart'; -import 'package:fcs/fcs/common/pages/model/main_model.dart'; -import 'package:fcs/fcs/common/pages/payment_methods/model/payment_method_model.dart'; -import 'package:fcs/fcs/common/pages/payment_methods/payment_method_editor.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/fcs/common/pages/widgets/bottom_up_page_route.dart'; -import 'package:fcs/fcs/common/pages/widgets/display_text.dart'; -import 'package:fcs/fcs/common/pages/widgets/local_text.dart'; -import 'package:fcs/fcs/common/pages/widgets/progress.dart'; +import 'package:fcs/domain/entities/payment_method.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/localization/app_translations.dart'; +import 'package:fcs/pages/main/model/main_model.dart'; +import 'package:fcs/pages/payment_methods/model/payment_method_model.dart'; +import 'package:fcs/pages/payment_methods/payment_method_editor.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/widgets/bottom_up_page_route.dart'; +import 'package:fcs/pages/widgets/display_text.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_icons/flutter_icons.dart'; @@ -35,7 +36,7 @@ class _PaymentMethodPageState extends State { appBar: AppBar( leading: new IconButton( icon: new Icon( - Icons.close, + CupertinoIcons.back, color: primaryColor, ), onPressed: () => Navigator.of(context).pop(), @@ -69,7 +70,8 @@ class _PaymentMethodPageState extends State { onPressed: () { Navigator.push( context, - BottomUpPageRoute(PaymentMethodEditor()), + CupertinoPageRoute( + builder: (context) => PaymentMethodEditor()), ); }, icon: Icon(Icons.add), @@ -95,9 +97,10 @@ class _PaymentMethodPageState extends State { ? () { Navigator.push( context, - BottomUpPageRoute(PaymentMethodEditor( - paymentMethod: method, - )), + CupertinoPageRoute( + builder: (context) => PaymentMethodEditor( + paymentMethod: method, + )), ); } : null, @@ -132,7 +135,7 @@ class _PaymentMethodPageState extends State { Expanded( child: DisplayText( text: text, - labelText: getLocalString(context, labelKey), + labelTextKey: labelKey, iconData: iconData, ), ), diff --git a/lib/pages/pd/pd_form.dart b/lib/pages/pd/pd_form.dart deleted file mode 100644 index 7b6a794..0000000 --- a/lib/pages/pd/pd_form.dart +++ /dev/null @@ -1,225 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/language_model.dart'; -import 'package:fcs/model/log_model.dart'; -import 'package:fcs/model/main_model.dart'; -import 'package:fcs/model/pd_model.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/pd.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:fcs/widget/my_data_table.dart'; -import 'package:fcs/widget/progress.dart'; -import '../../fcs/common/pages/util.dart'; -import 'pd_item.dart'; - -class PDForm extends StatefulWidget { - final PD pd; - const PDForm({Key key, this.pd}) : super(key: key); - @override - _PDFormState createState() => _PDFormState(); -} - -class _PDFormState extends State { - TextEditingController _date = new TextEditingController(); - TextEditingController _userName = new TextEditingController(); - - PD pd = PD(); - bool _isLoading = false; - bool isNew = true; - - @override - void initState() { - super.initState(); - if (widget.pd != null) { - _userName.text = widget.pd.userName; - } else { - var mainModel = Provider.of(context, listen: false); - _userName.text = mainModel.user.name; - } - - _load(); - } - - _load() async { - if (widget.pd != null) { - this.pd = widget.pd; - _date.text = DateFormat('dd MMM yyyy – hh:mm a').format(widget.pd.date); - isNew = false; - Provider.of(context, listen: false).loadPDLines(pd).then((_pd) { - setState(() { - this.pd = _pd; - }); - }); - } - } - - @override - Widget build(BuildContext context) { - var languageModel = Provider.of(context); - final _formKey = GlobalKey(); - - final dateBox = Container( - padding: EdgeInsets.only(left: 20, right: 15), - child: TextFormField( - controller: _date, - enabled: false, - cursorColor: primaryColor, - style: textStyle, - decoration: new InputDecoration( - labelText: AppTranslations.of(context).text("pd.date"), - labelStyle: languageModel.isEng ? labelStyle : labelStyleMM, - icon: Icon( - Icons.date_range, - color: primaryColor, - size: 23, - )), - )); - - final nameBox = Container( - padding: EdgeInsets.only(left: 20, right: 15), - child: TextFormField( - controller: _userName, - autofocus: false, - readOnly: true, - style: textStyle, - decoration: new InputDecoration( - border: InputBorder.none, - focusedBorder: InputBorder.none, - icon: Icon( - Icons.person, - color: primaryColor, - size: 25, - )), - )); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - title: Text( - AppTranslations.of(context).text('pd'), - style: languageModel.isEng - ? TextStyle() - : TextStyle(fontFamily: 'MyanmarUnicode'), - ), - actions: [ - isNew - ? IconButton( - icon: Icon(Icons.send), - onPressed: () { - if (!_formKey.currentState.validate()) return; - showConfirmDialog(context, "pd.confirm", () { - _submit(); - }); - }, - ) - : Container() - ], - ), - floatingActionButton: isNew - ? FloatingActionButton( - backgroundColor: primaryColor, - child: Icon(Icons.add), - onPressed: () async { - final PDLine pdLine = await Navigator.push( - context, - MaterialPageRoute(builder: (context) => PDItem()), - ); - _save(pdLine); - }, - ) - : null, - body: Form( - key: _formKey, - child: ListView( - children: [ - isNew ? Container() : dateBox, - nameBox, - SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: MyDataTable( - columns: [ - MyDataColumn(label: LocalText(context, "pd.product")), - MyDataColumn( - label: LocalText(context, "pd.storage"), - ), - MyDataColumn(label: LocalText(context, "pd.quantity")), - ], - rows: getProductRow(pd), - ), - ), - ], - ), - )), - ); - } - - List getProductRow(PD pd) { - return pd.pdLines.map((p) { - return MyDataRow( - onSelectChanged: (bool selected) async { - if (!isNew) return; - var pdLine = await Navigator.push( - context, - MaterialPageRoute( - builder: (context) => PDItem( - pdLine: p, - )), - ); - _save(pdLine); - }, - cells: [ - MyDataCell( - new Text( - p.productName, - style: textStyle, - ), - ), - MyDataCell( - new Text(p.storageName, style: textStyle), - ), - MyDataCell( - new Text(p.quantity.toString(), style: textStyle), - ), - ], - ); - }).toList(); - } - - _save(PDLine pdLine) { - if (pdLine == null) return; - if (pdLine.action == "create") { - if (pd.pdLines.contains(pdLine)) { - showMsgDialog(context, "Error", "Duplicate line"); - return; - } - pd.pdLines.add(pdLine); - } else if (pdLine.action == "delete") { - pd.pdLines.remove(pdLine); - } - } - - _submit() async { - if (pd.pdLines.length == 0) { - showMsgDialog(context, "Error", "No product line"); - return; - } - setState(() { - _isLoading = true; - }); - try { - PDModel pdModel = Provider.of(context); - await pdModel.createPD(pd); - Navigator.pop(context); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - setState(() { - _isLoading = false; - }); - } - } -} diff --git a/lib/pages/pd/pd_item.dart b/lib/pages/pd/pd_item.dart deleted file mode 100644 index 6c39801..0000000 --- a/lib/pages/pd/pd_item.dart +++ /dev/null @@ -1,223 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/language_model.dart'; -import 'package:fcs/model/product_model.dart'; -import 'package:fcs/model/storage_model.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/pd.dart'; -import 'package:fcs/vo/product.dart'; -import 'package:fcs/vo/storage.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:fcs/widget/progress.dart'; - -class PDItem extends StatefulWidget { - final PDLine pdLine; - const PDItem({Key key, this.pdLine}) : super(key: key); - @override - _PDItemState createState() => _PDItemState(); -} - -class _PDItemState extends State { - final _formKey = GlobalKey(); - bool _isLoading = false; - String currentStorageID; - String currentProductID; - TextEditingController _quantity = new TextEditingController(); - PDLine pdLine = PDLine(); - - @override - void initState() { - super.initState(); - if (widget.pdLine != null) { - this._quantity.text = widget.pdLine.quantity.toString(); - this.currentProductID = widget.pdLine.productID; - this.currentStorageID = widget.pdLine.storageID; - this.pdLine = widget.pdLine; - this.pdLine.action = "update"; - } else { - this.pdLine.action = "create"; - } - } - - Widget showInventoryList(BuildContext context, StorageModel storageModel) { - return Row( - mainAxisSize: MainAxisSize.max, - children: [ - Image.asset( - "assets/inventory.png", - color: primaryColor, - width: 25, - ), - SizedBox( - width: 20, - ), - new Flexible( - child: Container( - width: 170.0, - child: DropdownButton( - value: currentStorageID, - isExpanded: true, - hint: Text( - 'Select Storage', - style: labelStyle, - ), - onChanged: changedDropDownItem, - items: storageModel.storages - .map>((Storage storage) { - return new DropdownMenuItem( - value: storage.id, - child: new Text(storage.name, style: textStyle), - ); - }).toList(), - ), - ), - ), - ], - ); - } - - void changedDropDownItem(selected) { - setState(() { - currentStorageID = selected; - }); - } - - Widget showProducts(BuildContext context, ProductModel productModel) { - return Row( - mainAxisSize: MainAxisSize.max, - children: [ - Icon( - FontAwesomeIcons.tag, - color: primaryColor, - size: 20, - ), - SizedBox( - width: 20, - ), - new Flexible( - child: Container( - width: 170.0, - child: DropdownButton( - value: currentProductID, - isExpanded: true, - hint: Text( - 'Select Product', - style: labelStyle, - ), - onChanged: changedProduct, - items: productModel.products - .map>((Product product) { - return new DropdownMenuItem( - value: product.id, - child: new Text(product.name, style: textStyle), - ); - }).toList(), - ), - ), - ), - ], - ); - } - - void changedProduct(selected) { - setState(() { - currentProductID = selected; - }); - } - - @override - Widget build(BuildContext context) { - var storageModel = Provider.of(context); - var productModel = Provider.of(context); - var languageModel = Provider.of(context); - - final quantityBox = Container( - padding: EdgeInsets.only(top: 10), - child: TextFormField( - controller: _quantity, - keyboardType: TextInputType.number, - autofocus: false, - cursorColor: primaryColor, - decoration: new InputDecoration( - labelText: AppTranslations.of(context).text("pd.quantity"), - labelStyle: languageModel.isEng ? labelStyle : labelStyleMM, - icon: Icon( - FontAwesomeIcons.sortNumericUpAlt, - color: primaryColor, - ), - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - ), - validator: (value) { - if (value.isEmpty) { - return AppTranslations.of(context).text("pd.form.quan"); - } - return null; - }, - ), - ); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - title: Text( - AppTranslations.of(context).text('pd.product.title'), - style: languageModel.isEng - ? TextStyle() - : TextStyle(fontFamily: 'MyanmarUnicode'), - ), - actions: [ - IconButton( - icon: Icon(Icons.delete), - onPressed: () { - _delete(); - }, - ), - IconButton( - icon: Icon(Icons.save), - onPressed: () { - if (!_formKey.currentState.validate()) return; - _save(); - }, - ) - ], - ), - body: Form( - key: _formKey, - child: ListView( - shrinkWrap: true, - padding: EdgeInsets.only(left: 24.0, right: 20.0), - children: [ - quantityBox, - showInventoryList(context, storageModel), - showProducts(context, productModel) - ], - ), - )), - ); - } - - _save() { - if (currentProductID == null || currentStorageID == null) return; - this.pdLine.storageID = currentStorageID; - var storageName = - Provider.of(context).getStorageName(currentStorageID); - this.pdLine.storageName = storageName; - this.pdLine.productID = currentProductID; - var productName = - Provider.of(context).getProductName(currentProductID); - this.pdLine.productName = productName; - this.pdLine.quantity = int.parse(_quantity.text); - Navigator.pop(context, this.pdLine); - } - - _delete() { - this.pdLine.action = "delete"; - Navigator.pop(context, this.pdLine); - } -} diff --git a/lib/pages/pd/pd_list.dart b/lib/pages/pd/pd_list.dart deleted file mode 100644 index c32b736..0000000 --- a/lib/pages/pd/pd_list.dart +++ /dev/null @@ -1,187 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/language_model.dart'; -import 'package:fcs/model/pd_model.dart'; -import 'package:fcs/pages/pd/pd_form.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:fcs/widget/progress.dart'; - -class PDList extends StatefulWidget { - @override - _PDListState createState() => _PDListState(); -} - -class _PDListState extends State { - final double dotSize = 15.0; - DateTime _selectedDate = DateTime.now(); - int _dateIndex = 0; - bool _isLoading = false; - - @override - void initState() { - super.initState(); - - var pdModel = Provider.of(context, listen: false); - // pdModel.loadPDs(); - _selectedDate = pdModel.selectedDate; - _dateIndex = pdModel.dateIndex; - } - - Future _selectDate(BuildContext context) async { - var pdModel = Provider.of(context); - - final DateTime picked = await showDatePicker( - context: context, - initialDate: _selectedDate, - firstDate: DateTime(2015, 8), - lastDate: DateTime(2101), - builder: (BuildContext context, Widget child) { - return Theme( - data: ThemeData.light().copyWith( - primaryColor: primaryColor, //Head background - accentColor: secondaryColor, //selection color - dialogBackgroundColor: Colors.white, //Background color - ), - child: child, - ); - }, - ); - - if (picked != null) { - var pickedDate = new DateTime(picked.year, picked.month, picked.day); - var currentDate = new DateTime( - DateTime.now().year, DateTime.now().month, DateTime.now().day); - - this._dateIndex = pickedDate == currentDate ? 0 : 1; - setState(() { - _selectedDate = picked; - pdModel.filterDate(_selectedDate, _dateIndex); - }); - } - } - - @override - Widget build(BuildContext context) { - var pdModel = Provider.of(context); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - title: Text( - AppTranslations.of(context).text('pd.title'), - style: Provider.of(context).isEng - ? TextStyle() - : TextStyle(fontFamily: 'MyanmarUnicode'), - ), - actions: [ - InkWell( - child: Container( - padding: EdgeInsets.only(right: 15, top: 15), - child: Stack( - children: [ - Image.asset( - "assets/date_filter.png", - color: Colors.white, - width: 25, - ), - _dateIndex == 0 - ? Container() - : Positioned( - bottom: 15, - right: 10, - child: Container( - width: 10, - height: 10, - decoration: new BoxDecoration( - shape: BoxShape.circle, - color: secondaryColor, - ), - ), - ) - ], - ), - ), - onTap: () => _selectDate(context), - ), - ], - ), - floatingActionButton: FloatingActionButton( - backgroundColor: primaryColor, - child: Icon(Icons.add), - onPressed: () { - Navigator.push( - context, - MaterialPageRoute(builder: (context) => PDForm()), - ); - }, - ), - body: new ListView.builder( - padding: EdgeInsets.only(left: 10, right: 10, top: 15), - shrinkWrap: true, - itemCount: pdModel.pds.length, - itemBuilder: (BuildContext context, int index) { - return InkWell( - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => PDForm( - pd: pdModel.pds[index], - )), - ); - }, - child: Card( - elevation: 10, - color: Colors.white, - child: Row( - children: [ - new Padding( - padding: EdgeInsets.all(10), - child: Padding( - padding: EdgeInsets.all(10.0), - child: Image.asset( - "assets/pdo.png", - width: 30, - color: primaryColor, - )), - ), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: new Text( - pdModel.pds[index].date == null - ? "" - : DateFormat('dd MMM yyyy') - .format(pdModel.pds[index].date), - style: textStyle), - ), - Padding( - padding: const EdgeInsets.only(left: 8.0), - child: new Text( - pdModel.pds[index].pdNumber == null - ? '' - : pdModel.pds[index].pdNumber, - style: new TextStyle( - fontSize: 12.0, color: Colors.grey), - ), - ), - ], - ), - SizedBox( - height: 15, - ) - ], - ), - ), - ); - }), - ), - ); - } -} diff --git a/lib/pages/phone_input.dart b/lib/pages/phone_input.dart deleted file mode 100644 index d6e6e44..0000000 --- a/lib/pages/phone_input.dart +++ /dev/null @@ -1,103 +0,0 @@ -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; - -class PhoneEditor extends StatefulWidget { - @override - _PhoneEditorState createState() => _PhoneEditorState(); -} - -class _PhoneEditorState extends State { - final _formKey = GlobalKey(); - TextEditingController _phone = new TextEditingController(); - @override - void initState() { - super.initState(); - _phone.text = '09'; - } - - @override - void dispose() { - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return AlertDialog( - title: Center( - child: Text( - AppTranslations.of(context).text("contact.phone.title"), - style: TextStyle( - color: primaryColor, fontWeight: FontWeight.bold, fontSize: 20), - )), - content: Form( - key: _formKey, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - new Expanded( - child: new TextFormField( - keyboardType: TextInputType.number, - autofocus: true, - controller: _phone, - style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20), - cursorColor: primaryColor, - decoration: new InputDecoration( - fillColor: primaryColor, - icon: Icon( - Icons.phone, - color: primaryColor, - ), - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide(color: Colors.grey, width: 1.0)), - ), - validator: (value) { - if (value.isEmpty) { - return AppTranslations.of(context) - .text("contact.phone.empty"); - } - return null; - }, - )) - ], - ), - ), - actions: [ - FlatButton( - child: LocalText( - context, - 'do.cancel', - color: secondaryColor, - ), - onPressed: () { - _phone.clear(); - Navigator.of(context).pop(); - }), - FlatButton( - color: primaryColor, - child: LocalText( - context, - 'do.enter', - color: Colors.white, - fontWeight: FontWeight.bold, - ), - onPressed: () async { - if (!_formKey.currentState.validate()) return; - _save(); - }) - ], - ); - } - - _save() { - try { - Navigator.pop(context, _phone.text); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } - } -} diff --git a/lib/pages/pickup_box_editor.dart b/lib/pages/pickup_box_editor.dart deleted file mode 100644 index 5660500..0000000 --- a/lib/pages/pickup_box_editor.dart +++ /dev/null @@ -1,318 +0,0 @@ -import 'package:fcs/model/main_model.dart'; -import 'package:fcs/model/shipment_model.dart'; -import 'package:fcs/model_fcs/package_model.dart'; -import 'package:fcs/pages/invoice/package_addition.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/pages_fcs/shipping_address_row.dart'; -import 'package:fcs/vo/box.dart'; -import 'package:fcs/vo/cargo.dart'; -import 'package:fcs/vo/package.dart'; -import 'package:fcs/vo/shipping_address.dart'; -import 'package:fcs/widget/bottom_up_page_route.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:fcs/widget/my_data_table.dart'; -import 'package:fcs/widget/progress.dart'; -import 'package:flutter/material.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -import 'package:provider/provider.dart'; -import '../fcs/common/helpers/theme.dart'; -import 'shipping_address_editor.dart'; - -class PickupBoxEditor extends StatefulWidget { - final Box box; - PickupBoxEditor({this.box}); - - @override - _PickupBoxEditorState createState() => _PickupBoxEditorState(); -} - -class _PickupBoxEditorState extends State { - Box _box; - bool _isLoading = false; - - bool isNew; - - bool isMixBox = false; - ShippingAddress _shippingAddress = new ShippingAddress(); - - @override - void initState() { - super.initState(); - if (widget.box != null) { - _box = widget.box; - _shippingAddress = _box.shippingAddress; - - isNew = false; - } else { - List packages = [ - PackageModel.packages[0], - PackageModel.packages[1], - PackageModel.packages[2] - ]; - - List _cargoTypes = [ - Cargo(type: 'General Cargo', weight: 25), - Cargo(type: 'Medicine', weight: 20), - Cargo(type: 'Dangerous Cargo', weight: 30) - ]; - - var shipmentModel = Provider.of(context, listen: false); - _shippingAddress = shipmentModel.shippingAddresses[1]; - - isNew = true; - _box = Box( - rate: 0, - weight: 75, - width: 0, - height: 0, - length: 0, - packages: packages, - cargoTypes: _cargoTypes, - shipmentWeight: 0); - } - } - - @override - void dispose() { - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - centerTitle: true, - leading: new IconButton( - icon: new Icon(Icons.close), - onPressed: () => Navigator.of(context).pop(), - ), - backgroundColor: primaryColor, - title: Text(AppTranslations.of(context).text("package.edit.title")), - ), - body: Card( - child: Column( - children: [ - Expanded( - child: ListView( - children: [ - ExpansionTile( - title: Text( - 'Cargo Types', - style: TextStyle( - color: primaryColor, fontWeight: FontWeight.bold), - ), - children: [ - Padding( - padding: const EdgeInsets.only(left: 20.0, right: 20), - child: TextFormField( - initialValue: _box.weight.toString(), - textAlign: TextAlign.end, - decoration: InputDecoration( - fillColor: Colors.white, - labelText: 'Actual Weight', - filled: true, - icon: Icon(FontAwesomeIcons.weightHanging, - color: primaryColor), - )), - ), - Container( - padding: EdgeInsets.only(top: 10), - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: MyDataTable( - headingRowHeight: 40, - columnSpacing: 120, - columns: [ - MyDataColumn( - label: LocalText( - context, - "cargo.type", - color: Colors.grey, - ), - ), - MyDataColumn( - label: LocalText( - context, - "cargo.weight", - color: Colors.grey, - ), - ), - ], - rows: getCargoRows(context), - ), - ), - ), - Container( - padding: EdgeInsets.only(top: 20), - child: Align( - alignment: Alignment.bottomRight, - child: FloatingActionButton.extended( - icon: Icon(Icons.add), - label: Text("Add Cargo"), - backgroundColor: primaryColor, - onPressed: () { - // Navigator.of(context).push( - // BottomUpPageRoute(PackageAddition())); - }, - ), - ), - ), - SizedBox(height: 25), - ], - ), - ExpansionTile( - title: Text( - 'Box Dimension', - style: TextStyle( - color: primaryColor, fontWeight: FontWeight.bold), - ), - children: [ - Padding( - padding: const EdgeInsets.only(left: 20.0, right: 20), - child: fcsInputReadOnly( - "Shipment Weight", FontAwesomeIcons.weightHanging, - value: _box.shipmentWeight.toString()), - ), - Padding( - padding: const EdgeInsets.only(left: 20.0, right: 20), - child: TextFormField( - initialValue: _box.width.toString(), - textAlign: TextAlign.end, - decoration: InputDecoration( - fillColor: Colors.white, - labelText: 'Width', - filled: true, - icon: Icon(FontAwesomeIcons.arrowCircleRight, - color: primaryColor), - )), - ), - Padding( - padding: const EdgeInsets.only(left: 20.0, right: 20), - child: TextFormField( - initialValue: _box.height.toString(), - textAlign: TextAlign.end, - decoration: InputDecoration( - fillColor: Colors.white, - labelText: 'Height', - filled: true, - icon: Icon(FontAwesomeIcons.arrowAltCircleUp, - color: primaryColor), - )), - ), - Padding( - padding: const EdgeInsets.only(left: 20.0, right: 20), - child: TextFormField( - initialValue: _box.length.toString(), - textAlign: TextAlign.end, - decoration: InputDecoration( - fillColor: Colors.white, - labelText: 'Length', - filled: true, - icon: Icon(FontAwesomeIcons.arrowCircleUp, - color: primaryColor), - )), - ), - SizedBox(height: 25), - ], - ), - ExpansionTile( - title: Text( - 'Shipment Address', - style: TextStyle( - color: primaryColor, fontWeight: FontWeight.bold), - ), - children: [ - ShippingAddressRow(shippingAddress: _shippingAddress), - Container( - padding: - EdgeInsets.only(top: 20, bottom: 15, right: 15), - child: Align( - alignment: Alignment.bottomRight, - child: Container( - width: 120, - height: 40, - child: FloatingActionButton.extended( - materialTapTargetSize: - MaterialTapTargetSize.shrinkWrap, - onPressed: () {}, - icon: Icon(Icons.add), - label: Text( - 'Select\nAddress', - style: TextStyle(fontSize: 12), - ), - backgroundColor: primaryColor, - ), - ), - ), - ), - SizedBox(height: 25), - ], - ), - ], - ), - ), - widget.box == null - ? Align( - alignment: Alignment.bottomCenter, - child: Center( - child: Container( - width: 250, - child: FlatButton( - child: Text('Create New Package'), - color: primaryColor, - textColor: Colors.white, - onPressed: () { - Navigator.pop(context); - }, - ), - ))) - : Container( - child: Column( - children: [ - Align( - alignment: Alignment.bottomCenter, - child: Center( - child: Container( - width: 250, - child: FlatButton( - child: Text('Update Package'), - color: primaryColor, - textColor: Colors.white, - onPressed: () { - Navigator.pop(context); - }, - ), - ))), - ], - )) - ], - ), - ), - ), - ); - } - - List getCargoRows(BuildContext context) { - if (_box == null || _box.cargoTypes == null) { - return []; - } - return _box.cargoTypes.map((c) { - return MyDataRow( - onSelectChanged: (bool selected) {}, - cells: [ - MyDataCell(new Text( - c.type == null ? "" : c.type, - style: textStyle, - )), - MyDataCell( - new Text(c.weight == null ? "0" : c.weight.toString(), - style: textStyle), - ), - ], - ); - }).toList(); - } -} diff --git a/lib/pages/pickup_editor.dart b/lib/pages/pickup_editor.dart deleted file mode 100644 index 3e3d574..0000000 --- a/lib/pages/pickup_editor.dart +++ /dev/null @@ -1,836 +0,0 @@ -import 'package:fcs/model/main_model.dart'; -import 'package:fcs/model/pickup_model.dart'; -import 'package:fcs/model/shipment_model.dart'; -import 'package:fcs/model_fcs/box_model.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/pages_fcs/shipping_address_row.dart'; -import 'package:fcs/vo/box.dart'; -import 'package:fcs/vo/cargo.dart'; -import 'package:fcs/vo/pickup.dart'; -import 'package:fcs/vo/shipping_address.dart'; -import 'package:fcs/widget/bottom_up_page_route.dart'; -import 'package:fcs/widget/fcs_text_field.dart'; -import 'package:fcs/widget/fcs_text_field_readonly.dart'; -import 'package:fcs/widget/multi_img_controller.dart'; -import 'package:fcs/widget/multi_img_file.dart'; -import 'package:flutter_datetime_picker/flutter_datetime_picker.dart'; -import 'package:flutter_icons/flutter_icons.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; - -import 'package:flutter/material.dart'; -import 'package:fcs/widget/progress.dart'; - -import '../fcs/common/helpers/theme.dart'; -import 'pickup_box_editor.dart'; - -class PickUpEditor extends StatefulWidget { - final PickUp pickUp; - PickUpEditor({this.pickUp}); - - @override - _PickUpEditorState createState() => _PickUpEditorState(); -} - -class _PickUpEditorState extends State { - var dateFormatter = new DateFormat('dd MMM yyyy'); - final numberFormatter = new NumberFormat("#,###"); - MultiImgController multiImgController = MultiImgController(); - - TextEditingController _addressEditingController = new TextEditingController(); - TextEditingController _fromTimeEditingController = - new TextEditingController(); - TextEditingController _toTimeEditingController = new TextEditingController(); - TextEditingController _noOfPackageEditingController = - new TextEditingController(); - TextEditingController _weightEditingController = new TextEditingController(); - TextEditingController _recipientNameEditingController = - new TextEditingController(); - TextEditingController _recipientPhoneEditingController = - new TextEditingController(); - TextEditingController _recipientAddressEditingController = - new TextEditingController(); - TextEditingController _pickupDate = new TextEditingController(); - TextEditingController _handlingFeeController = new TextEditingController(); - - PickUp _pickUp; - bool _isLoading = false; - var now = new DateTime.now(); - bool isNew; - ShippingAddress _shippingAddress = new ShippingAddress(); - - int _currVal = 1; - - @override - void initState() { - super.initState(); - if (widget.pickUp != null) { - isNew = false; - _pickUp = widget.pickUp; - _addressEditingController.text = _pickUp.address; - _fromTimeEditingController.text = _pickUp.fromTime; - _toTimeEditingController.text = _pickUp.toTime; - _noOfPackageEditingController.text = _pickUp.numberOfPackage.toString(); - _weightEditingController.text = _pickUp.weight.toString(); - _pickupDate.text = dateFormatter.format(now); - _handlingFeeController.text = numberFormatter.format(_pickUp.handlingFee); - _currVal = _pickUp.radioIndex; - - var mainModel = Provider.of(context, listen: false); - _recipientNameEditingController.text = mainModel.recipient.name; - _recipientPhoneEditingController.text = mainModel.recipient.phoneNumber; - _recipientAddressEditingController.text = - mainModel.recipient.shippingAddress; - } else { - isNew = true; - List _cargoTypes = [ - Cargo(type: 'General Cargo', weight: 25), - Cargo(type: 'Medicine', weight: 20), - Cargo(type: 'Dangerous Cargo', weight: 30) - ]; - _pickUp = PickUp(cargoTypes: _cargoTypes); - } - var shipmentModel = Provider.of(context, listen: false); - _shippingAddress = shipmentModel.shippingAddresses[1]; - } - - @override - void dispose() { - super.dispose(); - } - - @override - Widget build(BuildContext context) { - var pickupModel = Provider.of(context); - - final pickUpAddress = fcsInput('Pickup Address', Icons.location_on, - controller: _addressEditingController); - - final pickUpAddressReadOnly = fcsInputReadOnly( - 'Pickup Address', Icons.location_on, - controller: _addressEditingController); - - final fromTimeBox = fcsInput( - 'From', - Icons.timer, - controller: _fromTimeEditingController, - ); - - final toTimeBox = fcsInput( - 'To', - null, - controller: _toTimeEditingController, - ); - - final fromTimeBoxReadOnly = fcsInputReadOnly( - 'From', - Icons.timer, - controller: _fromTimeEditingController, - ); - - final toTimeBoxReadOnly = fcsInputReadOnly( - 'To', - null, - controller: _toTimeEditingController, - ); - - final pickupTime = Padding( - padding: const EdgeInsets.only(left: 20.0), - child: Row( - children: [ - Container( - child: fromTimeBox, - width: 120, - ), - Padding( - padding: const EdgeInsets.only(left: 8.0), - child: Text('-'), - ), - Container( - child: toTimeBox, - width: 120, - ), - ], - ), - ); - - final pickupTimeReadOnly = Padding( - padding: const EdgeInsets.only(left: 20.0), - child: Row( - children: [ - SizedBox(height: 5), - Container( - child: fromTimeBoxReadOnly, - width: 120, - ), - Padding( - padding: const EdgeInsets.only(left: 8.0), - child: Text('-'), - ), - Container( - child: toTimeBoxReadOnly, - width: 120, - ), - ], - ), - ); - - final noOfPackageBox = fcsInput( - 'Number of Packages', - Octicons.package, - controller: _noOfPackageEditingController, - ); - - final noOfPackageBoxReadonly = fcsInputReadOnly( - 'Number of Packages', - Octicons.package, - controller: _noOfPackageEditingController, - ); - - final requestDateBox = Container( - child: InkWell( - onTap: () { - DatePicker.showDatePicker( - context, - showTitleActions: true, - currentTime: _pickupDate.text == "" - ? null - : dateFormatter.parse(_pickupDate.text), - minTime: DateTime.now(), - maxTime: DateTime(2030, 12, 31), - onConfirm: (date) {}, - locale: LocaleType.en, - ); - }, - child: TextFormField( - controller: _pickupDate, - autofocus: false, - cursorColor: primaryColor, - style: textStyle, - enabled: false, - keyboardType: TextInputType.datetime, - decoration: new InputDecoration( - border: InputBorder.none, - focusedBorder: InputBorder.none, - labelText: AppTranslations.of(context).text("pickup.date"), - // labelStyle: languageModel.isEng ? labelStyle : labelStyleMM, - contentPadding: - EdgeInsets.symmetric(vertical: 10.0, horizontal: 0.0), - icon: Icon( - Icons.date_range, - color: primaryColor, - )), - validator: (value) { - if (value.isEmpty) { - return AppTranslations.of(context).text("do.form.date"); - } - return null; - }, - ), - )); - - MainModel mainModel = Provider.of(context); - var boxModel = Provider.of(context); - var shipmentModel = Provider.of(context); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - centerTitle: true, - leading: new IconButton( - icon: new Icon(Icons.close), - onPressed: () => Navigator.of(context).pop(), - ), - backgroundColor: primaryColor, - title: Text(AppTranslations.of(context).text("pickup.edit.title")), - ), - body: Card( - child: Column( - children: [ - Expanded( - child: Padding( - padding: const EdgeInsets.all(10.0), - child: ListView(children: [ - Center(child: nameWidget(mainModel.customer.name)), - Center(child: nameWidget(mainModel.customer.phoneNumber)), - isNew - ? Container() - : Center( - child: Padding( - padding: const EdgeInsets.only(left: 10.0, top: 8), - child: Text( - '#P200304', - style: TextStyle( - color: Colors.black87, - fontSize: 14, - fontWeight: FontWeight.bold), - ), - ), - ), - widget.pickUp == null - ? Container() - : widget.pickUp.isCourier - ? Padding( - padding: const EdgeInsets.only(left: 15.0), - child: fcsInputReadOnly( - "Handling Fee/Courier Fee", - FontAwesomeIcons.moneyBill, - controller: _handlingFeeController), - ) - : Padding( - padding: const EdgeInsets.only(left: 15.0), - child: fcsInputReadOnly( - "Handling Fee/Courier Fee", - FontAwesomeIcons.moneyBill, - controller: _handlingFeeController), - ), - - ExpansionTile( - title: Text( - 'Pickup/Drop-off', - style: TextStyle( - color: primaryColor, fontWeight: FontWeight.bold), - ), - children: [ - Container( - child: Wrap( - children: pickupModel.radioGroups - .map((t) => RadioListTile( - title: Text("${t.text}"), - groupValue: _currVal, - activeColor: primaryColor, - value: t.index, - onChanged: (val) { - setState(() { - _currVal = val; - }); - }, - )) - .toList(), - ), - ), - ], - ), - _currVal == 3 - ? Container( - child: ShippingAddressRow( - shippingAddress: ShippingAddress( - fullName: 'FCS Office', - addressLine1: '154-19 64th Ave.', - addressLine2: 'Flushing', - city: 'NY', - state: 'NY', - phoneNumber: '+1 (292)215-2247'), - ), - ) - : _currVal == 4 - ? Container( - child: Column( - children: [ - Container( - padding: EdgeInsets.only( - top: 20, bottom: 15, right: 15), - child: Align( - alignment: Alignment.center, - child: Container( - width: 350, - height: 40, - child: FloatingActionButton.extended( - materialTapTargetSize: - MaterialTapTargetSize.shrinkWrap, - onPressed: () {}, - icon: Icon(Icons.arrow_right), - label: Text( - 'Visit courier websie for nearest drop-off', - style: TextStyle(fontSize: 12), - ), - backgroundColor: primaryColor, - ), - ), - ), - ), - ], - )) - : Container(), - - ExpansionTile( - title: Text( - 'Package Information', - style: TextStyle( - color: primaryColor, fontWeight: FontWeight.bold), - ), - children: [ - Column( - children: getBoxList(context, boxModel.boxes), - ), - Container( - padding: - EdgeInsets.only(top: 20, bottom: 15, right: 15), - child: Align( - alignment: Alignment.bottomRight, - child: Container( - width: 120, - height: 40, - child: FloatingActionButton.extended( - materialTapTargetSize: - MaterialTapTargetSize.shrinkWrap, - icon: Icon(Icons.add), - onPressed: () { - Navigator.push( - context, - BottomUpPageRoute(PickupBoxEditor()), - ); - }, - label: Text( - 'Add Package', - style: TextStyle(fontSize: 12), - ), - backgroundColor: primaryColor, - ), - ), - ), - ), - SizedBox(height: 10.0), - ], - ), - _currVal == 3 || _currVal == 4 - ? Container() - : ExpansionTile( - title: Text( - 'Pickup Location / Time', - style: TextStyle( - color: primaryColor, - fontWeight: FontWeight.bold), - ), - children: [ - Padding( - padding: const EdgeInsets.only(left: 20.0), - child: Column( - children: [ - Row( - children: [ - Icon( - Icons.location_on, - color: primaryColor, - ), - Padding( - padding: const EdgeInsets.all(8.0), - child: Text('Pickup Address'), - ), - ], - ), - Padding( - padding: const EdgeInsets.only(left: 10.0), - child: ShippingAddressRow( - shippingAddress: _shippingAddress), - ), - Container( - padding: EdgeInsets.only( - top: 20, bottom: 15, right: 15), - child: Align( - alignment: Alignment.bottomRight, - child: Container( - width: 120, - height: 40, - child: FloatingActionButton.extended( - materialTapTargetSize: - MaterialTapTargetSize.shrinkWrap, - onPressed: () {}, - icon: Icon(Icons.add), - label: Text( - 'Select\nAddress', - style: TextStyle(fontSize: 12), - ), - backgroundColor: primaryColor, - ), - ), - ), - ), - ], - ), - // child: ExpansionTile( - // leading: Icon( - // Icons.location_on, - // color: primaryColor, - // ), - // title: Text('My Address'), - // children: [ - // Padding( - // padding: const EdgeInsets.only(left: 10.0), - // child: ShippingAddressRow( - // shippingAddress: _shippingAddress), - // ), - // Container( - // padding: EdgeInsets.only( - // top: 20, bottom: 15, right: 15), - // child: Align( - // alignment: Alignment.bottomRight, - // child: Container( - // width: 120, - // height: 40, - // child: FloatingActionButton.extended( - // materialTapTargetSize: - // MaterialTapTargetSize.shrinkWrap, - // onPressed: () {}, - // icon: Icon(Icons.add), - // label: Text( - // 'Select\nAddress', - // style: TextStyle(fontSize: 12), - // ), - // backgroundColor: primaryColor, - // ), - // ), - // ), - // ), - // ], - // ), - ), - widget.pickUp == null - ? pickupTime - : widget.pickUp.status == 'Pending' - ? pickupTime - : pickupTimeReadOnly, - Padding( - padding: const EdgeInsets.only(left: 20.0), - child: Column( - children: [ - SizedBox(height: 5), - Container(height: 50.0, child: requestDateBox) - ], - ), - ), - SizedBox(height: 15.0), - ], - ), - // ExpansionTile( - // title: Text( - // 'Package Information', - // style: TextStyle( - // color: primaryColor, fontWeight: FontWeight.bold), - // ), - // children: [ - // Padding( - // padding: const EdgeInsets.only(left: 20.0), - // child: widget.pickUp == null - // ? noOfPackageBox - // : widget.pickUp.status == 'Pending' - // ? noOfPackageBox - // : noOfPackageBoxReadonly, - // ), - // Padding( - // padding: const EdgeInsets.only(left: 20.0), - // child: widget.pickUp == null - // ? fcsInput("Total Weight (lb)", - // FontAwesomeIcons.weightHanging, - // controller: _weightEditingController) - // : widget.pickUp.status == 'Pending' - // ? fcsInput("Total Weight (lb)", - // FontAwesomeIcons.weightHanging, - // controller: _weightEditingController) - // : fcsInputReadOnly("Total Weight (lb)", - // FontAwesomeIcons.weightHanging, - // controller: _weightEditingController), - // ), - // Padding( - // padding: const EdgeInsets.only(left: 20.0), - // child: fcsInput("Remark", MaterialCommunityIcons.note), - // ), - // Padding( - // padding: const EdgeInsets.only(left: 3.0), - // child: ExpansionTile( - // leading: Icon( - // SimpleLineIcons.location_pin, - // color: primaryColor, - // ), - // title: Text( - // 'Shipping Address', - // ), - // children: [ - // ShippingAddressRow( - // shippingAddress: _shippingAddress), - // Container( - // padding: EdgeInsets.only( - // top: 20, bottom: 15, right: 15), - // child: Align( - // alignment: Alignment.bottomRight, - // child: Container( - // width: 130, - // height: 40, - // child: FloatingActionButton.extended( - // materialTapTargetSize: - // MaterialTapTargetSize.shrinkWrap, - // onPressed: () {}, - // icon: Icon(Icons.add), - // label: Text( - // 'Add Shipping\nAddress', - // style: TextStyle(fontSize: 12), - // ), - // backgroundColor: primaryColor, - // ), - // ), - // ), - // ), - // ], - // ), - // ), - // SizedBox(height: 10.0), - // ], - // ), - mainModel.isCustomer() - ? Container() - : ExpansionTile( - title: Text('For FCS'), - children: [ - widget.pickUp != null - ? widget.pickUp.status == 'Pending' - ? Padding( - padding: - const EdgeInsets.only(left: 20.0), - child: fcsDropDown("Assigned", - MaterialCommunityIcons.worker), - ) - : Container() - : Container(), - Padding( - padding: EdgeInsets.only(left: 20), - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - padding: EdgeInsets.only(top: 8), - child: Text( - 'Attach Courier Shiping Labels', - style: TextStyle( - color: Colors.black, fontSize: 16), - ), - ), - Container( - padding: EdgeInsets.only(left: 10), - child: MultiImageFile( - enabled: true, - controller: multiImgController, - title: "Receipt File", - )), - ], - ), - ), - ], - ), - ]), - )), - widget.pickUp == null - ? Align( - alignment: Alignment.bottomCenter, - child: Center( - child: Container( - width: 250, - child: FlatButton( - child: Text('Create shipment'), - color: primaryColor, - textColor: Colors.white, - onPressed: () { - Navigator.pop(context); - }, - ), - ))) - : Container( - child: Column( - children: [ - widget.pickUp.status == 'Confirmed' - ? Align( - alignment: Alignment.bottomCenter, - child: Center( - child: Container( - width: 250, - child: FlatButton( - child: Text('Complete Shipment'), - color: primaryColor, - textColor: Colors.white, - onPressed: () { - Navigator.pop(context); - }, - ), - ))) - : Align( - alignment: Alignment.bottomCenter, - child: Center( - child: Container( - width: 250, - child: FlatButton( - child: Text('Confirm Shipment'), - color: primaryColor, - textColor: Colors.white, - onPressed: () { - Navigator.pop(context); - }, - ), - ))), - Align( - alignment: Alignment.bottomCenter, - child: Center( - child: Container( - width: 250, - child: FlatButton( - child: Text('Cancel Shipment'), - color: Colors.grey[600], - textColor: Colors.white, - onPressed: () { - Navigator.pop(context); - }, - ), - ))) - ], - )) - ], - ), - ), - ), - ); - } - - List getBoxList(BuildContext context, List boxes) { - List _boxes = [boxes[0], boxes[1]]; - - return _boxes.asMap().entries.map((_box) { - ShippingAddress shippingAddress = _box.value.shippingAddress; - - return InkWell( - onTap: () { - Navigator.of(context) - .push(BottomUpPageRoute(PickupBoxEditor(box: _box.value))); - }, - child: Container( - padding: EdgeInsets.only(left: 10), - child: Column( - children: [ - Row( - children: [ - Expanded( - child: new Padding( - padding: const EdgeInsets.symmetric(vertical: 10.0), - child: new Row( - children: [ - new Expanded( - child: new Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.only(left: 8.0), - child: new Text( - shippingAddress.fullName == null - ? '' - : shippingAddress.fullName, - style: new TextStyle( - fontSize: 15.0, - color: Colors.black, - fontWeight: FontWeight.bold), - ), - ), - Padding( - padding: const EdgeInsets.only(left: 8.0), - child: new Text( - shippingAddress.addressLine1 == null - ? '' - : shippingAddress.addressLine1, - style: new TextStyle( - fontSize: 14.0, color: Colors.grey), - ), - ), - Padding( - padding: const EdgeInsets.only(left: 8.0), - child: new Text( - shippingAddress.addressLine2 == null - ? '' - : shippingAddress.addressLine2, - style: new TextStyle( - fontSize: 14.0, color: Colors.grey), - ), - ), - Padding( - padding: const EdgeInsets.only(left: 8.0), - child: new Text( - shippingAddress.city == null - ? '' - : shippingAddress.city, - style: new TextStyle( - fontSize: 14.0, color: Colors.grey), - ), - ), - Padding( - padding: const EdgeInsets.only(left: 8.0), - child: new Text( - shippingAddress.state == null - ? '' - : shippingAddress.state, - style: new TextStyle( - fontSize: 14.0, color: Colors.grey), - ), - ), - Padding( - padding: const EdgeInsets.only(left: 8.0), - child: new Text( - shippingAddress.phoneNumber == null - ? '' - : "Phone:${shippingAddress.phoneNumber}", - style: new TextStyle( - fontSize: 14.0, color: Colors.grey), - ), - ), - ], - ), - ), - ], - ), - ), - ), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.only(left: 8.0), - child: new Text( - "L${_box.value.length}xW${_box.value.weight}xH${_box.value.height}", - style: new TextStyle( - fontSize: 15.0, color: Colors.black), - ), - ), - Padding( - padding: const EdgeInsets.only(left: 8.0), - child: new Text( - _box.value.weight == null - ? '' - : "Actual Weight:${_box.value.weight.toString()}lb", - style: - new TextStyle(fontSize: 14.0, color: Colors.grey), - ), - ), - Padding( - padding: const EdgeInsets.only(left: 8.0), - child: new Text( - _box.value.shipmentWeight == null - ? '' - : "Shipment Weight:${_box.value.shipmentWeight.toString()}lb", - style: - new TextStyle(fontSize: 14.0, color: Colors.grey), - ), - ), - ], - ) - ], - ), - _box.key == _boxes.length - 1 - ? Container() - : Divider( - color: Colors.black, - ) - ], - ), - ), - ); - }).toList(); - } -} diff --git a/lib/pages/pickup_list.dart b/lib/pages/pickup_list.dart deleted file mode 100644 index 4018abe..0000000 --- a/lib/pages/pickup_list.dart +++ /dev/null @@ -1,167 +0,0 @@ -import 'package:fcs/model/pickup_model.dart'; -import 'package:fcs/pages/pickup_list_row.dart'; -import 'package:fcs/widget/bottom_up_page_route.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/pages/search_page.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; - -import 'package:flutter/material.dart'; -import 'package:fcs/widget/progress.dart'; - -import '../fcs/common/helpers/theme.dart'; -import 'pickup_editor.dart'; - -class PickUpList extends StatefulWidget { - @override - _PickUpListState createState() => _PickUpListState(); -} - -class _PickUpListState extends State { - bool _isLoading = false; - - @override - void initState() { - super.initState(); - } - - @override - void dispose() { - super.dispose(); - } - - @override - Widget build(BuildContext context) { - var pickupModel = Provider.of(context); - return LocalProgress( - inAsyncCall: _isLoading, - child: DefaultTabController( - length: 3, - child: Scaffold( - appBar: AppBar( - centerTitle: true, - leading: new IconButton( - icon: new Icon(Icons.close), - onPressed: () => Navigator.of(context).pop(), - ), - backgroundColor: primaryColor, - title: Text(AppTranslations.of(context).text("pickup.title")), - actions: [ - IconButton( - icon: Icon( - Icons.search, - color: Colors.white, - ), - iconSize: 30, - onPressed: () => showPlacesSearch(context), - ), - ], - // bottom: TabBar( - // unselectedLabelColor: Colors.grey, - // tabs: [ - // Tab( - // text: "Upcoming", - // ), - // Tab(text: "Completed"), - // Tab(text: "Canceled"), - // ], - // ), - ), - floatingActionButton: FloatingActionButton.extended( - onPressed: () { - _newPickup(); - }, - icon: Icon(Icons.add), - label: Text(AppTranslations.of(context).text("pickup.new")), - backgroundColor: primaryColor, - ), - body: new ListView.separated( - separatorBuilder: (context, index) => Divider( - color: Colors.black, - ), - scrollDirection: Axis.vertical, - padding: EdgeInsets.only(top: 15), - shrinkWrap: true, - itemCount: pickupModel.pickups.length, - itemBuilder: (BuildContext context, int index) { - return PickupListRow(pickUp: pickupModel.pickups[index]); - }), - // body: TabBarView( - // children: [ - // //Icon(Icons.directions_car), - // _upComing(), - // _completed(), - // _canceled() - // ], - // ) - ), - ), - ); - } - - _newPickup() { - Navigator.of(context).push(BottomUpPageRoute(PickUpEditor())); - } - - Widget _upComing() { - var pickupModel = Provider.of(context); - return Column( - children: [ - Expanded( - child: new ListView.separated( - separatorBuilder: (context, index) => Divider( - color: Colors.black, - ), - scrollDirection: Axis.vertical, - padding: EdgeInsets.only(top: 15), - shrinkWrap: true, - itemCount: pickupModel.upcoming.length, - itemBuilder: (BuildContext context, int index) { - return PickupListRow(pickUp: pickupModel.upcoming[index]); - }), - ), - ], - ); - } - - Widget _completed() { - var pickupModel = Provider.of(context); - return Column( - children: [ - Expanded( - child: new ListView.separated( - separatorBuilder: (context, index) => Divider( - color: Colors.black, - ), - scrollDirection: Axis.vertical, - padding: EdgeInsets.only(top: 15), - shrinkWrap: true, - itemCount: pickupModel.completed.length, - itemBuilder: (BuildContext context, int index) { - return PickupListRow(pickUp: pickupModel.completed[index]); - }), - ), - ], - ); - } - - Widget _canceled() { - var pickupModel = Provider.of(context); - return Column( - children: [ - Expanded( - child: new ListView.separated( - separatorBuilder: (context, index) => Divider( - color: Colors.black, - ), - scrollDirection: Axis.vertical, - padding: EdgeInsets.only(top: 15), - shrinkWrap: true, - itemCount: pickupModel.canceled.length, - itemBuilder: (BuildContext context, int index) { - return PickupListRow(pickUp: pickupModel.canceled[index]); - }), - ), - ], - ); - } -} diff --git a/lib/pages/pickup_list_row.dart b/lib/pages/pickup_list_row.dart deleted file mode 100644 index 7ee9b8d..0000000 --- a/lib/pages/pickup_list_row.dart +++ /dev/null @@ -1,127 +0,0 @@ -import 'package:fcs/model/pickup_model.dart'; -import 'package:fcs/pages/pickup_editor.dart'; -import 'package:fcs/vo/pickup.dart'; -import 'package:fcs/widget/bottom_up_page_route.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_icons/flutter_icons.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/buyer_model.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/buyer.dart'; - -import 'buyer_info.dart'; - -class PickupListRow extends StatefulWidget { - final PickUp pickUp; - const PickupListRow({this.pickUp}); - - @override - _PickupListRowState createState() => _PickupListRowState(); -} - -class _PickupListRowState extends State { - final double dotSize = 15.0; - PickUp _pickUp = new PickUp(); - - @override - void initState() { - super.initState(); - // PickUpModel pickUpModel = Provider.of(context, listen: false); - if (widget.pickUp != null) { - _pickUp = widget.pickUp; - // pickUpModel.pickups.forEach((b) { - // if (widget.pickUp.id == b.id) { - // _pickUp = b; - // } - // }); - } - } - - @override - Widget build(BuildContext context) { - print('_pickup $_pickUp'); - return Container( - padding: EdgeInsets.only(left: 15, right: 15), - child: InkWell( - onTap: () { - Navigator.of(context) - .push(BottomUpPageRoute(PickUpEditor(pickUp: _pickUp))); - }, - child: Row( - children: [ - Expanded( - child: new Padding( - padding: const EdgeInsets.symmetric(vertical: 16.0), - child: new Row( - children: [ - Padding( - padding: EdgeInsets.all(5.0), - child: Icon( - SimpleLineIcons.direction, - color: primaryColor, - )), - new Expanded( - child: new Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.only(left: 8.0), - child: new Text( - _pickUp.id == null ? '' : _pickUp.id, - style: new TextStyle( - fontSize: 15.0, color: Colors.black), - ), - ), - Padding( - padding: const EdgeInsets.only(left: 10.0, top: 10), - child: new Text( - _pickUp.id == null - ? '' - : "Last ${_pickUp.last} days", - style: new TextStyle( - fontSize: 15.0, color: Colors.grey), - ), - ) - ], - ), - ), - ], - ), - ), - ), - Column( - children: [ - Padding( - padding: const EdgeInsets.all(0), - child: getStatus(_pickUp.status), - ), - Padding( - padding: const EdgeInsets.only(left: 8.0, top: 5, bottom: 5), - child: Row( - children: [ - new Text( - _pickUp.weight == null - ? '' - : _pickUp.weight.toString() + 'lb - ', - style: - new TextStyle(fontSize: 15.0, color: Colors.grey), - ), - new Text( - _pickUp.numberOfPackage == null - ? "" - : _pickUp.numberOfPackage.toString() + ' packages', - style: - new TextStyle(fontSize: 15.0, color: Colors.grey), - ), - ], - ), - ), - ], - ) - ], - ), - ), - ); - } -} diff --git a/lib/pages/pin_login_dialog.dart b/lib/pages/pin_login_dialog.dart deleted file mode 100644 index c62bcc0..0000000 --- a/lib/pages/pin_login_dialog.dart +++ /dev/null @@ -1,102 +0,0 @@ -import 'dart:async'; - -import 'package:flutter/material.dart'; -import 'package:flutter_verification_code_input/flutter_verification_code_input.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/main_model.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:quiver/async.dart'; - -class PinLoginDialog extends StatefulWidget { - @override - _PinLoginDialogState createState() => _PinLoginDialogState(); -} - -class _PinLoginDialogState extends State { - String pin; - - @override - void initState() { - super.initState(); - } - - @override - Widget build(BuildContext context) { - var mainModel = Provider.of(context); - - return AlertDialog( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.all(Radius.circular(32.0))), - title: Column( - children: [ - Image.asset( - "assets/pin.png", - height: 90, - color: primaryColor, - ), - Text( - "Enter PIN Code", - style: TextStyle( - color: primaryColor, fontWeight: FontWeight.bold, fontSize: 20), - ), - ], - ), - content: Container( - width: double.maxFinite, - height: 120.0, - child: new ListView( - shrinkWrap: true, - children: [ - Center( - child: VerificationCodeInput( - keyboardType: TextInputType.number, - length: 6, - autofocus: false, - itemSize: 40, - itemDecoration: BoxDecoration( - border: Border.all( - color: Colors.grey, - ), - ), - textStyle: TextStyle(fontWeight: FontWeight.bold, fontSize: 23), - onCompleted: (String value) { - this.pin = value; - }, - ), - ), - SizedBox( - height: 15, - ), - Row( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - FlatButton( - child: Text("Cancel"), - onPressed: () { - Navigator.of(context).pop(); - }), - FlatButton( - color: primaryColor, - child: Text("OK", - style: TextStyle( - color: Colors.white, fontWeight: FontWeight.bold)), - onPressed: () async { - if (this.pin == null) return; - - if (mainModel.user.pin == this.pin) { - mainModel.resetPinTimer(); - Navigator.of(context).pop(); - } else { - showMsgDialog(context, "Error", "Invalid PIN Code !"); - } - }), - ], - ) - ], - ), - ), - ); - } -} diff --git a/lib/pages/po/po_files.dart b/lib/pages/po/po_files.dart deleted file mode 100644 index 0d1268d..0000000 --- a/lib/pages/po/po_files.dart +++ /dev/null @@ -1,27 +0,0 @@ -import 'dart:io'; - -class POFiles { - File poPaymentFile, storageChargeFile; - List poPaymentFilesAdded=[]; - List poPaymentFilesRemoved=[]; // only url - bool poFileChanged = false, storageFileChanged = false; - - set addPoPaymentFile(File file) { - poPaymentFilesAdded.add(file); - poFileChanged = true; - } - - set removePoPaymentFile(String url) { - poPaymentFilesRemoved.add(url); - poFileChanged = true; - } - - set setStorageChargeFile(File file) { - storageChargeFile = file; - storageFileChanged = true; - } - - bool get anyChanged => poFileChanged || storageFileChanged; - - -} diff --git a/lib/pages/po/po_item.dart b/lib/pages/po/po_item.dart deleted file mode 100644 index 6f11ba9..0000000 --- a/lib/pages/po/po_item.dart +++ /dev/null @@ -1,208 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/language_model.dart'; -import 'package:fcs/model/product_model.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/po.dart'; -import 'package:fcs/vo/product.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:fcs/widget/progress.dart'; - -import '../../fcs/common/pages/util.dart'; - -class POItem extends StatefulWidget { - final POLine poLine; - const POItem({Key key, this.poLine}) : super(key: key); - @override - _POItemState createState() => _POItemState(); -} - -class _POItemState extends State { - final _formKey = GlobalKey(); - bool _isLoading = false; - String currentProductID; - TextEditingController _qty = new TextEditingController(); - POLine poLine = POLine(); - - @override - void initState() { - super.initState(); - if (widget.poLine != null) { - this.poLine = widget.poLine; - - this._qty.text = this.poLine.qty.toString(); - this.currentProductID = this.poLine.productID; - this.poLine.action = "update"; - } else { - this.poLine.action = "create"; - } - } - - @override - void dispose() { - super.dispose(); - } - - Widget showProducts(BuildContext context, ProductModel productModel) { - return Row( - mainAxisSize: MainAxisSize.max, - children: [ - Icon( - FontAwesomeIcons.tag, - color: primaryColor, - size: 20, - ), - SizedBox( - width: 20, - ), - new Flexible( - child: Container( - width: 170.0, - child: DropdownButton( - value: currentProductID, - isExpanded: true, - hint: Text( - 'Select Product', - style: labelStyle, - ), - onChanged: changedProduct, - items: productModel.products - .map>((Product product) { - return new DropdownMenuItem( - value: product.id, - child: new Text(product.name, style: textStyle), - ); - }).toList(), - ), - ), - ), - ], - ); - } - - void changedProduct(selected) { - setState(() { - // currentProductID = selected; - }); - } - - @override - Widget build(BuildContext context) { - var productModel = Provider.of(context); - var languageModel = Provider.of(context); - - final volumeBox = Container( - padding: EdgeInsets.only(top: 10), - child: TextFormField( - controller: _qty, - autofocus: false, - cursorColor: primaryColor, - keyboardType: TextInputType.number, - decoration: new InputDecoration( - labelText: AppTranslations.of(context).text("po.volume"), - labelStyle: languageModel.isEng ? labelStyle : labelStyleMM, - icon: Icon( - FontAwesomeIcons.sortNumericUpAlt, - color: primaryColor, - ), - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - ), - validator: (value) { - if (value.isEmpty) { - return AppTranslations.of(context).text("po.form.volume"); - } - return null; - }, - ), - ); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - title: LocalText( - context, - "po", - color: Colors.white, - fontSize: 20, - ), - actions: [ - // IconButton( - // icon: Icon(Icons.delete), - // onPressed: () { - // _delete(); - // }, - // ), - IconButton( - icon: Icon(Icons.save), - onPressed: () { - if (!_formKey.currentState.validate()) return; - _save(); - }, - ) - ], - ), - body: Form( - key: _formKey, - child: Column( - children: [ - Expanded( - child: ListView( - shrinkWrap: true, - padding: EdgeInsets.only(left: 24.0, right: 24.0), - children: [ - volumeBox, - showProducts(context, productModel) - ], - ), - ), - ], - ), - )), - ); - } - - _save() { - setState(() { - _isLoading = true; - }); - try { - this.poLine.productID = currentProductID; - var product = - Provider.of(context).getProduct(currentProductID); - this.poLine.productName = product.name; - this.poLine.price = product.price; - this.poLine.qty = int.parse(_qty.text); - this.poLine.amount = this.poLine.price * this.poLine.qty; - Navigator.pop(context, this.poLine); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - setState(() { - _isLoading = false; - }); - } - } - - _delete() { - setState(() { - _isLoading = true; - }); - try { - this.poLine.action = "delete"; - Navigator.pop(context, this.poLine); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - setState(() { - _isLoading = false; - }); - } - } -} diff --git a/lib/pages/po/po_submission_form.dart b/lib/pages/po/po_submission_form.dart deleted file mode 100644 index daa47d2..0000000 --- a/lib/pages/po/po_submission_form.dart +++ /dev/null @@ -1,601 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/language_model.dart'; -import 'package:fcs/model/log_model.dart'; -import 'package:fcs/model/main_model.dart'; -import 'package:fcs/model/po_model.dart'; -import 'package:fcs/model/product_model.dart'; -import 'package:fcs/pages/po/po_item.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/attach.dart'; -import 'package:fcs/vo/po.dart'; -import 'package:fcs/widget/img_file.dart'; -import 'package:fcs/widget/label_widgets.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:fcs/widget/multi_img_controller.dart'; -import 'package:fcs/widget/multi_img_file.dart'; -import 'package:fcs/widget/my_data_table.dart'; -import 'package:fcs/widget/number_cell.dart'; -import 'package:fcs/widget/progress.dart'; - -import '../../util.dart'; -import '../document_log_page.dart'; -import '../../fcs/common/pages/util.dart'; -import 'po_files.dart'; - -class POSubmissionForm extends StatefulWidget { - final POSubmission poSubmission; - - POSubmissionForm({this.poSubmission}); - - @override - _POSubmissionFormState createState() => _POSubmissionFormState(); -} - -class _POSubmissionFormState extends State { - final numberFormatter = new NumberFormat("#,###"); - var dateFormatter = new DateFormat('dd MMM yyyy - hh:mm a'); - MultiImgController multiImgController = MultiImgController(); - - TextEditingController _numberController = new TextEditingController(); - TextEditingController _storage = new TextEditingController(); - TextEditingController _comment = new TextEditingController(); - TextEditingController _name = new TextEditingController(); - TextEditingController _bizName = new TextEditingController(); - - List poLines = new List(); - bool _isLoading = false; - bool _isNew = true; - int _amount = 0; - String _date = "", _status = ""; - POSubmission poSubmission = POSubmission(); - AttachFile attachFile; - POFiles files = POFiles(); - - @override - void initState() { - super.initState(); - if (widget.poSubmission != null) { - _isNew = false; - poSubmission = widget.poSubmission; - - _date = dateFormatter.format(poSubmission.poDate); - _numberController.text = poSubmission.poNumber.toString(); - _comment.text = poSubmission.comment; - _name.text = poSubmission.userName; - _bizName.text = poSubmission.bizName; - poLines = poSubmission.poLines; - _status = poSubmission.status; - _storage.text = poSubmission.storageCharge.toString(); - multiImgController.setImageUrls = poSubmission.poReceiptUrls; - - Provider.of(context, listen: false) - .loadPOLines(poSubmission.id) - .then((poLines) { - setState(() { - this.poSubmission.poLines = poLines; - _amount = poSubmission.getAmount; - }); - }); - } else { - _amount = 0; - _date = dateFormatter.format(DateTime.now()); - var productModel = Provider.of(context, listen: false); - productModel.products.forEach((p) { - var _poLine = POLine( - productID: p.id, - productName: p.name, - price: p.price, - balanceQty: 0, - qty: 0, - amount: 0); - poSubmission.poLines.add(_poLine); - }); - } - } - - @override - Widget build(BuildContext context) { - MainModel mainModel = Provider.of(context); - bool isBuyer = mainModel.user.isBuyer(); - var logModel = Provider.of(context); - - final dateBox = Container( - padding: EdgeInsets.only(top: 15, left: 20, bottom: 5), - child: Row( - children: [ - LocalText(context, "po.date"), - Container( - padding: EdgeInsets.only(left: 10), - child: Text(_date, style: textStyle), - ), - ], - ), - ); - - final numberBox = Container( - padding: EdgeInsets.only(top: 5, left: 20, bottom: 5), - child: Row( - children: [ - LocalText(context, "po.number"), - Container( - padding: EdgeInsets.only(left: 10), - child: Text( - _numberController.text, - style: textStyle, - ), - ) - ], - ), - ); - - final userNameBox = Container( - padding: EdgeInsets.only(top: 5, left: 20, bottom: 5), - child: Row( - children: [ - LocalText(context, "po.name"), - Container( - padding: EdgeInsets.only(left: 20), - child: Text( - _name.text, - style: textStyle, - ), - ) - ], - ), - ); - final bizNameBox = Container( - padding: EdgeInsets.only(top: 5, left: 20, bottom: 5), - child: Row( - children: [ - LocalText(context, "po.biz"), - Container( - padding: EdgeInsets.only(left: 20), - child: Text( - _bizName.text, - style: textStyle, - ), - ) - ], - ), - ); - - final statusBox = Container( - padding: EdgeInsets.only(top: 5, left: 20), - child: Row( - children: [ - LocalText(context, "po.status"), - Container( - padding: EdgeInsets.only(left: 10), - child: Text( - _status, - style: textStyle, - ), - ) - ], - ), - ); - final commentBox = Container( - padding: EdgeInsets.only(top: 5, left: 20), - child: Row( - children: [ - LocalText(context, "po.comment"), - Container( - padding: EdgeInsets.only(left: 10), - child: Text( - _comment.text, - style: textStyle, - ), - ) - ], - ), - ); - - final amountBox = Container( - padding: EdgeInsets.only(top: 5, left: 10), - child: labeledText(context, formatNumber(_amount), "po.amount", - number: true)); - - final storageBox = Container( - padding: EdgeInsets.only(top: 5, left: 20), - child: Row( - children: [ - LocalText(context, "po.storage_charge"), - Container( - padding: EdgeInsets.only(left: 10), - child: Text( - _storage.text, - style: textStyle, - ), - ) - ], - ), - ); - final poPaymentBox = Container( - padding: EdgeInsets.only(left: 20), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - LocalText(context, "po.po_payment_receipt"), - MultiImageFile( - enabled: isBuyer - ? _isNew || this.poSubmission.isPending() ? true : false - : false, - controller: multiImgController, - title: "Receipt File", - ) - ])); - - final storagePaymentBox = Container( - padding: EdgeInsets.only(left: 20), - child: Row(children: [ - LocalText(context, "po.storage_receipt"), - ImageFile( - enabled: isBuyer - ? _isNew || this.poSubmission.isPending() ? true : false - : false, - initialImgUrl: this.poSubmission.storageReceiptUrl, - title: "Receipt File", - onFile: (file) { - this.files.setStorageChargeFile = file; - }), - ])); - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - title: Text(AppTranslations.of(context).text("po"), - style: Provider.of(context).isEng - ? TextStyle(fontSize: 18) - : TextStyle(fontSize: 18, fontFamily: 'MyanmarUnicode')), - actions: [ - _isNew || !mainModel.showHistoryBtn() - ? Container() - : IconButton( - icon: Icon(Icons.history), - onPressed: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => - DocumentLogPage(docID: poSubmission.id)), - ); - }, - ), - isBuyer && (_isNew || poSubmission.isPending()) - ? IconButton( - icon: Icon(Icons.send), - onPressed: () { - showConfirmDialog(context, "po.confirm", () { - _submit(); - }); - }, - ) - : Container(), - isBuyer - ? Container() - : PopupMenuButton( - onSelected: _select, - itemBuilder: (context) => [ - PopupMenuItem( - enabled: poSubmission.isPending(), - value: 1, - child: Text("Approve PO"), - ), - PopupMenuItem( - enabled: poSubmission.isPending(), - value: 2, - child: Text("Reject PO"), - ), - PopupMenuItem( - enabled: mainModel.user.isOwner() && - poSubmission.isApproved(), - value: 3, - child: Text("Cancel PO"), - ), - ], - ), - ], - ), - // floatingActionButton: isBuyer && (_isNew || poSubmission.isPending()) - // ? FloatingActionButton( - // backgroundColor: primaryColor, - // child: Icon(Icons.add), - // onPressed: () async { - // final POLine poLine = await Navigator.push( - // context, - // MaterialPageRoute(builder: (context) => POItem()), - // ); - // _save(poLine); - // }, - // ) - // : null, - body: Container( - child: ListView( - children: [ - dateBox, - Divider(), - _isNew ? Container() : numberBox, - _isNew ? Container() : Divider(), - _isNew ? Container() : userNameBox, - _isNew ? Container() : Divider(), - _isNew ? Container() : bizNameBox, - _isNew ? Container() : Divider(), - _isNew ? Container() : statusBox, - _isNew || - widget.poSubmission.comment == null || - widget.poSubmission.comment == '' - ? Container() - : Divider(), - _isNew || - widget.poSubmission.comment == null || - widget.poSubmission.comment == '' - ? Container() - : commentBox, - _isNew ? Container() : Divider(), - amountBox, - Divider(), - poPaymentBox, - Divider(), - _isNew || !poSubmission.hasStorageCharge() - ? Container() - : storageBox, - _isNew || !poSubmission.hasStorageCharge() - ? Container() - : Divider(), - _isNew || !poSubmission.hasStorageCharge() - ? Container() - : storagePaymentBox, - _isNew || !poSubmission.hasStorageCharge() - ? Container() - : Divider(), - Container( - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: MyDataTable( - headingRowHeight: 40, - columnSpacing: 7, - columns: _isNew - ? [ - MyDataColumn( - label: LocalText(context, "po.product")), - MyDataColumn( - label: LocalText(context, "po.price"), - numeric: true), - MyDataColumn( - label: LocalText(context, "po.volume"), - numeric: true), - MyDataColumn( - label: LocalText(context, "po.amount"), - numeric: true), - ] - : [ - MyDataColumn( - label: LocalText(context, "po.product")), - MyDataColumn( - label: LocalText(context, "po.price"), - numeric: true), - MyDataColumn( - label: LocalText(context, "po.balance.volume"), - numeric: true), - MyDataColumn( - label: LocalText(context, "po.volume"), - numeric: true), - MyDataColumn( - label: LocalText(context, "po.amount"), - numeric: true), - ], - rows: getProductRow(poSubmission.poLines), - ), - ), - ), - ], - ), - ), - ), - ); - } - - _select(s) { - if (s == 1) { - showConfirmDialog(context, "po.approve.confirm", () { - _approve(); - }); - } else if (s == 2) { - showCommentDialog(context, (comment) { - this.poSubmission.comment = comment; - _reject(); - }); - } else if (s == 3) { - showConfirmDialog(context, "po.cancel.confirm", () { - _cancel(); - }); - } - } - - List getProductRow(List poLines) { - MainModel mainModel = Provider.of(context); - bool isBuyer = mainModel.user.isBuyer(); - - ProductModel productModel = Provider.of(context); - if (poLines.isNotEmpty) { - poLines.forEach((d) { - productModel.products.forEach((p) { - if (p.id == d.productID) { - d.displayOrder = p.displayOrder; - } else { - return; - } - }); - }); - - poLines.sort((p1, p2) => p1.displayOrder.compareTo(p2.displayOrder)); - } - - return poLines.map((p) { - return MyDataRow( - onSelectChanged: (bool selected) async { - if (!isBuyer) return; - - if (_isNew || this.poSubmission.isPending()) { - var poLine = await Navigator.push( - context, - MaterialPageRoute( - builder: (context) => POItem( - poLine: p, - )), - ); - _save(poLine); - } - }, - cells: _isNew - ? [ - MyDataCell( - new Text( - p.productName, - style: textStyle, - ), - ), - MyDataCell(NumberCell(p.price)), - MyDataCell( - Container( - alignment: Alignment.centerRight, - width: 100, - child: NumberCell( - p.qty, - textStyle: textStyleOdd, - ), - ), - ), - MyDataCell(NumberCell(p.amount)), - ] - : [ - MyDataCell( - new Text( - p.productName, - style: textStyle, - ), - ), - MyDataCell(NumberCell(p.price)), - MyDataCell(NumberCell(p.balanceQty)), - MyDataCell(NumberCell(p.qty)), - MyDataCell(NumberCell(p.amount)), - ], - ); - }).toList(); - } - - _save(POLine poLine) { - if (poLine == null) return; - if (poLine.action == "create") { - if (poSubmission.poLines.contains(poLine)) { - showMsgDialog(context, "Error", "Duplicate line"); - return; - } - poSubmission.poLines.add(poLine); - } else if (poLine.action == "delete") { - poSubmission.poLines.remove(poLine); - } - setState(() { - _amount = poSubmission.getAmount; - }); - } - - _submit() async { - if (poSubmission.poLines.length == 0) { - showMsgDialog(context, "Error", "No product line"); - return; - } - List _poLines = []; - poSubmission.poLines.forEach((p) => p.qty <= 0 ? _poLines.add(p) : p); - poSubmission.poLines.removeWhere((p) => p.qty <= 0); - - setState(() { - _isLoading = true; - }); - try { - POSubmissionModel poModel = Provider.of(context); - if (_isNew) { - await poModel.createPO(poSubmission, multiImgController.getAddedFile); - } else { - if (poSubmission.hasStorageCharge()) { - if (files.storageChargeFile == null) { - showMsgDialog( - context, "Error", "Please insert storage charge file"); - return; - } - } - await poModel.updatePO(poSubmission, multiImgController.getAddedFile, - multiImgController.getDeletedUrl); - } - Navigator.pop(context); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - setState(() { - _isLoading = false; - _poLines.forEach((e) { - if (!poSubmission.poLines.contains(e)) poSubmission.poLines.add(e); - }); - }); - } - } - - _approve() async { - setState(() { - _isLoading = true; - }); - var oldStatus = poSubmission.status; - try { - POSubmissionModel poModel = Provider.of(context); - - poSubmission.status = "approved"; - await poModel.approvePO(poSubmission); - Navigator.pop(context); - } catch (e) { - poSubmission.status = oldStatus; - showMsgDialog(context, "Error", e.toString()); - } finally { - setState(() { - _isLoading = false; - }); - } - } - - _reject() async { - setState(() { - _isLoading = true; - }); - try { - POSubmissionModel poModel = Provider.of(context); - await poModel.rejectPO(poSubmission); - Navigator.pop(context); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - setState(() { - _isLoading = false; - }); - } - } - - _cancel() async { - setState(() { - _isLoading = true; - }); - try { - POSubmissionModel poModel = Provider.of(context); - await poModel.cancelPO(poSubmission); - Navigator.pop(context); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - setState(() { - _isLoading = false; - }); - } - } -} diff --git a/lib/pages/processing/processing_editor.dart b/lib/pages/processing/processing_editor.dart new file mode 100644 index 0000000..e521dc3 --- /dev/null +++ b/lib/pages/processing/processing_editor.dart @@ -0,0 +1,261 @@ +import 'package:fcs/domain/entities/market.dart'; +import 'package:fcs/domain/entities/package.dart'; +import 'package:fcs/domain/entities/user.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/market/market_editor.dart'; +import 'package:fcs/pages/market/model/market_model.dart'; +import 'package:fcs/pages/package/model/package_model.dart'; +import 'package:fcs/pages/package/tracking_id_page.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/user_search/user_serach.dart'; +import 'package:fcs/pages/widgets/bottom_up_page_route.dart'; +import 'package:fcs/pages/widgets/display_text.dart'; +import 'package:fcs/pages/widgets/fcs_id_icon.dart'; +import 'package:fcs/pages/widgets/input_text.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/multi_img_controller.dart'; +import 'package:fcs/pages/widgets/multi_img_file.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_icons/flutter_icons.dart'; +import 'package:intl/intl.dart'; +import 'package:provider/provider.dart'; + +class ProcessingEditor extends StatefulWidget { + final Package package; + ProcessingEditor({this.package}); + + @override + _ProcessingEditorState createState() => _ProcessingEditorState(); +} + +class _ProcessingEditorState extends State { + TextEditingController _remarkCtl = new TextEditingController(); + TextEditingController _descCtl = new TextEditingController(); + + Package _package; + User _user; + bool _isLoading = false; + + @override + void initState() { + super.initState(); + _package = widget.package; + selectedMarket = _package.market ?? ""; + _descCtl.text = _package.desc; + _remarkCtl.text = _package.remark; + multiImgController.setImageUrls = _package.photoUrls; + _user = User( + fcsID: _package.fcsID ?? "", + name: _package.userName ?? "", + phoneNumber: _package.phoneNumber ?? ""); + } + + final DateFormat dateFormat = DateFormat("d MMM yyyy"); + + bool isNew = false; + MultiImgController multiImgController = MultiImgController(); + + @override + Widget build(BuildContext context) { + var fcsIDBox = Row( + children: [ + Expanded( + child: DisplayText( + text: _user.fcsID, + labelTextKey: "processing.fcs.id", + icon: FcsIDIcon(), + )), + IconButton( + icon: Icon(Icons.search, color: primaryColor), + onPressed: () => searchUser(context, callbackUserSelect: (u) { + setState(() { + this._user = u; + }); + })), + ], + ); + final namebox = DisplayText( + text: _user.name, + labelTextKey: "processing.name", + iconData: Icons.person, + ); + final phoneNumberBox = DisplayText( + text: _user.phoneNumber, + labelTextKey: "processing.phone", + iconData: Icons.phone, + ); + + final trackingIdBox = DisplayText( + text: _package.trackingID, + labelTextKey: "processing.tracking.id", + iconData: MaterialCommunityIcons.barcode_scan, + ); + final completeProcessingBtn = fcsButton( + context, + getLocalString(context, 'processing.edit.complete.btn'), + callack: _completeProcessing, + ); + final descBox = InputText( + labelTextKey: 'processing.desc', + iconData: MaterialCommunityIcons.message_text_outline, + controller: _descCtl); + final remarkBox = InputText( + labelTextKey: 'processing.remark', + iconData: Entypo.new_message, + controller: _remarkCtl); + + final img = MultiImageFile( + enabled: true, + controller: multiImgController, + title: "Receipt File", + ); + return LocalProgress( + inAsyncCall: _isLoading, + child: Scaffold( + appBar: AppBar( + centerTitle: true, + leading: new IconButton( + icon: new Icon(CupertinoIcons.back, color: primaryColor, size: 30), + onPressed: () => Navigator.of(context).pop(), + ), + shadowColor: Colors.transparent, + backgroundColor: Colors.white, + title: LocalText( + context, + "processing.edit.title", + fontSize: 20, + color: primaryColor, + ), + ), + body: Padding( + padding: const EdgeInsets.all(8.0), + child: ListView( + children: [ + trackingIdBox, + fcsIDBox, + namebox, + phoneNumberBox, + marketDropdown(), + descBox, + remarkBox, + img, + completeProcessingBtn, + SizedBox( + height: 20, + ) + ], + ), + ), + ), + ); + } + + String selectedMarket; + Widget marketDropdown() { + List _markets = Provider.of(context).markets; + List markets = _markets.map((e) => e.name).toList(); + markets.insert(0, MANAGE_MARKET); + if (!markets.contains(selectedMarket)) { + markets.insert(0, selectedMarket); + } + + return Padding( + padding: const EdgeInsets.only(left: 5.0, right: 0), + child: Row( + children: [ + Padding( + padding: const EdgeInsets.only(left: 0, right: 10), + child: Icon(Icons.store, color: primaryColor), + ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(right: 18.0), + child: LocalText( + context, + "processing.market", + color: Colors.black54, + fontSize: 16, + ), + ), + DropdownButton( + isDense: true, + value: selectedMarket, + style: TextStyle(color: Colors.black, fontSize: 14), + underline: Container( + height: 1, + color: Colors.grey, + ), + onChanged: (String newValue) { + setState(() { + if (newValue == MANAGE_MARKET) { + selectedMarket = null; + _manageMarket(); + return; + } + selectedMarket = newValue; + }); + }, + isExpanded: true, + items: markets.map>((String value) { + return DropdownMenuItem( + value: value, + child: Text(value ?? "", + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: value == MANAGE_MARKET + ? secondaryColor + : primaryColor)), + ); + }).toList(), + ), + ], + ), + ), + ], + ), + ); + } + + _manageMarket() { + Navigator.push( + context, + CupertinoPageRoute(builder: (context) => MarketEditor()), + ); + } + + _completeProcessing() async { + if (_descCtl.text == "") { + showMsgDialog(context, "Error", "Expected some description"); + return; + } + if (_user.fcsID == null || _user.fcsID == "") { + showMsgDialog(context, "Error", "Expected FCS-ID"); + return; + } + setState(() { + _isLoading = true; + }); + PackageModel packageModel = + Provider.of(context, listen: false); + try { + _package.fcsID = _user.fcsID; + _package.desc = _descCtl.text; + _package.remark = _remarkCtl.text; + _package.market = selectedMarket; + await packageModel.updateProcessing(_package, + multiImgController.getAddedFile, multiImgController.getDeletedUrl); + Navigator.pop(context); + } catch (e) { + showMsgDialog(context, "Error", e.toString()); + } finally { + setState(() { + _isLoading = false; + }); + } + } +} diff --git a/lib/pages/processing/processing_info.dart b/lib/pages/processing/processing_info.dart new file mode 100644 index 0000000..0b6fe43 --- /dev/null +++ b/lib/pages/processing/processing_info.dart @@ -0,0 +1,194 @@ +import 'package:fcs/domain/entities/package.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/package/model/package_model.dart'; +import 'package:fcs/pages/widgets/bottom_up_page_route.dart'; +import 'package:fcs/pages/widgets/display_text.dart'; +import 'package:fcs/pages/widgets/fcs_id_icon.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/multi_img_controller.dart'; +import 'package:fcs/pages/widgets/multi_img_file.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:fcs/pages/widgets/status_tree.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_icons/flutter_icons.dart'; +import 'package:intl/intl.dart'; +import 'package:provider/provider.dart'; + +import 'processing_editor.dart'; + +final DateFormat dateFormat = DateFormat("d MMM yyyy"); + +class ProcessingInfo extends StatefulWidget { + final Package package; + ProcessingInfo({this.package}); + + @override + _ProcessingInfoState createState() => _ProcessingInfoState(); +} + +class _ProcessingInfoState extends State { + var dateFormatter = new DateFormat('dd MMM yyyy'); + Package _package; + bool _isLoading = false; + MultiImgController multiImgController = MultiImgController(); + + @override + void initState() { + super.initState(); + initPackage(widget.package); + } + + initPackage(Package package) { + setState(() { + _package = package; + multiImgController.setImageUrls = package.photoUrls; + }); + } + + @override + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final trackingIdBox = DisplayText( + text: _package.trackingID, + labelTextKey: "processing.tracking.id", + iconData: MaterialCommunityIcons.barcode_scan, + ); + var fcsIDBox = DisplayText( + text: _package.fcsID, + labelTextKey: "processing.fcs.id", + icon: FcsIDIcon(), + ); + final phoneNumberBox = DisplayText( + text: _package.phoneNumber, + labelTextKey: "processing.phone", + iconData: Icons.phone, + ); + final customerNameBox = DisplayText( + text: _package.userName, + labelTextKey: "processing.name", + iconData: Icons.perm_identity, + ); + final marketBox = DisplayText( + text: _package.market ?? "-", + labelTextKey: "processing.market", + iconData: Icons.store, + ); + final descBox = DisplayText( + text: _package.desc ?? "-", + labelTextKey: "processing.desc", + iconData: MaterialCommunityIcons.message_text_outline, + ); + final remarkBox = DisplayText( + text: _package.remark ?? "-", + labelTextKey: "processing.remark", + iconData: Entypo.new_message, + ); + final img = MultiImageFile( + enabled: false, + controller: multiImgController, + title: "Receipt File", + ); + + return LocalProgress( + inAsyncCall: _isLoading, + child: Scaffold( + appBar: AppBar( + centerTitle: true, + leading: new IconButton( + icon: new Icon(CupertinoIcons.back, color: primaryColor, size: 30), + onPressed: () => Navigator.of(context).pop(), + ), + shadowColor: Colors.transparent, + backgroundColor: Colors.white, + title: LocalText( + context, + "processing.info.title", + fontSize: 20, + color: primaryColor, + ), + actions: [ + IconButton( + icon: Icon(Icons.delete, color: primaryColor), + onPressed: _delete, + ), + IconButton( + icon: Icon(Icons.edit, color: primaryColor), + onPressed: _gotoEditor, + ), + ], + ), + body: Card( + child: Column( + children: [ + Expanded( + child: Padding( + padding: const EdgeInsets.all(10.0), + child: ListView(children: [ + trackingIdBox, + fcsIDBox, + customerNameBox, + phoneNumberBox, + marketBox, + descBox, + remarkBox, + _package.photoUrls.length == 0 ? Container() : img, + StatusTree( + shipmentHistory: _package.shipmentHistory, + currentStatus: _package.status), + SizedBox( + height: 20, + ) + ]), + )), + ], + ), + ), + ), + ); + } + + _delete() { + showConfirmDialog(context, "processing.delete.confirm", _deletePackage); + } + + _deletePackage() async { + setState(() { + _isLoading = true; + }); + PackageModel packageModel = + Provider.of(context, listen: false); + try { + await packageModel.deleteProcessing(_package); + Navigator.pop(context, true); + } catch (e) { + showMsgDialog(context, "Error", e.toString()); + } finally { + setState(() { + _isLoading = false; + }); + } + } + + _gotoEditor() async { + bool deleted = await Navigator.push( + context, + CupertinoPageRoute( + builder: (context) => ProcessingEditor( + package: widget.package, + ))); + if (deleted ?? false) { + Navigator.pop(context); + } else { + PackageModel packageModel = + Provider.of(context, listen: false); + Package p = await packageModel.getPackage(_package.id); + initPackage(p); + } + } +} diff --git a/lib/pages/processing/processing_list.dart b/lib/pages/processing/processing_list.dart new file mode 100644 index 0000000..9a1d5f0 --- /dev/null +++ b/lib/pages/processing/processing_list.dart @@ -0,0 +1,95 @@ +import 'package:fcs/domain/entities/package.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/main/model/main_model.dart'; +import 'package:fcs/pages/package/model/package_model.dart'; +import 'package:fcs/pages/package_search/package_serach.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import 'processing_info.dart'; +import 'processing_list_row.dart'; + +class ProcessingList extends StatefulWidget { + @override + _ProcessingListState createState() => _ProcessingListState(); +} + +class _ProcessingListState extends State { + bool _isLoading = false; + + @override + void initState() { + super.initState(); + } + + @override + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + var packageModel = Provider.of(context); + bool isCustomer = context.select((MainModel m) => m.isCustomer()); + + return LocalProgress( + inAsyncCall: _isLoading, + child: Scaffold( + appBar: AppBar( + centerTitle: true, + leading: new IconButton( + icon: new Icon(CupertinoIcons.back), + onPressed: () => Navigator.of(context).pop(), + ), + backgroundColor: primaryColor, + title: LocalText( + context, + "processing.title", + fontSize: 20, + color: Colors.white, + ), + actions: [ + isCustomer + ? Container() + : IconButton( + icon: Icon( + Icons.search, + color: Colors.white, + ), + iconSize: 30, + onPressed: () => searchPackage(context, + callbackPackageSelect: _searchCallback), + ), + ], + ), + body: new ListView.separated( + separatorBuilder: (context, index) => Divider( + color: Colors.black, + height: 1, + ), + scrollDirection: Axis.vertical, + shrinkWrap: true, + itemCount: packageModel.packages.length, + itemBuilder: (BuildContext context, int index) { + return ProcessingListRow( + key: ValueKey(packageModel.packages[index].id), + package: packageModel.packages[index], + ); + })), + ); + } + + _searchCallback(Package package) async { + var packageModel = Provider.of(context, listen: false); + Package _package = await packageModel.getPackage(package.id); + if (_package == null) return; + Navigator.push( + context, + CupertinoPageRoute( + builder: (context) => ProcessingInfo(package: _package)), + ); + } +} diff --git a/lib/pages/processing/processing_list_row.dart b/lib/pages/processing/processing_list_row.dart new file mode 100644 index 0000000..cc06c16 --- /dev/null +++ b/lib/pages/processing/processing_list_row.dart @@ -0,0 +1,100 @@ +import 'package:fcs/domain/entities/package.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_icons/flutter_icons.dart'; +import 'package:intl/intl.dart'; + +import 'processing_info.dart'; + +typedef CallbackPackageSelect(Package package); + +class ProcessingListRow extends StatelessWidget { + final Package package; + final CallbackPackageSelect callbackPackageSelect; + final double dotSize = 15.0; + final DateFormat dateFormat = new DateFormat("dd MMM yyyy"); + + ProcessingListRow({Key key, this.package, this.callbackPackageSelect}) + : super(key: key); + + @override + Widget build(BuildContext context) { + return InkWell( + onTap: () { + if (callbackPackageSelect != null) { + callbackPackageSelect(package); + return; + } + Navigator.push( + context, + CupertinoPageRoute( + builder: (context) => ProcessingInfo(package: package)), + ); + }, + child: Container( + padding: EdgeInsets.only(left: 15, right: 15), + child: Row( + children: [ + Expanded( + child: new Padding( + padding: const EdgeInsets.symmetric(vertical: 16.0), + child: new Row( + children: [ + Container( + padding: EdgeInsets.only(left: 5, right: 10), + child: Icon( + FontAwesome.dropbox, + color: primaryColor, + size: 30, + ), + ), + new Expanded( + child: new Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(left: 8.0), + child: new Text( + package.id == null ? '' : package.trackingID, + style: new TextStyle( + fontSize: 15.0, color: Colors.black), + ), + ), + Padding( + padding: const EdgeInsets.only(left: 8.0), + child: new Text( + package.market == null ? '' : package.market, + style: new TextStyle( + fontSize: 15.0, color: Colors.black), + ), + ), + ], + ), + ), + ], + ), + ), + ), + Column( + children: [ + Padding( + padding: const EdgeInsets.all(3.0), + child: getStatus(package.status), + ), + Padding( + padding: const EdgeInsets.all(0), + child: new Text( + dateFormat.format(package.currentStatusDate), + style: new TextStyle(fontSize: 15.0, color: Colors.grey), + ), + ), + ], + ) + ], + ), + ), + ); + } +} diff --git a/lib/pages/product_edit_item.dart b/lib/pages/product_edit_item.dart deleted file mode 100644 index df6596e..0000000 --- a/lib/pages/product_edit_item.dart +++ /dev/null @@ -1,223 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/language_model.dart'; -import 'package:fcs/model/product_model.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/vo/product.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:fcs/widget/progress.dart'; - -import '../fcs/common/helpers/theme.dart'; - -class ProductEditItem extends StatefulWidget { - final Product product; - - const ProductEditItem({Key key, this.product}) : super(key: key); - @override - _ProductEditItemState createState() => _ProductEditItemState(); -} - -class _ProductEditItemState extends State { - TextEditingController nameController = new TextEditingController(); - TextEditingController priceController = new TextEditingController(); - TextEditingController orderController = new TextEditingController(); - int color = primaryColor.value; - bool isDisable = false; - - final _formKey = GlobalKey(); - bool _isLoading = false; - - @override - void initState() { - super.initState(); - - if (widget.product != null) { - this.color = widget.product.color; - nameController.text = widget.product.name; - priceController.text = widget.product.price.toString(); - orderController.text = widget.product.displayOrder.toString(); - if (widget.product.isDisable != null) { - isDisable = widget.product.isDisable; - } else { - isDisable = false; - } - } - } - - @override - Widget build(BuildContext context) { - var maingModel = Provider.of(context); - final nameWidget = Container( - padding: EdgeInsets.only(top: 10), - child: TextFormField( - controller: nameController, - autofocus: true, - cursorColor: primaryColor, - style: textStyle, - decoration: new InputDecoration( - icon: InkWell( - child: Icon( - FontAwesomeIcons.tag, - color: Color(this.color), - size: 25, - ), - onTap: () => showColorPicker(context, Color(this.color), (color) { - setState(() { - this.color = color.value; - }); - }), - ), - labelText: AppTranslations.of(context).text("product.name"), - labelStyle: maingModel.isEng ? labelStyle : labelStyleMM, - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - ), - validator: (value) { - if (value.isEmpty) { - return AppTranslations.of(context).text("product.name_empty"); - } - return null; - }, - ), - ); - - final priceInput = Container( - child: TextFormField( - controller: priceController, - style: TextStyle(fontSize: 16.0, fontStyle: FontStyle.normal), - keyboardType: TextInputType.number, - cursorColor: primaryColor, - decoration: new InputDecoration( - icon: Icon( - FontAwesomeIcons.moneyBill, - color: primaryColor, - size: 25, - ), - border: InputBorder.none, - labelText: AppTranslations.of(context).text("product.new_price"), - labelStyle: maingModel.isEng ? labelStyle : labelStyleMM, - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - ), - validator: (value) { - if (value.isEmpty) { - return AppTranslations.of(context).text("product.price_empty"); - } - return null; - }, - ), - ); - - final orderInput = Container( - child: TextFormField( - controller: orderController, - style: TextStyle(fontSize: 16.0, fontStyle: FontStyle.normal), - keyboardType: TextInputType.number, - cursorColor: primaryColor, - decoration: new InputDecoration( - icon: Icon( - Icons.sort, - color: primaryColor, - size: 25, - ), - border: InputBorder.none, - labelText: AppTranslations.of(context).text("product.order"), - labelStyle: maingModel.isEng ? labelStyle : labelStyleMM, - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - ), - validator: (value) { - if (value.isEmpty) { - return AppTranslations.of(context).text("product.order_empty"); - } - return null; - }, - ), - ); - - final disableBox = Container( - padding: EdgeInsets.only(top: 10), - child: CheckboxListTile( - title: Text("Disable"), - value: isDisable, - activeColor: primaryColor, - onChanged: (value) { - setState(() { - isDisable = value; - }); - }, - controlAffinity: ListTileControlAffinity.leading, - )); - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - title: Text(AppTranslations.of(context).text("product.item"), - style: maingModel.isEng - ? TextStyle(color: Colors.white, fontSize: 20.0) - : TextStyle( - color: Colors.white, - fontSize: 20.0, - fontFamily: 'MyanmarUnicode')), - actions: [ - IconButton( - icon: Icon(Icons.save), - onPressed: () { - if (!_formKey.currentState.validate()) return; - Provider.of(context, listen: false).saveProduct( - widget.product, - nameController.text, - priceController.text, - orderController.text, - color, - isDisable); - Product _product = new Product(); - if (widget.product != null) { - _product = widget.product; - _product.name = nameController.text; - _product.price = int.parse(priceController.text); - _product.color = color; - _product.displayOrder = int.parse(orderController.text); - _product.isDisable = isDisable; - if (_product.id == null) { - _product.action = "create"; - } else { - _product.action = "update"; - } - } - Navigator.pop(context, _product); - }, - ) - ], - backgroundColor: primaryColor, - ), - body: Form( - key: _formKey, - child: SingleChildScrollView( - padding: EdgeInsets.only( - left: 25.0, - right: 25.0, - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - nameWidget, - priceInput, - orderInput, - this.widget.product != null ? disableBox : Container(), - ], - ), - ), - ), - ), - ); - } -} diff --git a/lib/pages/products_list.dart b/lib/pages/products_list.dart deleted file mode 100644 index a11d783..0000000 --- a/lib/pages/products_list.dart +++ /dev/null @@ -1,68 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/language_model.dart'; -import 'package:fcs/model/main_model.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:fcs/widget/products.dart'; -import 'package:fcs/widget/progress.dart'; - -import '../model/product_model.dart'; -import 'products_list_edit.dart'; - -class ProductsList extends StatefulWidget { - @override - _ProductsListState createState() => _ProductsListState(); -} - -class _ProductsListState extends State { - @override - void initState() { - super.initState(); - } - - @override - Widget build(BuildContext context) { - var productModel = Provider.of(context); - var mainModel = Provider.of(context); - bool _isLoading = false; - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - title: Text(AppTranslations.of(context).text("products.title"), - style: Provider.of(context).isEng - ? TextStyle() - : TextStyle(fontFamily: 'MyanmarUnicode')), - actions: [ - mainModel.user != null && mainModel.user.isOwner() || - mainModel.user.hasAdmin() - ? IconButton( - icon: Icon(Icons.edit), - onPressed: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => ProductsListEdit( - products: productModel.productsToEdit, - )), - ); - }, - ) - : Container() - ], - ), - backgroundColor: Colors.white, - body: ListView( - children: [ - Padding( - padding: const EdgeInsets.only(top: 5), - child: ProductsWidget(isWelcomePage: false), - ), - ], - )), - ); - } -} diff --git a/lib/pages/products_list_edit.dart b/lib/pages/products_list_edit.dart deleted file mode 100644 index ef45f73..0000000 --- a/lib/pages/products_list_edit.dart +++ /dev/null @@ -1,175 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/language_model.dart'; -import 'package:fcs/model/product_model.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/vo/product.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:fcs/widget/progress.dart'; - -import '../fcs/common/helpers/theme.dart'; -import 'product_edit_item.dart'; - -class ProductsListEdit extends StatefulWidget { - final List products; - - const ProductsListEdit({Key key, this.products}) : super(key: key); - - @override - _ProductsListEditState createState() => _ProductsListEditState(); -} - -class _ProductsListEditState extends State { - List products; - bool _isLoading = false; - - @override - void initState() { - super.initState(); - products = widget.products; - } - - @override - Widget build(BuildContext context) { - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - title: Text(AppTranslations.of(context).text("products.title"), - style: Provider.of(context).isEng - ? TextStyle(color: Colors.white, fontSize: 20.0) - : TextStyle( - color: Colors.white, - fontSize: 20.0, - fontFamily: 'MyanmarUnicode')), - actions: [ - IconButton( - icon: Icon(Icons.send), - onPressed: () { - _update(context); - }, - ) - ], - ), - floatingActionButton: FloatingActionButton( - backgroundColor: primaryColor, - child: Icon(Icons.add), - onPressed: _add, - ), - body: ListView( - shrinkWrap: true, - padding: EdgeInsets.all(5.0), - children: [ - new ListView.builder( - padding: EdgeInsets.only(left: 15, right: 15, top: 15), - shrinkWrap: true, - itemCount: products.length, - itemBuilder: (BuildContext context, int index) { - return _row(products[index]); - }), - ], - ), - ), - ); - } - - _add() { - Navigator.push( - context, - MaterialPageRoute(builder: (context) => ProductEditItem()), - ); - } - - void _update(BuildContext context) async { - await showConfirmDialog(context, "product.confirm", () async { - setState(() { - _isLoading = true; - }); - try { - var productModel = Provider.of(context); - await productModel.updateProducts(this.products); - Navigator.pop(context); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - setState(() { - _isLoading = false; - }); - } - }); - } - - Widget _row(Product product) { - return Container( - child: InkWell( - child: Card( - elevation: 10, - color: Colors.white, - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Row( - children: [ - Expanded( - child: new Padding( - padding: const EdgeInsets.symmetric(vertical: 3.0), - child: new Row( - children: [ - InkWell( - child: new Padding( - padding: new EdgeInsets.symmetric( - horizontal: 20.0 - 10 / 2), - child: Icon( - FontAwesomeIcons.tag, - color: Color(product.color), - size: 30, - ), - ), - ), - new Expanded( - child: new Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - product.name, - style: product.isDisable == true - ? TextStyle( - decoration: - TextDecoration.lineThrough, - color: Colors.red) - : null, - ) - ], - ), - ), - ], - ), - ), - ), - Column(children: [ - product.id == null - ? Text("New Product") - : Text("Old Price: ${product.oldPirce}"), - Text("New Price: ${product.price}") - ]), - ], - ), - ), - ), - onTap: () async { - Product _p = await Navigator.push( - context, - MaterialPageRoute( - builder: (context) => ProductEditItem( - product: product, - )), - ); - if (_p == null) return; - setState(() { - product = _p; - }); - }), - ); - } -} diff --git a/lib/pages/profile/profile_currency_edit.dart b/lib/pages/profile/profile_currency_edit.dart new file mode 100644 index 0000000..6d91664 --- /dev/null +++ b/lib/pages/profile/profile_currency_edit.dart @@ -0,0 +1,129 @@ +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/localization/app_translations.dart'; +import 'package:fcs/pages/main/model/language_model.dart'; +import 'package:fcs/pages/main/model/main_model.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:fcs/pages/main/util.dart'; + +typedef void ProfileCallback(); + +enum Currency { USD, MMK } + +class ProfileCurrencyEdit extends StatefulWidget { + @override + _ProfileCurrencyEditState createState() => _ProfileCurrencyEditState(); +} + +class _ProfileCurrencyEditState extends State { + final TextEditingController nameController = new TextEditingController(); + bool _loading = false; + + @override + void initState() { + super.initState(); + MainModel mainModel = Provider.of(context, listen: false); + if (mainModel.user.preferCurrency == "MMK") { + _currency = Currency.MMK; + } else { + _currency = Currency.USD; + } + } + + Currency _currency = Currency.USD; + + @override + Widget build(BuildContext context) { + final saveBtn = + fcsButton(context, getLocalString(context, "btn.save"), callack: _save); + + return LocalProgress( + inAsyncCall: _loading, + child: Scaffold( + appBar: AppBar( + centerTitle: true, + title: LocalText( + context, + "profile.edit.currency.title", + fontSize: 20, + color: primaryColor, + ), + backgroundColor: Colors.white, + shadowColor: Colors.transparent, + leading: IconButton( + icon: Icon( + CupertinoIcons.back, + size: 35, + color: primaryColor, + ), + onPressed: () => Navigator.of(context).pop(), + ), + ), + body: Column( + children: [ + InkWell( + onTap: () => setState(() { + _currency = Currency.USD; + }), + child: ListTile( + title: Text('USD'), + leading: Radio( + activeColor: primaryColor, + value: Currency.USD, + groupValue: _currency, + onChanged: (Currency value) { + setState(() { + _currency = value; + }); + }, + ), + ), + ), + InkWell( + onTap: () => setState(() { + _currency = Currency.MMK; + }), + child: ListTile( + title: const Text('MMK'), + leading: Radio( + activeColor: primaryColor, + value: Currency.MMK, + groupValue: _currency, + onChanged: (Currency value) { + setState(() { + _currency = value; + }); + }, + ), + ), + ), + Padding( + padding: const EdgeInsets.all(18.0), + child: saveBtn, + ), + ], + ), + ), + ); + } + + _save() async { + setState(() { + _loading = true; + }); + try { + await Provider.of(context, listen: false) + .updatePreferredCurrency(_currency.toString().split(".").last); + Navigator.pop(context); + } catch (e) { + showMsgDialog(context, "Error", e.toString()); + } finally { + setState(() { + _loading = false; + }); + } + } +} diff --git a/lib/fcs/common/pages/profile/profile_edit.dart b/lib/pages/profile/profile_edit.dart similarity index 85% rename from lib/fcs/common/pages/profile/profile_edit.dart rename to lib/pages/profile/profile_edit.dart index eb9e71b..23f4a37 100644 --- a/lib/fcs/common/pages/profile/profile_edit.dart +++ b/lib/pages/profile/profile_edit.dart @@ -1,13 +1,13 @@ -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/fcs/common/localization/app_translations.dart'; -import 'package:fcs/fcs/common/pages/model/language_model.dart'; -import 'package:fcs/fcs/common/pages/model/main_model.dart'; -import 'package:fcs/fcs/common/pages/widgets/local_text.dart'; -import 'package:fcs/fcs/common/pages/widgets/progress.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/localization/app_translations.dart'; +import 'package:fcs/pages/main/model/language_model.dart'; +import 'package:fcs/pages/main/model/main_model.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/progress.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; +import 'package:fcs/pages/main/util.dart'; typedef void ProfileCallback(); @@ -96,7 +96,7 @@ class _ProfileEditState extends State { }); try { await Provider.of(context, listen: false) - .updateProfile(nameController.text); + .updateProfileName(nameController.text); Navigator.pop(context); } catch (e) { showMsgDialog(context, "Error", e.toString()); diff --git a/lib/pages/profile/profile_page.dart b/lib/pages/profile/profile_page.dart new file mode 100644 index 0000000..67395f9 --- /dev/null +++ b/lib/pages/profile/profile_page.dart @@ -0,0 +1,317 @@ +import 'package:fcs/domain/entities/user.dart'; +import 'package:fcs/domain/vo/delivery_address.dart'; +import 'package:fcs/domain/vo/privilege.dart'; +import 'package:fcs/localization/transalation.dart'; +import 'package:fcs/pages/delivery_address/delivery_address_list.dart'; +import 'package:fcs/pages/delivery_address/delivery_address_row.dart'; +import 'package:fcs/pages/delivery_address/model/delivery_address_model.dart'; +import 'package:fcs/pages/main/model/language_model.dart'; +import 'package:fcs/pages/main/model/main_model.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/profile/profile_currency_edit.dart'; +import 'package:fcs/pages/profile/profile_edit.dart'; +import 'package:fcs/pages/staff/model/staff_model.dart'; +import 'package:fcs/pages/widgets/bottom_up_page_route.dart'; +import 'package:fcs/pages/widgets/defalut_delivery_address.dart'; +import 'package:fcs/pages/widgets/display_text.dart'; +import 'package:fcs/pages/widgets/fcs_id_icon.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_icons/flutter_icons.dart'; +import 'package:provider/provider.dart'; + +import '../../helpers/theme.dart'; + +typedef void ProfileCallback(); + +class Profile extends StatefulWidget { + @override + _ProfileState createState() => _ProfileState(); +} + +class _ProfileState extends State { + GlobalKey key = GlobalKey(); + bool _isLoading = false; + String selectedLanguage; + TextEditingController bizNameController = new TextEditingController(); + + static final List languagesList = Translation().supportedLanguages; + static final List languageCodesList = + Translation().supportedLanguagesCodes; + + final Map languagesMap = { + languagesList[0]: languageCodesList[0], + languagesList[1]: languageCodesList[1], + }; + + buildLanguage(LanguageModel languageModel) async { + var lan = await languageModel.load(); + if (this.selectedLanguage != lan) { + setState(() { + this.selectedLanguage = lan; + }); + } + } + + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + MainModel mainModel = Provider.of(context); + if (mainModel.user == null) { + return Container(); + } + DeliveryAddressModel deliveryAddressModel = + Provider.of(context); + + final namebox = DisplayText( + text: mainModel.user.name + " (${mainModel.user.status})", + labelTextKey: "profile.name", + iconData: Icons.person, + ); + final currencyBox = DisplayText( + text: mainModel.user.preferCurrency, + labelTextKey: "profile.currency", + iconData: FontAwesome5.money_bill_alt, + ); + + final phonenumberbox = DisplayText( + text: mainModel.user.phone, + labelTextKey: "profile.phone", + iconData: Icons.phone, + ); + final fcsIDBox = Row( + children: [ + Expanded( + child: DisplayText( + text: mainModel.user.fcsID, + labelTextKey: "customer.fcs.id", + icon: FcsIDIcon(), + ), + ), + IconButton( + icon: Icon(Icons.content_copy, color: Colors.grey), + onPressed: () => _copy( + getLocalString(context, "customer.fcs.id"), mainModel.user.fcsID), + ) + ], + ); + + final usaShippingAddressBox = Row( + children: [ + Expanded( + child: DisplayText( + text: mainModel.setting.usaAddress, + labelTextKey: "profile.usa.shipping.address", + iconData: Icons.location_on, + ), + ), + IconButton( + icon: Icon(Icons.content_copy, color: Colors.grey), + onPressed: () => _copy( + getLocalString(context, "profile.usa.shipping.address"), + mainModel.setting.usaAddress), + ) + ], + ); + + final logoutbutton = fcsButton( + context, getLocalString(context, "profile.logout"), + callack: _logout, iconData: Icons.exit_to_app); + + return LocalProgress( + inAsyncCall: _isLoading, + child: Scaffold( + key: key, + appBar: AppBar( + centerTitle: true, + leading: IconButton( + icon: Icon( + CupertinoIcons.back, + size: 35, + color: primaryColor, + ), + onPressed: () => Navigator.of(context).pop(), + ), + title: LocalText( + context, + "profile.title", + fontSize: 20, + color: primaryColor, + ), + shadowColor: Colors.transparent, + backgroundColor: Colors.white, + ), + body: Padding( + padding: const EdgeInsets.all(8.0), + child: ListView( + children: [ + Row( + children: [ + Expanded(child: namebox), + Padding( + padding: const EdgeInsets.only(right: 0), + child: IconButton( + icon: Icon(Icons.edit, color: Colors.grey), + onPressed: _editName), + ) + ], + ), + phonenumberbox, + fcsIDBox, + usaShippingAddressBox, + Row( + children: [ + Expanded(child: currencyBox), + Padding( + padding: const EdgeInsets.only(right: 0), + child: IconButton( + icon: Icon(Icons.edit, color: Colors.grey), + onPressed: _editCurrency), + ) + ], + ), + DefaultDeliveryAddress( + labelKey: "profile.default.delivery.address", + deliveryAddress: deliveryAddressModel.defalutAddress, + onTap: () { + Navigator.push( + context, + CupertinoPageRoute( + builder: (context) => DeliveryAddressList())); + }, + ), + getPrivilegeBox(context), + SizedBox(height: 15), + logoutbutton, + SizedBox(height: 25) + ], + ), + ), + ), + ); + } + + Widget getPrivilegeBox(BuildContext context) { + User user = Provider.of(context, listen: false).user; + List _privileges = + Provider.of(context, listen: false).privileges; + + if (user == null || user.isCustomer()) return Container(); + List privileges = []; + user.privileges.forEach((e) { + var p = _privileges.firstWhere((p) => p.id == e, orElse: () => null); + if (p != null) { + privileges.add(p); + } + }); + + return Column( + children: [ + DisplayText( + labelTextKey: "profile.privileges", + iconData: MaterialCommunityIcons.clipboard_check_outline, + ), + Padding( + padding: const EdgeInsets.only(left: 30.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: getRowPrivilegeWidget(privileges)), + ) + ], + ); + } + + List getRowPrivilegeWidget(List privileges) { + return privileges.map((p) { + return Container( + padding: EdgeInsets.all(3.0), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Icon( + p.iconData, + color: Colors.black38, + ), + SizedBox( + width: 10, + ), + Flexible( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("${p.name}", + style: TextStyle( + fontSize: 16.0, + fontStyle: FontStyle.normal, + color: primaryColor, + )), + Text( + "${p.desc}", + style: TextStyle( + fontSize: 14.0, + fontStyle: FontStyle.normal, + color: Colors.black38), + ), + ], + ), + ) + ], + ), + ); + }).toList(); + } + + _copy(String title, String data) { + Clipboard.setData(ClipboardData(text: data)); + _showToast(title); + } + + _showToast(String title) { + final ScaffoldState scaffold = key.currentState; + scaffold.showSnackBar( + SnackBar( + content: Text('copied "$title" data to clipboard'), + backgroundColor: secondaryColor, + duration: Duration(seconds: 1), + ), + ); + } + + _editName() { + Navigator.of(context) + .push(CupertinoPageRoute(builder: (context) => ProfileEdit())); + } + + _editCurrency() { + Navigator.of(context).push( + CupertinoPageRoute(builder: (context) => ProfileCurrencyEdit())); + } + + _logout() { + showConfirmDialog(context, "profile.logout.confirm", () async { + setState(() { + _isLoading = true; + }); + try { + await context.read().signout(); + } catch (e) {} finally { + Future.delayed(Duration(seconds: 1), () { + if (mounted) { + setState(() { + _isLoading = false; + }); + } + }); + Navigator.of(context).pushNamedAndRemoveUntil( + "/welcome", ModalRoute.withName('/welcome')); + } + }); + } +} diff --git a/lib/pages/profile_edit.dart b/lib/pages/profile_edit.dart deleted file mode 100644 index 60bfde1..0000000 --- a/lib/pages/profile_edit.dart +++ /dev/null @@ -1,113 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/language_model.dart'; -import 'package:fcs/model/main_model.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:fcs/widget/progress.dart'; - -import '../fcs/common/helpers/theme.dart'; - -typedef void ProfileCallback(); - -class ProfileEdit extends StatefulWidget { - @override - _ProfileEditState createState() => _ProfileEditState(); -} - -class _ProfileEditState extends State { - final TextEditingController nameController = new TextEditingController(); - bool _loading = false; - - @override - void initState() { - super.initState(); - MainModel mainModel = Provider.of(context, listen: false); - nameController.text = mainModel.user.name; - } - - @override - Widget build(BuildContext context) { - var languageModel = Provider.of(context); - - final name = Container( - padding: EdgeInsets.only(top: 0, left: 20, right: 15, bottom: 30), - child: TextFormField( - controller: nameController, - autofocus: true, - cursorColor: primaryColor, - style: textStyle, - decoration: new InputDecoration( - labelText: AppTranslations.of(context).text("profile.name"), - labelStyle: languageModel.isEng ? labelStyle : labelStyleMM, - icon: Icon( - Icons.account_box, - color: primaryColor, - ), - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - ), - )); - - final saveBtn = Card( - elevation: 23, - child: ButtonTheme( - minWidth: 200.0, - height: 50.0, - child: FlatButton.icon( - onPressed: () => _save(), - label: Text(AppTranslations.of(context).text("btn.save"), - style: languageModel.isEng - ? TextStyle( - fontSize: 18.0, - fontWeight: FontWeight.bold, - fontStyle: FontStyle.normal) - : TextStyle( - fontSize: 18.0, - fontWeight: FontWeight.bold, - fontStyle: FontStyle.normal, - fontFamily: "MyanmarUnicode")), - icon: Icon( - Icons.save, - ), - ), - ), - ); - - return LocalProgress( - inAsyncCall: _loading, - child: Scaffold( - appBar: AppBar( - title: Text( - AppTranslations.of(context).text("profile.edit_title"), - ), - backgroundColor: primaryColor, - ), - body: Column( - children: [ - name, - saveBtn, - ], - ), - ), - ); - } - - _save() async { - setState(() { - _loading = true; - }); - try { - await Provider.of(context, listen: false) - .updateProfile(nameController.text); - Navigator.pop(context); - setState(() { - _loading = false; - }); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } - } -} diff --git a/lib/pages/profile_setting.dart b/lib/pages/profile_setting.dart deleted file mode 100644 index c705422..0000000 --- a/lib/pages/profile_setting.dart +++ /dev/null @@ -1,201 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/main_model.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/progress.dart'; - -import '../fcs/common/helpers/theme.dart'; -import 'add_pin_editor.dart'; -import 'block_list.dart'; -import 'chage_phone_number.dart'; -import 'change_password.dart'; -import 'device_list.dart'; -import 'email_page.dart'; -import 'log_list.dart'; - -class ProfileSetting extends StatefulWidget { - @override - _ProfileSettingtate createState() => _ProfileSettingtate(); -} - -class _ProfileSettingtate extends State { - bool _isLoading = false; - - @override - Widget build(BuildContext context) { - MainModel mainModel = Provider.of(context); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - title: LocalText( - context, - "setting.title", - fontSize: 20, - color: Colors.white, - ), - backgroundColor: primaryColor, - ), - body: SingleChildScrollView( - padding: EdgeInsets.only( - left: 25.0, - right: 25.0, - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - SizedBox( - height: 8, - ), - buildSettingTile( - context: context, - text: 'log.title', - image: "assets/message.png", - width: 25, - height: 25, - tap: () { - Navigator.push(context, - MaterialPageRoute(builder: (context) => LogList())); - }, - ), - buildSettingTile( - context: context, - text: 'profile.devices', - image: "assets/device.png", - width: 29, - height: 29, - tap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => PhoneDeviceList())); - }, - ), - buildSettingTile( - context: context, - text: 'change.password.title', - image: "assets/password.png", - width: 27, - height: 27, - tap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => - ChangePassword(mainModel.user))); - }, - ), - buildSettingTile( - context: context, - text: 'change.phone', - image: "assets/phone.png", - width: 30, - height: 25, - tap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => - ChangePhoneNumber(mainModel.user))); - }, - ), - buildSettingTile( - context: context, - text: 'change.email', - image: "assets/email.png", - width: 25, - height: 25, - tap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => EmailPage( - user: mainModel.user, - ))); - }, - ), - // buildSettingTile( - // context: context, - // text: 'user.block_list', - // image: "assets/block.png", - // width: 27, - // height: 27, - // tap: () { - // Navigator.push(context, - // MaterialPageRoute(builder: (context) => BlockList())); - // }, - // ), - buildSettingTile( - context: context, - text: 'change.pin.title', - image: "assets/pin.png", - width: 30, - height: 30, - tap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => AddPINEditor( - mainModel.user, - ))); - }, - ), - ], - ), - ), - ), - ); - } -} - -Widget buildSettingTile( - {@required String text, - @required BuildContext context, - @required String image, - @required double width, - @required double height, - @required GestureTapCallback tap}) { - return InkWell( - onTap: () { - tap(); - }, - child: Column( - children: [ - Padding( - padding: EdgeInsets.only(top: 8.0, bottom: 5), - child: Row( - children: [ - Expanded( - child: Row( - children: [ - Padding( - padding: EdgeInsets.only(left: 12.0, right: 20.0), - child: Image.asset( - image, - width: width, - height: height, - color: primaryColor, - ), - ), - LocalText( - context, - text, - fontSize: 15.0, - color: Colors.black87, - ) - ], - ), - ), - Icon(Icons.keyboard_arrow_right) - ], - ), - ), - Divider( - color: Colors.grey, - ) - ], - ), - ); -} diff --git a/lib/pages/quota_form.dart b/lib/pages/quota_form.dart deleted file mode 100644 index c5735d4..0000000 --- a/lib/pages/quota_form.dart +++ /dev/null @@ -1,179 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/language_model.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/buyer.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:fcs/widget/progress.dart'; - -class QuotaForm extends StatefulWidget { - final BuyerProduct buyerProduct; - const QuotaForm({Key key, this.buyerProduct}) : super(key: key); - @override - _QuotaFormState createState() => _QuotaFormState(); -} - -class _QuotaFormState extends State { - final _formKey = GlobalKey(); - TextEditingController _product = new TextEditingController(); - TextEditingController _storageQty = new TextEditingController(); - TextEditingController _saleQty = new TextEditingController(); - TextEditingController _dailyQuota = new TextEditingController(); - TextEditingController _maxQuota = new TextEditingController(); - - BuyerProduct buyerProduct; - bool _isLoading = false; - - @override - void initState() { - super.initState(); - if (widget.buyerProduct != null) { - this.buyerProduct = widget.buyerProduct; - _product.text = widget.buyerProduct.productName; - _storageQty.text = widget.buyerProduct.storageCapacityQty == null - ? "" - : widget.buyerProduct.storageCapacityQty.toString(); - _saleQty.text = widget.buyerProduct.dailySaleQty == null - ? "" - : widget.buyerProduct.dailySaleQty.toString(); - _dailyQuota.text = widget.buyerProduct.dailyQuota == null - ? "" - : widget.buyerProduct.dailyQuota.toString(); - _maxQuota.text = widget.buyerProduct.maxQuota == null - ? "" - : widget.buyerProduct.maxQuota.toString(); - } - } - - @override - Widget build(BuildContext context) { - var language = Provider.of(context); - final productbox = Container( - padding: EdgeInsets.only(top: 10), - child: Row( - children: [ - LocalText(context, "reg.table_product"), - SizedBox( - width: 30, - ), - Text(_product.text, style: textStyle) - ], - )); - - final storageQtybox = Container( - padding: EdgeInsets.only(top: 10), - child: Row( - children: [ - LocalText(context, "reg.table_storage_vol"), - SizedBox( - width: 30, - ), - Text(_storageQty.text, style: textStyle) - ], - )); - - final saleQtybox = Container( - padding: EdgeInsets.only(top: 10), - child: Row( - children: [ - LocalText(context, "reg.table_sale_vol"), - SizedBox( - width: 25, - ), - Text(_saleQty.text, style: textStyle) - ], - )); - - final dailyQuotaBox = Container( - child: TextFormField( - controller: _dailyQuota, - autofocus: false, - cursorColor: primaryColor, - style: textStyle, - decoration: new InputDecoration( - labelText: AppTranslations.of(context).text('buyer.quota'), - labelStyle: language.isEng ? labelStyle : labelStyleMM, - icon: Icon( - FontAwesomeIcons.sortNumericUpAlt, - color: primaryColor, - ), - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - ), - validator: (value) { - if (value.isEmpty) { - return "Please enter quota"; - } - return null; - }, - ), - ); - - final maxQuotaBox = Container( - child: TextFormField( - controller: _maxQuota, - autofocus: false, - cursorColor: primaryColor, - style: textStyle, - decoration: new InputDecoration( - labelText: AppTranslations.of(context).text('buyer.max.quota'), - labelStyle: language.isEng ? labelStyle : labelStyleMM, - icon: Icon( - FontAwesomeIcons.sortNumericUpAlt, - color: primaryColor, - ), - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - ), - validator: (value) { - if (value.isEmpty) { - return "Please enter quota"; - } - return null; - }, - ), - ); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - title: Text("Quota"), - actions: [ - IconButton( - icon: Icon(Icons.save), - onPressed: () { - if (!_formKey.currentState.validate()) return; - buyerProduct.dailyQuota = int.parse(_dailyQuota.text); - buyerProduct.maxQuota = int.parse(_maxQuota.text); - Navigator.pop(context, buyerProduct); - }, - ) - ], - ), - body: Form( - key: _formKey, - child: Container( - child: ListView( - shrinkWrap: true, - padding: EdgeInsets.only(left: 24.0, right: 24.0), - children: [ - productbox, - storageQtybox, - saleQtybox, - dailyQuotaBox, - maxQuotaBox - ], - ), - ), - )), - ); - } -} diff --git a/lib/pages/quota_page.dart b/lib/pages/quota_page.dart deleted file mode 100644 index 6790715..0000000 --- a/lib/pages/quota_page.dart +++ /dev/null @@ -1,216 +0,0 @@ -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/buyer_model.dart'; -import 'package:fcs/model/language_model.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/vo/buyer.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:fcs/widget/progress.dart'; - -import '../fcs/common/helpers/theme.dart'; - -class QuotaPage extends StatefulWidget { - final Buyer buyer; - final bool isApproved; - const QuotaPage({this.buyer, this.isApproved}); - @override - _QuotaPageState createState() => _QuotaPageState(); -} - -class _QuotaPageState extends State { - final formKey = GlobalKey(); - - TextEditingController _dailyQuota = new TextEditingController(); - TextEditingController _maxQuota = new TextEditingController(); - - TextEditingController _companyName = new TextEditingController(); - TextEditingController _accountName = new TextEditingController(); - Buyer buyer = Buyer(); - bool _isLoading = false; - - @override - void initState() { - super.initState(); - if (widget.buyer != null) { - this.buyer = widget.buyer; - _companyName.text = buyer.bizName; - _accountName.text = buyer.userName; - _dailyQuota.text = buyer.dailyQuota.toString(); - _maxQuota.text = buyer.maxQuota.toString(); - Provider.of(context, listen: false) - .loadBuyerProducts(buyer, force: true) - .then((b) { - setState(() { - buyer = b; - }); - }); - } - } - - @override - Widget build(BuildContext context) { - var languageModel = Provider.of(context); - - final companyNameBox = Container( - padding: EdgeInsets.only(top: 0, left: 20, right: 20), - child: TextFormField( - controller: _companyName, - autofocus: false, - cursorColor: primaryColor, - readOnly: true, - style: textStyle, - decoration: new InputDecoration( - labelText: AppTranslations.of(context).text("reg.biz_name"), - labelStyle: languageModel.isEng ? labelStyle : labelStyleMM, - border: InputBorder.none, - focusedBorder: InputBorder.none, - icon: Icon( - Icons.business, - color: primaryColor, - ), - ), - )); - final accountNameBox = Container( - padding: EdgeInsets.only(top: 0, left: 20, right: 20), - child: TextFormField( - controller: _accountName, - autofocus: false, - cursorColor: primaryColor, - readOnly: true, - style: textStyle, - decoration: new InputDecoration( - labelText: AppTranslations.of(context).text("buyer.account_name"), - labelStyle: languageModel.isEng ? labelStyle : labelStyleMM, - border: InputBorder.none, - focusedBorder: InputBorder.none, - icon: Icon( - Icons.business, - color: primaryColor, - ), - ), - )); - - final dailyQuotaBox = Container( - padding: EdgeInsets.only(top: 0, left: 20, right: 15), - child: TextFormField( - controller: _dailyQuota, - autofocus: false, - cursorColor: primaryColor, - style: textStyle, - keyboardType: TextInputType.number, - decoration: new InputDecoration( - labelText: AppTranslations.of(context).text("reg.quota"), - labelStyle: languageModel.isEng ? labelStyle : labelStyleMM, - icon: Icon( - Icons.business, - color: primaryColor, - ), - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - ), - validator: _validateQuota, - )); - - final maxQuotaBox = Container( - padding: EdgeInsets.only(top: 0, left: 20, right: 15), - child: TextFormField( - controller: _maxQuota, - autofocus: false, - cursorColor: primaryColor, - style: textStyle, - keyboardType: TextInputType.number, - decoration: new InputDecoration( - labelText: AppTranslations.of(context).text("reg.max_quota"), - labelStyle: languageModel.isEng ? labelStyle : labelStyleMM, - icon: Icon( - Icons.business, - color: primaryColor, - ), - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - ), - validator: _validateQuota, - )); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - title: Text("Quota"), - actions: [ - IconButton( - icon: Icon(Icons.send), - onPressed: () { - showConfirmDialog(context, "buyer.allocate.quota.confirm", () { - _allocate(); - }); - }, - ) - ], - ), - body: Form( - key: formKey, - child: Container( - padding: EdgeInsets.only(left: 10, right: 10, top: 10, bottom: 10), - child: ListView( - children: [ - Container( - height: 500, - child: Card( - elevation: 23, - child: Column( - children: [ - accountNameBox, - companyNameBox, - dailyQuotaBox, - maxQuotaBox, - ], - ), - ), - ) - ], - ), - ), - ), - ), - ); - } - - String _validateQuota(value) { - if (value.isEmpty) { - return "Invalid number"; - } - return null; - } - - _allocate() async { - if (!formKey.currentState.validate()) { - return; - } - setState(() { - _isLoading = true; - }); - try { - buyer.dailyQuota = int.parse(_dailyQuota.text); - buyer.maxQuota = int.parse(_maxQuota.text); - if (widget.isApproved) { - await Provider.of(context).allocate(buyer); - Navigator.pop(context, true); - } else { - Navigator.pop(context, this.buyer); - } - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - setState(() { - _isLoading = false; - }); - } - } -} diff --git a/lib/pages/rates/cargo_editor.dart b/lib/pages/rates/cargo_editor.dart new file mode 100644 index 0000000..a570b1d --- /dev/null +++ b/lib/pages/rates/cargo_editor.dart @@ -0,0 +1,143 @@ +import 'package:fcs/domain/entities/cargo_type.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/localization/app_translations.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/widgets/input_text.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import 'model/shipment_rate_model.dart'; + +class CargoEditor extends StatefulWidget { + final CargoType cargo; + CargoEditor({this.cargo}); + + @override + _CargoEditorState createState() => _CargoEditorState(); +} + +class _CargoEditorState extends State { + TextEditingController _descController = new TextEditingController(); + TextEditingController _rateController = new TextEditingController(); + + bool _isLoading = false; + CargoType _cargo; + bool _isNew = false; + + @override + void initState() { + super.initState(); + if (widget.cargo != null) { + _cargo = widget.cargo; + _descController.text = _cargo.name; + _rateController.text = _cargo.rate.toString(); + } else { + _isNew = true; + } + } + + @override + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final typeBox = InputText( + labelTextKey: 'cargo.type', + iconData: Icons.text_format, + controller: _descController); + final rateBox = InputText( + labelTextKey: 'cargo.rate', + iconData: Icons.attach_money, + controller: _rateController); + return LocalProgress( + inAsyncCall: _isLoading, + child: Scaffold( + appBar: AppBar( + centerTitle: true, + leading: new IconButton( + icon: new Icon(CupertinoIcons.back), + onPressed: () => Navigator.of(context).pop(), + ), + backgroundColor: primaryColor, + title: Text(AppTranslations.of(context).text("cargo.form.title")), + actions: [ + IconButton( + icon: Icon(Icons.delete), + onPressed: _delete, + ) + ], + ), + body: Container( + padding: EdgeInsets.all(18), + child: Column( + children: [ + Expanded( + child: ListView( + children: [ + typeBox, + rateBox, + SizedBox(height: 30), + ], + ), + ), + fcsButton(context, getLocalString(context, "btn.save"), + callack: _save), + SizedBox(height: 10) + ], + ), + ), + ), + ); + } + + _save() async { + setState(() { + _isLoading = true; + }); + try { + var shipmentRateModel = + Provider.of(context, listen: false); + CargoType _cargo = CargoType( + name: _descController.text, rate: double.parse(_rateController.text)); + if (_isNew) { + await shipmentRateModel.addCargoType(_cargo); + } else { + _cargo.id = widget.cargo.id; + await shipmentRateModel.updateCargoType(_cargo); + } + Navigator.pop(context); + } catch (e) { + showMsgDialog(context, "Error", e.toString()); + } finally { + setState(() { + _isLoading = false; + }); + } + } + + _delete() { + showConfirmDialog(context, "cargo.edit.delete.confirm", _deleteCargoType); + } + + _deleteCargoType() async { + setState(() { + _isLoading = true; + }); + try { + var shipmentRateModel = + Provider.of(context, listen: false); + await shipmentRateModel.deleteCargoType(widget.cargo.id); + Navigator.pop(context); + } catch (e) { + showMsgDialog(context, "Error", e.toString()); + } finally { + setState(() { + _isLoading = false; + }); + } + } +} diff --git a/lib/pages/rates/cargo_type_list.dart b/lib/pages/rates/cargo_type_list.dart new file mode 100644 index 0000000..4b4aa14 --- /dev/null +++ b/lib/pages/rates/cargo_type_list.dart @@ -0,0 +1,116 @@ +import 'package:fcs/domain/entities/cargo_type.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import 'cargo_editor.dart'; +import 'model/shipment_rate_model.dart'; + +class CargoTypeList extends StatefulWidget { + const CargoTypeList({Key key}) : super(key: key); + @override + _CargoTypeListState createState() => _CargoTypeListState(); +} + +class _CargoTypeListState extends State { + bool _isLoading = false; + + @override + void initState() { + super.initState(); + } + + @override + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + var shipmentRateModel = Provider.of(context); + + return LocalProgress( + inAsyncCall: _isLoading, + child: Scaffold( + appBar: AppBar( + centerTitle: true, + leading: new IconButton( + icon: new Icon(CupertinoIcons.back), + onPressed: () => Navigator.pop(context), + ), + backgroundColor: primaryColor, + title: LocalText( + context, + "cargo.form.title", + fontSize: 20, + color: Colors.white, + ), + ), + floatingActionButton: FloatingActionButton.extended( + onPressed: () { + Navigator.of(context).push( + CupertinoPageRoute(builder: (context) => CargoEditor())); + }, + icon: Icon(Icons.add, color: Colors.white), + backgroundColor: primaryColor, + label: + LocalText(context, 'cargo.form.title', color: Colors.white)), + body: Padding( + padding: const EdgeInsets.all(8.0), + child: ListView.separated( + separatorBuilder: (c, i) => Divider( + color: primaryColor, + ), + itemCount: shipmentRateModel.rate.cargoTypes.length, + itemBuilder: (context, index) { + CargoType cargo = shipmentRateModel.rate.cargoTypes[index]; + return InkWell( + onTap: () { + Navigator.of(context).push(CupertinoPageRoute( + builder: (context) => CargoEditor( + cargo: cargo, + ))); + }, + child: Container( + child: _row(cargo.name, "\$ " + cargo.rate.toString(), + 'per pound'), + ), + ); + }), + )), + ); + } + + _row(String desc, String price, String unit) { + return Container( + padding: EdgeInsets.only(left: 25, top: 5, bottom: 5), + child: Row( + children: [ + Text('$desc ', style: TextStyle(fontSize: 15)), + Spacer(), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Padding( + padding: const EdgeInsets.only(bottom: 3.0), + child: Text( + '$price', + style: TextStyle(color: primaryColor, fontSize: 14), + ), + ), + Text( + '$unit', + style: TextStyle(color: Colors.grey, fontSize: 14), + ), + ], + ), + SizedBox( + width: 50, + ), + ], + )); + } +} diff --git a/lib/pages/rates/custom_editor.dart b/lib/pages/rates/custom_editor.dart new file mode 100644 index 0000000..747716d --- /dev/null +++ b/lib/pages/rates/custom_editor.dart @@ -0,0 +1,150 @@ +import 'package:fcs/domain/entities/custom_duty.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/localization/app_translations.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/widgets/input_text.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:provider/provider.dart'; + +import 'model/shipment_rate_model.dart'; + +class CustomEditor extends StatefulWidget { + final CustomDuty custom; + CustomEditor({this.custom}); + + @override + _CustomEditorState createState() => _CustomEditorState(); +} + +class _CustomEditorState extends State { + TextEditingController _productController = new TextEditingController(); + TextEditingController _feeController = new TextEditingController(); + + bool _isLoading = false; + CustomDuty _custom = new CustomDuty(); + bool _isNew = false; + + @override + void initState() { + super.initState(); + if (widget.custom != null) { + _custom = widget.custom; + _productController.text = _custom.productType; + _feeController.text = _custom.fee.toString(); + } else { + _isNew = true; + } + } + + @override + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final productBox = InputText( + labelTextKey: 'rate.cutom.product_type', + iconData: FontAwesomeIcons.weightHanging, + controller: _productController); + final feeBox = InputText( + labelTextKey: 'rate.custom.fee', + iconData: Icons.attach_money, + controller: _feeController); + return LocalProgress( + inAsyncCall: _isLoading, + child: Scaffold( + appBar: AppBar( + centerTitle: true, + leading: new IconButton( + icon: new Icon( + CupertinoIcons.back, + ), + onPressed: () => Navigator.of(context).pop(), + ), + backgroundColor: primaryColor, + title: + Text(AppTranslations.of(context).text("rate.custom.form.title")), + actions: [ + IconButton( + icon: Icon(Icons.delete), + onPressed: _delete, + ) + ], + ), + body: Container( + padding: EdgeInsets.all(18), + child: Column( + children: [ + Expanded( + child: ListView( + children: [ + productBox, + feeBox, + SizedBox(height: 30), + ], + ), + ), + fcsButton(context, getLocalString(context, "btn.save"), + callack: _save), + SizedBox(height: 10) + ], + ), + ), + ), + ); + } + + _save() async { + setState(() { + _isLoading = true; + }); + try { + var shipmentRateModel = + Provider.of(context, listen: false); + CustomDuty _customduty = CustomDuty( + productType: _productController.text, + fee: double.parse(_feeController.text)); + print('_customduty => $_customduty'); + if (_isNew) { + await shipmentRateModel.addCustomDuty(_customduty); + } else { + _customduty.id = widget.custom.id; + await shipmentRateModel.updateCustomDuty(_customduty); + } + Navigator.pop(context); + } catch (e) { + showMsgDialog(context, "Error", e.toString()); + } finally { + setState(() { + _isLoading = false; + }); + } + } + + _delete() { + showConfirmDialog( + context, "rate.custom.edit.delete.confirm", _deleteCustomDuty); + } + + _deleteCustomDuty() async { + setState(() { + _isLoading = true; + }); + try { + var shipmentRateModel = + Provider.of(context, listen: false); + await shipmentRateModel.deleteCustomDuty(widget.custom.id); + Navigator.pop(context); + } catch (e) { + showMsgDialog(context, "Error", e.toString()); + } finally { + setState(() { + _isLoading = false; + }); + } + } +} diff --git a/lib/pages/rates/custom_list.dart b/lib/pages/rates/custom_list.dart new file mode 100644 index 0000000..41946e0 --- /dev/null +++ b/lib/pages/rates/custom_list.dart @@ -0,0 +1,124 @@ +import 'package:fcs/domain/entities/custom_duty.dart'; +import 'package:fcs/domain/vo/delivery_address.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/delivery_address/delivery_address_editor.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/rates/custom_editor.dart'; +import 'package:fcs/pages/widgets/bottom_up_page_route.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import 'custom_row.dart'; +import 'model/shipment_rate_model.dart'; + +class CustomList extends StatefulWidget { + final bool selected; + const CustomList({Key key, this.selected}) : super(key: key); + @override + _CustomListState createState() => _CustomListState(); +} + +class _CustomListState extends State { + bool _isLoading = false; + bool _selected = false; + + @override + void initState() { + super.initState(); + if (widget.selected != null) { + _selected = widget.selected; + } + } + + @override + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + var shipmentRateModel = Provider.of(context); + + return LocalProgress( + inAsyncCall: _isLoading, + child: Scaffold( + appBar: AppBar( + centerTitle: true, + leading: new IconButton( + icon: new Icon(CupertinoIcons.back), + onPressed: () => Navigator.pop(context), + ), + backgroundColor: primaryColor, + title: LocalText( + context, + "rate.custom_duty.title", + fontSize: 20, + color: Colors.white, + ), + ), + floatingActionButton: FloatingActionButton.extended( + onPressed: () { + Navigator.of(context).push( + CupertinoPageRoute(builder: (context) => CustomEditor())); + }, + icon: Icon(Icons.add, color: Colors.white), + backgroundColor: primaryColor, + label: + LocalText(context, 'rate.custom_duty', color: Colors.white)), + body: Padding( + padding: const EdgeInsets.all(8.0), + child: ListView.separated( + separatorBuilder: (c, i) => Divider( + color: primaryColor, + ), + itemCount: shipmentRateModel.rate.customDuties.length, + itemBuilder: (context, index) { + CustomDuty custom = + shipmentRateModel.rate.customDuties[index]; + return InkWell( + onTap: () { + _selected + ? Navigator.pop(context, custom) + : Navigator.of(context).push(CupertinoPageRoute( + builder: (context) => + CustomEditor(custom: custom))); + }, + child: Container( + child: _row( + custom.productType, "\$ " + custom.fee.toString()), + ), + ); + }), + )), + ); + } + + _row(String desc, String price) { + return Container( + padding: EdgeInsets.only(left: 25, top: 5, bottom: 5), + child: Row( + children: [ + Text('$desc ', style: TextStyle(fontSize: 15)), + Spacer(), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Padding( + padding: const EdgeInsets.only(bottom: 3.0), + child: Text( + '$price', + style: TextStyle(color: primaryColor, fontSize: 14), + ), + ), + ], + ), + SizedBox( + width: 50, + ), + ], + )); + } +} diff --git a/lib/pages/rates/custom_row.dart b/lib/pages/rates/custom_row.dart new file mode 100644 index 0000000..87a1a89 --- /dev/null +++ b/lib/pages/rates/custom_row.dart @@ -0,0 +1,64 @@ +import 'package:fcs/domain/entities/custom_duty.dart'; +import 'package:fcs/domain/vo/delivery_address.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_icons/flutter_icons.dart'; + +typedef SelectionCallback(CustomDuty custom); + +class CustomRow extends StatelessWidget { + final CustomDuty custom; + final SelectionCallback selectionCallback; + const CustomRow({Key key, this.custom, this.selectionCallback}) + : super(key: key); + + @override + Widget build(BuildContext context) { + return InkWell( + onTap: selectionCallback == null + ? null + : () => this.selectionCallback(custom), + child: Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + line(context, custom.productType, + iconData: MaterialCommunityIcons.account, + color: primaryColor, + fontSize: 16), + line(context, custom.fee.toString(), + iconData: Icons.phone, color: primaryColor, fontSize: 16), + ], + ), + ), + ], + ), + ); + } + + Widget line(BuildContext context, String text, + {IconData iconData, Color color, double fontSize}) { + return Row( + children: [ + iconData == null + ? SizedBox(width: 40) + : Padding( + padding: const EdgeInsets.only(left: 8.0, right: 8), + child: Icon(iconData, color: Colors.black38), + ), + Flexible( + child: TextLocalStyle( + context, + text ?? "", + fontSize: fontSize ?? 14, + color: color, + ), + ), + ], + ); + } +} diff --git a/lib/pages/rates/discount_by weight_list.dart b/lib/pages/rates/discount_by weight_list.dart new file mode 100644 index 0000000..84ee955 --- /dev/null +++ b/lib/pages/rates/discount_by weight_list.dart @@ -0,0 +1,119 @@ +import 'package:fcs/domain/entities/custom_duty.dart'; +import 'package:fcs/domain/entities/discount.dart'; +import 'package:fcs/domain/entities/discount_by_weight.dart'; +import 'package:fcs/domain/vo/delivery_address.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/delivery_address/delivery_address_editor.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/rates/custom_editor.dart'; +import 'package:fcs/pages/rates/discount_by_weight_editor.dart'; +import 'package:fcs/pages/widgets/bottom_up_page_route.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import 'custom_row.dart'; +import 'model/shipment_rate_model.dart'; + +class DiscountByWeightList extends StatefulWidget { + const DiscountByWeightList({Key key}) : super(key: key); + @override + _DiscountByWeightListState createState() => _DiscountByWeightListState(); +} + +class _DiscountByWeightListState extends State { + bool _isLoading = false; + + @override + void initState() { + super.initState(); + } + + @override + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + var shipmentRateModel = Provider.of(context); + + return LocalProgress( + inAsyncCall: _isLoading, + child: Scaffold( + appBar: AppBar( + centerTitle: true, + leading: new IconButton( + icon: new Icon(CupertinoIcons.back), + onPressed: () => Navigator.pop(context), + ), + backgroundColor: primaryColor, + title: LocalText( + context, + "rate.discount_by_weight", + fontSize: 20, + color: Colors.white, + ), + ), + floatingActionButton: FloatingActionButton.extended( + onPressed: () { + Navigator.of(context).push(CupertinoPageRoute( + builder: (context) => DiscountByWeightEditor())); + }, + icon: Icon(Icons.add, color: Colors.white), + backgroundColor: primaryColor, + label: LocalText(context, 'discount.new', color: Colors.white)), + body: Padding( + padding: const EdgeInsets.all(8.0), + child: ListView.separated( + separatorBuilder: (c, i) => Divider( + color: primaryColor, + ), + itemCount: shipmentRateModel.rate.discountByWeights.length, + itemBuilder: (context, index) { + DiscountByWeight discountByWeight = + shipmentRateModel.rate.discountByWeights[index]; + return InkWell( + onTap: () { + Navigator.of(context).push(CupertinoPageRoute( + builder: (context) => DiscountByWeightEditor( + discountByWeight: discountByWeight))); + }, + child: Container( + child: _row("${discountByWeight.weight.toString()} lb", + "\$ " + discountByWeight.discount.toString()), + ), + ); + }), + )), + ); + } + + _row(String desc, String price) { + return Container( + padding: EdgeInsets.only(left: 25, top: 5, bottom: 5), + child: Row( + children: [ + Text('$desc ', style: TextStyle(fontSize: 15)), + Spacer(), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Padding( + padding: const EdgeInsets.only(bottom: 3.0), + child: Text( + '$price', + style: TextStyle(color: primaryColor, fontSize: 14), + ), + ), + ], + ), + SizedBox( + width: 50, + ), + ], + )); + } +} diff --git a/lib/pages/rates/discount_by_weight_editor.dart b/lib/pages/rates/discount_by_weight_editor.dart new file mode 100644 index 0000000..c271183 --- /dev/null +++ b/lib/pages/rates/discount_by_weight_editor.dart @@ -0,0 +1,148 @@ +import 'package:fcs/domain/entities/discount_by_weight.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/localization/app_translations.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/rates/model/shipment_rate_model.dart'; +import 'package:fcs/pages/widgets/input_text.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:provider/provider.dart'; + +class DiscountByWeightEditor extends StatefulWidget { + final DiscountByWeight discountByWeight; + DiscountByWeightEditor({this.discountByWeight}); + + @override + _DiscountByWeightEditorState createState() => _DiscountByWeightEditorState(); +} + +class _DiscountByWeightEditorState extends State { + TextEditingController _weightController = new TextEditingController(); + TextEditingController _discountController = new TextEditingController(); + + bool _isLoading = false; + bool _isNew; + DiscountByWeight _discountByWeight = new DiscountByWeight(); + + @override + void initState() { + super.initState(); + if (widget.discountByWeight != null) { + _discountByWeight = widget.discountByWeight; + _weightController.text = _discountByWeight.weight.toString(); + _discountController.text = _discountByWeight.discount.toString(); + _isNew = false; + } else { + _isNew = true; + } + } + + @override + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final weightBox = InputText( + labelTextKey: 'rate.discount.weight', + iconData: FontAwesomeIcons.weightHanging, + controller: _weightController); + final discountRateBox = InputText( + labelTextKey: 'rate.discount.rate', + iconData: Icons.attach_money, + controller: _discountController); + + return LocalProgress( + inAsyncCall: _isLoading, + child: Scaffold( + appBar: AppBar( + centerTitle: true, + leading: new IconButton( + icon: new Icon(CupertinoIcons.back), + onPressed: () => Navigator.of(context).pop(), + ), + backgroundColor: primaryColor, + title: Text(AppTranslations.of(context).text("discount.new")), + actions: [ + IconButton( + icon: Icon(Icons.delete), + onPressed: _delete, + ) + ], + ), + body: Container( + padding: EdgeInsets.all(18), + child: Column( + children: [ + Expanded( + child: ListView( + children: [ + weightBox, + discountRateBox, + SizedBox(height: 30), + ], + ), + ), + fcsButton(context, getLocalString(context, "btn.save"), + callack: _save), + SizedBox(height: 10) + ], + ), + ), + ), + ); + } + + _save() async { + setState(() { + _isLoading = true; + }); + try { + var shipmentRateModel = + Provider.of(context, listen: false); + DiscountByWeight _discount = DiscountByWeight( + weight: double.parse(_weightController.text), + discount: double.parse(_discountController.text)); + if (_isNew) { + await shipmentRateModel.addDiscountByWeight(_discount); + } else { + _discount.id = widget.discountByWeight.id; + await shipmentRateModel.updateDiscountByWeight(_discount); + } + Navigator.pop(context); + } catch (e) { + showMsgDialog(context, "Error", e.toString()); + } finally { + setState(() { + _isLoading = false; + }); + } + } + + _delete() { + showConfirmDialog(context, "rate.discount_by_weight.edit.delete.confirm", + _deleteDiscountByWeight); + } + + _deleteDiscountByWeight() async { + setState(() { + _isLoading = true; + }); + try { + var shipmentRateModel = + Provider.of(context, listen: false); + await shipmentRateModel + .deleteDiscountByWeight(widget.discountByWeight.id); + Navigator.pop(context); + } catch (e) { + showMsgDialog(context, "Error", e.toString()); + } finally { + setState(() { + _isLoading = false; + }); + } + } +} diff --git a/lib/pages/rates/model/shipment_rate_model.dart b/lib/pages/rates/model/shipment_rate_model.dart new file mode 100644 index 0000000..1bf26d3 --- /dev/null +++ b/lib/pages/rates/model/shipment_rate_model.dart @@ -0,0 +1,79 @@ +import 'dart:async'; + +import 'package:fcs/data/services/services.dart'; +import 'package:fcs/domain/entities/cargo_type.dart'; +import 'package:fcs/domain/entities/custom_duty.dart'; +import 'package:fcs/domain/entities/discount_by_weight.dart'; +import 'package:fcs/domain/entities/rate.dart'; +import 'package:fcs/pages/main/model/base_model.dart'; +import 'package:logging/logging.dart'; + +class ShipmentRateModel extends BaseModel { + final log = Logger('ShipmentRateModel'); + + StreamSubscription listener; + Rate rate; + + void initUser(user) { + super.initUser(user); + if (listener != null) listener.cancel(); + listener = Services.instance.rateService.getRateStream().listen((rate) { + this.rate = rate; + notifyListeners(); + }); + } + + @override + logout() async { + if (listener != null) await listener.cancel(); + } + + // Rate + + Future updateRate(Rate rate) { + return Services.instance.rateService.updateRate(rate); + } + + //Cargo Type + + Future addCargoType(CargoType cargoType) { + return Services.instance.rateService.createCargoType(cargoType); + } + + Future updateCargoType(CargoType cargoType) { + return Services.instance.rateService.updateCargoType(cargoType); + } + + Future deleteCargoType(String id) { + return Services.instance.rateService.deleteCargoType(id); + } + + //CustomDuty + + Future addCustomDuty(CustomDuty customDuty) { + return Services.instance.rateService.createCustomDuty(customDuty); + } + + Future updateCustomDuty(CustomDuty customDuty) { + return Services.instance.rateService.updateCustomDuty(customDuty); + } + + Future deleteCustomDuty(String id) { + return Services.instance.rateService.deleteCustomDuty(id); + } + + //Discount by weight + Future addDiscountByWeight(DiscountByWeight discountByWeight) { + return Services.instance.rateService + .createDiscountByWeight(discountByWeight); + } + + Future updateDiscountByWeight(DiscountByWeight discountByWeight) { + return Services.instance.rateService + .updateDiscountByWeight(discountByWeight); + } + + Future deleteDiscountByWeight(String id) { + return Services.instance.rateService.deleteDiscountByWeight(id); + } +} diff --git a/lib/pages/rates/shipment_rates.dart b/lib/pages/rates/shipment_rates.dart new file mode 100644 index 0000000..f5f6a8a --- /dev/null +++ b/lib/pages/rates/shipment_rates.dart @@ -0,0 +1,234 @@ +import 'package:fcs/domain/entities/cargo_type.dart'; +import 'package:fcs/domain/entities/custom_duty.dart'; +import 'package:fcs/domain/entities/discount_by_weight.dart'; +import 'package:fcs/domain/entities/rate.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/main/model/main_model.dart'; +import 'package:fcs/pages/rates/cargo_type_list.dart'; +import 'package:fcs/pages/rates/custom_list.dart'; +import 'package:fcs/pages/rates/model/shipment_rate_model.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import '../main/util.dart'; +import 'discount_by weight_list.dart'; +import 'shipment_rates_calculate.dart'; +import 'shipment_rates_edit.dart'; + +class ShipmentRates extends StatefulWidget { + ShipmentRates(); + + @override + _ShipmentRatesState createState() => _ShipmentRatesState(); +} + +class _ShipmentRatesState extends State { + bool _isLoading = false; + + @override + void initState() { + super.initState(); + } + + @override + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + var shipmentRateModel = Provider.of(context); + Rate rate = shipmentRateModel.rate; + bool isEditable = context.select((MainModel m) => m.rateEditable()); + + return LocalProgress( + inAsyncCall: _isLoading, + child: Scaffold( + appBar: AppBar( + centerTitle: true, + leading: new IconButton( + icon: new Icon(CupertinoIcons.back, color: primaryColor), + onPressed: () => Navigator.of(context).pop(), + ), + backgroundColor: Colors.white, + shadowColor: Colors.transparent, + title: LocalText(context, 'rate.title', + color: primaryColor, fontSize: 20), + actions: isEditable + ? [ + IconButton( + onPressed: () => Navigator.of(context).push( + CupertinoPageRoute( + builder: (context) => ShipmentRatesEdit())), + icon: Icon( + CupertinoIcons.pen, + color: primaryColor, + )) + ] + : [], + ), + body: Padding( + padding: const EdgeInsets.all(8.0), + child: ListView( + // crossAxisAlignment: CrossAxisAlignment.center, + children: [ + fcsButton(context, getLocalString(context, "rate.cal.title"), + callack: () { + Navigator.of(context).push(CupertinoPageRoute( + builder: (context) => ShipmentRatesCal())); + }), + Divider( + color: Colors.grey, + ), + Container( + padding: EdgeInsets.only(left: 25, top: 10, right: 25), + child: Row( + children: [ + LocalText(context, "rate.cargo.type", + color: primaryColor, + fontWeight: FontWeight.bold, + fontSize: 15), + Spacer(), + isEditable + ? IconButton( + icon: Icon(Icons.edit, color: primaryColor), + onPressed: () { + Navigator.of(context).push(CupertinoPageRoute( + builder: (context) => CargoTypeList())); + }) + : Container() + ], + ), + ), + Column( + children: getCargoWidget(shipmentRateModel.rate.cargoTypes), + ), + Divider( + color: Colors.grey, + ), + Container( + padding: EdgeInsets.only(left: 25, top: 10, right: 25), + child: Row( + children: [ + LocalText(context, "rate.discount_by_weight", + color: primaryColor, + fontWeight: FontWeight.bold, + fontSize: 15), + Spacer(), + isEditable + ? IconButton( + icon: Icon(Icons.edit, color: primaryColor), + onPressed: () { + Navigator.of(context).push(CupertinoPageRoute( + builder: (context) => + DiscountByWeightList())); + }) + : Container() + ], + ), + ), + Column( + children: + getDiscountWidget(shipmentRateModel.rate.discountByWeights), + ), + Divider( + color: Colors.grey, + ), + _row("Free delivery within Yangon \nfor shipments over", + "${rate.freeDeliveryWeight}", "pounds"), + _row("Delivery fees", "\$ ${rate.deliveryFee}", + "below ${rate.freeDeliveryWeight} pounds"), + _row("Volumetric Ratio", "${rate.volumetricRatio}", + "in3 per pound"), + Divider( + color: Colors.grey, + ), + Container( + padding: EdgeInsets.only(left: 25, top: 10, right: 25), + child: Row( + children: [ + LocalText(context, "rate.custom_duty", + color: primaryColor, + fontWeight: FontWeight.bold, + fontSize: 15), + Spacer(), + isEditable + ? IconButton( + icon: Icon(Icons.edit, color: primaryColor), + onPressed: () { + Navigator.of(context).push(CupertinoPageRoute( + builder: (context) => CustomList())); + }) + : Container() + ], + ), + ), + Column( + children: getCustonWidget(shipmentRateModel.rate.customDuties), + ), + ], + ), + ), + ), + ); + } + + List getCargoWidget(List cargos) { + return cargos.map((cargo) { + return Container( + child: _row(cargo.name, "\$ " + cargo.rate.toString(), 'per pound'), + ); + }).toList(); + } + + List getCustonWidget(List customs) { + return customs.map((c) { + return Container( + child: _row(c.productType, "\$ " + c.fee.toString(), ''), + ); + }).toList(); + } + + List getDiscountWidget(List discounts) { + if (discounts == null) return []; + return discounts.map((d) { + return Container( + child: _row( + "${d.weight.toString()} lb", "\$ " + d.discount.toString(), ''), + ); + }).toList(); + } + + _row(String desc, String price, String unit) { + return Container( + padding: EdgeInsets.only(left: 25, top: 5, bottom: 5), + child: Row( + children: [ + Text('$desc ', style: TextStyle(fontSize: 15)), + Spacer(), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Padding( + padding: const EdgeInsets.only(bottom: 3.0), + child: Text( + '$price', + style: TextStyle(color: primaryColor, fontSize: 14), + ), + ), + Text( + '$unit', + style: TextStyle(color: Colors.grey, fontSize: 14), + ), + ], + ), + SizedBox( + width: 50, + ), + ], + )); + } +} diff --git a/lib/pages/rates/shipment_rates_calculate.dart b/lib/pages/rates/shipment_rates_calculate.dart new file mode 100644 index 0000000..3ad1f62 --- /dev/null +++ b/lib/pages/rates/shipment_rates_calculate.dart @@ -0,0 +1,231 @@ +import 'package:fcs/domain/entities/carton.dart'; +import 'package:fcs/domain/entities/cargo_type.dart'; +import 'package:fcs/domain/entities/rate.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/rates/model/shipment_rate_model.dart'; +import 'package:fcs/pages/widgets/display_text.dart'; +import 'package:fcs/pages/widgets/input_text.dart'; +import 'package:fcs/pages/widgets/length_picker.dart'; +import 'package:fcs/pages/widgets/local_dropdown.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_icons/flutter_icons.dart'; +import 'package:provider/provider.dart'; + +class ShipmentRatesCal extends StatefulWidget { + ShipmentRatesCal(); + + @override + _ShipmentRatesCalState createState() => _ShipmentRatesCalState(); +} + +class _ShipmentRatesCalState extends State { + bool _isLoading = false; + CargoType _cargoType; + TextEditingController _widthController = new TextEditingController(); + TextEditingController _heightController = new TextEditingController(); + TextEditingController _lengthController = new TextEditingController(); + TextEditingController _actualWeightCtl = new TextEditingController(); + double _shipmentWeight = 0; + double _amount = 0; + double _deliveryFee = 0; + + @override + void initState() { + super.initState(); + + //for shipment weight + Rate rate = Provider.of(context, listen: false).rate; + _lengthController.addListener(_calShipmentWeight); + _widthController.addListener(_calShipmentWeight); + _heightController.addListener(_calShipmentWeight); + _actualWeightCtl.addListener(_calShipmentWeight); + _cargoType = rate.defaultCargoType; + _lengthController.text = '12'; + _widthController.text = '12'; + _heightController.text = '12'; + _actualWeightCtl.text = "10"; + _calShipmentWeight(); + } + + _calShipmentWeight() { + Rate rate = Provider.of(context, listen: false).rate; + + double l = double.parse(_lengthController.text, (s) => 0); + double w = double.parse(_widthController.text, (s) => 0); + double h = double.parse(_heightController.text, (s) => 0); + _cargoType.weight = double.tryParse(_actualWeightCtl.text) ?? 0; + Carton box = + Carton(cargoTypes: [_cargoType], length: l, width: w, height: h); + var amount = box.calAmount(rate); + var shipmentWeight = box.getShipmentWeight(rate.volumetricRatio); + var effectiveWeight = + _cargoType.weight > shipmentWeight ? _cargoType.weight : shipmentWeight; + + setState(() { + _deliveryFee = + effectiveWeight > rate.freeDeliveryWeight ? 0 : rate.deliveryFee; + _amount = amount == null ? 0 : amount + _deliveryFee; + _shipmentWeight = shipmentWeight; + }); + } + + @override + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + var shipmentRateModel = Provider.of(context); + List cargos = shipmentRateModel.rate.cargoTypes; + + final lengthBox = LengthPicker( + controller: _lengthController, + lableKey: "box.length", + ); + final widthBox = LengthPicker( + controller: _widthController, + lableKey: "box.width", + ); + final heightBox = LengthPicker( + controller: _heightController, + lableKey: "box.height", + ); + + final dimBox = Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(right: 8.0), + child: Icon(FontAwesome.arrow_circle_right, color: primaryColor), + ), + SizedBox(child: lengthBox, width: 80), + SizedBox(child: widthBox, width: 80), + SizedBox(child: heightBox, width: 80), + ], + ); + + final shipmentWeightBox = DisplayText( + text: _shipmentWeight != null ? _shipmentWeight.toStringAsFixed(2) : "0", + labelTextKey: "box.shipment_weight", + iconData: MaterialCommunityIcons.weight, + ); + + final actualWeightBox = InputText( + controller: _actualWeightCtl, + labelTextKey: "box.actual_weight", + iconData: MaterialCommunityIcons.weight, + textInputType: TextInputType.number, + ); + + var cargoTypeBox = LocalDropdown( + callback: (v) { + setState(() { + _cargoType = v; + }); + }, + labelKey: "cargo.type", + iconData: Icons.text_format, + selectedValue: _cargoType, + values: cargos, + ); + + return LocalProgress( + inAsyncCall: _isLoading, + child: Scaffold( + appBar: AppBar( + centerTitle: true, + leading: new IconButton( + icon: new Icon(CupertinoIcons.back, color: primaryColor), + onPressed: () => Navigator.of(context).pop(), + ), + backgroundColor: Colors.white, + shadowColor: Colors.transparent, + title: LocalText(context, 'rate.cal.title', + color: primaryColor, fontSize: 20), + ), + body: Padding( + padding: const EdgeInsets.all(8.0), + child: ListView( + children: [ + cargoTypeBox, + actualWeightBox, + dimBox, + shipmentWeightBox, + SizedBox(height: 50), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + LocalText(context, "rate.delivery_fee", + color: primaryColor, fontSize: 16), + Text( + ':\$ $_deliveryFee', + style: TextStyle( + color: primaryColor, + fontSize: 16, + ), + ) + ], + ), + SizedBox(height: 20), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + LocalText(context, "rate.total_estimated_amount", + color: primaryColor, fontSize: 16), + Text( + ':\$${_amount.toStringAsFixed(2)}', + style: TextStyle( + color: primaryColor, + fontSize: 16, + ), + ) + ], + ) + ], + ), + ), + ), + ); + } + + _row(String desc, String price, String unit, String value, {bool input}) { + return Container( + padding: EdgeInsets.only(left: 25, top: 5, bottom: 5), + child: Row( + children: [ + Text('$desc ', style: TextStyle(fontSize: 15)), + Spacer(), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Padding( + padding: const EdgeInsets.only(bottom: 3.0), + child: Text( + '$price', + style: TextStyle(color: primaryColor, fontSize: 14), + ), + ), + Text( + '$unit', + style: TextStyle(color: Colors.grey, fontSize: 14), + ), + // TextFormField(), + ], + ), + SizedBox( + width: 50, + ), + Container( + width: 50, + child: TextFormField( + initialValue: value, + textAlign: TextAlign.end, + )), + ], + )); + } +} diff --git a/lib/pages/rates/shipment_rates_edit.dart b/lib/pages/rates/shipment_rates_edit.dart new file mode 100644 index 0000000..286be1c --- /dev/null +++ b/lib/pages/rates/shipment_rates_edit.dart @@ -0,0 +1,244 @@ +import 'package:fcs/domain/entities/cargo_type.dart'; +import 'package:fcs/domain/entities/custom_duty.dart'; +import 'package:fcs/domain/entities/discount_by_weight.dart'; +import 'package:fcs/domain/entities/rate.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/localization/app_translations.dart'; +import 'package:fcs/pages/rates/model/shipment_rate_model.dart'; +import 'package:fcs/pages/widgets/input_text.dart'; +import 'package:fcs/pages/widgets/my_data_table.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:provider/provider.dart'; + +import '../main/util.dart'; +import 'cargo_editor.dart'; +import 'custom_editor.dart'; + +class ShipmentRatesEdit extends StatefulWidget { + ShipmentRatesEdit(); + + @override + _ShipmentRatesEditState createState() => _ShipmentRatesEditState(); +} + +class _ShipmentRatesEditState extends State { + bool _isLoading = false; + TextEditingController _minWeight = new TextEditingController(); + TextEditingController _deliveryFee = new TextEditingController(); + TextEditingController _volumetricRatio = new TextEditingController(); + + @override + void initState() { + super.initState(); + var shipmentRateModel = + Provider.of(context, listen: false); + Rate rate = shipmentRateModel.rate; + + _minWeight.text = rate.freeDeliveryWeight?.toString() ?? ""; + _deliveryFee.text = rate.deliveryFee?.toString() ?? ""; + _volumetricRatio.text = rate.volumetricRatio?.toString() ?? ""; + } + + @override + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + var shipmentRateModel = Provider.of(context); + + final minWigBox = InputText( + labelTextKey: 'rate.min_weight', + iconData: FontAwesomeIcons.weightHanging, + controller: _minWeight); + final feeBox = InputText( + labelTextKey: 'rate.delivery_fee', + iconData: Icons.attach_money, + controller: _deliveryFee); + final ratioBox = InputText( + labelTextKey: 'rate.volumetric_ratio', + iconData: Icons.attach_money, + controller: _volumetricRatio); + + return LocalProgress( + inAsyncCall: _isLoading, + child: Scaffold( + appBar: AppBar( + centerTitle: true, + leading: new IconButton( + icon: new Icon( + CupertinoIcons.back, + ), + onPressed: () => Navigator.of(context).pop(), + ), + backgroundColor: primaryColor, + title: Text(AppTranslations.of(context).text("rate.edit.title")), + ), + body: Container( + padding: EdgeInsets.all(18), + child: Column( + children: [ + Expanded( + child: ListView( + children: [ + minWigBox, + feeBox, + ratioBox, + SizedBox(height: 10), + ], + ), + ), + fcsButton(context, getLocalString(context, "btn.save"), + callack: _save), + SizedBox(height: 10) + ], + ), + ), + ), + ); + } + + _save() async { + setState(() { + _isLoading = true; + }); + try { + var shipmentRateModel = + Provider.of(context, listen: false); + Rate _rate = new Rate( + deliveryFee: double.parse(_deliveryFee.text), + freeDeliveryWeight: double.parse(_minWeight.text), + volumetricRatio: double.parse(_volumetricRatio.text)); + Rate r = new Rate(); + print('_rate =>$r'); + await shipmentRateModel.updateRate(_rate); + Navigator.pop(context); + } catch (e) { + showMsgDialog(context, "Error", e.toString()); + } finally { + setState(() { + _isLoading = false; + }); + } + } + + List getCargoRows(List cargos) { + return cargos.map((r) { + return MyDataRow( + onSelectChanged: (selected) { + Navigator.push( + context, + CupertinoPageRoute(builder: (context) => CargoEditor(cargo: r)), + ); + }, + cells: [ + MyDataCell( + new Text( + r.name, + style: textStyle, + ), + ), + MyDataCell( + new Text( + r.rate.toString(), + style: textStyle, + ), + ), + MyDataCell(IconButton(icon: Icon(Icons.delete), onPressed: null)), + ], + ); + }).toList(); + } + + List getCustomsRows(List customs) { + return customs.map((c) { + return MyDataRow( + onSelectChanged: (selected) { + Navigator.push( + context, + CupertinoPageRoute(builder: (context) => CustomEditor(custom: c)), + ); + }, + cells: [ + MyDataCell( + new Text( + c.productType, + style: textStyle, + ), + ), + MyDataCell( + new Text( + c.fee.toString(), + style: textStyle, + ), + ), + MyDataCell(IconButton(icon: Icon(Icons.delete), onPressed: null)), + ], + ); + }).toList(); + } + + List getDiscounts(List discounts) { + return discounts.map((d) { + return MyDataRow( + onSelectChanged: (selected) { + // Navigator.push( + // context, + // CupertinoPageRoute(builder: (context) => CargoEditor(rate: r)), + // ); + }, + cells: [ + MyDataCell( + new Text( + "${d.weight} lb", + style: textStyle, + ), + ), + MyDataCell( + Center( + child: new Text( + d.discount.toString(), + style: textStyle, + ), + ), + ), + MyDataCell(IconButton(icon: Icon(Icons.delete), onPressed: null)), + ], + ); + }).toList(); + } + + _row(String desc, String price, String unit) { + return Container( + padding: EdgeInsets.only(left: 25, top: 5, bottom: 5), + child: Row( + children: [ + Text('$desc ', style: TextStyle(fontSize: 15)), + Spacer(), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Padding( + padding: const EdgeInsets.only(bottom: 3.0), + child: Text( + '$price', + style: TextStyle(color: primaryColor, fontSize: 14), + ), + ), + Text( + '$unit', + style: TextStyle(color: Colors.grey, fontSize: 14), + ), + ], + ), + SizedBox( + width: 50, + ), + ], + )); + } +} diff --git a/lib/pages/receiving/receiving_editor.dart b/lib/pages/receiving/receiving_editor.dart new file mode 100644 index 0000000..f8c59d3 --- /dev/null +++ b/lib/pages/receiving/receiving_editor.dart @@ -0,0 +1,239 @@ +import 'package:barcode_scan/barcode_scan.dart'; +import 'package:fcs/domain/entities/package.dart'; +import 'package:fcs/domain/entities/user.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/package/model/package_model.dart'; +import 'package:fcs/pages/user_search/user_serach.dart'; +import 'package:fcs/pages/widgets/barcode_scanner.dart'; +import 'package:fcs/pages/widgets/display_text.dart'; +import 'package:fcs/pages/widgets/fcs_id_icon.dart'; +import 'package:fcs/pages/widgets/input_text.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/multi_img_controller.dart'; +import 'package:fcs/pages/widgets/multi_img_file.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_icons/flutter_icons.dart'; +import 'package:permission_handler/permission_handler.dart'; +import 'package:provider/provider.dart'; + +typedef void FindCallBack(); + +class ReceivingEditor extends StatefulWidget { + final Package package; + const ReceivingEditor({this.package}); + @override + _ReceivingEditorState createState() => _ReceivingEditorState(); +} + +class _ReceivingEditorState extends State { + Package package = Package(); + bool _isLoading = false; + bool _isNew; + User user; + TextEditingController _trackingIDCtl = new TextEditingController(); + TextEditingController _remarkCtl = new TextEditingController(); + MultiImgController _multiImgController = MultiImgController(); + + @override + void initState() { + super.initState(); + _isNew = widget.package == null; + if (!_isNew) { + package = widget.package; + _trackingIDCtl.text = package.trackingID; + _remarkCtl.text = package.remark; + _multiImgController.setImageUrls = package.photoUrls; + user = User( + fcsID: package.fcsID, + name: package.userName, + phoneNumber: package.phoneNumber); + } else { + package = new Package(); + } + } + + @override + Widget build(BuildContext context) { + var fcsIDBox = Row( + children: [ + Expanded( + child: DisplayText( + text: user != null ? user.fcsID : "", + labelTextKey: "receiving.fcs.id", + icon: FcsIDIcon(), + )), + IconButton( + icon: Icon(Icons.search, color: primaryColor), + onPressed: () => searchUser(context, callbackUserSelect: (u) { + setState(() { + this.user = u; + }); + })), + ], + ); + + final trackingIDBox = Container( + padding: EdgeInsets.only(left: 6), + child: Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Expanded( + child: InputText( + iconData: MaterialCommunityIcons.barcode_scan, + labelTextKey: "receiving.tracking.id", + controller: _trackingIDCtl, + )), + InkWell( + onTap: _scan, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + Icon( + MaterialCommunityIcons.barcode_scan, + color: primaryColor, + ), + Text("Scan") + ], + ), + ), + ), + ], + )); + + final remarkBox = InputText( + labelTextKey: 'receiving.remark', + iconData: Entypo.new_message, + controller: _remarkCtl); + final img = MultiImageFile( + enabled: true, + controller: _multiImgController, + title: "Receiving", + ); + final namebox = DisplayText( + text: user != null ? user.name : "", + labelTextKey: "receiving.name", + iconData: Icons.person, + ); + + final createButton = fcsButton( + context, + getLocalString(context, 'receiving.create_btn'), + callack: _save, + ); + + final updateButton = fcsButton( + context, + getLocalString(context, 'receiving.update_btn'), + callack: _save, + ); + + return LocalProgress( + inAsyncCall: _isLoading, + child: Scaffold( + appBar: AppBar( + centerTitle: true, + leading: new IconButton( + icon: new Icon(CupertinoIcons.back, color: primaryColor, size: 30), + onPressed: () => Navigator.of(context).pop(), + ), + shadowColor: Colors.transparent, + backgroundColor: Colors.white, + title: LocalText( + context, + _isNew ? "receiving.create" : "receiving.update", + fontSize: 20, + color: primaryColor, + ), + ), + body: Padding( + padding: const EdgeInsets.only(left: 12.0, right: 12), + child: ListView( + children: [ + trackingIDBox, + SizedBox( + height: 10, + ), + remarkBox, + img, + SizedBox( + height: 10, + ), + fcsIDBox, + namebox, + SizedBox( + height: 20, + ), + _isNew ? createButton : updateButton, + SizedBox( + height: 10, + ), + ], + ), + ), + )); + } + + _scan() async { + PermissionStatus permission = + await PermissionHandler().checkPermissionStatus(PermissionGroup.camera); + if (permission != PermissionStatus.granted) { + Map permissions = + await PermissionHandler() + .requestPermissions([PermissionGroup.camera]); + if (permissions[PermissionGroup.camera] != PermissionStatus.granted) { + showMsgDialog(context, "Error", "Camera permission is not granted"); + return null; + } + } + + try { + String barcode = await scanBarcode(); + if (barcode != null) { + setState(() { + _trackingIDCtl.text = barcode; + }); + } + } catch (e) { + print('error: $e'); + } + } + + _save() async { + package.trackingID = _trackingIDCtl.text; + package.remark = _remarkCtl.text; + + if (package.trackingID == null || package.trackingID == "") { + showMsgDialog(context, "Error", "Invalid tracking ID!"); + return; + } + setState(() { + _isLoading = true; + }); + PackageModel packageModel = + Provider.of(context, listen: false); + try { + if (_isNew) { + await packageModel.createReceiving( + user, package, _multiImgController.getAddedFile); + } else { + package.id = widget.package.id; + await packageModel.updateReceiving( + user, + package, + _multiImgController.getAddedFile, + _multiImgController.getDeletedUrl); + } + Navigator.pop(context); + } catch (e) { + showMsgDialog(context, "Error", e.toString()); + } finally { + setState(() { + _isLoading = false; + }); + } + } +} diff --git a/lib/pages/receiving/receiving_info.dart b/lib/pages/receiving/receiving_info.dart new file mode 100644 index 0000000..ff5c12a --- /dev/null +++ b/lib/pages/receiving/receiving_info.dart @@ -0,0 +1,177 @@ +import 'package:fcs/domain/entities/package.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/main/model/main_model.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/package/model/package_model.dart'; +import 'package:fcs/pages/widgets/display_text.dart'; +import 'package:fcs/pages/widgets/fcs_id_icon.dart'; +import 'package:fcs/pages/widgets/local_button.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/multi_img_controller.dart'; +import 'package:fcs/pages/widgets/multi_img_file.dart'; +import 'package:fcs/pages/widgets/progress.dart'; +import 'package:fcs/pages/widgets/status_tree.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_icons/flutter_icons.dart'; +import 'package:intl/intl.dart'; +import 'package:provider/provider.dart'; + +import 'receiving_editor.dart'; + +final DateFormat dateFormat = DateFormat("d MMM yyyy"); + +class ReceivingInfo extends StatefulWidget { + final Package package; + ReceivingInfo({this.package}); + + @override + _ReceivingInfoState createState() => _ReceivingInfoState(); +} + +class _ReceivingInfoState extends State { + Package _package; + bool _isLoading = false; + MultiImgController multiImgController = MultiImgController(); + + @override + void initState() { + super.initState(); + initPackage(widget.package); + } + + initPackage(Package package) { + multiImgController.setImageUrls = package.photoUrls; + setState(() { + _package = package; + }); + } + + @override + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + bool isCustomer = Provider.of(context).isCustomer(); + + final trackingIdBox = DisplayText( + text: _package.trackingID, + labelTextKey: "package.tracking.id", + iconData: MaterialCommunityIcons.barcode_scan, + ); + var fcsIDBox = DisplayText( + text: _package.fcsID, + labelTextKey: "processing.fcs.id", + icon: FcsIDIcon(), + ); + final customerNameBox = DisplayText( + text: _package.userName, + labelTextKey: "package.create.name", + iconData: Icons.perm_identity, + ); + final remarkBox = DisplayText( + text: _package.remark ?? "-", + labelTextKey: "package.edit.remark", + iconData: Entypo.new_message, + ); + final img = MultiImageFile( + enabled: false, + controller: multiImgController, + title: "Receipt File", + ); + + return LocalProgress( + inAsyncCall: _isLoading, + child: Scaffold( + appBar: AppBar( + centerTitle: true, + leading: new IconButton( + icon: new Icon(CupertinoIcons.back, color: primaryColor, size: 30), + onPressed: () => Navigator.of(context).pop(), + ), + shadowColor: Colors.transparent, + backgroundColor: Colors.white, + title: LocalText( + context, + "receiving.info", + fontSize: 20, + color: primaryColor, + ), + actions: isCustomer + ? null + : [ + IconButton( + icon: Icon(Icons.delete, color: primaryColor), + onPressed: _delete, + ), + IconButton( + icon: Icon(Icons.edit, color: primaryColor), + onPressed: _edit, + ) + ], + ), + body: Card( + child: Column( + children: [ + Expanded( + child: Padding( + padding: const EdgeInsets.all(10.0), + child: ListView(children: [ + trackingIdBox, + fcsIDBox, + customerNameBox, + remarkBox, + _package.photoUrls.length == 0 ? Container() : img, + StatusTree( + shipmentHistory: _package.shipmentHistory, + currentStatus: _package.status), + SizedBox( + height: 20, + ) + ]), + )), + ], + ), + ), + ), + ); + } + + _edit() async { + await Navigator.push( + context, + CupertinoPageRoute( + builder: (context) => ReceivingEditor( + package: widget.package, + )), + ); + PackageModel packageModel = + Provider.of(context, listen: false); + var pkg = await packageModel.getPackage(widget.package.id); + initPackage(pkg); + } + + _delete() { + showConfirmDialog(context, "receiving.delete.confirm", _deleteReceiving); + } + + _deleteReceiving() async { + setState(() { + _isLoading = true; + }); + try { + PackageModel packageModel = + Provider.of(context, listen: false); + await packageModel.deleteReceiving(_package); + Navigator.pop(context); + } catch (e) { + showMsgDialog(context, "Error", e.toString()); + } finally { + setState(() { + _isLoading = false; + }); + } + } +} diff --git a/lib/fcs/common/pages/package/package_list.dart b/lib/pages/receiving/receiving_list.dart similarity index 64% rename from lib/fcs/common/pages/package/package_list.dart rename to lib/pages/receiving/receiving_list.dart index ce6eee7..4d6ecee 100644 --- a/lib/fcs/common/pages/package/package_list.dart +++ b/lib/pages/receiving/receiving_list.dart @@ -1,31 +1,31 @@ -import 'package:fcs/fcs/common/domain/entities/package.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/fcs/common/localization/app_translations.dart'; -import 'package:fcs/fcs/common/pages/model/main_model.dart'; -import 'package:fcs/fcs/common/pages/package/model/package_model.dart'; -import 'package:fcs/fcs/common/pages/package/package_info.dart'; -import 'package:fcs/fcs/common/pages/package/package_list_row.dart'; -import 'package:fcs/fcs/common/pages/package/package_new.dart'; -import 'package:fcs/fcs/common/pages/package_search/package_serach.dart'; -import 'package:fcs/fcs/common/pages/user_search/user_serach.dart'; -import 'package:fcs/fcs/common/pages/widgets/bottom_up_page_route.dart'; -import 'package:fcs/fcs/common/pages/widgets/local_text.dart'; -import 'package:fcs/fcs/common/pages/widgets/progress.dart'; +import 'package:fcs/domain/entities/package.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/main/model/main_model.dart'; +import 'package:fcs/pages/package/model/package_model.dart'; +import 'package:fcs/pages/package_search/package_serach.dart'; +import 'package:fcs/pages/widgets/bottom_up_page_route.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/progress.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -class PackageList extends StatefulWidget { +import 'receiving_info.dart'; +import 'receiving_list_row.dart'; +import 'receiving_editor.dart'; + +class ReceivingList extends StatefulWidget { @override - _PackageListState createState() => _PackageListState(); + _ReceivingListState createState() => _ReceivingListState(); } -class _PackageListState extends State { +class _ReceivingListState extends State { bool _isLoading = false; @override void initState() { super.initState(); + Provider.of(context, listen: false).initData(false); } @override @@ -50,7 +50,7 @@ class _PackageListState extends State { backgroundColor: primaryColor, title: LocalText( context, - "package.title", + "receiving.title", fontSize: 20, color: Colors.white, ), @@ -72,23 +72,23 @@ class _PackageListState extends State { ? Container() : FloatingActionButton.extended( onPressed: () { - _newPackage(); + _newReceiving(); }, icon: Icon(Icons.add), - label: Text( - AppTranslations.of(context).text("package.create.title")), + label: + LocalText(context, "receiving.new", color: Colors.white), backgroundColor: primaryColor, ), body: new ListView.separated( separatorBuilder: (context, index) => Divider( color: Colors.black, + height: 1, ), scrollDirection: Axis.vertical, - padding: EdgeInsets.only(top: 15), shrinkWrap: true, itemCount: packageModel.packages.length, itemBuilder: (BuildContext context, int index) { - return PackageListRow( + return ReceivingListRow( key: ValueKey(packageModel.packages[index].id), package: packageModel.packages[index], ); @@ -96,10 +96,10 @@ class _PackageListState extends State { ); } - _newPackage() { + _newReceiving() { Navigator.push( context, - BottomUpPageRoute(PackageNew()), + CupertinoPageRoute(builder: (context) => ReceivingEditor()), ); } @@ -109,7 +109,8 @@ class _PackageListState extends State { if (_package == null) return; Navigator.push( context, - BottomUpPageRoute(PackageInfo(package: _package)), + CupertinoPageRoute( + builder: (context) => ReceivingInfo(package: _package)), ); } } diff --git a/lib/fcs/common/pages/package/package_list_row.dart b/lib/pages/receiving/receiving_list_row.dart similarity index 67% rename from lib/fcs/common/pages/package/package_list_row.dart rename to lib/pages/receiving/receiving_list_row.dart index 7cf0f61..d7a4393 100644 --- a/lib/fcs/common/pages/package/package_list_row.dart +++ b/lib/pages/receiving/receiving_list_row.dart @@ -1,36 +1,40 @@ -import 'package:fcs/fcs/common/domain/entities/package.dart'; -import 'package:fcs/fcs/common/pages/package/package_info.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/fcs/common/pages/widgets/bottom_up_page_route.dart'; +import 'package:fcs/domain/entities/package.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_icons/flutter_icons.dart'; import 'package:intl/intl.dart'; +import 'receiving_info.dart'; + typedef CallbackPackageSelect(Package package); -class PackageListRow extends StatelessWidget { +class ReceivingListRow extends StatelessWidget { final Package package; final CallbackPackageSelect callbackPackageSelect; final double dotSize = 15.0; final DateFormat dateFormat = new DateFormat("dd MMM yyyy"); - PackageListRow({Key key, this.package, this.callbackPackageSelect}) + ReceivingListRow({Key key, this.package, this.callbackPackageSelect}) : super(key: key); @override Widget build(BuildContext context) { - return Container( - padding: EdgeInsets.only(left: 15, right: 15), - child: InkWell( - onTap: () { - if (callbackPackageSelect != null) { - callbackPackageSelect(package); - return; - } - Navigator.push( - context, - BottomUpPageRoute(PackageInfo(package: package)), - ); - }, + return InkWell( + onTap: () { + if (callbackPackageSelect != null) { + callbackPackageSelect(package); + return; + } + Navigator.push( + context, + CupertinoPageRoute( + builder: (context) => ReceivingInfo(package: package)), + ); + }, + child: Container( + padding: EdgeInsets.only(left: 15, right: 15), child: Row( children: [ Expanded( @@ -38,6 +42,12 @@ class PackageListRow extends StatelessWidget { padding: const EdgeInsets.symmetric(vertical: 16.0), child: new Row( children: [ + Padding( + padding: EdgeInsets.all(5.0), + child: Icon( + MaterialCommunityIcons.inbox_arrow_down, + color: primaryColor, + )), new Expanded( child: new Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -69,7 +79,7 @@ class PackageListRow extends StatelessWidget { children: [ Padding( padding: const EdgeInsets.all(3.0), - child: getStatus(package.currentStatus), + child: getStatus(package.status), ), Padding( padding: const EdgeInsets.all(0), diff --git a/lib/pages/report_user_editor.dart b/lib/pages/report_user_editor.dart deleted file mode 100644 index d3999d0..0000000 --- a/lib/pages/report_user_editor.dart +++ /dev/null @@ -1,260 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/language_model.dart'; -import 'package:fcs/model/report_user_model.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/report.dart'; -import 'package:fcs/vo/report_user.dart'; -import 'package:fcs/vo/user.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:fcs/widget/progress.dart'; -import '../fcs/common/pages/util.dart'; - -typedef void FindCallBack(); - -class ReportUserEditor extends StatefulWidget { - final Report report; - const ReportUserEditor({this.report}); - @override - _ReportUserEditorState createState() => _ReportUserEditorState(); -} - -class _ReportUserEditorState extends State { - TextEditingController _name = new TextEditingController(); - TextEditingController _searchInput = new TextEditingController(); - final GlobalKey _scaffoldKey = new GlobalKey(); - - bool _isLoading = false; - bool isSend = false; - User selectedUser; - List _users = []; - int selectedIndex; - - @override - void initState() { - super.initState(); - } - - Widget searchInputBox(BuildContext context, FindCallBack findCallBack) { - var languageModel = Provider.of(context); - return Container( - padding: EdgeInsets.only(top: 10, left: 15, right: 15), - child: Stack( - alignment: const Alignment(1.2, 1.0), - children: [ - TextFormField( - controller: _searchInput, - autofocus: false, - cursorColor: primaryColor, - style: textStyle, - decoration: new InputDecoration( - labelText: - AppTranslations.of(context).text('report.user.search'), - labelStyle: languageModel.isEng ? labelStyle : labelStyleMM, - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - ), - ), - new FlatButton( - onPressed: () { - findCallBack(); - }, - child: new Icon( - Icons.search, - size: 25, - )) - ], - )); - } - - @override - Widget build(BuildContext context) { - final namebox = Container( - padding: EdgeInsets.only(left: 10, top: 10), - child: TextFormField( - controller: _name, - autofocus: false, - readOnly: true, - cursorColor: primaryColor, - decoration: new InputDecoration( - border: InputBorder.none, - focusedBorder: InputBorder.none, - icon: Icon( - Icons.person, - color: primaryColor, - ), - ), - ), - ); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - key: _scaffoldKey, - appBar: AppBar( - backgroundColor: primaryColor, - title: LocalText(context, "user.title", - fontSize: 20, color: Colors.white), - actions: [ - IconButton( - icon: Icon( - Icons.save, - color: Colors.white, - ), - onPressed: () { - _save(context); - }) - ], - ), - body: Column( - children: [ - Expanded( - child: ListView( - shrinkWrap: true, - children: [ - searchInputBox(context, () => _findUser(context)), - this.isSend ? namebox : Container(), - Container( - padding: EdgeInsets.only( - top: this.isSend ? 10 : 20, left: 20, right: 20), - child: Column( - children: _getUsers(context), - ), - ), - ], - ), - ), - SizedBox( - height: 20, - ) - ], - )), - ); - } - - _findUser(BuildContext context) async { - var reportUserModel = Provider.of(context); - if (_searchInput.text == '') { - showMsgDialog(context, "Error", 'Please fill the search field'); - } - setState(() { - _isLoading = true; - }); - - try { - List users = await reportUserModel.findUser(_searchInput.text); - if (users.isEmpty) return; - setState(() { - this._users = users; - }); - } catch (e) { - setState(() { - this.isSend = false; - }); - showMsgDialog(context, "Error", e.toString()); - } finally { - setState(() { - _isLoading = false; - }); - } - } - - List _getUsers(BuildContext context) { - return _users.asMap().entries.map((u) { - return Container( - child: Card( - elevation: 10, - color: Colors.white, - child: InkWell( - onTap: () { - setState(() { - this.selectedUser = u.value; - isSend = true; - _name.text = selectedUser.name; - selectedIndex = u.key; - }); - }, - child: Row( - children: [ - Expanded( - child: new Padding( - padding: const EdgeInsets.symmetric(vertical: 5.0), - child: new Row( - children: [ - new Padding( - padding: new EdgeInsets.symmetric( - horizontal: 32.0 - 15.0 / 2), - child: Icon( - Icons.account_circle, - color: Colors.grey, - size: 50, - ), - ), - Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - u.value.name == null ? "" : u.value.name, - style: new TextStyle( - fontSize: 15.0, color: Colors.black), - ), - ], - ), - ], - ), - ), - ), - selectedIndex != null && selectedIndex == u.key - ? Container( - padding: EdgeInsets.only(right: 25), - child: Icon(Icons.check)) - : Container() - ], - ), - ), - )); - }).toList(); - } - - _save(BuildContext context) async { - var reportUserModel = Provider.of(context); - - if (selectedUser == null) return; - - setState(() { - _isLoading = true; - }); - - reportUserModel.getUsersForReport(widget.report.id).then((users) async { - if (users.any((u) => u.userID == this.selectedUser.docID)) { - setState(() { - _isLoading = false; - }); - showMsgDialog(context, "Error", 'Duplicate User'); - } else { - try { - ReportUser _reportUser = ReportUser( - userID: this.selectedUser.docID, - userName: this.selectedUser.name, - reportID: widget.report.id, - reportName: widget.report.display); - - await reportUserModel.assignUser(_reportUser); - reportUserModel.getUsersForReport(widget.report.id).then((users) { - Navigator.pop>(context, users); - }); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - setState(() { - _isLoading = false; - }); - } - } - }); - } -} diff --git a/lib/pages/report_user_list.dart b/lib/pages/report_user_list.dart deleted file mode 100644 index 2b08a3a..0000000 --- a/lib/pages/report_user_list.dart +++ /dev/null @@ -1,220 +0,0 @@ -import 'package:provider/provider.dart'; -import 'package:fcs/model/report_user_model.dart'; -import 'package:fcs/vo/report.dart'; -import 'package:fcs/vo/report_user.dart'; -import 'package:fcs/widget/local_text.dart'; - -import 'package:flutter/material.dart'; -import 'package:fcs/widget/progress.dart'; - -import '../fcs/common/helpers/theme.dart'; -import 'report_user_editor.dart'; -import '../fcs/common/pages/util.dart'; - -class ReportUserList extends StatefulWidget { - final Report report; - - const ReportUserList({Key key, this.report}) : super(key: key); - @override - _ReportUserListState createState() => _ReportUserListState(); -} - -class _ReportUserListState extends State { - Report _report = new Report(); - final double dotSize = 15.0; - bool _isLoading = false; - List _users = []; - bool isForAllUsers = false; - - @override - void initState() { - super.initState(); - - if (widget.report != null) { - this._report = widget.report; - var reportUserModel = - Provider.of(context, listen: false); - reportUserModel.getUsersForReport(this._report.id).then((users) { - if (mounted) { - setState(() { - this._users = users; - }); - } - }); - this.isForAllUsers = - widget.report.forAllUser == null ? false : widget.report.forAllUser; - } - } - - @override - Widget build(BuildContext context) { - final allUserBox = Container( - child: new ListTile( - title: new Row( - children: [ - new Checkbox( - value: isForAllUsers, - activeColor: primaryColor, - onChanged: (bool value) async { - setState(() { - _isLoading = true; - }); - try { - setState(() { - this.isForAllUsers = value; - }); - this._report.forAllUser = this.isForAllUsers; - var reportUserModel = Provider.of(context); - await reportUserModel.updateReportForAllUsers(this._report); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - setState(() { - _isLoading = false; - }); - } - }), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - new Text( - 'All Users', - style: TextStyle( - fontSize: 15.0, - ), - ), - ], - ), - ], - ))); - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - title: LocalText( - context, - 'report.users.title', - translationVariables: [this._report.display], - color: Colors.white, - fontSize: 18, - ), - ), - floatingActionButton: FloatingActionButton( - backgroundColor: primaryColor, - child: Icon(Icons.add), - onPressed: () async { - List _us = await Navigator.push( - context, - MaterialPageRoute( - builder: (context) => - ReportUserEditor(report: widget.report)), - ); - - if (_us == null) return; - setState(() { - _users.clear(); - _users.addAll(_us); - }); - }, - ), - body: ListView( - shrinkWrap: true, - children: [ - allUserBox, - Container( - padding: EdgeInsets.only(left: 10, right: 10), - child: Column( - children: _getUserRow(context), - ), - ), - SizedBox(height: 15) - ], - ), - ), - ); - } - - List _getUserRow(BuildContext context) { - _users.sort((a, b) => a.userName.compareTo(b.userName)); - return _users.map((u) { - return Container( - child: Card( - elevation: 10, - color: Colors.white, - child: InkWell( - onTap: () {}, - child: Row( - children: [ - Expanded( - child: new Padding( - padding: const EdgeInsets.symmetric(vertical: 10.0), - child: new Row( - children: [ - new Padding( - padding: new EdgeInsets.symmetric( - horizontal: 32.0 - dotSize / 2), - child: Icon( - Icons.account_circle, - color: primaryColor, - size: 50, - ), - ), - Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - u.userName == null ? "" : u.userName, - style: new TextStyle( - fontSize: 17.0, color: Colors.black), - ), - ], - ), - ], - ), - ), - ), - IconButton( - padding: EdgeInsets.only(right: 10), - icon: Icon( - Icons.delete, - color: Colors.grey[700], - ), - onPressed: () { - showConfirmDialog(context, "report.user_delete_confirm", - () { - _delete(context, u); - }); - }) - ], - ), - ), - )); - }).toList(); - } - - void _delete(BuildContext context, ReportUser reportUser) async { - setState(() { - _isLoading = true; - }); - try { - var reportUserModel = Provider.of(context); - await reportUserModel.deleteReportUser(reportUser); - - reportUserModel.getUsersForReport(widget.report.id).then((users) { - if (mounted) { - setState(() { - this._users = users; - }); - } - }); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - setState(() { - _isLoading = false; - }); - } - } -} diff --git a/lib/pages/reset_password.dart b/lib/pages/reset_password.dart deleted file mode 100644 index a1eed65..0000000 --- a/lib/pages/reset_password.dart +++ /dev/null @@ -1,368 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/language_model.dart'; -import 'package:fcs/model/user_model.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/localization/app_translations.dart'; -import 'package:fcs/widget/progress.dart'; - -import '../fcs/common/helpers/theme.dart' as Theme; -import '../fcs/common/pages/util.dart'; - -class ResetPasswordPage extends StatefulWidget { - final String phoneNumber; - ResetPasswordPage( - this.phoneNumber, { - Key key, - }) : super(key: key); - - @override - _ResetPasswordPageState createState() => new _ResetPasswordPageState(); -} - -class _ResetPasswordPageState extends State - with SingleTickerProviderStateMixin { - final GlobalKey _scaffoldKey = new GlobalKey(); - - final FocusNode myFocusNodePassword = FocusNode(); - final FocusNode myFocusNodeEmail = FocusNode(); - - bool _obscureTextLogin = true; - bool _obscureTextSignup = true; - bool _obscureTextSignupConfirm = true; - - TextEditingController _smsController = new TextEditingController(); - TextEditingController _passwordController = new TextEditingController(); - TextEditingController _confirmPasswordController = - new TextEditingController(); - final formKey = GlobalKey(); - bool _isLoading = false; - - @override - Widget build(BuildContext context) { - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - key: _scaffoldKey, - body: SingleChildScrollView( - child: Container( - width: MediaQuery.of(context).size.width, - height: MediaQuery.of(context).size.height >= 775.0 - ? MediaQuery.of(context).size.height - : 580.0, - child: Column( - mainAxisSize: MainAxisSize.max, - children: [ - Padding( - padding: EdgeInsets.only(top: 35.0, bottom: 10), - child: ListTile( - leading: IconButton( - icon: Icon(Icons.arrow_back), - onPressed: () { - Navigator.of(context).pop(); - }, - ), - title: LocalText( - context, - 'reset.password.title', - color: Colors.black87, - fontSize: 17, - ), - ), - ), - Expanded( - flex: 2, - child: PageView( - children: [ - new ConstrainedBox( - constraints: const BoxConstraints.expand(), - child: _buildReset(context), - ), - ], - ), - ), - ], - ), - ), - ), - ), - ); - } - - @override - void dispose() { - myFocusNodePassword.dispose(); - myFocusNodeEmail.dispose(); - super.dispose(); - } - - @override - void initState() { - super.initState(); - - // SystemChrome.setPreferredOrientations([ - // DeviceOrientation.portraitUp, - // DeviceOrientation.portraitDown, - // ]); - - _smsController.text = ""; - } - - Widget _buildReset(BuildContext context) { - return Container( - child: ListView( - children: [ - Column( - children: [ - Form( - key: formKey, - child: Card( - elevation: 2.0, - color: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - child: Container( - width: 300.0, - child: Column( - children: [ - Padding( - padding: EdgeInsets.only(left: 25.0, right: 25.0), - child: TextFormField( - focusNode: myFocusNodeEmail, - controller: _smsController, - keyboardType: TextInputType.phone, - style: TextStyle( - fontFamily: "WorkSansSemiBold", - fontSize: 16.0, - color: Colors.black), - decoration: InputDecoration( - border: InputBorder.none, - icon: Icon( - FontAwesomeIcons.sms, - color: Colors.black, - ), - labelText: AppTranslations.of(context) - .text("reset.sms"), - labelStyle: - Provider.of(context).isEng - ? TextStyle( - fontFamily: "WorkSansSemiBold", - color: Colors.grey) - : TextStyle( - fontFamily: "MyanmarUnicode", - color: Colors.grey), - ), - validator: _validateSMSCode), - ), - Container( - width: 250.0, - height: 1.0, - color: Colors.grey[400], - ), - Padding( - padding: EdgeInsets.only(left: 25.0, right: 25.0), - child: TextFormField( - focusNode: myFocusNodePassword, - controller: _passwordController, - obscureText: _obscureTextSignup, - style: TextStyle( - fontFamily: "WorkSansSemiBold", - fontSize: 16.0, - color: Colors.black), - decoration: InputDecoration( - border: InputBorder.none, - icon: Icon( - FontAwesomeIcons.lock, - color: Colors.black, - ), - labelText: AppTranslations.of(context) - .text("reset.new_password"), - labelStyle: - Provider.of(context).isEng - ? TextStyle( - fontFamily: "WorkSansSemiBold", - color: Colors.grey) - : TextStyle( - fontFamily: "MyanmarUnicode", - color: Colors.grey), - suffixIcon: GestureDetector( - onTap: _toggleSignup, - child: Icon( - _obscureTextSignup - ? FontAwesomeIcons.eye - : FontAwesomeIcons.eyeSlash, - size: 15.0, - color: Colors.black, - ), - ), - ), - validator: _validatePassword, - ), - ), - Container( - width: 250.0, - height: 1.0, - color: Colors.grey[400], - ), - Padding( - padding: EdgeInsets.only(left: 25.0, right: 25.0), - child: TextFormField( - controller: _confirmPasswordController, - obscureText: _obscureTextSignupConfirm, - style: TextStyle( - fontFamily: "WorkSansSemiBold", - fontSize: 16.0, - color: Colors.black), - decoration: InputDecoration( - border: InputBorder.none, - icon: Icon( - FontAwesomeIcons.lock, - color: Colors.black, - ), - labelText: AppTranslations.of(context) - .text("login.confirm_password"), - labelStyle: - Provider.of(context).isEng - ? TextStyle( - fontFamily: "WorkSansSemiBold", - color: Colors.grey) - : TextStyle( - fontFamily: "MyanmarUnicode", - color: Colors.grey), - suffixIcon: GestureDetector( - onTap: _toggleSignupConfirm, - child: Icon( - _obscureTextSignupConfirm - ? FontAwesomeIcons.eye - : FontAwesomeIcons.eyeSlash, - size: 15.0, - color: Colors.black, - ), - ), - ), - validator: _validateConfirmPassword, - ), - ), - ], - ), - ), - ), - ), - Container( - // margin: EdgeInsets.only(top: 320.0), - decoration: new BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(5.0)), - color: Theme.primaryColor, - ), - child: MaterialButton( - highlightColor: Colors.transparent, - splashColor: Theme.LoginColors.loginGradientEnd, - //shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(5.0))), - child: Padding( - padding: const EdgeInsets.symmetric( - vertical: 10.0, horizontal: 42.0), - child: Text( - AppTranslations.of(context).text("reset"), - style: Provider.of(context).isEng - ? TextStyle( - color: Colors.white, - fontSize: 18.0, - fontFamily: "WorkSansBold") - : TextStyle( - color: Colors.white, - fontSize: 18.0, - fontFamily: "MyanmarUnicode"), - ), - ), - onPressed: () => _reset(context)), - ), - ], - ), - ], - ), - ); - } - - void _toggleLogin() { - setState(() { - _obscureTextLogin = !_obscureTextLogin; - }); - } - - void _toggleSignup() { - setState(() { - _obscureTextSignup = !_obscureTextSignup; - }); - } - - void _toggleSignupConfirm() { - setState(() { - _obscureTextSignupConfirm = !_obscureTextSignupConfirm; - }); - } - - void _reset(BuildContext context) async { - if (!formKey.currentState.validate()) { - return; - } - - var smsCode = _smsController.text; - var password = _passwordController.text; - - setState(() { - _isLoading = true; - }); - - UserModel userModel = Provider.of(context); - try { - await userModel.resetPassword(widget.phoneNumber, password, smsCode); - Navigator.pushNamedAndRemoveUntil(context, "/login", (r) => false); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - Future.delayed(Duration(seconds: 1), () { - if (mounted) { - setState(() { - _isLoading = false; - }); - } - }); - } - } - - String _validatePassword(value) { - if (value.isEmpty) { - return AppTranslations.of(context).text("login.password_empty"); - } - if (value.length < 6) { - return AppTranslations.of(context).text("login.password_size"); - } - return null; - } - - String _validateConfirmPassword(value) { - if (value.isEmpty) { - return AppTranslations.of(context).text("login.confirm_password_empty"); - } - if (value.length < 6) { - return AppTranslations.of(context).text("login.password_size"); - } - if (value != _passwordController.text) { - return AppTranslations.of(context).text("login.password_mismatch"); - } - return null; - } - - String _validateSMSCode(value) { - if (value.isEmpty) { - return AppTranslations.of(context).text("login.sms_empty"); - } - if (value.length != 6) { - return AppTranslations.of(context).text("login.sms_size"); - } - return null; - } -} diff --git a/lib/pages/search_page.dart b/lib/pages/search_page.dart deleted file mode 100644 index 459c9f0..0000000 --- a/lib/pages/search_page.dart +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/buyer_model.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/buyer.dart'; - -import 'buyer_list_row.dart'; - -Future showPlacesSearch(BuildContext context) async => - await showSearch( - context: context, - delegate: UserSearchDelegate(), - ); - -class UserSearchDelegate extends SearchDelegate { - @override - ThemeData appBarTheme(BuildContext context) { - final ThemeData theme = Theme.of(context); - return theme.copyWith( - inputDecorationTheme: InputDecorationTheme( - hintStyle: TextStyle( - color: theme.primaryTextTheme.title.color, fontSize: 16)), - primaryColor: primaryColor, - primaryIconTheme: theme.primaryIconTheme.copyWith(color: Colors.white), - primaryColorBrightness: Brightness.light, - primaryTextTheme: theme.textTheme, - textTheme: theme.textTheme.copyWith( - title: theme.textTheme.title.copyWith( - color: theme.primaryTextTheme.title.color, fontSize: 16)), - ); - } - - @override - List buildActions(BuildContext context) { - return [ - IconButton( - icon: Icon(Icons.clear), - onPressed: () => query = '', - ), - ]; - } - - @override - Widget buildLeading(BuildContext context) { - return IconButton( - icon: Icon(Icons.arrow_back), - onPressed: () => close(context, null), - ); - } - - @override - Widget buildResults(BuildContext context) { - final buyerModel = Provider.of(context); - return FutureBuilder( - future: buyerModel.search(query), - builder: (context, AsyncSnapshot> snapshot) { - if (snapshot.hasData) { - if (snapshot.data.length == 0) { - return Container( - child: Center( - child: Text( - "Error :No Search Buyer", - textAlign: TextAlign.center, - ), - ), - ); - } - return Container( - padding: EdgeInsets.only(top: 15), - child: ListView( - children: - snapshot.data.map((u) => BuyerListRow(buyer: u)).toList(), - ), - ); - } else if (snapshot.hasError) { - return Container( - child: Center( - child: Text( - '${snapshot.error}', - textAlign: TextAlign.center, - ), - ), - ); - } else { - return Container( - child: Center( - child: CircularProgressIndicator( - valueColor: - new AlwaysStoppedAnimation(primaryColor)), - ), - ); - } - }); - } - - @override - Widget buildSuggestions(BuildContext context) { - return Container( - child: Center( - child: Opacity( - opacity: 0.2, - child: Icon( - Icons.supervised_user_circle, - size: 200, - )), - ), - ); - } -} diff --git a/lib/pages/setting_editor.dart b/lib/pages/setting_editor.dart deleted file mode 100644 index ba184c6..0000000 --- a/lib/pages/setting_editor.dart +++ /dev/null @@ -1,416 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:font_awesome_flutter/font_awesome_flutter.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/language_model.dart'; -import 'package:fcs/model/main_model.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/setting.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/progress.dart'; - -class SettingEidtor extends StatefulWidget { - final Setting setting; - const SettingEidtor({this.setting}); - @override - _SettingEidtorState createState() => _SettingEidtorState(); -} - -class _SettingEidtorState extends State { - TextEditingController _doExpire = new TextEditingController(); - TextEditingController _poExpire = new TextEditingController(); - TextEditingController _poOpend = new TextEditingController(); - TextEditingController _poClosed = new TextEditingController(); - TextEditingController _latestDeliveryDay = new TextEditingController(); - TextEditingController _firstStorageDay = new TextEditingController(); - TextEditingController _firstStorageCharge = new TextEditingController(); - TextEditingController _secondStorageDay = new TextEditingController(); - TextEditingController _secondStorgeCharge = new TextEditingController(); - - final _formKey = GlobalKey(); - bool _isLoading = false; - List days = []; - - @override - void initState() { - super.initState(); - days = dayLists; - if (widget.setting != null) { - _doExpire.text = widget.setting.doExpireInHours.toString(); - _poExpire.text = widget.setting.poExpireInHours.toString(); - _poOpend.text = widget.setting.poOpenAt.toString(); - _poClosed.text = widget.setting.poCloseAt.toString(); - _latestDeliveryDay.text = widget.setting.latestDeliveryDay.toString(); - _firstStorageDay.text = widget.setting.firstStorageChargeIn.toString(); - _firstStorageCharge.text = widget.setting.firstStorageCharge.toString(); - _secondStorageDay.text = widget.setting.secondStorageChargeIn.toString(); - _secondStorgeCharge.text = widget.setting.secondStorageCharge.toString(); - - days.forEach((d) => widget.setting.poCloseOn.contains(d.id) - ? d.isChecked = true - : d.isChecked = false); - } - } - - Widget showDayList(BuildContext context, MainModel mainModel) { - return Container( - margin: EdgeInsets.symmetric(vertical: 5.0), - height: 75.0, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: EdgeInsets.only(left: 10, top: 10), - child: Text( - "PO submission closed Day", - style: TextStyle(color: Colors.black54), - ), - ), - Expanded( - child: ListView.builder( - itemCount: days.length, - scrollDirection: Axis.horizontal, - padding: EdgeInsets.only(top: 10), - itemBuilder: (BuildContext context, int index) { - return new Row( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - new Checkbox( - value: days[index].isChecked == null - ? false - : days[index].isChecked, - activeColor: primaryColor, - onChanged: (bool value) { - setState(() { - days[index].isChecked = value; - }); - }), - Container( - padding: EdgeInsets.only(top: 13), - child: new Text( - dayLists[index].name, - style: TextStyle( - fontSize: 15.0, - ), - ), - ), - ], - ); - }), - ), - ], - ), - ); - } - - @override - Widget build(BuildContext context) { - var languageModel = Provider.of(context); - var mainModel = Provider.of(context); - - final doExpireBox = TextFormField( - controller: _doExpire, - autofocus: false, - cursorColor: primaryColor, - keyboardType: TextInputType.phone, - style: textStyle, - decoration: new InputDecoration( - labelText: 'DO expired Time', - labelStyle: languageModel.isEng ? labelStyle : labelStyleMM, - icon: Icon( - FontAwesomeIcons.clock, - color: primaryColor, - ), - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - ), - validator: (value) { - if (value.isEmpty) { - return 'Please enter DO expired Time'; - } - return null; - }, - ); - - final poExpireBox = TextFormField( - controller: _poExpire, - autofocus: false, - cursorColor: primaryColor, - keyboardType: TextInputType.phone, - style: textStyle, - decoration: new InputDecoration( - labelText: 'PO expired Time', - labelStyle: languageModel.isEng ? labelStyle : labelStyleMM, - icon: Icon( - FontAwesomeIcons.clock, - color: primaryColor, - ), - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - ), - validator: (value) { - if (value.isEmpty) { - return 'Please enter PO expired Time'; - } - return null; - }, - ); - - final poOpenedBox = TextFormField( - controller: _poOpend, - autofocus: false, - cursorColor: primaryColor, - keyboardType: TextInputType.phone, - style: textStyle, - decoration: new InputDecoration( - labelText: 'PO submission opened Time', - labelStyle: languageModel.isEng ? labelStyle : labelStyleMM, - icon: Icon( - FontAwesomeIcons.clock, - color: primaryColor, - ), - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - ), - validator: (value) { - if (value.isEmpty) { - return 'Please enter PO submission opened Time'; - } - return null; - }, - ); - - final poClosedBox = TextFormField( - controller: _poClosed, - autofocus: false, - cursorColor: primaryColor, - keyboardType: TextInputType.phone, - style: textStyle, - decoration: new InputDecoration( - labelText: 'PO submission closed Time', - labelStyle: languageModel.isEng ? labelStyle : labelStyleMM, - icon: Icon( - FontAwesomeIcons.clock, - color: primaryColor, - ), - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - ), - validator: (value) { - if (value.isEmpty) { - return 'Please enter PO submission closed Time'; - } - return null; - }, - ); - - final latestDeliveryDayBox = TextFormField( - controller: _latestDeliveryDay, - autofocus: false, - cursorColor: primaryColor, - keyboardType: TextInputType.phone, - style: textStyle, - decoration: new InputDecoration( - labelText: 'Latest Delivery Day', - labelStyle: languageModel.isEng ? labelStyle : labelStyleMM, - icon: Icon( - FontAwesomeIcons.clock, - color: primaryColor, - ), - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - ), - validator: (value) { - if (value.isEmpty) { - return 'Please enter Latest Delivery Day'; - } - return null; - }, - ); - - final firstStorageDayBox = TextFormField( - controller: _firstStorageDay, - autofocus: false, - cursorColor: primaryColor, - keyboardType: TextInputType.phone, - style: textStyle, - decoration: new InputDecoration( - labelText: 'First storage charge starts Day', - labelStyle: languageModel.isEng ? labelStyle : labelStyleMM, - icon: Icon( - FontAwesomeIcons.calendarDay, - color: primaryColor, - ), - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - ), - validator: (value) { - if (value.isEmpty) { - return 'Please enter First storage charge starts Day'; - } - return null; - }, - ); - - final firstStorgeChargeBox = TextFormField( - controller: _firstStorageCharge, - autofocus: false, - cursorColor: primaryColor, - keyboardType: TextInputType.phone, - style: textStyle, - decoration: new InputDecoration( - labelText: 'First storage charge Fees', - labelStyle: languageModel.isEng ? labelStyle : labelStyleMM, - icon: Icon( - FontAwesomeIcons.sortNumericUp, - color: primaryColor, - ), - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - ), - validator: (value) { - if (value.isEmpty) { - return 'Please enter First storage charge Fees'; - } - return null; - }, - ); - - final secondStorgeDayBox = TextFormField( - controller: _secondStorageDay, - autofocus: false, - cursorColor: primaryColor, - keyboardType: TextInputType.phone, - style: textStyle, - decoration: new InputDecoration( - labelText: 'Second storage charge starts Day', - labelStyle: languageModel.isEng ? labelStyle : labelStyleMM, - icon: Icon( - FontAwesomeIcons.calendarDay, - color: primaryColor, - ), - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - ), - validator: (value) { - if (value.isEmpty) { - return 'Please enter Second storage charge starts Day'; - } - return null; - }, - ); - - final secondStorgeChargeBox = TextFormField( - controller: _secondStorgeCharge, - autofocus: false, - cursorColor: primaryColor, - keyboardType: TextInputType.phone, - style: textStyle, - decoration: new InputDecoration( - labelText: 'Second storage charge Fees', - labelStyle: languageModel.isEng ? labelStyle : labelStyleMM, - icon: Icon( - FontAwesomeIcons.sortNumericUp, - color: primaryColor, - ), - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor, width: 1.0)), - ), - validator: (value) { - if (value.isEmpty) { - return 'Please enter Second storage charge Fees'; - } - return null; - }, - ); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - title: LocalText( - context, - "setting.title", - fontSize: 20, - color: Colors.white, - ), - actions: [ - IconButton( - icon: Icon(Icons.send), - onPressed: () { - if (!_formKey.currentState.validate()) return; - showConfirmDialog(context, "setting.confirm", () { - _submit(); - }); - }) - ], - ), - body: Form( - key: _formKey, - child: ListView( - shrinkWrap: true, - padding: EdgeInsets.only(left: 24.0, right: 24.0), - children: [ - // doExpireBox, - poExpireBox, - poOpenedBox, - poClosedBox, - showDayList(context, mainModel), - latestDeliveryDayBox, - firstStorageDayBox, - firstStorgeChargeBox, - secondStorgeDayBox, - secondStorgeChargeBox - ], - ), - ), - )); - } - - _submit() async { - setState(() { - _isLoading = true; - }); - try { - widget.setting.poExpireInHours = int.parse(_poExpire.text); - widget.setting.poOpenAt = int.parse(_poOpend.text); - widget.setting.poCloseAt = int.parse(_poClosed.text); - widget.setting.latestDeliveryDay = int.parse(_latestDeliveryDay.text); - widget.setting.firstStorageChargeIn = int.parse(_firstStorageDay.text); - widget.setting.firstStorageCharge = int.parse(_firstStorageCharge.text); - widget.setting.secondStorageChargeIn = int.parse(_secondStorageDay.text); - widget.setting.secondStorageCharge = int.parse(_secondStorgeCharge.text); - widget.setting.poCloseOn = - this.days.where((d) => d.isChecked == true).map((p) => p.id).toList(); - var mainModel = Provider.of(context); - await mainModel.updateSetting(widget.setting); - Navigator.pop(context); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - setState(() { - _isLoading = false; - }); - } - } -} diff --git a/lib/pages/setting_editor_byOwner.dart b/lib/pages/setting_editor_byOwner.dart deleted file mode 100644 index 54af0e8..0000000 --- a/lib/pages/setting_editor_byOwner.dart +++ /dev/null @@ -1,256 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:fcs/model/main_model.dart'; -import 'package:fcs/fcs/common/pages/util.dart'; -import 'package:fcs/fcs/common/helpers/theme.dart'; -import 'package:fcs/vo/setting.dart'; -import 'package:fcs/widget/local_text.dart'; -import 'package:fcs/widget/progress.dart'; - -class Time { - final int value; - Time(this.value); - String get getValue => - value > 12 ? (value - 12).toString() + "PM" : value.toString() + "AM"; - - @override - bool operator ==(other) { - if (identical(this, other)) { - return true; - } - return other.value == this.value; - } - - @override - int get hashCode { - int result = 17; - result = 37 * result + value.hashCode; - return result; - } -} - -class SettingOwner extends StatefulWidget { - final Setting setting; - const SettingOwner({this.setting}); - @override - _SettingOwnerState createState() => _SettingOwnerState(); -} - -class _SettingOwnerState extends State { - final _formKey = GlobalKey(); - bool _isLoading = false; - List days = []; - int poOpenAt = 0; - int poCloseAt = 0; - - @override - void initState() { - super.initState(); - days = dayLists; - if (widget.setting != null) { - poOpenAt = widget.setting.poOpenAt; - poCloseAt = widget.setting.poCloseAt; - days.forEach((d) => widget.setting.poCloseOn.contains(d.id) - ? d.isChecked = true - : d.isChecked = false); - } - } - - Widget showDayList(BuildContext context, MainModel mainModel) { - return Container( - margin: EdgeInsets.symmetric(vertical: 5.0), - height: 500.0, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: EdgeInsets.only(left: 10, top: 10), - child: Text( - "PO submission closed Day", - style: TextStyle(color: Colors.black54), - ), - ), - Expanded( - child: ListView.builder( - itemCount: days.length, - scrollDirection: Axis.vertical, - padding: EdgeInsets.only(top: 10), - itemBuilder: (BuildContext context, int index) { - return new Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - new Checkbox( - value: days[index].isChecked == null - ? false - : days[index].isChecked, - activeColor: primaryColor, - onChanged: (bool value) { - setState(() { - days[index].isChecked = value; - }); - }), - Container( - padding: EdgeInsets.only(top: 13), - child: new Text( - dayLists[index].name, - style: TextStyle( - fontSize: 15.0, - ), - ), - ), - ], - ); - }), - ), - ], - ), - ); - } - - @override - Widget build(BuildContext context) { - var mainModel = Provider.of(context); - - return LocalProgress( - inAsyncCall: _isLoading, - child: Scaffold( - appBar: AppBar( - backgroundColor: primaryColor, - title: LocalText( - context, - "setting.title", - fontSize: 20, - color: Colors.white, - ), - actions: [ - IconButton( - icon: Icon(Icons.send), - onPressed: () { - if (!_formKey.currentState.validate()) return; - showConfirmDialog(context, "setting.confirm", () { - _submit(); - }); - }) - ], - ), - body: ListView( - children: [ - Padding( - padding: const EdgeInsets.only(left: 24), - child: Row( - children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: Text("PO submission opened at:"), - ), - getDropDown(poOpenAt, (value) { - setState(() { - setState(() { - this.poOpenAt = value; - }); - }); - }), - ], - ), - ), - Padding( - padding: const EdgeInsets.only(left: 24), - child: Row( - children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: Text("PO submission closed at:"), - ), - getDropDown(poCloseAt, (value) { - setState(() { - setState(() { - this.poCloseAt = value; - }); - }); - }), - ], - ), - ), - Form( - key: _formKey, - child: ListView( - shrinkWrap: true, - padding: EdgeInsets.only(left: 24.0, right: 24.0), - children: [ - showDayList(context, mainModel), - ], - ), - ), - ], - ), - )); - } - - Widget getDropDown(int initial, Function(int) onChanged) { - Time value = Time(initial); - return DropdownButton