mirror of
https://github.com/SyncrowIOT/syncrow-app.git
synced 2025-07-14 17:25:47 +00:00
refactor code and implement CeilingSensor taps
This commit is contained in:
28
assets/icons/bathroom.svg
Normal file
28
assets/icons/bathroom.svg
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<svg width="21" height="25" viewBox="0 0 21 25" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M16.9628 0C15.5449 0 14.3965 1.15256 14.3965 2.56632C14.3965 2.78191 14.5748 2.96018 14.7903 2.96018C15.0059 2.96018 15.1842 2.78191 15.1842 2.56632C15.1842 1.58374 15.9844 0.787724 16.9628 0.787724C17.9454 0.787724 18.7414 1.58789 18.7414 2.56632V15.1782C18.7414 15.3938 18.9197 15.5721 19.1353 15.5721C19.3509 15.5721 19.5291 15.3938 19.5291 15.1782V2.56632C19.5291 1.15256 18.3766 0 16.9628 0Z" fill="#C3BEC6"/>
|
||||||
|
<path d="M6.95808 7.69098H5.2168V3.41654C5.2168 3.18852 5.40336 3.00195 5.63139 3.00195H6.54349C6.77152 3.00195 6.95808 3.18852 6.95808 3.41654V7.69098Z" fill="#A7CCF9"/>
|
||||||
|
<path d="M6.53841 3.00195H5.63875C5.58485 3.00195 5.53096 3.01439 5.48535 3.03097C5.6429 3.09316 5.75069 3.24242 5.75069 3.42069V7.69098H6.95715V3.42069C6.95715 3.19267 6.77059 3.00195 6.53841 3.00195Z" fill="#8CBDF9"/>
|
||||||
|
<path d="M5.21973 4.34912H6.96101V5.13685H5.21973V4.34912Z" fill="#4C5E71"/>
|
||||||
|
<path d="M3.47957 7.69102H1.73828V2.54594C1.73828 2.31791 1.92485 2.13135 2.15287 2.13135H3.06497C3.293 2.13135 3.47957 2.31791 3.47957 2.54594V7.69102Z" fill="#A7DDA7"/>
|
||||||
|
<path d="M3.06185 2.13525H2.16219C2.10829 2.13525 2.05439 2.14769 2.00879 2.16428C2.16633 2.22646 2.27413 2.37572 2.27413 2.55399V7.69078H3.48059V2.55399C3.48059 2.32182 3.29402 2.13525 3.06185 2.13525Z" fill="#8ACE9B"/>
|
||||||
|
<path d="M1.73828 3.479H3.47957V4.26673H1.73828V3.479Z" fill="#4C5E71"/>
|
||||||
|
<path d="M11.3064 15.1788C11.3064 14.2004 10.5021 13.4127 9.51952 13.4417H7.47559V15.3695H11.3064V15.1788Z" fill="#EABC73"/>
|
||||||
|
<path d="M15.2205 24.7462L14.7852 23.0049V22.582H16.9618V24.9991H15.2329L15.2205 24.7462Z" fill="#C3BEC6"/>
|
||||||
|
<path d="M5.6512 24.7462L6.08652 23.0049V22.582H3.91406V24.9991H5.64291L5.6512 24.7462Z" fill="#C3BEC6"/>
|
||||||
|
<path d="M20.0045 16.3267H0.871094V16.9195L1.87855 21.6334C2.04853 22.4336 2.75749 23.0099 3.57838 23.0099H17.2931C18.114 23.0099 18.8229 22.4377 18.9929 21.6334L20.0045 16.9195V16.3267Z" fill="#E2DFE2"/>
|
||||||
|
<path d="M18.7983 16.3267V16.9195L17.7867 21.6334C17.6168 22.4336 16.9078 23.0099 16.0869 23.0099H17.2934C18.1143 23.0099 18.8232 22.4377 18.9932 21.6334L20.0048 16.9195V16.3267H18.7983Z" fill="#D3CED5"/>
|
||||||
|
<path d="M0.870642 16.9195C0.389716 16.9195 0 16.5298 0 16.0489C0 15.5679 0.389716 15.1782 0.870642 15.1782H20.004C20.485 15.1782 20.8747 15.5679 20.8747 16.0489C20.8747 16.5298 20.485 16.9195 20.004 16.9195H0.870642Z" fill="#F4F2F4"/>
|
||||||
|
<path d="M20.0053 15.1782H18.7988C19.2798 15.1782 19.6695 15.5679 19.6695 16.0489C19.6695 16.5298 19.2798 16.9195 18.7988 16.9195H20.0053C20.4862 16.9195 20.8759 16.5298 20.8759 16.0489C20.8759 15.5679 20.4862 15.1782 20.0053 15.1782Z" fill="#E2DFE2"/>
|
||||||
|
<path d="M19.5466 19.0509L19.7124 18.2632H1.15527L1.32526 19.0509H19.5466Z" fill="#C3BEC6"/>
|
||||||
|
<path d="M5.22175 13.4424C4.2599 13.4424 3.48047 14.2218 3.48047 15.1837V19.9681C3.48047 20.2085 3.67533 20.4034 3.91579 20.4034H7.39421C7.63468 20.4034 7.82953 20.2085 7.82953 19.9681V15.2168C7.82953 14.2674 8.57165 13.4673 9.52107 13.4424H5.22175Z" fill="#EFD27C"/>
|
||||||
|
<path d="M3.48047 16.9214H7.82954V18.6627H3.48047V16.9214Z" fill="#EAA96A"/>
|
||||||
|
<path d="M16.5265 4.3072C16.5265 3.34535 15.7471 2.56592 14.7852 2.56592C13.8234 2.56592 13.0439 3.34535 13.0439 4.3072V4.80471H16.5224L16.5265 4.3072Z" fill="#E2DFE2"/>
|
||||||
|
<path d="M14.785 2.56592C14.5735 2.56592 14.3704 2.60323 14.1797 2.67371C14.843 2.91832 15.3157 3.55679 15.3157 4.3072V4.80471H16.5221V4.3072C16.5263 3.34535 15.7468 2.56592 14.785 2.56592Z" fill="#D3CED5"/>
|
||||||
|
<path d="M16.5268 6.0489C17.0077 6.0489 17.3974 5.65919 17.3974 5.17826C17.3974 4.69733 17.0077 4.30762 16.5268 4.30762H13.0484C12.5675 4.30762 12.1777 4.69733 12.1777 5.17826C12.1777 5.65919 12.5675 6.0489 13.0484 6.0489H16.5268Z" fill="#F4F2F4"/>
|
||||||
|
<path d="M16.5268 4.30762H15.3203C15.8012 4.30762 16.191 4.69733 16.191 5.17826C16.191 5.65919 15.8012 6.0489 15.3203 6.0489H16.5268C17.0077 6.0489 17.3974 5.65919 17.3974 5.17826C17.3974 4.69733 17.0077 4.30762 16.5268 4.30762Z" fill="#E2DFE2"/>
|
||||||
|
<path d="M13.0491 9.05046C12.8335 9.05046 12.6553 8.87218 12.6553 8.65659V7.78595C12.6553 7.57036 12.8335 7.39209 13.0491 7.39209C13.2647 7.39209 13.443 7.57036 13.443 7.78595V8.65659C13.443 8.87218 13.2647 9.05046 13.0491 9.05046Z" fill="#A7CCF9"/>
|
||||||
|
<path d="M14.7845 9.05046C14.5689 9.05046 14.3906 8.87218 14.3906 8.65659V7.78595C14.3906 7.57036 14.5689 7.39209 14.7845 7.39209C15.0001 7.39209 15.1783 7.57036 15.1783 7.78595V8.65659C15.1783 8.87218 15.0042 9.05046 14.7845 9.05046Z" fill="#A7CCF9"/>
|
||||||
|
<path d="M16.5277 9.05046C16.3121 9.05046 16.1338 8.87218 16.1338 8.65659V7.78595C16.1338 7.57036 16.3121 7.39209 16.5277 7.39209C16.7432 7.39209 16.9215 7.57036 16.9215 7.78595V8.65659C16.9215 8.87218 16.7432 9.05046 16.5277 9.05046Z" fill="#A7CCF9"/>
|
||||||
|
<path d="M8.28354 9.09236H0.414592C0.186566 9.09236 0 8.90579 0 8.67777V7.76567C0 7.53764 0.186566 7.35107 0.414592 7.35107H8.28354C8.51157 7.35107 8.69813 7.53764 8.69813 7.76567V8.67777C8.69813 8.90579 8.51157 9.09236 8.28354 9.09236Z" fill="#EAA96A"/>
|
||||||
|
<path d="M8.2758 7.35107H7.06934C7.30151 7.35107 7.48807 7.53764 7.48807 7.76981V8.66948C7.48807 8.90165 7.30151 9.08821 7.06934 9.08821H8.2758C8.50797 9.08821 8.69453 8.90165 8.69453 8.66948V7.76981C8.69868 7.54179 8.50797 7.35107 8.2758 7.35107Z" fill="#E5935D"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 5.2 KiB |
33
assets/icons/bedroom.svg
Normal file
33
assets/icons/bedroom.svg
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<svg width="25" height="20" viewBox="0 0 25 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M2.91701 6.80859H2.18457V10.1036H2.91701V6.80859Z" fill="#78A7AF"/>
|
||||||
|
<path d="M3.52837 11.1936V10.1333C3.52837 9.98345 3.40576 9.86084 3.2559 9.86084H1.84766C1.69781 9.86084 1.5752 9.98345 1.5752 10.1333V11.1936H3.52837Z" fill="#ABCCD3"/>
|
||||||
|
<path d="M4.40077 7.0244C4.53906 7.0244 4.62153 6.91546 4.58398 6.78235L3.7531 3.83726C3.71555 3.70415 3.57165 3.59521 3.43332 3.59521H1.67048C1.53215 3.59521 1.38825 3.70415 1.3507 3.83726L0.519819 6.78235C0.482269 6.91546 0.564693 7.0244 0.703026 7.0244H4.40077Z" fill="#FCC96C"/>
|
||||||
|
<path opacity="0.1" d="M1.59445 6.78235L2.42533 3.83726C2.46288 3.70415 2.60678 3.59521 2.74512 3.59521H1.67048C1.53215 3.59521 1.38825 3.70415 1.3507 3.83726L0.519819 6.78235C0.482269 6.91546 0.564693 7.0244 0.703026 7.0244H1.77761C1.63933 7.0244 1.5569 6.91546 1.59445 6.78235Z" fill="black"/>
|
||||||
|
<path d="M22.8164 6.80859H22.084V10.1036H22.8164V6.80859Z" fill="#78A7AF"/>
|
||||||
|
<path d="M23.4249 11.1936V10.1333C23.4249 9.98345 23.3022 9.86084 23.1524 9.86084H21.7441C21.5943 9.86084 21.4717 9.98345 21.4717 10.1333V11.1936H23.4249Z" fill="#ABCCD3"/>
|
||||||
|
<path d="M24.2973 7.02445C24.4356 7.02445 24.518 6.91551 24.4805 6.7824L23.6496 3.83726C23.612 3.7041 23.4681 3.59521 23.3298 3.59521H21.5669C21.4286 3.59521 21.2847 3.7041 21.2471 3.83726L20.4163 6.7824C20.3788 6.91551 20.4612 7.02445 20.5996 7.02445H24.2973Z" fill="#FCC96C"/>
|
||||||
|
<path opacity="0.1" d="M21.5628 6.7824L22.3936 3.83726C22.4312 3.7041 22.5751 3.59521 22.7134 3.59521H21.5669C21.4286 3.59521 21.2847 3.7041 21.2471 3.83726L20.4163 6.7824C20.3788 6.91551 20.4612 7.02445 20.5996 7.02445H21.7461C21.6077 7.02445 21.5253 6.91551 21.5628 6.7824Z" fill="black"/>
|
||||||
|
<path d="M3.39173 15.325C3.39173 15.1866 3.50492 15.0734 3.64325 15.0734H3.83798V13.7245C3.83798 13.3095 4.17754 12.97 4.59254 12.97H5.28821V11.048C5.28455 11.0479 5.28113 11.0469 5.27747 11.0469H0.25152C0.113186 11.0469 0 11.1601 0 11.2984V15.8435C0 15.9819 0.113186 16.095 0.25152 16.095H3.39178L3.39173 15.325Z" fill="#CB7C52"/>
|
||||||
|
<path d="M4.59249 12.97H5.28821V11.048C5.28455 11.0479 5.28113 11.0469 5.27747 11.0469H0.25152C0.113186 11.0469 0 11.1601 0 11.2984V13.03H4.2984C4.38892 12.9914 4.48829 12.97 4.59249 12.97Z" fill="#FFBB4A"/>
|
||||||
|
<path opacity="0.1" d="M1.08587 15.8435V11.2984C1.08587 11.1601 1.19905 11.0469 1.33739 11.0469H0.25152C0.113186 11.0469 0 11.1601 0 11.2984V15.8435C0 15.9819 0.113186 16.095 0.25152 16.095H1.33739C1.19905 16.095 1.08587 15.9818 1.08587 15.8435Z" fill="black"/>
|
||||||
|
<path d="M2.76563 12.3745C2.66895 12.3745 2.57471 12.3355 2.50635 12.2676C2.43848 12.1992 2.39941 12.105 2.39941 12.0088C2.39941 11.9121 2.43848 11.8179 2.50635 11.7495C2.57471 11.6816 2.66895 11.6426 2.76563 11.6426C2.86183 11.6426 2.95607 11.6816 3.02443 11.7495C3.0923 11.8179 3.13185 11.9121 3.13185 12.0088C3.13185 12.105 3.09235 12.1992 3.02443 12.2676C2.95607 12.3355 2.86183 12.3745 2.76563 12.3745Z" fill="white"/>
|
||||||
|
<path d="M24.7476 11.0469H19.7216C19.7089 11.0469 19.6968 11.0488 19.6846 11.0506V12.97H20.3803C20.7953 12.97 21.1348 13.3095 21.1348 13.7245V15.0734H21.3296C21.4679 15.0734 21.5811 15.1866 21.5811 15.3249V16.095H24.7476C24.886 16.095 24.9992 15.9819 24.9992 15.8435V11.2984C24.9991 11.1601 24.8859 11.0469 24.7476 11.0469Z" fill="#CB7C52"/>
|
||||||
|
<path d="M24.7476 11.0469H19.7216C19.7089 11.0469 19.6968 11.0488 19.6846 11.0506V12.97H20.3803C20.4845 12.97 20.5839 12.9914 20.6744 13.03H24.9991V11.2984C24.9991 11.1601 24.8859 11.0469 24.7476 11.0469Z" fill="#FFBB4A"/>
|
||||||
|
<path d="M22.2354 12.375C22.1392 12.375 22.0449 12.3355 21.9766 12.2676C21.9087 12.1992 21.8691 12.105 21.8691 12.0083C21.8691 11.9121 21.9087 11.8179 21.9766 11.7495C22.0449 11.6816 22.1392 11.6426 22.2354 11.6426C22.332 11.6426 22.4263 11.6816 22.4946 11.7495C22.5625 11.8179 22.6021 11.9121 22.6021 12.0083C22.6021 12.105 22.5625 12.1992 22.4946 12.2676C22.4263 12.3355 22.332 12.375 22.2354 12.375Z" fill="white"/>
|
||||||
|
<path d="M19.9184 13.1712V9.67632C19.9184 9.53799 19.8052 9.4248 19.6669 9.4248H5.33257C5.19424 9.4248 5.08105 9.53799 5.08105 9.67632V13.1712H19.9184Z" fill="#FF9F3D"/>
|
||||||
|
<path opacity="0.1" d="M6.1636 13.1712V9.67632C6.1636 9.53799 6.27679 9.4248 6.41512 9.4248H5.33257C5.19424 9.4248 5.08105 9.53799 5.08105 9.67632V13.1712H6.1636Z" fill="black"/>
|
||||||
|
<path d="M11.9437 13.171V12.0422C11.9437 11.6272 11.6041 11.2876 11.1891 11.2876H7.27702C6.86207 11.2876 6.52246 11.6272 6.52246 12.0422V13.171H11.9437Z" fill="white"/>
|
||||||
|
<path d="M18.636 13.171V12.0422C18.636 11.6272 18.2965 11.2876 17.8815 11.2876H13.9694C13.5544 11.2876 13.2148 11.6272 13.2148 12.0422V13.171H18.636Z" fill="white"/>
|
||||||
|
<path d="M21.3677 15.2937V13.7253C21.3677 13.3103 21.0282 12.9707 20.6132 12.9707H4.38444C3.96944 12.9707 3.62988 13.3103 3.62988 13.7253V15.2937H21.3677Z" fill="#FFCFAB"/>
|
||||||
|
<path opacity="0.1" d="M5.00365 15.2937V13.7253C5.00365 13.3103 5.34321 12.9707 5.75821 12.9707H4.38444C3.96944 12.9707 3.62988 13.3103 3.62988 13.7253V15.2937H5.00365Z" fill="black"/>
|
||||||
|
<path d="M5.16518 19.1609C5.30352 19.1609 5.4167 19.0477 5.4167 18.9094V17.5694C5.4167 17.4311 5.52989 17.3179 5.66822 17.3179H19.3331C19.4714 17.3179 19.5846 17.4311 19.5846 17.5694V18.9094C19.5846 19.0477 19.6978 19.1609 19.8361 19.1609H21.5643C21.7026 19.1609 21.8158 19.0477 21.8158 18.9094V15.3257C21.8158 15.1874 21.7026 15.0742 21.5643 15.0742H3.43707C3.29873 15.0742 3.18555 15.1874 3.18555 15.3257V18.9094C3.18555 19.0477 3.29873 19.1609 3.43707 19.1609H5.16518Z" fill="#FF9F3D"/>
|
||||||
|
<g opacity="0.1">
|
||||||
|
<path d="M4.28118 18.9089V15.3253C4.28118 15.1869 4.39437 15.0737 4.5327 15.0737H3.43511C3.29678 15.0737 3.18359 15.1869 3.18359 15.3253V18.9089C3.18359 19.0472 3.29678 19.1604 3.43511 19.1604H4.5327C4.39437 19.1604 4.28118 19.0472 4.28118 18.9089Z" fill="black"/>
|
||||||
|
</g>
|
||||||
|
<path d="M18.0893 6.21186C18.0893 6.35019 17.9761 6.46338 17.8378 6.46338H7.16265C7.02432 6.46338 6.91113 6.35019 6.91113 6.21186V0.617731C6.91113 0.479397 7.02432 0.366211 7.16265 0.366211H17.8378C17.9761 0.366211 18.0893 0.479397 18.0893 0.617731V6.21186Z" fill="#B1E8FF"/>
|
||||||
|
<path opacity="0.1" d="M8.01238 6.21186V0.617731C8.01238 0.479397 8.12557 0.366211 8.2639 0.366211H7.16265C7.02432 0.366211 6.91113 0.479397 6.91113 0.617731V6.21191C6.91113 6.35024 7.02432 6.46343 7.16265 6.46343H8.2639C8.12557 6.46333 8.01238 6.35019 8.01238 6.21186Z" fill="black"/>
|
||||||
|
<path d="M12.2235 2.33252L9.83887 6.46284H14.6082L12.2235 2.33252Z" fill="#86D5B5"/>
|
||||||
|
<path d="M12.7314 6.46345H17.8379C17.9763 6.46345 18.0894 6.35027 18.0894 6.21193V5.80025L15.6018 1.4917L12.7314 6.46345Z" fill="#FCC96C"/>
|
||||||
|
<path d="M17.8388 6.82956H7.16364C6.823 6.82956 6.5459 6.55245 6.5459 6.21182V0.61774C6.5459 0.277106 6.823 0 7.16364 0H17.8388C18.1794 0 18.4565 0.277106 18.4565 0.61774V6.21192C18.4565 6.55245 18.1794 6.82956 17.8388 6.82956ZM7.27839 6.09712H17.7241V0.73244H7.27839V6.09712Z" fill="#CB7C52"/>
|
||||||
|
<path d="M9.31653 3.35424C9.8144 3.35424 10.218 2.95063 10.218 2.45276C10.218 1.95488 9.8144 1.55127 9.31653 1.55127C8.81865 1.55127 8.41504 1.95488 8.41504 2.45276C8.41504 2.95063 8.81865 3.35424 9.31653 3.35424Z" fill="white"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 6.9 KiB |
13
assets/icons/dyi.svg
Normal file
13
assets/icons/dyi.svg
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<svg width="25" height="25" viewBox="0 0 25 25" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M15.6477 18.1286L14.5695 16.9625L14.5381 16.5231L16.7995 14.2617L17.2592 14.2729L18.4253 15.351L18.531 15.6845L16.0777 18.1378L15.6477 18.1286Z" fill="#9DE4FB"/>
|
||||||
|
<path d="M21.0627 1.25136C21.36 0.954133 21.36 0.467791 21.0627 0.170566C20.5522 -0.0791971 19.9499 -0.0533175 19.4627 0.239367L17.8536 1.206C16.9222 1.76553 16.4706 2.86478 16.7228 3.92175C16.9226 4.75917 16.6735 5.64059 16.0645 6.24964L16.6364 6.30048C17.2244 5.86531 17.9823 5.71853 18.7089 5.88914C19.131 5.98821 19.5596 5.97283 19.9571 5.85876L20.2488 5.31134L19.4473 4.50975C19.3068 4.36927 19.226 4.18001 19.2217 3.98137L19.21 3.44029C19.2055 3.23013 19.287 3.02719 19.4356 2.8785L21.0627 1.25136Z" fill="#9DE4FB"/>
|
||||||
|
<path d="M6.73692 15.5776C5.0442 17.2704 3.21412 15.8824 1.26475 17.8318C0.124481 18.972 -0.210539 20.6126 0.259592 22.0469C0.259836 22.0463 0.26008 22.0458 0.260276 22.0453L0.554425 22.3394C1.20913 22.5533 1.91218 22.4551 2.61679 22.3364L2.69584 22.0944L2.3972 21.7957C2.26219 21.6607 2.18631 21.4776 2.18631 21.2866V20.2244C2.18631 20.0335 2.26219 19.8504 2.3972 19.7154L3.1483 18.9643C3.28331 18.8292 3.46647 18.7534 3.65739 18.7534H4.71958C4.91055 18.7534 5.09366 18.8292 5.22868 18.9642L5.52644 19.262L5.92421 19.0998C6.02919 18.4761 5.98173 17.3544 6.61944 16.3753L6.73692 15.5776Z" fill="#9DE4FB"/>
|
||||||
|
<path d="M24.7746 3.88015C24.4774 3.58292 23.9911 3.58292 23.6938 3.88015L22.0483 5.5257C21.9105 5.66345 21.7257 5.74397 21.531 5.751L21.0555 5.76814C20.8416 5.77585 20.6341 5.69426 20.4827 5.54289L20.2504 5.31065C19.7111 5.63151 19.0563 5.74455 18.4163 5.59431C17.5859 5.39938 16.7146 5.61887 16.1028 6.20975C16.0904 6.22274 16.0788 6.23627 16.066 6.24901C15.861 6.45405 6.762 15.553 6.73842 15.5766C6.72137 15.5937 6.70399 15.6096 6.68675 15.626C5.67012 16.6895 5.75328 18.0817 5.63155 18.8046C5.60572 18.958 5.5709 19.1104 5.52793 19.261L5.98122 19.7143C6.11623 19.8493 6.19211 20.0325 6.19211 20.2234V21.2856C6.19211 21.4765 6.11623 21.6597 5.98122 21.7947L5.23012 22.5458C5.09511 22.6808 4.91195 22.7567 4.72102 22.7567H3.65884C3.46786 22.7567 3.28475 22.6808 3.14974 22.5458L2.69729 22.0933C1.90097 22.3186 1.04929 22.3015 0.261719 22.0442C0.463043 22.6591 0.811197 23.2365 1.30853 23.72C2.87869 25.2466 5.40669 25.2743 7.008 23.7803C9.10421 21.8246 7.64269 19.9312 9.36784 18.206C9.3922 18.1817 18.4983 9.0756 18.7037 8.87018C19.3169 8.25708 20.2038 8.02787 21.048 8.22602C22.096 8.47202 23.184 8.01327 23.7391 7.08932L24.7057 5.48024C24.9985 4.99297 25.0244 4.39066 24.7746 3.88015Z" fill="#7BD9EC"/>
|
||||||
|
<path d="M7.84826 17.0949C7.70162 16.9482 7.70162 16.7105 7.84826 16.5639L17.1039 7.30818C17.2505 7.1616 17.4883 7.1616 17.6349 7.30818C17.7816 7.45487 17.7816 7.69257 17.6349 7.83925L8.37928 17.0949C8.23259 17.2416 7.99489 17.2415 7.84826 17.0949Z" fill="#9DE4FB"/>
|
||||||
|
<path d="M15.6484 18.1282L18.4261 15.3506L24.5753 21.0359C25.1252 21.5442 25.1421 22.4078 24.6126 22.9373L23.2352 24.3147C22.7057 24.8442 21.8421 24.8273 21.3338 24.2774L15.6484 18.1282Z" fill="#F9BC66"/>
|
||||||
|
<path d="M14.5721 16.9625L17.2618 14.2729L7.34683 5.10596L5.40527 7.04756L14.5721 16.9625Z" fill="#43B5C3"/>
|
||||||
|
<path d="M1.59863 8.09863L3.72729 5.96998L5.7503 7.99299L3.62165 10.1216L1.59863 8.09863Z" fill="#43B5C3"/>
|
||||||
|
<path d="M9.69327 2.70391C9.56329 2.50937 9.41045 2.32582 9.23437 2.15736L7.91231 0.892578L7.6668 0.914844C6.58571 1.58352 6.19688 2.19393 3.02331 5.30428C2.76827 5.55931 2.76827 5.9728 3.02331 6.22784L5.59853 8.80306C5.84185 9.04637 6.23639 9.04637 6.47971 8.80306L9.11616 6.1666C9.56646 5.7163 9.73868 5.06438 9.59102 4.44492C9.45323 3.86669 9.50674 3.4134 9.68766 3.03946C9.71652 2.9798 9.69327 2.70391 9.69327 2.70391Z" fill="#9DE4FB"/>
|
||||||
|
<path d="M12.4915 1.11902C11.0321 -0.0662658 9.32021 -0.113826 7.66602 0.915305L9.10219 2.28927C9.33872 2.51555 9.5333 2.76907 9.68692 3.03988C10.1761 2.00879 11.5877 1.66479 12.3709 1.55175C12.5824 1.52123 12.6575 1.25374 12.4915 1.11902Z" fill="#7BD9EC"/>
|
||||||
|
<path d="M0.996513 7.33135L0.189263 8.1386C-0.0630877 8.39095 -0.0630877 8.8001 0.189263 9.05245L2.75301 11.6162C3.00536 11.8685 3.4145 11.8685 3.66685 11.6162L4.4741 10.8089C4.72645 10.5566 4.72645 10.1474 4.4741 9.8951L1.91036 7.33135C1.65801 7.079 1.24886 7.079 0.996513 7.33135Z" fill="#7BD9EC"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 4.2 KiB |
39
assets/icons/office.svg
Normal file
39
assets/icons/office.svg
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<svg width="25" height="23" viewBox="0 0 25 23" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M23.9152 9.49653V6.93262H17.4302C17.2913 6.93262 17.1787 7.04521 17.1787 7.18413V9.49653H23.9152Z" fill="#FED402"/>
|
||||||
|
<path d="M23.7237 6.88413H18.3818L18.2641 6.93296H17.4302C17.2913 6.93296 17.1787 7.04556 17.1787 7.18447V8.19053H23.9152V6.93296L23.7514 6.88135C23.7422 6.88257 23.7332 6.88413 23.7237 6.88413Z" fill="#FE6C55"/>
|
||||||
|
<path d="M10.4375 6.52441H11.9465V8.08906H10.4375V6.52441Z" fill="#918291"/>
|
||||||
|
<path d="M13.959 9.49687V8.79409C13.959 8.37739 13.6212 8.03955 13.2044 8.03955H9.18032C8.76362 8.03955 8.42578 8.37734 8.42578 8.79409V9.49687H13.959Z" fill="#A79BA7"/>
|
||||||
|
<path d="M10.0266 9.448V8.79409C10.0266 8.37739 10.3644 8.03955 10.7812 8.03955H9.18032C8.76362 8.03955 8.42578 8.37734 8.42578 8.79409V9.448H10.0266Z" fill="#918291"/>
|
||||||
|
<path d="M15.7282 6.20679H6.65918C6.52437 6.20679 6.41504 6.09746 6.41504 5.96265V0.610352C6.41504 0.475537 6.52437 0.366211 6.65918 0.366211H15.7282C15.863 0.366211 15.9724 0.475537 15.9724 0.610352V5.96265C15.9724 6.09751 15.8631 6.20679 15.7282 6.20679Z" fill="#EAF6FF"/>
|
||||||
|
<path d="M8.4271 5.95527V0.617725C8.4271 0.478809 8.5397 0.366211 8.67861 0.366211H6.66655C6.52764 0.366211 6.41504 0.478809 6.41504 0.617725V5.95532C6.41504 6.09424 6.52764 6.20684 6.66655 6.20684H8.67861C8.5397 6.20679 8.4271 6.09419 8.4271 5.95527Z" fill="#D8ECFE"/>
|
||||||
|
<path d="M15.718 6.573H6.66362C6.323 6.573 6.0459 6.2959 6.0459 5.95527V0.617724C6.0459 0.2771 6.323 0 6.66362 0H15.7253C16.0619 0 16.3356 0.273779 16.3356 0.610351V5.95527C16.3357 6.2959 16.0585 6.573 15.718 6.573ZM6.77832 5.84058H15.6032V0.732422H6.77832V5.84058Z" fill="#A79BA7"/>
|
||||||
|
<path d="M1.88359 8.06533V7.69912H1.2311C1.01699 7.69912 0.842773 7.52495 0.842773 7.31079V6.80776C0.842773 6.59365 1.01694 6.41943 1.2311 6.41943H1.88355V5.68701H1.2311C0.613135 5.68701 0.110352 6.1898 0.110352 6.80776V7.31079C0.110352 7.92876 0.613086 8.43154 1.2311 8.43154H1.92603C1.89858 8.31377 1.88359 8.19131 1.88359 8.06533Z" fill="#EAF6FF"/>
|
||||||
|
<path d="M2.65684 9.49746H4.33486C4.82593 9.20913 5.15581 8.67593 5.15581 8.06533V5.93115C5.15581 5.79634 5.04648 5.68701 4.91167 5.68701H1.83594V8.06533C1.83594 8.67593 2.16582 9.20913 2.65684 9.49746Z" fill="#EAF6FF"/>
|
||||||
|
<path d="M2.57842 9.44863H3.83784C3.3896 9.15146 3.09346 8.64341 3.09346 8.06533V5.68701H1.83594V8.06533C1.83594 8.64282 2.13101 9.15127 2.57842 9.44863Z" fill="#D8ECFE"/>
|
||||||
|
<path d="M17.1787 8.19141H19.6977V9.44897H17.1787V8.19141Z" fill="#FAC600"/>
|
||||||
|
<path d="M19.9492 6.93262H17.4302C17.2913 6.93262 17.1787 7.04521 17.1787 7.18413V8.19019H19.6977V7.18413C19.6977 7.04521 19.8103 6.93262 19.9492 6.93262Z" fill="#FD544D"/>
|
||||||
|
<path d="M24.7477 6.93384H18.2627V5.92778C18.2627 5.78887 18.3753 5.67627 18.5142 5.67627H24.7477C24.8866 5.67627 24.9992 5.78887 24.9992 5.92778V6.68232C24.9992 6.82124 24.8866 6.93384 24.7477 6.93384Z" fill="#00C27A"/>
|
||||||
|
<path d="M20.6018 5.67627H18.5142C18.3753 5.67627 18.2627 5.78887 18.2627 5.92778V6.93384H20.3502V5.92778C20.3502 5.78887 20.4629 5.67627 20.6018 5.67627Z" fill="#09A755"/>
|
||||||
|
<path d="M2.26367 10.7251H14.0313V15.6865H2.26367V10.7251Z" fill="#FFBD86"/>
|
||||||
|
<path d="M2.31348 10.7734H3.56406V15.686H2.31348V10.7734Z" fill="#F6A96C"/>
|
||||||
|
<path d="M13.9854 10.7241V13.5457L14.1291 13.5945H22.5894L22.7364 13.5457V10.7241H13.9854Z" fill="#EA9B58"/>
|
||||||
|
<path d="M13.9854 10.7729H15.5196V13.5457H13.9854V10.7729Z" fill="#D88A55"/>
|
||||||
|
<path d="M18.9885 12.519H17.6807C17.4784 12.519 17.3145 12.3551 17.3145 12.1528C17.3145 11.9506 17.4784 11.7866 17.6807 11.7866H18.9885C19.1908 11.7866 19.3547 11.9506 19.3547 12.1528C19.3547 12.3551 19.1908 12.519 18.9885 12.519Z" fill="#D88A55"/>
|
||||||
|
<path d="M13.9854 13.5464V16.3191L14.0939 16.3679H22.6279L22.7364 16.3191V13.5464H13.9854Z" fill="#F6A96C"/>
|
||||||
|
<path d="M13.9854 13.5464H15.5196V16.3191H13.9854V13.5464Z" fill="#EA9B58"/>
|
||||||
|
<path d="M18.9885 15.291H17.6807C17.4784 15.291 17.3145 15.1271 17.3145 14.9248C17.3145 14.7226 17.4784 14.5586 17.6807 14.5586H18.9885C19.1908 14.5586 19.3547 14.7226 19.3547 14.9248C19.3547 15.1271 19.1908 15.291 18.9885 15.291Z" fill="#D88A55"/>
|
||||||
|
<path d="M22.7364 16.3188H13.9854V19.7856C13.9854 19.9245 14.0979 20.0371 14.2369 20.0371H22.7364V16.3188Z" fill="#EA9B58"/>
|
||||||
|
<path d="M15.5196 19.7856V16.3188H13.9854V19.7856C13.9854 19.9245 14.0979 20.0371 14.2369 20.0371H15.7711C15.6322 20.0371 15.5196 19.9245 15.5196 19.7856Z" fill="#D88A55"/>
|
||||||
|
<path d="M18.9885 18.064H17.6807C17.4784 18.064 17.3145 17.9 17.3145 17.6978C17.3145 17.4955 17.4784 17.3315 17.6807 17.3315H18.9885C19.1908 17.3315 19.3547 17.4955 19.3547 17.6978C19.3547 17.9 19.1908 18.064 18.9885 18.064Z" fill="#D88A55"/>
|
||||||
|
<path d="M0.804688 10.7251V21.773C0.804688 21.912 0.917285 22.0246 1.0562 22.0246H2.06226C2.20117 22.0246 2.31377 21.912 2.31377 21.773V10.7251H0.804688Z" fill="#A79BA7"/>
|
||||||
|
<path d="M1.4647 21.773V10.7251H0.804688V21.773C0.804688 21.912 0.917285 22.0246 1.0562 22.0246H1.71621C1.5773 22.0246 1.4647 21.912 1.4647 21.773Z" fill="#918291"/>
|
||||||
|
<path d="M22.6875 10.7251V21.773C22.6875 21.912 22.8001 22.0246 22.939 22.0246H23.9451C24.084 22.0246 24.1966 21.912 24.1966 21.773V10.7251H22.6875Z" fill="#A79BA7"/>
|
||||||
|
<path d="M23.3475 21.773V10.7251H22.6875V21.773C22.6875 21.912 22.8001 22.0246 22.939 22.0246H23.599C23.4601 22.0246 23.3475 21.912 23.3475 21.773Z" fill="#918291"/>
|
||||||
|
<path d="M24.7485 9.44873H0.251514C0.112598 9.44873 0 9.56133 0 9.70024V10.522C0 10.6609 0.112598 10.7735 0.251514 10.7735H24.7485C24.8874 10.7735 25 10.6609 25 10.522V9.70024C25 9.56133 24.8874 9.44873 24.7485 9.44873Z" fill="#F6A96C"/>
|
||||||
|
<path d="M3.41797 10.522V9.70024C3.41797 9.56133 3.53057 9.44873 3.66948 9.44873H0.251514C0.112598 9.44873 0 9.56133 0 9.70024V10.522C0 10.6609 0.112598 10.7735 0.251514 10.7735H3.66948C3.53057 10.7735 3.41797 10.6609 3.41797 10.522Z" fill="#EA9B58"/>
|
||||||
|
<path d="M14.3078 2.30615H10.5352C10.3329 2.30615 10.1689 2.14219 10.1689 1.93994C10.1689 1.7377 10.3329 1.57373 10.5352 1.57373H14.3078C14.5101 1.57373 14.674 1.7377 14.674 1.93994C14.674 2.14219 14.5101 2.30615 14.3078 2.30615Z" fill="#0593FC"/>
|
||||||
|
<path d="M9.37915 2.30566H8.07129C7.86904 2.30566 7.70508 2.1417 7.70508 1.93945C7.70508 1.73721 7.86904 1.57324 8.07129 1.57324H9.37915C9.5814 1.57324 9.74536 1.73721 9.74536 1.93945C9.74536 2.1417 9.5814 2.30566 9.37915 2.30566Z" fill="#0593FC"/>
|
||||||
|
<path d="M14.3078 3.61475H13.1006C12.8983 3.61475 12.7344 3.45078 12.7344 3.24854C12.7344 3.04629 12.8983 2.88232 13.1006 2.88232H14.3078C14.5101 2.88232 14.674 3.04629 14.674 3.24854C14.674 3.45078 14.5101 3.61475 14.3078 3.61475Z" fill="#0593FC"/>
|
||||||
|
<path d="M11.7936 3.61426H8.07129C7.86904 3.61426 7.70508 3.45029 7.70508 3.24805C7.70508 3.0458 7.86904 2.88184 8.07129 2.88184H11.7936C11.9959 2.88184 12.1598 3.0458 12.1598 3.24805C12.1598 3.45029 11.9959 3.61426 11.7936 3.61426Z" fill="#0593FC"/>
|
||||||
|
<path d="M10.2846 4.92236H8.07129C7.86904 4.92236 7.70508 4.7584 7.70508 4.55615C7.70508 4.35391 7.86904 4.18994 8.07129 4.18994H10.2846C10.4868 4.18994 10.6508 4.35391 10.6508 4.55615C10.6508 4.7584 10.4868 4.92236 10.2846 4.92236Z" fill="#0593FC"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 6.9 KiB |
29
assets/icons/parlour.svg
Normal file
29
assets/icons/parlour.svg
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<svg width="25" height="22" viewBox="0 0 25 22" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M9.05824 9.95946C8.90674 9.92645 8.73888 9.90869 8.55508 9.90869H3.02024C2.03877 9.90869 1.51074 10.4155 1.51074 11.0408V14.9798L9.56141 15.483L9.05824 9.95946Z" fill="#D273B3"/>
|
||||||
|
<path d="M10.0646 11.0403C10.0646 10.5321 9.71578 10.1022 9.05824 9.95898V14.602C9.05824 14.8104 8.88928 14.9793 8.68087 14.9793H4.02658C4.02658 14.4711 3.58802 14.0412 2.93048 13.898V14.9793H1.51074V16.659H10.5677C10.5677 16.659 10.0646 11.6656 10.0646 11.0403Z" fill="#CA59A6"/>
|
||||||
|
<path d="M18.1152 5.37996L17.6121 0H1.88812C1.67971 0 1.51074 0.168963 1.51074 0.377375V5.37996H18.1152Z" fill="#FFE07D"/>
|
||||||
|
<path d="M17.6104 0V5.37996H18.1135L18.6167 1.5095V0.377375C18.6167 0.168963 18.4477 0 18.2393 0H17.6104Z" fill="#FFC250"/>
|
||||||
|
<path d="M17.6121 2.07861C16.0781 2.99101 15.0219 3.81972 15.0219 3.81972C15.0219 3.81972 13.1458 2.57202 11.989 2.57202C9.76353 2.57202 8.06293 5.37954 1.51074 5.37954V5.88271L18.1152 6.38587L17.6121 2.07861Z" fill="#FFF0AF"/>
|
||||||
|
<path d="M17.2347 5.88339H1.51074V6.51235C1.51074 6.72076 1.67971 6.88973 1.88812 6.88973H18.241C18.4495 6.88973 18.6184 6.72076 18.6184 6.51235V1.50977C18.2658 1.69886 17.929 1.89081 17.6121 2.07935V5.50607C17.6121 5.71443 17.4431 5.88339 17.2347 5.88339Z" fill="#FFE07D"/>
|
||||||
|
<path d="M17.611 9.95946C17.4595 9.92645 17.2916 9.90869 17.1078 9.90869H11.573C10.5915 9.90869 10.0635 10.4155 10.0635 11.0408V14.9798L18.1141 15.483L17.611 9.95946Z" fill="#D273B3"/>
|
||||||
|
<path d="M17.611 9.95898V14.602C17.611 14.8104 17.442 14.9793 17.2336 14.9793H10.0635V16.659H18.6173C18.6173 16.659 18.6173 11.6656 18.6173 11.0403C18.6173 10.5321 18.2685 10.1022 17.611 9.95898Z" fill="#CA59A6"/>
|
||||||
|
<path d="M16.1014 16.489L14.5836 15.9858H10.9613C10.3775 15.9858 10.0635 16.2873 10.0635 16.6592V16.9922L18.1147 17.4953L16.1014 16.489Z" fill="#DA8BC1"/>
|
||||||
|
<path d="M16.1015 16.4888V16.6146C16.1015 16.823 15.9325 16.9919 15.7241 16.9919H10.0635V18.5014H18.6173V16.4888H16.1015Z" fill="#D273B3"/>
|
||||||
|
<path d="M9.0573 15.9858H4.02563L3.52246 17.4953H9.56046L9.0573 15.9858Z" fill="#DA8BC1"/>
|
||||||
|
<path d="M10.0646 16.6592C10.0646 16.2873 9.7505 15.9858 9.16678 15.9858H9.05824V16.6148C9.05824 16.8232 8.88928 16.9922 8.68087 16.9922H4.02658V15.9858H1.51074V18.5017H10.5677C10.5677 18.5017 10.0646 17.0311 10.0646 16.6592Z" fill="#D273B3"/>
|
||||||
|
<path d="M19.1203 12.9785C18.9688 12.9455 18.801 12.9277 18.6172 12.9277C17.6357 12.9277 17.1077 13.4346 17.1077 14.0599V18.2504H3.019L2.01267 12.9785C1.86116 12.9455 1.69331 12.9277 1.5095 12.9277C0.528023 12.9277 0 13.4346 0 14.0599V19.5084L19.6235 20.0115L19.1203 12.9785Z" fill="#DA8BC1"/>
|
||||||
|
<path d="M3.02001 18.25C3.02001 18.25 3.02001 14.6847 3.02001 14.0594C3.02001 13.5512 2.67121 13.1212 2.01367 12.978V17.9984L3.02001 18.25Z" fill="#DA8BC1"/>
|
||||||
|
<path d="M19.1203 12.978V19.1305C19.1203 19.3389 18.9514 19.5079 18.743 19.5079H0V20.1368C0 20.3452 0.168963 20.5142 0.377375 20.5142H19.7493C19.9577 20.5142 20.1267 20.3452 20.1267 20.1368V14.0594C20.1267 13.5512 19.7779 13.1212 19.1203 12.978Z" fill="#D273B3"/>
|
||||||
|
<path d="M10.2412 20.0115C8.73172 20.0115 6.03877 20.0115 4.52927 20.0115C3.01977 20.0115 2.5166 19.4172 2.5166 19.0051C2.5166 18.7272 2.74187 18.502 3.01977 18.502H11.7507C12.0286 18.502 12.2539 18.7272 12.2539 19.0051C12.2539 19.4172 11.7507 20.0115 10.2412 20.0115Z" fill="#D273B3"/>
|
||||||
|
<path d="M20.1267 18.25H14.4951C15.2643 19.2151 16.9145 19.8487 18.8263 19.8487C19.277 19.8487 19.7132 19.8116 20.1267 19.7422V18.25Z" fill="#D273B3"/>
|
||||||
|
<path d="M3.90931 18.1172L2.92104 21.2378C2.85809 21.4365 2.96819 21.6486 3.16689 21.7115C3.36559 21.7745 3.57767 21.6644 3.64057 21.4657L4.62884 18.345L3.90931 18.1172Z" fill="#DCE6EB"/>
|
||||||
|
<path d="M9.13379 18.345L10.1221 21.4657C10.185 21.6644 10.3971 21.7744 10.5957 21.7115C10.7944 21.6486 10.9045 21.4365 10.8416 21.2378L9.85332 18.1172L9.13379 18.345Z" fill="#DCE6EB"/>
|
||||||
|
<path d="M11.2477 17.4956H2.51684C2.23894 17.4956 2.01367 17.7209 2.01367 17.9988C2.01367 18.0778 2.03234 18.1635 2.07289 18.2504C2.07289 18.2504 7.89574 18.6026 9.38607 18.6026C10.8955 18.6026 11.2477 17.4956 11.2477 17.4956Z" fill="#E0BBA4"/>
|
||||||
|
<path d="M11.2481 17.4956C11.2481 17.4956 10.8959 18.2504 9.38642 18.2504C7.89609 18.2504 3.63402 18.2504 2.07324 18.2504C2.24412 18.6168 2.80656 19.0051 4.02669 19.0051H9.73859C9.73859 19.0051 11.7513 18.4108 11.7513 17.9988C11.7513 17.7209 11.526 17.4956 11.2481 17.4956Z" fill="#CF9875"/>
|
||||||
|
<path d="M15.9337 18.1172L14.9455 21.2378C14.8825 21.4365 14.9926 21.6486 15.1913 21.7115C15.39 21.7745 15.6021 21.6644 15.665 21.4657L16.6533 18.345L15.9337 18.1172Z" fill="#DCE6EB"/>
|
||||||
|
<path d="M21.2432 17.5306L22.4893 21.4653C22.5522 21.664 22.7643 21.774 22.9629 21.7111C23.1616 21.6482 23.2717 21.4361 23.2088 21.2374L21.9627 17.3027L21.2432 17.5306Z" fill="#DCE6EB"/>
|
||||||
|
<path d="M21.3791 16.4893L23.786 7.40723C23.2671 7.46846 22.8111 7.79472 22.5903 8.27755L19.6694 14.6637C19.3009 15.4694 18.4963 15.9862 17.6104 15.9862L21.3791 16.4893Z" fill="#FFE07D"/>
|
||||||
|
<path d="M24.2456 7.39551H23.9652C23.9054 7.39551 23.8465 7.39994 23.7881 7.40683L20.6881 14.1845C20.3144 15.0017 20.1277 15.4717 19.4238 15.9857L21.3812 16.4889L24.7274 7.56985C24.5968 7.46117 24.4291 7.39551 24.2456 7.39551Z" fill="#FFC250"/>
|
||||||
|
<path d="M21.4367 17.4869C22.9619 16.5631 24.1083 13.6303 24.1083 8.9209L21.4815 14.6639C21.113 15.4697 20.3084 15.9864 19.4224 15.9864C19.0923 15.9864 17.611 15.9864 17.611 15.9864H14.583C13.9515 15.9864 13.5979 16.7167 13.9916 17.2106C14.5624 17.7568 16.1091 18.3398 18.0209 18.3398C19.3581 18.3398 20.5673 18.0134 21.4367 17.4869Z" fill="#E0BBA4"/>
|
||||||
|
<path d="M24.7265 7.56982L24.1089 8.92017C23.7576 13.438 22.4593 16.0592 20.9341 16.983C20.0648 17.5095 18.8555 17.8359 17.5183 17.8359C15.6065 17.8359 14.4859 17.4952 13.9922 17.2099C14.7613 18.175 16.4116 18.8423 18.3234 18.8423C19.6606 18.8423 20.8699 18.5158 21.7392 17.9893C23.4525 16.9516 24.8794 13.7722 24.9994 8.16859C25.0045 7.92828 24.8974 7.71212 24.7265 7.56982Z" fill="#CF9875"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 5.8 KiB |
@ -1,3 +1,4 @@
|
|||||||
|
import 'package:dio/dio.dart';
|
||||||
import 'package:firebase_database/firebase_database.dart';
|
import 'package:firebase_database/firebase_database.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:syncrow_app/features/devices/bloc/ceiling_bloc/ceiling_sensor_event.dart';
|
import 'package:syncrow_app/features/devices/bloc/ceiling_bloc/ceiling_sensor_event.dart';
|
||||||
@ -5,6 +6,7 @@ import 'package:syncrow_app/features/devices/bloc/ceiling_bloc/ceiling_sensor_st
|
|||||||
import 'package:syncrow_app/features/devices/model/ceiling_sensor_model.dart';
|
import 'package:syncrow_app/features/devices/model/ceiling_sensor_model.dart';
|
||||||
import 'package:syncrow_app/features/devices/model/device_control_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_model.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/device_report_model.dart';
|
||||||
import 'package:syncrow_app/features/devices/model/status_model.dart';
|
import 'package:syncrow_app/features/devices/model/status_model.dart';
|
||||||
import 'package:syncrow_app/services/api/devices_api.dart';
|
import 'package:syncrow_app/services/api/devices_api.dart';
|
||||||
|
|
||||||
@ -17,9 +19,11 @@ class CeilingSensorBloc extends Bloc<CeilingSensorEvent, CeilingSensorState> {
|
|||||||
on<InitialEvent>(_fetchCeilingSensorStatus);
|
on<InitialEvent>(_fetchCeilingSensorStatus);
|
||||||
on<ChangeValueEvent>(_changeValue);
|
on<ChangeValueEvent>(_changeValue);
|
||||||
on<CeilingSensorUpdated>(_onCeilingSensorUpdated);
|
on<CeilingSensorUpdated>(_onCeilingSensorUpdated);
|
||||||
|
on<ReportLogsInitial>(fetchLogsForLastMonth);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _fetchCeilingSensorStatus(InitialEvent event, Emitter<CeilingSensorState> emit) async {
|
void _fetchCeilingSensorStatus(
|
||||||
|
InitialEvent event, Emitter<CeilingSensorState> emit) async {
|
||||||
emit(LoadingInitialState());
|
emit(LoadingInitialState());
|
||||||
try {
|
try {
|
||||||
var response = await DevicesAPI.getDeviceStatus(deviceId);
|
var response = await DevicesAPI.getDeviceStatus(deviceId);
|
||||||
@ -38,15 +42,18 @@ class CeilingSensorBloc extends Bloc<CeilingSensorEvent, CeilingSensorState> {
|
|||||||
|
|
||||||
_listenToChanges() {
|
_listenToChanges() {
|
||||||
try {
|
try {
|
||||||
DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$deviceId');
|
DatabaseReference ref =
|
||||||
|
FirebaseDatabase.instance.ref('device-status/$deviceId');
|
||||||
Stream<DatabaseEvent> stream = ref.onValue;
|
Stream<DatabaseEvent> stream = ref.onValue;
|
||||||
|
|
||||||
stream.listen((DatabaseEvent event) {
|
stream.listen((DatabaseEvent event) {
|
||||||
Map<dynamic, dynamic> usersMap = event.snapshot.value as Map<dynamic, dynamic>;
|
Map<dynamic, dynamic> usersMap =
|
||||||
|
event.snapshot.value as Map<dynamic, dynamic>;
|
||||||
List<StatusModel> statusList = [];
|
List<StatusModel> statusList = [];
|
||||||
|
|
||||||
usersMap['status'].forEach((element) {
|
usersMap['status'].forEach((element) {
|
||||||
statusList.add(StatusModel(code: element['code'], value: element['value']));
|
statusList
|
||||||
|
.add(StatusModel(code: element['code'], value: element['value']));
|
||||||
});
|
});
|
||||||
|
|
||||||
deviceStatus = CeilingSensorModel.fromJson(statusList);
|
deviceStatus = CeilingSensorModel.fromJson(statusList);
|
||||||
@ -55,20 +62,62 @@ class CeilingSensorBloc extends Bloc<CeilingSensorEvent, CeilingSensorState> {
|
|||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
_onCeilingSensorUpdated(CeilingSensorUpdated event, Emitter<CeilingSensorState> emit) {
|
_onCeilingSensorUpdated(
|
||||||
|
CeilingSensorUpdated event, Emitter<CeilingSensorState> emit) {
|
||||||
emit(UpdateState(ceilingSensorModel: deviceStatus));
|
emit(UpdateState(ceilingSensorModel: deviceStatus));
|
||||||
}
|
}
|
||||||
|
|
||||||
void _changeValue(ChangeValueEvent event, Emitter<CeilingSensorState> emit) async {
|
void _changeValue(
|
||||||
|
ChangeValueEvent event, Emitter<CeilingSensorState> emit) async {
|
||||||
emit(LoadingNewSate(ceilingSensorModel: deviceStatus));
|
emit(LoadingNewSate(ceilingSensorModel: deviceStatus));
|
||||||
try {
|
try {
|
||||||
final response = await DevicesAPI.controlDevice(
|
final response = await DevicesAPI.controlDevice(
|
||||||
DeviceControlModel(deviceId: deviceId, code: event.code, value: event.value), deviceId);
|
DeviceControlModel(
|
||||||
|
deviceId: deviceId, code: event.code, value: event.value),
|
||||||
|
deviceId);
|
||||||
if (response['success'] ?? false) {
|
if (response['success'] ?? false) {
|
||||||
deviceStatus.sensitivity = event.value;
|
if (event.type == 'Sensitivity') {
|
||||||
}
|
deviceStatus.sensitivity = event.value;
|
||||||
|
} else if (event.type == 'Maximum Distance') {
|
||||||
|
deviceStatus.movingMaxDis = event.value;
|
||||||
|
} else if (event.type == 'Nobody Time') {
|
||||||
|
deviceStatus.nobodyTime = event.value;
|
||||||
|
} else if (event.type == 'Space Type') {
|
||||||
|
deviceStatus.spaceType = SpaceTypes.values.firstWhere(
|
||||||
|
(e) => e.name == event.value,
|
||||||
|
orElse: () => SpaceTypes.none,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} //scene
|
||||||
|
emit(UpdateState(ceilingSensorModel: deviceStatus));
|
||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
emit(UpdateState(ceilingSensorModel: deviceStatus));
|
}
|
||||||
|
|
||||||
|
DeviceReport recordGroups =
|
||||||
|
DeviceReport(startTime: '0', endTime: '0', data: []);
|
||||||
|
|
||||||
|
Future<void> fetchLogsForLastMonth(
|
||||||
|
ReportLogsInitial event, Emitter<CeilingSensorState> emit) async {
|
||||||
|
DateTime now = DateTime.now();
|
||||||
|
|
||||||
|
DateTime lastMonth = DateTime(now.year, now.month - 1, now.day);
|
||||||
|
int startTime = lastMonth.millisecondsSinceEpoch;
|
||||||
|
int endTime = now.millisecondsSinceEpoch;
|
||||||
|
try {
|
||||||
|
emit(LoadingInitialState());
|
||||||
|
var response = await DevicesAPI.getReportLogs(
|
||||||
|
startTime: startTime.toString(),
|
||||||
|
endTime: endTime.toString(),
|
||||||
|
deviceUuid: deviceId,
|
||||||
|
code: 'switch_1',
|
||||||
|
);
|
||||||
|
recordGroups = response;
|
||||||
|
|
||||||
|
emit(UpdateState(ceilingSensorModel: deviceStatus));
|
||||||
|
} on DioException catch (e) {
|
||||||
|
final errorData = e.response!.data;
|
||||||
|
String errorMessage = errorData['message'];
|
||||||
|
emit(FailedState(error: errorMessage));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,10 +14,16 @@ class InitialEvent extends CeilingSensorEvent {}
|
|||||||
class CeilingSensorUpdated extends CeilingSensorEvent {}
|
class CeilingSensorUpdated extends CeilingSensorEvent {}
|
||||||
|
|
||||||
class ChangeValueEvent extends CeilingSensorEvent {
|
class ChangeValueEvent extends CeilingSensorEvent {
|
||||||
final int value;
|
final dynamic value;
|
||||||
final String code;
|
final String code;
|
||||||
const ChangeValueEvent({required this.value, required this.code});
|
final String type;
|
||||||
|
|
||||||
|
const ChangeValueEvent({required this.value, required this.code,required this.type});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [value, code];
|
List<Object> get props => [value, code,type];
|
||||||
|
}
|
||||||
|
|
||||||
|
class ReportLogsInitial extends CeilingSensorEvent {
|
||||||
|
const ReportLogsInitial();
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,8 @@ class UpdateState extends CeilingSensorState {
|
|||||||
List<Object> get props => [ceilingSensorModel];
|
List<Object> get props => [ceilingSensorModel];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class LoadingNewSate extends CeilingSensorState {
|
class LoadingNewSate extends CeilingSensorState {
|
||||||
final CeilingSensorModel ceilingSensorModel;
|
final CeilingSensorModel ceilingSensorModel;
|
||||||
const LoadingNewSate({required this.ceilingSensorModel});
|
const LoadingNewSate({required this.ceilingSensorModel});
|
||||||
|
@ -7,13 +7,19 @@ class CeilingSensorModel {
|
|||||||
int presenceRange;
|
int presenceRange;
|
||||||
int sportsPara;
|
int sportsPara;
|
||||||
String bodyMovement;
|
String bodyMovement;
|
||||||
|
String nobodyTime;
|
||||||
|
int movingMaxDis;
|
||||||
|
SpaceTypes spaceType;
|
||||||
|
|
||||||
CeilingSensorModel(
|
CeilingSensorModel(
|
||||||
{required this.presenceState,
|
{required this.presenceState,
|
||||||
required this.sensitivity,
|
required this.sensitivity,
|
||||||
|
required this.nobodyTime,
|
||||||
|
required this.spaceType,
|
||||||
required this.checkingResult,
|
required this.checkingResult,
|
||||||
required this.presenceRange,
|
required this.presenceRange,
|
||||||
required this.sportsPara,
|
required this.sportsPara,
|
||||||
|
required this.movingMaxDis,
|
||||||
required this.bodyMovement});
|
required this.bodyMovement});
|
||||||
|
|
||||||
factory CeilingSensorModel.fromJson(List<StatusModel> jsonList) {
|
factory CeilingSensorModel.fromJson(List<StatusModel> jsonList) {
|
||||||
@ -22,8 +28,10 @@ class CeilingSensorModel {
|
|||||||
late String _checkingResult;
|
late String _checkingResult;
|
||||||
int _presenceRange = 1;
|
int _presenceRange = 1;
|
||||||
int _sportsPara = 1;
|
int _sportsPara = 1;
|
||||||
|
int _moving_max_dis = 0;
|
||||||
String _bodyMovement = 'none';
|
String _bodyMovement = 'none';
|
||||||
|
String _nobody_time = 'none';
|
||||||
|
SpaceTypes _spaceType = SpaceTypes.none;
|
||||||
for (int i = 0; i < jsonList.length; i++) {
|
for (int i = 0; i < jsonList.length; i++) {
|
||||||
if (jsonList[i].code == 'presence_state') {
|
if (jsonList[i].code == 'presence_state') {
|
||||||
_presenceState = jsonList[i].value ?? 'none';
|
_presenceState = jsonList[i].value ?? 'none';
|
||||||
@ -37,14 +45,46 @@ class CeilingSensorModel {
|
|||||||
_sportsPara = jsonList[i].value ?? 0;
|
_sportsPara = jsonList[i].value ?? 0;
|
||||||
} else if (jsonList[i].code == 'body_movement') {
|
} else if (jsonList[i].code == 'body_movement') {
|
||||||
_bodyMovement = jsonList[i].value ?? '';
|
_bodyMovement = jsonList[i].value ?? '';
|
||||||
}
|
} else if (jsonList[i].code == 'nobody_time') {
|
||||||
|
_nobody_time = jsonList[i].value ?? 'none';
|
||||||
|
} else if (jsonList[i].code == 'moving_max_dis') {
|
||||||
|
_moving_max_dis = jsonList[i].value ?? 0;
|
||||||
|
} else if (jsonList[i].code == 'scene')
|
||||||
|
_spaceType = getSpaceType(jsonList[i].value ?? 'none');
|
||||||
}
|
}
|
||||||
return CeilingSensorModel(
|
return CeilingSensorModel(
|
||||||
|
spaceType: _spaceType,
|
||||||
|
movingMaxDis: _moving_max_dis,
|
||||||
presenceState: _presenceState,
|
presenceState: _presenceState,
|
||||||
sensitivity: _sensitivity,
|
sensitivity: _sensitivity,
|
||||||
checkingResult: _checkingResult,
|
checkingResult: _checkingResult,
|
||||||
presenceRange: _presenceRange,
|
presenceRange: _presenceRange,
|
||||||
sportsPara: _sportsPara,
|
sportsPara: _sportsPara,
|
||||||
|
nobodyTime: _nobody_time,
|
||||||
bodyMovement: _bodyMovement);
|
bodyMovement: _bodyMovement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum SpaceTypes {
|
||||||
|
none,
|
||||||
|
parlour,
|
||||||
|
area,
|
||||||
|
toilet,
|
||||||
|
bedroom,
|
||||||
|
}
|
||||||
|
|
||||||
|
SpaceTypes getSpaceType(String value) {
|
||||||
|
switch (value) {
|
||||||
|
case 'parlour':
|
||||||
|
return SpaceTypes.parlour;
|
||||||
|
case 'area':
|
||||||
|
return SpaceTypes.area;
|
||||||
|
case 'toilet':
|
||||||
|
return SpaceTypes.toilet;
|
||||||
|
case 'bedroom':
|
||||||
|
return SpaceTypes.bedroom;
|
||||||
|
case 'none':
|
||||||
|
default:
|
||||||
|
return SpaceTypes.none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -0,0 +1,44 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
|
||||||
|
|
||||||
|
class CeilingHelpDescription extends StatelessWidget {
|
||||||
|
const CeilingHelpDescription({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return DefaultScaffold(
|
||||||
|
title: 'Help Description',
|
||||||
|
child: Center(
|
||||||
|
child: ListView(
|
||||||
|
shrinkWrap: true,
|
||||||
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'1. Nobody, the report to someone\n'
|
||||||
|
'Instruction: The propagation and processing of electromagnetic waves are complicated. '
|
||||||
|
'There will be false alarms in the actual use of radar, and there will be some influencing '
|
||||||
|
'factors in the environment, including:\n\n'
|
||||||
|
'A. Physical disturbance: including air conditioning, fan, motor and other facilities vibration, '
|
||||||
|
'cats, dogs, mice, birds and other animals passing by, which may cause radar misjudgement '
|
||||||
|
'of the environment.\n\n'
|
||||||
|
'B. Space electromagnetic wave disturbance: This includes the possible existence of high-power '
|
||||||
|
'electrical equipment around the radar, electromagnetic-wave-intensive places, and the '
|
||||||
|
'simultaneous coexistence of multiple radars and other environmental factors. These '
|
||||||
|
'interferences are relatively few in home and office scenarios but may be more common '
|
||||||
|
'in factories and industrial environments.\n\n'
|
||||||
|
'C. Power supply disturbance: This is mainly caused by power supply radar crosstalk due to '
|
||||||
|
'associated facilities and equipment in the mains environment, resulting in an unstable '
|
||||||
|
'power supply for the radar and potential misjudgement.\n\n'
|
||||||
|
'2. In the case of human misreporting no one:\n'
|
||||||
|
'A. The presence of a human body may be beyond the radar test range.\n\n'
|
||||||
|
'B. The human body is covered by metal or by extremely thick office desks and chairs.\n\n'
|
||||||
|
'C. When sleeping, the body might not exhibit noticeable breathing micro-movements on the side, '
|
||||||
|
'leading to a short-term misjudgement as nobody.',
|
||||||
|
style: Theme.of(context).textTheme.bodyMedium,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -7,6 +7,11 @@ import 'package:syncrow_app/features/devices/bloc/ceiling_bloc/ceiling_sensor_ev
|
|||||||
import 'package:syncrow_app/features/devices/bloc/ceiling_bloc/ceiling_sensor_state.dart';
|
import 'package:syncrow_app/features/devices/bloc/ceiling_bloc/ceiling_sensor_state.dart';
|
||||||
import 'package:syncrow_app/features/devices/model/ceiling_sensor_model.dart';
|
import 'package:syncrow_app/features/devices/model/ceiling_sensor_model.dart';
|
||||||
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/ceiling_sensor/ceiling_help_description.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/ceiling_sensor/double_parameter_control.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/ceiling_sensor/max_distance_control.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/ceiling_sensor/presence_record.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/view/widgets/ceiling_sensor/presence_space_type.dart';
|
||||||
import 'package:syncrow_app/features/devices/view/widgets/device_appbar.dart';
|
import 'package:syncrow_app/features/devices/view/widgets/device_appbar.dart';
|
||||||
import 'package:syncrow_app/features/devices/view/widgets/wall_sensor/wall_sensor_interface.dart';
|
import 'package:syncrow_app/features/devices/view/widgets/wall_sensor/wall_sensor_interface.dart';
|
||||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||||
@ -22,382 +27,375 @@ import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
|
|||||||
|
|
||||||
class CeilingSensorInterface extends StatelessWidget {
|
class CeilingSensorInterface extends StatelessWidget {
|
||||||
const CeilingSensorInterface({super.key, required this.ceilingSensor});
|
const CeilingSensorInterface({super.key, required this.ceilingSensor});
|
||||||
|
|
||||||
final DeviceModel ceilingSensor;
|
final DeviceModel ceilingSensor;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
// String state = ceilingSensor.status
|
|
||||||
// .firstWhere((element) => element.code == "presence_state")
|
|
||||||
// .value
|
|
||||||
// .toString();
|
|
||||||
|
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (context) =>
|
create: (context) => CeilingSensorBloc(deviceId: ceilingSensor.uuid ?? '')
|
||||||
CeilingSensorBloc(deviceId: ceilingSensor.uuid ?? '')..add(InitialEvent()),
|
..add(InitialEvent()),
|
||||||
child: BlocBuilder<CeilingSensorBloc, CeilingSensorState>(builder: (context, state) {
|
child: BlocBuilder<CeilingSensorBloc, CeilingSensorState>(
|
||||||
CeilingSensorModel ceilingSensorModel = CeilingSensorModel(
|
builder: (context, state) {
|
||||||
presenceState: 'none',
|
final _bloc = BlocProvider.of<CeilingSensorBloc>(context);
|
||||||
sensitivity: 1,
|
|
||||||
checkingResult: '',
|
CeilingSensorModel ceilingSensorModel = _initializeSensorModel(state);
|
||||||
presenceRange: 1,
|
|
||||||
sportsPara: 1,
|
return AnnotatedRegion(
|
||||||
bodyMovement: 'none');
|
value: SystemUiOverlayStyle(
|
||||||
if (state is UpdateState) {
|
statusBarColor: ColorsManager.primaryColor.withOpacity(0.5),
|
||||||
ceilingSensorModel = state.ceilingSensorModel;
|
statusBarIconBrightness: Brightness.light,
|
||||||
} else if (state is LoadingNewSate) {
|
|
||||||
ceilingSensorModel = state.ceilingSensorModel;
|
|
||||||
}
|
|
||||||
return AnnotatedRegion(
|
|
||||||
value: SystemUiOverlayStyle(
|
|
||||||
statusBarColor: ColorsManager.primaryColor.withOpacity(0.5),
|
|
||||||
statusBarIconBrightness: Brightness.light,
|
|
||||||
),
|
|
||||||
child: Scaffold(
|
|
||||||
backgroundColor: ColorsManager.backgroundColor,
|
|
||||||
extendBodyBehindAppBar: true,
|
|
||||||
extendBody: true,
|
|
||||||
appBar: DeviceAppbar(
|
|
||||||
deviceName: ceilingSensor.name!,
|
|
||||||
deviceUuid: ceilingSensor.uuid!,
|
|
||||||
),
|
),
|
||||||
body: Container(
|
child: Scaffold(
|
||||||
width: MediaQuery.sizeOf(context).width,
|
backgroundColor: ColorsManager.backgroundColor,
|
||||||
height: MediaQuery.sizeOf(context).height,
|
extendBodyBehindAppBar: true,
|
||||||
padding: const EdgeInsets.all(Constants.defaultPadding),
|
extendBody: true,
|
||||||
decoration: const BoxDecoration(
|
appBar: DeviceAppbar(
|
||||||
image: DecorationImage(
|
deviceName: ceilingSensor.name!,
|
||||||
image: AssetImage(
|
deviceUuid: ceilingSensor.uuid!,
|
||||||
Assets.assetsImagesBackground,
|
),
|
||||||
),
|
body: _buildBody(context, state, _bloc, ceilingSensorModel),
|
||||||
fit: BoxFit.cover,
|
),
|
||||||
opacity: 0.4,
|
);
|
||||||
),
|
},
|
||||||
),
|
),
|
||||||
child: state is LoadingInitialState
|
|
||||||
? const Center(
|
|
||||||
child: RefreshProgressIndicator(),
|
|
||||||
)
|
|
||||||
: SafeArea(
|
|
||||||
child: RefreshIndicator(
|
|
||||||
onRefresh: () async {
|
|
||||||
BlocProvider.of<CeilingSensorBloc>(context).add(InitialEvent());
|
|
||||||
},
|
|
||||||
child: Container(
|
|
||||||
child: ListView(
|
|
||||||
shrinkWrap: true,
|
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
height: MediaQuery.of(context).size.height,
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
// InkWell(
|
|
||||||
// onTap: () {
|
|
||||||
// if ((ceilingSensor.isOnline ?? false) == false) {
|
|
||||||
// ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
// const SnackBar(
|
|
||||||
// content: Text(
|
|
||||||
// 'Device is offline',
|
|
||||||
// ),
|
|
||||||
// backgroundColor: Colors.red,
|
|
||||||
// ),
|
|
||||||
// );
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// String controlCode = 'sensitivity';
|
|
||||||
// showDialog(
|
|
||||||
// context: context,
|
|
||||||
// builder: (context) => ParameterControlDialog(
|
|
||||||
// title: 'Sensitivity',
|
|
||||||
// sensor: ceilingSensor,
|
|
||||||
// controlCode: controlCode,
|
|
||||||
// value: ceilingSensor.status
|
|
||||||
// .firstWhere((element) => element.code == controlCode)
|
|
||||||
// .value as int,
|
|
||||||
// min: ceilingSensor.functions
|
|
||||||
// .firstWhere((element) => element.code == controlCode)
|
|
||||||
// .values
|
|
||||||
// ?.min ??
|
|
||||||
// 0,
|
|
||||||
// max: ceilingSensor.functions
|
|
||||||
// .firstWhere((element) => element.code == controlCode)
|
|
||||||
// .values
|
|
||||||
// ?.max ??
|
|
||||||
// 0,
|
|
||||||
// ),
|
|
||||||
// );
|
|
||||||
// },
|
|
||||||
// child:
|
|
||||||
// ),
|
|
||||||
|
|
||||||
SvgPicture.asset(
|
|
||||||
ceilingSensorModel.presenceState.toLowerCase() ==
|
|
||||||
'motion'
|
|
||||||
? Assets
|
|
||||||
.assetsIconsPresenceSensorAssetsPresenceSensorMotion
|
|
||||||
: Assets.assetsIconsPresenceSensorAssetsPresence,
|
|
||||||
width: 100,
|
|
||||||
height: 100,
|
|
||||||
// colorFilter: ColorFilter.mode(
|
|
||||||
// (ceilingSensor.isOnline ?? false)
|
|
||||||
// ? ColorsManager.primaryColor
|
|
||||||
// : Colors.grey.withOpacity(0.9),
|
|
||||||
// BlendMode.srcIn,
|
|
||||||
// ),
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
height: 10,
|
|
||||||
),
|
|
||||||
BodyMedium(
|
|
||||||
text: StringHelpers.toTitleCase(
|
|
||||||
ceilingSensorModel.presenceState),
|
|
||||||
// (ceilingSensor.isOnline ?? false)
|
|
||||||
// ? StringHelpers.toTitleCase(ceilingSensor.status
|
|
||||||
// .firstWhere((element) =>
|
|
||||||
// element.code == 'presence_state')
|
|
||||||
// .value
|
|
||||||
// .toString())
|
|
||||||
// : "Offline",
|
|
||||||
style: context.bodyMedium.copyWith(
|
|
||||||
fontWeight: FontsManager.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
flex: 3,
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
DefaultContainer(
|
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
vertical: 20,
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
Flexible(
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
const BodySmall(text: 'Sports Para'),
|
|
||||||
BodyLarge(
|
|
||||||
text: ceilingSensorModel.sportsPara
|
|
||||||
.toString(),
|
|
||||||
style: context.bodyLarge.copyWith(
|
|
||||||
fontWeight: FontsManager.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding:
|
|
||||||
const EdgeInsets.symmetric(horizontal: 10),
|
|
||||||
child: Container(
|
|
||||||
width: 1,
|
|
||||||
height: 45,
|
|
||||||
color: ColorsManager.greyColor,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Flexible(
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
const BodySmall(
|
|
||||||
text: 'Detection Range',
|
|
||||||
textOverflow: TextOverflow.ellipsis,
|
|
||||||
),
|
|
||||||
BodyLarge(
|
|
||||||
text:
|
|
||||||
'${ceilingSensorModel.presenceRange}M',
|
|
||||||
textOverflow: TextOverflow.ellipsis,
|
|
||||||
style: context.bodyLarge.copyWith(
|
|
||||||
fontWeight: FontsManager.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding:
|
|
||||||
const EdgeInsets.symmetric(horizontal: 10),
|
|
||||||
child: Container(
|
|
||||||
width: 1,
|
|
||||||
height: 45,
|
|
||||||
color: ColorsManager.greyColor,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Flexible(
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
const BodySmall(
|
|
||||||
text: 'Movement',
|
|
||||||
textOverflow: TextOverflow.ellipsis,
|
|
||||||
),
|
|
||||||
BodyLarge(
|
|
||||||
text: ceilingSensorModel.bodyMovement,
|
|
||||||
textOverflow: TextOverflow.ellipsis,
|
|
||||||
style: context.bodyLarge.copyWith(
|
|
||||||
fontWeight: FontsManager.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)),
|
|
||||||
const SizedBox(
|
|
||||||
height: 15,
|
|
||||||
),
|
|
||||||
for (int index = 0;
|
|
||||||
index < ceilingSensorButtons().length;
|
|
||||||
index++)
|
|
||||||
DefaultContainer(
|
|
||||||
margin: const EdgeInsets.only(bottom: 5),
|
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
vertical: 12, horizontal: 20),
|
|
||||||
onTap: () async {
|
|
||||||
if (ceilingSensorButtons()[index]['title'] ==
|
|
||||||
'Sensitivity') {
|
|
||||||
final result = await showDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (context) {
|
|
||||||
return ParameterControlDialog(
|
|
||||||
title: ceilingSensorButtons()[index]
|
|
||||||
['title']
|
|
||||||
.toString(),
|
|
||||||
sensor: ceilingSensor,
|
|
||||||
value: ceilingSensorModel.sensitivity,
|
|
||||||
min: 0,
|
|
||||||
max: 10,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
if (result != null) {
|
|
||||||
BlocProvider.of<CeilingSensorBloc>(context).add(
|
|
||||||
ChangeValueEvent(
|
|
||||||
value: result, code: 'sensitivity'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if (ceilingSensorButtons[index]['page'] != null) {
|
|
||||||
// Navigator.push(
|
|
||||||
// context,
|
|
||||||
// MaterialPageRoute(
|
|
||||||
// builder: (context) =>
|
|
||||||
// ceilingSensorButtons[index]['page'] as Widget,
|
|
||||||
// ),
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
},
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
SvgPicture.asset(
|
|
||||||
ceilingSensorButtons()[index]['icon']
|
|
||||||
as String,
|
|
||||||
// width: 30,
|
|
||||||
// height: 50,
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
width: 25,
|
|
||||||
),
|
|
||||||
BodyMedium(
|
|
||||||
text: ceilingSensorButtons()[index]['title']
|
|
||||||
as String,
|
|
||||||
style: context.bodyMedium.copyWith(
|
|
||||||
fontWeight: FontsManager.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
if (ceilingSensorButtons()[index]['withArrow'] ==
|
|
||||||
true)
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
|
||||||
children: [
|
|
||||||
Text(ceilingSensorButtons(
|
|
||||||
sensitivity_val: ceilingSensorModel
|
|
||||||
.sensitivity
|
|
||||||
.toString())[index]['val']
|
|
||||||
.toString()),
|
|
||||||
const Icon(
|
|
||||||
Icons.arrow_forward_ios,
|
|
||||||
color: ColorsManager.greyColor,
|
|
||||||
size: 15,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
))),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
dynamic ceilingSensorButtons({
|
CeilingSensorModel _initializeSensorModel(CeilingSensorState state) {
|
||||||
sensitivity_val = 0,
|
CeilingSensorModel ceilingSensorModel = CeilingSensorModel(
|
||||||
|
spaceType: SpaceTypes.none,
|
||||||
|
nobodyTime: '',
|
||||||
|
movingMaxDis: 0,
|
||||||
|
presenceState: 'none',
|
||||||
|
sensitivity: 1,
|
||||||
|
checkingResult: '',
|
||||||
|
presenceRange: 1,
|
||||||
|
sportsPara: 1,
|
||||||
|
bodyMovement: 'none',
|
||||||
|
);
|
||||||
|
|
||||||
|
if (state is UpdateState) {
|
||||||
|
ceilingSensorModel = state.ceilingSensorModel;
|
||||||
|
} else if (state is LoadingNewSate) {
|
||||||
|
ceilingSensorModel = state.ceilingSensorModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ceilingSensorModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildBody(BuildContext context, CeilingSensorState state,
|
||||||
|
CeilingSensorBloc bloc, CeilingSensorModel model) {
|
||||||
|
return Container(
|
||||||
|
width: MediaQuery.sizeOf(context).width,
|
||||||
|
height: MediaQuery.sizeOf(context).height,
|
||||||
|
padding: const EdgeInsets.all(Constants.defaultPadding),
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
image: DecorationImage(
|
||||||
|
image: AssetImage(Assets.assetsImagesBackground),
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
opacity: 0.4,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: state is LoadingInitialState
|
||||||
|
? const Center(child: RefreshProgressIndicator())
|
||||||
|
: SafeArea(
|
||||||
|
child: RefreshIndicator(
|
||||||
|
onRefresh: () async => bloc.add(InitialEvent()),
|
||||||
|
child: ListView(
|
||||||
|
shrinkWrap: true,
|
||||||
|
children: [
|
||||||
|
_buildMainContent(context, bloc, model),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildMainContent(
|
||||||
|
BuildContext context, CeilingSensorBloc bloc, CeilingSensorModel model) {
|
||||||
|
return SizedBox(
|
||||||
|
height: MediaQuery.of(context).size.height,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
_buildPresenceDisplay(context, model),
|
||||||
|
Expanded(flex: 3, child: _buildControlButtons(context, bloc, model)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildPresenceDisplay(BuildContext context, CeilingSensorModel model) {
|
||||||
|
return Expanded(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
SvgPicture.asset(
|
||||||
|
model.presenceState.toLowerCase() == 'motion'
|
||||||
|
? Assets.assetsIconsPresenceSensorAssetsPresenceSensorMotion
|
||||||
|
: Assets.assetsIconsPresenceSensorAssetsPresence,
|
||||||
|
width: 100,
|
||||||
|
height: 100,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
BodyMedium(
|
||||||
|
text: StringHelpers.toTitleCase(model.presenceState),
|
||||||
|
style: context.bodyMedium.copyWith(fontWeight: FontsManager.bold),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildControlButtons(
|
||||||
|
BuildContext context, CeilingSensorBloc bloc, CeilingSensorModel model) {
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
DefaultContainer(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 20),
|
||||||
|
child: _buildSensorAttributes(context, model),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 15),
|
||||||
|
..._buildActionButtons(context, bloc, model),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildSensorAttributes(
|
||||||
|
BuildContext context, CeilingSensorModel model) {
|
||||||
|
return Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
_buildAttribute(context, 'Sports Para', model.sportsPara.toString()),
|
||||||
|
_divider(),
|
||||||
|
_buildAttribute(context, 'Detection Range', '${model.presenceRange}M'),
|
||||||
|
_divider(),
|
||||||
|
_buildAttribute(context, 'Movement', model.bodyMovement),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildAttribute(BuildContext context, String label, String value) {
|
||||||
|
return Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
BodySmall(
|
||||||
|
text: label,
|
||||||
|
),
|
||||||
|
BodyLarge(
|
||||||
|
text: value,
|
||||||
|
style: context.bodyLarge.copyWith(
|
||||||
|
fontWeight: FontsManager.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _divider() {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 10),
|
||||||
|
child: Container(width: 1, height: 45, color: ColorsManager.greyColor),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Widget> _buildActionButtons(
|
||||||
|
BuildContext context, CeilingSensorBloc bloc, CeilingSensorModel model) {
|
||||||
|
return ceilingSensorButtons().map((button) {
|
||||||
|
return DefaultContainer(
|
||||||
|
margin: const EdgeInsets.only(bottom: 5),
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 20),
|
||||||
|
onTap: () => _handleButtonTap(context, bloc, button, model),
|
||||||
|
child: _buildButtonContent(context, button, model),
|
||||||
|
);
|
||||||
|
}).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildButtonContent(BuildContext context, Map<String, dynamic> button,
|
||||||
|
CeilingSensorModel model) {
|
||||||
|
return Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
SvgPicture.asset(button['icon'] as String),
|
||||||
|
const SizedBox(width: 25),
|
||||||
|
BodyMedium(
|
||||||
|
text: button['title'] as String,
|
||||||
|
style: context.bodyMedium.copyWith(fontWeight: FontsManager.bold),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
if (button['withArrow'] == true)
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
if (button['title'] == 'Sensitivity') ...[
|
||||||
|
Text(
|
||||||
|
model.sensitivity.toString(),
|
||||||
|
style: const TextStyle(color: Colors.black),
|
||||||
|
),
|
||||||
|
] else if (button['title'] == 'Maximum Distance') ...[
|
||||||
|
Text(
|
||||||
|
model.movingMaxDis.toString(),
|
||||||
|
style: const TextStyle(color: Colors.black),
|
||||||
|
),
|
||||||
|
const Text(
|
||||||
|
"m",
|
||||||
|
style: TextStyle(color: ColorsManager.greyColor),
|
||||||
|
),
|
||||||
|
] else if (button['title'] == 'Nobody Time') ...[
|
||||||
|
Text(
|
||||||
|
model.nobodyTime.toString(),
|
||||||
|
style: const TextStyle(color: Colors.black),
|
||||||
|
),
|
||||||
|
] else if (button['title'] == 'Space Type') ...[
|
||||||
|
Text(
|
||||||
|
model.spaceType.name.toString(),
|
||||||
|
style: const TextStyle(color: Colors.black),
|
||||||
|
),
|
||||||
|
] else ...[
|
||||||
|
Text(
|
||||||
|
button['val'].toString(),
|
||||||
|
style: const TextStyle(color: Colors.black),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
const Icon(
|
||||||
|
Icons.arrow_forward_ios,
|
||||||
|
color: ColorsManager.greyColor,
|
||||||
|
size: 15,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _handleButtonTap(BuildContext context, CeilingSensorBloc bloc,
|
||||||
|
Map<String, dynamic> button, CeilingSensorModel model) async {
|
||||||
|
final title = button['title'];
|
||||||
|
if (title == 'Space Type') {
|
||||||
|
final result = await _showDialog(
|
||||||
|
context,
|
||||||
|
PresenceSpaceTypeDialog(
|
||||||
|
description: 'Space Type',
|
||||||
|
onSpaceTypeSelected: (spaceType) {
|
||||||
|
bloc.add(ChangeValueEvent(
|
||||||
|
type: title.toString(), value: spaceType.name, code: 'scene'));
|
||||||
|
},
|
||||||
|
selectedSpaceType: model.spaceType,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else if (title == 'Nobody Time') {
|
||||||
|
final result = await _showDialog(
|
||||||
|
context,
|
||||||
|
MaxDistanceControl(
|
||||||
|
title: title.toString(),
|
||||||
|
sensor: ceilingSensor,
|
||||||
|
value: model.nobodyTime,
|
||||||
|
min: 0.0,
|
||||||
|
max: 5.0,
|
||||||
|
measurement: '',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
if (result != null) {
|
||||||
|
bloc.add(ChangeValueEvent(
|
||||||
|
type: title.toString(), value: result, code: 'nobody_time'));
|
||||||
|
}
|
||||||
|
} else if (title == 'Maximum Distance') {
|
||||||
|
final result = await _showDialog(
|
||||||
|
context,
|
||||||
|
DoubleParameterControl(
|
||||||
|
title: title.toString(),
|
||||||
|
sensor: ceilingSensor,
|
||||||
|
value: model.movingMaxDis,
|
||||||
|
min: 0,
|
||||||
|
max: 500,
|
||||||
|
measurement: 'm',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
if (result != null) {
|
||||||
|
bloc.add(ChangeValueEvent(
|
||||||
|
type: title.toString(), value: result, code: 'moving_max_dis'));
|
||||||
|
}
|
||||||
|
} else if (title == 'Sensitivity') {
|
||||||
|
final result = await _showDialog(
|
||||||
|
context,
|
||||||
|
ParameterControlDialog(
|
||||||
|
title: title.toString(),
|
||||||
|
sensor: ceilingSensor,
|
||||||
|
value: model.sensitivity,
|
||||||
|
min: 0,
|
||||||
|
max: 10,
|
||||||
|
));
|
||||||
|
if (result != null) {
|
||||||
|
bloc.add(ChangeValueEvent(
|
||||||
|
type: title.toString(), value: result, code: 'sensitivity'));
|
||||||
|
}
|
||||||
|
} else if (title == 'Help Description') {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(builder: (context) => const CeilingHelpDescription()),
|
||||||
|
);
|
||||||
|
} else if (title == 'Induction History') {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => PresenceRecord(uuid: ceilingSensor.uuid!)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<dynamic> _showDialog(BuildContext context, Widget dialog) {
|
||||||
|
return showDialog(context: context, builder: (context) => dialog);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Map<String, dynamic>> ceilingSensorButtons({
|
||||||
|
sensitivityVal = 0,
|
||||||
spaceType = 'Office',
|
spaceType = 'Office',
|
||||||
maximumDistanceVal = '3.9m',
|
maximumDistanceVal = '3.9m',
|
||||||
nobodyTimeVal = '1hr',
|
nobodyTimeVal = '1hr',
|
||||||
}) =>
|
}) {
|
||||||
[
|
return [
|
||||||
{
|
{
|
||||||
'title': 'Space Type',
|
'title': 'Space Type',
|
||||||
'icon': Assets.spaceTypeIcon,
|
'icon': Assets.spaceTypeIcon,
|
||||||
'page': null,
|
'page': null,
|
||||||
'withArrow': true,
|
'withArrow': true,
|
||||||
'val': spaceType
|
'val': spaceType,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'title': 'Sensitivity',
|
'title': 'Sensitivity',
|
||||||
'icon': Assets.sensitivityIcon,
|
'icon': Assets.sensitivityIcon,
|
||||||
'page': null,
|
'page': null,
|
||||||
'withArrow': true,
|
'withArrow': true,
|
||||||
'val': sensitivity_val
|
'val': sensitivityVal,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'title': 'Maximum Distance',
|
'title': 'Maximum Distance',
|
||||||
'icon': Assets.maximumDistanceIcon,
|
'icon': Assets.maximumDistanceIcon,
|
||||||
'page': null,
|
'page': null,
|
||||||
'withArrow': true,
|
'withArrow': true,
|
||||||
'val': maximumDistanceVal,
|
'val': maximumDistanceVal,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'title': 'Nobody Time',
|
'title': 'Nobody Time',
|
||||||
'icon': Assets.assetsIconsPresenceSensorAssetsEmpty,
|
'icon': Assets.assetsIconsPresenceSensorAssetsEmpty,
|
||||||
'page': null,
|
'page': null,
|
||||||
'withArrow': true,
|
'withArrow': true,
|
||||||
'val': nobodyTimeVal,
|
'val': nobodyTimeVal,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'title': 'Induction History',
|
'title': 'Induction History',
|
||||||
'icon': Assets.assetsIconsPresenceSensorAssetsInductionRecording,
|
'icon': Assets.assetsIconsPresenceSensorAssetsInductionRecording,
|
||||||
'page': null,
|
'page': null,
|
||||||
'withArrow': false,
|
'withArrow': false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'title': 'Help Description',
|
'title': 'Help Description',
|
||||||
'icon': Assets.assetsIconsPresenceSensorAssetsHelpDescription,
|
'icon': Assets.assetsIconsPresenceSensorAssetsHelpDescription,
|
||||||
'page': null,
|
'page': null,
|
||||||
'withArrow': false,
|
'withArrow': false,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,201 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/title_medium.dart';
|
||||||
|
import 'package:syncrow_app/utils/context_extension.dart';
|
||||||
|
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
|
||||||
|
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||||
|
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
|
||||||
|
|
||||||
|
class DoubleParameterControl extends StatefulWidget {
|
||||||
|
final String title;
|
||||||
|
final String measurement;
|
||||||
|
final DeviceModel sensor;
|
||||||
|
final int value;
|
||||||
|
final int min;
|
||||||
|
final int max;
|
||||||
|
|
||||||
|
const DoubleParameterControl({
|
||||||
|
super.key,
|
||||||
|
required this.title,
|
||||||
|
required this.measurement,
|
||||||
|
required this.sensor,
|
||||||
|
required this.value,
|
||||||
|
required this.min,
|
||||||
|
required this.max,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
DoubleParameterControlState createState() => DoubleParameterControlState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class DoubleParameterControlState extends State<DoubleParameterControl> {
|
||||||
|
late int _value;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_value = widget.value.clamp(widget.min, widget.max);
|
||||||
|
}
|
||||||
|
|
||||||
|
int? _getDivisions(int min, int max, int step) {
|
||||||
|
final range = max - min;
|
||||||
|
final divisions = (range / step).floor();
|
||||||
|
return divisions > 0 ? divisions : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Dialog(
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(20),
|
||||||
|
),
|
||||||
|
padding: const EdgeInsets.only(top: 20),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
BodyMedium(
|
||||||
|
text: widget.title,
|
||||||
|
style: context.bodyMedium.copyWith(
|
||||||
|
color: ColorsManager.primaryColorWithOpacity,
|
||||||
|
fontWeight: FontsManager.extraBold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 15,
|
||||||
|
horizontal: 50,
|
||||||
|
),
|
||||||
|
child: Container(
|
||||||
|
height: 1,
|
||||||
|
width: double.infinity,
|
||||||
|
color: ColorsManager.greyColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 10,
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
TitleMedium(
|
||||||
|
text: _value.toStringAsFixed(0),
|
||||||
|
style: context.titleMedium.copyWith(
|
||||||
|
color: Colors.black,
|
||||||
|
fontWeight: FontsManager.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TitleMedium(
|
||||||
|
text: widget.measurement.toString(),
|
||||||
|
style: context.titleMedium.copyWith(
|
||||||
|
color: Colors.black,
|
||||||
|
fontWeight: FontsManager.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: MediaQuery.sizeOf(context).width,
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
setState(() {
|
||||||
|
_value = (_value - 50).clamp(widget.min, widget.max);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
icon: const Icon(
|
||||||
|
Icons.remove,
|
||||||
|
color: Colors.grey,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Flexible(
|
||||||
|
child: Slider(
|
||||||
|
value: _value.toDouble(),
|
||||||
|
min: widget.min.toDouble(),
|
||||||
|
max: widget.max.toDouble(),
|
||||||
|
divisions: _getDivisions(
|
||||||
|
widget.min, widget.max, 50),
|
||||||
|
onChanged: (value) {
|
||||||
|
setState(() {
|
||||||
|
_value =
|
||||||
|
value.round();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
label: _value.toStringAsFixed(0),
|
||||||
|
inactiveColor: ColorsManager.greyColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
setState(() {
|
||||||
|
_value = (_value + 50).clamp(widget.min, widget.max);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
icon: const Icon(
|
||||||
|
Icons.add,
|
||||||
|
color: Colors.grey,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
height: 1,
|
||||||
|
width: double.infinity,
|
||||||
|
color: ColorsManager.greyColor,
|
||||||
|
),
|
||||||
|
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, _value);
|
||||||
|
if (widget.sensor.isOnline == null) {
|
||||||
|
CustomSnackBar.displaySnackBar('The device is offline');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!widget.sensor.isOnline!) {
|
||||||
|
CustomSnackBar.displaySnackBar('The device is offline');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Center(
|
||||||
|
child: BodyMedium(
|
||||||
|
text: 'Confirm',
|
||||||
|
style: context.bodyMedium.copyWith(
|
||||||
|
color: ColorsManager.primaryColorWithOpacity),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,248 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/device_model.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/title_medium.dart';
|
||||||
|
import 'package:syncrow_app/utils/context_extension.dart';
|
||||||
|
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
|
||||||
|
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||||
|
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
|
||||||
|
|
||||||
|
class MaxDistanceControl extends StatefulWidget {
|
||||||
|
final String title;
|
||||||
|
final String measurement;
|
||||||
|
final DeviceModel sensor;
|
||||||
|
final String value;
|
||||||
|
|
||||||
|
final double min;
|
||||||
|
final double max;
|
||||||
|
|
||||||
|
const MaxDistanceControl({
|
||||||
|
super.key,
|
||||||
|
required this.title,
|
||||||
|
required this.measurement,
|
||||||
|
required this.sensor,
|
||||||
|
required this.value,
|
||||||
|
required this.min,
|
||||||
|
required this.max,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
MaxDistanceControlState createState() => MaxDistanceControlState();
|
||||||
|
}
|
||||||
|
|
||||||
|
int _parseValue(String value) {
|
||||||
|
if (value.endsWith('sec')) {
|
||||||
|
return int.parse(value.replaceAll('sec', '').trim());
|
||||||
|
} else if (value.endsWith('min')) {
|
||||||
|
return int.parse(value.replaceAll('min', '').trim()) * 60;
|
||||||
|
} else if (value.endsWith('hr')) {
|
||||||
|
return int.parse(value.replaceAll('hr', '').trim()) * 3600;
|
||||||
|
}
|
||||||
|
return 0; // Default to 0 if the format is unrecognized
|
||||||
|
}
|
||||||
|
|
||||||
|
class MaxDistanceControlState extends State<MaxDistanceControl> {
|
||||||
|
final List<double> _stepValues = [
|
||||||
|
0,
|
||||||
|
10,
|
||||||
|
30,
|
||||||
|
60,
|
||||||
|
120,
|
||||||
|
300,
|
||||||
|
600,
|
||||||
|
1800,
|
||||||
|
3600,
|
||||||
|
];
|
||||||
|
|
||||||
|
late int _currentIndex;
|
||||||
|
|
||||||
|
String _formatLabel(double seconds) {
|
||||||
|
if (seconds == 0) return 'None';
|
||||||
|
if (seconds < 60) return '${seconds.toInt()}sec';
|
||||||
|
if (seconds < 3600) {
|
||||||
|
final minutes = (seconds / 60).round();
|
||||||
|
return '${minutes}min';
|
||||||
|
}
|
||||||
|
final hours = (seconds / 3600).round();
|
||||||
|
return '${hours}hr';
|
||||||
|
}
|
||||||
|
|
||||||
|
int _nearestStepIndex(double initialValue) {
|
||||||
|
double minDiff = double.infinity;
|
||||||
|
int nearestIndex = 0;
|
||||||
|
for (int i = 0; i < _stepValues.length; i++) {
|
||||||
|
final diff = (initialValue - _stepValues[i]).abs();
|
||||||
|
if (diff < minDiff) {
|
||||||
|
minDiff = diff;
|
||||||
|
nearestIndex = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nearestIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
final int parsedSeconds = _parseValue(widget.value);
|
||||||
|
_currentIndex = _nearestStepIndex(parsedSeconds.toDouble());
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final double currentSeconds = _stepValues[_currentIndex];
|
||||||
|
|
||||||
|
return Dialog(
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(20),
|
||||||
|
),
|
||||||
|
padding: const EdgeInsets.only(top: 20),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
BodyMedium(
|
||||||
|
text: widget.title,
|
||||||
|
style: context.bodyMedium.copyWith(
|
||||||
|
color: ColorsManager.primaryColorWithOpacity,
|
||||||
|
fontWeight: FontsManager.extraBold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 15,
|
||||||
|
horizontal: 50,
|
||||||
|
),
|
||||||
|
child: Container(
|
||||||
|
height: 1,
|
||||||
|
width: double.infinity,
|
||||||
|
color: ColorsManager.greyColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 10,
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
TitleMedium(
|
||||||
|
text: _formatLabel(currentSeconds),
|
||||||
|
style: context.titleMedium.copyWith(
|
||||||
|
color: Colors.black,
|
||||||
|
fontWeight: FontsManager.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 5),
|
||||||
|
TitleMedium(
|
||||||
|
text: widget.measurement,
|
||||||
|
style: context.titleMedium.copyWith(
|
||||||
|
color: Colors.black,
|
||||||
|
fontWeight: FontsManager.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: MediaQuery.sizeOf(context).width,
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
setState(() {
|
||||||
|
_currentIndex =
|
||||||
|
(_currentIndex > 0) ? _currentIndex - 1 : 0;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
icon: const Icon(
|
||||||
|
Icons.remove,
|
||||||
|
color: Colors.grey,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Flexible(
|
||||||
|
child: Slider(
|
||||||
|
min: 0,
|
||||||
|
max: (_stepValues.length - 1).toDouble(),
|
||||||
|
divisions: _stepValues.length - 1,
|
||||||
|
value: _currentIndex.toDouble(),
|
||||||
|
onChanged: (double newIndex) {
|
||||||
|
setState(() {
|
||||||
|
_currentIndex = newIndex.round();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
label: _formatLabel(_stepValues[_currentIndex]),
|
||||||
|
inactiveColor: ColorsManager.greyColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
setState(() {
|
||||||
|
_currentIndex = (_currentIndex < _stepValues.length - 1)
|
||||||
|
? _currentIndex + 1
|
||||||
|
: _currentIndex;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
icon: const Icon(
|
||||||
|
Icons.add,
|
||||||
|
color: Colors.grey,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
height: 1,
|
||||||
|
width: double.infinity,
|
||||||
|
color: ColorsManager.greyColor,
|
||||||
|
),
|
||||||
|
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: () {
|
||||||
|
Future.delayed(const Duration(seconds: 1), () {
|
||||||
|
Navigator.pop(context, _formatLabel(currentSeconds));
|
||||||
|
|
||||||
|
if (widget.sensor.isOnline == null ||
|
||||||
|
widget.sensor.isOnline == false) {
|
||||||
|
CustomSnackBar.displaySnackBar('The device is offline');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: Center(
|
||||||
|
child: BodyMedium(
|
||||||
|
text: 'Confirm',
|
||||||
|
style: context.bodyMedium.copyWith(
|
||||||
|
color: ColorsManager.primaryColorWithOpacity,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,120 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/ceiling_bloc/ceiling_sensor_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/ceiling_bloc/ceiling_sensor_event.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/bloc/ceiling_bloc/ceiling_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 PresenceRecord extends StatelessWidget {
|
||||||
|
final String uuid;
|
||||||
|
const PresenceRecord({super.key, required this.uuid});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return DefaultScaffold(
|
||||||
|
title: 'Presence Record',
|
||||||
|
child: BlocProvider(
|
||||||
|
create: (context) =>
|
||||||
|
CeilingSensorBloc(deviceId: uuid)..add(const ReportLogsInitial()),
|
||||||
|
child: BlocBuilder<CeilingSensorBloc, CeilingSensorState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
final garageDoorBloc = BlocProvider.of<CeilingSensorBloc>(context);
|
||||||
|
final Map<String, List<DeviceEvent>> groupedRecords = {};
|
||||||
|
|
||||||
|
if (state is LoadingInitialState) {
|
||||||
|
return const Center(
|
||||||
|
child: DefaultContainer(
|
||||||
|
width: 50, height: 50, child: CircularProgressIndicator()),
|
||||||
|
);
|
||||||
|
} else if (state is UpdateState) {
|
||||||
|
for (var record in garageDoorBloc.recordGroups.data!) {
|
||||||
|
final DateTime eventDateTime =
|
||||||
|
DateTime.fromMillisecondsSinceEpoch(record.eventTime!);
|
||||||
|
final String formattedDate =
|
||||||
|
DateFormat('EEEE, dd/MM/yyyy').format(eventDateTime);
|
||||||
|
if (groupedRecords.containsKey(formattedDate)) {
|
||||||
|
groupedRecords[formattedDate]!.add(record);
|
||||||
|
} else {
|
||||||
|
groupedRecords[formattedDate] = [record];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 5, top: 10),
|
||||||
|
child: Text(
|
||||||
|
date,
|
||||||
|
style: const TextStyle(
|
||||||
|
color: ColorsManager.grayColor,
|
||||||
|
fontSize: 13,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
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'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (idx != recordsForDate.length - 1)
|
||||||
|
const Divider(
|
||||||
|
color: ColorsManager.graysColor,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,181 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
import 'package:syncrow_app/features/devices/model/ceiling_sensor_model.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/context_extension.dart';
|
||||||
|
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||||
|
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
|
||||||
|
|
||||||
|
class PresenceSpaceTypeDialog extends StatefulWidget {
|
||||||
|
final String description;
|
||||||
|
final SpaceTypes selectedSpaceType;
|
||||||
|
final void Function(SpaceTypes spaceType) onSpaceTypeSelected;
|
||||||
|
|
||||||
|
const PresenceSpaceTypeDialog({
|
||||||
|
super.key,
|
||||||
|
required this.description,
|
||||||
|
required this.selectedSpaceType,
|
||||||
|
required this.onSpaceTypeSelected,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
_PresenceSpaceTypeDialogState createState() =>
|
||||||
|
_PresenceSpaceTypeDialogState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _PresenceSpaceTypeDialogState extends State<PresenceSpaceTypeDialog> {
|
||||||
|
late SpaceTypes _selectedSpaceType;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_selectedSpaceType = widget.selectedSpaceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final Map<SpaceTypes, String> spaceTypeIcons = {
|
||||||
|
SpaceTypes.none: Assets.office,
|
||||||
|
SpaceTypes.parlour: Assets.parlour,
|
||||||
|
SpaceTypes.area: Assets.dyi,
|
||||||
|
SpaceTypes.toilet: Assets.bathroom,
|
||||||
|
SpaceTypes.bedroom: Assets.bedroom,
|
||||||
|
};
|
||||||
|
|
||||||
|
final Map<SpaceTypes, String> spaceTypeTitles = {
|
||||||
|
SpaceTypes.none: 'None',
|
||||||
|
SpaceTypes.parlour: 'Parlour',
|
||||||
|
SpaceTypes.area: 'Area',
|
||||||
|
SpaceTypes.toilet: 'Toilet',
|
||||||
|
SpaceTypes.bedroom: 'Bedroom',
|
||||||
|
};
|
||||||
|
|
||||||
|
return Dialog(
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(20),
|
||||||
|
),
|
||||||
|
child: Container(
|
||||||
|
// padding: const EdgeInsets.all(20),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: Text(
|
||||||
|
widget.description,
|
||||||
|
style: context.bodyMedium.copyWith(
|
||||||
|
color: ColorsManager.primaryColorWithOpacity,
|
||||||
|
fontWeight: FontsManager.extraBold,
|
||||||
|
fontSize: 16),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
height: 1,
|
||||||
|
width: double.infinity,
|
||||||
|
color: ColorsManager.greyColor,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
Wrap(
|
||||||
|
runSpacing: 12,
|
||||||
|
spacing: 16,
|
||||||
|
children: spaceTypeIcons.entries.map((entry) {
|
||||||
|
final spaceType = entry.key;
|
||||||
|
final icon = entry.value;
|
||||||
|
final title = spaceTypeTitles[spaceType]!;
|
||||||
|
return Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(25),
|
||||||
|
color: _selectedSpaceType == spaceType
|
||||||
|
? ColorsManager.primaryColorWithOpacity
|
||||||
|
: ColorsManager.textGray,
|
||||||
|
),
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
setState(() {
|
||||||
|
_selectedSpaceType = spaceType;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 10, right: 10),
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.all(10),
|
||||||
|
child: SvgPicture.asset(
|
||||||
|
icon,
|
||||||
|
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
Text(
|
||||||
|
title,
|
||||||
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodySmall
|
||||||
|
?.copyWith(
|
||||||
|
color: _selectedSpaceType == spaceType
|
||||||
|
? ColorsManager.onPrimaryColor
|
||||||
|
: ColorsManager.blackColor,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
fontSize: 15),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
|
||||||
|
Container(
|
||||||
|
height: 1,
|
||||||
|
width: double.infinity,
|
||||||
|
color: ColorsManager.greyColor,
|
||||||
|
),
|
||||||
|
|
||||||
|
/// Cancel / Confirm
|
||||||
|
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: () {
|
||||||
|
widget.onSpaceTypeSelected(_selectedSpaceType);
|
||||||
|
Navigator.pop(context, _selectedSpaceType);
|
||||||
|
},
|
||||||
|
child: Center(
|
||||||
|
child: BodyMedium(
|
||||||
|
text: 'Confirm',
|
||||||
|
style: context.bodyMedium.copyWith(
|
||||||
|
color: ColorsManager.primaryColorWithOpacity,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -195,4 +195,5 @@ class SecurityBloc extends Bloc<SecurityEvent, SecurityState> {
|
|||||||
emit(AuthInitialState());
|
emit(AuthInitialState());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
import 'package:syncrow_app/features/auth/bloc/auth_cubit.dart';
|
import 'package:syncrow_app/features/auth/bloc/auth_cubit.dart';
|
||||||
import 'package:syncrow_app/features/devices/view/device_settings/update_dialog.dart';
|
|
||||||
import 'package:syncrow_app/features/menu/view/widgets/securty/bloc/security_bloc.dart';
|
import 'package:syncrow_app/features/menu/view/widgets/securty/bloc/security_bloc.dart';
|
||||||
import 'package:syncrow_app/features/menu/view/widgets/securty/bloc/security_event.dart';
|
import 'package:syncrow_app/features/menu/view/widgets/securty/bloc/security_event.dart';
|
||||||
import 'package:syncrow_app/features/menu/view/widgets/securty/bloc/security_state.dart';
|
import 'package:syncrow_app/features/menu/view/widgets/securty/bloc/security_state.dart';
|
||||||
@ -18,193 +17,201 @@ class SetPasswordPage extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final _formKey = GlobalKey<FormState>();
|
||||||
|
|
||||||
return BlocProvider<SecurityBloc>(
|
return BlocProvider<SecurityBloc>(
|
||||||
create: (context) => SecurityBloc(),
|
create: (context) => SecurityBloc(),
|
||||||
child: BlocConsumer<SecurityBloc, SecurityState>(
|
child: Form(
|
||||||
listener: (context, state) {
|
key: _formKey,
|
||||||
if (state is SuccessForgetState) {
|
child: BlocConsumer<SecurityBloc, SecurityState>(
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
listener: (context, state) {
|
||||||
const SnackBar(
|
if (state is SuccessForgetState) {
|
||||||
content: Text('Change Password Successfully '),
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
),
|
const SnackBar(
|
||||||
);
|
content: Text('Change Password Successfully '),
|
||||||
Navigator.of(context).pop();
|
|
||||||
}
|
|
||||||
if (state is ChangedPassState) {
|
|
||||||
showDialog(
|
|
||||||
context: context,
|
|
||||||
barrierDismissible: false,
|
|
||||||
builder: (context) {
|
|
||||||
return AlertDialog(
|
|
||||||
contentPadding: EdgeInsets.zero,
|
|
||||||
content: SizedBox(
|
|
||||||
height: MediaQuery.of(context).size.height * 0.2,
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: <Widget>[
|
|
||||||
const SizedBox(
|
|
||||||
height: 10,
|
|
||||||
),
|
|
||||||
BodyLarge(
|
|
||||||
text: 'Password Changed',
|
|
||||||
fontWeight: FontWeight.w700,
|
|
||||||
fontColor:
|
|
||||||
ColorsManager.switchButton.withOpacity(0.6),
|
|
||||||
fontSize: 16,
|
|
||||||
),
|
|
||||||
const Padding(
|
|
||||||
padding: EdgeInsets.only(left: 15, right: 15),
|
|
||||||
child: Divider(
|
|
||||||
color: ColorsManager.textGray,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const Padding(
|
|
||||||
padding: EdgeInsets.only(
|
|
||||||
left: 15, right: 20, top: 15, bottom: 20),
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
Center(
|
|
||||||
child: Text(
|
|
||||||
'Your password has been',
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
)),
|
|
||||||
Center(
|
|
||||||
child: Text(
|
|
||||||
'successfully updated.',
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
)),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Container(
|
|
||||||
decoration: const BoxDecoration(
|
|
||||||
border: Border(
|
|
||||||
left: BorderSide(
|
|
||||||
color: ColorsManager.textGray,
|
|
||||||
width: 0.5,
|
|
||||||
),
|
|
||||||
top: BorderSide(
|
|
||||||
color: ColorsManager.textGray,
|
|
||||||
width: 1.0,
|
|
||||||
),
|
|
||||||
)),
|
|
||||||
child: InkWell(
|
|
||||||
onTap: () {
|
|
||||||
AuthCubit.get(context).logout();
|
|
||||||
},
|
|
||||||
child: Padding(
|
|
||||||
padding:
|
|
||||||
const EdgeInsets.only(top: 15, bottom: 15),
|
|
||||||
child: Center(
|
|
||||||
child: Text(
|
|
||||||
'Done',
|
|
||||||
style: TextStyle(
|
|
||||||
color: ColorsManager.switchButton
|
|
||||||
.withOpacity(0.6),
|
|
||||||
fontSize: 14,
|
|
||||||
fontWeight: FontWeight.w400),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
Navigator.of(context).pop();
|
||||||
);
|
}
|
||||||
}
|
if (state is ChangedPassState) {
|
||||||
}, builder: (context, state) {
|
showDialog(
|
||||||
final _bloc = BlocProvider.of<SecurityBloc>(context);
|
context: context,
|
||||||
|
barrierDismissible: false,
|
||||||
|
builder: (context) {
|
||||||
|
return AlertDialog(
|
||||||
|
contentPadding: EdgeInsets.zero,
|
||||||
|
content: SizedBox(
|
||||||
|
height: MediaQuery.of(context).size.height * 0.2,
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: <Widget>[
|
||||||
|
const SizedBox(
|
||||||
|
height: 10,
|
||||||
|
),
|
||||||
|
BodyLarge(
|
||||||
|
text: 'Password Changed',
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
fontColor:
|
||||||
|
ColorsManager.switchButton.withOpacity(0.6),
|
||||||
|
fontSize: 16,
|
||||||
|
),
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.only(left: 15, right: 15),
|
||||||
|
child: Divider(
|
||||||
|
color: ColorsManager.textGray,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
left: 15, right: 20, top: 15, bottom: 20),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Center(
|
||||||
|
child: Text(
|
||||||
|
'Your password has been',
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
)),
|
||||||
|
Center(
|
||||||
|
child: Text(
|
||||||
|
'successfully updated.',
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Container(
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
border: Border(
|
||||||
|
top: BorderSide(
|
||||||
|
color: ColorsManager.textGray,
|
||||||
|
width: 1.0,
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () {
|
||||||
|
AuthCubit.get(context).logout();
|
||||||
|
},
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
top: 5, bottom: 5),
|
||||||
|
child: Center(
|
||||||
|
child: Text(
|
||||||
|
'Done',
|
||||||
|
style: TextStyle(
|
||||||
|
color: ColorsManager.switchButton
|
||||||
|
.withOpacity(0.6),
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w400),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}, builder: (context, state) {
|
||||||
|
final _bloc = BlocProvider.of<SecurityBloc>(context);
|
||||||
|
|
||||||
return DefaultScaffold(
|
return DefaultScaffold(
|
||||||
title: 'Change Password',
|
title: 'Change Password',
|
||||||
child: ListView(
|
child: ListView(
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
children: [
|
children: [
|
||||||
const SizedBox(height: 55),
|
const SizedBox(height: 55),
|
||||||
const Center(
|
const Center(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: EdgeInsets.all(8.0),
|
padding: EdgeInsets.all(8.0),
|
||||||
child: BodyMedium(
|
child: BodyMedium(
|
||||||
text: 'Set Password',
|
text: 'Set Password',
|
||||||
fontWeight: FontWeight.w700,
|
|
||||||
fontSize: 18,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const Center(
|
|
||||||
child: BodyMedium(
|
|
||||||
text: 'Secure your account with a',
|
|
||||||
fontWeight: FontWeight.w400,
|
|
||||||
fontSize: 16,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 4),
|
|
||||||
const Center(
|
|
||||||
child: BodyMedium(
|
|
||||||
text: 'strong password',
|
|
||||||
fontWeight: FontWeight.w400,
|
|
||||||
fontSize: 14,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 40),
|
|
||||||
BlocBuilder<SecurityBloc, SecurityState>(
|
|
||||||
builder: (context, state) {
|
|
||||||
if (state is PasswordErrorState) {
|
|
||||||
return Center(
|
|
||||||
child: Text(
|
|
||||||
state.error,
|
|
||||||
style: const TextStyle(color: Colors.red),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
} else if (state is PasswordSetState) {
|
|
||||||
return Center(
|
|
||||||
child: Text(
|
|
||||||
state.message,
|
|
||||||
style: const TextStyle(color: Colors.green),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return const SizedBox.shrink();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
PasswordInputField(controller: _bloc.newPassword),
|
|
||||||
const SizedBox(height: 55),
|
|
||||||
InkWell(
|
|
||||||
onTap: () {
|
|
||||||
_bloc.add(ChangePasswordEvent(otpCode: otpCode.toString()));
|
|
||||||
},
|
|
||||||
child: Container(
|
|
||||||
padding: const EdgeInsets.only(
|
|
||||||
right: 20, left: 20, top: 15, bottom: 15),
|
|
||||||
decoration: const BoxDecoration(
|
|
||||||
color: ColorsManager.blueColor,
|
|
||||||
borderRadius: BorderRadius.all(Radius.circular(20)),
|
|
||||||
),
|
|
||||||
child: const Center(
|
|
||||||
child: Text(
|
|
||||||
"Done",
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 16,
|
|
||||||
color: Colors.white,
|
|
||||||
fontWeight: FontWeight.w700,
|
fontWeight: FontWeight.w700,
|
||||||
|
fontSize: 18,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
const Center(
|
||||||
)
|
child: BodyMedium(
|
||||||
],
|
text: 'Secure your account with a',
|
||||||
),
|
fontWeight: FontWeight.w400,
|
||||||
);
|
fontSize: 16,
|
||||||
}));
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
const Center(
|
||||||
|
child: BodyMedium(
|
||||||
|
text: 'strong password',
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
fontSize: 14,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 40),
|
||||||
|
BlocBuilder<SecurityBloc, SecurityState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
if (state is PasswordErrorState) {
|
||||||
|
return Center(
|
||||||
|
child: Text(
|
||||||
|
state.error,
|
||||||
|
style: const TextStyle(color: Colors.red),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else if (state is PasswordSetState) {
|
||||||
|
return Center(
|
||||||
|
child: Text(
|
||||||
|
state.message,
|
||||||
|
style: const TextStyle(color: Colors.green),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return const SizedBox.shrink();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
PasswordInputField(
|
||||||
|
controller: _bloc.newPassword,
|
||||||
|
validatorl: _bloc.passwordValidator,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 55),
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
if (_formKey.currentState!.validate()) {
|
||||||
|
_bloc.add(
|
||||||
|
ChangePasswordEvent(otpCode: otpCode.toString()));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
right: 20, left: 20, top: 15, bottom: 15),
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
color: ColorsManager.blueColor,
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(20)),
|
||||||
|
),
|
||||||
|
child: const Center(
|
||||||
|
child: Text(
|
||||||
|
"Done",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
color: Colors.white,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
})));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class PasswordInputField extends StatelessWidget {
|
class PasswordInputField extends StatelessWidget {
|
||||||
PasswordInputField({this.controller});
|
PasswordInputField({this.controller, this.validatorl});
|
||||||
TextEditingController? controller = TextEditingController();
|
TextEditingController? controller = TextEditingController();
|
||||||
|
String? Function(String?)? validatorl;
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocBuilder<SecurityBloc, SecurityState>(
|
return BlocBuilder<SecurityBloc, SecurityState>(
|
||||||
@ -214,9 +221,10 @@ class PasswordInputField extends StatelessWidget {
|
|||||||
isPasswordVisible = state.isVisible;
|
isPasswordVisible = state.isVisible;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TextField(
|
return TextFormField(
|
||||||
controller: controller,
|
controller: controller,
|
||||||
obscureText: !isPasswordVisible,
|
obscureText: !isPasswordVisible,
|
||||||
|
validator: validatorl,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: 'Password',
|
hintText: 'Password',
|
||||||
suffixIcon: IconButton(
|
suffixIcon: IconButton(
|
||||||
|
@ -1132,4 +1132,11 @@ class Assets {
|
|||||||
"assets/icons/password_unvisibility.svg";
|
"assets/icons/password_unvisibility.svg";
|
||||||
static const String passwordVisibility =
|
static const String passwordVisibility =
|
||||||
"assets/icons/password_visibility.svg";
|
"assets/icons/password_visibility.svg";
|
||||||
|
|
||||||
|
static const String bathroom = 'assets/icons/bathroom.svg';
|
||||||
|
static const String bedroom = 'assets/icons/bedroom.svg';
|
||||||
|
static const String dyi = 'assets/icons/dyi.svg';
|
||||||
|
static const String office = 'assets/icons/office.svg';
|
||||||
|
static const String parlour = 'assets/icons/parlour.svg';
|
||||||
|
static const String grid = 'assets/images/grid.svg';
|
||||||
}
|
}
|
||||||
|
@ -469,14 +469,14 @@ class DevicesAPI {
|
|||||||
required String startTime,
|
required String startTime,
|
||||||
required String endTime,
|
required String endTime,
|
||||||
}) async {
|
}) async {
|
||||||
|
final requestUrl = ApiEndpoints.reportLogs
|
||||||
|
.replaceAll('{deviceUuid}', deviceUuid)
|
||||||
|
.replaceAll('{code}', code)
|
||||||
|
.replaceAll('{startTime}', startTime)
|
||||||
|
.replaceAll('{endTime}', endTime);
|
||||||
final response = await _httpService.get(
|
final response = await _httpService.get(
|
||||||
path: ApiEndpoints.reportLogs
|
path: requestUrl,
|
||||||
.replaceAll('{deviceUuid}', deviceUuid)
|
|
||||||
.replaceAll('{code}', code)
|
|
||||||
.replaceAll('{startTime}', startTime)
|
|
||||||
.replaceAll('{endTime}', endTime),
|
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
log('json=====$json');
|
|
||||||
return DeviceReport.fromJson(json);
|
return DeviceReport.fromJson(json);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
Reference in New Issue
Block a user