diff --git a/assets/animations/lottie/HourGlass.json b/assets/animations/lottie/HourGlass.json new file mode 100644 index 00000000..d0c87fd3 --- /dev/null +++ b/assets/animations/lottie/HourGlass.json @@ -0,0 +1 @@ +{"nm":"Hourglass","h":500,"w":500,"meta":{"g":"LottieFiles AE 1.1.0"},"layers":[{"ty":4,"nm":"Side 2 Matte","sr":1,"st":-25,"op":76,"ip":0,"hasMask":false,"td":1,"ao":0,"ks":{"a":{"a":0,"k":[-6552.114,-5982.041,0]},"s":{"a":0,"k":[100,100,100]},"sk":{"a":0,"k":0},"p":{"a":0,"k":[-6552,-6594.232,0]},"r":{"a":0,"k":0},"sa":{"a":0,"k":0},"o":{"a":0,"k":100}},"ef":[],"shapes":[{"ty":"gr","nm":"Group 1","it":[{"ty":"sh","nm":"Path 1","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[-2.437,0],[0,0]],"o":[[0,0],[0,0],[0,0],[2.437,0],[0,0]],"v":[[-6469.931,-6116.998],[-6634.298,-6117.35],[-6555.846,-5981.885],[-6552.176,-5979.025],[-6548.382,-5982.198]]}}},{"ty":"fl","nm":"Fill 1","c":{"a":0,"k":[0.18,0.188,0.224]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"sk":{"a":0,"k":0},"p":{"a":0,"k":[0,0]},"r":{"a":0,"k":0},"sa":{"a":0,"k":0},"o":{"a":0,"k":100}}]}],"ind":1,"parent":7},{"ty":4,"nm":"Sand 2","sr":1,"st":-25,"op":76,"ip":0,"tt":1,"hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[0,0,0]},"s":{"a":0,"k":[100,100,100]},"sk":{"a":0,"k":0},"p":{"a":0,"k":[-6552.114,-5982.041,0]},"r":{"a":0,"k":0},"sa":{"a":0,"k":0},"o":{"a":0,"k":100}},"ef":[],"shapes":[{"ty":"gr","nm":"Shape 1","it":[{"ty":"sh","nm":"Path 1","d":1,"ks":{"a":1,"k":[{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[{"c":true,"i":[[0.486,0.846],[0.625,-1.344],[-0.28,-0.728],[0.057,-0.656],[-0.144,-3.463],[0,0],[-0.063,3.469],[-0.062,1.125],[-0.268,0.626]],"o":[[-0.844,-1.469],[-0.34,0.73],[0.235,0.612],[-0.125,1.438],[0.144,3.463],[0,0],[0.063,-3.469],[0.026,-0.477],[0.364,-0.851]],"v":[[1.781,1.656],[-1.906,1.969],[-1.715,4.139],[-1.281,6.031],[-3.988,12.194],[-1.25,23],[5.062,8.062],[1,5.969],[1.59,4.283]]}],"t":0},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[{"c":true,"i":[[0,0],[0,0],[2.534,0.174],[-4.393,-4.956],[4.426,-20.319],[0,0],[4.269,23.889],[-9.5,9],[-0.283,0.932]],"o":[[0,0],[0,0],[-2.13,-0.147],[9.75,11],[-4.333,19.892],[0,0],[-5.875,-32.875],[3.487,-3.304],[0.384,-1.268]],"v":[[14,-138.75],[-3.5,-136.5],[-10.497,-138.771],[-9,-132.75],[-3.676,2.319],[-1.25,23],[3.375,1.375],[10,-131.75],[15.02,-137.747]]}],"t":9},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[{"c":true,"i":[[0,0],[0,0],[-20.182,-2.387],[-4.393,-4.956],[4.426,-20.319],[0,0],[4.269,23.889],[-9.5,9],[-15.597,1.657]],"o":[[0,0],[0,0],[16.964,2.006],[9.75,11],[-4.333,19.892],[0,0],[-5.875,-32.875],[3.487,-3.304],[21.209,-2.253]],"v":[[91.5,-136],[-89.75,-137.5],[-49.161,-134.405],[-11,-124.25],[-3.676,2.319],[-1.25,23],[3.375,1.375],[13.5,-125.5],[47.123,-132.85]]}],"t":25},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[{"c":true,"i":[[0,0],[0,0],[-21.104,-9.934],[-6.5,-8],[0,-21.193],[0,0],[0,24.267],[-7.401,10.793],[-19.85,6.269]],"o":[[0,0],[0,0],[21.691,10.211],[9.269,11.408],[0,20.359],[0,0],[0,-31.5],[6,-8.75],[22.388,-7.071]],"v":[[91.5,-136],[-89.75,-137.5],[-72.691,-114.461],[-9.25,-108.5],[-3.301,0.194],[-1.25,23],[2.75,-0.25],[13,-106.75],[64.35,-110.519]]}],"t":36},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[{"c":true,"i":[[0,0],[0,0],[-22.88,-4.534],[-1.313,-0.25],[-1.613,-0.182],[-1.375,-0.062],[-1.75,0.062],[-1.937,0.188],[-19.225,4.769]],"o":[[0,0],[0,0],[14.941,2.961],[1.312,0.25],[1.613,0.182],[1.375,0.062],[1.75,-0.062],[1.937,-0.188],[22.788,-5.653]],"v":[[91.5,-136],[-89.75,-137.5],[-64.441,-101.961],[-11.188,-97],[-4.863,-96.557],[-0.75,-96.5],[3.75,-96.5],[10.188,-96.625],[64.1,-102.019]]}],"t":50},{"s":[{"c":true,"i":[[14.5,-2],[25,7],[-12.809,-15.539],[-1.313,-0.25],[-1.613,-0.182],[-1.375,-0.062],[-1.75,0.062],[-1.937,0.188],[-6.715,12.881]],"o":[[-18.589,2.564],[-23.131,-6.477],[9.688,11.753],[1.312,0.25],[1.613,0.182],[1.375,0.062],[1.75,-0.062],[1.937,-0.188],[3.9,-7.481]],"v":[[38.5,-89],[-32.75,-76.5],[-45.191,-56.711],[-10.188,-2.5],[-4.613,0.193],[-0.25,0.5],[3.25,0.25],[9.938,-0.875],[57.6,-77.519]]}],"t":75}]}},{"ty":"st","nm":"Stroke 1","lc":1,"lj":1,"ml":4,"o":{"a":0,"k":100},"w":{"a":0,"k":0},"c":{"a":0,"k":[0,0.58,0.616]}},{"ty":"fl","nm":"Fill 1","c":{"a":0,"k":[0.18,0.188,0.224]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"sk":{"a":0,"k":0},"p":{"a":0,"k":[0,0]},"r":{"a":0,"k":0},"sa":{"a":0,"k":0},"o":{"a":0,"k":100}}]}],"ind":2,"parent":1},{"ty":4,"nm":"Side 1 Matte","sr":1,"st":-25,"op":76,"ip":0,"hasMask":false,"td":1,"ao":0,"ks":{"a":{"a":0,"k":[-6552.114,-5982.041,0]},"s":{"a":0,"k":[100,100,100]},"sk":{"a":0,"k":0},"p":{"a":0,"k":[250,250,0]},"r":{"a":0,"k":0},"sa":{"a":0,"k":0},"o":{"a":0,"k":100}},"ef":[],"shapes":[{"ty":"gr","nm":"Group 1","it":[{"ty":"sh","nm":"Path 1","d":1,"ks":{"a":0,"k":{"c":true,"i":[[0,0],[0,0],[0,0],[-0.99,-0.125],[0,0]],"o":[[0,0],[0,0],[0,0],[0.99,0.125],[0,0]],"v":[[-6469.931,-6116.998],[-6634.298,-6117.35],[-6555.846,-5981.885],[-6552.229,-5980.042],[-6548.382,-5982.198]]}}},{"ty":"fl","nm":"Fill 1","c":{"a":0,"k":[0.18,0.188,0.224]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"sk":{"a":0,"k":0},"p":{"a":0,"k":[0,0]},"r":{"a":0,"k":0},"sa":{"a":0,"k":0},"o":{"a":0,"k":100}}]}],"ind":3},{"ty":4,"nm":"Sand 1","sr":1,"st":-25,"op":76,"ip":0,"tt":1,"hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[0,0,0]},"s":{"a":0,"k":[100,100,100]},"sk":{"a":0,"k":0},"p":{"a":1,"k":[{"o":{"x":0.167,"y":0.167},"i":{"x":0.4,"y":1},"s":[250,250,0],"t":0,"ti":[0,0,0],"to":[0,0,0]},{"s":[250,331,0],"t":50}]},"r":{"a":0,"k":0},"sa":{"a":0,"k":0},"o":{"a":0,"k":100}},"ef":[],"shapes":[{"ty":"gr","nm":"Shape 1","it":[{"ty":"sh","nm":"Path 1","d":1,"ks":{"a":1,"k":[{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[{"c":true,"i":[[14.5,-2],[9.627,-3.183],[8.064,-1.099],[7.079,1.982],[-12.809,-15.539],[-1.156,-1.094],[-0.582,-0.244],[-0.656,0],[-0.719,0.281],[-1.219,1.562],[-6.715,12.881]],"o":[[-7.462,1.029],[-7.564,2.501],[-7.239,0.986],[-23.131,-6.477],[9.688,11.753],[1.156,1.094],[0.582,0.244],[0.656,0],[0.719,-0.281],[1.219,-1.562],[3.9,-7.481]],"v":[[38.5,-89],[12.486,-81.442],[-11.141,-75.441],[-32.75,-76.5],[-45.191,-56.711],[-10.188,-2.5],[-3.019,2.287],[0.094,2.719],[2.75,2.344],[9.938,-0.875],[57.6,-77.519]]}],"t":0},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[{"c":true,"i":[[14.5,-2],[2.585,2.626],[5.445,-3.528],[6.397,1.791],[-12.809,-15.539],[-1.156,-1.094],[-0.582,-0.244],[-0.656,0],[-0.719,0.281],[-1.219,1.562],[-6.715,12.881]],"o":[[-8.027,1.107],[-5.58,-5.669],[-5.652,3.663],[-23.131,-6.477],[9.688,11.753],[1.156,1.094],[0.582,0.244],[0.656,0],[0.719,-0.281],[1.219,-1.562],[3.9,-7.481]],"v":[[38.5,-89],[8.79,-71.474],[-8.07,-72.57],[-32.75,-76.5],[-45.191,-56.711],[-10.188,-2.5],[-3.019,2.287],[0.094,2.719],[2.75,2.344],[9.938,-0.875],[57.6,-77.519]]}],"t":39},{"s":[{"c":true,"i":[[14.5,-2],[9.627,-3.183],[8.064,-1.099],[7.079,1.982],[-12.809,-15.539],[-1.156,-1.094],[-0.582,-0.244],[-0.656,0],[-0.719,0.281],[-1.219,1.562],[-6.715,12.881]],"o":[[-7.462,1.029],[-7.564,2.501],[-7.239,0.986],[-23.131,-6.477],[9.688,11.753],[1.156,1.094],[0.582,0.244],[0.656,0],[0.719,-0.281],[1.219,-1.562],[3.9,-7.481]],"v":[[38.5,-89],[12.486,-81.442],[-11.141,-75.441],[-32.75,-76.5],[-45.191,-56.711],[-10.188,-2.5],[-3.019,2.287],[0.094,2.719],[2.75,2.344],[9.938,-0.875],[57.6,-77.519]]}],"t":45}]}},{"ty":"st","nm":"Stroke 1","lc":1,"lj":1,"ml":4,"o":{"a":0,"k":100},"w":{"a":0,"k":0},"c":{"a":0,"k":[0,0.58,0.616]}},{"ty":"fl","nm":"Fill 1","c":{"a":0,"k":[0.18,0.188,0.224]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"sk":{"a":0,"k":0},"p":{"a":0,"k":[0,0]},"r":{"a":0,"k":0},"sa":{"a":0,"k":0},"o":{"a":0,"k":100}}]}],"ind":4},{"ty":4,"nm":"Shadow Matte","sr":1,"st":-25,"op":76,"ip":0,"hasMask":false,"td":1,"ao":0,"ks":{"a":{"a":0,"k":[-6552,-6594.232,0]},"s":{"a":0,"k":[100,100,100]},"sk":{"a":0,"k":0},"p":{"a":0,"k":[-6552,-6594.232,0]},"r":{"a":0,"k":0},"sa":{"a":0,"k":0},"o":{"a":0,"k":100}},"ef":[],"shapes":[{"ty":"gr","nm":"Group 3","it":[{"ty":"sh","nm":"Path 1","d":1,"ks":{"a":0,"k":{"c":true,"i":[[8.207,0],[0,0],[-1.738,-7.444],[-0.605,-1.021],[0,0],[-0.214,-1.589],[0.143,-1.057],[0.823,-1.388],[0,0],[0.269,-1.149],[-8.207,0],[0,0],[1.738,7.444],[0.605,1.021],[0,0],[0.214,1.589],[-0.143,1.057],[-0.823,1.388],[0,0],[-0.269,1.149]],"o":[[0,0],[-8.207,0],[0.269,1.149],[0,0],[0.823,1.388],[0.143,1.057],[-0.214,1.589],[0,0],[-0.605,1.021],[-1.738,7.444],[0,0],[8.207,0],[-0.269,-1.149],[0,0],[-0.823,-1.388],[-0.143,-1.057],[0.214,-1.589],[0,0],[0.605,-1.021],[1.738,-7.444]],"v":[[-6458.712,-6744.95],[-6645.288,-6744.95],[-6657.545,-6730.055],[-6656.154,-6726.804],[-6581.067,-6600.158],[-6579.392,-6595.673],[-6579.392,-6592.49],[-6581.067,-6588.004],[-6656.154,-6461.358],[-6657.545,-6458.107],[-6645.288,-6443.213],[-6458.712,-6443.213],[-6446.455,-6458.107],[-6447.846,-6461.358],[-6522.933,-6588.004],[-6524.608,-6592.49],[-6524.608,-6595.673],[-6522.933,-6600.158],[-6447.846,-6726.804],[-6446.455,-6730.055]]}}},{"ty":"fl","nm":"Fill 1","c":{"a":0,"k":[1,1,1]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"sk":{"a":0,"k":0},"p":{"a":0,"k":[0,0]},"r":{"a":0,"k":0},"sa":{"a":0,"k":0},"o":{"a":0,"k":100}}]}],"ind":5,"parent":7},{"ty":4,"nm":"Shadow","sr":1,"st":-25,"op":76,"ip":0,"tt":1,"hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[0,0,0]},"s":{"a":0,"k":[100,100,100]},"sk":{"a":0,"k":0},"p":{"a":0,"k":[250,250,0]},"r":{"a":0,"k":0},"sa":{"a":0,"k":0},"o":{"a":0,"k":10}},"ef":[],"shapes":[{"ty":"gr","nm":"Shape 1","it":[{"ty":"sh","nm":"Path 1","d":1,"ks":{"a":1,"k":[{"o":{"x":0.6,"y":0},"i":{"x":0.833,"y":0.833},"s":[{"c":true,"i":[[0,0],[49.135,-3.183],[-13.025,-0.599],[-29.109,-5.019],[13.5,-22],[-0.77,-28.49],[29.438,-20.455],[28.507,-1.289],[-25.5,-5.5],[0,0]],"o":[[0,0],[-12.896,0.835],[43.5,2],[29,5],[-13.5,22],[1,37],[-21.22,14.745],[-24.059,1.087],[25.5,5.5],[0,0]],"v":[[229.5,-239],[-92.882,-163.672],[-71.5,-153],[41,-141.5],[66.5,-106],[13,1],[57,123],[-37.5,133.501],[-42.5,152],[238,239.5]]}],"t":50},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[{"c":true,"i":[[0,0],[48.989,-4.946],[-18.192,-25.462],[-22.077,-19.192],[7.048,-23.757],[2.816,-27.802],[1.115,-25.846],[53.077,0.154],[-25.5,-5.5],[0,0]],"o":[[0,0],[-46.272,4.672],[18.192,25.462],[22.077,19.192],[-7.039,24.308],[-3.749,36.459],[-1.115,25.846],[-53.077,-0.154],[25.5,5.5],[0,0]],"v":[[237.269,-237.077],[115.272,-238.672],[25.808,-162.462],[78.923,-108.192],[124.885,-41.538],[37.692,15.808],[61.615,97.154],[1.577,168.654],[-49.038,228.923],[241.615,239.193]]}],"t":57},{"o":{"x":0.167,"y":0.167},"i":{"x":0.833,"y":0.833},"s":[{"c":true,"i":[[0,0],[49.135,-3.183],[-39.5,-8],[-27.395,11.046],[-3.726,-32.793],[13,-36],[36,18],[28.507,-1.289],[-25.5,-5.5],[0,0]],"o":[[0,0],[-12.896,0.835],[39.5,8],[31,-12.5],[2.5,22],[-11.892,32.933],[-23.112,-11.556],[-24.059,1.088],[25.5,5.5],[0,0]],"v":[[220.5,-166.5],[-18.882,-189.672],[10.5,-128.5],[117,-126],[138.5,-50],[130,54],[81,152],[-12.5,143],[-12,233],[217,157]]}],"t":63},{"o":{"x":0.167,"y":0.167},"i":{"x":0.4,"y":1},"s":[{"c":true,"i":[[0,0],[49.135,-3.183],[-16.242,-32.949],[-16.167,-13.833],[-28.167,-13.5],[-3.833,-25.667],[28.167,-23.833],[28.337,-16.478],[-25.5,-5.5],[0,0]],"o":[[0,0],[-12.896,0.835],[23.333,47.333],[16.167,13.833],[28.167,13.5],[4.387,24.133],[-28.167,23.833],[-20.032,9.541],[25.5,5.5],[0,0]],"v":[[222.833,-223.333],[-65.548,-175.506],[-15.333,-124.333],[29.833,-53.833],[75.833,-31.5],[138.167,21.833],[78.167,128.167],[2.667,206.334],[-43.833,233.5],[235.333,241.5]]}],"t":68},{"s":[{"c":true,"i":[[0,0],[49.135,-3.183],[-13.025,-0.599],[-29.109,-5.019],[13.5,-22],[-0.77,-28.49],[29.438,-20.455],[28.507,-1.289],[-25.5,-5.5],[0,0]],"o":[[0,0],[-12.896,0.835],[43.5,2],[29,5],[-13.5,22],[1,37],[-21.22,14.745],[-24.059,1.087],[25.5,5.5],[0,0]],"v":[[229.5,-239],[-92.882,-163.672],[-71.5,-153],[41,-141.5],[66.5,-106],[13,1],[57,123],[-37.5,133.501],[-42.5,152],[238,239.5]]}],"t":75}]}},{"ty":"st","nm":"Stroke 1","lc":1,"lj":1,"ml":4,"o":{"a":0,"k":100},"w":{"a":0,"k":0},"c":{"a":0,"k":[0,0.58,0.616]}},{"ty":"fl","nm":"Fill 1","c":{"a":0,"k":[0.18,0.188,0.224]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"sk":{"a":0,"k":0},"p":{"a":0,"k":[0,0]},"r":{"a":0,"k":0},"sa":{"a":0,"k":0},"o":{"a":0,"k":100}}]}],"ind":6},{"ty":4,"nm":"Main Hourglass","sr":1,"st":-25,"op":76,"ip":0,"hasMask":false,"ao":0,"ks":{"a":{"a":0,"k":[-6552,-6594.232,0]},"s":{"a":0,"k":[100,100,100]},"sk":{"a":0,"k":0},"p":{"a":0,"k":[250,250,0]},"r":{"a":1,"k":[{"o":{"x":0.6,"y":0},"i":{"x":0.4,"y":1},"s":[0],"t":-25},{"o":{"x":0.6,"y":0},"i":{"x":0.4,"y":1},"s":[180],"t":0},{"o":{"x":0.6,"y":0},"i":{"x":0.4,"y":1},"s":[180],"t":50},{"s":[360],"t":75}]},"sa":{"a":0,"k":0},"o":{"a":0,"k":100}},"ef":[],"shapes":[{"ty":"gr","nm":"Group 1","it":[{"ty":"sh","nm":"Path 1","d":1,"ks":{"a":0,"k":{"c":true,"i":[[3.931,0],[0,0],[0,3.931],[0,0],[-3.931,0],[0,0],[0,-3.931],[0,0]],"o":[[0,0],[-3.931,0],[0,0],[0,-3.931],[0,0],[3.931,0],[0,0],[0,3.931]],"v":[[-6436.617,-6754.998],[-6667.383,-6754.998],[-6674.5,-6762.115],[-6674.5,-6762.115],[-6667.383,-6769.232],[-6436.617,-6769.232],[-6429.5,-6762.115],[-6429.5,-6762.115]]}}},{"ty":"fl","nm":"Fill 1","c":{"a":0,"k":[0.18,0.188,0.224]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"sk":{"a":0,"k":0},"p":{"a":0,"k":[0,0]},"r":{"a":0,"k":0},"sa":{"a":0,"k":0},"o":{"a":0,"k":100}}]},{"ty":"gr","nm":"Group 2","it":[{"ty":"sh","nm":"Path 1","d":1,"ks":{"a":0,"k":{"c":true,"i":[[3.931,0],[0,0],[0,3.931],[0,0],[-3.931,0],[0,0],[0,-3.931],[0,0]],"o":[[0,0],[-3.931,0],[0,0],[0,-3.931],[0,0],[3.931,0],[0,0],[0,3.931]],"v":[[-6436.617,-6419.232],[-6667.383,-6419.232],[-6674.5,-6426.35],[-6674.5,-6426.35],[-6667.383,-6433.467],[-6436.617,-6433.467],[-6429.5,-6426.35],[-6429.5,-6426.35]]}}},{"ty":"fl","nm":"Fill 1","c":{"a":0,"k":[0.18,0.188,0.224]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"sk":{"a":0,"k":0},"p":{"a":0,"k":[0,0]},"r":{"a":0,"k":0},"sa":{"a":0,"k":0},"o":{"a":0,"k":100}}]},{"ty":"gr","nm":"Group 3","it":[{"ty":"sh","nm":"Path 1","d":1,"ks":{"a":0,"k":{"c":true,"i":[[8.207,0],[0,0],[-1.738,-7.444],[-0.605,-1.021],[0,0],[-0.214,-1.589],[0.143,-1.057],[0.823,-1.388],[0,0],[0.269,-1.149],[-8.207,0],[0,0],[1.738,7.444],[0.605,1.021],[0,0],[0.214,1.589],[-0.143,1.057],[-0.823,1.388],[0,0],[-0.269,1.149]],"o":[[0,0],[-8.207,0],[0.269,1.149],[0,0],[0.823,1.388],[0.143,1.057],[-0.214,1.589],[0,0],[-0.605,1.021],[-1.738,7.444],[0,0],[8.207,0],[-0.269,-1.149],[0,0],[-0.823,-1.388],[-0.143,-1.057],[0.214,-1.589],[0,0],[0.605,-1.021],[1.738,-7.444]],"v":[[-6458.712,-6744.95],[-6645.288,-6744.95],[-6657.545,-6730.055],[-6656.154,-6726.804],[-6581.067,-6600.158],[-6579.392,-6595.673],[-6579.392,-6592.49],[-6581.067,-6588.004],[-6656.154,-6461.358],[-6657.545,-6458.107],[-6645.288,-6443.213],[-6458.712,-6443.213],[-6446.455,-6458.107],[-6447.846,-6461.358],[-6522.933,-6588.004],[-6524.608,-6592.49],[-6524.608,-6595.673],[-6522.933,-6600.158],[-6447.846,-6726.804],[-6446.455,-6730.055]]}}},{"ty":"fl","nm":"Fill 1","c":{"a":0,"k":[1,1,1]},"r":1,"o":{"a":0,"k":100}},{"ty":"tr","a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"sk":{"a":0,"k":0},"p":{"a":0,"k":[0,0]},"r":{"a":0,"k":0},"sa":{"a":0,"k":0},"o":{"a":0,"k":100}}]}],"ind":7}],"v":"4.8.0","fr":25,"op":76,"ip":0,"assets":[]} \ No newline at end of file diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index 92f202f0..822b73dd 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -1249,7 +1249,7 @@ "quickLinks": "روابط سريعة", "viewMedicalFileLandingPage": "عرض الملف الطبي", "immediateLiveCareRequest": "طلب لايف كير فوري", - "yourTurnIsAfterPatients": "دورك بعد {count} مريض.", + "yourTurnIsAfterPatients": "دورك بعد {count} مريض. يرجى الانتظار حتى يحين دورك، وسيناديك الطبيب قريباً.", "dontHaveHHCOrders": "ليس لديك أي أوامر رعاية صحية منزلية حتى الآن.", "hhcOrders": "أوامر الرعاية الصحية المنزلية", "requestedServices": "الخدمات المطلوبة", @@ -1578,7 +1578,7 @@ "noFreeSlot": "لا توجد مواعيد متاحة في التاريخ المحدد. يرجى اختيار تاريخ آخر أو إعادة المحاولة لاحقاً.", "noThanksIKnowTheClinic": "لا، شكراً. أنا أعرف العيادة.", "unableToSendOTP": "تعذر إرسال رمز التحقق لمرة واحدة", - "loadingAIAnalysis": "جارٍ تحليل نتائج المختبر، يرجى التحلي بالصبر والسماح للذكاء الاصطناعي بالقيام بالمهمة، قد يستغرق هذا بعض الوقت.", + "loadingAIAnalysis": "نقوم بتحليل نتائجك، يرجى التحلي بالصبر والسماح للذكاء الاصطناعي بالقيام بالمهمة، قد يستغرق هذا بعض الوقت.", "symptoms": "أعراض", "insuranceInActive": "التأمين غير نشط", "insuranceInActiveContactSupport": "لديك تأمين ساري المفعول، ولكنه غير مُفعّل حاليًا في مجموعة حبيب الطبية. يُرجى التواصل مع خدمة عملاء مجموعة حبيب الطبية.", @@ -1689,5 +1689,7 @@ "openGallery": "افتح المعرض", "openFiles": "فتح الملفات", "generateAiAnalysisRadResult": "بإنشاء تحليل الذكاء الاصطناعي لهذا التقرير", - "grantLocationPermission": "يرجى منح إذن الوصول إلى الموقع من إعدادات التطبيق للحصول على نتائج أفضل." + "grantLocationPermission": "يرجى منح إذن الوصول إلى الموقع من إعدادات التطبيق للحصول على نتائج أفضل.", + "NoBookedAppointments": "لا توجد مواعيد محجوزة", + "aiDisclaimerRad": "سيتم مشاركة بيانات نتائج الأشعة الخاصة بك بشكل آمن مع محلل الذكاء الاصطناعي لدينا لتحليلها. يساعد هذا في توفير رؤى صحية مخصصة. هل ترغب في المتابعة؟" } diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index 384b16d5..27a67857 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -1572,7 +1572,7 @@ "contextDependent": "Context Dependent", "calculatedValue": "Calculated Value", "calculationFormula": "Calculation Formula", - "loadingAIAnalysis": "Analysing your lab results, Please be patient and let the AI do the magic, This might take some time.", + "loadingAIAnalysis": "Analysing your results, Please be patient and let the AI do the magic, This might take some time.", "symptoms": "Symptoms", "insuranceInActive": "Insurance Inactive", "insuranceInActiveContactSupport": "You have a valid insurance but it is currently inactive in HMG. Please contact HMG customer support to activate it.", @@ -1681,5 +1681,7 @@ "openGallery": "Open Gallery", "openFiles": "Open Files", "generateAiAnalysisRadResult": "Generate AI analysis for this result", - "grantLocationPermission": "Please grant location permission from app settings to see better results." + "grantLocationPermission": "Please grant location permission from app settings to see better results.", + "NoBookedAppointments": "No Booked Appointments", + "aiDisclaimerRad": "Your radiology result data will be securely shared with our AI Analyzer for analysis. This helps provide personalized health insights. Do you want to proceed?" } diff --git a/lib/core/app_assets.dart b/lib/core/app_assets.dart index e4308bd5..21280f45 100644 --- a/lib/core/app_assets.dart +++ b/lib/core/app_assets.dart @@ -415,4 +415,6 @@ class AppAnimations { static const String ambulance = '$lottieBasePath/ambulance.json'; static const String ambulanceAlert = '$lottieBasePath/ambulance_alert.json'; static const String rrtAmbulance = '$lottieBasePath/rrt_ambulance.json'; + + static const String hourGlass = '$lottieBasePath/HourGlass.json'; } diff --git a/lib/features/book_appointments/book_appointments_view_model.dart b/lib/features/book_appointments/book_appointments_view_model.dart index 6f2092f9..647b8632 100644 --- a/lib/features/book_appointments/book_appointments_view_model.dart +++ b/lib/features/book_appointments/book_appointments_view_model.dart @@ -402,7 +402,11 @@ class BookAppointmentsViewModel extends ChangeNotifier { refreshDoctorsList() { setIsDoctorsListLoading(true); - getDoctorsList(isNearest: isNearestAppointmentSelected); + if(selectedClinic.clinicID == 17) { + getDentalChiefComplaintDoctorsList(projectID: currentlySelectedHospitalFromRegionFlow != null ? int.parse(currentlySelectedHospitalFromRegionFlow!) : 0); + } else { + getDoctorsList(isNearest: isNearestAppointmentSelected); + } } setIsNearestAppointmentSelected(bool isNearestAppointmentSelected) { @@ -861,8 +865,8 @@ class BookAppointmentsViewModel extends ChangeNotifier { } initialSlotDuration = apiResponse.data["InitialSlotDuration"]; freeSlotsResponse = apiResponse.data['FreeTimeSlots']; - // isWaitingAppointmentAvailable = apiResponse.data["IsAllowToBookWaitingAppointment"]; - isWaitingAppointmentAvailable = true; + isWaitingAppointmentAvailable = apiResponse.data["IsAllowToBookWaitingAppointment"]; + // isWaitingAppointmentAvailable = true; freeSlotsResponse.forEach((element) { // date = (isLiveCareSchedule != null && isLiveCareSchedule) @@ -1044,7 +1048,8 @@ class BookAppointmentsViewModel extends ChangeNotifier { ); LoaderBottomSheet.showLoader( - loadingText: LocaleKeys.reschedulingAppo.tr(context: navigationService.navigatorKey.currentContext!), + // loadingText: LocaleKeys.reschedulingAppo.tr(context: navigationService.navigatorKey.currentContext!), + loadingText: LocaleKeys.loadingText.tr(context: navigationService.navigatorKey.currentContext!), ); await cancelAppointment(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel).then((val) async { LoaderBottomSheet.hideLoader(); @@ -1466,7 +1471,10 @@ class BookAppointmentsViewModel extends ChangeNotifier { } Future getDentalChiefComplaintDoctorsList({int projectID = 0, Function(dynamic)? onSuccess, Function(String)? onError}) async { + setIsNearestAppointmentSelected(false); doctorsList.clear(); + notifyListeners(); + projectID = currentlySelectedHospitalFromRegionFlow != null ? int.parse(currentlySelectedHospitalFromRegionFlow!) : projectID; final result = await bookAppointmentsRepo.getDentalChiefComplaintDoctorsList(projectID, selectedChiefComplaintID); @@ -1485,6 +1493,7 @@ class BookAppointmentsViewModel extends ChangeNotifier { // clearSearchFilters(); // getFiltersFromDoctorList(); _groupDoctorsList(); + setIsNearestAppointmentSelected(isNearestAppointmentSelected); notifyListeners(); if (onSuccess != null) { onSuccess(apiResponse); diff --git a/lib/features/emergency_services/emergency_services_view_model.dart b/lib/features/emergency_services/emergency_services_view_model.dart index bfe226f8..c8a16455 100644 --- a/lib/features/emergency_services/emergency_services_view_model.dart +++ b/lib/features/emergency_services/emergency_services_view_model.dart @@ -713,7 +713,7 @@ class EmergencyServicesViewModel extends ChangeNotifier { appointments = response.data; if (appointments?.isEmpty == true) { haveAnAppointment = false; - dialogService.showErrorBottomSheet(message: "Unable to Fetch Appointment"); + dialogService.showErrorBottomSheet(message: LocaleKeys.NoBookedAppointments.tr()); } notifyListeners(); }); diff --git a/lib/features/lab/lab_repo.dart b/lib/features/lab/lab_repo.dart index 08946e97..82468ada 100644 --- a/lib/features/lab/lab_repo.dart +++ b/lib/features/lab/lab_repo.dart @@ -26,9 +26,9 @@ abstract class LabRepo { Future>> getLabResultsByAppointmentNo({required num appointmentNo, required num projectID, required num clinicID}); - Future>> getPatientAiOverViewLabOrders(var payload); + Future>> getPatientAiOverViewLabOrders({required int langId, required dynamic payload}); - Future>> getPatientAiOverViewLabOrder(var payload); + Future>> getPatientAiOverViewLabOrder(var payloa); } class LabRepoImp implements LabRepo { @@ -358,7 +358,7 @@ class LabRepoImp implements LabRepo { } @override - Future>> getPatientAiOverViewLabOrders(var labOrder) async { + Future>> getPatientAiOverViewLabOrders({required int langId, required dynamic payload}) async { try { GenericApiModel? apiResponse; Failure? failure; @@ -372,7 +372,7 @@ class LabRepoImp implements LabRepo { 'X-API-KEY': '9d9d2ac4c1fc302299dbb0fbb1b7fea1', 'accept': 'application/json', }, - body: {"lab_results": labOrder}, + body: {"lab_results": payload, "language_id": langId}, onFailure: (error, statusCode, {messageStatus, failureType}) { failure = failureType; }, diff --git a/lib/features/lab/lab_view_model.dart b/lib/features/lab/lab_view_model.dart index 6835badb..09caf578 100644 --- a/lib/features/lab/lab_view_model.dart +++ b/lib/features/lab/lab_view_model.dart @@ -447,20 +447,19 @@ class LabViewModel extends ChangeNotifier { minY = resultValue; } // if (highRefrenceValue < double.parse(element.referenceHigh ?? "0.0")) { - highRefrenceValue = double.parse(element.referenceHigh ?? "0.0"); - flagForHighReferenceRange = element.calculatedResultFlag; + highRefrenceValue = double.parse(element.referenceHigh ?? "0.0"); + flagForHighReferenceRange = element.calculatedResultFlag; // } // if (lowRefenceValue > double.parse(element.referenceLow ?? "0.0")) { - lowRefenceValue = double.parse(element.referenceLow ?? "0.0"); - flagForLowReferenceRange = element.calculatedResultFlag; + lowRefenceValue = double.parse(element.referenceLow ?? "0.0"); + flagForLowReferenceRange = element.calculatedResultFlag; // } - if(double.parse(element.referenceHigh ?? "0.0") == 0 ){ + if (double.parse(element.referenceHigh ?? "0.0") == 0) { highRefrenceValue = double.negativeInfinity; } - - if(double.parse(element.referenceLow ?? "0.0") == 0 ){ + if (double.parse(element.referenceLow ?? "0.0") == 0) { lowRefenceValue = double.negativeInfinity; } @@ -473,18 +472,16 @@ class LabViewModel extends ChangeNotifier { time: DateUtil.convertStringToDate(element.verifiedOnDateTime), referenceValue: element.calculatedResultFlag ?? "", )); - - } catch (e) { - } + } catch (e) {} }); if (flagForLowReferenceRange == null && flagForHighReferenceRange == null) { highRefrenceValue = maxY; lowRefenceValue = minY; } // - if (lowRefenceValue != double.negativeInfinity &&minY > lowRefenceValue) { + if (lowRefenceValue != double.negativeInfinity && minY > lowRefenceValue) { minY = lowRefenceValue - getInterval(); - }else if (highRefrenceValue != double.negativeInfinity && minY > highRefrenceValue) { + } else if (highRefrenceValue != double.negativeInfinity && minY > highRefrenceValue) { minY = highRefrenceValue - getInterval(); } @@ -494,17 +491,16 @@ class LabViewModel extends ChangeNotifier { lowTransformedReferenceValue = double.parse(transformValueInRange(lowRefenceValue, flagForLowReferenceRange ?? "").toStringAsFixed(1)); this.highRefrenceValue = double.parse(highRefrenceValue.toStringAsFixed(2)); this.lowRefenceValue = double.parse(lowRefenceValue.toStringAsFixed(2)); - if(highRefrenceValue != double.negativeInfinity &&maxY=1.0 && maxX < 5.0) return .3; - if(maxX >=5.0 && maxX < 10.0) return 1.5; - if(maxX >=10.0 && maxX < 50.0) return 2.5; - if(maxX >=50.0 && maxX < 100.0) return 5; - if(maxX >=100.0 && maxX < 200.0) return 10; + if (maxX < 1) return .2; + if (maxX >= 1.0 && maxX < 5.0) return .3; + if (maxX >= 5.0 && maxX < 10.0) return 1.5; + if (maxX >= 10.0 && maxX < 50.0) return 2.5; + if (maxX >= 50.0 && maxX < 100.0) return 5; + if (maxX >= 100.0 && maxX < 200.0) return 10; return 15; } @@ -617,7 +614,7 @@ class LabViewModel extends ChangeNotifier { rangeStart = 40.0; rangeEnd = 59.0; break; - // throw ArgumentError('Invalid flag: $flag'); + // throw ArgumentError('Invalid flag: $flag'); } // Clamp input value to 0-100 and map it to the range bounds @@ -845,9 +842,7 @@ class LabViewModel extends ChangeNotifier { notifyListeners(); } - Future getAiOverviewLabOrders({required PatientLabOrdersResponseModel labOrder, required String loadingText}) async { - // LoadingUtils.showFullScreenLoader(loadingText: "Loading and analysing your data,\nPlease be patient and let the AI do the magic. \nPlease be patient, This might take some time."); - // LoadingUtils.showFullScreenLoader(loadingText: loadingText); + Future getAiOverviewLabOrders({required int langId, required PatientLabOrdersResponseModel labOrder, required String loadingText}) async { isLabAIAnalysisNeedsToBeShown = true; notifyListeners(); @@ -875,7 +870,8 @@ class LabViewModel extends ChangeNotifier { } orderData["results"] = testResults; results.add(orderData); - final result = await labRepo.getPatientAiOverViewLabOrders(results); + + final result = await labRepo.getPatientAiOverViewLabOrders(payload: results, langId: langId); result.fold( (failure) async { LoaderBottomSheet.hideLoader(); @@ -903,7 +899,7 @@ class LabViewModel extends ChangeNotifier { // LoadingUtils.hideFullScreenLoader(); } - Future getAiOverviewSingleLabResult({required String langId, required LabResult recentLabResult, required String loadingText}) async { + Future getAiOverviewSingleLabResult({required int langId, required LabResult recentLabResult, required String loadingText}) async { LoaderBottomSheet.showLoader( loadingText: loadingText, showCloseButton: true, diff --git a/lib/features/radiology/radiology_repo.dart b/lib/features/radiology/radiology_repo.dart index a6ea293e..30b078ef 100644 --- a/lib/features/radiology/radiology_repo.dart +++ b/lib/features/radiology/radiology_repo.dart @@ -19,7 +19,7 @@ abstract class RadiologyRepo { Future>>> getPatientRadiologyOrderByAppointment({required num appointmentNo, required num projectID}); - Future>> getRadiologyAiAnalysis({required String reportData}); + Future>> getRadiologyAiAnalysis({required String reportData, required int langId,}); } class RadiologyRepoImp implements RadiologyRepo { @@ -223,9 +223,10 @@ class RadiologyRepoImp implements RadiologyRepo { } @override - Future>> getRadiologyAiAnalysis({required String reportData}) async { + Future>> getRadiologyAiAnalysis({required String reportData, required int langId}) async { Map payload = { "text": reportData, + "language_id": langId }; try { diff --git a/lib/features/radiology/radiology_view_model.dart b/lib/features/radiology/radiology_view_model.dart index c8385870..7386a5a0 100644 --- a/lib/features/radiology/radiology_view_model.dart +++ b/lib/features/radiology/radiology_view_model.dart @@ -127,8 +127,7 @@ class RadiologyViewModel extends ChangeNotifier { ); } - Future getRadiologyImage( - {required PatientRadiologyResponseModel patientRadiologyResponseModel, Function(dynamic)? onSuccess, Function(String)? onError}) async { + Future getRadiologyImage({required PatientRadiologyResponseModel patientRadiologyResponseModel, Function(dynamic)? onSuccess, Function(String)? onError}) async { final result = await radiologyRepo.getRadiologyImage(patientRadiologyResponseModel: patientRadiologyResponseModel); result.fold( @@ -149,12 +148,8 @@ class RadiologyViewModel extends ChangeNotifier { } Future getRadiologyPDF( - {required PatientRadiologyResponseModel patientRadiologyResponseModel, - required AuthenticatedUser authenticatedUser, - Function(dynamic)? onSuccess, - Function(String)? onError}) async { - final result = - await radiologyRepo.getRadiologyReportPDF(patientRadiologyResponseModel: patientRadiologyResponseModel, authenticatedUser: authenticatedUser); + {required PatientRadiologyResponseModel patientRadiologyResponseModel, required AuthenticatedUser authenticatedUser, Function(dynamic)? onSuccess, Function(String)? onError}) async { + final result = await radiologyRepo.getRadiologyReportPDF(patientRadiologyResponseModel: patientRadiologyResponseModel, authenticatedUser: authenticatedUser); result.fold( (failure) async => await errorHandlerService.handleError( @@ -229,7 +224,7 @@ class RadiologyViewModel extends ChangeNotifier { notifyListeners(); } - Future getRadiologyAiAnalysis({required String reportData, required String loadingText}) async { + Future getRadiologyAiAnalysis({required String reportData, required String loadingText, required int langId}) async { LoaderBottomSheet.showLoader( loadingText: loadingText, showCloseButton: true, @@ -238,7 +233,7 @@ class RadiologyViewModel extends ChangeNotifier { }, ); - final result = await radiologyRepo.getRadiologyAiAnalysis(reportData: reportData); + final result = await radiologyRepo.getRadiologyAiAnalysis(reportData: reportData, langId: langId); result.fold( (failure) async { diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart index 2a999ae7..29656b23 100644 --- a/lib/generated/locale_keys.g.dart +++ b/lib/generated/locale_keys.g.dart @@ -1681,5 +1681,7 @@ abstract class LocaleKeys { static const openFiles = 'openFiles'; static const generateAiAnalysisRadResult = 'generateAiAnalysisRadResult'; static const grantLocationPermission = 'grantLocationPermission'; + static const NoBookedAppointments = 'NoBookedAppointments'; + static const aiDisclaimerRad = 'aiDisclaimerRad'; } diff --git a/lib/main.dart b/lib/main.dart index c44a3a45..e9b599c9 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -10,6 +10,7 @@ import 'package:flutter/services.dart'; import 'package:hmg_patient_app_new/core/app_state.dart'; import 'package:hmg_patient_app_new/core/dependencies.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart'; +import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/features/ask_doctor/ask_doctor_view_model.dart'; import 'package:hmg_patient_app_new/features/authentication/authentication_view_model.dart'; import 'package:hmg_patient_app_new/features/blood_donation/blood_donation_view_model.dart'; @@ -50,6 +51,7 @@ import 'package:hmg_patient_app_new/routes/app_routes.dart'; import 'package:hmg_patient_app_new/services/logger_service.dart'; import 'package:hmg_patient_app_new/services/navigation_service.dart'; import 'package:hmg_patient_app_new/theme/app_theme.dart'; +import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/widgets/date_range_selector/viewmodel/date_range_view_model.dart' show DateRangeSelectorRangeViewModel; import 'package:provider/provider.dart'; import 'package:provider/single_child_widget.dart'; diff --git a/lib/presentation/appointments/appointment_details_page.dart b/lib/presentation/appointments/appointment_details_page.dart index 10f616e8..31cd5403 100644 --- a/lib/presentation/appointments/appointment_details_page.dart +++ b/lib/presentation/appointments/appointment_details_page.dart @@ -393,8 +393,8 @@ class _AppointmentDetailsPageState extends State { ), const Spacer(), Switch( - // activeThumbColor: AppColors.successColor, - activeTrackColor: AppColors.successColor.withValues(alpha: .15), + activeThumbColor: AppColors.successColor, + // activeTrackColor: AppColors.successColor.withValues(alpha: .15), value: widget.patientAppointmentHistoryResponseModel.hasReminder!, onChanged: (newValue) async { CalenderUtilsNew calender = CalenderUtilsNew.instance; @@ -612,7 +612,7 @@ class _AppointmentDetailsPageState extends State { isLocked: false, ).toShimmer2() : MedicalFileCard( - label: !((myAppointmentsVM.appointmentRatedResponseModel!).isAppointmentRated ?? true) + label: !((myAppointmentsVM.appointmentRatedResponseModel!).isAllowedToRate ?? false) ? LocaleKeys.ratingSubmitted.tr(context: context) : LocaleKeys.doctorRatingAppointment.tr(context: context), textColor: AppColors.blackColor, @@ -620,9 +620,9 @@ class _AppointmentDetailsPageState extends State { svgIcon: AppAssets.appointmentRatingIcon, isLargeText: true, iconSize: 36.w, - isLocked: !(myAppointmentsVM.appointmentRatedResponseModel!.isAppointmentRated ?? true), + isLocked: !(myAppointmentsVM.appointmentRatedResponseModel!.isAllowedToRate ?? false), ).onPress(() { - if(!(myAppointmentsVM.appointmentRatedResponseModel!.isAppointmentRated ?? true)) { + if ((myAppointmentsVM.appointmentRatedResponseModel!.isAllowedToRate ?? true)) { showCommonBottomSheetWithoutHeight( context, title: LocaleKeys.doctorRating.tr(context: context), diff --git a/lib/presentation/appointments/appointment_queue_page.dart b/lib/presentation/appointments/appointment_queue_page.dart index cc1c7fd1..35403dc6 100644 --- a/lib/presentation/appointments/appointment_queue_page.dart +++ b/lib/presentation/appointments/appointment_queue_page.dart @@ -15,6 +15,7 @@ import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart'; import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart'; import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart'; +import 'package:lottie/lottie.dart'; import 'package:provider/provider.dart'; class AppointmentQueuePage extends StatelessWidget { @@ -32,13 +33,14 @@ class AppointmentQueuePage extends StatelessWidget { children: [ Expanded( child: CollapsingListView( - title: LocaleKeys.queueing.tr(context: context), + title: LocaleKeys.queueing.tr(context: context), child: RefreshIndicator( color: AppColors.primaryRedColor, onRefresh: () async { await myAppointmentsVM.getPatientAppointmentQueueDetails(); }, child: SingleChildScrollView( + physics: const AlwaysScrollableScrollPhysics(), child: Padding( padding: EdgeInsets.all(24.0), child: Column( @@ -59,13 +61,21 @@ class AppointmentQueuePage extends StatelessWidget { children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, children: [ AppCustomChipWidget( labelText: myAppointmentsVM.currentQueueStatus == 0 ? LocaleKeys.inQueue.tr(context: context) : LocaleKeys.yourTurn.tr(context: context), backgroundColor: Utils.getCardBorderColor(myAppointmentsVM.currentQueueStatus).withValues(alpha: 0.20), textColor: Utils.getCardBorderColor(myAppointmentsVM.currentQueueStatus), ), - Utils.buildSvgWithAssets(icon: AppAssets.waiting_icon, width: 24.h, height: 24.h), + Container( + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.greyColor, + borderRadius: 10.h, + hasShadow: false, + ), + padding: EdgeInsets.all(6.h), + child: Lottie.asset(AppAnimations.hourGlass, repeat: true, reverse: false, frameRate: FrameRate(60), width: 40.h, height: 40.h, fit: BoxFit.fill)), ], ).toShimmer2(isShow: myAppointmentsVM.isAppointmentQueueDetailsLoading), SizedBox(height: 10.h), @@ -189,9 +199,9 @@ class AppointmentQueuePage extends StatelessWidget { ], ), ), + ), ), ), - ), ), Container( decoration: RoundedRectangleBorder().toSmoothCornerDecoration( diff --git a/lib/presentation/appointments/widgets/appointment_card.dart b/lib/presentation/appointments/widgets/appointment_card.dart index b7ffc826..fb24f689 100644 --- a/lib/presentation/appointments/widgets/appointment_card.dart +++ b/lib/presentation/appointments/widgets/appointment_card.dart @@ -243,42 +243,123 @@ class AppointmentCard extends StatelessWidget { (patientAppointmentHistoryResponseModel.isExecludeDoctor ?? false) || !Utils.isClinicAllowedForRebook(patientAppointmentHistoryResponseModel.clinicID ?? 0))) && AppointmentType.isArrived(patientAppointmentHistoryResponseModel)) { - return CustomButton( - text: isFromMedicalReport ? LocaleKeys.selectAppointment.tr(context: context) : LocaleKeys.viewDetails.tr(context: context), - onPressed: () { - if (isFromMedicalReport) { - if (isForFeedback) { - contactUsViewModel!.setPatientFeedbackSelectedAppointment(patientAppointmentHistoryResponseModel); + if (((patientAppointmentHistoryResponseModel.isLiveCareAppointment ?? false) && + DateTime.now().difference(DateUtil.convertStringToDate(patientAppointmentHistoryResponseModel.appointmentDate)).inDays <= 15)) { + return Row( + children: [ + Expanded( + flex: 6, + child: CustomButton( + text: LocaleKeys.askDoctor.tr(context: context), + onPressed: () async { + LoaderBottomSheet.showLoader(loadingText: LocaleKeys.checkingDoctorAvailability.tr(context: context)); + await myAppointmentsViewModel.isDoctorAvailable( + projectID: patientAppointmentHistoryResponseModel.projectID, + doctorId: patientAppointmentHistoryResponseModel.doctorID, + clinicId: patientAppointmentHistoryResponseModel.clinicID, + onSuccess: (value) async { + if (value) { + await myAppointmentsViewModel.getAskDoctorRequestTypes(onSuccess: (val) { + LoaderBottomSheet.hideLoader(); + showCommonBottomSheetWithoutHeight( + context, + title: LocaleKeys.askDoctor.tr(context: context), + child: AskDoctorRequestTypeSelect( + askDoctorRequestTypeList: myAppointmentsViewModel.askDoctorRequestTypeList, + myAppointmentsViewModel: myAppointmentsViewModel, + patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel, + ), + callBackFunc: () {}, + isFullScreen: false, + isCloseButtonVisible: true, + ); + }); + } else { + print("Doctor is not available"); + } + }); + }, + backgroundColor: AppColors.secondaryLightRedColor, + borderColor: AppColors.secondaryLightRedColor, + textColor: AppColors.primaryRedColor, + fontSize: (isFoldable || isTablet) ? 12.f : 14.f, + fontWeight: FontWeight.w600, + borderRadius: 12.r, + padding: EdgeInsets.symmetric(horizontal: 10.w), + // height: isTablet || isFoldable ? 46.h : 40.h, + height: 40.h, + icon: AppAssets.ask_doctor_icon, + iconColor: AppColors.primaryRedColor, + iconSize: 16.h, + ), + ), + SizedBox(width: 8.h), + Expanded( + flex: 1, + child: Container( + height: (isFoldable || isTablet) ? 50.h : 40.h, + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.textColor, + borderRadius: 10.h, + side: BorderSide( + color: AppColors.textColor, + width: 1.2, + ), + ), + child: Transform.flip( + flipX: appState.isArabic(), + child: Utils.buildSvgWithAssets( + icon: AppAssets.forward_arrow_icon, + iconColor: AppColors.whiteColor, + width: 24.w, + height: 24.h, + fit: BoxFit.contain, + ), + ), + ).toShimmer2(isShow: isLoading).onPress(() { + _goToDetails(context); + }), + ), + ], + ); + } else { + return CustomButton( + text: isFromMedicalReport ? LocaleKeys.selectAppointment.tr(context: context) : LocaleKeys.viewDetails.tr(context: context), + onPressed: () { + if (isFromMedicalReport) { + if (isForFeedback) { + contactUsViewModel!.setPatientFeedbackSelectedAppointment(patientAppointmentHistoryResponseModel); + } else { + medicalFileViewModel!.setSelectedMedicalReportAppointment(patientAppointmentHistoryResponseModel); + } + Navigator.pop(context, false); } else { - medicalFileViewModel!.setSelectedMedicalReportAppointment(patientAppointmentHistoryResponseModel); + Navigator.of(context) + .push( + CustomPageRoute( + page: AppointmentDetailsPage(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel), + ), + ) + .then((_) { + myAppointmentsViewModel.initAppointmentsViewModel(); + myAppointmentsViewModel.getPatientAppointments(true, false); + }); } - Navigator.pop(context, false); - } else { - Navigator.of(context) - .push( - CustomPageRoute( - page: AppointmentDetailsPage(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel), - ), - ) - .then((_) { - myAppointmentsViewModel.initAppointmentsViewModel(); - myAppointmentsViewModel.getPatientAppointments(true, false); - }); - } - }, - backgroundColor: AppColors.secondaryLightRedColor, - borderColor: AppColors.secondaryLightRedColor, - textColor: AppColors.primaryRedColor, - fontSize: (isFoldable || isTablet) ? 12.f : 14.f, - fontWeight: FontWeight.w600, - borderRadius: 12.r, - padding: EdgeInsets.symmetric(horizontal: 10.w), - // height: isTablet || isFoldable ? 46.h : 40.h, - height: 40.h, - icon: isFromMedicalReport ? AppAssets.checkmark_icon : null, - iconColor: AppColors.primaryRedColor, - iconSize: 16.h, - ); + }, + backgroundColor: AppColors.secondaryLightRedColor, + borderColor: AppColors.secondaryLightRedColor, + textColor: AppColors.primaryRedColor, + fontSize: (isFoldable || isTablet) ? 12.f : 14.f, + fontWeight: FontWeight.w600, + borderRadius: 12.r, + padding: EdgeInsets.symmetric(horizontal: 10.w), + // height: isTablet || isFoldable ? 46.h : 40.h, + height: 40.h, + icon: isFromMedicalReport ? AppAssets.checkmark_icon : null, + iconColor: AppColors.primaryRedColor, + iconSize: 16.h, + ); + } } else { if (isFromMedicalReport) { if (isForEyeMeasurements) { @@ -309,7 +390,6 @@ class AppointmentCard extends StatelessWidget { ); } } - return Row( children: [ Expanded( diff --git a/lib/presentation/appointments/widgets/appointment_checkin_bottom_sheet.dart b/lib/presentation/appointments/widgets/appointment_checkin_bottom_sheet.dart index da50b3c7..817ebfa0 100644 --- a/lib/presentation/appointments/widgets/appointment_checkin_bottom_sheet.dart +++ b/lib/presentation/appointments/widgets/appointment_checkin_bottom_sheet.dart @@ -168,7 +168,7 @@ class AppointmentCheckinBottomSheet extends StatelessWidget { // page: AppointmentQueuePage(), // ), // ); - }, isFullScreen: false); + }, isFullScreen: false, isAutoDismiss: true, isCloseButtonVisible: false); }, onError: (error) { LoaderBottomSheet.hideLoader(); diff --git a/lib/presentation/book_appointment/livecare/immediate_livecare_payment_details.dart b/lib/presentation/book_appointment/livecare/immediate_livecare_payment_details.dart index 5f44448a..1228e1e4 100644 --- a/lib/presentation/book_appointment/livecare/immediate_livecare_payment_details.dart +++ b/lib/presentation/book_appointment/livecare/immediate_livecare_payment_details.dart @@ -215,8 +215,8 @@ class ImmediateLiveCarePaymentDetails extends StatelessWidget { children: [ LocaleKeys.amountBeforeTax.tr(context: context).toText14(isBold: true), Utils.getPaymentAmountWithSymbol((immediateLiveCareVM.liveCareImmediateAppointmentFeesList.amount ?? "").toText16(isBold: true, isEnglishOnly: true), AppColors.blackColor, 13, - isSaudiCurrency: immediateLiveCareVM.liveCareImmediateAppointmentFeesList.currency!.toLowerCase() == "sar" || - immediateLiveCareVM.liveCareImmediateAppointmentFeesList.currency!.toLowerCase() == "ريال"), + isSaudiCurrency: (immediateLiveCareVM.liveCareImmediateAppointmentFeesList.currency ?? "sar").toLowerCase() == "sar" || + (immediateLiveCareVM.liveCareImmediateAppointmentFeesList.currency ?? "ريال").toLowerCase() == "ريال"), ], ).paddingSymmetrical(24.h, 0.h), Row( @@ -224,9 +224,9 @@ class ImmediateLiveCarePaymentDetails extends StatelessWidget { children: [ LocaleKeys.vat15.tr(context: context).toText14(isBold: true, color: AppColors.greyTextColor), Utils.getPaymentAmountWithSymbol( - immediateLiveCareVM.liveCareImmediateAppointmentFeesList.tax!.toText14(isBold: true, color: AppColors.greyTextColor, isEnglishOnly: true), AppColors.greyTextColor, 13, - isSaudiCurrency: (immediateLiveCareVM.liveCareImmediateAppointmentFeesList.currency!.toLowerCase() == "sar" || - immediateLiveCareVM.liveCareImmediateAppointmentFeesList.currency!.toLowerCase() == "ريال")), + (immediateLiveCareVM.liveCareImmediateAppointmentFeesList.tax ?? "0.0").toText14(isBold: true, color: AppColors.greyTextColor, isEnglishOnly: true), AppColors.greyTextColor, 13, + isSaudiCurrency: ((immediateLiveCareVM.liveCareImmediateAppointmentFeesList.currency ?? "sar").toLowerCase() == "sar" || + (immediateLiveCareVM.liveCareImmediateAppointmentFeesList.currency ?? "ريال").toLowerCase() == "ريال")), ], ).paddingSymmetrical(24.h, 0.h), SizedBox(height: 17.h), @@ -234,9 +234,9 @@ class ImmediateLiveCarePaymentDetails extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ SizedBox(width: 200.h, child: Utils.getPaymentMethods()), - Utils.getPaymentAmountWithSymbol(immediateLiveCareVM.liveCareImmediateAppointmentFeesList.total!.toText24(isBold: true, isEnglishOnly: true), AppColors.blackColor, 17, - isSaudiCurrency: (immediateLiveCareVM.liveCareImmediateAppointmentFeesList.currency!.toLowerCase() == "sar" || - immediateLiveCareVM.liveCareImmediateAppointmentFeesList.currency!.toLowerCase() == "ريال")), + Utils.getPaymentAmountWithSymbol((immediateLiveCareVM.liveCareImmediateAppointmentFeesList.total ?? "0.0").toText24(isBold: true, isEnglishOnly: true), AppColors.blackColor, 17, + isSaudiCurrency: ((immediateLiveCareVM.liveCareImmediateAppointmentFeesList.currency ?? "sar").toLowerCase() == "sar" || + (immediateLiveCareVM.liveCareImmediateAppointmentFeesList.currency ?? "ريال").toLowerCase() == "ريال")), ], ).paddingSymmetrical(24.h, 0.h), (immediateLiveCareVM.liveCareImmediateAppointmentFeesList.total == "0" || immediateLiveCareVM.liveCareImmediateAppointmentFeesList.total == "0.0") diff --git a/lib/presentation/book_appointment/livecare/immediate_livecare_payment_page.dart b/lib/presentation/book_appointment/livecare/immediate_livecare_payment_page.dart index 0341796f..031bb0b8 100644 --- a/lib/presentation/book_appointment/livecare/immediate_livecare_payment_page.dart +++ b/lib/presentation/book_appointment/livecare/immediate_livecare_payment_page.dart @@ -264,7 +264,7 @@ class _ImmediateLiveCarePaymentPageState extends State( valueListenable: immediateLiveCareVM.durationNotifier, diff --git a/lib/presentation/book_appointment/review_appointment_page.dart b/lib/presentation/book_appointment/review_appointment_page.dart index a3138dff..689e6cf3 100644 --- a/lib/presentation/book_appointment/review_appointment_page.dart +++ b/lib/presentation/book_appointment/review_appointment_page.dart @@ -317,7 +317,8 @@ class _ReviewAppointmentPageState extends State { void initiateBookAppointment() async { // LoadingUtils.showFullScreenLoader(barrierDismissible: true, isSuccessDialog: false, loadingText: bookAppointmentsViewModel.isPatientRescheduleAppointment ? LocaleKeys.reschedulingAppo.tr(context: context) : LocaleKeys.bookingYourAppointment.tr(context: context)); - LoaderBottomSheet.showLoader(loadingText: bookAppointmentsViewModel.isPatientRescheduleAppointment ? LocaleKeys.reschedulingAppo.tr(context: context) : LocaleKeys.bookingYourAppointment.tr(context: context)); + // LoaderBottomSheet.showLoader(loadingText: bookAppointmentsViewModel.isPatientRescheduleAppointment ? LocaleKeys.reschedulingAppo.tr(context: context) : LocaleKeys.bookingYourAppointment.tr(context: context)); + LoaderBottomSheet.showLoader(loadingText: LocaleKeys.loadingText.tr(context: context)); myAppointmentsViewModel.setIsAppointmentDataToBeLoaded(true); if (bookAppointmentsViewModel.isLiveCareSchedule) { diff --git a/lib/presentation/book_appointment/select_clinic_page.dart b/lib/presentation/book_appointment/select_clinic_page.dart index b08564ca..e617194e 100644 --- a/lib/presentation/book_appointment/select_clinic_page.dart +++ b/lib/presentation/book_appointment/select_clinic_page.dart @@ -1079,7 +1079,8 @@ class _SelectClinicPageState extends State { // } var bottomSheetType = RegionBottomSheetType.FOR_CLINIIC; if (clinic.clinicID == 17) { - regionalViewModel.setBottomSheetState(AppointmentViaRegionState.HOSPITAL_SELECTION); + // regionalViewModel.setBottomSheetState(AppointmentViaRegionState.HOSPITAL_SELECTION); + // bottomSheetType = RegionBottomSheetType.REGION_FOR_DENTAL_AND_LASER; bottomSheetType = RegionBottomSheetType.REGION_FOR_DENTAL_AND_LASER; } // if (clinic.clinicID == 253) { diff --git a/lib/presentation/emergency_services/nearest_er_page.dart b/lib/presentation/emergency_services/nearest_er_page.dart index 0ea3ab8f..ea9a1517 100644 --- a/lib/presentation/emergency_services/nearest_er_page.dart +++ b/lib/presentation/emergency_services/nearest_er_page.dart @@ -44,7 +44,7 @@ class _NearestErPageState extends State { children: [ TextInputWidget( labelText: LocaleKeys.search.tr(), - hintText: 'Type any facility name', + hintText: '', controller: searchText, onChange: (value) { debouncer.run(() { diff --git a/lib/presentation/emergency_services/widgets/nearestERItem.dart b/lib/presentation/emergency_services/widgets/nearestERItem.dart index 5579fd75..58e89421 100644 --- a/lib/presentation/emergency_services/widgets/nearestERItem.dart +++ b/lib/presentation/emergency_services/widgets/nearestERItem.dart @@ -59,7 +59,7 @@ class NearestERItem extends StatelessWidget { Expanded( child: (nearestERItem.projectName?.toText16( color: AppColors.textColor, - weight: FontWeight.w600, + isBold: true ) ?? SizedBox.shrink()).toShimmer2(isShow: isLoading), ), @@ -84,7 +84,7 @@ class NearestERItem extends StatelessWidget { Directionality( textDirection: ui.TextDirection.ltr, child: AppCustomChipWidget( - labelText: "Expected waiting time: ${nearestERItem.getTime()} mins", + labelText: "${LocaleKeys.waitingTime.tr(context: context)} ${nearestERItem.getTime()} ${LocaleKeys.mins.tr(context: context)}", icon: AppAssets.waiting_time_clock, iconHasColor: false, labelPadding: EdgeInsetsDirectional.only(start: 4.h, end: 0.h), @@ -109,14 +109,14 @@ class NearestERItem extends StatelessWidget { borderColor: AppColors.secondaryLightRedColor, textColor: AppColors.primaryRedColor, iconColor: AppColors.primaryRedColor, - height: 40.h, + height: 46.h, fontSize: 14.f, isBold: true, ).toShimmer2(isShow: isLoading), ), SizedBox(width: 8.h), SizedBox( - height: 40.h, + height: 46.h, width: 40.h, child: CustomButton( text: '', @@ -124,12 +124,11 @@ class NearestERItem extends StatelessWidget { icon: AppAssets.call_fill, onPressed: () { context.read().openDialer( nearestERItem.phonenumber??""); - }, backgroundColor: AppColors.greyColor, iconColor: AppColors.textColor, borderColor: AppColors.greyColor, - height: 40.h, + height: 46.h, ).toShimmer2(isShow: isLoading), ), ], diff --git a/lib/presentation/habib_wallet/habib_wallet_page.dart b/lib/presentation/habib_wallet/habib_wallet_page.dart index 8e6230e8..fd5d17a1 100644 --- a/lib/presentation/habib_wallet/habib_wallet_page.dart +++ b/lib/presentation/habib_wallet/habib_wallet_page.dart @@ -74,7 +74,8 @@ class _HabibWalletState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ "${_appState.getAuthenticatedUser()!.firstName!} ${_appState.getAuthenticatedUser()!.lastName!}".toText19(isBold: true, color: Colors.white), - "MRN: ${_appState.getAuthenticatedUser()!.patientId!}".toText14(isBold: true, color: AppColors.greyTextColor, isEnglishOnly: true), + "${LocaleKeys.fileno.tr(context: context)}: ${_appState.getAuthenticatedUser()!.patientId!}" + .toText14(isBold: true, color: AppColors.greyTextColor, isEnglishOnly: true), ], ).expanded, Utils.buildSvgWithAssets(icon: AppAssets.habiblogo, width: 24.h, height: 24.h, applyThemeColor: false), @@ -84,8 +85,15 @@ class _HabibWalletState extends State { LocaleKeys.balanceAmount.tr(context: context).toText14(isBold: true, color: Colors.white), SizedBox(height: 4.h), Consumer(builder: (context, habibWalletVM, child) { - return Utils.getPaymentAmountWithSymbol2(num.parse(NumberFormat.decimalPattern().format(habibWalletVM.habibWalletAmount)), - textColor: Colors.white, iconColor: Colors.white, iconSize: 16, isExpanded: false) + return Utils.getPaymentAmountWithSymbol2( + num.parse( + NumberFormat.decimalPattern().format(habibWalletVM.habibWalletAmount), + ), + textColor: Colors.white, + iconColor: Colors.white, + iconSize: 16, + isExpanded: false, + letterSpacing: -1) .toShimmer2(isShow: habibWalletVM.isWalletAmountLoading, radius: 12.h, width: 80.h, height: 24.h); }), ], @@ -140,7 +148,7 @@ class _HabibWalletState extends State { children: [ Expanded(child: habibWalletVM.habibWalletBalanceList[index].projectDescription!.toText16(isBold: true, color: AppColors.textColor)), Utils.getPaymentAmountWithSymbol2(num.parse(NumberFormat.decimalPattern().format(habibWalletVM.habibWalletBalanceList[index].patientAdvanceBalanceAmount!)), - textColor: AppColors.textColor, iconColor: AppColors.textColor, iconSize: 18.h, isExpanded: false, fontSize: 28.f, fontWeight: FontWeight.w600,), + textColor: AppColors.textColor, iconColor: AppColors.textColor, iconSize: 18.h, isExpanded: false, fontSize: 28.f, fontWeight: FontWeight.w600, letterSpacing: -1), ], ).paddingSymmetrical(0, 12.h); }, diff --git a/lib/presentation/home/landing_page.dart b/lib/presentation/home/landing_page.dart index 414a2def..b6311c58 100644 --- a/lib/presentation/home/landing_page.dart +++ b/lib/presentation/home/landing_page.dart @@ -69,6 +69,7 @@ import 'package:hmg_patient_app_new/widgets/countdown_timer.dart'; import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart'; import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart'; import 'package:hmg_patient_app_new/widgets/routes/spring_page_route_builder.dart'; +import 'package:lottie/lottie.dart'; import 'package:provider/provider.dart'; import 'package:smooth_corner/smooth_corner.dart'; @@ -264,8 +265,8 @@ class _LandingPageState extends State { borderColor: AppColors.secondaryLightRedColor, textColor: AppColors.primaryRedColor, fontSize: 14.f, - fontWeight: FontWeight.w600, - borderRadius: 12.r, + fontWeight: FontWeight.w700, + borderRadius: 12.r, padding: EdgeInsets.fromLTRB(12.h, 0, 12.h, 0), height: 40.h, ), @@ -484,29 +485,37 @@ class _LandingPageState extends State { ) : SizedBox( height: 255.h + 20 + 30, // itemHeight + shadow padding (10 top + 10 bottom) + pagination dots space - child: Swiper( - itemCount: myAppointmentsVM.isMyAppointmentsLoading - ? 3 - : myAppointmentsVM.patientAppointmentsHistoryList.length < 3 - ? myAppointmentsVM.patientAppointmentsHistoryList.length - : 3, - layout: SwiperLayout.STACK, - loop: false, - itemWidth: MediaQuery.of(context).size.width - 48.h, - indicatorLayout: PageIndicatorLayout.COLOR, - axisDirection: appState.isArabic() ? AxisDirection.right : AxisDirection.left, - controller: _controller, - itemHeight: 255.h + 20, - // extra space for shadow - pagination: SwiperPagination( - alignment: Alignment.bottomCenter, - margin: EdgeInsets.only(top: 220.h + 20 + 8 + 24), - builder: DotSwiperPaginationBuilder(color: Color(0xffD9D9D9), activeColor: AppColors.blackBgColor), - ), - itemBuilder: (BuildContext context, int index) { - return Padding( - padding: const EdgeInsets.symmetric(vertical: 10), - child: getIndexSwiperCard(index), + child: Builder( + builder: (context) { + final int swiperItemCount = myAppointmentsVM.isMyAppointmentsLoading + ? 3 + : myAppointmentsVM.patientAppointmentsHistoryList.length < 3 + ? myAppointmentsVM.patientAppointmentsHistoryList.length + : 3; + final bool isArabic = appState.isArabic(); + return Swiper( + itemCount: swiperItemCount, + layout: SwiperLayout.STACK, + loop: false, + itemWidth: MediaQuery.of(context).size.width - 48.h, + indicatorLayout: PageIndicatorLayout.COLOR, + axisDirection: isArabic ? AxisDirection.right : AxisDirection.left, + controller: _controller, + index: isArabic ? swiperItemCount - 1 : 0, + itemHeight: 255.h + 20, + // extra space for shadow + pagination: SwiperPagination( + alignment: Alignment.bottomCenter, + margin: EdgeInsets.only(top: 220.h + 20 + 8 + 24), + builder: DotSwiperPaginationBuilder(color: Color(0xffD9D9D9), activeColor: AppColors.blackBgColor), + ), + itemBuilder: (BuildContext context, int index) { + final int actualIndex = isArabic ? (swiperItemCount - 1 - index) : index; + return Padding( + padding: const EdgeInsets.symmetric(vertical: 10), + child: getIndexSwiperCard(actualIndex), + ); + }, ); }, ), @@ -1005,17 +1014,21 @@ class _LandingPageState extends State { Widget _buildQueueHeader(int currentStatus) { return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, children: [ AppCustomChipWidget( labelText: currentStatus == 0 ? LocaleKeys.inQueue.tr() : LocaleKeys.yourTurn.tr(), backgroundColor: Utils.getCardBorderColor(currentStatus).withValues(alpha: 0.20), textColor: Utils.getCardBorderColor(currentStatus), ), - Utils.buildSvgWithAssets( - icon: AppAssets.waiting_icon, - width: 24.h, - height: 24.h, - ), + Container( + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.greyColor, + borderRadius: 10.h, + hasShadow: false, + ), + padding: EdgeInsets.all(6.h), + child: Lottie.asset(AppAnimations.hourGlass, repeat: true, reverse: false, frameRate: FrameRate(60), width: 40.h, height: 40.h, fit: BoxFit.fill)), ], ); } @@ -1149,6 +1162,7 @@ class _LandingPageState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( + crossAxisAlignment: CrossAxisAlignment.start, children: [ AppCustomChipWidget( labelText: liveCareData.stringCallStatus, @@ -1163,13 +1177,42 @@ class _LandingPageState extends State { false, ), ), + SizedBox(width: 8.w), + AppCustomChipWidget( + richText: ValueListenableBuilder( + valueListenable: immediateLiveCareViewModel.durationNotifier, + builder: (context, duration, child) { + final hours = duration.inHours.toString().padLeft(2, '0'); + final minutes = duration.inMinutes.remainder(60).toString().padLeft(2, '0'); + final seconds = duration.inSeconds.remainder(60).toString().padLeft(2, '0'); + return Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + '$hours:$minutes:$seconds'.toText10(isBold: true), + ], + ); + }, + ), + // labelText: DateUtil.formatDateToDate( + // DateUtil.convertStringToDate(liveCareData.arrivalTime), + // false, + // ), + ), ], ), - Utils.buildSvgWithAssets( - icon: AppAssets.waiting_icon, - width: 24.h, - height: 24.h, - ), + Container( + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.greyColor, + borderRadius: 10.h, + hasShadow: false, + ), + padding: EdgeInsets.all(6.h), + child: Lottie.asset(AppAnimations.hourGlass, repeat: true, reverse: false, frameRate: FrameRate(60), width: 40.h, height: 40.h, fit: BoxFit.fill)), + // Utils.buildSvgWithAssets( + // icon: AppAssets.waiting_icon, + // width: 24.h, + // height: 24.h, + // ), ], ); } diff --git a/lib/presentation/home/widgets/habib_wallet_card.dart b/lib/presentation/home/widgets/habib_wallet_card.dart index 2e1292b2..2a45e2f5 100644 --- a/lib/presentation/home/widgets/habib_wallet_card.dart +++ b/lib/presentation/home/widgets/habib_wallet_card.dart @@ -1,6 +1,8 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart'; +import 'package:hmg_patient_app_new/core/app_state.dart'; +import 'package:hmg_patient_app_new/core/dependencies.dart'; import 'package:hmg_patient_app_new/core/utils/size_utils.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; @@ -76,13 +78,14 @@ class HabibWalletCard extends StatelessWidget { // ], // ), SizedBox(height: 4.h), - Row( + Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Consumer(builder: (context, habibWalletVM, child) { - return Row( + Consumer(builder: (context, habibWalletVM, child) { + return Row( + mainAxisSize: MainAxisSize.max, + children: [ + Row( children: [ Utils.buildSvgWithAssets( icon: AppAssets.saudi_riyal_icon, @@ -98,58 +101,70 @@ class HabibWalletCard extends StatelessWidget { .toText32(isBold: true, isEnglishOnly: true) .toShimmer2(isShow: habibWalletVM.isWalletAmountLoading, radius: 12.h, width: 80.h, height: 40.h), ], - ); - }), - Padding( - padding: EdgeInsets.symmetric(horizontal: 35.h), - child: Row( - children: [ - LocaleKeys.viewDetails.tr(context: context).toText12(color: AppColors.primaryRedColor, isBold: true), - Icon(Icons.arrow_forward_ios, color: AppColors.primaryRedColor, size: 10.h), - ], - ).onPress(() { - Navigator.of(context).push( - CustomPageRoute( - page: HabibWalletPage(), - ), - ); - }), - ), - ], - ), - SizedBox( - // width: 50.h, - child: Utils.getPaymentMethods(), - ), + ), + Spacer(), + Utils.getPaymentMethods(), + ], + ); + }), ], ), SizedBox(height: 16.h), - CustomButton( - height: 40.h, - icon: AppAssets.recharge_icon, - iconColor: AppColors.infoColor, - iconSize: 24.h, - backgroundColor: AppColors.infoColor.withAlpha(15), - textColor: AppColors.infoColor, - text: LocaleKeys.recharge.tr(context: context), - borderWidth: 0.w, - fontWeight: FontWeight.w600, - borderColor: AppColors.infoColor.withAlpha(15), - padding: EdgeInsets.fromLTRB(4, 0, 12, 0), - fontSize: 14.f, - onPressed: () { - Navigator.of(context).push(CustomPageRoute(page: RechargeWalletPage())); - }, + Row( + children: [ + Expanded( + flex: 6, + child: CustomButton( + height: 40.h, + icon: AppAssets.recharge_icon, + iconColor: AppColors.infoColor, + iconSize: 24.h, + backgroundColor: AppColors.infoColor.withAlpha(15), + textColor: AppColors.infoColor, + text: LocaleKeys.recharge.tr(context: context), + borderWidth: 0.w, + fontWeight: FontWeight.w600, + borderColor: AppColors.infoColor.withAlpha(15), + padding: EdgeInsets.fromLTRB(4, 0, 12, 0), + fontSize: 14.f, + onPressed: () { + Navigator.of(context).push(CustomPageRoute(page: RechargeWalletPage())); + }, + ), + ), + SizedBox(width: 8.h), + Expanded( + flex: 1, + child: Container( + height: (isFoldable || isTablet) ? 50.h : 40.h, + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.textColor, + borderRadius: 10.h, + side: BorderSide( + color: AppColors.textColor, + width: 1.2, + ), + ), + child: Transform.flip( + flipX: getIt.get().isArabic(), + child: Utils.buildSvgWithAssets( + icon: AppAssets.forward_arrow_icon, + iconColor: AppColors.whiteColor, + width: 24.w, + height: 24.h, + fit: BoxFit.contain, + ), + ), + ).onPress(() { + Navigator.of(context).push( + CustomPageRoute( + page: HabibWalletPage(), + ), + ); + }), + ), + ], ), - // Row( - // mainAxisAlignment: MainAxisAlignment.spaceBetween, - // children: [ - // SizedBox( - // width: 200.h, - // child: Utils.getPaymentMethods(), - // ), - // ], - // ), ], ), ), diff --git a/lib/presentation/lab/lab_result_via_clinic/LabResultByClinic.dart b/lib/presentation/lab/lab_result_via_clinic/LabResultByClinic.dart index c883c863..cd1718bd 100644 --- a/lib/presentation/lab/lab_result_via_clinic/LabResultByClinic.dart +++ b/lib/presentation/lab/lab_result_via_clinic/LabResultByClinic.dart @@ -168,15 +168,16 @@ class LabResultByClinic extends StatelessWidget { ], ), ).paddingSymmetrical(24.h, 24.h).onPress(() async { - final _dialogService = getIt.get(); - await _dialogService.showCommonBottomSheetWithoutH( + final dialogService = getIt.get(); + final appState = getIt.get(); + await dialogService.showCommonBottomSheetWithoutH( message: LocaleKeys.aiDisclaimer.tr(), label: LocaleKeys.consent.tr(), okLabel: LocaleKeys.acceptLbl.tr(), cancelLabel: LocaleKeys.rejectView.tr(), onOkPressed: () { context.pop(); - labViewModel.getAiOverviewLabOrders(labOrder: labOrder, loadingText: LocaleKeys.loadingAIAnalysis.tr(context: context)); + labViewModel.getAiOverviewLabOrders(langId: appState.getLanguageID(), labOrder: labOrder, loadingText: LocaleKeys.loadingAIAnalysis.tr(context: context)); }, onCancelPressed: () { context.pop(); diff --git a/lib/presentation/lab/lab_results/lab_result_details.dart b/lib/presentation/lab/lab_results/lab_result_details.dart index bb4b2d8b..feb1596a 100644 --- a/lib/presentation/lab/lab_results/lab_result_details.dart +++ b/lib/presentation/lab/lab_results/lab_result_details.dart @@ -197,7 +197,7 @@ class _LabResultDetailsState extends State { onOkPressed: () { context.pop(); labViewModel.getAiOverviewSingleLabResult( - langId: appState.getLanguageID().toString(), recentLabResult: recentLabResult, loadingText: LocaleKeys.loadingAIAnalysis.tr(context: context)); + langId: appState.getLanguageID(), recentLabResult: recentLabResult, loadingText: LocaleKeys.loadingAIAnalysis.tr(context: context)); }, onCancelPressed: () { context.pop(); diff --git a/lib/presentation/my_invoices/my_invoices_details_page.dart b/lib/presentation/my_invoices/my_invoices_details_page.dart index 62e5a336..b8f534ac 100644 --- a/lib/presentation/my_invoices/my_invoices_details_page.dart +++ b/lib/presentation/my_invoices/my_invoices_details_page.dart @@ -185,7 +185,7 @@ class _MyInvoicesDetailsPageState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - (getIt().isArabic() ? widget.getInvoiceDetailsResponseModel.doctorNameN ?? LocaleKeys.doctor.tr(context: context) : widget.getInvoiceDetailsResponseModel.doctorName!).toText16(isBold: true), + (getIt().isArabic() ? widget.getInvoiceDetailsResponseModel.doctorName ?? LocaleKeys.doctor.tr(context: context) : widget.getInvoiceDetailsResponseModel.doctorName!).toText16(isBold: true), SizedBox(height: 8.h), Wrap( direction: Axis.horizontal, @@ -199,7 +199,7 @@ class _MyInvoicesDetailsPageState extends State { ), AppCustomChipWidget( labelText: ((getIt().isArabic() ? widget.getInvoiceDetailsResponseModel.clinicDescriptionN : widget.getInvoiceDetailsResponseModel.clinicDescription ?? "")!.length > 15 - ? '${widget.getInvoiceDetailsResponseModel.clinicDescription!.substring(0, 12)}...' + ? '${(getIt().isArabic() ? widget.getInvoiceDetailsResponseModel.clinicDescriptionN : widget.getInvoiceDetailsResponseModel.clinicDescription ?? "")!.substring(0, 12)}...' : getIt().isArabic() ? widget.getInvoiceDetailsResponseModel.clinicDescriptionN : widget.getInvoiceDetailsResponseModel.clinicDescription ?? ""), labelPadding: EdgeInsetsDirectional.only(start: 4.w, end: 4.w), ), diff --git a/lib/presentation/radiology/radiology_result_page.dart b/lib/presentation/radiology/radiology_result_page.dart index 911cea01..39a268ad 100644 --- a/lib/presentation/radiology/radiology_result_page.dart +++ b/lib/presentation/radiology/radiology_result_page.dart @@ -48,6 +48,14 @@ class _RadiologyResultPageState extends State { super.initState(); } + @override + void dispose() { + // Clear AI analysis data when leaving the screen + radiologyViewModel.closeRadiologyAIAnalysis(); + radiologyViewModel.setIsRadiologyAIAnalysisNeedsToBeShown(true); + super.dispose(); + } + @override Widget build(BuildContext context) { radiologyViewModel = Provider.of(context, listen: false); @@ -80,198 +88,199 @@ class _RadiologyResultPageState extends State { }); return Column( - children: [ - Expanded( - child: CollapsingListView( - title: LocaleKeys.radiologyResult.tr(context: context), - downloadReport: () async { - LoaderBottomSheet.showLoader(); - await radiologyViewModel - .getRadiologyPDF( - patientRadiologyResponseModel: widget.patientRadiologyResponseModel, - authenticatedUser: _appState.getAuthenticatedUser()!, - onError: (err) { - LoaderBottomSheet.hideLoader(); - showCommonBottomSheetWithoutHeight( - context, - child: Utils.getErrorWidget(loadingText: err), - callBackFunc: () {}, - isFullScreen: false, - isCloseButtonVisible: true, - ); - }) - .then((val) async { - LoaderBottomSheet.hideLoader(); - if (radiologyViewModel.patientRadiologyReportPDFBase64.isNotEmpty) { - String path = await Utils.createFileFromString(radiologyViewModel.patientRadiologyReportPDFBase64, "pdf"); - try { - OpenFilex.open(path); - } catch (ex) { - showCommonBottomSheetWithoutHeight( - context, - child: Utils.getErrorWidget(loadingText: "Cannot open file"), - callBackFunc: () {}, - isFullScreen: false, - isCloseButtonVisible: true, - ); + children: [ + Expanded( + child: CollapsingListView( + title: LocaleKeys.radiologyResult.tr(context: context), + downloadReport: () async { + LoaderBottomSheet.showLoader(); + await radiologyViewModel + .getRadiologyPDF( + patientRadiologyResponseModel: widget.patientRadiologyResponseModel, + authenticatedUser: _appState.getAuthenticatedUser()!, + onError: (err) { + LoaderBottomSheet.hideLoader(); + showCommonBottomSheetWithoutHeight( + context, + child: Utils.getErrorWidget(loadingText: err), + callBackFunc: () {}, + isFullScreen: false, + isCloseButtonVisible: true, + ); + }) + .then((val) async { + LoaderBottomSheet.hideLoader(); + if (radiologyViewModel.patientRadiologyReportPDFBase64.isNotEmpty) { + String path = await Utils.createFileFromString(radiologyViewModel.patientRadiologyReportPDFBase64, "pdf"); + try { + OpenFilex.open(path); + } catch (ex) { + showCommonBottomSheetWithoutHeight( + context, + child: Utils.getErrorWidget(loadingText: "Cannot open file"), + callBackFunc: () {}, + isFullScreen: false, + isCloseButtonVisible: true, + ); + } } - } - }); - }, - // viewImage: () { - // if (radiologyViewModel.radiologyImageURL.isNotEmpty) { - // Uri uri = Uri.parse(radiologyViewModel.radiologyImageURL); - // launchUrl(uri, mode: LaunchMode.platformDefault, webOnlyWindowName: ""); - // } else { - // Utils.showToast("Radiology image not available"); - // } - // }, - child: SingleChildScrollView( - child: Padding( - padding: EdgeInsets.symmetric(horizontal: 24.h), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox(height: 24.h), - Container( - decoration: RoundedRectangleBorder().toSmoothCornerDecoration( - color: AppColors.whiteColor, - borderRadius: 20.h, - hasShadow: true, - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox(height: 16.h), - // widget.patientRadiologyResponseModel.description!.toText16(isBold: true), - SizedBox(height: 8.h), - Directionality( - textDirection: ui.TextDirection.ltr, - child: widget.patientRadiologyResponseModel.reportData!.trim().toText12(isBold: true, color: AppColors.textColorLight, isEnglishOnly: true), - ), - SizedBox(height: 16.h), - // CustomButton( - // text: LocaleKeys.viewRadiologyImage.tr(context: context), - // onPressed: () async { - // if (radiologyViewModel.radiologyImageURL.isNotEmpty) { - // Uri uri = Uri.parse(radiologyViewModel.radiologyImageURL); - // launchUrl(uri, mode: LaunchMode.platformDefault, webOnlyWindowName: ""); - // } else { - // Utils.showToast("Radiology image not available"); - // } - // }, - // backgroundColor: AppColors.primaryRedColor, - // borderColor: AppColors.primaryRedColor, - // textColor: Colors.white, - // fontSize: 14, - // isBold: true, - // borderRadius: 12, - // padding: EdgeInsets.fromLTRB(10, 0, 10, 0), - // height: 40.h, - // icon: AppAssets.download, - // iconColor: Colors.white, - // iconSize: 20.h, - // ), - // SizedBox(height: 16.h), - ], - ).paddingSymmetrical(16.h, 0.h), - ), - SizedBox(height: 24.h), - if (radVM.radiologyAiAnalysisResponse != null) - RadiologyAiAnalysisWidget( - key: _aiAnalysisKey, - data: radVM.radiologyAiAnalysisResponse!, + }); + }, + // viewImage: () { + // if (radiologyViewModel.radiologyImageURL.isNotEmpty) { + // Uri uri = Uri.parse(radiologyViewModel.radiologyImageURL); + // launchUrl(uri, mode: LaunchMode.platformDefault, webOnlyWindowName: ""); + // } else { + // Utils.showToast("Radiology image not available"); + // } + // }, + child: SingleChildScrollView( + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 24.h), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox(height: 24.h), + Container( + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 20.h, + hasShadow: true, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox(height: 16.h), + // widget.patientRadiologyResponseModel.description!.toText16(isBold: true), + SizedBox(height: 8.h), + Directionality( + textDirection: ui.TextDirection.ltr, + child: widget.patientRadiologyResponseModel.reportData!.trim().toText12(isBold: true, color: AppColors.textColorLight, isEnglishOnly: true), + ), + SizedBox(height: 16.h), + // CustomButton( + // text: LocaleKeys.viewRadiologyImage.tr(context: context), + // onPressed: () async { + // if (radiologyViewModel.radiologyImageURL.isNotEmpty) { + // Uri uri = Uri.parse(radiologyViewModel.radiologyImageURL); + // launchUrl(uri, mode: LaunchMode.platformDefault, webOnlyWindowName: ""); + // } else { + // Utils.showToast("Radiology image not available"); + // } + // }, + // backgroundColor: AppColors.primaryRedColor, + // borderColor: AppColors.primaryRedColor, + // textColor: Colors.white, + // fontSize: 14, + // isBold: true, + // borderRadius: 12, + // padding: EdgeInsets.fromLTRB(10, 0, 10, 0), + // height: 40.h, + // icon: AppAssets.download, + // iconColor: Colors.white, + // iconSize: 20.h, + // ), + // SizedBox(height: 16.h), + ], + ).paddingSymmetrical(16.h, 0.h), ), - ], + SizedBox(height: 24.h), + if (radVM.radiologyAiAnalysisResponse != null) + RadiologyAiAnalysisWidget( + key: _aiAnalysisKey, + data: radVM.radiologyAiAnalysisResponse!, + ), + ], + ), ), ), ), ), - ), - radVM.radiologyAiAnalysisResponse == null - ? Container( - decoration: RoundedRectangleBorder().toSmoothCornerDecoration( - color: AppColors.whiteColor, - borderRadius: 24.h, - hasShadow: true, - ), - child: Column( - children: [ - SizedBox(height: 24.h), - widget.patientRadiologyResponseModel.dIAPACSURL != "" - ? CustomButton( - text: LocaleKeys.openRad.tr(context: context), - onPressed: () async { - if (radiologyViewModel.radiologyImageURL.isNotEmpty) { - Uri uri = Uri.parse(radiologyViewModel.radiologyImageURL); - launchUrl(uri, mode: LaunchMode.platformDefault, webOnlyWindowName: ""); - } else { - Utils.showToast("Radiology image not available"); - } - }, - backgroundColor: AppColors.primaryRedColor, - borderColor: AppColors.primaryRedColor, - textColor: Colors.white, - fontSize: 16, - isBold: true, - borderRadius: 12, - padding: EdgeInsets.fromLTRB(10, 0, 10, 0), - height: 56.h, - icon: AppAssets.imageIcon, - iconColor: Colors.white, - iconSize: 20.h, - ).paddingSymmetrical(24.h, 0.h) - : SizedBox.shrink(), - Container( - height: 56.h, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12.r), - gradient: LinearGradient( - begin: Alignment.centerLeft, - end: Alignment.centerRight, - stops: [0.236, 1.0], // 53.6% and 100% - colors: [ - Color(0xFF8A38F5), // Transparent - Color(0xFFE20BBB), // Solid #F8F8F8 + radVM.radiologyAiAnalysisResponse == null + ? Container( + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 24.h, + hasShadow: true, + ), + child: Column( + children: [ + SizedBox(height: 24.h), + widget.patientRadiologyResponseModel.dIAPACSURL != "" + ? CustomButton( + text: LocaleKeys.openRad.tr(context: context), + onPressed: () async { + if (radiologyViewModel.radiologyImageURL.isNotEmpty) { + Uri uri = Uri.parse(radiologyViewModel.radiologyImageURL); + launchUrl(uri, mode: LaunchMode.platformDefault, webOnlyWindowName: ""); + } else { + Utils.showToast("Radiology image not available"); + } + }, + backgroundColor: AppColors.primaryRedColor, + borderColor: AppColors.primaryRedColor, + textColor: Colors.white, + fontSize: 16, + isBold: true, + borderRadius: 12, + padding: EdgeInsets.fromLTRB(10, 0, 10, 0), + height: 56.h, + icon: AppAssets.imageIcon, + iconColor: Colors.white, + iconSize: 20.h, + ).paddingSymmetrical(24.h, 0.h) + : SizedBox.shrink(), + Container( + height: 56.h, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12.r), + gradient: LinearGradient( + begin: Alignment.centerLeft, + end: Alignment.centerRight, + stops: [0.236, 1.0], // 53.6% and 100% + colors: [ + Color(0xFF8A38F5), // Transparent + Color(0xFFE20BBB), // Solid #F8F8F8 + ], + ), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: EdgeInsets.only(right: 4.w, left: 4.w), + child: Utils.buildSvgWithAssets(icon: AppAssets.aiOverView, width: 16.h, height: 16.h, iconColor: Colors.white), + ), + LocaleKeys.generateAiAnalysisRadResult.tr(context: context).toText16(isBold: true, color: Colors.white) ], ), - ), - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Padding( - padding: EdgeInsets.only(right: 4.w, left: 4.w), - child: Utils.buildSvgWithAssets(icon: AppAssets.aiOverView, width: 16.h, height: 16.h, iconColor: Colors.white), - ), - LocaleKeys.generateAiAnalysisRadResult.tr(context: context).toText16(isBold: true, color: Colors.white) - ], - ), - ).paddingSymmetrical(24.h, 12.h).onPress(() async { - final _dialogService = getIt.get(); - await _dialogService.showCommonBottomSheetWithoutH( - message: LocaleKeys.aiDisclaimer.tr(), - label: LocaleKeys.consent.tr(), - okLabel: LocaleKeys.acceptLbl.tr(), - cancelLabel: LocaleKeys.rejectView.tr(), - onOkPressed: () { - context.pop(); - radiologyViewModel.getRadiologyAiAnalysis( - reportData: widget.patientRadiologyResponseModel.reportData ?? "", - loadingText: LocaleKeys.loadingAIAnalysis.tr(context: context), - ); - }, - onCancelPressed: () { - context.pop(); - }, - ); - }), - ], - ), - ) - : SizedBox.shrink(), - ], - ); + ).paddingSymmetrical(24.h, 12.h).onPress(() async { + final _dialogService = getIt.get(); + await _dialogService.showCommonBottomSheetWithoutH( + message: LocaleKeys.aiDisclaimerRad.tr(), + label: LocaleKeys.consent.tr(), + okLabel: LocaleKeys.acceptLbl.tr(), + cancelLabel: LocaleKeys.rejectView.tr(), + onOkPressed: () { + context.pop(); + radiologyViewModel.getRadiologyAiAnalysis( + reportData: widget.patientRadiologyResponseModel.reportData ?? "", + loadingText: LocaleKeys.loadingAIAnalysis.tr(context: context), + langId: _appState.getLanguageID(), + ); + }, + onCancelPressed: () { + context.pop(); + }, + ); + }), + ], + ), + ) + : SizedBox.shrink(), + ], + ); }), ); } diff --git a/lib/presentation/symptoms_checker/widgets/selected_organs_section.dart b/lib/presentation/symptoms_checker/widgets/selected_organs_section.dart index 52eef749..e2b342b6 100644 --- a/lib/presentation/symptoms_checker/widgets/selected_organs_section.dart +++ b/lib/presentation/symptoms_checker/widgets/selected_organs_section.dart @@ -58,6 +58,7 @@ class _SelectedOrgansSectionState extends State { style: TextStyle( fontSize: 16.f, // isBold: true, + fontWeight: FontWeight.w600, color: AppColors.textColor, ), ), @@ -78,7 +79,7 @@ class _SelectedOrgansSectionState extends State { style: TextStyle( color: AppColors.whiteColor, fontSize: 12.f, - // isBold: true, + fontWeight: FontWeight.w600, ), ), ), diff --git a/lib/theme/app_theme.dart b/lib/theme/app_theme.dart index 0f057efe..c676819f 100644 --- a/lib/theme/app_theme.dart +++ b/lib/theme/app_theme.dart @@ -26,8 +26,7 @@ class AppTheme { canvasColor: Colors.white, highlightColor: Colors.grey[100]!.withOpacity(0.4), splashColor: Colors.transparent, - bottomSheetTheme: BottomSheetThemeData( - backgroundColor: Colors.black.withOpacity(0)), + bottomSheetTheme: BottomSheetThemeData(backgroundColor: Colors.black.withOpacity(0)), floatingActionButtonTheme: const FloatingActionButtonThemeData(highlightElevation: 2, disabledElevation: 0, elevation: 2), appBarTheme: AppBarTheme( color: const Color(0xff515A5D), @@ -35,7 +34,7 @@ class AppTheme { actionsIconTheme: IconThemeData( color: Colors.grey[800], ), - systemOverlayStyle: SystemUiOverlayStyle.light, + systemOverlayStyle: SystemUiOverlayStyle.dark, surfaceTintColor: Colors.transparent, ), ); diff --git a/lib/widgets/countdown_timer.dart b/lib/widgets/countdown_timer.dart index 86249fc8..8cd3fa73 100644 --- a/lib/widgets/countdown_timer.dart +++ b/lib/widgets/countdown_timer.dart @@ -88,7 +88,7 @@ Widget buildDigit(String digit) { style: TextStyle( fontWeight: FontWeight.bold, color: Colors.black, - fontSize: 14.f, + fontSize: 10.f, ), ), ), diff --git a/lib/widgets/map/gms_map.dart b/lib/widgets/map/gms_map.dart index 1d06fb10..33e0befb 100644 --- a/lib/widgets/map/gms_map.dart +++ b/lib/widgets/map/gms_map.dart @@ -210,7 +210,7 @@ class _GMSMapState extends State { Icons.location_pin, size: 36.h, color: AppColors.primaryRedColor, - ).paddingOnly(bottom: Platform.isAndroid ? 30.h : double.parse((widget.bottomPaddingHeight + 25.h).toString())), + ).paddingOnly(bottom: Platform.isAndroid ? 30.h : 60.h), ), // ── My Location button ──────────────────────────────────────────── diff --git a/package/flutter_swiper_view/lib/src/custom_layout.dart b/package/flutter_swiper_view/lib/src/custom_layout.dart index 68eab940..8270a490 100644 --- a/package/flutter_swiper_view/lib/src/custom_layout.dart +++ b/package/flutter_swiper_view/lib/src/custom_layout.dart @@ -204,44 +204,22 @@ abstract class _CustomLayoutStateBase extends State void _onPanEnd(DragEndDetails details) { if (_lockScroll) return; - final bool _isReversedGesture = widget.axisDirection == AxisDirection.right; - double velocity = widget.scrollDirection == Axis.horizontal ? details.velocity.pixelsPerSecond.dx : details.velocity.pixelsPerSecond.dy; - if (_isReversedGesture) { - // Reversed: swipe right (value >= 0.75) = next, swipe left (value < 0.25) = previous - if (_animationController.value >= 0.75 || velocity > 500.0) { - if (_currentIndex >= widget.itemCount - 1 && !widget.loop) { - _move(0.5); - return; - } - _move(1.0, nextIndex: _currentIndex + 1); - } else if (_animationController.value < 0.25 || velocity < -500.0) { - if (_currentIndex <= 0 && !widget.loop) { - _move(0.5); - return; - } - _move(0.0, nextIndex: _currentIndex - 1); - } else { - _move(0.5); + if (_animationController.value >= 0.75 || velocity > 500.0) { + if (_currentIndex <= 0 && !widget.loop) { + return; } - } else { - // Default: swipe right (value >= 0.75) = previous, swipe left (value < 0.25) = next - if (_animationController.value >= 0.75 || velocity > 500.0) { - if (_currentIndex <= 0 && !widget.loop) { - return; - } - _move(1.0, nextIndex: _currentIndex - 1); - } else if (_animationController.value < 0.25 || velocity < -500.0) { - if (_currentIndex >= widget.itemCount - 1 && !widget.loop) { - return; - } - _move(0.0, nextIndex: _currentIndex + 1); - } else { - _move(0.5); + _move(1.0, nextIndex: _currentIndex - 1); + } else if (_animationController.value < 0.25 || velocity < -500.0) { + if (_currentIndex >= widget.itemCount - 1 && !widget.loop) { + return; } + _move(0.0, nextIndex: _currentIndex + 1); + } else { + _move(0.5); } } @@ -255,7 +233,6 @@ abstract class _CustomLayoutStateBase extends State void _onPanUpdate(DragUpdateDetails details) { if (_lockScroll) return; - double value = _currentValue + ((widget.scrollDirection == Axis.horizontal ? details.globalPosition.dx @@ -265,26 +242,13 @@ abstract class _CustomLayoutStateBase extends State 2; // no loop ? if (!widget.loop) { - if (widget.axisDirection == AxisDirection.right) { - // Reversed bounds: block dragging left past first, right past last - if (_currentIndex <= 0) { - if (value < 0.5) { - value = 0.5; - } - } else if (_currentIndex >= widget.itemCount - 1) { - if (value > 0.5) { - value = 0.5; - } + if (_currentIndex >= widget.itemCount - 1) { + if (value < 0.5) { + value = 0.5; } - } else { - if (_currentIndex >= widget.itemCount - 1) { - if (value < 0.5) { - value = 0.5; - } - } else if (_currentIndex <= 0) { - if (value > 0.5) { - value = 0.5; - } + } else if (_currentIndex <= 0) { + if (value > 0.5) { + value = 0.5; } } }