Compare commits

..

11 Commits

Author SHA1 Message Date
jahongireshonqulov
2750564b08 feat:browse bloc done 2025-10-25 17:54:59 +05:00
jahongireshonqulov
97aae6e108 feat:browse bloc done 2025-10-25 17:54:56 +05:00
jahongireshonqulov
57af573b6f feat:browse page ui done 2025-10-25 15:29:38 +05:00
jahongireshonqulov
33da49df6c feat: app text form field done 2025-10-25 12:20:00 +05:00
jahongireshonqulov
6a5b4b6e3a feat: Baskets page's loading,loaded state done 2025-10-25 11:38:17 +05:00
jahongireshonqulov
7474a8b677 feat:Order item created 2025-10-24 20:43:08 +05:00
jahongireshonqulov
7e9fbd2cf3 feat:Order item created 2025-10-24 20:43:05 +05:00
jahongireshonqulov
30f190aab9 feat:Baskets empty page ui done 2025-10-24 20:17:59 +05:00
jahongireshonqulov
ffbc153b55 feat:restaurants by category page done 2025-10-24 19:44:52 +05:00
jahongireshonqulov
e0f3d900d7 feat:filters done 2025-10-24 18:06:43 +05:00
jahongireshonqulov
f2ab615b4e feat: filters added to home page 2025-10-24 14:54:08 +05:00
83 changed files with 4764 additions and 106 deletions

View File

@@ -0,0 +1,3 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M18 16.25L14.3335 12.5833C15.2502 11.25 15.8333 9.6667 15.8333 7.9167C15.8333 3.58336 12.25 0 7.91665 0C3.58334 0 0 3.58336 0 7.9167C0 12.25 3.58334 15.8334 7.91665 15.8334C9.66665 15.8334 11.2501 15.25 12.5835 14.3333L16.25 18L18 16.25ZM2.5 8C2.5 5.00001 4.91667 2.58334 7.91665 2.58334C10.9166 2.58334 13.3333 5.00001 13.3333 8C13.3333 11 10.9166 13.4167 7.91665 13.4167C4.91667 13.4167 2.5 11 2.5 8Z" fill="black"/>
</svg>

After

Width:  |  Height:  |  Size: 531 B

View File

@@ -0,0 +1,3 @@
<svg width="9" height="15" viewBox="0 0 9 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 0H2.97391L9 7.5L2.97391 15H0L6.02609 7.5L0 0Z" fill="black"/>
</svg>

After

Width:  |  Height:  |  Size: 175 B

45
assets/icons/ic_carts.svg Normal file
View File

@@ -0,0 +1,45 @@
<svg width="177" height="176" viewBox="0 0 177 176" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_335_2606)">
<path d="M142.479 72.1698C146.691 66.6038 145.596 58.6778 140.032 54.4668C134.468 50.2558 126.542 51.3538 122.329 56.9208L109.553 73.7998C105.34 79.3658 106.436 87.2928 112 91.5038C117.564 95.7148 125.49 94.6158 129.703 89.0498L142.479 72.1698Z" fill="#A0BFF8"/>
<path d="M103.844 42.8671L88.4569 27.4801C87.9393 26.9626 87.2373 26.6719 86.5054 26.6719C85.7735 26.6719 85.0715 26.9626 84.5539 27.4801L69.1679 42.8671C68.6504 43.3847 68.3596 44.0867 68.3596 44.8186C68.3596 45.5506 68.6504 46.2526 69.1679 46.7701L84.5539 62.1571C85.0715 62.6747 85.7735 62.9654 86.5054 62.9654C87.2373 62.9654 87.9393 62.6747 88.4569 62.1571L103.844 46.7701C104.361 46.2526 104.652 45.5506 104.652 44.8186C104.652 44.0867 104.361 43.3847 103.844 42.8671Z" fill="#FFC043"/>
<path d="M95.0098 8.44C96.1291 8.43973 97.2023 7.99487 97.9935 7.20328C98.7848 6.41169 99.2291 5.33821 99.2288 4.219C99.2286 3.09979 98.7837 2.02652 97.9921 1.2353C97.2005 0.444086 96.1271 -0.000265098 95.0078 1.18655e-07C93.8886 1.18655e-07 92.8153 0.444606 92.0238 1.23601C91.2324 2.02741 90.7878 3.10079 90.7878 4.22C90.7878 5.33921 91.2324 6.41259 92.0238 7.20399C92.8153 7.99539 93.8886 8.44 95.0078 8.44H95.0098Z" fill="#05A357"/>
<path d="M106.169 36.6799C110.803 36.6799 114.559 32.9239 114.559 28.2899C114.559 23.6559 110.803 19.8999 106.169 19.8999C103.944 19.8999 101.81 20.7838 100.236 22.3573C98.6628 23.9307 97.7788 26.0647 97.7788 28.2899C97.7788 30.5151 98.6628 32.6491 100.236 34.2225C101.81 35.796 103.944 36.6799 106.169 36.6799Z" fill="#66D19E"/>
<path d="M119.741 121.93H56.3909L46.6309 74.0498H63.4209L126.961 79.5598C127.548 79.5976 128.12 79.7608 128.638 80.0384C129.156 80.3159 129.609 80.7014 129.966 81.1688C130.323 81.6358 130.576 82.1738 130.708 82.7465C130.84 83.3193 130.848 83.9137 130.731 84.4898L123.731 118.64C123.545 119.563 123.047 120.395 122.321 120.994C121.594 121.593 120.683 121.924 119.741 121.93Z" fill="#AB1300"/>
<path d="M133.81 121.93H73.1799L63.4199 74.0498L141.03 79.5598C141.617 79.5976 142.189 79.7608 142.707 80.0384C143.225 80.3159 143.678 80.7014 144.035 81.1688C144.392 81.6358 144.645 82.1738 144.777 82.7465C144.909 83.3193 144.917 83.9137 144.8 84.4898L137.8 118.64C137.614 119.563 137.116 120.395 136.39 120.994C135.663 121.593 134.752 121.924 133.81 121.93Z" fill="#E8503D"/>
<path d="M128.32 102.71C128.971 102.692 129.588 102.416 130.036 101.944C130.484 101.471 130.726 100.841 130.71 100.19V92.8999H125.93V100.19C125.914 100.841 126.157 101.471 126.605 101.943C127.053 102.415 127.669 102.691 128.32 102.71Z" fill="#FFD7D2"/>
<path d="M128.32 85.0698C127.669 85.0881 127.052 85.3637 126.604 85.836C126.156 86.3084 125.914 86.939 125.93 87.5898V92.8998H130.71V87.5898C130.727 86.9387 130.485 86.3075 130.037 85.8349C129.589 85.3623 128.971 85.0871 128.32 85.0698Z" fill="#F1998E"/>
<path d="M81.3898 102.71C82.0406 102.692 82.6575 102.416 83.1055 101.944C83.5535 101.471 83.7959 100.841 83.7798 100.19V92.8999H79.0098V100.19C79.0005 100.512 79.0547 100.832 79.1692 101.133C79.2838 101.434 79.4566 101.709 79.6776 101.943C79.8986 102.177 80.1636 102.365 80.4574 102.497C80.7512 102.628 81.068 102.701 81.3898 102.71Z" fill="#FFD7D2"/>
<path d="M81.3899 85.0698C81.068 85.0786 80.7511 85.1508 80.4571 85.2823C80.1632 85.4138 79.8981 85.602 79.6771 85.8361C79.456 86.0701 79.2833 86.3455 79.1688 86.6465C79.0543 86.9474 79.0003 87.268 79.0099 87.5898V92.8998H83.7799V87.5898C83.796 86.939 83.5535 86.3084 83.1055 85.836C82.6576 85.3637 82.0406 85.0881 81.3899 85.0698Z" fill="#F1998E"/>
<path d="M118.94 111.47C119.262 111.461 119.579 111.388 119.873 111.257C120.465 110.99 120.928 110.5 121.161 109.893C121.275 109.592 121.33 109.272 121.32 108.95V92.8999H116.52V108.95C116.513 109.275 116.569 109.597 116.687 109.9C116.804 110.203 116.98 110.479 117.205 110.714C117.43 110.948 117.699 111.135 117.997 111.265C118.295 111.394 118.615 111.464 118.94 111.47Z" fill="#FFD7D2"/>
<path d="M118.94 85.0698C118.289 85.0881 117.672 85.3637 117.224 85.836C116.776 86.3084 116.534 86.939 116.55 87.5898V92.8998H121.32V87.5898C121.329 87.268 121.275 86.9475 121.161 86.6466C121.046 86.3457 120.873 86.0704 120.652 85.8363C120.431 85.6023 120.166 85.4141 119.872 85.2826C119.579 85.1511 119.262 85.0788 118.94 85.0698Z" fill="#F1998E"/>
<path d="M109.52 111.47C110.171 111.452 110.788 111.176 111.236 110.704C111.684 110.231 111.926 109.601 111.91 108.95V92.8999H107.13V108.95C107.114 109.601 107.357 110.231 107.805 110.703C108.252 111.176 108.869 111.451 109.52 111.47Z" fill="#FFD7D2"/>
<path d="M109.52 85.0698C108.869 85.0881 108.252 85.3637 107.804 85.836C107.356 86.3084 107.114 86.939 107.13 87.5898V92.8998H111.91V87.5898C111.926 86.9391 111.683 86.3086 111.235 85.8363C110.787 85.364 110.171 85.0884 109.52 85.0698Z" fill="#F1998E"/>
<path d="M100.17 111.47C100.819 111.449 101.433 111.172 101.879 110.7C102.325 110.228 102.566 109.599 102.55 108.95V92.8999H97.7798V108.95C97.7637 109.601 98.0062 110.231 98.4541 110.704C98.9021 111.176 99.5191 111.452 100.17 111.47Z" fill="#FFD7D2"/>
<path d="M100.17 85.0698C99.5191 85.0881 98.9021 85.3637 98.4541 85.836C98.0062 86.3084 97.7637 86.939 97.7798 87.5898V92.8998H102.52V87.5898C102.535 86.9459 102.298 86.3215 101.859 85.8505C101.42 85.3794 100.813 85.0992 100.17 85.0698Z" fill="#F1998E"/>
<path d="M90.7799 111.47C91.4306 111.452 92.0476 111.176 92.4955 110.704C92.9435 110.231 93.186 109.601 93.1699 108.95V92.8999H88.3899V108.95C88.3743 109.601 88.6169 110.231 89.0648 110.703C89.5127 111.175 90.1293 111.451 90.7799 111.47Z" fill="#FFD7D2"/>
<path d="M90.7799 85.0698C90.1292 85.0881 89.5122 85.3637 89.0642 85.836C88.6163 86.3084 88.3738 86.939 88.3899 87.5898V92.8998H93.1699V87.5898C93.1861 86.939 92.9436 86.3084 92.4956 85.836C92.0476 85.3637 91.4307 85.0881 90.7799 85.0698Z" fill="#F1998E"/>
<path d="M72.8298 121.93L60.8298 65.59C60.4752 63.9325 59.5631 62.4466 58.2456 61.3802C56.9281 60.3138 55.2848 59.7314 53.5898 59.73H40.5198" stroke="#231F20" stroke-width="2.51" stroke-miterlimit="10"/>
<path d="M57.6098 121.93L45.6098 65.59C45.2551 63.9326 44.343 62.4468 43.0255 61.3804C41.708 60.3141 40.0648 59.7316 38.3698 59.73H30.8198" stroke="#231F20" stroke-width="2.51" stroke-miterlimit="10"/>
<path d="M121.011 121.86H61.3708C60.2604 121.86 59.1642 122.108 58.1617 122.586C57.1593 123.063 56.2759 123.758 55.5758 124.62C54.8769 125.483 54.3792 126.491 54.1189 127.57C53.8585 128.649 53.8421 129.773 54.0708 130.86C54.4189 132.538 55.3353 134.044 56.6653 135.124C57.9953 136.205 59.6573 136.793 61.3708 136.79H120.921" stroke="#231F20" stroke-width="2.51" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M71.0598 150.39C73.1815 150.39 75.2164 149.547 76.7167 148.047C78.217 146.547 79.0598 144.512 79.0598 142.39C79.0598 140.268 78.217 138.234 76.7167 136.733C75.2164 135.233 73.1815 134.39 71.0598 134.39C68.9381 134.39 66.9032 135.233 65.403 136.733C63.9027 138.234 63.0598 140.268 63.0598 142.39C63.0598 144.512 63.9027 146.547 65.403 148.047C66.9032 149.547 68.9381 150.39 71.0598 150.39Z" fill="#141414"/>
<path d="M70.9399 150.39H74.6099V134.4H70.9399V150.39Z" fill="#141414"/>
<path d="M74.6099 150.39C76.7316 150.39 78.7664 149.547 80.2667 148.047C81.767 146.547 82.6099 144.512 82.6099 142.39C82.6099 140.268 81.767 138.234 80.2667 136.733C78.7664 135.233 76.7316 134.39 74.6099 134.39C72.4881 134.39 70.4533 135.233 68.953 136.733C67.4527 138.234 66.6099 140.268 66.6099 142.39C66.6099 144.512 67.4527 146.547 68.953 148.047C70.4533 149.547 72.4881 150.39 74.6099 150.39Z" fill="#545454"/>
<path d="M74.6098 146.68C75.7476 146.68 76.8388 146.228 77.6433 145.424C78.4478 144.619 78.8998 143.528 78.8998 142.39C78.8998 141.252 78.4478 140.161 77.6433 139.357C76.8388 138.552 75.7476 138.1 74.6098 138.1C73.472 138.1 72.3809 138.552 71.5763 139.357C70.7718 140.161 70.3198 141.252 70.3198 142.39C70.3198 143.528 70.7718 144.619 71.5763 145.424C72.3809 146.228 73.472 146.68 74.6098 146.68Z" fill="#F6F6F6"/>
<path d="M71.3999 137.518L69.7249 139.194L77.2549 146.725L78.9309 145.049L71.3999 137.518Z" fill="#545454"/>
<path d="M123.42 150.39C125.542 150.39 127.576 149.547 129.077 148.047C130.577 146.547 131.42 144.512 131.42 142.39C131.42 140.268 130.577 138.234 129.077 136.733C127.576 135.233 125.542 134.39 123.42 134.39C121.298 134.39 119.263 135.233 117.763 136.733C116.263 138.234 115.42 140.268 115.42 142.39C115.42 144.512 116.263 146.547 117.763 148.047C119.263 149.547 121.298 150.39 123.42 150.39Z" fill="#141414"/>
<path d="M123.289 150.39H126.959V134.4H123.289V150.39Z" fill="#141414"/>
<path d="M126.959 150.39C129.081 150.39 131.116 149.547 132.616 148.047C134.116 146.547 134.959 144.512 134.959 142.39C134.959 140.268 134.116 138.234 132.616 136.733C131.116 135.233 129.081 134.39 126.959 134.39C124.837 134.39 122.802 135.233 121.302 136.733C119.802 138.234 118.959 140.268 118.959 142.39C118.959 144.512 119.802 146.547 121.302 148.047C122.802 149.547 124.837 150.39 126.959 150.39Z" fill="#545454"/>
<path d="M126.96 146.68C128.098 146.68 129.189 146.228 129.993 145.424C130.798 144.619 131.25 143.528 131.25 142.39C131.25 141.252 130.798 140.161 129.993 139.357C129.189 138.552 128.098 138.1 126.96 138.1C125.822 138.1 124.731 138.552 123.926 139.357C123.122 140.161 122.67 141.252 122.67 142.39C122.67 143.528 123.122 144.619 123.926 145.424C124.731 146.228 125.822 146.68 126.96 146.68Z" fill="#F6F6F6"/>
<path d="M123.764 137.514L122.088 139.19L129.619 146.721L131.294 145.045L123.764 137.514Z" fill="#545454"/>
<path d="M26.2999 63.1201H45.3699C46.9599 63.1201 48.2499 61.8331 48.2499 60.2451C48.2499 58.6571 46.9599 57.3701 45.3699 57.3701H26.2999C24.7099 57.3701 23.4199 58.6571 23.4199 60.2451C23.4199 61.8331 24.7099 63.1201 26.2999 63.1201Z" fill="#231F20"/>
<path d="M114.439 146.37C113.857 146.144 113.242 146.016 112.619 145.99C112.282 145.963 111.943 146.031 111.643 146.186C111.342 146.342 111.091 146.579 110.919 146.87C110.699 147.31 110.829 147.87 110.629 148.29C110.829 147.84 106.709 145.54 106.179 145.29C104.921 144.679 103.568 144.287 102.179 144.13C99.1789 143.82 96.9189 145.21 97.3589 148.45C93.8889 145.82 89.0489 142.32 84.5289 144.45C82.3289 145.45 80.9189 148.4 82.1989 150.45C85.0289 150.05 87.8789 150.77 90.6989 151.2C94.3659 151.675 98.0609 151.906 101.759 151.89L114.409 152.11C115.519 152.11 123.349 153.88 123.519 152.11C123.629 150.94 118.159 148.2 117.369 147.78C116.428 147.239 115.449 146.768 114.439 146.37ZM54.8299 138.09C53.8364 137.448 52.7302 137 51.5699 136.77C50.9876 136.666 50.389 136.702 49.8237 136.876C49.2584 137.05 48.7428 137.356 48.3199 137.77C47.9434 138.252 47.6789 138.811 47.5457 139.408C47.4126 140.005 47.414 140.624 47.5499 141.22C47.8199 142.404 48.1539 143.572 48.5499 144.72C45.3087 142.128 41.8415 139.832 38.1899 137.86C34.8399 136.06 31.1899 135.08 27.5799 133.76C23.9699 132.44 17.8999 131.59 16.8399 136.64C16.631 137.987 16.7758 139.365 17.2599 140.64C17.7345 142.086 18.455 143.439 19.3899 144.64C19.9399 145.41 21.8899 147.19 20.7699 148.19C19.6499 149.19 17.5399 147.39 16.5799 146.68C15.6199 145.97 14.3999 145.52 13.5799 146.62C13.0799 147.33 13.6799 148.26 13.1099 148.94C11.5999 150.73 7.86986 148.58 6.56986 147.54C5.965 146.95 5.26953 146.46 4.50986 146.09C4.12418 145.914 3.6898 145.877 3.27995 145.985C2.8701 146.092 2.50982 146.338 2.25986 146.68C1.25986 148.51 3.99986 151.06 5.47986 151.68C7.39986 152.45 9.64986 152.14 11.6599 152.14H63.1199C64.1199 152.14 68.1199 152.84 68.5399 151.51C68.8499 150.51 66.8499 148.85 66.3099 148.29C62.8099 144.53 59.3399 140.74 54.8299 138.09ZM34.5599 129.32C35.0797 129.32 35.5782 129.113 35.9456 128.745C36.3131 128.378 36.5195 127.879 36.5194 127.359C36.5192 126.84 36.3126 126.341 35.9449 125.974C35.5773 125.606 35.0787 125.4 34.5589 125.4C34.039 125.4 33.5405 125.606 33.1729 125.974C32.8054 126.342 32.5989 126.84 32.5989 127.36C32.5989 127.88 32.8054 128.378 33.1729 128.746C33.5405 129.113 34.039 129.32 34.5589 129.32H34.5599Z" fill="#D4E2FC"/>
<path d="M6.69999 119.32C7.21981 119.32 7.71835 119.113 8.08592 118.746C8.45349 118.378 8.65999 117.88 8.65999 117.36C8.65999 116.84 8.45349 116.342 8.08592 115.974C7.71835 115.606 7.21981 115.4 6.69999 115.4C6.18017 115.4 5.68163 115.606 5.31406 115.974C4.94649 116.342 4.73999 116.84 4.73999 117.36C4.73999 117.88 4.94649 118.378 5.31406 118.746C5.68163 119.113 6.18017 119.32 6.69999 119.32Z" fill="#5B91F5"/>
<path d="M2.12992 127.96C2.38731 127.96 2.64218 127.909 2.87998 127.811C3.11778 127.712 3.33385 127.568 3.51585 127.386C3.69785 127.204 3.84223 126.988 3.94073 126.75C4.03923 126.512 4.08992 126.257 4.08992 126C4.08992 125.743 4.03923 125.488 3.94073 125.25C3.84223 125.012 3.69785 124.796 3.51585 124.614C3.33385 124.432 3.11778 124.288 2.87998 124.189C2.64218 124.091 2.38731 124.04 2.12992 124.04C1.6101 124.04 1.11156 124.247 0.743993 124.614C0.376421 124.982 0.169922 125.48 0.169922 126C0.169922 126.52 0.376421 127.018 0.743993 127.386C1.11156 127.754 1.6101 127.96 2.12992 127.96Z" fill="#D4E2FC"/>
<path d="M176.82 150.38H2.8999V175.74H176.82V150.38Z" fill="white"/>
</g>
<defs>
<clipPath id="clip0_335_2606">
<rect width="177" height="176" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -0,0 +1,3 @@
<svg width="19" height="13" viewBox="0 0 19 13" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1.5 6.5L7.5 11.5L17.5 1.5" stroke="#4BA457" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 223 B

BIN
assets/icons/ic_clock.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 389 B

View File

@@ -0,0 +1,8 @@
<svg width="24" height="16" viewBox="0 0 24 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M15.7236 0.400391C20.0862 0.400391 23.5996 3.81531 23.5996 8C23.5996 12.1847 20.0862 15.5996 15.7236 15.5996C11.3612 15.5994 7.84863 12.1845 7.84863 8C7.84863 3.81546 11.3612 0.400637 15.7236 0.400391Z" stroke="black" stroke-width="0.8"/>
<line x1="0.827637" y1="5.19998" x2="7.44833" y2="5.19998" stroke="black" stroke-width="0.8"/>
<line x1="15.3241" y1="8" x2="15.3241" y2="1.6" stroke="black" stroke-width="0.8"/>
<line x1="2.48267" y1="10" x2="6.6206" y2="10" stroke="black" stroke-width="0.8"/>
<line y1="7.6" x2="6.62069" y2="7.6" stroke="black" stroke-width="0.8"/>
<path d="M19.9827 11.2972L14.8965 7.2" stroke="black" stroke-width="0.8"/>
</svg>

After

Width:  |  Height:  |  Size: 761 B

View File

@@ -0,0 +1,4 @@
<svg width="21" height="21" viewBox="0 0 21 21" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M19.5 1.5L1.5 19.5" stroke="black" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M1.5 1.5L19.5 19.5" stroke="black" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 323 B

View File

@@ -0,0 +1,3 @@
<svg width="26" height="25" viewBox="0 0 26 25" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M25.3532 -1.17809e-05L17.0302 24.1971L12.8532 13.1168L-4.19789e-05 10.2697L25.3532 -1.17809e-05Z" fill="black"/>
</svg>

After

Width:  |  Height:  |  Size: 225 B

View File

@@ -0,0 +1,5 @@
<svg width="23" height="21" viewBox="0 0 23 21" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M15.5174 3.10349C18.1037 3.10349 19.6554 5.06903 19.6554 7.44837C19.6554 8.68976 19.0347 9.82771 18.3106 10.6553C17.0692 11.8967 11.3795 16.5519 11.3795 16.5519C11.3795 16.5519 5.68973 11.8967 4.44833 10.6553C3.62073 9.82771 3.10349 8.68976 3.10349 7.44837C3.10349 5.06903 4.65523 3.10349 7.24147 3.10349C9.00011 3.10349 10.6553 4.75868 11.3795 6.20697C12.1036 4.75868 13.7588 3.10349 15.5174 3.10349ZM15.5174 0C13.9657 0 12.5174 0.620697 11.3795 1.44829C10.2415 0.517248 8.79321 0 7.24147 0C3.10349 0 0 3.20694 0 7.44837C0 9.41391 0.827596 11.276 2.27589 12.8277C3.72418 14.3795 11.3795 20.5865 11.3795 20.5865C11.3795 20.5865 19.0347 14.3795 20.483 12.8277C21.9313 11.276 22.7589 9.41391 22.7589 7.44837C22.7589 3.20694 19.6554 0 15.5174 0Z"
fill="#8A8A8A" />
</svg>

After

Width:  |  Height:  |  Size: 894 B

View File

@@ -0,0 +1,3 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M18 16.25L14.3335 12.5833C15.2502 11.25 15.8333 9.6667 15.8333 7.9167C15.8333 3.58336 12.25 0 7.91665 0C3.58334 0 0 3.58336 0 7.9167C0 12.25 3.58334 15.8334 7.91665 15.8334C9.66665 15.8334 11.2501 15.25 12.5835 14.3333L16.25 18L18 16.25ZM2.5 8C2.5 5.00001 4.91667 2.58334 7.91665 2.58334C10.9166 2.58334 13.3333 5.00001 13.3333 8C13.3333 11 10.9166 13.4167 7.91665 13.4167C4.91667 13.4167 2.5 11 2.5 8Z" fill="black"/>
</svg>

After

Width:  |  Height:  |  Size: 531 B

View File

@@ -50,7 +50,97 @@
"ride": "Ride",
"chinese": "Chinese",
"dessert": "Dessert",
"more":"More"
"more":"More",
"orderDetails": "Order details",
"deliverNow": "Deliver now",
"schedule": "Schedule",
"enterNewAddress": "Enter a new address",
"nearby": "Nearby",
"currentLocation": "Current location",
"enable": "Enable",
"recentLocations": "Recent locations",
"allFilters": "All filters",
"sort": "Sort",
"pickedForYou": "Picked for you (default)",
"mostPopular": "Most popular",
"rating": "Rating",
"deliveryTime": "Delivery time",
"fromUberEats": "From Uber Eats",
"deals": "Deals",
"bestOverall": "Best overall",
"priceRange": "Price range",
"maxDeliveryFee": "Max. Delivery Fee",
"dietary": "Dietary",
"vegetarian": "Vegetarian",
"vegan": "Vegan",
"glutenFree": "Gluten-free",
"halal": "Halal",
"allergyFriendly": "Allergy friendly",
"atLeast":"At least",
"apply": "Apply",
"pickedForYouDefault": "Picked for you (default)",
"popular": "Most popular",
"topRated": "Top rated",
"fast": "Fast",
"delivery": "Delivery",
"featuredStores": "Featured stores",
"fromUberEats": "From {name}",
"@fromUberEats":{
"placeholders": {
"name": {
"type": "String"
}
}
},
"opensAt": "Opens at {time}",
"@opensAt": {
"placeholders":{
"time": {
"type": "String"
}
}
},
"spendAndSave": "Spend {spend}, save {save}",
"@spendAndSave": {
"placeholders":{
"spend": {
"type": "String"
},
"save": {
"type": "String"
}
}
},
"cartsTitle": "Carts",
"addItemsStartBasket": "Add items to start a basket",
"basketHint": "Once you add items from a restaurant or store, your basket will appear here.",
"startShopping": "Start Shopping",
"orders": "Orders",
"recentSearches": "Recent searches",
"cafe": "Cafe",
"irish": "Irish",
"topCategories": "Top Categories",
"breakfastAndBrunch": "Breakfast and Brunch",
"coffeeAndTea": "Coffee and Tea",
"chinese": "Chinese",
"indian": "Indian",
"latestDeals": "Latest Deals",
"restaurantRewards": "Restaurant Rewards",
"bestOverall": "Best Overall",
"nationwideShipping": "Nationwide Shipping",
"mexican": "Mexican",
"fastFood": "Fast Food",
"healthy": "Healthy",
"pizza": "Pizza",
"sandwich": "Sandwich",
"asian": "Asian",
"bakery": "Bakery",
"allCategories": "All categories",
"categoriesShort": "Food, shopping, drinks, etc."
}

View File

@@ -57,6 +57,89 @@
"ride": "Поездка",
"chinese": "Китайская",
"dessert": "Десерт",
"more":"Ещё"
"more":"Ещё",
"orderDetails": "Детали заказа",
"deliverNow": "Доставить сейчас",
"schedule": "Запланировать",
"enterNewAddress": "Введите новый адрес",
"nearby": "Рядом",
"currentLocation": "Текущее местоположение",
"enable": "Включить",
"recentLocations": "Недавние адреса",
"allFilters": "Все фильтры",
"sort": "Сортировка",
"pickedForYou": "Подобрано для вас (по умолчанию)",
"mostPopular": "Самые популярные",
"rating": "Рейтинг",
"deliveryTime": "Время доставки",
"fromUberEats": "От Uber Eats",
"deals": "Скидки",
"bestOverall": "Лучший выбор",
"priceRange": "Диапазон цен",
"maxDeliveryFee": "Макс. стоимость доставки",
"dietary": "Диета",
"vegetarian": "Вегетарианское",
"vegan": "Веганское",
"glutenFree": "Без глютена",
"halal": "Халяль",
"allergyFriendly": "Без аллергенов",
"atLeast":"Kак минимум",
"apply": "Применить",
"pickedForYouDefault": "Выбрано для вас (по умолчанию)",
"popular": "Самые популярные",
"topRated": "Высокий рейтинг",
"fast": "Быстро",
"delivery": "Доставка",
"featuredStores": "Популярные магазины",
"fromUberEats": "От {name}",
"@fromUberEats":{
"placeholders": {
"name": {
"type": "String"
}
}
},
"opensAt": "Открывается в {time}",
"opensAt@placeholders": {
"time": {}
},
"spendAndSave": "Потратьте {spend}, сэкономьте {save}",
"spendAndSave@placeholders": {
"spend": {},
"save": {}
},
"cartsTitle": "Корзины",
"addItemsStartBasket": "Добавьте товары, чтобы создать корзину",
"basketHint": "Когда вы добавите товары из ресторана или магазина, ваша корзина появится здесь.",
"startShopping": "Начать покупки",
"orders": "Заказы",
"recentSearches": "Недавние запросы",
"cafe": "Кафе",
"irish": "Ирландская кухня",
"topCategories": "Популярные категории",
"breakfastAndBrunch": "Завтрак и бранч",
"coffeeAndTea": "Кофе и чай",
"chinese": "Китайская кухня",
"indian": "Индийская кухня",
"latestDeals": "Новые предложения",
"restaurantRewards": "Ресторанные бонусы",
"bestOverall": "Лучшие варианты",
"nationwideShipping": "Доставка по всей стране",
"mexican": "Мексиканская кухня",
"fastFood": "Фастфуд",
"healthy": "Здоровая еда",
"pizza": "Пицца",
"sandwich": "Сэндвич",
"asian": "Азиатская кухня",
"bakery": "Пекарня",
"categoriesShort": "Еда, покупки, напитки и т.д.",
"allCategories": "Все категории"
}

View File

@@ -57,5 +57,90 @@
"ride": "Yol",
"chinese": "Xitoy",
"dessert": "Desert",
"more":"Ko'proq"
"more":"Ko'proq",
"orderDetails": "Buyurtma tafsilotlari",
"deliverNow": "Hozir yetkazish",
"schedule": "Rejalashtirish",
"enterNewAddress": "Yangi manzil kiriting",
"nearby": "Yaqin joylar",
"currentLocation": "Joriy joylashuv",
"enable": "Yoqqish",
"recentLocations": "Yaqinda ishlatilgan manzillar",
"allFilters": "Barcha filtrlar",
"sort": "Saralash",
"pickedForYou": "Siz uchun",
"mostPopular": "Eng ommabop",
"rating": "Reyting",
"deliveryTime": "Yetkazib berish vaqti",
"fromUberEats": "Uber Eats dan",
"deals": "Aksiyalar",
"bestOverall": "Eng yaxshisi",
"priceRange": "Narx oraligi",
"maxDeliveryFee": "Maks. yetkazish narxi",
"dietary": "Parhez",
"vegetarian": "Vegetarian",
"vegan": "Vegan",
"glutenFree": "Glutensiz",
"halal": "Halol",
"allergyFriendly": "Allergiyaga mos",
"atLeast":"Kаmida",
"apply": "Qollash",
"pickedForYouDefault": "Siz uchun tanlangan (standart)",
"popular": "Eng ommabop",
"topRated": "Yuqori reytingli",
"fast": "Tezkor",
"delivery": "Yetkazish",
"featuredStores": "Mashhur dokonlar",
"fromUberEats": "{name} tomonidan",
"@fromUberEats":{
"placeholders": {
"name": {
"type": "String"
}
}
},
"opensAt": "Soat {time} dan ochiladi",
"opensAt@placeholders": {
"time": {}
},
"spendAndSave": "{spend} sarflang, {save} tejang",
"spendAndSave@placeholders": {
"spend": {},
"save": {}
},
"cartsTitle": "Savatlar",
"addItemsStartBasket": "Savatni boshlash uchun mahsulot qoshing",
"basketHint": "Restorandan yoki do'kondan mahsulot qoshsangiz, savatingiz shu yerda paydo boladi.",
"startShopping": "Xaridni boshlash",
"orders": "Buyurtmalar",
"recentSearches": "Yaqinda qidirilganlar",
"cafe": "Kafe",
"irish": "Irlandcha",
"topCategories": "Eng ommabop toifalar",
"breakfastAndBrunch": "Nonushta va bransh",
"coffeeAndTea": "Qahva va choy",
"chinese": "Xitoy taomlari",
"indian": "Hind taomlari",
"latestDeals": "Yangi chegirmalar",
"restaurantRewards": "Restoran mukofotlari",
"bestOverall": "Eng yaxshilari",
"nationwideShipping": "Butun mamlakat boylab yetkazib berish",
"mexican": "Meksika taomlari",
"fastFood": "Tezkor ovqatlar",
"healthy": "Soglom ovqatlar",
"pizza": "Pitsa",
"sandwich": "Sendvich",
"asian": "Osiyo taomlari",
"bakery": "Qandolatxona",
"categoriesShort": "Ovqat, xaridlar, ichimliklar va boshqalar.",
"allCategories": "Barcha toifalar"
}

View File

@@ -1,6 +1,7 @@
abstract class AppLocaleKeys {
///Storage keys
static const String language = 'language';
static const String browseSearchHistory = 'browse-search-history';
static const String fontBold = "fontBold";
static const String fontMedium = "fontMedium";
@@ -9,4 +10,14 @@ abstract class AppLocaleKeys {
static const String imageUrl =
"https://xsznseejebbai1lj.public.blob.vercel-storage.com/homepage/hero/hero-1.webp";
static const String foodImageUrl =
"https://www.precisionorthomd.com/wp-content/uploads/2023/10/percision-blog-header-junk-food-102323.jpg";
static const String lorem = '''Lorem Ipsum is simply dummy text of the
printing and typesetting industry. Lorem Ipsum
has been the industry's standard dummy text ever
since the 1500s, when an unknown printer took a
galley of type and scrambled it to make a type
specimen book''';
}

View File

@@ -1,4 +1,5 @@
abstract class TimeDelayConst {
static const Duration durationMill150 = Duration(milliseconds: 150);
static const Duration durationMill300 = Duration(milliseconds: 300);
static const Duration durationMill800 = Duration(milliseconds: 800);

View File

@@ -12,6 +12,9 @@
import 'package:get_it/get_it.dart' as _i174;
import 'package:injectable/injectable.dart' as _i526;
import '../../feature/basket/presentation/blocs/basket_bloc.dart' as _i728;
import '../../feature/browse/presentation/blocs/browse_bloc/browse_bloc.dart'
as _i991;
import '../../feature/common/presentation/blocs/language_bloc/language_bloc.dart'
as _i942;
import '../../feature/home/presentation/blocs/home_bloc/home_bloc.dart'
@@ -31,9 +34,11 @@ extension GetItInjectableX on _i174.GetIt {
_i526.EnvironmentFilter? environmentFilter,
}) {
final gh = _i526.GetItHelper(this, environment, environmentFilter);
gh.factory<_i1007.HomeBloc>(() => _i1007.HomeBloc());
gh.factory<_i728.BasketBloc>(() => _i728.BasketBloc());
gh.factory<_i991.BrowseBloc>(() => _i991.BrowseBloc());
gh.factory<_i580.MainBloc>(() => _i580.MainBloc());
gh.factory<_i311.SplashBloc>(() => _i311.SplashBloc());
gh.factory<_i1007.HomeBloc>(() => _i1007.HomeBloc());
gh.singleton<_i306.StorageService>(() => _i306.StorageService());
gh.singleton<_i152.AppRoutes>(() => _i152.AppRoutes());
gh.factory<_i942.LanguageBloc>(

View File

@@ -327,6 +327,330 @@ abstract class AppLocalizations {
/// In en, this message translates to:
/// **'More'**
String get more;
/// No description provided for @orderDetails.
///
/// In en, this message translates to:
/// **'Order details'**
String get orderDetails;
/// No description provided for @deliverNow.
///
/// In en, this message translates to:
/// **'Deliver now'**
String get deliverNow;
/// No description provided for @schedule.
///
/// In en, this message translates to:
/// **'Schedule'**
String get schedule;
/// No description provided for @enterNewAddress.
///
/// In en, this message translates to:
/// **'Enter a new address'**
String get enterNewAddress;
/// No description provided for @nearby.
///
/// In en, this message translates to:
/// **'Nearby'**
String get nearby;
/// No description provided for @currentLocation.
///
/// In en, this message translates to:
/// **'Current location'**
String get currentLocation;
/// No description provided for @enable.
///
/// In en, this message translates to:
/// **'Enable'**
String get enable;
/// No description provided for @recentLocations.
///
/// In en, this message translates to:
/// **'Recent locations'**
String get recentLocations;
/// No description provided for @allFilters.
///
/// In en, this message translates to:
/// **'All filters'**
String get allFilters;
/// No description provided for @sort.
///
/// In en, this message translates to:
/// **'Sort'**
String get sort;
/// No description provided for @pickedForYou.
///
/// In en, this message translates to:
/// **'Picked for you (default)'**
String get pickedForYou;
/// No description provided for @mostPopular.
///
/// In en, this message translates to:
/// **'Most popular'**
String get mostPopular;
/// No description provided for @rating.
///
/// In en, this message translates to:
/// **'Rating'**
String get rating;
/// No description provided for @deliveryTime.
///
/// In en, this message translates to:
/// **'Delivery time'**
String get deliveryTime;
/// No description provided for @fromUberEats.
///
/// In en, this message translates to:
/// **'From {name}'**
String fromUberEats(String name);
/// No description provided for @deals.
///
/// In en, this message translates to:
/// **'Deals'**
String get deals;
/// No description provided for @bestOverall.
///
/// In en, this message translates to:
/// **'Best Overall'**
String get bestOverall;
/// No description provided for @priceRange.
///
/// In en, this message translates to:
/// **'Price range'**
String get priceRange;
/// No description provided for @maxDeliveryFee.
///
/// In en, this message translates to:
/// **'Max. Delivery Fee'**
String get maxDeliveryFee;
/// No description provided for @dietary.
///
/// In en, this message translates to:
/// **'Dietary'**
String get dietary;
/// No description provided for @vegetarian.
///
/// In en, this message translates to:
/// **'Vegetarian'**
String get vegetarian;
/// No description provided for @vegan.
///
/// In en, this message translates to:
/// **'Vegan'**
String get vegan;
/// No description provided for @glutenFree.
///
/// In en, this message translates to:
/// **'Gluten-free'**
String get glutenFree;
/// No description provided for @allergyFriendly.
///
/// In en, this message translates to:
/// **'Allergy friendly'**
String get allergyFriendly;
/// No description provided for @atLeast.
///
/// In en, this message translates to:
/// **'At least'**
String get atLeast;
/// No description provided for @apply.
///
/// In en, this message translates to:
/// **'Apply'**
String get apply;
/// No description provided for @pickedForYouDefault.
///
/// In en, this message translates to:
/// **'Picked for you (default)'**
String get pickedForYouDefault;
/// No description provided for @popular.
///
/// In en, this message translates to:
/// **'Most popular'**
String get popular;
/// No description provided for @topRated.
///
/// In en, this message translates to:
/// **'Top rated'**
String get topRated;
/// No description provided for @fast.
///
/// In en, this message translates to:
/// **'Fast'**
String get fast;
/// No description provided for @featuredStores.
///
/// In en, this message translates to:
/// **'Featured stores'**
String get featuredStores;
/// No description provided for @opensAt.
///
/// In en, this message translates to:
/// **'Opens at {time}'**
String opensAt(String time);
/// No description provided for @spendAndSave.
///
/// In en, this message translates to:
/// **'Spend {spend}, save {save}'**
String spendAndSave(String spend, String save);
/// No description provided for @cartsTitle.
///
/// In en, this message translates to:
/// **'Carts'**
String get cartsTitle;
/// No description provided for @addItemsStartBasket.
///
/// In en, this message translates to:
/// **'Add items to start a basket'**
String get addItemsStartBasket;
/// No description provided for @basketHint.
///
/// In en, this message translates to:
/// **'Once you add items from a restaurant or store, your basket will appear here.'**
String get basketHint;
/// No description provided for @startShopping.
///
/// In en, this message translates to:
/// **'Start Shopping'**
String get startShopping;
/// No description provided for @orders.
///
/// In en, this message translates to:
/// **'Orders'**
String get orders;
/// No description provided for @recentSearches.
///
/// In en, this message translates to:
/// **'Recent searches'**
String get recentSearches;
/// No description provided for @cafe.
///
/// In en, this message translates to:
/// **'Cafe'**
String get cafe;
/// No description provided for @irish.
///
/// In en, this message translates to:
/// **'Irish'**
String get irish;
/// No description provided for @topCategories.
///
/// In en, this message translates to:
/// **'Top Categories'**
String get topCategories;
/// No description provided for @breakfastAndBrunch.
///
/// In en, this message translates to:
/// **'Breakfast and Brunch'**
String get breakfastAndBrunch;
/// No description provided for @coffeeAndTea.
///
/// In en, this message translates to:
/// **'Coffee and Tea'**
String get coffeeAndTea;
/// No description provided for @latestDeals.
///
/// In en, this message translates to:
/// **'Latest Deals'**
String get latestDeals;
/// No description provided for @restaurantRewards.
///
/// In en, this message translates to:
/// **'Restaurant Rewards'**
String get restaurantRewards;
/// No description provided for @nationwideShipping.
///
/// In en, this message translates to:
/// **'Nationwide Shipping'**
String get nationwideShipping;
/// No description provided for @mexican.
///
/// In en, this message translates to:
/// **'Mexican'**
String get mexican;
/// No description provided for @fastFood.
///
/// In en, this message translates to:
/// **'Fast Food'**
String get fastFood;
/// No description provided for @healthy.
///
/// In en, this message translates to:
/// **'Healthy'**
String get healthy;
/// No description provided for @pizza.
///
/// In en, this message translates to:
/// **'Pizza'**
String get pizza;
/// No description provided for @sandwich.
///
/// In en, this message translates to:
/// **'Sandwich'**
String get sandwich;
/// No description provided for @bakery.
///
/// In en, this message translates to:
/// **'Bakery'**
String get bakery;
/// No description provided for @categoriesShort.
///
/// In en, this message translates to:
/// **'Food, shopping, drinks, etc.'**
String get categoriesShort;
}
class _AppLocalizationsDelegate

View File

@@ -126,4 +126,173 @@ class AppLocalizationsEn extends AppLocalizations {
@override
String get more => 'More';
@override
String get orderDetails => 'Order details';
@override
String get deliverNow => 'Deliver now';
@override
String get schedule => 'Schedule';
@override
String get enterNewAddress => 'Enter a new address';
@override
String get nearby => 'Nearby';
@override
String get currentLocation => 'Current location';
@override
String get enable => 'Enable';
@override
String get recentLocations => 'Recent locations';
@override
String get allFilters => 'All filters';
@override
String get sort => 'Sort';
@override
String get pickedForYou => 'Picked for you (default)';
@override
String get mostPopular => 'Most popular';
@override
String get rating => 'Rating';
@override
String get deliveryTime => 'Delivery time';
@override
String fromUberEats(String name) {
return 'From $name';
}
@override
String get deals => 'Deals';
@override
String get bestOverall => 'Best Overall';
@override
String get priceRange => 'Price range';
@override
String get maxDeliveryFee => 'Max. Delivery Fee';
@override
String get dietary => 'Dietary';
@override
String get vegetarian => 'Vegetarian';
@override
String get vegan => 'Vegan';
@override
String get glutenFree => 'Gluten-free';
@override
String get allergyFriendly => 'Allergy friendly';
@override
String get atLeast => 'At least';
@override
String get apply => 'Apply';
@override
String get pickedForYouDefault => 'Picked for you (default)';
@override
String get popular => 'Most popular';
@override
String get topRated => 'Top rated';
@override
String get fast => 'Fast';
@override
String get featuredStores => 'Featured stores';
@override
String opensAt(String time) {
return 'Opens at $time';
}
@override
String spendAndSave(String spend, String save) {
return 'Spend $spend, save $save';
}
@override
String get cartsTitle => 'Carts';
@override
String get addItemsStartBasket => 'Add items to start a basket';
@override
String get basketHint =>
'Once you add items from a restaurant or store, your basket will appear here.';
@override
String get startShopping => 'Start Shopping';
@override
String get orders => 'Orders';
@override
String get recentSearches => 'Recent searches';
@override
String get cafe => 'Cafe';
@override
String get irish => 'Irish';
@override
String get topCategories => 'Top Categories';
@override
String get breakfastAndBrunch => 'Breakfast and Brunch';
@override
String get coffeeAndTea => 'Coffee and Tea';
@override
String get latestDeals => 'Latest Deals';
@override
String get restaurantRewards => 'Restaurant Rewards';
@override
String get nationwideShipping => 'Nationwide Shipping';
@override
String get mexican => 'Mexican';
@override
String get fastFood => 'Fast Food';
@override
String get healthy => 'Healthy';
@override
String get pizza => 'Pizza';
@override
String get sandwich => 'Sandwich';
@override
String get bakery => 'Bakery';
@override
String get categoriesShort => 'Food, shopping, drinks, etc.';
}

View File

@@ -90,7 +90,7 @@ class AppLocalizationsRu extends AppLocalizations {
String get takeout => 'На вынос';
@override
String get asian => 'Азиатская';
String get asian => 'Азиатская кухня';
@override
String get iceCream => 'Мороженое';
@@ -105,7 +105,7 @@ class AppLocalizationsRu extends AppLocalizations {
String get caribbean => 'Карибская';
@override
String get indian => 'Индийская';
String get indian => 'Индийская кухня';
@override
String get french => 'Французская';
@@ -120,11 +120,180 @@ class AppLocalizationsRu extends AppLocalizations {
String get ride => 'Поездка';
@override
String get chinese => 'Китайская';
String get chinese => 'Китайская кухня';
@override
String get dessert => 'Десерт';
@override
String get more => 'Ещё';
@override
String get orderDetails => 'Детали заказа';
@override
String get deliverNow => 'Доставить сейчас';
@override
String get schedule => 'Запланировать';
@override
String get enterNewAddress => 'Введите новый адрес';
@override
String get nearby => 'Рядом';
@override
String get currentLocation => 'Текущее местоположение';
@override
String get enable => 'Включить';
@override
String get recentLocations => 'Недавние адреса';
@override
String get allFilters => 'Все фильтры';
@override
String get sort => 'Сортировка';
@override
String get pickedForYou => 'Подобрано для вас (по умолчанию)';
@override
String get mostPopular => 'Самые популярные';
@override
String get rating => 'Рейтинг';
@override
String get deliveryTime => 'Время доставки';
@override
String fromUberEats(String name) {
return 'От $name';
}
@override
String get deals => 'Скидки';
@override
String get bestOverall => 'Лучшие варианты';
@override
String get priceRange => 'Диапазон цен';
@override
String get maxDeliveryFee => 'Макс. стоимость доставки';
@override
String get dietary => 'Диета';
@override
String get vegetarian => 'Вегетарианское';
@override
String get vegan => 'Веганское';
@override
String get glutenFree => 'Без глютена';
@override
String get allergyFriendly => 'Без аллергенов';
@override
String get atLeast => 'Kак минимум';
@override
String get apply => 'Применить';
@override
String get pickedForYouDefault => 'Выбрано для вас (по умолчанию)';
@override
String get popular => 'Самые популярные';
@override
String get topRated => 'Высокий рейтинг';
@override
String get fast => 'Быстро';
@override
String get featuredStores => 'Популярные магазины';
@override
String opensAt(String time) {
return 'Открывается в $time';
}
@override
String spendAndSave(String spend, String save) {
return 'Потратьте $spend, сэкономьте $save';
}
@override
String get cartsTitle => 'Корзины';
@override
String get addItemsStartBasket => 'Добавьте товары, чтобы создать корзину';
@override
String get basketHint =>
'Когда вы добавите товары из ресторана или магазина, ваша корзина появится здесь.';
@override
String get startShopping => 'Начать покупки';
@override
String get orders => 'Заказы';
@override
String get recentSearches => 'Недавние запросы';
@override
String get cafe => 'Кафе';
@override
String get irish => 'Ирландская кухня';
@override
String get topCategories => 'Популярные категории';
@override
String get breakfastAndBrunch => 'Завтрак и бранч';
@override
String get coffeeAndTea => 'Кофе и чай';
@override
String get latestDeals => 'Новые предложения';
@override
String get restaurantRewards => 'Ресторанные бонусы';
@override
String get nationwideShipping => 'Доставка по всей стране';
@override
String get mexican => 'Мексиканская кухня';
@override
String get fastFood => 'Фастфуд';
@override
String get healthy => 'Здоровая еда';
@override
String get pizza => 'Пицца';
@override
String get sandwich => 'Сэндвич';
@override
String get bakery => 'Пекарня';
@override
String get categoriesShort => 'Еда, покупки, напитки и т.д.';
}

View File

@@ -54,7 +54,7 @@ class AppLocalizationsUz extends AppLocalizations {
}
@override
String get delivery => 'Yetkazib berish';
String get delivery => 'Yetkazish';
@override
String get pickUp => 'Olib ketish';
@@ -90,7 +90,7 @@ class AppLocalizationsUz extends AppLocalizations {
String get takeout => 'Olib ketish';
@override
String get asian => 'Osiyo';
String get asian => 'Osiyo taomlari';
@override
String get iceCream => 'Muzqaymoq';
@@ -105,7 +105,7 @@ class AppLocalizationsUz extends AppLocalizations {
String get caribbean => 'Karib';
@override
String get indian => 'Hind';
String get indian => 'Hind taomlari';
@override
String get french => 'Fransuz';
@@ -120,11 +120,180 @@ class AppLocalizationsUz extends AppLocalizations {
String get ride => 'Yol';
@override
String get chinese => 'Xitoy';
String get chinese => 'Xitoy taomlari';
@override
String get dessert => 'Desert';
@override
String get more => 'Ko\'proq';
@override
String get orderDetails => 'Buyurtma tafsilotlari';
@override
String get deliverNow => 'Hozir yetkazish';
@override
String get schedule => 'Rejalashtirish';
@override
String get enterNewAddress => 'Yangi manzil kiriting';
@override
String get nearby => 'Yaqin joylar';
@override
String get currentLocation => 'Joriy joylashuv';
@override
String get enable => 'Yoqqish';
@override
String get recentLocations => 'Yaqinda ishlatilgan manzillar';
@override
String get allFilters => 'Barcha filtrlar';
@override
String get sort => 'Saralash';
@override
String get pickedForYou => 'Siz uchun';
@override
String get mostPopular => 'Eng ommabop';
@override
String get rating => 'Reyting';
@override
String get deliveryTime => 'Yetkazib berish vaqti';
@override
String fromUberEats(String name) {
return '$name tomonidan';
}
@override
String get deals => 'Aksiyalar';
@override
String get bestOverall => 'Eng yaxshilari';
@override
String get priceRange => 'Narx oraligi';
@override
String get maxDeliveryFee => 'Maks. yetkazish narxi';
@override
String get dietary => 'Parhez';
@override
String get vegetarian => 'Vegetarian';
@override
String get vegan => 'Vegan';
@override
String get glutenFree => 'Glutensiz';
@override
String get allergyFriendly => 'Allergiyaga mos';
@override
String get atLeast => 'Kаmida';
@override
String get apply => 'Qollash';
@override
String get pickedForYouDefault => 'Siz uchun tanlangan (standart)';
@override
String get popular => 'Eng ommabop';
@override
String get topRated => 'Yuqori reytingli';
@override
String get fast => 'Tezkor';
@override
String get featuredStores => 'Mashhur dokonlar';
@override
String opensAt(String time) {
return 'Soat $time dan ochiladi';
}
@override
String spendAndSave(String spend, String save) {
return '$spend sarflang, $save tejang';
}
@override
String get cartsTitle => 'Savatlar';
@override
String get addItemsStartBasket => 'Savatni boshlash uchun mahsulot qoshing';
@override
String get basketHint =>
'Restorandan yoki do\'kondan mahsulot qoshsangiz, savatingiz shu yerda paydo boladi.';
@override
String get startShopping => 'Xaridni boshlash';
@override
String get orders => 'Buyurtmalar';
@override
String get recentSearches => 'Yaqinda qidirilganlar';
@override
String get cafe => 'Kafe';
@override
String get irish => 'Irlandcha';
@override
String get topCategories => 'Eng ommabop toifalar';
@override
String get breakfastAndBrunch => 'Nonushta va bransh';
@override
String get coffeeAndTea => 'Qahva va choy';
@override
String get latestDeals => 'Yangi chegirmalar';
@override
String get restaurantRewards => 'Restoran mukofotlari';
@override
String get nationwideShipping => 'Butun mamlakat boylab yetkazib berish';
@override
String get mexican => 'Meksika taomlari';
@override
String get fastFood => 'Tezkor ovqatlar';
@override
String get healthy => 'Soglom ovqatlar';
@override
String get pizza => 'Pitsa';
@override
String get sandwich => 'Sendvich';
@override
String get bakery => 'Qandolatxona';
@override
String get categoriesShort => 'Ovqat, xaridlar, ichimliklar va boshqalar.';
}

View File

@@ -1,6 +1,5 @@
import 'package:flutter/cupertino.dart';
import 'package:food_delivery_client/feature/home/presentation/pages/categories_page/categories_page.dart';
import 'package:food_delivery_client/feature/on_boarding/presentation/pages/splash_page/splash_page.dart';
import 'package:food_delivery_client/feature/home/presentation/pages/restaurants_by_category_page/restaurants_by_category_page.dart';
import '../../food_delivery_client.dart';
@@ -11,7 +10,6 @@ class AppRoutes {
final GoRouter router = GoRouter(
navigatorKey: navigatorKey,
initialLocation: Routes.splash,
routes: [
GoRoute(path: Routes.splash, builder: (context, state) => SplashPage()),
GoRoute(
@@ -22,6 +20,22 @@ class AppRoutes {
path: Routes.categories,
pageBuilder: (context, state) => CupertinoPage(child: CategoriesPage()),
),
GoRoute(
path: Routes.filters,
pageBuilder: (context, state) => CupertinoPage(
child: FiltersPage(homeBloc: state.extra as HomeBloc),
),
),
GoRoute(
path: Routes.restaurantsByCategory,
pageBuilder: (context, state) => CupertinoPage(
child: RestaurantsByCategoryPage(categoryName: state.extra as String),
),
),
GoRoute(
path: Routes.browse,
pageBuilder: (context, state) => CupertinoPage(child: BrowsePage()),
),
],
);
}

View File

@@ -4,5 +4,7 @@ abstract class Routes {
static const String register = '/register';
static const String main = '/main';
static const String categories = '/categories';
static const String filters = '/filters';
static const String browse = '/browse';
static const String restaurantsByCategory = '/restaurants-by-category';
}

View File

@@ -12,6 +12,16 @@ class StorageService {
_sharedPreference.setString(key, value);
}
void setStringList({required String key, required String value}) {
final oldList = _sharedPreference.getStringList(key);
final newList = oldList?..add(value);
_sharedPreference.setStringList(key, newList ?? []);
}
List<String> getStringList({required String key}) {
return _sharedPreference.getStringList(key) ?? [];
}
String? getString({required String key}) {
return _sharedPreference.getString(key);
}

View File

@@ -3,6 +3,7 @@ import '../../food_delivery_client.dart';
abstract class AppColors {
static const Color cTransparent = Colors.transparent;
static const Color cRed = Colors.red;
static const Color cYellow = Colors.yellow;
static const Color cFFFFFF = Color(0xFFFFFFFF);
static const Color c000000 = Color(0xFF000000);
@@ -19,5 +20,9 @@ abstract class AppColors {
static const Color cC99EE2 = Color(0xFFC99EE2);
static const Color cE29EC7 = Color(0xFFE29EC7);
static const Color c545454 = Color(0xFF545454);
static const Color cEFF3FE = Color(0xFFEFF3FE);
static const Color c05A357 = Color(0xFF05A357);
static const Color cE8E8E8 = Color(0xFFE8E8E8);
static const Color c660000 = Color(0x66000000);
}

View File

@@ -13,6 +13,7 @@ abstract class AppIcons {
static const String icAccountActive = "$baseUrl/ic_account_active.svg";
static const String icBack = "$baseUrl/ic_back.svg";
static const String icDislike = "$baseUrl/ic_dislike.svg";
static const String icDislikeGrey = "$baseUrl/ic_dislike_grey.svg";
static const String icEat = "$baseUrl/ic_eat.svg";
static const String icEye = "$baseUrl/ic_eye.svg";
static const String icFilter = "$baseUrl/ic_filter.svg";
@@ -22,6 +23,29 @@ abstract class AppIcons {
static const String icUber = "$baseUrl/ic_uber.svg";
static const String icLocation = "$baseUrl/ic_location.svg";
static const String icArrowBottom = "$baseUrl/ic_arrow_btm.svg";
static const String icEmptyBasket = "$baseUrl/ic_empty_basket.svg";
static const String icPicked = "$baseUrl/ic_picked.svg";
static const String icMostPopular = "$baseUrl/ic_popular.svg";
static const String icStar = "$baseUrl/ic_rating.svg";
static const String icDeliveryTime = "$baseUrl/ic_delivery_time.svg";
static const String icDeals = "$baseUrl/ic_deals.svg";
static const String icClose = "$baseUrl/ic_close.svg";
static const String icCurrentLocation = "$baseUrl/ic_current_loc.svg";
static const String icEdit = "$baseUrl/ic_edit.svg";
static const String icSearch = "$baseUrl/ic_search.svg";
static const String icCheck= "$baseUrl/ic_check.svg";
static const String icCheck1= "$baseUrl/ic_check1.svg";
static const String icArrowRight= "$baseUrl/ic_arrow_right.svg";
///.png icons
static const String icBestOverall = "$baseUrl/ic_best.png";
static const String icVegetarian = "$baseUrl/ic_vegetarian.png";
static const String icVegen = "$baseUrl/ic_vegen.png";
static const String icGlutenFree = "$baseUrl/ic_gluten_free.png";
static const String icAllergyFriendly = "$baseUrl/ic_allergy_friendly.png";
static const String icClock = "$baseUrl/ic_clock.svg";
static const String icOrders= "$baseUrl/ic_orders.png";
}

View File

@@ -28,6 +28,13 @@ abstract class AppTextStyles {
fontWeight: FontWeight.w400,
);
static const TextStyle size16Regular = TextStyle(
color: _defaultColor,
fontSize: SizesCons.size_16,
fontFamily: _fontRegular,
fontWeight: FontWeight.w400,
);
static const TextStyle size20Regular = TextStyle(
color: _defaultColor,
fontSize: SizesCons.size_20,
@@ -63,6 +70,27 @@ abstract class AppTextStyles {
fontWeight: FontWeight.w500,
);
static const TextStyle size20Medium = TextStyle(
color: _defaultColor,
fontSize: SizesCons.size_20,
fontFamily: _fontMedium,
fontWeight: FontWeight.w500,
);
static const TextStyle size24Medium = TextStyle(
color: _defaultColor,
fontSize: SizesCons.size_24,
fontFamily: _fontMedium,
fontWeight: FontWeight.w500,
);
static const TextStyle size16Bold= TextStyle(
color: _defaultColor,
fontSize: SizesCons.size_16,
fontFamily: _fontBold,
fontWeight: FontWeight.w700,
);
static const TextStyle size17Bold = TextStyle(
color: _defaultColor,
fontSize: SizesCons.size_17,
@@ -76,6 +104,20 @@ abstract class AppTextStyles {
fontFamily: _fontBold,
fontWeight: FontWeight.w700,
);
static const TextStyle size30Bold = TextStyle(
color: _defaultColor,
fontSize: SizesCons.size_30,
fontFamily: _fontBold,
fontWeight: FontWeight.w700,
);
static const TextStyle size36Bold = TextStyle(
color: _defaultColor,
fontSize: SizesCons.size_36,
fontFamily: _fontBold,
fontWeight: FontWeight.w700,
);
}
/*

View File

@@ -1,6 +1,8 @@
import '../../food_delivery_client.dart';
abstract class AppUtils {
static const SizedBox kSizedBox = SizedBox.shrink();
static const Radius kRadius = Radius.zero;
static const Radius kRadius8 = Radius.circular(8);
static const Radius kRadius12 = Radius.circular(12);
@@ -36,6 +38,9 @@ abstract class AppUtils {
static const BorderRadius kBorderRadius14 = BorderRadius.all(
Radius.circular(14),
);
static const BorderRadius kBorderRadius15 = BorderRadius.all(
Radius.circular(15),
);
static const BorderRadius kBorderRadius16 = BorderRadius.all(
Radius.circular(16),
);
@@ -79,6 +84,14 @@ abstract class AppUtils {
static const BorderRadius kBorderRadius40 = BorderRadius.all(
Radius.circular(40),
);
static const BorderRadius kBorderRadiusTop15 = BorderRadius.only(
topLeft: kRadius15,
topRight: kRadius15,
);
static const BorderRadius kBorderRadiusTop20 = BorderRadius.only(
topLeft: kRadius20,
topRight: kRadius20,
);
static const BorderRadius kBorderRadiusTop20Bottom20 = BorderRadius.only(
bottomRight: kRadius20,
topRight: kRadius20,
@@ -87,4 +100,8 @@ abstract class AppUtils {
bottomRight: kRadius15,
topRight: kRadius15,
);
static const BorderRadius kBorderRadiusBottom15 = BorderRadius.only(
bottomLeft: kRadius15,
bottomRight: kRadius15,
);
}

View File

@@ -1 +1,8 @@
export 'presentation/pages/basket_page/basket_page.dart';
export 'package:food_delivery_client/feature/basket/presentation/pages/basket_page/widgets/w_basket_empty.dart';
export 'package:food_delivery_client/feature/basket/presentation/pages/basket_page/widgets/w_basket_header.dart';
export 'presentation/blocs/basket_bloc.dart';
export 'package:food_delivery_client/feature/basket/presentation/pages/basket_page/widgets/w_basket_body.dart';
export 'package:food_delivery_client/feature/basket/presentation/pages/basket_page/widgets/w_basket_carts.dart';
export 'package:food_delivery_client/feature/basket/presentation/pages/basket_page/widgets/w_basket_loading.dart';
export 'package:food_delivery_client/feature/basket/presentation/pages/basket_page/widgets/w_order_item.dart';

View File

@@ -0,0 +1,20 @@
import 'package:food_delivery_client/food_delivery_client.dart';
part 'basket_event.dart';
part 'basket_state.dart';
part 'basket_bloc.freezed.dart';
@injectable
class BasketBloc extends Bloc<BasketEvent, BasketState> {
BasketBloc() : super(const BasketState()) {
on<_Started>(_onStarted);
}
_onStarted(_Started event, Emitter<BasketState> emit) async {
emit(state.copyWith(status: RequestStatus.loading));
await Future.delayed(TimeDelayConst.duration3);
emit(state.copyWith(status: RequestStatus.loaded, orders: []));
}
}

View File

@@ -0,0 +1,472 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
// coverage:ignore-file
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'basket_bloc.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
// dart format off
T _$identity<T>(T value) => value;
/// @nodoc
mixin _$BasketEvent {
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is BasketEvent);
}
@override
int get hashCode => runtimeType.hashCode;
@override
String toString() {
return 'BasketEvent()';
}
}
/// @nodoc
class $BasketEventCopyWith<$Res> {
$BasketEventCopyWith(BasketEvent _, $Res Function(BasketEvent) __);
}
/// Adds pattern-matching-related methods to [BasketEvent].
extension BasketEventPatterns on BasketEvent {
/// A variant of `map` that fallback to returning `orElse`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeMap<TResult extends Object?>({TResult Function( _Started value)? started,required TResult orElse(),}){
final _that = this;
switch (_that) {
case _Started() when started != null:
return started(_that);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// Callbacks receives the raw object, upcasted.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case final Subclass2 value:
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult map<TResult extends Object?>({required TResult Function( _Started value) started,}){
final _that = this;
switch (_that) {
case _Started():
return started(_that);case _:
throw StateError('Unexpected subclass');
}
}
/// A variant of `map` that fallback to returning `null`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>({TResult? Function( _Started value)? started,}){
final _that = this;
switch (_that) {
case _Started() when started != null:
return started(_that);case _:
return null;
}
}
/// A variant of `when` that fallback to an `orElse` callback.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>({TResult Function()? started,required TResult orElse(),}) {final _that = this;
switch (_that) {
case _Started() when started != null:
return started();case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// As opposed to `map`, this offers destructuring.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case Subclass2(:final field2):
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult when<TResult extends Object?>({required TResult Function() started,}) {final _that = this;
switch (_that) {
case _Started():
return started();case _:
throw StateError('Unexpected subclass');
}
}
/// A variant of `when` that fallback to returning `null`
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>({TResult? Function()? started,}) {final _that = this;
switch (_that) {
case _Started() when started != null:
return started();case _:
return null;
}
}
}
/// @nodoc
class _Started implements BasketEvent {
const _Started();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _Started);
}
@override
int get hashCode => runtimeType.hashCode;
@override
String toString() {
return 'BasketEvent.started()';
}
}
/// @nodoc
mixin _$BasketState {
RequestStatus get status; List get orders;
/// Create a copy of BasketState
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
$BasketStateCopyWith<BasketState> get copyWith => _$BasketStateCopyWithImpl<BasketState>(this as BasketState, _$identity);
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is BasketState&&(identical(other.status, status) || other.status == status)&&const DeepCollectionEquality().equals(other.orders, orders));
}
@override
int get hashCode => Object.hash(runtimeType,status,const DeepCollectionEquality().hash(orders));
@override
String toString() {
return 'BasketState(status: $status, orders: $orders)';
}
}
/// @nodoc
abstract mixin class $BasketStateCopyWith<$Res> {
factory $BasketStateCopyWith(BasketState value, $Res Function(BasketState) _then) = _$BasketStateCopyWithImpl;
@useResult
$Res call({
RequestStatus status, List orders
});
}
/// @nodoc
class _$BasketStateCopyWithImpl<$Res>
implements $BasketStateCopyWith<$Res> {
_$BasketStateCopyWithImpl(this._self, this._then);
final BasketState _self;
final $Res Function(BasketState) _then;
/// Create a copy of BasketState
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? status = null,Object? orders = null,}) {
return _then(_self.copyWith(
status: null == status ? _self.status : status // ignore: cast_nullable_to_non_nullable
as RequestStatus,orders: null == orders ? _self.orders : orders // ignore: cast_nullable_to_non_nullable
as List,
));
}
}
/// Adds pattern-matching-related methods to [BasketState].
extension BasketStatePatterns on BasketState {
/// A variant of `map` that fallback to returning `orElse`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _BasketState value)? $default,{required TResult orElse(),}){
final _that = this;
switch (_that) {
case _BasketState() when $default != null:
return $default(_that);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// Callbacks receives the raw object, upcasted.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case final Subclass2 value:
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _BasketState value) $default,){
final _that = this;
switch (_that) {
case _BasketState():
return $default(_that);case _:
throw StateError('Unexpected subclass');
}
}
/// A variant of `map` that fallback to returning `null`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _BasketState value)? $default,){
final _that = this;
switch (_that) {
case _BasketState() when $default != null:
return $default(_that);case _:
return null;
}
}
/// A variant of `when` that fallback to an `orElse` callback.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( RequestStatus status, List orders)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _BasketState() when $default != null:
return $default(_that.status,_that.orders);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// As opposed to `map`, this offers destructuring.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case Subclass2(:final field2):
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( RequestStatus status, List orders) $default,) {final _that = this;
switch (_that) {
case _BasketState():
return $default(_that.status,_that.orders);case _:
throw StateError('Unexpected subclass');
}
}
/// A variant of `when` that fallback to returning `null`
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( RequestStatus status, List orders)? $default,) {final _that = this;
switch (_that) {
case _BasketState() when $default != null:
return $default(_that.status,_that.orders);case _:
return null;
}
}
}
/// @nodoc
class _BasketState implements BasketState {
const _BasketState({this.status = RequestStatus.initial, final List orders = const []}): _orders = orders;
@override@JsonKey() final RequestStatus status;
final List _orders;
@override@JsonKey() List get orders {
if (_orders is EqualUnmodifiableListView) return _orders;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_orders);
}
/// Create a copy of BasketState
/// with the given fields replaced by the non-null parameter values.
@override @JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$BasketStateCopyWith<_BasketState> get copyWith => __$BasketStateCopyWithImpl<_BasketState>(this, _$identity);
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _BasketState&&(identical(other.status, status) || other.status == status)&&const DeepCollectionEquality().equals(other._orders, _orders));
}
@override
int get hashCode => Object.hash(runtimeType,status,const DeepCollectionEquality().hash(_orders));
@override
String toString() {
return 'BasketState(status: $status, orders: $orders)';
}
}
/// @nodoc
abstract mixin class _$BasketStateCopyWith<$Res> implements $BasketStateCopyWith<$Res> {
factory _$BasketStateCopyWith(_BasketState value, $Res Function(_BasketState) _then) = __$BasketStateCopyWithImpl;
@override @useResult
$Res call({
RequestStatus status, List orders
});
}
/// @nodoc
class __$BasketStateCopyWithImpl<$Res>
implements _$BasketStateCopyWith<$Res> {
__$BasketStateCopyWithImpl(this._self, this._then);
final _BasketState _self;
final $Res Function(_BasketState) _then;
/// Create a copy of BasketState
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? status = null,Object? orders = null,}) {
return _then(_BasketState(
status: null == status ? _self.status : status // ignore: cast_nullable_to_non_nullable
as RequestStatus,orders: null == orders ? _self._orders : orders // ignore: cast_nullable_to_non_nullable
as List,
));
}
}
// dart format on

View File

@@ -0,0 +1,6 @@
part of 'basket_bloc.dart';
@freezed
class BasketEvent with _$BasketEvent {
const factory BasketEvent.started() = _Started;
}

View File

@@ -0,0 +1,9 @@
part of 'basket_bloc.dart';
@freezed
abstract class BasketState with _$BasketState {
const factory BasketState({
@Default(RequestStatus.initial) RequestStatus status,
@Default([]) List orders,
}) = _BasketState;
}

View File

@@ -5,8 +5,13 @@ class BasketPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return WLayout(
child: Scaffold(body: Center(child: Text(context.loc.useYourTAxiAccount))),
return BlocProvider(
create: (context) => sl<BasketBloc>()..add(BasketEvent.started()),
child: BlocBuilder<BasketBloc, BasketState>(
builder: (context, state) {
return WLayout(child: Scaffold(body: WBasketBody()));
},
),
);
}
}

View File

@@ -0,0 +1,23 @@
import '../../../../../../food_delivery_client.dart';
class WBasketBody extends StatelessWidget {
const WBasketBody({super.key});
@override
Widget build(BuildContext context) {
return BlocBuilder<BasketBloc, BasketState>(
builder: (context, state) {
return Column(
children: [
WBasketHeader(),
if (state.status.isLoading()) WBasketLoading(),
if (state.status.isLoaded())
if (state.orders.isEmpty) WBasketEmpty() else WBasketCarts(),
],
);
},
);
}
}

View File

@@ -0,0 +1,29 @@
import '../../../../../../food_delivery_client.dart';
class WBasketCarts extends StatelessWidget {
const WBasketCarts({super.key});
@override
Widget build(BuildContext context) {
return BlocBuilder<BasketBloc, BasketState>(
builder: (context, state) {
return Expanded(
child: RefreshIndicator(
onRefresh: () async {
context.read<BasketBloc>().add(BasketEvent.started());
await Future.delayed(TimeDelayConst.duration3);
},
child: ListView.builder(
shrinkWrap: true,
itemCount: 10,
scrollDirection: Axis.vertical,
physics: const AlwaysScrollableScrollPhysics(),
itemBuilder: (context, index) => OrderItem(),
),
),
);
},
);
}
}

View File

@@ -0,0 +1,46 @@
import '../../../../../../food_delivery_client.dart';
class WBasketEmpty extends StatelessWidget {
const WBasketEmpty({super.key});
@override
Widget build(BuildContext context) {
return BlocBuilder<MainBloc, MainState>(
builder: (context, state) {
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: [
70.verticalSpace,
SvgPicture.asset(AppIcons.icEmptyBasket),
Text(
context.loc.addItemsStartBasket,
textAlign: TextAlign.center,
style: AppTextStyles.size20Medium,
),
12.verticalSpace,
Text(
context.loc.basketHint,
textAlign: TextAlign.center,
style: AppTextStyles.size16Regular.copyWith(
color: AppColors.c545454,
height: 24 / 16,
),
),
38.verticalSpace,
AppButton(
name: context.loc.startShopping,
onPressed: () {
context.read<MainBloc>().add(MainEvent.loaded(0));
},
height: 45,
width: 250,
borderRadius: 99,
),
],
);
},
).paddingSymmetric(horizontal: 35);
}
}

View File

@@ -0,0 +1,44 @@
import '../../../../../../food_delivery_client.dart';
class WBasketHeader extends StatelessWidget {
const WBasketHeader({super.key});
@override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.max,
children: [
Align(
alignment: AlignmentGeometry.centerRight,
child: InkWell(
borderRadius: BorderRadius.circular(99),
onTap: () {},
child: Ink(
decoration: BoxDecoration(
color: AppColors.cEEEEEE,
borderRadius: BorderRadius.circular(99),
),
child: Row(
spacing: 10,
mainAxisSize: MainAxisSize.min,
children: [
Image.asset(
AppIcons.icOrders,
height: 20,
width: 20,
fit: BoxFit.cover,
),
Text(context.loc.orders, style: AppTextStyles.size14Medium),
],
).paddingSymmetric(vertical: 10, horizontal: 16),
),
),
),
Align(
alignment: AlignmentGeometry.centerLeft,
child: Text(context.loc.cartsTitle, style: AppTextStyles.size36Bold),
),
],
).paddingSymmetric(horizontal: 15);
}
}

View File

@@ -0,0 +1,80 @@
import '../../../../../../food_delivery_client.dart';
class WBasketLoading extends StatelessWidget {
const WBasketLoading({super.key});
@override
Widget build(BuildContext context) {
return Expanded(
child: ListView.builder(
shrinkWrap: true,
itemCount: 10,
scrollDirection: Axis.vertical,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (context, index) =>
Skeletonizer(enabled: true, child: OrderItemSkeletonizer()),
),
);
}
}
class OrderItemSkeletonizer extends StatelessWidget {
const OrderItemSkeletonizer({super.key});
@override
Widget build(BuildContext context) {
return InkWell(
onTap: () {},
child: Ink(
child: Column(
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ClipRRect(
borderRadius: AppUtils.kBorderRadius40,
child: CachedNetworkImage(
imageUrl: AppLocaleKeys.imageUrl,
height: 70,
width: 70,
fit: BoxFit.cover,
),
),
16.horizontalSpace,
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Begs & Megs", style: AppTextStyles.size16Medium),
Text(
AppLocaleKeys.lorem,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: AppTextStyles.size14Regular.copyWith(
color: AppColors.c6B6B6B,
),
),
Text(
"Deliver to San Franciscao Bay Area",
style: AppTextStyles.size14Regular.copyWith(
color: AppColors.c6B6B6B,
),
),
],
),
),
Icon(
Icons.arrow_forward_ios_outlined,
color: AppColors.cFFFFFF,
),
],
).paddingSymmetric(vertical: 10, horizontal: 18),
10.verticalSpace,
WDivider(indent: 120, endIndent: 20, height: 1),
],
),
),
);
}
}

View File

@@ -0,0 +1,86 @@
import '../../../../../../food_delivery_client.dart';
class OrderItem extends StatelessWidget {
const OrderItem({super.key});
@override
Widget build(BuildContext context) {
return InkWell(
onTap: () {},
child: Ink(
child: Column(
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ClipRRect(
borderRadius: AppUtils.kBorderRadius40,
child: CachedNetworkImage(
imageUrl: AppLocaleKeys.imageUrl,
height: 70,
width: 70,
fit: BoxFit.cover,
),
),
16.horizontalSpace,
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
AppLocaleKeys.lorem,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: AppTextStyles.size16Medium,
),
Row(
spacing: 5,
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Expanded(
child: Text(
AppLocaleKeys.lorem,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: AppTextStyles.size14Regular.copyWith(
color: AppColors.c6B6B6B,
),
),
),
Icon(Icons.circle, size: 5, color: AppColors.c6B6B6B),
Expanded(
child: Text(
AppLocaleKeys.lorem,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: AppTextStyles.size14Regular.copyWith(
color: AppColors.c6B6B6B,
),
),
),
],
),
Text(
AppLocaleKeys.lorem,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: AppTextStyles.size14Regular.copyWith(
color: AppColors.c6B6B6B,
),
),
],
),
),
10.horizontalSpace,
SvgPicture.asset(AppIcons.icArrowRight),
],
).paddingSymmetric(vertical: 10, horizontal: 18),
10.verticalSpace,
WDivider(indent: 120, endIndent: 20, height: 1),
],
),
),
);
}
}

View File

@@ -1 +1,10 @@
export 'presentation/pages/browse_page/browse_page.dart';
export 'package:food_delivery_client/feature/browse/presentation/pages/browse_page/widgets/w_browse_body.dart';
export 'package:food_delivery_client/feature/browse/presentation/pages/browse_page/widgets/w_browse_item.dart';
export "presentation/blocs/browse_bloc/browse_bloc.dart";
export 'package:food_delivery_client/feature/browse/presentation/pages/browse_page/widgets/w_all_categories_skeletonizer.dart';
export 'package:food_delivery_client/feature/browse/presentation/pages/browse_page/widgets/w_browse_skeletonizer.dart';
export 'package:food_delivery_client/feature/browse/presentation/pages/browse_page/widgets/w_all_categories.dart';
export 'package:food_delivery_client/feature/browse/presentation/pages/browse_page/widgets/w_top_categories.dart';
export 'package:food_delivery_client/feature/common/presentation/widgets/app_text_form_field.dart';
export 'package:food_delivery_client/feature/browse/presentation/pages/browse_page/widgets/w_top_categories_skeletonizer.dart';

View File

@@ -0,0 +1,48 @@
import 'package:food_delivery_client/food_delivery_client.dart';
part 'browse_event.dart';
part 'browse_state.dart';
part 'browse_bloc.freezed.dart';
@injectable
class BrowseBloc extends Bloc<BrowseEvent, BrowseState> {
BrowseBloc() : super(const BrowseState()) {
on<_GetTopCategories>(_onGetTopCategories);
on<_GetAllCategories>(_onGetAllCategories);
on<_GetSearchHistory>(_onGetSearchHistory);
on<_FocusChanged>(_onFocusChanged);
}
Future<void> _onGetTopCategories(
_GetTopCategories event,
Emitter<BrowseState> emit,
) async {
emit(state.copyWith(topCategorySt: RequestStatus.loading));
await Future.delayed(TimeDelayConst.duration3);
emit(state.copyWith(topCategorySt: RequestStatus.loaded));
}
Future<void> _onGetAllCategories(
_GetAllCategories event,
Emitter<BrowseState> emit,
) async {
emit(state.copyWith(allCategorySt: RequestStatus.loading));
await Future.delayed(TimeDelayConst.duration3);
emit(state.copyWith(allCategorySt: RequestStatus.loaded));
}
Future<void> _onGetSearchHistory(
_GetSearchHistory event,
Emitter<BrowseState> emit,
) async {
emit(state.copyWith(searchHistorySt: RequestStatus.loading));
await Future.delayed(TimeDelayConst.duration3);
emit(state.copyWith(searchHistorySt: RequestStatus.loading));
}
void _onFocusChanged(_FocusChanged event, Emitter<BrowseState> emit) {
emit(state.copyWith(isActive: event.isActive ?? !(state.isActive)));
}
}

View File

@@ -0,0 +1,667 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
// coverage:ignore-file
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'browse_bloc.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
// dart format off
T _$identity<T>(T value) => value;
/// @nodoc
mixin _$BrowseEvent {
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is BrowseEvent);
}
@override
int get hashCode => runtimeType.hashCode;
@override
String toString() {
return 'BrowseEvent()';
}
}
/// @nodoc
class $BrowseEventCopyWith<$Res> {
$BrowseEventCopyWith(BrowseEvent _, $Res Function(BrowseEvent) __);
}
/// Adds pattern-matching-related methods to [BrowseEvent].
extension BrowseEventPatterns on BrowseEvent {
/// A variant of `map` that fallback to returning `orElse`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeMap<TResult extends Object?>({TResult Function( _Started value)? started,TResult Function( _GetTopCategories value)? getTopCategories,TResult Function( _GetAllCategories value)? getAllCategories,TResult Function( _GetSearchHistory value)? getSearchHistory,TResult Function( _FocusChanged value)? focusChanged,required TResult orElse(),}){
final _that = this;
switch (_that) {
case _Started() when started != null:
return started(_that);case _GetTopCategories() when getTopCategories != null:
return getTopCategories(_that);case _GetAllCategories() when getAllCategories != null:
return getAllCategories(_that);case _GetSearchHistory() when getSearchHistory != null:
return getSearchHistory(_that);case _FocusChanged() when focusChanged != null:
return focusChanged(_that);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// Callbacks receives the raw object, upcasted.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case final Subclass2 value:
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult map<TResult extends Object?>({required TResult Function( _Started value) started,required TResult Function( _GetTopCategories value) getTopCategories,required TResult Function( _GetAllCategories value) getAllCategories,required TResult Function( _GetSearchHistory value) getSearchHistory,required TResult Function( _FocusChanged value) focusChanged,}){
final _that = this;
switch (_that) {
case _Started():
return started(_that);case _GetTopCategories():
return getTopCategories(_that);case _GetAllCategories():
return getAllCategories(_that);case _GetSearchHistory():
return getSearchHistory(_that);case _FocusChanged():
return focusChanged(_that);case _:
throw StateError('Unexpected subclass');
}
}
/// A variant of `map` that fallback to returning `null`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>({TResult? Function( _Started value)? started,TResult? Function( _GetTopCategories value)? getTopCategories,TResult? Function( _GetAllCategories value)? getAllCategories,TResult? Function( _GetSearchHistory value)? getSearchHistory,TResult? Function( _FocusChanged value)? focusChanged,}){
final _that = this;
switch (_that) {
case _Started() when started != null:
return started(_that);case _GetTopCategories() when getTopCategories != null:
return getTopCategories(_that);case _GetAllCategories() when getAllCategories != null:
return getAllCategories(_that);case _GetSearchHistory() when getSearchHistory != null:
return getSearchHistory(_that);case _FocusChanged() when focusChanged != null:
return focusChanged(_that);case _:
return null;
}
}
/// A variant of `when` that fallback to an `orElse` callback.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>({TResult Function()? started,TResult Function()? getTopCategories,TResult Function()? getAllCategories,TResult Function()? getSearchHistory,TResult Function( bool? isActive)? focusChanged,required TResult orElse(),}) {final _that = this;
switch (_that) {
case _Started() when started != null:
return started();case _GetTopCategories() when getTopCategories != null:
return getTopCategories();case _GetAllCategories() when getAllCategories != null:
return getAllCategories();case _GetSearchHistory() when getSearchHistory != null:
return getSearchHistory();case _FocusChanged() when focusChanged != null:
return focusChanged(_that.isActive);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// As opposed to `map`, this offers destructuring.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case Subclass2(:final field2):
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult when<TResult extends Object?>({required TResult Function() started,required TResult Function() getTopCategories,required TResult Function() getAllCategories,required TResult Function() getSearchHistory,required TResult Function( bool? isActive) focusChanged,}) {final _that = this;
switch (_that) {
case _Started():
return started();case _GetTopCategories():
return getTopCategories();case _GetAllCategories():
return getAllCategories();case _GetSearchHistory():
return getSearchHistory();case _FocusChanged():
return focusChanged(_that.isActive);case _:
throw StateError('Unexpected subclass');
}
}
/// A variant of `when` that fallback to returning `null`
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>({TResult? Function()? started,TResult? Function()? getTopCategories,TResult? Function()? getAllCategories,TResult? Function()? getSearchHistory,TResult? Function( bool? isActive)? focusChanged,}) {final _that = this;
switch (_that) {
case _Started() when started != null:
return started();case _GetTopCategories() when getTopCategories != null:
return getTopCategories();case _GetAllCategories() when getAllCategories != null:
return getAllCategories();case _GetSearchHistory() when getSearchHistory != null:
return getSearchHistory();case _FocusChanged() when focusChanged != null:
return focusChanged(_that.isActive);case _:
return null;
}
}
}
/// @nodoc
class _Started implements BrowseEvent {
const _Started();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _Started);
}
@override
int get hashCode => runtimeType.hashCode;
@override
String toString() {
return 'BrowseEvent.started()';
}
}
/// @nodoc
class _GetTopCategories implements BrowseEvent {
const _GetTopCategories();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _GetTopCategories);
}
@override
int get hashCode => runtimeType.hashCode;
@override
String toString() {
return 'BrowseEvent.getTopCategories()';
}
}
/// @nodoc
class _GetAllCategories implements BrowseEvent {
const _GetAllCategories();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _GetAllCategories);
}
@override
int get hashCode => runtimeType.hashCode;
@override
String toString() {
return 'BrowseEvent.getAllCategories()';
}
}
/// @nodoc
class _GetSearchHistory implements BrowseEvent {
const _GetSearchHistory();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _GetSearchHistory);
}
@override
int get hashCode => runtimeType.hashCode;
@override
String toString() {
return 'BrowseEvent.getSearchHistory()';
}
}
/// @nodoc
class _FocusChanged implements BrowseEvent {
const _FocusChanged(this.isActive);
final bool? isActive;
/// Create a copy of BrowseEvent
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$FocusChangedCopyWith<_FocusChanged> get copyWith => __$FocusChangedCopyWithImpl<_FocusChanged>(this, _$identity);
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _FocusChanged&&(identical(other.isActive, isActive) || other.isActive == isActive));
}
@override
int get hashCode => Object.hash(runtimeType,isActive);
@override
String toString() {
return 'BrowseEvent.focusChanged(isActive: $isActive)';
}
}
/// @nodoc
abstract mixin class _$FocusChangedCopyWith<$Res> implements $BrowseEventCopyWith<$Res> {
factory _$FocusChangedCopyWith(_FocusChanged value, $Res Function(_FocusChanged) _then) = __$FocusChangedCopyWithImpl;
@useResult
$Res call({
bool? isActive
});
}
/// @nodoc
class __$FocusChangedCopyWithImpl<$Res>
implements _$FocusChangedCopyWith<$Res> {
__$FocusChangedCopyWithImpl(this._self, this._then);
final _FocusChanged _self;
final $Res Function(_FocusChanged) _then;
/// Create a copy of BrowseEvent
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') $Res call({Object? isActive = freezed,}) {
return _then(_FocusChanged(
freezed == isActive ? _self.isActive : isActive // ignore: cast_nullable_to_non_nullable
as bool?,
));
}
}
/// @nodoc
mixin _$BrowseState {
RequestStatus get topCategorySt; RequestStatus get allCategorySt; RequestStatus get searchHistorySt; List<String> get searchHistory; bool get isActive;
/// Create a copy of BrowseState
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
$BrowseStateCopyWith<BrowseState> get copyWith => _$BrowseStateCopyWithImpl<BrowseState>(this as BrowseState, _$identity);
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is BrowseState&&(identical(other.topCategorySt, topCategorySt) || other.topCategorySt == topCategorySt)&&(identical(other.allCategorySt, allCategorySt) || other.allCategorySt == allCategorySt)&&(identical(other.searchHistorySt, searchHistorySt) || other.searchHistorySt == searchHistorySt)&&const DeepCollectionEquality().equals(other.searchHistory, searchHistory)&&(identical(other.isActive, isActive) || other.isActive == isActive));
}
@override
int get hashCode => Object.hash(runtimeType,topCategorySt,allCategorySt,searchHistorySt,const DeepCollectionEquality().hash(searchHistory),isActive);
@override
String toString() {
return 'BrowseState(topCategorySt: $topCategorySt, allCategorySt: $allCategorySt, searchHistorySt: $searchHistorySt, searchHistory: $searchHistory, isActive: $isActive)';
}
}
/// @nodoc
abstract mixin class $BrowseStateCopyWith<$Res> {
factory $BrowseStateCopyWith(BrowseState value, $Res Function(BrowseState) _then) = _$BrowseStateCopyWithImpl;
@useResult
$Res call({
RequestStatus topCategorySt, RequestStatus allCategorySt, RequestStatus searchHistorySt, List<String> searchHistory, bool isActive
});
}
/// @nodoc
class _$BrowseStateCopyWithImpl<$Res>
implements $BrowseStateCopyWith<$Res> {
_$BrowseStateCopyWithImpl(this._self, this._then);
final BrowseState _self;
final $Res Function(BrowseState) _then;
/// Create a copy of BrowseState
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? topCategorySt = null,Object? allCategorySt = null,Object? searchHistorySt = null,Object? searchHistory = null,Object? isActive = null,}) {
return _then(_self.copyWith(
topCategorySt: null == topCategorySt ? _self.topCategorySt : topCategorySt // ignore: cast_nullable_to_non_nullable
as RequestStatus,allCategorySt: null == allCategorySt ? _self.allCategorySt : allCategorySt // ignore: cast_nullable_to_non_nullable
as RequestStatus,searchHistorySt: null == searchHistorySt ? _self.searchHistorySt : searchHistorySt // ignore: cast_nullable_to_non_nullable
as RequestStatus,searchHistory: null == searchHistory ? _self.searchHistory : searchHistory // ignore: cast_nullable_to_non_nullable
as List<String>,isActive: null == isActive ? _self.isActive : isActive // ignore: cast_nullable_to_non_nullable
as bool,
));
}
}
/// Adds pattern-matching-related methods to [BrowseState].
extension BrowseStatePatterns on BrowseState {
/// A variant of `map` that fallback to returning `orElse`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _BrowseState value)? $default,{required TResult orElse(),}){
final _that = this;
switch (_that) {
case _BrowseState() when $default != null:
return $default(_that);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// Callbacks receives the raw object, upcasted.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case final Subclass2 value:
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _BrowseState value) $default,){
final _that = this;
switch (_that) {
case _BrowseState():
return $default(_that);case _:
throw StateError('Unexpected subclass');
}
}
/// A variant of `map` that fallback to returning `null`.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case final Subclass value:
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _BrowseState value)? $default,){
final _that = this;
switch (_that) {
case _BrowseState() when $default != null:
return $default(_that);case _:
return null;
}
}
/// A variant of `when` that fallback to an `orElse` callback.
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return orElse();
/// }
/// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( RequestStatus topCategorySt, RequestStatus allCategorySt, RequestStatus searchHistorySt, List<String> searchHistory, bool isActive)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _BrowseState() when $default != null:
return $default(_that.topCategorySt,_that.allCategorySt,_that.searchHistorySt,_that.searchHistory,_that.isActive);case _:
return orElse();
}
}
/// A `switch`-like method, using callbacks.
///
/// As opposed to `map`, this offers destructuring.
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case Subclass2(:final field2):
/// return ...;
/// }
/// ```
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( RequestStatus topCategorySt, RequestStatus allCategorySt, RequestStatus searchHistorySt, List<String> searchHistory, bool isActive) $default,) {final _that = this;
switch (_that) {
case _BrowseState():
return $default(_that.topCategorySt,_that.allCategorySt,_that.searchHistorySt,_that.searchHistory,_that.isActive);case _:
throw StateError('Unexpected subclass');
}
}
/// A variant of `when` that fallback to returning `null`
///
/// It is equivalent to doing:
/// ```dart
/// switch (sealedClass) {
/// case Subclass(:final field):
/// return ...;
/// case _:
/// return null;
/// }
/// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( RequestStatus topCategorySt, RequestStatus allCategorySt, RequestStatus searchHistorySt, List<String> searchHistory, bool isActive)? $default,) {final _that = this;
switch (_that) {
case _BrowseState() when $default != null:
return $default(_that.topCategorySt,_that.allCategorySt,_that.searchHistorySt,_that.searchHistory,_that.isActive);case _:
return null;
}
}
}
/// @nodoc
class _BrowseState implements BrowseState {
const _BrowseState({this.topCategorySt = RequestStatus.initial, this.allCategorySt = RequestStatus.initial, this.searchHistorySt = RequestStatus.initial, final List<String> searchHistory = const [], this.isActive = false}): _searchHistory = searchHistory;
@override@JsonKey() final RequestStatus topCategorySt;
@override@JsonKey() final RequestStatus allCategorySt;
@override@JsonKey() final RequestStatus searchHistorySt;
final List<String> _searchHistory;
@override@JsonKey() List<String> get searchHistory {
if (_searchHistory is EqualUnmodifiableListView) return _searchHistory;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_searchHistory);
}
@override@JsonKey() final bool isActive;
/// Create a copy of BrowseState
/// with the given fields replaced by the non-null parameter values.
@override @JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$BrowseStateCopyWith<_BrowseState> get copyWith => __$BrowseStateCopyWithImpl<_BrowseState>(this, _$identity);
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _BrowseState&&(identical(other.topCategorySt, topCategorySt) || other.topCategorySt == topCategorySt)&&(identical(other.allCategorySt, allCategorySt) || other.allCategorySt == allCategorySt)&&(identical(other.searchHistorySt, searchHistorySt) || other.searchHistorySt == searchHistorySt)&&const DeepCollectionEquality().equals(other._searchHistory, _searchHistory)&&(identical(other.isActive, isActive) || other.isActive == isActive));
}
@override
int get hashCode => Object.hash(runtimeType,topCategorySt,allCategorySt,searchHistorySt,const DeepCollectionEquality().hash(_searchHistory),isActive);
@override
String toString() {
return 'BrowseState(topCategorySt: $topCategorySt, allCategorySt: $allCategorySt, searchHistorySt: $searchHistorySt, searchHistory: $searchHistory, isActive: $isActive)';
}
}
/// @nodoc
abstract mixin class _$BrowseStateCopyWith<$Res> implements $BrowseStateCopyWith<$Res> {
factory _$BrowseStateCopyWith(_BrowseState value, $Res Function(_BrowseState) _then) = __$BrowseStateCopyWithImpl;
@override @useResult
$Res call({
RequestStatus topCategorySt, RequestStatus allCategorySt, RequestStatus searchHistorySt, List<String> searchHistory, bool isActive
});
}
/// @nodoc
class __$BrowseStateCopyWithImpl<$Res>
implements _$BrowseStateCopyWith<$Res> {
__$BrowseStateCopyWithImpl(this._self, this._then);
final _BrowseState _self;
final $Res Function(_BrowseState) _then;
/// Create a copy of BrowseState
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? topCategorySt = null,Object? allCategorySt = null,Object? searchHistorySt = null,Object? searchHistory = null,Object? isActive = null,}) {
return _then(_BrowseState(
topCategorySt: null == topCategorySt ? _self.topCategorySt : topCategorySt // ignore: cast_nullable_to_non_nullable
as RequestStatus,allCategorySt: null == allCategorySt ? _self.allCategorySt : allCategorySt // ignore: cast_nullable_to_non_nullable
as RequestStatus,searchHistorySt: null == searchHistorySt ? _self.searchHistorySt : searchHistorySt // ignore: cast_nullable_to_non_nullable
as RequestStatus,searchHistory: null == searchHistory ? _self._searchHistory : searchHistory // ignore: cast_nullable_to_non_nullable
as List<String>,isActive: null == isActive ? _self.isActive : isActive // ignore: cast_nullable_to_non_nullable
as bool,
));
}
}
// dart format on

View File

@@ -0,0 +1,14 @@
part of 'browse_bloc.dart';
@freezed
class BrowseEvent with _$BrowseEvent {
const factory BrowseEvent.started() = _Started;
const factory BrowseEvent.getTopCategories() = _GetTopCategories;
const factory BrowseEvent.getAllCategories() = _GetAllCategories;
const factory BrowseEvent.getSearchHistory() = _GetSearchHistory;
const factory BrowseEvent.focusChanged(bool? isActive) = _FocusChanged;
}

View File

@@ -0,0 +1,12 @@
part of 'browse_bloc.dart';
@freezed
abstract class BrowseState with _$BrowseState {
const factory BrowseState({
@Default(RequestStatus.initial) RequestStatus topCategorySt,
@Default(RequestStatus.initial) RequestStatus allCategorySt,
@Default(RequestStatus.initial) RequestStatus searchHistorySt,
@Default([]) List<String> searchHistory,
@Default(false) bool isActive,
}) = _BrowseState;
}

View File

@@ -1,3 +1,4 @@
import '../../../../../food_delivery_client.dart';
class BrowsePage extends StatelessWidget {
@@ -5,8 +6,11 @@ class BrowsePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return WLayout(
child: Scaffold(body: Center(child: Text(context.loc.mobileNumber))),
return BlocProvider(
create: (context) => sl<BrowseBloc>()
..add(BrowseEvent.getTopCategories())
..add(BrowseEvent.getAllCategories()),
child: WLayout(child: Scaffold(body: WBrowseBody())),
);
}
}

View File

@@ -0,0 +1,52 @@
import '../../../../../../food_delivery_client.dart';
class WAllCategories extends StatelessWidget {
const WAllCategories({super.key});
@override
Widget build(BuildContext context) {
return BlocBuilder<BrowseBloc, BrowseState>(
builder: (context, state) {
if (state.allCategorySt.isLoaded()) {
return WAllCategoriesBody();
}
return WAllCategoriesSkeletonizer();
},
);
}
}
class WAllCategoriesBody extends StatelessWidget {
const WAllCategoriesBody({super.key});
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
25.verticalSpace,
Text(
context.loc.allCategories,
style: AppTextStyles.size24Medium.copyWith(height: 36 / 24),
),
11.verticalSpace,
GridView.builder(
itemCount: 10,
shrinkWrap: true,
padding: EdgeInsets.zero,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: 15,
crossAxisSpacing: 10,
mainAxisExtent: 140,
),
itemBuilder: (context, index) {
return WBrowseItem();
},
),
],
);
}
}

View File

@@ -0,0 +1,41 @@
import '../../../../../../food_delivery_client.dart';
class WAllCategoriesSkeletonizer extends StatelessWidget {
const WAllCategoriesSkeletonizer({
super.key,
});
@override
Widget build(BuildContext context) {
return Skeletonizer(
enabled: true,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
25.verticalSpace,
Text(
context.loc.allCategories,
style: AppTextStyles.size24Medium.copyWith(height: 36 / 24),
),
11.verticalSpace,
GridView.builder(
itemCount: 10,
shrinkWrap: true,
padding: EdgeInsets.zero,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: 15,
crossAxisSpacing: 10,
mainAxisExtent: 140,
),
itemBuilder: (context, index) {
return WBrowseSkeletonizerItem();
},
),
],
),
);
}
}

View File

@@ -0,0 +1,117 @@
import '../../../../../../food_delivery_client.dart';
class WBrowseBody extends StatefulWidget {
const WBrowseBody({super.key});
@override
State<WBrowseBody> createState() => _WBrowseBodyState();
}
class _WBrowseBodyState extends State<WBrowseBody> {
late FocusNode _focusNode;
late TextEditingController _controller;
@override
void initState() {
_controller = TextEditingController();
_focusNode = FocusNode();
_focusNode.addListener(() {
context.read<BrowseBloc>().add(BrowseEvent.focusChanged(true));
});
super.initState();
}
void listener() {
_focusNode.addListener(() {
log("${_focusNode.hasFocus}");
setState(() {});
});
}
@override
void dispose() {
_controller.dispose();
_focusNode.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return BlocBuilder<BrowseBloc, BrowseState>(
builder: (context, state) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
DecoratedBox(
decoration: BoxDecoration(color: AppColors.cFFFFFF),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
10.verticalSpace,
Row(
spacing: 15,
children: [
/*
InkWell(
onTap: () {},
borderRadius: AppUtils.kBorderRadius25,
child: Ink(
height: 44,
width: 44,
decoration: BoxDecoration(
color: AppColors.cEEEEEE,
borderRadius: AppUtils.kBorderRadius25,
),
child: SizedBox(
height: 44,
width: 44,
child: SvgPicture.asset(
AppIcons.icBack,
height: 20,
width: 20,
).paddingAll(10),
),
),
),
*/
Expanded(
child: AppTextFormField(
focusNode: _focusNode,
controller: _controller,
prefixIcon: SvgPicture.asset(AppIcons.icSearch),
hintText: context.loc.categoriesShort,
hintTextStyle: AppTextStyles.size16Medium.copyWith(
color: AppColors.c660000,
),
),
),
],
),
15.verticalSpace,
],
),
),
Expanded(
child: RefreshIndicator.adaptive(
onRefresh: () async {
context.read<BrowseBloc>()
..add(BrowseEvent.getTopCategories())
..add(BrowseEvent.getAllCategories());
},
child: SingleChildScrollView(
child: Column(
children: [
WTopCategories(),
WAllCategories(),
40.verticalSpace,
],
),
),
),
),
],
);
},
).paddingSymmetric(horizontal: 16);
}
}

View File

@@ -0,0 +1,52 @@
import '../../../../../../food_delivery_client.dart';
class WBrowseItem extends StatelessWidget {
const WBrowseItem({
super.key,
});
@override
Widget build(BuildContext context) {
return Bounceable(
onTap: () {},
child: Ink(
decoration: BoxDecoration(
color: AppColors.cFFFFFF,
borderRadius: AppUtils.kBorderRadius15,
),
child: Column(
children: [
ClipRRect(
borderRadius: AppUtils.kBorderRadiusTop15,
child: CachedNetworkImage(
imageUrl: AppLocaleKeys.foodImageUrl,
width: context.w,
height: 96,
fit: BoxFit.cover,
),
),
SizedBox(
width: context.w,
child: DecoratedBox(
decoration: BoxDecoration(
borderRadius: AppUtils.kBorderRadiusBottom15,
border: Border.all(
color: AppColors.cE8E8E8,
width: 1,
),
),
child: Text(
"Restaurant Rewards",
textAlign: TextAlign.center,
style: AppTextStyles.size16Regular.copyWith(
height: 20 / 16,
),
).paddingSymmetric(horizontal: 30),
),
),
],
),
),
);
}
}

View File

@@ -0,0 +1,52 @@
import '../../../../../../food_delivery_client.dart';
class WBrowseSkeletonizerItem extends StatelessWidget {
const WBrowseSkeletonizerItem({
super.key,
});
@override
Widget build(BuildContext context) {
return Bounceable(
onTap: () {},
child: Ink(
decoration: BoxDecoration(
color: AppColors.cFFFFFF,
borderRadius: AppUtils.kBorderRadius15,
),
child: Column(
children: [
ClipRRect(
borderRadius: AppUtils.kBorderRadiusTop15,
child: CachedNetworkImage(
imageUrl: AppLocaleKeys.foodImageUrl,
width: context.w,
height: 96,
fit: BoxFit.cover,
),
),
SizedBox(
width: context.w,
child: DecoratedBox(
decoration: BoxDecoration(
borderRadius: AppUtils.kBorderRadiusBottom15,
border: Border.all(
color: AppColors.cE8E8E8,
width: 1,
),
),
child: Text(
"Restaurant Rewards",
textAlign: TextAlign.center,
style: AppTextStyles.size16Regular.copyWith(
height: 20 / 16,
),
).paddingSymmetric(horizontal: 30),
),
),
],
),
),
);
}
}

View File

@@ -0,0 +1,52 @@
import '../../../../../../food_delivery_client.dart';
class WTopCategories extends StatelessWidget {
const WTopCategories({super.key});
@override
Widget build(BuildContext context) {
return BlocBuilder<BrowseBloc, BrowseState>(
builder: (context, state) {
if (state.topCategorySt.isLoaded()) {
return WTopCategoriesBody();
}
return WTopCategoriesSkeletonizer();
},
);
}
}
class WTopCategoriesBody extends StatelessWidget {
const WTopCategoriesBody({super.key});
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
context.loc.topCategories,
style: AppTextStyles.size24Medium.copyWith(height: 36 / 24),
),
11.verticalSpace,
GridView.builder(
itemCount: 6,
shrinkWrap: true,
padding: EdgeInsets.zero,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: 15,
crossAxisSpacing: 10,
mainAxisExtent: 140,
),
itemBuilder: (context, index) {
return WBrowseItem();
},
),
],
);
}
}

View File

@@ -0,0 +1,40 @@
import '../../../../../../food_delivery_client.dart';
class WTopCategoriesSkeletonizer extends StatelessWidget {
const WTopCategoriesSkeletonizer({super.key});
@override
Widget build(BuildContext context) {
return Skeletonizer(
enabled: true,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
context.loc.topCategories,
style: AppTextStyles.size24Medium.copyWith(height: 36 / 24),
),
11.verticalSpace,
GridView.builder(
itemCount: 6,
shrinkWrap: true,
padding: EdgeInsets.zero,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: 15,
crossAxisSpacing: 10,
mainAxisExtent: 140,
),
itemBuilder: (context, index) {
return WBrowseSkeletonizerItem();
},
),
],
),
);
}
}

View File

@@ -0,0 +1,10 @@
import '../../../../../food_delivery_client.dart';
class SearchPage extends StatelessWidget {
const SearchPage({super.key});
@override
Widget build(BuildContext context) {
return WLayout(child: Scaffold());
}
}

View File

@@ -0,0 +1,61 @@
import '../../../../food_delivery_client.dart';
class AppButton extends StatelessWidget {
const AppButton({
super.key,
required this.name,
required this.onPressed,
this.margin,
this.backgroundColor,
this.borderRadius,
this.height,
this.textColor,
this.width,
this.action,
this.trailing,
this.mainAxisAlignment,
});
final String name;
final VoidCallback onPressed;
final EdgeInsets? margin;
final Color? backgroundColor;
final Color? textColor;
final double? borderRadius;
final double? width;
final double? height;
final Widget? action;
final Widget? trailing;
final MainAxisAlignment? mainAxisAlignment;
@override
Widget build(BuildContext context) {
return Bounceable(
onTap: onPressed,
duration: TimeDelayConst.durationMill150,
child: Container(
width: width ?? double.infinity,
height: height ?? 55,
margin: margin,
alignment: Alignment.center,
padding: const EdgeInsets.symmetric(horizontal: 16),
decoration: BoxDecoration(
color: backgroundColor ?? AppColors.c000000,
borderRadius: BorderRadius.circular(borderRadius ?? 0),
),
child: Row(
mainAxisAlignment: mainAxisAlignment ?? MainAxisAlignment.center,
children: [
action ?? AppUtils.kSizedBox,
Text(name, style: AppTextStyles.size16Bold.copyWith(
color: AppColors.cFFFFFF
)),
trailing ?? AppUtils.kSizedBox,
],
),
),
);
}
}

View File

@@ -0,0 +1,44 @@
import '../../../../food_delivery_client.dart';
class AppListTile extends StatelessWidget {
const AppListTile({
super.key,
required this.onPressed,
required this.isSelected,
required this.svgPath,
required this.title,
this.contentPadding,
this.leading,
this.titleWidget,
this.trailing,
this.titleTextStyle,
this.subTitle,
});
final VoidCallback onPressed;
final bool isSelected;
final String svgPath;
final String title;
final EdgeInsets? contentPadding;
final Widget? leading;
final Widget? titleWidget;
final Widget? trailing;
final TextStyle? titleTextStyle;
final Widget? subTitle;
@override
Widget build(BuildContext context) {
return ListTile(
onTap: onPressed,
subtitle: subTitle,
contentPadding:
contentPadding ?? EdgeInsetsGeometry.only(left: 20, right: 27),
leading: leading ?? SvgPicture.asset(svgPath),
title:
titleWidget ??
Text(title, style: titleTextStyle ?? AppTextStyles.size16Regular),
trailing:
trailing ?? (isSelected ? SvgPicture.asset(AppIcons.icCheck) : null),
);
}
}

View File

@@ -0,0 +1,95 @@
import '../../../../food_delivery_client.dart';
class AppTextFormField extends StatelessWidget {
AppTextFormField({
super.key,
this.maxLines,
this.minLines,
this.textStyle,
this.onTap,
this.textAlign,
this.onChanged,
this.inputFormatters,
this.keyBoardType,
this.fillColor,
this.hintText,
this.hintTextStyle,
this.obscureText = false,
required this.controller,
this.prefixIcon,
this.prefixSvgPath, this.focusNode,
});
final int? maxLines;
final int? minLines;
final TextStyle? textStyle;
final VoidCallback? onTap;
final TextAlign? textAlign;
final TextEditingController controller;
final Function(String? value)? onChanged;
final List<TextInputFormatter>? inputFormatters;
final TextInputType? keyBoardType;
FormFieldValidator<String>? validator;
final bool obscureText;
final Color? fillColor;
final String? hintText;
final TextStyle? hintTextStyle;
late final Widget? prefixIcon;
final String? prefixSvgPath;
final FocusNode? focusNode;
@override
Widget build(BuildContext context) {
return TextFormField(
enabled: true,
autofocus: true,
maxLines: maxLines ?? 1,
minLines: minLines ?? 1,
onChanged: onChanged,
focusNode: focusNode,
inputFormatters: inputFormatters,
keyboardType: keyBoardType,
style: textStyle ?? AppTextStyles.size16Regular,
onTap: onTap,
textAlign: textAlign ?? TextAlign.start,
controller: controller,
validator: validator,
autovalidateMode: AutovalidateMode.onUserInteraction,
decoration: InputDecoration(
enabled: true,
filled: true,
fillColor: fillColor ?? AppColors.cEEEEEE,
hintText: hintText,
hintStyle: hintTextStyle,
prefixIconConstraints: BoxConstraints(
minHeight: 0,
maxHeight: 24,
maxWidth: 34,
minWidth: 0,
),
prefixIcon: prefixIcon?.paddingOnly(left: 10).paddingAll(3),
contentPadding: EdgeInsets.symmetric(vertical: 12, horizontal: 12),
border: OutlineInputBorder(
borderRadius: AppUtils.kBorderRadius40,
borderSide: BorderSide.none,
),
errorBorder: OutlineInputBorder(
borderRadius: AppUtils.kBorderRadius40,
borderSide: BorderSide.none,
),
enabledBorder: OutlineInputBorder(
borderRadius: AppUtils.kBorderRadius40,
borderSide: BorderSide.none,
),
focusedBorder: OutlineInputBorder(
borderRadius: AppUtils.kBorderRadius40,
borderSide: BorderSide.none,
),
disabledBorder: OutlineInputBorder(
borderRadius: AppUtils.kBorderRadius40,
borderSide: BorderSide.none,
),
),
);
}
}

View File

@@ -0,0 +1,37 @@
import '../../../../../../food_delivery_client.dart';
class WCustomModalBottomSheet extends StatelessWidget {
const WCustomModalBottomSheet({super.key, required this.child});
final Widget child;
@override
Widget build(BuildContext context) {
return Material(
color: AppColors.cFFFFFF,
borderRadius: AppUtils.kBorderRadiusTop20,
child: SafeArea(
child: SizedBox(
width: context.w,
child: Column(
children: [
10.verticalSpace,
SizedBox(
height: 6,
width: 100,
child: DecoratedBox(
decoration: BoxDecoration(
borderRadius: AppUtils.kBorderRadius6,
color: AppColors.cE6E6E6.newWithOpacity(.6),
),
),
),
10.verticalSpace,
child,
],
),
),
),
);
}
}

View File

@@ -18,8 +18,8 @@ class WDivider extends StatelessWidget {
color: AppColors.cF6F6F6,
height: height,
thickness: height,
endIndent: 0,
indent: 0,
endIndent: endIndent??0,
indent:indent?? 0,
);
}
}

View File

@@ -3,3 +3,6 @@ export 'w_food_item.dart';
export 'w_divider.dart';
export 'w_see_all_raw.dart';
export 'w_stories_list_item.dart';
export 'w_custom_modal_bottom_sheet.dart';
export 'app_button.dart';
export 'app_list_tile.dart';

View File

@@ -9,3 +9,17 @@ export 'presentation/pages/home_page/widgets/w_offers_carouseL_slider.dart';
export 'presentation/pages/home_page/widgets/w_popular_near_you.dart';
export 'presentation/pages/home_page/widgets/w_todays_offers.dart';
export 'package:food_delivery_client/feature/home/presentation/pages/home_page/widgets/pick_it_for_free.dart';
export 'package:flutter_svg/flutter_svg.dart';
export 'package:food_delivery_client/feature/home/presentation/pages/categories_page/categories_page.dart';
export 'package:food_delivery_client/feature/home/presentation/pages/home_page/widgets/w_rating_btm_sheet.dart';
export 'package:food_delivery_client/feature/home/presentation/pages/filters_page/filters_page.dart';
export 'presentation/mixins/filter_mixins.dart';
export 'package:food_delivery_client/feature/home/presentation/pages/filters_page/widgets/w_filter_app_bar.dart';
export 'package:food_delivery_client/feature/home/presentation/pages/filters_page/widgets/w_filters_body.dart';
export 'package:food_delivery_client/feature/home/presentation/pages/filters_page/widgets/w_delivery_duration.dart';
export 'package:food_delivery_client/feature/home/presentation/pages/filters_page/widgets/w_filter_dietary.dart';
export 'package:food_delivery_client/feature/home/presentation/pages/filters_page/widgets/w_filters_deals.dart';
export 'package:food_delivery_client/feature/home/presentation/pages/filters_page/widgets/w_filters_sort.dart';
export 'package:food_delivery_client/feature/home/presentation/pages/restaurants_by_category_page/widgets/w_restaurants_by_category_body.dart';
export 'package:food_delivery_client/feature/home/presentation/pages/restaurants_by_category_page/widgets/w_featured_stores.dart';
export 'package:food_delivery_client/feature/home/presentation/pages/restaurants_by_category_page/widgets/w_stores_list.dart';

View File

@@ -5,13 +5,36 @@ part 'home_event.dart';
part 'home_state.dart';
part 'home_bloc.freezed.dart';
@injectable
class HomeBloc extends Bloc<HomeEvent, HomeState> {
HomeBloc() : super(const HomeState()) {
on<_Changed>(_onChanged);
on<_Filtered>(_onFiltered);
on<_Rated>(_onRated);
on<_DurationChanged>(_onDurationChanged);
}
void _onChanged(_Changed event, Emitter<HomeState> emit) {
emit(state.copyWith(currentIndex: event.index));
}
void _onFiltered(_Filtered event, Emitter<HomeState> emit) {
final oldFilters = List.from(state.filters);
if (oldFilters.contains(event.filter)) {
final newFilters = oldFilters..remove(event.filter);
emit(state.copyWith(filters: newFilters));
} else {
final newFilters = oldFilters..add(event.filter);
emit(state.copyWith(filters: newFilters));
}
}
void _onRated(_Rated event, Emitter<HomeState> emit) {
emit(state.copyWith(rating: event.filter));
}
void _onDurationChanged(_DurationChanged event, Emitter<HomeState> emit) {
emit(state.copyWith(deliveryDuration: event.filter));
}
}

View File

@@ -55,12 +55,15 @@ extension HomeEventPatterns on HomeEvent {
/// }
/// ```
@optionalTypeArgs TResult maybeMap<TResult extends Object?>({TResult Function( _Started value)? started,TResult Function( _Changed value)? changed,required TResult orElse(),}){
@optionalTypeArgs TResult maybeMap<TResult extends Object?>({TResult Function( _Started value)? started,TResult Function( _Changed value)? changed,TResult Function( _DurationChanged value)? durationChanged,TResult Function( _Filtered value)? filtered,TResult Function( _Rated value)? rated,required TResult orElse(),}){
final _that = this;
switch (_that) {
case _Started() when started != null:
return started(_that);case _Changed() when changed != null:
return changed(_that);case _:
return changed(_that);case _DurationChanged() when durationChanged != null:
return durationChanged(_that);case _Filtered() when filtered != null:
return filtered(_that);case _Rated() when rated != null:
return rated(_that);case _:
return orElse();
}
@@ -78,12 +81,15 @@ return changed(_that);case _:
/// }
/// ```
@optionalTypeArgs TResult map<TResult extends Object?>({required TResult Function( _Started value) started,required TResult Function( _Changed value) changed,}){
@optionalTypeArgs TResult map<TResult extends Object?>({required TResult Function( _Started value) started,required TResult Function( _Changed value) changed,required TResult Function( _DurationChanged value) durationChanged,required TResult Function( _Filtered value) filtered,required TResult Function( _Rated value) rated,}){
final _that = this;
switch (_that) {
case _Started():
return started(_that);case _Changed():
return changed(_that);case _:
return changed(_that);case _DurationChanged():
return durationChanged(_that);case _Filtered():
return filtered(_that);case _Rated():
return rated(_that);case _:
throw StateError('Unexpected subclass');
}
@@ -100,12 +106,15 @@ return changed(_that);case _:
/// }
/// ```
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>({TResult? Function( _Started value)? started,TResult? Function( _Changed value)? changed,}){
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>({TResult? Function( _Started value)? started,TResult? Function( _Changed value)? changed,TResult? Function( _DurationChanged value)? durationChanged,TResult? Function( _Filtered value)? filtered,TResult? Function( _Rated value)? rated,}){
final _that = this;
switch (_that) {
case _Started() when started != null:
return started(_that);case _Changed() when changed != null:
return changed(_that);case _:
return changed(_that);case _DurationChanged() when durationChanged != null:
return durationChanged(_that);case _Filtered() when filtered != null:
return filtered(_that);case _Rated() when rated != null:
return rated(_that);case _:
return null;
}
@@ -122,11 +131,14 @@ return changed(_that);case _:
/// }
/// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>({TResult Function()? started,TResult Function( int index)? changed,required TResult orElse(),}) {final _that = this;
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>({TResult Function()? started,TResult Function( int index)? changed,TResult Function( String filter)? durationChanged,TResult Function( String filter)? filtered,TResult Function( List<String> filter)? rated,required TResult orElse(),}) {final _that = this;
switch (_that) {
case _Started() when started != null:
return started();case _Changed() when changed != null:
return changed(_that.index);case _:
return changed(_that.index);case _DurationChanged() when durationChanged != null:
return durationChanged(_that.filter);case _Filtered() when filtered != null:
return filtered(_that.filter);case _Rated() when rated != null:
return rated(_that.filter);case _:
return orElse();
}
@@ -144,11 +156,14 @@ return changed(_that.index);case _:
/// }
/// ```
@optionalTypeArgs TResult when<TResult extends Object?>({required TResult Function() started,required TResult Function( int index) changed,}) {final _that = this;
@optionalTypeArgs TResult when<TResult extends Object?>({required TResult Function() started,required TResult Function( int index) changed,required TResult Function( String filter) durationChanged,required TResult Function( String filter) filtered,required TResult Function( List<String> filter) rated,}) {final _that = this;
switch (_that) {
case _Started():
return started();case _Changed():
return changed(_that.index);case _:
return changed(_that.index);case _DurationChanged():
return durationChanged(_that.filter);case _Filtered():
return filtered(_that.filter);case _Rated():
return rated(_that.filter);case _:
throw StateError('Unexpected subclass');
}
@@ -165,11 +180,14 @@ return changed(_that.index);case _:
/// }
/// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>({TResult? Function()? started,TResult? Function( int index)? changed,}) {final _that = this;
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>({TResult? Function()? started,TResult? Function( int index)? changed,TResult? Function( String filter)? durationChanged,TResult? Function( String filter)? filtered,TResult? Function( List<String> filter)? rated,}) {final _that = this;
switch (_that) {
case _Started() when started != null:
return started();case _Changed() when changed != null:
return changed(_that.index);case _:
return changed(_that.index);case _DurationChanged() when durationChanged != null:
return durationChanged(_that.filter);case _Filtered() when filtered != null:
return filtered(_that.filter);case _Rated() when rated != null:
return rated(_that.filter);case _:
return null;
}
@@ -273,12 +291,216 @@ as int,
}
}
/// @nodoc
class _DurationChanged implements HomeEvent {
const _DurationChanged(this.filter);
final String filter;
/// Create a copy of HomeEvent
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$DurationChangedCopyWith<_DurationChanged> get copyWith => __$DurationChangedCopyWithImpl<_DurationChanged>(this, _$identity);
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _DurationChanged&&(identical(other.filter, filter) || other.filter == filter));
}
@override
int get hashCode => Object.hash(runtimeType,filter);
@override
String toString() {
return 'HomeEvent.durationChanged(filter: $filter)';
}
}
/// @nodoc
abstract mixin class _$DurationChangedCopyWith<$Res> implements $HomeEventCopyWith<$Res> {
factory _$DurationChangedCopyWith(_DurationChanged value, $Res Function(_DurationChanged) _then) = __$DurationChangedCopyWithImpl;
@useResult
$Res call({
String filter
});
}
/// @nodoc
class __$DurationChangedCopyWithImpl<$Res>
implements _$DurationChangedCopyWith<$Res> {
__$DurationChangedCopyWithImpl(this._self, this._then);
final _DurationChanged _self;
final $Res Function(_DurationChanged) _then;
/// Create a copy of HomeEvent
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') $Res call({Object? filter = null,}) {
return _then(_DurationChanged(
null == filter ? _self.filter : filter // ignore: cast_nullable_to_non_nullable
as String,
));
}
}
/// @nodoc
class _Filtered implements HomeEvent {
const _Filtered(this.filter);
final String filter;
/// Create a copy of HomeEvent
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$FilteredCopyWith<_Filtered> get copyWith => __$FilteredCopyWithImpl<_Filtered>(this, _$identity);
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _Filtered&&(identical(other.filter, filter) || other.filter == filter));
}
@override
int get hashCode => Object.hash(runtimeType,filter);
@override
String toString() {
return 'HomeEvent.filtered(filter: $filter)';
}
}
/// @nodoc
abstract mixin class _$FilteredCopyWith<$Res> implements $HomeEventCopyWith<$Res> {
factory _$FilteredCopyWith(_Filtered value, $Res Function(_Filtered) _then) = __$FilteredCopyWithImpl;
@useResult
$Res call({
String filter
});
}
/// @nodoc
class __$FilteredCopyWithImpl<$Res>
implements _$FilteredCopyWith<$Res> {
__$FilteredCopyWithImpl(this._self, this._then);
final _Filtered _self;
final $Res Function(_Filtered) _then;
/// Create a copy of HomeEvent
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') $Res call({Object? filter = null,}) {
return _then(_Filtered(
null == filter ? _self.filter : filter // ignore: cast_nullable_to_non_nullable
as String,
));
}
}
/// @nodoc
class _Rated implements HomeEvent {
const _Rated(final List<String> filter): _filter = filter;
final List<String> _filter;
List<String> get filter {
if (_filter is EqualUnmodifiableListView) return _filter;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_filter);
}
/// Create a copy of HomeEvent
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$RatedCopyWith<_Rated> get copyWith => __$RatedCopyWithImpl<_Rated>(this, _$identity);
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _Rated&&const DeepCollectionEquality().equals(other._filter, _filter));
}
@override
int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(_filter));
@override
String toString() {
return 'HomeEvent.rated(filter: $filter)';
}
}
/// @nodoc
abstract mixin class _$RatedCopyWith<$Res> implements $HomeEventCopyWith<$Res> {
factory _$RatedCopyWith(_Rated value, $Res Function(_Rated) _then) = __$RatedCopyWithImpl;
@useResult
$Res call({
List<String> filter
});
}
/// @nodoc
class __$RatedCopyWithImpl<$Res>
implements _$RatedCopyWith<$Res> {
__$RatedCopyWithImpl(this._self, this._then);
final _Rated _self;
final $Res Function(_Rated) _then;
/// Create a copy of HomeEvent
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') $Res call({Object? filter = null,}) {
return _then(_Rated(
null == filter ? _self._filter : filter // ignore: cast_nullable_to_non_nullable
as List<String>,
));
}
}
/// @nodoc
mixin _$HomeState {
int get currentIndex;
int get currentIndex; String get deliveryDuration; List get filters; List<String> get rating;
/// Create a copy of HomeState
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@@ -289,16 +511,16 @@ $HomeStateCopyWith<HomeState> get copyWith => _$HomeStateCopyWithImpl<HomeState>
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is HomeState&&(identical(other.currentIndex, currentIndex) || other.currentIndex == currentIndex));
return identical(this, other) || (other.runtimeType == runtimeType&&other is HomeState&&(identical(other.currentIndex, currentIndex) || other.currentIndex == currentIndex)&&(identical(other.deliveryDuration, deliveryDuration) || other.deliveryDuration == deliveryDuration)&&const DeepCollectionEquality().equals(other.filters, filters)&&const DeepCollectionEquality().equals(other.rating, rating));
}
@override
int get hashCode => Object.hash(runtimeType,currentIndex);
int get hashCode => Object.hash(runtimeType,currentIndex,deliveryDuration,const DeepCollectionEquality().hash(filters),const DeepCollectionEquality().hash(rating));
@override
String toString() {
return 'HomeState(currentIndex: $currentIndex)';
return 'HomeState(currentIndex: $currentIndex, deliveryDuration: $deliveryDuration, filters: $filters, rating: $rating)';
}
@@ -309,7 +531,7 @@ abstract mixin class $HomeStateCopyWith<$Res> {
factory $HomeStateCopyWith(HomeState value, $Res Function(HomeState) _then) = _$HomeStateCopyWithImpl;
@useResult
$Res call({
int currentIndex
int currentIndex, String deliveryDuration, List filters, List<String> rating
});
@@ -326,10 +548,13 @@ class _$HomeStateCopyWithImpl<$Res>
/// Create a copy of HomeState
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? currentIndex = null,}) {
@pragma('vm:prefer-inline') @override $Res call({Object? currentIndex = null,Object? deliveryDuration = null,Object? filters = null,Object? rating = null,}) {
return _then(_self.copyWith(
currentIndex: null == currentIndex ? _self.currentIndex : currentIndex // ignore: cast_nullable_to_non_nullable
as int,
as int,deliveryDuration: null == deliveryDuration ? _self.deliveryDuration : deliveryDuration // ignore: cast_nullable_to_non_nullable
as String,filters: null == filters ? _self.filters : filters // ignore: cast_nullable_to_non_nullable
as List,rating: null == rating ? _self.rating : rating // ignore: cast_nullable_to_non_nullable
as List<String>,
));
}
@@ -414,10 +639,10 @@ return $default(_that);case _:
/// }
/// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( int currentIndex)? $default,{required TResult orElse(),}) {final _that = this;
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( int currentIndex, String deliveryDuration, List filters, List<String> rating)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _HomeState() when $default != null:
return $default(_that.currentIndex);case _:
return $default(_that.currentIndex,_that.deliveryDuration,_that.filters,_that.rating);case _:
return orElse();
}
@@ -435,10 +660,10 @@ return $default(_that.currentIndex);case _:
/// }
/// ```
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( int currentIndex) $default,) {final _that = this;
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( int currentIndex, String deliveryDuration, List filters, List<String> rating) $default,) {final _that = this;
switch (_that) {
case _HomeState():
return $default(_that.currentIndex);case _:
return $default(_that.currentIndex,_that.deliveryDuration,_that.filters,_that.rating);case _:
throw StateError('Unexpected subclass');
}
@@ -455,10 +680,10 @@ return $default(_that.currentIndex);case _:
/// }
/// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( int currentIndex)? $default,) {final _that = this;
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( int currentIndex, String deliveryDuration, List filters, List<String> rating)? $default,) {final _that = this;
switch (_that) {
case _HomeState() when $default != null:
return $default(_that.currentIndex);case _:
return $default(_that.currentIndex,_that.deliveryDuration,_that.filters,_that.rating);case _:
return null;
}
@@ -470,10 +695,25 @@ return $default(_that.currentIndex);case _:
class _HomeState implements HomeState {
const _HomeState({this.currentIndex = 0});
const _HomeState({this.currentIndex = 0, this.deliveryDuration = "60+", final List filters = const [], final List<String> rating = const []}): _filters = filters,_rating = rating;
@override@JsonKey() final int currentIndex;
@override@JsonKey() final String deliveryDuration;
final List _filters;
@override@JsonKey() List get filters {
if (_filters is EqualUnmodifiableListView) return _filters;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_filters);
}
final List<String> _rating;
@override@JsonKey() List<String> get rating {
if (_rating is EqualUnmodifiableListView) return _rating;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_rating);
}
/// Create a copy of HomeState
/// with the given fields replaced by the non-null parameter values.
@@ -485,16 +725,16 @@ _$HomeStateCopyWith<_HomeState> get copyWith => __$HomeStateCopyWithImpl<_HomeSt
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _HomeState&&(identical(other.currentIndex, currentIndex) || other.currentIndex == currentIndex));
return identical(this, other) || (other.runtimeType == runtimeType&&other is _HomeState&&(identical(other.currentIndex, currentIndex) || other.currentIndex == currentIndex)&&(identical(other.deliveryDuration, deliveryDuration) || other.deliveryDuration == deliveryDuration)&&const DeepCollectionEquality().equals(other._filters, _filters)&&const DeepCollectionEquality().equals(other._rating, _rating));
}
@override
int get hashCode => Object.hash(runtimeType,currentIndex);
int get hashCode => Object.hash(runtimeType,currentIndex,deliveryDuration,const DeepCollectionEquality().hash(_filters),const DeepCollectionEquality().hash(_rating));
@override
String toString() {
return 'HomeState(currentIndex: $currentIndex)';
return 'HomeState(currentIndex: $currentIndex, deliveryDuration: $deliveryDuration, filters: $filters, rating: $rating)';
}
@@ -505,7 +745,7 @@ abstract mixin class _$HomeStateCopyWith<$Res> implements $HomeStateCopyWith<$Re
factory _$HomeStateCopyWith(_HomeState value, $Res Function(_HomeState) _then) = __$HomeStateCopyWithImpl;
@override @useResult
$Res call({
int currentIndex
int currentIndex, String deliveryDuration, List filters, List<String> rating
});
@@ -522,10 +762,13 @@ class __$HomeStateCopyWithImpl<$Res>
/// Create a copy of HomeState
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? currentIndex = null,}) {
@override @pragma('vm:prefer-inline') $Res call({Object? currentIndex = null,Object? deliveryDuration = null,Object? filters = null,Object? rating = null,}) {
return _then(_HomeState(
currentIndex: null == currentIndex ? _self.currentIndex : currentIndex // ignore: cast_nullable_to_non_nullable
as int,
as int,deliveryDuration: null == deliveryDuration ? _self.deliveryDuration : deliveryDuration // ignore: cast_nullable_to_non_nullable
as String,filters: null == filters ? _self._filters : filters // ignore: cast_nullable_to_non_nullable
as List,rating: null == rating ? _self._rating : rating // ignore: cast_nullable_to_non_nullable
as List<String>,
));
}

View File

@@ -4,5 +4,8 @@ part of 'home_bloc.dart';
class HomeEvent with _$HomeEvent {
const factory HomeEvent.started() = _Started;
const factory HomeEvent.changed(int index) = _Changed;
const factory HomeEvent.durationChanged(String filter) = _DurationChanged;
const factory HomeEvent.filtered(String filter) = _Filtered;
const factory HomeEvent.rated(List<String> filter) = _Rated;
}

View File

@@ -3,6 +3,10 @@ part of 'home_bloc.dart';
@freezed
abstract class HomeState with _$HomeState {
const factory HomeState({
@Default(0) int currentIndex
}) = _HomeState;
@Default(0) int currentIndex,
@Default("60+") String deliveryDuration,
@Default([]) List filters,
@Default([]) List<String> rating
}) = _HomeState;
}

View File

@@ -0,0 +1,20 @@
import '../../../../core/theme/app_icons.dart';
mixin FilterMixins {
final List<String> deliveryDurations = ["30", "45", "60", "60+"];
final List<String> filterSortSvgs = [
AppIcons.icPicked,
AppIcons.icMostPopular,
AppIcons.icStar,
AppIcons.icDeliveryTime,
];
final List<String> filterDietary = [
AppIcons.icVegetarian,
AppIcons.icVegen,
AppIcons.icGlutenFree,
AppIcons.icAllergyFriendly,
];
final List<String> filterDeals = [AppIcons.icDeals, AppIcons.icBestOverall];
}

View File

@@ -59,7 +59,12 @@ class CategoriesPage extends StatelessWidget with CategoriesMixin {
childAspectRatio: 78 / 100,
),
itemBuilder: (context, index) => WCategoryItem(
onTap: () {},
onTap: () {
context.push(
Routes.restaurantsByCategory,
extra: _titles[index],
);
},
imgUrl: images[index],
text: _titles[index],
),

View File

@@ -0,0 +1,26 @@
import '../../../../../food_delivery_client.dart';
class FiltersPage extends StatefulWidget {
const FiltersPage({super.key, required this.homeBloc});
final HomeBloc homeBloc;
@override
State<FiltersPage> createState() => _FiltersPageState();
}
class _FiltersPageState extends State<FiltersPage> {
@override
Widget build(BuildContext context) {
return BlocProvider.value(
value: widget.homeBloc,
child: BlocBuilder<HomeBloc, HomeState>(
builder: (context, state) {
return WFiltersBody();
},
),
);
}
}

View File

@@ -0,0 +1,84 @@
import '../../../../../../food_delivery_client.dart';
class WDeliveryDuration extends StatelessWidget with FilterMixins {
WDeliveryDuration({super.key});
@override
Widget build(BuildContext context) {
return BlocBuilder<HomeBloc, HomeState>(
builder: (context, state) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
context.loc.delivery,
style: AppTextStyles.size18Medium,
).paddingSymmetric(horizontal: 20),
15.verticalSpace,
SizedBox(
height: 60,
child: Stack(
alignment: AlignmentGeometry.center,
children: [
SizedBox(
height: 40,
width: context.w,
child: DecoratedBox(
decoration: BoxDecoration(
borderRadius: AppUtils.kBorderRadius8,
color: AppColors.cE6E6E6.newWithOpacity(.6),
),
),
),
Material(
color: AppColors.cTransparent,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: List.generate(deliveryDurations.length, (
index,
) {
final isActive =
state.deliveryDuration == deliveryDurations[index];
return InkWell(
onTap: () {
context.read<HomeBloc>().add(
HomeEvent.durationChanged(
deliveryDurations[index],
),
);
},
borderRadius: AppUtils.kBorderRadius40,
child: Ink(
height: 60,
width: 60,
decoration: BoxDecoration(
color: isActive
? AppColors.c34A853
: AppColors.cTransparent,
borderRadius: AppUtils.kBorderRadius40,
),
child: Center(
child: Text(
deliveryDurations[index],
style: AppTextStyles.size16Medium.copyWith(
color: isActive
? AppColors.cFFFFFF
: AppColors.c000000,
),
),
),
),
);
}),
),
),
],
),
).paddingSymmetric(horizontal: 20),
25.verticalSpace,
],
);
},
);
}
}

View File

@@ -0,0 +1,25 @@
import '../../../../../../food_delivery_client.dart';
class WFiltersAppBar extends StatelessWidget {
const WFiltersAppBar({super.key});
@override
Widget build(BuildContext context) {
return AppBar(
centerTitle: true,
elevation: 30,
bottomOpacity: 1,
scrolledUnderElevation: 10,
backgroundColor: AppColors.cFFFFFF,
surfaceTintColor: AppColors.cTransparent,
useDefaultSemanticsOrder: true,
leading: IconButton(
onPressed: () {
context.pop();
},
icon: SvgPicture.asset(AppIcons.icClose),
),
title: Text(context.loc.allCategories, style: AppTextStyles.size20Medium),
);
}
}

View File

@@ -0,0 +1,38 @@
import '../../../../../../food_delivery_client.dart';
class WFilterDietary extends StatelessWidget with FilterMixins {
WFilterDietary({super.key});
@override
Widget build(BuildContext context) {
final List<String> dietaryTitles = [
context.loc.vegetarian,
context.loc.vegan,
context.loc.glutenFree,
context.loc.allergyFriendly,
];
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
25.verticalSpace,
Text(
context.loc.dietary,
style: AppTextStyles.size18Medium,
).paddingSymmetric(horizontal: 20),
15.verticalSpace,
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: List.generate(4, (index) {
return AppListTile(
onPressed: () {},
isSelected: false,
leading: Image.asset(filterDietary[index], height: 30, width: 30),
svgPath: filterDietary[index],
title: dietaryTitles[index],
);
}),
),
],
);
}
}

View File

@@ -0,0 +1,42 @@
import '../../../../../../food_delivery_client.dart';
class WFiltersBody extends StatelessWidget {
const WFiltersBody({super.key});
@override
Widget build(BuildContext context) {
return BlocBuilder<HomeBloc, HomeState>(
builder: (context, state) {
return WLayout(
child: Scaffold(
appBar: PreferredSize(
preferredSize: Size.fromHeight(56),
child: WFiltersAppBar(),
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: SingleChildScrollView(
scrollDirection: Axis.vertical,
physics: const AlwaysScrollableScrollPhysics(),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
18.verticalSpace,
WDeliveryDuration(),
WFiltersSort(),
WFiltersDeals(),
WFilterDietary(),
],
),
),
),
],
),
),
);
},
);
}
}

View File

@@ -0,0 +1,59 @@
import 'package:flutter/cupertino.dart';
import '../../../../../../food_delivery_client.dart';
class WFiltersDeals extends StatefulWidget {
const WFiltersDeals({super.key});
@override
State<WFiltersDeals> createState() => _WFiltersDealsState();
}
class _WFiltersDealsState extends State<WFiltersDeals> with FilterMixins {
List<bool> values = [false, false];
@override
Widget build(BuildContext context) {
final List<String> dealsTitle = [
context.loc.deals,
context.loc.bestOverall,
];
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
25.verticalSpace,
Text(
"From Uber eats",
style: AppTextStyles.size18Medium,
).paddingSymmetric(horizontal: 20),
15.verticalSpace,
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: List.generate(2, (index) {
return AppListTile(
onPressed: () {
setState(() {
values[index] = !values[index];
});
},
isSelected: false,
leading: index == 0
? SvgPicture.asset(filterDeals[index], height: 30, width: 30)
: Image.asset(filterDeals[index], height: 30, width: 30),
svgPath: filterDeals[index],
title: dealsTitle[index],
trailing: CupertinoSwitch(
value: values[index],
onChanged: (value) {
setState(() {
values[index] = !values[index];
});
},
),
);
}),
),
],
);
}
}

View File

@@ -0,0 +1,60 @@
import '../../../../../../food_delivery_client.dart';
class WFiltersSort extends StatelessWidget with FilterMixins {
WFiltersSort({super.key});
@override
Widget build(BuildContext context) {
final List<String> filterSortTitles = [
context.loc.pickedForYouDefault,
context.loc.mostPopular,
context.loc.topRated,
context.loc.fast,
];
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
context.loc.sort,
style: AppTextStyles.size18Medium,
).paddingSymmetric(horizontal: 20),
15.verticalSpace,
Column(
children: List.generate(filterSortTitles.length, (index) {
return AppListTile(
onPressed: () {},
isSelected: false,
svgPath: filterSortSvgs[index],
title: filterSortTitles[index],
);
}),
),
// AppListTile(
// onPressed: () {},
// isSelected: true,
// svgPath: AppIcons.icPicked,
// title: context.loc.pickedForYouDefault,
// ),
// AppListTile(
// onPressed: () {},
// isSelected: false,
// svgPath: AppIcons.icMostPopular,
// title: context.loc.popular,
// ),
// AppListTile(
// onPressed: () {},
// isSelected: false,
// svgPath: AppIcons.icStar,
// title: context.loc.topRated,
// ),
// AppListTile(
// onPressed: () {},
// isSelected: false,
// svgPath: AppIcons.icClock,
// title: context.loc.fast,
// ),
],
);
}
}

View File

@@ -1,5 +1,3 @@
import 'package:food_delivery_client/feature/home/presentation/pages/categories_page/categories_page.dart';
import '../../../../../../food_delivery_client.dart';
class WDeliveryHeader extends StatelessWidget {
@@ -13,19 +11,51 @@ class WDeliveryHeader extends StatelessWidget {
context.loc.petSupplies,
context.loc.more,
];
/*
Siz uchun
Eng ommabop,
Reyting
Yetkazib berish vaqti,
Aksiyalar
*/
List titles = [
'',
context.loc.pickedForYou,
context.loc.mostPopular,
context.loc.rating,
context.loc.deliveryTime,
context.loc.deals,
];
return BlocBuilder<HomeBloc, HomeState>(
builder: (context, state) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
children: [
15.verticalSpace,
Row(
spacing: 12,
children: [
WCategoriesHeaderItem(
onTap: () {},
onTap: () {
context.push(
Routes.restaurantsByCategory,
extra: context.loc.american,
);
},
text: context.loc.american,
imageUrl: AppImages.imgAmerican,
),
WCategoriesHeaderItem(
onTap: () {},
onTap: () {
context.push(
Routes.restaurantsByCategory,
extra: context.loc.grocery,
);
},
text: context.loc.grocery,
imageUrl: AppImages.imgGrocery,
),
@@ -38,30 +68,125 @@ class WDeliveryHeader extends StatelessWidget {
padding: EdgeInsets.zero,
scrollDirection: Axis.vertical,
physics: const NeverScrollableScrollPhysics(),
keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
keyboardDismissBehavior:
ScrollViewKeyboardDismissBehavior.onDrag,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4,
crossAxisSpacing: 5,
mainAxisSpacing: 10,
childAspectRatio: 78 / 100,
mainAxisExtent: 118,
// childAspectRatio: 78 / 100,
),
itemBuilder: (context, index) => WCategoryItem(
onTap: () {
if (index == 3) {
CategoriesPage().show(context);
} else {
context.push(
Routes.restaurantsByCategory,
extra: _titles[index],
);
}
},
imgUrl: index != 3 ? _images[index] : null,
text: _titles[index],
child: index == 3
? SizedBox(height: 55, width: 55, child: Icon(Icons.more_horiz))
? SizedBox(
height: 55,
width: 55,
child: Icon(Icons.more_horiz),
)
: null,
),
),
8.verticalSpace,
WDivider()
],
).paddingSymmetric(horizontal: 15);
).paddingSymmetric(horizontal: 15),
15.verticalSpace,
SizedBox(
height: 40,
child: ListView.separated(
padding: EdgeInsets.symmetric(horizontal: 15),
scrollDirection: Axis.horizontal,
itemCount: titles.length,
physics: const AlwaysScrollableScrollPhysics(),
separatorBuilder: (context, index) => 10.horizontalSpace,
itemBuilder: (context, index) => InkWell(
onTap: () async {
if (index != 3 && index != 0) {
context.read<HomeBloc>().add(
HomeEvent.filtered(titles[index]),
);
}
if (index == 3) {
final response = await WRatingBottomSheet(
savedRatings: state.rating ?? [],
).show(context);
if (response != null) {
context.read<HomeBloc>().add(
HomeEvent.rated(response ?? []),
);
}
}
},
borderRadius: AppUtils.kBorderRadius25,
child: Ink(
padding: EdgeInsets.zero,
decoration: BoxDecoration(
color: AppColors.cEEEEEE,
borderRadius: AppUtils.kBorderRadius25,
),
child: Row(
children: [
if (index != 0 && state.filters.contains(titles[index]))
SvgPicture.asset(
AppIcons.icCheck1,
).paddingOnly(right: 5),
if (index == 0)
Badge(
isLabelVisible:
state.filters.isNotEmpty ||
state.rating.isNotEmpty,
backgroundColor: AppColors.c34A853,
child: SvgPicture.asset(AppIcons.icFilter),
).paddingSymmetric(vertical: 6),
if (index == 3 && state.rating.isNotEmpty)
SizedBox(
height: 25,
width: 25,
child: DecoratedBox(
decoration: BoxDecoration(
color: AppColors.c34A853,
borderRadius: AppUtils.kBorderRadius16,
),
child: Center(
child: Text(
"${state.rating.length}",
style: AppTextStyles.size14Regular.copyWith(
color: AppColors.cFFFFFF,
),
),
),
),
).paddingOnly(right: 8),
Text(titles[index], style: AppTextStyles.size14Medium),
if (index == 3) Icon(Icons.keyboard_arrow_down),
],
).paddingSymmetric(vertical: 0, horizontal: 15),
),
),
),
),
10.verticalSpace,
WDivider(),
],
);
},
);
}
}

View File

@@ -35,7 +35,12 @@ class WHomeHeader extends StatelessWidget {
Align(
alignment: AlignmentGeometry.topRight,
child: IconButton(
onPressed: () {},
onPressed: () {
context.push(
Routes.filters,
extra: context.read<HomeBloc>(),
);
},
icon: SvgPicture.asset(
AppIcons.icFilter,
height: 36,

View File

@@ -0,0 +1,134 @@
import '../../../../../../food_delivery_client.dart';
class WRatingBottomSheet extends StatefulWidget {
const WRatingBottomSheet({super.key, required this.savedRatings});
final List<String> savedRatings;
Future<List<String>?> show(BuildContext context) {
return showModalBottomSheet<List<String>>(
context: context,
builder: (context) => Wrap(children: [this]),
);
}
@override
State<WRatingBottomSheet> createState() => _WRatingBottomSheetState();
}
class _WRatingBottomSheetState extends State<WRatingBottomSheet> {
List<String> rating = [];
void updateRating(String value) {
final list = List<String>.from(rating);
if (list.contains(value)) {
list.remove(value);
setState(() {
rating = list;
});
} else {
list.add(value);
setState(() {
rating = list;
});
}
}
@override
void initState() {
rating = widget.savedRatings;
super.initState();
}
@override
Widget build(BuildContext context) {
final List<String> value = [
"${context.loc.atLeast} 4,9",
"${context.loc.atLeast} 4,7",
"${context.loc.atLeast} 4,5",
];
return WCustomModalBottomSheet(
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(context.loc.rating, style: AppTextStyles.size20Medium),
IconButton(
onPressed: () {
context.pop(null);
},
icon: SvgPicture.asset(AppIcons.icClose, height: 15),
),
],
),
15.verticalSpace,
Wrap(
spacing: 10,
runSpacing: 15,
children: List.generate(value.length, (index) {
return WRatingButton(
onTap: () {
updateRating(value[index]);
},
isActive: rating.contains(value[index]),
rating: value[index],
);
}),
),
25.verticalSpace,
AppButton(
name: context.loc.apply,
onPressed: () {
context.pop(rating);
},
),
20.verticalSpace,
],
).paddingSymmetric(horizontal: 15),
);
}
}
class WRatingButton extends StatelessWidget {
const WRatingButton({
super.key,
required this.onTap,
required this.isActive,
required this.rating,
});
final VoidCallback onTap;
final bool isActive;
final String rating;
@override
Widget build(BuildContext context) {
return InkWell(
borderRadius: AppUtils.kBorderRadius25,
onTap: onTap,
child: Ink(
decoration: BoxDecoration(
color: isActive
? AppColors.c34A853
: AppColors.cE6E6E6.newWithOpacity(.6),
borderRadius: AppUtils.kBorderRadius25,
),
child: Row(
spacing: 4,
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.star, color: AppColors.cYellow),
Text(
rating,
style: AppTextStyles.size14Medium.copyWith(
color: isActive ? AppColors.cFFFFFF : AppColors.c000000,
),
),
],
).paddingSymmetric(vertical: 6, horizontal: 10),
),
);
}
}

View File

@@ -0,0 +1,24 @@
import '../../../../../food_delivery_client.dart';
class RestaurantsByCategoryPage extends StatelessWidget {
const RestaurantsByCategoryPage({super.key, required this.categoryName});
final String categoryName;
@override
Widget build(BuildContext context) {
return WLayout(
child: Scaffold(
appBar: AppBar(
leading: IconButton(
onPressed: () {
context.pop();
},
icon: SvgPicture.asset(AppIcons.icBack),
),
),
body: WRestaurantsByCategoryBody(categoryName: categoryName),
),
);
}
}

View File

@@ -0,0 +1,66 @@
import '../../../../../../food_delivery_client.dart';
class WFeaturedStores extends StatelessWidget {
const WFeaturedStores({super.key});
@override
Widget build(BuildContext context) {
return SizedBox(
height: 200,
child: ListView.separated(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
padding: EdgeInsets.symmetric(horizontal: 20),
physics: const AlwaysScrollableScrollPhysics(),
itemBuilder: (context, index) => WFeaturedStoresItem(),
separatorBuilder: (context, index) => 7.horizontalSpace,
itemCount: 10,
),
);
}
}
class WFeaturedStoresItem extends StatelessWidget {
const WFeaturedStoresItem({super.key});
@override
Widget build(BuildContext context) {
return InkWell(
onTap: () {},
borderRadius: AppUtils.kBorderRadius16,
child: Ink(
height: 200,
width: 165,
decoration: BoxDecoration(
color: AppColors.cEFF3FE,
borderRadius: AppUtils.kBorderRadius16,
),
child: Column(
spacing: 20,
children: [
Expanded(
child: CachedNetworkImage(imageUrl: AppLocaleKeys.imageUrl),
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text("7Eleven", style: AppTextStyles.size16Medium),
Text(
context.loc.opensAt("10:00 AM"),
textAlign: TextAlign.center,
style: AppTextStyles.size14Regular.copyWith(
color: AppColors.c6B6B6B,
),
),
],
),
),
],
).paddingAll(20),
),
);
}
}

View File

@@ -0,0 +1,42 @@
import '../../../../../../food_delivery_client.dart';
class WRestaurantsByCategoryBody extends StatelessWidget {
const WRestaurantsByCategoryBody({super.key, required this.categoryName});
final String categoryName;
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
scrollDirection: Axis.vertical,
physics: const AlwaysScrollableScrollPhysics(),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
categoryName,
style: AppTextStyles.size36Bold.copyWith(
height: 44/36
),
).paddingSymmetric(horizontal: 15),
15.verticalSpace,
Text(
context.loc.featuredStores,
style: AppTextStyles.size30Bold.copyWith(
height: 44/30
),
).paddingSymmetric(horizontal: 15),
15.verticalSpace,
WFeaturedStores(),
16.verticalSpace,
WDivider(),
WStoresList()
],
),
);
}
}

View File

@@ -0,0 +1,69 @@
import '../../../../../../food_delivery_client.dart';
class WStoresList extends StatelessWidget {
const WStoresList({super.key});
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: 20,
shrinkWrap: true,
padding: EdgeInsets.symmetric(vertical: 17),
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (context, index) {
return WStoreItem();
},
);
}
}
class WStoreItem extends StatelessWidget {
const WStoreItem({super.key});
@override
Widget build(BuildContext context) {
return InkWell(
onTap: () {},
child: Ink(
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ClipRRect(
borderRadius: AppUtils.kBorderRadius36,
child: CachedNetworkImage(
imageUrl: AppLocaleKeys.imageUrl,
height: 70,
width: 70,
fit: BoxFit.cover,
),
),
16.horizontalSpace,
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Begs & Megs", style: AppTextStyles.size16Medium),
Text(
context.loc.opensAt("10:00"),
style: AppTextStyles.size14Regular.copyWith(
color: AppColors.c6B6B6B,
),
),
Text(
context.loc.spendAndSave("\$20", "\$5"),
style: AppTextStyles.size14Medium.copyWith(
color: AppColors.c05A357,
),
),
],
),
const Spacer(),
IconButton(
onPressed: () {},
icon: SvgPicture.asset(AppIcons.icDislikeGrey),
),
],
).paddingSymmetric(vertical: 10, horizontal: 18),
),
);
}
}

View File

@@ -19,3 +19,6 @@ export 'package:freezed_annotation/freezed_annotation.dart';
export 'package:shared_preferences/shared_preferences.dart';
export 'package:cached_network_image/cached_network_image.dart';
export 'package:carousel_slider/carousel_slider.dart';
export 'package:flutter_bounceable/flutter_bounceable.dart';
export 'package:food_delivery_client/feature/on_boarding/presentation/pages/splash_page/splash_page.dart';
export 'package:skeletonizer/skeletonizer.dart';

View File

@@ -725,6 +725,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.0.0"
skeletonizer:
dependency: "direct main"
description:
name: skeletonizer
sha256: eebc03dc86b298e2d7f61e0ebce5713e9dbbc3e786f825909b4591756f196eb6
url: "https://pub.dev"
source: hosted
version: "2.1.0+1"
sky_engine:
dependency: transitive
description: flutter

View File

@@ -42,6 +42,8 @@ dependencies:
freezed: ^3.2.3
freezed_annotation: ^3.1.0
#loading:
skeletonizer: ^2.1.0+1
dev_dependencies:
flutter_test: