Giter Club home page Giter Club logo

boldo-mobile's People

Contributors

elias7991 avatar everfgmolinas avatar everfgmolinasfpuna avatar joelepping avatar pa1nd avatar rbenitez94 avatar santiracca avatar zommerberg avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

boldo-mobile's Issues

Fetch and store initial profile data.

When the profile screen is opened we need to:

  1. Get the profile data from the database.
  2. Set that data inside a provider so it is available globally.
  3. Set this data for every field inside the screen.

This includes setting the data for the "Location" screen too, since this is a part of the flow.
Additionally we need to add a loading spinner while we fetch the data and show an error if fetching the data failed.

Setup provider for user settings.

We need to control the user setting state from a provider because we have multiple screens that need to share the same data.
This includes sending the data to the server from the "Location" and "Profile" screen. The main action button (submit) should do the same for both pages.

Add timezones EVERYWHERE

Problem:

Core did not accept timezones. Now it does. We should now add timezones everywhere 😊

Show information about logout

There is no message once the user is logged out. The app simply changes it state.

There should be some notification that the user has been logged out and that he/she has to login again.

iOS

Make sure the app runs on iOS - additional setup is required for deep links and eventually other libraries

Breaking changes in appointments and call

There one breaking change in appointments.

In the past, appointments would only have the status upcoming open and closed.
Now we have added "locked". This status will be added around 8 hours after the appointment has taken place and should be handled in the app UI exactly as the closed state.

There is another breaking change in the call.

During the call-end (doctor ends the call) we update the status of the appointment in the database.
It seems like there is a glitch possibility where the app has processed the call-end and switched to the home screen, before the appointment has been fully updated.

Therefore we should make sure to reload the home screen AFTER the patient has confirmed the pop-up. This should give enough time for the new status to fully settle in the database.

Translations

Some translations were not in the codebase and need another look.

  1. Doctors List
    EN: "Pull up Load more" and "Release to load more"
    ES: "Sube para cargar más" and "Suelte para cargar más"

Screenshot 2020-12-04 at 23 29 56

Improve profile validation.

We need to think about the error messages we are going to display under every screen and translate them to spanish
We also need to create the requirements for the validation on the client side (password length, firstname maxlength etc...)

Breaking Change: Doctor Search

There is a new way to pass parameters to the GET /doctors endpoint:

Search

Before: /doctors?text=text%20from%20search&languages=1,2,3&specialties=4,5,2

Now: /doctors?content=text%20from%20search&content=LanguageName,LanguageName2&content=SpecializationName

Note: it is actually important to send several content, as each content in the query will result in an AND while each item within a content (content=language1,language2) will count as an OR.

Also check https://ihub-docs.netlify.app/docs/ihub-docs/doctor which will hopefully reflect the new way already.

Pagination

We now have pagination available. The next page of doctors should start loading as soon as the user scrolls close to the end of the existing search results.

To pass pagination parameters: /doctors?count=20&offset=40

The return value is now of format: {total: int, items: []} where total contains information about the total amount of doctors.

Minor adjustments

We need to change the datetime format from YYYY-MM-DD to DD.MM.YYYY on the mobile (but still send YYY-MM-DD) to the server.

Add loading spinner to the button when it is loading. (next to the text)

App not updating logged-in state after user logged in

Problem:

The Status (e.g. header on the home screen and app bar) are not updated once the user is logged in until a SECOND click on the login.

Expected behaviour:

After user has logged in and returns to app, the UI shows the correct status.

Steps to reproduce are shown in the GIF below:
CleanShot 2020-11-29 at 17 10 36

Update profile picture.

Currently we only change the profile screen locally. We need to send the picture to the server,get the signed url, send the image to the url we get from the first response and finally send the profile picture url to the server together with all of the other data.

We also need to configure the picture component to work with URL links instead of local images.

Implement Appointments Lists UI.

We need to implement the UI for the upcoming and past appointments.
For this we need to:

  1. Fetch the appointments data once we open the Home page. ( iHub-PTI/boldo-server#7 ).
  2. Create a navbar with two tabs, where each tab can accepts a list.
  3. Once we get the data we need to separate it into upcoming/past on the client and put it into the correct navbar tab by using the end date as a main separating parameter.
  4. Create the design for the list items and the navbar
  5. Sort the lists by data. For the appointment items show the closes events on top. For the past items show the last appointment that was ended at top. (use start date for sorting)
  6. Dynamically adjust the data within the appointment item (show how soon the appointment is , days remaining). If the appointment is today show "today/¡Hoy!".
  7. Show a loading spinner on both navbar tabs when loading the data.
  8. Show error when we get something that is not 200 or 401 response status code. (snackbar error)
  9. Add a retry button if we fail to get the data first time. The retry button will retry to get the data.
  10. If the user is not logged in the show the empty state of the dashboard and change the top navbar so we don't show the patient image etc.. We need to show the boldo logo.
    11)If the user is logged in and there no appointments then show the empty state of the dashboard.
  11. Once we click on the card we will go to the reservations screen (same design just without the "confirm") button.

Registration flow for unauthenticated users

Users can use the app to explore doctors even without being logged in.

If a user is not logged in, they can go until the screen where they can select a date.

On this screen, clicking on "Reservar ahora" or "Acceptar" should show a message that you have to login or register to proceed. This could be a pop up with the following content:

  • Text: "No estás registrada. Por favor, inicie sesión o regístrese antes de continuar."
  • Button 1 (just text): Cancelar
  • Button 2: Continuar

Design: https://www.figma.com/file/s5QFKXhMS3Lcmpg5ZFb7Xo/CMR?node-id=2581%3A0

2

Here a screenshot of the screen containing the buttons that should trigger the pop-up.
Screenshot 2020-12-04 at 23 46 22

Implement Specializations Filtering

We need to implement a filter screen that will help us selected specializations we need.

  • for that we will need a "specializations" input button that will navigate us to the filter screen.
  • the filter screen should have a list of specializations that we get from the DB.
  • the filter screen should show a second list of selected specializations
  • the filter screen should have a search input, the search input should have a "remove" and "done" buttons.
  • the remove button should clear the text input state
  • the done button should set the selected specializations globally.
  • when we are typing something in the search bar we should hide the list of selected specializations
  • one the specializations are selected we need to show them in the filter's main screen.

BUG: Appointments List View in Home Screen does not show all appointments

Problem: In the Home Screen page in the past and future appointments lists You can't scroll to the bottom of the list of appointments. The user is not able to access all appointments. It's hard to spot because its roughly one viewport height of appointments but for user 1 there are actually many more appointments. You can see an example in the picture below where at the bottom you can see a part of the card is clipped and you cant scroll further down.

The list view has the physics property set to NeverScrollablePhysics. This was meant to only have the scroll controller on the parent custom scroll view. However this is not allowing for scrolling the full list.

File

add SSL Pinning

To mitigate Man-in-the-middle attacks, we could add SSL Pinning.

Error handling

Every request might fail with a 500 (Server f*** up) or 400. 400 errors include a {message:string} answer describing the problem. Every request needs to handle 500 and 400 errors and informing the user about the error + ensuring there is a way for them to recover (back button or automatically moving them back or another button to e.g. retry).

500 errors should show a generic error message, 400 errors should show a generic error message + the specific message.

Sidenote : The server can also return other error codes that are handed through from the core - e.g. 404. These should be handled as 500 or how it makes sense given the context.

Allow to switch user in boldo mobile

Currently, after logging in in Boldo using a chrome tab, the session with KC is persisted in the main browser.

Logging out in the app and logging in again, will immediately log the person into the app as the previously logged in user.

How can we allow a user to logout and login as a different user - using the app?

Example use case: One smartphone, two users.

Improve the phone number field.

Currently we have a unrestricted phone number field. Means everyone can input a too-long or too-short phone number. Currently it is a Spanish phone number only.
We need to discuss if we keep it Spanish only and how to validate the phone number correctly.

intercept API errors and try to refresh token

The server will send a 400, if the authToken is not valid anymore (every 5 to 15 minutes in production). The client should then use the refresh token to receive a new set of tokens (access AND refresh) and store those. Afterwards, the request should be triggered again.

App crashes on first booking

Problem:

The app is crashing the first time a user books an appointment.
It happens exactly after the appointment was booked. On the confirmation page there is a button that leads back to the home screen (expected behaviour). Clicking this button leaves the app with a black screen.

Steps to reproduce:

It's important to delete all the app data beforehand!
After wiping the app data:

  1. Open Boldo
  2. Go to the doctors list (you can skip the wizzard or login directly, it doesn't matter)
  3. Find a doctor that offers appointments and book a slot
  4. Click on the button on the confirmation page.
  5. See a black screen.

Breaking API Change in doctors

Problem:
Breaking change in doctors.
languages and specializations will now be arrays of objets (instead of arrays of strings).
The objects will have the shape:

{
  id: string,
  description: string
}

Task:

  • Make the app work with the new data schema
  • Remove all requests that are currently made in order to get the value of the ids (if any).
  • fix #36 which is related
  • Double check: specializations is a list, not a single value. All items from the list should be shown with a comma separated.

Implement socketIO tokens

The time has come to secure the socket connection.

Everything is prepared to make it as comfortable as possible.

Preparation

  • Checkout branch feature/token from boldo-server, boldo-sockets, boldo-mobile.
  • There are several breaking changes in the .env of server and sockets. Make sure to double check those and also do npm i.
  • The most important breaking change is the RSA256 Private and Public keys. Here is a great gist how to generate the keys. Important is, when adding the keys to the .env file: Add " and "\n" after the first line (header) and before the last line (footer).

Implementation

The app is passing token: "superPenguinMagic" in all socket.emit() calls currently. superPenguinMagic` is a magic value that will always validate successfully. But of course, this is not good. We need to pass the real token.

To get your hands on a real token, use the /profile/patient/appointments/:id endpoint exposed by the server. It returns the appointment object, including patient details and also a token:string property 😱.

Some notes about this token:
It will only be defined, if the status is "open" (15 minutes before the meeting and until the doctor leaves the room open). Otherwise the token is an empty string. The token is valid for 1 day, this should be more than enough as open appointments are locked the latest 8 hours after the meeting was scheduled to take place.

If the token is not defined, it means the user should also not be able to be in the waiting room.

It seems like a good idea (but maybe it just seems like it) to download the token once the waiting room is opened. Important is to show some loading animation in this case as it can take a second or three until the data arrives. If there is no token, send the user back to the previous screen and show some snack bar 🍫 that the user should try shortly again. In this erroneous situation, it might also be good to reload the data on the home screen.

User is cached beyond logout

When logging in after logging out, the old user is shown data of the previously logged in user.

To try this out, use these credentials:
2, password
10, password

After logging in with one user, logging out, logging in with the other user, you will still see that the whole app shows data from the first logged-in user.

Expected would be that we remove tokens and all other user related data during logout.

Improve the profile page form

How our form works

Currently in the profile screen profile_screen.dart page we have a form. From this form we are able to navigate to address_screen.dart.
Inside the address_screen.dart we also have a form. It is actually extending the form we have from profile_screen.dart. Clicking on "submit" in any of the forms will trigger the same function updateProfile. This function takes the data from the provider (from both forms) and sends it to the server. We save the data from the inputs not onChange but onSubmit. So the data will go inside the provider when we try to submit the form. Then we get this data from provider and pass it to the server. We need a provider because we shared the data of the same form between 2 screens.

Problem 1

Because of the functionality above if we try to remove some text from profile_screen.dart and then navigate to address_screen.dart we will successfully submit the form. This should not happen(or at least not as it happens right now). The changes we made in profile_screen.dart will not be reflected because we save the data onSave. We don't submit the form in profile_screen.dart so we don't save the new data. We submit the form in address_screen.dart so we save the data only there.

Solution 1

Save the data onChange and not on onSave in the text controller.

Problem 2

The errors are not shared between the forms. We should share them.

Solution 2

Store the error inside the provider

Doctor Table shows wrong speciality

Problem: Doctors show wrong speciality. In both cases it should not show "Dermatologia" but the doctor has a different speciality.

Note:
From now on, you can get the actual specialities (and languages) from the endpoints of the doctor (e.g. /doctors).

Via: doctors.specializations[].description

Screenshot 2020-11-29 at 17 26 06

Screenshot 2020-11-29 at 17 37 22

Error I/flutter (20126): unhandled element filter

flutter curently throws the following error:

I/flutter (20126): unhandled element filter; Picture key: AssetBundlePictureKey(bundle: PlatformAssetBundle#69fba(), name: "assets/images/DoctorImage.svg", colorFilter: null)

The problem is that the svg library does not support the dropshadow on the svg.
For more details, see: dnfield/flutter_svg#98

Solution:

Use the original images and add drop-shadow where needed via flutter.
https://www.figma.com/file/s5QFKXhMS3Lcmpg5ZFb7Xo/CMR?node-id=1242%3A19999

Improve dropdown.

We need to improve the dropdown so we can show a default value like "select your gender". This value should not be selectable but it should be the value that the user sees if nothing is selected.

Dynamically show the "Waiting room card"

Problem:

We need to dynamically show the waiting room notification in the dashboard.
It should open 15 minutes before a call starts and close after the appointment has actually happened.

Solution:

We receive appointments from the server.

Start of an appointment:
We can use the start property of an appointment and check every second (or n seconds) if there is an appointment that is about to start. And then render a card for it.

End of an appointment:
We can NOT use the end property of an appointment as the doctor might be delayed longer than the appointment actually was scheduled so it would not be possible for a patient to join the call anymore.
INSTEAD, we check for a prop from the server waitingRoomStatus ('upcoming' | 'open' | 'closed'). If an appointment has the status closed, we never show a waitingRoom card for it.

The implementation includes two tasks:

  1. Show "Waiting Room Card" for every appointment that is waitingRoomStatus == 'open'.
  2. Check for appointments that have waitingRoomStatus == 'upcoming' and open them once it's LATER than 15 minutes before the appointment.

Doctor reloading should not end the call for patient

Problem:

If the doctor reloads currently, the patient immediately sees the "call ended" screen.
This should not happen, instead the call should try to reestablish connection OR go into the waiting room. Whatever is best to connect the call immediately back once the doctor's browser did load.

Potential Issues:

  1. Does browser emit an event on reload? (SOCKETS)
  2. The app have a listener for connection disconnected that ends the call. (WEBRTC Listeners)

Enable Mute Video and Mute Audio buttons

Problem:

Right now clicking on video and audio mute buttons does not do anything.

Solution:

Implement them in both waiting room and call to be functional. Make sure that the configuration from waiting room stays this way once entering the call.
Expect that this value can be set on the local media stream which would automatically take care to also mute it in the RTC connection.

Logout

Logout will now have to be handeled directly via calling the KC endpoint.
Neither the node server, nor appAuth will help with that.

There is a revoke endpoint that KC offers. It's documented here:
https://www.keycloak.org/docs/latest/securing_apps/#_token_revocation_endpoint

This is the official OIDC Description of such an endpiont:

This document proposes an additional endpoint for OAuth authorization
servers, which allows clients to notify the authorization server that
a previously obtained refresh or access token is no longer needed.
This allows the authorization server to clean up security
credentials. A revocation request will invalidate the actual token
and, if applicable, other tokens based on the same authorization
grant.

Opening Doctors List triggers 3 times same requests

Problem:
Navigating to the doctors page triggers 3 times the same request (/doctors?text=).

It can be observed in the flutter dev tools and also in the server by adding a console.log into the endpoint.
Screenshot 2020-11-30 at 17.51.33.png

Expected Behaviour:
Opening the page should only trigger one request.

Margins of home header

As shown in the screenshot below, the header looks a bit off, because:

  • too little padding left
  • too little padding between text and image

Screenshot 2020-12-04 at 17.28.32.png

memory leak on Home screen

In encountered the following error when leaving the home screen while it was still sending the request (I had clicked the button to reload after an error occured).

The solution seems to be given in the screenshots and it probably involves to check for mounted before setting the state in the callback (or after the await of the request).

Exception has occurred.
FlutterError (setState() called after dispose(): _HomeTabState#7d1a0(lifecycle state: defunct, not mounted)
This error happens if you call setState() on a State object for a widget that no longer appears in the widget tree (e.g., whose parent widget no longer includes the widget in its build). This error can occur when code calls setState() from a timer or an animation callback.
The preferred solution is to cancel the timer or stop listening to the animation in the dispose() callback. Another solution is to check the "mounted" property of this object before calling setState() to ensure the object is still in the tree.
This error might indicate a memory leak if setState() is being called because another object is retaining a reference to this State object after it has been removed from the tree. To avoid memory leaks, consider breaking the reference to this object during dispose().)

Screenshot 2020-11-29 at 15 22 20

Screenshot 2020-11-29 at 15 23 02

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.