mirror of
https://github.com/SyncrowIOT/syncrow-app.git
synced 2026-10-23 10:37:56 +00:00
@@ -0,0 +1,47 @@
|
||||
<svg width="201" height="260" viewBox="0 0 201 260" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g filter="url(#filter0_d_3851_4852)">
|
||||
<g filter="url(#filter1_i_3851_4852)">
|
||||
<path d="M1 32.5794C1 17.65 11.9782 4.87264 26.8261 3.31376C56.9938 0.146434 80.4127 0.288676 110.23 3.38644C125.15 4.93649 136.229 17.743 136.229 32.7433V219.157C136.229 233.932 125.474 246.635 110.8 248.355C80.8281 251.869 57.0283 251.901 26.4597 248.336C11.7726 246.623 1 233.917 1 219.131V32.5794Z" fill="#EAF6FF"/>
|
||||
</g>
|
||||
<path d="M116.627 154.669C117.475 154.669 118.323 154.345 118.971 153.698C120.266 152.403 120.266 150.304 118.971 149.009C107.888 137.927 107.888 119.894 118.971 108.812C120.266 107.517 120.266 105.418 118.971 104.123C117.676 102.829 115.577 102.829 114.283 104.123C100.615 117.792 100.615 140.03 114.283 153.698C114.93 154.345 115.778 154.669 116.627 154.669Z" fill="#B3DAFE"/>
|
||||
<path d="M123.6 141.79C124.312 141.79 125.024 141.518 125.567 140.975C126.653 139.889 126.653 138.127 125.566 137.041C123.395 134.87 122.199 131.982 122.199 128.911C122.199 125.839 123.395 122.952 125.566 120.78C126.653 119.694 126.653 117.933 125.567 116.847C124.48 115.76 122.719 115.76 121.633 116.846C118.411 120.069 116.636 124.353 116.636 128.911C116.636 133.468 118.41 137.753 121.633 140.975C122.176 141.518 122.888 141.79 123.6 141.79Z" fill="#B3DAFE"/>
|
||||
<path d="M74.4947 201.887L74.4947 214.513C74.4947 217.026 72.4581 219.063 69.9447 219.063C67.4313 219.063 65.3948 217.026 65.3948 214.513L65.3948 201.887C65.3948 199.374 67.4313 197.337 69.9447 197.337C72.4581 197.337 74.4947 199.374 74.4947 201.887Z" fill="#B3DAFE"/>
|
||||
<g filter="url(#filter2_i_3851_4852)">
|
||||
<path d="M146.229 60.2459C146.229 53.612 150.555 47.5909 157.072 46.3483C165.305 44.7783 172.168 44.839 180.304 46.382C186.889 47.6306 191.305 53.6871 191.305 60.3888V203.89C191.305 210.378 187.172 216.307 180.833 217.686C172.408 219.518 165.306 219.531 156.73 217.674C150.379 216.299 146.229 210.366 146.229 203.867V60.2459Z" fill="#EAF6FF"/>
|
||||
</g>
|
||||
<path d="M162.423 103.153C161.575 103.153 160.727 103.476 160.079 104.124C158.784 105.419 158.784 107.517 160.079 108.812C171.162 119.894 171.162 137.927 160.079 149.009C158.784 150.305 158.784 152.403 160.079 153.698C161.374 154.992 163.473 154.992 164.767 153.698C178.435 140.03 178.435 117.791 164.767 104.123C164.12 103.476 163.272 103.153 162.423 103.153Z" fill="#B3DAFE"/>
|
||||
<path d="M155.45 116.032C154.738 116.032 154.026 116.303 153.483 116.847C152.397 117.933 152.397 119.694 153.484 120.78C155.655 122.952 156.851 125.839 156.851 128.911C156.851 131.982 155.655 134.869 153.484 137.041C152.397 138.128 152.397 139.889 153.483 140.975C154.57 142.061 156.331 142.061 157.417 140.975C160.639 137.753 162.414 133.468 162.414 128.911C162.414 124.353 160.64 120.069 157.417 116.846C156.874 116.304 156.162 116.032 155.45 116.032Z" fill="#B3DAFE"/>
|
||||
</g>
|
||||
<defs>
|
||||
<filter id="filter0_d_3851_4852" x="0" y="0" width="200.305" height="260" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset dx="4" dy="4"/>
|
||||
<feGaussianBlur stdDeviation="2.5"/>
|
||||
<feComposite in2="hardAlpha" operator="out"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.2 0"/>
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_3851_4852"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_3851_4852" result="shape"/>
|
||||
</filter>
|
||||
<filter id="filter1_i_3851_4852" x="0" y="1" width="136.229" height="250" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset dx="-1"/>
|
||||
<feGaussianBlur stdDeviation="10"/>
|
||||
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.3 0"/>
|
||||
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_3851_4852"/>
|
||||
</filter>
|
||||
<filter id="filter2_i_3851_4852" x="144.229" y="45.1975" width="47.0764" height="173.866" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset dx="-2"/>
|
||||
<feGaussianBlur stdDeviation="5"/>
|
||||
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.3 0"/>
|
||||
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_3851_4852"/>
|
||||
</filter>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.9 KiB |
@@ -0,0 +1,10 @@
|
||||
<svg width="44" height="50" viewBox="0 0 44 50" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M24.9023 9.10478C24.0934 9.10478 23.4375 8.44893 23.4375 7.63994V4.39453C23.4375 3.58682 22.7804 2.92969 21.9727 2.92969C21.1649 2.92969 20.5078 3.58682 20.5078 4.39453V7.63994C20.5078 8.44893 19.852 9.10478 19.043 9.10478C18.234 9.10478 17.5781 8.44893 17.5781 7.63994V4.39453C17.5781 1.97139 19.5495 0 21.9727 0C24.3958 0 26.3672 1.97139 26.3672 4.39453V7.63994C26.3672 8.44893 25.7113 9.10478 24.9023 9.10478Z" fill="#FFB454"/>
|
||||
<path d="M23.4375 4.39453V7.63994C23.4375 8.44893 24.0934 9.10478 24.9023 9.10478C25.7113 9.10478 26.3672 8.44893 26.3672 7.63994V4.39453C26.3672 1.97139 24.3958 0 21.9727 0V2.92969C22.7805 2.92969 23.4375 3.58682 23.4375 4.39453Z" fill="#FF8E00"/>
|
||||
<path d="M21.9727 50C17.9341 50 14.6484 46.7144 14.6484 42.6758C14.6484 41.8668 15.3043 41.2109 16.1133 41.2109H27.832C28.641 41.2109 29.2969 41.8668 29.2969 42.6758C29.2969 46.7144 26.0113 50 21.9727 50Z" fill="#FFB454"/>
|
||||
<path d="M27.832 41.2109H21.9727V50C26.0112 50 29.2969 46.7144 29.2969 42.6758C29.2969 41.8668 28.641 41.2109 27.832 41.2109Z" fill="#FF8E00"/>
|
||||
<path d="M42.4805 44.1406H1.46486C0.877946 44.1406 0.34777 43.7903 0.117497 43.2505C-0.112777 42.7106 0.00138367 42.0855 0.407634 41.6619C4.55295 37.3389 6.83595 31.6595 6.83595 25.6701V20.9961C6.83595 12.6497 13.6263 5.85938 21.9727 5.85938C30.3191 5.85938 37.1094 12.6497 37.1094 20.9961V25.6701C37.1094 31.6596 39.3924 37.3389 43.5378 41.6619C43.944 42.0855 44.0581 42.7106 43.8279 43.2505C43.5977 43.7903 43.0674 44.1406 42.4805 44.1406Z" fill="#FFE278"/>
|
||||
<path d="M42.4805 44.1406C43.0674 44.1406 43.5976 43.7903 43.8278 43.2505C44.0581 42.7106 43.9439 42.0855 43.5378 41.6619C39.3924 37.3389 37.1094 31.6595 37.1094 25.6701V20.9961C37.1094 12.6497 30.319 5.85938 21.9727 5.85938V44.1406H42.4805Z" fill="#FFB454"/>
|
||||
<path d="M42.4803 22.4612C41.6713 22.4612 41.0154 21.8053 41.0154 20.9963C41.0154 15.9097 39.0347 11.1276 35.4379 7.53091C34.8658 6.95884 34.8658 6.0314 35.4379 5.45933C36.0099 4.88726 36.9374 4.88726 37.5095 5.45933C41.6596 9.60933 43.9451 15.1272 43.9451 20.9963C43.9451 21.8053 43.2893 22.4612 42.4803 22.4612Z" fill="#08475E"/>
|
||||
<path d="M1.46484 22.4612C0.655859 22.4612 0 21.8053 0 20.9963C0 15.1272 2.28555 9.60942 6.43564 5.45933C7.00762 4.88726 7.93516 4.88726 8.50723 5.45933C9.0793 6.0314 9.0793 6.95884 8.50723 7.53091C4.91055 11.1277 2.92969 15.9098 2.92969 20.9963C2.92969 21.8053 2.27383 22.4612 1.46484 22.4612Z" fill="#0A789B"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.5 KiB |
@@ -0,0 +1,18 @@
|
||||
<svg width="50" height="50" viewBox="0 0 50 50" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.61102 32.55L0.0294905 14.2492C-0.0650406 13.9826 0.0752911 13.6874 0.341795 13.5901C8.9949 10.4779 18.7455 7.58334 27.0805 4.02691C27.453 3.79194 27.7453 4.02407 27.9057 4.46821L38.2465 31.1229L41.0545 38.9321C41.149 39.1986 41.0115 39.4967 40.745 39.5913L20.9575 46.707L13.2441 49.4811C12.9776 49.5786 12.6825 49.4381 12.5851 49.1716L6.61102 32.55Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.098 26.4772L8.81158 7.31083C8.76285 7.02997 8.95201 6.76347 9.22994 6.71474L31.8627 2.83448L37.046 1.98047C37.3297 1.85723 37.791 2.00049 37.8998 2.63389L43.4985 30.5925L44.8997 38.7715C44.9484 39.0495 44.7593 39.3189 44.4813 39.3676L23.7568 42.9212L15.6767 44.3082C15.3988 44.3541 15.1294 44.165 15.0807 43.8869L12.098 26.4772Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M18.439 20.8256V39.2527C18.439 39.5479 18.6797 39.7914 18.9748 39.7914H27.5276H40.1893H42.0088H49.4642C49.7593 39.7914 50 39.5479 50 39.2527V30.5952V6.68016V6.43085H44.556C44.0317 6.43085 42.9428 6.50536 42.9428 5.3161L42.9313 0H18.9747C18.6796 0 18.4389 0.240722 18.4389 0.535936V5.13554V7.08143V20.8256H18.439Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.35594 10.4889C6.29012 11.5206 3.25292 12.5436 0.341795 13.5896C0.0752911 13.6871 -0.0650406 13.9822 0.0294905 14.2487L6.61102 32.5497L12.5851 49.1712C12.6826 49.4377 12.9777 49.5781 13.2441 49.4807L20.9575 46.7066L38.5331 40.3875L9.35594 10.4889Z" fill="#B5C4CF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M18.4389 5.13535L9.22994 6.71435C8.95201 6.76308 8.76285 7.02958 8.81158 7.31044L9.35601 10.4886L12.0981 26.4768L15.0808 43.8864C15.1295 44.1645 15.3989 44.3535 15.6768 44.3077L23.7569 42.9207L38.5331 40.3873L42.0087 39.7912H40.1893L18.4389 5.13535Z" fill="#D7E7EC"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M49.9999 30.5952V6.68016V6.43085V6.34774C49.9999 6.19296 49.934 6.16718 49.6962 5.93505L43.8196 0.329589C43.5417 0.0659178 43.4959 0 43.3325 0H42.9313H18.9747C18.6796 0 18.4389 0.240722 18.4389 0.535936V39.2527C18.4389 39.5479 18.6796 39.7914 18.9747 39.7914H49.4641C49.7592 39.7914 49.9999 39.5479 49.9999 39.2527V30.5952Z" fill="#EDF3F4"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M18.4389 5.13535L16.2814 5.50507V41.2328C16.2814 41.5309 16.5221 41.7716 16.8172 41.7716H25.37H30.4588L38.5331 40.3874L42.0087 39.7913H40.1893H37.9515H27.5276H18.9747C18.6796 39.7913 18.4389 39.5478 18.4389 39.2526C18.4389 27.881 18.4389 16.5067 18.4389 5.13535Z" fill="#B5C4CF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.098 26.4771L9.35591 10.4889C8.61383 10.7382 7.87457 10.9875 7.13815 11.2368L7.47916 13.2228L10.2212 29.2111L13.2069 46.6207C13.2527 46.8987 13.522 47.0878 13.7999 47.042L21.88 45.655L25.7138 44.9988L37.2608 40.8434L37.1233 40.6285L30.4587 41.7719L23.7569 42.9211L15.6768 44.3081C15.3989 44.354 15.1295 44.1649 15.0808 43.8868L12.098 26.4771Z" fill="#9AAFB7"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M49.9999 30.5952V6.68016V6.43085C49.9999 6.14139 49.9053 6.13856 49.6962 5.93505L43.8195 0.329589C43.5416 0.0659178 43.4958 0 43.3324 0H42.9312H36.9685C44.255 9.75516 44.6704 27.3396 39.2637 38.3156C39.0143 38.8257 38.7536 39.3157 38.4814 39.7914H40.1891H42.0086H49.464C49.7591 39.7914 49.9999 39.5479 49.9999 39.2527V30.5952Z" fill="#D7E7EC"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M42.9427 5.3161C42.9427 6.50536 44.0315 6.43085 44.5559 6.43085H49.9999V6.34774C49.9999 6.19296 49.934 6.16718 49.6962 5.93505L43.8196 0.329589C43.5416 0.0659178 43.4958 0 43.3325 0H42.9313L42.9427 5.3161Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M49.6962 5.93505L43.8196 0.329589C43.5416 0.0659178 43.4958 0 43.3325 0H42.9313L42.9427 5.31601C42.9427 6.50526 44.0315 6.43075 44.5559 6.43075H49.9999V6.34764C49.9999 6.19296 49.934 6.16718 49.6962 5.93505Z" fill="#B5C4CF"/>
|
||||
<path d="M45.1576 11.7192H23.5849C23.1682 11.7192 22.8304 11.3813 22.8304 10.9644C22.8304 10.5475 23.1682 10.2096 23.5849 10.2096H45.1576C45.5742 10.2096 45.912 10.5475 45.912 10.9644C45.912 11.3813 45.5743 11.7192 45.1576 11.7192Z" fill="#9AAFB7"/>
|
||||
<path d="M45.1576 17.0811H23.5849C23.1682 17.0811 22.8304 16.7432 22.8304 16.3263C22.8304 15.9095 23.1682 15.5716 23.5849 15.5716H45.1576C45.5742 15.5716 45.912 15.9095 45.912 16.3263C45.912 16.7432 45.5743 17.0811 45.1576 17.0811Z" fill="#9AAFB7"/>
|
||||
<path d="M45.1576 22.4431H23.5849C23.1682 22.4431 22.8304 22.1052 22.8304 21.6883C22.8304 21.2714 23.1682 20.9335 23.5849 20.9335H45.1576C45.5742 20.9335 45.912 21.2714 45.912 21.6883C45.912 22.1052 45.5743 22.4431 45.1576 22.4431Z" fill="#9AAFB7"/>
|
||||
<path d="M45.1576 27.805H23.5849C23.1682 27.805 22.8304 27.4671 22.8304 27.0502C22.8304 26.6333 23.1682 26.2954 23.5849 26.2954H45.1576C45.5742 26.2954 45.912 26.6333 45.912 27.0502C45.912 27.4671 45.5743 27.805 45.1576 27.805Z" fill="#9AAFB7"/>
|
||||
<path d="M45.1576 33.1669H23.5849C23.1682 33.1669 22.8304 32.829 22.8304 32.4121C22.8304 31.9952 23.1682 31.6573 23.5849 31.6573H45.1576C45.5742 31.6573 45.912 31.9952 45.912 32.4121C45.912 32.829 45.5743 33.1669 45.1576 33.1669Z" fill="#9AAFB7"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.1 KiB |
@@ -0,0 +1,23 @@
|
||||
<svg width="29" height="39" viewBox="0 0 29 39" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g filter="url(#filter0_i_3851_4689)">
|
||||
<path d="M0 5.33646C0 2.84823 1.82766 0.716451 4.30322 0.46559C8.74889 0.0150898 12.2724 0.0349553 16.6673 0.476887C19.1549 0.727017 21 2.86372 21 5.36377V33.7227C21 36.1852 19.2096 38.3047 16.7627 38.5821C12.3371 39.0837 8.75437 39.0879 4.2429 38.579C1.794 38.3027 0 36.1827 0 33.7182V5.33646Z" fill="#EAF6FF"/>
|
||||
</g>
|
||||
<path d="M17.9558 24C18.0876 24 18.2194 23.9498 18.3199 23.8493C18.521 23.6481 18.521 23.3222 18.3199 23.1212C16.5988 21.4002 16.5988 18.5998 18.3199 16.8788C18.521 16.6777 18.521 16.3518 18.3199 16.1507C18.1188 15.9498 17.7929 15.9498 17.5918 16.1507C15.4693 18.2733 15.4693 21.7268 17.5918 23.8493C17.6923 23.9498 17.8241 24 17.9558 24Z" fill="#8AC9FE"/>
|
||||
<path d="M19.0387 22C19.1493 22 19.2598 21.9578 19.3442 21.8735C19.5129 21.7048 19.5129 21.4313 19.3441 21.2626C19.0069 20.9254 18.8212 20.477 18.8212 20C18.8212 19.523 19.0069 19.0747 19.3441 18.7374C19.5129 18.5687 19.5129 18.2952 19.3442 18.1265C19.1754 17.9578 18.9019 17.9579 18.7333 18.1265C18.2329 18.6269 17.9573 19.2923 17.9573 20C17.9573 20.7078 18.2329 21.3731 18.7333 21.8735C18.8176 21.9578 18.9282 22 19.0387 22Z" fill="#8AC9FE"/>
|
||||
<path d="M11.4131 31.3326L11.4131 33.2934C11.4131 33.6836 11.0969 34 10.7066 34C10.3163 34 10 33.6836 10 33.2934L10 31.3326C10 30.9423 10.3163 30.6261 10.7066 30.6261C11.0969 30.6261 11.4131 30.9423 11.4131 31.3326Z" fill="#B3DAFE"/>
|
||||
<path d="M22 9.09138C22 8.20685 22.5774 7.4095 23.4429 7.22709C24.914 6.91707 26.0828 6.92986 27.5356 7.23253C28.4104 7.41477 29 8.21687 29 9.11042V31.8825C29 32.7476 28.4479 33.5327 27.6064 33.733C26.117 34.0877 24.9156 34.0909 23.3975 33.7314C22.5543 33.5317 22 32.746 22 31.8795V9.09138Z" fill="#EAF6FF"/>
|
||||
<path d="M24.5149 24C24.3831 24 24.2514 23.9498 24.1508 23.8493C23.9497 23.6481 23.9497 23.3222 24.1508 23.1212C25.8719 21.4002 25.8719 18.5998 24.1508 16.8788C23.9497 16.6777 23.9497 16.3518 24.1508 16.1507C24.3519 15.9498 24.6778 15.9498 24.8789 16.1507C27.0014 18.2733 27.0014 21.7268 24.8789 23.8493C24.7784 23.9498 24.6466 24 24.5149 24Z" fill="#8AC9FE"/>
|
||||
<path d="M23.432 22C23.3214 22 23.2109 21.9578 23.1265 21.8735C22.9578 21.7048 22.9578 21.4313 23.1266 21.2626C23.4638 20.9254 23.6495 20.477 23.6495 20C23.6495 19.523 23.4638 19.0747 23.1266 18.7374C22.9578 18.5687 22.9578 18.2952 23.1265 18.1265C23.2953 17.9578 23.5688 17.9579 23.7374 18.1265C24.2378 18.6269 24.5134 19.2923 24.5134 20C24.5134 20.7078 24.2379 21.3731 23.7374 21.8735C23.6531 21.9578 23.5425 22 23.432 22Z" fill="#8AC9FE"/>
|
||||
<defs>
|
||||
<filter id="filter0_i_3851_4689" x="-1" y="0.136475" width="22" height="38.823" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset dx="-1"/>
|
||||
<feGaussianBlur stdDeviation="1.5"/>
|
||||
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0.538295 0 0 0 0 0.538295 0 0 0 0 0.538295 0 0 0 0.3 0"/>
|
||||
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_3851_4689"/>
|
||||
</filter>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.3 KiB |
@@ -0,0 +1,47 @@
|
||||
<svg width="241" height="260" viewBox="0 0 241 260" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g filter="url(#filter0_d_3851_4840)">
|
||||
<g filter="url(#filter1_i_3851_4840)">
|
||||
<path d="M1 32.5794C1 17.65 11.9782 4.87264 26.8261 3.31376C56.9938 0.146434 80.4127 0.288676 110.23 3.38644C125.15 4.93649 136.229 17.743 136.229 32.7433V219.157C136.229 233.932 125.474 246.635 110.8 248.355C80.8281 251.869 57.0283 251.901 26.4597 248.336C11.7726 246.623 1 233.917 1 219.131V32.5794Z" fill="#EAF6FF"/>
|
||||
</g>
|
||||
<path d="M113.787 154.669C112.938 154.669 112.09 154.345 111.442 153.698C110.147 152.403 110.147 150.304 111.442 149.009C122.525 137.927 122.525 119.894 111.442 108.812C110.147 107.517 110.147 105.418 111.442 104.123C112.737 102.829 114.836 102.829 116.131 104.123C129.798 117.792 129.798 140.03 116.131 153.698C115.484 154.345 114.635 154.669 113.787 154.669Z" fill="#FF0000" fill-opacity="0.7"/>
|
||||
<path d="M106.813 141.79C106.101 141.79 105.39 141.518 104.846 140.975C103.76 139.889 103.76 138.127 104.847 137.041C107.018 134.87 108.214 131.982 108.214 128.911C108.214 125.839 107.018 122.952 104.847 120.78C103.76 119.694 103.76 117.933 104.846 116.847C105.933 115.76 107.694 115.76 108.78 116.846C112.002 120.069 113.777 124.353 113.777 128.911C113.777 133.468 112.003 137.753 108.78 140.975C108.237 141.518 107.525 141.79 106.813 141.79Z" fill="#FF0000" fill-opacity="0.7"/>
|
||||
<path d="M74.4946 201.887L74.4946 214.513C74.4946 217.026 72.4581 219.063 69.9447 219.063C67.4313 219.063 65.3948 217.026 65.3948 214.513L65.3948 201.887C65.3948 199.374 67.4313 197.337 69.9447 197.337C72.4581 197.337 74.4946 199.374 74.4946 201.887Z" fill="#B3DAFE"/>
|
||||
<g filter="url(#filter2_i_3851_4840)">
|
||||
<path d="M186.229 60.2459C186.229 53.612 190.555 47.5909 197.072 46.3483C205.305 44.7783 212.168 44.839 220.304 46.382C226.889 47.6306 231.305 53.6871 231.305 60.3888V203.89C231.305 210.378 227.172 216.307 220.833 217.686C212.408 219.518 205.306 219.531 196.73 217.674C190.379 216.299 186.229 210.366 186.229 203.867V60.2459Z" fill="#EAF6FF"/>
|
||||
</g>
|
||||
<path d="M205.263 103.153C206.112 103.153 206.96 103.476 207.608 104.124C208.903 105.419 208.903 107.517 207.608 108.812C196.525 119.894 196.525 137.927 207.608 149.009C208.903 150.305 208.903 152.403 207.608 153.698C206.313 154.992 204.214 154.992 202.919 153.698C189.252 140.03 189.252 117.791 202.919 104.123C203.567 103.476 204.415 103.153 205.263 103.153Z" fill="#FF0000" fill-opacity="0.7"/>
|
||||
<path d="M212.237 116.032C212.949 116.032 213.66 116.303 214.204 116.847C215.29 117.933 215.29 119.694 214.203 120.78C212.032 122.952 210.836 125.839 210.836 128.911C210.836 131.982 212.032 134.869 214.203 137.041C215.29 138.128 215.29 139.889 214.204 140.975C213.117 142.061 211.356 142.061 210.27 140.975C207.048 137.753 205.273 133.468 205.273 128.911C205.273 124.353 207.047 120.069 210.27 116.846C210.813 116.304 211.525 116.032 212.237 116.032Z" fill="#FF0000" fill-opacity="0.7"/>
|
||||
</g>
|
||||
<defs>
|
||||
<filter id="filter0_d_3851_4840" x="0" y="0" width="240.305" height="260" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset dx="4" dy="4"/>
|
||||
<feGaussianBlur stdDeviation="2.5"/>
|
||||
<feComposite in2="hardAlpha" operator="out"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.2 0"/>
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_3851_4840"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_3851_4840" result="shape"/>
|
||||
</filter>
|
||||
<filter id="filter1_i_3851_4840" x="0" y="1" width="136.229" height="250" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset dx="-1"/>
|
||||
<feGaussianBlur stdDeviation="10"/>
|
||||
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.3 0"/>
|
||||
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_3851_4840"/>
|
||||
</filter>
|
||||
<filter id="filter2_i_3851_4840" x="184.229" y="45.1975" width="47.0763" height="173.866" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset dx="-2"/>
|
||||
<feGaussianBlur stdDeviation="5"/>
|
||||
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.3 0"/>
|
||||
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_3851_4840"/>
|
||||
</filter>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.9 KiB |
@@ -8,7 +8,6 @@ import 'package:syncrow_app/features/auth/model/user_model.dart';
|
||||
import 'package:syncrow_app/navigation/navigation_service.dart';
|
||||
import 'package:syncrow_app/navigation/routing_constants.dart';
|
||||
import 'package:syncrow_app/services/api/authentication_api.dart';
|
||||
import 'package:syncrow_app/services/api/profile_api.dart';
|
||||
import 'package:syncrow_app/utils/helpers/shared_preferences_helper.dart';
|
||||
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/strings_manager.dart';
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:firebase_database/firebase_database.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/door_sensor_bloc/door_sensor_event.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/door_sensor_bloc/door_sensor_state.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_control_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_report_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/door_sensor_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/status_model.dart';
|
||||
import 'package:syncrow_app/services/api/devices_api.dart';
|
||||
|
||||
class DoorSensorBloc extends Bloc<DoorSensorEvent, DoorSensorState> {
|
||||
final String DSId;
|
||||
DoorSensorBloc({
|
||||
required this.DSId,
|
||||
}) : super(const DoorSensorState()) {
|
||||
on<DoorSensorInitial>(_fetchStatus);
|
||||
on<ReportLogsInitial>(fetchLogsForLastMonth);
|
||||
on<ToggleLowBatteryEvent>(_toggleLowBattery);
|
||||
on<ToggleClosingReminderEvent>(_toggleClosingReminder);
|
||||
on<ToggleDoorAlarmEvent>(_toggleDoorAlarm);
|
||||
}
|
||||
Timer? _timer;
|
||||
bool lowBattery = false;
|
||||
bool closingReminder = false;
|
||||
bool doorAlarm = false;
|
||||
DoorSensorModel deviceStatus =
|
||||
DoorSensorModel(doorContactState: false, batteryPercentage: 0);
|
||||
|
||||
void _fetchStatus(
|
||||
DoorSensorInitial event, Emitter<DoorSensorState> emit) async {
|
||||
emit(DoorSensorLoadingState());
|
||||
try {
|
||||
var response = await DevicesAPI.getDeviceStatus(DSId);
|
||||
List<StatusModel> statusModelList = [];
|
||||
for (var status in response['status']) {
|
||||
statusModelList.add(StatusModel.fromJson(status));
|
||||
}
|
||||
deviceStatus = DoorSensorModel.fromJson(
|
||||
statusModelList,
|
||||
);
|
||||
emit(UpdateState(doorSensor: deviceStatus));
|
||||
Future.delayed(const Duration(milliseconds: 500));
|
||||
_listenToChanges();
|
||||
} catch (e) {
|
||||
emit(DoorSensorFailedState(errorMessage: e.toString()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Toggle functions for each switch
|
||||
void _toggleLowBattery(
|
||||
ToggleLowBatteryEvent event, Emitter<DoorSensorState> emit) async {
|
||||
emit(LoadingNewSate(doorSensor: deviceStatus));
|
||||
try {
|
||||
lowBattery = event.isLowBatteryEnabled;
|
||||
emit(UpdateState(doorSensor: deviceStatus));
|
||||
|
||||
// API call to update the state, if necessary
|
||||
await DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: DSId,
|
||||
code: 'low_battery',
|
||||
value: lowBattery,
|
||||
),
|
||||
DSId,
|
||||
);
|
||||
} catch (e) {
|
||||
emit(DoorSensorFailedState(errorMessage: e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
void _toggleClosingReminder(
|
||||
ToggleClosingReminderEvent event, Emitter<DoorSensorState> emit) async {
|
||||
emit(LoadingNewSate(doorSensor: deviceStatus));
|
||||
try {
|
||||
closingReminder = event.isClosingReminderEnabled;
|
||||
emit(UpdateState(doorSensor: deviceStatus));
|
||||
|
||||
// API call to update the state, if necessary
|
||||
await DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: DSId,
|
||||
code: 'closing_reminder',
|
||||
value: closingReminder,
|
||||
),
|
||||
DSId,
|
||||
);
|
||||
} catch (e) {
|
||||
emit(DoorSensorFailedState(errorMessage: e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
void _toggleDoorAlarm(
|
||||
ToggleDoorAlarmEvent event, Emitter<DoorSensorState> emit) async {
|
||||
emit(LoadingNewSate(doorSensor: deviceStatus));
|
||||
try {
|
||||
doorAlarm = event.isDoorAlarmEnabled;
|
||||
emit(UpdateState(doorSensor: deviceStatus));
|
||||
|
||||
// API call to update the state, if necessary
|
||||
await DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: DSId,
|
||||
code: 'door_alarm',
|
||||
value: doorAlarm,
|
||||
),
|
||||
DSId,
|
||||
);
|
||||
} catch (e) {
|
||||
emit(DoorSensorFailedState(errorMessage: e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
DeviceReport recordGroups =
|
||||
DeviceReport(startTime: '0', endTime: '0', data: []);
|
||||
|
||||
Future<void> fetchLogsForLastMonth(
|
||||
ReportLogsInitial event, Emitter<DoorSensorState> emit) async {
|
||||
// Get the current date and time
|
||||
DateTime now = DateTime.now();
|
||||
|
||||
// Calculate the date one month ago
|
||||
DateTime lastMonth = DateTime(now.year, now.month - 1, now.day);
|
||||
|
||||
// Convert the date to milliseconds since epoch (Unix timestamp in milliseconds)
|
||||
int startTime = lastMonth.millisecondsSinceEpoch;
|
||||
int endTime = now.millisecondsSinceEpoch;
|
||||
try {
|
||||
emit(DoorSensorLoadingState());
|
||||
var response = await DevicesAPI.getReportLogs(
|
||||
startTime:
|
||||
startTime.toString(), // Convert to String if the API expects it
|
||||
endTime: endTime.toString(), // Convert to String if the API expects it
|
||||
deviceUuid: DSId,
|
||||
code: 'doorcontact_state',
|
||||
);
|
||||
print('response======${response}');
|
||||
recordGroups = response;
|
||||
// Process response here
|
||||
emit(UpdateState(doorSensor: deviceStatus));
|
||||
} on DioException catch (e) {
|
||||
final errorData = e.response!.data;
|
||||
String errorMessage = errorData['message'];
|
||||
// Handle error
|
||||
print('Error fetching logs: ${errorMessage}');
|
||||
}
|
||||
}
|
||||
|
||||
_listenToChanges() {
|
||||
try {
|
||||
DatabaseReference ref =
|
||||
FirebaseDatabase.instance.ref('device-status/$DSId');
|
||||
Stream<DatabaseEvent> stream = ref.onValue;
|
||||
|
||||
stream.listen((DatabaseEvent event) async {
|
||||
if (_timer != null) {
|
||||
await Future.delayed(const Duration(seconds: 2));
|
||||
}
|
||||
Map<dynamic, dynamic> usersMap =
|
||||
event.snapshot.value as Map<dynamic, dynamic>;
|
||||
List<StatusModel> statusList = [];
|
||||
|
||||
usersMap['status'].forEach((element) {
|
||||
statusList.add(StatusModel(code: element['code'], value: true));
|
||||
});
|
||||
|
||||
deviceStatus = DoorSensorModel.fromJson(statusList);
|
||||
if (!isClosed) {
|
||||
add(
|
||||
DoorSensorSwitch(switchD: deviceStatus.doorContactState),
|
||||
);
|
||||
}
|
||||
});
|
||||
} catch (_) {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
abstract class DoorSensorEvent extends Equatable {
|
||||
const DoorSensorEvent();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class DoorSensorLoading extends DoorSensorEvent {}
|
||||
|
||||
class DoorSensorSwitch extends DoorSensorEvent {
|
||||
final bool switchD;
|
||||
final String deviceId;
|
||||
final String productId;
|
||||
const DoorSensorSwitch({required this.switchD, this.deviceId = '', this.productId = ''});
|
||||
|
||||
@override
|
||||
List<Object> get props => [switchD, deviceId, productId];
|
||||
}
|
||||
|
||||
class DoorSensorUpdated extends DoorSensorEvent {}
|
||||
|
||||
class DoorSensorInitial extends DoorSensorEvent {
|
||||
const DoorSensorInitial();
|
||||
}
|
||||
|
||||
class ReportLogsInitial extends DoorSensorEvent {
|
||||
const ReportLogsInitial();
|
||||
}
|
||||
|
||||
|
||||
class DoorSensorChangeStatus extends DoorSensorEvent {}
|
||||
|
||||
|
||||
class GetCounterEvent extends DoorSensorEvent {
|
||||
final String deviceCode;
|
||||
const GetCounterEvent({required this.deviceCode});
|
||||
@override
|
||||
List<Object> get props => [deviceCode];
|
||||
}
|
||||
|
||||
|
||||
|
||||
class ToggleLowBatteryEvent extends DoorSensorEvent {
|
||||
final bool isLowBatteryEnabled;
|
||||
|
||||
const ToggleLowBatteryEvent(this.isLowBatteryEnabled);
|
||||
|
||||
@override
|
||||
List<Object> get props => [isLowBatteryEnabled];
|
||||
}
|
||||
|
||||
class ToggleClosingReminderEvent extends DoorSensorEvent {
|
||||
final bool isClosingReminderEnabled;
|
||||
|
||||
const ToggleClosingReminderEvent(this.isClosingReminderEnabled);
|
||||
|
||||
@override
|
||||
List<Object> get props => [isClosingReminderEnabled];
|
||||
}
|
||||
|
||||
class ToggleDoorAlarmEvent extends DoorSensorEvent {
|
||||
final bool isDoorAlarmEnabled;
|
||||
|
||||
const ToggleDoorAlarmEvent(this.isDoorAlarmEnabled);
|
||||
|
||||
@override
|
||||
List<Object> get props => [isDoorAlarmEnabled];
|
||||
}
|
||||
|
||||
|
||||
|
||||
class SetCounterValue extends DoorSensorEvent {
|
||||
final Duration duration;
|
||||
final String deviceCode;
|
||||
const SetCounterValue({required this.duration, required this.deviceCode});
|
||||
@override
|
||||
List<Object> get props => [duration, deviceCode];
|
||||
}
|
||||
|
||||
class StartTimer extends DoorSensorEvent {
|
||||
final int duration;
|
||||
|
||||
const StartTimer(this.duration);
|
||||
|
||||
@override
|
||||
List<Object> get props => [duration];
|
||||
}
|
||||
|
||||
class TickTimer extends DoorSensorEvent {
|
||||
final int remainingTime;
|
||||
|
||||
const TickTimer(this.remainingTime);
|
||||
|
||||
@override
|
||||
List<Object> get props => [remainingTime];
|
||||
}
|
||||
|
||||
class StopTimer extends DoorSensorEvent {}
|
||||
|
||||
class OnClose extends DoorSensorEvent {}
|
||||
@@ -0,0 +1,128 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:syncrow_app/features/devices/model/door_sensor_model.dart';
|
||||
|
||||
class DoorSensorState extends Equatable {
|
||||
const DoorSensorState();
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class DoorSensorInitialState extends DoorSensorState {}
|
||||
|
||||
class DoorSensorLoadingState extends DoorSensorState {}
|
||||
|
||||
class DoorSensorFailedState extends DoorSensorState {
|
||||
final String errorMessage;
|
||||
|
||||
const DoorSensorFailedState({required this.errorMessage});
|
||||
|
||||
@override
|
||||
List<Object> get props => [errorMessage];
|
||||
}
|
||||
|
||||
class UpdateState extends DoorSensorState {
|
||||
final DoorSensorModel doorSensor;
|
||||
const UpdateState({required this.doorSensor});
|
||||
|
||||
@override
|
||||
List<Object> get props => [doorSensor];
|
||||
}
|
||||
|
||||
|
||||
class LoadingNewSate extends DoorSensorState {
|
||||
final DoorSensorModel doorSensor;
|
||||
const LoadingNewSate({required this.doorSensor});
|
||||
|
||||
@override
|
||||
List<Object> get props => [doorSensor];
|
||||
}
|
||||
|
||||
// class WHModifyingState extends DoorSensorState {
|
||||
// final WHModel whStatusModel;
|
||||
// const WHModifyingState({required this.whStatusModel});
|
||||
//
|
||||
// @override
|
||||
// List<Object> get props => [whStatusModel];
|
||||
// }
|
||||
//
|
||||
// class GetWHStatusState extends DoorSensorState {
|
||||
// final WHModel whStatusModel;
|
||||
// const GetWHStatusState({required this.whStatusModel});
|
||||
//
|
||||
// @override
|
||||
// List<Object> get props => [whStatusModel];
|
||||
// }
|
||||
//
|
||||
//
|
||||
// class WHFailedState extends WaterHeaterState {
|
||||
// final String errorMessage;
|
||||
//
|
||||
// const WHFailedState({required this.errorMessage});
|
||||
//
|
||||
// @override
|
||||
// List<Object> get props => [errorMessage];
|
||||
// }
|
||||
|
||||
|
||||
// class LoadingNewSate extends WaterHeaterState {
|
||||
// final WHModel whModel;
|
||||
// const LoadingNewSate({required this.whModel});
|
||||
//
|
||||
// @override
|
||||
// List<Object> get props => [whModel];
|
||||
// }
|
||||
// class TimerRunComplete extends WaterHeaterState {}
|
||||
// class UpdateTimerState extends WaterHeaterState {
|
||||
// final int seconds;
|
||||
// const UpdateTimerState({required this.seconds});
|
||||
//
|
||||
// @override
|
||||
// List<Object> get props => [seconds];
|
||||
// }
|
||||
//
|
||||
// class TimerRunInProgress extends WaterHeaterState {
|
||||
// final int remainingTime;
|
||||
//
|
||||
// const TimerRunInProgress(this.remainingTime);
|
||||
//
|
||||
// @override
|
||||
// List<Object> get props => [remainingTime];
|
||||
// }
|
||||
//
|
||||
// class SaveSchedule extends WaterHeaterState {}
|
||||
// class ChangeTimeState extends WaterHeaterState {}
|
||||
// class UpdateCreateScheduleState extends WaterHeaterState {
|
||||
// final bool createSchedule;
|
||||
// UpdateCreateScheduleState(this.createSchedule);
|
||||
// }
|
||||
// class IsToggleState extends WaterHeaterState {
|
||||
// final bool? onOff;
|
||||
// const IsToggleState({this.onOff});
|
||||
// }
|
||||
//
|
||||
//
|
||||
// class UpdateState extends WaterHeaterState {
|
||||
// final WHModel whModel;
|
||||
// const UpdateState({required this.whModel});
|
||||
//
|
||||
// @override
|
||||
// List<Object> get props => [WHModel];
|
||||
// }
|
||||
//
|
||||
// class ChangeSwitchStatusEvent extends WaterHeaterState {
|
||||
// final bool value;
|
||||
// final String deviceId;
|
||||
// const ChangeSwitchStatusEvent({required this.value, this.deviceId = ''});
|
||||
// @override
|
||||
// List<Object> get props => [value, deviceId];
|
||||
// }
|
||||
//
|
||||
// class ChangeSlidingSegmentState extends WaterHeaterState {
|
||||
// final int value;
|
||||
//
|
||||
// const ChangeSlidingSegmentState({required this.value});
|
||||
//
|
||||
// @override
|
||||
// List<Object> get props => [value];
|
||||
// }
|
||||
@@ -24,7 +24,7 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
||||
bool oneGangGroup = false;
|
||||
List<DeviceModel> devicesList = [];
|
||||
|
||||
OneGangBloc({required this.oneGangId,required this.switchCode}) : super(InitialState()) {
|
||||
OneGangBloc({required this.oneGangId, required this.switchCode}) : super(InitialState()) {
|
||||
on<InitialEvent>(_fetchOneGangStatus);
|
||||
on<OneGangUpdated>(_oneGangUpdated);
|
||||
on<ChangeFirstSwitchStatusEvent>(_changeFirstSwitch);
|
||||
@@ -34,14 +34,13 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
||||
on<TickTimer>(_onTickTimer);
|
||||
on<OnClose>(_onClose);
|
||||
|
||||
|
||||
|
||||
|
||||
on<ToggleDaySelectionEvent>(toggleDaySelection);
|
||||
on<ThreeGangSave>(saveSchedule);
|
||||
on<ScheduleSave>(saveSchedule);
|
||||
on<GetScheduleEvent>(getSchedule);
|
||||
on<ToggleScheduleEvent>(toggleChange);
|
||||
on<DeleteScheduleEvent>(deleteSchedule);
|
||||
on<ToggleSelectedEvent>(toggleSelectedIndex);
|
||||
on<ToggleCreateScheduleEvent>(toggleCreateSchedule);
|
||||
}
|
||||
|
||||
void _fetchOneGangStatus(InitialEvent event, Emitter<OneGangState> emit) async {
|
||||
@@ -114,7 +113,6 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void _changeSliding(ChangeSlidingSegment event, Emitter<OneGangState> emit) async {
|
||||
emit(ChangeSlidingSegmentState(value: event.value));
|
||||
}
|
||||
@@ -199,11 +197,14 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
||||
{"day": "Sat", "key": "Sat"},
|
||||
];
|
||||
|
||||
Future<void> saveSchedule(ThreeGangSave event, Emitter<OneGangState> emit,) async {
|
||||
Future<void> saveSchedule(
|
||||
ScheduleSave event,
|
||||
Emitter<OneGangState> emit,
|
||||
) async {
|
||||
try {
|
||||
if(selectedDays.isNotEmpty) {
|
||||
if (selectedDays.isNotEmpty) {
|
||||
emit(LoadingInitialState());
|
||||
final response = await DevicesAPI.postSchedule(
|
||||
await DevicesAPI.postSchedule(
|
||||
category: switchCode,
|
||||
deviceId: oneGangId,
|
||||
time: getTimeStampWithoutSeconds(selectedTime).toString(),
|
||||
@@ -212,9 +213,10 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
||||
days: selectedDays);
|
||||
CustomSnackBar.displaySnackBar('Save Successfully');
|
||||
add(GetScheduleEvent());
|
||||
emit(ThreeGangSaveSchedule());
|
||||
toggleCreateSchedule();
|
||||
}else{
|
||||
emit(SaveSchedule());
|
||||
|
||||
add(const ToggleCreateScheduleEvent(index:1 ));
|
||||
} else {
|
||||
CustomSnackBar.displaySnackBar('Please select days');
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -222,13 +224,15 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Future<void> getSchedule(GetScheduleEvent event, Emitter<OneGangState> emit,) async {
|
||||
Future<void> getSchedule(
|
||||
GetScheduleEvent event,
|
||||
Emitter<OneGangState> emit,
|
||||
) async {
|
||||
try {
|
||||
emit(LoadingInitialState());
|
||||
final response = await DevicesAPI.getSchedule(
|
||||
category: switchCode,
|
||||
deviceId: oneGangId ,
|
||||
deviceId: oneGangId,
|
||||
);
|
||||
List<dynamic> jsonData = response;
|
||||
listSchedule = jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
|
||||
@@ -242,13 +246,12 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
||||
|
||||
int? getTimeStampWithoutSeconds(DateTime? dateTime) {
|
||||
if (dateTime == null) return null;
|
||||
DateTime dateTimeWithoutSeconds = DateTime(dateTime.year, dateTime.month,
|
||||
dateTime.day, dateTime.hour, dateTime.minute);
|
||||
DateTime dateTimeWithoutSeconds =
|
||||
DateTime(dateTime.year, dateTime.month, dateTime.day, dateTime.hour, dateTime.minute);
|
||||
return dateTimeWithoutSeconds.millisecondsSinceEpoch ~/ 1000;
|
||||
}
|
||||
|
||||
Future toggleChange(
|
||||
ToggleScheduleEvent event, Emitter<OneGangState> emit) async {
|
||||
Future toggleChange(ToggleScheduleEvent event, Emitter<OneGangState> emit) async {
|
||||
try {
|
||||
emit(LoadingInitialState());
|
||||
final response = await DevicesAPI.changeSchedule(
|
||||
@@ -267,13 +270,13 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
||||
}
|
||||
}
|
||||
|
||||
Future deleteSchedule(
|
||||
DeleteScheduleEvent event, Emitter<OneGangState> emit) async {
|
||||
Future deleteSchedule(DeleteScheduleEvent event, Emitter<OneGangState> emit) async {
|
||||
try {
|
||||
emit(LoadingInitialState());
|
||||
final response = await DevicesAPI.deleteSchedule(
|
||||
scheduleId: event.id,
|
||||
deviceUuid: oneGangId, );
|
||||
deviceUuid: oneGangId,
|
||||
);
|
||||
if (response == true) {
|
||||
add(GetScheduleEvent());
|
||||
return toggleSchedule;
|
||||
@@ -287,24 +290,33 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
||||
}
|
||||
}
|
||||
|
||||
void toggleCreateSchedule() {
|
||||
emit(LoadingInitialState());
|
||||
createSchedule = !createSchedule;
|
||||
selectedDays.clear();
|
||||
selectedTime=DateTime.now();
|
||||
emit(UpdateCreateScheduleState(createSchedule));
|
||||
emit(ChangeSlidingSegmentState(value: 1));
|
||||
}
|
||||
// void toggleCreateSchedule() {
|
||||
// emit(LoadingInitialState());
|
||||
// createSchedule = !createSchedule;
|
||||
// selectedDays.clear();
|
||||
// selectedTime = DateTime.now();
|
||||
// emit(UpdateCreateScheduleState(createSchedule));
|
||||
// emit(ChangeSlidingSegmentState(value: 1));
|
||||
// }
|
||||
|
||||
|
||||
void toggleCreateSchedule(ToggleCreateScheduleEvent event, Emitter<OneGangState> emit) {
|
||||
emit(LoadingInitialState());
|
||||
createSchedule = !createSchedule;
|
||||
selectedDays.clear();
|
||||
selectedTime = DateTime.now();
|
||||
emit(UpdateCreateScheduleState(createSchedule));
|
||||
}
|
||||
|
||||
bool toggleSchedule = true;
|
||||
List<String> selectedDays = [];
|
||||
bool createSchedule = false;
|
||||
List<ScheduleModel> listSchedule = [];
|
||||
DateTime? selectedTime=DateTime.now();
|
||||
DateTime? selectedTime = DateTime.now();
|
||||
Future<void> toggleDaySelection(
|
||||
ToggleDaySelectionEvent event,
|
||||
Emitter<OneGangState> emit,
|
||||
) async {
|
||||
ToggleDaySelectionEvent event,
|
||||
Emitter<OneGangState> emit,
|
||||
) async {
|
||||
emit(LoadingInitialState());
|
||||
if (selectedDays.contains(event.key)) {
|
||||
selectedDays.remove(event.key);
|
||||
@@ -317,10 +329,9 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
|
||||
|
||||
int selectedTabIndex = 0;
|
||||
|
||||
void toggleSelectedIndex(index) {
|
||||
void toggleSelectedIndex( ToggleSelectedEvent event, Emitter<OneGangState> emit) {
|
||||
emit(LoadingInitialState());
|
||||
selectedTabIndex = index;
|
||||
selectedTabIndex =event.index;
|
||||
emit(ChangeSlidingSegmentState(value: selectedTabIndex));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ class OnClose extends OneGangEvent {}
|
||||
|
||||
//------------------- Schedule ----------=---------
|
||||
class GetScheduleEvent extends OneGangEvent {}
|
||||
class ThreeGangSave extends OneGangEvent {}
|
||||
class ScheduleSave extends OneGangEvent {}
|
||||
class ToggleScheduleEvent extends OneGangEvent {
|
||||
final String id;
|
||||
final bool toggle;
|
||||
@@ -114,3 +114,19 @@ class DeleteScheduleEvent extends OneGangEvent {
|
||||
@override
|
||||
List<Object> get props => [id];
|
||||
}
|
||||
|
||||
|
||||
class ToggleSelectedEvent extends OneGangEvent {
|
||||
final int index;
|
||||
const ToggleSelectedEvent({required this.index});
|
||||
@override
|
||||
List<Object> get props => [index];
|
||||
}
|
||||
|
||||
|
||||
class ToggleCreateScheduleEvent extends OneGangEvent {
|
||||
final int index;
|
||||
const ToggleCreateScheduleEvent({required this.index});
|
||||
@override
|
||||
List<Object> get props => [index];
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:syncrow_app/features/devices/model/groupTwoGangModel.dart';
|
||||
import 'package:syncrow_app/features/devices/model/group_one_gang_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/one_gang_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/two_gang_model.dart';
|
||||
|
||||
|
||||
class OneGangState extends Equatable {
|
||||
const OneGangState();
|
||||
|
||||
@@ -32,13 +31,13 @@ class LoadingNewSate extends OneGangState {
|
||||
}
|
||||
|
||||
class UpdateGroupState extends OneGangState {
|
||||
final List<GroupTwoGangModel> twoGangList;
|
||||
final List<GroupOneGangModel> oneGangList;
|
||||
final bool allSwitches;
|
||||
|
||||
const UpdateGroupState({required this.twoGangList, required this.allSwitches});
|
||||
const UpdateGroupState({required this.oneGangList, required this.allSwitches});
|
||||
|
||||
@override
|
||||
List<Object> get props => [twoGangList, allSwitches];
|
||||
List<Object> get props => [oneGangList, allSwitches];
|
||||
}
|
||||
|
||||
class FailedState extends OneGangState {
|
||||
@@ -77,13 +76,17 @@ class TimerRunInProgress extends OneGangState {
|
||||
}
|
||||
|
||||
class TimerRunComplete extends OneGangState {}
|
||||
class ThreeGangSaveSchedule extends OneGangState {}
|
||||
|
||||
class SaveSchedule extends OneGangState {}
|
||||
|
||||
class IsToggleState extends OneGangState {
|
||||
final bool? onOff;
|
||||
const IsToggleState({this.onOff});
|
||||
}
|
||||
|
||||
class ChangeTimeState extends OneGangState {}
|
||||
|
||||
class UpdateCreateScheduleState extends OneGangState {
|
||||
final bool createSchedule;
|
||||
UpdateCreateScheduleState(this.createSchedule);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ import 'package:syncrow_app/features/devices/model/three_gang_model.dart';
|
||||
import 'package:syncrow_app/services/api/devices_api.dart';
|
||||
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
|
||||
|
||||
|
||||
class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||
final String threeGangId;
|
||||
final String switchCode;
|
||||
@@ -35,7 +34,7 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||
List<GroupThreeGangModel> groupThreeGangList = [];
|
||||
bool allSwitchesOn = true;
|
||||
|
||||
ThreeGangBloc({required this.threeGangId,required this.switchCode}) : super(InitialState()) {
|
||||
ThreeGangBloc({required this.threeGangId, required this.switchCode}) : super(InitialState()) {
|
||||
on<InitialEvent>(_fetchThreeGangStatus);
|
||||
on<ThreeGangUpdated>(_threeGangUpdated);
|
||||
on<ChangeFirstSwitchStatusEvent>(_changeFirstSwitch);
|
||||
@@ -51,13 +50,14 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||
on<GroupAllOnEvent>(_groupAllOn);
|
||||
on<GroupAllOffEvent>(_groupAllOff);
|
||||
|
||||
|
||||
|
||||
on<ToggleDaySelectionEvent>(toggleDaySelection);
|
||||
on<ThreeGangSave>(saveSchedule);
|
||||
on<GetScheduleEvent>(getSchedule);
|
||||
on<ToggleScheduleEvent>(toggleChange);
|
||||
on<DeleteScheduleEvent>(deleteSchedule);
|
||||
|
||||
on<ToggleSelectedEvent>(toggleSelectedIndex);
|
||||
on<ToggleCreateScheduleEvent>(toggleCreateSchedule);
|
||||
}
|
||||
|
||||
void _fetchThreeGangStatus(InitialEvent event, Emitter<ThreeGangState> emit) async {
|
||||
@@ -490,9 +490,6 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
List<Map<String, String>> days = [
|
||||
{"day": "Sun", "key": "Sun"},
|
||||
{"day": "Mon", "key": "Mon"},
|
||||
@@ -504,9 +501,9 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||
];
|
||||
|
||||
Future<void> toggleDaySelection(
|
||||
ToggleDaySelectionEvent event,
|
||||
Emitter<ThreeGangState> emit,
|
||||
) async {
|
||||
ToggleDaySelectionEvent event,
|
||||
Emitter<ThreeGangState> emit,
|
||||
) async {
|
||||
emit(LoadingInitialState());
|
||||
if (selectedDays.contains(event.key)) {
|
||||
selectedDays.remove(event.key);
|
||||
@@ -517,11 +514,14 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||
add(ChangeSlidingSegment(value: 1));
|
||||
}
|
||||
|
||||
Future<void> saveSchedule(ThreeGangSave event, Emitter<ThreeGangState> emit,) async {
|
||||
Future<void> saveSchedule(
|
||||
ThreeGangSave event,
|
||||
Emitter<ThreeGangState> emit,
|
||||
) async {
|
||||
try {
|
||||
if(selectedDays.isNotEmpty) {
|
||||
if (selectedDays.isNotEmpty) {
|
||||
emit(LoadingInitialState());
|
||||
final response = await DevicesAPI.postSchedule(
|
||||
await DevicesAPI.postSchedule(
|
||||
category: switchCode,
|
||||
deviceId: threeGangId,
|
||||
time: getTimeStampWithoutSeconds(selectedTime).toString(),
|
||||
@@ -531,8 +531,8 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||
CustomSnackBar.displaySnackBar('Save Successfully');
|
||||
add(GetScheduleEvent());
|
||||
emit(ThreeGangSaveSchedule());
|
||||
toggleCreateSchedule();
|
||||
}else{
|
||||
add(const ToggleCreateScheduleEvent(index:1 ));
|
||||
} else {
|
||||
CustomSnackBar.displaySnackBar('Please select days');
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -540,13 +540,15 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Future<void> getSchedule(GetScheduleEvent event, Emitter<ThreeGangState> emit,) async {
|
||||
Future<void> getSchedule(
|
||||
GetScheduleEvent event,
|
||||
Emitter<ThreeGangState> emit,
|
||||
) async {
|
||||
try {
|
||||
emit(LoadingInitialState());
|
||||
final response = await DevicesAPI.getSchedule(
|
||||
category: switchCode,
|
||||
deviceId: threeGangId ,
|
||||
deviceId: threeGangId,
|
||||
);
|
||||
List<dynamic> jsonData = response;
|
||||
listSchedule = jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
|
||||
@@ -560,13 +562,12 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||
|
||||
int? getTimeStampWithoutSeconds(DateTime? dateTime) {
|
||||
if (dateTime == null) return null;
|
||||
DateTime dateTimeWithoutSeconds = DateTime(dateTime.year, dateTime.month,
|
||||
dateTime.day, dateTime.hour, dateTime.minute);
|
||||
DateTime dateTimeWithoutSeconds =
|
||||
DateTime(dateTime.year, dateTime.month, dateTime.day, dateTime.hour, dateTime.minute);
|
||||
return dateTimeWithoutSeconds.millisecondsSinceEpoch ~/ 1000;
|
||||
}
|
||||
|
||||
Future toggleChange(
|
||||
ToggleScheduleEvent event, Emitter<ThreeGangState> emit) async {
|
||||
Future toggleChange(ToggleScheduleEvent event, Emitter<ThreeGangState> emit) async {
|
||||
try {
|
||||
emit(LoadingInitialState());
|
||||
final response = await DevicesAPI.changeSchedule(
|
||||
@@ -585,13 +586,13 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||
}
|
||||
}
|
||||
|
||||
Future deleteSchedule(
|
||||
DeleteScheduleEvent event, Emitter<ThreeGangState> emit) async {
|
||||
Future deleteSchedule(DeleteScheduleEvent event, Emitter<ThreeGangState> emit) async {
|
||||
try {
|
||||
emit(LoadingInitialState());
|
||||
final response = await DevicesAPI.deleteSchedule(
|
||||
scheduleId: event.id,
|
||||
deviceUuid: threeGangId, );
|
||||
scheduleId: event.id,
|
||||
deviceUuid: threeGangId,
|
||||
);
|
||||
if (response == true) {
|
||||
add(GetScheduleEvent());
|
||||
return toggleSchedule;
|
||||
@@ -605,27 +606,43 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
|
||||
}
|
||||
}
|
||||
|
||||
void toggleCreateSchedule() {
|
||||
emit(LoadingInitialState());
|
||||
createSchedule = !createSchedule;
|
||||
selectedDays.clear();
|
||||
selectedTime=DateTime.now();
|
||||
emit(UpdateCreateScheduleState(createSchedule));
|
||||
emit(ChangeSlidingSegmentState(value: 1));
|
||||
}
|
||||
// void toggleCreateSchedule() {
|
||||
// emit(LoadingInitialState());
|
||||
// createSchedule = !createSchedule;
|
||||
// selectedDays.clear();
|
||||
// selectedTime = DateTime.now();
|
||||
// emit(UpdateCreateScheduleState(createSchedule));
|
||||
// emit(ChangeSlidingSegmentState(value: 1));
|
||||
// }
|
||||
|
||||
int selectedTabIndex = 0;
|
||||
|
||||
void toggleSelectedIndex(index) {
|
||||
|
||||
// void toggleSelectedIndex(index) {
|
||||
// emit(LoadingInitialState());
|
||||
// selectedTabIndex = index;
|
||||
// emit(ChangeSlidingSegmentState(value: selectedTabIndex));
|
||||
// }
|
||||
|
||||
|
||||
void toggleSelectedIndex( ToggleSelectedEvent event, Emitter<ThreeGangState> emit) {
|
||||
emit(LoadingInitialState());
|
||||
selectedTabIndex = index;
|
||||
selectedTabIndex =event.index;
|
||||
emit(ChangeSlidingSegmentState(value: selectedTabIndex));
|
||||
}
|
||||
|
||||
void toggleCreateSchedule(ToggleCreateScheduleEvent event, Emitter<ThreeGangState> emit) {
|
||||
emit(LoadingInitialState());
|
||||
createSchedule = !createSchedule;
|
||||
selectedDays.clear();
|
||||
selectedTime = DateTime.now();
|
||||
emit(UpdateCreateScheduleState(createSchedule));
|
||||
}
|
||||
|
||||
|
||||
int selectedTabIndex = 0;
|
||||
bool toggleSchedule = true;
|
||||
List<String> selectedDays = [];
|
||||
bool createSchedule = false;
|
||||
List<ScheduleModel> listSchedule = [];
|
||||
DateTime? selectedTime=DateTime.now();
|
||||
|
||||
DateTime? selectedTime = DateTime.now();
|
||||
}
|
||||
|
||||
@@ -119,3 +119,20 @@ class DeleteScheduleEvent extends ThreeGangEvent {
|
||||
@override
|
||||
List<Object> get props => [id];
|
||||
}
|
||||
|
||||
|
||||
|
||||
class ToggleSelectedEvent extends ThreeGangEvent {
|
||||
final int index;
|
||||
const ToggleSelectedEvent({required this.index});
|
||||
@override
|
||||
List<Object> get props => [index];
|
||||
}
|
||||
|
||||
|
||||
class ToggleCreateScheduleEvent extends ThreeGangEvent {
|
||||
final int index;
|
||||
const ToggleCreateScheduleEvent({required this.index});
|
||||
@override
|
||||
List<Object> get props => [index];
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import 'package:syncrow_app/features/devices/bloc/two_gang_bloc/two_gang_event.d
|
||||
import 'package:syncrow_app/features/devices/bloc/two_gang_bloc/two_gang_state.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_control_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/groupTwoGangModel.dart';
|
||||
import 'package:syncrow_app/features/devices/model/group_two_gang_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/schedule_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/status_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/two_gang_model.dart';
|
||||
@@ -35,7 +35,8 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
|
||||
bool createSchedule = false;
|
||||
List<ScheduleModel> listSchedule = [];
|
||||
|
||||
TwoGangBloc({required this.twoGangId,required this.switchCode}) : super(InitialState()) {
|
||||
TwoGangBloc({required this.twoGangId, required this.switchCode})
|
||||
: super(InitialState()) {
|
||||
on<InitialEvent>(_fetchTwoGangStatus);
|
||||
on<TwoGangUpdated>(_twoGangUpdated);
|
||||
on<ChangeFirstSwitchStatusEvent>(_changeFirstSwitch);
|
||||
@@ -54,28 +55,47 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
|
||||
on<GetScheduleEvent>(getSchedule);
|
||||
on<ToggleScheduleEvent>(toggleRepeat);
|
||||
on<DeleteScheduleEvent>(deleteSchedule);
|
||||
|
||||
on<ToggleSelectedEvent>(toggleSelectedIndex);
|
||||
on<ToggleCreateScheduleEvent>(toggleCreateSchedule);
|
||||
}
|
||||
|
||||
DateTime? selectedTime = DateTime.now();
|
||||
|
||||
void toggleCreateSchedule() {
|
||||
emit(LoadingInitialState());
|
||||
createSchedule = !createSchedule;
|
||||
selectedDays.clear();
|
||||
selectedTime=DateTime.now();
|
||||
emit(UpdateCreateScheduleState(createSchedule));
|
||||
emit(ChangeSlidingSegmentState(value: 1));
|
||||
}
|
||||
// void toggleCreateSchedule() {
|
||||
// emit(LoadingInitialState());
|
||||
// createSchedule = !createSchedule;
|
||||
// selectedDays.clear();
|
||||
// selectedTime = DateTime.now();
|
||||
// emit(UpdateCreateScheduleState(createSchedule));
|
||||
// emit(ChangeSlidingSegmentState(value: 1));
|
||||
// }
|
||||
|
||||
int selectedTabIndex = 0;
|
||||
|
||||
void toggleSelectedIndex(index) {
|
||||
// void toggleSelectedIndex(index) {
|
||||
// emit(LoadingInitialState());
|
||||
// selectedTabIndex = index;
|
||||
// emit(ChangeSlidingSegmentState(value: selectedTabIndex));
|
||||
// }
|
||||
|
||||
void toggleSelectedIndex(
|
||||
ToggleSelectedEvent event, Emitter<TwoGangState> emit) {
|
||||
emit(LoadingInitialState());
|
||||
selectedTabIndex = index;
|
||||
selectedTabIndex = event.index;
|
||||
emit(ChangeSlidingSegmentState(value: selectedTabIndex));
|
||||
}
|
||||
|
||||
void _fetchTwoGangStatus(InitialEvent event, Emitter<TwoGangState> emit) async {
|
||||
void toggleCreateSchedule(
|
||||
ToggleCreateScheduleEvent event, Emitter<TwoGangState> emit) {
|
||||
emit(LoadingInitialState());
|
||||
createSchedule = !createSchedule;
|
||||
selectedDays.clear();
|
||||
selectedTime = DateTime.now();
|
||||
emit(UpdateCreateScheduleState(createSchedule));
|
||||
}
|
||||
|
||||
void _fetchTwoGangStatus(
|
||||
InitialEvent event, Emitter<TwoGangState> emit) async {
|
||||
emit(LoadingInitialState());
|
||||
try {
|
||||
twoGangGroup = event.groupScreen;
|
||||
@@ -363,16 +383,13 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
|
||||
seconds = event.duration.inSeconds;
|
||||
final response = await DevicesAPI.controlDevice(
|
||||
DeviceControlModel(
|
||||
deviceId: twoGangId,
|
||||
code: event.deviceCode,
|
||||
value: seconds),
|
||||
deviceId: twoGangId, code: event.deviceCode, value: seconds),
|
||||
twoGangId);
|
||||
|
||||
if (response['success'] ?? false) {
|
||||
if (event.deviceCode == 'countdown_1') {
|
||||
deviceStatus.firstCountDown = seconds;
|
||||
}
|
||||
else if (event.deviceCode == 'countdown_2') {
|
||||
} else if (event.deviceCode == 'countdown_2') {
|
||||
deviceStatus.secondCountDown = seconds;
|
||||
}
|
||||
} else {
|
||||
@@ -462,9 +479,12 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
|
||||
add(ChangeSlidingSegment(value: 1));
|
||||
}
|
||||
|
||||
Future<void> saveSchedule(TwoGangSave event, Emitter<TwoGangState> emit,) async {
|
||||
Future<void> saveSchedule(
|
||||
TwoGangSave event,
|
||||
Emitter<TwoGangState> emit,
|
||||
) async {
|
||||
try {
|
||||
if(selectedDays.isNotEmpty) {
|
||||
if (selectedDays.isNotEmpty) {
|
||||
emit(LoadingInitialState());
|
||||
final response = await DevicesAPI.postSchedule(
|
||||
category: switchCode,
|
||||
@@ -476,8 +496,9 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
|
||||
CustomSnackBar.displaySnackBar('Save Successfully');
|
||||
add(GetScheduleEvent());
|
||||
emit(TwoGangSaveSchedule());
|
||||
toggleCreateSchedule();
|
||||
}else{
|
||||
add(const ToggleCreateScheduleEvent(index: 1));
|
||||
// toggleCreateSchedule();
|
||||
} else {
|
||||
CustomSnackBar.displaySnackBar('Please select days');
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -485,7 +506,10 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> getSchedule(GetScheduleEvent event, Emitter<TwoGangState> emit,) async {
|
||||
Future<void> getSchedule(
|
||||
GetScheduleEvent event,
|
||||
Emitter<TwoGangState> emit,
|
||||
) async {
|
||||
try {
|
||||
emit(LoadingInitialState());
|
||||
final response = await DevicesAPI.getSchedule(
|
||||
@@ -493,7 +517,8 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
|
||||
deviceId: twoGangId,
|
||||
);
|
||||
List<dynamic> jsonData = response;
|
||||
listSchedule = jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
|
||||
listSchedule =
|
||||
jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
|
||||
emit(InitialState());
|
||||
} on DioException catch (e) {
|
||||
final errorData = e.response!.data;
|
||||
@@ -514,9 +539,7 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
|
||||
try {
|
||||
emit(LoadingInitialState());
|
||||
final response = await DevicesAPI.changeSchedule(
|
||||
scheduleId: event.id,
|
||||
deviceUuid: twoGangId,
|
||||
enable: event.toggle);
|
||||
scheduleId: event.id, deviceUuid: twoGangId, enable: event.toggle);
|
||||
if (response == true) {
|
||||
add(GetScheduleEvent());
|
||||
toggleSchedule = event.toggle;
|
||||
@@ -537,7 +560,8 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
|
||||
emit(LoadingInitialState());
|
||||
final response = await DevicesAPI.deleteSchedule(
|
||||
scheduleId: event.id,
|
||||
deviceUuid: twoGangId, );
|
||||
deviceUuid: twoGangId,
|
||||
);
|
||||
if (response == true) {
|
||||
add(GetScheduleEvent());
|
||||
return toggleSchedule;
|
||||
|
||||
@@ -62,7 +62,7 @@ class GroupAllOffEvent extends TwoGangEvent {}
|
||||
|
||||
|
||||
// two_gang_event.dart
|
||||
class ToggleCreateScheduleEvent extends TwoGangEvent {}
|
||||
// class ToggleCreateScheduleEvent extends TwoGangEvent {}
|
||||
|
||||
|
||||
|
||||
@@ -125,6 +125,20 @@ class TabChangedEvent extends TwoGangEvent {
|
||||
}
|
||||
|
||||
|
||||
class ToggleSelectedEvent extends TwoGangEvent {
|
||||
final int index;
|
||||
const ToggleSelectedEvent({required this.index});
|
||||
@override
|
||||
List<Object> get props => [index];
|
||||
}
|
||||
|
||||
|
||||
class ToggleCreateScheduleEvent extends TwoGangEvent {
|
||||
final int index;
|
||||
const ToggleCreateScheduleEvent({required this.index});
|
||||
@override
|
||||
List<Object> get props => [index];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:syncrow_app/features/devices/model/groupTwoGangModel.dart';
|
||||
import 'package:syncrow_app/features/devices/model/group_two_gang_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/two_gang_model.dart';
|
||||
|
||||
|
||||
class TwoGangState extends Equatable {
|
||||
const TwoGangState();
|
||||
|
||||
@@ -11,7 +10,9 @@ class TwoGangState extends Equatable {
|
||||
}
|
||||
|
||||
class InitialState extends TwoGangState {}
|
||||
|
||||
class TwoGangSaveSchedule extends TwoGangState {}
|
||||
|
||||
class ChangeTimeState extends TwoGangState {}
|
||||
|
||||
class LoadingInitialState extends TwoGangState {}
|
||||
@@ -78,13 +79,12 @@ class TimerRunInProgress extends TwoGangState {
|
||||
}
|
||||
|
||||
class TimerRunComplete extends TwoGangState {}
|
||||
|
||||
class IsToggleState extends TwoGangState {
|
||||
final bool? onOff;
|
||||
const IsToggleState({this.onOff});
|
||||
}
|
||||
|
||||
|
||||
|
||||
// two_gang_state.dart
|
||||
class UpdateCreateScheduleState extends TwoGangState {
|
||||
final bool createSchedule;
|
||||
|
||||
@@ -48,6 +48,9 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
|
||||
on<TickTimer>(_onTickTimer);
|
||||
on<OnClose>(_onClose);
|
||||
on<SelectTimeEvent>(showTime);
|
||||
|
||||
on<ToggleSelectedEvent>(toggleSelectedIndex);
|
||||
on<ToggleCreateScheduleEvent>(toggleCreateSchedule);
|
||||
}
|
||||
|
||||
void _fetchWaterHeaterStatus(WaterHeaterInitial event, Emitter<WaterHeaterState> emit) async {
|
||||
@@ -201,7 +204,7 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
|
||||
CustomSnackBar.displaySnackBar('Save Successfully');
|
||||
add(GetScheduleEvent());
|
||||
emit(SaveSchedule());
|
||||
toggleCreateSchedule();
|
||||
add(const ToggleCreateScheduleEvent(index:1 ));
|
||||
}else{
|
||||
CustomSnackBar.displaySnackBar('Please select days');
|
||||
}
|
||||
@@ -272,22 +275,43 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
|
||||
}
|
||||
}
|
||||
|
||||
void toggleCreateSchedule() {
|
||||
emit(WHLoadingState());
|
||||
createSchedule = !createSchedule;
|
||||
selectedDays.clear();
|
||||
selectedTime=DateTime.now();
|
||||
emit(UpdateCreateScheduleState(createSchedule));
|
||||
}
|
||||
// void toggleCreateSchedule() {
|
||||
// emit(WHLoadingState());
|
||||
// createSchedule = !createSchedule;
|
||||
// selectedDays.clear();
|
||||
// selectedTime=DateTime.now();
|
||||
// emit(UpdateCreateScheduleState(createSchedule));
|
||||
// }
|
||||
|
||||
void toggleCreateCirculate() {
|
||||
emit(WHLoadingState());
|
||||
emit(WHLoadingState());
|
||||
createCirculate = !createCirculate;
|
||||
selectedDays.clear();
|
||||
selectedTime=DateTime.now();
|
||||
emit(UpdateCreateScheduleState(createCirculate));
|
||||
}
|
||||
|
||||
|
||||
// void toggleSelectedIndex(index) {
|
||||
// emit(WHLoadingState());
|
||||
// selectedTabIndex = index;
|
||||
// emit(ChangeSlidingSegmentState(value: selectedTabIndex));
|
||||
// }
|
||||
void toggleSelectedIndex( ToggleSelectedEvent event, Emitter<WaterHeaterState> emit) {
|
||||
emit(WHLoadingState());
|
||||
selectedTabIndex =event.index;
|
||||
emit(ChangeSlidingSegmentState(value: selectedTabIndex));
|
||||
}
|
||||
|
||||
|
||||
void toggleCreateSchedule(ToggleCreateScheduleEvent event, Emitter<WaterHeaterState> emit) {
|
||||
emit(WHLoadingState());
|
||||
createSchedule = !createSchedule;
|
||||
selectedDays.clear();
|
||||
selectedTime = DateTime.now();
|
||||
emit(UpdateCreateScheduleState(createSchedule));
|
||||
}
|
||||
|
||||
Future<void> toggleDaySelection(
|
||||
ToggleDaySelectionEvent event,
|
||||
Emitter<WaterHeaterState> emit,
|
||||
@@ -303,11 +327,6 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
|
||||
|
||||
int selectedTabIndex = 0;
|
||||
|
||||
void toggleSelectedIndex(index) {
|
||||
emit(WHLoadingState());
|
||||
selectedTabIndex = index;
|
||||
emit(ChangeSlidingSegmentState(value: selectedTabIndex));
|
||||
}
|
||||
|
||||
showTime(SelectTimeEvent event, Emitter<WaterHeaterState> emit) async {
|
||||
final TimeOfDay? timePicked = await showTimePicker(
|
||||
|
||||
@@ -98,4 +98,28 @@ class SelectTimeEvent extends WaterHeaterEvent {
|
||||
const SelectTimeEvent({required this.context, required this.isEffective});
|
||||
@override
|
||||
List<Object> get props => [context, isEffective];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class ToggleSelectedEvent extends WaterHeaterEvent {
|
||||
final int index;
|
||||
const ToggleSelectedEvent({required this.index});
|
||||
@override
|
||||
List<Object> get props => [index];
|
||||
}
|
||||
|
||||
|
||||
class ToggleCreateScheduleEvent extends WaterHeaterEvent {
|
||||
final int index;
|
||||
const ToggleCreateScheduleEvent({required this.index});
|
||||
@override
|
||||
List<Object> get props => [index];
|
||||
}
|
||||
|
||||
|
||||
class ToggleCreateCirculateEvent extends WaterHeaterEvent {
|
||||
final int index;
|
||||
const ToggleCreateCirculateEvent({required this.index});
|
||||
@override
|
||||
List<Object> get props => [index];
|
||||
}
|
||||
|
||||
@@ -42,7 +42,9 @@ class DevicesCategoryModel {
|
||||
: name = json['groupName'],
|
||||
// id = json['groupId'],
|
||||
type = devicesTypesMap[json['groupName']] ?? DeviceType.Other,
|
||||
icon = deviceTypeIconMap[devicesTypesMap[json['groupName']] ?? DeviceType.Other] ?? '',
|
||||
icon = deviceTypeIconMap[
|
||||
devicesTypesMap[json['groupName']] ?? DeviceType.Other] ??
|
||||
'',
|
||||
devices = [],
|
||||
isSelected = false;
|
||||
|
||||
@@ -60,5 +62,9 @@ Map<DeviceType, String> deviceTypeIconMap = {
|
||||
DeviceType.CeilingSensor: Assets.assetsIconsSensors,
|
||||
DeviceType.WallSensor: Assets.assetsIconsSensors,
|
||||
DeviceType.ThreeGang: Assets.assetsIconsGang,
|
||||
DeviceType.OneGang: Assets.oneGang,
|
||||
DeviceType.TwoGang: Assets.twoGang,
|
||||
DeviceType.WH: Assets.waterHeaterIcon,
|
||||
DeviceType.DS: Assets.doorSensorIcon,
|
||||
DeviceType.Other: Assets.assetsIconsAC,
|
||||
};
|
||||
|
||||
@@ -62,11 +62,14 @@ class DeviceModel {
|
||||
tempIcon = Assets.oneGang;
|
||||
} else if (type == DeviceType.TwoGang) {
|
||||
tempIcon = Assets.twoGang;
|
||||
}else if (type == DeviceType.WH) {
|
||||
} else if (type == DeviceType.WH) {
|
||||
tempIcon = Assets.waterHeaterIcon;
|
||||
} else if (type == DeviceType.DS) {
|
||||
tempIcon = Assets.doorSensorIcon;
|
||||
} else {
|
||||
tempIcon = Assets.assetsIconsLogo;
|
||||
}
|
||||
|
||||
return DeviceModel(
|
||||
icon: tempIcon,
|
||||
activeTime: json['activeTime'],
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
class DeviceReport {
|
||||
final dynamic deviceUuid;
|
||||
final dynamic startTime;
|
||||
final dynamic endTime;
|
||||
final List<DeviceEvent>? data;
|
||||
|
||||
DeviceReport({
|
||||
this.deviceUuid,
|
||||
this.startTime,
|
||||
this.endTime,
|
||||
this.data,
|
||||
});
|
||||
|
||||
DeviceReport.fromJson(Map<String, dynamic> json)
|
||||
: deviceUuid = json['deviceUuid'] as String?,
|
||||
startTime = json['startTime'] as String?,
|
||||
endTime = json['endTime'] as String?,
|
||||
data = (json['data'] as List<dynamic>?)
|
||||
?.map((e) => DeviceEvent.fromJson(e as Map<String, dynamic>))
|
||||
.toList();
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'deviceUuid': deviceUuid,
|
||||
'startTime': startTime,
|
||||
'endTime': endTime,
|
||||
'data': data?.map((e) => e.toJson()).toList(),
|
||||
};
|
||||
}
|
||||
|
||||
class DeviceEvent {
|
||||
final String? code;
|
||||
final int? eventTime;
|
||||
final String? value;
|
||||
|
||||
DeviceEvent({
|
||||
this.code,
|
||||
this.eventTime,
|
||||
this.value,
|
||||
});
|
||||
|
||||
DeviceEvent.fromJson(Map<String, dynamic> json)
|
||||
: code = json['code'] as String?,
|
||||
eventTime = json['eventTime'] as int?,
|
||||
value = json['value'] as String?;
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'code': code,
|
||||
'eventTime': eventTime,
|
||||
'value': value,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
|
||||
|
||||
|
||||
|
||||
import 'package:syncrow_app/features/devices/model/status_model.dart';
|
||||
|
||||
class DoorSensorModel {
|
||||
bool doorContactState;
|
||||
int batteryPercentage;
|
||||
|
||||
DoorSensorModel(
|
||||
{required this.doorContactState,
|
||||
required this.batteryPercentage,
|
||||
});
|
||||
|
||||
factory DoorSensorModel.fromJson(List<StatusModel> jsonList) {
|
||||
late bool _doorContactState;
|
||||
late int _batteryPercentage;
|
||||
|
||||
|
||||
for (int i = 0; i < jsonList.length; i++) {
|
||||
if (jsonList[i].code == 'doorcontact_state') {
|
||||
_doorContactState = jsonList[i].value ?? false;
|
||||
} else if (jsonList[i].code == 'battery_percentage') {
|
||||
_batteryPercentage = jsonList[i].value ?? 0;
|
||||
}
|
||||
}
|
||||
return DoorSensorModel(
|
||||
doorContactState: _doorContactState,
|
||||
batteryPercentage: _batteryPercentage,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
class GroupOneGangModel {
|
||||
final String deviceId;
|
||||
final String deviceName;
|
||||
bool firstSwitch;
|
||||
|
||||
GroupOneGangModel({
|
||||
required this.deviceId,
|
||||
required this.deviceName,
|
||||
required this.firstSwitch,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// Record model
|
||||
class Record {
|
||||
final String status;
|
||||
final String time;
|
||||
final bool isOpen;
|
||||
|
||||
Record({
|
||||
required this.status,
|
||||
required this.time,
|
||||
required this.isOpen,
|
||||
});
|
||||
}
|
||||
|
||||
// RecordGroup model to group records by date
|
||||
class RecordGroup {
|
||||
final DateTime date;
|
||||
final List<Record> records;
|
||||
|
||||
RecordGroup({
|
||||
required this.date,
|
||||
required this.records,
|
||||
});
|
||||
}
|
||||
@@ -1,9 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/universal_switch.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/devices_default_switch.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
|
||||
|
||||
class CurtainList extends StatelessWidget {
|
||||
|
||||
@@ -20,16 +20,16 @@ class CurtainView extends StatelessWidget {
|
||||
child: BlocBuilder<CurtainBloc, CurtainState>(
|
||||
builder: (context, state) {
|
||||
double curtainWidth = 270;
|
||||
double blindHeight = 310;
|
||||
// double blindHeight = 310;
|
||||
if (state is CurtainsOpening) {
|
||||
curtainWidth = state.curtainWidth;
|
||||
blindHeight = state.blindHeight;
|
||||
// blindHeight = state.blindHeight;
|
||||
} else if (state is CurtainsClosing) {
|
||||
curtainWidth = state.curtainWidth;
|
||||
blindHeight = state.blindHeight;
|
||||
// blindHeight = state.blindHeight;
|
||||
} else if (state is CurtainsPaused) {
|
||||
curtainWidth = state.curtainWidth;
|
||||
blindHeight = state.blindHeight;
|
||||
// blindHeight = state.blindHeight;
|
||||
}
|
||||
return DefaultScaffold(
|
||||
title: curtain.name,
|
||||
@@ -58,7 +58,8 @@ class CurtainView extends StatelessWidget {
|
||||
width: curtainWidth,
|
||||
child: Stack(
|
||||
children: List.generate(
|
||||
10, (index) {
|
||||
10,
|
||||
(index) {
|
||||
double spacing = curtainWidth / 9;
|
||||
double leftMostPosition = index * spacing;
|
||||
return AnimatedPositioned(
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/popup_menu_widget.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
||||
@@ -11,30 +10,33 @@ class DeviceAppbar extends StatelessWidget implements PreferredSizeWidget {
|
||||
final String deviceUuid;
|
||||
final double appBarHeight = 56.0;
|
||||
final void Function()? onPressed;
|
||||
const DeviceAppbar({super.key, required this.deviceName, required this.deviceUuid,this.onPressed});
|
||||
const DeviceAppbar(
|
||||
{super.key, required this.deviceName, required this.deviceUuid, this.onPressed});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AppBar(
|
||||
return AppBar(
|
||||
backgroundColor: Colors.transparent,
|
||||
centerTitle: true,
|
||||
title: BodyLarge(
|
||||
text: deviceName ?? "",
|
||||
text: deviceName,
|
||||
fontColor: ColorsManager.primaryColor,
|
||||
fontWeight: FontsManager.bold,
|
||||
),
|
||||
actions: [
|
||||
IconButton(onPressed: () {
|
||||
showPopupMenu(context: context, items: [
|
||||
PopupMenuItem(
|
||||
onTap: () async {
|
||||
HomeCubit.getInstance().updateDevice(deviceUuid);
|
||||
},
|
||||
value: 'Update',
|
||||
child: const Text('Update'),
|
||||
)
|
||||
]);
|
||||
}, icon: Icon(Icons.edit))
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
showPopupMenu(context: context, items: [
|
||||
PopupMenuItem(
|
||||
onTap: () async {
|
||||
HomeCubit.getInstance().updateDevice(deviceUuid);
|
||||
},
|
||||
value: 'Update',
|
||||
child: const Text('Update'),
|
||||
)
|
||||
]);
|
||||
},
|
||||
icon: Icon(Icons.edit))
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/door_sensor_bloc/door_sensor_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/door_sensor_bloc/door_sensor_event.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/door_sensor_bloc/door_sensor_state.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
|
||||
class NotificationSettingsPage extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DefaultScaffold(
|
||||
title: 'Notification Settings',
|
||||
child: BlocProvider(
|
||||
create: (context) => DoorSensorBloc(DSId: '')..add(const DoorSensorInitial()),
|
||||
child: BlocBuilder<DoorSensorBloc, DoorSensorState>(
|
||||
builder: (context, state) {
|
||||
final doorSensorBloc = BlocProvider.of<DoorSensorBloc>(context);
|
||||
|
||||
return state is DoorSensorLoadingState
|
||||
? const Center(
|
||||
child: DefaultContainer(
|
||||
width: 50, height: 50, child: CircularProgressIndicator()),
|
||||
)
|
||||
: Column(
|
||||
children: [
|
||||
DefaultContainer(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 50,
|
||||
child: ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
leading: const BodyLarge(
|
||||
text: 'Low Battery',
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
trailing: Transform.scale(
|
||||
scale: .8,
|
||||
child: CupertinoSwitch(
|
||||
value: doorSensorBloc.lowBattery,
|
||||
onChanged: (value) {
|
||||
context
|
||||
.read<DoorSensorBloc>()
|
||||
.add(ToggleLowBatteryEvent(value));
|
||||
},
|
||||
applyTheme: true,
|
||||
)),
|
||||
),
|
||||
),
|
||||
const Divider(
|
||||
color: ColorsManager.graysColor,
|
||||
),
|
||||
SizedBox(
|
||||
height: 50,
|
||||
child: ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
leading: const BodyLarge(
|
||||
text: 'Closing Reminder',
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
trailing: Transform.scale(
|
||||
scale: .8,
|
||||
child: CupertinoSwitch(
|
||||
value: doorSensorBloc.closingReminder,
|
||||
onChanged: (value) {
|
||||
context
|
||||
.read<DoorSensorBloc>()
|
||||
.add(ToggleClosingReminderEvent(value));
|
||||
},
|
||||
applyTheme: true,
|
||||
)),
|
||||
),
|
||||
),
|
||||
const Divider(
|
||||
color: ColorsManager.graysColor,
|
||||
),
|
||||
SizedBox(
|
||||
height: 50,
|
||||
child: ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
leading: const BodyLarge(
|
||||
text: 'Door Alarm',
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
trailing: Transform.scale(
|
||||
scale: .8,
|
||||
child: CupertinoSwitch(
|
||||
value: doorSensorBloc.closingReminder,
|
||||
onChanged: (value) {
|
||||
context
|
||||
.read<DoorSensorBloc>()
|
||||
.add(ToggleDoorAlarmEvent(value));
|
||||
},
|
||||
applyTheme: true,
|
||||
)),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/door_sensor_bloc/door_sensor_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/door_sensor_bloc/door_sensor_event.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/door_sensor_bloc/door_sensor_state.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_report_model.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
|
||||
class DoorRecordsScreen extends StatelessWidget {
|
||||
final String DSId;
|
||||
const DoorRecordsScreen({super.key, required this.DSId});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DefaultScaffold(
|
||||
title: 'Records',
|
||||
child: BlocProvider(
|
||||
create: (context) =>
|
||||
DoorSensorBloc(DSId: DSId)..add(const ReportLogsInitial()),
|
||||
child: BlocBuilder<DoorSensorBloc, DoorSensorState>(
|
||||
builder: (context, state) {
|
||||
final doorSensorBloc = BlocProvider.of<DoorSensorBloc>(context);
|
||||
|
||||
if (state is DoorSensorLoadingState) {
|
||||
return const Center(
|
||||
child: DefaultContainer(
|
||||
width: 50, height: 50, child: CircularProgressIndicator()),
|
||||
);
|
||||
} else if (state is UpdateState) {
|
||||
// Group records by formatted date
|
||||
final Map<String, List<DeviceEvent>> groupedRecords = {};
|
||||
|
||||
// Iterate over the data list in DeviceReport
|
||||
for (var record in doorSensorBloc.recordGroups.data!) {
|
||||
final DateTime eventDateTime =
|
||||
DateTime.fromMillisecondsSinceEpoch(record.eventTime!);
|
||||
final String formattedDate =
|
||||
DateFormat('EEEE, dd/MM/yyyy').format(eventDateTime);
|
||||
|
||||
// Group by formatted date
|
||||
if (groupedRecords.containsKey(formattedDate)) {
|
||||
groupedRecords[formattedDate]!.add(record);
|
||||
} else {
|
||||
groupedRecords[formattedDate] = [record];
|
||||
}
|
||||
}
|
||||
|
||||
// Build the ListView with grouped data
|
||||
return ListView.builder(
|
||||
itemCount: groupedRecords.length,
|
||||
itemBuilder: (context, index) {
|
||||
final String date = groupedRecords.keys.elementAt(index);
|
||||
final List<DeviceEvent> recordsForDate =
|
||||
groupedRecords[date]!;
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Date header
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Text(
|
||||
date,
|
||||
style: const TextStyle(
|
||||
color: ColorsManager.grayColor,
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
),
|
||||
),
|
||||
// List of records for the specific date
|
||||
DefaultContainer(
|
||||
child: Column(
|
||||
children: [
|
||||
...recordsForDate.asMap().entries.map((entry) {
|
||||
final int idx = entry.key;
|
||||
final DeviceEvent record = entry.value;
|
||||
final DateTime eventDateTime =
|
||||
DateTime.fromMillisecondsSinceEpoch(
|
||||
record.eventTime!);
|
||||
final String formattedTime =
|
||||
DateFormat('HH:mm:ss').format(eventDateTime);
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
Container(
|
||||
child: ListTile(
|
||||
leading: Icon(
|
||||
record.value == 'true'
|
||||
? Icons.radio_button_checked
|
||||
: Icons.radio_button_unchecked,
|
||||
color: record.value == 'true'
|
||||
? Colors.blue
|
||||
: Colors.grey,
|
||||
),
|
||||
title: Text(
|
||||
record.value == 'true'
|
||||
? "Opened"
|
||||
: "Closed",
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 18,
|
||||
),
|
||||
),
|
||||
subtitle: Text('$formattedTime'),
|
||||
),
|
||||
),
|
||||
// Only add Divider if it's not the last item
|
||||
if (idx != recordsForDate.length - 1)
|
||||
const Divider(
|
||||
color: ColorsManager.graysColor,
|
||||
),
|
||||
],
|
||||
);
|
||||
}).toList(),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
return const Center(child: Text('No data available.'));
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/door_sensor_bloc/door_sensor_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/door_sensor_bloc/door_sensor_event.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/door_sensor_bloc/door_sensor_state.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/door_sensor_model.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/door_sensor/door_notification_settings.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/door_sensor/door_records_screen.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/battery_bar.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
|
||||
import 'package:syncrow_app/generated/assets.dart';
|
||||
|
||||
class DoorSensorScreen extends StatelessWidget {
|
||||
final DeviceModel? device;
|
||||
|
||||
const DoorSensorScreen({super.key, this.device});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DefaultScaffold(
|
||||
title: 'Door Sensor',
|
||||
child: BlocProvider(
|
||||
create: (context) =>
|
||||
DoorSensorBloc(DSId: device?.uuid ?? '')..add(const DoorSensorInitial()),
|
||||
child: BlocBuilder<DoorSensorBloc, DoorSensorState>(
|
||||
builder: (context, state) {
|
||||
final doorSensorBloc = BlocProvider.of<DoorSensorBloc>(context);
|
||||
DoorSensorModel model = DoorSensorModel(batteryPercentage: 0, doorContactState: false);
|
||||
if (state is LoadingNewSate) {
|
||||
model = state.doorSensor;
|
||||
} else if (state is UpdateState) {
|
||||
model = state.doorSensor;
|
||||
}
|
||||
return state is DoorSensorLoadingState
|
||||
? const Center(
|
||||
child:
|
||||
DefaultContainer(width: 50, height: 50, child: CircularProgressIndicator()),
|
||||
)
|
||||
: RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
doorSensorBloc.add(const DoorSensorInitial());
|
||||
},
|
||||
child: ListView(
|
||||
children: [
|
||||
SizedBox(
|
||||
height: MediaQuery.sizeOf(context).height * 0.8,
|
||||
child: Column(
|
||||
children: [
|
||||
BatteryBar(
|
||||
batteryPercentage: model.batteryPercentage,
|
||||
),
|
||||
Expanded(
|
||||
flex: 4,
|
||||
child: InkWell(
|
||||
overlayColor: WidgetStateProperty.all(Colors.transparent),
|
||||
onTap: () {},
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
// color: Colors.white.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(890),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.white.withOpacity(0.1),
|
||||
blurRadius: 24,
|
||||
offset: const Offset(-5, -5),
|
||||
blurStyle: BlurStyle.outer,
|
||||
),
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.11),
|
||||
blurRadius: 25,
|
||||
offset: const Offset(5, 5),
|
||||
blurStyle: BlurStyle.outer,
|
||||
),
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.13),
|
||||
blurRadius: 30,
|
||||
offset: const Offset(5, 5),
|
||||
blurStyle: BlurStyle.inner,
|
||||
),
|
||||
],
|
||||
),
|
||||
child: SvgPicture.asset(
|
||||
model.doorContactState
|
||||
? Assets.doorOpen
|
||||
: Assets.doorClose,
|
||||
fit: BoxFit.fill,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: DefaultContainer(
|
||||
onTap: () {
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (context) =>
|
||||
DoorRecordsScreen(DSId: device!.uuid!)),
|
||||
);
|
||||
},
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
ConstrainedBox(
|
||||
constraints:
|
||||
const BoxConstraints(maxHeight: 46, maxWidth: 50),
|
||||
child: SvgPicture.asset(Assets.doorRecordsIcon),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 15,
|
||||
),
|
||||
const Flexible(
|
||||
child: FittedBox(
|
||||
child: BodySmall(
|
||||
text: 'Records',
|
||||
// doorLockButtons.keys.elementAt(index),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Expanded(
|
||||
child: DefaultContainer(
|
||||
onTap: () {
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (context) => NotificationSettingsPage()),
|
||||
);
|
||||
},
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
ConstrainedBox(
|
||||
constraints:
|
||||
const BoxConstraints(maxHeight: 46, maxWidth: 50),
|
||||
child:
|
||||
SvgPicture.asset(Assets.doorNotificationSetting),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 15,
|
||||
),
|
||||
const Flexible(
|
||||
child: FittedBox(
|
||||
child: BodySmall(
|
||||
text: 'Notification Settings',
|
||||
// doorLockButtons.keys.elementAt(index),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -8,12 +8,10 @@ import 'package:syncrow_app/features/devices/bloc/gateway_bloc/gateway_state.dar
|
||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/device_appbar.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/room_page_switch.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
||||
import 'package:syncrow_app/generated/assets.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/constants.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
|
||||
|
||||
class GateWayView extends StatelessWidget {
|
||||
final DeviceModel gatewayObj;
|
||||
@@ -38,9 +36,10 @@ class GateWayView extends StatelessWidget {
|
||||
backgroundColor: ColorsManager.backgroundColor,
|
||||
extendBodyBehindAppBar: true,
|
||||
extendBody: true,
|
||||
appBar:DeviceAppbar(
|
||||
deviceName: 'Gateway',
|
||||
deviceUuid: gatewayObj.uuid!,),
|
||||
appBar: DeviceAppbar(
|
||||
deviceName: 'Gateway',
|
||||
deviceUuid: gatewayObj.uuid!,
|
||||
),
|
||||
body: Container(
|
||||
width: MediaQuery.sizeOf(context).width,
|
||||
height: MediaQuery.sizeOf(context).height,
|
||||
@@ -55,11 +54,11 @@ class GateWayView extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
child: RefreshIndicator(
|
||||
onRefresh:()async {
|
||||
BlocProvider.of<GatewayBloc>(context).add(GatewayInitial(gatewayId: gatewayObj.uuid ?? ''));
|
||||
},
|
||||
child: ListView(
|
||||
|
||||
onRefresh: () async {
|
||||
BlocProvider.of<GatewayBloc>(context)
|
||||
.add(GatewayInitial(gatewayId: gatewayObj.uuid ?? ''));
|
||||
},
|
||||
child: ListView(
|
||||
children: [
|
||||
Container(
|
||||
height: MediaQuery.of(context).size.height,
|
||||
@@ -120,7 +119,8 @@ class GateWayView extends StatelessWidget {
|
||||
)
|
||||
: Expanded(
|
||||
child: GridView.builder(
|
||||
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
gridDelegate:
|
||||
const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
crossAxisSpacing: 10,
|
||||
mainAxisSpacing: 10,
|
||||
@@ -141,8 +141,7 @@ class GateWayView extends StatelessWidget {
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
));
|
||||
)));
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/lights/lights_list.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/universal_switch.dart';
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@@ -7,7 +5,6 @@ import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_blo
|
||||
import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_event.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_state.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/smart_door/repeat_widget.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_button.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/door_lock_button.dart';
|
||||
@@ -29,14 +26,12 @@ class OfflineOneTimePasswordPage extends StatelessWidget {
|
||||
create: (BuildContext context) => SmartDoorBloc(deviceId: deviceId!),
|
||||
child: BlocConsumer<SmartDoorBloc, SmartDoorState>(listener: (context, state) {
|
||||
if (state is FailedState) {
|
||||
CustomSnackBar.displaySnackBar(
|
||||
state.errorMessage
|
||||
);
|
||||
CustomSnackBar.displaySnackBar(state.errorMessage);
|
||||
}
|
||||
if (state is IsRepeatState){
|
||||
if (state is IsRepeatState) {
|
||||
isRepeat = state.repeat;
|
||||
}
|
||||
if (state is GeneratePasswordOneTimestate ){
|
||||
if (state is GeneratePasswordOneTimestate) {
|
||||
generated = state.generated;
|
||||
}
|
||||
}, builder: (context, state) {
|
||||
@@ -54,170 +49,173 @@ class OfflineOneTimePasswordPage extends StatelessWidget {
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(true);
|
||||
},
|
||||
icon: const Icon(Icons.arrow_back)
|
||||
),
|
||||
icon: const Icon(Icons.arrow_back)),
|
||||
),
|
||||
child: state is LoadingInitialState
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const BodyMedium(
|
||||
text: 'Save the password immediately. The password is not displayed in the app.',
|
||||
fontWeight: FontWeight.normal,
|
||||
fontColor: ColorsManager.grayColor,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
const BodyMedium(
|
||||
text: '7-Digit Password',
|
||||
fontWeight: FontWeight.normal,
|
||||
fontColor: ColorsManager.grayColor,
|
||||
),
|
||||
DefaultContainer(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 15),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Flexible(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children:smartDoorBloc.passwordController.text.isEmpty?
|
||||
List.generate(10, (index) {
|
||||
return const Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 4.0,vertical: 15),
|
||||
child: Icon(
|
||||
Icons.circle,
|
||||
size: 20.0,
|
||||
color: Colors.black,
|
||||
),
|
||||
);
|
||||
}) :[
|
||||
Expanded(
|
||||
child: Row(
|
||||
children: [
|
||||
|
||||
Expanded(
|
||||
child: BodyLarge(
|
||||
style: const TextStyle(
|
||||
color: ColorsManager.primaryColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
letterSpacing: 8.0 ,
|
||||
fontSize: 25,
|
||||
wordSpacing: 2),
|
||||
textAlign: TextAlign.center,
|
||||
text: smartDoorBloc.passwordController.text,
|
||||
fontSize: 23,
|
||||
),),
|
||||
|
||||
IconButton(
|
||||
onPressed: () async {
|
||||
await Clipboard.setData(ClipboardData(
|
||||
text: smartDoorBloc.passwordController.text));
|
||||
},
|
||||
icon: const Icon(Icons.copy)
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
)),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
|
||||
],
|
||||
const BodyMedium(
|
||||
text:
|
||||
'Save the password immediately. The password is not displayed in the app.',
|
||||
fontWeight: FontWeight.normal,
|
||||
fontColor: ColorsManager.grayColor,
|
||||
),
|
||||
if(smartDoorBloc.passwordController.text.isNotEmpty)
|
||||
Column(
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
const BodyMedium(
|
||||
text: '7-Digit Password',
|
||||
fontWeight: FontWeight.normal,
|
||||
fontColor: ColorsManager.grayColor,
|
||||
),
|
||||
DefaultContainer(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 15),
|
||||
child: Column(
|
||||
children: [
|
||||
const Divider(
|
||||
color: ColorsManager.graysColor,
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
child: const BodyMedium(
|
||||
text: 'Password Name',
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: smartDoorBloc.passwordController.text.isEmpty
|
||||
? List.generate(10, (index) {
|
||||
return const Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 4.0, vertical: 15),
|
||||
child: Icon(
|
||||
Icons.circle,
|
||||
size: 20.0,
|
||||
color: Colors.black,
|
||||
),
|
||||
);
|
||||
})
|
||||
: [
|
||||
Expanded(
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: BodyLarge(
|
||||
style: const TextStyle(
|
||||
color: ColorsManager.primaryColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
letterSpacing: 8.0,
|
||||
fontSize: 25,
|
||||
wordSpacing: 2),
|
||||
textAlign: TextAlign.center,
|
||||
text: smartDoorBloc.passwordController.text,
|
||||
fontSize: 23,
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () async {
|
||||
await Clipboard.setData(ClipboardData(
|
||||
text: smartDoorBloc
|
||||
.passwordController.text));
|
||||
},
|
||||
icon: const Icon(Icons.copy)),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
)),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
SizedBox(
|
||||
width: MediaQuery.of(context).size.width / 2.6,
|
||||
child: TextFormField(
|
||||
controller: BlocProvider.of<SmartDoorBloc>(context).passwordNameController,
|
||||
decoration: const InputDecoration(
|
||||
hintText: 'Enter The Name',
|
||||
hintStyle: TextStyle(
|
||||
fontSize: 14, color: ColorsManager.textGray)),
|
||||
)),
|
||||
],
|
||||
),
|
||||
|
||||
if (smartDoorBloc.passwordController.text.isNotEmpty)
|
||||
Column(
|
||||
children: [
|
||||
const Divider(
|
||||
color: ColorsManager.graysColor,
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
child: const BodyMedium(
|
||||
text: 'Password Name',
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: MediaQuery.of(context).size.width / 2.6,
|
||||
child: TextFormField(
|
||||
controller: BlocProvider.of<SmartDoorBloc>(context)
|
||||
.passwordNameController,
|
||||
decoration: const InputDecoration(
|
||||
hintText: 'Enter The Name',
|
||||
hintStyle: TextStyle(
|
||||
fontSize: 14, color: ColorsManager.textGray)),
|
||||
)),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
const BodyMedium(
|
||||
textAlign: TextAlign.center,
|
||||
text:
|
||||
'Save the password immediately. The password is not displayed in the app.',
|
||||
fontWeight: FontWeight.normal,
|
||||
fontColor: ColorsManager.grayColor,
|
||||
),
|
||||
|
||||
// NameTimeWidget(type:type!),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
Center(
|
||||
child: SizedBox(
|
||||
width: MediaQuery.of(context).size.width / 1.5,
|
||||
child: DoorLockButton(
|
||||
isDone: generated,
|
||||
isLoading: smartDoorBloc.isSavingPassword,
|
||||
borderRadius: 30,
|
||||
backgroundColor: ColorsManager.primaryColor,
|
||||
onPressed: () async {
|
||||
if (generated == false) {
|
||||
smartDoorBloc
|
||||
.add(GenerateAndSavePasswordOneTimeEvent(context: context));
|
||||
} else {
|
||||
if (smartDoorBloc.passwordNameController.text.isNotEmpty) {
|
||||
smartDoorBloc.add(RenamePasswordEvent());
|
||||
}
|
||||
Navigator.of(context).pop(true);
|
||||
}
|
||||
},
|
||||
child: const BodyMedium(
|
||||
text: 'Obtain Password',
|
||||
fontWeight: FontWeight.bold,
|
||||
fontColor: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
isRepeat ? const RepeatWidget() : const SizedBox(),
|
||||
const SizedBox(
|
||||
height: 40,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
const BodyMedium(
|
||||
textAlign: TextAlign.center,
|
||||
text: 'Save the password immediately. The password is not displayed in the app.',
|
||||
fontWeight: FontWeight.normal,
|
||||
fontColor: ColorsManager.grayColor,
|
||||
),
|
||||
|
||||
// NameTimeWidget(type:type!),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
Center(
|
||||
child: SizedBox(
|
||||
width: MediaQuery.of(context).size.width/1.5,
|
||||
child: DoorLockButton(
|
||||
isDone: generated,
|
||||
isLoading: smartDoorBloc.isSavingPassword ,
|
||||
borderRadius: 30,
|
||||
backgroundColor:ColorsManager.primaryColor ,
|
||||
onPressed: () async {
|
||||
if(generated==false){
|
||||
smartDoorBloc.add(GenerateAndSavePasswordOneTimeEvent(context: context));
|
||||
}else{
|
||||
if(smartDoorBloc.passwordNameController.text.isNotEmpty){
|
||||
smartDoorBloc.add(RenamePasswordEvent());
|
||||
}
|
||||
Navigator.of(context).pop(true);
|
||||
}
|
||||
},
|
||||
child: const BodyMedium(
|
||||
text: 'Obtain Password',
|
||||
fontWeight: FontWeight.bold,
|
||||
fontColor: Colors.white,
|
||||
),),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
isRepeat? const RepeatWidget():const SizedBox(),
|
||||
const SizedBox(
|
||||
height: 40,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ import 'package:flutter/services.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/device_appbar.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/one_gang/one_gang_screen.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/two_gang/two_gang_screen.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
||||
import 'package:syncrow_app/generated/assets.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/one_gang_bloc/one_gang_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/one_gang_bloc/one_gang_event.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/one_gang_bloc/one_gang_state.dart';
|
||||
import 'package:syncrow_app/features/devices/model/group_one_gang_model.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/devices_default_switch.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
|
||||
|
||||
class OneGangList extends StatelessWidget {
|
||||
const OneGangList({super.key, required this.oneGangList, required this.allSwitches});
|
||||
|
||||
final List<GroupOneGangModel> oneGangList;
|
||||
final bool allSwitches;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<OneGangBloc, OneGangState>(
|
||||
builder: (context, state) {
|
||||
return SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
const SizedBox(height: 10),
|
||||
const BodySmall(text: 'All Lights'),
|
||||
const SizedBox(height: 5),
|
||||
DevicesDefaultSwitch(
|
||||
switchValue: allSwitches,
|
||||
action: () {
|
||||
BlocProvider.of<OneGangBloc>(context).add(GroupAllOnEvent());
|
||||
},
|
||||
secondAction: () {
|
||||
BlocProvider.of<OneGangBloc>(context).add(GroupAllOffEvent());
|
||||
},
|
||||
),
|
||||
ListView.builder(
|
||||
shrinkWrap: true,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
padding: const EdgeInsets.all(0),
|
||||
itemCount: oneGangList.length,
|
||||
itemBuilder: (context, index) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(height: 10),
|
||||
BodySmall(text: oneGangList[index].deviceName),
|
||||
const SizedBox(height: 5),
|
||||
DevicesDefaultSwitch(
|
||||
switchValue: oneGangList[index].firstSwitch,
|
||||
action: () {
|
||||
BlocProvider.of<OneGangBloc>(context).add(ChangeFirstSwitchStatusEvent(
|
||||
value: oneGangList[index].firstSwitch,
|
||||
deviceId: oneGangList[index].deviceId));
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,9 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/one_gang_bloc/one_gang_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/one_gang_bloc/one_gang_state.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/group_one_gang_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/one_gang_model.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/one_gang/one_gang_list.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/one_gang/one_gang_timer_screen.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/three_gang/gang_switch.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||
@@ -20,10 +22,9 @@ class OneGangScreen extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider(
|
||||
create: (context) => OneGangBloc(
|
||||
switchCode: 'switch_1',
|
||||
oneGangId : device?.uuid ?? '')
|
||||
..add(const InitialEvent(groupScreen:false)),
|
||||
create: (context) =>
|
||||
OneGangBloc(switchCode: 'switch_1', oneGangId: device?.uuid ?? '')
|
||||
..add(const InitialEvent(groupScreen: false)),
|
||||
child: BlocBuilder<OneGangBloc, OneGangState>(
|
||||
builder: (context, state) {
|
||||
OneGangModel oneGangModel = OneGangModel(
|
||||
@@ -31,141 +32,166 @@ class OneGangScreen extends StatelessWidget {
|
||||
firstCountDown: 0,
|
||||
);
|
||||
|
||||
List<GroupOneGangModel> groupOneGangModel = [];
|
||||
bool allSwitchesOn = false;
|
||||
|
||||
if (state is LoadingNewSate) {
|
||||
oneGangModel = state.oneGangModel;
|
||||
} else if (state is UpdateState) {
|
||||
oneGangModel = state.oneGangModel;
|
||||
} else if (state is UpdateGroupState) {
|
||||
groupOneGangModel = state.oneGangList;
|
||||
allSwitchesOn = state.allSwitches;
|
||||
}
|
||||
return state is LoadingInitialState ?
|
||||
const Center(
|
||||
child:
|
||||
DefaultContainer(width: 50, height: 50, child: CircularProgressIndicator()),
|
||||
):
|
||||
RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
BlocProvider.of<OneGangBloc>(context)
|
||||
.add(InitialEvent(groupScreen: device != null ? false : true));
|
||||
},
|
||||
child: ListView(
|
||||
children: [
|
||||
SizedBox(
|
||||
height: MediaQuery.of(context).size.height,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
const Expanded(child: SizedBox.shrink()),
|
||||
Expanded(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Column(
|
||||
return state is LoadingInitialState
|
||||
? const Center(
|
||||
child: DefaultContainer(
|
||||
width: 50,
|
||||
height: 50,
|
||||
child: CircularProgressIndicator()),
|
||||
)
|
||||
: device == null
|
||||
? OneGangList(
|
||||
oneGangList: groupOneGangModel,
|
||||
allSwitches: allSwitchesOn)
|
||||
: RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
BlocProvider.of<OneGangBloc>(context).add(InitialEvent(
|
||||
groupScreen: device != null ? false : true));
|
||||
},
|
||||
child: ListView(
|
||||
children: [
|
||||
SizedBox(
|
||||
height: MediaQuery.of(context).size.height,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
GangSwitch(
|
||||
threeGangSwitch: device!,
|
||||
value: oneGangModel.firstSwitch,
|
||||
action: () {
|
||||
BlocProvider.of<OneGangBloc>(context).add(
|
||||
ChangeFirstSwitchStatusEvent(
|
||||
value: oneGangModel.firstSwitch));
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
const SizedBox(
|
||||
width: 70,
|
||||
child: BodySmall(
|
||||
text:" Entrance Light",
|
||||
fontColor: ColorsManager.textPrimaryColor,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Center(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const SizedBox(
|
||||
width: 20,
|
||||
),
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Card(
|
||||
elevation: 3,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(100),
|
||||
),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
pageBuilder: (context, animation1, animation2) => TimerScheduleScreen(
|
||||
switchCode:'switch_1' ,
|
||||
device: device!,
|
||||
deviceCode: 'countdown_1',
|
||||
)));
|
||||
},
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Container(
|
||||
width: 60,
|
||||
height: 60,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey[300],
|
||||
borderRadius: BorderRadius.circular(100),
|
||||
const Expanded(child: SizedBox.shrink()),
|
||||
Expanded(
|
||||
child: Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceAround,
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.center,
|
||||
children: [
|
||||
Column(
|
||||
children: [
|
||||
GangSwitch(
|
||||
threeGangSwitch: device!,
|
||||
value: oneGangModel.firstSwitch,
|
||||
action: () {
|
||||
BlocProvider.of<OneGangBloc>(
|
||||
context)
|
||||
.add(
|
||||
ChangeFirstSwitchStatusEvent(
|
||||
value: oneGangModel
|
||||
.firstSwitch));
|
||||
},
|
||||
),
|
||||
),
|
||||
Container(
|
||||
width: 40,
|
||||
height: 40,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(100),
|
||||
),
|
||||
child: Center(
|
||||
child: Icon(
|
||||
Icons.access_time,
|
||||
color:
|
||||
ColorsManager.primaryColorWithOpacity,
|
||||
size: 25,
|
||||
const SizedBox(height: 20),
|
||||
const SizedBox(
|
||||
width: 70,
|
||||
child: BodySmall(
|
||||
text: " Entrance Light",
|
||||
fontColor: ColorsManager
|
||||
.textPrimaryColor,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
BodySmall(
|
||||
text: "Timer",
|
||||
style: context.bodyMedium.copyWith(
|
||||
color: ColorsManager.textPrimaryColor,
|
||||
Center(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.center,
|
||||
children: [
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Card(
|
||||
elevation: 3,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius:
|
||||
BorderRadius.circular(100),
|
||||
),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
pageBuilder: (context,
|
||||
animation1,
|
||||
animation2) =>
|
||||
TimerScheduleScreen(
|
||||
switchCode:
|
||||
'switch_1',
|
||||
device: device!,
|
||||
deviceCode:
|
||||
'countdown_1',
|
||||
)));
|
||||
},
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Container(
|
||||
width: 60,
|
||||
height: 60,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey[300],
|
||||
borderRadius:
|
||||
BorderRadius.circular(
|
||||
100),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
width: 40,
|
||||
height: 40,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius:
|
||||
BorderRadius.circular(
|
||||
100),
|
||||
),
|
||||
child: Center(
|
||||
child: Icon(
|
||||
Icons.access_time,
|
||||
color: ColorsManager
|
||||
.primaryColorWithOpacity,
|
||||
size: 25,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
BodySmall(
|
||||
text: "Timer",
|
||||
style: context.bodyMedium.copyWith(
|
||||
color: ColorsManager
|
||||
.textPrimaryColor,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(child: SizedBox())
|
||||
],
|
||||
),
|
||||
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Expanded(child: SizedBox())
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,16 +17,15 @@ import 'package:syncrow_app/utils/context_extension.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
|
||||
|
||||
|
||||
class TimerScheduleScreen extends StatelessWidget {
|
||||
final DeviceModel device;
|
||||
final String deviceCode;
|
||||
final String switchCode;
|
||||
const TimerScheduleScreen(
|
||||
{required this.device,
|
||||
required this.deviceCode,
|
||||
required this.switchCode,
|
||||
super.key});
|
||||
required this.deviceCode,
|
||||
required this.switchCode,
|
||||
super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -37,9 +36,9 @@ class TimerScheduleScreen extends StatelessWidget {
|
||||
),
|
||||
child: BlocProvider(
|
||||
create: (context) =>
|
||||
OneGangBloc(switchCode: switchCode, oneGangId: device.uuid ?? '')
|
||||
..add(GetCounterEvent(deviceCode: deviceCode))
|
||||
..add(GetScheduleEvent()),
|
||||
OneGangBloc(switchCode: switchCode, oneGangId: device.uuid ?? '')
|
||||
..add(GetCounterEvent(deviceCode: deviceCode))
|
||||
..add(GetScheduleEvent()),
|
||||
child: BlocBuilder<OneGangBloc, OneGangState>(
|
||||
builder: (context, state) {
|
||||
final oneGangBloc = BlocProvider.of<OneGangBloc>(context);
|
||||
@@ -64,7 +63,7 @@ class TimerScheduleScreen extends StatelessWidget {
|
||||
},
|
||||
child: DefaultTabController(
|
||||
length: 2,
|
||||
child: DefaultScaffold(
|
||||
child: DefaultScaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.transparent,
|
||||
centerTitle: true,
|
||||
@@ -74,175 +73,213 @@ class TimerScheduleScreen extends StatelessWidget {
|
||||
fontWeight: FontsManager.bold,
|
||||
),
|
||||
actions: [
|
||||
oneGangBloc.createSchedule == true ?
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
oneGangBloc.add(ThreeGangSave());
|
||||
},
|
||||
child: const Text('Save')
|
||||
) :
|
||||
oneGangBloc.selectedTabIndex==1? IconButton(
|
||||
onPressed: () {
|
||||
oneGangBloc.toggleCreateSchedule();
|
||||
},
|
||||
icon: const Icon(Icons.add),
|
||||
):SizedBox(),
|
||||
oneGangBloc.createSchedule == true
|
||||
? TextButton(
|
||||
onPressed: () {
|
||||
oneGangBloc.add(ScheduleSave());
|
||||
},
|
||||
child: const Text('Save'))
|
||||
: oneGangBloc.selectedTabIndex == 1
|
||||
? IconButton(
|
||||
onPressed: () {
|
||||
// oneGangBloc.toggleCreateSchedule();
|
||||
oneGangBloc.add(
|
||||
const ToggleCreateScheduleEvent(
|
||||
index: 1));
|
||||
},
|
||||
icon: const Icon(Icons.add),
|
||||
)
|
||||
: const SizedBox(),
|
||||
],
|
||||
),
|
||||
child:
|
||||
state is LoadingInitialState?
|
||||
const Center(child: CircularProgressIndicator()):
|
||||
Column(
|
||||
children: [
|
||||
Container(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
decoration: const ShapeDecoration(
|
||||
color: ColorsManager.onPrimaryColor,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(30)),
|
||||
),
|
||||
),
|
||||
child: TabBar(
|
||||
onTap: (value) {
|
||||
if(value==0){
|
||||
if(oneGangBloc.createSchedule == true){
|
||||
oneGangBloc.toggleCreateSchedule();
|
||||
}
|
||||
oneGangBloc.toggleSelectedIndex(0);
|
||||
}else{
|
||||
oneGangBloc.toggleSelectedIndex(1);
|
||||
}
|
||||
},
|
||||
indicatorColor: Colors.white, // Customize the indicator
|
||||
dividerHeight: 0,
|
||||
indicatorSize: TabBarIndicatorSize.tab,
|
||||
indicator: const ShapeDecoration(
|
||||
color: ColorsManager.slidingBlueColor,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius:
|
||||
BorderRadius.all(Radius.circular(20)),
|
||||
),
|
||||
),
|
||||
tabs: [
|
||||
Tab(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 10),
|
||||
child: BodySmall(
|
||||
text: 'Countdown',
|
||||
style: context.bodySmall.copyWith(
|
||||
color: ColorsManager.blackColor,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Tab(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: Text(
|
||||
'Schedule',
|
||||
style: context.bodySmall.copyWith(
|
||||
color: ColorsManager.blackColor,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: TabBarView(
|
||||
child: state is LoadingInitialState
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: Column(
|
||||
children: [
|
||||
Center(
|
||||
child: Container(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
countNum > 0
|
||||
? BodyLarge(
|
||||
text: _formatDuration(countNum),
|
||||
fontColor:
|
||||
ColorsManager.slidingBlueColor,
|
||||
fontSize: 40,
|
||||
)
|
||||
: CupertinoTimerPicker(
|
||||
mode: CupertinoTimerPickerMode.hm,
|
||||
onTimerDurationChanged:
|
||||
(Duration newDuration) {
|
||||
duration = newDuration;
|
||||
},
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
if (state is LoadingNewSate) {
|
||||
return;
|
||||
}
|
||||
if (countNum > 0) {
|
||||
oneGangBloc.add(SetCounterValue(
|
||||
deviceCode: deviceCode,
|
||||
duration: Duration.zero));
|
||||
} else if (duration != Duration.zero) {
|
||||
oneGangBloc.add(SetCounterValue(
|
||||
deviceCode: deviceCode,
|
||||
duration: duration));
|
||||
}
|
||||
},
|
||||
child: SvgPicture.asset(countNum > 0
|
||||
? Assets.pauseIcon
|
||||
: Assets.playIcon)),
|
||||
],
|
||||
Container(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
decoration: const ShapeDecoration(
|
||||
color: ColorsManager.onPrimaryColor,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius:
|
||||
BorderRadius.all(Radius.circular(30)),
|
||||
),
|
||||
),
|
||||
),
|
||||
Column(
|
||||
mainAxisAlignment:oneGangBloc.listSchedule.isNotEmpty?
|
||||
MainAxisAlignment.start:MainAxisAlignment.center,
|
||||
children: [
|
||||
SizedBox(
|
||||
child: oneGangBloc.createSchedule == true ?
|
||||
CreateSchedule(
|
||||
onToggleChanged: (bool isOn) {
|
||||
oneGangBloc.toggleSchedule = isOn;
|
||||
},
|
||||
onDateTimeChanged: (DateTime dateTime) {
|
||||
oneGangBloc.selectedTime=dateTime;
|
||||
},
|
||||
days: oneGangBloc.days,
|
||||
selectDays: (List<String> selectedDays) {
|
||||
oneGangBloc.selectedDays = selectedDays;
|
||||
},
|
||||
)
|
||||
:
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 10),
|
||||
child: ScheduleListView(
|
||||
listSchedule: oneGangBloc.listSchedule, // Pass the schedule list here
|
||||
onDismissed: (scheduleId) {
|
||||
oneGangBloc.listSchedule.removeWhere((schedule) => schedule.scheduleId == scheduleId);
|
||||
oneGangBloc.add(DeleteScheduleEvent(id: scheduleId));
|
||||
},
|
||||
onToggleSchedule: (scheduleId, isEnabled) {
|
||||
oneGangBloc.add(ToggleScheduleEvent(
|
||||
id: scheduleId,
|
||||
toggle: isEnabled,
|
||||
));
|
||||
},
|
||||
),
|
||||
child: TabBar(
|
||||
onTap: (value) {
|
||||
if (value == 0) {
|
||||
if (oneGangBloc.createSchedule ==
|
||||
true) {
|
||||
// oneGangBloc.toggleCreateSchedule();
|
||||
oneGangBloc.add(
|
||||
const ToggleCreateScheduleEvent(
|
||||
index: 0));
|
||||
}
|
||||
oneGangBloc.add(
|
||||
const ToggleSelectedEvent(
|
||||
index: 0));
|
||||
} else {
|
||||
oneGangBloc.add(
|
||||
const ToggleSelectedEvent(
|
||||
index: 1));
|
||||
}
|
||||
},
|
||||
indicatorColor:
|
||||
Colors.white, // Customize the indicator
|
||||
dividerHeight: 0,
|
||||
indicatorSize: TabBarIndicatorSize.tab,
|
||||
indicator: const ShapeDecoration(
|
||||
color: ColorsManager.slidingBlueColor,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(20)),
|
||||
),
|
||||
),
|
||||
],
|
||||
tabs: [
|
||||
Tab(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 10),
|
||||
child: BodySmall(
|
||||
text: 'Countdown',
|
||||
style: context.bodySmall.copyWith(
|
||||
color: ColorsManager.blackColor,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Tab(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 10),
|
||||
child: Text(
|
||||
'Schedule',
|
||||
style: context.bodySmall.copyWith(
|
||||
color: ColorsManager.blackColor,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: TabBarView(
|
||||
physics: const NeverScrollableScrollPhysics(), // Disable swiping
|
||||
|
||||
children: [
|
||||
Center(
|
||||
child: Container(
|
||||
child: Column(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.center,
|
||||
children: [
|
||||
countNum > 0
|
||||
? BodyLarge(
|
||||
text: _formatDuration(
|
||||
countNum),
|
||||
fontColor: ColorsManager
|
||||
.slidingBlueColor,
|
||||
fontSize: 40,
|
||||
)
|
||||
: CupertinoTimerPicker(
|
||||
mode:
|
||||
CupertinoTimerPickerMode
|
||||
.hm,
|
||||
onTimerDurationChanged:
|
||||
(Duration
|
||||
newDuration) {
|
||||
duration = newDuration;
|
||||
},
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
if (state
|
||||
is LoadingNewSate) {
|
||||
return;
|
||||
}
|
||||
if (countNum > 0) {
|
||||
oneGangBloc.add(
|
||||
SetCounterValue(
|
||||
deviceCode:
|
||||
deviceCode,
|
||||
duration: Duration
|
||||
.zero));
|
||||
} else if (duration !=
|
||||
Duration.zero) {
|
||||
oneGangBloc.add(
|
||||
SetCounterValue(
|
||||
deviceCode:
|
||||
deviceCode,
|
||||
duration:
|
||||
duration));
|
||||
}
|
||||
},
|
||||
child: SvgPicture.asset(
|
||||
countNum > 0
|
||||
? Assets.pauseIcon
|
||||
: Assets.playIcon)),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
child: oneGangBloc.createSchedule ==
|
||||
true
|
||||
? CreateSchedule(
|
||||
onToggleChanged: (bool isOn) {
|
||||
oneGangBloc.toggleSchedule =
|
||||
isOn;
|
||||
},
|
||||
onDateTimeChanged:
|
||||
(DateTime dateTime) {
|
||||
oneGangBloc.selectedTime =
|
||||
dateTime;
|
||||
},
|
||||
days: oneGangBloc.days,
|
||||
selectDays: (List<String>
|
||||
selectedDays) {
|
||||
oneGangBloc.selectedDays =
|
||||
selectedDays;
|
||||
},
|
||||
)
|
||||
: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 10),
|
||||
child: ScheduleListView(
|
||||
listSchedule: oneGangBloc
|
||||
.listSchedule, // Pass the schedule list here
|
||||
onDismissed: (scheduleId) {
|
||||
oneGangBloc.listSchedule
|
||||
.removeWhere((schedule) =>
|
||||
schedule
|
||||
.scheduleId ==
|
||||
scheduleId);
|
||||
oneGangBloc.add(
|
||||
DeleteScheduleEvent(
|
||||
id: scheduleId));
|
||||
},
|
||||
onToggleSchedule:
|
||||
(scheduleId, isEnabled) {
|
||||
oneGangBloc.add(
|
||||
ToggleScheduleEvent(
|
||||
id: scheduleId,
|
||||
toggle: isEnabled,
|
||||
));
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
))
|
||||
);
|
||||
)));
|
||||
},
|
||||
),
|
||||
),
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
|
||||
import 'package:syncrow_app/features/devices/model/room_model.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/room_page_switch.dart';
|
||||
|
||||
|
||||
@@ -9,10 +9,10 @@ import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/ACs/acs_view.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/curtains/curtain_view.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/door_sensor/door_sensor_screen.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/gateway/gateway_view.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/lights/light_interface.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/one_gang/one_gang_Interface.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/one_gang/one_gang_screen.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/two_gang/two_gang_Interface.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/wall_sensor/wall_sensor_interface.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/ceiling_sensor/ceiling_sensor_interface.dart';
|
||||
@@ -31,7 +31,6 @@ class RoomPageSwitch extends StatelessWidget {
|
||||
});
|
||||
|
||||
final DeviceModel device;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
@@ -87,7 +86,8 @@ void showDeviceInterface(DeviceModel device, BuildContext context) {
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
pageBuilder: (context, animation1, animation2) => ACsView(deviceModel: device)));
|
||||
pageBuilder: (context, animation1, animation2) =>
|
||||
ACsView(deviceModel: device)));
|
||||
// navigateToInterface(ACsView(deviceModel: device), context);
|
||||
break;
|
||||
case DeviceType.WallSensor:
|
||||
@@ -110,8 +110,9 @@ void showDeviceInterface(DeviceModel device, BuildContext context) {
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
pageBuilder: (context, animation1, animation2) =>
|
||||
CurtainView(curtain: device,)));
|
||||
pageBuilder: (context, animation1, animation2) => CurtainView(
|
||||
curtain: device,
|
||||
)));
|
||||
break;
|
||||
case DeviceType.Blind:
|
||||
break;
|
||||
@@ -119,14 +120,16 @@ void showDeviceInterface(DeviceModel device, BuildContext context) {
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
pageBuilder: (context, animation1, animation2) => DoorInterface(doorLock: device)));
|
||||
pageBuilder: (context, animation1, animation2) =>
|
||||
DoorInterface(doorLock: device)));
|
||||
// navigateToInterface(DoorInterface(doorlock: device), context);
|
||||
break;
|
||||
case DeviceType.Gateway:
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
pageBuilder: (context, animation1, animation2) => GateWayView(gatewayObj: device)));
|
||||
pageBuilder: (context, animation1, animation2) =>
|
||||
GateWayView(gatewayObj: device)));
|
||||
break;
|
||||
case DeviceType.LightBulb:
|
||||
navigateToInterface(LightInterface(light: device), context);
|
||||
@@ -149,13 +152,18 @@ void showDeviceInterface(DeviceModel device, BuildContext context) {
|
||||
pageBuilder: (context, animation1, animation2) =>
|
||||
ThreeGangInterface(gangSwitch: device)));
|
||||
|
||||
|
||||
case DeviceType.WH:
|
||||
case DeviceType.WH:
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
pageBuilder: (context, animation1, animation2) =>
|
||||
WaterHeaterPage(device: device)));
|
||||
case DeviceType.DS:
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
pageBuilder: (context, animation1, animation2) =>
|
||||
DoorSensorScreen(device: device)));
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ class CreateTemporaryPassword extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
bool isRepeat = false;
|
||||
bool generated = false;
|
||||
// bool generated = false;
|
||||
return BlocProvider(
|
||||
create: (BuildContext context) => SmartDoorBloc(deviceId: deviceId!),
|
||||
child: BlocConsumer<SmartDoorBloc, SmartDoorState>(listener: (context, state) {
|
||||
@@ -35,11 +35,11 @@ class CreateTemporaryPassword extends StatelessWidget {
|
||||
),
|
||||
);
|
||||
}
|
||||
if (state is IsRepeatState){
|
||||
if (state is IsRepeatState) {
|
||||
isRepeat = state.repeat;
|
||||
}
|
||||
if (state is GeneratePasswordOneTimestate ){
|
||||
generated = state.generated;
|
||||
if (state is GeneratePasswordOneTimestate) {
|
||||
// generated = state.generated;
|
||||
}
|
||||
}, builder: (context, state) {
|
||||
final smartDoorBloc = BlocProvider.of<SmartDoorBloc>(context);
|
||||
@@ -56,141 +56,142 @@ class CreateTemporaryPassword extends StatelessWidget {
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(true);
|
||||
},
|
||||
icon: const Icon(Icons.arrow_back)
|
||||
),
|
||||
actions:
|
||||
type == 'Online Password'?[
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
smartDoorBloc.add(SavePasswordEvent(context: context));
|
||||
},
|
||||
child: const Text('Save')
|
||||
)
|
||||
]:null,
|
||||
icon: const Icon(Icons.arrow_back)),
|
||||
actions: type == 'Online Password'
|
||||
? [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
smartDoorBloc.add(SavePasswordEvent(context: context));
|
||||
},
|
||||
child: const Text('Save'))
|
||||
]
|
||||
: null,
|
||||
),
|
||||
child: state is LoadingInitialState
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const BodyMedium(
|
||||
text: 'Save the password immediately. The password is not displayed in the app.',
|
||||
fontWeight: FontWeight.normal,
|
||||
fontColor: ColorsManager.grayColor,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
const BodyMedium(
|
||||
text: '7-Digit Password',
|
||||
fontWeight: FontWeight.normal,
|
||||
fontColor: ColorsManager.grayColor,
|
||||
),
|
||||
DefaultContainer(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 15),
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: type == 'Online Password'?0:25),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Flexible(
|
||||
flex: 2,
|
||||
child: PinCodeTextField(
|
||||
onCompleted: (value) {
|
||||
if (value.split('').every((char) => char == '1')) {
|
||||
smartDoorBloc.passwordController.clear();
|
||||
CustomSnackBar.displaySnackBar('All characters cannot be 1.');
|
||||
}
|
||||
},
|
||||
autoDisposeControllers: false,
|
||||
keyboardType: TextInputType.phone,
|
||||
length: 7,
|
||||
// enabled:type == 'Online Password'? true:false,
|
||||
obscureText: false,
|
||||
animationType: AnimationType.fade,
|
||||
pinTheme: PinTheme(
|
||||
shape: PinCodeFieldShape.underline,
|
||||
fieldHeight: 45,
|
||||
fieldWidth: 20,
|
||||
activeFillColor: Colors.white,
|
||||
disabledColor: Colors.grey,
|
||||
activeColor: Colors.grey,
|
||||
errorBorderColor: Colors.grey,
|
||||
inactiveColor: Colors.grey,
|
||||
inactiveFillColor: Colors.grey,
|
||||
selectedColor: Colors.grey),
|
||||
animationDuration: const Duration(milliseconds: 300),
|
||||
backgroundColor: Colors.white,
|
||||
enableActiveFill: false,
|
||||
controller: smartDoorBloc.passwordController,
|
||||
appContext: context,
|
||||
)),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const BodyMedium(
|
||||
text:
|
||||
'Save the password immediately. The password is not displayed in the app.',
|
||||
fontWeight: FontWeight.normal,
|
||||
fontColor: ColorsManager.grayColor,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
const BodyMedium(
|
||||
text: '7-Digit Password',
|
||||
fontWeight: FontWeight.normal,
|
||||
fontColor: ColorsManager.grayColor,
|
||||
),
|
||||
DefaultContainer(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 15),
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: type == 'Online Password' ? 0 : 25),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Flexible(
|
||||
flex: 2,
|
||||
child: PinCodeTextField(
|
||||
onCompleted: (value) {
|
||||
if (value.split('').every((char) => char == '1')) {
|
||||
smartDoorBloc.passwordController.clear();
|
||||
CustomSnackBar.displaySnackBar(
|
||||
'All characters cannot be 1.');
|
||||
}
|
||||
},
|
||||
autoDisposeControllers: false,
|
||||
keyboardType: TextInputType.phone,
|
||||
length: 7,
|
||||
// enabled:type == 'Online Password'? true:false,
|
||||
obscureText: false,
|
||||
animationType: AnimationType.fade,
|
||||
pinTheme: PinTheme(
|
||||
shape: PinCodeFieldShape.underline,
|
||||
fieldHeight: 45,
|
||||
fieldWidth: 20,
|
||||
activeFillColor: Colors.white,
|
||||
disabledColor: Colors.grey,
|
||||
activeColor: Colors.grey,
|
||||
errorBorderColor: Colors.grey,
|
||||
inactiveColor: Colors.grey,
|
||||
inactiveFillColor: Colors.grey,
|
||||
selectedColor: Colors.grey),
|
||||
animationDuration: const Duration(milliseconds: 300),
|
||||
backgroundColor: Colors.white,
|
||||
enableActiveFill: false,
|
||||
controller: smartDoorBloc.passwordController,
|
||||
appContext: context,
|
||||
)),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
if (type == 'Online Password')
|
||||
Flexible(
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
smartDoorBloc.add(GeneratePasswordEvent());
|
||||
},
|
||||
child: const BodyMedium(
|
||||
text: 'Generate Randomly',
|
||||
fontWeight: FontWeight.bold,
|
||||
fontColor: ColorsManager.primaryColor,
|
||||
)),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
if(type == 'Online Password')
|
||||
Flexible(
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
smartDoorBloc.add(GeneratePasswordEvent());
|
||||
),
|
||||
if (smartDoorBloc.passwordController.text.isNotEmpty)
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
await Clipboard.setData(
|
||||
ClipboardData(text: smartDoorBloc.passwordController.text));
|
||||
},
|
||||
child: const Text('Copy')),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
NameTimeWidget(),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
DefaultContainer(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
|
||||
child: ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
leading: const BodyMedium(
|
||||
text: 'Repeat',
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
trailing: Transform.scale(
|
||||
scale: .8,
|
||||
child: CupertinoSwitch(
|
||||
value: smartDoorBloc.repeat,
|
||||
onChanged: (value) {
|
||||
smartDoorBloc.add(ToggleRepeatEvent());
|
||||
},
|
||||
child: const BodyMedium(
|
||||
text: 'Generate Randomly',
|
||||
fontWeight: FontWeight.bold,
|
||||
fontColor: ColorsManager.primaryColor,
|
||||
)),
|
||||
)
|
||||
],
|
||||
),
|
||||
applyTheme: true,
|
||||
)),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
isRepeat ? const RepeatWidget() : const SizedBox(),
|
||||
const SizedBox(
|
||||
height: 40,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
if(smartDoorBloc.passwordController.text.isNotEmpty)
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
await Clipboard.setData(ClipboardData(
|
||||
text: smartDoorBloc.passwordController.text));
|
||||
},
|
||||
child: const Text('Copy')
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
NameTimeWidget(),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
DefaultContainer(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
|
||||
child: ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
leading: const BodyMedium(
|
||||
text: 'Repeat',
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
trailing: Transform.scale(
|
||||
scale: .8,
|
||||
child: CupertinoSwitch(
|
||||
value: smartDoorBloc.repeat,
|
||||
onChanged: (value) {
|
||||
smartDoorBloc.add(ToggleRepeatEvent());
|
||||
},
|
||||
applyTheme: true,
|
||||
)),
|
||||
),
|
||||
) ,
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
isRepeat? const RepeatWidget():const SizedBox(),
|
||||
const SizedBox(
|
||||
height: 40,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -31,16 +31,18 @@ class DoorDialogState extends State<DoorDialog> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final effectiveTime = widget.temporaryPassword?.effectiveTime ??int.parse( widget.offline?.gmtStart);
|
||||
final invalidTime = widget.temporaryPassword?.invalidTime ?? int.parse(widget.offline?.gmtExpired);
|
||||
final effectiveTime =
|
||||
widget.temporaryPassword?.effectiveTime ?? int.parse(widget.offline?.gmtStart);
|
||||
final invalidTime =
|
||||
widget.temporaryPassword?.invalidTime ?? int.parse(widget.offline?.gmtExpired);
|
||||
|
||||
final DateTime effectiveDateTime =
|
||||
DateTime.fromMillisecondsSinceEpoch(effectiveTime! * 1000, isUtc: false);
|
||||
DateTime.fromMillisecondsSinceEpoch(effectiveTime * 1000, isUtc: false);
|
||||
String formattedDateEffectiveTime = DateFormat('yyyy-MM-dd').format(effectiveDateTime);
|
||||
String formattedTimeEffectiveTime = DateFormat('hh:mm a').format(effectiveDateTime);
|
||||
|
||||
final DateTime expiredDateTime =
|
||||
DateTime.fromMillisecondsSinceEpoch(invalidTime! * 1000, isUtc: false);
|
||||
DateTime.fromMillisecondsSinceEpoch(invalidTime * 1000, isUtc: false);
|
||||
String formattedDateExpiredDateTime = DateFormat('yyyy-MM-dd').format(expiredDateTime);
|
||||
String formattedTimeExpiredDateTime = DateFormat('hh:mm a').format(expiredDateTime);
|
||||
return Dialog(
|
||||
@@ -116,60 +118,59 @@ class DoorDialogState extends State<DoorDialog> {
|
||||
width: double.infinity,
|
||||
color: ColorsManager.greyColor,
|
||||
),
|
||||
widget.temporaryPassword?.effectiveTime!=null?
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Center(
|
||||
child: BodyMedium(
|
||||
text: 'Cancel',
|
||||
style: context.bodyMedium.copyWith(color: ColorsManager.greyColor),
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
height: 50,
|
||||
width: 1,
|
||||
color: ColorsManager.greyColor,
|
||||
),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Navigator.pop(context, 'delete');
|
||||
},
|
||||
child: Center(
|
||||
child: BodyMedium(
|
||||
text: 'Delete Password',
|
||||
style: context.bodyMedium.copyWith(color: ColorsManager.primaryColorWithOpacity),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
):
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
Container(
|
||||
height: 50,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Center(
|
||||
child: BodyMedium(
|
||||
text: 'Cancel',
|
||||
style: context.bodyMedium.copyWith(color: ColorsManager.greyColor),
|
||||
widget.temporaryPassword?.effectiveTime != null
|
||||
? Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Center(
|
||||
child: BodyMedium(
|
||||
text: 'Cancel',
|
||||
style: context.bodyMedium.copyWith(color: ColorsManager.greyColor),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
),
|
||||
|
||||
],
|
||||
)
|
||||
Container(
|
||||
height: 50,
|
||||
width: 1,
|
||||
color: ColorsManager.greyColor,
|
||||
),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Navigator.pop(context, 'delete');
|
||||
},
|
||||
child: Center(
|
||||
child: BodyMedium(
|
||||
text: 'Delete Password',
|
||||
style: context.bodyMedium
|
||||
.copyWith(color: ColorsManager.primaryColorWithOpacity),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
Container(
|
||||
height: 50,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Center(
|
||||
child: BodyMedium(
|
||||
text: 'Cancel',
|
||||
style: context.bodyMedium.copyWith(color: ColorsManager.greyColor),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/smart_door/members_management_view.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/smart_door/smart_linkage_view.dart';
|
||||
@@ -10,9 +9,8 @@ import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart
|
||||
import 'package:syncrow_app/generated/assets.dart';
|
||||
|
||||
class DoorLockGrid extends StatelessWidget {
|
||||
String uuid;
|
||||
DoorLockGrid({
|
||||
super.key,required this.uuid});
|
||||
final String uuid;
|
||||
const DoorLockGrid({super.key, required this.uuid});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -67,24 +65,24 @@ class DoorLockGrid extends StatelessWidget {
|
||||
}
|
||||
|
||||
List<Map<String, dynamic>> doorLockButtons({val}) => [
|
||||
{
|
||||
'title': 'Unlocking Records',
|
||||
'image': Assets.assetsIconsDoorlockAssetsUnlockingRecords,
|
||||
'page': const UnlockingRecordsView(),
|
||||
},
|
||||
{
|
||||
'title': 'Members Management',
|
||||
'image': Assets.assetsIconsDoorlockAssetsMembersManagement,
|
||||
'page': const MembersManagementView(),
|
||||
},
|
||||
{
|
||||
'title': 'Temporary Password',
|
||||
'image': Assets.assetsIconsDoorlockAssetsTemporaryPassword,
|
||||
'page': TemporaryPasswordPage(deviceId:val) ,
|
||||
},
|
||||
{
|
||||
'title': 'Smart Linkage',
|
||||
'image': Assets.assetsIconsDoorlockAssetsSmartLinkage,
|
||||
'page': const SmartLinkgeView()
|
||||
},
|
||||
];
|
||||
{
|
||||
'title': 'Unlocking Records',
|
||||
'image': Assets.assetsIconsDoorlockAssetsUnlockingRecords,
|
||||
'page': const UnlockingRecordsView(),
|
||||
},
|
||||
{
|
||||
'title': 'Members Management',
|
||||
'image': Assets.assetsIconsDoorlockAssetsMembersManagement,
|
||||
'page': const MembersManagementView(),
|
||||
},
|
||||
{
|
||||
'title': 'Temporary Password',
|
||||
'image': Assets.assetsIconsDoorlockAssetsTemporaryPassword,
|
||||
'page': TemporaryPasswordPage(deviceId: val),
|
||||
},
|
||||
{
|
||||
'title': 'Smart Linkage',
|
||||
'image': Assets.assetsIconsDoorlockAssetsSmartLinkage,
|
||||
'page': const SmartLinkgeView()
|
||||
},
|
||||
];
|
||||
|
||||
@@ -14,98 +14,103 @@ import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
|
||||
class OnetimePasswordPage extends StatelessWidget {
|
||||
final String? deviceId;
|
||||
const OnetimePasswordPage({super.key, this.deviceId,});
|
||||
const OnetimePasswordPage({
|
||||
super.key,
|
||||
this.deviceId,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider(
|
||||
create: (BuildContext context) => SmartDoorBloc(deviceId: deviceId!)..add(InitialOneTimePassword( )),
|
||||
child: BlocConsumer<SmartDoorBloc, SmartDoorState>(
|
||||
listener: (context, state) {
|
||||
if (state is FailedState) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(state.errorMessage),
|
||||
backgroundColor: Colors.red,
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
builder: (context, state) {
|
||||
final smartDoorBloc = BlocProvider.of<SmartDoorBloc>(context);
|
||||
return DefaultScaffold(
|
||||
title: 'Passwords',
|
||||
actions: [
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(builder: (context) => OfflineOneTimePasswordPage(deviceId: deviceId, )
|
||||
)).then((result) {
|
||||
if(result!=null){
|
||||
smartDoorBloc.add(InitialOneTimePassword());
|
||||
smartDoorBloc.add(InitialOneTimePassword());
|
||||
}
|
||||
});
|
||||
},
|
||||
icon: const Icon(Icons.add)
|
||||
)
|
||||
],
|
||||
child: Builder(
|
||||
builder: (context) {
|
||||
return state is LoadingInitialState
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: Center(
|
||||
child: smartDoorBloc.oneTimePasswords!.isNotEmpty
|
||||
? ListView.builder(
|
||||
itemCount: smartDoorBloc.oneTimePasswords!.length,
|
||||
itemBuilder: (context, index) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(5.0),
|
||||
child: DefaultContainer(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10),
|
||||
child: ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
leading: SvgPicture.asset(Assets.timeLimitedPasswordIcon),
|
||||
title: BodyMedium(
|
||||
text: 'Password Name: ${smartDoorBloc.oneTimePasswords![index].pwdName}',
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
onTap: () async {
|
||||
final result = await showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return DoorDialog(
|
||||
title: 'Password Information',
|
||||
offline: smartDoorBloc.oneTimePasswords![index],
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
},
|
||||
trailing: const Icon(
|
||||
Icons.arrow_forward_ios,
|
||||
color: ColorsManager.greyColor,
|
||||
size: 15,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
) : Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
SvgPicture.asset(Assets.noValidPasswords),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
const BodyMedium(text: 'No Valid Passwords')
|
||||
],
|
||||
),
|
||||
);
|
||||
create: (BuildContext context) =>
|
||||
SmartDoorBloc(deviceId: deviceId!)..add(InitialOneTimePassword()),
|
||||
child: BlocConsumer<SmartDoorBloc, SmartDoorState>(listener: (context, state) {
|
||||
if (state is FailedState) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(state.errorMessage),
|
||||
backgroundColor: Colors.red,
|
||||
),
|
||||
);
|
||||
}
|
||||
}, builder: (context, state) {
|
||||
final smartDoorBloc = BlocProvider.of<SmartDoorBloc>(context);
|
||||
return DefaultScaffold(
|
||||
title: 'Passwords',
|
||||
actions: [
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context)
|
||||
.push(MaterialPageRoute(
|
||||
builder: (context) => OfflineOneTimePasswordPage(
|
||||
deviceId: deviceId,
|
||||
)))
|
||||
.then((result) {
|
||||
if (result != null) {
|
||||
smartDoorBloc.add(InitialOneTimePassword());
|
||||
smartDoorBloc.add(InitialOneTimePassword());
|
||||
}
|
||||
});
|
||||
},
|
||||
));
|
||||
})
|
||||
);
|
||||
icon: const Icon(Icons.add))
|
||||
],
|
||||
child: Builder(
|
||||
builder: (context) {
|
||||
return state is LoadingInitialState
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: Center(
|
||||
child: smartDoorBloc.oneTimePasswords!.isNotEmpty
|
||||
? ListView.builder(
|
||||
itemCount: smartDoorBloc.oneTimePasswords!.length,
|
||||
itemBuilder: (context, index) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(5.0),
|
||||
child: DefaultContainer(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 15, vertical: 10),
|
||||
child: ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
leading: SvgPicture.asset(Assets.timeLimitedPasswordIcon),
|
||||
title: BodyMedium(
|
||||
text:
|
||||
'Password Name: ${smartDoorBloc.oneTimePasswords![index].pwdName}',
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
onTap: () async {
|
||||
await showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return DoorDialog(
|
||||
title: 'Password Information',
|
||||
offline: smartDoorBloc.oneTimePasswords![index],
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
trailing: const Icon(
|
||||
Icons.arrow_forward_ios,
|
||||
color: ColorsManager.greyColor,
|
||||
size: 15,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
)
|
||||
: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
SvgPicture.asset(Assets.noValidPasswords),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
const BodyMedium(text: 'No Valid Passwords')
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
));
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,87 +19,88 @@ class TimeLimitedPasswordPage extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider(
|
||||
create: (BuildContext context) => SmartDoorBloc(deviceId: deviceId!)..add(InitialTimeLimitPassword()),
|
||||
child: BlocConsumer<SmartDoorBloc, SmartDoorState>(
|
||||
listener: (context, state) {
|
||||
if (state is FailedState) {
|
||||
CustomSnackBar.displaySnackBar(
|
||||
state.errorMessage
|
||||
);
|
||||
}
|
||||
},
|
||||
builder: (context, state) {
|
||||
final smartDoorBloc = BlocProvider.of<SmartDoorBloc>(context);
|
||||
return DefaultScaffold(
|
||||
title: 'Passwords',
|
||||
actions: [
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(builder: (context) => CreateOfflineTimeLimitPasswordPage(deviceId: deviceId,)
|
||||
)).then((result) {
|
||||
smartDoorBloc.add(InitialTimeLimitPassword());
|
||||
smartDoorBloc.add(InitialTimeLimitPassword());
|
||||
});
|
||||
},
|
||||
icon: const Icon(Icons.add)
|
||||
)
|
||||
],
|
||||
child: Builder(
|
||||
builder: (context) {
|
||||
return state is LoadingInitialState
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: Center(
|
||||
child: smartDoorBloc.timeLimitPasswords!.isNotEmpty
|
||||
? ListView.builder(
|
||||
itemCount: smartDoorBloc.timeLimitPasswords!.length,
|
||||
itemBuilder: (context, index) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(5.0),
|
||||
child: DefaultContainer(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10),
|
||||
child: ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
leading: SvgPicture.asset(Assets.timeLimitedPasswordIcon),
|
||||
title: BodyMedium(
|
||||
text: 'Password Name: ${smartDoorBloc.timeLimitPasswords![index].pwdName}',
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
onTap: () async {
|
||||
final result = await showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return DoorDialog(
|
||||
title: 'Password Information',
|
||||
offline: smartDoorBloc.timeLimitPasswords![index],
|
||||
);
|
||||
},
|
||||
create: (BuildContext context) =>
|
||||
SmartDoorBloc(deviceId: deviceId!)..add(InitialTimeLimitPassword()),
|
||||
child: BlocConsumer<SmartDoorBloc, SmartDoorState>(listener: (context, state) {
|
||||
if (state is FailedState) {
|
||||
CustomSnackBar.displaySnackBar(state.errorMessage);
|
||||
}
|
||||
}, builder: (context, state) {
|
||||
final smartDoorBloc = BlocProvider.of<SmartDoorBloc>(context);
|
||||
return DefaultScaffold(
|
||||
title: 'Passwords',
|
||||
actions: [
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context)
|
||||
.push(MaterialPageRoute(
|
||||
builder: (context) => CreateOfflineTimeLimitPasswordPage(
|
||||
deviceId: deviceId,
|
||||
)))
|
||||
.then((result) {
|
||||
smartDoorBloc.add(InitialTimeLimitPassword());
|
||||
smartDoorBloc.add(InitialTimeLimitPassword());
|
||||
});
|
||||
},
|
||||
icon: const Icon(Icons.add))
|
||||
],
|
||||
child: Builder(
|
||||
builder: (context) {
|
||||
return state is LoadingInitialState
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: Center(
|
||||
child: smartDoorBloc.timeLimitPasswords!.isNotEmpty
|
||||
? ListView.builder(
|
||||
itemCount: smartDoorBloc.timeLimitPasswords!.length,
|
||||
itemBuilder: (context, index) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(5.0),
|
||||
child: DefaultContainer(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 15, vertical: 10),
|
||||
child: ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
leading: SvgPicture.asset(Assets.timeLimitedPasswordIcon),
|
||||
title: BodyMedium(
|
||||
text:
|
||||
'Password Name: ${smartDoorBloc.timeLimitPasswords![index].pwdName}',
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
onTap: () async {
|
||||
await showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return DoorDialog(
|
||||
title: 'Password Information',
|
||||
offline: smartDoorBloc.timeLimitPasswords![index],
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
trailing: const Icon(
|
||||
Icons.arrow_forward_ios,
|
||||
color: ColorsManager.greyColor,
|
||||
size: 15,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
trailing: const Icon(
|
||||
Icons.arrow_forward_ios,
|
||||
color: ColorsManager.greyColor,
|
||||
size: 15,
|
||||
),
|
||||
)
|
||||
: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
SvgPicture.asset(Assets.noValidPasswords),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
const BodyMedium(text: 'No Valid Passwords')
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
) : Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
SvgPicture.asset(Assets.noValidPasswords),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
const BodyMedium(text: 'No Valid Passwords')
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
));
|
||||
})
|
||||
);
|
||||
);
|
||||
},
|
||||
));
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ class GangSwitch extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return InkWell(
|
||||
overlayColor: MaterialStateProperty.all(Colors.transparent),
|
||||
overlayColor: WidgetStateProperty.all(Colors.transparent),
|
||||
onTap: () {
|
||||
action();
|
||||
// var tempControl = DeviceControlModel(
|
||||
|
||||
@@ -63,17 +63,20 @@ class ScheduleScreen extends StatelessWidget {
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
pageBuilder: (context, animation1, animation2) => TimerScheduleScreen(
|
||||
switchCode :"switch_1",
|
||||
device: device,
|
||||
deviceCode: 'countdown_1',
|
||||
)));
|
||||
pageBuilder:
|
||||
(context, animation1, animation2) =>
|
||||
TimerScheduleScreen(
|
||||
switchCode: "switch_1",
|
||||
device: device,
|
||||
deviceCode: 'countdown_1',
|
||||
)));
|
||||
},
|
||||
child: Container(
|
||||
padding:
|
||||
const EdgeInsets.only(left: 25, right: 15, top: 20, bottom: 20),
|
||||
padding: const EdgeInsets.only(
|
||||
left: 25, right: 15, top: 20, bottom: 20),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
BodySmall(
|
||||
text: "Bedside Light",
|
||||
@@ -100,17 +103,20 @@ class ScheduleScreen extends StatelessWidget {
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
pageBuilder: (context, animation1, animation2) => TimerScheduleScreen(
|
||||
switchCode :"switch_2",
|
||||
device: device,
|
||||
deviceCode: 'countdown_2',
|
||||
)));
|
||||
pageBuilder:
|
||||
(context, animation1, animation2) =>
|
||||
TimerScheduleScreen(
|
||||
switchCode: "switch_2",
|
||||
device: device,
|
||||
deviceCode: 'countdown_2',
|
||||
)));
|
||||
},
|
||||
child: Container(
|
||||
padding:
|
||||
const EdgeInsets.only(left: 25, right: 15, top: 20, bottom: 20),
|
||||
padding: const EdgeInsets.only(
|
||||
left: 25, right: 15, top: 20, bottom: 20),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
BodySmall(
|
||||
text: "Ceiling Light",
|
||||
@@ -137,17 +143,20 @@ class ScheduleScreen extends StatelessWidget {
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
pageBuilder: (context, animation1, animation2) => TimerScheduleScreen(
|
||||
switchCode :"switch_3",
|
||||
device: device,
|
||||
deviceCode: 'countdown_3',
|
||||
)));
|
||||
pageBuilder:
|
||||
(context, animation1, animation2) =>
|
||||
TimerScheduleScreen(
|
||||
switchCode: "switch_3",
|
||||
device: device,
|
||||
deviceCode: 'countdown_3',
|
||||
)));
|
||||
},
|
||||
child: Container(
|
||||
padding:
|
||||
const EdgeInsets.only(left: 25, right: 15, top: 20, bottom: 20),
|
||||
padding: const EdgeInsets.only(
|
||||
left: 25, right: 15, top: 20, bottom: 20),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
BodySmall(
|
||||
text: "Spotlight",
|
||||
|
||||
@@ -8,7 +8,6 @@ import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_eve
|
||||
import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_state.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/create_schedule.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/schedule_list.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
||||
@@ -18,17 +17,15 @@ import 'package:syncrow_app/utils/context_extension.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
|
||||
|
||||
|
||||
|
||||
class TimerScheduleScreen extends StatelessWidget {
|
||||
final DeviceModel device;
|
||||
final String deviceCode;
|
||||
final String switchCode;
|
||||
const TimerScheduleScreen(
|
||||
{required this.device,
|
||||
required this.deviceCode,
|
||||
required this.switchCode,
|
||||
super.key});
|
||||
required this.deviceCode,
|
||||
required this.switchCode,
|
||||
super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -38,8 +35,8 @@ class TimerScheduleScreen extends StatelessWidget {
|
||||
statusBarIconBrightness: Brightness.light,
|
||||
),
|
||||
child: BlocProvider(
|
||||
create: (context) =>
|
||||
ThreeGangBloc(switchCode: switchCode, threeGangId: device.uuid ?? '')
|
||||
create: (context) => ThreeGangBloc(
|
||||
switchCode: switchCode, threeGangId: device.uuid ?? '')
|
||||
..add(GetCounterEvent(deviceCode: deviceCode))
|
||||
..add(GetScheduleEvent()),
|
||||
child: BlocBuilder<ThreeGangBloc, ThreeGangState>(
|
||||
@@ -66,7 +63,7 @@ class TimerScheduleScreen extends StatelessWidget {
|
||||
},
|
||||
child: DefaultTabController(
|
||||
length: 2,
|
||||
child: DefaultScaffold(
|
||||
child: DefaultScaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.transparent,
|
||||
centerTitle: true,
|
||||
@@ -76,177 +73,238 @@ class TimerScheduleScreen extends StatelessWidget {
|
||||
fontWeight: FontsManager.bold,
|
||||
),
|
||||
actions: [
|
||||
threeGangBloc.createSchedule == true ?
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
threeGangBloc.add(ThreeGangSave());
|
||||
},
|
||||
child: const Text('Save')
|
||||
) :
|
||||
threeGangBloc.selectedTabIndex==1? IconButton(
|
||||
onPressed: () {
|
||||
threeGangBloc.toggleCreateSchedule();
|
||||
},
|
||||
icon: const Icon(Icons.add),
|
||||
):SizedBox(),
|
||||
threeGangBloc.createSchedule == true
|
||||
? TextButton(
|
||||
onPressed: () {
|
||||
threeGangBloc.add(ThreeGangSave());
|
||||
},
|
||||
child: const Text('Save'))
|
||||
: threeGangBloc.selectedTabIndex == 1
|
||||
? IconButton(
|
||||
onPressed: () {
|
||||
// oneGangBloc.toggleCreateSchedule();
|
||||
threeGangBloc.add(
|
||||
const ToggleCreateScheduleEvent(
|
||||
index: 1));
|
||||
},
|
||||
icon: const Icon(Icons.add),
|
||||
)
|
||||
: const SizedBox(),
|
||||
],
|
||||
),
|
||||
child:
|
||||
state is LoadingInitialState?
|
||||
const Center(child: CircularProgressIndicator()):
|
||||
Column(
|
||||
children: [
|
||||
Container(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
decoration: const ShapeDecoration(
|
||||
color: ColorsManager.onPrimaryColor,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(30)),
|
||||
),
|
||||
),
|
||||
child: TabBar(
|
||||
onTap: (value) {
|
||||
if(value==0){
|
||||
if(threeGangBloc.createSchedule == true){
|
||||
threeGangBloc.toggleCreateSchedule();
|
||||
}
|
||||
threeGangBloc.toggleSelectedIndex(0);
|
||||
|
||||
}else{
|
||||
threeGangBloc.toggleSelectedIndex(1);
|
||||
}
|
||||
},
|
||||
indicatorColor: Colors.white, // Customize the indicator
|
||||
dividerHeight: 0,
|
||||
indicatorSize: TabBarIndicatorSize.tab,
|
||||
indicator: const ShapeDecoration(
|
||||
color: ColorsManager.slidingBlueColor,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius:
|
||||
BorderRadius.all(Radius.circular(20)),
|
||||
),
|
||||
),
|
||||
tabs: [
|
||||
Tab(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 10),
|
||||
child: BodySmall(
|
||||
text: 'Countdown',
|
||||
style: context.bodySmall.copyWith(
|
||||
color: ColorsManager.blackColor,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Tab(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: Text(
|
||||
'Schedule',
|
||||
style: context.bodySmall.copyWith(
|
||||
color: ColorsManager.blackColor,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
),
|
||||
Expanded(
|
||||
child: TabBarView(
|
||||
child: state is LoadingInitialState
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: Column(
|
||||
children: [
|
||||
Center(
|
||||
child: Container(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
countNum > 0
|
||||
? BodyLarge(
|
||||
text: _formatDuration(countNum),
|
||||
fontColor:
|
||||
ColorsManager.slidingBlueColor,
|
||||
fontSize: 40,
|
||||
)
|
||||
: CupertinoTimerPicker(
|
||||
mode: CupertinoTimerPickerMode.hm,
|
||||
onTimerDurationChanged:
|
||||
(Duration newDuration) {
|
||||
duration = newDuration;
|
||||
},
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
if (state is LoadingNewSate) {
|
||||
return;
|
||||
}
|
||||
if (countNum > 0) {
|
||||
threeGangBloc.add(SetCounterValue(
|
||||
deviceCode: deviceCode,
|
||||
duration: Duration.zero));
|
||||
} else if (duration != Duration.zero) {
|
||||
threeGangBloc.add(SetCounterValue(
|
||||
deviceCode: deviceCode,
|
||||
duration: duration));
|
||||
}
|
||||
},
|
||||
child: SvgPicture.asset(countNum > 0
|
||||
? Assets.pauseIcon
|
||||
: Assets.playIcon)),
|
||||
],
|
||||
Container(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
decoration: const ShapeDecoration(
|
||||
color: ColorsManager.onPrimaryColor,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius:
|
||||
BorderRadius.all(Radius.circular(30)),
|
||||
),
|
||||
),
|
||||
),
|
||||
Column(
|
||||
mainAxisAlignment:threeGangBloc.listSchedule.isNotEmpty?
|
||||
MainAxisAlignment.start:MainAxisAlignment.center,
|
||||
children: [
|
||||
SizedBox(
|
||||
child: threeGangBloc.createSchedule == true ?
|
||||
CreateSchedule(
|
||||
onToggleChanged: (bool isOn) {
|
||||
threeGangBloc.toggleSchedule = isOn;
|
||||
},
|
||||
onDateTimeChanged: (DateTime dateTime) {
|
||||
threeGangBloc.selectedTime=dateTime;
|
||||
},
|
||||
days: threeGangBloc.days,
|
||||
selectDays: (List<String> selectedDays) {
|
||||
threeGangBloc.selectedDays = selectedDays;
|
||||
},
|
||||
)
|
||||
:
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 10),
|
||||
child: ScheduleListView(
|
||||
listSchedule: threeGangBloc.listSchedule, // Pass the schedule list here
|
||||
onDismissed: (scheduleId) {
|
||||
threeGangBloc.listSchedule.removeWhere((schedule) => schedule.scheduleId == scheduleId);
|
||||
threeGangBloc.add(DeleteScheduleEvent(id: scheduleId));
|
||||
},
|
||||
onToggleSchedule: (scheduleId, isEnabled) {
|
||||
threeGangBloc.add(ToggleScheduleEvent(
|
||||
id: scheduleId,
|
||||
toggle: isEnabled,
|
||||
));
|
||||
},
|
||||
),
|
||||
child: TabBar(
|
||||
// onTap: (value) {
|
||||
// if (value == 0) {
|
||||
// if (threeGangBloc.createSchedule ==
|
||||
// true) {
|
||||
// threeGangBloc.toggleCreateSchedule();
|
||||
// }
|
||||
// threeGangBloc.toggleSelectedIndex(0);
|
||||
// } else {
|
||||
// threeGangBloc.toggleSelectedIndex(1);
|
||||
// }
|
||||
// },
|
||||
|
||||
onTap: (value) {
|
||||
if (value == 0) {
|
||||
if (threeGangBloc.createSchedule ==
|
||||
true) {
|
||||
// oneGangBloc.toggleCreateSchedule();
|
||||
threeGangBloc.add(
|
||||
const ToggleCreateScheduleEvent(
|
||||
index: 0));
|
||||
}
|
||||
threeGangBloc.add(
|
||||
const ToggleSelectedEvent(
|
||||
index: 0));
|
||||
} else {
|
||||
threeGangBloc.add(
|
||||
const ToggleSelectedEvent(
|
||||
index: 1));
|
||||
}
|
||||
},
|
||||
indicatorColor: Colors.white,
|
||||
dividerHeight: 0,
|
||||
indicatorSize: TabBarIndicatorSize.tab,
|
||||
indicator: const ShapeDecoration(
|
||||
color: ColorsManager.slidingBlueColor,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(20)),
|
||||
),
|
||||
),
|
||||
],
|
||||
tabs: [
|
||||
Tab(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 10),
|
||||
child: BodySmall(
|
||||
text: 'Countdown',
|
||||
style: context.bodySmall.copyWith(
|
||||
color: ColorsManager.blackColor,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Tab(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 10),
|
||||
child: Text(
|
||||
'Schedule',
|
||||
style: context.bodySmall.copyWith(
|
||||
color: ColorsManager.blackColor,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: TabBarView(
|
||||
physics: const NeverScrollableScrollPhysics(), // Disable swiping
|
||||
|
||||
children: [
|
||||
Center(
|
||||
child: Container(
|
||||
child: Column(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.center,
|
||||
children: [
|
||||
countNum > 0
|
||||
? BodyLarge(
|
||||
text: _formatDuration(
|
||||
countNum),
|
||||
fontColor: ColorsManager
|
||||
.slidingBlueColor,
|
||||
fontSize: 40,
|
||||
)
|
||||
: CupertinoTimerPicker(
|
||||
mode:
|
||||
CupertinoTimerPickerMode
|
||||
.hm,
|
||||
onTimerDurationChanged:
|
||||
(Duration
|
||||
newDuration) {
|
||||
duration = newDuration;
|
||||
},
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
if (state
|
||||
is LoadingNewSate) {
|
||||
return;
|
||||
}
|
||||
if (countNum > 0) {
|
||||
threeGangBloc.add(
|
||||
SetCounterValue(
|
||||
deviceCode:
|
||||
deviceCode,
|
||||
duration: Duration
|
||||
.zero));
|
||||
} else if (duration !=
|
||||
Duration.zero) {
|
||||
threeGangBloc.add(
|
||||
SetCounterValue(
|
||||
deviceCode:
|
||||
deviceCode,
|
||||
duration:
|
||||
duration));
|
||||
}
|
||||
},
|
||||
child: SvgPicture.asset(
|
||||
countNum > 0
|
||||
? Assets.pauseIcon
|
||||
: Assets.playIcon)),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
child: threeGangBloc.createSchedule ==
|
||||
true
|
||||
? CreateSchedule(
|
||||
onToggleChanged: (bool isOn) {
|
||||
threeGangBloc.toggleSchedule =
|
||||
isOn;
|
||||
},
|
||||
onDateTimeChanged:
|
||||
(DateTime dateTime) {
|
||||
threeGangBloc.selectedTime =
|
||||
dateTime;
|
||||
},
|
||||
days: threeGangBloc.days,
|
||||
selectDays: (List<String>
|
||||
selectedDays) {
|
||||
threeGangBloc.selectedDays =
|
||||
selectedDays;
|
||||
},
|
||||
)
|
||||
: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 10),
|
||||
child: Column(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.start,
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: ScheduleListView(
|
||||
listSchedule: threeGangBloc
|
||||
.listSchedule, // Pass the schedule list here
|
||||
onDismissed:
|
||||
(scheduleId) {
|
||||
threeGangBloc
|
||||
.listSchedule
|
||||
.removeWhere(
|
||||
(schedule) =>
|
||||
schedule
|
||||
.scheduleId ==
|
||||
scheduleId);
|
||||
threeGangBloc.add(
|
||||
DeleteScheduleEvent(
|
||||
id: scheduleId));
|
||||
},
|
||||
onToggleSchedule:
|
||||
(scheduleId,
|
||||
isEnabled) {
|
||||
threeGangBloc.add(
|
||||
ToggleScheduleEvent(
|
||||
id: scheduleId,
|
||||
toggle: isEnabled,
|
||||
));
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
))
|
||||
);
|
||||
)));
|
||||
},
|
||||
),
|
||||
),
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_event.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_state.dart';
|
||||
import 'package:syncrow_app/features/devices/model/groupTwoGangModel.dart';
|
||||
import 'package:syncrow_app/features/devices/model/group_three_gang_model.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/two_gang_bloc/two_gang_bloc.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/two_gang_bloc/two_gang_event.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/two_gang_bloc/two_gang_state.dart';
|
||||
import 'package:syncrow_app/features/devices/model/group_two_gang_model.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/devices_default_switch.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
|
||||
|
||||
@@ -16,7 +15,7 @@ class TwoGangList extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<ThreeGangBloc, ThreeGangState>(
|
||||
return BlocBuilder<TwoGangBloc, TwoGangState>(
|
||||
builder: (context, state) {
|
||||
return SingleChildScrollView(
|
||||
child: Column(
|
||||
@@ -28,10 +27,10 @@ class TwoGangList extends StatelessWidget {
|
||||
DevicesDefaultSwitch(
|
||||
switchValue: allSwitches,
|
||||
action: () {
|
||||
BlocProvider.of<ThreeGangBloc>(context).add(GroupAllOnEvent());
|
||||
BlocProvider.of<TwoGangBloc>(context).add(GroupAllOnEvent());
|
||||
},
|
||||
secondAction: () {
|
||||
BlocProvider.of<ThreeGangBloc>(context).add(GroupAllOffEvent());
|
||||
BlocProvider.of<TwoGangBloc>(context).add(GroupAllOffEvent());
|
||||
},
|
||||
),
|
||||
ListView.builder(
|
||||
@@ -44,30 +43,27 @@ class TwoGangList extends StatelessWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(height: 10),
|
||||
BodySmall(text: '${twoGangList[index].deviceName} beside light'),
|
||||
BodySmall(text: twoGangList[index].deviceName),
|
||||
const SizedBox(height: 5),
|
||||
DevicesDefaultSwitch(
|
||||
switchValue: twoGangList[index].firstSwitch,
|
||||
action: () {
|
||||
BlocProvider.of<ThreeGangBloc>(context).add(ChangeFirstSwitchStatusEvent(
|
||||
BlocProvider.of<TwoGangBloc>(context).add(ChangeFirstSwitchStatusEvent(
|
||||
value: twoGangList[index].firstSwitch,
|
||||
deviceId: twoGangList[index].deviceId));
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
BodySmall(text: '${twoGangList[index].deviceName} ceiling light'),
|
||||
BodySmall(text: twoGangList[index].deviceName),
|
||||
const SizedBox(height: 5),
|
||||
DevicesDefaultSwitch(
|
||||
switchValue: twoGangList[index].secondSwitch,
|
||||
action: () {
|
||||
BlocProvider.of<ThreeGangBloc>(context).add(ChangeSecondSwitchStatusEvent(
|
||||
BlocProvider.of<TwoGangBloc>(context).add(ChangeSecondSwitchStatusEvent(
|
||||
value: twoGangList[index].secondSwitch,
|
||||
deviceId: twoGangList[index].deviceId));
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
BodySmall(text: '${twoGangList[index].deviceName} spotlight'),
|
||||
const SizedBox(height: 5),
|
||||
],
|
||||
);
|
||||
},
|
||||
|
||||
@@ -4,7 +4,7 @@ import 'package:syncrow_app/features/devices/bloc/two_gang_bloc/two_gang_bloc.da
|
||||
import 'package:syncrow_app/features/devices/bloc/two_gang_bloc/two_gang_event.dart';
|
||||
import 'package:syncrow_app/features/devices/bloc/two_gang_bloc/two_gang_state.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/groupTwoGangModel.dart';
|
||||
import 'package:syncrow_app/features/devices/model/group_two_gang_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/two_gang_model.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/three_gang/gang_switch.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/two_gang/two_gang_list.dart';
|
||||
@@ -22,18 +22,16 @@ class TwoGangScreen extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider(
|
||||
create: (context) => TwoGangBloc(
|
||||
switchCode: switchCode??'',
|
||||
twoGangId: device?.uuid ?? '')
|
||||
create: (context) => TwoGangBloc(switchCode: switchCode ?? '', twoGangId: device?.uuid ?? '')
|
||||
..add(InitialEvent(groupScreen: device != null ? false : true)),
|
||||
child: BlocBuilder<TwoGangBloc, TwoGangState>(
|
||||
builder: (context, state) {
|
||||
TwoGangModel twoGangModel = TwoGangModel(
|
||||
firstSwitch: false,
|
||||
secondSwitch: false,
|
||||
firstCountDown: 0,
|
||||
secondCountDown: 0,
|
||||
);
|
||||
firstSwitch: false,
|
||||
secondSwitch: false,
|
||||
firstCountDown: 0,
|
||||
secondCountDown: 0,
|
||||
);
|
||||
|
||||
List<GroupTwoGangModel> groupTwoGangModel = [];
|
||||
bool allSwitchesOn = false;
|
||||
@@ -47,7 +45,9 @@ class TwoGangScreen extends StatelessWidget {
|
||||
}
|
||||
return state is LoadingInitialState
|
||||
? const Center(
|
||||
child: DefaultContainer(width: 50, height: 50, child: CircularProgressIndicator()),)
|
||||
child:
|
||||
DefaultContainer(width: 50, height: 50, child: CircularProgressIndicator()),
|
||||
)
|
||||
: device == null
|
||||
? TwoGangList(
|
||||
twoGangList: groupTwoGangModel,
|
||||
@@ -116,7 +116,6 @@ class TwoGangScreen extends StatelessWidget {
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -63,7 +63,7 @@ class TimerScheduleScreen extends StatelessWidget {
|
||||
},
|
||||
child: DefaultTabController(
|
||||
length: 2,
|
||||
child: DefaultScaffold(
|
||||
child: DefaultScaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.transparent,
|
||||
centerTitle: true,
|
||||
@@ -73,177 +73,221 @@ class TimerScheduleScreen extends StatelessWidget {
|
||||
fontWeight: FontsManager.bold,
|
||||
),
|
||||
actions: [
|
||||
twoGangBloc.createSchedule == true ?
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
twoGangBloc.add(TwoGangSave());
|
||||
},
|
||||
child: const Text('Save')
|
||||
) :
|
||||
twoGangBloc.selectedTabIndex==1? IconButton(
|
||||
onPressed: () {
|
||||
twoGangBloc.toggleCreateSchedule();
|
||||
},
|
||||
icon: const Icon(Icons.add),
|
||||
):SizedBox(),
|
||||
twoGangBloc.createSchedule == true
|
||||
? TextButton(
|
||||
onPressed: () {
|
||||
twoGangBloc.add(TwoGangSave());
|
||||
},
|
||||
child: const Text('Save'))
|
||||
: twoGangBloc.selectedTabIndex == 1
|
||||
? IconButton(
|
||||
onPressed: () {
|
||||
// oneGangBloc.toggleCreateSchedule();
|
||||
twoGangBloc.add(
|
||||
const ToggleCreateScheduleEvent(
|
||||
index: 1));
|
||||
},
|
||||
icon: const Icon(Icons.add),
|
||||
)
|
||||
: const SizedBox(),
|
||||
],
|
||||
),
|
||||
child:
|
||||
state is LoadingInitialState?
|
||||
const Center(child: CircularProgressIndicator()):
|
||||
Column(
|
||||
children: [
|
||||
Container(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
decoration: const ShapeDecoration(
|
||||
color: ColorsManager.onPrimaryColor,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(30)),
|
||||
),
|
||||
),
|
||||
child: TabBar(
|
||||
onTap: (value) {
|
||||
print(value);
|
||||
if(value==0){
|
||||
if(twoGangBloc.createSchedule == true){
|
||||
twoGangBloc.toggleCreateSchedule();
|
||||
}
|
||||
twoGangBloc.toggleSelectedIndex(0);
|
||||
|
||||
}else{
|
||||
twoGangBloc.toggleSelectedIndex(1);
|
||||
}
|
||||
},
|
||||
indicatorColor: Colors.white, // Customize the indicator
|
||||
dividerHeight: 0,
|
||||
indicatorSize: TabBarIndicatorSize.tab,
|
||||
indicator: const ShapeDecoration(
|
||||
color: ColorsManager.slidingBlueColor,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius:
|
||||
BorderRadius.all(Radius.circular(20)),
|
||||
),
|
||||
),
|
||||
tabs: [
|
||||
Tab(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 10),
|
||||
child: BodySmall(
|
||||
text: 'Countdown',
|
||||
style: context.bodySmall.copyWith(
|
||||
color: ColorsManager.blackColor,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Tab(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: Text(
|
||||
'Schedule',
|
||||
style: context.bodySmall.copyWith(
|
||||
color: ColorsManager.blackColor,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: TabBarView(
|
||||
child: state is LoadingInitialState
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: Column(
|
||||
children: [
|
||||
Center(
|
||||
child: Container(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
countNum > 0
|
||||
? BodyLarge(
|
||||
text: _formatDuration(countNum),
|
||||
fontColor:
|
||||
ColorsManager.slidingBlueColor,
|
||||
fontSize: 40,
|
||||
)
|
||||
: CupertinoTimerPicker(
|
||||
mode: CupertinoTimerPickerMode.hm,
|
||||
onTimerDurationChanged:
|
||||
(Duration newDuration) {
|
||||
duration = newDuration;
|
||||
},
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
if (state is LoadingNewSate) {
|
||||
return;
|
||||
}
|
||||
if (countNum > 0) {
|
||||
twoGangBloc.add(SetCounterValue(
|
||||
deviceCode: deviceCode,
|
||||
duration: Duration.zero));
|
||||
} else if (duration != Duration.zero) {
|
||||
twoGangBloc.add(SetCounterValue(
|
||||
deviceCode: deviceCode,
|
||||
duration: duration));
|
||||
}
|
||||
},
|
||||
child: SvgPicture.asset(countNum > 0
|
||||
? Assets.pauseIcon
|
||||
: Assets.playIcon)),
|
||||
],
|
||||
Container(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
decoration: const ShapeDecoration(
|
||||
color: ColorsManager.onPrimaryColor,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius:
|
||||
BorderRadius.all(Radius.circular(30)),
|
||||
),
|
||||
),
|
||||
),
|
||||
Column(
|
||||
mainAxisAlignment:twoGangBloc.listSchedule.isNotEmpty?
|
||||
MainAxisAlignment.start:MainAxisAlignment.center,
|
||||
children: [
|
||||
SizedBox(
|
||||
child: twoGangBloc.createSchedule == true ?
|
||||
CreateSchedule(
|
||||
onToggleChanged: (bool isOn) {
|
||||
twoGangBloc.toggleSchedule = isOn;
|
||||
},
|
||||
onDateTimeChanged: (DateTime dateTime) {
|
||||
twoGangBloc.selectedTime=dateTime;
|
||||
},
|
||||
days: twoGangBloc.days,
|
||||
selectDays: (List<String> selectedDays) {
|
||||
twoGangBloc.selectedDays = selectedDays;
|
||||
},
|
||||
)
|
||||
:
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 10),
|
||||
child: ScheduleListView(
|
||||
listSchedule: twoGangBloc.listSchedule, // Pass the schedule list here
|
||||
onDismissed: (scheduleId) {
|
||||
twoGangBloc.listSchedule.removeWhere((schedule) => schedule.scheduleId == scheduleId);
|
||||
twoGangBloc.add(DeleteScheduleEvent(id: scheduleId));
|
||||
},
|
||||
onToggleSchedule: (scheduleId, isEnabled) {
|
||||
twoGangBloc.add(ToggleScheduleEvent(
|
||||
id: scheduleId,
|
||||
toggle: isEnabled,
|
||||
));
|
||||
},
|
||||
),
|
||||
child: TabBar(
|
||||
onTap: (value) {
|
||||
if (value == 0) {
|
||||
if (twoGangBloc.createSchedule ==
|
||||
true) {
|
||||
// oneGangBloc.toggleCreateSchedule();
|
||||
twoGangBloc.add(
|
||||
const ToggleCreateScheduleEvent(
|
||||
index: 0));
|
||||
}
|
||||
twoGangBloc.add(
|
||||
const ToggleSelectedEvent(
|
||||
index: 0));
|
||||
} else {
|
||||
twoGangBloc.add(
|
||||
const ToggleSelectedEvent(
|
||||
index: 1));
|
||||
}
|
||||
},
|
||||
indicatorColor:
|
||||
Colors.white, // Customize the indicator
|
||||
dividerHeight: 0,
|
||||
indicatorSize: TabBarIndicatorSize.tab,
|
||||
indicator: const ShapeDecoration(
|
||||
color: ColorsManager.slidingBlueColor,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(20)),
|
||||
),
|
||||
),
|
||||
],
|
||||
tabs: [
|
||||
Tab(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 10),
|
||||
child: BodySmall(
|
||||
text: 'Countdown',
|
||||
style: context.bodySmall.copyWith(
|
||||
color: ColorsManager.blackColor,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Tab(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 10),
|
||||
child: Text(
|
||||
'Schedule',
|
||||
style: context.bodySmall.copyWith(
|
||||
color: ColorsManager.blackColor,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: TabBarView(
|
||||
physics: const NeverScrollableScrollPhysics(), // Disable swiping
|
||||
|
||||
children: [
|
||||
Center(
|
||||
child: Column(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.center,
|
||||
children: [
|
||||
countNum > 0
|
||||
? BodyLarge(
|
||||
text: _formatDuration(
|
||||
countNum),
|
||||
fontColor: ColorsManager
|
||||
.slidingBlueColor,
|
||||
fontSize: 40,
|
||||
)
|
||||
: CupertinoTimerPicker(
|
||||
mode:
|
||||
CupertinoTimerPickerMode
|
||||
.hm,
|
||||
onTimerDurationChanged:
|
||||
(Duration
|
||||
newDuration) {
|
||||
duration = newDuration;
|
||||
},
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
if (state
|
||||
is LoadingNewSate) {
|
||||
return;
|
||||
}
|
||||
if (countNum > 0) {
|
||||
twoGangBloc.add(
|
||||
SetCounterValue(
|
||||
deviceCode:
|
||||
deviceCode,
|
||||
duration: Duration
|
||||
.zero));
|
||||
} else if (duration !=
|
||||
Duration.zero) {
|
||||
twoGangBloc.add(
|
||||
SetCounterValue(
|
||||
deviceCode:
|
||||
deviceCode,
|
||||
duration:
|
||||
duration));
|
||||
}
|
||||
},
|
||||
child: SvgPicture.asset(
|
||||
countNum > 0
|
||||
? Assets.pauseIcon
|
||||
: Assets.playIcon)),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
child: twoGangBloc.createSchedule ==
|
||||
true
|
||||
? CreateSchedule(
|
||||
onToggleChanged: (bool isOn) {
|
||||
twoGangBloc.toggleSchedule =
|
||||
isOn;
|
||||
},
|
||||
onDateTimeChanged:
|
||||
(DateTime dateTime) {
|
||||
twoGangBloc.selectedTime =
|
||||
dateTime;
|
||||
},
|
||||
days: twoGangBloc.days,
|
||||
selectDays: (List<String>
|
||||
selectedDays) {
|
||||
twoGangBloc.selectedDays =
|
||||
selectedDays;
|
||||
},
|
||||
)
|
||||
: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 10),
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: ScheduleListView(
|
||||
listSchedule: twoGangBloc
|
||||
.listSchedule, // Pass the schedule list here
|
||||
onDismissed:
|
||||
(scheduleId) {
|
||||
twoGangBloc
|
||||
.listSchedule
|
||||
.removeWhere(
|
||||
(schedule) =>
|
||||
schedule
|
||||
.scheduleId ==
|
||||
scheduleId);
|
||||
twoGangBloc.add(
|
||||
DeleteScheduleEvent(
|
||||
id: scheduleId));
|
||||
},
|
||||
onToggleSchedule:
|
||||
(scheduleId,
|
||||
isEnabled) {
|
||||
twoGangBloc.add(
|
||||
ToggleScheduleEvent(
|
||||
id: scheduleId,
|
||||
toggle: isEnabled,
|
||||
));
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
))
|
||||
);
|
||||
)));
|
||||
},
|
||||
),
|
||||
),
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||
|
||||
|
||||
class InchingWidget extends StatefulWidget {
|
||||
const InchingWidget({super.key,this.onDateTimeChanged});
|
||||
const InchingWidget({super.key, this.onDateTimeChanged});
|
||||
final Function(DateTime)? onDateTimeChanged;
|
||||
|
||||
@override
|
||||
@@ -22,7 +20,7 @@ class _InchingWidgetState extends State<InchingWidget> {
|
||||
children: [
|
||||
DefaultContainer(
|
||||
child: Container(
|
||||
padding: EdgeInsets.all(10),
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
@@ -46,26 +44,29 @@ class _InchingWidgetState extends State<InchingWidget> {
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 10,),
|
||||
const Text('Once enabled this feature, each time the device is turned on, it will automatically turn of after a period time as pre-set.'),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
const Text(
|
||||
'Once enabled this feature, each time the device is turned on, it will automatically turn of after a period time as pre-set.'),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const Padding(
|
||||
padding: EdgeInsets.only(right: 30,left: 30),
|
||||
padding: EdgeInsets.only(right: 30, left: 30),
|
||||
child: Divider(),
|
||||
),
|
||||
Container(
|
||||
child: MinuteSecondPicker()),
|
||||
Container(child: MinuteSecondPicker()),
|
||||
const Padding(
|
||||
padding: EdgeInsets.only(right: 30,left: 30),
|
||||
padding: EdgeInsets.only(right: 30, left: 30),
|
||||
child: Divider(),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class MinuteSecondPicker extends StatefulWidget {
|
||||
const MinuteSecondPicker({super.key});
|
||||
|
||||
@@ -79,7 +80,7 @@ class _MinuteSecondPickerState extends State<MinuteSecondPicker> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Center(
|
||||
return Center(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
@@ -98,10 +99,9 @@ class _MinuteSecondPickerState extends State<MinuteSecondPicker> {
|
||||
children: List<Widget>.generate(61, (int index) {
|
||||
return Center(
|
||||
child: BodyLarge(
|
||||
text: index.toString().padLeft(2, '0'),
|
||||
text: index.toString().padLeft(2, '0'),
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.w400,
|
||||
fontSize: 30,color: Colors.blue),
|
||||
fontWeight: FontWeight.w400, fontSize: 30, color: Colors.blue),
|
||||
),
|
||||
);
|
||||
}),
|
||||
@@ -124,20 +124,17 @@ class _MinuteSecondPickerState extends State<MinuteSecondPicker> {
|
||||
children: List<Widget>.generate(60, (int index) {
|
||||
return Center(
|
||||
child: BodyLarge(
|
||||
text: index.toString().padLeft(2, '0'),
|
||||
text: index.toString().padLeft(2, '0'),
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.w400,
|
||||
fontSize: 30,color: Colors.blue),
|
||||
fontWeight: FontWeight.w400, fontSize: 30, color: Colors.blue),
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
),
|
||||
const Text('S'),
|
||||
|
||||
],
|
||||
),
|
||||
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
@@ -13,7 +8,6 @@ import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
||||
import 'package:syncrow_app/generated/assets.dart';
|
||||
|
||||
|
||||
class CirculateListView extends StatelessWidget {
|
||||
final List<ScheduleModel> listSchedule;
|
||||
final Function(String) onDismissed;
|
||||
@@ -30,96 +24,98 @@ class CirculateListView extends StatelessWidget {
|
||||
return Center(
|
||||
child: listSchedule.isNotEmpty
|
||||
? SizedBox(
|
||||
child: ListView.builder(
|
||||
shrinkWrap: true,
|
||||
itemCount: listSchedule.length,
|
||||
itemBuilder: (context, index) {
|
||||
return Dismissible(
|
||||
key: Key(listSchedule[index].scheduleId),
|
||||
background: Container(
|
||||
padding: const EdgeInsets.only(right: 10),
|
||||
alignment: AlignmentDirectional.centerEnd,
|
||||
decoration: const ShapeDecoration(
|
||||
color: Color(0xFFFF0000),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(20)),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 10, right: 10),
|
||||
child: SvgPicture.asset(
|
||||
Assets.assetsDeleteIcon,
|
||||
width: 20,
|
||||
height: 22,
|
||||
),
|
||||
),
|
||||
),
|
||||
direction: DismissDirection.endToStart,
|
||||
onDismissed: (direction) {
|
||||
child: ListView.builder(
|
||||
shrinkWrap: true,
|
||||
itemCount: listSchedule.length,
|
||||
itemBuilder: (context, index) {
|
||||
return Dismissible(
|
||||
key: Key(listSchedule[index].scheduleId),
|
||||
background: Container(
|
||||
padding: const EdgeInsets.only(right: 10),
|
||||
alignment: AlignmentDirectional.centerEnd,
|
||||
decoration: const ShapeDecoration(
|
||||
color: Color(0xFFFF0000),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(20)),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 10, right: 10),
|
||||
child: SvgPicture.asset(
|
||||
Assets.assetsDeleteIcon,
|
||||
width: 20,
|
||||
height: 22,
|
||||
),
|
||||
),
|
||||
),
|
||||
direction: DismissDirection.endToStart,
|
||||
onDismissed: (direction) {
|
||||
onDismissed(listSchedule[index].scheduleId);
|
||||
|
||||
onDismissed(listSchedule[index].scheduleId);
|
||||
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('Schedule removed')),
|
||||
);
|
||||
},
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
|
||||
},
|
||||
child: DefaultContainer(
|
||||
padding: const EdgeInsets.all(20),
|
||||
height: MediaQuery.of(context).size.height / 6.4,
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('Schedule removed')),
|
||||
);
|
||||
},
|
||||
child: InkWell(
|
||||
onTap: () {},
|
||||
child: DefaultContainer(
|
||||
padding: const EdgeInsets.all(20),
|
||||
height: MediaQuery.of(context).size.height / 6.5,
|
||||
child: Row(
|
||||
children: [
|
||||
BodyLarge(
|
||||
text: '12:30 AM - 01:30 PM',
|
||||
// text: listSchedule[index].time,
|
||||
fontWeight: FontWeight.w500,
|
||||
fontColor: Colors.black,
|
||||
fontSize: 22,
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
BodyLarge(
|
||||
text: '12:30 AM - 01:30 PM',
|
||||
// text: listSchedule[index].time,
|
||||
fontWeight: FontWeight.w500,
|
||||
fontColor: Colors.black,
|
||||
fontSize: 18,
|
||||
),
|
||||
],
|
||||
),
|
||||
Text(listSchedule[index].days.join(' ')),
|
||||
// Text('Function ${listSchedule[index].function.value ? "ON" : "OFF"}'),
|
||||
Text(
|
||||
'Start Duration: 0h 10m End Duration: 0h 15m'),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
leading: const BodyMedium(
|
||||
text: '',
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
trailing: Transform.scale(
|
||||
scale: .8,
|
||||
child: CupertinoSwitch(
|
||||
value: listSchedule[index].enable,
|
||||
onChanged: (value) {
|
||||
onToggleSchedule(
|
||||
listSchedule[index].scheduleId,
|
||||
value,
|
||||
);
|
||||
},
|
||||
applyTheme: true,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(listSchedule[index].days.join(' ')),
|
||||
// Text('Function ${listSchedule[index].function.value ? "ON" : "OFF"}'),
|
||||
Text('Start Duration: 0h 10m End Duration: 0h 15m'),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
leading: const BodyMedium(
|
||||
text: '',
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
trailing: Transform.scale(
|
||||
scale: .8,
|
||||
child: CupertinoSwitch(
|
||||
value: listSchedule[index].enable,
|
||||
onChanged: (value) {
|
||||
onToggleSchedule(
|
||||
listSchedule[index].scheduleId,
|
||||
value,
|
||||
);
|
||||
},
|
||||
applyTheme: true,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
)
|
||||
: const EmptySchedule()
|
||||
);
|
||||
)
|
||||
: const EmptySchedule());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,10 +21,10 @@ class WaterHeaterPage extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DefaultScaffold(
|
||||
title: 'Water heater',
|
||||
child: BlocProvider(
|
||||
create: (context) =>
|
||||
WaterHeaterBloc(switchCode: 'switch_1', whId: device?.uuid ?? '')
|
||||
..add(const WaterHeaterInitial()),
|
||||
create: (context) => WaterHeaterBloc(switchCode: 'switch_1', whId: device?.uuid ?? '')
|
||||
..add(const WaterHeaterInitial()),
|
||||
child: BlocBuilder<WaterHeaterBloc, WaterHeaterState>(
|
||||
builder: (context, state) {
|
||||
final waterHeaterBloc = BlocProvider.of<WaterHeaterBloc>(context);
|
||||
@@ -36,10 +36,8 @@ class WaterHeaterPage extends StatelessWidget {
|
||||
}
|
||||
return state is WHLoadingState
|
||||
? const Center(
|
||||
child: DefaultContainer(
|
||||
width: 50,
|
||||
height: 50,
|
||||
child: CircularProgressIndicator()),
|
||||
child:
|
||||
DefaultContainer(width: 50, height: 50, child: CircularProgressIndicator()),
|
||||
)
|
||||
: RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
@@ -53,13 +51,11 @@ class WaterHeaterPage extends StatelessWidget {
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
InkWell(
|
||||
overlayColor: MaterialStateProperty.all(
|
||||
Colors.transparent),
|
||||
overlayColor: MaterialStateProperty.all(Colors.transparent),
|
||||
onTap: () {
|
||||
waterHeaterBloc.add(
|
||||
WaterHeaterSwitch(
|
||||
whSwitch:whModel.firstSwitch
|
||||
),);
|
||||
WaterHeaterSwitch(whSwitch: whModel.firstSwitch),
|
||||
);
|
||||
},
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
@@ -68,26 +64,22 @@ class WaterHeaterPage extends StatelessWidget {
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
// color: Colors.white.withOpacity(0.1),
|
||||
borderRadius:
|
||||
BorderRadius.circular(890),
|
||||
borderRadius: BorderRadius.circular(890),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color:
|
||||
Colors.white.withOpacity(0.1),
|
||||
color: Colors.white.withOpacity(0.1),
|
||||
blurRadius: 24,
|
||||
offset: const Offset(-5, -5),
|
||||
blurStyle: BlurStyle.outer,
|
||||
),
|
||||
BoxShadow(
|
||||
color:
|
||||
Colors.black.withOpacity(0.11),
|
||||
color: Colors.black.withOpacity(0.11),
|
||||
blurRadius: 25,
|
||||
offset: const Offset(5, 5),
|
||||
blurStyle: BlurStyle.outer,
|
||||
),
|
||||
BoxShadow(
|
||||
color:
|
||||
Colors.black.withOpacity(0.13),
|
||||
color: Colors.black.withOpacity(0.13),
|
||||
blurRadius: 30,
|
||||
offset: const Offset(5, 5),
|
||||
blurStyle: BlurStyle.inner,
|
||||
@@ -111,8 +103,7 @@ class WaterHeaterPage extends StatelessWidget {
|
||||
Card(
|
||||
elevation: 3,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius:
|
||||
BorderRadius.circular(100),
|
||||
borderRadius: BorderRadius.circular(100),
|
||||
),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
@@ -121,8 +112,10 @@ class WaterHeaterPage extends StatelessWidget {
|
||||
PageRouteBuilder(
|
||||
pageBuilder: (context, animation1, animation2) =>
|
||||
WHTimerScheduleScreen(
|
||||
switchCode: 'switch_1', device: device!, deviceCode: 'countdown_1',
|
||||
)));
|
||||
switchCode: 'switch_1',
|
||||
device: device!,
|
||||
deviceCode: 'countdown_1',
|
||||
)));
|
||||
},
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
@@ -132,8 +125,7 @@ class WaterHeaterPage extends StatelessWidget {
|
||||
height: 60,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey[300],
|
||||
borderRadius:
|
||||
BorderRadius.circular(100),
|
||||
borderRadius: BorderRadius.circular(100),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
@@ -141,14 +133,12 @@ class WaterHeaterPage extends StatelessWidget {
|
||||
height: 40,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius:
|
||||
BorderRadius.circular(100),
|
||||
borderRadius: BorderRadius.circular(100),
|
||||
),
|
||||
child: Center(
|
||||
child: Icon(
|
||||
Icons.access_time,
|
||||
color: ColorsManager
|
||||
.primaryColorWithOpacity,
|
||||
color: ColorsManager.primaryColorWithOpacity,
|
||||
size: 25,
|
||||
),
|
||||
),
|
||||
|
||||
@@ -76,33 +76,39 @@ class WHTimerScheduleScreen extends StatelessWidget {
|
||||
fontWeight: FontsManager.bold,
|
||||
),
|
||||
actions: [
|
||||
waterHeaterBloc.createSchedule == true && waterHeaterBloc.selectedTabIndex == 1 ?
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
waterHeaterBloc.add(ScheduleSave());
|
||||
},
|
||||
child: const Text('Save')) : waterHeaterBloc.selectedTabIndex == 1
|
||||
? IconButton(
|
||||
onPressed: () {
|
||||
waterHeaterBloc.toggleCreateSchedule();
|
||||
},
|
||||
icon: const Icon(Icons.add),
|
||||
)
|
||||
: const SizedBox(),
|
||||
waterHeaterBloc.createCirculate == true &&waterHeaterBloc.selectedTabIndex==2 ?
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
waterHeaterBloc.add(ScheduleSave());
|
||||
},
|
||||
child: const Text('Save'))
|
||||
: waterHeaterBloc.selectedTabIndex == 2
|
||||
? IconButton(
|
||||
onPressed: () {
|
||||
waterHeaterBloc.toggleCreateCirculate();
|
||||
waterHeaterBloc.createSchedule == true &&
|
||||
waterHeaterBloc.selectedTabIndex == 1
|
||||
? TextButton(
|
||||
onPressed: () {
|
||||
waterHeaterBloc.add(ScheduleSave());
|
||||
},
|
||||
icon: const Icon(Icons.add),
|
||||
)
|
||||
: const SizedBox(),
|
||||
child: const Text('Save'))
|
||||
: waterHeaterBloc.selectedTabIndex == 1
|
||||
? IconButton(
|
||||
onPressed: () {
|
||||
// waterHeaterBloc.toggleCreateSchedule();
|
||||
waterHeaterBloc.add(
|
||||
const ToggleCreateScheduleEvent(
|
||||
index: 1));
|
||||
},
|
||||
icon: const Icon(Icons.add),
|
||||
)
|
||||
: const SizedBox(),
|
||||
waterHeaterBloc.createCirculate == true &&
|
||||
waterHeaterBloc.selectedTabIndex == 2
|
||||
? TextButton(
|
||||
onPressed: () {
|
||||
waterHeaterBloc.add(ScheduleSave());
|
||||
},
|
||||
child: const Text('Save'))
|
||||
: waterHeaterBloc.selectedTabIndex == 2
|
||||
? IconButton(
|
||||
onPressed: () {
|
||||
waterHeaterBloc.toggleCreateCirculate();
|
||||
},
|
||||
icon: const Icon(Icons.add),
|
||||
)
|
||||
: const SizedBox(),
|
||||
],
|
||||
),
|
||||
child: state is WHLoadingState
|
||||
@@ -124,20 +130,51 @@ class WHTimerScheduleScreen extends StatelessWidget {
|
||||
labelPadding: EdgeInsets.zero,
|
||||
onTap: (value) {
|
||||
if (value == 0) {
|
||||
if (waterHeaterBloc.createSchedule == true) {
|
||||
waterHeaterBloc.toggleCreateSchedule();
|
||||
if (waterHeaterBloc.createSchedule ==
|
||||
true) {
|
||||
// waterHeaterBloc
|
||||
// .toggleCreateSchedule();
|
||||
waterHeaterBloc.add(
|
||||
const ToggleCreateScheduleEvent(
|
||||
index: 1));
|
||||
}
|
||||
waterHeaterBloc.toggleSelectedIndex(value);
|
||||
} else if (value == 2) {
|
||||
if (waterHeaterBloc.createCirculate == true) {
|
||||
waterHeaterBloc.toggleCreateCirculate();
|
||||
waterHeaterBloc.add(
|
||||
ToggleSelectedEvent(
|
||||
index: value));
|
||||
// waterHeaterBloc
|
||||
// .toggleSelectedIndex(value);
|
||||
} else if (value == 2) {
|
||||
if (waterHeaterBloc.createCirculate ==
|
||||
true) {
|
||||
waterHeaterBloc.add(
|
||||
ToggleCreateCirculateEvent(
|
||||
index: value));
|
||||
// waterHeaterBloc
|
||||
// .toggleCreateCirculate();
|
||||
}
|
||||
waterHeaterBloc.toggleSelectedIndex(value);
|
||||
waterHeaterBloc.add(
|
||||
ToggleSelectedEvent(
|
||||
index: value));
|
||||
// waterHeaterBloc
|
||||
// .toggleSelectedIndex(value);
|
||||
} else {
|
||||
if (waterHeaterBloc.createSchedule == true) {
|
||||
waterHeaterBloc.toggleCreateSchedule();
|
||||
if (waterHeaterBloc.createSchedule ==
|
||||
true) {
|
||||
waterHeaterBloc.add(
|
||||
ToggleSelectedEvent(
|
||||
index: value));
|
||||
// waterHeaterBloc
|
||||
// .toggleCreateSchedule();
|
||||
}
|
||||
waterHeaterBloc.toggleSelectedIndex(value);
|
||||
waterHeaterBloc.createCirculate =
|
||||
false;
|
||||
waterHeaterBloc.createSchedule =
|
||||
false;
|
||||
waterHeaterBloc.add(
|
||||
ToggleSelectedEvent(
|
||||
index: value));
|
||||
// waterHeaterBloc
|
||||
// .toggleSelectedIndex(value);
|
||||
}
|
||||
},
|
||||
indicatorColor: Colors.white,
|
||||
@@ -151,96 +188,128 @@ class WHTimerScheduleScreen extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
isScrollable: false,
|
||||
labelColor: Colors.white, // Text color when selected
|
||||
unselectedLabelColor: ColorsManager.blackColor, // Text color when not selected
|
||||
labelColor: Colors
|
||||
.white, // Text color when selected
|
||||
unselectedLabelColor: ColorsManager
|
||||
.blackColor, // Text color when not selected
|
||||
tabs: [
|
||||
Tab(
|
||||
icon: SvgPicture.asset(
|
||||
Assets.scheduleTimeIcon,
|
||||
color: waterHeaterBloc.selectedTabIndex == 0
|
||||
? Colors.white
|
||||
: ColorsManager.blackColor, // Change icon color based on selectedIndex
|
||||
icon: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 10.0),
|
||||
child: SvgPicture.asset(
|
||||
Assets.scheduleTimeIcon,
|
||||
color: waterHeaterBloc
|
||||
.selectedTabIndex ==
|
||||
0
|
||||
? Colors.white
|
||||
: ColorsManager
|
||||
.blackColor, // Change icon color based on selectedIndex
|
||||
),
|
||||
),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 10),
|
||||
vertical: 5),
|
||||
child: BodySmall(
|
||||
text: 'Countdown',
|
||||
style: context.bodySmall.copyWith(
|
||||
color: waterHeaterBloc.selectedTabIndex == 0
|
||||
color: waterHeaterBloc
|
||||
.selectedTabIndex ==
|
||||
0
|
||||
? Colors.white
|
||||
: ColorsManager
|
||||
.blackColor, // Text color based on selectedTabIndex
|
||||
fontSize: 8,
|
||||
fontSize: 10,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Tab(
|
||||
icon: SvgPicture.asset(
|
||||
Assets.scheduleCelenderIcon,
|
||||
color: waterHeaterBloc.selectedTabIndex == 1
|
||||
? Colors.white
|
||||
: ColorsManager.blackColor,
|
||||
icon: Padding(
|
||||
padding:
|
||||
const EdgeInsets.only(top: 10),
|
||||
child: SvgPicture.asset(
|
||||
Assets.scheduleCelenderIcon,
|
||||
color: waterHeaterBloc
|
||||
.selectedTabIndex ==
|
||||
1
|
||||
? Colors.white
|
||||
: ColorsManager.blackColor,
|
||||
),
|
||||
),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 10),
|
||||
vertical: 5),
|
||||
child: Text(
|
||||
'Schedule',
|
||||
style: context.bodySmall.copyWith(
|
||||
color: waterHeaterBloc.selectedTabIndex == 1
|
||||
color: waterHeaterBloc
|
||||
.selectedTabIndex ==
|
||||
1
|
||||
? Colors.white
|
||||
: ColorsManager.blackColor,
|
||||
fontSize: 8,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Tab(
|
||||
icon: SvgPicture.asset(
|
||||
Assets.scheduleCirculateIcon,
|
||||
color: waterHeaterBloc.selectedTabIndex == 2
|
||||
? Colors.white
|
||||
: ColorsManager.blackColor,
|
||||
icon: Padding(
|
||||
padding:
|
||||
const EdgeInsets.only(top: 10),
|
||||
child: SvgPicture.asset(
|
||||
Assets.scheduleCirculateIcon,
|
||||
color: waterHeaterBloc
|
||||
.selectedTabIndex ==
|
||||
2
|
||||
? Colors.white
|
||||
: ColorsManager.blackColor,
|
||||
),
|
||||
),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 10),
|
||||
vertical: 5),
|
||||
child: Text(
|
||||
'Circulate',
|
||||
style: context.bodySmall.copyWith(
|
||||
color: waterHeaterBloc
|
||||
.selectedTabIndex == 2
|
||||
.selectedTabIndex ==
|
||||
2
|
||||
? Colors.white
|
||||
: ColorsManager.blackColor,
|
||||
fontSize: 8,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Tab(
|
||||
icon: SvgPicture.asset(
|
||||
Assets.scheduleInchingIcon,
|
||||
color: waterHeaterBloc
|
||||
.selectedTabIndex == 3
|
||||
? Colors.white
|
||||
: ColorsManager.blackColor,
|
||||
icon: Padding(
|
||||
padding:
|
||||
const EdgeInsets.only(top: 10),
|
||||
child: SvgPicture.asset(
|
||||
Assets.scheduleInchingIcon,
|
||||
color: waterHeaterBloc
|
||||
.selectedTabIndex ==
|
||||
3
|
||||
? Colors.white
|
||||
: ColorsManager.blackColor,
|
||||
),
|
||||
),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 10),
|
||||
vertical: 5),
|
||||
child: Text(
|
||||
'Inching',
|
||||
style: context.bodySmall.copyWith(
|
||||
color: waterHeaterBloc
|
||||
.selectedTabIndex == 3
|
||||
.selectedTabIndex ==
|
||||
3
|
||||
? Colors.white
|
||||
: ColorsManager.blackColor,
|
||||
fontSize: 8,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
@@ -308,93 +377,132 @@ class WHTimerScheduleScreen extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
),
|
||||
Column(
|
||||
mainAxisAlignment: waterHeaterBloc
|
||||
.listSchedule.isNotEmpty
|
||||
? MainAxisAlignment.start
|
||||
: MainAxisAlignment.center,
|
||||
children: [
|
||||
SizedBox(
|
||||
child: waterHeaterBloc.createSchedule == true
|
||||
? CreateSchedule(
|
||||
onToggleChanged: (bool isOn) {
|
||||
waterHeaterBloc.toggleSchedule = isOn;
|
||||
},
|
||||
onDateTimeChanged: (DateTime dateTime) {
|
||||
waterHeaterBloc.selectedTime = dateTime;
|
||||
},
|
||||
days: waterHeaterBloc.days,
|
||||
selectDays: (List<String>
|
||||
selectedDays) {
|
||||
waterHeaterBloc
|
||||
.selectedDays =
|
||||
selectedDays;
|
||||
},
|
||||
)
|
||||
: Padding(
|
||||
padding: const EdgeInsets.only(top: 10),
|
||||
child: ScheduleListView(
|
||||
listSchedule: waterHeaterBloc.listSchedule, // Pass the schedule list here
|
||||
onDismissed:
|
||||
(scheduleId) {
|
||||
waterHeaterBloc.listSchedule.removeWhere(
|
||||
(schedule) => schedule.scheduleId == scheduleId);
|
||||
waterHeaterBloc.add(
|
||||
DeleteScheduleEvent(id: scheduleId));
|
||||
},
|
||||
onToggleSchedule: (scheduleId, isEnabled) {
|
||||
|
||||
waterHeaterBloc.add(ToggleScheduleEvent(
|
||||
id: scheduleId, toggle: isEnabled,
|
||||
));
|
||||
},
|
||||
SizedBox(
|
||||
child: waterHeaterBloc.createSchedule ==
|
||||
true
|
||||
? CreateSchedule(
|
||||
onToggleChanged: (bool isOn) {
|
||||
waterHeaterBloc
|
||||
.toggleSchedule = isOn;
|
||||
},
|
||||
onDateTimeChanged:
|
||||
(DateTime dateTime) {
|
||||
waterHeaterBloc.selectedTime =
|
||||
dateTime;
|
||||
},
|
||||
days: waterHeaterBloc.days,
|
||||
selectDays: (List<String>
|
||||
selectedDays) {
|
||||
waterHeaterBloc.selectedDays =
|
||||
selectedDays;
|
||||
},
|
||||
)
|
||||
: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 10),
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: ScheduleListView(
|
||||
listSchedule:
|
||||
waterHeaterBloc
|
||||
.listSchedule, // Pass the schedule list here
|
||||
onDismissed:
|
||||
(scheduleId) {
|
||||
waterHeaterBloc
|
||||
.listSchedule
|
||||
.removeWhere(
|
||||
(schedule) =>
|
||||
schedule
|
||||
.scheduleId ==
|
||||
scheduleId);
|
||||
waterHeaterBloc.add(
|
||||
DeleteScheduleEvent(
|
||||
id: scheduleId));
|
||||
},
|
||||
onToggleSchedule:
|
||||
(scheduleId,
|
||||
isEnabled) {
|
||||
waterHeaterBloc.add(
|
||||
ToggleScheduleEvent(
|
||||
id: scheduleId,
|
||||
toggle: isEnabled,
|
||||
));
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Center(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.center,
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.center,
|
||||
children: [
|
||||
waterHeaterBloc.createCirculate == true
|
||||
?
|
||||
CirculateWidget(
|
||||
endDuration: () {
|
||||
waterHeaterBloc.add(SelectTimeEvent(context: context, isEffective: false));
|
||||
},
|
||||
startDuration: () {
|
||||
waterHeaterBloc.add(SelectTimeEvent(context: context, isEffective: false));
|
||||
|
||||
},
|
||||
isStartEndTime: true,
|
||||
startTime: DateTime.now(),
|
||||
endTime: DateTime.now(),
|
||||
days: waterHeaterBloc.days,
|
||||
selectedDays: [],
|
||||
onToggleStartEndTime: (c) {},
|
||||
onTimeChanged: (x, f) {
|
||||
},
|
||||
onDaySelected: (p0) {},
|
||||
):CirculateListView(
|
||||
listSchedule: waterHeaterBloc.listSchedule, // Pass the schedule list here
|
||||
onDismissed: (scheduleId) {
|
||||
waterHeaterBloc.listSchedule.removeWhere((schedule) => schedule.scheduleId == scheduleId);
|
||||
waterHeaterBloc.add(DeleteScheduleEvent(id: scheduleId));
|
||||
},
|
||||
onToggleSchedule: (scheduleId, isEnabled) {
|
||||
waterHeaterBloc.add(ToggleScheduleEvent(
|
||||
id: scheduleId, toggle: isEnabled,
|
||||
));
|
||||
},
|
||||
)
|
||||
waterHeaterBloc.createCirculate ==
|
||||
true
|
||||
? CirculateWidget(
|
||||
endDuration: () {
|
||||
waterHeaterBloc.add(
|
||||
SelectTimeEvent(
|
||||
context: context,
|
||||
isEffective:
|
||||
false));
|
||||
},
|
||||
startDuration: () {
|
||||
waterHeaterBloc.add(
|
||||
SelectTimeEvent(
|
||||
context: context,
|
||||
isEffective:
|
||||
false));
|
||||
},
|
||||
isStartEndTime: true,
|
||||
startTime: DateTime.now(),
|
||||
endTime: DateTime.now(),
|
||||
days: waterHeaterBloc.days,
|
||||
selectedDays: [],
|
||||
onToggleStartEndTime:
|
||||
(c) {},
|
||||
onTimeChanged: (x, f) {},
|
||||
onDaySelected: (p0) {},
|
||||
)
|
||||
: CirculateListView(
|
||||
listSchedule: [], // Pass the schedule list here
|
||||
onDismissed: (scheduleId) {
|
||||
waterHeaterBloc
|
||||
.listSchedule
|
||||
.removeWhere((schedule) =>
|
||||
schedule
|
||||
.scheduleId ==
|
||||
scheduleId);
|
||||
waterHeaterBloc.add(
|
||||
DeleteScheduleEvent(
|
||||
id: scheduleId));
|
||||
},
|
||||
onToggleSchedule:
|
||||
(scheduleId,
|
||||
isEnabled) {
|
||||
waterHeaterBloc.add(
|
||||
ToggleScheduleEvent(
|
||||
id: scheduleId,
|
||||
toggle: isEnabled,
|
||||
));
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
Column(children: [
|
||||
SizedBox(height: 20),
|
||||
Container(child: InchingWidget(),),],)
|
||||
Column(
|
||||
children: [
|
||||
SizedBox(height: 20),
|
||||
Container(
|
||||
child: InchingWidget(),
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -2,7 +2,9 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_category_model.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/ACs/acs_view.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/one_gang/one_gang_Interface.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/three_gang/three_gang_interface.dart';
|
||||
import 'package:syncrow_app/features/devices/view/widgets/two_gang/two_gang_Interface.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
||||
import 'package:syncrow_app/utils/context_extension.dart';
|
||||
@@ -39,6 +41,18 @@ class WizardPage extends StatelessWidget {
|
||||
pageBuilder: (context, animation1, animation2) =>
|
||||
const ThreeGangInterface()));
|
||||
}
|
||||
if (groupsList[index].name == '2G') {
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
pageBuilder: (context, animation1, animation2) => const TwoGangInterface()));
|
||||
}
|
||||
if (groupsList[index].name == '1G') {
|
||||
Navigator.push(
|
||||
context,
|
||||
PageRouteBuilder(
|
||||
pageBuilder: (context, animation1, animation2) => const OneGangInterface()));
|
||||
}
|
||||
},
|
||||
child: DefaultContainer(
|
||||
padding: const EdgeInsets.all(15),
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
|
||||
|
||||
|
||||
class BatteryBar extends StatelessWidget {
|
||||
const BatteryBar({
|
||||
required this.batteryPercentage,
|
||||
super.key,
|
||||
});
|
||||
|
||||
final int batteryPercentage;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
SizedBox(),
|
||||
Transform.rotate(
|
||||
angle: 1.5708, // 90 degrees in radians (π/2 or 1.5708)
|
||||
child: Icon(
|
||||
_getBatteryIcon(batteryPercentage),
|
||||
color: _getBatteryColor(batteryPercentage),
|
||||
size: 30,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
IconData _getBatteryIcon(int batteryLevel) {
|
||||
// if (batteryState == BatteryState.charging) {
|
||||
// return Icons.battery_charging_full;
|
||||
// } else
|
||||
if (batteryLevel >= 80) {
|
||||
return Icons.battery_full;
|
||||
} else if (batteryLevel >= 60) {
|
||||
return Icons.battery_4_bar;
|
||||
} else if (batteryLevel >= 40) {
|
||||
return Icons.battery_3_bar;
|
||||
} else if (batteryLevel >= 20) {
|
||||
return Icons.battery_2_bar;
|
||||
} else {
|
||||
return Icons.battery_alert;
|
||||
}
|
||||
}
|
||||
|
||||
Color _getBatteryColor(int batteryLevel) {
|
||||
if (batteryLevel >= 80) {
|
||||
return Colors.green;
|
||||
} else if (batteryLevel >= 40) {
|
||||
return Colors.yellowAccent;
|
||||
} else {
|
||||
return Colors.red;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,13 @@
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:syncrow_app/features/devices/model/schedule_model.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_button.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
||||
import 'package:syncrow_app/generated/assets.dart';
|
||||
import 'empty_schedule.dart'; // for SVG icons
|
||||
|
||||
|
||||
class ScheduleListView extends StatelessWidget {
|
||||
final List<ScheduleModel> listSchedule;
|
||||
final Function(String) onDismissed;
|
||||
@@ -24,97 +21,97 @@ class ScheduleListView extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Center(
|
||||
child: listSchedule.isNotEmpty
|
||||
? SizedBox(
|
||||
child: ListView.builder(
|
||||
shrinkWrap: true,
|
||||
itemCount: listSchedule.length,
|
||||
itemBuilder: (context, index) {
|
||||
return Dismissible(
|
||||
key: Key(listSchedule[index].scheduleId),
|
||||
background: Container(
|
||||
padding: const EdgeInsets.only(right: 10),
|
||||
alignment: AlignmentDirectional.centerEnd,
|
||||
decoration: const ShapeDecoration(
|
||||
color: Color(0xFFFF0000),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(20)),
|
||||
return listSchedule.isNotEmpty
|
||||
? SizedBox(
|
||||
child: ListView.builder(
|
||||
shrinkWrap: true,
|
||||
itemCount: listSchedule.length,
|
||||
itemBuilder: (context, index) {
|
||||
return Dismissible(
|
||||
key: Key(listSchedule[index].scheduleId),
|
||||
background: Container(
|
||||
padding: const EdgeInsets.only(right: 10),
|
||||
alignment: AlignmentDirectional.centerEnd,
|
||||
decoration: const ShapeDecoration(
|
||||
color: Color(0xFFFF0000),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(20)),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 10, right: 10),
|
||||
child: SvgPicture.asset(
|
||||
Assets.assetsDeleteIcon,
|
||||
width: 20,
|
||||
height: 22,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 10, right: 10),
|
||||
child: SvgPicture.asset(
|
||||
Assets.assetsDeleteIcon,
|
||||
width: 20,
|
||||
height: 22,
|
||||
direction: DismissDirection.endToStart,
|
||||
onDismissed: (direction) {
|
||||
onDismissed(listSchedule[index].scheduleId);
|
||||
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('Schedule removed')),
|
||||
);
|
||||
},
|
||||
child: InkWell(
|
||||
onTap: () {},
|
||||
child: DefaultContainer(
|
||||
padding: const EdgeInsets.all(20),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
BodyLarge(
|
||||
text: listSchedule[index].time,
|
||||
fontWeight: FontWeight.w500,
|
||||
fontColor: Colors.black,
|
||||
fontSize: 22,
|
||||
),
|
||||
Text(listSchedule[index].days.join(' ')),
|
||||
Text(
|
||||
'Function ${listSchedule[index].function.value ? "ON" : "OFF"}'),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
leading: const BodyMedium(
|
||||
text: '',
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
trailing: Transform.scale(
|
||||
scale: .8,
|
||||
child: CupertinoSwitch(
|
||||
value: listSchedule[index].enable,
|
||||
onChanged: (value) {
|
||||
onToggleSchedule(
|
||||
listSchedule[index].scheduleId,
|
||||
value,
|
||||
);
|
||||
},
|
||||
applyTheme: true,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
direction: DismissDirection.endToStart,
|
||||
onDismissed: (direction) {
|
||||
|
||||
onDismissed(listSchedule[index].scheduleId);
|
||||
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('Schedule removed')),
|
||||
);
|
||||
},
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
|
||||
},
|
||||
child: DefaultContainer(
|
||||
padding: const EdgeInsets.all(20),
|
||||
height: MediaQuery.of(context).size.height / 6.4,
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
BodyLarge(
|
||||
text: listSchedule[index].time,
|
||||
fontWeight: FontWeight.w500,
|
||||
fontColor: Colors.black,
|
||||
fontSize: 22,
|
||||
),
|
||||
Text(listSchedule[index].days.join(' ')),
|
||||
Text('Function ${listSchedule[index].function.value ? "ON" : "OFF"}'),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
leading: const BodyMedium(
|
||||
text: '',
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
trailing: Transform.scale(
|
||||
scale: .8,
|
||||
child: CupertinoSwitch(
|
||||
value: listSchedule[index].enable,
|
||||
onChanged: (value) {
|
||||
onToggleSchedule(
|
||||
listSchedule[index].scheduleId,
|
||||
value,
|
||||
);
|
||||
},
|
||||
applyTheme: true,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
)
|
||||
: const EmptySchedule()
|
||||
);
|
||||
),
|
||||
)
|
||||
: const Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Center(child: EmptySchedule()),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -735,7 +735,7 @@ class Assets {
|
||||
|
||||
//assets/icons/success-white.svg
|
||||
//assets for success white image
|
||||
static const String assetsSuccessWhite ="assets/icons/success-white.svg";
|
||||
static const String assetsSuccessWhite = "assets/icons/success-white.svg";
|
||||
|
||||
/// Assets for assetsImagesAutomation
|
||||
/// assets/images/automation.jpg
|
||||
@@ -1044,13 +1044,19 @@ class Assets {
|
||||
static const String waterHeaterOn = "assets/icons/water_heater_on.svg";
|
||||
static const String waterHeaterOff = "assets/icons/water_heater_off.svg";
|
||||
|
||||
static const String scheduleCelenderIcon = "assets/icons/schedule_celender_icon.svg";
|
||||
static const String scheduleCirculateIcon = "assets/icons/schedule_circulate_icon.svg";
|
||||
static const String scheduleInchingIcon = "assets/icons/schedule_Inching_icon.svg";
|
||||
static const String scheduleCelenderIcon =
|
||||
"assets/icons/schedule_celender_icon.svg";
|
||||
static const String scheduleCirculateIcon =
|
||||
"assets/icons/schedule_circulate_icon.svg";
|
||||
static const String scheduleInchingIcon =
|
||||
"assets/icons/schedule_Inching_icon.svg";
|
||||
static const String scheduleTimeIcon = "assets/icons/schedule_time_icon.svg";
|
||||
static const String waterHeaterIcon = "assets/icons/water_heater_icon.svg";
|
||||
|
||||
|
||||
|
||||
|
||||
static const String doorOpen = "assets/icons/opened_door.svg";
|
||||
static const String doorClose = "assets/icons/closed_door.svg";
|
||||
static const String doorNotificationSetting =
|
||||
"assets/icons/door_notification_setting_icon.svg";
|
||||
static const String doorRecordsIcon = "assets/icons/door_records_icon.svg";
|
||||
static const String doorSensorIcon = "assets/icons/door_sensor_icon.svg";
|
||||
}
|
||||
|
||||
@@ -81,7 +81,8 @@ abstract class ApiEndpoints {
|
||||
static const String controlGroup = '/group/control';
|
||||
//GET
|
||||
static const String groupBySpace = '/group/{unitUuid}';
|
||||
static const String devicesByGroupName = '/group/{unitUuid}/devices/{groupName}';
|
||||
static const String devicesByGroupName =
|
||||
'/group/{unitUuid}/devices/{groupName}';
|
||||
|
||||
static const String groupByUuid = '/group/{groupUuid}';
|
||||
//DELETE
|
||||
@@ -93,7 +94,8 @@ abstract class ApiEndpoints {
|
||||
static const String addDeviceToRoom = '/device/room';
|
||||
static const String addDeviceToGroup = '/device/group';
|
||||
static const String controlDevice = '/device/{deviceUuid}/control';
|
||||
static const String firmwareDevice = '/device/{deviceUuid}/firmware/{firmwareVersion}';
|
||||
static const String firmwareDevice =
|
||||
'/device/{deviceUuid}/firmware/{firmwareVersion}';
|
||||
static const String getDevicesByUserId = '/device/user/{userId}';
|
||||
static const String getDevicesByUnitId = '/device/unit/{unitUuid}';
|
||||
static const String openDoorLock = '/door-lock/open/{doorLockUuid}';
|
||||
@@ -103,7 +105,8 @@ abstract class ApiEndpoints {
|
||||
static const String deviceByUuid = '/device/{deviceUuid}';
|
||||
static const String deviceFunctions = '/device/{deviceUuid}/functions';
|
||||
static const String gatewayApi = '/device/gateway/{gatewayUuid}/devices';
|
||||
static const String deviceFunctionsStatus = '/device/{deviceUuid}/functions/status';
|
||||
static const String deviceFunctionsStatus =
|
||||
'/device/{deviceUuid}/functions/status';
|
||||
|
||||
///Device Permission Module
|
||||
//POST
|
||||
@@ -128,24 +131,29 @@ abstract class ApiEndpoints {
|
||||
|
||||
static const String getUnitAutomation = '/automation/{unitUuid}';
|
||||
|
||||
static const String getAutomationDetails = '/automation/details/{automationId}';
|
||||
static const String getAutomationDetails =
|
||||
'/automation/details/{automationId}';
|
||||
|
||||
/// PUT
|
||||
static const String updateScene = '/scene/tap-to-run/{sceneId}';
|
||||
|
||||
static const String updateAutomation = '/automation/{automationId}';
|
||||
|
||||
static const String updateAutomationStatus = '/automation/status/{automationId}';
|
||||
static const String updateAutomationStatus =
|
||||
'/automation/status/{automationId}';
|
||||
|
||||
/// DELETE
|
||||
static const String deleteScene = '/scene/tap-to-run/{unitUuid}/{sceneId}';
|
||||
|
||||
static const String deleteAutomation = '/automation/{unitUuid}/{automationId}';
|
||||
static const String deleteAutomation =
|
||||
'/automation/{unitUuid}/{automationId}';
|
||||
|
||||
//////////////////////Door Lock //////////////////////
|
||||
//online
|
||||
static const String addTemporaryPassword = '/door-lock/temporary-password/online/{doorLockUuid}';
|
||||
static const String getTemporaryPassword = '/door-lock/temporary-password/online/{doorLockUuid}';
|
||||
static const String addTemporaryPassword =
|
||||
'/door-lock/temporary-password/online/{doorLockUuid}';
|
||||
static const String getTemporaryPassword =
|
||||
'/door-lock/temporary-password/online/{doorLockUuid}';
|
||||
|
||||
//one-time offline
|
||||
static const String addOneTimeTemporaryPassword =
|
||||
@@ -176,11 +184,10 @@ abstract class ApiEndpoints {
|
||||
static const String deleteTemporaryPassword =
|
||||
'/door-lock/temporary-password/online/{doorLockUuid}/{passwordId}';
|
||||
|
||||
|
||||
static const String saveSchedule = '/schedule/{deviceUuid}';
|
||||
static const String getSchedule = '/schedule/{deviceUuid}?category={category}';
|
||||
static const String getSchedule =
|
||||
'/schedule/{deviceUuid}?category={category}';
|
||||
static const String changeSchedule = '/schedule/enable/{deviceUuid}';
|
||||
static const String deleteSchedule = '/schedule/{deviceUuid}/{scheduleId}';
|
||||
|
||||
|
||||
static const String reportLogs = '/device/report-logs/{deviceUuid}?code={code}&startTime={startTime}&endTime={endTime}';
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'dart:convert';
|
||||
import 'package:syncrow_app/features/devices/model/device_category_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_control_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/device_report_model.dart';
|
||||
import 'package:syncrow_app/features/devices/model/function_model.dart';
|
||||
import 'package:syncrow_app/services/api/api_links_endpoints.dart';
|
||||
import 'package:syncrow_app/services/api/http_service.dart';
|
||||
@@ -39,7 +40,6 @@ class DevicesAPI {
|
||||
expectedResponseModel: (json) {
|
||||
return json;
|
||||
},
|
||||
|
||||
);
|
||||
return response;
|
||||
} catch (e) {
|
||||
@@ -72,7 +72,8 @@ class DevicesAPI {
|
||||
|
||||
static Future<Map<String, dynamic>> getDeviceStatus(String deviceId) async {
|
||||
final response = await _httpService.get(
|
||||
path: ApiEndpoints.deviceFunctionsStatus.replaceAll('{deviceUuid}', deviceId),
|
||||
path: ApiEndpoints.deviceFunctionsStatus
|
||||
.replaceAll('{deviceUuid}', deviceId),
|
||||
showServerMessage: false,
|
||||
expectedResponseModel: (json) {
|
||||
return json;
|
||||
@@ -82,7 +83,9 @@ class DevicesAPI {
|
||||
}
|
||||
|
||||
static Future<Map<String, dynamic>> renamePass(
|
||||
{required String name, required String doorLockUuid, required String passwordId}) async {
|
||||
{required String name,
|
||||
required String doorLockUuid,
|
||||
required String passwordId}) async {
|
||||
final response = await _httpService.put(
|
||||
path: ApiEndpoints.renamePassword
|
||||
.replaceAll('{doorLockUuid}', doorLockUuid)
|
||||
@@ -107,7 +110,8 @@ class DevicesAPI {
|
||||
return response;
|
||||
}
|
||||
|
||||
static Future<List<DeviceModel>> getDeviceByGroupName(String unitId, String groupName) async {
|
||||
static Future<List<DeviceModel>> getDeviceByGroupName(
|
||||
String unitId, String groupName) async {
|
||||
final response = await _httpService.get(
|
||||
path: ApiEndpoints.devicesByGroupName
|
||||
.replaceAll('{unitUuid}', unitId)
|
||||
@@ -146,7 +150,8 @@ class DevicesAPI {
|
||||
return response;
|
||||
}
|
||||
|
||||
static Future<List<DeviceModel>> getDevicesByGatewayId(String gatewayId) async {
|
||||
static Future<List<DeviceModel>> getDevicesByGatewayId(
|
||||
String gatewayId) async {
|
||||
final response = await _httpService.get(
|
||||
path: ApiEndpoints.gatewayApi.replaceAll('{gatewayUuid}', gatewayId),
|
||||
showServerMessage: false,
|
||||
@@ -168,7 +173,8 @@ class DevicesAPI {
|
||||
String deviceId,
|
||||
) async {
|
||||
final response = await _httpService.get(
|
||||
path: ApiEndpoints.getTemporaryPassword.replaceAll('{doorLockUuid}', deviceId),
|
||||
path: ApiEndpoints.getTemporaryPassword
|
||||
.replaceAll('{doorLockUuid}', deviceId),
|
||||
showServerMessage: false,
|
||||
expectedResponseModel: (json) {
|
||||
return json;
|
||||
@@ -179,7 +185,8 @@ class DevicesAPI {
|
||||
|
||||
static Future getOneTimePasswords(String deviceId) async {
|
||||
final response = await _httpService.get(
|
||||
path: ApiEndpoints.getOneTimeTemporaryPassword.replaceAll('{doorLockUuid}', deviceId),
|
||||
path: ApiEndpoints.getOneTimeTemporaryPassword
|
||||
.replaceAll('{doorLockUuid}', deviceId),
|
||||
showServerMessage: false,
|
||||
expectedResponseModel: (json) {
|
||||
return json;
|
||||
@@ -190,7 +197,8 @@ class DevicesAPI {
|
||||
|
||||
static Future getTimeLimitPasswords(String deviceId) async {
|
||||
final response = await _httpService.get(
|
||||
path: ApiEndpoints.getMultipleTimeTemporaryPassword.replaceAll('{doorLockUuid}', deviceId),
|
||||
path: ApiEndpoints.getMultipleTimeTemporaryPassword
|
||||
.replaceAll('{doorLockUuid}', deviceId),
|
||||
showServerMessage: false,
|
||||
expectedResponseModel: (json) {
|
||||
return json;
|
||||
@@ -215,10 +223,12 @@ class DevicesAPI {
|
||||
"invalidTime": invalidTime,
|
||||
};
|
||||
if (scheduleList != null) {
|
||||
body["scheduleList"] = scheduleList.map((schedule) => schedule.toJson()).toList();
|
||||
body["scheduleList"] =
|
||||
scheduleList.map((schedule) => schedule.toJson()).toList();
|
||||
}
|
||||
final response = await _httpService.post(
|
||||
path: ApiEndpoints.addTemporaryPassword.replaceAll('{doorLockUuid}', deviceId),
|
||||
path: ApiEndpoints.addTemporaryPassword
|
||||
.replaceAll('{doorLockUuid}', deviceId),
|
||||
body: body,
|
||||
showServerMessage: false,
|
||||
expectedResponseModel: (json) => json,
|
||||
@@ -229,7 +239,8 @@ class DevicesAPI {
|
||||
static Future generateOneTimePassword({deviceId}) async {
|
||||
try {
|
||||
final response = await _httpService.post(
|
||||
path: ApiEndpoints.addOneTimeTemporaryPassword.replaceAll('{doorLockUuid}', deviceId),
|
||||
path: ApiEndpoints.addOneTimeTemporaryPassword
|
||||
.replaceAll('{doorLockUuid}', deviceId),
|
||||
showServerMessage: false,
|
||||
expectedResponseModel: (json) {
|
||||
return json;
|
||||
@@ -241,10 +252,12 @@ class DevicesAPI {
|
||||
}
|
||||
}
|
||||
|
||||
static Future generateMultiTimePassword({deviceId, effectiveTime, invalidTime}) async {
|
||||
static Future generateMultiTimePassword(
|
||||
{deviceId, effectiveTime, invalidTime}) async {
|
||||
try {
|
||||
final response = await _httpService.post(
|
||||
path: ApiEndpoints.addMultipleTimeTemporaryPassword.replaceAll('{doorLockUuid}', deviceId),
|
||||
path: ApiEndpoints.addMultipleTimeTemporaryPassword
|
||||
.replaceAll('{doorLockUuid}', deviceId),
|
||||
showServerMessage: true,
|
||||
body: {"effectiveTime": effectiveTime, "invalidTime": invalidTime},
|
||||
expectedResponseModel: (json) {
|
||||
@@ -277,21 +290,22 @@ class DevicesAPI {
|
||||
required String time,
|
||||
required String code,
|
||||
required bool value,
|
||||
required List<String> days,
|
||||
required List<String> days,
|
||||
}) async {
|
||||
final response = await _httpService.post(
|
||||
path: ApiEndpoints.saveSchedule.replaceAll('{deviceUuid}', deviceId),
|
||||
showServerMessage: false,
|
||||
body:
|
||||
jsonEncode({
|
||||
"category": category,
|
||||
"time": time,
|
||||
"function":{
|
||||
"code": code,
|
||||
"value":value,
|
||||
body: jsonEncode(
|
||||
{
|
||||
"category": category,
|
||||
"time": time,
|
||||
"function": {
|
||||
"code": code,
|
||||
"value": value,
|
||||
},
|
||||
"days": days
|
||||
},
|
||||
"days": days
|
||||
},),
|
||||
),
|
||||
expectedResponseModel: (json) {
|
||||
return json;
|
||||
},
|
||||
@@ -304,7 +318,9 @@ class DevicesAPI {
|
||||
required String deviceId,
|
||||
}) async {
|
||||
final response = await _httpService.get(
|
||||
path: ApiEndpoints.getSchedule.replaceAll('{deviceUuid}', deviceId).replaceAll('{category}', category),
|
||||
path: ApiEndpoints.getSchedule
|
||||
.replaceAll('{deviceUuid}', deviceId)
|
||||
.replaceAll('{category}', category),
|
||||
showServerMessage: false,
|
||||
expectedResponseModel: (json) {
|
||||
return json;
|
||||
@@ -320,10 +336,7 @@ class DevicesAPI {
|
||||
}) async {
|
||||
final response = await _httpService.put(
|
||||
path: ApiEndpoints.changeSchedule.replaceAll('{deviceUuid}', deviceUuid),
|
||||
body: {
|
||||
"scheduleId": scheduleId,
|
||||
"enable": enable
|
||||
},
|
||||
body: {"scheduleId": scheduleId, "enable": enable},
|
||||
expectedResponseModel: (json) {
|
||||
return json['success'];
|
||||
},
|
||||
@@ -336,11 +349,33 @@ class DevicesAPI {
|
||||
required String scheduleId,
|
||||
}) async {
|
||||
final response = await _httpService.delete(
|
||||
path: ApiEndpoints.deleteSchedule.replaceAll('{deviceUuid}', deviceUuid).replaceAll('{scheduleId}', scheduleId),
|
||||
path: ApiEndpoints.deleteSchedule
|
||||
.replaceAll('{deviceUuid}', deviceUuid)
|
||||
.replaceAll('{scheduleId}', scheduleId),
|
||||
expectedResponseModel: (json) {
|
||||
return json;
|
||||
},
|
||||
);
|
||||
return response;
|
||||
}
|
||||
|
||||
static Future<DeviceReport> getReportLogs({
|
||||
required String deviceUuid,
|
||||
required String code,
|
||||
required String startTime,
|
||||
required String endTime,
|
||||
}) async {
|
||||
final response = await _httpService.get(
|
||||
path: ApiEndpoints.reportLogs
|
||||
.replaceAll('{deviceUuid}', deviceUuid)
|
||||
.replaceAll('{code}', code)
|
||||
.replaceAll('{startTime}', startTime)
|
||||
.replaceAll('{endTime}', endTime),
|
||||
expectedResponseModel: (json) {
|
||||
return DeviceReport.fromJson(json);
|
||||
},
|
||||
);
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
//ignore_for_file: constant_identifier_names
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:syncrow_app/features/devices/model/function_model.dart';
|
||||
import 'package:syncrow_app/features/menu/view/widgets/create_home/create_home_view.dart';
|
||||
import 'package:syncrow_app/features/menu/view/widgets/join_home/join_home_view.dart';
|
||||
@@ -50,6 +49,7 @@ enum DeviceType {
|
||||
CeilingSensor,
|
||||
WallSensor,
|
||||
WH,
|
||||
DS,
|
||||
Other,
|
||||
}
|
||||
|
||||
@@ -75,11 +75,14 @@ Map<String, DeviceType> devicesTypesMap = {
|
||||
"1G": DeviceType.OneGang,
|
||||
"CUR": DeviceType.Curtain,
|
||||
"WH": DeviceType.WH,
|
||||
"DS": DeviceType.DS,
|
||||
};
|
||||
Map<DeviceType, List<FunctionModel>> devicesFunctionsMap = {
|
||||
DeviceType.AC: [
|
||||
FunctionModel(
|
||||
code: 'switch', type: functionTypesMap['Boolean'], values: ValueModel.fromJson({})),
|
||||
code: 'switch',
|
||||
type: functionTypesMap['Boolean'],
|
||||
values: ValueModel.fromJson({})),
|
||||
FunctionModel(
|
||||
code: 'mode',
|
||||
type: functionTypesMap['Enum'],
|
||||
@@ -102,7 +105,9 @@ Map<DeviceType, List<FunctionModel>> devicesFunctionsMap = {
|
||||
// "range": ["low", "middle", "high", "auto"]
|
||||
})),
|
||||
FunctionModel(
|
||||
code: 'child_lock', type: functionTypesMap['Boolean'], values: ValueModel.fromJson({})),
|
||||
code: 'child_lock',
|
||||
type: functionTypesMap['Boolean'],
|
||||
values: ValueModel.fromJson({})),
|
||||
],
|
||||
DeviceType.Gateway: [
|
||||
FunctionModel(
|
||||
@@ -116,7 +121,9 @@ Map<DeviceType, List<FunctionModel>> devicesFunctionsMap = {
|
||||
"range": ["normal", "alarm"]
|
||||
})),
|
||||
FunctionModel(
|
||||
code: 'factory_reset', type: functionTypesMap['Boolean'], values: ValueModel.fromJson({})),
|
||||
code: 'factory_reset',
|
||||
type: functionTypesMap['Boolean'],
|
||||
values: ValueModel.fromJson({})),
|
||||
FunctionModel(
|
||||
code: 'alarm_active',
|
||||
type: functionTypesMap['String'],
|
||||
@@ -126,7 +133,8 @@ Map<DeviceType, List<FunctionModel>> devicesFunctionsMap = {
|
||||
FunctionModel(
|
||||
code: 'sensitivity',
|
||||
type: functionTypesMap['Integer'],
|
||||
values: ValueModel.fromJson({"unit": "", "min": 1, "max": 10, "scale": 0, "step": 1})),
|
||||
values: ValueModel.fromJson(
|
||||
{"unit": "", "min": 1, "max": 10, "scale": 0, "step": 1})),
|
||||
],
|
||||
DeviceType.DoorLock: [
|
||||
FunctionModel(
|
||||
@@ -134,7 +142,9 @@ Map<DeviceType, List<FunctionModel>> devicesFunctionsMap = {
|
||||
type: functionTypesMap['Raw'],
|
||||
values: ValueModel.fromJson({})),
|
||||
FunctionModel(
|
||||
code: 'remote_no_dp_key', type: functionTypesMap['Raw'], values: ValueModel.fromJson({})),
|
||||
code: 'remote_no_dp_key',
|
||||
type: functionTypesMap['Raw'],
|
||||
values: ValueModel.fromJson({})),
|
||||
FunctionModel(
|
||||
code: 'normal_open_switch',
|
||||
type: functionTypesMap['Boolean'],
|
||||
@@ -144,120 +154,143 @@ Map<DeviceType, List<FunctionModel>> devicesFunctionsMap = {
|
||||
FunctionModel(
|
||||
code: 'far_detection',
|
||||
type: functionTypesMap['Integer'],
|
||||
values: ValueModel.fromJson({"unit": "cm", "min": 75, "max": 600, "scale": 0, "step": 75})),
|
||||
values: ValueModel.fromJson(
|
||||
{"unit": "cm", "min": 75, "max": 600, "scale": 0, "step": 75})),
|
||||
FunctionModel(
|
||||
code: 'presence_time',
|
||||
type: functionTypesMap['Integer'],
|
||||
values:
|
||||
ValueModel.fromJson({"unit": "Min", "min": 0, "max": 65535, "scale": 0, "step": 1})),
|
||||
values: ValueModel.fromJson(
|
||||
{"unit": "Min", "min": 0, "max": 65535, "scale": 0, "step": 1})),
|
||||
FunctionModel(
|
||||
code: 'motion_sensitivity_value',
|
||||
type: functionTypesMap['Integer'],
|
||||
values: ValueModel.fromJson({"unit": "", "min": 1, "max": 5, "scale": 0, "step": 1})),
|
||||
values: ValueModel.fromJson(
|
||||
{"unit": "", "min": 1, "max": 5, "scale": 0, "step": 1})),
|
||||
FunctionModel(
|
||||
code: 'motionless_sensitivity',
|
||||
type: functionTypesMap['Integer'],
|
||||
values: ValueModel.fromJson({"unit": "", "min": 1, "max": 5, "scale": 0, "step": 1})),
|
||||
values: ValueModel.fromJson(
|
||||
{"unit": "", "min": 1, "max": 5, "scale": 0, "step": 1})),
|
||||
FunctionModel(
|
||||
code: 'indicator', type: functionTypesMap['Boolean'], values: ValueModel.fromJson({})),
|
||||
code: 'indicator',
|
||||
type: functionTypesMap['Boolean'],
|
||||
values: ValueModel.fromJson({})),
|
||||
],
|
||||
DeviceType.OneGang:[
|
||||
DeviceType.OneGang: [
|
||||
FunctionModel(
|
||||
code: 'switch_1', type: functionTypesMap['Boolean'], values: ValueModel.fromJson({})),
|
||||
code: 'switch_1',
|
||||
type: functionTypesMap['Boolean'],
|
||||
values: ValueModel.fromJson({})),
|
||||
FunctionModel(
|
||||
code: 'countdown_1',
|
||||
type: functionTypesMap['Integer'],
|
||||
values: ValueModel.fromJson({"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
|
||||
values: ValueModel.fromJson(
|
||||
{"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
|
||||
],
|
||||
DeviceType.TwoGang:[
|
||||
DeviceType.TwoGang: [
|
||||
FunctionModel(
|
||||
code: 'switch_1', type: functionTypesMap['Boolean'], values: ValueModel.fromJson({})
|
||||
),
|
||||
code: 'switch_1',
|
||||
type: functionTypesMap['Boolean'],
|
||||
values: ValueModel.fromJson({})),
|
||||
FunctionModel(
|
||||
code: 'switch_2', type: functionTypesMap['Boolean'], values: ValueModel.fromJson({})
|
||||
),
|
||||
code: 'switch_2',
|
||||
type: functionTypesMap['Boolean'],
|
||||
values: ValueModel.fromJson({})),
|
||||
FunctionModel(
|
||||
code: 'countdown_1',
|
||||
type: functionTypesMap['Integer'],
|
||||
values: ValueModel.fromJson({"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})
|
||||
),
|
||||
values: ValueModel.fromJson(
|
||||
{"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
|
||||
FunctionModel(
|
||||
code: 'countdown_2',
|
||||
type: functionTypesMap['Integer'],
|
||||
values: ValueModel.fromJson({"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})
|
||||
),
|
||||
values: ValueModel.fromJson(
|
||||
{"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
|
||||
],
|
||||
DeviceType.ThreeGang: [
|
||||
FunctionModel(
|
||||
code: 'switch_1', type: functionTypesMap['Boolean'], values: ValueModel.fromJson({})),
|
||||
code: 'switch_1',
|
||||
type: functionTypesMap['Boolean'],
|
||||
values: ValueModel.fromJson({})),
|
||||
FunctionModel(
|
||||
code: 'switch_2', type: functionTypesMap['Boolean'], values: ValueModel.fromJson({})),
|
||||
code: 'switch_2',
|
||||
type: functionTypesMap['Boolean'],
|
||||
values: ValueModel.fromJson({})),
|
||||
FunctionModel(
|
||||
code: 'switch_3', type: functionTypesMap['Boolean'], values: ValueModel.fromJson({})),
|
||||
code: 'switch_3',
|
||||
type: functionTypesMap['Boolean'],
|
||||
values: ValueModel.fromJson({})),
|
||||
FunctionModel(
|
||||
code: 'countdown_1',
|
||||
type: functionTypesMap['Integer'],
|
||||
values: ValueModel.fromJson({"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
|
||||
values: ValueModel.fromJson(
|
||||
{"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
|
||||
FunctionModel(
|
||||
code: 'countdown_2',
|
||||
type: functionTypesMap['Integer'],
|
||||
values: ValueModel.fromJson({"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
|
||||
values: ValueModel.fromJson(
|
||||
{"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
|
||||
FunctionModel(
|
||||
code: 'countdown_3',
|
||||
type: functionTypesMap['Integer'],
|
||||
values: ValueModel.fromJson({"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
|
||||
values: ValueModel.fromJson(
|
||||
{"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
|
||||
],
|
||||
DeviceType.Curtain: [
|
||||
FunctionModel(
|
||||
code: 'control',
|
||||
type: functionTypesMap['Enum'],
|
||||
values: ValueModel.fromJson(
|
||||
{"range": ["open","stop","close"]}
|
||||
)
|
||||
),
|
||||
values: ValueModel.fromJson({
|
||||
"range": ["open", "stop", "close"]
|
||||
})),
|
||||
FunctionModel(
|
||||
code: 'percent_control',
|
||||
type: functionTypesMap['Integer'],
|
||||
values: ValueModel.fromJson(
|
||||
{"unit": "%", "min": 0, "max": 100, "scale": 0, "step": 1})
|
||||
),
|
||||
{"unit": "%", "min": 0, "max": 100, "scale": 0, "step": 1})),
|
||||
],
|
||||
DeviceType.WH: [
|
||||
FunctionModel(
|
||||
code: 'switch_1',
|
||||
type: functionTypesMap['Boolean'],
|
||||
values: ValueModel.fromJson({})
|
||||
),
|
||||
values: ValueModel.fromJson({})),
|
||||
FunctionModel(
|
||||
code: 'countdown_1',
|
||||
type: functionTypesMap['Integer'],
|
||||
values: ValueModel.fromJson(
|
||||
{"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})
|
||||
),
|
||||
{"unit": "s", "min": 0, "max": 43200, "scale": 0, "step": 1})),
|
||||
FunctionModel(
|
||||
code: 'relay_status',
|
||||
type: functionTypesMap['Enum'],
|
||||
values: ValueModel.fromJson(
|
||||
{"range": [ "off", "on"]})
|
||||
),
|
||||
values: ValueModel.fromJson({
|
||||
"range": ["off", "on"]
|
||||
})),
|
||||
FunctionModel(
|
||||
code: 'switch_backlight',
|
||||
type: functionTypesMap['Boolean'],
|
||||
values: ValueModel.fromJson(
|
||||
{})
|
||||
),
|
||||
values: ValueModel.fromJson({})),
|
||||
FunctionModel(
|
||||
code: 'switch_inching',
|
||||
type: functionTypesMap['String'],
|
||||
values: ValueModel.fromJson(
|
||||
{"maxlen": 255,})
|
||||
),
|
||||
values: ValueModel.fromJson({
|
||||
"maxlen": 255,
|
||||
})),
|
||||
FunctionModel(
|
||||
code: 'cycle_timing',
|
||||
type: functionTypesMap['Raw'],
|
||||
values: ValueModel.fromJson(
|
||||
{"maxlen": 255})
|
||||
),
|
||||
values: ValueModel.fromJson({"maxlen": 255})),
|
||||
],
|
||||
DeviceType.DS: [
|
||||
FunctionModel(
|
||||
code: 'doorcontact_state',
|
||||
type: functionTypesMap['Raw'],
|
||||
values: ValueModel.fromJson({})
|
||||
),
|
||||
FunctionModel(
|
||||
code: 'battery_percentage',
|
||||
type: functionTypesMap['Integer'],
|
||||
values: ValueModel.fromJson({})
|
||||
),
|
||||
],
|
||||
};
|
||||
|
||||
@@ -404,7 +437,11 @@ List<Map<String, Object>> menuSections = [
|
||||
'Icon': Assets.assetsIconsMenuIconsMessagesCenterIconsMessages,
|
||||
'page': null
|
||||
},
|
||||
{'title': 'FAQs', 'Icon': Assets.assetsIconsMenuIconsMessagesCenterIconsFAQs, 'page': null},
|
||||
{
|
||||
'title': 'FAQs',
|
||||
'Icon': Assets.assetsIconsMenuIconsMessagesCenterIconsFAQs,
|
||||
'page': null
|
||||
},
|
||||
{
|
||||
'title': 'Help & Feedback',
|
||||
'Icon': Assets.assetsIconsMenuIconsMessagesCenterIconsHelpAndFeedback,
|
||||
@@ -434,7 +471,11 @@ List<Map<String, Object>> menuSections = [
|
||||
'title': 'Legal Information',
|
||||
'color': const Color(0xFF001B72),
|
||||
'buttons': [
|
||||
{'title': 'About', 'Icon': Assets.assetsIconsMenuIconsLeagalInfoIconsAbout, 'page': null},
|
||||
{
|
||||
'title': 'About',
|
||||
'Icon': Assets.assetsIconsMenuIconsLeagalInfoIconsAbout,
|
||||
'page': null
|
||||
},
|
||||
{
|
||||
'title': 'Privacy Policy',
|
||||
'Icon': Assets.assetsIconsMenuIconsLeagalInfoIconsPrivacyPolicy,
|
||||
|
||||
Reference in New Issue
Block a user