feat : profile and map

This commit is contained in:
2025-07-28 15:57:30 +03:30
parent 6057976b46
commit d9724f681c
67 changed files with 2835 additions and 444 deletions

57
assets/icons/bg_auth.svg Normal file
View File

@@ -0,0 +1,57 @@
<svg width="412" height="931" viewBox="0 0 412 931" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_5923_16746)">
<rect width="412" height="931" fill="#6B81CC"/>
<circle cx="41.5" cy="55.5" r="69.5" fill="url(#paint0_linear_5923_16746)"/>
<path d="M156.868 50C161.131 29.7998 170.993 24.6101 190.867 23V1H413.367V931.5H330.367L324.367 827C314.902 793.807 295.891 785.525 252.367 778L177.368 656C162.361 613.603 140.263 597.834 94.3675 573.5C55.8294 529.516 49.1364 497.135 82.3675 416L100.368 344C103.185 305.471 115.632 283.368 171.368 206.5C179.879 191.777 182.381 182.062 182.868 162.5C165.825 94.8788 153.447 71.4583 156.868 50Z"
fill="#8295D0"/>
<path d="M186.19 51.7725C182.67 30.0235 182.611 18.3388 191.907 0H418V285C309.401 241.916 222.061 222.776 186.19 51.7725Z"
fill="url(#paint1_linear_5923_16746)"/>
<path d="M395.42 139.366C400.547 146.919 405.799 147.936 418.42 145.366V228.866C354.331 247.781 316.88 228.664 248.92 171.366C236.505 149.452 233.509 137.374 237.92 116.366C255.966 58.6707 315.46 53.9971 356.92 84.8657C374.25 97.9054 382.179 111.629 395.42 139.366Z"
fill="url(#paint2_linear_5923_16746)"/>
<circle cx="271.5" cy="180.5" r="55.5" fill="url(#paint3_linear_5923_16746)"/>
<path d="M0 931.474V245C58.5185 250.098 88.061 260.166 131.442 298.812C171.798 351.307 174.011 406.284 217.559 478.854C242.164 507.953 244.753 505.005 275.474 522.104C306.194 539.203 352.109 568.55 375.188 599.05C408.645 645.354 418.256 678.341 417.995 750.426C418.164 796.377 412.001 815.257 397.85 845.476C381.431 887.893 358.765 917.466 397.85 936L198.925 933.737L0 931.474Z"
fill="url(#paint4_linear_5923_16746)" fill-opacity="0.5"/>
<circle cx="61.5" cy="625.5" r="36.5" fill="url(#paint5_linear_5923_16746)"/>
<circle cx="185.5" cy="738.5" r="82.5" fill="url(#paint6_linear_5923_16746)"/>
</g>
<defs>
<linearGradient id="paint0_linear_5923_16746" x1="5" y1="-20.5" x2="103.5" y2="125"
gradientUnits="userSpaceOnUse">
<stop stop-color="#395DBD"/>
<stop offset="1" stop-color="#162039"/>
</linearGradient>
<linearGradient id="paint1_linear_5923_16746" x1="403.5" y1="203.715" x2="216.572" y2="82.4952"
gradientUnits="userSpaceOnUse">
<stop stop-color="#5079E1"/>
<stop offset="1" stop-color="#FEFEFA"/>
</linearGradient>
<linearGradient id="paint2_linear_5923_16746" x1="400.92" y1="183.366" x2="235.92" y2="150.866"
gradientUnits="userSpaceOnUse">
<stop stop-color="#6F7EE3"/>
<stop offset="1" stop-color="#6DABE8"/>
</linearGradient>
<linearGradient id="paint3_linear_5923_16746" x1="251.5" y1="136" x2="306.5" y2="228"
gradientUnits="userSpaceOnUse">
<stop stop-color="#E5EBFA"/>
<stop offset="1" stop-color="#5780E3"/>
</linearGradient>
<linearGradient id="paint4_linear_5923_16746" x1="0" y1="245" x2="208.983" y2="850.181"
gradientUnits="userSpaceOnUse">
<stop stop-color="#3D67D3"/>
<stop offset="1" stop-color="#192243"/>
</linearGradient>
<linearGradient id="paint5_linear_5923_16746" x1="61.5" y1="589" x2="61.5" y2="662"
gradientUnits="userSpaceOnUse">
<stop stop-color="#F0EFFC"/>
<stop offset="1" stop-color="#5480E6"/>
</linearGradient>
<linearGradient id="paint6_linear_5923_16746" x1="243" y1="806" x2="167" y2="670"
gradientUnits="userSpaceOnUse">
<stop stop-color="#11163C"/>
<stop offset="1" stop-color="#3962C5"/>
</linearGradient>
<clipPath id="clip0_5923_16746">
<rect width="412" height="931" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@@ -0,0 +1,116 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 59.14 62.89">
<defs>
<style>
.cls-1 {
fill: #f37448;
}
.cls-1, .cls-2, .cls-3, .cls-4, .cls-5, .cls-6, .cls-7, .cls-8, .cls-9, .cls-10, .cls-11, .cls-12, .cls-13, .cls-14, .cls-15, .cls-16 {
stroke-width: 0px;
}
.cls-1, .cls-2, .cls-10, .cls-12, .cls-15 {
mix-blend-mode: multiply;
}
.cls-2, .cls-8 {
fill: #f57e2d;
}
.cls-17 {
isolation: isolate;
}
.cls-3 {
fill: #f15633;
}
.cls-4 {
fill: #f68d49;
}
.cls-5 {
fill: #ee3532;
}
.cls-6 {
fill: #f47421;
}
.cls-7 {
fill: #fff;
}
.cls-8, .cls-13 {
mix-blend-mode: screen;
}
.cls-9 {
fill: #fff4ee;
}
.cls-10 {
fill: #f36d21;
}
.cls-10, .cls-12, .cls-15 {
opacity: .4;
}
.cls-11 {
fill: #ef3e23;
}
.cls-12 {
fill: #f89b67;
}
.cls-13 {
fill: #f79351;
}
.cls-14 {
fill: #5b290d;
}
.cls-15 {
fill: #f68c70;
}
.cls-16 {
fill: #f47920;
}
</style>
</defs>
<g class="cls-17">
<g id="Layer_1" data-name="Layer 1">
<g>
<path class="cls-14" d="m38.62,55.13c-.31-.77-1.06-1.07-1.77-1.32-2.05-.71-3.57-.79-3.85-3.58-.13-1.33-.25-2.68-.45-4,.84-.82,1.31-2.1,1.75-3.41-.27.16-.55.32-.83.47-.18.51-.37.96-.56,1.27-.16.25-.33.47-.5.65-.06-.43-.16-.88-.51-1.09-.08-.05-.2.11-.13.18.21.23.3.67.34,1.19-.79.64-1.7.67-2.63.4-.22-.25-.48-.44-.78-.55.05.02.1-.07.07-.11-.02-.02-.04-.05-.06-.08-.08.02-.15.04-.23.06,0,0,0,0,0,0,.01.12.04.21.06.3-.15-.07-.29-.15-.43-.22-.12.03-.25.06-.37.09-.4.09-.81.18-1.22.25.88.57,1.76,1.14,2.75,1.38.41.89.54,1.86.61,2.84.09,1.29-.04,2.76.02,4.15-.5.34-1.23.38-1.73.53-.75.22-1.49.49-2.19.83-.54.27-1.69.71-1.77,1.45,0,.06.03.11.08.14.38.28.93.28,1.49.16-.81.56-1.96,1.62-1.82,2.61.13.94,1.26.16,1.68-.14.88-.62,1.84-1.25,2.83-1.65.18-.08.38-.14.59-.2.04-.03.09-.06.14-.1.16-.02.32-.04.46-.07.65-.12.66.23.52.62-.02.04-.05.07-.06.1-.16.25-.34.58-.49.93-.05.15-.1.29-.15.44,0,0-.02.02-.03.03-.22.65-.32,1.34-.09,1.88.11.16.3.22.61.08.75-.36,1.22-1.08,1.65-1.79.25-.41.48-.83.71-1.26.44-.56.98-1.1,1.46-1.48.48-.22.97-.41,1.43-.66.45-.07.92-.08,1.37-.17.77-.04,1.5-.17,1.91-.62.13-.14.25-.34.17-.55Z"/>
<path class="cls-4" d="m38.01,55.23c-.16.62-1.19.41-1.62.43-.46.02-.9.12-1.33.26-.49.15-.97.39-1.44.74-.06.05-.11.11-.17.16-.43.35-.81.77-1.13,1.25-.2.29-1.86,3.58-2.47,2.48,0,0,0,0,0,0,0-.02.01-.03,0-.04-.05-.72.21-1.26.53-1.87.11-.21.26-.48.33-.75.02-.05.04-.1.06-.16.03-.08.06-.16.09-.25.04-.14.07-.28.08-.42-1.04-.28-2.35.15-3.25.62-.91.48-1.68,1.23-2.61,1.65-.13.06-.33,0-.32-.19.05-.97,1.11-1.58,1.83-2.03.47-.29.96-.55,1.45-.78-.83-.35-2.14.8-3.04.44-.18-.07-.21-.29-.05-.4.94-.69,2.06-.99,3.19-1.25.09-.03.18-.06.28-.08.17-.04.34-.08.51-.13.8-.26,1.44-.63,1.83-1.25.05-1.19,0-2.39-.07-3.57-.05-.76-.17-1.93-.52-2.93.09,0,.17,0,.26,0,.68-.03,1.23-.23,1.69-.55-.02.76-.09,1.51-.07,1.91.03.77.02,1.6.12,2.38.15.46.34.91.59,1.31.5.83,1.13,1.39,1.88,1.82.81.15,1.62.28,2.41.49.25.06,1.08.27.97.71Z"/>
<path class="cls-1" d="m30.73,51.03c.53.15,1.07.27,1.62.36-.07-.17-.14-.33-.19-.5-.1-.79-.09-1.61-.12-2.38-.01-.4.05-1.15.07-1.91-.46.32-1.01.52-1.69.55-.09,0-.17,0-.26,0,.35,1,.47,2.17.52,2.93.02.32.04.63.06.95Z"/>
<path class="cls-14" d="m49.91,56.3c-.31-.78-1.06-1.07-1.77-1.32-2.05-.71-3.57-.79-3.85-3.58-.13-1.33-.25-2.68-.45-4,.84-.82,1.31-2.1,1.74-3.42-.27.16-.55.32-.83.47-.18.51-.37.96-.56,1.27-.16.25-.33.47-.5.65-.06-.43-.16-.88-.51-1.09-.08-.05-.2.11-.13.18.21.23.3.67.34,1.19-.79.64-1.7.67-2.63.4-.22-.25-.48-.44-.78-.55.05.02.1-.07.07-.11-.02-.03-.04-.05-.06-.08-.08.02-.15.04-.23.06,0,0,0,0,0,0,.02.11.04.21.06.3-.14-.07-.29-.15-.43-.22-.12.03-.25.06-.37.09-.4.09-.81.17-1.22.25.88.57,1.76,1.14,2.75,1.38.41.89.54,1.86.61,2.84.09,1.28-.04,2.76.02,4.14-.5.34-1.23.38-1.73.53-.75.22-1.49.49-2.19.83-.54.26-1.69.71-1.77,1.45,0,.07.03.11.08.14.38.28.93.27,1.49.16-.81.56-1.96,1.62-1.83,2.61.13.94,1.26.16,1.68-.14.88-.62,1.84-1.25,2.83-1.65.19-.07.39-.14.59-.2.04-.03.09-.06.14-.1.16-.02.33-.04.46-.07.65-.12.65.22.52.62-.02.04-.05.07-.06.1-.16.25-.34.58-.49.93-.05.15-.1.29-.15.44,0,0-.02.02-.03.03-.22.65-.32,1.34-.09,1.88.11.16.3.22.61.07.75-.36,1.22-1.08,1.65-1.79.25-.41.48-.83.71-1.25.44-.56.98-1.1,1.46-1.48.48-.22.97-.41,1.43-.65.45-.07.91-.08,1.37-.17.77-.04,1.5-.17,1.91-.62.13-.14.25-.34.17-.55Z"/>
<path class="cls-4" d="m49.3,56.39c-.16.61-1.19.41-1.62.43-.46.02-.9.11-1.33.26-.49.15-.97.39-1.44.74-.06.05-.11.11-.17.16-.43.35-.81.77-1.13,1.25-.2.29-1.86,3.58-2.47,2.48,0,0,0,0,0,0,0-.02.01-.03.01-.04-.05-.72.21-1.25.53-1.87.11-.21.26-.48.33-.75.02-.05.04-.1.06-.16.03-.08.06-.16.09-.25.04-.14.07-.28.08-.42-1.04-.28-2.36.16-3.25.62-.91.48-1.68,1.23-2.61,1.65-.13.06-.33,0-.32-.19.05-.97,1.11-1.58,1.83-2.03.47-.29.96-.55,1.45-.78-.83-.35-2.14.8-3.04.44-.18-.07-.21-.29-.05-.4.94-.69,2.06-.99,3.19-1.25.09-.02.18-.05.28-.08.17-.04.34-.08.51-.12.8-.26,1.44-.63,1.84-1.25.05-1.19,0-2.38-.07-3.57-.05-.76-.17-1.93-.52-2.93.09,0,.17,0,.26,0,.68-.03,1.23-.23,1.69-.55-.02.76.39,5.2.64,5.6.5.84,1.13,1.39,1.88,1.82.81.15,1.62.29,2.42.49.24.06,1.08.28.97.71Z"/>
<path class="cls-1" d="m43.61,50.62c-.13-1.23-.22-2.49-.21-2.86-.46.32-1.01.52-1.69.55-.09,0-.17,0-.26,0,.33.93.45,1.99.51,2.75.56-.12,1.11-.27,1.65-.45Z"/>
<path class="cls-14" d="m59.1,25.23c-.1-2.38-2.09-9.97-2.86-11.36.11-1.48.1-3.33-.17-4.84-.17-.93-1.12-.35-1.41.1.66-1.92,1.03-3.9.52-5.74-.66-2.4-4.96,4.06-5.06,4.2-1.93,2.61-3.62,5.42-6.82,6.32-2.28.64-4.54.96-6.88,1.24-2.82.33-6.07.31-8.91-.65-3.87-2.1-5.91-6.91-9.9-8.55-.04-.02-.08-.04-.12-.06.03-.03.06-.06.08-.09.57-.94,1.3-3.04.06-3.75-.41-.24-1.03-.08-1.52.14.59-1.95-1.3-2.63-3.11-1.92-1.12.44-2.06,1.32-2.83,2.23-.83.98-1.01,2.06-1.39,3.16-.41-1.27-1.51-1.31-2.52-.2-1.49,1.63-1.71,5.7-.03,7.22-.03.05-.05.1-.08.15h0c.05-.1-.09-.1-.14-.03l-.02.03s-.02.03-.02.05C3.46,13.6.7,16.81,0,19.19c-.01.04-.02.11.02.14.04.04.09.08.13.12.07.07.17.04.24,0,.36-.23.72-.42,1.09-.6,2.4-.33,4.96,1.75,7.38,1-1.6,1.91-4.59,4.23-3.91,7.12.52,2.25,3.18.84,4.47-.37-.32.87-1.22,2.7-.72,3.2.03.03.07.03.11.01.55-.28.86-.64,1.29-1.11.11-.12.19-.21.25-.29-.06.1-.13.21-.2.37-.19.4-.39.92-.55,1.33-.8,2.02-1.07,4.29-.78,6.45.08.59.3,2.52,1.31,2.11.57-.23.93-.84,1.16-1.52-.03,1.36.15,2.87,1.08,3.07.12.02.25-.1.3-.2.14-.28.22-.56.28-.85.6,2.05,1.89,4.48,3.86,4.61.55.04.94-.11,1.21-.35.99,1.32,2.3,2.1,3.82,2.68,1.63.61,3.17,1.42,4.82,1.97,1.07.03,2.15.42,3.15.74.16.05.31.1.46.14.87.16,1.73.29,2.59.37.49-.02.98.01,1.48.05.02,0,.04-.01.06-.01.65,0,1.31.03,1.96,0,1.16-.08,2.33-.25,3.53-.55.54-.14,1.06-.29,1.59-.46,1.29-.54,3.98-1.72,4.02-1.68,1.57-.82,3.07-1.79,4.48-2.9.34-.27.7-.55,1.07-.85.79-.49,1.54-1.03,2.22-1.6,3.39-2.86,6.17-8.17,5.82-13.01.06-1.05.05-2.09,0-3.06Z"/>
<path class="cls-5" d="m5.7,9.65c-.04-.76.03-1.51.23-2.25.02-.11.06-.22.09-.33.09-.4.24-.77.46-1.07.32-.43,1-.89,1.54-.59.46.25.6.73.78,1.19.07-.07.12-.16.13-.23.17-1.64.8-2.91,1.93-4.07.52-.49,1.09-.89,1.73-1.18.91-.46,3.36-1.02,2.64,1.66-.08.08-.16.16-.24.25-.04.11-.07.22-.1.33.83-.67,2.16-1.33,2.61-.11.32.86-.18,2.17-.98,2.16,0,.01-.01.02-.02.03-2.1-.7-4.55.32-6.3,1.45-.96.62-1.72,1.49-2.4,2.4-.49.66-.76,1.4-1.03,2.13-.11.25-.21.5-.31.76-.04.1-.08.19-.12.28-.3-.93-.55-1.76-.65-2.81Z"/>
<path class="cls-8" d="m9.79,5.13c.67-1.22,1.81-2.85,3.23-3.17,1.18-.27,1.74.29,1.95,1.16,0-.03.02-.05.02-.08.07-.09.15-.17.24-.25.71-2.68-1.73-2.12-2.64-1.66-.64.29-1.22.69-1.73,1.18-1.12,1.16-1.75,2.42-1.93,4.07,0,.07-.06.16-.13.23-.18-.46-.33-.94-.78-1.19-.54-.3-1.21.16-1.54.59-.23.3-.37.67-.46,1.07-.04.1-.07.21-.09.33-.19.74-.27,1.49-.23,2.25,0,.02,0,.03,0,.05.02-1.58.45-3.06,1.72-3.06.62,0,1.07.68,1.37,1.32.18-1,.52-1.96,1-2.83Z"/>
<path class="cls-8" d="m17.5,3.26c-.43-1.16-1.66-.61-2.5.02,0,.02,0,.04,0,.06.53-.41,1.13-.61,1.63-.16.53.48.54,1.28.37,2.05.49-.39.73-1.31.49-1.98Z"/>
<path class="cls-11" d="m12.66,16.37c.64,1.17,1.31,1.75,1.38,3.24-.02.68-.14,1.33-.36,1.97l-.09.05c-.17.71-.52,1.35-1.26,1.53-.69.16-.81-.8-.86-1.44-.07.03-.16.1-.17.14-.37.75-.59,1.55-.9,2.33.13-1.77-.29-2.89-.99-4.56.07-.03.13-.06.2-.1.56-.32.82-2.47.48-3.55-.06-.34-.21-.68-.38-.96-.65-1.65-1.68-2.29-2.82-2.27.28-.75.47-1.51.79-2.25.17-.39.38-.76.57-1.14.1-.14.19-.29.3-.43.71-.93,1.64-1.63,2.67-2.14,1.78-.47,3.63.13,4.88,1.6.9,1.05,1.15,2.29,1.09,3.66-.12,2.52-2.17,3.65-4.26,3.92-.16.02-.36.24-.27.41Z"/>
<path class="cls-2" d="m16.71,9.31c.26,1.22.01,2.51-.63,3.58-.84,1.39-3.02,2.93-4.77,2.52.46.74.94,1.47,1.08,2.33.15.93.22,2.22-.4,3-.39.49-1.09,1.01-1.69.58-.27-.19-.4-.5-.53-.81.47,1.22.73,2.23.63,3.66.3-.78.52-1.58.9-2.33.02-.03.1-.1.17-.14.05.64.18,1.61.86,1.44.73-.18,1.09-.82,1.26-1.53l.09-.05c.22-.64.34-1.29.36-1.97-.07-1.49-.74-2.07-1.38-3.24-.09-.17.1-.39.27-.41,2.1-.27,4.14-1.4,4.26-3.92.05-.98-.08-1.9-.48-2.73Z"/>
<path class="cls-6" d="m1.25,18.52s-.07.04-.11.06c-.12.04-.24.1-.35.16-.56.17.13-.84.39-1.33.73-1.39,1.84-2.65,3.09-3.52,2.27-1.58,4.05-.34,5.24,1.53.32,2.16-2.83,1.53-4.21,1.74-1.31.21-2.92.66-4.07,1.36Z"/>
<path class="cls-13" d="m9.01,14.7c-1.17-1.43-2.76-2.17-4.72-.81-1.26.87-2.36,2.13-3.09,3.52-.1.18-.25.43-.38.66,1.94-2.32,6-4.88,8.19-3.38Z"/>
<path class="cls-16" d="m5.49,19.18c-.87-.26-1.99-.68-3.03-.76.88-.34,1.78-.59,2.73-.79,1.35-.29,2.75-.05,4.11-.35.28-.06.48-.18.61-.34-.06.71-.23,1.45-.26,1.65-.29,1.63-3.2.86-4.16.58Z"/>
<path class="cls-3" d="m7.39,27.37c-1.97.57-2.06-1.38-1.75-2.55.53-1.94,2.45-3.34,3.45-5.06.02,0,.05-.02.08-.02.14.75.43,1.42.63,2.17.31,1.17.13,2.46-.12,3.66-.56.8-1.33,1.4-2.29,1.81Z"/>
<path class="cls-2" d="m9.24,20s-.03-.01-.04-.02c-.07-.06-.11-.1-.15-.14,0,0,0,.01-.01.02.78,1.84-.04,4.76-1.39,6.13-.44.45-1.22,1.17-1.89.69-.06-.04-.12-.09-.17-.14.18.68.7,1.15,1.8.84.96-.41,1.72-1.01,2.29-1.81.25-1.19.43-2.49.12-3.66-.17-.65-.41-1.25-.56-1.9Z"/>
<path class="cls-9" d="m56.42,35.16c.31-.27.58-.57.82-.88-.47,1.33-1.12,2.57-1.92,3.7-.75.95-1.47,2.07-2.37,2.92-.15.13-4.61,3.55-5.71,4.25-1.34.84-2.73,1.61-4.24,1.99-1.39.55-2.82.99-4.31,1.31-1.25.27-2.49.37-3.74.35-.03-.03-1.22-.09-1.8-.13.01,0,.02.02.03.02-.2-.02-.4-.05-.59-.08-.13-.01-.26-.03-.39-.05-.07,0-.14-.02-.21-.04-.21-.03-.42-.06-.63-.1-.36-.06-.71-.13-1.07-.2-.05-.01-.09-.02-.14-.03-.99-.21-1.98-.47-2.95-.76-3.06-.91-6.07-2.04-8.67-4-.11-.08-.15-.23-.05-.34-.05-.01-.11-.03-.16-.04.3-.57.3-1.4.19-2.23-.03-.27-.06-.49-.09-.68.18.57.51,1.17,1.01,1.03,1.09-.31,1.07-4.47,1.06-5.16,0-.22-.32,0-.33.14-.08.74-.17,1.47-.28,2.2.03-.17-.43,3.02-.95,2.02-.3-.57-.35-1.3-.74-1.82-.07-.09-.25.06-.24.16.12,1.15.87,5.39-1.66,4.17-1.92-.93-2.91-3.54-3.21-5.55-.04-.25-.47.06-.47.24,0,.18-.1,2.47-.56,1.4-.35-.83-.47-1.61-.51-2.52,0-.08-.01-.14-.02-.2.08-.4.13-.79.16-1.1.01-.13-.2-.02-.21.06-.03.19-.07.46-.11.79-.28.03-.81,1.33-.9,1.66-.57.77-.92-.93-.96-1.14-.66-3.07.18-6.25,1.58-8.95.12-.23-.17-.19-.27-.07-.45.51-2.13,2.13-1.4.24.26-.66.53-1.34.72-2.03.34-.57.6-1.12.84-1.76.15-.41.19-2.3.41-1.03.11.63.77,1.04,1.3.62,1.13-.9,1.51-1.93,1.8-3.38.34-1.74-.42-2.56-1.21-3.79,1.27-.14,2.43-.32,3.33-1.54.91-1.24,1.59-2.87,1.26-4.47-.49-2.37-2.57-4.12-4.78-4.27.18-.05.37-.1.55-.14,1.8-.38,3.43.36,4.89,1.36,1.06.82,2,1.74,2.94,2.76.06.08.13.17.19.25.83.83,1.63,1.68,2.5,2.45,1.22,1.08,2.5,2.06,3.9,2.8.84.27,1.68.46,2.46.56,4.29.55,9.11-.42,13.22-1.6,3.62-1.03,5.53-5.08,7.63-8.02.3-.41.61-.82.92-1.22.16-.2.31-.39.47-.59.12-.23.27-.38.44-.47.24-.33.54-.59.89-.71.55-.19.86.49.85.95-.03,1.1-.36,2.19-.77,3.24-.03.15-.07.29-.1.44-.1.41-.21.81-.34,1.21-.33,1.45-.66,2.89-.97,4.34.26-.6.53-1.21.81-1.85.2-.35.4-.7.56-1.03.01-.03,1.2-2.03,1.29-.97.06.69-.03,1.42,0,2.11.04,1.06-.02,2.11-.16,3.15-.02,1.29-.07,2.59-.2,3.87.46-1.28.82-2.6,1.04-3.94.16.79.35,1.57.57,2.34.64,2.18,1.13,4.32,1.35,6.6.34,3.55.48,8.12-1.86,11.02-.17.21.07.32.23.18Z"/>
<path class="cls-15" d="m56.42,35.16c-.17.15-.4.04-.23-.18,2.34-2.9,2.2-7.47,1.86-11.02-.22-2.27-.71-4.42-1.35-6.6-.23-.78-.41-1.56-.57-2.34-.21,1.34-.57,2.66-1.04,3.94.13-1.28.18-2.58.2-3.87.14-1.03.2-2.09.16-3.15-.02-.69.06-1.42,0-2.11-.09-1.06-1.28.94-1.29.97-.16.33-.36.67-.56,1.03-.28.64-.55,1.26-.81,1.85.31-1.45.65-2.89.97-4.34.13-.4.24-.8.34-1.21.03-.15.07-.29.1-.44.41-1.06.74-2.14.77-3.24.01-.45-.3-1.14-.85-.95-.35.12-.65.39-.89.71-.18.08-.33.23-.44.47-.16.2-.31.39-.47.59-.31.4-.62.81-.92,1.22-2.1,2.95-4.01,6.99-7.63,8.02-4.12,1.18-8.93,2.15-13.22,1.6-.79-.1-1.63-.29-2.46-.56-1.4-.74-2.68-1.72-3.9-2.8-.87-.77-1.67-1.62-2.5-2.45-.06-.08-.12-.17-.19-.25-.94-1.02-1.88-1.94-2.94-2.76-1.46-1-3.09-1.74-4.89-1.36-.18.04-.37.09-.55.14,2.2.15,4.29,1.9,4.78,4.27.33,1.6-.35,3.24-1.26,4.47-.89,1.22-2.05,1.4-3.33,1.54.79,1.23,1.56,2.05,1.21,3.79-.29,1.45-.67,2.48-1.8,3.38-.53.42-1.2,0-1.3-.62-.22-1.27-.25.62-.41,1.03-.24.64-.5,1.19-.84,1.76-.19.69-.46,1.36-.72,2.03-.73,1.88.94.27,1.4-.24.1-.11.39-.16.27.07-1.4,2.7-2.24,5.88-1.58,8.95.05.21.39,1.92.96,1.14.09-.33.62-1.63.9-1.66.03-.33.07-.6.11-.79.01-.08.22-.19.21-.06-.03.31-.08.7-.16,1.1,0,.06.02.12.02.2.05.91.16,1.69.51,2.52.45,1.07.56-1.22.56-1.4,0-.18.43-.5.47-.24.3,2.01,1.29,4.62,3.21,5.55,2.52,1.22,1.78-3.02,1.66-4.17,0-.09.17-.25.24-.16.4.52.44,1.25.74,1.82.52,1,.98-2.19.95-2.02.11-.73.2-1.46.28-2.2.01-.14.33-.36.33-.14,0,.69.03,4.86-1.06,5.16-.5.14-.83-.46-1.01-1.03.03.19.06.41.09.68.11.83.11,1.66-.19,2.23.05.02.11.03.16.04-.1.11-.06.26.05.34,2.6,1.96,5.61,3.08,8.67,4,.97.29,1.96.54,2.95.76.05,0,.09.02.14.03.36.07.71.14,1.07.2.21.04.42.07.63.1.07.01.14.03.21.04.13.02.26.03.39.05.2.03.39.06.59.08-.01,0-.02-.02-.03-.02.58.04,1.77.1,1.8.13,1.25.02,2.5-.08,3.74-.35,1.48-.33,2.92-.77,4.31-1.31,1.51-.38,2.91-1.14,4.24-1.99,1.1-.7,5.56-4.12,5.71-4.25.9-.84,1.62-1.97,2.37-2.92.8-1.13,1.45-2.37,1.92-3.7-.24.31-.52.61-.82.88Zm-5.79-14.27c-.11.19-.39.11-.39-.11,0-.53-.01-1.05-.03-1.58-.2.25-.47.42-.84.31-1.42-.4-2.66-.72-4.15-.59-1.58.13-3.14.46-4.71.61-.13.01-.26.02-.39.03-1.4.31-2.84-.05-4.22.25-.28.06-.55.14-.83.21,4.37.64,9.38,1.94,11.48,6.17.05.1.03.25-.08.3-.87.39-1.8.56-2.75.58.9.23,1.79.48,2.66.84.64.27,3.76,1.91,2.93,3.08-.39.56-1.1.66-1.71.77-1.2.22-2.42.38-3.65.42-.99.04-1.93,0-2.89-.19.87.26,1.74.5,2.61.79,1.01.33,2.25.47,3.12,1.14,2.25,1.73-1.67,3.21-2.93,3.45-4.31.83-9.14.1-12.42-2.93.25.44.48.9.66,1.37.35.94,0,1.78-1.08,1.33-.61-.25-1.15-.82-1.57-1.33-.64-.76-1.34-1.43-1.87-2.28-.55-.87-1.06-1.84-1.31-2.85-.23-.9-.32-1.83-.51-2.74-.13,1.85.39,3.68.43,5.55,0,.18-.24.3-.36.16-1.38-1.7-2.34-3.87-3-5.98-.25-.8-.46-1.6-.67-2.41-.11-.08-.22-.16-.32-.25.04,1.07-.04,2.14-.15,3.15-.26,2.21-.28,5.15-1.91,6.81-.1.1-.26.08-.33-.04-.27-.44-.42-.92-.52-1.42-.03,1.35-.24,2.67-.95,3.84-.07.11-.25.16-.33.04-.53-.7-.84-1.52-1.06-2.38,0,.47,0,.94.02,1.41.04.83.33,3.47-.83,3.79-1.29.35-2.11-2.05-2.44-2.98-.52-1.47-.73-2.97-.71-4.49-.18.29-.36.57-.57.84-.22.28-1.26,1.56-1.63.67-.46-1.12-.16-2.59.23-3.78.11-.85.48-1.77.7-2.42.45-1.3.92-2.75,1.73-3.87.09-.12.29-.16.37,0,.3.63,1.11,2.08,1.66.83.24-.56.41-1.14.57-1.73.41-1.53.81-3.39.19-4.92-.08-.17-.16-.34-.24-.5-.13-.25.22-.46.37-.22.1.17.19.35.26.54.75,1.54,1.2,3.19,1.32,4.88.57-1.49.63-3.29.65-4.81.02-1.63-.23-3.31-.07-4.93.25-2.54,2.09-1.68,3.59-.47.07-.02.14-.02.21.05,3.13,3.11,7.32,4.25,11.51,4.75.36.04.77.05,1.19.05,1.65-.32,3.35-.19,5-.66,1.92-.55,3.93-1.24,5.64-2.31,1.66-1.04,3.01-2.44,4.06-4.13.83-1.35,1.57-2.75,2.53-4.02.1-.14.31-.04.35.1,1.07,3.59-1.49,6.92-2.34,10.3,1.11-.88,1.75-2.28,2.95-3.08.14-.1.31.03.32.19.13,2.56-1.29,4.7-2.5,6.8Z"/>
<path class="cls-10" d="m17.95,39.43c-.15,1.25-.52,2.48-1.52,2.94-.28.13-.54.15-.79.11.2.15.42.29.64.4,2.04.98,1.94-1.6,1.77-3.23-.03-.07-.07-.14-.1-.21Z"/>
<path class="cls-12" d="m56.42,35.16c-.17.15-.4.04-.23-.18,2.34-2.9,2.2-7.47,1.86-11.02-.21-2.21-.69-4.3-1.3-6.42.22,3.26.4,6.49-.14,9.76-.29,1.75-.64,3.54-1.49,5.1-.7,1.29-1.62,2.4-2.53,3.53,1.11-.67,2.08-1.6,2.94-2.58.17-.2.42.06.33.27-1.74,4.05-4.9,6.94-8.59,9.02-3.71,2.09-7.68,3.55-11.91,3.83-3.84.25-7.84-.32-11.42-1.82-1.97-.82-3.81-1.98-5.06-3.66-.08-.08-.15-.19-.21-.3-.06-.1-.13-.19-.19-.29.02.13.04.27.06.42.11.83.11,1.66-.19,2.23.05.02.11.03.16.04-.1.11-.06.26.05.34,2.6,1.96,5.61,3.08,8.67,4,.97.29,1.96.54,2.95.76.05,0,.09.02.14.03.36.07.71.14,1.07.2.21.04.42.07.63.1.07.01.14.03.21.04.13.02.26.03.39.05.2.03.39.06.59.08-.01,0-.02-.02-.03-.02.58.04,1.77.1,1.8.13,1.25.02,2.5-.08,3.74-.35,1.48-.33,2.92-.77,4.31-1.31,1.51-.38,2.91-1.14,4.24-1.99,1.1-.7,5.56-4.12,5.71-4.25.9-.84,1.62-1.97,2.37-2.92.8-1.13,1.45-2.37,1.92-3.7-.24.31-.52.61-.82.88Z"/>
<path class="cls-14" d="m50.79,27.81c1.09.04,2.1-.14,2.67-.93.67-.93-.66-2-1.24-2.44-1.73-1.33-3.36-2.18-5.23-2.81.32.02.64.06.96.13.49.12.92.09,1.23-.33.08-.11.14-.24.06-.37,0,0-.01-.02-.02-.03-2.2-1.14-4.41-1.37-6.89-1.44-1.28-.04-2.71-.18-3.97.12-.14.03-.28.07-.42.12,2.16-.05,4.25-.11,6.44.35,1.25.26,2.61.92,3.89,1.01-1.09-.08-2.4.06-3.47-.17-.07-.02-.15.04-.22.11.4.23.81.45,1.22.64,1.41.41,2.78.98,4.03,1.79.49.31,4.35,3.07,2.43,3.45-.6.12-1.21.11-1.83.05-.63.07-1.27.14-1.9.2.37.3.76.58,1.15.84.95.51,1.89,1.04,2.89,1.45.77.31,1.74.96.96,1.79-.95,1.01-2.75,1.18-4,1.44-.08.02-.16.04-.24.06.82.08,1.7.16,2.33.62.11.08.19.18.25.28.26.26.21.63.03,1.02-.29.83-1.11,1.71-1.51,2.03-.11.09-.21.16-.32.24-.76.65-1.64,1.15-2.57,1.55,0,0-.02,0-.03,0-.12.05-.23.1-.35.15-1.36.57-2.8.91-4.26,1.02-3.2.32-6.35.34-9.2-1.22.38.6.83,1.14,1.12,1.79.06.14.01.27-.13.33-1.33.51-3.02-1.14-3.96-1.92-1.45-1.21-2.88-2.73-3.68-4.52.02.21.04.41.05.62,0,.02.1,1.96-.16,1.75-.45-.37-.81-.95-1.11-1.46-.48-.82-.75-1.63-.92-2.44-.24-.74-.46-1.5-.63-2.26-.02.51.04,1.06.07,1.32.1.88.29,1.77.61,2.6.5,1.32,1.21,2.4,2.28,3.2.16-.07.31-.19.44-.35.18-.23.27-.55.31-.9,1.26,2.28,3.33,4.06,5.75,4.94.59.21,1.46.16,1.72-.55.16-.43,0-.75-.22-1.11,2.02,1.15,4.51,1.38,6.85.94,1.26-.09,2.52-.32,3.67-.68,2.43-.76,7.7-3.29,7.24-6.75-.02-.05-.05-.08-.09-.11-.13-.04-.27-.07-.41-.11.84-.26,1.68-.7,2.07-1.46.69-1.31-1.59-2.67-3.74-3.59Z"/>
<path class="cls-14" d="m13.9,11.45c0,.99-.58,1.8-1.29,1.8s-1.29-.8-1.29-1.8.58-1.8,1.29-1.8,1.29.81,1.29,1.8Z"/>
<path class="cls-7" d="m12.61,10.76c0,.3-.18.55-.39.55s-.39-.25-.39-.55.18-.55.39-.55.39.24.39.55Z"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -1,5 +1,3 @@
import 'package:rasadyar_chicken/data/di/chicken_di.dart';
import 'package:rasadyar_core/core.dart';
final di = GetIt.instance;
@@ -7,7 +5,3 @@ final di = GetIt.instance;
Future<void> setupPreInjection() async {
await setupAllCoreProvider();
}
Future<void> setupInjection() async {
await setupChickenDI();
}

View File

@@ -1,7 +1,9 @@
import 'package:flutter/material.dart';
import 'package:rasadyar_app/infrastructure/di/di.dart';
import 'package:rasadyar_chicken/chicken.dart';
import 'package:rasadyar_chicken/data/di/chicken_di.dart';
import 'package:rasadyar_core/core.dart';
import 'package:rasadyar_inspection/injection/inspection_di.dart';
import 'package:rasadyar_inspection/inspection.dart';
class CustomNavigationObserver extends NavigatorObserver {
bool _isWorkDone = false;
@@ -16,7 +18,11 @@ class CustomNavigationObserver extends NavigatorObserver {
final routeName = route.settings.name;
if (!_isWorkDone && routeName == ChickenRoutes.init) {
_isWorkDone = true;
await setupInjection();
setupChickenDI();
} else if (!_isWorkDone && (routeName == InspectionRoutes.init || routeName == InspectionRoutes.auth)) {
_isWorkDone = true;
await setupInspectionDI();
}
tLog('CustomNavigationObserver: didPush - $routeName');
}

View File

@@ -14,6 +14,7 @@ Future<void> main() async {
await Get.find<TokenStorageService>().init();
Get.put<AuthRouteResolver>(AppAuthRouteResolver());
Get.put(AuthMiddleware());
runApp(MyApp());
// runApp(DevicePreview(builder: (context) => ForDevicePreview(),));

View File

@@ -1,28 +1,28 @@
import 'package:rasadyar_core/core.dart';
class ModulesLogic extends GetxController {
TokenStorageService tokenService = Get.find<TokenStorageService>();
List<ModuleModel> moduleList=[
List<ModuleModel> moduleList = [
ModuleModel(title: 'بازرسی', icon: Assets.icons.inspection.path, module: Module.inspection),
ModuleModel(title: 'دام', icon: Assets.icons.liveStock.path, module: Module.liveStocks),
ModuleModel(title: 'مرغ', icon: Assets.icons.liveStock.path, module: Module.chicken),
];
RxnInt selectedIndex = RxnInt(null);
@override
void onReady() {
super.onReady();
}
@override
void onClose() {
super.onClose();
}
void saveModule(Module module) {
tokenService.saveModule(module);
tokenService.appModule.value = module;
}
}

View File

@@ -25,6 +25,9 @@ class ModulesPage extends GetView<ModulesLogic> {
icon: module.icon,
onTap: () {
controller.selectedIndex.value = index;
controller.saveModule(module.module);
// Navigate to the appropriate route based on the selected module
switch (module.module) {
case Module.inspection:
Get.toNamed(InspectionRoutes.init);

View File

@@ -152,7 +152,7 @@ class SplashLogic extends GetxController with GetTickerProviderStateMixin {
try {
final isUpdateNeeded = await checkVersion();
if (isUpdateNeeded) return;
tokenService.getModule();
final module = tokenService.appModule.value;
final target = getTargetPage(module);
Get.offAndToNamed(target);

View File

@@ -10,14 +10,14 @@ _LoginRequestModel _$LoginRequestModelFromJson(Map<String, dynamic> json) =>
_LoginRequestModel(
username: json['username'] as String?,
password: json['password'] as String?,
captchaCode: json['captchaCode'] as String?,
captchaKey: json['captchaKey'] as String?,
captchaCode: json['captcha_code'] as String?,
captchaKey: json['captcha_key'] as String?,
);
Map<String, dynamic> _$LoginRequestModelToJson(_LoginRequestModel instance) =>
<String, dynamic>{
'username': instance.username,
'password': instance.password,
'captchaCode': instance.captchaCode,
'captchaKey': instance.captchaKey,
'captcha_code': instance.captchaCode,
'captcha_key': instance.captchaKey,
};

View File

@@ -10,12 +10,12 @@ _AuthResponseModel _$AuthResponseModelFromJson(Map<String, dynamic> json) =>
_AuthResponseModel(
refresh: json['refresh'] as String?,
access: json['access'] as String?,
otpStatus: json['otpStatus'] as bool?,
otpStatus: json['otp_status'] as bool?,
);
Map<String, dynamic> _$AuthResponseModelToJson(_AuthResponseModel instance) =>
<String, dynamic>{
'refresh': instance.refresh,
'access': instance.access,
'otpStatus': instance.otpStatus,
'otp_status': instance.otpStatus,
};

View File

@@ -9,17 +9,17 @@ part of 'captcha_response_model.dart';
_CaptchaResponseModel _$CaptchaResponseModelFromJson(
Map<String, dynamic> json,
) => _CaptchaResponseModel(
captchaKey: json['captchaKey'] as String?,
captchaImage: json['captchaImage'] as String?,
imageType: json['imageType'] as String?,
imageDecode: json['imageDecode'] as String?,
captchaKey: json['captcha_key'] as String?,
captchaImage: json['captcha_image'] as String?,
imageType: json['image_type'] as String?,
imageDecode: json['image_decode'] as String?,
);
Map<String, dynamic> _$CaptchaResponseModelToJson(
_CaptchaResponseModel instance,
) => <String, dynamic>{
'captchaKey': instance.captchaKey,
'captchaImage': instance.captchaImage,
'imageType': instance.imageType,
'imageDecode': instance.imageDecode,
'captcha_key': instance.captchaKey,
'captcha_image': instance.captchaImage,
'image_type': instance.imageType,
'image_decode': instance.imageDecode,
};

View File

@@ -8,16 +8,16 @@ part of 'user_info_model.dart';
_UserInfoModel _$UserInfoModelFromJson(Map<String, dynamic> json) =>
_UserInfoModel(
isUser: json['isUser'] as bool?,
isUser: json['is_user'] as bool?,
address: json['address'] as String?,
backend: json['backend'] as String?,
apiKey: json['apiKey'] as String?,
apiKey: json['api_key'] as String?,
);
Map<String, dynamic> _$UserInfoModelToJson(_UserInfoModel instance) =>
<String, dynamic>{
'isUser': instance.isUser,
'is_user': instance.isUser,
'address': instance.address,
'backend': instance.backend,
'apiKey': instance.apiKey,
'api_key': instance.apiKey,
};

View File

@@ -8,40 +8,40 @@ part of 'user_profile_model.dart';
_UserProfileModel _$UserProfileModelFromJson(Map<String, dynamic> json) =>
_UserProfileModel(
accessToken: json['accessToken'] as String?,
expiresIn: json['expiresIn'] as String?,
accessToken: json['access_token'] as String?,
expiresIn: json['expires_in'] as String?,
scope: json['scope'] as String?,
expireTime: json['expireTime'] as String?,
expireTime: json['expire_time'] as String?,
mobile: json['mobile'] as String?,
fullname: json['fullname'] as String?,
firstname: json['firstname'] as String?,
lastname: json['lastname'] as String?,
city: json['city'] as String?,
province: json['province'] as String?,
nationalCode: json['nationalCode'] as String?,
nationalId: json['nationalId'] as String?,
nationalCode: json['national_code'] as String?,
nationalId: json['national_id'] as String?,
birthday: json['birthday'] as String?,
image: json['image'] as String?,
baseOrder: (json['baseOrder'] as num?)?.toInt(),
baseOrder: (json['base_order'] as num?)?.toInt(),
role: (json['role'] as List<dynamic>?)?.map((e) => e as String).toList(),
);
Map<String, dynamic> _$UserProfileModelToJson(_UserProfileModel instance) =>
<String, dynamic>{
'accessToken': instance.accessToken,
'expiresIn': instance.expiresIn,
'access_token': instance.accessToken,
'expires_in': instance.expiresIn,
'scope': instance.scope,
'expireTime': instance.expireTime,
'expire_time': instance.expireTime,
'mobile': instance.mobile,
'fullname': instance.fullname,
'firstname': instance.firstname,
'lastname': instance.lastname,
'city': instance.city,
'province': instance.province,
'nationalCode': instance.nationalCode,
'nationalId': instance.nationalId,
'national_code': instance.nationalCode,
'national_id': instance.nationalId,
'birthday': instance.birthday,
'image': instance.image,
'baseOrder': instance.baseOrder,
'base_order': instance.baseOrder,
'role': instance.role,
};

6
packages/core/build.yaml Normal file
View File

@@ -0,0 +1,6 @@
targets:
$default:
builders:
json_serializable:
options:
field_rename: snake

View File

@@ -1,3 +1,4 @@
export 'pagination_model/pagination_model.dart';
export 'local/module/module_model.dart';
export 'local/user_local/user_local_model.dart';
export 'pagination_model/pagination_model.dart';

View File

@@ -1,4 +1,5 @@
import 'dart:convert';
import 'package:rasadyar_core/core.dart';
import 'package:rasadyar_core/hive_registrar.g.dart';
@@ -38,7 +39,7 @@ class TokenStorageService extends GetxService {
accessToken.value = _localStorage.read<String?>(boxName: _tokenBoxName, key: _accessTokenKey);
refreshToken.value = _localStorage.read<String?>(boxName: _tokenBoxName, key: _refreshTokenKey);
appModule.value = _localStorage.read<Module?>(boxName: _appBoxName, key: _moduleKey);
appModule.value = getModule();
baseurl.value = _localStorage.read<String?>(boxName: _appBoxName, key: _baseUrlKey);
}
@@ -60,6 +61,10 @@ class TokenStorageService extends GetxService {
appModule.refresh();
}
Module? getModule() {
return _localStorage.read<Module?>(boxName: _tokenBoxName, key: _moduleKey);
}
Future<void> deleteTokens() async {
await _localStorage.clear(_tokenBoxName);
accessToken.value = null;

View File

@@ -46,6 +46,9 @@ class $AssetsIconsGen {
/// File path: assets/icons/arrow_right.svg
SvgGenImage get arrowRight => const SvgGenImage('assets/icons/arrow_right.svg');
/// File path: assets/icons/bg_auth.svg
SvgGenImage get bgAuth => const SvgGenImage('assets/icons/bg_auth.svg');
/// File path: assets/icons/bg_header_user_profile.svg
SvgGenImage get bgHeaderUserProfile => const SvgGenImage('assets/icons/bg_header_user_profile.svg');
@@ -278,6 +281,7 @@ class $AssetsIconsGen {
appBarInspection,
arrowLeft,
arrowRight,
bgAuth,
bgHeaderUserProfile,
buy,
calendar,
@@ -403,6 +407,9 @@ class $AssetsVecGen {
/// File path: assets/vec/arrow_right.svg.vec
SvgGenImage get arrowRightSvg => const SvgGenImage.vec('assets/vec/arrow_right.svg.vec');
/// File path: assets/vec/bg_auth.svg.vec
SvgGenImage get bgAuthSvg => const SvgGenImage.vec('assets/vec/bg_auth.svg.vec');
/// File path: assets/vec/bg_header_user_profile.svg.vec
SvgGenImage get bgHeaderUserProfileSvg => const SvgGenImage.vec('assets/vec/bg_header_user_profile.svg.vec');
@@ -635,6 +642,7 @@ class $AssetsVecGen {
appBarInspectionSvg,
arrowLeftSvg,
arrowRightSvg,
bgAuthSvg,
bgHeaderUserProfileSvg,
buySvg,
calendarSvg,

View File

@@ -0,0 +1,6 @@
targets:
$default:
builders:
json_serializable:
options:
field_rename: snake

View File

@@ -0,0 +1,14 @@
import 'package:rasadyar_inspection/data/model/response/auth/auth_response_model.dart';
import 'package:rasadyar_inspection/data/model/response/captcha/captcha_response_model.dart';
abstract class AuthRemote {
Future<AuthResponseModel?> login({required Map<String, dynamic> authRequest});
Future<CaptchaResponseModel?> captcha();
Future<void> logout();
Future<bool> hasAuthenticated();
Future<AuthResponseModel?> loginWithRefreshToken({required Map<String, dynamic> authRequest});
}

View File

@@ -1,22 +1,22 @@
import 'package:rasadyar_core/core.dart';
import 'package:rasadyar_core/data/model/response/auth/auth_response_model.dart';
import 'package:rasadyar_core/data/model/response/captcha/captcha_response_model.dart';
import 'package:rasadyar_core/data/model/response/user_info/user_info_model.dart';
import 'package:rasadyar_core/data/model/response/user_profile_model/user_profile_model.dart';
import 'auth_repository.dart';
import 'package:rasadyar_inspection/data/model/response/auth/auth_response_model.dart';
import 'package:rasadyar_inspection/data/model/response/captcha/captcha_response_model.dart';
import 'package:rasadyar_inspection/data/model/response/user_profile/user_profile_model.dart';
class AuthRepositoryImpl implements AuthRepository {
import 'auth_remote.dart';
class AuthRemoteImp extends AuthRemote {
final DioRemote _httpClient;
final String _BASE_URL = 'auth/api/v1/';
AuthRepositoryImpl(this._httpClient);
AuthRemoteImp(this._httpClient);
@override
Future<UserProfileModel?> login({required Map<String, dynamic> authRequest}) async {
var res = await _httpClient.post<UserProfileModel?>(
'/api/login/',
Future<AuthResponseModel?> login({required Map<String, dynamic> authRequest}) async {
var res = await _httpClient.post<AuthResponseModel?>(
'${_BASE_URL}login/',
data: authRequest,
fromJson: UserProfileModel.fromJson,
fromJson: AuthResponseModel.fromJson,
headers: {'Content-Type': 'application/json'},
);
return res.data;
@@ -59,14 +59,14 @@ class AuthRepositoryImpl implements AuthRepository {
return response.data ?? false;
}
@override
Future<UserInfoModel?> getUserInfo(String phoneNumber) async {
var res = await _httpClient.post<UserInfoModel?>(
/* @override
Future<UserProfileModel?> getUserInfo(String phoneNumber) async {
var res = await _httpClient.post<UserProfileModel?>(
'https://userbackend.rasadyaar.ir/api/send_otp/',
data: {"mobile": phoneNumber, "state": ""},
fromJson: UserInfoModel.fromJson,
fromJson: UserProfileModel.fromJson,
headers: {'Content-Type': 'application/json'},
);
return res.data;
}
}*/
}

View File

@@ -0,0 +1,22 @@
import 'package:rasadyar_inspection/data/model/response/poultry_location/poultry_location_model.dart';
abstract class InspectionRemoteDataSource {
/// Fetches the inspection data for a given [inspectionId].
///
/// Returns a `Future` that resolves to a `Map<String, dynamic>` containing
/// the inspection data.
Future<Map<String, dynamic>> fetchInspectionData(String inspectionId);
/// Fetches the list of inspections for a given [userId].
///
/// Returns a `Future` that resolves to a `List<Map<String, dynamic>>`
/// containing the list of inspections.
Future<List<Map<String, dynamic>>> fetchInspections(String userId);
Future<List<PoultryLocationModel>?> getNearbyLocation({
double? centerLat,
double? centerLng,
double? radius,
});
}

View File

@@ -0,0 +1,42 @@
import 'package:rasadyar_core/core.dart';
import 'package:rasadyar_inspection/data/data_source/remote/inspection/inspection_remote.dart';
import 'package:rasadyar_inspection/data/model/response/poultry_location/poultry_location_model.dart';
class InspectionRemoteDataSourceImp implements InspectionRemoteDataSource {
final DioRemote _httpClient;
final String _BASE_URL = 'auth/api/v1/';
InspectionRemoteDataSourceImp(this._httpClient);
@override
Future<Map<String, dynamic>> fetchInspectionData(String inspectionId) {
// TODO: implement fetchInspectionData
throw UnimplementedError();
}
@override
Future<List<Map<String, dynamic>>> fetchInspections(String userId) {
// TODO: implement fetchInspections
throw UnimplementedError();
}
@override
Future<List<PoultryLocationModel>?> getNearbyLocation({
double? centerLat,
double? centerLng,
double? radius,
}) async {
DioRemote dioRemote = DioRemote(baseUrl: 'https://habackend.rasadyaar.ir/');
await dioRemote.init();
var res = await dioRemote.get<List<PoultryLocationModel>>(
'poultry-loc/',
queryParameters: {'center_lat': centerLat, 'center_lng': centerLng, 'radius': radius},
headers: {'Content-Type': 'application/json'},
fromJsonList: (json) =>
json.map((item) => PoultryLocationModel.fromJson(item as Map<String, dynamic>)).toList(),
);
return res.data;
}
}

View File

@@ -0,0 +1,8 @@
import 'package:rasadyar_inspection/data/model/response/user_profile/user_profile_model.dart';
abstract class UserRemoteDataSource {
Future<UserProfileModel?> getProfile({required String token});
}

View File

@@ -0,0 +1,25 @@
import 'package:rasadyar_core/core.dart';
import 'package:rasadyar_inspection/data/data_source/remote/user/user_data_source.dart';
import 'package:rasadyar_inspection/data/model/response/user_profile/user_profile_model.dart';
class UserRemoteDataSourceImp extends UserRemoteDataSource {
final DioRemote _httpClient;
final String _BASE_URL = 'auth/api/v1/';
UserRemoteDataSourceImp(this._httpClient);
@override
Future<UserProfileModel?> getProfile({required String token}) async {
var res = await _httpClient.get<UserProfileModel>(
'${_BASE_URL}user/profile/',
fromJson: UserProfileModel.fromJson,
headers: {'Content-Type': 'application/json', 'Authorization': 'Bearer $token'},
);
if (res.data == null) {
throw Exception('Failed to load user profile');
}
return res.data!;
}
}

View File

@@ -0,0 +1,34 @@
import 'package:rasadyar_core/core.dart';
part 'login_request_model.freezed.dart';
part 'login_request_model.g.dart';
@freezed
abstract class LoginRequestModel with _$LoginRequestModel {
const factory LoginRequestModel({
String? username,
String? password,
String? captchaCode,
String? captchaKey,
}) = _LoginRequestModel;
factory LoginRequestModel.createWithCaptcha({
required String username,
required String password,
required String captchaCode,
required String captchaKey,
}) {
return LoginRequestModel(
username: username,
password: password,
captchaCode: captchaCode,
captchaKey: 'rest_captcha_$captchaKey.0',
);
}
factory LoginRequestModel.fromJson(Map<String, dynamic> json) =>
_$LoginRequestModelFromJson(json);
const LoginRequestModel._();
}

View File

@@ -0,0 +1,286 @@
// 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 'login_request_model.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
// dart format off
T _$identity<T>(T value) => value;
/// @nodoc
mixin _$LoginRequestModel {
String? get username; String? get password; String? get captchaCode; String? get captchaKey;
/// Create a copy of LoginRequestModel
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
$LoginRequestModelCopyWith<LoginRequestModel> get copyWith => _$LoginRequestModelCopyWithImpl<LoginRequestModel>(this as LoginRequestModel, _$identity);
/// Serializes this LoginRequestModel to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is LoginRequestModel&&(identical(other.username, username) || other.username == username)&&(identical(other.password, password) || other.password == password)&&(identical(other.captchaCode, captchaCode) || other.captchaCode == captchaCode)&&(identical(other.captchaKey, captchaKey) || other.captchaKey == captchaKey));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,username,password,captchaCode,captchaKey);
@override
String toString() {
return 'LoginRequestModel(username: $username, password: $password, captchaCode: $captchaCode, captchaKey: $captchaKey)';
}
}
/// @nodoc
abstract mixin class $LoginRequestModelCopyWith<$Res> {
factory $LoginRequestModelCopyWith(LoginRequestModel value, $Res Function(LoginRequestModel) _then) = _$LoginRequestModelCopyWithImpl;
@useResult
$Res call({
String? username, String? password, String? captchaCode, String? captchaKey
});
}
/// @nodoc
class _$LoginRequestModelCopyWithImpl<$Res>
implements $LoginRequestModelCopyWith<$Res> {
_$LoginRequestModelCopyWithImpl(this._self, this._then);
final LoginRequestModel _self;
final $Res Function(LoginRequestModel) _then;
/// Create a copy of LoginRequestModel
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? username = freezed,Object? password = freezed,Object? captchaCode = freezed,Object? captchaKey = freezed,}) {
return _then(_self.copyWith(
username: freezed == username ? _self.username : username // ignore: cast_nullable_to_non_nullable
as String?,password: freezed == password ? _self.password : password // ignore: cast_nullable_to_non_nullable
as String?,captchaCode: freezed == captchaCode ? _self.captchaCode : captchaCode // ignore: cast_nullable_to_non_nullable
as String?,captchaKey: freezed == captchaKey ? _self.captchaKey : captchaKey // ignore: cast_nullable_to_non_nullable
as String?,
));
}
}
/// Adds pattern-matching-related methods to [LoginRequestModel].
extension LoginRequestModelPatterns on LoginRequestModel {
/// 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( _LoginRequestModel value)? $default,{required TResult orElse(),}){
final _that = this;
switch (_that) {
case _LoginRequestModel() 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( _LoginRequestModel value) $default,){
final _that = this;
switch (_that) {
case _LoginRequestModel():
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( _LoginRequestModel value)? $default,){
final _that = this;
switch (_that) {
case _LoginRequestModel() 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( String? username, String? password, String? captchaCode, String? captchaKey)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _LoginRequestModel() when $default != null:
return $default(_that.username,_that.password,_that.captchaCode,_that.captchaKey);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( String? username, String? password, String? captchaCode, String? captchaKey) $default,) {final _that = this;
switch (_that) {
case _LoginRequestModel():
return $default(_that.username,_that.password,_that.captchaCode,_that.captchaKey);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( String? username, String? password, String? captchaCode, String? captchaKey)? $default,) {final _that = this;
switch (_that) {
case _LoginRequestModel() when $default != null:
return $default(_that.username,_that.password,_that.captchaCode,_that.captchaKey);case _:
return null;
}
}
}
/// @nodoc
@JsonSerializable()
class _LoginRequestModel extends LoginRequestModel {
const _LoginRequestModel({this.username, this.password, this.captchaCode, this.captchaKey}): super._();
factory _LoginRequestModel.fromJson(Map<String, dynamic> json) => _$LoginRequestModelFromJson(json);
@override final String? username;
@override final String? password;
@override final String? captchaCode;
@override final String? captchaKey;
/// Create a copy of LoginRequestModel
/// with the given fields replaced by the non-null parameter values.
@override @JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$LoginRequestModelCopyWith<_LoginRequestModel> get copyWith => __$LoginRequestModelCopyWithImpl<_LoginRequestModel>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$LoginRequestModelToJson(this, );
}
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _LoginRequestModel&&(identical(other.username, username) || other.username == username)&&(identical(other.password, password) || other.password == password)&&(identical(other.captchaCode, captchaCode) || other.captchaCode == captchaCode)&&(identical(other.captchaKey, captchaKey) || other.captchaKey == captchaKey));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,username,password,captchaCode,captchaKey);
@override
String toString() {
return 'LoginRequestModel(username: $username, password: $password, captchaCode: $captchaCode, captchaKey: $captchaKey)';
}
}
/// @nodoc
abstract mixin class _$LoginRequestModelCopyWith<$Res> implements $LoginRequestModelCopyWith<$Res> {
factory _$LoginRequestModelCopyWith(_LoginRequestModel value, $Res Function(_LoginRequestModel) _then) = __$LoginRequestModelCopyWithImpl;
@override @useResult
$Res call({
String? username, String? password, String? captchaCode, String? captchaKey
});
}
/// @nodoc
class __$LoginRequestModelCopyWithImpl<$Res>
implements _$LoginRequestModelCopyWith<$Res> {
__$LoginRequestModelCopyWithImpl(this._self, this._then);
final _LoginRequestModel _self;
final $Res Function(_LoginRequestModel) _then;
/// Create a copy of LoginRequestModel
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? username = freezed,Object? password = freezed,Object? captchaCode = freezed,Object? captchaKey = freezed,}) {
return _then(_LoginRequestModel(
username: freezed == username ? _self.username : username // ignore: cast_nullable_to_non_nullable
as String?,password: freezed == password ? _self.password : password // ignore: cast_nullable_to_non_nullable
as String?,captchaCode: freezed == captchaCode ? _self.captchaCode : captchaCode // ignore: cast_nullable_to_non_nullable
as String?,captchaKey: freezed == captchaKey ? _self.captchaKey : captchaKey // ignore: cast_nullable_to_non_nullable
as String?,
));
}
}
// dart format on

View File

@@ -0,0 +1,23 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'login_request_model.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_LoginRequestModel _$LoginRequestModelFromJson(Map<String, dynamic> json) =>
_LoginRequestModel(
username: json['username'] as String?,
password: json['password'] as String?,
captchaCode: json['captcha_code'] as String?,
captchaKey: json['captcha_key'] as String?,
);
Map<String, dynamic> _$LoginRequestModelToJson(_LoginRequestModel instance) =>
<String, dynamic>{
'username': instance.username,
'password': instance.password,
'captcha_code': instance.captchaCode,
'captcha_key': instance.captchaKey,
};

View File

@@ -0,0 +1,20 @@
import 'package:freezed_annotation/freezed_annotation.dart';
part 'auth_response_model.freezed.dart';
part 'auth_response_model.g.dart';
@freezed
abstract class AuthResponseModel with _$AuthResponseModel {
const factory AuthResponseModel({
String? refresh,
String? access,
bool? otpStatus,
}) = _AuthResponseModel;
factory AuthResponseModel.fromJson(Map<String, dynamic> json) =>
_$AuthResponseModelFromJson(json);
}

View File

@@ -0,0 +1,283 @@
// 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 'auth_response_model.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
// dart format off
T _$identity<T>(T value) => value;
/// @nodoc
mixin _$AuthResponseModel {
String? get refresh; String? get access; bool? get otpStatus;
/// Create a copy of AuthResponseModel
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
$AuthResponseModelCopyWith<AuthResponseModel> get copyWith => _$AuthResponseModelCopyWithImpl<AuthResponseModel>(this as AuthResponseModel, _$identity);
/// Serializes this AuthResponseModel to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is AuthResponseModel&&(identical(other.refresh, refresh) || other.refresh == refresh)&&(identical(other.access, access) || other.access == access)&&(identical(other.otpStatus, otpStatus) || other.otpStatus == otpStatus));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,refresh,access,otpStatus);
@override
String toString() {
return 'AuthResponseModel(refresh: $refresh, access: $access, otpStatus: $otpStatus)';
}
}
/// @nodoc
abstract mixin class $AuthResponseModelCopyWith<$Res> {
factory $AuthResponseModelCopyWith(AuthResponseModel value, $Res Function(AuthResponseModel) _then) = _$AuthResponseModelCopyWithImpl;
@useResult
$Res call({
String? refresh, String? access, bool? otpStatus
});
}
/// @nodoc
class _$AuthResponseModelCopyWithImpl<$Res>
implements $AuthResponseModelCopyWith<$Res> {
_$AuthResponseModelCopyWithImpl(this._self, this._then);
final AuthResponseModel _self;
final $Res Function(AuthResponseModel) _then;
/// Create a copy of AuthResponseModel
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? refresh = freezed,Object? access = freezed,Object? otpStatus = freezed,}) {
return _then(_self.copyWith(
refresh: freezed == refresh ? _self.refresh : refresh // ignore: cast_nullable_to_non_nullable
as String?,access: freezed == access ? _self.access : access // ignore: cast_nullable_to_non_nullable
as String?,otpStatus: freezed == otpStatus ? _self.otpStatus : otpStatus // ignore: cast_nullable_to_non_nullable
as bool?,
));
}
}
/// Adds pattern-matching-related methods to [AuthResponseModel].
extension AuthResponseModelPatterns on AuthResponseModel {
/// 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( _AuthResponseModel value)? $default,{required TResult orElse(),}){
final _that = this;
switch (_that) {
case _AuthResponseModel() 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( _AuthResponseModel value) $default,){
final _that = this;
switch (_that) {
case _AuthResponseModel():
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( _AuthResponseModel value)? $default,){
final _that = this;
switch (_that) {
case _AuthResponseModel() 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( String? refresh, String? access, bool? otpStatus)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _AuthResponseModel() when $default != null:
return $default(_that.refresh,_that.access,_that.otpStatus);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( String? refresh, String? access, bool? otpStatus) $default,) {final _that = this;
switch (_that) {
case _AuthResponseModel():
return $default(_that.refresh,_that.access,_that.otpStatus);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( String? refresh, String? access, bool? otpStatus)? $default,) {final _that = this;
switch (_that) {
case _AuthResponseModel() when $default != null:
return $default(_that.refresh,_that.access,_that.otpStatus);case _:
return null;
}
}
}
/// @nodoc
@JsonSerializable()
class _AuthResponseModel implements AuthResponseModel {
const _AuthResponseModel({this.refresh, this.access, this.otpStatus});
factory _AuthResponseModel.fromJson(Map<String, dynamic> json) => _$AuthResponseModelFromJson(json);
@override final String? refresh;
@override final String? access;
@override final bool? otpStatus;
/// Create a copy of AuthResponseModel
/// with the given fields replaced by the non-null parameter values.
@override @JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$AuthResponseModelCopyWith<_AuthResponseModel> get copyWith => __$AuthResponseModelCopyWithImpl<_AuthResponseModel>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$AuthResponseModelToJson(this, );
}
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _AuthResponseModel&&(identical(other.refresh, refresh) || other.refresh == refresh)&&(identical(other.access, access) || other.access == access)&&(identical(other.otpStatus, otpStatus) || other.otpStatus == otpStatus));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,refresh,access,otpStatus);
@override
String toString() {
return 'AuthResponseModel(refresh: $refresh, access: $access, otpStatus: $otpStatus)';
}
}
/// @nodoc
abstract mixin class _$AuthResponseModelCopyWith<$Res> implements $AuthResponseModelCopyWith<$Res> {
factory _$AuthResponseModelCopyWith(_AuthResponseModel value, $Res Function(_AuthResponseModel) _then) = __$AuthResponseModelCopyWithImpl;
@override @useResult
$Res call({
String? refresh, String? access, bool? otpStatus
});
}
/// @nodoc
class __$AuthResponseModelCopyWithImpl<$Res>
implements _$AuthResponseModelCopyWith<$Res> {
__$AuthResponseModelCopyWithImpl(this._self, this._then);
final _AuthResponseModel _self;
final $Res Function(_AuthResponseModel) _then;
/// Create a copy of AuthResponseModel
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? refresh = freezed,Object? access = freezed,Object? otpStatus = freezed,}) {
return _then(_AuthResponseModel(
refresh: freezed == refresh ? _self.refresh : refresh // ignore: cast_nullable_to_non_nullable
as String?,access: freezed == access ? _self.access : access // ignore: cast_nullable_to_non_nullable
as String?,otpStatus: freezed == otpStatus ? _self.otpStatus : otpStatus // ignore: cast_nullable_to_non_nullable
as bool?,
));
}
}
// dart format on

View File

@@ -0,0 +1,21 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'auth_response_model.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_AuthResponseModel _$AuthResponseModelFromJson(Map<String, dynamic> json) =>
_AuthResponseModel(
refresh: json['refresh'] as String?,
access: json['access'] as String?,
otpStatus: json['otp_status'] as bool?,
);
Map<String, dynamic> _$AuthResponseModelToJson(_AuthResponseModel instance) =>
<String, dynamic>{
'refresh': instance.refresh,
'access': instance.access,
'otp_status': instance.otpStatus,
};

View File

@@ -0,0 +1,17 @@
import 'package:freezed_annotation/freezed_annotation.dart';
part 'captcha_response_model.freezed.dart';
part 'captcha_response_model.g.dart';
@freezed
abstract class CaptchaResponseModel with _$CaptchaResponseModel {
const factory CaptchaResponseModel({
String? captchaKey,
String? captchaImage,
String? imageType,
String? imageDecode,
}) = _CaptchaResponseModel;
factory CaptchaResponseModel.fromJson(Map<String, dynamic> json) =>
_$CaptchaResponseModelFromJson(json);
}

View File

@@ -0,0 +1,286 @@
// 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 'captcha_response_model.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
// dart format off
T _$identity<T>(T value) => value;
/// @nodoc
mixin _$CaptchaResponseModel {
String? get captchaKey; String? get captchaImage; String? get imageType; String? get imageDecode;
/// Create a copy of CaptchaResponseModel
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
$CaptchaResponseModelCopyWith<CaptchaResponseModel> get copyWith => _$CaptchaResponseModelCopyWithImpl<CaptchaResponseModel>(this as CaptchaResponseModel, _$identity);
/// Serializes this CaptchaResponseModel to a JSON map.
Map<String, dynamic> toJson();
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is CaptchaResponseModel&&(identical(other.captchaKey, captchaKey) || other.captchaKey == captchaKey)&&(identical(other.captchaImage, captchaImage) || other.captchaImage == captchaImage)&&(identical(other.imageType, imageType) || other.imageType == imageType)&&(identical(other.imageDecode, imageDecode) || other.imageDecode == imageDecode));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,captchaKey,captchaImage,imageType,imageDecode);
@override
String toString() {
return 'CaptchaResponseModel(captchaKey: $captchaKey, captchaImage: $captchaImage, imageType: $imageType, imageDecode: $imageDecode)';
}
}
/// @nodoc
abstract mixin class $CaptchaResponseModelCopyWith<$Res> {
factory $CaptchaResponseModelCopyWith(CaptchaResponseModel value, $Res Function(CaptchaResponseModel) _then) = _$CaptchaResponseModelCopyWithImpl;
@useResult
$Res call({
String? captchaKey, String? captchaImage, String? imageType, String? imageDecode
});
}
/// @nodoc
class _$CaptchaResponseModelCopyWithImpl<$Res>
implements $CaptchaResponseModelCopyWith<$Res> {
_$CaptchaResponseModelCopyWithImpl(this._self, this._then);
final CaptchaResponseModel _self;
final $Res Function(CaptchaResponseModel) _then;
/// Create a copy of CaptchaResponseModel
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? captchaKey = freezed,Object? captchaImage = freezed,Object? imageType = freezed,Object? imageDecode = freezed,}) {
return _then(_self.copyWith(
captchaKey: freezed == captchaKey ? _self.captchaKey : captchaKey // ignore: cast_nullable_to_non_nullable
as String?,captchaImage: freezed == captchaImage ? _self.captchaImage : captchaImage // ignore: cast_nullable_to_non_nullable
as String?,imageType: freezed == imageType ? _self.imageType : imageType // ignore: cast_nullable_to_non_nullable
as String?,imageDecode: freezed == imageDecode ? _self.imageDecode : imageDecode // ignore: cast_nullable_to_non_nullable
as String?,
));
}
}
/// Adds pattern-matching-related methods to [CaptchaResponseModel].
extension CaptchaResponseModelPatterns on CaptchaResponseModel {
/// 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( _CaptchaResponseModel value)? $default,{required TResult orElse(),}){
final _that = this;
switch (_that) {
case _CaptchaResponseModel() 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( _CaptchaResponseModel value) $default,){
final _that = this;
switch (_that) {
case _CaptchaResponseModel():
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( _CaptchaResponseModel value)? $default,){
final _that = this;
switch (_that) {
case _CaptchaResponseModel() 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( String? captchaKey, String? captchaImage, String? imageType, String? imageDecode)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _CaptchaResponseModel() when $default != null:
return $default(_that.captchaKey,_that.captchaImage,_that.imageType,_that.imageDecode);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( String? captchaKey, String? captchaImage, String? imageType, String? imageDecode) $default,) {final _that = this;
switch (_that) {
case _CaptchaResponseModel():
return $default(_that.captchaKey,_that.captchaImage,_that.imageType,_that.imageDecode);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( String? captchaKey, String? captchaImage, String? imageType, String? imageDecode)? $default,) {final _that = this;
switch (_that) {
case _CaptchaResponseModel() when $default != null:
return $default(_that.captchaKey,_that.captchaImage,_that.imageType,_that.imageDecode);case _:
return null;
}
}
}
/// @nodoc
@JsonSerializable()
class _CaptchaResponseModel implements CaptchaResponseModel {
const _CaptchaResponseModel({this.captchaKey, this.captchaImage, this.imageType, this.imageDecode});
factory _CaptchaResponseModel.fromJson(Map<String, dynamic> json) => _$CaptchaResponseModelFromJson(json);
@override final String? captchaKey;
@override final String? captchaImage;
@override final String? imageType;
@override final String? imageDecode;
/// Create a copy of CaptchaResponseModel
/// with the given fields replaced by the non-null parameter values.
@override @JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$CaptchaResponseModelCopyWith<_CaptchaResponseModel> get copyWith => __$CaptchaResponseModelCopyWithImpl<_CaptchaResponseModel>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$CaptchaResponseModelToJson(this, );
}
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _CaptchaResponseModel&&(identical(other.captchaKey, captchaKey) || other.captchaKey == captchaKey)&&(identical(other.captchaImage, captchaImage) || other.captchaImage == captchaImage)&&(identical(other.imageType, imageType) || other.imageType == imageType)&&(identical(other.imageDecode, imageDecode) || other.imageDecode == imageDecode));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType,captchaKey,captchaImage,imageType,imageDecode);
@override
String toString() {
return 'CaptchaResponseModel(captchaKey: $captchaKey, captchaImage: $captchaImage, imageType: $imageType, imageDecode: $imageDecode)';
}
}
/// @nodoc
abstract mixin class _$CaptchaResponseModelCopyWith<$Res> implements $CaptchaResponseModelCopyWith<$Res> {
factory _$CaptchaResponseModelCopyWith(_CaptchaResponseModel value, $Res Function(_CaptchaResponseModel) _then) = __$CaptchaResponseModelCopyWithImpl;
@override @useResult
$Res call({
String? captchaKey, String? captchaImage, String? imageType, String? imageDecode
});
}
/// @nodoc
class __$CaptchaResponseModelCopyWithImpl<$Res>
implements _$CaptchaResponseModelCopyWith<$Res> {
__$CaptchaResponseModelCopyWithImpl(this._self, this._then);
final _CaptchaResponseModel _self;
final $Res Function(_CaptchaResponseModel) _then;
/// Create a copy of CaptchaResponseModel
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? captchaKey = freezed,Object? captchaImage = freezed,Object? imageType = freezed,Object? imageDecode = freezed,}) {
return _then(_CaptchaResponseModel(
captchaKey: freezed == captchaKey ? _self.captchaKey : captchaKey // ignore: cast_nullable_to_non_nullable
as String?,captchaImage: freezed == captchaImage ? _self.captchaImage : captchaImage // ignore: cast_nullable_to_non_nullable
as String?,imageType: freezed == imageType ? _self.imageType : imageType // ignore: cast_nullable_to_non_nullable
as String?,imageDecode: freezed == imageDecode ? _self.imageDecode : imageDecode // ignore: cast_nullable_to_non_nullable
as String?,
));
}
}
// dart format on

View File

@@ -0,0 +1,25 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'captcha_response_model.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_CaptchaResponseModel _$CaptchaResponseModelFromJson(
Map<String, dynamic> json,
) => _CaptchaResponseModel(
captchaKey: json['captcha_key'] as String?,
captchaImage: json['captcha_image'] as String?,
imageType: json['image_type'] as String?,
imageDecode: json['image_decode'] as String?,
);
Map<String, dynamic> _$CaptchaResponseModelToJson(
_CaptchaResponseModel instance,
) => <String, dynamic>{
'captcha_key': instance.captchaKey,
'captcha_image': instance.captchaImage,
'image_type': instance.imageType,
'image_decode': instance.imageDecode,
};

View File

@@ -0,0 +1,68 @@
import 'package:freezed_annotation/freezed_annotation.dart';
part 'poultry_location_model.freezed.dart';
part 'poultry_location_model.g.dart';
@freezed
abstract class PoultryLocationModel with _$PoultryLocationModel {
const factory PoultryLocationModel({
int? id,
String? unitName,
@JsonKey(name: 'Lat')
double? lat,
@JsonKey(name: 'Long')
double? long,
User? user,
List<Hatching>? hatching,
Address? address,
}) = _PoultryLocationModel;
factory PoultryLocationModel.fromJson(Map<String, dynamic> json) =>
_$PoultryLocationModelFromJson(json);
}
@freezed
abstract class User with _$User {
const factory User({
String? fullname,
String? mobile,
}) = _User;
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
}
@freezed
abstract class Hatching with _$Hatching {
const factory Hatching({
int? quantity,
int? leftOver,
int? period,
int? chickenAge,
DateTime? date,
bool?violation,
bool?archive,
}) = _Hatching;
factory Hatching.fromJson(Map<String, dynamic> json) =>
_$HatchingFromJson(json);
}
@freezed
abstract class Address with _$Address {
const factory Address({
City? city,
String? address,
}) = _Address;
factory Address.fromJson(Map<String, dynamic> json) =>
_$AddressFromJson(json);
}
@freezed
abstract class City with _$City {
const factory City({
String? name,
}) = _City;
factory City.fromJson(Map<String, dynamic> json) => _$CityFromJson(json);
}

View File

@@ -0,0 +1,73 @@
import 'package:rasadyar_core/core.dart';
part 'user_profile_model.freezed.dart';
part 'user_profile_model.g.dart';
@freezed
abstract class UserProfileModel with _$UserProfileModel {
const factory UserProfileModel({
required User user,
required Role role,
required List<Permission> permissions,
}) = _UserProfileModel;
factory UserProfileModel.fromJson(Map<String, dynamic> json) => _$UserProfileModelFromJson(json);
}
@freezed
abstract class User with _$User {
const factory User({
required int id,
required String username,
required String password,
required String firstName,
required String lastName,
required bool isActive,
required String mobile,
required String phone,
required String nationalCode,
required DateTime birthdate,
required String nationality,
required String ownership,
required String address,
required String photo,
required int province,
required int city,
required bool otpStatus,
required String cityName,
required String provinceName,
}) = _User;
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
}
@freezed
abstract class Role with _$Role {
const factory Role({
required int id,
required String roleName,
required String description,
required RoleType type,
required List<dynamic> permissions,
}) = _Role;
factory Role.fromJson(Map<String, dynamic> json) => _$RoleFromJson(json);
}
@freezed
abstract class RoleType with _$RoleType {
const factory RoleType({String? key, required String name}) = _RoleType;
factory RoleType.fromJson(Map<String, dynamic> json) => _$RoleTypeFromJson(json);
}
@freezed
abstract class Permission with _$Permission {
const factory Permission({required String pageName, required List<String> pageAccess}) =
_Permission;
factory Permission.fromJson(Map<String, dynamic> json) => _$PermissionFromJson(json);
}

View File

@@ -0,0 +1,17 @@
import 'package:rasadyar_inspection/data/model/response/auth/auth_response_model.dart';
import 'package:rasadyar_inspection/data/model/response/captcha/captcha_response_model.dart';
abstract class AuthRepository {
Future<AuthResponseModel?> login({required Map<String, dynamic> authRequest});
Future<CaptchaResponseModel?> captcha();
Future<void> logout();
Future<bool> hasAuthenticated();
Future<AuthResponseModel?> loginWithRefreshToken({required Map<String, dynamic> authRequest});
}

View File

@@ -0,0 +1,37 @@
import 'package:rasadyar_inspection/data/data_source/remote/auth/auth_remote.dart';
import 'package:rasadyar_inspection/data/model/response/auth/auth_response_model.dart';
import 'package:rasadyar_inspection/data/model/response/captcha/captcha_response_model.dart';
import 'auth_repository.dart';
class AuthRepositoryImpl implements AuthRepository {
final AuthRemote authRemote;
AuthRepositoryImpl(this.authRemote);
@override
Future<AuthResponseModel?> login({required Map<String, dynamic> authRequest}) async =>
await authRemote.login(authRequest: authRequest);
@override
Future<CaptchaResponseModel?> captcha() async {
return await authRemote.captcha();
}
@override
Future<AuthResponseModel?> loginWithRefreshToken({
required Map<String, dynamic> authRequest,
}) async {
return await authRemote.loginWithRefreshToken(authRequest: authRequest);
}
@override
Future<void> logout() async {
await authRemote.logout();
}
@override
Future<bool> hasAuthenticated() async {
return await authRemote.hasAuthenticated();
}
}

View File

@@ -1,18 +0,0 @@
import 'package:rasadyar_core/data/model/response/auth/auth_response_model.dart';
import 'package:rasadyar_core/data/model/response/captcha/captcha_response_model.dart';
import 'package:rasadyar_core/data/model/response/user_info/user_info_model.dart';
import 'package:rasadyar_core/data/model/response/user_profile_model/user_profile_model.dart';
abstract class AuthRepository {
Future<UserProfileModel?> login({required Map<String, dynamic> authRequest});
Future<CaptchaResponseModel?> captcha();
Future<void> logout();
Future<bool> hasAuthenticated();
Future<AuthResponseModel?> loginWithRefreshToken({required Map<String, dynamic> authRequest});
Future<UserInfoModel?> getUserInfo(String phoneNumber);
}

View File

@@ -0,0 +1,24 @@
import 'package:rasadyar_inspection/data/model/response/poultry_location/poultry_location_model.dart';
abstract class InspectionRepository {
/// Fetches the inspection data for a given [inspectionId].
///
/// Returns a `Future` that resolves to a `Map<String, dynamic>` containing
/// the inspection data.
Future<Map<String, dynamic>> fetchInspectionData(String inspectionId);
/// Fetches the list of inspections for a given [userId].
///
/// Returns a `Future` that resolves to a `List<Map<String, dynamic>>`
/// containing the list of inspections.
Future<List<Map<String, dynamic>>> fetchInspections(String userId);
/// Fetches nearby poultry locations based on the provided coordinates and radius.
///
/// Returns a `Future` that resolves to a `List<PoultryLocationModel>?`.
Future<List<PoultryLocationModel>?> getNearbyLocation({
double? centerLat,
double? centerLng,
double? radius,
});
}

View File

@@ -0,0 +1,34 @@
import 'package:rasadyar_inspection/data/data_source/remote/inspection/inspection_remote.dart';
import 'package:rasadyar_inspection/data/model/response/poultry_location/poultry_location_model.dart';
import 'package:rasadyar_inspection/data/repositories/inspection/inspection_repository.dart';
class InspectionRepositoryImp implements InspectionRepository {
final InspectionRemoteDataSource remoteDataSource;
InspectionRepositoryImp({required this.remoteDataSource});
@override
Future<Map<String, dynamic>> fetchInspectionData(String inspectionId) {
// TODO: implement fetchInspectionData
throw UnimplementedError();
}
@override
Future<List<Map<String, dynamic>>> fetchInspections(String userId) {
// TODO: implement fetchInspections
throw UnimplementedError();
}
@override
Future<List<PoultryLocationModel>?> getNearbyLocation({
double? centerLat,
double? centerLng,
double? radius,
}) async {
return remoteDataSource.getNearbyLocation(
centerLat: centerLat,
centerLng: centerLng,
radius: radius,
);
}
}

View File

@@ -0,0 +1,19 @@
import 'package:rasadyar_inspection/data/model/response/user_profile/user_profile_model.dart';
abstract class UserRepository {
/// Fetches the user profile from the remote data source.
///
/// Returns a [Future] that resolves to a [UserProfileModel].
Future<UserProfileModel?> fetchUserProfile({required String token});
/// Updates the user profile in the remote data source.
///
/// Takes a [UserProfileModel] as an argument and returns a [Future] that resolves to a boolean indicating success or failure.
Future<bool> updateUserProfile(UserProfileModel userProfile);
/// Changes the password of the user in the remote data source.
///
/// Takes the old password, new password, and confirm password as arguments and returns a [Future] that resolves to a boolean indicating success or failure.
Future<bool> changePassword(String oldPassword, String newPassword, String confirmPassword);
}

View File

@@ -0,0 +1,28 @@
import 'package:rasadyar_inspection/data/data_source/remote/user/user_data_source_imp.dart';
import 'package:rasadyar_inspection/data/model/response/user_profile/user_profile_model.dart';
import 'user_repository.dart';
class UserRepositoryImp implements UserRepository {
final UserRemoteDataSourceImp _remoteDataSource;
UserRepositoryImp(this._remoteDataSource);
@override
Future<bool> changePassword(String oldPassword, String newPassword, String confirmPassword) {
// TODO: implement changePassword
throw UnimplementedError();
}
@override
Future<UserProfileModel?> fetchUserProfile({required String token}) async {
return await _remoteDataSource.getProfile(token: token);
}
@override
Future<bool> updateUserProfile(UserProfileModel userProfile) {
// TODO: implement updateUserProfile
throw UnimplementedError();
}
}

View File

@@ -0,0 +1,58 @@
import 'package:flutter/material.dart';
import 'package:rasadyar_core/core.dart';
class DioErrorHandler {
void handle(DioException error) {
switch (error.response?.statusCode) {
case 401:
_handleGeneric(error);
break;
case 403:
_handleGeneric(error);
break;
case 410:
_handle410();
break;
default:
_handleGeneric(error);
}
}
//wrong password/user name => "detail": "No active account found with the given credentials" - 401
void _handle410() {
Get.showSnackbar(_errorSnackBar('نام کاربری یا رمز عبور اشتباه است'));
}
//wrong captcha => "detail": "Captcha code is incorrect" - 403
void _handle403() {}
void _handleGeneric(DioException error) {
Get.showSnackbar(
_errorSnackBar(
error.response?.data.keys.first == 'is_user'
? 'کاربر با این شماره تلفن وجود ندارد'
: error.response?.data[error.response?.data.keys.first] ??
'خطا در برقراری ارتباط با سرور',
),
);
}
GetSnackBar _errorSnackBar(String message) {
return GetSnackBar(
titleText: Text(
'خطا',
style: AppFonts.yekan14.copyWith(color: Colors.white),
),
messageText: Text(
message,
style: AppFonts.yekan12.copyWith(color: Colors.white),
),
backgroundColor: AppColor.error,
margin: EdgeInsets.symmetric(horizontal: 12, vertical: 8),
borderRadius: 12,
duration: Duration(milliseconds: 3500),
snackPosition: SnackPosition.TOP,
);
}
}

View File

@@ -0,0 +1,71 @@
import 'package:rasadyar_core/core.dart';
import 'package:rasadyar_inspection/data/data_source/remote/auth/auth_remote.dart';
import 'package:rasadyar_inspection/data/data_source/remote/auth/auth_remote_imp.dart';
import 'package:rasadyar_inspection/data/data_source/remote/inspection/inspection_remote_imp.dart';
import 'package:rasadyar_inspection/data/data_source/remote/user/user_data_source_imp.dart';
import 'package:rasadyar_inspection/data/repositories/auth/auth_repository_imp.dart';
import 'package:rasadyar_inspection/data/repositories/inspection/inspection_repository_imp.dart';
import 'package:rasadyar_inspection/data/repositories/user/user_repository_imp.dart';
import 'package:rasadyar_inspection/data/utils/dio_exception_handeler.dart';
import 'package:rasadyar_inspection/presentation/routes/app_routes.dart';
GetIt diInspection = GetIt.instance;
Future<void> setupInspectionDI() async {
diInspection.registerSingleton(DioErrorHandler());
var tokenService = Get.find<TokenStorageService>();
if (tokenService.baseurl.value == null) {
await tokenService.saveBaseUrl('https://bazrasbackend.rasadyaar.ir/');
}
diInspection.registerLazySingleton<AppInterceptor>(
() => AppInterceptor(
//TODO : Update the base URL to the correct one for inspection module
refreshTokenCallback: () async => null,
saveTokenCallback: (String newToken) async {
await tokenService.saveAccessToken(newToken);
},
clearTokenCallback: () async {
await tokenService.deleteTokens();
Get.offAllNamed(InspectionRoutes.auth, arguments: Module.inspection);
},
authArguments: Module.inspection,
),
instanceName: 'inspectionInterceptor',
);
diInspection.registerLazySingleton<DioRemote>(() {
return DioRemote(
baseUrl: tokenService.baseurl.value,
interceptors: diInspection.get<AppInterceptor>(instanceName: 'inspectionInterceptor'),
);
}, instanceName: 'inspectionDioRemote');
var dioRemote = diInspection.get<DioRemote>(instanceName: 'inspectionDioRemote');
await dioRemote.init();
diInspection.registerLazySingleton<AuthRemote>(
() => AuthRemoteImp(diInspection.get<DioRemote>(instanceName: 'inspectionDioRemote')),
);
diInspection.registerSingleton<AuthRepositoryImpl>(
AuthRepositoryImpl(diInspection.get<AuthRemote>()),
);
diInspection.registerSingleton<UserRemoteDataSourceImp>(
UserRemoteDataSourceImp(diInspection.get<DioRemote>(instanceName: 'inspectionDioRemote')),
);
diInspection.registerSingleton<UserRepositoryImp>(
UserRepositoryImp(diInspection.get<UserRemoteDataSourceImp>()),
);
diInspection.registerSingleton<InspectionRemoteDataSourceImp>(
InspectionRemoteDataSourceImp(diInspection.get<DioRemote>(instanceName: 'inspectionDioRemote')),
);
diInspection.registerSingleton<InspectionRepositoryImp>(
InspectionRepositoryImp(remoteDataSource: diInspection.get<InspectionRemoteDataSourceImp>()),
);
diInspection.registerSingleton(ImagePicker());
}

View File

@@ -2,10 +2,12 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:rasadyar_core/core.dart';
import 'package:rasadyar_core/data/model/request/login_request/login_request_model.dart';
import 'package:rasadyar_core/data/model/response/user_info/user_info_model.dart';
import 'package:rasadyar_core/data/model/response/user_profile_model/user_profile_model.dart';
import 'package:rasadyar_inspection/data/repositories/auth_repository_imp.dart';
import 'package:rasadyar_inspection/data/model/request/login_request/login_request_model.dart';
import 'package:rasadyar_inspection/data/model/response/auth/auth_response_model.dart';
import 'package:rasadyar_inspection/data/repositories/auth/auth_repository_imp.dart';
import 'package:rasadyar_inspection/data/utils/dio_exception_handeler.dart';
import 'package:rasadyar_inspection/injection/inspection_di.dart';
import 'package:rasadyar_inspection/presentation/routes/app_routes.dart';
import 'package:rasadyar_inspection/presentation/widget/captcha/logic.dart';
enum AuthType { useAndPass, otp }
@@ -38,7 +40,7 @@ class AuthLogic extends GetxController {
RxInt secondsRemaining = 120.obs;
Timer? _timer;
//AuthRepositoryImpl authRepository = diAuth.get<AuthRepositoryImpl>();
AuthRepositoryImpl authRepository = diInspection.get<AuthRepositoryImpl>();
final Module _module = Get.arguments;
@@ -97,27 +99,28 @@ class AuthLogic extends GetxController {
);
}
/*Future<void> submitLoginForm() async {
Future<void> submitLoginForm() async {
if (!_isFormValid()) return;
iLog('module222 : ${_module.toString()}');
final loginRequestModel = _buildLoginRequest();
isLoading.value = true;
await safeCall<AuthResponseModel?>(
call: () => authRepository.login(authRequest: loginRequestModel.toJson()),
call: () async => authRepository.login(authRequest: loginRequestModel.toJson()),
onSuccess: (result) async {
await tokenStorageService.saveModule(_module);
await tokenStorageService.saveRefreshToken(result?.refresh ?? '');
await tokenStorageService.saveAccessToken(result?.access ?? '');
Get.offAllNamed(InspectionRoutes.init);
},
onError: (error, stackTrace) {
if (error is DioException) {
diAuth.get<DioErrorHandler>().handle(error);
diInspection.get<DioErrorHandler>().handle(error);
}
captchaController.getCaptcha();
},
);
isLoading.value = false;
}*/
}
Future<void> submitLoginForm2() async {
if (!_isFormValid()) return;

View File

@@ -184,7 +184,7 @@ class AuthPage extends GetView<AuthLogic> {
onPressed: controller.isDisabled.value
? null
: () async {
await controller.submitLoginForm2();
await controller.submitLoginForm();
},
width: Get.width,
height: 48,

View File

@@ -1,20 +1,23 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:rasadyar_core/core.dart';
import 'package:rasadyar_inspection/data/utils/marker_generator.dart';
import 'package:rasadyar_inspection/data/model/response/poultry_location/poultry_location_model.dart';
import 'package:rasadyar_inspection/data/repositories/inspection/inspection_repository_imp.dart';
import 'package:rasadyar_inspection/injection/inspection_di.dart';
import 'package:rasadyar_inspection/presentation/widget/base_page/logic.dart';
import '../filter/view.dart';
class InspectionMapLogic extends GetxController with GetTickerProviderStateMixin {
final BaseLogic baseLogic = Get.find<BaseLogic>();
Rx<LatLng> currentLocation = LatLng(35.824891, 50.948025).obs;
RxList<LatLng> allMarkers = <LatLng>[].obs;
RxList<LatLng> markers = <LatLng>[].obs;
Rx<LatLng> currentLocation = LatLng(34.798315281272544, 48.51479142983491).obs;
Rx<Resource<List<PoultryLocationModel>>> allPoultryLocation =
Resource<List<PoultryLocationModel>>.loading().obs;
RxList<PoultryLocationModel> markers = <PoultryLocationModel>[].obs;
Timer? _debounceTimer;
RxBool isLoading = false.obs;
RxBool isSelectedDetailsLocation = false.obs;
@@ -33,55 +36,7 @@ class InspectionMapLogic extends GetxController with GetTickerProviderStateMixin
late DraggableBottomSheetController detailsLocationBottomSheetController;
late final BottomSheetManager bottomSheetManager;
Future<void> determineCurrentPosition() async {
isLoading.value = true;
final position = await Geolocator.getCurrentPosition(
locationSettings: AndroidSettings(accuracy: LocationAccuracy.best),
);
final latLng = LatLng(position.latitude, position.longitude);
currentLocation.value = latLng;
markers.add(latLng);
animatedMapController.animateTo(
dest: latLng,
zoom: 18,
curve: Curves.easeInOut,
duration: const Duration(seconds: 1),
);
isLoading.value = false;
}
void debouncedUpdateVisibleMarkers({required LatLng center}) {
_debounceTimer?.cancel();
_debounceTimer = Timer(const Duration(milliseconds: 300), () {
final filtered = filterNearbyMarkers({
'markers': allMarkers,
'centerLat': center.latitude,
'centerLng': center.longitude,
'radius': 2000.0,
});
markers.addAll(filtered);
});
}
List<LatLng> filterNearbyMarkers(Map<String, dynamic> args) {
final List<LatLng> rawMarkers = args['markers'];
final double centerLat = args['centerLat'];
final double centerLng = args['centerLng'];
final double radiusInMeters = args['radius'];
final center = LatLng(centerLat, centerLng);
final distance = Distance();
return rawMarkers
.where((marker) => distance(center, marker) <= radiusInMeters)
.toList();
}
Future<void> generatedMarkers() async {
final generatedMarkers = await generateLocationsUsingCompute(100000);
allMarkers.value = generatedMarkers;
}
InspectionRepositoryImp inspectionRepository = diInspection.get<InspectionRepositoryImp>();
@override
void onInit() {
@@ -92,6 +47,7 @@ class InspectionMapLogic extends GetxController with GetTickerProviderStateMixin
curve: Curves.easeInOut,
cancelPreviousAnimations: true,
);
fetchAllPoultryLocations();
filterBottomSheetController = DraggableBottomSheetController(
initialHeight: 350,
@@ -105,7 +61,6 @@ class InspectionMapLogic extends GetxController with GetTickerProviderStateMixin
maxHeight: 200,
);
detailsLocationBottomSheetController = DraggableBottomSheetController(
initialHeight: Get.height * 0.5,
minHeight: Get.height * 0.37,
@@ -114,13 +69,10 @@ class InspectionMapLogic extends GetxController with GetTickerProviderStateMixin
slidController = SlidableController(this).obs;
bottomSheetManager = BottomSheetManager({
filterBottomSheetController:
() => filterWidget(filterIndex: filterIndex, showIndex: showIndex),
selectedLocationBottomSheetController:
() => selectedLocationWidget(
showHint:
selectedLocationBottomSheetController.isVisible.value &&
showSlideHint,
filterBottomSheetController: () =>
filterWidget(filterIndex: filterIndex, showIndex: showIndex),
selectedLocationBottomSheetController: () => selectedLocationWidget(
showHint: selectedLocationBottomSheetController.isVisible.value && showSlideHint,
sliderController: slidController.value,
trigger: triggerSlidableAnimation,
toggle: selectedLocationBottomSheetController.toggle,
@@ -132,8 +84,63 @@ class InspectionMapLogic extends GetxController with GetTickerProviderStateMixin
@override
void onReady() {
super.onReady();
determineCurrentPosition();
generatedMarkers();
//determineCurrentPosition();
}
@override
void onClose() {
slidController.close();
super.onClose();
}
Future<void> determineCurrentPosition() async {
isLoading.value = true;
final position = await Geolocator.getCurrentPosition(
locationSettings: AndroidSettings(accuracy: LocationAccuracy.best),
);
final latLng = LatLng(position.latitude, position.longitude);
/*currentLocation.value = latLng;
markers.add(PoultryLocationModel(
lat: latLng.latitude,
long: latLng.longitude
));*/
animatedMapController.animateTo(
dest: latLng,
zoom: 18,
curve: Curves.easeInOut,
duration: const Duration(seconds: 1),
);
isLoading.value = false;
}
void debouncedUpdateVisibleMarkers({required LatLng center}) {
_debounceTimer?.cancel();
_debounceTimer = Timer(const Duration(milliseconds: 300), () {
final filtered = filterNearbyMarkers(
allPoultryLocation.value.data ?? [],
center.latitude,
center.longitude,
10000, // Radius in meters
);
markers.addAll(filtered);
});
}
List<PoultryLocationModel> filterNearbyMarkers(
List<PoultryLocationModel> allMarkers,
double centerLat,
double centerLng,
double radiusInMeters,
) {
final center = LatLng(centerLat, centerLng);
final distance = Distance();
return allMarkers.where((marker) {
var tmp =LatLng(marker.lat ?? 0, marker.long ?? 0);
return distance(center,tmp ) <= radiusInMeters;
}).toList();
}
Future<void> triggerSlidableAnimation() async {
@@ -144,9 +151,23 @@ class InspectionMapLogic extends GetxController with GetTickerProviderStateMixin
showSlideHint = false;
}
@override
void onClose() {
slidController.close();
super.onClose();
Future<void> fetchAllPoultryLocations() async {
isLoading.value = true;
allPoultryLocation.value = Resource<List<PoultryLocationModel>>.loading();
await safeCall(
call: () => inspectionRepository.getNearbyLocation(),
onSuccess: (result) {
if (result != null) {
allPoultryLocation.value = Resource<List<PoultryLocationModel>>.success(result);
} else {
allPoultryLocation.value = Resource<List<PoultryLocationModel>>.error(
'No locations found',
);
}
},
onError: (error, stackTrace) {
allPoultryLocation.value = Resource<List<PoultryLocationModel>>.error(error.toString());
},
);
}
}

View File

@@ -54,7 +54,7 @@ class InspectionMapPage extends GetView<InspectionMapLogic> {
markers: markers
.map(
(e) => markerWidget(
marker: e,
marker: LatLng(e.lat??0, e.long??0),
onTap: () {
Get.bottomSheet(
selectedLocationWidget2(
@@ -295,6 +295,7 @@ class InspectionMapPage extends GetView<InspectionMapLogic> {
}
Marker markerWidget({required LatLng marker, required VoidCallback onTap}) {
iLog('lat: ${marker.latitude}, lng: ${marker.longitude}');
return Marker(
point: marker,
child: GestureDetector(

View File

@@ -1,28 +1,27 @@
import 'package:rasadyar_core/core.dart';
import 'package:rasadyar_inspection/data/model/response/user_profile/user_profile_model.dart';
import 'package:rasadyar_inspection/data/repositories/user/user_repository_imp.dart';
import 'package:rasadyar_inspection/injection/inspection_di.dart';
import 'package:rasadyar_inspection/inspection.dart';
class ProfileLogic extends GetxController {
List<String> roles = <String>[
'کاربر عادی',
'کاربر ویژه',
'کاربر VIP',
'کاربر نقره ای',
'کاربر طلایی',
];
RootLogic rootLogic = Get.find<RootLogic>();
UserRepositoryImp userRepository = diInspection.get<UserRepositoryImp>();
Rx<Resource<UserProfileModel>> userProfile = Resource<UserProfileModel>.loading().obs;
RxInt selectedRole = 0.obs;
RxInt selectedInformationType = 0.obs;
@override
void onReady() {
// TODO: implement onReady
super.onReady();
rootLogic.userProfile.listen((data) {
if (data != null) {
userProfile.value = Resource<UserProfileModel>.success(data);
} else {
userProfile.value = Resource<UserProfileModel>.error('Failed to load user profile');
}
});
}
@override
@@ -30,4 +29,26 @@ class ProfileLogic extends GetxController {
// TODO: implement onClose
super.onClose();
}
Future<void> fetchUserProfile() async {
userProfile.value = Resource<UserProfileModel>.loading();
await safeCall(
call: () => userRepository.fetchUserProfile(
token: rootLogic.tokenStorageService.accessToken.value ?? '',
),
onSuccess: (profile) {
if (profile != null) {
userProfile.value = Resource<UserProfileModel>.success(profile);
} else {
userProfile.value = Resource<UserProfileModel>.error('Failed to load user profile');
}
},
onError: (error, stackTrace) {
userProfile.value = Resource<UserProfileModel>.error(
'Failed to load user profile: ${error.toString()}',
);
},
);
}
}

View File

@@ -1,5 +1,7 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:rasadyar_core/core.dart';
import 'package:rasadyar_inspection/data/model/response/user_profile/user_profile_model.dart';
import 'logic.dart';
@@ -9,124 +11,96 @@ class ProfilePage extends GetView<ProfileLogic> {
@override
Widget build(BuildContext context) {
return Column(
spacing: 30,
children: [
SizedBox(
height: Get.height * 0.3,
child: Stack(
fit: StackFit.expand,
alignment: Alignment.center,
clipBehavior: Clip.none,
Expanded(
flex: 1,
child: Container(
color: AppColor.blueNormal,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Assets.vec.bgHeaderUserProfileSvg.svg(),
Positioned(
bottom: -20,
left: 0,
right: 0,
child: SizedBox(
width: 110,
height: 110,
Row(),
ObxValue((data) {
final status = data.value.status;
if (status == ResourceStatus.loading) {
return Container(
width: 128.w,
height: 128.h,
child: Center(child: CupertinoActivityIndicator(color: AppColor.greenNormal)),
);
}
if (status == ResourceStatus.error) {
return Container(
width: 128.w,
height: 128.h,
child: Center(child: Text('خطا در دریافت اطلاعات')),
);
}
// Default UI
return Container(
width: 128.w,
height: 128.h,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: AppColor.blueLightActive,
),
child: Center(
child: CircleAvatar(
backgroundColor: AppColor.blueLightHover,
child: FaIcon(
FontAwesomeIcons.user,
size: 45,
color: Colors.white,
),
),
radius: 64.w,
backgroundImage: NetworkImage(data.value.data?.user.photo ?? ''),
),
),
);
}, controller.userProfile),
],
),
),
),
Expanded(
flex: 3,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 16,
children: [
SizedBox(
height: 75,
child: ListView.separated(
shrinkWrap: true,
padding: EdgeInsets.all(16),
scrollDirection: Axis.horizontal,
itemBuilder:
(context, index) => ObxValue((data) {
return ChoiceChip(
onSelected: (value) {
data.value = index;
},
selectedColor: AppColor.blueNormal,
labelStyle:
data.value == index
? AppFonts.yekan13.copyWith(
color: AppColor.whiteLight,
)
: AppFonts.yekan12.copyWith(
color: AppColor.darkGreyNormalActive,
),
checkmarkColor: Colors.white,
label: Text(controller.roles[index]),
selected: index == data.value,
);
}, controller.selectedRole),
separatorBuilder: (context, index) => SizedBox(width: 8),
itemCount: controller.roles.length,
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 30,
vertical: 10,
),
child: ObxValue((data) {
return switch (data.value) {
0 => userProfileInformation(),
1 => bankInformationWidget(),
2 => invoiceIssuanceInformation(),
int() => Placeholder(),
};
}, controller.selectedInformationType),
padding: const EdgeInsets.symmetric(horizontal: 30, vertical: 10),
child: userProfileInformation(),
),
),
ObxValue((data) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
Center(
child: Wrap(
alignment: WrapAlignment.center,
spacing: 20,
runSpacing: 10,
children: [
cardActionWidget(
title: 'اطلاعات کاربری',
title: 'تغییر رمز عبور',
selected: true,
onPressed: () {
data.value = 0;
Get.bottomSheet(changePasswordBottomSheet(), isScrollControlled: true);
},
icon: Assets.vec.profileUserSvg.path,
selected: data.value == 0,
icon: Assets.vec.lockSvg.path,
),
cardActionWidget(
title: 'اطلاعات بانکی',
title: 'خروج',
selected: true,
color: ColorFilter.mode(Colors.redAccent, BlendMode.srcIn),
cardColor: Color(0xFFEFEFEF),
textColor: AppColor.redDarkerText,
onPressed: () {
data.value = 1;
Get.bottomSheet(exitBottomSheet(), isScrollControlled: true);
},
icon: Assets.vec.informationSvg.path,
selected: data.value == 1,
),
cardActionWidget(
title: 'اطلاعات \nصدور فاکتور',
onPressed: () {
data.value = 2;
},
icon: Assets.vec.receiptDiscountSvg.path,
selected: data.value == 2,
icon: Assets.vec.logoutSvg.path,
),
],
),
);
}, controller.selectedInformationType),
),
SizedBox(height: 100),
],
@@ -149,72 +123,113 @@ class ProfilePage extends GetView<ProfileLogic> {
],
);
Column userProfileInformation() {
Widget userProfileInformation() {
return ObxValue((data) {
if (data.value.status == ResourceStatus.loading) {
return LoadingWidget();
} else if (data.value.status == ResourceStatus.error) {
return ErrorWidget('خطا در دریافت اطلاعات کاربر');
} else if (data.value.status == ResourceStatus.success) {
User item = data.value.data!.user;
return Column(
spacing: 10,
spacing: 6,
children: [
buildRowOnTapped(
onTap: () {
Get.bottomSheet(
userInformationBottomSheet(),
isScrollControlled: true,
ignoreSafeArea: false,
);
},
titleWidget: Column(
spacing: 3,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'اطلاعات هویتی',
style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal),
),
Container(width: 37.w, height: 1.h, color: AppColor.greenNormal),
],
),
valueWidget: Assets.vec.editSvg.svg(
width: 24.w,
height: 24.h,
colorFilter: ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
),
),
itemList(
title: 'نام و نام خانوادگی',
content: 'آیدا گل محمدی',
content: '${item.firstName} ${item.lastName}',
icon: Assets.vec.userSvg.path,
hasColoredBox: true,
),
itemList(
title: 'موبایل',
content: '09302654896',
content: item.mobile ?? 'نامشخص',
icon: Assets.vec.callSvg.path,
),
itemList(
title: 'کدملی',
content: 'نا مشخص',
content: item.nationalCode ?? 'نامشخص',
icon: Assets.vec.tagUserSvg.path,
),
itemList(
title: 'شماره شناسنامه',
content: 'نا مشخص',
content: item.nationalCode ?? 'نامشخص',
icon: Assets.vec.userSquareSvg.path,
),
itemList(
title: 'تاریخ تولد',
content: '1404/10/12',
icon: Assets.vec.calendarSvg.path,
),
itemList(
title: 'استان',
content: 'لرستان',
content: item.provinceName ?? 'نامشخص',
icon: Assets.vec.pictureFrameSvg.path,
),
itemList(
title: 'شهر',
content: 'خرم آباد',
content: item.cityName ?? 'نامشخص',
icon: Assets.vec.mapSvg.path,
),
],
);
} else {
return SizedBox.shrink();
}
}, controller.userProfile);
}
Widget itemList({
required String title,
required String content,
String? icon,
}) => Row(
bool hasColoredBox = false,
}) => Container(
padding: EdgeInsets.symmetric(horizontal: 12.h, vertical: 6.h),
decoration: BoxDecoration(
color: hasColoredBox ? AppColor.greenLight : Colors.transparent,
borderRadius: BorderRadius.circular(8),
border: hasColoredBox
? Border.all(width: 0.25, color: AppColor.bgDark)
: Border.all(width: 0, color: Colors.transparent),
),
child: Row(
spacing: 4,
children: [
if (icon != null)
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: SvgGenImage.vec(icon).svg(
width: 20,
height: 20,
colorFilter: ColorFilter.mode(AppColor.blueNormal, BlendMode.srcIn),
width: 20.w,
height: 20.h,
colorFilter: ColorFilter.mode(AppColor.mediumGreyNormalActive, BlendMode.srcIn),
),
),
Text(title, style: AppFonts.yekan12.copyWith(color: AppColor.blueNormal)),
Text(title, style: AppFonts.yekan12.copyWith(color: AppColor.mediumGreyNormalActive)),
Spacer(),
Text(
content,
style: AppFonts.yekan13.copyWith(color: AppColor.darkGreyNormalHover),
),
Text(content, style: AppFonts.yekan13.copyWith(color: AppColor.mediumGreyNormalHover)),
],
),
);
Widget cardActionWidget({
@@ -222,6 +237,9 @@ class ProfilePage extends GetView<ProfileLogic> {
required VoidCallback onPressed,
required String icon,
bool selected = false,
ColorFilter? color,
Color? cardColor,
Color? textColor,
}) {
return GestureDetector(
onTap: onPressed,
@@ -233,16 +251,16 @@ class ProfilePage extends GetView<ProfileLogic> {
height: 52,
padding: EdgeInsets.all(8),
decoration: ShapeDecoration(
color: selected ? AppColor.blueLightActive : AppColor.blueLight,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
color: cardColor ?? AppColor.blueLight,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
),
child: SvgGenImage.vec(icon).svg(
width: 40,
height: 40,
colorFilter: ColorFilter.mode(
selected ? AppColor.whiteLight : AppColor.blueNormal,
colorFilter:
color ??
ColorFilter.mode(
selected ? AppColor.blueNormal : AppColor.whiteLight,
BlendMode.srcIn,
),
),
@@ -251,7 +269,7 @@ class ProfilePage extends GetView<ProfileLogic> {
Text(
title,
style: AppFonts.yekan10.copyWith(
color: selected ? AppColor.blueNormal : AppColor.blueLightActive,
color: textColor ?? (selected ? AppColor.blueNormal : AppColor.blueLightActive),
),
textAlign: TextAlign.center,
),
@@ -259,4 +277,359 @@ class ProfilePage extends GetView<ProfileLogic> {
),
);
}
Widget userInformationBottomSheet() {
return Container(color: Colors.red);
/* return BaseBottomSheet(
height: 750.h,
child: SingleChildScrollView(
child: Column(
spacing: 8,
children: [
Text(
'ویرایش اطلاعات هویتی',
style: AppFonts.yekan16Bold.copyWith(color: AppColor.darkGreyDarkHover),
),
Container(
padding: EdgeInsets.all(8),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
border: Border.all(color: AppColor.darkGreyLight, width: 1),
),
child: Column(
spacing: 12,
children: [
RTextField(
controller: controller.nameController,
label: 'نام',
borderColor: AppColor.darkGreyLight,
filledColor: AppColor.bgLight,
filled: true,
),
RTextField(
controller: controller.lastNameController,
label: 'نام خانوادگی',
borderColor: AppColor.darkGreyLight,
filledColor: AppColor.bgLight,
filled: true,
),
RTextField(
controller: controller.nationalCodeController,
label: 'شماره شناسنامه',
borderColor: AppColor.darkGreyLight,
filledColor: AppColor.bgLight,
filled: true,
),
RTextField(
controller: controller.nationalIdController,
label: 'کد ملی',
borderColor: AppColor.darkGreyLight,
filledColor: AppColor.bgLight,
filled: true,
),
ObxValue((data) {
return RTextField(
controller: controller.birthdayController,
label: 'تاریخ تولد',
initText: data.value?.formatCompactDate() ?? '',
borderColor: AppColor.darkGreyLight,
filledColor: AppColor.bgLight,
filled: true,
onTap: () {},
);
}, controller.birthDate),
SizedBox(),
],
),
),
SizedBox(),
Container(
padding: EdgeInsets.all(8),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
border: Border.all(color: AppColor.darkGreyLight, width: 1),
),
child: Column(
spacing: 8,
children: [
Text(
'عکس پروفایل',
style: AppFonts.yekan16Bold.copyWith(color: AppColor.blueNormal),
),
ObxValue((data) {
return Container(
width: Get.width,
height: 270,
decoration: BoxDecoration(
color: AppColor.lightGreyNormal,
borderRadius: BorderRadius.circular(8),
border: Border.all(width: 1, color: AppColor.blackLight),
),
child: Center(
child: data.value == null
? Padding(
padding: const EdgeInsets.fromLTRB(30, 10, 10, 30),
child: Image.network(
controller.userProfile.value.data?.image ?? '',
),
)
: Image.file(File(data.value!.path), fit: BoxFit.cover),
),
);
}, controller.selectedImage),
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
RElevated(
text: 'گالری',
width: 150.w,
height: 40.h,
textStyle: AppFonts.yekan20.copyWith(color: Colors.white),
onPressed: () async {
controller.selectedImage.value = await controller.imagePicker.pickImage(
source: ImageSource.gallery,
imageQuality: 60,
maxWidth: 1080,
maxHeight: 720,
);
},
),
SizedBox(width: 16),
ROutlinedElevated(
text: 'دوربین',
width: 150.w,
height: 40.h,
textStyle: AppFonts.yekan20.copyWith(color: AppColor.blueNormal),
onPressed: () async {
controller.selectedImage.value = await controller.imagePicker.pickImage(
source: ImageSource.camera,
imageQuality: 60,
maxWidth: 1080,
maxHeight: 720,
);
},
),
],
),
],
),
),
Row(
spacing: 16,
mainAxisAlignment: MainAxisAlignment.center,
children: [
ObxValue((data) {
return RElevated(
height: 40.h,
text: 'ویرایش',
isLoading: data.value,
onPressed: () async {
await controller.updateUserProfile();
controller.getUserProfile();
Get.back();
},
);
}, controller.isOnLoading),
ROutlinedElevated(
height: 40.h,
text: 'انصراف',
borderColor: AppColor.blueNormal,
onPressed: () {
Get.back();
},
),
],
),
],
),
),
);*/
}
/* Widget _provinceWidget() {
return Obx(() {
return OverlayDropdownWidget<IranProvinceCityModel>(
items: controller.rootLogic.provinces,
onChanged: (value) {
controller.selectedProvince.value = value;
},
selectedItem: controller.selectedProvince.value,
itemBuilder: (item) => Text(item.name ?? 'بدون نام'),
labelBuilder: (item) => Text(item?.name ?? 'انتخاب استان'),
);
});
}
Widget _cityWidget() {
return ObxValue((data) {
return OverlayDropdownWidget<IranProvinceCityModel>(
items: data,
onChanged: (value) {
controller.selectedCity.value = value;
},
selectedItem: controller.selectedCity.value,
itemBuilder: (item) => Text(item.name ?? 'بدون نام'),
labelBuilder: (item) => Text(item?.name ?? 'انتخاب شهر'),
);
}, controller.cites);
}*/
Widget changePasswordBottomSheet() {
return Container(color: Colors.red);
/* return BaseBottomSheet(
height: 400.h,
child: SingleChildScrollView(
child: Form(
key: controller.formKey,
child: Column(
spacing: 8,
children: [
Text(
'تغییر رمز عبور',
style: AppFonts.yekan16Bold.copyWith(color: AppColor.darkGreyDarkHover),
),
SizedBox(),
RTextField(
controller: controller.oldPasswordController,
hintText: 'رمز عبور قبلی',
borderColor: AppColor.darkGreyLight,
filledColor: AppColor.bgLight,
filled: true,
validator: (value) {
if (value == null || value.isEmpty) {
return 'رمز عبور را وارد کنید';
} else if (controller.userProfile.value.data?.password != value) {
return 'رمز عبور صحیح نیست';
}
return null;
},
),
RTextField(
controller: controller.newPasswordController,
hintText: 'رمز عبور جدید',
borderColor: AppColor.darkGreyLight,
filledColor: AppColor.bgLight,
filled: true,
validator: (value) {
if (value == null || value.isEmpty) {
return 'رمز عبور را وارد کنید';
} else if (value.length < 6) {
return 'رمز عبور باید بیش از 6 کارکتر باشد.';
}
return null;
},
),
RTextField(
controller: controller.retryNewPasswordController,
hintText: 'تکرار رمز عبور جدید',
borderColor: AppColor.darkGreyLight,
filledColor: AppColor.bgLight,
filled: true,
validator: (value) {
if (value == null || value.isEmpty) {
return 'رمز عبور را وارد کنید';
} else if (value.length < 6) {
return 'رمز عبور باید بیش از 6 کارکتر باشد.';
} else if (controller.newPasswordController.text != value) {
return 'رمز عبور جدید یکسان نیست';
}
return null;
},
),
SizedBox(),
Row(
spacing: 16,
mainAxisAlignment: MainAxisAlignment.center,
children: [
RElevated(
height: 40.h,
text: 'ویرایش',
onPressed: () async {
if (controller.formKey.currentState?.validate() != true) {
return;
}
await controller.updatePassword();
controller.getUserProfile();
controller.clearPasswordForm();
Get.back();
},
),
ROutlinedElevated(
height: 40.h,
text: 'انصراف',
borderColor: AppColor.blueNormal,
onPressed: () {
Get.back();
},
),
],
),
],
),
),
),
);*/
}
Widget exitBottomSheet() {
return Container(color: Colors.red);
/* return BaseBottomSheet(
height: 220.h,
child: SingleChildScrollView(
child: Form(
key: controller.formKey,
child: Column(
spacing: 8,
children: [
Text('خروج', style: AppFonts.yekan16Bold.copyWith(color: AppColor.error)),
SizedBox(),
Text(
'آیا مطمئن هستید که می‌خواهید از حساب کاربری خود خارج شوید؟',
textAlign: TextAlign.center,
style: AppFonts.yekan16Bold.copyWith(color: AppColor.textColor),
),
SizedBox(),
Row(
spacing: 16,
mainAxisAlignment: MainAxisAlignment.center,
children: [
RElevated(
height: 40.h,
text: 'خروج',
backgroundColor: AppColor.error,
onPressed: () async {
await controller.rootLogic.tokenService.deleteTokens().then((value) {
Get.back();
Get.offAllNamed(ChickenRoutes.auth, arguments: Module.chicken);
});
},
),
ROutlinedElevated(
height: 40.h,
text: 'انصراف',
borderColor: AppColor.blueNormal,
onPressed: () {
Get.back();
},
),
],
),
],
),
),
),
);*/
}
}

View File

@@ -1,16 +1,60 @@
import 'package:flutter/material.dart';
import 'package:rasadyar_core/core.dart';
import 'package:rasadyar_inspection/data/model/response/user_profile/user_profile_model.dart';
import 'package:rasadyar_inspection/data/repositories/user/user_repository_imp.dart';
import 'package:rasadyar_inspection/injection/inspection_di.dart';
import 'package:rasadyar_inspection/presentation/pages/action/view.dart';
import 'package:rasadyar_inspection/presentation/pages/inspection_map/view.dart';
import 'package:rasadyar_inspection/presentation/pages/profile/view.dart';
enum ErrorLocationType { serviceDisabled, permissionDenied, none }
class RootLogic extends GetxController {
RxInt currentIndex = 0.obs;
List<Widget> pages = [InspectionMapPage(), ActionPage(), ProfilePage()];
RxList<ErrorLocationType> errorLocationType = RxList();
TokenStorageService tokenStorageService = Get.find<TokenStorageService>();
UserRepositoryImp userRepository = diInspection.get<UserRepositoryImp>();
Rxn<UserProfileModel> userProfile = Rxn<UserProfileModel>();
@override
void onInit() {
super.onInit();
userRepository
.fetchUserProfile(token: tokenStorageService.accessToken.value ?? '')
.then((value) => userProfile.value = value);
}
@override
void onReady() {
super.onReady();
locationServiceEnabled().then((value) {
if (!value) {
errorLocationType.add(ErrorLocationType.serviceDisabled);
}
});
checkPermission().then((value) {
if (!value) {
errorLocationType.add(ErrorLocationType.permissionDenied);
}
});
listenToLocationServiceStatus().listen((event) {
if (!event) {
errorLocationType.add(ErrorLocationType.serviceDisabled);
} else {
errorLocationType.remove(ErrorLocationType.serviceDisabled);
}
});
}
@override
void onClose() {
// TODO: implement onClose
super.onClose();
}
Stream<bool> listenToLocationServiceStatus() {
return Geolocator.getServiceStatusStream().map((status) {
@@ -52,38 +96,7 @@ class RootLogic extends GetxController {
}
}
@override
void onReady() {
super.onReady();
locationServiceEnabled().then((value) {
if (!value) {
errorLocationType.add(ErrorLocationType.serviceDisabled);
}
});
checkPermission().then((value) {
if (!value) {
errorLocationType.add(ErrorLocationType.permissionDenied);
}
});
listenToLocationServiceStatus().listen((event) {
if (!event) {
errorLocationType.add(ErrorLocationType.serviceDisabled);
} else {
errorLocationType.remove(ErrorLocationType.serviceDisabled);
}
});
}
void changePage(int index) {
currentIndex.value = index;
}
@override
void onClose() {
// TODO: implement onClose
super.onClose();
}
}

View File

@@ -9,11 +9,11 @@ class RootPage extends GetView<RootLogic> {
@override
Widget build(BuildContext context) {
return ObxValue((currentIndex) {
return Scaffold(
body: ObxValue(
(currentIndex) => IndexedStack(index: currentIndex.value, children: controller.pages),
controller.currentIndex,
),
return PopScope(
canPop: false,
child: Scaffold(
backgroundColor: AppColor.bgLight,
body: IndexedStack(index: currentIndex.value, children: controller.pages),
bottomNavigationBar: RBottomNavigation(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
items: [
@@ -23,7 +23,6 @@ class RootPage extends GetView<RootLogic> {
isSelected: currentIndex.value == 0,
onTap: () {
Get.nestedKey(1)?.currentState?.popUntil((route) => route.isFirst);
controller.changePage(0);
},
),
@@ -40,16 +39,17 @@ class RootPage extends GetView<RootLogic> {
RBottomNavigationItem(
label: 'پروفایل',
icon: Assets.vec.profileCircleSvg.path,
isSelected: currentIndex.value == 4,
isSelected: currentIndex.value == 2,
onTap: () {
Get.nestedKey(1)?.currentState?.popUntil((route) => route.isFirst);
Get.nestedKey(0)?.currentState?.popUntil((route) => route.isFirst);
controller.changePage(4);
controller.changePage(2);
},
),
],
),
),
);
}, controller.currentIndex);
}

View File

@@ -6,6 +6,7 @@ import 'package:rasadyar_inspection/presentation/pages/pages.dart';
import 'package:rasadyar_inspection/presentation/pages/users/logic.dart';
import 'package:rasadyar_inspection/presentation/routes/app_routes.dart';
import 'package:rasadyar_inspection/presentation/widget/base_page/logic.dart';
import 'package:rasadyar_inspection/presentation/widget/captcha/logic.dart';
sealed class InspectionPages {
InspectionPages._();
@@ -64,7 +65,10 @@ sealed class InspectionPages {
GetPage(
name: InspectionRoutes.auth,
page: () => AuthPage(),
binding: BindingsBuilder.put(() => AuthLogic()),
binding: BindingsBuilder(() {
Get.lazyPut(() => AuthLogic());
Get.lazyPut(() =>CaptchaWidgetLogic());
}),
),
];
}

View File

@@ -1,16 +1,14 @@
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:rasadyar_core/core.dart';
import 'package:rasadyar_core/data/model/response/captcha/captcha_response_model.dart';
import 'package:rasadyar_inspection/data/repositories/auth_repository_imp.dart';
import 'package:rasadyar_inspection/data/model/response/captcha/captcha_response_model.dart';
import 'package:rasadyar_inspection/data/repositories/auth/auth_repository_imp.dart';
import 'package:rasadyar_inspection/injection/inspection_di.dart';
class CaptchaWidgetLogic extends GetxController with StateMixin<CaptchaResponseModel> {
TextEditingController textController = TextEditingController();
RxnString captchaKey = RxnString();
GlobalKey<FormState> formKey = GlobalKey<FormState>();
//AuthRepositoryImpl authRepository = .get<AuthRepositoryImpl>();
final Random random = Random();
AuthRepositoryImpl authRepository = diInspection.get<AuthRepositoryImpl>();
@override
void onInit() {
@@ -29,8 +27,21 @@ class CaptchaWidgetLogic extends GetxController with StateMixin<CaptchaResponseM
Future<void> getCaptcha() async {
change(null, status: RxStatus.loading());
textController.clear();
await Future.delayed(Duration(milliseconds: 800));
captchaKey.value = (random.nextInt(900000) + 100000).toString();
formKey.currentState?.reset();
await Future.delayed(Duration(milliseconds: 200));
await safeCall(
call: () async => authRepository.captcha(),
onSuccess: (result) {
if (result == null) {
change(null, status: RxStatus.error('Failed to load captcha'));
return;
}
captchaKey.value = result.captchaKey;
change(result, status: RxStatus.success());
},
onError: (error, stackTrace) {},
);
change(value, status: RxStatus.success());
}
}

View File

@@ -1,3 +1,4 @@
import 'dart:convert';
import 'dart:math';
import 'package:flutter/cupertino.dart';
@@ -28,12 +29,7 @@ class CaptchaWidget extends GetView<CaptchaWidgetLogic> {
borderRadius: BorderRadius.circular(8),
),
child: controller.obx(
(state) => Center(
child: Text(
controller.captchaKey.value ?? 'دوباره سعی کنید',
style: AppFonts.yekan24Bold,
),
),
(state) => Image.memory(base64Decode(state?.captchaImage ?? ''), fit: BoxFit.cover),
onLoading: const Center(
child: CupertinoActivityIndicator(color: AppColor.blueNormal),
),
@@ -64,9 +60,6 @@ class CaptchaWidget extends GetView<CaptchaWidgetLogic> {
validator: (value) {
if (value == null || value.isEmpty) {
return 'کد امنیتی را وارد کنید';
} else if (controller.captchaKey.value != null &&
controller.captchaKey.value != value) {
return 'کد امنیتی اشتباه است';
}
return null;
},

View File

@@ -98,7 +98,7 @@ packages:
source: hosted
version: "3.0.0"
build_runner:
dependency: transitive
dependency: "direct dev"
description:
name: build_runner
sha256: b971d4a1c789eba7be3e6fe6ce5e5b50fd3719e3cb485b3fad6d04358304351d
@@ -145,6 +145,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.4"
cli_config:
dependency: transitive
description:
name: cli_config
sha256: ac20a183a07002b700f0c25e61b7ee46b23c309d76ab7b7640a028f18e4d99ec
url: "https://pub.dev"
source: hosted
version: "0.2.0"
clock:
dependency: transitive
description:
@@ -185,6 +193,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.1.2"
coverage:
dependency: transitive
description:
name: coverage
sha256: "5da775aa218eaf2151c721b16c01c7676fbfdd99cebba2bf64e8b807a28ff94d"
url: "https://pub.dev"
source: hosted
version: "1.15.0"
cross_file:
dependency: transitive
description:
@@ -289,6 +305,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "5.0.3"
fake_async:
dependency: transitive
description:
name: fake_async
sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44"
url: "https://pub.dev"
source: hosted
version: "1.3.3"
ffi:
dependency: transitive
description:
@@ -366,6 +390,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "5.11.0"
flutter_lints:
dependency: "direct dev"
description:
name: flutter_lints
sha256: "3105dc8492f6183fb076ccf1f351ac3d60564bff92e20bfc4af9cc1651f4e7e1"
url: "https://pub.dev"
source: hosted
version: "6.0.0"
flutter_localizations:
dependency: transitive
description: flutter
@@ -475,6 +507,11 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.2.0"
flutter_test:
dependency: "direct dev"
description: flutter
source: sdk
version: "0.0.0"
flutter_web_plugins:
dependency: transitive
description: flutter
@@ -488,8 +525,16 @@ packages:
url: "https://pub.dev"
source: hosted
version: "10.8.0"
freezed:
dependency: "direct dev"
description:
name: freezed
sha256: da32f8ba8cfcd4ec71d9decc8cbf28bd2c31b5283d9887eb51eb4a0659d8110c
url: "https://pub.dev"
source: hosted
version: "3.2.0"
freezed_annotation:
dependency: transitive
dependency: "direct main"
description:
name: freezed_annotation
sha256: "7294967ff0a6d98638e7acb774aac3af2550777accd8149c90af5b014e6d44d8"
@@ -584,6 +629,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "8.0.3"
get_test:
dependency: "direct dev"
description:
name: get_test
sha256: "558c39cb35fb37bd501f337dc143de60a4314d5ef3b75f4b0551d6741634995b"
url: "https://pub.dev"
source: hosted
version: "4.0.1"
glob:
dependency: transitive
description:
@@ -632,6 +685,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.3.1"
hive_ce_generator:
dependency: "direct dev"
description:
name: hive_ce_generator
sha256: a169feeff2da9cc2c417ce5ae9bcebf7c8a95d7a700492b276909016ad70a786
url: "https://pub.dev"
source: hosted
version: "1.9.3"
http:
dependency: transitive
description:
@@ -769,13 +830,21 @@ packages:
source: hosted
version: "0.6.7"
json_annotation:
dependency: transitive
dependency: "direct main"
description:
name: json_annotation
sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1"
url: "https://pub.dev"
source: hosted
version: "4.9.0"
json_serializable:
dependency: "direct dev"
description:
name: json_serializable
sha256: ce2cf974ccdee13be2a510832d7fba0b94b364e0b0395dee42abaa51b855be27
url: "https://pub.dev"
source: hosted
version: "6.10.0"
latlong2:
dependency: transitive
description:
@@ -784,6 +853,38 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.9.1"
leak_tracker:
dependency: transitive
description:
name: leak_tracker
sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0"
url: "https://pub.dev"
source: hosted
version: "10.0.9"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573
url: "https://pub.dev"
source: hosted
version: "3.0.9"
leak_tracker_testing:
dependency: transitive
description:
name: leak_tracker_testing
sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
url: "https://pub.dev"
source: hosted
version: "3.0.1"
lints:
dependency: "direct dev"
description:
name: lints
sha256: a5e2b223cb7c9c8efdc663ef484fdd95bb243bff242ef5b13e26883547fce9a0
url: "https://pub.dev"
source: hosted
version: "6.0.0"
lists:
dependency: transitive
description:
@@ -856,6 +957,30 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.0"
mockito:
dependency: transitive
description:
name: mockito
sha256: "2314cbe9165bcd16106513df9cf3c3224713087f09723b128928dc11a4379f99"
url: "https://pub.dev"
source: hosted
version: "5.5.0"
mocktail:
dependency: "direct dev"
description:
name: mocktail
sha256: "890df3f9688106f25755f26b1c60589a92b3ab91a22b8b224947ad041bf172d8"
url: "https://pub.dev"
source: hosted
version: "1.0.4"
node_preamble:
dependency: transitive
description:
name: node_preamble
sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db"
url: "https://pub.dev"
source: hosted
version: "2.0.2"
package_config:
dependency: transitive
description:
@@ -1111,6 +1236,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.4.2"
shelf_packages_handler:
dependency: transitive
description:
name: shelf_packages_handler
sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e"
url: "https://pub.dev"
source: hosted
version: "3.0.2"
shelf_static:
dependency: transitive
description:
name: shelf_static
sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3
url: "https://pub.dev"
source: hosted
version: "1.1.3"
shelf_web_socket:
dependency: transitive
description:
@@ -1132,6 +1273,38 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
source_gen:
dependency: transitive
description:
name: source_gen
sha256: fc787b1f89ceac9580c3616f899c9a447413cbdac1df071302127764c023a134
url: "https://pub.dev"
source: hosted
version: "3.0.0"
source_helper:
dependency: transitive
description:
name: source_helper
sha256: "4f81479fe5194a622cdd1713fe1ecb683a6e6c85cd8cec8e2e35ee5ab3fdf2a1"
url: "https://pub.dev"
source: hosted
version: "1.3.6"
source_map_stack_trace:
dependency: transitive
description:
name: source_map_stack_trace
sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b
url: "https://pub.dev"
source: hosted
version: "2.1.2"
source_maps:
dependency: transitive
description:
name: source_maps
sha256: "190222579a448b03896e0ca6eca5998fa810fda630c1d65e2f78b3f638f54812"
url: "https://pub.dev"
source: hosted
version: "0.10.13"
source_span:
dependency: transitive
description:
@@ -1188,14 +1361,30 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.2.2"
test:
dependency: "direct dev"
description:
name: test
sha256: "301b213cd241ca982e9ba50266bd3f5bd1ea33f1455554c5abb85d1be0e2d87e"
url: "https://pub.dev"
source: hosted
version: "1.25.15"
test_api:
dependency: transitive
description:
name: test_api
sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55
sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd
url: "https://pub.dev"
source: hosted
version: "0.7.7"
version: "0.7.4"
test_core:
dependency: transitive
description:
name: test_core
sha256: "84d17c3486c8dfdbe5e12a50c8ae176d15e2a771b96909a9442b40173649ccaa"
url: "https://pub.dev"
source: hosted
version: "0.6.8"
time:
dependency: transitive
description:
@@ -1268,6 +1457,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.4"
vm_service:
dependency: transitive
description:
name: vm_service
sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02
url: "https://pub.dev"
source: hosted
version: "15.0.0"
watcher:
dependency: transitive
description:
@@ -1300,6 +1497,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.0.3"
webkit_inspection_protocol:
dependency: transitive
description:
name: webkit_inspection_protocol
sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572"
url: "https://pub.dev"
source: hosted
version: "1.2.1"
win32:
dependency: transitive
description:
@@ -1348,6 +1553,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.1.3"
yaml_writer:
dependency: transitive
description:
name: yaml_writer
sha256: "69651cd7238411179ac32079937d4aa9a2970150d6b2ae2c6fe6de09402a5dc5"
url: "https://pub.dev"
source: hosted
version: "2.1.0"
sdks:
dart: ">=3.8.1 <4.0.0"
flutter: ">=3.29.0"

View File

@@ -11,3 +11,21 @@ dependencies:
sdk: flutter
rasadyar_core:
path: ../core
##code generation
freezed_annotation: ^3.1.0
json_annotation: ^4.9.0
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^6.0.0
lints: ^6.0.0
test: ^1.25.15
##code generation
build_runner: ^2.6.0
hive_ce_generator: ^1.9.3
freezed: ^3.2.0
json_serializable: ^6.10.0
##test
mocktail: ^1.0.4
get_test: ^4.0.1