Commits (2)
<svg id="TRAVEL" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="linear-gradient" gradientUnits="userSpaceOnUse" x1="0" x2="512.02" y1="256" y2="256"><stop offset="0" stop-color="#283451"/><stop offset=".6" stop-color="#384c6c"/><stop offset="1" stop-color="#465a77"/></linearGradient><path d="m362.83 228.31c-7.59-53.3-53.25-92.9-107.08-92.9s-99.99 39.99-107.19 93.63c0 0-1.26 9.34-1.46 19.06h-124.87l-7.64-53.39c-.33-3.77-3.49-6.66-7.27-6.66h-7.29v60.05h-.03v18.93c0 9.81 7.5 18 17.27 18.86l120.84 10.62c3.19.28 5.68 2.87 5.85 6.07v.05c1.43 26.33 21.96 51.78 47.44 57.6 15.65 3.31 35.29 5.62 64.89 5.67 29.61-.05 49.22-2.36 64.85-5.67 25.45-5.81 45.79-31.27 47.03-57.6 0-.02 0-.04 0-.05.14-3.19 2.6-5.79 5.79-6.07l120.79-10.62c9.77-.86 17.27-9.04 17.27-18.85v-18.93h-.03v-60.05h-7.29c-3.78 0-6.94 2.89-7.27 6.66l-7.64 53.39h-125.25c-.03-8.28-1.71-19.79-1.71-19.79zm-98.96-35.58c-.09-3.44 2.39-6.22 5.59-6.2 18.25.13 36.5.51 54.75 1.15 2.61.09 5.75 1.96 7.41 4.54 3.36 5.26 6.01 10.49 7.8 15.67 1.08 3.05-1.04 6.19-4.35 7.13-21.52 6.1-43.67 12.73-63.91 19.19-3.82 1.23-7.39-1.75-7.29-5.92.39-11.86.39-23.71 0-35.57zm-91.24 15.17c1.79-5.19 4.44-10.41 7.8-15.67 1.66-2.58 4.8-4.45 7.41-4.54 18.25-.64 36.5-1.02 54.75-1.15 3.2-.02 5.68 2.76 5.59 6.2-.39 11.86-.39 23.71 0 35.57.1 4.18-3.47 7.15-7.29 5.92-20.23-6.46-42.39-13.09-63.91-19.19-3.32-.94-5.43-4.09-4.35-7.13zm66.34-89.37 4.11-51.59c.56-7.06 6.46-12.51 13.54-12.51s12.98 5.45 13.54 12.51l4.13 51.85c-6.11-.91-12.3-1.38-18.55-1.38-5.64 0-11.24.38-16.77 1.12zm34.19 318.58c.04 3.92-.48 9.84-.91 11.96-.68 3.48-3.86 6.85-7.33 7.62-2.11.44-4.98.87-8.9.88-3.92 0-6.79-.44-8.9-.88-3.47-.77-6.66-4.14-7.33-7.62-.42-2.12-.95-8.04-.91-11.96-.04-3.92.48-9.84.91-11.96.68-3.48 3.86-6.85 7.33-7.62 1.05-.22 2.29-.43 3.75-.6v-37.15c0-1.99 1.61-3.6 3.6-3.6h3.1c1.99 0 3.6 1.61 3.6 3.6v37.15c1.46.16 2.7.38 3.75.6 3.47.77 6.66 4.14 7.33 7.62.42 2.12.95 8.04.91 11.96zm-48.23-32.57c.03 3.01-.37 7.57-.7 9.21-.52 2.68-2.97 5.27-5.64 5.87-1.62.34-3.83.67-6.85.67s-5.22-.34-6.85-.67c-2.67-.59-5.12-3.18-5.64-5.87-.33-1.63-.73-6.19-.7-9.21-.03-3.01.37-7.57.7-9.21.52-2.68 2.97-5.27 5.64-5.87.77-.16 1.68-.32 2.74-.44v-12.2c0-1.99 1.61-3.6 3.6-3.6h1.02c1.99 0 3.6 1.61 3.6 3.6v12.2c1.06.12 1.97.28 2.74.44 2.67.59 5.12 3.19 5.64 5.87.33 1.63.73 6.19.7 9.21zm88.56 0c.03 3.01-.37 7.57-.7 9.21-.52 2.68-2.97 5.27-5.64 5.87-1.62.34-3.83.67-6.85.67s-5.22-.34-6.85-.67c-2.67-.59-5.12-3.18-5.64-5.87-.33-1.63-.73-6.19-.7-9.21-.03-3.01.37-7.57.7-9.21.52-2.68 2.97-5.27 5.64-5.87.77-.16 1.68-.32 2.74-.44v-13.14c0-1.47 1.19-2.66 2.66-2.66h2.9c1.47 0 2.66 1.19 2.66 2.66v13.14c1.06.12 1.97.28 2.74.44 2.67.59 5.12 3.19 5.64 5.87.33 1.63.73 6.19.7 9.21zm-242.63-96.91c-23.42 0-42.4 18.98-42.4 42.4s18.98 42.4 42.4 42.4 42.4-18.98 42.4-42.4-18.98-42.4-42.4-42.4zm0 61.84c-10.73 0-19.43-8.7-19.43-19.43s8.7-19.44 19.43-19.44 19.43 8.7 19.43 19.44-8.7 19.43-19.43 19.43zm370.28-61.84c-23.42 0-42.4 18.98-42.4 42.4s18.98 42.4 42.4 42.4 42.4-18.98 42.4-42.4-18.98-42.4-42.4-42.4zm0 61.84c-10.73 0-19.43-8.7-19.43-19.43s8.7-19.44 19.43-19.44 19.43 8.7 19.43 19.44-8.7 19.43-19.43 19.43z" fill="url(#linear-gradient)"/></svg>
\ No newline at end of file
<svg id="TRAVEL" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="linear-gradient" gradientUnits="userSpaceOnUse" x1="0" x2="512" y1="256" y2="256"><stop offset="0" stop-color="#ed6c14"/><stop offset=".6" stop-color="#ff9045"/><stop offset="1" stop-color="#ffb54a"/></linearGradient><path d="m105.04 328.91c27.89 0 50.49 22.61 50.49 50.49 0 27.89-22.61 50.49-50.49 50.49-27.89 0-50.49-22.61-50.49-50.49 0-27.89 22.61-50.49 50.49-50.49zm251.92 50.49c0 27.89 22.61 50.49 50.49 50.49 27.89 0 50.49-22.61 50.49-50.49s-22.61-50.49-50.49-50.49c-27.89 0-50.49 22.61-50.49 50.49zm117.47-139.24-3.76-32.85c-.72-6.26-6.38-10.76-12.64-10.04-6.26.72-10.76 6.38-10.04 12.64l3.76 32.85c.72 6.26 6.38 10.76 12.64 10.04 6.26-.72 10.76-6.38 10.04-12.64zm34.19 101.69c-3.12 19.19-15.24 26.29-33 30.87-3.37-34.64-32.65-61.81-68.16-61.81-37.77 0-68.49 30.73-68.49 68.49 0 4.92.53 9.71 1.52 14.34-25.41 1.05-49.83 1.67-65.18 1.52-15.64.16-73.17-.49-103.28-1.58.98-4.61 1.51-9.39 1.51-14.28 0-37.77-30.73-68.49-68.49-68.49-35.3 0-64.44 26.84-68.1 61.19-17.18-4.85-28.8-14.43-32.84-33.79-4-19.15-5.35-64.17-2.84-100.08 2.64-35.9 8.58-62.2 14.07-81.53 9.35-31.84 42.31-61.01 74.67-67.2 19.66-3.89 129.25-7.77 165.14-7.37 35.88-.4 170.56 4.41 190.25 8.3 32.43 6.19 43.43 34.43 53.11 66.27 5.68 19.33 9.12 45.63 12.12 81.53 2.87 35.9.79 84.28-2 103.61zm-369.06-170.84c0-6.05-4.94-10.93-10.98-10.86-6.39.07-31.32.15-37.71.23-8.75.12-18.64 5.58-22.46 12.96-8.33 18.1-12.11 36.16-10.74 54.15.21 9.49 12.86 18.4 24.2 18.57 9.39.13 37.32.24 46.71.35 6.05.07 10.99-4.81 10.99-10.86v-64.54zm112.96-.85c0-6.02-4.9-10.9-10.92-10.87-17.83.09-44.94.21-62.77.37-5.96.05-10.77 4.9-10.77 10.87v65.52c0 5.96 4.81 10.81 10.77 10.86 17.83.15 44.94.28 62.77.37 6.02.03 10.92-4.84 10.92-10.87v-66.26zm111.1-.2c0-5.99-4.85-10.86-10.85-10.86-17.83-.03-44.94-.02-62.77 0-5.99.01-10.84 4.88-10.84 10.87v66.62c0 5.99 4.85 10.85 10.84 10.87 17.83.04 44.94.04 62.77.01 5.99 0 10.85-4.87 10.85-10.86zm123.94 90.34c-1.54-30.6-4-57.01-13-89.05-.01-.04-.03-.08-.04-.12-2.51-6.88-10.13-11.51-18.62-11.58-16.7-.13-37.1-.22-53.8-.3-6.01-.03-10.9 4.84-10.9 10.86v66.37c0 .27 0 .54.03.8.31 4.24 3.37 7.78 7.41 9.09l74.22 23.96c3.51 1.13 7.42.7 10.43-1.44 2.86-2.04 4.58-5.18 4.27-8.59z" fill="url(#linear-gradient)"/></svg>
\ No newline at end of file
<svg id="TRAVEL" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="linear-gradient" gradientUnits="userSpaceOnUse" x1="0" x2="512" y1="256" y2="256"><stop offset="0" stop-color="#cc3232"/><stop offset=".6" stop-color="#ef5a5a"/><stop offset="1" stop-color="#f47e67"/></linearGradient><path d="m404.82 313.19c27.47 0 49.73 22.27 49.73 49.73 0 27.47-22.27 49.73-49.73 49.73s-49.73-22.27-49.73-49.73c0-27.47 22.27-49.73 49.73-49.73zm-347.37 49.73c0 27.47 22.27 49.73 49.73 49.73s49.73-22.27 49.73-49.73c0-27.47-22.27-49.73-49.73-49.73-27.47 0-49.73 22.27-49.73 49.73zm-57.12-42.83c2.57-18.45 5.13-37.14 7.7-56.08 1.77-13 10.59-24.53 22.8-29.88 16.58-7.19 33.18-14.67 49.79-22.29 4.52-24.67 10.58-43 15.81-56.63 9.16-23.56 35.23-45.15 59.16-49.73 14.46-2.87 54.11-6.41 80.13-6.12 26.03-.29 65.62 3.21 80.04 6.04 23.86 4.49 49.63 25.65 58.47 48.74 4.85 12.83 10.4 29.91 14.53 52.68 28.48 9.69 56.92 19.42 85.32 28.68 12.67 4.18 22.49 15.19 25.32 28.27 3.92 18.21 7.85 36.09 11.77 53.6 4.73 20.8-11.45 42.9-33.29 45.62-1.74.19-3.48.37-5.23.55 0-.21.02-.43.02-.64 0-37.41-30.44-67.85-67.85-67.85s-67.85 30.44-67.85 67.85c0 3.58.28 7.1.82 10.53-54.5 2.18-109.07 2.18-163.57 0 .54-3.43.82-6.95.82-10.53 0-37.41-30.44-67.85-67.85-67.85s-67.85 30.44-67.85 67.85c0 .21.01.43.02.64-1.74-.19-3.49-.36-5.23-.55-20.71-2.54-36.62-22.79-33.78-42.91zm249.51-134.41c0 6.31 5.12 11.43 11.43 11.43h81.15c7.63 0 13.13-7.35 10.96-14.67-2.2-7.41-4.37-13.47-6.18-18.26-5.31-13.81-22.74-28.31-37.33-31.06l-.11-.02-.11-.02c-8.03-1.58-27.91-3.69-47.74-4.79-6.55-.36-12.07 4.85-12.07 11.41zm-122.78 11.42h79.54c6.31 0 11.43-5.12 11.43-11.43v-45.85c0-6.57-5.53-11.8-12.09-11.41-19.1 1.14-37.82 3.18-45.55 4.72l-.09.02-.09.02c-14.75 2.82-32.57 17.87-38.17 32.22-1.73 4.51-3.77 10.11-5.88 16.85-2.3 7.36 3.19 14.86 10.9 14.86z" fill="url(#linear-gradient)"/></svg>
\ No newline at end of file
<svg id="TIME_AND_DATE_GLYPH" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" data-name="TIME AND DATE GLYPH"><linearGradient id="linear-gradient" gradientUnits="userSpaceOnUse" x1="17.33" x2="494.67" y1="256" y2="256"><stop offset="0" stop-color="#0caa0c"/><stop offset=".6" stop-color="#4bd14b"/><stop offset="1" stop-color="#60e260"/></linearGradient><path d="m25.29 158.12c.57-3.82 1.15-7.49 1.73-11 8.56-48.43 51.94-92.47 100.21-102.25v-19.62c0-13.94 11.3-25.24 25.24-25.24s25.24 11.3 25.24 25.24v12.92c15.71-1.47 33.3-2.6 53.04-3.15v-9.77c0-13.94 11.3-25.24 25.24-25.24 13.94 0 25.24 11.3 25.24 25.24v9.77c19.74.54 37.33 1.68 53.04 3.15v-12.92c0-13.94 11.3-25.24 25.24-25.24s25.24 11.3 25.24 25.24v19.62c48.27 9.78 91.65 53.82 100.21 102.25.58 3.46 1.15 7.08 1.71 10.84-197.7-13.79-391.9-4.2-461.39.17zm469.38 115.21c-.06 55.59-4.72 96.3-9.7 126.21-8.71 49.29-53.47 94.05-102.76 102.76-29.91 4.98-70.62 9.64-126.21 9.7-55.59-.06-96.3-4.72-126.21-9.7-49.29-8.71-94.06-53.47-102.76-102.76-4.98-29.91-9.63-70.62-9.7-126.21.03-29.64 1.37-55.04 3.37-76.83 62.07-4.07 265.33-15.04 470.59-.12 2 21.82 3.35 47.26 3.38 76.95zm-135.32-15.35c-12.53-11.94-32.37-11.45-44.3 1.09l-84.34 88.57-33.97-35c-12.06-12.43-31.89-12.72-44.3-.67-12.42 12.05-12.72 31.89-.67 44.31l56.68 58.4c5.9 6.08 14.01 9.51 22.49 9.51h.14c8.53-.04 16.67-3.56 22.54-9.73l106.82-112.17c11.94-12.54 11.45-32.38-1.09-44.3z" fill="url(#linear-gradient)"/></svg>
\ No newline at end of file
<svg viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="linear-gradient" gradientUnits="userSpaceOnUse" x2="512.09" y1="256" y2="256"><stop offset="0" stop-color="#cc3232"/><stop offset=".6" stop-color="#ef5a5a"/><stop offset="1" stop-color="#f47e67"/></linearGradient><g id="SECURITY_BLACK" data-name="SECURITY BLACK"><path d="m376.82 302.65c-1.82 21.44-4.07 39.77-6.17 50.31-8.29 42.61-46 81.7-87.72 90.94l-.24.05q-9.65 2-19.45 3.55c-7.73 35.66-33.24 60.05-61.37 57.5h-.18c-20.91-2.26-42.51-7.8-66.05-16.94a338.62 338.62 0 0 1 -66.11-34.71l-.17-.12c-29.76-20.58-56.65-69.08-62.56-112.81-1.2-8.68-2.45-22.16-3.55-37.66-2.06-24.17-3.45-51.37-3.25-72.83-.42-40 4.79-99.93 9.4-123 3.7-18.93 13.17-37.14 26.21-52.36a47.24 47.24 0 0 1 10.33-10.73c14.76-13.67 32.57-23.75 51.19-27.84l.25-.05c29.32-6.13 59.62-9.11 92.62-9.17s63.42 3 92.69 9.13l.24.05c41.73 9.24 79.43 48.33 87.72 90.94 2.1 10.52 4.34 28.81 6.16 50.2a19 19 0 0 1 -37.87 3.22c-1.68-19.78-3.76-37-5.57-46v-.11c-5.37-27.7-31.61-55.08-58.52-61.1-26.68-5.54-54.43-8.26-84.83-8.31a426.08 426.08 0 0 0 -66.7 5q6.08 2.09 12.29 4.5a338.2 338.2 0 0 1 66.08 34.7l.18.12c29.75 20.61 56.64 69.11 62.55 112.84 3.29 23.75 7 83.43 6.7 122.19.2 25.37-1.31 58.27-3.29 84 2.33-.44 4.67-.9 7-1.38 26.91-6 53.15-33.4 58.52-61.1v-.11c1.82-9.06 3.9-26.3 5.58-46.12a19 19 0 1 1 37.87 3.21zm135.27-72.75c0-.63 0-1.26-.1-1.89a.5.5 0 0 0 0-.12 17.39 17.39 0 0 0 -.27-1.76v-.13a18.9 18.9 0 0 0 -5.15-9.53l-68-68.06a19 19 0 0 0 -26.88 26.87l35.67 35.66h-131.17a19 19 0 0 0 0 38h131l-35.64 35.64a19 19 0 0 0 26.87 26.87l67.69-67.69a18.86 18.86 0 0 0 5.2-8.44 16.53 16.53 0 0 0 .42-1.75 2.17 2.17 0 0 0 0-.25c.09-.51.18-1 .23-1.54s0-.78 0-1.16c0-.22 0-.44 0-.66z" fill="url(#linear-gradient)"/></g></svg>
\ No newline at end of file
<svg id="TRAVEL" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="linear-gradient" gradientUnits="userSpaceOnUse" x1="90.05" x2="421.95" y1="256" y2="256"><stop offset="0" stop-color="#0caa0c"/><stop offset=".6" stop-color="#4bd14b"/><stop offset="1" stop-color="#60e260"/></linearGradient><path d="m256.19 512h-.38c-21.22 0-38.43-17.21-38.43-38.43v-141.8c0-21.22 17.21-38.43 38.43-38.43h.38c21.22 0 38.43 17.21 38.43 38.43v141.8c0 21.22-17.21 38.43-38.43 38.43zm165.76-457.81c0 5.98-4.85 10.83-10.83 10.83h-49.34c-3.94 7.67-11.91 12.93-21.13 12.93h-22.87c-7.47 0-14.41 3.59-19 9.49-9.91 12.74-25.39 20.94-42.78 20.94s-32.87-8.2-42.78-20.94c-4.59-5.9-11.52-9.49-19-9.49h-22.87c-9.22 0-17.19-5.26-21.13-12.93h-49.34c-5.98 0-10.83-4.85-10.83-10.83s4.85-10.83 10.83-10.83h49.34c3.94-7.67 11.91-12.93 21.13-12.93h22.87c7.47 0 14.41-3.59 19-9.49 9.91-12.74 25.39-20.94 42.78-20.94s32.87 8.2 42.78 20.94c4.59 5.9 11.52 9.49 19 9.49h22.87c9.22 0 17.19 5.26 21.13 12.93h49.34c5.98 0 10.83 4.85 10.83 10.83zm-135.72-.22c0-16.7-13.53-30.23-30.23-30.23s-30.23 13.53-30.23 30.23 13.53 30.23 30.23 30.23 30.23-13.53 30.23-30.23zm100.73 221.39c.33 29.93-3.68 75.18-6.92 91.4-5.16 26.63-29.49 52.37-56.04 58.25-3.65.76-7.62 1.51-11.89 2.23v-95.28c0-30.93-25.17-56.1-56.1-56.1s-56.1 25.17-56.1 56.1v95.28c-4.27-.72-8.24-1.47-11.89-2.23-26.55-5.88-50.88-31.62-56.04-58.25-3.24-16.22-7.25-61.47-6.92-91.4-.33-29.93 3.68-75.18 6.92-91.4 5.16-26.62 29.49-52.37 56.04-58.25 16.12-3.35 38.05-6.64 68-6.69 29.94.05 51.87 3.34 68 6.69 26.55 5.88 50.88 31.62 56.04 58.25 3.24 16.22 7.25 61.47 6.92 91.4zm-193.24-69.73c0-11.59-.5-21.39-.95-23.61-.71-3.65-4.04-7.18-7.69-7.99-2.21-.46-5.22-.91-9.33-.92-4.11 0-7.11.46-9.33.92-3.64.81-6.98 4.34-7.69 7.99-.44 2.23-.95 11.84-.95 23.61s.5 21.39.95 23.61c.71 3.65 4.04 7.18 7.69 7.99 2.21.46 5.22.91 9.33.92 4.11 0 7.11-.46 9.33-.92 3.64-.81 6.98-4.34 7.69-7.99.44-2.23.95-11.32.95-23.61zm160.48 0c0-11.59-.5-21.39-.95-23.61-.71-3.65-4.04-7.18-7.69-7.99-2.21-.46-5.22-.91-9.33-.92-4.11 0-7.11.46-9.33.92-3.64.81-6.98 4.34-7.69 7.99-.44 2.23-.95 11.84-.95 23.61s.5 21.39.95 23.61c.71 3.65 4.04 7.18 7.69 7.99 2.21.46 5.22.91 9.33.92 4.11 0 7.11-.46 9.33-.92 3.64-.81 6.98-4.34 7.69-7.99.44-2.23.95-11.32.95-23.61z" fill="url(#linear-gradient)"/></svg>
\ No newline at end of file
<svg width="40" height="40" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
<!-- Circle background same as your first icon -->
<circle cx="20" cy="20" r="20" fill="#EDF8FF"/>
<!-- Scale down the original 512x512 drawing into 40x40 -->
<g transform="scale(0.078125) translate(0,0)">
<path d="m207.72 34.37c-116.82 13.63-207.5 112.85-207.72 233.28-.22 127.67 105.81 234.77 233.48 235.74a234.38 234.38 0 0 0 151.08-53.39 24.62 24.62 0 0 0 1.38-36.73l-143.08-137.91a24.67 24.67 0 0 1 -7.54-17.75v-198.76a24.68 24.68 0 0 0 -27.6-24.48z" fill="#4193d2"/>
<path d="m463.2 386a234.24 234.24 0 0 0 48.8-143.49c0-120.71-90.89-220.2-208-233.75a24.61 24.61 0 0 0 -27.34 24.51v198.85a24.66 24.66 0 0 0 7.43 17.64l142.36 138.83a24.66 24.66 0 0 0 36.75-2.59z" fill="#dd4247"/>
<path d="m302.62 333-59.76-57.61a24.67 24.67 0 0 1 -7.54-17.75v-198.79a24.68 24.68 0 0 0 -27.6-24.48c-116.82 13.63-207.5 112.85-207.72 233.28a231.56 231.56 0 0 0 32.93 119.08 278.59 278.59 0 0 0 269.69-53.73z" fill="#48a4df"/>
<path d="m276.69 33.27v198.85a24.66 24.66 0 0 0 7.43 17.64l51.09 49.83a278.5 278.5 0 0 0 48.79-266.59 233.81 233.81 0 0 0 -80-24.24 24.62 24.62 0 0 0 -27.31 24.51z" fill="#e55353"/>
</g>
</svg>
<svg id="TRAVEL" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="linear-gradient" gradientUnits="userSpaceOnUse" x1="0" x2="512" y1="256" y2="256"><stop offset="0" stop-color="#6949c6"/><stop offset=".6" stop-color="#7c6ee0"/><stop offset="1" stop-color="#a28eef"/></linearGradient><path d="m434.01 401.46c-.18 9.4-7.85 16.97-17.3 16.97h-397.4c-9.45 0-17.13-7.57-17.3-16.97-.18-9.7 8.06-17.63 17.76-17.63h62.3c-5.53-3.2-10.01-8-12.81-13.77-.78-1.61.41-3.49 2.21-3.49h53.14c1.79 0 2.99 1.88 2.21 3.49-2.8 5.77-7.28 10.57-12.81 13.77h39.63c-5.53-3.2-10.01-8-12.81-13.77-.78-1.61.41-3.49 2.21-3.49h53.14c1.79 0 2.99 1.88 2.21 3.49-2.8 5.77-7.28 10.57-12.81 13.77h100.79c-5.53-3.2-10.01-8-12.81-13.77-.78-1.61.41-3.49 2.21-3.49h53.14c1.79 0 2.99 1.88 2.21 3.49-2.8 5.77-7.28 10.57-12.81 13.77h38.3c-5.53-3.2-10.01-8-12.81-13.77-.78-1.61.41-3.49 2.21-3.49h53.14c1.79 0 2.99 1.88 2.21 3.49-2.8 5.77-7.28 10.57-12.81 13.77h27.74c9.7 0 17.94 7.94 17.76 17.63zm-433.46-137.15c-1.11-42.11-.55-84.23 1.7-126.35 1.27-23.09 21.6-42.22 44.65-42.64 98.58-1.65 197.16-2.14 295.74-1.47 72.61.62 140.21 54.2 155.04 126.11 5.28 26.45 9.94 52.85 13.88 79.18 3.82 25.74-18.03 50.14-44.28 50.63-140.13 2.34-280.25 2.34-420.38 0-23.05-.41-43.38-19.54-44.65-42.64-.44-8.28-.81-16.55-1.12-24.83l-.58-18zm141.37-78.35c.07-8.49-6.72-15.34-15.2-15.31-26.28.09-52.56.22-78.83.37-8.48.05-15.54 6.91-15.69 15.31-.27 15-.38 25-.31 40 .04 8.4 7.02 15.23 15.52 15.26 26.34.07 52.69.13 79.03.17 8.5.01 15.35-6.85 15.34-15.34-.03-15.15.02-25.3.15-40.45zm126.97-.09c-.03-8.5-6.93-15.41-15.41-15.41-25.14-.01-50.29 0-75.43.05-8.48.02-15.42 6.92-15.48 15.41-.1 15.17-.14 25.33-.11 40.5.01 8.49 6.94 15.39 15.44 15.4 25.21.02 50.41.03 75.62.03 8.5 0 15.41-6.9 15.41-15.41 0-15.19 0-25.38-.04-40.57zm197.27 35.24-5.8-19.24c-5.21-18.13-22.22-30.84-41.18-30.95-35.12-.19-40.24-.32-75.37-.39-8.48-.02-15.31 6.86-15.28 15.37.07 15.18.09 25.36.08 40.54 0 8.5 6.86 15.39 15.37 15.38 45.75-.04 60.49-.13 106.24-.27 10.79-.04 18.77-10.18 15.95-20.44z" fill="url(#linear-gradient)"/></svg>
\ No newline at end of file
<svg id="Layer_16" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" data-name="Layer 16"><linearGradient id="linear-gradient" gradientUnits="userSpaceOnUse" x1="0" x2="512" y1="256" y2="256"><stop offset="0" stop-color="#283451"/><stop offset=".6" stop-color="#384c6c"/><stop offset="1" stop-color="#465a77"/></linearGradient><path d="m505.25 229.85c-8.7-15.32-25.39-42.69-48.09-70.71-16.93-20.9-42.21-33.3-69.11-33.74-16.03-.26-31.77-.41-43.63-.41h-.12c-5.08-25.65-26.52-45.29-53.07-47.64-17.25-1.52-84.91-2.63-117.3-2.63s-100.05 1.1-117.3 2.63c-28.71 2.54-51.46 25.29-54 54-1.53 17.26-2.63 66.07-2.63 98.46s1.1 81.2 2.63 98.45c2.16 24.46 19 44.58 41.69 51.58 4.62-35.94 35.39-63.81 72.56-63.81s70.76 30.48 73.04 68.79c21.7-.16 49.87-.61 71.63-1.24 17.35.54 38.92.94 57.86 1.15 2.32-38.27 34.19-68.7 73.04-68.7s68.37 28.26 72.66 64.56c24.01-6.2 42.08-26.92 44.33-52.32 1.32-14.88 2.32-43.9 2.57-72.39.08-9.12-2.25-18.09-6.75-26.02zm-48.69 15.32h-108.78c.05-5.37.07-10.55.07-15.36 0-22.32-.52-52.44-1.35-74.65 11.39.02 26.19.16 41.05.4 17.96.29 34.79 8.52 46.17 22.57 13.78 17.01 25.24 33.86 33.72 47.32 5.4 8.57-.76 19.72-10.89 19.72zm-339.68 95.99c-26.54 0-48.05 21.51-48.05 48.05s21.52 48.05 48.05 48.05 48.05-21.51 48.05-48.05-21.51-48.05-48.05-48.05zm275.56 0c-26.54 0-48.05 21.51-48.05 48.05s21.51 48.05 48.05 48.05 48.05-21.51 48.05-48.05-21.51-48.05-48.05-48.05z" fill="url(#linear-gradient)"/></svg>
\ No newline at end of file
...@@ -44,6 +44,7 @@ class TP_List { ...@@ -44,6 +44,7 @@ class TP_List {
String? contactName; String? contactName;
String? engineNo; String? engineNo;
TP_List({ TP_List({
this.genId, this.genId,
this.address, this.address,
......
class jobDescriptionResponse {
JobDescription? jobDescription;
String? error;
String? message;
int? sessionExists;
jobDescriptionResponse(
{this.jobDescription, this.error, this.message, this.sessionExists});
jobDescriptionResponse.fromJson(Map<String, dynamic> json) {
jobDescription = json['job_description'] != null
? new JobDescription.fromJson(json['job_description'])
: null;
error = json['error'];
message = json['message'];
sessionExists = json['session_exists'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.jobDescription != null) {
data['job_description'] = this.jobDescription!.toJson();
}
data['error'] = this.error;
data['message'] = this.message;
data['session_exists'] = this.sessionExists;
return data;
}
}
class JobDescription {
String? name;
String? jobDescription;
String? id;
JobDescription({this.name, this.jobDescription, this.id});
JobDescription.fromJson(Map<String, dynamic> json) {
name = json['name'];
jobDescription = json['job_description'];
id = json['id'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['name'] = this.name;
data['job_description'] = this.jobDescription;
data['id'] = this.id;
return data;
}
}
...@@ -5,6 +5,7 @@ import 'package:generp/screens/LoginScreen.dart'; ...@@ -5,6 +5,7 @@ import 'package:generp/screens/LoginScreen.dart';
import 'package:generp/services/api_calling.dart'; import 'package:generp/services/api_calling.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import '../Models/hrmModels/jobDescriptionResponse.dart';
import '../Utils/BackgroundLocationService.dart'; import '../Utils/BackgroundLocationService.dart';
import '../Utils/WebSocketManager.dart'; import '../Utils/WebSocketManager.dart';
import '../Utils/background_service.dart'; import '../Utils/background_service.dart';
...@@ -176,4 +177,5 @@ class HomescreenNotifier extends ChangeNotifier { ...@@ -176,4 +177,5 @@ class HomescreenNotifier extends ChangeNotifier {
print("$e"); print("$e");
} }
} }
} }
...@@ -8,6 +8,8 @@ import 'package:generp/screens/LoginScreen.dart'; ...@@ -8,6 +8,8 @@ import 'package:generp/screens/LoginScreen.dart';
import 'package:generp/services/api_calling.dart'; import 'package:generp/services/api_calling.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../Models/hrmModels/jobDescriptionResponse.dart';
class ProfileNotifer extends ChangeNotifier{ class ProfileNotifer extends ChangeNotifier{
var _profileImage = ""; var _profileImage = "";
var _company = ""; var _company = "";
...@@ -101,4 +103,40 @@ class ProfileNotifer extends ChangeNotifier{ ...@@ -101,4 +103,40 @@ class ProfileNotifer extends ChangeNotifier{
} }
} }
String? _errorMessage;
jobDescriptionResponse? _response;
String? get errorMessage => _errorMessage;
jobDescriptionResponse? get response => _response;
Future<void> fetchJobDescription(HomescreenNotifier prov, BuildContext context) async {
_isLoading = true;
_errorMessage = null;
_response = null;
notifyListeners();
try {
final provider = Provider.of<HomescreenNotifier>(context, listen: false);
final result = await ApiCalling.jobDescriptAPI(
provider.empId,
provider.session,
);
if (result != null) {
_response = result;
} else {
_errorMessage = "No job description data found!";
}
} catch (e) {
_errorMessage = "Something went wrong: $e";
}
_isLoading = false;
notifyListeners();
}
} }
\ No newline at end of file
...@@ -410,9 +410,22 @@ class Attendancelistprovider extends ChangeNotifier { ...@@ -410,9 +410,22 @@ class Attendancelistprovider extends ChangeNotifier {
/// Show Cupertino Date Picker /// Show Cupertino Date Picker
void showDatePickerDialog(BuildContext context) { void showDatePickerDialog(BuildContext context) {
DateTime now = DateTime.now();
DateTime today = DateTime(now.year, now.month, now.day);
// Normalize selected date (strip time)
if (_selectedDate == null) { if (_selectedDate == null) {
setSelectedDate(DateTime.now()); setSelectedDate(today);
} else {
_selectedDate = DateTime(
_selectedDate!.year,
_selectedDate!.month,
_selectedDate!.day,
);
} }
// Always reset before showing
_selectedDate = today;
setSelectedDate(today);
showCupertinoModalPopup<void>( showCupertinoModalPopup<void>(
context: context, context: context,
...@@ -452,7 +465,13 @@ class Attendancelistprovider extends ChangeNotifier { ...@@ -452,7 +465,13 @@ class Attendancelistprovider extends ChangeNotifier {
), ),
), ),
onPressed: () { onPressed: () {
setSelectedDate(_selectedDate ?? DateTime.now()); // Ensure we save only date without time
final pickedDate = _selectedDate ?? today;
setSelectedDate(DateTime(
pickedDate.year,
pickedDate.month,
pickedDate.day,
));
Navigator.pop(context); Navigator.pop(context);
}, },
), ),
...@@ -463,12 +482,15 @@ class Attendancelistprovider extends ChangeNotifier { ...@@ -463,12 +482,15 @@ class Attendancelistprovider extends ChangeNotifier {
Expanded( Expanded(
child: CupertinoDatePicker( child: CupertinoDatePicker(
dateOrder: DatePickerDateOrder.dmy, dateOrder: DatePickerDateOrder.dmy,
initialDateTime: _selectedDate ?? DateTime.now(), initialDateTime: _selectedDate ?? today,
minimumDate: today.subtract(const Duration(days: 2)),
maximumDate: today,
mode: CupertinoDatePickerMode.date, mode: CupertinoDatePickerMode.date,
use24hFormat: true, use24hFormat: true,
showDayOfWeek: true, showDayOfWeek: true,
onDateTimeChanged: (DateTime newDate) { onDateTimeChanged: (DateTime newDate) {
setSelectedDate(newDate); // Always normalize new date to midnight
setSelectedDate(DateTime(newDate.year, newDate.month, newDate.day));
}, },
), ),
), ),
...@@ -478,4 +500,5 @@ class Attendancelistprovider extends ChangeNotifier { ...@@ -478,4 +500,5 @@ class Attendancelistprovider extends ChangeNotifier {
), ),
); );
} }
} }
...@@ -20,6 +20,12 @@ import 'package:location/location.dart' as loc; ...@@ -20,6 +20,12 @@ import 'package:location/location.dart' as loc;
import '../Utils/app_colors.dart'; import '../Utils/app_colors.dart';
import 'inventory/InventoryScreen.dart'; import 'inventory/InventoryScreen.dart';
import 'package:auto_size_text/auto_size_text.dart'; import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/material.dart';
import 'package:flutter_html/flutter_html.dart';
import 'package:flutter/material.dart';
import 'package:flutter_html/flutter_html.dart';
import 'package:flutter_html/flutter_html.dart' as html;
class MyHomePage extends StatefulWidget { class MyHomePage extends StatefulWidget {
const MyHomePage({super.key}); const MyHomePage({super.key});
...@@ -42,6 +48,7 @@ class _MyHomePageState extends State<MyHomePage> { ...@@ -42,6 +48,7 @@ class _MyHomePageState extends State<MyHomePage> {
}); });
var prov = Provider.of<HomescreenNotifier>(context, listen: false); var prov = Provider.of<HomescreenNotifier>(context, listen: false);
var prof_prov = Provider.of<ProfileNotifer>(context, listen: false); var prof_prov = Provider.of<ProfileNotifer>(context, listen: false);
// var jobDisc_prov = Provider.of<fetchJobDescription>(context, listen: false);
Future.microtask(() { Future.microtask(() {
prov.DashboardApiFunction(context); prov.DashboardApiFunction(context);
}); });
...@@ -157,7 +164,7 @@ class _MyHomePageState extends State<MyHomePage> { ...@@ -157,7 +164,7 @@ class _MyHomePageState extends State<MyHomePage> {
"assets/svg/home/home_order_ic.svg", "assets/svg/home/home_order_ic.svg",
"assets/svg/home/home_service_ic.svg", "assets/svg/home/home_service_ic.svg",
"assets/svg/home/home_gentracker_ic.svg", "assets/svg/home/home_gentracker_ic.svg",
"assets/svg/home/home_erp_ic.svg", "assets/svg/hrm/pie-chart.svg",
]; ];
final icons = [ final icons = [
...@@ -1871,28 +1878,43 @@ class _MyHomePageState extends State<MyHomePage> { ...@@ -1871,28 +1878,43 @@ class _MyHomePageState extends State<MyHomePage> {
child: Align( child: Align(
alignment: Alignment.centerLeft, alignment: Alignment.centerLeft,
child: InkWell( child: InkWell(
onTap: () { onTap: () async {
showJobDescriptionSheet(context, [ final profileNotifier = Provider.of<ProfileNotifer>(context, listen: false);
"Statewise End to end sales activities reg booking and dispatches and payment collection and branch visit every month & quarterly basis.", // Call API
"Conducting monthly/Quarterly/Annually– sales meeting, review of targets and achievements of total team.", await profileNotifier.fetchJobDescription(
"Team CRM Tracking, Order Update Track and as well as payment entry in CRM by Team.", Provider.of<HomescreenNotifier>(context, listen: false),
"If required special Price to be taken from Prasad, Madhavi Madam/MD Sir.", context,
"Preparation of MIS reports on monthly basis (Rating wise data, employee wise data, TIV etc.).", );
"Dispatch co-ordination with factory team- Anuradha / Sai Ram (commercial clearance with Susmitha / Rajeevi).", // fetching, check response
"Commercial / Technical Support to BDE team order finalisation. If required client visit.", if (profileNotifier.response != null &&
"Team tour bills approvals in CRM.", profileNotifier.response!.jobDescription != null) {
"Level -1 approvals to be given to sales team orders.",
"Outstanding payment collection followed on regular basis.", if (profileNotifier.response!.jobDescription!.jobDescription != null && profileNotifier.response!.jobDescription!.jobDescription != "") {
]); showJobDescriptionSheet(
context: context,
htmlData: profileNotifier.response!.jobDescription!.jobDescription ?? "<p>No description</p>",
title: "Job Description",//profileNotifier.response!.jobDescription!.name ??
);
}
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(profileNotifier.errorMessage ?? "Failed to fetch job description"),
),
);
}
}, },
// no click for others // no click for others
child: Text( child: Text(
itemText, itemText,
textAlign: TextAlign.left, textAlign: TextAlign.left,
style: TextStyle( style: TextStyle(
fontSize: 14, fontSize: 14,
color: index == 2 ? AppColors.semi_black : AppColors.semi_black, // highlight clickable color: index == 2 ? AppColors.semi_black : AppColors.semi_black,
decoration: index == 2 ? TextDecoration.underline : null, decoration: index == 2 ? TextDecoration.underline : null,
decorationStyle: TextDecorationStyle.dotted,
), ),
), ),
), ),
...@@ -1966,10 +1988,17 @@ class _MyHomePageState extends State<MyHomePage> { ...@@ -1966,10 +1988,17 @@ class _MyHomePageState extends State<MyHomePage> {
} }
Future<void> showJobDescriptionSheet(
BuildContext context,
List<String> jobPoints,
) {
// Job Descriptions
Future<void> showJobDescriptionSheet({
required BuildContext context,
required String htmlData, // pass details_articles!.description
String title = "Job Description",
}) {
return showModalBottomSheet( return showModalBottomSheet(
useSafeArea: true, useSafeArea: true,
isDismissible: true, isDismissible: true,
...@@ -1985,7 +2014,7 @@ class _MyHomePageState extends State<MyHomePage> { ...@@ -1985,7 +2014,7 @@ class _MyHomePageState extends State<MyHomePage> {
bottom: 15, bottom: 15,
left: 15, left: 15,
right: 15, right: 15,
top: 30, top: 15,
), ),
padding: EdgeInsets.only( padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom, bottom: MediaQuery.of(context).viewInsets.bottom,
...@@ -1997,47 +2026,76 @@ class _MyHomePageState extends State<MyHomePage> { ...@@ -1997,47 +2026,76 @@ class _MyHomePageState extends State<MyHomePage> {
children: [ children: [
/// Heading /// Heading
Text( Text(
"Job Description", title,
style: TextStyle( style: TextStyle(
fontFamily: "JakartaMedium", fontFamily: "JakartaMedium",
fontSize: 16, fontSize: 18,
color: AppColors.app_blue, // same as Logout "Yes, Logout" button color: AppColors.app_blue,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
), ),
const SizedBox(height: 15), const SizedBox(height: 5),
/// Bullet points list /// HTML description
...jobPoints.map( Html(
(point) => Padding( data: htmlData,
padding: const EdgeInsets.symmetric(vertical: 6), style: {
child: Row( "h2": Style(
crossAxisAlignment: CrossAxisAlignment.start, wordSpacing: 0,
children: [ letterSpacing: 0,
Text( fontSize: FontSize(16),
"• ", fontFamily: "JakartaMedium",
style: TextStyle(
fontSize: 14,
color: AppColors.semi_black, color: AppColors.semi_black,
), ),
), "h3": Style(
Expanded( wordSpacing: 0,
child: Text( letterSpacing: 0,
point, fontSize: FontSize(12),
style: TextStyle( fontFamily: "JakartaMedium",
fontSize: 14,
color: AppColors.semi_black, color: AppColors.semi_black,
fontFamily: "JakartaRegular",
height: 1.4, // line spacing
),
), ),
"p": Style(
wordSpacing: 0,
letterSpacing: 0,
fontSize: FontSize(12),
fontFamily: "JakartaMedium",
color: AppColors.grey_semi,
lineHeight: LineHeight.number(2.4),
), ),
], "ul": Style(
wordSpacing: 0,
letterSpacing: 0,
fontSize: FontSize(15),
fontFamily: "JakartaMedium",
color: AppColors.grey_semi,
padding: HtmlPaddings.only(left: 10, right: 8), // fixed for v3.0.0
lineHeight: LineHeight.number(1.4),
),
"li": Style(
wordSpacing: 0,
letterSpacing: 0,
fontSize: FontSize(14),
fontFamily: "JakartaMedium",
color: Colors.black,
padding: HtmlPaddings.only(left: 4),
lineHeight: LineHeight.number(1.4), // bullet text line height
margin: Margins.only(bottom: 10),
), ),
"a": Style(
color: Colors.blue,
textDecoration: TextDecoration.underline,
), ),
},
onLinkTap: (url, _, __) {
debugPrint("Link tapped: $url");
if (url != null) {
// launchUrl(Uri.parse(url)); // needs url_launcher
}
},
), ),
const SizedBox(height: 20), const SizedBox(height: 6),
/// Close button /// Close button
InkWell( InkWell(
...@@ -2075,6 +2133,118 @@ class _MyHomePageState extends State<MyHomePage> { ...@@ -2075,6 +2133,118 @@ class _MyHomePageState extends State<MyHomePage> {
} }
// Future<void> showJobDescriptionSheet(
// BuildContext context,
// List<String> jobPoints,
// ) {
// return showModalBottomSheet(
// useSafeArea: true,
// isDismissible: true,
// isScrollControlled: true,
// showDragHandle: true,
// enableDrag: true,
// backgroundColor: Colors.white,
// context: context,
// builder: (context) {
// return SafeArea(
// child: Container(
// margin: const EdgeInsets.only(
// bottom: 15,
// left: 15,
// right: 15,
// top: 30,
// ),
// padding: EdgeInsets.only(
// bottom: MediaQuery.of(context).viewInsets.bottom,
// ),
// child: SingleChildScrollView(
// child: Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// mainAxisSize: MainAxisSize.min,
// children: [
// /// Heading
// Text(
// "Job Description",
// style: TextStyle(
// fontFamily: "JakartaMedium",
// fontSize: 16,
// color: AppColors.app_blue, // same as Logout "Yes, Logout" button
// fontWeight: FontWeight.w600,
// ),
// ),
// const SizedBox(height: 15),
//
// /// Bullet points list
// ...jobPoints.map(
// (point) => Padding(
// padding: const EdgeInsets.symmetric(vertical: 6),
// child: Row(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// Text(
// "• ",
// style: TextStyle(
// fontSize: 14,
// color: AppColors.semi_black,
// ),
// ),
// Expanded(
// child: Text(
// point,
// style: TextStyle(
// fontSize: 14,
// color: AppColors.semi_black,
// fontFamily: "JakartaRegular",
// height: 1.4, // line spacing
// ),
// ),
// ),
// ],
// ),
// ),
// ),
//
// const SizedBox(height: 20),
//
// /// Close button
// InkWell(
// onTap: () => Navigator.pop(context),
// child: Container(
// alignment: Alignment.center,
// height: 45,
// margin: const EdgeInsets.symmetric(
// horizontal: 5.0,
// vertical: 5.0,
// ),
// decoration: BoxDecoration(
// borderRadius: BorderRadius.circular(15.0),
// ),
// child: Center(
// child: Text(
// "Close",
// textAlign: TextAlign.center,
// style: TextStyle(
// color: AppColors.app_blue,
// fontFamily: "JakartaMedium",
// fontSize: 15,
// ),
// ),
// ),
// ),
// ),
// ],
// ),
// ),
// ),
// );
// },
// );
// }
Future<void> _showLogoutBottomSheet(BuildContext context) { Future<void> _showLogoutBottomSheet(BuildContext context) {
return showModalBottomSheet( return showModalBottomSheet(
useSafeArea: true, useSafeArea: true,
......
...@@ -282,13 +282,13 @@ class _AddLeaveRequestState extends State<AddLeaveRequest> { ...@@ -282,13 +282,13 @@ class _AddLeaveRequestState extends State<AddLeaveRequest> {
leaveTypeError = null; leaveTypeError = null;
reasonError = null; reasonError = null;
}); });
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
const SnackBar( const SnackBar(
content: Text("Leave request submitted successfully!"), content: Text("Leave request submitted successfully!"),
backgroundColor: Colors.black87, backgroundColor: Colors.black87,
), ),
); );
Navigator.pop(context, true);
} }
}, },
child: Container( child: Container(
......
...@@ -212,6 +212,7 @@ class _AddLiveAttendanceScreenState extends State<AddLiveAttendanceScreen> { ...@@ -212,6 +212,7 @@ class _AddLiveAttendanceScreenState extends State<AddLiveAttendanceScreen> {
_showSnack(context, "Attendance Submitted Successfully!"); _showSnack(context, "Attendance Submitted Successfully!");
_autoFetchLocation(); _autoFetchLocation();
Navigator.pop(context, true);
} }
void _showSnack(BuildContext context, String msg) { void _showSnack(BuildContext context, String msg) {
......
...@@ -69,14 +69,49 @@ class _AddManualAttendanceScreenState extends State<AddManualAttendanceScreen> { ...@@ -69,14 +69,49 @@ class _AddManualAttendanceScreenState extends State<AddManualAttendanceScreen> {
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
_fetchInitialLocation(); _fetchInitialLocation();
}); });
// Add listeners to text controllers to clear errors when user types
checkInLocation.addListener(_clearCheckInLocError);
checkInDescription.addListener(_clearCheckInDescError);
checkOutLocation.addListener(_clearCheckOutLocError);
checkOutDescription.addListener(_clearCheckOutDescError);
} }
@override @override
void dispose() { void dispose() {
_connectivity.disposeStream(); _connectivity.disposeStream();
checkInLocation.removeListener(_clearCheckInLocError);
checkInDescription.removeListener(_clearCheckInDescError);
checkOutLocation.removeListener(_clearCheckOutLocError);
checkOutDescription.removeListener(_clearCheckOutDescError);
super.dispose(); super.dispose();
} }
// Error clearing methods
void _clearCheckInLocError() {
if (checkInLocError != null && checkInLocation.text.isNotEmpty) {
setState(() => checkInLocError = null);
}
}
void _clearCheckInDescError() {
if (checkInDescError != null && checkInDescription.text.isNotEmpty) {
setState(() => checkInDescError = null);
}
}
void _clearCheckOutLocError() {
if (checkOutLocError != null && checkOutLocation.text.isNotEmpty) {
setState(() => checkOutLocError = null);
}
}
void _clearCheckOutDescError() {
if (checkOutDescError != null && checkOutDescription.text.isNotEmpty) {
setState(() => checkOutDescError = null);
}
}
Future<void> _fetchInitialLocation() async { Future<void> _fetchInitialLocation() async {
String loc = await getCurrentLocation(); String loc = await getCurrentLocation();
setState(() { setState(() {
...@@ -112,10 +147,18 @@ class _AddManualAttendanceScreenState extends State<AddManualAttendanceScreen> { ...@@ -112,10 +147,18 @@ class _AddManualAttendanceScreenState extends State<AddManualAttendanceScreen> {
} }
} }
Future<void> _pickTime(TextEditingController controller) async { Future<void> _pickTime(TextEditingController controller, bool isCheckIn) async {
final TimeOfDay? picked = final TimeOfDay? picked =
await showTimePicker(context: context, initialTime: TimeOfDay.now()); await showTimePicker(context: context, initialTime: TimeOfDay.now());
if (picked != null) controller.text = picked.format(context); if (picked != null) {
controller.text = picked.format(context);
// Clear error when time is selected
if (isCheckIn) {
if (checkInTimeError != null) setState(() => checkInTimeError = null);
} else {
if (checkOutTimeError != null) setState(() => checkOutTimeError = null);
}
}
} }
Future<void> _pickFile(bool isCheckIn) async { Future<void> _pickFile(bool isCheckIn) async {
...@@ -138,8 +181,13 @@ class _AddManualAttendanceScreenState extends State<AddManualAttendanceScreen> { ...@@ -138,8 +181,13 @@ class _AddManualAttendanceScreenState extends State<AddManualAttendanceScreen> {
await picker.pickImage(source: ImageSource.camera); await picker.pickImage(source: ImageSource.camera);
if (file != null) { if (file != null) {
setState(() { setState(() {
if (isCheckIn) checkInProof = file; if (isCheckIn) {
else checkOutProof = file; checkInProof = file;
if (checkInProofError != null) setState(() => checkInProofError = null);
} else {
checkOutProof = file;
if (checkOutProofError != null) setState(() => checkOutProofError = null);
}
}); });
} }
Navigator.pop(context); Navigator.pop(context);
...@@ -153,8 +201,13 @@ class _AddManualAttendanceScreenState extends State<AddManualAttendanceScreen> { ...@@ -153,8 +201,13 @@ class _AddManualAttendanceScreenState extends State<AddManualAttendanceScreen> {
await picker.pickImage(source: ImageSource.gallery); await picker.pickImage(source: ImageSource.gallery);
if (file != null) { if (file != null) {
setState(() { setState(() {
if (isCheckIn) checkInProof = file; if (isCheckIn) {
else checkOutProof = file; checkInProof = file;
if (checkInProofError != null) setState(() => checkInProofError = null);
} else {
checkOutProof = file;
if (checkOutProofError != null) setState(() => checkOutProofError = null);
}
}); });
} }
Navigator.pop(context); Navigator.pop(context);
...@@ -337,9 +390,6 @@ class _AddManualAttendanceScreenState extends State<AddManualAttendanceScreen> { ...@@ -337,9 +390,6 @@ class _AddManualAttendanceScreenState extends State<AddManualAttendanceScreen> {
); );
} }
} }
// it's date picker need to take day before yesterday, yesterday and today
Future<bool> _onBackPressed(BuildContext context) async { Future<bool> _onBackPressed(BuildContext context) async {
Navigator.pop(context, true); Navigator.pop(context, true);
...@@ -389,9 +439,14 @@ class _AddManualAttendanceScreenState extends State<AddManualAttendanceScreen> { ...@@ -389,9 +439,14 @@ class _AddManualAttendanceScreenState extends State<AddManualAttendanceScreen> {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
// TextWidget(context, "Date"), // Date field with error clearing
GestureDetector( GestureDetector(
onTap: () => provider.showDatePickerDialog(context), onTap: () {
provider.showDatePickerDialog(context);
if (dateError != null) {
setState(() => dateError = null);
}
},
child: AbsorbPointer( child: AbsorbPointer(
child: textControllerWidget( child: textControllerWidget(
context, context,
...@@ -410,6 +465,7 @@ class _AddManualAttendanceScreenState extends State<AddManualAttendanceScreen> { ...@@ -410,6 +465,7 @@ class _AddManualAttendanceScreenState extends State<AddManualAttendanceScreen> {
), ),
errorWidget(context, dateError), errorWidget(context, dateError),
// Type dropdown with error clearing
TextWidget(context, "Type"), TextWidget(context, "Type"),
DropdownButtonHideUnderline( DropdownButtonHideUnderline(
child: Row( child: Row(
...@@ -426,7 +482,12 @@ class _AddManualAttendanceScreenState extends State<AddManualAttendanceScreen> { ...@@ -426,7 +482,12 @@ class _AddManualAttendanceScreenState extends State<AddManualAttendanceScreen> {
.toList(), .toList(),
value: selectedType, value: selectedType,
onChanged: (val) { onChanged: (val) {
setState(() => selectedType = val); setState(() {
selectedType = val;
if (typeError != null) {
typeError = null;
}
});
}, },
buttonStyleData: ddtheme.buttonStyleData, buttonStyleData: ddtheme.buttonStyleData,
iconStyleData: ddtheme.iconStyleData, iconStyleData: ddtheme.iconStyleData,
...@@ -489,9 +550,9 @@ class _AddManualAttendanceScreenState extends State<AddManualAttendanceScreen> { ...@@ -489,9 +550,9 @@ class _AddManualAttendanceScreenState extends State<AddManualAttendanceScreen> {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
// TextWidget(context, "$title Time"), // Time field with error clearing
GestureDetector( GestureDetector(
onTap: () => _pickTime(timeCtrl), // ⏰ open time picker onTap: () => _pickTime(timeCtrl, isCheckIn),
child: AbsorbPointer( child: AbsorbPointer(
child: textControllerWidget( child: textControllerWidget(
context, context,
...@@ -510,6 +571,7 @@ class _AddManualAttendanceScreenState extends State<AddManualAttendanceScreen> { ...@@ -510,6 +571,7 @@ class _AddManualAttendanceScreenState extends State<AddManualAttendanceScreen> {
), ),
errorWidget(context, isCheckIn ? checkInTimeError : checkOutTimeError), errorWidget(context, isCheckIn ? checkInTimeError : checkOutTimeError),
// Location field (errors cleared via listener)
textControllerWidget( textControllerWidget(
context, context,
locCtrl, locCtrl,
...@@ -525,6 +587,7 @@ class _AddManualAttendanceScreenState extends State<AddManualAttendanceScreen> { ...@@ -525,6 +587,7 @@ class _AddManualAttendanceScreenState extends State<AddManualAttendanceScreen> {
), ),
errorWidget(context, isCheckIn ? checkInLocError : checkOutLocError), errorWidget(context, isCheckIn ? checkInLocError : checkOutLocError),
// Description field (errors cleared via listener)
textControllerWidget( textControllerWidget(
context, context,
descCtrl, descCtrl,
...@@ -540,6 +603,7 @@ class _AddManualAttendanceScreenState extends State<AddManualAttendanceScreen> { ...@@ -540,6 +603,7 @@ class _AddManualAttendanceScreenState extends State<AddManualAttendanceScreen> {
), ),
errorWidget(context, isCheckIn ? checkInDescError : checkOutDescError), errorWidget(context, isCheckIn ? checkInDescError : checkOutDescError),
// Proof attachment with error clearing
InkResponse( InkResponse(
onTap: () => _pickFile(isCheckIn), onTap: () => _pickFile(isCheckIn),
child: Container( child: Container(
...@@ -589,5 +653,17 @@ class _AddManualAttendanceScreenState extends State<AddManualAttendanceScreen> { ...@@ -589,5 +653,17 @@ class _AddManualAttendanceScreenState extends State<AddManualAttendanceScreen> {
], ],
); );
} }
}
// Helper widget to display errors
Widget errorWidget(BuildContext context, String? error) {
if (error == null) return const SizedBox(height: 8);
return Padding(
padding: const EdgeInsets.only(bottom: 8, left: 4),
child: Text(
error,
style: const TextStyle(color: Colors.red, fontSize: 12),
),
);
} }
\ No newline at end of file
...@@ -441,11 +441,13 @@ class _AddBillScreenState extends State<AddBillScreen> { ...@@ -441,11 +441,13 @@ class _AddBillScreenState extends State<AddBillScreen> {
if (!validateFields()) { if (!validateFields()) {
return; return;
} }
String formattedDate = "";
final provider = Provider.of<TourExpensesProvider>(context, listen: false); final provider = Provider.of<TourExpensesProvider>(context, listen: false);
provider.dateController.clear();
tourDateError = null; tourDateError = null;
final parsedDate = DateFormat("dd MMM yyyy").parse(provider.dateController.text);
formattedDate = DateFormat("yyyy-MM-dd").format(parsedDate);
final success = await provider.addTourBill( final success = await provider.addTourBill(
...@@ -453,7 +455,7 @@ class _AddBillScreenState extends State<AddBillScreen> { ...@@ -453,7 +455,7 @@ class _AddBillScreenState extends State<AddBillScreen> {
placeOfVisit: placeController.text, placeOfVisit: placeController.text,
daAmount: selectedDAAmount ?? "", daAmount: selectedDAAmount ?? "",
tourType: selectedTourType ?? "", tourType: selectedTourType ?? "",
tourDate: provider.dateController.text, tourDate: formattedDate,
travelExpenses: travelExpenses.map((e) => e.map((k, v) => MapEntry(k, v as dynamic))).toList(), travelExpenses: travelExpenses.map((e) => e.map((k, v) => MapEntry(k, v as dynamic))).toList(),
hotelExpenses: hotelExpenses.map((e) => e.map((k, v) => MapEntry(k, v as dynamic))).toList(), hotelExpenses: hotelExpenses.map((e) => e.map((k, v) => MapEntry(k, v as dynamic))).toList(),
otherExpenses: otherExpenses.map((e) => e.map((k, v) => MapEntry(k, v as dynamic))).toList(), otherExpenses: otherExpenses.map((e) => e.map((k, v) => MapEntry(k, v as dynamic))).toList(),
...@@ -461,6 +463,7 @@ class _AddBillScreenState extends State<AddBillScreen> { ...@@ -461,6 +463,7 @@ class _AddBillScreenState extends State<AddBillScreen> {
hotelImages: hotelImages, hotelImages: hotelImages,
otherImages: otherImages, otherImages: otherImages,
); );
provider.dateController.clear();
print("image================== $travelImages"); print("image================== $travelImages");
if (success) { if (success) {
...@@ -537,6 +540,26 @@ class _AddBillScreenState extends State<AddBillScreen> { ...@@ -537,6 +540,26 @@ class _AddBillScreenState extends State<AddBillScreen> {
); );
} }
String _getTravelIcon(String? travelType) {
switch (travelType?.toLowerCase()) {
case "flight":
return "assets/svg/hrm/airplane_ic.svg";
case "train":
return "assets/svg/hrm/train_ic.svg";
case "bus":
return "assets/svg/hrm/bus_ic.svg";
case "car":
return "assets/svg/hrm/car_ic.svg";
case "auto":
return "assets/svg/hrm/truck_ic.svg";
case "bike":
return "assets/svg/hrm/motorcycle_ic.svg";
default:
return "assets/svg/hrm/travel_ic.svg"; // fallback
}
}
Widget travelExpenseList(List<Map<String, String>> items) { Widget travelExpenseList(List<Map<String, String>> items) {
return Container( return Container(
height: 90, height: 90,
...@@ -565,7 +588,7 @@ class _AddBillScreenState extends State<AddBillScreen> { ...@@ -565,7 +588,7 @@ class _AddBillScreenState extends State<AddBillScreen> {
), ),
child: Center( child: Center(
child: SvgPicture.asset( child: SvgPicture.asset(
"assets/svg/hrm/travel_ic.svg", _getTravelIcon(exp["travel_type"]),
height: 20, height: 20,
), ),
), ),
......
...@@ -90,6 +90,10 @@ class _AttendanceRequestDetailScreenState ...@@ -90,6 +90,10 @@ class _AttendanceRequestDetailScreenState
} }
final details = provider.response!.requestDetails!; final details = provider.response!.requestDetails!;
final checkInTime = details.status == "Requested" ? "--" : details.checkInTime;
/// scr /// scr
return SingleChildScrollView( return SingleChildScrollView(
...@@ -200,7 +204,9 @@ class _AttendanceRequestDetailScreenState ...@@ -200,7 +204,9 @@ class _AttendanceRequestDetailScreenState
_buildSectionHeader("Check In/Out Details", scaleFactor), _buildSectionHeader("Check In/Out Details", scaleFactor),
_buildDate_TimeTile("Check In Date & Time", details.date, details.checkInTime, scaleFactor), _buildDate_TimeTile("Check In Date & Time", details.date, details.checkInTime, scaleFactor),
_buildDate_TimeTile("Check Out Date & Time", details.date, details.checkOutTime, scaleFactor), _buildDate_TimeTile("Check Out Date & Time", details.date, details.checkOutTime, scaleFactor),
_buildDetailTile("Original Check In", details.checkInTime, scaleFactor),
_buildDetailTile("Original Check In", checkInTime, scaleFactor),
_buildDetailTile("Original Check Out", "--", scaleFactor), _buildDetailTile("Original Check Out", "--", scaleFactor),
_buildDetailTile("Original Check In Location", details.checkInLocation, scaleFactor), _buildDetailTile("Original Check In Location", details.checkInLocation, scaleFactor),
_buildDetailTile("Original Check Out Location", details.checkOutLocation, scaleFactor), _buildDetailTile("Original Check Out Location", details.checkOutLocation, scaleFactor),
......