From 2c47ff7d2105d6d20d57f91b3293fee763e4f256 Mon Sep 17 00:00:00 2001 From: SKGEzhil Date: Tue, 12 Nov 2024 10:43:24 +0530 Subject: [PATCH 1/5] Backend: Added qr route, Frontend: created small card widget --- backend/backend/Routes/Transport/qr.py | 33 ++++++ backend/backend/main.py | 7 +- backend/poetry.lock | 107 +++++++++++++++++- backend/pyproject.toml | 2 + frontend/lib/router.dart | 20 ++++ frontend/lib/screens/bus_ticket_screen.dart | 17 +++ frontend/lib/screens/home_screen.dart | 103 ++++++++++++----- frontend/lib/services/api_service.dart | 3 +- frontend/lib/widgets/homeScreenCardSmall.dart | 92 +++++++++++++++ 9 files changed, 353 insertions(+), 31 deletions(-) create mode 100644 backend/backend/Routes/Transport/qr.py create mode 100644 frontend/lib/screens/bus_ticket_screen.dart create mode 100644 frontend/lib/widgets/homeScreenCardSmall.dart diff --git a/backend/backend/Routes/Transport/qr.py b/backend/backend/Routes/Transport/qr.py new file mode 100644 index 0000000..84a3f38 --- /dev/null +++ b/backend/backend/Routes/Transport/qr.py @@ -0,0 +1,33 @@ +from fastapi import APIRouter, HTTPException +import json +import os +from pydantic import BaseModel +from datetime import datetime + +router = APIRouter(prefix="/transport", tags=["transport_schedule"]) +dir = os.path.dirname(os.path.realpath(__file__)) + + +# Request body model +class TransactionRequest(BaseModel): + transactionId: str + + +# Response model +class TransactionResponse(BaseModel): + transactionId: str + payment_time: str # hh:mm dd/mm/yy + busTiming: str # hh:mm + + +@router.post("/qr", response_model=TransactionResponse) +async def process_transaction(request: TransactionRequest): + # Sample data generation for the response + payment_time = datetime.now().strftime("%H:%M %d/%m/%y") + bus_timing = "14:30" # Example bus timing; replace with actual data logic if needed + + return TransactionResponse( + transactionId=request.transactionId, + payment_time=payment_time, + busTiming=bus_timing + ) diff --git a/backend/backend/main.py b/backend/backend/main.py index 2623055..2729e28 100644 --- a/backend/backend/main.py +++ b/backend/backend/main.py @@ -16,6 +16,8 @@ from Routes.Auth.tokens import verify_token from fastapi.responses import JSONResponse from Routes.Transport.transport_schedule import router as transport_router +from Routes.Transport.qr import router as transaction_verification_route + load_dotenv() @@ -46,6 +48,7 @@ app.include_router(cab_router) app.include_router(user_router) app.include_router(transport_router) +app.include_router(transaction_verification_route) async def cookie_verification_middleware(request: Request, call_next): if request.method == "OPTIONS": @@ -61,14 +64,14 @@ async def cookie_verification_middleware(request: Request, call_next): else: return JSONResponse(status_code=401, content={"detail": "Session cookie is missing"}) response = await call_next(request) - + #updating the cookie set_cookie(response=response, key="session", value=token, days_expire=15) return response @app.middleware("http") async def apply_middleware(request: Request, call_next): - excluded_routes = ["/auth/login", "/auth/logout", "/docs", "/openapi.json", "/transport/", "/mess_menu/"] # Add routes to exclude guard here + excluded_routes = ["/transport/qr","/auth/login", "/auth/logout", "/docs", "/openapi.json", "/transport/", "/mess_menu/"] # Add routes to exclude guard here if request.url.path not in excluded_routes: return await cookie_verification_middleware(request, call_next) diff --git a/backend/poetry.lock b/backend/poetry.lock index 4968503..44710af 100644 --- a/backend/poetry.lock +++ b/backend/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.4 and should not be changed by hand. [[package]] name = "aiosql" @@ -1008,6 +1008,109 @@ files = [ {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, ] +[[package]] +name = "regex" +version = "2024.11.6" +description = "Alternative regular expression module, to replace re." +optional = false +python-versions = ">=3.8" +files = [ + {file = "regex-2024.11.6-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ff590880083d60acc0433f9c3f713c51f7ac6ebb9adf889c79a261ecf541aa91"}, + {file = "regex-2024.11.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:658f90550f38270639e83ce492f27d2c8d2cd63805c65a13a14d36ca126753f0"}, + {file = "regex-2024.11.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:164d8b7b3b4bcb2068b97428060b2a53be050085ef94eca7f240e7947f1b080e"}, + {file = "regex-2024.11.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3660c82f209655a06b587d55e723f0b813d3a7db2e32e5e7dc64ac2a9e86fde"}, + {file = "regex-2024.11.6-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d22326fcdef5e08c154280b71163ced384b428343ae16a5ab2b3354aed12436e"}, + {file = "regex-2024.11.6-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f1ac758ef6aebfc8943560194e9fd0fa18bcb34d89fd8bd2af18183afd8da3a2"}, + {file = "regex-2024.11.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:997d6a487ff00807ba810e0f8332c18b4eb8d29463cfb7c820dc4b6e7562d0cf"}, + {file = "regex-2024.11.6-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:02a02d2bb04fec86ad61f3ea7f49c015a0681bf76abb9857f945d26159d2968c"}, + {file = "regex-2024.11.6-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f02f93b92358ee3f78660e43b4b0091229260c5d5c408d17d60bf26b6c900e86"}, + {file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:06eb1be98df10e81ebaded73fcd51989dcf534e3c753466e4b60c4697a003b67"}, + {file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:040df6fe1a5504eb0f04f048e6d09cd7c7110fef851d7c567a6b6e09942feb7d"}, + {file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:fdabbfc59f2c6edba2a6622c647b716e34e8e3867e0ab975412c5c2f79b82da2"}, + {file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:8447d2d39b5abe381419319f942de20b7ecd60ce86f16a23b0698f22e1b70008"}, + {file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:da8f5fc57d1933de22a9e23eec290a0d8a5927a5370d24bda9a6abe50683fe62"}, + {file = "regex-2024.11.6-cp310-cp310-win32.whl", hash = "sha256:b489578720afb782f6ccf2840920f3a32e31ba28a4b162e13900c3e6bd3f930e"}, + {file = "regex-2024.11.6-cp310-cp310-win_amd64.whl", hash = "sha256:5071b2093e793357c9d8b2929dfc13ac5f0a6c650559503bb81189d0a3814519"}, + {file = "regex-2024.11.6-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5478c6962ad548b54a591778e93cd7c456a7a29f8eca9c49e4f9a806dcc5d638"}, + {file = "regex-2024.11.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2c89a8cc122b25ce6945f0423dc1352cb9593c68abd19223eebbd4e56612c5b7"}, + {file = "regex-2024.11.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:94d87b689cdd831934fa3ce16cc15cd65748e6d689f5d2b8f4f4df2065c9fa20"}, + {file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1062b39a0a2b75a9c694f7a08e7183a80c63c0d62b301418ffd9c35f55aaa114"}, + {file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:167ed4852351d8a750da48712c3930b031f6efdaa0f22fa1933716bfcd6bf4a3"}, + {file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d548dafee61f06ebdb584080621f3e0c23fff312f0de1afc776e2a2ba99a74f"}, + {file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2a19f302cd1ce5dd01a9099aaa19cae6173306d1302a43b627f62e21cf18ac0"}, + {file = "regex-2024.11.6-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bec9931dfb61ddd8ef2ebc05646293812cb6b16b60cf7c9511a832b6f1854b55"}, + {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9714398225f299aa85267fd222f7142fcb5c769e73d7733344efc46f2ef5cf89"}, + {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:202eb32e89f60fc147a41e55cb086db2a3f8cb82f9a9a88440dcfc5d37faae8d"}, + {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:4181b814e56078e9b00427ca358ec44333765f5ca1b45597ec7446d3a1ef6e34"}, + {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:068376da5a7e4da51968ce4c122a7cd31afaaec4fccc7856c92f63876e57b51d"}, + {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ac10f2c4184420d881a3475fb2c6f4d95d53a8d50209a2500723d831036f7c45"}, + {file = "regex-2024.11.6-cp311-cp311-win32.whl", hash = "sha256:c36f9b6f5f8649bb251a5f3f66564438977b7ef8386a52460ae77e6070d309d9"}, + {file = "regex-2024.11.6-cp311-cp311-win_amd64.whl", hash = "sha256:02e28184be537f0e75c1f9b2f8847dc51e08e6e171c6bde130b2687e0c33cf60"}, + {file = "regex-2024.11.6-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:52fb28f528778f184f870b7cf8f225f5eef0a8f6e3778529bdd40c7b3920796a"}, + {file = "regex-2024.11.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fdd6028445d2460f33136c55eeb1f601ab06d74cb3347132e1c24250187500d9"}, + {file = "regex-2024.11.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:805e6b60c54bf766b251e94526ebad60b7de0c70f70a4e6210ee2891acb70bf2"}, + {file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b85c2530be953a890eaffde05485238f07029600e8f098cdf1848d414a8b45e4"}, + {file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bb26437975da7dc36b7efad18aa9dd4ea569d2357ae6b783bf1118dabd9ea577"}, + {file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:abfa5080c374a76a251ba60683242bc17eeb2c9818d0d30117b4486be10c59d3"}, + {file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b7fa6606c2881c1db9479b0eaa11ed5dfa11c8d60a474ff0e095099f39d98e"}, + {file = "regex-2024.11.6-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0c32f75920cf99fe6b6c539c399a4a128452eaf1af27f39bce8909c9a3fd8cbe"}, + {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:982e6d21414e78e1f51cf595d7f321dcd14de1f2881c5dc6a6e23bbbbd68435e"}, + {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a7c2155f790e2fb448faed6dd241386719802296ec588a8b9051c1f5c481bc29"}, + {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:149f5008d286636e48cd0b1dd65018548944e495b0265b45e1bffecce1ef7f39"}, + {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:e5364a4502efca094731680e80009632ad6624084aff9a23ce8c8c6820de3e51"}, + {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0a86e7eeca091c09e021db8eb72d54751e527fa47b8d5787caf96d9831bd02ad"}, + {file = "regex-2024.11.6-cp312-cp312-win32.whl", hash = "sha256:32f9a4c643baad4efa81d549c2aadefaeba12249b2adc5af541759237eee1c54"}, + {file = "regex-2024.11.6-cp312-cp312-win_amd64.whl", hash = "sha256:a93c194e2df18f7d264092dc8539b8ffb86b45b899ab976aa15d48214138e81b"}, + {file = "regex-2024.11.6-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a6ba92c0bcdf96cbf43a12c717eae4bc98325ca3730f6b130ffa2e3c3c723d84"}, + {file = "regex-2024.11.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:525eab0b789891ac3be914d36893bdf972d483fe66551f79d3e27146191a37d4"}, + {file = "regex-2024.11.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:086a27a0b4ca227941700e0b31425e7a28ef1ae8e5e05a33826e17e47fbfdba0"}, + {file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bde01f35767c4a7899b7eb6e823b125a64de314a8ee9791367c9a34d56af18d0"}, + {file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b583904576650166b3d920d2bcce13971f6f9e9a396c673187f49811b2769dc7"}, + {file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c4de13f06a0d54fa0d5ab1b7138bfa0d883220965a29616e3ea61b35d5f5fc7"}, + {file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3cde6e9f2580eb1665965ce9bf17ff4952f34f5b126beb509fee8f4e994f143c"}, + {file = "regex-2024.11.6-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0d7f453dca13f40a02b79636a339c5b62b670141e63efd511d3f8f73fba162b3"}, + {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:59dfe1ed21aea057a65c6b586afd2a945de04fc7db3de0a6e3ed5397ad491b07"}, + {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b97c1e0bd37c5cd7902e65f410779d39eeda155800b65fc4d04cc432efa9bc6e"}, + {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f9d1e379028e0fc2ae3654bac3cbbef81bf3fd571272a42d56c24007979bafb6"}, + {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:13291b39131e2d002a7940fb176e120bec5145f3aeb7621be6534e46251912c4"}, + {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4f51f88c126370dcec4908576c5a627220da6c09d0bff31cfa89f2523843316d"}, + {file = "regex-2024.11.6-cp313-cp313-win32.whl", hash = "sha256:63b13cfd72e9601125027202cad74995ab26921d8cd935c25f09c630436348ff"}, + {file = "regex-2024.11.6-cp313-cp313-win_amd64.whl", hash = "sha256:2b3361af3198667e99927da8b84c1b010752fa4b1115ee30beaa332cabc3ef1a"}, + {file = "regex-2024.11.6-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:3a51ccc315653ba012774efca4f23d1d2a8a8f278a6072e29c7147eee7da446b"}, + {file = "regex-2024.11.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ad182d02e40de7459b73155deb8996bbd8e96852267879396fb274e8700190e3"}, + {file = "regex-2024.11.6-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ba9b72e5643641b7d41fa1f6d5abda2c9a263ae835b917348fc3c928182ad467"}, + {file = "regex-2024.11.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40291b1b89ca6ad8d3f2b82782cc33807f1406cf68c8d440861da6304d8ffbbd"}, + {file = "regex-2024.11.6-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cdf58d0e516ee426a48f7b2c03a332a4114420716d55769ff7108c37a09951bf"}, + {file = "regex-2024.11.6-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a36fdf2af13c2b14738f6e973aba563623cb77d753bbbd8d414d18bfaa3105dd"}, + {file = "regex-2024.11.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d1cee317bfc014c2419a76bcc87f071405e3966da434e03e13beb45f8aced1a6"}, + {file = "regex-2024.11.6-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:50153825ee016b91549962f970d6a4442fa106832e14c918acd1c8e479916c4f"}, + {file = "regex-2024.11.6-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ea1bfda2f7162605f6e8178223576856b3d791109f15ea99a9f95c16a7636fb5"}, + {file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:df951c5f4a1b1910f1a99ff42c473ff60f8225baa1cdd3539fe2819d9543e9df"}, + {file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:072623554418a9911446278f16ecb398fb3b540147a7828c06e2011fa531e773"}, + {file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:f654882311409afb1d780b940234208a252322c24a93b442ca714d119e68086c"}, + {file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:89d75e7293d2b3e674db7d4d9b1bee7f8f3d1609428e293771d1a962617150cc"}, + {file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:f65557897fc977a44ab205ea871b690adaef6b9da6afda4790a2484b04293a5f"}, + {file = "regex-2024.11.6-cp38-cp38-win32.whl", hash = "sha256:6f44ec28b1f858c98d3036ad5d7d0bfc568bdd7a74f9c24e25f41ef1ebfd81a4"}, + {file = "regex-2024.11.6-cp38-cp38-win_amd64.whl", hash = "sha256:bb8f74f2f10dbf13a0be8de623ba4f9491faf58c24064f32b65679b021ed0001"}, + {file = "regex-2024.11.6-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5704e174f8ccab2026bd2f1ab6c510345ae8eac818b613d7d73e785f1310f839"}, + {file = "regex-2024.11.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:220902c3c5cc6af55d4fe19ead504de80eb91f786dc102fbd74894b1551f095e"}, + {file = "regex-2024.11.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5e7e351589da0850c125f1600a4c4ba3c722efefe16b297de54300f08d734fbf"}, + {file = "regex-2024.11.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5056b185ca113c88e18223183aa1a50e66507769c9640a6ff75859619d73957b"}, + {file = "regex-2024.11.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2e34b51b650b23ed3354b5a07aab37034d9f923db2a40519139af34f485f77d0"}, + {file = "regex-2024.11.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5670bce7b200273eee1840ef307bfa07cda90b38ae56e9a6ebcc9f50da9c469b"}, + {file = "regex-2024.11.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:08986dce1339bc932923e7d1232ce9881499a0e02925f7402fb7c982515419ef"}, + {file = "regex-2024.11.6-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:93c0b12d3d3bc25af4ebbf38f9ee780a487e8bf6954c115b9f015822d3bb8e48"}, + {file = "regex-2024.11.6-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:764e71f22ab3b305e7f4c21f1a97e1526a25ebdd22513e251cf376760213da13"}, + {file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:f056bf21105c2515c32372bbc057f43eb02aae2fda61052e2f7622c801f0b4e2"}, + {file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:69ab78f848845569401469da20df3e081e6b5a11cb086de3eed1d48f5ed57c95"}, + {file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:86fddba590aad9208e2fa8b43b4c098bb0ec74f15718bb6a704e3c63e2cef3e9"}, + {file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:684d7a212682996d21ca12ef3c17353c021fe9de6049e19ac8481ec35574a70f"}, + {file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a03e02f48cd1abbd9f3b7e3586d97c8f7a9721c436f51a5245b3b9483044480b"}, + {file = "regex-2024.11.6-cp39-cp39-win32.whl", hash = "sha256:41758407fc32d5c3c5de163888068cfee69cb4c2be844e7ac517a52770f9af57"}, + {file = "regex-2024.11.6-cp39-cp39-win_amd64.whl", hash = "sha256:b2837718570f95dd41675328e111345f9b7095d821bac435aac173ac80b19983"}, + {file = "regex-2024.11.6.tar.gz", hash = "sha256:7ab159b063c52a0333c884e4679f8d7a85112ee3078fe3d9004b2dd875585519"}, +] + [[package]] name = "requests" version = "2.32.3" @@ -1386,4 +1489,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "ca2d432d6f42eb5b65d4d3040c6e30af7d7e501fd144447ed0438d6aa204e2b0" +content-hash = "3789a0b44f1ac25df29fb7e0c002c26e798e4cd95bc491fa6e52cbebee8e6c8f" diff --git a/backend/pyproject.toml b/backend/pyproject.toml index 7b164d8..2c55f8b 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -27,6 +27,8 @@ html2text = "^2024.2.26" aiosql = "^10.2" gunicorn = "^22.0.0" pytz = "^2024.1" +regex = "^2024.11.6" + [tool.poetry.group.dev.dependencies] diff --git a/frontend/lib/router.dart b/frontend/lib/router.dart index ce8d6c3..d9b66ed 100644 --- a/frontend/lib/router.dart +++ b/frontend/lib/router.dart @@ -2,6 +2,7 @@ import 'package:dashbaord/constants/enums/lost_and_found.dart'; import 'package:dashbaord/error.dart'; import 'package:dashbaord/models/mess_menu_model.dart'; import 'package:dashbaord/models/user_model.dart'; +import 'package:dashbaord/screens/bus_ticket_screen.dart'; import 'package:dashbaord/screens/bus_timings_screen.dart'; import 'package:dashbaord/screens/cab_add_screen.dart'; import 'package:dashbaord/screens/cab_add_success.dart'; @@ -117,6 +118,25 @@ class AppRouter { ); }, ), + GoRoute( + path: '/bus_ticket', + pageBuilder: (context, state) { + return CustomTransitionPage( + key: state.pageKey, + child: BusTicketScreen(), + transitionsBuilder: + (context, animation, secondaryAnimation, child) { + return SlideTransition( + position: Tween( + begin: const Offset(1, 0), + end: Offset.zero, + ).animate(animation), + child: child, + ); + }, + ); + }, + ), GoRoute( path: '/cabsharing', pageBuilder: (context, state) { diff --git a/frontend/lib/screens/bus_ticket_screen.dart b/frontend/lib/screens/bus_ticket_screen.dart new file mode 100644 index 0000000..441ab74 --- /dev/null +++ b/frontend/lib/screens/bus_ticket_screen.dart @@ -0,0 +1,17 @@ +import 'package:flutter/material.dart'; + +class BusTicketScreen extends StatelessWidget { + const BusTicketScreen({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Bus Ticket'), + ), + body: const Center( + child: Text('Bus Ticket Screen'), + ), + ); + } +} diff --git a/frontend/lib/screens/home_screen.dart b/frontend/lib/screens/home_screen.dart index c56d4e2..abbfe06 100644 --- a/frontend/lib/screens/home_screen.dart +++ b/frontend/lib/screens/home_screen.dart @@ -8,6 +8,7 @@ import 'package:dashbaord/services/api_service.dart'; import 'package:dashbaord/services/shared_service.dart'; import 'package:dashbaord/utils/bus_schedule.dart'; import 'package:dashbaord/utils/loading_widget.dart'; +import 'package:dashbaord/widgets/homeScreenCardSmall.dart'; import 'package:dashbaord/widgets/home_card_no_options.dart'; import 'package:dashbaord/widgets/home_screen_appbar.dart'; import 'package:dashbaord/widgets/home_screen_bus_timings.dart'; @@ -506,36 +507,86 @@ class _HomeScreenState extends State { const SizedBox(height: 20), HomeScreenMessMenu(messMenu: messMenu), const SizedBox(height: 20), - HomeCardNoOptions( - isComingSoon: false, - title: 'Cab Sharing', - child: 'assets/icons/cab-sharing-icon.svg', - onTap: () { - widget.isGuest - ? showError() - : context.push('/cabsharing', extra: { - 'user': userModel ?? - UserModel( - email: "user@iith.ac.in", - name: "User"), - 'image': image, - }); - }, - ), - const SizedBox(height: 20), - HomeCardNoOptions( - isComingSoon: false, - isLnF: true, - title: 'Lost & Found', - child: 'assets/icons/magnifying-icon.svg', - onTap: widget.isGuest - ? showError - : () => context.push('/lnf', extra: { + SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Padding( + padding: const EdgeInsets.only(bottom: 8.0), + child: Row( + children: [ + HomeScreenCardSmall( + isComingSoon: false, + title: 'Cab Sharing', + child: 'assets/icons/cab-sharing-icon.svg', + onTap: () { + widget.isGuest + ? showError() + : context.push('/cabsharing', extra: { + 'user': userModel ?? + UserModel( + email: "user@iith.ac.in", + name: "User"), + 'image': image, + }); + }, + ), + const SizedBox(width: 10), + HomeScreenCardSmall( + isComingSoon: false, + isLnF: true, + title: 'Lost & Found', + child: 'assets/icons/magnifying-icon.svg', + onTap: widget.isGuest + ? showError + : () => context.push('/lnf', extra: { 'currentUserEmail': - userModel?.email ?? 'user@iith.ac.in' + userModel?.email ?? 'user@iith.ac.in' }), + ), + const SizedBox(height: 20), + HomeScreenCardSmall( + isComingSoon: false, + title: 'Patencheru Bus', + child: 'assets/icons/cab-sharing-icon.svg', + onTap: () { + context.push('/bus_ticket'); + }, + ), + + ], + ), + ), ), const SizedBox(height: 20), + // HomeCardNoOptions( + // isComingSoon: true, + // title: 'Cab Sharing', + // child: 'assets/icons/cab-sharing-icon.svg', + // onTap: () { + // widget.isGuest + // ? showError() + // : context.push('/cabsharing', extra: { + // 'user': userModel ?? + // UserModel( + // email: "user@iith.ac.in", + // name: "User"), + // 'image': image, + // }); + // }, + // ), + // const SizedBox(height: 20), + // HomeCardNoOptions( + // isComingSoon: false, + // isLnF: true, + // title: 'Lost & Found', + // child: 'assets/icons/magnifying-icon.svg', + // onTap: widget.isGuest + // ? showError + // : () => context.push('/lnf', extra: { + // 'currentUserEmail': + // userModel?.email ?? 'user@iith.ac.in' + // }), + // ), + // const SizedBox(height: 20), ], ), ), diff --git a/frontend/lib/services/api_service.dart b/frontend/lib/services/api_service.dart index f559be3..c5e7318 100644 --- a/frontend/lib/services/api_service.dart +++ b/frontend/lib/services/api_service.dart @@ -31,7 +31,8 @@ class ApiServices { ApiServices._internal(); PersistCookieJar? cookieJar; - String backendUrl = dotenv.env["BACKEND_URL"] ?? ""; + // String backendUrl = dotenv.env["BACKEND_URL"] ?? "https://api.iith.dev/"; + String backendUrl = "https://api.iith.dev/"; Dio dio = Dio(); diff --git a/frontend/lib/widgets/homeScreenCardSmall.dart b/frontend/lib/widgets/homeScreenCardSmall.dart new file mode 100644 index 0000000..0cd5a97 --- /dev/null +++ b/frontend/lib/widgets/homeScreenCardSmall.dart @@ -0,0 +1,92 @@ +import 'dart:math'; + +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; + +class HomeScreenCardSmall extends StatelessWidget { + final String title; + final dynamic child; + final bool isLnF; + final bool isImageShow; + final bool isComingSoon; + final void Function() onTap; + + const HomeScreenCardSmall( + {super.key, + required this.title, + this.child, + this.isLnF = false, + this.isImageShow = true, + this.isComingSoon = true, + required this.onTap}); + + @override + Widget build(BuildContext context) { + final screenWidth = MediaQuery.of(context).size.width; + + return InkWell( + onTap: onTap, + child: Container( + // clipBehavior: Clip.hardEdge, + height: 170, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(10), + boxShadow: const [ + BoxShadow( + color: Color.fromRGBO(51, 51, 51, 0.10), // Shadow color + offset: Offset(0, 4), // Offset in the x, y direction + blurRadius: 10.0, + spreadRadius: 0.0, + ), + ], + ), + child: Column( + children: [ + Stack( + children: [ + Stack( + children: [ + isImageShow + ? SvgPicture.asset( + child, + width: min(0.32 * screenWidth, 200), + ) + : Container(), + ], + ), + if (isComingSoon) + Container( + decoration: BoxDecoration( + color: Theme.of(context).brightness == Brightness.dark + ? const Color.fromARGB(255, 57, 57, 57) + .withOpacity(0.5) + : Colors.white.withOpacity(0.5)), + child: Center( + child: SizedBox( + height: 100, + child: Image.asset( + "assets/icons/comingsoon.png", + ))), + ) + ], + ), + Expanded(child: SizedBox()), + Padding( + padding: const EdgeInsets.only(left: 8.0, right: 8.0), + child: Text( + title, + style: const TextStyle( + color: Colors.black, + fontWeight: FontWeight.bold, + fontSize: 20, + ), + ), + ), + const SizedBox(height: 10), + ], + ), + ), + ); + } +} From 7938fa61139f6573dcbe9a584ee0955134b2ec69 Mon Sep 17 00:00:00 2001 From: SKGEzhil Date: Sun, 17 Nov 2024 10:27:01 +0530 Subject: [PATCH 2/5] feat: added city bus screen, implemented bus schedule and qr feature --- backend/backend/Routes/Transport/qr.py | 7 +- .../Routes/Transport/transport_schedule.py | 19 +- frontend/lib/models/transport_qr_model.dart | 76 ++++ frontend/lib/router.dart | 6 +- frontend/lib/screens/city_bus_screen.dart | 348 ++++++++++++++++++ frontend/lib/screens/home_screen.dart | 2 +- frontend/lib/services/api_service.dart | 61 +++ frontend/lib/services/shared_service.dart | 17 + frontend/lib/utils/bus_schedule.dart | 51 +++ frontend/pubspec.yaml | 3 +- 10 files changed, 581 insertions(+), 9 deletions(-) create mode 100644 frontend/lib/models/transport_qr_model.dart create mode 100644 frontend/lib/screens/city_bus_screen.dart diff --git a/backend/backend/Routes/Transport/qr.py b/backend/backend/Routes/Transport/qr.py index 84a3f38..9db6773 100644 --- a/backend/backend/Routes/Transport/qr.py +++ b/backend/backend/Routes/Transport/qr.py @@ -16,7 +16,8 @@ class TransactionRequest(BaseModel): # Response model class TransactionResponse(BaseModel): transactionId: str - payment_time: str # hh:mm dd/mm/yy + paymentTime: str # hh:mm dd/mm/yy + travelDate: str # dd/mm/yy busTiming: str # hh:mm @@ -24,10 +25,12 @@ class TransactionResponse(BaseModel): async def process_transaction(request: TransactionRequest): # Sample data generation for the response payment_time = datetime.now().strftime("%H:%M %d/%m/%y") + travel_date = datetime.now().strftime("%d/%m/%y") bus_timing = "14:30" # Example bus timing; replace with actual data logic if needed return TransactionResponse( transactionId=request.transactionId, - payment_time=payment_time, + paymentTime=payment_time, + travelDate=travel_date, busTiming=bus_timing ) diff --git a/backend/backend/Routes/Transport/transport_schedule.py b/backend/backend/Routes/Transport/transport_schedule.py index 4ee03e8..caf3c81 100644 --- a/backend/backend/Routes/Transport/transport_schedule.py +++ b/backend/backend/Routes/Transport/transport_schedule.py @@ -1,17 +1,32 @@ from fastapi import APIRouter, HTTPException import json import os + router = APIRouter(prefix="/transport", tags=["transport_schedule"]) dir = os.path.dirname(os.path.realpath(__file__)) + @router.get("/") async def get_bus_schedule(): - try: + try: file = open(dir + "/transport.json") menu = json.load(file) file.close() return menu except FileNotFoundError: raise HTTPException( - status_code=500, detail="Transport Schdule file does not exist. Please make one." + status_code=500, detail="Transport Schedule file does not exist. Please make one." + ) + + +@router.get("/cityBus") +async def get_city_bus_schedule(): + try: + file = open(dir + "/cityBus.json") + menu = json.load(file) + file.close() + return menu + except FileNotFoundError: + raise HTTPException( + status_code=500, detail="City Bus Schedule file does not exist. Please make one." ) diff --git a/frontend/lib/models/transport_qr_model.dart b/frontend/lib/models/transport_qr_model.dart new file mode 100644 index 0000000..111ac35 --- /dev/null +++ b/frontend/lib/models/transport_qr_model.dart @@ -0,0 +1,76 @@ +class TransactionQRModel { + final String transactionId; + final String paymentTime; + final String travelDate; + final String busTiming; + + TransactionQRModel({ + required this.transactionId, + required this.paymentTime, + required this.travelDate, + required this.busTiming, + }); + + // Factory constructor to create a TransactionResponse from JSON + factory TransactionQRModel.fromJson(Map json) { + return TransactionQRModel( + transactionId: json['transactionId'] as String, + paymentTime: json['paymentTime'] as String, + travelDate: json['travelDate'] as String, + busTiming: json['busTiming'] as String, + ); + } + + // Method to convert TransactionResponse to JSON (if needed for other purposes) + Map toJson() { + return { + 'transactionId': transactionId, + 'paymentTime': paymentTime, + 'travelDate': travelDate, + 'busTiming': busTiming, + }; + } + + TransactionQRModel parseTransaction(String input) { + // Remove the curly braces and split by commas + input = input.replaceAll(RegExp(r'[{}]'), ''); + List parts = input.split(', '); + + // Initialize variables to store the parsed data + String transactionId = ''; + String paymentTime = ''; + String travelDate = ''; + String busTiming = ''; + + // Extract the key-value pairs + for (String part in parts) { + List keyValue = part.split(': '); + if (keyValue.length == 2) { + String key = keyValue[0].trim(); + String value = keyValue[1].trim(); + + switch (key) { + case 'transactionId': + transactionId = value; + break; + case 'paymentTime': + paymentTime = value; + break; + case 'busTiming': + busTiming = value; + break; + case 'travelDate': + travelDate = value; + break; + } + } + } + + // Create and return the Transaction object + return TransactionQRModel( + transactionId: transactionId, + paymentTime: paymentTime, + busTiming: busTiming, + travelDate: travelDate); + } +} diff --git a/frontend/lib/router.dart b/frontend/lib/router.dart index d9b66ed..39aa95a 100644 --- a/frontend/lib/router.dart +++ b/frontend/lib/router.dart @@ -2,7 +2,7 @@ import 'package:dashbaord/constants/enums/lost_and_found.dart'; import 'package:dashbaord/error.dart'; import 'package:dashbaord/models/mess_menu_model.dart'; import 'package:dashbaord/models/user_model.dart'; -import 'package:dashbaord/screens/bus_ticket_screen.dart'; +import 'package:dashbaord/screens/city_bus_screen.dart'; import 'package:dashbaord/screens/bus_timings_screen.dart'; import 'package:dashbaord/screens/cab_add_screen.dart'; import 'package:dashbaord/screens/cab_add_success.dart'; @@ -119,11 +119,11 @@ class AppRouter { }, ), GoRoute( - path: '/bus_ticket', + path: '/city_bus', pageBuilder: (context, state) { return CustomTransitionPage( key: state.pageKey, - child: BusTicketScreen(), + child: CityBusScreen(), transitionsBuilder: (context, animation, secondaryAnimation, child) { return SlideTransition( diff --git a/frontend/lib/screens/city_bus_screen.dart b/frontend/lib/screens/city_bus_screen.dart new file mode 100644 index 0000000..27b86ca --- /dev/null +++ b/frontend/lib/screens/city_bus_screen.dart @@ -0,0 +1,348 @@ +import 'package:dashbaord/services/shared_service.dart'; +import 'package:dashbaord/utils/bus_schedule.dart'; +import 'package:flutter/material.dart'; +import 'package:dashbaord/services/api_service.dart'; +import 'package:go_router/go_router.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:qr_flutter/qr_flutter.dart'; + +import '../models/transport_qr_model.dart'; +import '../widgets/bus_timing_list_widget.dart'; + +class CityBusScreen extends StatefulWidget { + CityBusScreen({super.key}); + + @override + State createState() => _CityBusScreenState(); +} + +class _CityBusScreenState extends State + with TickerProviderStateMixin { + final TextEditingController transactionIdController = TextEditingController(); + + late final Map toIITH; + late final Map fromIITH; + + final ApiServices apiServices = ApiServices(); + + Map? transactionDetails; + + late TabController _tabController; + + String startingPoint = "Starting"; + String destination = "Destination"; + + CityBusSchedule? busSchedule; + + void showError({String? msg}) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(msg ?? 'Please login to use this feature'), + duration: const Duration(milliseconds: 1500), + behavior: SnackBarBehavior.floating, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + ), + ); + } + + Future fetchBus() async { + final response = await ApiServices().getCityBusSchedule(context); + if (response == null) { + showError(msg: "Server Refresh Failed..."); + final res = await SharedService().getCityBusSchedule(); + + setState(() { + busSchedule = res; + toIITH = busSchedule?.toIITH ?? {}; + fromIITH = busSchedule?.fromIITH ?? {}; + }); + } else { + setState(() { + busSchedule = response; + toIITH = busSchedule?.toIITH ?? {}; + fromIITH = busSchedule?.fromIITH ?? {}; + }); + } + } + + @override + void initState() { + super.initState(); + _tabController = TabController(length: 3, vsync: this); + fetchBus(); + } + + @override + void dispose() { + _tabController + .dispose(); // Dispose of the tab controller when the widget is removed + super.dispose(); + } + + Future submitTransactionID() async { + final result = + await apiServices.submitTransactionID(transactionIdController.text); + + SharedService() + .saveUserDetails(name: "SKGEzhil", email: "ep23btech11016@iith.ac.in"); + + final email = (await SharedService().getUserDetails())['email']; + final name = (await SharedService().getUserDetails())['name']; + + setState(() { + final transactionId = (result['data']).transactionId; + final PaymentTime = result['data'].paymentTime; + final BusTime = result['data'].busTiming; + + transactionDetails = { + 'transactionId': transactionId, + 'travelDate': '2022-01-01', + 'paymentTime': PaymentTime, + 'busTiming': BusTime, + 'name': name, + 'email': email, + }; + }); + + _tabController.animateTo(2); + } + + @override + Widget build(BuildContext context) { + return DefaultTabController( + length: 3, + child: Scaffold( + appBar: AppBar( + title: const Text('City Bus', + style: TextStyle( + color: Colors.black, + fontSize: 20, + fontWeight: FontWeight.bold)), + bottom: TabBar( + controller: _tabController, + tabs: const [ + Tab(text: 'Payment Form'), + Tab(text: 'Bus Schedule'), + Tab(text: 'Show QR'), + ], + )), + body: TabBarView( + controller: _tabController, + children: [paymentFormTab(), schedule(), showQRTab()], + ), + ), + ); + } + + Column paymentFormTab() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + padding: const EdgeInsets.all(20), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + startingPoint, + style: TextStyle( + color: Colors.black.withOpacity(0.8), + fontWeight: FontWeight.bold, + fontSize: 25), + ), + Text( + 'Destination', + style: TextStyle( + color: Colors.black.withOpacity(0.8), + fontWeight: FontWeight.bold, + fontSize: 25), + ), + ], + ), + IconButton( + onPressed: () {}, + icon: Icon( + Icons.swap_vert_rounded, + size: 40, + )), + ], + ), + ), + Padding( + padding: const EdgeInsets.only(left: 20.0, right: 20), + child: Text( + 'Transaction ID for next bus will be noted from 4pm', + style: TextStyle( + color: Colors.black.withOpacity(0.8), + fontWeight: FontWeight.w500, + fontSize: 16), + ), + ), + SizedBox(height: 20), + Padding( + padding: const EdgeInsets.all(8.0), + child: ClipRRect( + borderRadius: BorderRadius.circular(10), + child: TextField( + controller: transactionIdController, + decoration: InputDecoration( + // labelText: 'Transaction ID', + hintText: 'Transaction ID', + filled: true, + fillColor: Colors.black.withOpacity(0.1), + border: InputBorder.none, + ), + ), + ), + ), + Expanded(child: SizedBox()), + Padding( + padding: const EdgeInsets.all(8.0), + child: Align( + child: InkWell( + customBorder: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(50), + ), + onTap: submitTransactionID, + child: Container( + decoration: BoxDecoration( + border: Border.all(color: Colors.black.withOpacity(0.3)), + borderRadius: BorderRadius.circular(50), + ), + child: Padding( + padding: const EdgeInsets.fromLTRB(30.0, 8, 30, 8), + child: Text('Submit', + style: + TextStyle(fontWeight: FontWeight.w500, fontSize: 16)), + ), + ), + ), + ), + ), + ], + ); + } + + Column showQRTab() { + return Column( + children: [ + transactionDetails != null + ? Column( + children: [ + QrImageView( + data: transactionDetails.toString(), + version: QrVersions.auto, + size: 200.0, + ), + SizedBox(height: 20), + Text('${transactionDetails?['name']}', style: TextStyle( + fontWeight: FontWeight.bold, + color: Colors.black.withOpacity(0.8), + fontSize: 24 + ),), + Text('${transactionDetails?['email']}', style: TextStyle( + fontWeight: FontWeight.bold, + color: Colors.black.withOpacity(0.8), + fontSize: 20 + ),), + Text('${transactionDetails?['travelDate']}, ${transactionDetails?['busTiming']}', style: TextStyle( + fontWeight: FontWeight.w500, + color: Colors.black.withOpacity(0.8), + fontSize: 24 + ),), + SizedBox(height: 20,), + Text('Transaction ID: ${transactionDetails?['transactionId']}', style: TextStyle( + fontWeight: FontWeight.w500, + color: Colors.black.withOpacity(0.8), + fontSize: 16 + ),), + ], + ) + : SizedBox(), + ], + ); + } + + Column schedule(){ + return Column( + children: [ + Expanded( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: BusTimingList( + from: startingPoint, + destination: destination, + timings: toIITH, + ), + ), + const SizedBox(width: 4.0), + Expanded( + child: BusTimingList( + from: destination, + destination: startingPoint, + timings: fromIITH, + ), + ), + ], + ), + ), + // _buildNoteWidget(), + ], + ); + } + +} + +class FullScheduleWidget extends StatelessWidget { + final Map toIITH; + final Map fromIITH; + + const FullScheduleWidget({ + Key? key, + required this.toIITH, + required this.fromIITH, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + Expanded( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: BusTimingList( + from: 'Maingate', + destination: 'Hostel', + timings: toIITH, + ), + ), + const SizedBox(width: 4.0), + Expanded( + child: BusTimingList( + from: 'Hostel', + destination: 'Maingate', + timings: fromIITH, + ), + ), + ], + ), + ), + _buildNoteWidget(), + ], + ); + } + + Widget _buildNoteWidget() { + return Text( + '* indicates EV', + style: GoogleFonts.inter(fontSize: 14), + ); + } +} diff --git a/frontend/lib/screens/home_screen.dart b/frontend/lib/screens/home_screen.dart index abbfe06..ebb96b7 100644 --- a/frontend/lib/screens/home_screen.dart +++ b/frontend/lib/screens/home_screen.dart @@ -548,7 +548,7 @@ class _HomeScreenState extends State { title: 'Patencheru Bus', child: 'assets/icons/cab-sharing-icon.svg', onTap: () { - context.push('/bus_ticket'); + context.push('/city_bus'); }, ), diff --git a/frontend/lib/services/api_service.dart b/frontend/lib/services/api_service.dart index c5e7318..fb54923 100644 --- a/frontend/lib/services/api_service.dart +++ b/frontend/lib/services/api_service.dart @@ -22,6 +22,7 @@ import 'package:google_sign_in/google_sign_in.dart'; import 'package:image_picker/image_picker.dart'; import 'package:path_provider/path_provider.dart'; +import '../models/transport_qr_model.dart'; import 'dio_non_web_config.dart' if (dart.library.html) 'dio_web_config.dart'; class ApiServices { @@ -962,4 +963,64 @@ class ApiServices { return -1; } } + + Future> submitTransactionID(String transactionId) async { + final dio = Dio(); + + // Define the request URL + const url = 'http://10.0.2.2:8000/transport/qr'; + + try { + // Sending the POST request + final response = await dio.post( + url, + data: { + 'transactionId': transactionId, + }, + ); + + // Handling the response + if (response.statusCode == 200) { + final data = response.data; + print("Transaction ID: ${data['transactionId']}"); + print("Payment Time: ${data['paymentTime']}"); + print("Travel Date: ${data['travelDate']}"); + print("But Timing: ${data['busTiming']}"); + + final transaction = TransactionQRModel.fromJson(data); + return { + 'status': response.statusCode, + 'data': transaction, + }; + + } else { + print('Error: ${response.statusCode}'); + return { + 'error': 'Failed to send request ${response.statusMessage}', + 'status': response.statusCode + }; + } + } on DioException catch (e) { + print('Request failed: $e'); + return { + 'error': e.response?.data['detail'], + 'status': e.response?.statusCode + }; + } + } + + Future getCityBusSchedule(BuildContext context) async { + try { + debugPrint("Making request to: ${dio.options.baseUrl}/transport/cityBus"); + final response = await dio.get('http://10.0.2.2:8000/transport/cityBus'); + + final data = response.data; + return CityBusSchedule.fromJson(data); + } catch (e) { + debugPrint("Failed to fetch bus schedule: $e"); + return null; + } + } + + } diff --git a/frontend/lib/services/shared_service.dart b/frontend/lib/services/shared_service.dart index f2a9794..087fa98 100644 --- a/frontend/lib/services/shared_service.dart +++ b/frontend/lib/services/shared_service.dart @@ -11,6 +11,7 @@ class SharedService { static const String _keyTimetable = 'timetable'; static const String _keyMessMenu = 'mess_menu'; static const String _keyBusSchedule = 'bus_schedule'; + static const String _keyCityBusSchedule = 'city_bus_schedule'; Future saveUserDetails({ required String name, @@ -87,6 +88,12 @@ class SharedService { await prefs.setString(_keyBusSchedule, busScheduleJson); } + Future saveCityBusSchedule(CityBusSchedule cityBusSchedule) async { + final prefs = await SharedPreferences.getInstance(); + final cityBusScheduleJson = jsonEncode(cityBusSchedule.toJson()); + await prefs.setString(_keyCityBusSchedule, cityBusScheduleJson); + } + Future getBusSchedule() async { final prefs = await SharedPreferences.getInstance(); final busScheduleJson = prefs.getString(_keyBusSchedule); @@ -97,6 +104,16 @@ class SharedService { return null; } + Future getCityBusSchedule() async { + final prefs = await SharedPreferences.getInstance(); + final cityBusScheduleJson = prefs.getString(_keyCityBusSchedule); + if (cityBusScheduleJson != null) { + final Map cityBusScheduleMap = jsonDecode(cityBusScheduleJson); + return CityBusSchedule.fromJson(cityBusScheduleMap); + } + return null; + } + Future clearAllData() async { final prefs = await SharedPreferences.getInstance(); await prefs.clear(); diff --git a/frontend/lib/utils/bus_schedule.dart b/frontend/lib/utils/bus_schedule.dart index 7ff6903..1b2b799 100644 --- a/frontend/lib/utils/bus_schedule.dart +++ b/frontend/lib/utils/bus_schedule.dart @@ -66,3 +66,54 @@ class BusSchedule { }; } } + +class CityBusSchedule { + final Map fromIITH; + final Map toIITH; + + CityBusSchedule({ + required this.fromIITH, + required this.toIITH, + }); + + factory CityBusSchedule.fromJson(Map json) { + Map fromIITH = {}; + json['bus']['iith-ptc'].forEach((item) { + fromIITH[item] = 0; // Bus values should be 0 + }); + + Map toIITH = {}; + json['bus']['ptc-iith'].forEach((item) { + toIITH[item] = 0; // Bus values should be 0 + }); + + return CityBusSchedule( + fromIITH: fromIITH, + toIITH: toIITH, + ); + } + + Map toJson() { + List busFromIITH = []; + List busToIITH = []; + + fromIITH.forEach((key, value) { + if (value == 0) { + busFromIITH.add(key); + } + }); + + toIITH.forEach((key, value) { + if (value == 0) { + busToIITH.add(key); + } + }); + + return { + 'bus': { + 'iith-ptc': busFromIITH, + 'ptc-iith': busToIITH, + } + }; + } +} diff --git a/frontend/pubspec.yaml b/frontend/pubspec.yaml index 5b0c6f5..732902d 100644 --- a/frontend/pubspec.yaml +++ b/frontend/pubspec.yaml @@ -69,6 +69,7 @@ dependencies: paged_vertical_calendar: ^1.1.9 collection: ^1.18.0 go_router: ^14.3.0 + qr_flutter: ^4.1.0 dev_dependencies: flutter_test: @@ -129,7 +130,7 @@ flutter: assets: - assets/icons/ - assets/lost_and_found/ - - .env +# - .env - shorebird.yaml # - images/a_dot_ham.jpeg From 15626d1576a43ea071c5740cbcfa1ed9bb8f4331 Mon Sep 17 00:00:00 2001 From: SKGEzhil Date: Sun, 17 Nov 2024 11:52:39 +0530 Subject: [PATCH 3/5] feat: store transaction details in db, show whether QR is already used --- backend/backend/Routes/Transport/qr.py | 70 ++++++++++++++++++++- backend/backend/queries/transport.py | 52 +++++++++++++++ frontend/lib/models/transport_qr_model.dart | 11 +++- frontend/lib/screens/city_bus_screen.dart | 17 ++++- frontend/lib/services/api_service.dart | 1 + 5 files changed, 146 insertions(+), 5 deletions(-) create mode 100644 backend/backend/queries/transport.py diff --git a/backend/backend/Routes/Transport/qr.py b/backend/backend/Routes/Transport/qr.py index 9db6773..8550139 100644 --- a/backend/backend/Routes/Transport/qr.py +++ b/backend/backend/Routes/Transport/qr.py @@ -3,6 +3,9 @@ import os from pydantic import BaseModel from datetime import datetime +from backend.backend.utils import conn + +from backend.backend.queries.transport import log_transaction_to_db, scan_qr router = APIRouter(prefix="/transport", tags=["transport_schedule"]) dir = os.path.dirname(os.path.realpath(__file__)) @@ -19,7 +22,10 @@ class TransactionResponse(BaseModel): paymentTime: str # hh:mm dd/mm/yy travelDate: str # dd/mm/yy busTiming: str # hh:mm + isUsed: bool +class ScanQRModel(BaseModel): + isScanned: bool @router.post("/qr", response_model=TransactionResponse) async def process_transaction(request: TransactionRequest): @@ -28,9 +34,69 @@ async def process_transaction(request: TransactionRequest): travel_date = datetime.now().strftime("%d/%m/%y") bus_timing = "14:30" # Example bus timing; replace with actual data logic if needed - return TransactionResponse( + # Prepare the response + response = TransactionResponse( transactionId=request.transactionId, paymentTime=payment_time, travelDate=travel_date, - busTiming=bus_timing + busTiming=bus_timing, + isUsed=False ) + + # Log the transaction in the database + transaction_data = { + "transaction_id": response.transactionId, + "payment_time": datetime.now(), + "travel_date": datetime.now(), + "bus_timing": response.busTiming, + "isUsed": False + } + result = log_transaction_to_db(transaction_data) + + if not result: + query = """ + SELECT payment_time, travel_date, bus_timing, isUsed + FROM transactions + WHERE transaction_id = %s; + """ + + try: + with conn.cursor() as cur: + cur.execute(query, (request.transactionId,)) + result = cur.fetchone() + if not result: + return {"error": "Transaction not found"}, 404 + + payment_time, travel_date, bus_timing, is_used = result + + # Prepare the response + response = TransactionResponse( + transactionId=request.transactionId, + paymentTime=payment_time.strftime("%H:%M %d/%m/%y"), + travelDate=travel_date.strftime("%d/%m/%y"), + busTiming=bus_timing.strftime("%H:%M"), + isUsed=is_used + ) + + return response + + except Exception as e: + print(f"Error fetching transaction: {e}") + return {"error": "Internal server error"}, 500 + + return response + +@router.post("/qr/scan", response_model= ScanQRModel) +async def scan_qr_code(request: TransactionRequest): + # Sample QR code scanning logic + + transaction_data = { + "transaction_id": request.transactionId, + } + + result = scan_qr(transaction_data) + + return ScanQRModel(isScanned=result) + + + diff --git a/backend/backend/queries/transport.py b/backend/backend/queries/transport.py new file mode 100644 index 0000000..c1f8d45 --- /dev/null +++ b/backend/backend/queries/transport.py @@ -0,0 +1,52 @@ +from pypika import Query, Table, functions as fn, Order +from typing import Dict, Any +from backend.backend.utils import conn + +def log_transaction_to_db(transaction_data: Dict[str, Any]) -> bool: + """ + Function to log transaction data into PostgreSQL. + """ + query = """ + INSERT INTO transactions (transaction_id, payment_time, travel_date, bus_timing, isUsed) + VALUES (%s, %s, %s, %s, %s); + """ + values = ( + transaction_data["transaction_id"], + transaction_data["payment_time"], + transaction_data["travel_date"], + transaction_data["bus_timing"], + transaction_data["isUsed"] + ) + + try: + with conn.cursor() as cur: + cur.execute(query, values) + conn.commit() + return True + except Exception as e: + conn.rollback() + print(f"Error logging transaction: {e}") + return False + +def scan_qr(transaction_data: Dict[str, Any]) -> bool: + """ + Function to log transaction data into PostgreSQL. + """ + query = """ + UPDATE transactions + SET isUsed = TRUE + WHERE transaction_id = %s; +""" + values = ( + transaction_data["transaction_id"], + ) + + try: + with conn.cursor() as cur: + cur.execute(query, values) + conn.commit() + return True + except Exception as e: + conn.rollback() + print(f"Error logging transaction: {e}") + return False \ No newline at end of file diff --git a/frontend/lib/models/transport_qr_model.dart b/frontend/lib/models/transport_qr_model.dart index 111ac35..f0cfc35 100644 --- a/frontend/lib/models/transport_qr_model.dart +++ b/frontend/lib/models/transport_qr_model.dart @@ -3,12 +3,14 @@ class TransactionQRModel { final String paymentTime; final String travelDate; final String busTiming; + final bool isUsed; TransactionQRModel({ required this.transactionId, required this.paymentTime, required this.travelDate, required this.busTiming, + required this.isUsed, }); // Factory constructor to create a TransactionResponse from JSON @@ -18,6 +20,7 @@ class TransactionQRModel { paymentTime: json['paymentTime'] as String, travelDate: json['travelDate'] as String, busTiming: json['busTiming'] as String, + isUsed: json['isUsed'] as bool, ); } @@ -28,6 +31,7 @@ class TransactionQRModel { 'paymentTime': paymentTime, 'travelDate': travelDate, 'busTiming': busTiming, + 'isUsed': isUsed, }; } @@ -41,6 +45,7 @@ class TransactionQRModel { String paymentTime = ''; String travelDate = ''; String busTiming = ''; + bool isUsed = false; // Extract the key-value pairs for (String part in parts) { @@ -62,6 +67,9 @@ class TransactionQRModel { case 'travelDate': travelDate = value; break; + case 'isUsed': + isUsed = value.toLowerCase() == 'true'; + break; } } } @@ -71,6 +79,7 @@ class TransactionQRModel { transactionId: transactionId, paymentTime: paymentTime, busTiming: busTiming, - travelDate: travelDate); + travelDate: travelDate, + isUsed: isUsed); } } diff --git a/frontend/lib/screens/city_bus_screen.dart b/frontend/lib/screens/city_bus_screen.dart index 27b86ca..3baea41 100644 --- a/frontend/lib/screens/city_bus_screen.dart +++ b/frontend/lib/screens/city_bus_screen.dart @@ -93,6 +93,7 @@ class _CityBusScreenState extends State final transactionId = (result['data']).transactionId; final PaymentTime = result['data'].paymentTime; final BusTime = result['data'].busTiming; + final isUsed = result['data'].isUsed; transactionDetails = { 'transactionId': transactionId, @@ -101,6 +102,7 @@ class _CityBusScreenState extends State 'busTiming': BusTime, 'name': name, 'email': email, + 'isUsed': isUsed, }; }); @@ -154,7 +156,7 @@ class _CityBusScreenState extends State fontSize: 25), ), Text( - 'Destination', + destination, style: TextStyle( color: Colors.black.withOpacity(0.8), fontWeight: FontWeight.bold, @@ -163,7 +165,13 @@ class _CityBusScreenState extends State ], ), IconButton( - onPressed: () {}, + onPressed: () { + setState(() { + final temp = startingPoint; + startingPoint = destination; + destination = temp; + }); + }, icon: Icon( Icons.swap_vert_rounded, size: 40, @@ -253,6 +261,11 @@ class _CityBusScreenState extends State color: Colors.black.withOpacity(0.8), fontSize: 24 ),), + Text('isUsed: ${transactionDetails?['isUsed'].toString()}', style: TextStyle( + fontWeight: FontWeight.w500, + color: Colors.black.withOpacity(0.8), + fontSize: 16 + ),), SizedBox(height: 20,), Text('Transaction ID: ${transactionDetails?['transactionId']}', style: TextStyle( fontWeight: FontWeight.w500, diff --git a/frontend/lib/services/api_service.dart b/frontend/lib/services/api_service.dart index fb54923..ac52432 100644 --- a/frontend/lib/services/api_service.dart +++ b/frontend/lib/services/api_service.dart @@ -986,6 +986,7 @@ class ApiServices { print("Payment Time: ${data['paymentTime']}"); print("Travel Date: ${data['travelDate']}"); print("But Timing: ${data['busTiming']}"); + print("Is Used: ${data['isUsed']}"); final transaction = TransactionQRModel.fromJson(data); return { From c5cde31bb5220fb4a3299a0cdb790d53761f922b Mon Sep 17 00:00:00 2001 From: SKGEzhil Date: Mon, 18 Nov 2024 01:57:42 +0530 Subject: [PATCH 4/5] fix: change server base url to production server, UI fixes in home screen and small card widget --- frontend/lib/screens/bus_ticket_screen.dart | 17 ---- frontend/lib/screens/city_bus_screen.dart | 4 +- frontend/lib/screens/home_screen.dart | 99 ++++++++++--------- frontend/lib/services/api_service.dart | 11 ++- frontend/lib/widgets/homeScreenCardSmall.dart | 88 +++++++++-------- 5 files changed, 106 insertions(+), 113 deletions(-) delete mode 100644 frontend/lib/screens/bus_ticket_screen.dart diff --git a/frontend/lib/screens/bus_ticket_screen.dart b/frontend/lib/screens/bus_ticket_screen.dart deleted file mode 100644 index 441ab74..0000000 --- a/frontend/lib/screens/bus_ticket_screen.dart +++ /dev/null @@ -1,17 +0,0 @@ -import 'package:flutter/material.dart'; - -class BusTicketScreen extends StatelessWidget { - const BusTicketScreen({super.key}); - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: const Text('Bus Ticket'), - ), - body: const Center( - child: Text('Bus Ticket Screen'), - ), - ); - } -} diff --git a/frontend/lib/screens/city_bus_screen.dart b/frontend/lib/screens/city_bus_screen.dart index 3baea41..acb7d98 100644 --- a/frontend/lib/screens/city_bus_screen.dart +++ b/frontend/lib/screens/city_bus_screen.dart @@ -83,8 +83,8 @@ class _CityBusScreenState extends State final result = await apiServices.submitTransactionID(transactionIdController.text); - SharedService() - .saveUserDetails(name: "SKGEzhil", email: "ep23btech11016@iith.ac.in"); + // SharedService() + // .saveUserDetails(name: "SKGEzhil", email: "ep23btech11016@iith.ac.in"); final email = (await SharedService().getUserDetails())['email']; final name = (await SharedService().getUserDetails())['name']; diff --git a/frontend/lib/screens/home_screen.dart b/frontend/lib/screens/home_screen.dart index ebb96b7..db43cfe 100644 --- a/frontend/lib/screens/home_screen.dart +++ b/frontend/lib/screens/home_screen.dart @@ -507,55 +507,60 @@ class _HomeScreenState extends State { const SizedBox(height: 20), HomeScreenMessMenu(messMenu: messMenu), const SizedBox(height: 20), - SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: Padding( - padding: const EdgeInsets.only(bottom: 8.0), - child: Row( - children: [ - HomeScreenCardSmall( - isComingSoon: false, - title: 'Cab Sharing', - child: 'assets/icons/cab-sharing-icon.svg', - onTap: () { - widget.isGuest - ? showError() - : context.push('/cabsharing', extra: { - 'user': userModel ?? - UserModel( - email: "user@iith.ac.in", - name: "User"), - 'image': image, - }); - }, - ), - const SizedBox(width: 10), - HomeScreenCardSmall( - isComingSoon: false, - isLnF: true, - title: 'Lost & Found', - child: 'assets/icons/magnifying-icon.svg', - onTap: widget.isGuest - ? showError - : () => context.push('/lnf', extra: { - 'currentUserEmail': - userModel?.email ?? 'user@iith.ac.in' - }), - ), - const SizedBox(height: 20), - HomeScreenCardSmall( - isComingSoon: false, - title: 'Patencheru Bus', - child: 'assets/icons/cab-sharing-icon.svg', - onTap: () { - context.push('/city_bus'); - }, - ), - - ], + + Wrap( + spacing: 10.0, // Horizontal spacing between cards + runSpacing: 10.0, // Vertical spacing between rows + children: [ + SizedBox( + width: MediaQuery.of(context).size.width / 2 - 25, // Half of the screen width minus spacing + child: HomeScreenCardSmall( + isComingSoon: false, + title: 'Cab Sharing', + child: 'assets/icons/cab-sharing-icon.svg', + onTap: () { + widget.isGuest + ? showError() + : context.push('/cabsharing', extra: { + 'user': userModel ?? + UserModel( + email: "user@iith.ac.in", + name: "User"), + 'image': image, + }); + }, + ), ), - ), + SizedBox( + width: MediaQuery.of(context).size.width / 2 - 25, + child: HomeScreenCardSmall( + isComingSoon: false, + isLnF: true, + title: 'Lost & Found', + child: 'assets/icons/magnifying-icon.svg', + onTap: widget.isGuest + ? showError + : () => context.push('/lnf', extra: { + 'currentUserEmail': userModel?.email ?? 'user@iith.ac.in' + }), + ), + ), + SizedBox( + width: MediaQuery.of(context).size.width / 2 - 25, + child: HomeScreenCardSmall( + isComingSoon: false, + title: 'Patencheru Bus', + child: 'assets/icons/cab-sharing-icon.svg', + onTap: () { + widget.isGuest ? + showError() : + context.push('/city_bus'); + }, + ), + ), + ], ), + const SizedBox(height: 20), // HomeCardNoOptions( // isComingSoon: true, diff --git a/frontend/lib/services/api_service.dart b/frontend/lib/services/api_service.dart index ac52432..1057519 100644 --- a/frontend/lib/services/api_service.dart +++ b/frontend/lib/services/api_service.dart @@ -32,8 +32,8 @@ class ApiServices { ApiServices._internal(); PersistCookieJar? cookieJar; - // String backendUrl = dotenv.env["BACKEND_URL"] ?? "https://api.iith.dev/"; - String backendUrl = "https://api.iith.dev/"; + String backendUrl = dotenv.env["BACKEND_URL"] ?? "https://api.iith.dev/"; + // String backendUrl = "https://api.iith.dev/"; Dio dio = Dio(); @@ -968,8 +968,8 @@ class ApiServices { final dio = Dio(); // Define the request URL - const url = 'http://10.0.2.2:8000/transport/qr'; - + // const url = 'http://10.0.2.2:8000/transport/qr'; + final url = '${dio.options.baseUrl}/transport/qr'; try { // Sending the POST request final response = await dio.post( @@ -1013,7 +1013,8 @@ class ApiServices { Future getCityBusSchedule(BuildContext context) async { try { debugPrint("Making request to: ${dio.options.baseUrl}/transport/cityBus"); - final response = await dio.get('http://10.0.2.2:8000/transport/cityBus'); + // final response = await dio.get('http://10.0.2.2:8000/transport/cityBus'); + final response = await dio.get('${dio.options.baseUrl}/transport/cityBus'); final data = response.data; return CityBusSchedule.fromJson(data); diff --git a/frontend/lib/widgets/homeScreenCardSmall.dart b/frontend/lib/widgets/homeScreenCardSmall.dart index 0cd5a97..36ccebb 100644 --- a/frontend/lib/widgets/homeScreenCardSmall.dart +++ b/frontend/lib/widgets/homeScreenCardSmall.dart @@ -3,6 +3,7 @@ import 'dart:math'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; + class HomeScreenCardSmall extends StatelessWidget { final String title; final dynamic child; @@ -27,8 +28,6 @@ class HomeScreenCardSmall extends StatelessWidget { return InkWell( onTap: onTap, child: Container( - // clipBehavior: Clip.hardEdge, - height: 170, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(10), @@ -41,52 +40,57 @@ class HomeScreenCardSmall extends StatelessWidget { ), ], ), - child: Column( - children: [ - Stack( - children: [ + child: Align( + alignment: Alignment.center, + child: Wrap( + direction: Axis.vertical, + children: [ Stack( children: [ - isImageShow - ? SvgPicture.asset( - child, - width: min(0.32 * screenWidth, 200), - ) - : Container(), + Stack( + children: [ + isImageShow + ? SvgPicture.asset( + child, + fit: BoxFit.contain, + height: min(0.32 * screenWidth, 200), + ) + : Container(), + ], + ), + if (isComingSoon) + Container( + decoration: BoxDecoration( + color: Theme.of(context).brightness == Brightness.dark + ? const Color.fromARGB(255, 57, 57, 57) + .withOpacity(0.5) + : Colors.white.withOpacity(0.5)), + child: Center( + child: SizedBox( + height: 100, + child: Image.asset( + "assets/icons/comingsoon.png", + ))), + ) ], ), - if (isComingSoon) - Container( - decoration: BoxDecoration( - color: Theme.of(context).brightness == Brightness.dark - ? const Color.fromARGB(255, 57, 57, 57) - .withOpacity(0.5) - : Colors.white.withOpacity(0.5)), - child: Center( - child: SizedBox( - height: 100, - child: Image.asset( - "assets/icons/comingsoon.png", - ))), - ) - ], - ), - Expanded(child: SizedBox()), - Padding( - padding: const EdgeInsets.only(left: 8.0, right: 8.0), - child: Text( - title, - style: const TextStyle( - color: Colors.black, - fontWeight: FontWeight.bold, - fontSize: 20, + // Expanded(child: SizedBox()), + Padding( + padding: const EdgeInsets.only(left: 8.0, right: 8.0), + child: Text( + title, + style: const TextStyle( + color: Colors.black, + fontWeight: FontWeight.bold, + fontSize: 20, + ), + ), ), - ), + const SizedBox(height: 10), + ], ), - const SizedBox(height: 10), - ], ), - ), - ); + ), + ); } } From 6c4087ba076f25133f6ea4007e4f1d6be2236751 Mon Sep 17 00:00:00 2001 From: SKGEzhil Date: Wed, 20 Nov 2024 11:04:00 +0530 Subject: [PATCH 5/5] fix: dark theme color fix on city bus screen --- frontend/lib/screens/city_bus_screen.dart | 116 ++++++++++++------ frontend/lib/widgets/homeScreenCardSmall.dart | 6 +- 2 files changed, 80 insertions(+), 42 deletions(-) diff --git a/frontend/lib/screens/city_bus_screen.dart b/frontend/lib/screens/city_bus_screen.dart index acb7d98..be51ac5 100644 --- a/frontend/lib/screens/city_bus_screen.dart +++ b/frontend/lib/screens/city_bus_screen.dart @@ -115,9 +115,9 @@ class _CityBusScreenState extends State length: 3, child: Scaffold( appBar: AppBar( - title: const Text('City Bus', + title: Text('City Bus', style: TextStyle( - color: Colors.black, + color: Theme.of(context).textTheme.bodyLarge?.color, fontSize: 20, fontWeight: FontWeight.bold)), bottom: TabBar( @@ -151,14 +151,22 @@ class _CityBusScreenState extends State Text( startingPoint, style: TextStyle( - color: Colors.black.withOpacity(0.8), + color: Theme.of(context) + .textTheme + .bodyLarge + ?.color + ?.withOpacity(0.8), fontWeight: FontWeight.bold, fontSize: 25), ), Text( destination, style: TextStyle( - color: Colors.black.withOpacity(0.8), + color: Theme.of(context) + .textTheme + .bodyLarge + ?.color + ?.withOpacity(0.8), fontWeight: FontWeight.bold, fontSize: 25), ), @@ -184,7 +192,11 @@ class _CityBusScreenState extends State child: Text( 'Transaction ID for next bus will be noted from 4pm', style: TextStyle( - color: Colors.black.withOpacity(0.8), + color: Theme.of(context) + .textTheme + .bodyLarge + ?.color + ?.withOpacity(0.8), fontWeight: FontWeight.w500, fontSize: 16), ), @@ -200,7 +212,11 @@ class _CityBusScreenState extends State // labelText: 'Transaction ID', hintText: 'Transaction ID', filled: true, - fillColor: Colors.black.withOpacity(0.1), + fillColor: Theme.of(context) + .textTheme + .bodyLarge + ?.color + ?.withOpacity(0.1), border: InputBorder.none, ), ), @@ -217,7 +233,10 @@ class _CityBusScreenState extends State onTap: submitTransactionID, child: Container( decoration: BoxDecoration( - border: Border.all(color: Colors.black.withOpacity(0.3)), + border: Border.all( + color: Theme.of(context).brightness == Brightness.light + ? Colors.black.withOpacity(0.3) + : Colors.white.withOpacity(0.3)), borderRadius: BorderRadius.circular(50), ), child: Padding( @@ -239,47 +258,67 @@ class _CityBusScreenState extends State children: [ transactionDetails != null ? Column( - children: [ - QrImageView( + children: [ + QrImageView( data: transactionDetails.toString(), + eyeStyle: QrEyeStyle( + eyeShape: QrEyeShape.square, + color: Theme.of(context).textTheme.bodyLarge?.color, + ), + dataModuleStyle: QrDataModuleStyle( + dataModuleShape: QrDataModuleShape.square, + color: Theme.of(context).textTheme.bodyLarge?.color, + ), version: QrVersions.auto, size: 200.0, ), SizedBox(height: 20), - Text('${transactionDetails?['name']}', style: TextStyle( - fontWeight: FontWeight.bold, - color: Colors.black.withOpacity(0.8), - fontSize: 24 - ),), - Text('${transactionDetails?['email']}', style: TextStyle( - fontWeight: FontWeight.bold, - color: Colors.black.withOpacity(0.8), - fontSize: 20 - ),), - Text('${transactionDetails?['travelDate']}, ${transactionDetails?['busTiming']}', style: TextStyle( - fontWeight: FontWeight.w500, - color: Colors.black.withOpacity(0.8), - fontSize: 24 - ),), - Text('isUsed: ${transactionDetails?['isUsed'].toString()}', style: TextStyle( - fontWeight: FontWeight.w500, - color: Colors.black.withOpacity(0.8), - fontSize: 16 - ),), - SizedBox(height: 20,), - Text('Transaction ID: ${transactionDetails?['transactionId']}', style: TextStyle( - fontWeight: FontWeight.w500, - color: Colors.black.withOpacity(0.8), - fontSize: 16 - ),), - ], - ) + Text( + '${transactionDetails?['name']}', + style: TextStyle( + fontWeight: FontWeight.bold, + color: Theme.of(context).textTheme.bodyLarge?.color?.withOpacity(0.8), + fontSize: 24), + ), + Text( + '${transactionDetails?['email']}', + style: TextStyle( + fontWeight: FontWeight.bold, + color: Theme.of(context).textTheme.bodyLarge?.color?.withOpacity(0.8), + fontSize: 20), + ), + Text( + '${transactionDetails?['travelDate']}, ${transactionDetails?['busTiming']}', + style: TextStyle( + fontWeight: FontWeight.w500, + color: Theme.of(context).textTheme.bodyLarge?.color?.withOpacity(0.8), + fontSize: 24), + ), + Text( + 'isUsed: ${transactionDetails?['isUsed'].toString()}', + style: TextStyle( + fontWeight: FontWeight.w500, + color: Theme.of(context).textTheme.bodyLarge?.color?.withOpacity(0.8), + fontSize: 16), + ), + SizedBox( + height: 20, + ), + Text( + 'Transaction ID: ${transactionDetails?['transactionId']}', + style: TextStyle( + fontWeight: FontWeight.w500, + color: Theme.of(context).textTheme.bodyLarge?.color?.withOpacity(0.8), + fontSize: 16), + ), + ], + ) : SizedBox(), ], ); } - Column schedule(){ + Column schedule() { return Column( children: [ Expanded( @@ -308,7 +347,6 @@ class _CityBusScreenState extends State ], ); } - } class FullScheduleWidget extends StatelessWidget { diff --git a/frontend/lib/widgets/homeScreenCardSmall.dart b/frontend/lib/widgets/homeScreenCardSmall.dart index 36ccebb..ef2cedb 100644 --- a/frontend/lib/widgets/homeScreenCardSmall.dart +++ b/frontend/lib/widgets/homeScreenCardSmall.dart @@ -29,7 +29,7 @@ class HomeScreenCardSmall extends StatelessWidget { onTap: onTap, child: Container( decoration: BoxDecoration( - color: Colors.white, + color: Theme.of(context).cardColor, borderRadius: BorderRadius.circular(10), boxShadow: const [ BoxShadow( @@ -79,8 +79,8 @@ class HomeScreenCardSmall extends StatelessWidget { padding: const EdgeInsets.only(left: 8.0, right: 8.0), child: Text( title, - style: const TextStyle( - color: Colors.black, + style: TextStyle( + color: Theme.of(context).textTheme.bodyLarge?.color, fontWeight: FontWeight.bold, fontSize: 20, ),