Compare commits

..

11 Commits

Author SHA1 Message Date
76fbfd2d95 Removed vs_scrollbar package 2024-10-23 13:08:34 +03:00
0b15391868 push logout dialog design 2024-10-23 11:56:48 +03:00
1c9943cfdb finilizing the alert dialog for logut 2024-10-23 02:40:44 +03:00
bd7651fa8c push scroll bar and design enhancment 2024-10-23 01:15:17 +03:00
a3a92e5d3f Merge pull request #38 from SyncrowIOT/access_bug_fixes
access_bug_fixes
2024-10-09 21:30:58 +03:00
3102c3823a Bug fixes 2024-10-09 21:29:20 +03:00
d5395f4fe7 Merge pull request #39 from SyncrowIOT/bug_fixes_sprint_10
Bug fixes sprint 10
2024-10-09 20:35:05 +03:00
13e90abf76 access_bug_fixes 2024-10-09 17:43:17 +03:00
853cccbcce Merge pull request #36 from SyncrowIOT/bug_fixes_sprint_10
Bug fixes
2024-10-08 23:18:06 +03:00
62e03bac27 Merge pull request #35 from SyncrowIOT/bug_fixes_sprint_10
fix oct/8 issues
2024-10-08 20:41:01 +03:00
4653c519c4 Merge pull request #34 from SyncrowIOT/bug_fixes_sprint_10
Bug fixes sprint 10
2024-10-08 12:40:26 +03:00
26 changed files with 999 additions and 417 deletions

View File

@ -0,0 +1,6 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0.892857 12.1429H2.44054C2.60714 12.733 2.84125 13.2989 3.13875 13.8311L2.04518 14.9246C1.87643 15.0932 1.78357 15.3175 1.78357 15.5561C1.78357 15.7946 1.87661 16.0188 2.04518 16.1873L3.43196 17.5741C3.57125 17.7136 3.7975 17.7136 3.93696 17.5741C4.07643 17.4346 4.07643 17.2086 3.93696 17.0691L2.55018 15.6821C2.50464 15.6368 2.49786 15.5836 2.49786 15.5559C2.49786 15.5282 2.50464 15.4752 2.55018 15.4295L3.83821 14.1414C3.95464 14.025 3.97643 13.8441 3.89089 13.7034C3.51482 13.0843 3.23607 12.4105 3.0625 11.7009C3.02357 11.5411 2.88018 11.4286 2.71571 11.4286H0.892857C0.794464 11.4286 0.714286 11.3484 0.714286 11.25V8.75C0.714286 8.65161 0.794464 8.57143 0.892857 8.57143H2.71571C2.88036 8.57143 3.02357 8.45893 3.06268 8.29911C3.23607 7.58964 3.51482 6.91571 3.89107 6.29661C3.97661 6.15589 3.95464 5.975 3.83839 5.85857L2.55036 4.57054C2.50482 4.525 2.49804 4.47179 2.49804 4.44411C2.49804 4.41661 2.50482 4.36339 2.55036 4.31786L4.31804 2.55C4.38786 2.48018 4.50089 2.48036 4.57071 2.55L5.85875 3.83821C5.97518 3.95464 6.15607 3.97643 6.29679 3.89089C6.91607 3.51464 7.58982 3.23589 8.29929 3.0625C8.45893 3.02357 8.57143 2.88018 8.57143 2.71571V0.892857C8.57143 0.794464 8.65161 0.714286 8.75 0.714286H11.25C11.3484 0.714286 11.4286 0.794464 11.4286 0.892857V2.71571C11.4286 2.88036 11.5411 3.02357 11.7009 3.06268C12.4104 3.23607 13.0843 3.51482 13.7034 3.89107C13.8441 3.97661 14.0252 3.95482 14.1414 3.83839L15.4295 2.55036C15.4991 2.48071 15.6125 2.48054 15.6821 2.55036L17.4498 4.31821C17.4954 4.36357 17.5021 4.41679 17.5021 4.44446C17.5021 4.47214 17.4954 4.52518 17.4498 4.57089L16.1618 5.85893C16.0454 5.97536 16.0236 6.15625 16.1091 6.29696C16.4854 6.91625 16.7641 7.59 16.9375 8.29946C16.9766 8.45929 17.1198 8.57179 17.2845 8.57179H19.1071C19.2055 8.57179 19.2857 8.65196 19.2857 8.75036V11.2504C19.2857 11.3488 19.2055 11.4289 19.1071 11.4289H17.2843C17.1196 11.4289 16.9764 11.5414 16.9373 11.7013C16.7639 12.4111 16.4852 13.0848 16.1089 13.7037C16.0234 13.8445 16.0452 14.0254 16.1616 14.1418L17.4496 15.4298C17.4952 15.4754 17.502 15.5286 17.502 15.5562C17.502 15.5837 17.4952 15.637 17.4496 15.6825L16.0629 17.0693C15.9234 17.2087 15.9234 17.4348 16.0629 17.5743C16.1327 17.6441 16.2239 17.6789 16.3154 17.6789C16.4068 17.6789 16.4982 17.6441 16.5679 17.5743L17.9546 16.1875C18.1232 16.0189 18.2163 15.7946 18.2163 15.5561C18.2163 15.3175 18.1234 15.0934 17.9546 14.9246L16.8611 13.8311C17.1586 13.2989 17.3927 12.7332 17.5593 12.1429H19.1071C19.5995 12.1429 20 11.7423 20 11.25V8.75C20 8.25768 19.5995 7.85714 19.1071 7.85714H17.5595C17.3929 7.26714 17.1588 6.70125 16.8612 6.16911L17.9548 5.07554C18.1236 4.90696 18.2164 4.68268 18.2164 4.44411C18.2164 4.20554 18.1234 3.98143 17.9548 3.81286L16.1871 2.045C15.8391 1.69696 15.2727 1.69679 14.9245 2.045L13.8309 3.13857C13.2988 2.84107 12.7329 2.60696 12.1429 2.44036V0.892857C12.1429 0.400536 11.7423 0 11.25 0H8.75C8.25768 0 7.85714 0.400536 7.85714 0.892857V2.44054C7.26714 2.60714 6.70125 2.84125 6.16911 3.13875L5.07554 2.045C4.72732 1.69696 4.16089 1.69696 3.81286 2.045L2.04518 3.81268C1.87661 3.98125 1.78357 4.20554 1.78357 4.44411C1.78357 4.68268 1.87643 4.90679 2.04518 5.07554L3.13875 6.16911C2.84125 6.70125 2.60714 7.26714 2.44054 7.85714H0.892857C0.400536 7.85714 0 8.25768 0 8.75V11.25C0 11.7423 0.400536 12.1429 0.892857 12.1429Z" fill="black"/>
<path d="M13.3929 9.28568C13.3929 7.41479 11.8709 5.89282 10 5.89282C8.12914 5.89282 6.60718 7.41479 6.60718 9.28568C6.60718 11.1566 8.12914 12.6785 10 12.6785C11.8709 12.6785 13.3929 11.1566 13.3929 9.28568ZM7.32146 9.28568C7.32146 7.80871 8.52307 6.60711 10 6.60711C11.477 6.60711 12.6786 7.80871 12.6786 9.28568C12.6786 10.7626 11.477 11.9643 10 11.9643C8.52307 11.9643 7.32146 10.7626 7.32146 9.28568Z" fill="black"/>
<path d="M4.64282 17.3214V18.75C4.64282 19.4393 5.20354 20 5.89282 20H14.1071C14.7964 20 15.3571 19.4393 15.3571 18.75V17.3214C15.3571 15.1551 13.5948 13.3928 11.4285 13.3928H8.57139C6.40514 13.3928 4.64282 15.1551 4.64282 17.3214ZM8.57139 14.1071H11.4285C13.2009 14.1071 14.6428 15.5491 14.6428 17.3214V18.75C14.6428 19.0453 14.4025 19.2857 14.1071 19.2857H5.89282C5.59747 19.2857 5.35711 19.0453 5.35711 18.75V17.3214C5.35711 15.5491 6.79907 14.1071 8.57139 14.1071Z" fill="black"/>
<path d="M10.3571 15.7143H11.3048C12.1607 15.7143 12.8571 16.4107 12.8571 17.2666C12.8571 17.4638 13.0171 17.6238 13.2143 17.6238C13.4114 17.6238 13.5714 17.4638 13.5714 17.2666C13.5714 16.0168 12.5546 15 11.3048 15H10.3571C10.16 15 10 15.16 10 15.3571C10 15.5543 10.16 15.7143 10.3571 15.7143Z" fill="black"/>
</svg>

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

@ -0,0 +1,4 @@
<svg width="39" height="39" viewBox="0 0 39 39" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="19.5" cy="19.5" r="18.5" fill="#D9D9D9" stroke="white" stroke-width="2"/>
<path opacity="0.994" fill-rule="evenodd" clip-rule="evenodd" d="M13.7258 10.75C14.6614 10.75 15.597 10.75 16.5326 10.75C16.5718 11.8783 17.0678 12.7378 18.0205 13.3285C19.1166 13.9015 20.1818 13.8508 21.2162 13.1763C22.0192 12.5708 22.4363 11.762 22.4674 10.75C23.403 10.75 24.3386 10.75 25.2742 10.75C25.2418 12.4975 24.5795 13.9516 23.2874 15.1123C23.2762 15.1236 23.2762 15.1349 23.2874 15.1461C23.4903 15.3265 23.682 15.5181 23.8623 15.721C25.0293 14.4194 26.4919 13.7543 28.25 13.7258C28.25 14.6614 28.25 15.597 28.25 16.5326C27.215 16.5583 26.3949 16.9866 25.7899 17.8176C25.2517 18.6453 25.1333 19.5301 25.4348 20.4722C25.948 21.7316 26.8864 22.3967 28.25 22.4674C28.25 23.403 28.25 24.3386 28.25 25.2742C26.4961 25.2406 25.0363 24.5755 23.8708 23.279C23.6793 23.4845 23.4793 23.6818 23.2705 23.8708C23.2593 23.882 23.2593 23.8933 23.2705 23.9046C24.5686 25.0695 25.2364 26.5293 25.2742 28.2838C24.3386 28.2838 23.403 28.2838 22.4674 28.2838C22.408 27.0503 21.8331 26.1514 20.7428 25.587C19.6978 25.1484 18.7059 25.2442 17.7669 25.8744C16.9735 26.4776 16.5621 27.2807 16.5326 28.2838C15.597 28.2838 14.6614 28.2838 13.7258 28.2838C13.7577 26.5268 14.4255 25.067 15.7295 23.9046C15.7407 23.8933 15.7407 23.882 15.7295 23.8708C15.5207 23.6818 15.3207 23.4845 15.1292 23.279C13.9613 24.57 12.5016 25.2351 10.75 25.2742C10.75 24.3386 10.75 23.403 10.75 22.4674C11.9627 22.4124 12.856 21.8544 13.43 20.7935C13.9025 19.7273 13.8123 18.7128 13.1594 17.75C12.5542 16.9612 11.751 16.5555 10.75 16.5326C10.75 15.597 10.75 14.6614 10.75 13.7258C12.5067 13.7576 13.9693 14.4227 15.1377 15.721C15.2222 15.6252 15.3068 15.5294 15.3913 15.4336C15.5042 15.3348 15.6141 15.2333 15.721 15.1292C14.4204 13.9649 13.7554 12.5051 13.7258 10.75ZM19.2717 16.5326C20.3739 16.4946 21.2559 16.9117 21.9179 17.7838C22.6033 18.8416 22.6427 19.9238 22.0362 21.0302C21.4416 21.9421 20.5962 22.4211 19.5 22.4674C18.4038 22.4211 17.5584 21.9421 16.9638 21.0302C16.3957 20.0193 16.3901 19.0048 16.9469 17.9867C17.4892 17.1319 18.2641 16.6472 19.2717 16.5326Z" fill="#FEFFFE"/>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -0,0 +1,4 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10.9333 20H9.06667C8.43583 20 7.90333 19.5275 7.82833 18.9L7.62917 17.3367C7.23167 17.2075 6.84833 17.0483 6.48417 16.8625L5.23917 17.83C4.73417 18.2208 4.02333 18.1758 3.585 17.725L2.2725 16.4125C1.825 15.9783 1.78 15.2675 2.17083 14.7633L3.13833 13.5175C2.95167 13.1533 2.7925 12.77 2.66417 12.3725L1.0975 12.1733C0.4725 12.0967 0 11.5642 0 10.9333V9.06667C0 8.43583 0.4725 7.90333 1.1 7.82833L2.66333 7.62917C2.7925 7.23167 2.95167 6.84833 3.1375 6.48417L2.17083 5.23917C1.77917 4.73417 1.825 4.0225 2.27667 3.58417L3.58917 2.27167C4.02333 1.82417 4.735 1.78 5.23833 2.17L6.48333 3.13833C6.8475 2.9525 7.23083 2.79333 7.62917 2.66417L7.82833 1.0975C7.90333 0.4725 8.43583 0 9.06667 0H10.9333C11.5642 0 12.0967 0.4725 12.1717 1.1L12.3708 2.66333C12.7692 2.7925 13.1525 2.95167 13.5167 3.1375L14.7617 2.17C15.2675 1.77917 15.9775 1.82417 16.4158 2.27583L17.7283 3.58833C18.1758 4.0225 18.2208 4.73333 17.83 5.2375L16.8625 6.48333C17.0492 6.8475 17.2083 7.23083 17.3367 7.62833L18.9033 7.8275C19.5275 7.90333 20 8.43583 20 9.06667V10.9333C20 11.5642 19.5275 12.0967 18.9 12.1717L17.3367 12.3708C17.2075 12.7683 17.0483 13.1517 16.8625 13.5158L17.83 14.7608C18.2217 15.2658 18.1758 15.9767 17.7242 16.415L16.4117 17.7275C15.9775 18.175 15.2658 18.2208 14.7625 17.8292L13.5167 16.8617C13.1525 17.0483 12.7692 17.2075 12.3717 17.3358L12.1725 18.9025C12.0967 19.5275 11.5642 20 10.9333 20ZM6.44167 15.95C6.51083 15.95 6.58167 15.9675 6.645 16.0025C7.10417 16.2592 7.60167 16.4658 8.12333 16.6158C8.28333 16.6617 8.40083 16.7983 8.42167 16.9633L8.655 18.7967C8.68 19.0058 8.86083 19.1667 9.06667 19.1667H10.9333C11.1392 19.1667 11.32 19.0058 11.3442 18.8008L11.5783 16.9642C11.5992 16.7992 11.7167 16.6625 11.8767 16.6167C12.3983 16.4667 12.8958 16.26 13.355 16.0033C13.5008 15.9217 13.6825 15.9358 13.8133 16.0383L15.2717 17.1717C15.4392 17.3017 15.6742 17.2908 15.8175 17.1433L17.1383 15.8225C17.2892 15.6758 17.3008 15.4408 17.1708 15.2725L16.0375 13.8142C15.935 13.6825 15.9208 13.5017 16.0025 13.3558C16.2592 12.8967 16.4658 12.3992 16.6158 11.8775C16.6617 11.7175 16.7983 11.6 16.9633 11.5792L18.7967 11.3458C19.0058 11.32 19.1667 11.1392 19.1667 10.9333V9.06667C19.1667 8.86083 19.0058 8.68 18.8008 8.65583L16.9642 8.42167C16.7992 8.40083 16.6625 8.28333 16.6167 8.12333C16.4667 7.60167 16.26 7.10417 16.0033 6.645C15.9217 6.49917 15.935 6.31833 16.0383 6.18667L17.1717 4.72833C17.3025 4.56 17.2908 4.325 17.1442 4.18333L15.8233 2.8625C15.6775 2.71083 15.4417 2.69917 15.2733 2.83L13.815 3.96333C13.6825 4.06583 13.5017 4.08 13.3558 3.99833C12.8983 3.74167 12.4008 3.53583 11.8775 3.385C11.7175 3.33917 11.6 3.2025 11.5792 3.0375L11.3458 1.20417C11.32 0.994167 11.1392 0.833333 10.9333 0.833333H9.06667C8.86083 0.833333 8.68 0.994167 8.65583 1.19917L8.42167 3.03583C8.40083 3.20083 8.28333 3.3375 8.12333 3.38417C7.6 3.53417 7.1025 3.74083 6.645 3.99667C6.49917 4.07917 6.31833 4.06417 6.18583 3.9625L4.7275 2.82917C4.55917 2.69833 4.325 2.71 4.1825 2.85667L2.86167 4.17833C2.71083 4.325 2.69917 4.56 2.82917 4.72833L3.9625 6.18667C4.065 6.31833 4.07917 6.49917 3.9975 6.645C3.74 7.10417 3.53417 7.60167 3.38417 8.12333C3.33833 8.28333 3.20167 8.40083 3.03667 8.42167L1.20333 8.655C0.994167 8.68 0.833333 8.86083 0.833333 9.06667V10.9333C0.833333 11.1392 0.994167 11.32 1.19917 11.3442L3.03583 11.5783C3.20083 11.5992 3.3375 11.7167 3.38333 11.8767C3.53333 12.3983 3.74 12.8958 3.99667 13.355C4.07833 13.5008 4.065 13.6817 3.96167 13.8133L2.82833 15.2717C2.6975 15.44 2.70917 15.675 2.85583 15.8167L4.17667 17.1375C4.3225 17.2883 4.55667 17.3 4.72667 17.17L6.185 16.0367C6.26083 15.98 6.35083 15.95 6.44167 15.95Z" fill="black"/>
<path d="M10.0002 14.1666C7.70266 14.1666 5.8335 12.2974 5.8335 9.99992C5.8335 7.70242 7.70266 5.83325 10.0002 5.83325C12.2977 5.83325 14.1668 7.70242 14.1668 9.99992C14.1668 12.2974 12.2977 14.1666 10.0002 14.1666ZM10.0002 6.66659C8.16183 6.66659 6.66683 8.16159 6.66683 9.99992C6.66683 11.8383 8.16183 13.3333 10.0002 13.3333C11.8385 13.3333 13.3335 11.8383 13.3335 9.99992C13.3335 8.16159 11.8385 6.66659 10.0002 6.66659Z" fill="black"/>
</svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@ -0,0 +1,3 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M20 10C20 10 20 10.0017 20 10.0025C19.9983 10.5633 19.7783 11.0892 19.3783 11.4825L15.9267 14.88C15.8458 14.96 15.74 15 15.6342 15C15.5267 15 15.4192 14.9583 15.3375 14.8758C15.1767 14.7125 15.1783 14.4483 15.3425 14.2867L18.7942 10.8892C18.9308 10.7542 19.0283 10.5925 19.0908 10.4175H5.41667C5.18667 10.4175 5 10.2308 5 10.0008C5 9.77083 5.18667 9.58417 5.41667 9.58417H19.0917C19.0292 9.40667 18.9317 9.24333 18.7933 9.1075L15.3425 5.71417C15.1783 5.55333 15.1758 5.28917 15.3375 5.125C15.4983 4.96 15.7625 4.95833 15.9267 5.12L19.3775 8.51333C19.7783 8.90833 20 9.435 20 9.99833C20 9.99833 20 9.99917 20 10ZM9.58333 12.5C9.35333 12.5 9.16667 12.6867 9.16667 12.9167V16.25C9.16667 17.8583 7.85833 19.1667 6.25 19.1667H3.75C2.14167 19.1667 0.833333 17.8583 0.833333 16.25V3.75C0.833333 2.14167 2.14167 0.833333 3.75 0.833333H6.25C7.85833 0.833333 9.16667 2.14167 9.16667 3.75V7.08333C9.16667 7.31333 9.35333 7.5 9.58333 7.5C9.81333 7.5 10 7.31333 10 7.08333V3.75C10 1.6825 8.3175 0 6.25 0H3.75C1.6825 0 0 1.6825 0 3.75V16.25C0 18.3175 1.6825 20 3.75 20H6.25C8.3175 20 10 18.3175 10 16.25V12.9167C10 12.6867 9.81333 12.5 9.58333 12.5Z" fill="black"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -5,7 +5,6 @@ import 'package:syncrow_web/pages/access_management/bloc/access_state.dart';
import 'package:syncrow_web/pages/access_management/model/password_model.dart';
import 'package:syncrow_web/pages/common/hour_picker_dialog.dart';
import 'package:syncrow_web/services/access_mang_api.dart';
import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/constants/app_enum.dart';
import 'package:syncrow_web/utils/snack_bar.dart';

View File

@ -15,8 +15,8 @@ import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/constants/app_enum.dart';
import 'package:syncrow_web/utils/constants/assets.dart';
import 'package:syncrow_web/utils/extension/build_context_x.dart';
import 'package:syncrow_web/utils/style.dart';
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
import 'package:syncrow_web/utils/style.dart';
import 'package:syncrow_web/web_layout/web_scaffold.dart';
class AccessManagementPage extends StatelessWidget with HelperResponsiveLayout {
@ -24,7 +24,6 @@ class AccessManagementPage extends StatelessWidget with HelperResponsiveLayout {
@override
Widget build(BuildContext context) {
final isLargeScreen = isLargeScreenSize(context);
final isSmallScreen = isSmallScreenSize(context);
final isHalfMediumScreen = isHafMediumScreenSize(context);
@ -86,7 +85,7 @@ class AccessManagementPage extends StatelessWidget with HelperResponsiveLayout {
_buildVisitorAdminPasswords(context, accessBloc),
const SizedBox(height: 20),
Expanded(
child: DynamicTable(
child: DynamicTable(
tableName: 'AccessManagement',
uuidIndex: 1,
withSelectAll: true,
@ -169,7 +168,7 @@ class AccessManagementPage extends StatelessWidget with HelperResponsiveLayout {
}
Row _buildNormalSearchWidgets(BuildContext context, AccessBloc accessBloc) {
TimeOfDay _selectedTime = TimeOfDay.now();
// TimeOfDay _selectedTime = TimeOfDay.now();
return Row(
mainAxisSize: MainAxisSize.min,
@ -184,6 +183,14 @@ class AccessManagementPage extends StatelessWidget with HelperResponsiveLayout {
isRequired: false,
textFieldName: 'Name',
description: '',
onSubmitted: (value) {
accessBloc.add(FilterDataEvent(
emailAuthorizer: accessBloc.emailAuthorizer.text.toLowerCase(),
selectedTabIndex: BlocProvider.of<AccessBloc>(context).selectedIndex,
passwordName: accessBloc.passwordName.text.toLowerCase(),
startTime: accessBloc.effectiveTimeTimeStamp,
endTime: accessBloc.expirationTimeTimeStamp));
},
),
),
const SizedBox(width: 15),
@ -195,6 +202,14 @@ class AccessManagementPage extends StatelessWidget with HelperResponsiveLayout {
isRequired: false,
textFieldName: 'Authorizer',
description: '',
onSubmitted: (value) {
accessBloc.add(FilterDataEvent(
emailAuthorizer: accessBloc.emailAuthorizer.text.toLowerCase(),
selectedTabIndex: BlocProvider.of<AccessBloc>(context).selectedIndex,
passwordName: accessBloc.passwordName.text.toLowerCase(),
startTime: accessBloc.effectiveTimeTimeStamp,
endTime: accessBloc.expirationTimeTimeStamp));
},
),
),
const SizedBox(width: 15),
@ -205,7 +220,7 @@ class AccessManagementPage extends StatelessWidget with HelperResponsiveLayout {
title: 'Access Time',
size: MediaQuery.of(context).size,
endTime: () {
accessBloc.add(SelectTime(context: context, isStart: false));
accessBloc.add(SelectTime(context: context, isStart: false));
},
startTime: () {
accessBloc.add(SelectTime(context: context, isStart: true));
@ -218,7 +233,7 @@ class AccessManagementPage extends StatelessWidget with HelperResponsiveLayout {
SearchResetButtons(
onSearch: () {
accessBloc.add(FilterDataEvent(
emailAuthorizer:accessBloc.emailAuthorizer.text.toLowerCase() ,
emailAuthorizer: accessBloc.emailAuthorizer.text.toLowerCase(),
selectedTabIndex: BlocProvider.of<AccessBloc>(context).selectedIndex,
passwordName: accessBloc.passwordName.text.toLowerCase(),
startTime: accessBloc.effectiveTimeTimeStamp,
@ -240,12 +255,19 @@ class AccessManagementPage extends StatelessWidget with HelperResponsiveLayout {
SizedBox(
width: 300,
child: CustomWebTextField(
controller: accessBloc.passwordName,
isRequired: true,
height: 40,
textFieldName: 'Name',
description: '',
),
controller: accessBloc.passwordName,
isRequired: true,
height: 40,
textFieldName: 'Name',
description: '',
onSubmitted: (value) {
accessBloc.add(FilterDataEvent(
emailAuthorizer: accessBloc.emailAuthorizer.text.toLowerCase(),
selectedTabIndex: BlocProvider.of<AccessBloc>(context).selectedIndex,
passwordName: accessBloc.passwordName.text.toLowerCase(),
startTime: accessBloc.effectiveTimeTimeStamp,
endTime: accessBloc.expirationTimeTimeStamp));
}),
),
DateTimeWebWidget(
icon: Assets.calendarIcon,
@ -264,12 +286,11 @@ class AccessManagementPage extends StatelessWidget with HelperResponsiveLayout {
SearchResetButtons(
onSearch: () {
accessBloc.add(FilterDataEvent(
emailAuthorizer:accessBloc.emailAuthorizer.text.toLowerCase() ,
emailAuthorizer: accessBloc.emailAuthorizer.text.toLowerCase(),
selectedTabIndex: BlocProvider.of<AccessBloc>(context).selectedIndex,
passwordName: accessBloc.passwordName.text.toLowerCase(),
startTime: accessBloc.effectiveTimeTimeStamp,
endTime: accessBloc.expirationTimeTimeStamp
));
endTime: accessBloc.expirationTimeTimeStamp));
},
onReset: () {
accessBloc.add(ResetSearch());
@ -278,6 +299,4 @@ class AccessManagementPage extends StatelessWidget with HelperResponsiveLayout {
],
);
}
}

View File

@ -108,20 +108,9 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
}
} on DioException catch (e) {
final errorData = e.response!.data;
String errorMessage = errorData['message'];
if (errorMessage == 'this email is not registered') {
validate = 'Invalid Credentials!';
emit(AuthInitialState());
} else if (errorMessage == "You entered wrong otp") {
forgetValidate = 'Wrong one time password.';
emit(AuthInitialState());
} else if (errorMessage == "OTP expired") {
forgetValidate = 'One time password has been expired.';
emit(AuthInitialState());
} else {
validate = '';
emit(AuthInitialState());
}
String errorMessage = errorData['error']['message'] ?? 'something went wrong';
validate = errorMessage;
emit(AuthInitialState());
}
}

View File

@ -48,8 +48,7 @@ class ForgetPasswordWebPage extends StatelessWidget {
late ScrollController _scrollController;
_scrollController = ScrollController();
void _scrollToCenter() {
final double middlePosition =
_scrollController.position.maxScrollExtent / 2;
final double middlePosition = _scrollController.position.maxScrollExtent / 2;
_scrollController.animateTo(
middlePosition,
duration: const Duration(seconds: 1),
@ -66,8 +65,7 @@ class ForgetPasswordWebPage extends StatelessWidget {
second: Center(
child: Stack(
children: [
if (state is AuthLoading)
const Center(child: CircularProgressIndicator()),
if (state is AuthLoading) const Center(child: CircularProgressIndicator()),
ListView(
shrinkWrap: true,
controller: _scrollController,
@ -97,21 +95,16 @@ class ForgetPasswordWebPage extends StatelessWidget {
child: Container(
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.1),
borderRadius:
const BorderRadius.all(Radius.circular(30)),
border: Border.all(
color:
ColorsManager.graysColor.withOpacity(0.2)),
borderRadius: const BorderRadius.all(Radius.circular(30)),
border: Border.all(color: ColorsManager.graysColor.withOpacity(0.2)),
),
child: Form(
key: forgetBloc.forgetFormKey,
child: Padding(
padding: EdgeInsets.symmetric(
horizontal: size.width * 0.02,
vertical: size.width * 0.003),
horizontal: size.width * 0.02, vertical: size.width * 0.003),
child: Column(
mainAxisAlignment:
MainAxisAlignment.spaceEvenly,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
const SizedBox(height: 10),
@ -128,66 +121,55 @@ class ForgetPasswordWebPage extends StatelessWidget {
style: Theme.of(context)
.textTheme
.bodySmall!
.copyWith(
fontSize: 14,
fontWeight: FontWeight.w400),
.copyWith(fontSize: 14, fontWeight: FontWeight.w400),
),
const SizedBox(height: 10),
Column(
crossAxisAlignment:
CrossAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
const SizedBox(height: 10),
Form(
key: forgetBloc.forgetRegionKey,
child: SizedBox(
child: _buildDropdownField(
context, forgetBloc, size)))
Form(
key: forgetBloc.forgetRegionKey,
child: SizedBox(
child:
_buildDropdownField(context, forgetBloc, size)))
],
),
const SizedBox(height: 20),
Form(
key: forgetBloc.forgetEmailKey,
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
mainAxisAlignment:
MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
"Account",
style: Theme.of(context)
.textTheme
.bodySmall!
.copyWith(
fontSize: 14,
fontWeight:
FontWeight.w400),
style: Theme.of(context).textTheme.bodySmall!.copyWith(
fontSize: 14, fontWeight: FontWeight.w400),
),
const SizedBox(height: 10),
SizedBox(
child: TextFormField(
controller: forgetBloc.forgetEmailController,
validator: forgetBloc.validateEmail,
decoration:
textBoxDecoration()!.copyWith(
decoration: textBoxDecoration()!.copyWith(
hintText: 'Enter your email',
hintStyle: Theme.of(context)
.textTheme.bodySmall!.copyWith(
color: ColorsManager.grayColor,
fontWeight: FontWeight.w400),
.textTheme
.bodySmall!
.copyWith(
color: ColorsManager.grayColor,
fontWeight: FontWeight.w400),
),
style: const TextStyle(
color: Colors.black),
style: const TextStyle(color: Colors.black),
),
),
],
)),
const SizedBox(height: 20.0),
Column(
crossAxisAlignment:
CrossAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
@ -195,35 +177,40 @@ class ForgetPasswordWebPage extends StatelessWidget {
style: Theme.of(context)
.textTheme
.bodySmall!
.copyWith(
fontSize: 14,
fontWeight: FontWeight.w400),
.copyWith(fontSize: 14, fontWeight: FontWeight.w400),
),
const SizedBox(height: 10),
SizedBox(
child: TextFormField(
validator: forgetBloc.validateCode,
keyboardType:
TextInputType.visiblePassword,
keyboardType: TextInputType.visiblePassword,
controller: forgetBloc.forgetOtp,
decoration:
textBoxDecoration()!.copyWith(
decoration: textBoxDecoration()!.copyWith(
hintText: 'Enter Code',
hintStyle: Theme.of(context).textTheme
.bodySmall!.copyWith(
color: ColorsManager.grayColor,
fontWeight: FontWeight.w400),
hintStyle: Theme.of(context)
.textTheme
.bodySmall!
.copyWith(
color: ColorsManager.grayColor,
fontWeight: FontWeight.w400),
suffixIcon: SizedBox(
width: 100,
child: Center(
child: InkWell(
onTap: state is TimerState &&
!state.isButtonEnabled &&
state.remainingTime != 1
!state.isButtonEnabled &&
state.remainingTime != 1
? null
: () {
if (forgetBloc.forgetEmailKey.currentState!.validate()||forgetBloc.forgetRegionKey.currentState!.validate()) {
if(forgetBloc.forgetRegionKey.currentState!.validate()){
if (forgetBloc
.forgetEmailKey.currentState!
.validate() ||
forgetBloc
.forgetRegionKey.currentState!
.validate()) {
if (forgetBloc
.forgetRegionKey.currentState!
.validate()) {
forgetBloc.add(StartTimerEvent());
}
}
@ -231,28 +218,23 @@ class ForgetPasswordWebPage extends StatelessWidget {
child: Text(
'Get Code ${state is TimerState && !state.isButtonEnabled && state.remainingTime != 1 ? "(${forgetBloc.formattedTime(state.remainingTime)}) " : ""}',
style: TextStyle(
color: state
is TimerState &&
!state
.isButtonEnabled
color: state is TimerState &&
!state.isButtonEnabled
? Colors.grey
: ColorsManager
.btnColor,
: ColorsManager.btnColor,
),
),
),
),
),
),
style: const TextStyle(
color: Colors.black),
style: const TextStyle(color: Colors.black),
),
),
if (forgetBloc.forgetValidate !=
'') // Check if there is a validation message
Padding(
padding:
const EdgeInsets.only(top: 8.0),
padding: const EdgeInsets.only(top: 8.0),
child: Text(
forgetBloc.forgetValidate,
style: const TextStyle(
@ -265,8 +247,7 @@ class ForgetPasswordWebPage extends StatelessWidget {
),
const SizedBox(height: 20.0),
Column(
crossAxisAlignment:
CrossAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
@ -274,35 +255,26 @@ class ForgetPasswordWebPage extends StatelessWidget {
style: Theme.of(context)
.textTheme
.bodySmall!
.copyWith(
fontSize: 14,
fontWeight: FontWeight.w400),
.copyWith(fontSize: 14, fontWeight: FontWeight.w400),
),
const SizedBox(height: 10),
SizedBox(
child: TextFormField(
obscureText: forgetBloc.obscureText,
keyboardType:
TextInputType.visiblePassword,
validator:
forgetBloc.passwordValidator,
controller: forgetBloc
.forgetPasswordController,
decoration:
textBoxDecoration()!.copyWith(
keyboardType: TextInputType.visiblePassword,
validator: forgetBloc.passwordValidator,
controller: forgetBloc.forgetPasswordController,
decoration: textBoxDecoration()!.copyWith(
suffixIcon: IconButton(
onPressed: () {
forgetBloc.add(
PasswordVisibleEvent(
newValue: forgetBloc
.obscureText));
forgetBloc.add(PasswordVisibleEvent(
newValue: forgetBloc.obscureText));
},
icon: SizedBox(
child: SvgPicture.asset(
forgetBloc.obscureText
? Assets.visiblePassword
: Assets
.invisiblePassword,
: Assets.invisiblePassword,
height: 15,
width: 15,
),
@ -313,13 +285,10 @@ class ForgetPasswordWebPage extends StatelessWidget {
.textTheme
.bodySmall!
.copyWith(
color:
ColorsManager.grayColor,
fontWeight:
FontWeight.w400),
color: ColorsManager.grayColor,
fontWeight: FontWeight.w400),
),
style: const TextStyle(
color: Colors.black),
style: const TextStyle(color: Colors.black),
),
),
],
@ -329,21 +298,22 @@ class ForgetPasswordWebPage extends StatelessWidget {
),
const SizedBox(height: 20.0),
Row(
crossAxisAlignment:
CrossAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
width: size.width * 0.2,
child: DefaultButton(
backgroundColor:
ColorsManager.btnColor,
backgroundColor: ColorsManager.btnColor,
child: const Text('Submit'),
onPressed: () {
if (forgetBloc.forgetFormKey.currentState!.validate() ||
forgetBloc.forgetEmailKey.currentState!.validate() ) {
if( forgetBloc.forgetEmailKey.currentState!.validate()
&&forgetBloc.forgetFormKey.currentState!.validate() ){
forgetBloc.forgetEmailKey.currentState!
.validate()) {
if (forgetBloc.forgetEmailKey.currentState!
.validate() &&
forgetBloc.forgetFormKey.currentState!
.validate()) {
forgetBloc.add(ChangePasswordEvent());
}
}
@ -358,8 +328,7 @@ class ForgetPasswordWebPage extends StatelessWidget {
child: Text(
forgetBloc.validate,
style: const TextStyle(
fontWeight: FontWeight.w700,
color: ColorsManager.red),
fontWeight: FontWeight.w700, color: ColorsManager.red),
),
),
),
@ -372,8 +341,7 @@ class ForgetPasswordWebPage extends StatelessWidget {
children: [
const Text(
"Do you have an account? ",
style:
TextStyle(color: Colors.white),
style: TextStyle(color: Colors.white),
),
InkWell(
onTap: () {
@ -407,8 +375,7 @@ class ForgetPasswordWebPage extends StatelessWidget {
));
}
Widget _buildDropdownField(
BuildContext context, AuthBloc loginBloc, Size size) {
Widget _buildDropdownField(BuildContext context, AuthBloc loginBloc, Size size) {
final TextEditingController textEditingController = TextEditingController();
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
@ -434,13 +401,10 @@ class ForgetPasswordWebPage extends StatelessWidget {
builder: (FormFieldState<String> field) {
return InputDecorator(
decoration: InputDecoration(
contentPadding:
const EdgeInsets.symmetric(horizontal: 2, vertical: 10),
contentPadding: const EdgeInsets.symmetric(horizontal: 2, vertical: 10),
errorText: field.errorText,
filled:
true, // Ensure the dropdown is filled with the background color
fillColor: ColorsManager
.boxColor, // Match the dropdown container color
filled: true, // Ensure the dropdown is filled with the background color
fillColor: ColorsManager.boxColor, // Match the dropdown container color
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
borderSide: BorderSide(
@ -451,22 +415,20 @@ class ForgetPasswordWebPage extends StatelessWidget {
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
borderSide: BorderSide(
color:
field.hasError ? Colors.red : ColorsManager.grayColor,
color: field.hasError ? Colors.red : ColorsManager.grayColor,
width: 1.5,
),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
borderSide: BorderSide(
color:
field.hasError ? Colors.red : ColorsManager.grayColor,
color: field.hasError ? Colors.red : ColorsManager.grayColor,
width: 1.5,
),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8.0),
borderSide: BorderSide(
borderSide: const BorderSide(
color: Colors.red,
width: 1.5,
),
@ -488,24 +450,22 @@ class ForgetPasswordWebPage extends StatelessWidget {
value: region.id,
child: Text(
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
fontSize: 14,
fontWeight: FontWeight.w400,
),
fontSize: 14,
fontWeight: FontWeight.w400,
),
region.name,
overflow: TextOverflow.ellipsis,
maxLines: 1,
),
);
}).toList(),
value: loginBloc.regionList!
.any((region) => region.id == loginBloc.regionUuid)
value: loginBloc.regionList!.any((region) => region.id == loginBloc.regionUuid)
? loginBloc.regionUuid
: null,
onChanged: (String? value) {
if (value != null) {
loginBloc.add(SelectRegionEvent(val: value));
field.didChange(
value); // Notify the form field of the change
field.didChange(value); // Notify the form field of the change
}
},
buttonStyleData: const ButtonStyleData(
@ -529,8 +489,7 @@ class ForgetPasswordWebPage extends StatelessWidget {
searchInnerWidgetHeight: 50,
searchInnerWidget: Container(
height: 50,
padding: const EdgeInsets.symmetric(
horizontal: 8, vertical: 4),
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
child: TextFormField(
style: const TextStyle(color: Colors.black),
controller: textEditingController,
@ -544,8 +503,7 @@ class ForgetPasswordWebPage extends StatelessWidget {
),
),
searchMatchFn: (item, searchValue) {
final regionName =
(item.child as Text).data?.toLowerCase() ?? '';
final regionName = (item.child as Text).data?.toLowerCase() ?? '';
final search = searchValue.toLowerCase().trim();
return regionName.contains(search);
},
@ -564,6 +522,4 @@ class ForgetPasswordWebPage extends StatelessWidget {
],
);
}
}

View File

@ -24,8 +24,7 @@ class LoginWebPage extends StatefulWidget {
State<LoginWebPage> createState() => _LoginWebPageState();
}
class _LoginWebPageState extends State<LoginWebPage>
with HelperResponsiveLayout {
class _LoginWebPageState extends State<LoginWebPage> with HelperResponsiveLayout {
@override
Widget build(BuildContext context) {
return Scaffold(
@ -60,8 +59,7 @@ class _LoginWebPageState extends State<LoginWebPage>
_scrollController = ScrollController();
void _scrollToCenter() {
final double middlePosition =
_scrollController.position.maxScrollExtent / 2;
final double middlePosition = _scrollController.position.maxScrollExtent / 2;
_scrollController.animateTo(
middlePosition,
duration: const Duration(seconds: 1),
@ -123,8 +121,7 @@ class _LoginWebPageState extends State<LoginWebPage>
const Spacer(),
Expanded(
flex: 2,
child: _buildLoginFormFields(
context, loginBloc, size),
child: _buildLoginFormFields(context, loginBloc, size),
),
const Spacer(),
],
@ -135,14 +132,12 @@ class _LoginWebPageState extends State<LoginWebPage>
),
),
),
if (state is AuthLoading)
const Center(child: CircularProgressIndicator())
if (state is AuthLoading) const Center(child: CircularProgressIndicator())
],
);
}
Widget _buildLoginFormFields(
BuildContext context, AuthBloc loginBloc, Size size) {
Widget _buildLoginFormFields(BuildContext context, AuthBloc loginBloc, Size size) {
return Container(
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.1),
@ -152,8 +147,8 @@ class _LoginWebPageState extends State<LoginWebPage>
child: Form(
key: loginBloc.loginFormKey,
child: Padding(
padding: EdgeInsets.symmetric(
horizontal: size.width * 0.02, vertical: size.width * 0.003),
padding:
EdgeInsets.symmetric(horizontal: size.width * 0.02, vertical: size.width * 0.003),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
@ -181,9 +176,7 @@ class _LoginWebPageState extends State<LoginWebPage>
);
}
Widget _buildDropdownField(
BuildContext context, AuthBloc loginBloc, Size size) {
Widget _buildDropdownField(BuildContext context, AuthBloc loginBloc, Size size) {
final TextEditingController textEditingController = TextEditingController();
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
@ -192,9 +185,9 @@ class _LoginWebPageState extends State<LoginWebPage>
Text(
"Country/Region",
style: Theme.of(context).textTheme.bodySmall!.copyWith(
fontSize: 14,
fontWeight: FontWeight.w400,
),
fontSize: 14,
fontWeight: FontWeight.w400,
),
),
const SizedBox(height: 10),
Container(
@ -211,9 +204,9 @@ class _LoginWebPageState extends State<LoginWebPage>
hint: Text(
'Select your region/country',
style: Theme.of(context).textTheme.bodySmall!.copyWith(
color: ColorsManager.grayColor,
fontWeight: FontWeight.w400,
),
color: ColorsManager.grayColor,
fontWeight: FontWeight.w400,
),
overflow: TextOverflow.ellipsis,
),
items: loginBloc.regionList!.map((RegionModel region) {
@ -227,7 +220,8 @@ class _LoginWebPageState extends State<LoginWebPage>
);
}).toList(),
value: loginBloc.regionList!.any(
(region) => region.id == loginBloc.regionUuid,)
(region) => region.id == loginBloc.regionUuid,
)
? loginBloc.regionUuid
: null,
onChanged: (String? value) {
@ -286,7 +280,6 @@ class _LoginWebPageState extends State<LoginWebPage>
);
}
Widget _buildEmailField(BuildContext context, AuthBloc loginBloc) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
@ -310,9 +303,10 @@ class _LoginWebPageState extends State<LoginWebPage>
decoration: textBoxDecoration()!.copyWith(
errorStyle: const TextStyle(height: 0),
hintText: 'Enter your email address',
hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith(
color: ColorsManager.grayColor,
fontWeight: FontWeight.w400)),
hintStyle: Theme.of(context)
.textTheme
.bodySmall!
.copyWith(color: ColorsManager.grayColor, fontWeight: FontWeight.w400)),
style: const TextStyle(color: Colors.black),
),
),
@ -344,18 +338,17 @@ class _LoginWebPageState extends State<LoginWebPage>
controller: loginBloc.loginPasswordController,
decoration: textBoxDecoration()!.copyWith(
hintText: 'At least 8 characters',
hintStyle: Theme.of(context).textTheme.bodySmall!.copyWith(
color: ColorsManager.grayColor, fontWeight: FontWeight.w400),
hintStyle: Theme.of(context)
.textTheme
.bodySmall!
.copyWith(color: ColorsManager.grayColor, fontWeight: FontWeight.w400),
suffixIcon: IconButton(
onPressed: () {
loginBloc.add(
PasswordVisibleEvent(newValue: loginBloc.obscureText));
loginBloc.add(PasswordVisibleEvent(newValue: loginBloc.obscureText));
},
icon: SizedBox(
child: SvgPicture.asset(
loginBloc.obscureText
? Assets.visiblePassword
: Assets.invisiblePassword,
loginBloc.obscureText ? Assets.visiblePassword : Assets.invisiblePassword,
height: 15,
width: 15,
),
@ -383,10 +376,10 @@ class _LoginWebPageState extends State<LoginWebPage>
},
child: Text(
"Forgot Password?",
style: Theme.of(context).textTheme.bodySmall!.copyWith(
color: Colors.black,
fontSize: 14,
fontWeight: FontWeight.w400),
style: Theme.of(context)
.textTheme
.bodySmall!
.copyWith(color: Colors.black, fontSize: 14, fontWeight: FontWeight.w400),
),
),
],
@ -450,8 +443,7 @@ class _LoginWebPageState extends State<LoginWebPage>
);
}
Widget _buildSignInButton(
BuildContext context, AuthBloc loginBloc, Size size) {
Widget _buildSignInButton(BuildContext context, AuthBloc loginBloc, Size size) {
return Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
@ -492,8 +484,7 @@ class _LoginWebPageState extends State<LoginWebPage>
SizedBox(
child: Text(
loginBloc.validate,
style: const TextStyle(
fontWeight: FontWeight.w700, color: ColorsManager.red),
style: const TextStyle(fontWeight: FontWeight.w700, color: ColorsManager.red),
),
)
],

View File

@ -0,0 +1,304 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/constants/assets.dart';
class AccessDeviceTable extends StatefulWidget {
final List<String> headers;
final String? tableName;
final List<List<dynamic>> data;
final BoxDecoration? headerDecoration;
final BoxDecoration? cellDecoration;
final Size size;
final bool withCheckBox;
final bool withSelectAll;
final bool isEmpty;
final void Function(bool?)? selectAll;
final void Function(int, bool, dynamic)? onRowSelected;
final List<String>? initialSelectedIds;
final int uuidIndex;
const AccessDeviceTable({
super.key,
required this.headers,
required this.data,
required this.size,
this.tableName,
required this.isEmpty,
required this.withCheckBox,
required this.withSelectAll,
this.headerDecoration,
this.cellDecoration,
this.selectAll,
this.onRowSelected,
this.initialSelectedIds,
required this.uuidIndex,
});
@override
_DynamicTableState createState() => _DynamicTableState();
}
class _DynamicTableState extends State<AccessDeviceTable> {
late List<bool> _selected;
bool _selectAll = false;
@override
void initState() {
super.initState();
_initializeSelection();
}
@override
void didUpdateWidget(AccessDeviceTable oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.data != widget.data) {
_initializeSelection();
}
}
void _initializeSelection() {
if (widget.data.isEmpty) {
_selected = [];
_selectAll = false;
} else {
_selected = List<bool>.generate(widget.data.length, (index) {
// Check if the initialSelectedIds contains the deviceUuid
// uuidIndex is the index of the column containing the deviceUuid
final deviceUuid = widget.data[index][widget.uuidIndex];
return widget.initialSelectedIds != null &&
widget.initialSelectedIds!.contains(deviceUuid);
});
_selectAll = _selected.every((element) => element == true);
}
}
void _toggleRowSelection(int index) {
setState(() {
_selected[index] = !_selected[index];
if (widget.onRowSelected != null) {
widget.onRowSelected!(index, _selected[index], widget.data[index]);
}
});
}
void _toggleSelectAll(bool? value) {
setState(() {
_selectAll = value ?? false;
_selected = List<bool>.filled(widget.data.length, _selectAll);
if (widget.selectAll != null) {
widget.selectAll!(_selectAll);
}
});
}
@override
Widget build(BuildContext context) {
return Container(
decoration: widget.cellDecoration,
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: SizedBox(
width: widget.size.width,
child: Column(
children: [
Container(
decoration: widget.headerDecoration ??
BoxDecoration(color: Colors.grey[200]),
child: Row(
children: [
if (widget.withCheckBox) _buildSelectAllCheckbox(),
...widget.headers
.map((header) => _buildTableHeaderCell(header)),
],
),
),
widget.isEmpty
? Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Column(
children: [
SvgPicture.asset(Assets.emptyTable),
const SizedBox(
height: 15,
),
Text(
// no password
widget.tableName == 'AccessManagement'
? 'No Password '
: 'No Devices',
style: Theme.of(context)
.textTheme
.bodySmall!
.copyWith(
color: ColorsManager.grayColor),
)
],
),
],
),
],
),
)
: Expanded(
child: Container(
color: Colors.white,
child: ListView.builder(
shrinkWrap: true,
itemCount: widget.data.length,
itemBuilder: (context, index) {
final row = widget.data[index];
return Row(
children: [
if (widget.withCheckBox)
_buildRowCheckbox(
index, widget.size.height * 0.10),
...row.map((cell) => _buildTableCell(
cell.toString(),
widget.size.height * 0.10)),
],
);
},
),
),
),
],
),
),
),
);
}
Widget _buildSelectAllCheckbox() {
return Container(
width: 50,
padding: const EdgeInsets.all(8.0),
decoration: const BoxDecoration(
border: Border.symmetric(
vertical: BorderSide(color: ColorsManager.boxDivider),
),
),
child: Checkbox(
value: widget.data.isNotEmpty &&
_selected.every((element) => element == true),
onChanged: widget.withSelectAll && widget.data.isNotEmpty
? _toggleSelectAll
: null,
),
);
}
Widget _buildRowCheckbox(int index, double size) {
return Container(
width: 50,
padding: const EdgeInsets.all(8.0),
height: size,
decoration: const BoxDecoration(
border: Border(
bottom: BorderSide(
color: ColorsManager.boxDivider,
width: 1.0,
),
),
),
alignment: Alignment.centerLeft,
child: Center(
child: Checkbox(
value: _selected[index],
onChanged: (bool? value) {
_toggleRowSelection(index);
},
),
),
);
}
Widget _buildTableHeaderCell(String title) {
return Expanded(
child: Container(
decoration: const BoxDecoration(
border: Border.symmetric(
vertical: BorderSide(color: ColorsManager.boxDivider),
),
),
alignment: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
title,
style: const TextStyle(
fontWeight: FontWeight.w400,
fontSize: 13,
color: Color(0xFF999999),
),
maxLines: 2,
),
),
),
);
}
Widget _buildTableCell(String content, double size) {
bool isBatteryLevel = content.endsWith('%');
double? batteryLevel;
if (isBatteryLevel) {
batteryLevel = double.tryParse(content.replaceAll('%', '').trim());
}
Color? statusColor;
switch (content) {
case 'Effective':
statusColor = ColorsManager.textGreen;
break;
case 'Expired':
statusColor = ColorsManager.red;
break;
case 'To be effective':
statusColor = ColorsManager.yaGreen;
break;
case 'Online':
statusColor = ColorsManager.green;
break;
case 'Offline':
statusColor = ColorsManager.red;
break;
default:
statusColor = Colors.black;
}
return Expanded(
child: Container(
height: size,
padding: const EdgeInsets.all(5.0),
decoration: const BoxDecoration(
border: Border(
bottom: BorderSide(
color: ColorsManager.boxDivider,
width: 1.0,
),
),
),
alignment: Alignment.centerLeft,
child: Text(
content,
style: TextStyle(
color: (batteryLevel != null && batteryLevel < 20)
? ColorsManager.red
: (batteryLevel != null && batteryLevel > 20)
? ColorsManager.green
: statusColor,
fontSize: 10,
fontWeight: FontWeight.w400),
maxLines: 2,
),
),
);
}
}

View File

@ -26,9 +26,12 @@ class CurtainToggle extends StatelessWidget {
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const SizedBox(
height: 10,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ClipOval(
child: Container(
@ -41,6 +44,9 @@ class CurtainToggle extends StatelessWidget {
),
),
),
const SizedBox(
width: 20,
),
SizedBox(
height: 20,
width: 35,

View File

@ -4,6 +4,7 @@ import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/bloc/device_managment_bloc.dart';
import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/constants/assets.dart';
import 'package:syncrow_web/utils/extension/build_context_x.dart';
class DynamicTable extends StatefulWidget {
final List<String> headers;
@ -45,6 +46,8 @@ class DynamicTable extends StatefulWidget {
class _DynamicTableState extends State<DynamicTable> {
late List<bool> _selectedRows;
bool _selectAll = false;
final ScrollController _verticalScrollController = ScrollController();
final ScrollController _horizontalScrollController = ScrollController();
@override
void initState() {
@ -102,68 +105,78 @@ class _DynamicTableState extends State<DynamicTable> {
Widget build(BuildContext context) {
return Container(
decoration: widget.cellDecoration,
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: SizedBox(
width: widget.size.width,
child: Column(
children: [
Container(
decoration: widget.headerDecoration ?? BoxDecoration(color: Colors.grey[200]),
child: Row(
child: Scrollbar(
controller: _verticalScrollController,
thumbVisibility: true,
trackVisibility: true,
child: Scrollbar(
controller: _horizontalScrollController,
thumbVisibility: false,
trackVisibility: false,
notificationPredicate: (notif) => notif.depth == 1,
child: SingleChildScrollView(
controller: _verticalScrollController,
child: SingleChildScrollView(
controller: _horizontalScrollController,
scrollDirection: Axis.horizontal,
child: SizedBox(
width: widget.size.width,
child: Column(
children: [
if (widget.withCheckBox) _buildSelectAllCheckbox(),
...widget.headers.map((header) => _buildTableHeaderCell(header)),
],
),
),
widget.isEmpty
? Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
Container(
decoration: widget.headerDecoration ??
const BoxDecoration(
color: ColorsManager.boxColor,
),
child: Row(
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.center,
if (widget.withCheckBox) _buildSelectAllCheckbox(),
...widget.headers.map((header) => _buildTableHeaderCell(header)),
],
),
),
widget.isEmpty
? Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Column(
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
SvgPicture.asset(Assets.emptyTable),
const SizedBox(
height: 15,
Column(
children: [
SvgPicture.asset(Assets.emptyTable),
const SizedBox(
height: 15,
),
Text(
widget.tableName == 'AccessManagement' ? 'No Password ' : 'No Devices',
style: Theme.of(context)
.textTheme
.bodySmall!
.copyWith(color: ColorsManager.grayColor),
)
],
),
Text(
// no password
widget.tableName == 'AccessManagement' ? 'No Password ' : 'No Devices',
style:
Theme.of(context).textTheme.bodySmall!.copyWith(color: ColorsManager.grayColor),
)
],
),
],
)
: Column(
children: List.generate(widget.data.length, (index) {
final row = widget.data[index];
return Row(
children: [
if (widget.withCheckBox) _buildRowCheckbox(index, widget.size.height * 0.08),
...row.map((cell) => _buildTableCell(cell.toString(), widget.size.height * 0.08)),
],
);
}),
),
],
),
)
: Expanded(
child: Container(
color: Colors.white,
child: ListView.builder(
shrinkWrap: true,
itemCount: widget.data.length,
itemBuilder: (context, index) {
final row = widget.data[index];
return Row(
children: [
if (widget.withCheckBox) _buildRowCheckbox(index, widget.size.height * 0.10),
...row.map((cell) => _buildTableCell(cell.toString(), widget.size.height * 0.10)),
],
);
},
),
),
),
],
],
),
),
),
),
),
),
@ -173,7 +186,6 @@ class _DynamicTableState extends State<DynamicTable> {
Widget _buildSelectAllCheckbox() {
return Container(
width: 50,
padding: const EdgeInsets.all(8.0),
decoration: const BoxDecoration(
border: Border.symmetric(
vertical: BorderSide(color: ColorsManager.boxDivider),
@ -198,6 +210,7 @@ class _DynamicTableState extends State<DynamicTable> {
width: 1.0,
),
),
color: ColorsManager.whiteColors,
),
alignment: Alignment.centerLeft,
child: Center(
@ -219,15 +232,16 @@ class _DynamicTableState extends State<DynamicTable> {
vertical: BorderSide(color: ColorsManager.boxDivider),
),
),
constraints: const BoxConstraints.expand(height: 40),
alignment: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.all(8.0),
padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4),
child: Text(
title,
style: const TextStyle(
style: context.textTheme.titleSmall!.copyWith(
color: ColorsManager.grayColor,
fontSize: 12,
fontWeight: FontWeight.w400,
fontSize: 13,
color: Color(0xFF999999),
),
maxLines: 2,
),
@ -276,6 +290,7 @@ class _DynamicTableState extends State<DynamicTable> {
width: 1.0,
),
),
color: Colors.white,
),
alignment: Alignment.centerLeft,
child: Text(
@ -286,7 +301,7 @@ class _DynamicTableState extends State<DynamicTable> {
: (batteryLevel != null && batteryLevel > 20)
? ColorsManager.green
: statusColor,
fontSize: 10,
fontSize: 13,
fontWeight: FontWeight.w400),
maxLines: 2,
),

View File

@ -13,6 +13,7 @@ class CustomWebTextField extends StatelessWidget {
this.validator,
this.hintText,
this.height,
this.onSubmitted,
});
final bool isRequired;
@ -22,6 +23,7 @@ class CustomWebTextField extends StatelessWidget {
final String? Function(String?)? validator;
final String? hintText;
final double? height;
final ValueChanged<String>? onSubmitted;
@override
Widget build(BuildContext context) {
@ -32,33 +34,29 @@ class CustomWebTextField extends StatelessWidget {
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
if (isRequired)
Text('* ',
style: Theme.of(context)
.textTheme.bodyMedium!
.copyWith(color: Colors.red),
),
Row(
children: [
if (isRequired)
Text(
textFieldName,
style: Theme.of(context)
.textTheme.bodySmall!
.copyWith(color: Colors.black, fontSize: 13),
'* ',
style: Theme.of(context).textTheme.bodyMedium!.copyWith(color: Colors.red),
),
],
),
Text(
textFieldName,
style: Theme.of(context).textTheme.bodySmall!.copyWith(color: Colors.black, fontSize: 13),
),
],
),
const SizedBox(
width: 10,
),
Expanded(
child: Text(
description ?? '',
style: Theme.of(context).textTheme.bodySmall!.copyWith(
fontSize: 9,
fontWeight: FontWeight.w400,
color: ColorsManager.textGray),
style: Theme.of(context)
.textTheme
.bodySmall!
.copyWith(fontSize: 9, fontWeight: FontWeight.w400, color: ColorsManager.textGray),
),
),
],
@ -68,26 +66,23 @@ class CustomWebTextField extends StatelessWidget {
),
Container(
height: height ?? 35,
decoration: containerDecoration.copyWith(
color: const Color(0xFFF5F6F7),
boxShadow: [
decoration: containerDecoration.copyWith(color: const Color(0xFFF5F6F7), boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.3),
spreadRadius: 2,
blurRadius: 3,
offset: const Offset(1, 1), // changes position of shadow
),
]
),
]),
child: TextFormField(
validator: validator,
controller: controller,
style: const TextStyle(color: Colors.black),
decoration: textBoxDecoration()!.copyWith(
errorStyle: const TextStyle(height: 0),
hintStyle: context.textTheme.titleSmall!
.copyWith(color: Colors.grey, fontSize: 12),
hintStyle: context.textTheme.titleSmall!.copyWith(color: Colors.grey, fontSize: 12),
hintText: hintText ?? 'Please enter'),
onFieldSubmitted: onSubmitted,
),
),
],

View File

@ -40,7 +40,7 @@ class AcDeviceControlsView extends StatelessWidget with HelperResponsiveLayout {
: 1,
mainAxisExtent: 140,
crossAxisSpacing: 12,
mainAxisSpacing: 12,
mainAxisSpacing: 16,
),
children: [
ToggleWidget(
@ -81,6 +81,7 @@ class AcDeviceControlsView extends StatelessWidget with HelperResponsiveLayout {
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
IconButton(
padding: const EdgeInsets.all(0),
onPressed: () {},
icon: const Icon(
Icons.remove,
@ -108,6 +109,7 @@ class AcDeviceControlsView extends StatelessWidget with HelperResponsiveLayout {
),
Text('m', style: context.textTheme.bodySmall!.copyWith(color: ColorsManager.blackColor)),
IconButton(
padding: const EdgeInsets.all(0),
onPressed: () {},
icon: const Icon(
Icons.add,
@ -127,7 +129,7 @@ class AcDeviceControlsView extends StatelessWidget with HelperResponsiveLayout {
deviceId: device.uuid!,
code: 'child_lock',
value: state.status.childLock,
label: 'Child Lock',
label: 'Lock',
icon: state.status.childLock ? Assets.acLock : Assets.unlock,
onChange: (value) {
context.read<AcBloc>().add(

View File

@ -14,10 +14,9 @@ class DeviceManagementBloc extends Bloc<DeviceManagementEvent, DeviceManagementS
int _lowBatteryCount = 0;
List<AllDevicesModel> _selectedDevices = [];
List<AllDevicesModel> _filteredDevices = [];
String productName = '';
String currentProductName = '';
String? currentCommunity;
String? currentUnitName;
String? currentProductName;
DeviceManagementBloc() : super(DeviceManagementInitial()) {
on<FetchDevices>(_onFetchDevices);
@ -77,14 +76,14 @@ class DeviceManagementBloc extends Bloc<DeviceManagementEvent, DeviceManagementS
isControlButtonEnabled: _selectedDevices.isNotEmpty,
));
if (productName.isNotEmpty) {
add(SearchDevices(productName: productName));
if (currentProductName.isNotEmpty) {
add(SearchDevices(productName: currentProductName));
}
}
}
Future<void> _onResetFilters(ResetFilters event, Emitter<DeviceManagementState> emit) async {
productName = '';
currentProductName = '';
_selectedDevices.clear();
_filteredDevices = List.from(_devices);
_selectedIndex = 0;
@ -238,20 +237,10 @@ class DeviceManagementBloc extends Bloc<DeviceManagementEvent, DeviceManagementS
}
void _onSearchDevices(SearchDevices event, Emitter<DeviceManagementState> emit) {
if (event.productName == currentProductName &&
event.community == currentCommunity &&
event.unitName == currentUnitName) {
return;
}
currentProductName = event.productName;
currentCommunity = event.community;
currentUnitName = event.unitName;
if ((event.community == null || event.community!.isEmpty) &&
(event.unitName == null || event.unitName!.isEmpty) &&
(event.productName == null || event.productName!.isEmpty)) {
productName = '';
currentProductName = '';
if (state is DeviceManagementFiltered) {
add(FilterDevices(_getFilterFromIndex(_selectedIndex)));
} else {
@ -259,7 +248,17 @@ class DeviceManagementBloc extends Bloc<DeviceManagementEvent, DeviceManagementS
}
}
productName = event.productName ?? '';
if (event.productName == currentProductName &&
event.community == currentCommunity &&
event.unitName == currentUnitName &&
event.searchField) {
return;
}
currentProductName = event.productName ?? '';
currentCommunity = event.community;
currentUnitName = event.unitName;
List<AllDevicesModel> devicesToSearch = _filteredDevices;
if (devicesToSearch.isNotEmpty) {

View File

@ -31,11 +31,13 @@ class SearchDevices extends DeviceManagementEvent {
final String? community;
final String? unitName;
final String? productName;
final bool searchField;
const SearchDevices({
this.community,
this.unitName,
this.productName,
this.searchField = false,
});
@override

View File

@ -8,7 +8,6 @@ import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_mo
import 'package:syncrow_web/pages/device_managment/all_devices/widgets/device_search_filters.dart';
import 'package:syncrow_web/pages/device_managment/shared/device_batch_control_dialog.dart';
import 'package:syncrow_web/pages/device_managment/shared/device_control_dialog.dart';
import 'package:syncrow_web/utils/extension/build_context_x.dart';
import 'package:syncrow_web/utils/format_date_time.dart';
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
import 'package:syncrow_web/utils/style.dart';
@ -132,7 +131,7 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
context.read<DeviceManagementBloc>().add(SelectDevice(selectedDevice));
},
withCheckBox: true,
size: context.screenSize,
size: MediaQuery.of(context).size,
uuidIndex: 2,
headers: const [
'Device Name',

View File

@ -67,9 +67,10 @@ class _DeviceSearchFiltersState extends State<DeviceSearchFilters> with HelperRe
controller: controller,
onSubmitted: () {
context.read<DeviceManagementBloc>().add(SearchDevices(
productName: productNameController.text,
unitName: unitNameController.text,
));
productName: productNameController.text,
unitName: unitNameController.text,
community: communityController.text,
searchField: true));
},
);
}
@ -78,10 +79,10 @@ class _DeviceSearchFiltersState extends State<DeviceSearchFilters> with HelperRe
return SearchResetButtons(
onSearch: () {
context.read<DeviceManagementBloc>().add(SearchDevices(
community: communityController.text,
unitName: unitNameController.text,
productName: productNameController.text,
));
community: communityController.text,
unitName: unitNameController.text,
productName: productNameController.text,
searchField: true));
},
onReset: () {
communityController.clear();

View File

@ -5,6 +5,7 @@ import 'package:syncrow_web/pages/device_managment/gateway/bloc/gate_way_bloc.da
import 'package:syncrow_web/pages/device_managment/shared/device_controls_container.dart';
import 'package:syncrow_web/pages/visitor_password/model/device_model.dart';
import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/extension/build_context_x.dart';
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
class GateWayControlsView extends StatelessWidget with HelperResponsiveLayout {
@ -25,25 +26,61 @@ class GateWayControlsView extends StatelessWidget with HelperResponsiveLayout {
if (state is GatewayLoadingState) {
return const Center(child: CircularProgressIndicator());
} else if (state is UpdateGatewayState) {
return GridView.builder(
padding: const EdgeInsets.symmetric(horizontal: 50),
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: isLarge || isExtraLarge
? 3
: isMedium
? 2
: 1,
mainAxisExtent: 140,
crossAxisSpacing: 12,
mainAxisSpacing: 12,
),
itemCount: state.list.length,
itemBuilder: (context, index) {
final device = state.list[index];
return _DeviceItem(device: device);
},
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: const EdgeInsets.symmetric(horizontal: 50),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(
"Bluetooth Devices:",
style: context.textTheme.bodyMedium!.copyWith(
color: ColorsManager.grayColor,
),
),
const SizedBox(height: 12),
Text(
"No devices found",
style: context.textTheme.bodySmall!.copyWith(
color: ColorsManager.blackColor,
),
),
const SizedBox(height: 30),
Text(
"ZigBee Devices:",
style: context.textTheme.bodyMedium!.copyWith(
color: ColorsManager.grayColor,
),
),
],
),
),
const SizedBox(height: 12),
GridView.builder(
padding: const EdgeInsets.symmetric(horizontal: 50),
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: isLarge || isExtraLarge
? 3
: isMedium
? 2
: 1,
mainAxisExtent: 140,
crossAxisSpacing: 12,
mainAxisSpacing: 12,
),
itemCount: state.list.length,
itemBuilder: (context, index) {
final device = state.list[index];
return _DeviceItem(device: device);
},
),
],
);
} else {
return const Center(child: Text('Error fetching status'));

View File

@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/helper/route_controls_based_code.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
import 'package:syncrow_web/pages/device_managment/shared/device_batch_control_dialog.dart';
import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/format_date_time.dart';
@ -31,7 +32,7 @@ class DeviceControlDialog extends StatelessWidget with RouteControlsBasedCode {
children: [
const SizedBox(),
Text(
device.productName ?? 'Device Control',
getBatchDialogName(device),
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 22,
@ -64,7 +65,7 @@ class DeviceControlDialog extends StatelessWidget with RouteControlsBasedCode {
),
const SizedBox(height: 20),
_buildDeviceInfoSection(),
const SizedBox(height: 20),
//const SizedBox(height: 20),
//// BUILD DEVICE CONTROLS
///
//// ROUTE TO SPECIFIC CONTROL VIEW BASED ON DEVICE CATEGORY

View File

@ -1,5 +1,4 @@
import 'package:flutter/material.dart';
import 'package:syncrow_web/utils/color_manager.dart';
class DeviceControlsContainer extends StatelessWidget {
const DeviceControlsContainer({required this.child, this.padding, super.key});
@ -8,21 +7,21 @@ class DeviceControlsContainer extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
color: ColorsManager.greyColor.withOpacity(0.2),
// boxShadow: <BoxShadow>[
// BoxShadow(
// color: ColorsManager.blackColor.withOpacity(0.05),
// blurRadius: 6.0,
// offset: const Offset(0, 5),
// spreadRadius: 0)
// ],
),
padding: EdgeInsets.all(padding ?? 12),
child: child,
elevation: 3,
surfaceTintColor: Colors.transparent,
child: Container(
decoration: BoxDecoration(
color: Colors.grey.shade100,
borderRadius: BorderRadius.circular(20),
),
padding:
EdgeInsets.symmetric(vertical: padding ?? 10, horizontal: padding ?? 16), //EdgeInsets.all(padding ?? 12),
child: child,
),
);
}
}

View File

@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_web/pages/common/custom_table.dart';
import 'package:syncrow_web/pages/common/access_device_table.dart';
import 'package:syncrow_web/pages/common/text_field/custom_web_textfield.dart';
import 'package:syncrow_web/pages/common/buttons/default_button.dart';
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_bloc.dart';
@ -49,7 +49,7 @@ class AddDeviceDialog extends StatelessWidget {
children: <Widget>[
Container(
width: size.width,
padding: EdgeInsets.all(15),
padding: const EdgeInsets.all(15),
decoration: containerDecoration.copyWith(
color: ColorsManager.worningColor,
border: Border.all(color: Color(0xffFFD22F)),
@ -163,7 +163,7 @@ class AddDeviceDialog extends StatelessWidget {
Expanded(
flex: 3,
child: state is TableLoaded
? DynamicTable(
? AccessDeviceTable(
uuidIndex: 1,
withSelectAll: true,
initialSelectedIds: selectedDeviceIds,

View File

@ -168,4 +168,16 @@ class Assets {
//assets/icons/2gang.svg
static const String twoGang = 'assets/icons/2gang.svg';
//assets/icons/account_setting.svg
static const String accountSetting = 'assets/icons/account_setting.svg';
//assets/icons/settings.svg
static const String settings = 'assets/icons/settings.svg';
//assets/icons/sign_out.svg
static const String signOut = 'assets/icons/sign_out.svg';
//assets/icons/logo_grey.svg
static const String logoGrey = 'assets/icons/logo-grey.svg';
}

View File

@ -3,6 +3,7 @@ import 'package:syncrow_web/utils/color_manager.dart';
final myTheme = ThemeData(
fontFamily: 'Aftika',
useMaterial3: true,
textTheme: const TextTheme(
bodySmall: TextStyle(
fontSize: 13,

View File

@ -0,0 +1,239 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:go_router/go_router.dart';
import 'package:syncrow_web/pages/auth/bloc/auth_bloc.dart';
import 'package:syncrow_web/pages/auth/model/user_model.dart';
import 'package:syncrow_web/pages/common/buttons/default_button.dart';
import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/constants/assets.dart';
import 'package:syncrow_web/utils/constants/routes_const.dart';
import 'package:syncrow_web/utils/extension/build_context_x.dart';
class UserDropdownMenu extends StatefulWidget {
const UserDropdownMenu({super.key, required this.user});
final UserModel? user;
@override
_UserDropdownMenuState createState() => _UserDropdownMenuState();
}
class _UserDropdownMenuState extends State<UserDropdownMenu> {
bool _isDropdownOpen = false;
void _toggleDropdown() {
setState(() {
_isDropdownOpen = !_isDropdownOpen;
});
}
@override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
GestureDetector(
onTap: () async {
_toggleDropdown();
await _showPopupMenu(context);
setState(() {
_isDropdownOpen = false;
});
},
child: Transform.rotate(
angle: _isDropdownOpen ? -1.5708 : 1.5708,
child: const Icon(
Icons.arrow_forward_ios,
color: Colors.white,
size: 16,
),
),
),
],
);
}
Future<void> _showPopupMenu(BuildContext context) async {
final RenderBox overlay = Overlay.of(context).context.findRenderObject() as RenderBox;
final RelativeRect position = RelativeRect.fromRect(
Rect.fromLTRB(
overlay.size.width,
75,
0,
overlay.size.height,
),
Offset.zero & overlay.size,
);
await showMenu(
context: context,
position: position,
color: ColorsManager.whiteColors,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
bottomRight: Radius.circular(10),
bottomLeft: Radius.circular(10),
),
),
items: <PopupMenuEntry>[
PopupMenuItem(
onTap: () {},
child: ListTile(
leading: SvgPicture.asset(Assets.accountSetting),
title: Text(
"Account Settings",
style: context.textTheme.bodyMedium,
),
),
),
PopupMenuItem(
onTap: () {},
child: ListTile(
leading: SvgPicture.asset(Assets.settings),
title: Text(
"Settings",
style: context.textTheme.bodyMedium,
),
),
),
PopupMenuItem(
onTap: () {
showDialog(
context: context,
builder: (BuildContext context) {
final size = MediaQuery.of(context).size;
return AlertDialog(
alignment: Alignment.center,
content: SizedBox(
height: 200,
width: 400,
child: Padding(
padding: const EdgeInsets.only(top: 24, left: 24, right: 24),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Image.asset(
Assets.blackLogo,
height: 40,
width: 200,
),
Padding(
padding: const EdgeInsets.only(top: 16),
child: Text(
'Log out of your Syncrow account',
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
fontSize: 14,
fontWeight: FontWeight.w400,
color: Colors.black,
),
),
),
const SizedBox(
height: 16,
),
Row(
children: [
SizedBox.square(
dimension: 80,
child: CircleAvatar(
backgroundColor: ColorsManager.whiteColors,
child: SizedBox.square(
dimension: 78,
child: SvgPicture.asset(
Assets.logoGrey,
fit: BoxFit.fitHeight,
height: 80,
),
),
),
),
const SizedBox(
width: 16,
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'${widget.user?.firstName ?? ''} ${widget.user?.lastName}',
style: Theme.of(context).textTheme.titleMedium!.copyWith(
color: Colors.black,
fontWeight: FontWeight.bold,
fontSize: 20,
),
),
Text(
' ${widget.user?.email}',
style: Theme.of(context).textTheme.bodySmall!.copyWith(
color: Colors.black,
),
),
],
),
),
],
),
],
),
),
),
actionsAlignment: MainAxisAlignment.center,
actions: [
SizedBox(
width: 200,
child: GestureDetector(
onTap: () {
context.pop();
},
child: DefaultButton(
backgroundColor: ColorsManager.boxColor,
elevation: 1,
child: Text(
'Cancel',
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
fontSize: 12,
color: Colors.black,
),
),
),
),
),
const SizedBox(
height: 10,
),
GestureDetector(
onTap: () {
AuthBloc.logout();
context.go(RoutesConst.auth);
},
child: SizedBox(
width: 200,
child: DefaultButton(
elevation: 1,
child: Text(
'Logout',
style:
Theme.of(context).textTheme.bodyMedium!.copyWith(fontSize: 12, color: Colors.white),
),
),
),
),
]);
},
);
},
child: ListTile(
leading: SvgPicture.asset(Assets.signOut),
title: Text(
"Log Out",
style: context.textTheme.bodyMedium,
),
),
),
],
).then((value) {
setState(() {
_isDropdownOpen = false;
});
});
}
}

View File

@ -1,14 +1,12 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';
import 'package:syncrow_web/pages/auth/bloc/auth_bloc.dart';
import 'package:syncrow_web/pages/common/buttons/default_button.dart';
import 'package:syncrow_web/pages/common/custom_dialog.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_web/pages/home/bloc/home_bloc.dart';
import 'package:syncrow_web/pages/home/bloc/home_state.dart';
import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/constants/routes_const.dart';
import 'package:syncrow_web/utils/constants/assets.dart';
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
import 'package:syncrow_web/utils/user_drop_down_menu.dart';
class WebAppBar extends StatefulWidget {
final Widget? title;
@ -58,15 +56,15 @@ class _WebAppBarState extends State<WebAppBar> with HelperResponsiveLayout {
if (widget.rightBody != null) widget.rightBody!,
Row(
children: [
const SizedBox.square(
SizedBox.square(
dimension: 40,
child: CircleAvatar(
backgroundColor: Colors.white,
backgroundColor: ColorsManager.whiteColors,
child: SizedBox.square(
dimension: 35,
child: CircleAvatar(
backgroundColor: Colors.grey,
child: FlutterLogo(),
child: SvgPicture.asset(
Assets.logoGrey,
fit: BoxFit.cover,
),
),
),
@ -112,15 +110,15 @@ class _WebAppBarState extends State<WebAppBar> with HelperResponsiveLayout {
const SizedBox(
width: 10,
),
const SizedBox.square(
SizedBox.square(
dimension: 40,
child: CircleAvatar(
backgroundColor: Colors.white,
backgroundColor: ColorsManager.whiteColors,
child: SizedBox.square(
dimension: 35,
child: CircleAvatar(
backgroundColor: Colors.grey,
child: FlutterLogo(),
child: SvgPicture.asset(
Assets.logoGrey,
fit: BoxFit.cover,
),
),
),
@ -136,54 +134,55 @@ class _WebAppBarState extends State<WebAppBar> with HelperResponsiveLayout {
const SizedBox(
width: 10,
),
GestureDetector(
onTap: () {
showCustomDialog(
context: context,
barrierDismissible: true,
title: 'Logout',
message: 'Are you sure you want to logout?',
actions: [
GestureDetector(
onTap: () {
AuthBloc.logout();
context.go(RoutesConst.auth);
},
child: DefaultButton(
child: Text(
'Ok',
style: Theme.of(context)
.textTheme
.bodyMedium!
.copyWith(fontSize: 12, color: Colors.white),
),
),
),
const SizedBox(
height: 10,
),
GestureDetector(
onTap: () {
context.pop();
},
child: DefaultButton(
child: Text(
'Cancel',
style: Theme.of(context)
.textTheme
.bodyMedium!
.copyWith(fontSize: 12, color: Colors.white),
),
),
),
],
);
},
child: const Icon(
Icons.logout,
color: ColorsManager.whiteColors,
),
)
UserDropdownMenu(user: user),
// GestureDetector(
// onTap: () {
// showCustomDialog(
// context: context,
// barrierDismissible: true,
// title: 'Logout',
// message: 'Are you sure you want to logout?',
// actions: [
// GestureDetector(
// onTap: () {
// AuthBloc.logout();
// context.go(RoutesConst.auth);
// },
// child: DefaultButton(
// child: Text(
// 'Ok',
// style: Theme.of(context)
// .textTheme
// .bodyMedium!
// .copyWith(fontSize: 12, color: Colors.white),
// ),
// ),
// ),
// const SizedBox(
// height: 10,
// ),
// GestureDetector(
// onTap: () {
// context.pop();
// },
// child: DefaultButton(
// child: Text(
// 'Cancel',
// style: Theme.of(context)
// .textTheme
// .bodyMedium!
// .copyWith(fontSize: 12, color: Colors.white),
// ),
// ),
// ),
// ],
// );
// },
// child: const Icon(
// Icons.logout,
// color: ColorsManager.whiteColors,
// ),
// )
],
),
],