{ list here sources of all reused/adapted ideas, code, documentation, and third-party libraries -- include links to the original source as well }
Refer to the guide Setting up and getting started.
The Architecture Diagram given above explains the high-level design of the App.
Given below is a quick overview of main components and how they interact with each other.
Main components of the architecture
Main
(consisting of classes Main
and MainApp
) is in charge of the app launch and shut down.
The bulk of the app's work is done by the following four components:
UI
: The UI of the App.Logic
: The command executor.Model
: Holds the data of the App in memory.Storage
: Reads data from, and writes data to, the hard disk.Commons
represents a collection of classes used by multiple other components.
How the architecture components interact with each other
The Sequence Diagram below shows how the components interact with each other for the scenario where
the user issues the command delete n/Alex
to delete Alex
from HealthSync.
Each of the four main components (also shown in the diagram above),
interface
with the same name as the Component.{Component Name}Manager
class (which follows the corresponding API interface
mentioned in the previous point).For example, the Logic
component defines its API in the Logic.java
interface and implements its functionality using the LogicManager.java
class which follows the Logic
interface. Other components interact with a given component through its interface rather than the concrete class (reason: to prevent outside component's being coupled to the implementation of a component), as illustrated in the (partial) class diagram below.
The sections below give more details of each component.
The API of this component is specified in Ui.java
The UI consists of a MainWindow
that is made up of parts e.g.CommandBox
, ResultDisplay
, PersonListPanel
, StatusBarFooter
etc. All these, including the MainWindow
, inherit from the abstract UiPart
class which captures the commonalities between classes that represent parts of the visible GUI.
The UI
component uses the JavaFx UI framework. The layout of these UI parts are defined in matching .fxml
files that are in the src/main/resources/view
folder. For example, the layout of the MainWindow
is specified in MainWindow.fxml
The UI
component,
Logic
component.Model
data so that the UI can be updated with the modified data.Logic
component, because the UI
relies on the Logic
to execute commands.Model
component, as it displays Person
object residing in the Model
.API : Logic.java
Here's a (partial) class diagram of the Logic
component:
The sequence diagram below illustrates the interactions within the Logic
component, taking execute("delete 1")
API call as an example.
Note: The lifeline for DeleteCommandParser
should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
How the Logic
component works:
Logic
is called upon to execute a command, it is passed to an AddressBookParser
object which in turn creates a parser that matches the command (e.g., DeleteCommandParser
) and uses it to parse the command.Command
object (more precisely, an object of one of its subclasses e.g., DeleteCommand
) which is executed by the LogicManager
.Model
when it is executed (e.g. to delete a person).CommandResult
object which is returned back from Logic
.Here are the other classes in Logic
(omitted from the class diagram above) that are used for parsing a user command:
How the parsing works:
AddressBookParser
class creates an XYZCommandParser
(XYZ
is a placeholder for the specific command name e.g., AddCommandParser
) which uses the other classes shown above to parse the user command and create a XYZCommand
object (e.g., AddCommand
) which the AddressBookParser
returns back as a Command
object.XYZCommandParser
classes (e.g., AddCommandParser
, DeleteCommandParser
, ...) inherit from the Parser
interface so that they can be treated similarly where possible e.g, during testing.API : Model.java
The Model
component,
Person
objects (which are contained in a UniquePersonList
object).Person
objects (filtered as foundPersonsList
by ModelManager
).Person
objects (e.g., results of a search query) as a separate filtered list which is exposed to outsiders as an unmodifiable ObservableList<Person>
that can be 'observed' e.g. the UI can be bound to this list so that the UI automatically updates when the data in the list change.UserPref
object that represents the user’s preferences. This is exposed to the outside as a ReadOnlyUserPref
objects.Model
represents data entities of the domain, they should make sense on their own without depending on other components)API : Storage.java
The Storage
component,
AddressBookStorage
and UserPrefStorage
, which means it can be treated as either one (if only the functionality of only one is needed).Model
component (because the Storage
component's job is to save/retrieve objects that belong to the Model
)Classes used by multiple components are in the seedu.addressbook.commons
package.
This section describes some noteworthy details on how certain features are implemented.
The Undo feature allows users to revert an undo-able command. The UndoCommand
serves as the entry point for users to
initiate the undo process.
The UndoCommand
is implemented as follows:
undo
or u
undo [number]
undo
: Undoes the last undo-able commandundo [number]
: Undoes the specified number of undo-able commandsUndoCommandParser
parses user input, ensuring it adheres to the expected format.
If the input is invalid or incomplete, appropriate error messages are generated.UndoCommandParser
returns a UndoCommand
object. The object
then interacts with the model to identify and undo the desired number of previous commandsIn the current implementation, the UndoCommand
relies on undoable commands storing the previous details of the patient as fields.
For example, the undo of an "add" command stores the details of the added patient and undoing it will simply delete the added patient,
representing a reversal of the addition. This approach prioritizes simplicity and efficiency, ensuring a quick and reliable undo operation.
By leveraging the existing structures and operations in the application, this method avoids the need for additional data storage and processing.
The following activity diagram summarizes what happens when a user executes a new command:
Alternative 1:: Explore more sophisticated undo strategies, such as storing the state of the address book after each command.
A way to add a property to Person
that could be nullable was needed, to reflect optionality within our
field implementation. While optional fields like MedicalHistory
exist in HealthSync, these fields are
Collections, and can natively handle the empty state. Singular optional properties can be added this way,
but is hard to distinguish between properties that allow for multiple entries and fields that don't.
The optional fields could be implemented directly to Person
as shown in the partial class diagram above.
However, several other packages depend upon Person
as well, including UI
and Storage
.
These packages already make assumptions on the non-null
property on the variables of Person
.
The diagram above illustrates a possible path that may arise if the optional property of the field is not explicitly defined. There is a need to explicitly denote that our optional field is possibly an empty value without having its implementers perform the check themselves, so that the compiler is able to assist in our coding.
Therefore, the implementation of optional fields now return its value wrapped in the Java
Optional
wrapper. In this example, when getAppointment
is called now, the implementer will be
informed of the type mismatch with the Appointment
type, explicitly informing the implementer that
this value is potentially null
. By doing it in this way, we also guarantee to the implementer that
the fields that do not generate an Optional
wrapper cannot be empty.
Aspect: Handling of Optional Fields
null
values
Optional
wrapper, which caused the team to favor
this implementation.Appointment
is a special field belonging to the Person
model class, as it implicitly stores a temporal
relationship within itself.
Appointment
is distinctly different from other fields in Person
in that it cannot store its values as
a String directly - otherwise, this would complicate the process of defining temporal relationships within itself.
Above is a partial class diagram of Appointment
. Note that several static members were excluded as they are not
relevant to its data-structure properties in HealthSync
.
The default Java packages provides its implementation of temporal objects in the java.time
package. In particular,
LocalDateTime
and its variants were the most relevant to us, as it allows the user to record time without needing
to account for timezone differences. This is powerful, as our target audience is not expected to change locations in
a significant way that causes them to change time regions entirely.
With the use of the java.time
package, the project could not use only regex
for Appointment
.
This is due to the level of checks required to parse a temporal object, with the amount of dependencies that exist
between the day, month and year fields. The provided DateTimeFormatter
and DateTimeFormatterBuilder
classes helps
create the parser objects used for Appointment
. However, the classes do not account for the combined time format that
HealthSync requests of its users.
Therefore, Appointment
uses a combination of regex
and DateTimeFormatter
to resolve its user input.
A partial activity diagram illustrating the relevant segment of the parse process.
As seen above, ParserUtil
verifies if the Appointment user input is trivially valid using
regex
, before passing the input into the of
constructor. DateTimeFormatter
cannot fully verify input strings
against its format without creating a LocalDate
/LocalTime
object as a side effect,
so of
handles a portion of the parse.
Aspect: Value to store Appointment
as
Alternative 1: Use of raw String
format for Appointment
Alternative 2 (current choice): Use of Java Temporal-related objects for Appointment
Aspect: Constructor for Appointment
to manage valid user input
Alternative 1: Directly use constructors for Appointment
, and using isValidAppointment
to verify input
now()
resourceAlternative 2 (current choice): Use of of
factory method for Appointment
, and verifying input inside of
Appointment
as a class that can throw an Exception
during constructionAppointment
only performed once user input is verifiedparse
for ParserUtil
Aspect: Parsing of Appointment
Field as multiple fields or single field
Alternative 1 (current choice): Use of the single ap/
flag.
Alternative 2: Use of 2 flags to denote start and end time for appointment.
The DeleteCommand
allows users to delete a patient's profile or a specified field from the patient's profile.
The DeleteCommand
is implemented as follows:
delete
DeleteCommand
by specifying the command word, followed by the name or IC of the person they wish to delete and any fields they wish to delete.delete n/Name [Fields] ...
delete id/IC_Number [Fields] ...
delete n/Name id/IC_Number [Fields] ...
DeleteCommand
relies on an DeletePersonDescriptor
to capture which fields the user wishes to delete from the patient's profile. The descriptor will be passed to the DeleteCommand
to execute the deletion. Currently, only Appointment
and MedicalHistory
can be deleted as they are optional.DeleteCommand
performs validation to ensure that the IC or Name provided is valid.DeleteCommand
identifies the patient to be deleted based on the provided name or IC. When the patient is found, if no there are no specified fields to delete, the entire patient profile will be deleted from the database. Otherwise, the specified fields will be deleted from the patient's profile.The following activity diagram summarizes what happens when a user executes a new command:
DeleteCommand
provides flexibility to users, allowing them to choose what to be deleted from the patient's profile, instead of an "all-or-nothing" approach.DeleteCommand
allows users to delete outdated or incorrect information from the patient's profile, ensuring that the database is up-to-date and accurate.DeleteCommand
supports "right to erasure" under the PDPA, allowing users to delete patient's information from the database when requested.DeleteCommand
could be implemented as a DeleteFieldCommand
and a DeletePersonCommand
. The DeleteFieldCommand
will delete the specified fields from the patient's profile, while the DeletePersonCommand
will delete the entire patient profile from the database. This approach will require the user to invoke two commands to delete a patient's profile and the specified fields from the patient's profile. This approach is not chosen as it is less intuitive and requires more effort from the user.{Explain here how the data archiving feature will be implemented}
The Graphical User Interface (GUI) is designed using JavaFX and employs a combination of HBox, VBox, and StackPane layouts. It also utilizes specific color choices to create an appealing and user-friendly interface.
Developers can use this information as a reference when working with the HealthSync GUI code.
The primary layout structure for the HealthSync GUI is based on HBox and VBox containers, which allow for a flexible arrangement of UI elements.
HBox Location: The HBox is the top-level container in the GUI and spans the entire application window.
VBox Location: There are two VBox containers within the HBox, which are responsible for organizing various elements of the GUI.
StackPane The StackPane is used to organize specific UI elements within the VBox containers. It allows for the layering of elements and effective management of screen real estate.
StackPane (PersonListPanel)
Location: Inside the first VBox (fx:id="personListPanelPlaceholder"
).
StackPane (LoggedPersonlListPanel)
Location: Also inside the first VBox (fx:id="loggerPanelPlaceholder"
).
StackPane (ResultDisplay, CommandBox, and StatusBarFooter)
Location: These StackPanes are located inside the second VBox
The HealthSync GUI utilizes specific color choices to create a visually pleasing and organized interface, while still maintaining the original Dark Theme.
#43314E
#231335
The EditCommand
allows users to modify the details of an existing person within the address book.
The EditCommand
is implemented as follows:
edit
.EditCommand
by specifying the command word, followed by the name or IC of the person they wish to edit and the fields they wish to modify.edit n/Name [Fields] ...
edit id/IC_Number [Fields] ...
edit n/Name id/IC_Number [Fields] ...
EditCommand
relies on an EditPersonDescriptor
to capture the details to edit the person with. This descriptor allows for updating various attributes of the person, such as phone, email, address, appointment, and medical histories.EditCommand
performs validation to ensure at least one field to edit is provided. It also checks for consistency when both a name and IC are provided.EditCommand
identifies the person to edit based on the provided name and/or IC. If the person is found, it creates an editedPerson
with the desired changes. The person is then updated with the new details.The following activity diagram summarizes what happens when a user executes a new command:
EditCommand
provides flexibility to users by allowing them to choose whether to edit a person by name or IC, as per their convenience.edit 1 p/93029393
to edit the first person of the list with the phone number.
Pros:
Cons:
The FindCommand
allows users to find existing person(s) within the patient list,
using their Name, NRIC and/or Appointment, and view their field data. This is done with aid by the concreted Predicate
classes, that directly implement the Predicate
functional interface given by the Java package.
The FindCommand
is implemented as follows:
find
.FindCommand
by specifying the command word,
followed by the Name, NRIC and/or Appointment period of the person(s) they wish to find.find n/Name [Fields] ...
find id/IC_Number [Fields] ...
find n/Name id/IC_Number [Fields] ...
execute
method: The FindCommand
executes the search by using the specified predicates generated from
the fields (NameContainsKeywordsPredicate
/IdContainsKeywordsPredicate
/AppointmentOverlapsPredicate
).
These predicates are composited into CompositePredicate
to filter and list all persons matching the search criteria.
CompositePredicate
is a collection of Predicate<Person>
objects that itself implements the Predicate<Person>
interface. The collection is stored in a Set, and test()
calls will perform a logical AND on all values in its
collection. By default, CompositePredicate
will have an instance of IdentityPredicate
which always returns true
.
FindCommand
instances handles its Predicate
values internally.As observed in the diagram above, each field provided will generate the appropriate Predicate
value and add it to the
CompositePredicate
collection, and each field not provided adds an instance of an IdentityPredicate
instead.
As the Set implementation enforces no duplicate Predicates, this means that collections with fewer fields provided
will also store less values in the collection overall.
FindCommand
performs validation to ensure at least one field is provided. For Appointment,
it asks for a valid Appointment format to be given.The following sequence diagram shows how the find operation works in the successful case:
Note: The lifeline for FindCommandParser
and FindCommand
should end at the destroy marker (X) but due to a
limitation of PlantUML, the lifeline reaches the end of diagram.
The following activity diagram summarizes what happens when a user executes a new command:
FindCommand
provides flexibility to users by allowing them to choose whether to find a person
by name, NRIC or Appointment timeslot, whichever is faster or available.What Fields to use as part of query
Alternative 1: Using existing implementation of only name to find patients
find n/NAME
which is easier to remember.Alternative 2: Search through all fields
Alternative 3 (current choice): Searching through ID, Name and Appointment
Pros:
Cons:
Handling multiple field queries
Alternative 1 (current choice): Logical AND
find
resultfind
Alternative 2: Logical OR
find
.The LogCommand
allows users to log patient profiles which are the results of FindCommand
to the Logger Tab.
The LogCommand
is implemented as follows:
log
, or lo
for short.LogCommand
by entering the command word.
log
, or lo
.execute
method: The LogCommand
sets persons in the logbook to be the foundPersonsList
of the model.LogCommand
performs validation to ensure the foundPersonsList
is not empty, to ensure there are patient profiles to be added to the Logger Tab.LogCommand
retrieves the logbook, then sets loggedPersons
to the current filtered list, foundPersonsList
, of the model. foundPersonsList
is a filtered list that is updated using the predicate only when FindCommand
is invoked.The following sequence diagram shows how the log operation works:
The following activity diagram summarizes what happens when a user executes a new log command:
FindCommand
has been invoked, so to maximise usage of the Logger Tab, foundPersonsList
is filtered with predicate PREDICATE_TODAY
, which loads the Logger Tab with patients that have an appointment on that day. This list remains until FindCommand
(with a non-empty result) then LogCommand
are invoked.LogCommand
provides convenience to users by simply overwriting what is currently in the Logger Tab with a new result, instead of having to clear the Logger Tab first, then logging the new result.EditCommand
or DeleteCommand
have been invoked for any patient in the Logger Tab, they remain unchanged in the Logger Tab. This preserves the patient profiles in the state at which they were logged.Alternative 1: Using the filtered list, filteredPersons
to set loggedPersons
in the logbook
Pros:
filteredPersons
is used by other commands that alter the patient list, such as FindCommand
, EditCommand
and DeleteCommand
.Cons:
EditCommand
or DeleteCommand
in between FindCommand
and LogCommand
, the whole list will be logged.filteredPersons
contains the entire patient list.Alternative 2: Directly interfacing with the logbook without the use of an intermediate filtered list
Pros:
foundPersonsList
, but rather logging will be performed directly based on the results of FindCommand
.foundPersonsList
and the need to retrieve it in order to set persons in logbook.Cons:
The AppendLogCommand
allows users to append patient profiles which are the results of FindCommand
to the existing profiles in the Logger Tab.
The AppendLogCommand
is implemented as follows:
alog
, or al
for short.AppendLogCommand
by entering the command word.
alog
, or al
.execute
method: The AppendLogCommand
iterates through the foundPersonsList
and records all the duplicates within duplicateClause
, and adds the non-duplicates to the logbook.AppendLogCommand
performs validation to ensure the foundPersonsList
is not empty, to ensure there are patient profiles to be appended to the Logger Tab. A hasDuplicates
boolean also keeps track of the possible duplicates within the foundPersonsList
.AppendLogCommand
retrieves the logbook, then iterates through the foundPersonsList
of model to add each non-duplicate person to the logbook individually (addPerson(person)
).The following activity diagram summarizes what happens when a user executes a new append log command:
FindCommand
results to the Logger Tab, instead of completely replacing results of FindCommand
with the new results. It's no longer all-or-nothing.AppendLogCommand
is able to save non-duplicate persons to the Logger Tab even if there exists duplicates within the foundPersonsList
through the for-loop, instead of terminating the command altogether due to the presence of duplicate person(s).EditCommand
or DeleteCommand
have been invoked for any patient in the Logger Tab, they remain unchanged in the Logger Tab. This preserves the patient profiles in the state at which they were append-logged.Alternative 1: Terminate the operation as soon as there is a duplicate person found
Pros:
foundPersonsList
is largeCons:
foundPersonsList
is known to have at least one duplicate, all the patient profiles in the list will not be added to the Logger Tab, limiting usability of the Logger Tab.Alternative 2: Directly interfacing with the logbook without the use of an intermediate filtered list
Pros:
foundPersonsList
, but rather append-logging will be performed directly based on the results of FindCommand
.foundPersonsList
and the need to retrieve it in order to add persons to logbook.Cons:
The ClearLogCommand
allows users to delete all the patient profiles in the Logger Tab.
The ClearLogCommand
is implemented as follows:
clog
, or cl
for short.ClearLogCommand
by entering the command word.
clog
, or cl
.execute
method: The ClearLogCommand
sets the logbook to be a new logbook.ClearLogCommand
performs validation to ensure model is non-null.ClearLogCommand
sets the logbook of the model to be a new logbook (new LogBook()
), effectively resetting the contents of the Logger Tab.The following sequence diagram shows how the clog operation works:
Pros:
Cons:
Target user profile:
Value proposition:
HealthSync caters to clinic assistants in small private clinic, enabling them to register and access patient information within 2-3 minutes. It offers a user-friendly platform, optimizing contact management, patient tracking, and health record access, ensuring efficient patient management, appointment scheduling, and comprehensive health record retrieval, enhancing care delivery and saving time.
Priorities: High (must have) - * * *
, Medium (nice to have) - * *
, Low (unlikely to have) - *
Priority | As a... | I can... | So that I can... |
---|---|---|---|
* * * | beginner of the app for an important operation | auto-save all my data | not lose my data when something goes wrong |
* * * | frontdesk worker | retrieve patient information | make use of the patient data when I need them |
* * * | frontdesk worker | create patient entries | add entries when new patients visit |
* * * | frontdesk worker | find a patient by some field they possess | locate details of persons without having to go through the entire list |
* * * | frontdesk worker | delete a patient entry | clean and update the database when patient no longer exist |
* * * | frontdesk worker | edit patient entries | update their details, especially for upcoming appointment dates |
* * * | frontdesk worker | store patient appointment information | track when they next come to the clinic |
* * | a new user of the app | view preloaded sample data | know how the basic UI look like when it is populated |
* * | a new user of the app | purge all sample data from the app | add my own data easily when I want to use the app |
* * | a new user of the app | have easy access to a help sheet | check what commands I can and cannot use in a situation |
* * | frontdesk worker | add medical histories to patients | view and filter patients accordingly |
* * | frontdesk worker | document patient encounters | maintain up-to-date records of patient information |
* * | frontdesk worker | use app with shortcuts | get my task done very quickly |
* * | frontdesk worker | see conflicts in appointment schedules | seamlessly schedule appointments for patients |
* * | frontdesk worker | reminder when patient's appointment is coming soon | call-up and remind patients, and prepare for the day accordingly |
* | a new user of the app | have physical UI Buttons | use them to execute tasks before I'm familiar with shortcuts |
* | a new user of the app | access an in-app help sheet | easily see what to do when I need help without opening another program |
* | a new user of the app | get in-app hints as I use the app | quickly acclimatise to using the app as I use it |
* | frontdesk worker | have a very optimised app | do my task and have data reading almost instantly |
* | frontdesk worker | leverage on statistics in my patient list | analyse data (ie. how many appointments booked/ month for doctors) |
* | frontdesk worker | save back-up or archive patient details somewhere | maintain a fast application while still having data securely stored |
* | frontdesk worker | have calendar-like UI to create appointments | show calendar to patients and allow smoother appointment booking process |
(For all use cases below, the System is the HealthSync
and the Actor is the user
, unless specified otherwise)
Use case: UC1 - Add a patient
MSS
User requests to add a patient into the list.
HealthSync adds the target patient into the list and displays the patient inside the updated list.
HealthSync performs an auto-save (UC0A).
Use case ends.
Extensions
1a. HealthSync detects an error in the input.
1a1. HealthSync shows an error message.
1a2. User corrects the input.
Steps 1a1-1a2 repeat until the user inputs all the fields correctly.
Use case continues from step 2.
Use case: UC2 - Delete a patient
MSS
User requests to delete a specific patient based on an identifier from the list.
HealthSync searches for the patient in the list.
HealthSync deletes the specified patient from the list.
HealthSync performs an auto-save (UC0A).
Use case ends.
Extensions
1a. HealthSync detects an error in the identifier input.
Steps 1a1-1a2 repeat until the user inputs all the fields correctly.
Use case continues from step 2.
1b. User also inputs non-identifier fields as well.
1b1. HealthSync deletes the patient fields from the patient instead (UC3).
Use case ends.
2a. The patient does not exist in the list.
2a1. HealthSync shows an error message.
Use case ends.
Use case: UC3 - Delete fields from a patient
MSS
User requests to delete fields from a specific patient based on an identifier from the list.
HealthSync searches for the patient in the list.
HealthSync deletes the fields of a specified patient from the list.
HealthSync performs an auto-save (UC0A).
Use case ends.
Extensions
1a. HealthSync detects an error in the identifier input.
1a1. HealthSync shows an error message.
1a2. User corrects the input.
Steps 1a1-1a2 repeat until the user inputs all the fields correctly.
Use case continues from step 2.
1b. The user does not specify any fields they want to delete.
1b1. HealthSync deletes the patient from the list instead (UC2).
Use case ends.
2a. The user does not exist in the list.
2a1. HealthSync shows an error message.
Use case ends.
Use case: UC4 - Edit a patient
MSS
User requests to change a specific user's fields based on an identifier with a new value in the list.
HealthSync searches for the patient in the list.
HealthSync edits the specified patient's fields in the list.
HealthSync performs an auto-save (UC0A).
Use case ends.
Extensions
1a. HealthSync detects an error in the input.
1a1. HealthSync shows an error message.
1a2. User corrects the input.
Steps 1a1-1a2 repeat until the user inputs all the fields correctly.
Use case continues from step 2.
2a. The user does not exist in the list.
2a1. HealthSync shows an error message.
Use case ends.
Use case: UC5 - Find a patient
MSS
User requests for matches to the given query for a particular field.
HealthSync displays the list of patients matching the query.
Use case ends.
Extensions
1a. HealthSync detects an error in the input.
1a1. HealthSync shows an error message.
1a2. User corrects the input.
Steps 1a1-1a2 repeat until the user inputs all the fields correctly.
Use case continues from step 2.
1b. User specifies multiple fields to query.
1b1. HealthSync combines the fields into a query that matches all the conditions given.
Use case continues from step 2.
Use case: UC6 - Log patient(s)
MSS
User requests to log patient profiles into the Logger Tab.
HealthSync adds the patient profiles to the Logger Tab and displays the profiles inside the updated Logger Tab.
Use case ends.
Extensions
1a. The user did not find patient profiles beforehand
1a1. HealthSync shows an error message.
Use case ends.
1b. The user tried to find profiles that did not exist in the list
1b1. HealthSync shows an error message.
Use case ends.
Use case: UC7 - Append-logging patient(s)
MSS
User requests to append patient profiles to the Logger Tab.
HealthSync adds the patient profiles to the Logger Tab and displays the profiles inside the updated Logger Tab, under the current Logger Tab.
Use case ends.
Extensions
1a. The user did not find patient profiles beforehand
1a1. HealthSync shows an error message.
Use case ends.
1b. The user tried to find profiles that did not exist in the list
1b1. HealthSync shows an error message.
Use case ends.
2a. The patient profiles to be added contain duplicates to the logged profiles
2a1. The non-duplicate patient profiles are added to and displayed in the Logger Tab.
Use case ends.
2b. Patient profiles to be added have been edited
2b1. HealthSync updates patient profile data in the Logger Tab.
Use case ends.
Use case: UC8 - Clearing the log
MSS
User requests to clear all data in the Logger Tab.
HealthSync removes the patient profiles inside the Logger Tab and displays an empty Logger Tab.
Use case ends.
Extensions
1a. The Logger Tab is already cleared
1a1. HealthSync shows an error message.
Use case ends.
Use case: UC0A - Auto-save
Actors: Operating System (OS)
MSS
HealthSync requests for permissions from the OS to access its save location.
OS grants HealthSync permission to access its save location.
HealthSync saves the session data into the save location.
Use case ends.
Extensions
1a. OS does not grant HealthSync save location permissions.
Use case ends.
Given below are instructions to test the app manually.
Note: These instructions only provide a starting point for testers to work on. Testers are expected to do more exploratory testing.
Note: The instructions below assume that the fields provided to the commands are all valid. Here is how the correctness of the fields is defined.
Fields that are compulsory are bolded. Fields that are optional are italicized.
Name
ID
Phone number
Email address
local-part@domainname
.
local-part
is alphanumeric, and may also contain these symbols: +
_
.
-
domainname
should be the site that the email leads to, such as gmail.com
, mail
.@
symbol.Address
Medical History
Appointment
Date, Start Time, End Time
. For example,
1-Aug-2023, 11:00 13:00
is a valid appointment denoting an appointment on 1st August 2023, from 11am
to 1pm.Jun
and 6
both represent June.1200
for 12 noon, 0900
for 9am.15
will be interpreted as 3pm.Note:: If any field is invalid, a MESSAGE_CONSTRAINT
conforming to the format of the fields will be generated as output and the command will not be executed. Invalid fields will not be considered in the test cases below.
Note: HealthSync provides shortcuts for commands to allow faster typing for users. In the test cases provided below, you have the flexibility to use either the original command or its shortcut interchangeably.
Here is the mapping between original command keywords and shortcuts:
Original Command | Shortcut |
---|---|
help | h |
list | ls |
add | a |
edit | e |
delete | d |
clear | c |
find | f |
log | l |
alog | al |
clog | cl |
undo | u |
exit | ex |
Initial launch
Saving window preferences
Successful Help command Execution
help
Help URL Generation
Copy URL
button or copy the shown URL list
find
command before executing the list
command Successful Patient Addition
add n/John Doe id/S1234567A p/91234567 e/johndoe@gmail.com a/123 Main st
New patient added: ...
add n/Alex Bee id/T9876543A p/97438807 e/alexb@gmail.com a/123 Minor st ap/13-Nov 09:00 11:00 m/Diabetes
New patient added: ...
add n/Alice May id/A135791B p/98765432 e/alicem@gmail.com a/456 Main st ap/09-09-2023 17:00 19:00
New patient added: ...
Duplicate Patient Addition
John Doe
and ID S7654321B
existsadd n/John Doe id/S7654321B p/98876543 e/johndoe2@email.com a/123 Oak St
Patient already exists in HealthSync.
add n/John Doe id/T9876543A p/94224432 e/johndoe3@gmail.com a/456 Oak St
Patient already exists in HealthSync.
add n/Bob Lee id/S7654321B p/92224432 e/bobl@gmail.com a/789 Oak St
Patient already exists in HealthSync.
Undo Adding of Patient
add
command before doing an undo
command. Invalid Command Format / Usage
Invalid command format! ...
Note: For editing using both n/NAME and id/ID, both the Name and ID must match to the same patient, otherwise an error message will be outputted.
Successful Editing of one field
John Doe
and ID S7654321B
existsedit n/John Doe p/99998888
John Doe
is updated to 99998888
edit id/S765321B e/johndoee@gmail.com
John Doe
is updated to johndoee@gmail.com
edit n/John Doe id/S765321B a/123 Oak Street
John Doe
is updated to 123 Oak Street
m/
and ap/
Expected: The corresponding field is updatedSuccessful Editing of multiple fields
John Doe
and ID S7654321B
existsedit n/John Doe p/98765432 ap/17-Nov-2023 09:00 11:00
Expected: The phone number of John Doe is updated to 98765432
and appointment is updated to 17-Nov-2023, 09:00 to 11:00
edit id/S7654321B m/cancer m/diabetes
Expected: The medical histories of John Doe is updated to cancer
and diabetes
Undo Editing of Patient
edit
command before doing an undo
command.
Expected: The edit on the patient is reverted.Invalid Command Format / Usage
John Doe
and ID S7654321B
existsedit n/John Doe id/S7654321B
Expected: Error message: At least one field to edit must be provided.
edit n/NONEXISTANT p/98765432
Expected: Error message: INVALID name and/or ID!
Note: For deletion using both n/NAME and id/ID, both the Name and ID must match to the same patient, otherwise an error message will be outputted.
Successful Patient Deletion
delete n/John Doe
Deleted Patient: ...
delete id/S9876678A
Deleted Patient: ...
delete n/Alice Tan id/S7654321B
Deleted Patient: ...
Successful Field Deletion
delete n/John Doe ap/
Deleted Patient's field: ...
delete id/S1234567A m/
Expected: Patient's medical history field (all of it) is deleted with output message: Deleted Patient's field: ...
delete n/Alice Tan id/S7654321B ap/
Expected: Patient's appointment field is deleted with output message: Deleted Patient's field: ...
Invalid Patient Deletion
delete n/Nonexistent Patient
The given combination of Name and ID does not match any patient in the Patients list.
delete id/IDNotFound
The given combination of Name and ID does not match any patient in the Patients list.
Invalid Field Deletion
delete n/John Doe ap/
The patient does not have an appointment to delete.
delete id/S1234567A m/
The patient does not have a medical history to delete.
delete n/Alice Tan id/S7654321B m/Asthma
The patient does not have a medical history of Asthma to delete.
Undo Deletion of Patient and Patient fields
delete
command on a patient before doing an undo
command. delete
command on a deletable field of a patient before doing an undo
command. Invalid Command Format
delete
Invalid command format! ...
Successful Deletion of All Patients
clear
clear someRandomStringThatWillBeIgnored
Undo clearing of HealthSync
clear
and then execute undo
Successful Patient Search by Name
find n/Alex
Successful Patient Search by ID
find id/T0123436F
Successful Patient Search by Appointment
find ap/12-Dec 0000 2359
Successful Patient Search by Name, ID and Appointment
find n/Alex Yeoh id/T0123436F ap/10-Dec 0000 2359
No Matching Patients Found
find id/T0123456F
No such patient found
find n/DoesNotExit
No such patient found
find ap/10-dec-1989 00:00 23:59
No such patient found
Successful Log After Find Command
log
Failed Log Due to Empty List
log
. Cannot log an empty list.
Undo logging of Patient(s)
log
command before doing an undo
command. log
command is reverted.Log After Closing HealthSync
Successful Append to Log
alog
after performing a find command. alog
after each. Append Duplicate Patients
alog
. Undo alog of Patient(s)
alog
command before doing an undo
command. alog
command is reverted.Failed Append Due to Empty List
alog
Cannot log an empty list.
Successful Log Clear
clog
Undo clog
clog
command before doing an undo
command. clog
command is reverted.Successful Undo of Undo-able Command(s)
undo
Undoing the last command: ...
undo 3
Undoing 3 command(s): ...
Failed Undo Due to Invalid Number
undo -2
Undo step count cannot be a negative number or zero.
undo 0
Undo step count cannot be a negative number or zero.
undo 999
Please provide a valid number of commands to undo, not exceeding the available command history size (Currently max is: 1) ...
Undo After Closing HealthSync
undo
. There is no history of undo-able commands to be undone.
exit
Editing Patient Details Directly
Automatic Save Caution
Making a Backup
Restoring Data from Backup
Handling Patients with Same Name: Currently, HealthSync cannot manage scenarios where patients share the same name. We plan to enhance this by allowing users to add patients with identical names, providing a more robust and flexible patient management system.
Improved UI Text Wrapping: HealthSync currently struggles with text wrapping on the UI, leading to obscured labels for long user inputs. Our plan is to explicitly denote labels on individual UI cards and enable inputs to stretch their containers, ensuring better visibility for users, even with lengthy inputs.
Enhanced Edit Feature Feedback: The current edit feature does not explicitly handle cases where no fields are edited after a change. For instance, if a patient's phone number remains the same after an edit operation, HealthSync doesn't provide a special message indicating that no fields were edited. We plan to improve this feedback for a more informative user experience.
Standardized Empty Optional Fields: HealthSync currently displays empty optional fields inconsistently in particular, for Appointment and Medical History. We intend to standardize the display of empty optional fields to be 'N/A' uniformly, enhancing clarity and consistency in the user interface.
Improved Email Validation: HealthSync's current email validation is not stringent enough, accepting invalid email formats. We plan to implement more thorough email validation to ensure only valid email addresses are accepted.
Consistent Capitalization of Patient IDs: While IDs are case-insensitive, HealthSync does not enforce consistent capitalization of patient IDs in the patient list. This is a cosmetic enhancement to maintain uniformity in the application.
Case-Insensitive Find Feature for Appointments: The current Find feature for appointments is case-sensitive, potentially causing inconvenience for users. We plan to enhance this feature to be case-insensitive, ensuring a smoother and more user-friendly experience.
Improved Messaging for Empty Find Results: When a Find command results in an empty set, the output message currently reads '0 patients found.' We propose an enhancement to provide a clearer message such as 'No patients found,' offering better clarity and user understanding.
Improved Patient Clearing Process:
Currently, HealthSync allows users to use the shortcut c
to clear all patients in the
HealthSync application. While this provides a quick method for clearing patient data, it lacks
a safeguard against accidental data loss. We propose an enhancement to the patient clearing
process by introducing a warning popup. When a user triggers the patient clearing shortcut 'c',
a confirmation popup will appear, prompting the user to double-check their intention before
proceeding with the clearance.